TRUST 1.9.8
HPC thermohydraulic platform
Loading...
Searching...
No Matches
Loi_horaire.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 <Schema_Temps_base.h>
17#include <Probleme_base.h>
18#include <Loi_horaire.h>
19#include <TRUST_Ref.h>
20#include <SFichier.h>
21#include <sys/stat.h>
22#include <EChaine.h>
23#include <Param.h>
24
25Implemente_instanciable(Loi_horaire,"Loi_horaire",Objet_U);
26// XD loi_horaire objet_u loi_horaire BRACE to define the movement with a time-dependant law for the solid interface.
27
28Sortie& Loi_horaire::printOn(Sortie& os) const { return os; }
29
31{
32 EChaine x(dimension==3?"3 0. 0. 0.":"2 0. 0.");
33 x >> position_;
34 EChaine v(dimension==3?"3 0. 0. 0.":"2 0. 0.");
35 v >> vitesse_;
36 EChaine r(dimension==3?"9 1. 0. 0. 0. 1. 0. 0. 0. 1.":"4 1. 0. 0. 1.");
37 r >> rotation_;
38 EChaine drdt(dimension==3?"9 0. 0. 0. 0. 0. 0. 0. 0. 0.":"4 0. 0. 0. 0.");
39 drdt >> derivee_rotation_;
40
41 // Lecture de jeu de donnees
42 Param param(que_suis_je());
43 param.ajouter("position",&position_); // XD attr position listchaine position OPT Vecteur position (default: zero
44 // XD_CONT vector of length `dimension`)
45 param.ajouter("vitesse",&vitesse_); // XD attr vitesse listchaine vitesse OPT Vecteur vitesse (default: zero
46 // XD_CONT vector of length `dimension`)
47 param.ajouter("rotation",&rotation_); // XD attr rotation listchaine rotation OPT Matrice de passage
48 param.ajouter("derivee_rotation",&derivee_rotation_); // XD attr derivee_rotation listchaine derivee_rotation OPT Derivee matrice de passage
49 param.ajouter("verification_derivee",&verification_derivee_); // XD attr verification_derivee entier verification_derivee OPT not_set
50 param.ajouter("impr",&impr_); // XD attr impr entier impr OPT Whether to print output
51 param.lire_avec_accolades_depuis(is);
52
53 // Verification de ce qui a ete lu: ( pourquoi le_nom() retourne neant ???
54 if (position_.valeurs().size_array()!=dimension)
55 {
56 Cerr << "The position vector of the schedule law " << le_nom() << " must have " << dimension << " components." << finl;
58 }
59 if (vitesse_.valeurs().size_array()!=dimension)
60 {
61 Cerr << "The velocity vector of the schedule law " << le_nom() << " must have " << dimension << " components." << finl;
63 }
64 if (rotation_.valeurs().size_array()!=dimension*dimension)
65 {
66 Cerr << "The matrix rotation of the schedule law " << le_nom() << " must be read" << finl;
67 Cerr << "as a vector of " << dimension*dimension << " components." << finl;
69 }
70 if (derivee_rotation_.valeurs().size_array()!=dimension*dimension)
71 {
72 Cerr << "The matrix derivee_rotation of the schedule law " << le_nom() << " must be read" << finl;
73 Cerr << "as a vector of " << dimension*dimension << " components." << finl;
75 }
76 return is;
77}
78
79inline void check(const DoubleTab& mat)
80{
81 // Champ_Fonc_t DoubleTab(1,nb_comp)
82 if (mat.dimension(0)!=1)
83 {
84 Cerr << "Problem in Loi_horaire::check" << finl;
85 Cerr << "Format of the array of values of Champ_Fonc_t" << finl;
86 Cerr << "Contact TRUST support." << finl;
88 }
89}
90
91// Produit Matrice*Vecteur stockes dans des tableaux
92inline void multiplie(const DoubleTab& matrice, ArrOfDouble& vecteur)
93{
94 check(matrice);
95 ArrOfDouble x(vecteur);
96 vecteur=0;
97 int dimension = vecteur.size_array();
98 for (int i=0; i<dimension; i++)
99 for (int j=0; j<dimension; j++)
100 vecteur[i] += matrice(0,i*dimension+j) * x[j];
101}
102
103// Produit Inverse(Matrice)*Vecteur dans des tableaux
104inline void inverse(const DoubleTab& mat, ArrOfDouble& x)
105{
106 check(mat);
107 int dimension = x.size_array();
108 if (dimension==2)
109 {
110 const double a=mat(0,0);
111 const double b=mat(0,1);
112 const double c=mat(0,2);
113 const double d=mat(0,3);
114 double det=a*d-b*c;
115 if (det==0)
116 {
117 Cerr << "Matrix of order 2 not invertible in Loi_horaire::inverse" << finl;
118 Cerr << mat << finl;
120 }
121 double y0=(d*x[0]-b*x[1])/det;
122 double y1=(-c*x[0]+a*x[1])/det;
123 x[0]=y0;
124 x[1]=y1;
125 }
126 else if (dimension==3)
127 {
128 const double a=mat(0,0);
129 const double b=mat(0,1);
130 const double c=mat(0,2);
131 const double d=mat(0,3);
132 const double e=mat(0,4);
133 const double f=mat(0,5);
134 const double g=mat(0,6);
135 const double h=mat(0,7);
136 const double i=mat(0,8);
137
138 double det=a*(e*i-f*h)
139 -b*(d*i-f*g)
140 +c*(d*h-e*g);
141 if (det==0)
142 {
143 Cerr << "Matrix of order 3 not invertible in Loi_horaire::inverse" << finl;
144 Cerr << mat << finl;
146 }
147 double y0=((e*i-f*h)*x[0]
148 +(c*h-b*i)*x[1]
149 +(b*f-c*e)*x[2])/det;
150 double y1=((f*g-d*i)*x[0]
151 +(a*i-c*g)*x[1]
152 +(c*d-a*f)*x[2])/det;
153 double y2=((d*h-e*g)*x[0]
154 +(b*g-a*h)*x[1]
155 +(a*e-b*d)*x[2])/det;
156 x[0]=y0;
157 x[1]=y1;
158 x[2]=y2;
159 }
160 else
161 {
162 Cerr << "Case not provided in Loi_horaire::inverse()" << finl;
164 }
165}
166
167/* Renvoie un tableau contenant la position xM(t) d'un point M au temps t
168 en fonction du temps t0 et de sa position xM(t0) au temps t0.
169 Pour cela, on utilisera les relations suivantes:
170 xM(t)=xG(t)+R(t)(xM(0)-xG(0))
171 xM(t0)=xG(t0)+R(t0)(xM(0)-xG(0))
172 On a:
173 xM(0)-xG(0)=R-1(t0)(xM(t0)-xG(t0))
174 Donc:
175 xM(t) = xG(t)+R(t)R-1(t0)(xM(t0)-xG(t0))
176*/
177ArrOfDouble Loi_horaire::position(const double t, const double t0, const ArrOfDouble& xMt0)
178{
179 ArrOfDouble xMt(xMt0); // xM(t0)
180 position_.me_calculer(t0); // xG(t0)
181 xMt -= position_.valeurs(); // xM(t0)-xG(t0)
182 rotation_.me_calculer(t0); // R(t0)
183 inverse(rotation_.valeurs(),xMt); // R-1(t0)(xM(t0)-xG(t0))
184 rotation_.me_calculer(t); // R(t)
185 multiplie(rotation_.valeurs(),xMt); // R(t)R-1(t0)(xM(t0)-xG(t0))
186 position_.me_calculer(t); // xG(t)
187 xMt += position_.valeurs(); // xM(t) = xG(t)+R(t)R-1(t0)(xM(t0)-xG(t0))
188 return xMt;
189}
190
191/* Renvoie un tableau contenant la vitesse vM(t) d'un point M au temps t
192 en fonction de sa position xM(t) au temps t. Pour connaitre cette vitesse du point M,
193 on utilise les relations suivantes:
194 xM(t)=xG(t)+R(t)(xM(0)-xG(0))
195 vM(t)=vG(t)+R'(t)(xM(0)-xG(0))
196 On a:
197 xM(0)-xG(0)=R-1(t)(xM(t)-xG(t))
198 Donc:
199 vM(t) = vG(t)+R'(t)R-1(t)(xM(t)-xG(t))
200*/
201ArrOfDouble Loi_horaire::vitesse(const double t, const ArrOfDouble& xMt)
202{
203 ArrOfDouble vMt(xMt); // xM(t)
204 position_.me_calculer(t); // xG(t)
205 vMt -= position_.valeurs(); // xM(t)-xG(t)
206 rotation_.me_calculer(t); // R(t)
207 inverse(rotation_.valeurs(),vMt); // R-1(t)(xM(t)-xG(t))
208 derivee_rotation_.me_calculer(t); // R'(t)
209 multiplie(derivee_rotation_.valeurs(),vMt); // R'(t)R-1(t)(xM(t)-xG(t))
210 vitesse_.me_calculer(t); // vG(t)
211 vMt += vitesse_.valeurs(); // vM(t) = vG(t)+R'(t)R-1(t)(xM(t)-xG(t))
212 return vMt;
213}
214
215// Verification de la coherence des derivees vitesse et derivee_rotation
216// par rapport a position et rotation. On utilise un developpement limite d'ordre 2
217// |f(t+dt)-f(t)-dt*f'(t)|=|0.5*f''(t)*dt*dt+O(dt*dt*dt)|>|10*f''(t)*dt*dt|
218// Une erreur sur des expressions de derivee seconde nulle ne sera donc pas detectee...
219void Loi_horaire::verifier_derivee(const double t)
220{
221 if (verification_derivee_)
222 {
223 double dt=0.001*t;
224 DoubleVect err_t(position_.valeurs());
225 position_.me_calculer(t+dt); // xG(t+dt)
226 err_t=position_.valeurs(); // xG(t+dt)
227 position_.me_calculer(t); // xG(t)
228 err_t-=position_.valeurs(); // xG(t+dt)-xG(t)
229 vitesse_.me_calculer(t); // vG(t)
230 err_t.ajoute(-dt, vitesse_.valeurs()); // xG(t+dt)-xG(t)-dt*vG(t)
231 // Evaluation d'un seuil avec la derivee seconde xG'' cad vG'
232 ArrOfDouble seuil_t(position_.valeurs());
233 vitesse_.me_calculer(t+dt); // vG(t+dt)
234 seuil_t=vitesse_.valeurs();
235 vitesse_.me_calculer(t); // vG(t)
236 seuil_t-=vitesse_.valeurs();
237 seuil_t*=100*dt; // ~vG'(t)*dt*dt
238 int n=err_t.size_array();
239 for (int i=0; i<n; i++)
240 {
241 double seuil=std::fabs(seuil_t[i]);
242 if (!est_egal(seuil,0) && std::fabs(err_t(i))>seuil)
243 {
244 Cerr << "At time " << t << ", inconsistency in the schedule law " << le_nom() << finl;
245 Cerr << "The expression of the component " << i << " of velocity does not appear" << finl;
246 Cerr << "to be the time derivative of the position expression." << finl;
247 Cerr << "Verify the expressions of this schedule law in your data set." << finl;
248 Cerr << "If the expressions are correct after all, add the option 'verification_derivee 0'" << finl;
249 Cerr << "in the law to not to make this verification." << finl;
251 }
252 }
253 DoubleTab err_r(rotation_.valeurs());
254 rotation_.me_calculer(t+dt); // R(t+dt)
255 err_r=rotation_.valeurs(); // R(t+dt)
256 rotation_.me_calculer(t); // R(t)
257 err_r-=rotation_.valeurs(); // R(t+dt)-R(t)
258 derivee_rotation_.me_calculer(t); // R'(t)
259 err_r.ajoute(-dt, derivee_rotation_.valeurs()); // R(t+dt)-R(t)-dt*R'(t)
260 // Evaluation d'un seuil avec la derivee seconde de R cad R''
261 DoubleTab seuil_r(rotation_.valeurs());
262 derivee_rotation_.me_calculer(t+dt); // R'(t+dt)
263 seuil_r=derivee_rotation_.valeurs();
264 derivee_rotation_.me_calculer(t); // R'(t)
265 seuil_r-=derivee_rotation_.valeurs(); // R'(t+dt)-R'(t)
266 seuil_r*=100*dt; // ~R''(t)*dt*dt
267 int ni=err_r.dimension(0);
268 int nj=err_r.dimension(1);
269 for (int i=0; i<ni; i++)
270 for (int j=0; j<nj; j++)
271 {
272 double seuil=std::fabs(seuil_r(i,j));
273 if (!est_egal(seuil,0) && std::fabs(err_r(i,j))>seuil)
274 {
275 Cerr << "At time " << t << ", inconsistency in the schedule law " << le_nom() << finl;
276 Cerr << "The expression of the component " << i*ni+j << " of derivee_rotation does not appear" << finl;
277 Cerr << "to be the time derivative of the rotation expression." << finl;
278 Cerr << "Verify the expressions of this schedule law in your data set" << finl;
279 Cerr << "or add the option 'verification_derivee 0' in this law." << finl;
281 }
282 }
283 }
284}
285
286void Loi_horaire::imprimer(const Schema_Temps_base& sch, const ArrOfDouble& coord_barycentre)
287{
289 {
290 // Ouverture du fichier
291 Nom nom_fichier(nom_du_cas());
292 nom_fichier+="_loi_horaire_";
293 nom_fichier+=le_nom();
294 nom_fichier+=".out";
295 SFichier fic; // * os=nullptr;
296 struct stat f;
297 // On cree le fichier a la premiere impression avec l'en tete ou si le fichier n'existe pas
298 if (stat(nom_fichier,&f) || (sch.nb_impr()==1 && !sch.pb_base().reprise_effectuee()))
299 {
300 tester(sch);
301 fic.ouvrir(nom_fichier);
302 // Ecriture en tete
303 fic << "# (xG,yG,...):Position du centre de gravite dont le mouvement est defini par la loi horaire " << le_nom() << finl;
304 fic << "# (moy(xi),moy(yi),...):Position du barycentre des noeuds du maillage de l'interface." << finl;
305 fic << "# Les trajectoires de ces 2 points doivent etre proches." << finl;
306 fic << "# Pour visualiser dans gnuplot ces trajectoires, faire: " << finl;
307 if (dimension==3)
308 {
309 fic << "# set param;splot '" << nom_fichier << "' using 2:3:4 with lines,'" << nom_fichier << "' using 5:6:7 with points" << finl;
310 fic << "# Temps xG(t) yG(t) zG(t) moy(xi) moy(yi) moy(zi)" << finl;
311 }
312 else
313 {
314 fic << "# set param;plot '" << nom_fichier << "' using 2:3 with lines,'" << nom_fichier << "' using 4:5 with points" << finl;
315 fic << "# Temps xG(t) yG(t) moy(xi) moy(yi)" << finl;
316 }
317 }
318 else
319 fic.ouvrir(nom_fichier,ios::app);
320
321 fic.precision(sch.precision_impr());
322 fic.setf(ios::scientific);
323 // Ecriture de t,xG(t),coord_barycentre
324 double t=sch.temps_courant();
325 fic << t;
326 position_.me_calculer(t);
327 for (int i=0; i<dimension; i++)
328 fic << " " << position_.valeurs()(0,i); // xG(t)
329 for (int i=0; i<dimension; i++)
330 fic << " " << coord_barycentre[i]; // Barycentre des noeuds de l'interface
331 fic << finl;
332 // Fermeture du fichier
333 fic.close();
334 }
335}
336
337// Tests divers de la classe
338void Loi_horaire::tester(const Schema_Temps_base& sch)
339{
340 // Test de produit et d'inversion de matrice
341 for (int dim=2; dim<=3; dim++)
342 {
343 DoubleTab mat(1,dim*dim);
344 for (int i=0; i<dim; i++)
345 for (int j=0; j<dim; j++)
346 mat(0,i*dim+j)=(i>j?1+i+j:-2*j);
347 ArrOfDouble vect(dim);
348 for (int i=0; i<dim; i++)
349 vect[i]=i;
350 ArrOfDouble tmp(vect);
351 multiplie(mat,vect);
352 inverse(mat,vect);
353 for (int i=0; i<dim; i++)
354 if (!est_egal(tmp[i],vect[i]))
355 {
356 Cerr << "Loi_horaire::inverse is not validated for dim=" << dim << finl;
357 Cerr << "A=" << mat << finl;
358 Cerr << "x=" << tmp << finl;
359 Cerr << "Inv(A)Ax=" << vect << finl;
360 Cerr << "Contact TRUST support." << finl;
362 }
363 }
364 // Verification entre tinit et tmax
365 double tinit=sch.temps_init();
366 double tmax=sch.temps_max();
367 // Test des derivees:
368 int n=100;
369 for (int i=1; i<n; i++)
370 {
371 double temps=tinit+(tmax-tinit)*(i+1)/n;
372 //Cerr << "Verification a t=" << temps << finl;
373 verifier_derivee(temps);
374 }
375 // Test de position et vitesse:
376 double t=0.5*(tinit+tmax);
377 double eps=1e-8;
378 double dt=eps*t;
379 ArrOfDouble pos(dimension);
380 pos[0]=dimension*2;
381 pos[1]=dimension*3;
382 if (dimension==3) pos[2]=-dimension;
383 // Verification que position(t,t,pos)=pos
384 ArrOfDouble tmp(position(t,t,pos));
385 for (int i=0; i<dimension; i++)
386 if (!est_egal(tmp[i],pos[i]))
387 {
388 Cerr << "Loi_horaire::position is not validated for pos=position(t,t,pos):" << finl;
389 Cerr << pos << finl;
390 Cerr << tmp << finl;
391 Cerr << "Contact TRUST support." << finl;
393 }
394 // Verification que vitesse(t,pos)~(position(t+dt,t,pos)-pos)/dt;
395 tmp=position(t+dt,t,pos);
396 tmp-=pos;
397 tmp/=dt;
398 ArrOfDouble vit(vitesse(t,pos));
399 ArrOfDouble relative_error(vit);
400 relative_error-=tmp;
401 relative_error/=(norme_array(tmp)!=0?norme_array(tmp):1);
402 for (int i=0; i<dimension; i++)
403 if (!est_egal(relative_error[i],0,0.001))
404 {
405 Cerr << "Loi_horaire::position is not validated for velocity(t,pos):" << finl;
406 Cerr << "t=" << t << finl;
407 Cerr << "dt=" << dt << finl;
408 Cerr << "vit=" << vit << finl;
409 Cerr << "tmp=" << tmp << finl;
410 Cerr << "relative_error=" << relative_error << finl;
411 Cerr << "Contact TRUST support." << finl;
413 }
414 Cerr << "Loi_horaire::tester() OK" << finl;
415}
416
Class defining operators and methods for all reading operation in an input flow (file,...
Definition Entree.h:42
ArrOfDouble vitesse(const double t, const ArrOfDouble &position_a_t)
const Nom & le_nom() const override
Donne le nom de l'Objet_U Methode a surcharger : renvoie "neant" dans cette implementation.
Definition Loi_horaire.h:39
void imprimer(const Schema_Temps_base &, const ArrOfDouble &)
ArrOfDouble position(const double t, const double t0, const ArrOfDouble &position_a_t0)
class Nom Une chaine de caractere pour nommer les objets de TRUST
Definition Nom.h:31
classe Objet_U Cette classe est la classe de base des Objets de TRUST
Definition Objet_U.h:73
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 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
bool & reprise_effectuee()
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
class Schema_Temps_base
int nb_impr() const
Renvoie le nombre d'impressions effectuees.
double temps_courant() const
Renvoie le temps courant.
double temps_max() const
Renvoie une reference sur le temps maximum.
Probleme_base & pb_base()
double temps_init() const
Renvoie le temps initial.
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
_SIZE_ size_array() const
_SIZE_ dimension(int d) const
Definition TRUSTTab.tpp:133