TrioCFD 1.9.9_beta
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 Prints the object to an output stream.
37 *
38 * @param is an output stream
39 * @return the modified output stream
40 */
42{
43 return is;
44}
45
46
47/*! @brief Reads the object from an input stream.
48 *
49 * @param is an input stream
50 * @return the modified input stream
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<<"We expected the keyword periode after " << les_mots[rang] << "."<<finl;
85 exit();
86 }
87 is >> periode;
88 break;
89 }
90 default :
91 {
92 Cerr << "Error while reading Traitement_particulier_NS_EC";
93 Cerr << "Possible keywords are "<< les_mots <<" { and }" << finl;
94 Cerr << "You read:" << motlu << finl;
95 exit();
96 break;
97 }
98 }
99 is >> motlu;
100 }
101 is >> motlu;
102 if (motlu != accfermee)
103 {
104 Cerr << "Error while reading Traitement_particulier_NS_EC";
105 Cerr << "We expected a }" << finl;
106 exit();
107 }
108 }
109 }
110 else
111 {
112 Cerr << "Error while reading Traitement_particulier_NS_EC";
113 Cerr << "We expected a {" << finl;
114 exit();
115 }
116 return is;
117}
118
120{
121 // Open the file 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 // Write first line
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 Helper function used in calculer_Ec.
172 *
173 * Computes the sum of 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 // Computation of the entrainment velocity
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 // One velocity component at the face (VDF)
218 const double v = vitesse(face);
219 if (repere_mobile_)
220 {
221 Cerr << "The computation of kinetic energy in a fixed frame" <<finl;
222 Cerr << "is not implemented in VDF." << finl;
223 Process::exit(); // Indeed, a design issue: the orientation of VDF faces would be needed
224 }
225 v2 = v * v;
226 // In VDF, at boundaries, only half the staggered volume is taken
227 volume = (frontiere ? 0.5 : 1) * volumes_entrelaces(face);
228 }
229 else
230 {
231 // Two or three components (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 // In VEF, this is incorrect; extended volumes should be used:
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 Same computation method for VDF and VEF.
250 *
251 * If no mass-density field has been associated, computes
252 * INTEGRAL of 1/2 * u^2 over the domain.
253 * If a mass-density field has been associated, it must be
254 * of type "champ aux faces". Computes INTEGRAL of 1/2 * rho * u^2.
255 * rho is a P0 field at elements, u is P0 on the staggered volumes.
256 * Return value:
257 * The sum over all processors of the integral of 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 // Check for the existence of an Acceleration source term in 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 // Check that the translation velocities of the moving
285 // frame are properly defined and associate the translation and
286 // optionally rotation arrays
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 << "You cannot compute kinetic energy in a fixed frame" << finl;
301 Cerr << "unless the calculation frame is moving, i.e. you have" << finl;
302 Cerr << "defined an acceleration source term in the Navier Stokes equation." << finl;
303 Cerr << "Or the definition of the velocity of the" << finl;
304 Cerr << "moving frame in the fixed frame is missing in this source term. Modify your data file." << 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 << "Error in Traitement_particulier_NS_EC::calculer_Ec" << finl;
317 Cerr << "the density field is not a scalar field at 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 // Boundary faces
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 // Interior faces of the domain (including joint faces)
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
Overrides Champ_base::valeurs() Returns the array of values.
virtual DoubleTab & valeurs()=0
class Champ_base This class is the base of the fields hierarchy.
Definition Champ_base.h:43
class Domaine_VF
Definition Domaine_VF.h:44
int nb_faces() const
Returns the total number of faces.
Definition Domaine_VF.h:471
DoubleVect & volumes_entrelaces()
Definition Domaine_VF.h:99
int nb_faces_internes() const
A face is internal if and only if it separates two elements.
Definition Domaine_VF.h:532
double xv(int num_face, int k) const
Definition Domaine_VF.h:76
ArrOfInt & faces_doubles()
Returns 1 for faces belonging to a periodic boundary or a shared item, 0 by default.
Definition Domaine_VF.h:566
int premiere_face_int() const
A face is internal if and only if it separates two elements.
Definition Domaine_VF.h:463
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.
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
Returns the number of faces of the boundary.
Definition Frontiere.h:59
const Frontiere & frontiere() const
Returns the associated geometric boundary.
A character string (Nom) in uppercase.
Definition Motcle.h:26
An array of Motcle objects.
Definition Motcle.h:63
int search(const Motcle &t) const
Definition Motcle.cpp:319
class Nom: a character string for naming TRUST objects.
Definition Nom.h:31
friend class Entree
Definition Objet_U.h:71
static int dimension
Definition Objet_U.h:94
virtual Entree & readOn(Entree &)
Reads an Objet_U from an input stream. Virtual method to override.
Definition Objet_U.cpp:289
static const Nom & nom_du_cas()
Returns a constant reference to the case name. This method is static.
Definition Objet_U.cpp:145
virtual Sortie & printOn(Sortie &) const
Writes the object to an output stream. Virtual method to override.
Definition Objet_U.cpp:278
class Probleme_base It is a Probleme_U that is not a coupling.
bool & reprise_effectuee()
static double mp_sum(double)
Computes the sum of x over all processors in the current group.
Definition Process.cpp:145
static void exit(int exit_code=-1)
Exit routine for TRUST within a Kokkos region.
Definition Process.cpp:466
static int je_suis_maitre()
Returns 1 if on the master processor of the current group (i.e. me() == 0), 0 otherwise.
Definition Process.cpp:82
SFichier is to the C++ ofstream class what Sortie is to the C++ ostream class.
Definition SFichier.h:29
virtual int ouvrir(const char *name, IOS_OPEN_MODE mode=ios::out)
void precision(int pre) override
void setf(IOS_FORMAT code) override
Base class for output streams.
Definition Sortie.h:52
class Sources Sources represents a list of Source objects.
Definition Sources.h:31
virtual const Champ_base & get_champ_masse_volumique() const
Returns the density field.
virtual int has_champ_masse_volumique() const
Returns 1 if the density field has been associated, 0 otherwise.
_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
Traitement_particulier_EC This class performs specific post-processing treatments.
virtual void calculer_Ec(double &)
Same computation method for VDF and VEF.
Traitement_particulier_NS_base Derives from Support_Champ_Masse_Volumique: use of rho.
OBS_PTR(Navier_Stokes_std) mon_equation