TrioCFD 1.9.9_beta
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 Fill the internal arrays.
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 // Use is_sommet_sur_bord to set the size of the lists stored in som_face_bord.
105 // - som_face_bord contains nb_som_tot lists
106 // - each list is sized by the number of boundary faces (bearing a Dirichlet BC)
107 // connected to the considered vertex
108 // - a given list for a vertex stores the indices of the faces connected to it
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 Called by remplir_volumes_entrelaces_Cl(): fills 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// If we have Dirichlet_paroi_fixe_iso_Genepi2, the 0 is not taken into account for the average
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 // if we have a Dirichlet, store 2*nb_participant + 1 if the vertex also belongs to a symmetry boundary
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 // Build the vertex -> symmetry boundary face connectivity
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 contains the number of symmetry faces associated with each vertex
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 // determine the vertex normal
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<<" must cancel a first 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 // ease debugging
294 if (std::fabs(min_array(t1))>max_array(t1))
295 t1*=-1;
296 t1/=norme_array(t1);
297
298
299 // Cerr<<som<<" must cancel a second 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 // ease debugging
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 Imposes symmetry conditions, i.e. cancels the field components along the normal(s).
348 *
349 * If tous_les_sommets_sym = 1, even vertices that also belong to a Dirichlet boundary are zeroed.
350 * @param values Field values array to modify.
351 * @param tous_les_sommets_sym If 1, apply symmetry to all symmetry vertices including Dirichlet ones.
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 Transforms la_matrice and secmem to produce a secmem normal to boundaries,
477 * plus the matrix needed to ensure that the solution is correct.
478 * @param la_matrice Morse matrix to modify.
479 * @param secmem Right-hand side vector to modify.
480 */
481void Domaine_Cl_EF::imposer_symetrie_matrice_secmem(Matrice_Morse& la_matrice, DoubleTab& secmem) const
482{
483 // return;
484 assert(secmem.dimension(1)==dimension);
485 const Domaine& z = domaine_dis().domaine();
486 int nb_som=z.nb_som();
487 assert(secmem.dimension(0)==nb_som);
488 int nb_comp=secmem.dimension(1);
489 const DoubleTab& n =normales_symetrie_->valeurs();
490 const DoubleTab& n_bis =normales_symetrie_bis_->valeurs();
491 ArrOfDouble normale(dimension);
492
493 const auto& tab1 = la_matrice.get_tab1();
494 const auto& tab2 = la_matrice.get_tab2();
495
496 const DoubleTab& champ_inconnue = equation().inconnue().valeurs();
497 int dirmax=2;
498 if (normales_symetrie_ter_) dirmax=3;
499 for (int som=0; som<nb_som; som++)
500 if ( type_sommet_[som]==1)
501 {
502 for (int dir=0; dir<dirmax; dir++)
503 {
504 const DoubleTab& nn=(dir==0?n:(dir==1?n_bis:normales_symetrie_ter_->valeurs()));
505 for (int d=0; d<dimension; d++) normale[d]=nn(som,d);
506 // First recompute secmem = secmem - A*present in order to be able to modify A (and project at the same time)
507 auto nb_coeff_ligne=tab1[som*nb_comp+1] - tab1[som*nb_comp];
508 for (int k=0; k<nb_coeff_ligne; k++)
509 {
510 for (int comp=0; comp<nb_comp; comp++)
511 {
512 int j=tab2[tab1[som*nb_comp+comp]-1+k]-1;
513 //assert(j!=(som*nb_comp+comp));
514 //if ((j>=(som*nb_comp))&&(j<(som*nb_comp+nb_comp)))
515
516 const double coef_ij=la_matrice(som*nb_comp+comp,j);
517 int som2=j/nb_comp;
518 int comp2=j-som2*nb_comp;
519 secmem(som,comp)-=coef_ij*champ_inconnue(som2,comp2);
520 }
521 }
522 double somme_b=0;
523
524 for (int comp=0; comp<nb_comp; comp++)
525 somme_b+=secmem(som,comp)*normale[comp];
526 //Cerr<<som<<" sommet " <<somme_b<<" "<<secmem(som,0)<<" "<<secmem(som,1)<<finl;
527 // subtract secmem.n * n
528 for (int comp=0; comp<nb_comp; comp++)
529 secmem(som,comp)-=somme_b*normale[comp];
530
531 if (1)
532 {
533 // restore the same diagonal everywhere, using the average
534 double ref=0;
535 for (int comp=0; comp<nb_comp; comp++)
536 {
537
538 int j0=som*nb_comp+comp;
539 ref+=la_matrice.coef(j0,j0);
540 }
541 ref/=nb_comp;
542
543 for (int comp=0; comp<nb_comp; comp++)
544 {
545 int j0=som*nb_comp+comp;
546 double rap=ref/la_matrice.coef(j0,j0);
547 //Cerr<<dir<<" "<<som <<" "<<comp<<" rpp "<<rap <<finl;
548 for (int k=0; k<nb_coeff_ligne; k++)
549 {
550
551 int j=tab2[tab1[j0]-1+k]-1;
552 la_matrice(j0,j)*=rap;
553 }
554 assert(est_egal(la_matrice(j0,j0),ref));
555 }
556 }
557 if (1)
558 {
559 // cancel all off-diagonal block coefficients
560 // on rows i for which normale(d) != 0
561 // i.e. fabs(normale(d)) > tol
562 const double tol = 1e-12;
563 for (int k=0; k<nb_coeff_ligne; k++)
564 {
565
566 for (int comp=0; comp<nb_comp; comp++)
567 if (std::fabs(normale[comp])>tol)
568 {
569 int j=tab2[tab1[som*nb_comp+comp]-1+k]-1;
570 if (j!=(som*nb_comp+comp))
571 if ((j>=(som*nb_comp))&&(j<(som*nb_comp+nb_comp)))
572 {
573 la_matrice(som*nb_comp+comp,j)=0;
574 }
575 }
576 }
577 }
578 {
579 // for off-diagonal blocks, ensure that Aij.ni = 0
580
581 ArrOfDouble somme((int)nb_coeff_ligne);
582 for (int k=0; k<nb_coeff_ligne; k++)
583 {
584
585 int j=tab2[tab1[som*nb_comp]-1+k]-1;
586 for (int comp=0; comp<nb_comp; comp++)
587 somme[k]+=la_matrice(som*nb_comp+comp,j)*normale[comp];
588 }
589 // subtract somme * ni
590 for (int k=0; k<nb_coeff_ligne; k++)
591 {
592
593 int j=tab2[tab1[som*nb_comp]-1+k]-1;
594 for (int comp=0; comp<nb_comp; comp++)
595 if ((j<(som*nb_comp))||(j>=(som*nb_comp+nb_comp)))
596 la_matrice(som*nb_comp+comp,j)-=(somme[k])*normale[comp];
597 }
598 }
599 // Finally recompute secmem = secmem + A*champ_inconnue (A has been heavily modified)
600 for (int k=0; k<nb_coeff_ligne; k++)
601 {
602 for (int comp=0; comp<nb_comp; comp++)
603 {
604 int j=tab2[tab1[som*nb_comp+comp]-1+k]-1;
605 int som2=j/nb_comp;
606 int comp2=j-som2*nb_comp;
607
608 const double coef_ij=la_matrice(som*nb_comp+comp,j);
609 secmem(som,comp)+=coef_ij*champ_inconnue(som2,comp2);
610
611 }
612 }
613 {
614 // verification
615 double somme_b2=0;
616
617 for (int comp=0; comp<nb_comp; comp++)
618 somme_b2+=secmem(som,comp)*normale[comp];
619 //Cerr<<" lllllllll "<<somme_b2<<" "<<tt<<finl;
620 if (std::fabs(somme_b2) >= 1e-8)
621 Cerr << "Domaine_Cl_EF::imposer_symetrie_matrice_secmem: secmem.n != 0 ("
622 << somme_b2 << ") au sommet " << som << ", projection appliquee." << finl;
623 // subtract secmem.n * n
624 for (int comp=0; comp<nb_comp; comp++)
625 secmem(som,comp)-=somme_b2*normale[comp];
626
627 }
628 }
629 }
630 // exit();
631}
632
633/*! @brief Imposes boundary conditions at time "temps" of the Champ_Inc.
634 * @param ch Instationary field to apply boundary conditions to.
635 * @param temps Current time value.
636 */
638{
639 DoubleTab& ch_tab = ch.valeurs(temps);
640 int nb_comp = ch.nb_comp();
641 const Domaine_EF& domaineEF = domaine_EF(); //ref_cast(Domaine_EF,ch.equation().domaine_dis());
642 const IntTab& faces_sommets=domaineEF.face_sommets();
643 int nb_som_face=faces_sommets.dimension(1);
644 const DoubleTab& coords= domaineEF.domaine().coord_sommets();
645
646 // first zero the field on Dirichlet boundaries
647 // then add 1/nb_cl * val_imp
648
649 for (int n_bord=0; n_bord<nb_cond_lim(); n_bord++)
650 {
651
652 const Cond_lim_base& la_cl = les_conditions_limites(n_bord).valeur();
653 const Front_VF& le_bord = ref_cast(Front_VF,la_cl.frontiere_dis());
654 int num2 = le_bord.nb_faces_tot();
655
656 if (sub_type(Dirichlet,la_cl)||(sub_type(Dirichlet_homogene,la_cl)))
657 {
658 //const Dirichlet& la_cl_diri = ref_cast(Dirichlet,la_cl);
659
660 for (int ind_face=0; ind_face<num2; ind_face++)
661 {
662 int face=le_bord.num_face(ind_face);
663 for (int s=0; s<nb_som_face; s++)
664 {
665 int som=faces_sommets(face,s);
666 assert(type_sommet_[som]>=2);
667
668
669 if (nb_comp == 1)
670 ch_tab[som]=0;
671 else
672 for (int ncomp=0; ncomp<nb_comp; ncomp++)
673 ch_tab(som,ncomp)=0;
674 }
675 }
676 }
677 }
678 for (int n_bord=0; n_bord<nb_cond_lim(); n_bord++)
679 {
680
681 const Cond_lim_base& la_cl = les_conditions_limites(n_bord).valeur();
682 const Front_VF& le_bord = ref_cast(Front_VF,la_cl.frontiere_dis());
683 int num2 = le_bord.nb_faces_tot();
684
685 if (sub_type(Dirichlet,la_cl))
686 {
687 const Dirichlet& la_cl_diri = ref_cast(Dirichlet,la_cl);
688 if (sub_type(Champ_front_softanalytique,la_cl_diri.champ_front()))
689 {
690 Cerr<<" You must use Champ_front_fonc_txyz instead of "<<la_cl_diri.champ_front().que_suis_je()<<finl;
691 exit();
692 }
693 int avec_valeur_aux_sommets=0;
694 if (sub_type(Champ_front_var_instationnaire,la_cl_diri.champ_front()))
695 {
697 avec_valeur_aux_sommets=ch_txyz.valeur_au_temps_et_au_point_disponible();
698 }
699 // For Dirichlet faces, impose the unknown at the vertex
700 if (avec_valeur_aux_sommets)
701 {
703 for (int ind_face=0; ind_face<num2; ind_face++)
704 {
705 int face=le_bord.num_face(ind_face);
706 for (int s=0; s<nb_som_face; s++)
707 {
708 int som=faces_sommets(face,s);
709 assert(type_sommet_[som]>=4);
710 double coef=1./(type_sommet_[som]/2-1);
711 //Cerr<<"iciPB "<<coef<<finl;
712 double x,y,z=0;
713 x=coords(som,0);
714 y=coords(som,1);
715 if (dimension==3)
716 z=coords(som,2);
717 if (nb_comp == 1)
718 ch_tab[som]+=coef*ch_txyz.valeur_au_temps_et_au_point(temps,som,x,y,z,0);
719 else
720 for (int ncomp=0; ncomp<nb_comp; ncomp++)
721 ch_tab(som,ncomp)+=coef*ch_txyz.valeur_au_temps_et_au_point(temps,som,x,y,z,ncomp);
722 }
723 }
724 }
725 else
726 for (int ind_face=0; ind_face<num2; ind_face++)
727 {
728 int face=le_bord.num_face(ind_face);
729 for (int s=0; s<nb_som_face; s++)
730 {
731 int som=faces_sommets(face,s);
732 assert(type_sommet_[som]>=4);
733 double coef=1./(type_sommet_[som]/2-1);
734 //Cerr<<"iciPB "<<coef<<finl;
735 if (nb_comp == 1)
736 ch_tab[som]+=coef*la_cl_diri.val_imp_au_temps(temps,ind_face);
737 else
738 for (int ncomp=0; ncomp<nb_comp; ncomp++)
739 ch_tab(som,ncomp)+=coef*la_cl_diri.val_imp_au_temps(temps,ind_face,ncomp);
740 }
741 }
742
743 }
744 /*
745 else if (sub_type(Dirichlet_homogene,la_cl))
746 {
747 // For Dirichlet faces, the unknown is imposed at the vertex
748 for (int ind_face=0; ind_face<num2; ind_face++)
749 {
750 int face=le_bord.num_face(ind_face);
751 for (int s=0;s<nb_som_face;s++)
752 {
753 int som=faces_sommets(face,s);
754 assert(type_sommet_(som)>=2);
755 if (nb_comp == 1)
756 ch_tab[som] = 0;
757 else
758 for (int ncomp=0; ncomp<nb_comp; ncomp++)
759 ch_tab(som,ncomp) =0;
760 }
761 }
762 }
763 */
764 // provisional: to be done only once
765 else if ( (sub_type(Symetrie,la_cl) ) &&
766 (ch.nature_du_champ()==vectoriel) )
767 {
768 imposer_symetrie(ch_tab);
769 }
770 }
771
772
773
774}
775
777{
778 exit();
779 /*
780 int compteur=0;
781 for(int cl=0; cl<les_conditions_limites_.size(); cl++)
782 {
783 if(sub_type(Neumann_sortie_libre, les_conditions_limites_[cl].valeur()))
784 {
785 const Front_VF& le_bord=ref_cast(Front_VF,les_conditions_limites_[cl]->frontiere_dis());
786 compteur+=le_bord.nb_faces();
787 }
788 }
789 return compteur;
790 */
791 return -1;
792}
793
795{
796 int compteur = 0;
797 for (const auto &itr : les_conditions_limites_)
798 {
799 if (sub_type(Periodique, itr.valeur()))
800 compteur++;
801 }
802 return compteur;
803}
804
805
807{
809
810 if (nb_bord_periodicite()>0)
811 {
812 Cerr<<" Periodicity is not implemented !!!"<<finl;
813 abort();
814 }
815 return 1;
816}
817
819{
820 return ref_cast(Domaine_EF, domaine_dis());
821}
822
824{
825 return ref_cast(Domaine_EF, domaine_dis());
826}
Class Champ_Inc_base.
DoubleTab & valeurs() override
Returns the array of field values at the current time.
Champ_front_softanalytique Class derived from Champ_front_var representing boundary.
class Champ_front_var_instationnaire Derived class from Champ_front_var that represents fields on
virtual double valeur_au_temps_et_au_point(double temps, int som, double x, double y, double z, int comp) const
class Cond_lim_base Base class for the hierarchy of classes that represent the different boundary con...
virtual Frontiere_dis_base & frontiere_dis()
Returns the discretized boundary to which the boundary conditions apply.
Champ_front_base & champ_front()
class Conds_lim This class represents a vector of boundary conditions.
Definition Conds_lim.h:32
Classe Dirichlet_homogene This class is the base class of the hierarchy of homogeneous Dirichlet-type...
Dirichlet This class is the base class of the hierarchy of Dirichlet-type boundary conditions.
Definition Dirichlet.h:31
virtual double val_imp_au_temps(double temps, int i) const
Returns the imposed value on the i-th component of the field at the boundary at the specified time.
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
Returns the total number of vertices of the domain i.e. the number of real and virtual vertices on th...
Definition Domaine.h:123
int_t nb_som() const
Returns the number of vertices of the domain.
Definition Domaine.h:121
void remplir_type_elem_Cl(const Domaine_EF &)
Called by remplir_volumes_entrelaces_Cl(): fills type_elem_Cl_.
Domaine_EF & domaine_EF()
int initialiser(double temps) override
Initializes the BCs. Unlike the update methods, the.
void imposer_symetrie(DoubleTab &, int tous_les_sommets_sym=0) const
Imposes symmetry conditions, i.e. cancels the field components along the normal(s).
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
Transforms la_matrice and secmem to produce a secmem normal to boundaries, plus the matrix needed to ...
void imposer_cond_lim(Champ_Inc_base &, double) override
Imposes boundary conditions at time "temps" of the Champ_Inc.
int nb_faces_sortie_libre() const
ArrOfInt type_sommet_
class Domaine_Cl_dis_base Domaine_Cl_dis_base objects represent discretized boundary conditions
virtual int initialiser(double temps)
Initializes the BCs. Unlike the update methods, the.
virtual const Champ_Inc_base & inconnue() const
int nb_cond_lim() const
Returns the number of boundary conditions.
void completer()
Calls Cond_lim_base::completer() on each boundary condition.
Conds_lim & les_conditions_limites()
Returns the array of boundary conditions.
Domaine_dis_base & domaine_dis()
Returns a reference to the discretized domain associated with the boundary conditions.
class Domaine_EF
Definition Domaine_EF.h:56
int nb_faces_tot() const
Returns the total number of 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
Returns the index of the i-th vertex of face num_face.
Definition Domaine_VF.h:582
const Front_VF & front_VF(int i) const
Definition Domaine_VF.h:112
class Domaine_dis_base This class is the base of the hierarchy of discretized domains.
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()
Returns the problem associated with the 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
Returns the name of the geometric boundary.
Matrice_Morse class - Represents a (sparse) matrix M, not necessarily square,.
const auto & get_tab2() const
const auto & get_tab1() const
double coef(int i, int j) const
const Equation_base & equation() const
Returns the reference to the equation pointed to by MorEqn::mon_equation.
Definition MorEqn.h:62
Classe Neumann_homogene This class is the base class of the hierarchy of homogeneous Neumann-type bou...
Classe Neumann This class is the base class of the hierarchy of Neumann-type boundary conditions.
Definition Neumann.h:31
class Nom: a character string for naming TRUST objects.
Definition Nom.h:31
An array of character strings (VECT(Nom)).
Definition Noms.h:26
int rang(const char *const ch) const
Definition Noms.cpp:65
static int dimension
Definition Objet_U.h:94
const Nom & que_suis_je() const
Returns the string identifying the class.
Definition Objet_U.cpp:104
virtual Entree & readOn(Entree &)
Reads an Objet_U from an input stream. Virtual method to override.
Definition Objet_U.cpp:289
static int bidim_axi
Definition Objet_U.h:97
virtual Sortie & printOn(Sortie &) const
Writes the object to an output stream. Virtual method to override.
Definition Objet_U.cpp:278
class Periodique This class represents a periodic boundary condition.
Definition Periodique.h:31
const Discretisation_base & discretisation() const
Returns the discretization associated with the problem.
static void abort()
Abort routine for TRUST on a fatal error.
Definition Process.cpp:573
static void exit(int exit_code=-1)
Exit routine for TRUST within a Kokkos region.
Definition Process.cpp:466
Base class for output streams.
Definition Sortie.h:52
void set_value(int_t i_liste, int_t i_element, int_t valeur)
Assigns "valeur" to the j-th element of the i-th list with 0 <= i < get_nb_lists() and 0 <= j < get_l...
int_t get_list_size(int_t i_liste) const
Returns the number of elements in list i.
void set_list_sizes(const ArrOfInt_t &sizes)
Destroys existing lists and creates new ones.
Symetrie On symmetry faces, the following properties hold:
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