TrioCFD 1.9.8
TrioCFD documentation
Loading...
Searching...
No Matches
Domaine_Cl_EF.cpp
1/****************************************************************************
2* Copyright (c) 2026, 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 <Domaine_Cl_EF.h>
17#include <Domaine_EF.h>
18#include <Dirichlet.h>
19#include <Dirichlet_homogene.h>
20#include <Symetrie.h>
21#include <Neumann.h>
22#include <Neumann_homogene.h>
23#include <Periodique.h>
24//#include <Champ_P0_EF.h>
25#include <Champ_P1_EF.h>
26#include <Domaine.h>
27#include <Tri_EF.h>
28#include <Tetra_EF.h>
29#include <Quadri_EF.h>
30#include <Equation_base.h>
31#include <Champ_front_txyz.h>
32#include <Champ_front_softanalytique.h>
33#include <Static_Int_Lists.h>
34#include <Probleme_base.h>
35#include <Discretisation_base.h>
36#include <Matrice_Morse.h>
37#include <Dirichlet_paroi_fixe_iso_Genepi2.h>
38#include <Champ_Don_base.h>
39
40Implemente_instanciable(Domaine_Cl_EF,"Domaine_Cl_EF",Domaine_Cl_dis_base);
41
43{
44 return os;
45}
46
48{
50}
51
52/*! @brief remplissage des tableaux
53 *
54 */
55void Domaine_Cl_EF::completer(const Domaine_dis_base& un_domaine_dis)
56{
57 if (sub_type(Domaine_EF,un_domaine_dis))
58 {
59 const Domaine_EF& le_dom_EF = ref_cast(Domaine_EF, un_domaine_dis);
60 remplir_type_elem_Cl(le_dom_EF);
61 }
62 else
63 {
64 Cerr << "Domaine_Cl_EF::completer() prend comme argument un Domaine_EF " << finl;
65 exit();
66 }
67}
68void construit_connectivite_sommet(int type_cl,Static_Int_Lists& som_face_bord,const Conds_lim& les_conditions_limites_,const Domaine_EF& domaine_EF)
69{
70 if (type_cl!=1) Process::exit();
71 int compt=0;
72 int nb_faces_tot=domaine_EF.nb_faces_tot();
73 ArrOfInt face_bords(nb_faces_tot);
74
75 for(int i=0; i<les_conditions_limites_.size(); i++)
76 {
77 const Cond_lim_base& la_cl=les_conditions_limites_[i].valeur();
78 const Front_VF& le_bord= domaine_EF.front_VF(i);
79 int num2 = le_bord.nb_faces_tot();
80
81 if ( (sub_type(Symetrie,la_cl)))
82 {
83 for (int ind_face=0; ind_face<num2; ind_face++)
84 {
85 int face=le_bord.num_face(ind_face);
86 face_bords[compt++]=face;
87 }
88 }
89 }
90 face_bords.resize_array(compt);
91 ArrOfInt is_sommet_sur_bord(domaine_EF.nb_som_tot());
92 const IntTab& face_sommets=domaine_EF.face_sommets();
93 int nb_som_face=face_sommets.dimension(1);
94 for (int fac=0; fac<compt; fac++)
95 {
96 int face=face_bords[fac];
97 for (int som=0; som<nb_som_face; som++)
98 {
99 int sommet=face_sommets(face,som);
100 is_sommet_sur_bord[sommet]++;
101 }
102 }
103
104 //On exploite is_sommet_sur_bord pour fixer la taille des List que va repertorier som_face_bord
105 //-som_face_bord contient nb_som_tot List
106 //-chaque List est dimensionnee par le nombre de faces de bord (portant une CL de Dirichlet)
107 // connectees au sommet considere
108 //-une List donnee pour un sommet repertorie le numero des faces qui lui sont connectees
109
110 som_face_bord.set_list_sizes(is_sommet_sur_bord);
111 is_sommet_sur_bord=0;
112 for (int fac=0; fac<compt; fac++)
113 {
114 int face=face_bords[fac];
115 for (int som=0; som<nb_som_face; som++)
116 {
117 int sommet=face_sommets(face,som);
118 int n=(is_sommet_sur_bord[sommet])++;
119 som_face_bord.set_value(sommet,n,face);
120
121 }
122 }
123
124}
125
126static void construire_normale_locale_face(const DoubleTab& face_normales,
127 const IntTab& faces_sommets,
128 const DoubleTab& coord_sommets,
129 int face,
130 int dimension,
131 int nb_som_face,
132 bool is_bidim_axi,
133 ArrOfDouble& normale_locale)
134{
135 for (int d = 0; d < dimension; d++)
136 normale_locale[d] = face_normales(face, d);
137
138 if (!(is_bidim_axi && norme_array(normale_locale) < 1e-12))
139 return;
140
141 for (int d = 0; d < dimension; d++)
142 normale_locale[d] = 0.;
143
144 const int som0 = faces_sommets(face, 0);
145 const int som1 = faces_sommets(face, 1);
146 const double dx = coord_sommets(som1, 0) - coord_sommets(som0, 0);
147 const double dy = coord_sommets(som1, 1) - coord_sommets(som0, 1);
148 normale_locale[0] = -dy;
149 normale_locale[1] = dx;
150}
151
152/*! @brief appele par remplir_volumes_entrelaces_Cl() : remplissage de type_elem_Cl_
153 *
154 */
156{
157 const Domaine& z = le_dom_EF.domaine();
158
159 const IntTab& faces_sommets=le_dom_EF.face_sommets();
160 int nb_som_face=faces_sommets.dimension(1);
161 const DoubleTab& coord_sommets = z.coord_sommets();
162 int nb_som_tot=z.nb_som_tot();
163 type_sommet_.resize_array(z.nb_som_tot());
164 type_sommet_=-1;
165 IntTab titi(nb_som_tot);
166
167 for(int i=0; i<les_conditions_limites_.size(); i++)
168 {
169 Cond_lim_base& la_cl=les_conditions_limites_[i].valeur();
170 const Front_VF& le_bord= le_dom_EF.front_VF(i);
171 int num2 = le_bord.nb_faces_tot();
172
173 if ( (sub_type(Dirichlet,la_cl))|| (sub_type(Dirichlet_homogene,la_cl)) )
174 {
175 for (int ind_face=0; ind_face<num2; ind_face++)
176 {
177 int face=le_bord.num_face(ind_face);
178 for (int s=0; s<nb_som_face; s++)
179 {
180 int som=faces_sommets(face,s);
181// Si on a Dirichlet_paroi_fixe_iso_Genepi2 on ne prend pas en compte le 0 pour la moyenne
182 if (!sub_type(Dirichlet_paroi_fixe_iso_Genepi2,la_cl))
183 titi(som)++;
184 if ((type_sommet_[som]!=1)&& (type_sommet_[som]!=3))
185 type_sommet_[som]=2;
186 else
187 type_sommet_[som]=3;
188 }
189 }
190 }
191 else if ( (sub_type(Symetrie,la_cl)))
192 {
193 for (int ind_face=0; ind_face<num2; ind_face++)
194 {
195 int face=le_bord.num_face(ind_face);
196 for (int s=0; s<nb_som_face; s++)
197 {
198 int som=faces_sommets(face,s);
199 if (type_sommet_[som]<=1)
200 type_sommet_[som]=1;
201 else
202 type_sommet_[som]=3;
203 }
204 }
205 }
206 else if ( (sub_type(Neumann,la_cl))|| (sub_type(Neumann_homogene,la_cl)) )
207 {
208 for (int ind_face=0; ind_face<num2; ind_face++)
209 {
210 int face=le_bord.num_face(ind_face);
211 for (int s=0; s<nb_som_face; s++)
212 {
213 int som=faces_sommets(face,s);
214 if (type_sommet_[som]<0)
215 type_sommet_[som]=0;
216 }
217 }
218 }
219 else
220 {
221 Cerr<<__FILE__<<":" <<(int)__LINE__<<" non code pour cette cl "<<la_cl.que_suis_je()<<finl;
222 }
223
224 }
225 // si on a un dirichet on stocke 2*nb participant + 1 si sommet aussi de sym
226 for (int som=0; som<nb_som_tot; som++)
227 {
228 if (type_sommet_[som]>1)
229 {
230 //assert(titi(som)>0);
231 type_sommet_[som]+=2*(titi(som));
232 }
233 }
234 // On cree la connectivite sommet -> face de bord symetrie
235 if (equation().inconnue().nature_du_champ()==vectoriel)
236 {
237 equation().probleme().discretisation().discretiser_champ("VITESSE",le_dom_EF,"normales_nodales","1",dimension,0.,normales_symetrie_);
238 equation().probleme().discretisation().discretiser_champ("CHAMP_SOMMETS",le_dom_EF,"normales_nodales_bis","1",dimension,0., normales_symetrie_bis_);
239 Static_Int_Lists sommet_face_symetrie;
240 int type_cl=1;
241 construit_connectivite_sommet(type_cl,sommet_face_symetrie,les_conditions_limites_,le_dom_EF);
242 // sommet_face_symetrie contient le nombre de face de symetrie associe a chaque sommet
243 const DoubleTab& face_normales = le_dom_EF.face_normales();
244 ArrOfDouble n(dimension),t1(dimension),t2(dimension),normale_locale(dimension);
245 for (int som=0; som<nb_som_tot; som++)
246 {
247 int nbf= sommet_face_symetrie.get_list_size(som);
248 if (nbf>0)
249 //if ( type_sommet_(som)==1)
250 {
251 n=0;
252 t1=0;
253 t2=0;
254 // on determine la normale sommet
255 //int nbf= sommet_face_symetrie.get_list_size(som);
256 for (int f=0; f<nbf; f++)
257 {
258 int face=sommet_face_symetrie(som,f);
259 construire_normale_locale_face(face_normales, faces_sommets, coord_sommets, face, dimension, nb_som_face, bidim_axi, normale_locale);
260 for (int d=0; d<dimension; d++)
261 n[d]+=normale_locale[d];
262 }
263 n/=nbf;
264
265 double norm_n=norme_array(n);
266 n/=norm_n;
267 for (int d=0; d<dimension; d++)
268 normales_symetrie_->valeurs()(som,d)=n[d];
269 // Cerr<<som<<" on doit annuler une premiere direction "<<n(0) << " " <<n(1)<<" "<<n(dimension==3?2:1)<<finl;
270
271 for (int f=0; f<nbf; f++)
272 {
273 int face=sommet_face_symetrie(som,f);
274 construire_normale_locale_face(face_normales, faces_sommets, coord_sommets, face, dimension, nb_som_face, bidim_axi, normale_locale);
275 double prod=0;
276 for (int d=0; d<dimension; d++)
277 prod+=normale_locale[d]*n[d];
278
279 double s=0;
280 // double v = 0;
281
282 for (int d=0; d<dimension; d++)
283 {
284 t1[d]=normale_locale[d]-n[d]*prod;
285 s+=normale_locale[d]*normale_locale[d];
286 // v+=t1[d]*n[d];
287 }
288
289 //Cerr<<" vv"<< v<<" "<<norme_array(t1)<<" "<<norm_n<<finl;
290 if (norme_array(t1)>(1e-4*sqrt(s)))
291 {
292
293 // facilite le debugage
294 if (std::fabs(min_array(t1))>max_array(t1))
295 t1*=-1;
296 t1/=norme_array(t1);
297
298
299 // Cerr<<som<<" on doit annuler une deuxieme direction "<<t1(0) << " " <<t1(1)<<" "<<t1(dimension==3?2:1)<<finl;
300 f=nbf;
301 for (int d=0; d<dimension; d++)
302 normales_symetrie_bis_->valeurs()(som,d)=t1[d];
303 //assert(v==0);
304 }
305
306 }
307 for (int f=0; f<nbf; f++)
308 {
309 int face=sommet_face_symetrie(som,f);
310 construire_normale_locale_face(face_normales, faces_sommets, coord_sommets, face, dimension, nb_som_face, bidim_axi, normale_locale);
311 double prod=0,prod1=0,s=0;
312 for (int d=0; d<dimension; d++)
313 {
314 prod+=normale_locale[d]*n[d];
315
316 prod1+=normale_locale[d]*t1[d];
317 s+=normale_locale[d]*normale_locale[d];
318
319 }
320 for (int d=0; d<dimension; d++)
321 t2[d]=normale_locale[d]-n[d]*prod-t1[d]*prod1;
322
323 if (norme_array(t2)>(1e-4*sqrt(s)))
324 {
325 // facilite le debugage
326 if (std::fabs(min_array(t2))>max_array(t2))
327 t2*=-1;
328 t2/=norme_array(t2);
329 Cerr<<face<<" "<<nbf<<" sommet "<<som<<" "<<norme_array(t2)/s<<" on doit annuler une troiseme direction"<<t2[0] << " " <<t2[1]<<" "<<t2[2]<<finl;
330 Cerr<<som<<" "<<t1[0] << " " <<t1[1]<<" "<<t1[2]<<finl;
331 Cerr<<som<<" "<<n[0] << " " <<n[1]<<" "<<n[2]<<finl;
332 f=nbf;
334 equation().probleme().discretisation().discretiser_champ("CHAMP_SOMMETS",le_dom_EF,"normales_nodales_bis","1",dimension,0., normales_symetrie_ter_);
335 for (int d=0; d<dimension; d++)
336 normales_symetrie_ter_->valeurs()(som,d)=t2[d];
337 //exit();
338 }
339 }
340 }
341 }
342 normales_symetrie_->valeurs().echange_espace_virtuel();
343 normales_symetrie_bis_->valeurs().echange_espace_virtuel();
344 //exit();
345 }
346}
347/*! @brief Impose les conditions de symetrie c.
348 *
349 * a.d annules les composantes du champ sur la ou les normales
350 * si tous_les_sommets_sym =1 alors meme les sommets appartenant aussi a un dirichlet sont mis a zero.
351 *
352 */
353void Domaine_Cl_EF::imposer_symetrie(DoubleTab& values,int tous_les_sommets_sym) const
354{
355 // return;
356
357 assert(values.dimension(1)==dimension);
358 const Domaine& z = domaine_dis().domaine();
359 int nb_som_tot=z.nb_som_tot();
360 assert(values.dimension_tot(0)==nb_som_tot);
361
362 const DoubleTab& n =normales_symetrie_->valeurs();
363 const DoubleTab& n_bis =normales_symetrie_bis_->valeurs();
364 int dirmax=2;
365 if (normales_symetrie_ter_) dirmax=3;
366 for (int som=0; som<nb_som_tot; som++)
367 if (( type_sommet_[som]==1)|| ( tous_les_sommets_sym&&(type_sommet_[som]%2==1)))
368 {
369 for (int dir=0; dir<dirmax; dir++)
370 {
371 const DoubleTab& nn=(dir==0?n:(dir==1?n_bis:normales_symetrie_ter_->valeurs()));
372 double prod=0;
373 for (int d=0; d<dimension; d++)
374 prod+=values(som,d)*nn(som,d);
375 for (int d=0; d<dimension; d++)
376 values(som,d)-=prod*nn(som,d);
377 }
378 }
379}
380
381void Domaine_Cl_EF::imposer_symetrie_partiellement(DoubleTab& values,const Noms& a_exclure) const
382{
383 const IntTab& faces_sommets=domaine_EF().face_sommets();
384 int nb_som_face=faces_sommets.dimension(1);
385
386
387 const DoubleTab& n =normales_symetrie_->valeurs();
388 const DoubleTab& n_bis =normales_symetrie_bis_->valeurs();
389 int dirmax=2;
390 if (normales_symetrie_ter_) dirmax=3;
391 int nbcond=nb_cond_lim();
392
393 ArrOfInt type_sommet_bis(type_sommet_);
394 for (int n_bord=0; n_bord<nbcond; n_bord++)
395 {
396
397 const Cond_lim_base& la_cl = les_conditions_limites(n_bord).valeur();
398 const Front_VF& le_bord = ref_cast(Front_VF,la_cl.frontiere_dis());
399 int num2 = le_bord.nb_faces_tot();
400 const Nom& nom_bord=le_bord.le_nom();
401
402 if (sub_type(Symetrie,la_cl)&&(a_exclure.rang(nom_bord)>-1))
403 {
404 Cerr<<__FILE__<<(int)__LINE__<<" on impose pas symetrie sur "<<nom_bord<<finl;
405 for (int ind_face=0; ind_face<num2; ind_face++)
406 {
407 int face=le_bord.num_face(ind_face);
408 for (int s=0; s<nb_som_face; s++)
409 {
410 int som=faces_sommets(face,s);
411 type_sommet_bis[som]=3;
412 }
413 }
414 }
415 }
416
417 for (int n_bord=0; n_bord<nbcond; n_bord++)
418 {
419
420 const Cond_lim_base& la_cl = les_conditions_limites(n_bord).valeur();
421 const Front_VF& le_bord = ref_cast(Front_VF,la_cl.frontiere_dis());
422 int num2 = le_bord.nb_faces_tot();
423 const Nom& nom_bord=le_bord.le_nom();
424
425 if (sub_type(Symetrie,la_cl)&&(a_exclure.rang(nom_bord)<0))
426 {
427 Cerr<<__FILE__<<(int)__LINE__<<" on impose symetrie sur "<<nom_bord<<finl;
428 for (int ind_face=0; ind_face<num2; ind_face++)
429 {
430 int face=le_bord.num_face(ind_face);
431 for (int s=0; s<nb_som_face; s++)
432 {
433 int som=faces_sommets(face,s);
434 if ( type_sommet_bis[som]==1) //|| ( tous_les_sommets_sym&&(type_sommet_(som)%2==1)))
435 {
436 for (int dir=0; dir<dirmax; dir++)
437 {
438 const DoubleTab& nn=(dir==0?n:(dir==1?n_bis:normales_symetrie_ter_->valeurs()));
439 double prod=0;
440 for (int d=0; d<dimension; d++)
441 prod+=values(som,d)*nn(som,d);
442 for (int d=0; d<dimension; d++)
443 values(som,d)-=prod*nn(som,d);
444 }
445 }
446 }
447 }
448 }
449 }
450}
451void Domaine_Cl_EF::modifie_gradient(ArrOfDouble& grad_mod, const ArrOfDouble& grad, int som) const
452{
453 if (type_sommet_[som]!=1) return;
454 assert(grad_mod.size_array()==dimension);
455
456
457 const DoubleTab& n =normales_symetrie_->valeurs();
458 const DoubleTab& n_bis =normales_symetrie_bis_->valeurs();
459
460 assert ( type_sommet_[som]>=1);
461 int dirmax=2;
462 if (normales_symetrie_ter_) dirmax=3;
463 for (int dir=0; dir<dirmax; dir++)
464 {
465 const DoubleTab& nn=(dir==0?n:(dir==1?n_bis:normales_symetrie_ter_->valeurs()));
466 double prod=0;
467 for (int d=0; d<dimension; d++)
468 prod+=grad[d]*nn(som,d);
469 for (int d=0; d<dimension; d++)
470 grad_mod[d]+=prod*nn(som,d);
471 }
472
473}
474
475
476/*! @brief On transforme la_matrice et le secmem pour avoir un secmem normal aux bords , plus la matrice pour assurer que la solution sera correcte
477 *
478 */
479void Domaine_Cl_EF::imposer_symetrie_matrice_secmem(Matrice_Morse& la_matrice, DoubleTab& secmem) const
480{
481 // return;
482 assert(secmem.dimension(1)==dimension);
483 const Domaine& z = domaine_dis().domaine();
484 int nb_som=z.nb_som();
485 assert(secmem.dimension(0)==nb_som);
486 int nb_comp=secmem.dimension(1);
487 const DoubleTab& n =normales_symetrie_->valeurs();
488 const DoubleTab& n_bis =normales_symetrie_bis_->valeurs();
489 ArrOfDouble normale(dimension);
490
491 const auto& tab1 = la_matrice.get_tab1();
492 const auto& tab2 = la_matrice.get_tab2();
493
494 const DoubleTab& champ_inconnue = equation().inconnue().valeurs();
495 int dirmax=2;
496 if (normales_symetrie_ter_) dirmax=3;
497 for (int som=0; som<nb_som; som++)
498 if ( type_sommet_[som]==1)
499 {
500 for (int dir=0; dir<dirmax; dir++)
501 {
502 const DoubleTab& nn=(dir==0?n:(dir==1?n_bis:normales_symetrie_ter_->valeurs()));
503 for (int d=0; d<dimension; d++) normale[d]=nn(som,d);
504 // On commence par recalculer secmem=secmem-A *present pour pouvoir modifier A (on en profite pour projeter)
505 auto nb_coeff_ligne=tab1[som*nb_comp+1] - tab1[som*nb_comp];
506 for (int k=0; k<nb_coeff_ligne; k++)
507 {
508 for (int comp=0; comp<nb_comp; comp++)
509 {
510 int j=tab2[tab1[som*nb_comp+comp]-1+k]-1;
511 //assert(j!=(som*nb_comp+comp));
512 //if ((j>=(som*nb_comp))&&(j<(som*nb_comp+nb_comp)))
513
514 const double coef_ij=la_matrice(som*nb_comp+comp,j);
515 int som2=j/nb_comp;
516 int comp2=j-som2*nb_comp;
517 secmem(som,comp)-=coef_ij*champ_inconnue(som2,comp2);
518 }
519 }
520 double somme_b=0;
521
522 for (int comp=0; comp<nb_comp; comp++)
523 somme_b+=secmem(som,comp)*normale[comp];
524 //Cerr<<som<<" sommet " <<somme_b<<" "<<secmem(som,0)<<" "<<secmem(som,1)<<finl;
525 // on retire secmem.n n
526 for (int comp=0; comp<nb_comp; comp++)
527 secmem(som,comp)-=somme_b*normale[comp];
528
529 if (1)
530 {
531 // on doit remettre la meme diagonale partout on prend la moyenne
532 double ref=0;
533 for (int comp=0; comp<nb_comp; comp++)
534 {
535
536 int j0=som*nb_comp+comp;
537 ref+=la_matrice.coef(j0,j0);
538 }
539 ref/=nb_comp;
540
541 for (int comp=0; comp<nb_comp; comp++)
542 {
543 int j0=som*nb_comp+comp;
544 double rap=ref/la_matrice.coef(j0,j0);
545 //Cerr<<dir<<" "<<som <<" "<<comp<<" rpp "<<rap <<finl;
546 for (int k=0; k<nb_coeff_ligne; k++)
547 {
548
549 int j=tab2[tab1[j0]-1+k]-1;
550 la_matrice(j0,j)*=rap;
551 }
552 assert(est_egal(la_matrice(j0,j0),ref));
553 }
554 }
555 if (1)
556 {
557 // on annule tous les coef extra diagonaux du bloc
558 // sur les lignes i pour lesquelles normale(d) !=0
559 // c.a.d dasb(normale(d)>tol)
560 const double tol = 1e-12;
561 for (int k=0; k<nb_coeff_ligne; k++)
562 {
563
564 for (int comp=0; comp<nb_comp; comp++)
565 if (std::fabs(normale[comp])>tol)
566 {
567 int j=tab2[tab1[som*nb_comp+comp]-1+k]-1;
568 if (j!=(som*nb_comp+comp))
569 if ((j>=(som*nb_comp))&&(j<(som*nb_comp+nb_comp)))
570 {
571 la_matrice(som*nb_comp+comp,j)=0;
572 }
573 }
574 }
575 }
576 {
577 // pour les blocs extra diagonaux on assure que Aij.ni=0
578
579 ArrOfDouble somme((int)nb_coeff_ligne);
580 for (int k=0; k<nb_coeff_ligne; k++)
581 {
582
583 int j=tab2[tab1[som*nb_comp]-1+k]-1;
584 for (int comp=0; comp<nb_comp; comp++)
585 somme[k]+=la_matrice(som*nb_comp+comp,j)*normale[comp];
586 }
587 // on retire somme ni
588 for (int k=0; k<nb_coeff_ligne; k++)
589 {
590
591 int j=tab2[tab1[som*nb_comp]-1+k]-1;
592 for (int comp=0; comp<nb_comp; comp++)
593 if ((j<(som*nb_comp))||(j>=(som*nb_comp+nb_comp)))
594 la_matrice(som*nb_comp+comp,j)-=(somme[k])*normale[comp];
595 }
596 }
597 // Finalement on recalule secmem=secmem+A*champ_inconnue (A a ete beaucoup modiife)
598 for (int k=0; k<nb_coeff_ligne; k++)
599 {
600 for (int comp=0; comp<nb_comp; comp++)
601 {
602 int j=tab2[tab1[som*nb_comp+comp]-1+k]-1;
603 int som2=j/nb_comp;
604 int comp2=j-som2*nb_comp;
605
606 const double coef_ij=la_matrice(som*nb_comp+comp,j);
607 secmem(som,comp)+=coef_ij*champ_inconnue(som2,comp2);
608
609 }
610 }
611 {
612 // verification
613 double somme_b2=0;
614
615 for (int comp=0; comp<nb_comp; comp++)
616 somme_b2+=secmem(som,comp)*normale[comp];
617 //Cerr<<" lllllllll "<<somme_b2<<" "<<tt<<finl;
618 if (std::fabs(somme_b2) >= 1e-8)
619 Cerr << "Domaine_Cl_EF::imposer_symetrie_matrice_secmem: secmem.n != 0 ("
620 << somme_b2 << ") au sommet " << som << ", projection appliquee." << finl;
621 // on retire secmem.n n
622 for (int comp=0; comp<nb_comp; comp++)
623 secmem(som,comp)-=somme_b2*normale[comp];
624
625 }
626 }
627 }
628 // exit();
629}
630
631/*! @brief Impose les conditions aux limites a la valeur temporelle "temps" du Champ_Inc
632 *
633 */
635{
636 DoubleTab& ch_tab = ch.valeurs(temps);
637 int nb_comp = ch.nb_comp();
638 const Domaine_EF& domaineEF = domaine_EF(); //ref_cast(Domaine_EF,ch.equation().domaine_dis());
639 const IntTab& faces_sommets=domaineEF.face_sommets();
640 int nb_som_face=faces_sommets.dimension(1);
641 const DoubleTab& coords= domaineEF.domaine().coord_sommets();
642
643 // dans un premier temps on annule le champ sur les dirichlets
644 // puis on ajoute 1/nb_cl*val_imp
645
646 for (int n_bord=0; n_bord<nb_cond_lim(); n_bord++)
647 {
648
649 const Cond_lim_base& la_cl = les_conditions_limites(n_bord).valeur();
650 const Front_VF& le_bord = ref_cast(Front_VF,la_cl.frontiere_dis());
651 int num2 = le_bord.nb_faces_tot();
652
653 if (sub_type(Dirichlet,la_cl)||(sub_type(Dirichlet_homogene,la_cl)))
654 {
655 //const Dirichlet& la_cl_diri = ref_cast(Dirichlet,la_cl);
656
657 for (int ind_face=0; ind_face<num2; ind_face++)
658 {
659 int face=le_bord.num_face(ind_face);
660 for (int s=0; s<nb_som_face; s++)
661 {
662 int som=faces_sommets(face,s);
663 assert(type_sommet_[som]>=2);
664
665
666 if (nb_comp == 1)
667 ch_tab[som]=0;
668 else
669 for (int ncomp=0; ncomp<nb_comp; ncomp++)
670 ch_tab(som,ncomp)=0;
671 }
672 }
673 }
674 }
675 for (int n_bord=0; n_bord<nb_cond_lim(); n_bord++)
676 {
677
678 const Cond_lim_base& la_cl = les_conditions_limites(n_bord).valeur();
679 const Front_VF& le_bord = ref_cast(Front_VF,la_cl.frontiere_dis());
680 int num2 = le_bord.nb_faces_tot();
681
682 if (sub_type(Dirichlet,la_cl))
683 {
684 const Dirichlet& la_cl_diri = ref_cast(Dirichlet,la_cl);
685 if (sub_type(Champ_front_softanalytique,la_cl_diri.champ_front()))
686 {
687 Cerr<<" Il faut utiliser Champ_front_fonc_txyz et non "<<la_cl_diri.champ_front().que_suis_je()<<finl;
688 exit();
689 }
690 int avec_valeur_aux_sommets=0;
691 if (sub_type(Champ_front_var_instationnaire,la_cl_diri.champ_front()))
692 {
694 avec_valeur_aux_sommets=ch_txyz.valeur_au_temps_et_au_point_disponible();
695 }
696 // Pour les faces de Dirichlet on impose l'inconnue au sommet
697 if (avec_valeur_aux_sommets)
698 {
700 for (int ind_face=0; ind_face<num2; ind_face++)
701 {
702 int face=le_bord.num_face(ind_face);
703 for (int s=0; s<nb_som_face; s++)
704 {
705 int som=faces_sommets(face,s);
706 assert(type_sommet_[som]>=4);
707 double coef=1./(type_sommet_[som]/2-1);
708 //Cerr<<"iciPB "<<coef<<finl;
709 double x,y,z=0;
710 x=coords(som,0);
711 y=coords(som,1);
712 if (dimension==3)
713 z=coords(som,2);
714 if (nb_comp == 1)
715 ch_tab[som]+=coef*ch_txyz.valeur_au_temps_et_au_point(temps,som,x,y,z,0);
716 else
717 for (int ncomp=0; ncomp<nb_comp; ncomp++)
718 ch_tab(som,ncomp)+=coef*ch_txyz.valeur_au_temps_et_au_point(temps,som,x,y,z,ncomp);
719 }
720 }
721 }
722 else
723 for (int ind_face=0; ind_face<num2; ind_face++)
724 {
725 int face=le_bord.num_face(ind_face);
726 for (int s=0; s<nb_som_face; s++)
727 {
728 int som=faces_sommets(face,s);
729 assert(type_sommet_[som]>=4);
730 double coef=1./(type_sommet_[som]/2-1);
731 //Cerr<<"iciPB "<<coef<<finl;
732 if (nb_comp == 1)
733 ch_tab[som]+=coef*la_cl_diri.val_imp_au_temps(temps,ind_face);
734 else
735 for (int ncomp=0; ncomp<nb_comp; ncomp++)
736 ch_tab(som,ncomp)+=coef*la_cl_diri.val_imp_au_temps(temps,ind_face,ncomp);
737 }
738 }
739
740 }
741 /*
742 else if (sub_type(Dirichlet_homogene,la_cl))
743 {
744 // Pour les faces de Dirichlet on impose l'inconnue au sommet
745 for (int ind_face=0; ind_face<num2; ind_face++)
746 {
747 int face=le_bord.num_face(ind_face);
748 for (int s=0;s<nb_som_face;s++)
749 {
750 int som=faces_sommets(face,s);
751 assert(type_sommet_(som)>=2);
752 if (nb_comp == 1)
753 ch_tab[som] = 0;
754 else
755 for (int ncomp=0; ncomp<nb_comp; ncomp++)
756 ch_tab(som,ncomp) =0;
757 }
758 }
759 }
760 */
761 // provsoire a fair equ'une fois
762 else if ( (sub_type(Symetrie,la_cl) ) &&
763 (ch.nature_du_champ()==vectoriel) )
764 {
765 imposer_symetrie(ch_tab);
766 }
767 }
768
769
770
771}
772
774{
775 exit();
776 /*
777 int compteur=0;
778 for(int cl=0; cl<les_conditions_limites_.size(); cl++)
779 {
780 if(sub_type(Neumann_sortie_libre, les_conditions_limites_[cl].valeur()))
781 {
782 const Front_VF& le_bord=ref_cast(Front_VF,les_conditions_limites_[cl]->frontiere_dis());
783 compteur+=le_bord.nb_faces();
784 }
785 }
786 return compteur;
787 */
788 return -1;
789}
790
792{
793 int compteur = 0;
794 for (const auto &itr : les_conditions_limites_)
795 {
796 if (sub_type(Periodique, itr.valeur()))
797 compteur++;
798 }
799 return compteur;
800}
801
802
804{
806
807 if (nb_bord_periodicite()>0)
808 {
809 Cerr<<" La periodicite n'est pas codee !!!"<<finl;
810 abort();
811 }
812 return 1;
813}
814
816{
817 return ref_cast(Domaine_EF, domaine_dis());
818}
819
821{
822 return ref_cast(Domaine_EF, domaine_dis());
823}
Classe Champ_Inc_base.
DoubleTab & valeurs() override
Renvoie le tableau des valeurs du champ au temps courant.
classe Champ_front_softanalytique Classe derivee de Champ_front_var qui represente les
classe Champ_front_var_instationnaire Classe derivee de Champ_front_var qui represente les champs aux
virtual double valeur_au_temps_et_au_point(double temps, int som, double x, double y, double z, int comp) const
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_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
virtual double val_imp_au_temps(double temps, int i) const
Renvoie la valeur imposee sur la i-eme composante du champ a la frontiere au temps precise.
Definition Dirichlet.cpp:54
void discretiser_champ(const Motcle &directive, const Domaine_dis_base &z, const Nom &nom, const Nom &unite, int nb_comp, int nb_pas_dt, double temps, OWN_PTR(Champ_Inc_base)&champ, const Nom &sous_type=NOM_VIDE) const
const DoubleTab_t & coord_sommets() const
Definition Domaine.h:112
int_t nb_som_tot() const
Renvoie le nombre total de sommets du domaine i.e. le nombre de sommets reels et virtuels sur le proc...
Definition Domaine.h:123
int_t nb_som() const
Renvoie le nombre de sommets du domaine.
Definition Domaine.h:121
void remplir_type_elem_Cl(const Domaine_EF &)
appele par remplir_volumes_entrelaces_Cl() : remplissage de type_elem_Cl_
Domaine_EF & domaine_EF()
int initialiser(double temps) override
Initialise les CLs Contrairement aux methodes mettre_a_jour, les methodes.
void imposer_symetrie(DoubleTab &, int tous_les_sommets_sym=0) const
Impose les conditions de symetrie c.
int nb_bord_periodicite() const
void modifie_gradient(ArrOfDouble &grad_mod, const ArrOfDouble &grad, int num_som) const
void imposer_symetrie_partiellement(DoubleTab &, const Noms &) const
void imposer_symetrie_matrice_secmem(Matrice_Morse &la_matrice, DoubleTab &secmem) const
On transforme la_matrice et le secmem pour avoir un secmem normal aux bords , plus la matrice pour as...
void imposer_cond_lim(Champ_Inc_base &, double) override
Impose les conditions aux limites a la valeur temporelle "temps" du Champ_Inc.
int nb_faces_sortie_libre() const
ArrOfInt type_sommet_
classe Domaine_Cl_dis_base Les objets Domaine_Cl_dis_base representent les conditions aux limites
virtual int initialiser(double temps)
Initialise les CLs Contrairement aux methodes mettre_a_jour, les methodes.
virtual const Champ_Inc_base & inconnue() const
int nb_cond_lim() const
Renvoie le nombre de conditions aux limites.
void completer()
Appel Cond_lim_base::completer() sur chaque condition aux limites.
Conds_lim & les_conditions_limites()
Renvoie le tableaux des conditions aux limites.
Domaine_dis_base & domaine_dis()
Renvoie une reference sur le domaine discretise associe aux conditions aux limites.
class Domaine_EF
Definition Domaine_EF.h:59
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
int face_sommets(int i, int j) const
renvoie le numero du ieme sommet de la face num_face.
Definition Domaine_VF.h:583
const Front_VF & front_VF(int i) const
Definition Domaine_VF.h:112
classe Domaine_dis_base Cette classe est la base de la hierarchie des domaines discretisees.
const Domaine & domaine() const
int nb_som_tot() const
Class defining operators and methods for all reading operation in an input flow (file,...
Definition Entree.h:42
virtual const Champ_Inc_base & inconnue() const =0
Probleme_base & probleme()
Renvoie le probleme associe a l'equation.
virtual int nb_comp() const
Definition Field_base.h:56
virtual Nature_du_champ nature_du_champ() const
Definition Field_base.h:77
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
const Nom & le_nom() const override
Renvoie le nom de la frontiere geometrique.
Classe Matrice_Morse Represente une matrice M (creuse), non necessairement carree.
const auto & get_tab2() const
const auto & get_tab1() const
double coef(int i, int j) const
const Equation_base & equation() const
Renvoie la reference sur l'equation pointe par MorEqn::mon_equation.
Definition MorEqn.h:62
Classe Neumann_homogene Cette classe est la classe de base de la hierarchie des conditions aux limite...
Classe Neumann Cette classe est la classe de base de la hierarchie des conditions aux limites de type...
Definition Neumann.h:31
class Nom Une chaine de caractere pour nommer les objets de TRUST
Definition Nom.h:31
Un tableau de chaine de caracteres (VECT(Nom)).
Definition Noms.h:26
int rang(const char *const ch) const
Definition Noms.cpp:65
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
static int bidim_axi
Definition Objet_U.h:102
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
const Discretisation_base & discretisation() const
Renvoie la discretisation associee au probleme.
static void abort()
Routine de sortie de Trio-U sur une erreur abort().
Definition Process.cpp:570
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
void set_value(int_t i_liste, int_t i_element, int_t valeur)
affecte la "valeur" au j-ieme element de la i-ieme liste avec 0 <= i < get_nb_lists() et 0 <= j < get...
int_t get_list_size(int_t i_liste) const
renvoie le nombre d'elements de la liste i
void set_list_sizes(const ArrOfInt_t &sizes)
detruit les listes existantes et en cree de nouvelles.
classe Symetrie Sur les faces de symetrie on a les proprietes suivantes:
Definition Symetrie.h:37
_SIZE_ size_array() const
_SIZE_ dimension_tot(int) const override
Definition TRUSTTab.tpp:160
_SIZE_ dimension(int d) const
Definition TRUSTTab.tpp:133