TrioCFD 1.9.8
TrioCFD documentation
Loading...
Searching...
No Matches
AssembleurPVDF_PF.cpp
1/****************************************************************************
2* Copyright (c) 2015 - 2016, CEA
3* All rights reserved.
4*
5* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
6* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
7* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
8* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
9*
10* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
11* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
12* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
13*
14*****************************************************************************/
15
16#include <Champ_front_instationnaire_base.h>
17#include <Champ_front_var_instationnaire.h>
18#include <Dirichlet_entree_fluide_leaves.h>
19#include <Dirichlet_paroi_defilante.h>
20#include <Navier_Stokes_phase_field.h>
21#include <Dirichlet_paroi_fixe.h>
22#include <Neumann_sortie_libre.h>
23#include <Champ_Fonc_Face_VDF.h>
24#include <Matrice_Morse_Sym.h>
25#include <AssembleurPVDF_PF.h>
26#include <Domaine_Cl_VDF.h>
27#include <Matrice_Bloc.h>
28#include <Milieu_base.h>
29#include <Domaine_VDF.h>
30#include <Periodique.h>
31#include <Symetrie.h>
32#include <Debog.h>
33
34Implemente_instanciable(AssembleurPVDF_PF,"Assembleur_P_VDF_Phase_Field",Assembleur_P_VDF);
35
37{
38 return s << que_suis_je() << " " << le_nom() ;
39}
40
42{
44}
45
46/*! @brief Remplit le tableau faces avec la liste des indices des faces periodiques dans le tableau faces_voisins.
47 *
48 * Chaque face periodique figure deux fois
49 * dans faces_voisins (a chaque face correspond la face opposee). On ne
50 * met dans le tableau faces que celle des deux qui a l'indice le + petit
51 * dans la liste des faces de chaque bord periodique.
52 * Valeur de retour:
53 * nombre de faces periodiques (egal a la taille du tableau faces).
54 *
55 */
57{
58 // On commence par surestimer largement la taille du tableau :
59 // nombre de faces de bord
60 const int nb_faces_bord = le_dom_VDF_->nb_faces_bord();
61 faces.resize_array(nb_faces_bord);
62
63 // Recherche des faces periodiques dans les conditions aux limites:
64 const Conds_lim& les_cl = le_dom_Cl_VDF_->les_conditions_limites();
65 const int nb_cl = les_cl.size();
66 int nb_faces_periodiques = 0;
67 for (int num_cl = 0; num_cl < nb_cl; num_cl++)
68 {
69 const Cond_lim_base& la_cl = les_cl[num_cl].valeur();
70 // Selectionne uniquement les conditions Periodique
71 if ( ! sub_type(Periodique,la_cl))
72 continue;
73 const Periodique& la_cl_perio = ref_cast(Periodique, la_cl);
74 const Front_VF& frontiere = ref_cast(Front_VF, la_cl.frontiere_dis());
75 const int nb_faces_cl = frontiere.nb_faces();
76 const int num_premiere_face = frontiere.num_premiere_face();
77 for (int i = 0; i < nb_faces_cl; i++)
78 {
79 // Numero de la face opposee dans le tableau des faces du bord:
80 const int face_associee = la_cl_perio.face_associee(i);
81 if (face_associee > i)
82 {
83 const int num_face_global = num_premiere_face + i;
84 faces[nb_faces_periodiques] = num_face_global;
85 nb_faces_periodiques++;
86 }
87 }
88 }
89
90 // Taille finale du tableau faces
91 faces.resize_array(nb_faces_periodiques);
92 return nb_faces_periodiques;
93}
94
95/*! @brief Determine les elements non nuls de la matrice et prepare le stockage.
96 *
97 * Matrice creuse de taille nb_elements (lignes) * nb_elem_tot (colonnes)
98 * Codee comme une matrice bloc composee de deux matrices morse:
99 * * Matrice carree symetrique nb_elements * nb_elements
100 * (contient les termes M(i,j) ou i et j sont des numeros d'elements reels)
101 * * Matrice rectangle nb_elements * (nb_elem_tot - nb_elem)
102 * (contient les termes M(i,j) ou i est reel et j est virtuel
103 *
104 */
106{
107 int i;
108 const Domaine_VDF& domaine_vdf = le_dom_VDF_.valeur();
109 const IntTab& face_voisins = domaine_vdf.face_voisins();
110
111 // Comptage du nombre total d'elements non nuls:
112 // matrice carree : nombre de faces internes / 2 + nb_elem + nbfaces periodiques
113 // (chaque face interne donne un coef, et on a un element
114 // diagonal et chaque face periodique donne aussi un coef)
115 // matrice rectangle : nombre de faces de joint
116
117
118 // Premiere etape : comptage du nombre d'elements non nuls sur chaque ligne
119 // Pour chaque ligne de la matrice carree, nombre d'elements non nuls
120 const int nb_elem = domaine_vdf.nb_elem();
121 const int nb_elem_tot = domaine_vdf.nb_elem_tot();
122 ArrOfInt carre_nb_non_zero(nb_elem);
123 // Idem pour le rectangle
124 ArrOfInt rect_nb_non_zero(nb_elem);
125 // Il y a l'element sur la diagonale :
126 carre_nb_non_zero = 1;
127 rect_nb_non_zero = 0;
128 int carre_nb_non_zero_tot = nb_elem;
129 int rect_nb_non_zero_tot = 0;
130
131 // Plus un element non nul pour chaque face interne et chaque face periodique
132 // (matrice symetrique, on ne stocke que l'element m(line,col) avec col>line)
133
134 ArrOfInt liste_faces_perio;
135 const int nb_faces_periodiques = liste_faces_periodiques(liste_faces_perio);
136 const int nb_faces_internes = domaine_vdf.nb_faces_internes();
137 const int premiere_face_interne = domaine_vdf.premiere_face_int();
138 for (i = 0; i < nb_faces_internes + nb_faces_periodiques; i++)
139 {
140 int face;
141 if (i < nb_faces_internes) // Astuce pour boucler sur les faces internes et periodiques
142 face = premiere_face_interne + i;
143 else
144 face = liste_faces_perio[i - nb_faces_internes];
145
146 int elem0 = face_voisins(face,0);
147 int elem1 = face_voisins(face,1);
148 if (elem0 > elem1)
149 {
150 int tmp = elem1;
151 elem1 = elem0;
152 elem0 = tmp;
153 }
154 if (elem0 < nb_elem) // elem0 est reel
155 {
156 if (elem1 < nb_elem) // elem1 reel
157 {
158 carre_nb_non_zero[elem0] ++;
159 carre_nb_non_zero_tot ++;
160 }
161 else // elem1 virtuel
162 {
163 rect_nb_non_zero[elem0] ++;
164 rect_nb_non_zero_tot ++;
165 }
166 }
167 }
168
169 // Typage et dimensionnement de la matrice de pression
170 la_matrice.typer("Matrice_Bloc");
171 Matrice_Bloc& matrice =ref_cast (Matrice_Bloc , la_matrice.valeur());
172 matrice.dimensionner(1,2);
173 matrice.get_bloc(0,0).typer("Matrice_Morse_Sym");
174 matrice.get_bloc(0,1).typer("Matrice_Morse");
175 Matrice_Morse_Sym& carre =ref_cast (Matrice_Morse_Sym, matrice.get_bloc(0,0).valeur());
176 Matrice_Morse& rect =ref_cast (Matrice_Morse , matrice.get_bloc(0,1).valeur());
177
178 carre.dimensionner(nb_elem, carre_nb_non_zero_tot);
179 rect.dimensionner(nb_elem, nb_elem_tot - nb_elem, rect_nb_non_zero_tot);
180
181 {
182 const int nb_faces_bord = domaine_vdf.nb_faces_bord();
183 les_coeff_pression_.resize_array(nb_faces_bord);
184 }
185 auto& carre_tab1 = carre.get_set_tab1();
186 auto& rect_tab1 = rect.get_set_tab1();
187
188 // Matrice creuse, stockage morse avec des indices fortran:
189 // lignes numerotees 1..n, colonnes 1..m
190 // Le k-ieme coefficient non nul de la ligne i (1<=i<=n) est (avec 1<=k)
191 // M(i,j) = coeff_[tab1_[k]] en fortran
192 // M(i,j) = coeff_[tab1_[k-1]-1] en C
193 // Le numero j de la colonne ou se trouve ce coefficient (1<=j<=m) est
194 // j = tab2_[tab1_[k]] en fortran
195 // j = tab2_[tab1_[k-1]-1] en C
196 //
197 // Calcul de l'indice du premier coefficient de la ligne i
198 // dans le tableau d'indices morse des deux matrices (tab1_)
199 {
200 int indice = 1; // tab1_ contient un indice fortran (1er element en 1)
201 for (i = 0; i < nb_elem; i++)
202 {
203 carre_tab1[i] = indice;
204 indice += carre_nb_non_zero[i];
205 }
206 carre_tab1[i] = indice;
207
208 indice = 1;
209 for (i = 0; i < nb_elem; i++)
210 {
211 rect_tab1[i] = indice;
212 indice += rect_nb_non_zero[i];
213 }
214 rect_tab1[i] = indice;
215 }
216
217 // Deuxieme etape : remplissage de tab2_ = numero de la colonne de chaque
218 // terme non nul de la matrice
219 auto& carre_tab2 = carre.get_set_tab2();
220 auto& rect_tab2 = rect.get_set_tab2();
221
222 carre_tab2 = -1;
223 rect_tab2 = -1;
224
225 // Terme diagonal:
226 for (i = 1; i <= nb_elem; i++)
227 carre_tab2[carre_tab1[i-1]-1] = i; // Indice fortran 1<=i<=nb_elem
228
229 carre_nb_non_zero = 1; // Nombre de coefficients non nuls sur chaque ligne
230 rect_nb_non_zero = 0;
231
232 // Termes extra-diagonaux:
233 for (int i_face = 0; i_face < nb_faces_internes + nb_faces_periodiques; i_face++)
234 {
235
236 // Calcul du numero de la face a traiter
237 const int face = (i_face < nb_faces_internes)
238 ? premiere_face_interne + i_face
239 : liste_faces_perio[i_face - nb_faces_internes];
240
241 int elem0 = face_voisins(face,0);
242 int elem1 = face_voisins(face,1);
243 if (elem0 > elem1)
244 {
245 int tmp = elem1;
246 elem1 = elem0;
247 elem0 = tmp;
248 }
249 assert(elem0 >= 0); // Verifie qu'on a bien deux elements voisins
250 if (elem0 < nb_elem) // elem0 est reel
251 {
252 const int ligne = elem0 + 1; // Indice fortran
253 if (elem1 < nb_elem) // elem1 est reel aussi
254 {
255 const int colonne = elem1 + 1; // Indice fortran
256 const int n = carre_nb_non_zero[ligne-1]++;
257 const int index = carre_tab1[ligne-1] + n; // Indice fortran dans tab2
258 carre_tab2[index - 1] = colonne;
259 }
260 else // elem1 est virtuel
261 {
262 const int colonne = elem1 - nb_elem + 1; // Indice fortran
263 const int n = rect_nb_non_zero[ligne-1]++;
264 const int index = rect_tab1[ligne-1] + n; // Indice fortran dans tab2
265 rect_tab2[index - 1] = colonne;
266 }
267 }
268 }
269
270 return 1;
271}
272
273/*! @brief Calcul des coefficients de la matrice de pression avec un champ de rho.
274 *
275 * Si rho_ptr == 0, on calcule la matrice -div( porosite * grad P ),
276 * sinon on calcule -div( porosite/rho grad P ) et *rho_ptr doit etre un Champ_Fonc_Face.
277 *
278 */
279int AssembleurPVDF_PF::remplir(Matrice& la_matrice, const Champ_Don_base * rho_ptr)
280{
281 const Domaine_VDF& domaine_vdf = le_dom_VDF_.valeur();
282 const IntTab& face_voisins = domaine_vdf.face_voisins();
283 const DoubleVect& face_surfaces = domaine_vdf.face_surfaces();
284 const DoubleVect& volumes_entrelaces = domaine_vdf.volumes_entrelaces();
285 const DoubleVect& porosite_face = le_dom_Cl_VDF_->equation().milieu().porosite_face();
286
287
288 const DoubleVect * valeurs_rho = 0;
289 if (rho_ptr)
290 {
291 assert(sub_type(Champ_Fonc_Face_VDF, *rho_ptr));
292 valeurs_rho = & (rho_ptr->valeurs());
293 }
294
295 // Raccourcis vers la partie carree (coefficients elements reels/reels)
296 // et la partie rectangulaire (elements reels / elements virtuels) de la matrice
297 Matrice_Bloc& matrice = ref_cast(Matrice_Bloc, la_matrice.valeur());
298 Matrice_Morse_Sym& carre = ref_cast(Matrice_Morse_Sym, matrice.get_bloc(0,0).valeur());
299 Matrice_Morse& rect = ref_cast(Matrice_Morse, matrice.get_bloc(0,1).valeur());
300
301 const int nb_elem = domaine_vdf.nb_elem();
302 ArrOfInt carre_nb_non_zero(nb_elem);
303 ArrOfInt rect_nb_non_zero(nb_elem);
304 carre_nb_non_zero = 1;
305 rect_nb_non_zero = 0;
306
307 auto& carre_tab1 = carre.get_set_tab1();
308 auto& rect_tab1 = rect.get_set_tab1();
309 auto& carre_coeff = carre.get_set_coeff();
310 auto& rect_coeff = rect.get_set_coeff();
311
312 carre_coeff = 0.;
313 rect_coeff = 0.;
314
315 // Traitement des faces internes et periodiques :
316 // Pour chaque face entre deux elements elem0 et elem1, y a quatre termes a ajouter :
317 // M(elem0,elem0)
318 // M(elem0,elem1)
319 // M(elem1,elem1)
320 // M(elem1,elem0) (omis car la matrice est stockee symetrique)
321
322 // Construction de la liste des faces periodiques
323 ArrOfInt liste_faces_perio;
324 const int nb_faces_periodiques = liste_faces_periodiques(liste_faces_perio);
325 const int nb_faces_internes = domaine_vdf.nb_faces_internes();
326 const int premiere_face_interne = domaine_vdf.premiere_face_int();
327 for (int i_face = 0; i_face < nb_faces_internes + nb_faces_periodiques; i_face++)
328 {
329
330 // Calcul du numero de la face a traiter
331 const int num_face = (i_face < nb_faces_internes)
332 ? premiere_face_interne + i_face
333 : liste_faces_perio[i_face - nb_faces_internes];
334 // Calcul de rho sur cette face
335 const double rho_face = (valeurs_rho) ? (*valeurs_rho)[num_face] : 1.;
336 // Calcul du coefficient
337 const double surface = face_surfaces[num_face];
338 const double volume = volumes_entrelaces[num_face];
339 const double porosite = porosite_face[num_face];
340 const double coefficient = surface * surface * porosite / (volume * rho_face);
341 // Numeros des deux elements voisins (le plus petit dans elem0)
342 int elem0 = face_voisins(num_face,0);
343 int elem1 = face_voisins(num_face,1);
344 if (elem0 > elem1)
345 {
346 int tmp = elem1;
347 elem1 = elem0;
348 elem0 = tmp;
349 }
350 if (elem0 < nb_elem)
351 {
352 // elem0 est reel
353 const int ligne = elem0 + 1; // Indice fortran
354 // Indice fortran de l'element diagonal (elem0, elem0)
355 const int index_diag = carre_tab1[ligne-1];
356 carre_coeff[index_diag - 1] += coefficient;
357 if (elem1 < nb_elem)
358 {
359 // elem1 est reel aussi
360 // Indice fortran de l'element diagonal (elem1, elem1)
361 const int index_diag1 = carre_tab1[elem1]; // a la ligne elem1+1
362 // Indice fortran de l'element extradiagonal (elem0, elem1)
363 const int n = carre_nb_non_zero[ligne-1]++;
364 const int index = index_diag + n;
365 // Coefficient diagonal
366 carre_coeff[index_diag1 - 1] += coefficient;
367 // Coefficient extra-diagonal
368 carre_coeff[index - 1] = - coefficient;
369 assert(carre.get_set_tab2()[index - 1] == elem1 + 1);
370 }
371 else
372 {
373 // elem1 est virtuel
374 const int n = rect_nb_non_zero[ligne-1]++;
375 const int index = rect_tab1[ligne-1] + n; // Indice fortran dans tab2
376 // Coefficient extra-diagonal
377 rect_coeff[index - 1] = - coefficient;
378 assert(rect.get_set_tab2()[index - 1] == elem1 - nb_elem + 1);
379 }
380 }
381 }
382
383 // Traitement des conditions aux limites
384 const Conds_lim& les_cl = le_dom_Cl_VDF_->les_conditions_limites();
385 const int nb_cl = les_cl.size();
386 for (int num_cl = 0; num_cl < nb_cl; num_cl++)
387 {
388 const Cond_lim_base& la_cl = les_cl[num_cl].valeur();
389
390 // Pour chaque face de bord entre elem0 et un element fictif exterieur
391 // a pression imposee P0, on a :
392 // grad P = (P(elem0) - P0) * surface / volume_entrelace
393 // elem0 est une inconnue, P0 est ajoute au second membre dans "modifier_secmem".
394
395 if (sub_type(Neumann_sortie_libre,la_cl))
396 {
397 has_P_ref_ = 1;
398 carre.set_est_definie(1);
399 const Front_VF& la_front_dis = ref_cast(Front_VF,la_cl.frontiere_dis());
400 const int ndeb = la_front_dis.num_premiere_face();
401 const int nfin = ndeb + la_front_dis.nb_faces();
402
403 for (int num_face = ndeb; num_face < nfin; num_face++)
404 {
405 // Calcul de rho sur cette face
406 const double rho_face = (valeurs_rho) ? (*valeurs_rho)[num_face] : 1.;
407 // Calcul du coefficient a ajouter dans la matrice
408 const double surface = face_surfaces[num_face];
409 // Attention: le volume entrelace a une valeur particuliere au bord
410 // (voir Domaine_VDF::calculer_volumes_entrelaces() )
411 const double volume = volumes_entrelaces[num_face];
412 const double porosite = porosite_face[num_face];
413 const double coefficient = surface * surface * porosite / (volume * rho_face);
414 assert(coefficient > 0.);
415 // Numero de l'element voisin (l'un est -1, l'autre est un element reel)
416 const int elem0 = face_voisins(num_face, 0);
417 const int elem1 = face_voisins(num_face, 1);
418 assert(elem0 == -1 || elem1 == -1);
419 const int elem = elem0 + elem1 + 1;
420 // Ajout du coefficient a la matrice
421 assert(elem < nb_elem);
422 const int index = carre_tab1[elem]; // Indice fortran
423 carre_coeff[index - 1] += coefficient;
424 les_coeff_pression_[num_face] = coefficient;
425 }
426 }
427 else
428 {
429 // Pour les autres conditions aux limites, aucun terme supplementaire dans
430 // la matrice (grad P scalaire n = 0 sur le bord,
431 // ou derivee en temps de grad P scalaire n = 0 sur le bord)
432 }
433 }
434
435 // Verification sanitaire: pas d'element nul sur la diagonale
436 for (int i = 0; i < nb_elem; i++)
437 {
438 const int index = carre_tab1[i];
439 const double coeff_diagonal = carre_coeff[index - 1];
440 if (coeff_diagonal == 0.)
441 {
442 // La maille i n'a pas de voisin: pression quelconque
443 carre_coeff[index - 1] = 1.;
444 }
445 }
446 return 1;
447}
448
449/*! @brief Modification du second membre pour appliquer les conditions aux limites.
450 *
451 * Les conditions prises en charge sont
452 * Neumann_sortie_libre,
453 * Entree_fluide_vitesse_imposee,
454 * Dirichlet_paroi_defilante (rien a faire),
455 * Dirichlet_paroi_fixe (rien a faire),
456 * Symetrie (rien a faire)
457 *
458 */
460{
461 const Domaine_Cl_VDF& le_dom_cl = le_dom_Cl_VDF_.valeur();
462 int nb_cond_lim = le_dom_cl.nb_cond_lim();
463
464 for (int indice_cl = 0; indice_cl < nb_cond_lim; indice_cl++)
465 {
466 const Cond_lim_base& la_cl_base =
467 le_dom_cl.les_conditions_limites(indice_cl).valeur();
468
469 const Front_VF& frontiere_vf = ref_cast(Front_VF, la_cl_base.frontiere_dis());
470
471 if (sub_type(Neumann_sortie_libre, la_cl_base))
472 {
474 frontiere_vf,
475 secmem);
476 }
477 else if (sub_type(Entree_fluide_vitesse_imposee, la_cl_base))
478 {
480 frontiere_vf,
481 secmem);
482 }
483 else if (sub_type(Dirichlet_paroi_defilante, la_cl_base))
484 {
485 // Pour une paroi defilante, rien a faire.
486 }
487 else if (sub_type(Dirichlet_paroi_fixe, la_cl_base))
488 {
489 // Rien a faire non plus.
490 }
491 else if (sub_type(Symetrie, la_cl_base))
492 {
493 // Encore rien a faire
494 }
495 else if (sub_type(Periodique, la_cl_base))
496 {
497 // Rien a faire
498 }
499 else
500 {
501 Cerr << "Erreur dans Assembleur_P_VDF::modifier_secmem\n la condition aux limites ";
502 Cerr << la_cl_base.que_suis_je() << " n'est pas prise en charge." << finl;
503 assert(0);
505 }
506 }
507 secmem.echange_espace_virtuel();
508 return 1;
509}
510
511/*! @brief Modification du second membre du solveur en pression pour une condition "Neumann_sortie_libre".
512 *
513 * Calcul en "increment de pression" :
514 * ajouter l'increment de pression, c'est a dire zero (c.l. instationnaire non supportee)
515 * Calcul en "pression" :
516 * Ajout du terme Pimpose * surface / volume_entrelace au second membre dans la discretisation de la
517 * pression au bord (entre un element elem0 et un element fictif exterieur a pression imposee) :
518 * grad P = (P(elem0) - Pimpose) * surface / volume_entrelace
519 *
520 */
522 const Front_VF& frontiere_vf,
523 DoubleTab& secmem)
524{
525 const Champ_front_base& champ_front = cond_lim.champ_front();
526 const Domaine_VDF& le_dom = le_dom_VDF_.valeur();
527 const IntTab& face_voisins = le_dom.face_voisins();
528
530 {
531 if (sub_type(Champ_front_instationnaire_base, champ_front)
532 || sub_type(Champ_front_var_instationnaire, champ_front))
533 {
534 Cerr << "Erreur dans Assembleur_P_VDF::modifier_secmem_pression_imposee\n ";
535 Cerr << champ_front.que_suis_je();
536 Cerr << " + resoudre_increment_pression non code" << finl;
537 assert(0);
539 }
540 else
541 {
542 // Champ stationnaire, on ajoute un increment de pression nul.
543 // Donc rien a faire.
544 }
545 }
546 else
547 {
548 const int nb_faces = frontiere_vf.nb_faces();
549 const int num_premiere_face = frontiere_vf.num_premiere_face();
550 for (int i = 0; i < nb_faces; i++)
551 {
552 const int num_face = num_premiere_face + i;
553 const double Pimp = cond_lim.flux_impose(i);
554 const double coef = les_coeff_pression_[num_face] * Pimp;
555 const int elem = face_voisins(num_face, 0) + face_voisins(num_face, 1) + 1;
556 secmem[elem] += coef;
557 }
558 }
559}
560
561/*! @brief Modification du second membre du systeme en pression pour une condition aux limites de vitesse imposee.
562 *
563 * Si on resout en increment de pression, ...
564 * sinon rien a faire.
565 *
566 */
568 const Front_VF& frontiere_vf,
569 DoubleTab& secmem)
570{
571 const Champ_front_base& champ_front = cond_lim.champ_front();
572 const Domaine_VDF& le_dom = le_dom_VDF_.valeur();
573 const DoubleVect& face_surfaces = le_dom.face_surfaces();
574 const IntTab& face_voisins = le_dom.face_voisins();
575
577 {
578 if (champ_front.instationnaire())
579 {
580 const DoubleTab& tab_gpoint = champ_front.derivee_en_temps();
581 bool ch_unif = (tab_gpoint.nb_dim()==1);
582 const int nb_faces = frontiere_vf.nb_faces();
583 const int num_premiere_face = frontiere_vf.num_premiere_face();
584 for (int i = 0; i < nb_faces; i++)
585 {
586 const int num_face = num_premiere_face + i;
587 const double surface = face_surfaces(num_face);
588 const int elem0 = face_voisins(num_face, 0);
589 const int elem1 = face_voisins(num_face, 1);
590 // gpoint est relatif a la normale a la face (elle pointe vers elem1)
591 // La normale est-elle entrante ou sortante ?
592 const double signe = (elem0 < 0) ? 1. : -1.;
593 // Numero de l'element adjacent a la face de bord
594 const int elem = elem0 + elem1 + 1;
595 const int ori = le_dom.orientation(num_face);
596 const double gpoint = ch_unif ? tab_gpoint(ori) : tab_gpoint(i, ori);
597
598 secmem[elem] += signe * surface * gpoint;
599 }
600 }
601 else
602 {
603 // Le champ frontiere est stationnaire, rien a faire.
604 }
605 }
606 else
607 {
608 // Resolution en pression: la condition aux limites est imposee ailleurs
609 }
610}
611
613{
614 // Projection :
615 double press_0;
616 if(!has_P_ref_)
617 {
618 // On prend la pression minimale comme pression de reference
619 // afin d'avoir la meme pression de reference en sequentiel et parallele
620 press_0=DMAXFLOAT;
621 int nb_elem=le_dom_VDF_->domaine().nb_elem();
622 for(int n=0; n<nb_elem; n++)
623 if (pression[n] < press_0)
624 press_0 = pression[n];
625 press_0 = mp_min(press_0);
626 pression -=press_0;
627 pression.echange_espace_virtuel();
628 }
629 return 1;
630}
631
632/*! @brief Assemblage de la matrice de pression M telle que M*P = div(porosite * grad (P))
633 *
634 * et calcul des coefficients pour modifier_secmem.
635 *
636 */
638{
639 // if (je_suis_maitre())
640 // Cerr << "Assemblage de la matrice pression : Assembleur_P_VDF_PF::assembler" << finl;
641 // Par defaut, resolution en increment de pression
643 construire(matrice);
644 remplir(matrice, 0);
645 return 1;
646}
647
648/*! @brief Assemblage de la matrice de pression M telle que M*P = div(porosite/rho * grad (P))
649 *
650 * et calcul des coefficients pour modifier_secmem.
651 *
652 * @param (matrice) La matrice a assembler. Contrainte: Soit la matrice n'est pas encore typee (alors on la "construit"), soit c'est la meme que lors de l'appel precedent.
653 * @param (rho)
654 */
656 const Champ_Don_base& rho)
657{
658 // assembler_rho_variable a ete introduit pour le front-tracking:
659 // il faut dire explicitement si on resout en increment de pression
660 assert(get_resoudre_increment_pression() >= 0);
661 // Si la matrice n'a pas encore ete typee, il faut la construire :
662 if (!matrice)
663 {
664 if (je_suis_maitre())
665 {
666 Cerr << "Assemblage de la matrice pression : ";
667 Cerr << "Assembleur_P_VDF_PF::assembler_rho_variable" << finl;
668 }
669 construire(matrice);
670 }
671 // Cerr << "Assemblage matrice pression (rho variable)" << finl;
672 remplir(matrice, & rho);
673 return 1;
674}
675
676/*! @brief Assemble la matrice de pression pour un fluide quasi compressible.
677 *
678 * La matrice M est telle que M*P = div( porosite * grad(P) ).
679 * Le drapeau resoudre_increment_pression est mis a zero s'il n'a pas
680 * encore ete assigne.
681 *
682 * @param (DoubleTab& tab_rho) mass volumique
683 * @return (int) renvoie toujours 1
684 */
685int AssembleurPVDF_PF::assembler_QC(const DoubleTab& tab_rho, Matrice& matrice)
686{
687 // Par defaut pour le qc: resolution en pression et pas en increment pression.
690 if (!matrice)
691 {
692 if (je_suis_maitre())
693 {
694 Cerr << "Assemblage de la matrice pression : ";
695 Cerr << "Assembleur_P_VDF::assembler_QC" << finl;
696 }
697 construire(matrice);
698 remplir(matrice, 0);
699
700 Matrice_Bloc& matrice_bloc =ref_cast (Matrice_Bloc,matrice.valeur());
701 Matrice_Morse_Sym& la_matrice = ref_cast(Matrice_Morse_Sym,matrice_bloc.get_bloc(0,0).valeur());
702
703 if (la_matrice.get_est_definie()!=1)
704 {
705 if ((je_suis_maitre()) && (la_matrice.nb_lignes()==0) && (la_matrice.nb_colonnes()==0))
706 {
707 Cerr<<"Pressure matrix will not be defined."<<finl;
709 }
710 if ((la_matrice.nb_lignes()>0) && (la_matrice.nb_colonnes()>0))
711 {
712 Cerr<<"la_matrice(0,0)"<<la_matrice(0,0)<<finl;
713 //assert(0);
714 Cerr<<"Pas de pression imposee --> P(0)=0"<<finl;
715 if (je_suis_maitre()) la_matrice(0,0) *= 2;
716 }
717 la_matrice.set_est_definie(1);
718 }
719 }
720 return 1;
721}
722
724{
725 return le_dom_VDF_.valeur();
726}
727
729{
730 return le_dom_Cl_VDF_.valeur();
731}
732
734{
735 le_dom_VDF_ = ref_cast(Domaine_VDF, le_dom_dis);
736}
737
739{
740 le_dom_Cl_VDF_ = ref_cast(Domaine_Cl_VDF, le_dom_Cl_dis);
741}
742
744{
745 // CCa 30/04/99 : je ne sais pas si je dois faire qqchose
746 ;
747}
const Domaine_dis_base & domaine_dis_base() const override
int liste_faces_periodiques(ArrOfInt &faces)
Remplit le tableau faces avec la liste des indices des faces periodiques dans le tableau faces_voisin...
void completer(const Equation_base &) override
ArrOfDouble les_coeff_pression_
int assembler_rho_variable(Matrice &, const Champ_Don_base &rho) override
Assemblage de la matrice de pression M telle que M*P = div(porosite/rho * grad (P)).
const Domaine_Cl_dis_base & domaine_Cl_dis_base() const override
int assembler_QC(const DoubleTab &, Matrice &) override
Assemble la matrice de pression pour un fluide quasi compressible.
int assembler(Matrice &) override
Assemblage de la matrice de pression M telle que M*P = div(porosite * grad (P)).
void modifier_secmem_pression_imposee(const Neumann_sortie_libre &cond_lim, const Front_VF &frontiere_vf, DoubleTab &secmem)
Modification du second membre du solveur en pression pour une condition "Neumann_sortie_libre".
void modifier_secmem_vitesse_imposee(const Entree_fluide_vitesse_imposee &cond_lim, const Front_VF &frontiere_vf, DoubleTab &secmem)
Modification du second membre du systeme en pression pour une condition aux limites de vitesse impose...
void associer_domaine_dis_base(const Domaine_dis_base &) override
int modifier_secmem(DoubleTab &) override
Modification du second membre pour appliquer les conditions aux limites.
int construire(Matrice &la_matrice)
Determine les elements non nuls de la matrice et prepare le stockage.
int modifier_solution(DoubleTab &) override
int remplir(Matrice &la_matrice, const Champ_Don_base *rho_ptr)
Calcul des coefficients de la matrice de pression avec un champ de rho.
void associer_domaine_cl_dis_base(const Domaine_Cl_dis_base &) override
int get_resoudre_increment_pression() const
Renvoie la valeur du drapeau resoudre_increment_pression_ (0 ou 1) Renvoie -1 si le drapeau n'a pas e...
int set_resoudre_increment_pression(int flag)
Definit la valeur du drapeau resoudre_increment_pression_.
classe Champ_Don_base classe de base des Champs donnes (non calcules)
DoubleTab & valeurs() override
Surcharge Champ_base::valeurs() Renvoie le tableau des valeurs.
classe Champ_Fonc_Face_VDF
classe Champ_front_base Classe de base pour la hierarchie des champs aux frontieres.
virtual const DoubleTab & derivee_en_temps() const
virtual bool instationnaire() const
classe Champ_front_base Classe de base pour les Champs aux frontieres instationnaires,
classe Champ_front_var_instationnaire Classe derivee de Champ_front_var qui represente les champs aux
classe Cond_lim_base Classe de base pour la hierarchie des classes qui representent les differentes c...
virtual Frontiere_dis_base & frontiere_dis()
Renvoie la frontiere discretisee a laquelle les conditions aux limites s'appliquent.
Champ_front_base & champ_front()
classe Conds_lim Cette classe represente un vecteur de conditions aux limites.
Definition Conds_lim.h:32
classe Dirichlet_paroi_defilante Impose la vitesse de paroi dnas une equation de type Navier_Stokes.
classe Dirichlet_paroi_fixe Represente une paroi immobile dans une equation de type Navier_Stokes.
class Domaine_Cl_VDF
classe Domaine_Cl_dis_base Les objets Domaine_Cl_dis_base representent les conditions aux limites
int nb_cond_lim() const
Renvoie le nombre de conditions aux limites.
const Cond_lim & les_conditions_limites(int) const
Renvoie la i-ieme condition aux limites.
class Domaine_VDF
Definition Domaine_VDF.h:64
int orientation(int) const override
inline DoubleVect& Domaine_VDF::porosite_face() {
virtual const DoubleVect & face_surfaces() const
Definition Domaine_VF.h:51
DoubleVect & volumes_entrelaces()
Definition Domaine_VF.h:99
int nb_faces_internes() const
une face est interne ssi elle separe deux elements.
Definition Domaine_VF.h:533
int premiere_face_int() const
une face est interne ssi elle separe deux elements.
Definition Domaine_VF.h:463
int face_voisins(int num_face, int i) const
renvoie l'element voisin de numface dans la direction i.
Definition Domaine_VF.h:418
int nb_faces_bord() const
renvoie le nombre de faces sur lesquelles sont appliquees les conditions limites :
Definition Domaine_VF.h:513
classe Domaine_dis_base Cette classe est la base de la hierarchie des domaines discretisees.
int nb_elem_tot() const
classe Entree_fluide_vitesse_imposee Cas particulier de la classe Dirichlet_entree_fluide
Class defining operators and methods for all reading operation in an input flow (file,...
Definition Entree.h:42
classe Equation_base Le role d'une equation est le calcul d'un ou plusieurs champs....
class Front_VF
Definition Front_VF.h:36
int nb_faces() const
Definition Front_VF.h:53
int num_premiere_face() const
Definition Front_VF.h:63
virtual void dimensionner(int N, int M)
virtual const Matrice & get_bloc(int i, int j) const
Classe Matrice_Morse_Sym Represente une matrice M (creuse) symetrique stockee au format Morse.
Classe Matrice_Morse Represente une matrice M (creuse), non necessairement carree.
auto & get_set_tab2()
void dimensionner(int n, _SIZE_ nnz)
Size the matrix with n lines and n columns and nnz zero-values coefficients.
auto & get_set_coeff()
int nb_colonnes() const override
Return local number of columns (=size on the current proc).
auto & get_set_tab1()
int nb_lignes() const override
Return local number of lines (=size on the current proc).
void set_est_definie(int)
int get_est_definie() const
Classe Matrice Classe generique de la hierarchie des matrices.
Definition Matrice.h:34
classe Neumann_sortie_libre Cette classe represente une frontiere ouverte sans vitesse imposee
virtual double flux_impose(int i) const
Renvoie la valeur du flux impose sur la i-eme composante du champ representant le flux a la frontiere...
Definition Neumann.cpp:35
const Nom & que_suis_je() const
renvoie la chaine identifiant la classe.
Definition Objet_U.cpp:104
virtual Entree & readOn(Entree &)
Lecture d'un Objet_U sur un flot d'entree Methode a surcharger.
Definition Objet_U.cpp:293
virtual const Nom & le_nom() const
Donne le nom de l'Objet_U Methode a surcharger : renvoie "neant" dans cette implementation.
Definition Objet_U.cpp:319
virtual Sortie & printOn(Sortie &) const
Ecriture de l'objet sur un flot de sortie Methode a surcharger.
Definition Objet_U.cpp:282
classe Periodique Cette classe represente une condition aux limites periodique.
Definition Periodique.h:31
int face_associee(int i) const
Definition Periodique.h:35
static double mp_min(double)
Definition Process.cpp:386
static void exit(int exit_code=-1)
Routine de sortie de TRUST dans une region Kokkos.
Definition Process.cpp:455
static int je_suis_maitre()
renvoie 1 si on est sur le processeur maitre du groupe courant (c'est a dire me() == 0),...
Definition Process.cpp:86
Classe de base des flux de sortie.
Definition Sortie.h:52
classe Symetrie Sur les faces de symetrie on a les proprietes suivantes:
Definition Symetrie.h:37
void resize_array(_SIZE_ new_size, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT)
int nb_dim() const
Definition TRUSTTab.h:199
virtual void echange_espace_virtuel(IsExchangeBlocking exchange_type=IsExchangeBlocking::DefaultBlocking, const std::string kernel_name="noname")