TrioCFD 1.9.8
TrioCFD documentation
Loading...
Searching...
No Matches
Modele_Jones_Launder_Thermique_VDF.cpp
1/****************************************************************************
2* Copyright (c) 2019, 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 <Modele_Jones_Launder_Thermique_VDF.h>
17#include <Domaine_VDF.h>
18#include <Domaine_Cl_VDF.h>
19#include <TRUSTTrav.h>
20#include <Probleme_base.h>
21#include <Dirichlet.h>
22#include <Dirichlet_entree_fluide_leaves.h>
23#include <Symetrie.h>
24#include <Neumann.h>
25#include <Neumann_homogene.h>
26#include <TRUSTTrav.h>
27
28Implemente_instanciable(Modele_Jones_Launder_Thermique_VDF,"Modele_Jones_Launder_Thermique_VDF",Modele_Fonc_Bas_Reynolds_Thermique_Base);
29
30// printOn et readOn
31
33{
34 return s;
35}
36
38{
39 Motcle motlu, accolade_fermee="}", accolade_ouverte="{";
40 is >> motlu;
41 if (motlu==accolade_ouverte)
42 {
43 is >> motlu;
44 if (motlu != accolade_fermee)
45 {
46 Cerr << "Erreur a la lecture du Modele fonc bas reynolds Jones et Launder pour la thermique" << finl;
47 Cerr << "On attendait } a la place de " << motlu << finl;
49 }
50 }
51 else
52 {
53 Cerr << "Erreur a la lecture du Modele fonc bas reynolds Jones et Launder pour la thermique" << finl;
54 Cerr << "On attendait { a la place de " << motlu << finl;
56 }
57 return is;
58}
59
61{
62 return is;
63}
64///////////////////////////////////////////////////////////////
65// Implementation des fonctions de la classe
66///////////////////////////////////////////////////////////////
67
69 const Domaine_Cl_dis_base& domaine_Cl_dis)
70{
71 //const Domaine_VDF& le_dom = ref_cast(Domaine_VDF,domaine_dis);
72 // const Domaine_Cl_VDF& le_dom_Cl = ref_cast(Domaine_Cl_VDF,domaine_Cl_dis);
73}
74
76{
77 eq_transport_Fluctu_Temp_Bas_Re = ref_cast(Transport_Fluctuation_Temperature_W_Bas_Re,equation());
78}
79
80DoubleTab& Modele_Jones_Launder_Thermique_VDF::Calcul_D(DoubleTab& D,const Domaine_dis_base& domaine_dis, const Domaine_Cl_dis_base& domaine_Cl_dis,
81 const DoubleTab& vitesse,const DoubleTab& Fluctu_Temp, double diffu ) const
82{
83 const Domaine_VDF& le_dom = ref_cast(Domaine_VDF,domaine_dis);
84 const Domaine_Cl_VDF& le_dom_Cl = ref_cast(Domaine_Cl_VDF,domaine_Cl_dis);
85 D = 0;
86 // const DoubleVect& volumes = le_dom.volumes();
87 const DoubleVect& porosite_surf = domaine_Cl_dis.equation().milieu().porosite_face();
88 const DoubleVect& volume_entrelaces = le_dom.volumes_entrelaces();
89 // int nb_elem = le_dom.nb_elem();
90 // int nb_elem_tot = le_dom.nb_elem_tot();
91 //const Domaine& domaine=le_dom.domaine();
92
93 //int nb_faces_elem = domaine.nb_faces_elem();
94 //IntTrav numfa(nb_faces_elem);
95 double coef;
96 // const IntTab& elem_faces = le_dom.elem_faces();
97 const IntTab& face_voisins = le_dom.face_voisins();
98 int nb_faces = le_dom.nb_faces();
99
100 DoubleTab gradth(nb_faces);
101 int num_face,poly1,poly2,ori, ndeb, nfin;
102
103 // Calcul de Gradient de racine de theta^2.
104
105 // Boucle sur les bords pour traiter les conditions aux limites
106 for (int n_bord=0; n_bord<le_dom.nb_front_Cl(); n_bord++)
107
108 {
109 const Cond_lim& la_cl = le_dom_Cl.les_conditions_limites(n_bord);
110
111 if ( sub_type(Dirichlet,la_cl.valeur()) )
112 {
113 const Dirichlet_entree_fluide& la_cl_typee = ref_cast(Dirichlet_entree_fluide,la_cl.valeur());
114 const Front_VF& le_bord = ref_cast(Front_VF,la_cl->frontiere_dis());
115 ndeb = le_bord.num_premiere_face();
116 nfin = ndeb + le_bord.nb_faces();
117
118 for (num_face=ndeb; num_face<nfin; num_face++)
119 {
120 gradth = 0;
121 poly1 = face_voisins(num_face,0);
122 poly2=-1;
123 // poiur faire planter si on en avait besoin
124 if (poly1 != -1)
125 {
126 coef = volume_entrelaces(num_face)*porosite_surf(num_face)*0.5;
127 if ( (Fluctu_Temp(poly1,0)>0) && (Fluctu_Temp(poly2,0)>0) )
128 gradth(num_face) += (coef*(la_cl_typee.val_imp(num_face-ndeb,0) - sqrt(Fluctu_Temp(poly1,0))))/le_dom.dist_norm_bord(num_face);
129 D[poly1] += 2*diffu*(gradth(num_face)*gradth(num_face));
130 }
131 else
132 {
133 poly2 = face_voisins(num_face,1);
134 coef = volume_entrelaces(num_face)*porosite_surf(num_face)*0.5;
135 if ( (Fluctu_Temp(poly1,0)>0) && (Fluctu_Temp(poly2,0)>0) )
136 gradth(num_face) += (coef*(sqrt(Fluctu_Temp(poly2,0)) - la_cl_typee.val_imp(num_face-ndeb,0)))/le_dom.dist_norm_bord(num_face);
137 D[poly2] += 2*diffu*(gradth(num_face)*gradth(num_face));
138 }
139 }
140
141 }
142 else if (sub_type(Symetrie,la_cl.valeur()))
143 ;
144 else if ( (sub_type(Neumann,la_cl.valeur()))
145 ||
146 (sub_type(Neumann_homogene,la_cl.valeur()))
147 )
148 {
149 // do nothing
150 ;
151 }
152 }
153 // Traitement des faces internes
154 for (num_face=le_dom.premiere_face_int(); num_face<nb_faces; num_face++)
155 {
156 poly1 = face_voisins(num_face,0);
157 poly2 = face_voisins(num_face,1);
158 ori = le_dom.orientation(num_face);
159 coef = volume_entrelaces(num_face)*porosite_surf(num_face);
160
161 if ( (Fluctu_Temp(poly1,0)>0) && (Fluctu_Temp(poly2,0)>0) )
162 gradth(num_face) += coef*(sqrt(Fluctu_Temp(poly1,0))-sqrt(Fluctu_Temp(poly2,0)))/(le_dom.xp(poly2,ori)- le_dom.xp(poly1,ori));
163
164 D[poly1] += 2*diffu*(gradth(num_face)*gradth(num_face));
165 D[poly2] += 2*diffu*(gradth(num_face)*gradth(num_face));
166 }
167 return D;
168}
169
170DoubleTab& Modele_Jones_Launder_Thermique_VDF::Calcul_E(DoubleTab& E,const Domaine_dis_base& domaine_dis, const Domaine_Cl_dis_base& domaine_Cl_dis, const DoubleTab& temp,const DoubleTab& Fluctu_Temp,double diffu, const DoubleTab& diffu_turb ) const
171{
172 const Domaine_VDF& le_dom = ref_cast(Domaine_VDF,domaine_dis);
173 const Domaine_Cl_VDF& le_dom_Cl = ref_cast(Domaine_Cl_VDF,domaine_Cl_dis);
174 E = 0;
175 const DoubleVect& volumes = le_dom.volumes();
176 // const DoubleVect& porosite_vol = la_equation().milieu().porosite_elem();
177
178 int nb_elem = le_dom.nb_elem();
179 int nb_elem_tot = le_dom.nb_elem_tot();
180 const IntTab& elem_faces = le_dom.elem_faces();
181 int nb_faces = le_dom.nb_faces();
182 const IntTab& face_voisins = le_dom.face_voisins();
183 // const IntTab& Qdm = le_dom.Qdm();
184 // const IntVect& orientation = le_dom.orientation();
185 int ndeb,nfin,poly1, poly2, num_face, ori;
186 const Domaine& domaine=le_dom.domaine();
187 int nb_faces_elem = domaine.nb_faces_elem();
188
189 DoubleTrav dT_dy(nb_faces);
190 DoubleTrav dT_dz(nb_faces);
191 DoubleTrav dT_dx(nb_faces);
192 DoubleTrav d2T_dy2(nb_elem_tot);
193 DoubleTrav d2T_dz2(nb_elem_tot);
194 DoubleTrav d2T_dx2(nb_elem_tot);
195
196 //Calcul des derives de T
197
198 //Boucle sur les frontieres pour traiter les cds aux limites.
199 for (int n_bord=0; n_bord<le_dom.nb_front_Cl(); n_bord++) //boucle sur les frontieres
200 {
201 const Cond_lim& la_cl = le_dom_Cl.les_conditions_limites(n_bord);
202
203 if ( sub_type(Dirichlet,la_cl.valeur()) )
204 {
205 const Dirichlet_entree_fluide& la_cl_typee = ref_cast(Dirichlet_entree_fluide,la_cl.valeur());
206 const Front_VF& le_bord = ref_cast(Front_VF,la_cl->frontiere_dis());
207 ndeb = le_bord.num_premiere_face();
208 nfin = ndeb + le_bord.nb_faces();
209
210 for (num_face=ndeb; num_face<nfin; num_face++) //boucle sur les faces des frontieres
211 {
212 // dT_dx = 0;
213 // dT_dy = 0;
214 // dT_dz = 0;
215 poly1 = face_voisins(num_face,0);
216 ori = le_dom.orientation(num_face);
217 if (poly1 != -1)
218 {
219 if (ori == 0)
220 {
221 dT_dx(num_face) = (la_cl_typee.val_imp(num_face-ndeb,0) - temp(poly1))/le_dom.dist_norm_bord(num_face);
222 }
223 if (ori == 1)
224 {
225 dT_dy(num_face) = (la_cl_typee.val_imp(num_face-ndeb,0) - temp(poly1))/le_dom.dist_norm_bord(num_face);
226 }
227 if (ori == 2)
228 {
229 dT_dz(num_face) = (la_cl_typee.val_imp(num_face-ndeb,0) - temp(poly1))/le_dom.dist_norm_bord(num_face);
230 }
231 }
232 else
233 {
234 poly2 = face_voisins(num_face,1);
235 if (ori == 0)
236 {
237 dT_dx(num_face) = (temp(poly2) - la_cl_typee.val_imp(num_face-ndeb,0))/le_dom.dist_norm_bord(num_face);
238 }
239 if (ori == 1)
240 {
241 dT_dy(num_face) = (temp(poly2) - la_cl_typee.val_imp(num_face-ndeb,0))/le_dom.dist_norm_bord(num_face);
242 }
243 if (ori == 2)
244 {
245 dT_dz(num_face) = (temp(poly2) - la_cl_typee.val_imp(num_face-ndeb,0))/le_dom.dist_norm_bord(num_face);
246 }
247 }
248 }
249 }
250 }
251
252
253 //Traitement des faces internes toujours pour le calcul des derivees de T
254 for (num_face=le_dom.premiere_face_int(); num_face<nb_faces; num_face++) //boucle sur les faces internes
255 {
256 poly1 = face_voisins(num_face,0);
257 poly2 = face_voisins(num_face,1);
258 ori = le_dom.orientation(num_face);
259 if (ori == 0)
260 {
261 dT_dx(num_face) = ( temp(poly2) - temp(poly1) ) / (le_dom.xp(poly2,ori) - le_dom.xp(poly1,ori));
262 }
263 if (ori == 1)
264 {
265 dT_dy(num_face) = ( temp(poly2) - temp(poly1) ) / (le_dom.xp(poly2,ori) - le_dom.xp(poly1,ori));
266 }
267 if (ori == 2)
268 {
269 dT_dz(num_face) = ( temp(poly2) - temp(poly1) ) / (le_dom.xp(poly2,ori) - le_dom.xp(poly1,ori));
270 }
271 }
272
273
274 //on passe maintenant au calcul des derivees secondes de T et du terme E
275 IntTrav numfa(nb_faces_elem);
276 for (int elem=0; elem<nb_elem; elem++) //boucle sur les elements du domaine
277 {
278 for (int i=0; i<nb_faces_elem; i++)
279 numfa[i] = elem_faces(elem,i);
280 if ( dimension == 2)
281 {
282 d2T_dx2(elem) = ( dT_dx(numfa[2]) - dT_dx(numfa[0]) ) * le_dom.dist_face(numfa[1],numfa[3],0);
283 d2T_dy2(elem) = ( dT_dy(numfa[1]) - dT_dx(numfa[3]) ) * le_dom.dist_face(numfa[0],numfa[2],1);
284 E[elem] = 2 * diffu * diffu_turb(elem) * ( d2T_dx2(elem) + d2T_dy2(elem) ) * ( d2T_dx2(elem) + d2T_dy2(elem) );
285 }
286 else if (dimension == 3)
287 {
288 d2T_dx2(elem) = ( dT_dx(numfa[3]) - dT_dx(numfa[0]) ) * volumes(numfa[3]);
289 d2T_dy2(elem) = ( dT_dy(numfa[1]) - dT_dx(numfa[4]) ) * volumes(numfa[4]);
290 d2T_dz2(elem) = ( dT_dy(numfa[5]) - dT_dx(numfa[2]) ) * volumes(numfa[5]);
291 E[elem] = 2 * diffu * diffu_turb(elem) * (d2T_dx2(elem)+d2T_dy2(elem)+d2T_dz2(elem)) * (d2T_dx2(elem)+d2T_dy2(elem)+d2T_dz2(elem));
292 }
293
294 }
295
296 return E;
297}
298
299DoubleTab& Modele_Jones_Launder_Thermique_VDF::Calcul_F1( DoubleTab& F1, const Domaine_dis_base& domaine_dis,const DoubleTab& K_Eps_Bas_Re,const DoubleTab& FluctuTemp_Bas_Re,double visco,double diffu) const
300{
301 const Domaine_VDF& le_dom = ref_cast(Domaine_VDF,domaine_dis);
302 int nb_elem = le_dom.nb_elem();
303 for (int elem=0; elem <nb_elem; elem ++ )
304 F1[elem] = 1.;
305 return F1;
306}
307
308DoubleTab& Modele_Jones_Launder_Thermique_VDF::Calcul_F2( DoubleTab& F2, const Domaine_dis_base& domaine_dis,const DoubleTab& K_Eps_Bas_Re,const DoubleTab& FluctuTemp_Bas_Re,double visco,double diffu) const
309{
310 const Domaine_VDF& le_dom = ref_cast(Domaine_VDF,domaine_dis);
311 int nb_elem = le_dom.nb_elem();
312 /* DoubleTab Re(nb_elem);
313 int elem;
314
315 for (elem=0; elem< nb_elem ; elem++)
316 {
317 Re(elem) = (K_eps_Bas_Re(elem,0)*K_eps_Bas_Re(elem,0))/(visco*K_eps_Bas_Re(elem,1));
318 F2[elem] = 1. - (0.3*exp(-1*carre(Re(elem))));
319 }*/
320 for (int elem=0; elem <nb_elem; elem ++ )
321 F2[elem] = 1.;
322 return F2;
323}
324
325DoubleTab& Modele_Jones_Launder_Thermique_VDF::Calcul_F3( DoubleTab& F3, const Domaine_dis_base& domaine_dis,const DoubleTab& K_Eps_Bas_Re,const DoubleTab& FluctuTemp_Bas_Re,double visco,double diffu) const
326{
327 const Domaine_VDF& le_dom = ref_cast(Domaine_VDF,domaine_dis);
328 int nb_elem = le_dom.nb_elem();
329 for (int elem=0; elem <nb_elem; elem ++ )
330 F3[elem] = 1.;
331 return F3;
332}
333DoubleTab& Modele_Jones_Launder_Thermique_VDF::Calcul_F4( DoubleTab& F4, const Domaine_dis_base& domaine_dis,const DoubleTab& K_Eps_Bas_Re,const DoubleTab& FluctuTemp_Bas_Re,double visco,double diffu) const
334{
335 const Domaine_VDF& le_dom = ref_cast(Domaine_VDF,domaine_dis);
336 int nb_elem = le_dom.nb_elem();
337 for (int elem=0; elem <nb_elem; elem ++ )
338 F4[elem] = 1.;
339 return F4;
340}
341
342
343DoubleTab& Modele_Jones_Launder_Thermique_VDF::Calcul_Flambda( DoubleTab& Flambda,const Domaine_dis_base& domaine_dis,const DoubleTab& K_Eps_Bas_Re, const DoubleTab& FluctuTemp_Bas_Re, double visco, double diffu) const
344{
345 const Domaine_VDF& le_dom = ref_cast(Domaine_VDF,domaine_dis);
346 Flambda = 0;
347 int nb_elem = le_dom.nb_elem();
348 DoubleTab Rt(nb_elem);
349 int elem;
350 for (elem=0; elem< nb_elem ; elem++)
351 {
352 if ( (K_Eps_Bas_Re(elem,1)*FluctuTemp_Bas_Re(elem,1) >= 1.e-6) && (K_Eps_Bas_Re(elem,0)*FluctuTemp_Bas_Re(elem,0) >= 1.e-6))
353 {
354 Rt(elem) = K_Eps_Bas_Re(elem,0)/sqrt(visco*diffu)*sqrt( (K_Eps_Bas_Re(elem,0)*FluctuTemp_Bas_Re(elem,0))/2/(K_Eps_Bas_Re(elem,1)*FluctuTemp_Bas_Re(elem,1)) );
355 // Re(elem) = (K_Eps_Bas_Re(elem,0)*K_Eps_Bas_Re(elem,0))/(visco*K_Eps_Bas_Re(elem,1));
356 Flambda[elem] = exp(-2.5/(1.+Rt(elem)/50.));
357 }
358 else
359 Flambda[elem] = 1.;
360 }
361 return Flambda;
362}
363
365{
366 ;
367}
classe Cond_lim Classe generique servant a representer n'importe quelle classe
Definition Cond_lim.h:31
classe Dirichlet_entree_fluide Cette classe represente une condition aux limite imposant une grandeur
classe Dirichlet Cette classe est la classe de base de la hierarchie des conditions aux limites de ty...
Definition Dirichlet.h:31
virtual double val_imp(int i) const
Renvoie la valeur imposee sur la i-eme composante du champ a la frontiere au temps par defaut du cham...
Definition Dirichlet.cpp:35
int nb_faces_elem(int=0) const
Renvoie le nombre de face de type i des elements geometriques constituants le domaine.
Definition Domaine.h:484
class Domaine_Cl_VDF
classe Domaine_Cl_dis_base Les objets Domaine_Cl_dis_base representent les conditions aux limites
const Cond_lim & les_conditions_limites(int) const
Renvoie la i-ieme condition aux limites.
class Domaine_VDF
Definition Domaine_VDF.h:64
int orientation(int) const override
inline DoubleVect& Domaine_VDF::porosite_face() {
double dist_face(int, int, int k) const
double dist_norm_bord(int num_face) const override
int nb_faces() const
renvoie le nombre global de faces.
Definition Domaine_VF.h:471
DoubleVect & volumes_entrelaces()
Definition Domaine_VF.h:99
double volumes(int i) const
Definition Domaine_VF.h:113
int elem_faces(int i, int j) const
renvoie le numero de le ieme face de la maille num_elem la facon dont ces faces sont numerotees est
Definition Domaine_VF.h:543
double xp(int num_elem, int k) const
Definition Domaine_VF.h:77
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
classe Domaine_dis_base Cette classe est la base de la hierarchie des domaines discretisees.
int nb_elem_tot() const
int nb_front_Cl() const
const Domaine & domaine() const
Class defining operators and methods for all reading operation in an input flow (file,...
Definition Entree.h:42
virtual const Milieu_base & milieu() const =0
class Front_VF
Definition Front_VF.h:36
int nb_faces() const
Definition Front_VF.h:53
int num_premiere_face() const
Definition Front_VF.h:63
DoubleVect & porosite_face()
Definition Milieu_base.h:62
const Transport_Fluctuation_Temperature_W_Bas_Re & equation() const
DoubleTab & Calcul_D(DoubleTab &, const Domaine_dis_base &, const Domaine_Cl_dis_base &, const DoubleTab &, const DoubleTab &, double) const override
void associer(const Domaine_dis_base &, const Domaine_Cl_dis_base &) override
DoubleTab & Calcul_F4(DoubleTab &, const Domaine_dis_base &, const DoubleTab &, const DoubleTab &, double, double) const override
DoubleTab & Calcul_Flambda(DoubleTab &, const Domaine_dis_base &, const DoubleTab &, const DoubleTab &, double, double) const override
DoubleTab & Calcul_F2(DoubleTab &, const Domaine_dis_base &, const DoubleTab &, const DoubleTab &, double, double) const override
DoubleTab & Calcul_E(DoubleTab &, const Domaine_dis_base &, const Domaine_Cl_dis_base &, const DoubleTab &, const DoubleTab &, double, const DoubleTab &) const override
DoubleTab & Calcul_F1(DoubleTab &, const Domaine_dis_base &, const DoubleTab &, const DoubleTab &, double, double) const override
DoubleTab & Calcul_F3(DoubleTab &, const Domaine_dis_base &, const DoubleTab &, const DoubleTab &, double, double) const override
void associer_pb(const Probleme_base &) override
const Equation_base & equation() const
Renvoie la reference sur l'equation pointe par MorEqn::mon_equation.
Definition MorEqn.h:62
Une chaine de caractere (Nom) en majuscules.
Definition Motcle.h:26
Classe Neumann_homogene Cette classe est la classe de base de la hierarchie des conditions aux limite...
Classe Neumann Cette classe est la classe de base de la hierarchie des conditions aux limites de type...
Definition Neumann.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
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.
static void exit(int exit_code=-1)
Routine de sortie de TRUST dans une region Kokkos.
Definition Process.cpp:455
Classe de base des flux de sortie.
Definition Sortie.h:52
classe Symetrie Sur les faces de symetrie on a les proprietes suivantes:
Definition Symetrie.h:37