TrioCFD 1.9.8
TrioCFD documentation
Loading...
Searching...
No Matches
Estimateur_Aposteriori_P0_VEF.cpp
1/****************************************************************************
2* Copyright (c) 2022, 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 <Estimateur_Aposteriori_P0_VEF.h>
17#include <Navier_Stokes_Aposteriori.h>
18#include <Terme_Source_Qdm_VEF_Face.h>
19#include <Champ_P1_isoP1Bulle.h>
20#include <Champ_P1NC.h>
21
22#include <Source.h>
23
24Implemente_instanciable( Estimateur_Aposteriori_P0_VEF, "Estimateur_Aposteriori_P0_VEF", Champ_Fonc_P0_VEF ) ;
25
26Sortie& Estimateur_Aposteriori_P0_VEF::printOn( Sortie& s ) const { return s << que_suis_je() << " " << le_nom(); }
27
29
30void Estimateur_Aposteriori_P0_VEF::associer_champ(const Champ_P1NC& la_vitesse, const Champ_P1_isoP1Bulle& la_pression, const Champ_Don_base& la_viscosite_cinematique, const Domaine_Cl_dis_base& le_dom_Cl_dis_base)
31{
32 le_dom_Cl_VEF = ref_cast(Domaine_Cl_VEF, le_dom_Cl_dis_base);
33 vitesse_= la_vitesse;
34 pression_p1isop1b_ = la_pression;
35 viscosite_cinematique_ = la_viscosite_cinematique;
36}
37
39{
40 const Domaine_Cl_VEF& domaine_cl_VEF = le_dom_Cl_VEF.valeur();
41 const Domaine_VEF& domaine_VEF = domaine_cl_VEF.domaine_vef();
42 const Domaine_VEF& domaine_VEF_p = ref_cast(Domaine_VEF, le_dom_VF.valeur());
43 const Domaine& domaine = domaine_VEF_p.domaine();
44
45 const DoubleTab& face_normales = domaine_VEF.face_normales();
46 const DoubleVect& face_surfaces = domaine_VEF.face_surfaces();
47 const int nb_faces = domaine_VEF.nb_faces_tot();
48 DoubleVect coeff_faces(nb_faces);
49 const IntTab& face_voisins = domaine_VEF.face_voisins();
50 int premiere_face_int = domaine_VEF.premiere_face_int();
51 const IntTab& som_elem=domaine.les_elems();
52
53 double sautdirectionnel;
54 double estimtot;
55 double contri_elem_i;
56 double signe;
57 double estimloc;
58
59 int dim = Objet_U::dimension;
60 int fac,elem1,elem2;
61 int i,j,ielem;
62 int som_opp;
63
64 int nps=domaine_VEF_p.numero_premier_sommet();
65 int nb_elem = domaine_VEF.nb_elem();
66 int nb_elem_tot = domaine_VEF.nb_elem_tot();
67 const DoubleVect& inverse_volumes = domaine_VEF.inverse_volumes();
68 DoubleTab la_vitesse = vitesse_->valeurs();
69 DoubleTab la_pression = pression_p1isop1b_->valeurs();
70
71 DoubleTab le_terme_source(vitesse_->valeurs());
72
73
74 Navier_Stokes_Aposteriori& eq = ref_cast(Navier_Stokes_Aposteriori,vitesse_->equation());
75 //const Sources& sources_eq = eq.sources();
76
77 OWN_PTR(Champ_base) espace_stockage;
78 const Champ_base& ch_bs = eq.get_champ_source().get_champ(espace_stockage);
79 const DoubleTab& src = ch_bs.valeurs();
80
81 //Cerr << src << finl;
82
83 le_terme_source = src;
84 DoubleTab gradient_elem(nb_elem_tot,dim,dim);
85 gradient_elem=0.;
86 const DoubleTab tabnu=viscosite_cinematique_->valeurs();
87 int sz=tabnu.size();
88
89 DoubleVect visc(nb_elem);
90 if ( sz == 1)
91 {
92 visc = tabnu(0,0);
93 }
94 else
95 {
96 visc = tabnu(0);
97 }
98 coeff_faces = 1.0; // Si dim = 2
99 if (dim == 3)
100 {
101 for (fac=0; fac<nb_faces; fac++)
102 {
103 coeff_faces(fac) = pow(face_surfaces(fac),0.5);
104 }
105 }
106
107
108 DoubleTab& estim = valeurs(); // Estimateur
109 estim = 0.;
110
111// Residus aux elements (le Laplacien de vitesse et le gradient de pression P0 sont nuls; il reste le terme source, le gradient de pression P1 et le terme de convection)
112
113 // Calcul du terme de convection "u . grad u"
114 // Calcul d'une vitesse moyenne par element, comme moyenne des (dim + 1) vitesses à ses faces; sert à calculer "u" dans "u . grad u"
115
116 DoubleTab vite_moye(nb_elem,dim);
117 vite_moye=0.;
118 DoubleTab convec(nb_elem,dim);
119 convec=0.;
120
121 for (fac=0; fac<nb_faces; fac++) // calcul de vite_moye comme moyenne de la vitesse
122 {
123 elem1=face_voisins(fac,0);
124 elem2=face_voisins(fac,1);
125 if (elem1>=0)
126 {
127 for (i=0; i<dim; i++)
128 {
129 vite_moye(elem1,i) += la_vitesse(fac,i);
130 }
131 }
132 if (elem2>=0)
133 {
134 for (i=0; i<dim; i++)
135 {
136 vite_moye(elem2,i) += la_vitesse(fac,i);
137 }
138 }
139 }
140 vite_moye /= (dim+1.0);
141
142 // Calcul du gradient des vitesses; sert à calculer "grad u" dans "u . grad u"
143 Champ_P1NC::calcul_gradient(la_vitesse, gradient_elem, le_dom_Cl_VEF.valeur());
144
145
146 // Calcul de "u . grad u"
147
148 for (ielem=0; ielem<nb_elem; ielem++)
149 {
150 for (i=0; i<dim; i++)
151 {
152 for (j=0; j<dim; j++)
153 {
154 convec(ielem,i) += vite_moye(ielem,j) * gradient_elem(ielem,i,j);
155 }
156 }
157 }
158 // Calcul du gradient de pression P1, si applicable
159 DoubleTab grad_pression(nb_elem,dim);
160 grad_pression = 0.;
161 if (domaine_VEF_p.get_alphaS()) // On a une pression P1
162 {
163 for (fac=0; fac<nb_faces; fac++)
164 {
165 elem1=face_voisins(fac,0);
166 elem2=face_voisins(fac,1);
167
168 if (elem1>=0)
169 {
170 signe=1.;
171 som_opp = le_dom_VF->get_num_fac_loc(fac, 0);
172 som_opp = som_elem(elem1, som_opp);
173 for (j=0; j<dim; j++)
174 {
175 grad_pression(elem1,j) -= signe * la_pression(nps+som_opp) * face_normales(fac,j);
176 }
177 }
178
179 if (elem2>=0)
180 {
181 signe=-1.;
182 som_opp = le_dom_VF->get_num_fac_loc(fac, 1);
183 som_opp = som_elem(elem2, som_opp);
184 for (j=0; j<dim; j++)
185 {
186 grad_pression(elem2,j) -= signe * la_pression(nps+som_opp) * face_normales(fac,j);
187 }
188 }
189 }
190 for (ielem=0; ielem<nb_elem; ielem++)
191 {
192 for (j=0; j<dim; j++)
193 {
194 grad_pression(ielem,j) *= inverse_volumes(ielem)/dim;
195 }
196 }
197 }
198 // Calcul du terme source par element, comme moyenne des sources aux faces
199 DoubleTab source_moye(nb_elem,dim);
200 source_moye=0.;
201 for (fac=0; fac<nb_faces; fac++) // calcul de vite_moye comme moyenne de la vitesse
202 {
203 elem1=face_voisins(fac,0);
204 elem2=face_voisins(fac,1);
205 if (elem1>=0)
206 {
207 for (i=0; i<dim; i++)
208 {
209 source_moye(elem1,i) += le_terme_source(fac,i);
210 }
211 }
212 if (elem2>=0)
213 {
214 for (i=0; i<dim; i++)
215 {
216 source_moye(elem2,i) += le_terme_source(fac,i);
217 }
218 }
219 }
220 source_moye /= (dim+1.0);
221
222// Calcul des Residus aux elements
223 for (ielem=0; ielem<nb_elem; ielem++)
224 {
225 estimloc = 0.;
226 for (i=0; i<dim; i++)
227 {
228 contri_elem_i = ( source_moye(ielem,i) - grad_pression(ielem,i) - convec(ielem,i) );
229 estimloc += contri_elem_i * contri_elem_i;
230 }
231 estim(ielem) += estimloc / pow( inverse_volumes(ielem), (1.0 + 2.0/dim) );
232 }
233
234// Fin Residus aux elements
235
236
237
238
239
240
241
242// Sauts au travers des faces - partie dans la direction de la normale (seules les faces internes contribuent)
243 if (domaine_VEF_p.get_alphaE()) // Si on a une pression P0 elle est discontinue et donc contribue aux sauts au travers des faces
244 {
245 for (fac=premiere_face_int; fac<nb_faces; fac++)
246 {
247 elem1=face_voisins(fac,0);
248 elem2=face_voisins(fac,1);
249 if ( (elem1>=0) && (elem2>=0) )
250 {
251 for (i=0; i<dim; i++)
252 {
253 sautdirectionnel = 0.;
254 for (j=0; j<dim; j++)
255 {
256 sautdirectionnel += ( visc(elem1)*gradient_elem(elem1,i,j) - visc(elem2)*gradient_elem(elem2,i,j) ) * face_normales(fac,j);
257 }
258 sautdirectionnel -= ( la_pression(elem1) - la_pression(elem2) ) * face_normales(fac,i);
259 sautdirectionnel *= sautdirectionnel;
260 sautdirectionnel /= coeff_faces(fac);
261 estim(elem1) += sautdirectionnel/2.0;
262 estim(elem2) += sautdirectionnel/2.0;
263 }
264 }
265 }
266 }
267 else // Sinon la pression est continue et ne contribue donc pas aux sauts
268 {
269 for (fac=premiere_face_int; fac<nb_faces; fac++)
270 {
271 elem1=face_voisins(fac,0);
272 elem2=face_voisins(fac,1);
273 if ( (elem1>=0) && (elem2>=0) )
274 {
275 for (i=0; i<dim; i++)
276 {
277 sautdirectionnel = 0.;
278 for (j=0; j<dim; j++)
279 {
280 sautdirectionnel += ( visc(elem1)*gradient_elem(elem1,i,j) - visc(elem2)*gradient_elem(elem2,i,j) ) * face_normales(fac,j);
281 }
282 sautdirectionnel *= sautdirectionnel;
283 sautdirectionnel /= coeff_faces(fac);
284 estim(elem1) += sautdirectionnel/2.0;
285 estim(elem2) += sautdirectionnel/2.0;
286 }
287 }
288 }
289 }
290
291// Sauts au travers des faces - partie dans la direction tangente à la face (1 contribution si dim=2 et 3 contributions si dim=3)
292
293 if (dim == 3)
294 {
295 for (fac=premiere_face_int; fac<nb_faces; fac++) // faces internes
296 {
297 elem1=face_voisins(fac,0);
298 elem2=face_voisins(fac,1);
299 if ( (elem1>=0) && (elem2>=0) )
300 {
301 for (i=0; i<dim; i++)
302 {
303 sautdirectionnel = ( visc(elem1)*gradient_elem(elem1,i,1) - visc(elem2)*gradient_elem(elem2,i,1) ) * face_normales(fac,2) - ( visc(elem1)*gradient_elem(elem1,i,2) - visc(elem2)*gradient_elem(elem2,i,2) ) * face_normales(fac,1); // composante 1 du produit vectoriel : [g(u_i)]_2 * n_3 - [g(u_i)]_3 * n_2
304 sautdirectionnel *= sautdirectionnel;
305 sautdirectionnel /= coeff_faces(fac);
306 estim(elem1) += sautdirectionnel/2.0;
307 estim(elem2) += sautdirectionnel/2.0;
308
309 sautdirectionnel = ( visc(elem1)*gradient_elem(elem1,i,2) - visc(elem2)*gradient_elem(elem2,i,2) ) * face_normales(fac,0) - ( visc(elem1)*gradient_elem(elem1,i,0) - visc(elem2)*gradient_elem(elem2,i,0) ) * face_normales(fac,2); // composante 2 du produit vectoriel : [g(u_i)]_3 * n_1 - [g(u_i)]_1 * n_3
310 sautdirectionnel *= sautdirectionnel;
311 sautdirectionnel /= coeff_faces(fac);
312 estim(elem1) += sautdirectionnel/2.0;
313 estim(elem2) += sautdirectionnel/2.0;
314
315 sautdirectionnel = ( visc(elem1)*gradient_elem(elem1,i,0) - visc(elem2)*gradient_elem(elem2,i,0) ) * face_normales(fac,1) - ( visc(elem1)*gradient_elem(elem1,i,1) - visc(elem2)*gradient_elem(elem2,i,1) ) * face_normales(fac,0); // composante 3 du produit vectoriel : [g(u_i)]_1 * n_2 - [g(u_i)]_2 * n_1
316 sautdirectionnel *= sautdirectionnel;
317 sautdirectionnel /= coeff_faces(fac);
318 estim(elem1) += sautdirectionnel/2.0;
319 estim(elem2) += sautdirectionnel/2.0;
320 }
321 }
322 }
323
324 /* for (fac=0; fac<premiere_face_int; fac++) // faces du bord (non implemente en attendant un traitement complet des differentes conditions aux limites possibles)
325 {
326 elem1=face_voisins(fac,0);
327 elem2=face_voisins(fac,1);
328 if ( elem1 > 0)
329 {
330 elem = elem1;
331 }
332 if ( elem2 > 0)
333 {
334 elem = elem2;
335 }
336 for (i=0; i<dim; i++)
337 {
338 sautdirectionnel = visc(elem)*gradient_elem(elem,i,1) * face_normales(fac,2) - visc(elem)*gradient_elem(elem,i,2) * face_normales(fac,1); // composante 1 du produit vectoriel : [g(u_i)]_2 * n_3 - [g(u_i)]_3 * n_2
339 sautdirectionnel *= sautdirectionnel;
340 sautdirectionnel /= coeff_faces(fac);
341 estim(elem) += sautdirectionnel;
342
343 sautdirectionnel = visc(elem)*gradient_elem(elem,i,2) * face_normales(fac,0) - visc(elem)*gradient_elem(elem,i,0) * face_normales(fac,2); // composante 2 du produit vectoriel : [g(u_i)]_3 * n_1 - [g(u_i)]_1 * n_3
344 sautdirectionnel *= sautdirectionnel;
345 sautdirectionnel /= coeff_faces(fac);
346 estim(elem) += sautdirectionnel;
347
348 sautdirectionnel = visc(elem)*gradient_elem(elem,i,0) * face_normales(fac,1) - visc(elem)*gradient_elem(elem,i,1) * face_normales(fac,0); // composante 3 du produit vectoriel : [g(u_i)]_1 * n_2 - [g(u_i)]_2 * n_1
349 sautdirectionnel *= sautdirectionnel;
350 sautdirectionnel /= coeff_faces(fac);
351 estim(elem) += sautdirectionnel;
352 }
353 } */
354 }
355
356
357
358 if (dim == 2)
359 {
360 for (fac=premiere_face_int; fac<nb_faces; fac++) // faces internes
361 {
362 elem1=face_voisins(fac,0);
363 elem2=face_voisins(fac,1);
364 if ( (elem1>=0) && (elem2>=0) )
365 {
366 for (i=0; i<dim; i++)
367 {
368 sautdirectionnel = 0.;
369 sautdirectionnel = ( visc(elem1)*gradient_elem(elem1,i,0) - visc(elem2)*gradient_elem(elem2,i,0) ) * face_normales(fac,1) - ( visc(elem1)*gradient_elem(elem1,i,1) - visc(elem2)*gradient_elem(elem2,i,1) ) * face_normales(fac,0);
370 sautdirectionnel *= sautdirectionnel;
371 sautdirectionnel /= coeff_faces(fac);
372 estim(elem1) += sautdirectionnel/2.0;
373 estim(elem2) += sautdirectionnel/2.0;
374 }
375 }
376 }
377
378 /* for (fac=0; fac<premiere_face_int; fac++) // faces du bord (non implemente en attendant un traitement complet des differentes conditions aux limites possibles)
379 {
380 elem1=face_voisins(fac,0);
381 elem2=face_voisins(fac,1);
382 cout << "17 " << endl;
383 if ( elem1 > 0)
384 {
385 ielem = elem1;
386 }
387 if ( elem2 > 0)
388 {
389 ielem = elem2;
390 }
391 for (i=0; i<dim; i++)
392 {
393 cout << "18 ielem" << ielem << endl;
394 sautdirectionnel = visc(ielem)*gradient_elem(ielem,i,0) * face_normales(fac,1) - visc(ielem)*gradient_elem(ielem,i,1) * face_normales(fac,0);
395 sautdirectionnel *= sautdirectionnel;
396 sautdirectionnel /= coeff_faces(fac);
397 estim(ielem) += sautdirectionnel;
398 }
399 } */
400 }
401
402
403 estimtot = 0.;
404
405 for (ielem=0; ielem<nb_elem; ielem++)
406 {
407 estimtot += estim(ielem);
408 estim(ielem) = sqrt(estim(ielem));
409 }
410 estimtot = sqrt(estimtot);
411 cout << "Estimateur_Aposteriori_P0_VEF::mettre_a_jour - estimateur = " << estimtot << endl;
412
413 changer_temps(tps);
415}
classe Champ_Don_base classe de base des Champs donnes (non calcules)
DoubleTab & valeurs() override
Surcharge Champ_base::valeurs() Renvoie le tableau des valeurs.
classe Champ_Fonc_P0_VEF
virtual const Domaine & domaine() const
void mettre_a_jour(double temps) override
Mise a jour en temps du champ.
static DoubleTab & calcul_gradient(const DoubleTab &, DoubleTab &, const Domaine_Cl_VEF &)
const Champ_base & get_champ(OWN_PTR(Champ_base)&espace_stockage) const override
virtual DoubleTab & valeurs()=0
classe Champ_base Cette classe est la base de la hierarchie des champs.
Definition Champ_base.h:43
virtual double changer_temps(const double t)
Fixe le temps auquel se situe le champ.
Domaine_VEF & domaine_vef()
classe Domaine_Cl_dis_base Les objets Domaine_Cl_dis_base representent les conditions aux limites
class Domaine_VEF
Definition Domaine_VEF.h:54
int numero_premier_sommet() const
int get_alphaS() const
Definition Domaine_VEF.h:93
int get_alphaE() const
Definition Domaine_VEF.h:92
virtual const DoubleVect & face_surfaces() const
Definition Domaine_VF.h:51
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 premiere_face_int() const
une face est interne ssi elle separe deux elements.
Definition Domaine_VF.h:463
int face_voisins(int num_face, int i) const
renvoie l'element voisin de numface dans la direction i.
Definition Domaine_VF.h:418
double inverse_volumes(int i) const
Definition Domaine_VF.h:114
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
void mettre_a_jour(double) override
Mise a jour en temps du champ.
void associer_champ(const Champ_P1NC &, const Champ_P1_isoP1Bulle &, const Champ_Don_base &, const Domaine_Cl_dis_base &)
const Nom & le_nom() const override
Renvoie le nom du champ.
Champ_Post_Operateur_Eqn & get_champ_source()
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
Classe de base des flux de sortie.
Definition Sortie.h:52
_SIZE_ size() const
Definition TRUSTVect.tpp:45