TrioCFD 1.9.8
TrioCFD documentation
Loading...
Searching...
No Matches
Traitement_particulier_NS_EC.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 <Traitement_particulier_NS_EC.h>
17#include <Navier_Stokes_std.h>
18#include <Domaine_VF.h>
19#include <Terme_Source_Acceleration.h>
20#include <Milieu_base.h>
21#include <TRUST_Ref.h>
22#include <Probleme_base.h>
23#include <Schema_Temps_base.h>
24#include <sys/stat.h>
25
26Implemente_base_sans_constructeur_ni_destructeur(Traitement_particulier_NS_EC,"Traitement_particulier_NS_EC",Traitement_particulier_NS_base);
27// XD ec traitement_particulier_base ec INHERITS_BRACE Keyword to print total kinetic energy into the referential linked
28// XD_CONT to the domain (keyword Ec). In the case where the domain is moving into a Galilean referential, the keyword
29// XD_CONT Ec_dans_repere_fixe will print total kinetic energy in the Galilean referential whereas Ec will print the
30// XD_CONT value calculated into the moving referential linked to the domain
31// XD attr Ec rien Ec OPT not_set
32// XD attr Ec_dans_repere_fixe rien Ec_dans_repere_fixe OPT not_set
33// XD attr periode floattant periode OPT periode is the keyword to set the period of printing into the file
34// XD_CONT datafile_Ec.son or datafile_Ec_dans_repere_fixe.son.
35
36/*! @brief
37 *
38 * @param (Sortie& is) un flot de sortie
39 * @return (Sortie&) le flot de sortie modifie
40 */
42{
43 return is;
44}
45
46
47/*! @brief
48 *
49 * @param (Entree& is) un flot d'entree
50 * @return (Entree&) le flot d'entree modifie
51 */
53{
54 return is;
55}
56
58{
59 Motcle accouverte = "{" , accfermee = "}" ;
60 //Motcle valec="Ec";
61 Motcle motbidon, motlu;
62 periode = mon_equation->probleme().schema_temps().pas_temps_min();
63 is >> motbidon ;
64 if (motbidon == accouverte)
65 {
66 Motcles les_mots(2);
67 les_mots[0] = "Ec";
68 les_mots[1] = "Ec_dans_repere_fixe";
69 {
70 is >> motlu;
71 while(motlu != accfermee)
72 {
73 int rang=les_mots.search(motlu);
74 switch(rang)
75 {
76 case 0 :
77 case 1 :
78 {
79 if (rang==1)
81 is >> motlu;
82 if (motlu!="periode")
83 {
84 Cerr<<"On attendait le mot cle periode apres " << les_mots[rang] << "."<<finl;
85 exit();
86 }
87 is >> periode;
88 break;
89 }
90 default :
91 {
92 Cerr << "Erreur dans la lecture de Traitement_particulier_NS_EC";
93 Cerr << "Les mots cles possibles sont "<< les_mots <<" { et }" << finl;
94 Cerr << "Vous avez lu :" << motlu << finl;
95 exit();
96 break;
97 }
98 }
99 is >> motlu;
100 }
101 is >> motlu;
102 if (motlu != accfermee)
103 {
104 Cerr << "Erreur dans la lecture de Traitement_particulier_NS_EC";
105 Cerr << "On attendait une }" << finl;
106 exit();
107 }
108 }
109 }
110 else
111 {
112 Cerr << "Erreur dans la lecture de Traitement_particulier_NS_EC";
113 Cerr << "On attendait une {" << finl;
114 exit();
115 }
116 return is;
117}
118
120{
121 // Ouverture du fichier Nom_du_cas_EC.son
122 Nom nom_fich(nom_du_cas());
123 nom_fich += "_EC";
124 if (repere_mobile_)
125 nom_fich+="_dans_repere_fixe";
126 nom_fich+=".son";
127
128 const Probleme_base& pb=mon_equation->probleme();
129 struct stat f;
130 if (stat(nom_fich,&f) || (nb_bip==0 && !pb.reprise_effectuee()))
131 s.ouvrir(nom_fich);
132 else
133 s.ouvrir(nom_fich,ios::app);
134 s.setf(ios::scientific);
135 s.precision(8);
136}
137
139{
140 tinit = mon_equation->inconnue().temps();
141 nb_bip=0;
142 double Ec;
143 calculer_Ec(Ec);
144 if(je_suis_maitre())
145 {
146 SFichier le_fichier;
147 ouvrir_fichier(le_fichier);
148 // Ecriture premiere ligne
149 le_fichier<<"# Temps Energie_cinetique_totale"<<finl;
150 le_fichier<<tinit<<" "<<Ec<<finl;
151 }
152}
154{
155 double temps = mon_equation->inconnue().temps();
156 double nb = floor((temps - tinit) / periode);
157 if (nb > nb_bip + 0.5)
158 {
159 nb_bip=nb;
160 double Ec;
161 calculer_Ec(Ec);
162 if(je_suis_maitre())
163 {
164 SFichier le_fichier;
165 ouvrir_fichier(le_fichier);
166 le_fichier<<temps<<" "<<Ec<<finl;
167 }
168 }
169}
170
171/*! @brief Fonction outil utilisee dans calculer_Ec.
172 *
173 * Calcule la somme de 0.5*v^2*rho*volumes_entrelaces.
174 *
175 */
176static double trait_part_calculer_ec_faces(const int face_debut,
177 const int nb_faces,
178 const int frontiere,
179 const DoubleTab& vitesse,
180 const DoubleVect& volumes_entrelaces,
181 const DoubleTab& xv,
182 const DoubleTab& masse_volumique,
183 const ArrOfDouble& translation,
184 const ArrOfDouble& rotation,
185 const int repere_mobile_,
186 const ArrOfInt& faces_doubles
187 )
188{
189 const int face_fin = face_debut + nb_faces;
190 double ec = 0.;
191 double rho = 0.;
192 const int nb_dim_1 = (vitesse.line_size() == 1);
193 const int dim = Objet_U::dimension;
194 ArrOfDouble ve(Objet_U::dimension);
195 for (int face = face_debut; face < face_fin; face++)
196 {
197 // Calcul de la vitesse d'entrainement
198 if (repere_mobile_)
199 {
200 ve[0]=translation[0];
201 ve[1]=translation[1];
202 if (Objet_U::dimension==3)
203 {
204 ve[2]=translation[2];
205 ve[0]+=rotation[1]*xv(face,2)-rotation[2]*xv(face,1);
206 ve[1]+=rotation[2]*xv(face,0)-rotation[0]*xv(face,2);
207 ve[2]+=rotation[0]*xv(face,1)-rotation[1]*xv(face,0);
208 }
209 }
210 else
211 ve=0;
212
213 double v2;
214 double volume;
215 if (nb_dim_1)
216 {
217 // Une composante de vitesse a la face (VDF)
218 const double v = vitesse(face);
219 if (repere_mobile_)
220 {
221 Cerr << "Le codage de l'energie cinetique calculee dans un repere fixe" <<finl;
222 Cerr << "n'est pas fait en VDF." << finl;
223 Process::exit(); // En effet probleme de conception, il faudrait avoir l'orientation des faces VDF
224 }
225 v2 = v * v;
226 // En VDF, sur les frontieres, on ne prend que le 1/2 volume entrelace
227 volume = (frontiere ? 0.5 : 1) * volumes_entrelaces(face);
228 }
229 else
230 {
231 // Deux ou trois composantes (VEFP1B)
232 v2 = 0.;
233 for (int i = 0; i < dim; i++)
234 {
235 const double v_i = vitesse(face, i);
236 v2 += (v_i + ve[i]) * (v_i + ve[i]);
237 }
238 // En VEF, cela est incorrect, il faudrait les volumes etendus:
239 volume = volumes_entrelaces(face);
240 }
241 const int k = (masse_volumique.dimension(0)==1) ? 0 : face;
242 rho = masse_volumique(k, 0);
243 double contribution = (faces_doubles[face]==1) ? 0.5 : 1 ;
244 ec += contribution * 0.5 * v2 * volume * rho;
245 }
246 return ec;
247}
248
249/*! @brief Meme methode de calcul en VDF et en VEF.
250 *
251 * Si aucun champ de masse volumique n'a ete associe, on calcule
252 * INTEGRALE de 1/2 * u^2 sur le domaine.
253 * Si un champ de masse volumique a ete associe, il doit etre
254 * de type "champ aux faces". On calcule INTEGRALE de 1/2 * rho * u^2.
255 * rho est un champ P0 aux elements, u est P0 sur les volumes entrelaces
256 * Valeur de retour:
257 * La somme sur tous les processeurs de l'integrale de 1/2*rho*u*u.
258 *
259 */
260void Traitement_particulier_NS_EC::calculer_Ec(double& energie_cinetique)
261{
262
263 const Domaine_dis_base& zdisbase = mon_equation->inconnue().domaine_dis_base();
264 const Domaine_VF& domaine_VF = ref_cast(Domaine_VF, zdisbase);
265 const DoubleVect& volumes_entrelaces = domaine_VF.volumes_entrelaces();
266 const DoubleTab& xv = domaine_VF.xv();
267 const DoubleTab& vitesse = mon_equation->inconnue().valeurs();
268 OBS_PTR(ArrOfDouble) translation(xv);
269 OBS_PTR(ArrOfDouble) rotation(xv);
270 OBS_PTR(DoubleTab) rho(xv);
271 DoubleVect rotation_nulle(dimension);
272 rotation_nulle=0;
273 if (repere_mobile_)
274 {
275 int ok=0;
276 // Verification de l'existence d'un terme source Acceleration dans Navier Stokes
277 const Sources& les_sources=mon_equation->sources();
278
279 for (const auto& itr : les_sources)
280 {
281 if (sub_type(Terme_Source_Acceleration,itr.valeur()))
282 {
283 const Terme_Source_Acceleration& terme_source_acceleration=ref_cast(Terme_Source_Acceleration,itr.valeur());
284 // Verification que les vitesses de translation du repere
285 // mobiles sont bien definies et association des tableaux translation et
286 // eventuellement rotation
287 if (terme_source_acceleration.has_champ_vitesse())
288 {
289 translation=terme_source_acceleration.champ_vitesse().valeurs();
290 if (terme_source_acceleration.has_omega())
291 rotation=terme_source_acceleration.omega().valeurs();
292 else
293 rotation=rotation_nulle;
294 ok=1;
295 }
296 }
297 }
298 if (!ok)
299 {
300 Cerr << "Vous ne pouvez calculer l'energie cinetique dans un repere fixe" << finl;
301 Cerr << "que si le repere de calcul est mobile, c'est a dire que vous avez" << finl;
302 Cerr << "defini un terme source d'acceleration dans l'equation Navier Stokes." << finl;
303 Cerr << "Ou bien il manque dans ce terme source la definition de la vitesse" << finl;
304 Cerr << "du repere mobile dans le repere fixe. Modifier votre jeu de donnees." << finl;
305 exit();
306 }
307 }
308 double ec = 0.;
309
311 {
312 const Champ_base& champ_rho = get_champ_masse_volumique();
313 rho = champ_rho.valeurs();
314 if (rho->dimension(0) != domaine_VF.nb_faces() || rho->line_size() != 1)
315 {
316 Cerr << "Erreur dans Traitement_particulier_NS_EC::calculer_Ec" << finl;
317 Cerr << "le champ de masse volumique n'est pas un champ scalaire aux faces" << finl;
319 }
320 }
321 else
322 {
323 rho = mon_equation->milieu().masse_volumique().valeurs();
324 }
325 const int nb_front = domaine_VF.nb_front_Cl();
326 const ArrOfInt& faces_doubles = domaine_VF.faces_doubles();
327 // Faces de bord
328 for (int i = 0; i < nb_front; i++)
329 {
330 const Frontiere& fr = domaine_VF.front_VF(i).frontiere();
331 const int debut = fr.num_premiere_face();
332 const int nb_faces = fr.nb_faces();
333 ec += trait_part_calculer_ec_faces(debut, nb_faces, 1,
334 vitesse, volumes_entrelaces, xv, rho, translation, rotation, repere_mobile_, faces_doubles);
335 }
336 // Faces a l'interieur du domaine (y compris les faces de joint)
337 {
338 const int debut = domaine_VF.premiere_face_int();
339 const int nb_faces = domaine_VF.nb_faces_internes();
340 ec += trait_part_calculer_ec_faces(debut, nb_faces, 0,
341 vitesse, volumes_entrelaces, xv, rho, translation, rotation, repere_mobile_, faces_doubles);
342 }
343 ec = Process::mp_sum(ec);
344 energie_cinetique = ec;
345}
DoubleTab & valeurs() override
Surcharge Champ_base::valeurs() Renvoie le tableau des valeurs.
virtual DoubleTab & valeurs()=0
classe Champ_base Cette classe est la base de la hierarchie des champs.
Definition Champ_base.h:43
class Domaine_VF
Definition Domaine_VF.h:44
int nb_faces() const
renvoie le nombre global de faces.
Definition Domaine_VF.h:471
DoubleVect & volumes_entrelaces()
Definition Domaine_VF.h:99
int nb_faces_internes() const
une face est interne ssi elle separe deux elements.
Definition Domaine_VF.h:533
double xv(int num_face, int k) const
Definition Domaine_VF.h:76
ArrOfInt & faces_doubles()
renvoie 1 pour les faces appartenant a un bord perio ou un item commun, 0 par defaut
Definition Domaine_VF.h:567
int premiere_face_int() const
une face est interne ssi elle separe deux elements.
Definition Domaine_VF.h:463
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.
int nb_front_Cl() const
Class defining operators and methods for all reading operation in an input flow (file,...
Definition Entree.h:42
int_t num_premiere_face() const
Definition Frontiere.h:67
int_t nb_faces() const
Renvoie le nombre de faces de la frontiere.
Definition Frontiere.h:59
const Frontiere & frontiere() const
Renvoie la frontiere geometrique associee.
Une chaine de caractere (Nom) en majuscules.
Definition Motcle.h:26
Un tableau d'objets de la classe Motcle.
Definition Motcle.h:63
int search(const Motcle &t) const
Definition Motcle.cpp:321
class Nom Une chaine de caractere pour nommer les objets de TRUST
Definition Nom.h:31
friend class Entree
Definition Objet_U.h:76
static int dimension
Definition Objet_U.h:99
virtual Entree & readOn(Entree &)
Lecture d'un Objet_U sur un flot d'entree Methode a surcharger.
Definition Objet_U.cpp:293
static const Nom & nom_du_cas()
Renvoie une reference constante vers le nom du cas.
Definition Objet_U.cpp:146
virtual Sortie & printOn(Sortie &) const
Ecriture de l'objet sur un flot de sortie Methode a surcharger.
Definition Objet_U.cpp:282
classe Probleme_base C'est un Probleme_U qui n'est pas un couplage.
bool & reprise_effectuee()
static double mp_sum(double)
Calcule la somme de x sur tous les processeurs du groupe courant.
Definition Process.cpp:146
static void exit(int exit_code=-1)
Routine de sortie de TRUST dans une region Kokkos.
Definition Process.cpp:455
static int je_suis_maitre()
renvoie 1 si on est sur le processeur maitre du groupe courant (c'est a dire me() == 0),...
Definition Process.cpp:86
Cette classe est a la classe C++ ofstream ce que la classe Sortie est a la classe C++ ostream Elle re...
Definition SFichier.h:27
virtual int ouvrir(const char *name, IOS_OPEN_MODE mode=ios::out)
void precision(int pre) override
void setf(IOS_FORMAT code) override
Classe de base des flux de sortie.
Definition Sortie.h:52
class Sources Sources represente une liste de Source.
Definition Sources.h:31
virtual const Champ_base & get_champ_masse_volumique() const
Renvoie le champ de masse volumique.
virtual int has_champ_masse_volumique() const
Renvoie 1 si la masse volumique a ete associee, 0 sinon.
_SIZE_ dimension(int d) const
Definition TRUSTTab.tpp:133
int line_size() const
Definition TRUSTVect.tpp:67
const Champ_Don_base & omega() const
const Champ_Don_base & champ_vitesse() const
classe Traitement_particulier_EC Cette classe permet de faire les traitements particuliers
virtual void calculer_Ec(double &)
Meme methode de calcul en VDF et en VEF.
classe Traitement_particulier_NS_base Derive de Support_Champ_Masse_Volumique: utilisation de rho
OBS_PTR(Navier_Stokes_std) mon_equation