TRUST 1.9.8
HPC thermohydraulic platform
Loading...
Searching...
No Matches
Op_Dift_Stab_VEF_Face.cpp
1/****************************************************************************
2* Copyright (c) 2024, 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 <Modele_turbulence_scal_base.h>
17#include <Echange_externe_impose.h>
18#include <Op_Dift_Stab_VEF_Face.h>
19#include <Scalaire_impose_paroi.h>
20#include <Neumann_sortie_libre.h>
21#include <Check_espace_virtuel.h>
22#include <Dirichlet_homogene.h>
23#include <Neumann_homogene.h>
24#include <Porosites_champ.h>
25#include <Neumann_paroi.h>
26#include <Periodique.h>
27#include <Champ_P1NC.h>
28#include <TRUSTTrav.h>
29#include <Dirichlet.h>
30#include <Symetrie.h>
31#include <Debog.h>
32
33Implemente_instanciable(Op_Dift_Stab_VEF_Face, "Op_Dift_VEF_P1NC_stab", Op_Dift_VEF_base);
34// XD diffusion_stab diffusion_deriv stab BRACE keyword allowing consistent and stable calculations even in case of
35// XD_CONT obtuse angle meshes.
36// XD attr standard entier standard OPT to recover the same results as calculations made by standard laminar diffusion
37// XD_CONT operator. However, no stabilization technique is used and calculations may be unstable when working with
38// XD_CONT obtuse angle meshes (by default 0)
39// XD attr info entier info OPT developer option to get the stabilizing ratio (by default 0)
40// XD attr new_jacobian entier new_jacobian OPT when implicit time schemes are used, this option defines a new jacobian
41// XD_CONT that may be more suitable to get stationary solutions (by default 0)
42// XD attr nu entier nu OPT (respectively nut 1) takes the molecular viscosity (resp. eddy viscosity) into account in
43// XD_CONT the velocity gradient part of the diffusion expression (by default nu=1 and nut=1)
44// XD attr nut entier nut OPT not_set
45// XD attr nu_transp entier nu_transp OPT (respectively nut_transp 1) takes the molecular viscosity (resp. eddy
46// XD_CONT viscosity) into account in the transposed velocity gradient part of the diffusion expression (by default
47// XD_CONT nu_transp=0 and nut_transp=1)
48// XD attr nut_transp entier nut_transp OPT not_set
49
50double my_minimum(double a, double b, double c)
51{
52 if (a <= b) return (a <= c) ? a : c;
53 else if (b <= c) return b;
54 else return c;
55}
56
57double my_maximum(double a, double b, double c)
58{
59 if (a >= b) return (a >= c) ? a : c;
60 else if (b >= c) return b;
61 else return c;
62}
63
64double my_minimum(double a, double b)
65{
66 return (a <= b) ? a : b;
67}
68
69double my_maximum(double a, double b)
70{
71 return (a >= b) ? a : b;
72}
73
74Sortie& Op_Dift_Stab_VEF_Face::printOn(Sortie& s) const { return s << que_suis_je(); }
75
77{
78 Motcle accouverte = "{", accfermee = "}", motlu;
79 Motcles les_mots(6);
80 {
81 les_mots[0] = "nu";
82 les_mots[1] = "nut";
83 les_mots[2] = "nu_transp";
84 les_mots[3] = "nut_transp";
85 les_mots[4] = "standard";
86 les_mots[5] = "new_jacobian";
87 }
88
89 is >> motlu;
90 if (motlu != accouverte)
91 Process::exit("Error in Op_Dift_Stab_VEF_Face::readOn(). Option keywords must be preceded by an open brace { !");
92
93 is >> motlu;
94 while (motlu != accfermee)
95 {
96 int rang = les_mots.search(motlu);
97 switch(rang)
98 {
99 case 0:
100 is >> nu_lu_;
101 break;
102 case 1:
103 is >> nut_lu_;
104 break;
105 case 2:
106 is >> nu_transp_lu_;
107 break;
108 case 3:
109 is >> nut_transp_lu_;
110 break;
111 case 4:
112 is >> standard_;
113 break;
114 case 5:
115 is >> new_jacobian_;
116 break;
117 default:
118 Cerr << "Error in Op_Dift_Stab_VEF_Face::readOn(). Word " << motlu << " is unknown !" << finl;
119 Cerr << "Known keywords are : " << les_mots << finl;
121 break;
122 }
123 is >> motlu;
124 }
125
126 is >> motlu;
127 if (motlu != accfermee)
128 {
129 Cerr << "Error in Op_Dift_Stab_VEF_Face::readOn(). Final known keyword is the closing brace sign } !" << finl;
131 }
132
133 return is;
134}
135
136/*
137 * METHODES GENERIQUES
138 */
139
140inline double aij_extradiag__(const Op_Dift_Stab_VEF_Face& z_class, const int elem, const int facei, const int facej, const int dim, const int dim2, const double nu_elem)
141{
142 const Domaine_VEF& domaine_VEF = z_class.domaine_vef();
143 const IntTab& face_voisins = domaine_VEF.face_voisins();
144 const DoubleTab& face_normales = domaine_VEF.face_normales();
145 const DoubleVect& volumes = domaine_VEF.volumes();
146
147 double volume = 0., signei = 1., signej = 1., aij = 0.;
148
149 assert(dim < z_class.equation().inconnue().valeurs().dimension(1));
150 assert(dim2 < z_class.equation().inconnue().valeurs().dimension(1));
151 assert(dim < dim2);
152
153 volume = 1. / volumes(elem);
154 volume *= nu_elem;
155
156 if (face_voisins(facei, 0) != elem) signei = -1.;
157 if (face_voisins(facej, 0) != elem) signej = -1.;
158
159 aij = face_normales(facei, dim2) * face_normales(facej, dim);
160 aij *= signei * signej;
161 aij *= volume;
162
163 return aij;
164}
165
166template <Type_Champ _TYPE_>
167void ajouter_operateur_centre__(const Op_Dift_Stab_VEF_Face& z_class, const DoubleTab& Aij_diag, const DoubleTab& nu, const DoubleTab& inconnue, DoubleTab& resu)
168{
169 constexpr bool is_VECT = (_TYPE_ == Type_Champ::VECTORIEL);
170
171 const Domaine_VEF& domaine_VEF = z_class.domaine_vef();
172 const IntTab& elem_faces = domaine_VEF.elem_faces();
173 const int nb_elem_tot = domaine_VEF.nb_elem_tot(), nb_faces_elem = domaine_VEF.domaine().nb_faces_elem(), nb_comp = resu.line_size();
174 double nu_elem = 0., aij = 0.;
175
176 for (int elem = 0; elem < nb_elem_tot; elem++)
177 {
178 if (is_VECT) nu_elem = nu(elem);
179
180 for (int facei_loc = 0; facei_loc < nb_faces_elem; facei_loc++)
181 {
182 const int facei = elem_faces(elem, facei_loc);
183
184 // Ajout de la partie diagonale : on tient compte de la symetrie de la matrice Aij_diag
185 for (int facej_loc = facei_loc + 1; facej_loc < nb_faces_elem; facej_loc++)
186 {
187 const int facej = elem_faces(elem, facej_loc);
188
189 if (!is_VECT) aij = Aij_diag(elem, facei_loc, facej_loc);
190
191 for (int nc = 0; nc < nb_comp; nc++)
192 {
193 if (is_VECT) aij = Aij_diag(elem, facei_loc, facej_loc, nc);
194
195 const double delta_ij = aij * (inconnue(facej, nc) - inconnue(facei, nc));
196 resu(facei, nc) += delta_ij;
197 resu(facej, nc) -= delta_ij;
198 }
199 }
200
201 //Ajout de la partie extra-diagonale : on tient compte de la symetrie de la partie extradiagonale de la matrice du laplacien
202 if (is_VECT)
203 for (int facej_loc = 0; facej_loc < nb_faces_elem; facej_loc++)
204 if (facej_loc != facei_loc)
205 {
206 const int facej = elem_faces(elem, facej_loc);
207
208 for (int nc = 0; nc < nb_comp; nc++)
209 for (int nc2 = nc + 1; nc2 < nb_comp; nc2++)
210 {
211 aij = aij_extradiag__(z_class, elem, facei, facej, nc, nc2, nu_elem);
212
213 double delta_ij = aij * (inconnue(facej, nc2) - inconnue(facei, nc2));
214 resu(facei, nc) += delta_ij;
215
216 delta_ij = aij * (inconnue(facej, nc) - inconnue(facei, nc));
217 resu(facej, nc2) -= delta_ij;
218 }
219 }
220 }
221 }
222}
223
224template <Type_Champ _TYPE_>
225void calculer_coefficients__(const Op_Dift_Stab_VEF_Face& z_class, const DoubleTab& nu, const DoubleTab& nu2 /* transpose */ , DoubleTab& Aij)
226{
227 constexpr bool is_VECT = (_TYPE_ == Type_Champ::VECTORIEL);
228
229 const Domaine_VEF& domaine_VEF = z_class.domaine_vef();
230 const IntTab& elem_faces = domaine_VEF.elem_faces(), &face_voisins = domaine_VEF.face_voisins();
231 const DoubleTab& face_normales = domaine_VEF.face_normales();
232 const DoubleVect& volumes = domaine_VEF.volumes();
233 const int nb_elem_tot = domaine_VEF.nb_elem_tot(), nb_faces_elem = domaine_VEF.domaine().nb_faces_elem(),
234 nb_comp = z_class.equation().inconnue().valeurs().line_size();
235
236 assert(Aij.dimension(0) == nb_elem_tot);
237 assert(Aij.dimension(1) == nb_faces_elem);
238 assert(Aij.dimension(2) == nb_faces_elem);
239
240 if (is_VECT)
241 {
242 assert(nb_comp == Objet_U::dimension);
243 assert(Aij.nb_dim() == 4);
244 assert(Aij.dimension(3) == nb_comp);
245 }
246 else
247 assert(Aij.nb_dim() == 3);
248
249 double nu2_elem = 0.;
250
251 for (int elem = 0; elem < nb_elem_tot; elem++)
252 {
253 double volume = 1. / volumes(elem);
254
255 double nu_elem = nu(elem);
256 nu_elem *= volume;
257
258 if (is_VECT)
259 {
260 nu2_elem = nu2(elem); // transpose
261 nu2_elem *= volume;
262 }
263
264 for (int facei_loc = 0; facei_loc < nb_faces_elem; facei_loc++)
265 {
266 const int facei = elem_faces(elem, facei_loc);
267
268 int signei = 1;
269 if (face_voisins(facei, 0) != elem) signei = -1;
270
271 for (int facej_loc = facei_loc + 1; facej_loc < nb_faces_elem; facej_loc++)
272 {
273 const int facej = elem_faces(elem, facej_loc);
274
275 int signej = 1;
276 if (face_voisins(facej, 0) != elem) signej = -1;
277
278 //Partie standard
279 double psc = 0.;
280 for (int dim = 0; dim < Objet_U::dimension; dim++)
281 psc += face_normales(facei, dim) * face_normales(facej, dim);
282
283 psc *= signei * signej;
284 psc *= nu_elem;
285
286 if (!is_VECT) // scalaire
287 {
288 Aij(elem, facei_loc, facej_loc) = psc;
289 Aij(elem, facej_loc, facei_loc) = psc;
290 }
291 else
292 {
293 for (int dim = 0; dim < nb_comp; dim++)
294 {
295 Aij(elem, facei_loc, facej_loc, dim) = psc;
296 Aij(elem, facej_loc, facei_loc, dim) = psc;
297 }
298
299 //Partie transposee
300 for (int dim = 0; dim < nb_comp; dim++)
301 {
302 psc = face_normales(facei, dim) * face_normales(facej, dim);
303 psc *= signei * signej;
304 psc *= nu2_elem;
305
306 Aij(elem, facei_loc, facej_loc, dim) += psc;
307 Aij(elem, facej_loc, facei_loc, dim) += psc;
308 }
309 }
310 }
311 }
312 }
313}
314
315/*
316 * FIN METHODES GENERIQUES
317 */
318
319void Op_Dift_Stab_VEF_Face::ajouter_diffusion(const DoubleTab& Aij, const DoubleTab& inconnueTab, DoubleTab& resuTab, const bool is_VECT) const
320{
321 const Domaine_VEF& domaine_VEF = domaine_vef();
322 const IntTab& elem_faces = domaine_VEF.elem_faces();
323 const int nb_elem_tot = domaine_VEF.nb_elem_tot(), nb_faces_elem = domaine_VEF.domaine().nb_faces_elem(), nb_comp = resuTab.line_size();
324 const DoubleVect& inconnue = inconnueTab;
325 DoubleVect& resu = resuTab;
326 int elem = 0, facei_loc = 0, facei = 0, facej_loc = 0, facej = 0, dim = 0;
327 double inc_i = 0., inc_j = 0., delta_ij = 0., dij = 0.;
328
329 for (elem = 0; elem < nb_elem_tot; elem++)
330 for (facei_loc = 0; facei_loc < nb_faces_elem; facei_loc++)
331 {
332 facei = elem_faces(elem, facei_loc);
333 for (facej_loc = facei_loc + 1; facej_loc < nb_faces_elem; facej_loc++)
334 {
335 facej = elem_faces(elem, facej_loc);
336 if (is_VECT) // eq QDM
337 for (dim = 0; dim < nb_comp; dim++)
338 {
339 const double aij = Aij(elem, facei_loc, facej_loc, dim);
340 if (aij > 0.)
341 {
342 dij = -aij;
343
344 inc_i = inconnue[facei * nb_comp + dim];
345 inc_j = inconnue[facej * nb_comp + dim];
346 delta_ij = dij * (inc_j - inc_i);
347
348 resu[facei * nb_comp + dim] += delta_ij;
349 resu[facej * nb_comp + dim] -= delta_ij;
350 }
351 }
352 else
353 {
354 const double aij = Aij(elem, facei_loc, facej_loc);
355 if (aij > 0.)
356 {
357 dij = -aij;
358 for (dim = 0; dim < nb_comp; dim++)
359 {
360 inc_i = inconnue[facei * nb_comp + dim];
361 inc_j = inconnue[facej * nb_comp + dim];
362 delta_ij = dij * (inc_j - inc_i);
363
364 resu[facei * nb_comp + dim] += delta_ij;
365 resu[facej * nb_comp + dim] -= delta_ij;
366 }
367 }
368 }
369 }
370 }
371}
372
373void Op_Dift_Stab_VEF_Face::ajouter_antidiffusion(const DoubleTab& Aij, const DoubleTab& inconnueTab, DoubleTab& resuTab, const bool is_VECT) const
374{
375 const Domaine_VEF& domaine_VEF = domaine_vef();
376 const DoubleTab& xv = domaine_VEF.xv();
377 const IntTab& elem_faces = domaine_VEF.elem_faces();
378 const int nb_elem_tot = domaine_VEF.nb_elem_tot(), nb_faces_tot = domaine_VEF.nb_faces_tot(),
379 nb_faces_elem = domaine_VEF.domaine().nb_faces_elem(), nb_comp = resuTab.line_size();
380
381 const DoubleVect& inconnue = inconnueTab;
382 DoubleVect& resu = resuTab;
383
384 DoubleTab rij(Objet_U::dimension), rji(rij);
385
386 int elem = 0, facei_loc = 0, facei = 0, facej_loc = 0, facej = 0, dim = 0, dim2 = 0;
387 double inc_i = 0., inc_j = 0., delta_ij = 0., delta_imax = 0., delta_imin = 0.;
388 double delta_jmax = 0., delta_jmin = 0., sij = 0., muij = 0., muji = 0.;
389
390 bool ok_facei = false, ok_facej = false;
391
392 DoubleTab Minima(nb_faces_tot), Maxima(nb_faces_tot);
393
394 for (dim = 0; dim < nb_comp; dim++)
395 {
396 calculer_min_max(inconnueTab, dim, Minima, false /* is_max */);
397 calculer_min_max(inconnueTab, dim, Maxima, true /* is_max */);
398
399 for (elem = 0; elem < nb_elem_tot; elem++)
400 for (facei_loc = 0; facei_loc < nb_faces_elem; facei_loc++)
401 {
402 facei = elem_faces(elem, facei_loc);
403 ok_facei = is_dirichlet_faces_(facei);
404 inc_i = inconnue[facei * nb_comp + dim];
405
406 delta_imin = Minima(facei) - inc_i;
407 delta_imax = Maxima(facei) - inc_i;
408 assert(delta_imax >= 0.);
409 assert(delta_imin <= 0.);
410
411 for (facej_loc = facei_loc + 1; facej_loc < nb_faces_elem; facej_loc++)
412 {
413 const double aij = is_VECT ? Aij(elem, facei_loc, facej_loc, dim) : Aij(elem, facei_loc, facej_loc);
414
415 if (aij > 0.)
416 {
417 facej = elem_faces(elem, facej_loc);
418 ok_facej = is_dirichlet_faces_(facej);
419 inc_j = inconnue[facej * nb_comp + dim];
420
421 for (dim2 = 0; dim2 < Objet_U::dimension; dim2++)
422 rij(dim2) = xv(facej, dim2) - xv(facei, dim2);
423
424 rji = rij;
425 rji *= -1.;
426
427 delta_ij = inc_i - inc_j;
428 delta_jmin = Minima(facej) - inc_j;
429 delta_jmax = Maxima(facej) - inc_j;
430 assert(delta_jmax >= 0.);
431 assert(delta_jmin <= 0.);
432
433 muij = calculer_gradients(facei, rij);
434 muji = calculer_gradients(facej, rji);
435
436 sij = 0.; //reste a 0 si que des faces de Dirichlet
437 if (delta_ij > 0.)
438 {
439 muij *= delta_imax;
440 muji *= -delta_jmin;
441
442 if (!ok_facei && !ok_facej) //pas de face de Dirichlet
443 sij = my_minimum(muij, delta_ij, muji);
444 if (!ok_facei && ok_facej) //facej Dirichlet et pas facei
445 sij = my_minimum(muij, delta_ij);
446 if (ok_facei && !ok_facej) //facei Dirichlet et pas facej
447 sij = my_minimum(delta_ij, muji);
448 }
449 else if (delta_ij < 0.)
450 {
451 muij *= delta_imin;
452 muji *= -delta_jmax;
453
454 if (!ok_facei && !ok_facej) //pas de face de Dirichlet
455 sij = my_maximum(muij, delta_ij, muji);
456 if (!ok_facei && ok_facej) //facej Dirichlet et pas facei
457 sij = my_maximum(muij, delta_ij);
458 if (ok_facei && !ok_facej) //facei Dirichlet et pas facej
459 sij = my_maximum(delta_ij, muji);
460 }
461
462 resu[facei * nb_comp + dim] -= aij * sij;
463 resu[facej * nb_comp + dim] += aij * sij;
464
465 }
466 }
467 }
468 }
469}
470
471double Op_Dift_Stab_VEF_Face::calculer_gradients(int facei, const DoubleTab& rij) const
472{
473 const Domaine_VEF& domaine_VEF = domaine_vef();
474 const IntTab& elem_faces = domaine_VEF.elem_faces(), &face_voisins = domaine_VEF.face_voisins(), &get_num_fac_loc = domaine_VEF.get_num_fac_loc();
475 const DoubleTab& face_normales = domaine_VEF.face_normales();
476 const DoubleVect& volumes = domaine_VEF.volumes();
477 const int nb_faces_elem = domaine_VEF.domaine().nb_faces_elem();
478 double volume = 0., signek = 0., psc = 0., mu_ij = 0.;
479 int elem = 0, elem_loc = 0, facei_loc = 0, facek_loc = 0, facek = 0, dim = 0;
480
481 for (elem_loc = 0; elem_loc < 2; elem_loc++)
482 {
483 facei_loc = get_num_fac_loc(facei, elem_loc);
484 elem = face_voisins(facei, elem_loc);
485
486 if (elem != -1)
487 {
488 volume += volumes(elem);
489
490 for (facek_loc = 0; facek_loc < nb_faces_elem; facek_loc++)
491 if (facek_loc != facei_loc)
492 {
493 facek = elem_faces(elem, facek_loc);
494
495 signek = 1.;
496 if (face_voisins(facek, 0) != elem)
497 signek = -1.;
498
499 psc = 0.;
500 for (dim = 0; dim < Objet_U::dimension; dim++)
501 psc += face_normales(facek, dim) * rij(dim);
502 psc *= signek;
503 if (psc < 0.)
504 psc *= -1.;
505
506 mu_ij += psc;
507 }
508 }
509 }
510
511 mu_ij /= volume;
512 mu_ij *= 2.;
513 return mu_ij;
514}
515
516void Op_Dift_Stab_VEF_Face::calculer_min_max(const DoubleTab& inconnueTab, int& dim, DoubleTab& minima_ou_maxima, const bool is_max) const
517{
518 const Domaine_VEF& domaine_VEF = domaine_vef();
519 const int nb_elem_tot = domaine_VEF.nb_elem_tot(), nb_faces_elem = domaine_VEF.domaine().nb_faces_elem(),
520 nb_faces_tot = domaine_VEF.nb_faces_tot(), nb_comp = inconnueTab.line_size();
521 const IntTab& elem_faces = domaine_VEF.elem_faces();
522 int elem = 0, facei_loc = 0, facei = 0, facej_loc = 0, facej = 0;
523 double inc_i = 0., inc_j = 0.;
524 const DoubleVect& inconnue = inconnueTab;
525
526 assert(minima_ou_maxima.nb_dim() == 1);
527 assert(minima_ou_maxima.dimension(0) == nb_faces_tot);
528 assert(dim < nb_comp);
529
530 for (facei = 0; facei < nb_faces_tot; facei++)
531 minima_ou_maxima(facei) = inconnue[facei * nb_comp + dim];
532
533 for (elem = 0; elem < nb_elem_tot; elem++)
534 for (facei_loc = 0; facei_loc < nb_faces_elem; facei_loc++)
535 {
536 facei = elem_faces(elem, facei_loc);
537
538 inc_i = inconnue[facei * nb_comp + dim];
539 double& min_ou_maxi = minima_ou_maxima(facei);
540
541 for (facej_loc = facei_loc + 1; facej_loc < nb_faces_elem; facej_loc++)
542 {
543 facej = elem_faces(elem, facej_loc);
544
545 inc_j = inconnue[facej * nb_comp + dim];
546 double& min_ou_maxj = minima_ou_maxima(facej);
547
548 if (is_max)
549 {
550 if (inc_j > min_ou_maxi)
551 min_ou_maxi = inc_j;
552 if (inc_i > min_ou_maxj)
553 min_ou_maxj = inc_i;
554 }
555 else
556 {
557 if (inc_j < min_ou_maxi)
558 min_ou_maxi = inc_j;
559 if (inc_i < min_ou_maxj)
560 min_ou_maxj = inc_i;
561 }
562 }
563 }
564
565 const Domaine_Cl_VEF& domaine_Cl_VEF = domaine_cl_vef();
566 const Conds_lim& les_cl = domaine_Cl_VEF.les_conditions_limites();
567 const int nb_bords = les_cl.size();
568 int num1 = 0, num2 = 0, n_bord = 0, ind_face = 0;
569
570 for (n_bord = 0; n_bord < nb_bords; n_bord++)
571 {
572 const Cond_lim& la_cl = domaine_Cl_VEF.les_conditions_limites(n_bord);
573 const Front_VF& le_bord = ref_cast(Front_VF, la_cl->frontiere_dis());
574
575 num1 = 0;
576 num2 = le_bord.nb_faces_tot();
577
578 if (sub_type(Periodique, la_cl.valeur()))
579 {
580 const Periodique& la_cl_perio = ref_cast(Periodique, la_cl.valeur());
581
582 for (ind_face = num1; ind_face < num2; ind_face++)
583 {
584 facei = le_bord.num_face(ind_face);
585 facej = le_bord.num_face(la_cl_perio.face_associee(ind_face));
586
587 if (facei < facej)
588 {
589 double& min_ou_maxi = minima_ou_maxima(facei);
590 double& min_ou_maxj = minima_ou_maxima(facej);
591 if (is_max)
592 {
593 if (min_ou_maxi > min_ou_maxj)
594 min_ou_maxj = min_ou_maxi;
595 if (min_ou_maxj > min_ou_maxi)
596 min_ou_maxi = min_ou_maxj;
597 }
598 else
599 {
600 if (min_ou_maxi < min_ou_maxj)
601 min_ou_maxj = min_ou_maxi;
602 if (min_ou_maxj < min_ou_maxi)
603 min_ou_maxi = min_ou_maxj;
604 }
605 }
606 }
607 }
608
609 }
610}
611
613{
615
616 const Domaine_VEF& domaine_VEF = domaine_vef();
617 const Domaine_Cl_VEF& domaine_Cl_VEF = domaine_cl_vef();
618 const Conds_lim& les_cl = domaine_Cl_VEF.les_conditions_limites();
619 const int nb_bord = les_cl.size(), nb_faces_tot = domaine_VEF.nb_faces_tot();
620 int ind_face = -1;
621
622 is_dirichlet_faces_.resize(nb_faces_tot);
623 is_dirichlet_faces_ = 0;
624
625 for (int n_bord = 0; n_bord < nb_bord; n_bord++)
626 {
627 const Cond_lim& la_cl = domaine_Cl_VEF.les_conditions_limites(n_bord);
628 const Front_VF& le_bord = ref_cast(Front_VF, la_cl->frontiere_dis());
629 int nb_faces_bord_tot = le_bord.nb_faces_tot(), face = -1;
630
631 if ((sub_type(Dirichlet, la_cl.valeur())) || (sub_type(Dirichlet_homogene, la_cl.valeur())))
632 for (ind_face = 0; ind_face < nb_faces_bord_tot; ind_face++)
633 {
634 face = le_bord.num_face(ind_face);
635 is_dirichlet_faces_(face) = 1;
636 }
637 }
638}
639
640void Op_Dift_Stab_VEF_Face::ajouter_cas_scalaire(const DoubleTab& inconnue, const DoubleTab& nu, const DoubleTab& nu_turb_m, DoubleTab& resu2) const
641{
642 const Domaine_VEF& domaine_VEF = domaine_vef();
643 const int nb_elem_tot = domaine_VEF.nb_elem_tot(), nb_faces_elem = domaine_VEF.domaine().nb_faces_elem();
644 DoubleTab Aij(nb_elem_tot, nb_faces_elem, nb_faces_elem), nu_total(nu);
645 nu_total += nu_turb_m;
646
647 calculer_coefficients__<Type_Champ::SCALAIRE>(*this, nu_total, nu_total /* poubelle */, Aij);
648 ajouter_operateur_centre__<Type_Champ::SCALAIRE>(*this, Aij, nu, inconnue, resu2);
649
650 if (!standard_)
651 {
652 ajouter_diffusion(Aij, inconnue, resu2, false /* is_VECT */);
653 ajouter_antidiffusion(Aij, inconnue, resu2, false /* is_VECT */);
654 }
655}
656
657void Op_Dift_Stab_VEF_Face::ajouter_cas_vectoriel(const DoubleTab& inconnue, const DoubleTab& nu, const DoubleTab& nu_turb_m, DoubleTab& resu2) const
658{
659 const Domaine_VEF& domaine_VEF = domaine_vef();
660 const int nb_elem_tot = domaine_VEF.nb_elem_tot(), nb_faces_elem = domaine_VEF.domaine().nb_faces_elem(), nb_comp = resu2.line_size();
661
662 DoubleTab Aij_diag(nb_elem_tot, nb_faces_elem, nb_faces_elem, nb_comp);
663
664 DoubleTab nu_total(nu);
665 if (nu_lu_ == 0) nu_total = 0.;
666 if (nut_lu_) nu_total += nu_turb_m;
667
668 DoubleTab nu_transp_total(nu);
669 if (nu_transp_lu_ == 0) nu_transp_total = 0.;
670 if (nut_transp_lu_) nu_transp_total += nu_turb_m;
671
672 calculer_coefficients__<Type_Champ::VECTORIEL>(*this, nu_total, nu_transp_total, Aij_diag);
673 ajouter_operateur_centre__<Type_Champ::VECTORIEL>(*this, Aij_diag, nu_transp_total, inconnue, resu2);
674
675 if (!standard_)
676 {
677 ajouter_diffusion(Aij_diag, inconnue, resu2, true /* is_VECT */);
678 ajouter_antidiffusion(Aij_diag, inconnue, resu2, true /* is_VECT */);
679 }
680}
681
682DoubleTab& Op_Dift_Stab_VEF_Face::ajouter(const DoubleTab& inconnue_org, DoubleTab& resu) const
683{
684 const DoubleTab& nu_turb = diffusivite_turbulente().valeurs();
685 const DoubleVect& porosite_face = equation().milieu().porosite_face(), &porosite_elem = equation().milieu().porosite_elem();
686 const int nb_comp = resu.line_size();
687
688 // On dimensionne et initialise le tableau des bilans de flux:
689 flux_bords_.resize(le_dom_vef->nb_faces_bord(), nb_comp);
690 flux_bords_ = 0.;
691
692 DoubleTab resu2(resu);
693 resu2 = 0.;
694
695 // soit on a div(phi nu grad inco) OU div(nu grad phi inco) : cela depend si on diffuse phi_psi ou psi
696 DoubleTab nu, nu_turb_m, tab_inconnue_;
697
698 const int marq = phi_psi_diffuse(equation());
699
701 modif_par_porosite_si_flag(nu_, nu, !marq, porosite_elem);
702 modif_par_porosite_si_flag(nu_turb, nu_turb_m, !marq, porosite_elem);
703 const DoubleTab& inconnue = modif_par_porosite_si_flag(inconnue_org, tab_inconnue_, marq, porosite_face);
704
705 assert_espace_virtuel_vect(nu);
706 assert_espace_virtuel_vect(inconnue);
707 assert_espace_virtuel_vect(nu_turb_m);
708 Debog::verifier("Op_Dift_Stab_VEF_Face::ajouter nu", nu);
709 Debog::verifier("Op_Dift_Stab_VEF_Face::ajouter nu_turb", nu_turb_m);
710 Debog::verifier("Op_Dift_Stab_VEF_Face::ajouter inconnue_org", inconnue_org);
711 Debog::verifier("Op_Dift_Stab_VEF_Face::ajouter inconnue", inconnue);
712
713 if (equation().inconnue().nature_du_champ() != vectoriel)
714 ajouter_cas_scalaire(inconnue, nu, nu_turb_m, resu2);
715 else
716 ajouter_cas_vectoriel(inconnue, nu, nu_turb_m, resu2);
717
718 modifie_pour_cl_gen<true /* _IS_STAB_ */>(inconnue, resu2, flux_bords_);
719
720 resu -= resu2; // -= car le laplacien est place en terme source dans l'equation
721 modifier_flux(*this);
722 return resu;
723}
724
725void Op_Dift_Stab_VEF_Face::contribuer_a_avec(const DoubleTab& inco, Matrice_Morse& matrice) const
726{
728 remplir_nu(nu_); // On remplit le tableau nu car l'assemblage d'une matrice avec ajouter_contribution peut se faire avant le premier pas de temps
729
730 const DoubleTab& nu_turb_ = diffusivite_turbulente().valeurs();
731 DoubleTab nu, nu_turb;
732
733 int marq = phi_psi_diffuse(equation());
734 const DoubleVect& porosite_elem = equation().milieu().porosite_elem();
735
736 // soit on a div(phi nu grad inco) OU on a div(nu grad phi inco) : cela depend si on diffuse phi_psi ou psi
737 modif_par_porosite_si_flag(nu_, nu, !marq, porosite_elem);
738 modif_par_porosite_si_flag(nu_turb_, nu_turb, !marq, porosite_elem);
739
740 DoubleVect porosite_eventuelle(equation().milieu().porosite_face());
741 if (!marq) porosite_eventuelle = 1;
742
743 if (equation().inconnue().nature_du_champ() == vectoriel)
744 {
745 if (!new_jacobian_)
746 {
747 ajouter_contribution_bord_gen<Type_Champ::VECTORIEL>(inco, matrice, nu, nu_turb, porosite_eventuelle);
748 ajouter_contribution_interne_gen<Type_Champ::VECTORIEL>(inco, matrice, nu, nu_turb, porosite_eventuelle);
749 }
750 else /* _IS_STAB_ = true */
751 {
752 ajouter_contribution_bord_gen<Type_Champ::VECTORIEL, true /* _IS_STAB_ */>(inco, matrice, nu, nu_turb, porosite_eventuelle);
753 ajouter_contribution_interne_gen<Type_Champ::VECTORIEL, true /* _IS_STAB_ */>(inco, matrice, nu, nu_turb, porosite_eventuelle);
754 }
755 }
756 else
757 {
758 if (!new_jacobian_)
759 {
760 ajouter_contribution_bord_gen<Type_Champ::SCALAIRE>(inco, matrice, nu, nu_turb, porosite_eventuelle);
761 ajouter_contribution_interne_gen<Type_Champ::SCALAIRE>(inco, matrice, nu, nu_turb, porosite_eventuelle);
762 }
763 else /* _IS_STAB_ = true */
764 {
765 ajouter_contribution_bord_gen<Type_Champ::SCALAIRE, true /* _IS_STAB_ */>(inco, matrice, nu, nu_turb, porosite_eventuelle);
766 ajouter_contribution_interne_gen<Type_Champ::SCALAIRE, true /* _IS_STAB_ */>(inco, matrice, nu, nu_turb, porosite_eventuelle);
767 }
768 }
769
771}
DoubleTab & valeurs() override
Surcharge Champ_base::valeurs() Renvoie le tableau des valeurs.
DoubleTab & valeurs() override
Renvoie le tableau des valeurs du champ au temps courant.
classe Cond_lim Classe generique servant a representer n'importe quelle classe
Definition Cond_lim.h:31
classe Conds_lim Cette classe represente un vecteur de conditions aux limites.
Definition Conds_lim.h:32
static void verifier(const char *const msg, double)
Definition Debog.cpp:21
Classe Dirichlet_homogene Cette classe est la classe de base de la hierarchie des conditions aux limi...
classe Dirichlet Cette classe est la classe de base de la hierarchie des conditions aux limites de ty...
Definition Dirichlet.h:31
int nb_faces_elem(int=0) const
Renvoie le nombre de face de type i des elements geometriques constituants le domaine.
Definition Domaine.h:484
const Cond_lim & les_conditions_limites(int) const
Renvoie la i-ieme condition aux limites.
class Domaine_VEF
Definition Domaine_VEF.h:54
int nb_faces_tot() const
renvoie le nombre total de faces.
Definition Domaine_VF.h:481
virtual double face_normales(int face, int comp) const
Definition Domaine_VF.h:47
double xv(int num_face, int k) const
Definition Domaine_VF.h:76
double volumes(int i) const
Definition Domaine_VF.h:113
const IntTab & get_num_fac_loc() const
Definition Domaine_VF.h:140
int elem_faces(int i, int j) const
renvoie le numero de le ieme face de la maille num_elem la facon dont ces faces sont numerotees est
Definition Domaine_VF.h:543
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_elem_tot() const
const Domaine & domaine() const
Class defining operators and methods for all reading operation in an input flow (file,...
Definition Entree.h:42
virtual const Milieu_base & milieu() const =0
virtual const Champ_Inc_base & inconnue() const =0
class Front_VF
Definition Front_VF.h:36
int nb_faces_tot() const
Definition Front_VF.h:58
int num_face(const int) const
Definition Front_VF.h:68
Classe Matrice_Morse Represente une matrice M (creuse), non necessairement carree.
DoubleVect & porosite_elem()
Definition Milieu_base.h:58
DoubleVect & porosite_face()
Definition Milieu_base.h:62
const Equation_base & equation() const
Renvoie la reference sur l'equation pointe par MorEqn::mon_equation.
Definition MorEqn.h:62
static int dimension
Definition Objet_U.h:99
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 Sortie & printOn(Sortie &) const
Ecriture de l'objet sur un flot de sortie Methode a surcharger.
Definition Objet_U.cpp:282
const Champ_Fonc_base & diffusivite_turbulente() const
int phi_psi_diffuse(const Equation_base &eq) const
definit si on calcule div(phi nu grad Psi) ou div(nu grap Phi psi)
virtual void remplir_nu(DoubleTab &) const
const Domaine_VEF & domaine_vef() const
const Domaine_Cl_VEF & domaine_cl_vef() const
void contribuer_a_avec(const DoubleTab &, Matrice_Morse &) const override
DOES NOTHING - to override in derived classes.
DoubleTab & ajouter(const DoubleTab &, DoubleTab &) const override
void completer() override
Associe l'operateur au domaine_dis, le domaine_Cl_dis, et a l'inconnue de son equation.
void modifie_pour_cl_gen(const DoubleTab &, DoubleTab &, DoubleTab &) const
void ajouter_contribution_bord_gen(const DoubleTab &, Matrice_Morse &, const DoubleTab &, const DoubleTab &, const DoubleVect &) const
void ajouter_contribution_interne_gen(const DoubleTab &inco, Matrice_Morse &mat, const DoubleTab &nu, const DoubleTab &nu_turb, const DoubleVect &porosite_eventuelle) const
void completer() override
Associe l'operateur au domaine_dis, le domaine_Cl_dis, et a l'inconnue de son equation.
void modifier_matrice_pour_periodique_apres_contribuer(Matrice_Morse &matrice, const Equation_base &) const
Somme les 2 lignes des faces periodiques associees permet de calculer dans le code sans se poser de q...
void modifier_matrice_pour_periodique_avant_contribuer(Matrice_Morse &matrice, const Equation_base &) const
divise les coefficients sur les ligne des faces periodiques par 2 en prevision de l'application modif...
void modifier_flux(const Operateur_base &) const
DoubleTab flux_bords_
int face_associee(int i) const
Definition Periodique.h:35
static void exit(int exit_code=-1)
Routine de sortie de TRUST dans une region Kokkos.
Definition Process.cpp:455
Classe de base des flux de sortie.
Definition Sortie.h:52
int nb_dim() const
Definition TRUSTTab.h:199
_SIZE_ dimension(int d) const
Definition TRUSTTab.tpp:133
int line_size() const
Definition TRUSTVect.tpp:67