TrioCFD 1.9.8
TrioCFD documentation
Loading...
Searching...
No Matches
Source_Con_Phase_field_Binaire_Compact.cpp
1/****************************************************************************
2* Copyright (c) 2021, 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 <Convection_Diffusion_Phase_field.h>
17#include <Source_Con_Phase_field_Binaire_Compact.h>
18#include <Source_Qdm_VDF_Phase_field.h>
19#include <Navier_Stokes_phase_field.h>
20#include <Source_Con_Phase_field.h>
21#include <Check_espace_virtuel.h>
22#include <MD_Vector_composite.h>
23#include <Milieu_Phase_field.h>
24#include <Champ_Fonc_Tabule.h>
25#include <Domaine_Cl_VDF.h>
26#include <TRUSTTab_parts.h>
27#include <Champ_Uniforme.h>
28#include <Equation_base.h>
29#include <Probleme_base.h>
30#include <Matrix_tools.h>
31#include <Domaine_VDF.h>
32#include <Milieu_base.h>
33#include <SolveurSys.h>
34#include <Dimension.h>
35#ifdef PETSCKSP_H
36#include <petscsnes.h>
37#endif
38#include <EChaine.h>
39#include <Param.h>
40#include <SFichier.h>
41#include <Perf_counters.h>
42
43
44Implemente_instanciable(Source_Con_Phase_field_Binaire_Compact,"Source_Con_Phase_field_Binaire_Compact_VDF_P0_VDF",Source_Con_Phase_field);
45
46
47// XD Source_Con_Phase_field_Binaire_Compact_VDF_P0_VDF Source_Con_Phase_field Source_Con_Phase_field_Binaire_Compact_VDF_P0_VDF INHERITS_BRACE Source for phase field
48
49
51{
52 return s << que_suis_je();
53}
54
56{
57 Cerr << "Source_Con_Phase_field_Binaire_Compact::readOn" << finl;
59 if (!Process::me())
60 {
61 SFichier fichier_residu("residu.txt");
62 fichier_residu << "# SAUVEGARDE DU RESIDU #" << finl;
63 fichier_residu << "# Time \t Time simu \t Residu" << finl;
64
65 SFichier fichier_eval("eval.txt");
66 fichier_eval << "# Time simu \t Number eval FormFunction" << finl;
67 }
68 return is;
69}
70
71DoubleTab& Source_Con_Phase_field_Binaire_Compact::laplacien(const DoubleTab& F, DoubleTab& resu) const
72{
73 const Navier_Stokes_std& eq_ns = ref_cast(Navier_Stokes_std, pb_->equation(0));
74 const Operateur_Grad& opgrad = eq_ns.operateur_gradient();
75 const Operateur_Div& opdiv = eq_ns.operateur_divergence();
76
77 resu = 0.;
78
79 // Dans cette partie, le laplacien est obtenu comme div.(grad F) avec
80 // une application du solveur masse entre l'etape de gradient et de divergence
81
82 DoubleTab& prov_face = ref_cast_non_const(DoubleTab, prov_face_);
83 if (prov_face.size() == 0)
84 prov_face = eq_ns.inconnue().valeurs();
85
86 prov_face = 0.;
87 // Grad(F)
88 opgrad.calculer(F, prov_face);
89 // Application solveur masse
90 eq_ns.solv_masse().appliquer(prov_face);
91
92 // Div(M*Grad(F))
93 opdiv.calculer(prov_face, resu);
94
95 return resu;
96}
97
98DoubleTab& Source_Con_Phase_field_Binaire_Compact::div_kappa_grad(const DoubleTab& F, const DoubleTab& kappa_var, DoubleTab& resu) const
99{
100 const Navier_Stokes_std& eq_ns = ref_cast(Navier_Stokes_std, pb_->equation(0));
101 const Operateur_Grad& opgrad = eq_ns.operateur_gradient();
102 const Operateur_Div& opdiv = eq_ns.operateur_divergence();
103
104 // const Convection_Diffusion_Phase_field& eq_c = ref_cast(Convection_Diffusion_Phase_field, pb_->equation(1));
105 // const DoubleTab& c = eq_c.inconnue().valeurs();
106
107 const Domaine_VDF& domaine_VDF = le_dom_VDF_.valeur();
108 const IntTab& face_voisins = domaine_VDF.face_voisins();
109 const DoubleVect& volumes = domaine_VDF.volumes();
110
111 DoubleTab& prov_face = ref_cast_non_const(DoubleTab, prov_face_);
112 if (prov_face.size() == 0)
113 prov_face = eq_ns.inconnue().valeurs();
114 prov_face = 0.;
115 resu = 0.;
116
117 // Grad(F)
118 opgrad.calculer(F, prov_face);
119
120 // M*Kappa*Grad(F)
121 int ndeb = domaine_VDF.premiere_face_int();
122 int nbfaces = domaine_VDF.nb_faces();
123 int el0, el1;
124 double kappa_face, vol0, vol1; // cface
125
126 for (int fac = ndeb; fac < nbfaces; fac++)
127 {
128 el0 = face_voisins(fac, 0);
129 el1 = face_voisins(fac, 1);
130 vol0 = volumes(el0);
131 vol1 = volumes(el1);
132 kappa_face = (vol0 * kappa_var(el0) + vol1 * kappa_var(el1)) / (vol0 + vol1);
133 // cface = (vol0 * c(el0) + vol1 * c(el1)) / (vol0 + vol1);
134 // prov_face(fac) = kappa_face * mobilite(cface) * prov_face(fac);
135 prov_face(fac) = kappa_face * prov_face(fac); // Changement de Luis: mobilite = 1 de toute façon dans le code initial
136 }
137
138 // Application solveur masse (/M)
139 eq_ns.solv_masse().appliquer(prov_face);
140
141 // Div(Kappa*Grad(F))
142 opdiv.calculer(prov_face, resu);
143 //Cerr <<"div_kappa_grad"<<resu<<finl;
144
145 return resu;
146}
147
148/*! @brief Calcul de Div(alpha*rho*Grad((C)) au centre des elements
149 *
150 * @param (DoubleTab& div_alpha_gradC) Div(alpha*Grad((C)) au centre des elements
151 */
152void Source_Con_Phase_field_Binaire_Compact::calculer_div_alpha_grad(const DoubleTab& c, DoubleTab& div_alpha_gradC) const
153{
154 const Convection_Diffusion_Phase_field& eq_c = ref_cast(Convection_Diffusion_Phase_field, pb_->equation(1));
155 const Navier_Stokes_std& eq_ns = ref_cast(Navier_Stokes_std, pb_->equation(0));
156 const Operateur_Grad& opgrad = eq_ns.operateur_gradient();
157 const Operateur_Div& opdiv = eq_ns.operateur_divergence();
158 const Milieu_Phase_field& mil = ref_cast(Milieu_Phase_field, pb_->milieu());
159 const auto& fermeture = mil.get_fermeture();
160
161 DoubleTab& prov_face = ref_cast_non_const(DoubleTab, prov_face_);
162 if (prov_face.size() == 0)
163 prov_face = eq_ns.inconnue().valeurs();
164 prov_face = 0.;
165
166 // Grad(C)
167 opgrad.calculer(c, prov_face);
168 eq_ns.solv_masse().appliquer(prov_face);
169 prov_face *= fermeture.get_alpha();
170
171 // Div(alpha*Grad(c))
172 opdiv.calculer(prov_face, div_alpha_gradC);
173 eq_c.solv_masse().appliquer(div_alpha_gradC);
174 //Cerr <<"div_alpha_gradC"<<div_alpha_gradC<<finl;
175
176}
177
178/*! @brief Calcul de Div(alpha*rho*Grad((C)) au centre des elements
179 *
180 * @param (DoubleTab& div_alpha_rho_gradC) Div(alpha*rho*Grad((C)) au centre des elements
181 */
182void Source_Con_Phase_field_Binaire_Compact::calculer_div_alpha_rho_grad(const DoubleTab& c, DoubleTab& div_alpha_rho_gradC) const
183{
184 const Convection_Diffusion_Phase_field& eq_c = ref_cast(Convection_Diffusion_Phase_field, pb_->equation(1));
185 const Navier_Stokes_phase_field& eq_ns = ref_cast(Navier_Stokes_phase_field, pb_->equation(0));
186 const Operateur_Grad& opgrad = eq_ns.operateur_gradient();
187 const Operateur_Div& opdiv = eq_ns.operateur_divergence();
188 const Milieu_Phase_field& mil = ref_cast(Milieu_Phase_field, pb_->milieu());
189 const auto& fermeture = mil.get_fermeture();
190
191 const Domaine_VDF& domaine_VDF = le_dom_VDF_.valeur();
192 const IntTab& face_voisins = domaine_VDF.face_voisins();
193 const DoubleVect& volumes = domaine_VDF.volumes();
194 const int ndeb = domaine_VDF.premiere_face_int();
195 const int nbfaces = domaine_VDF.nb_faces();
196
197 int el0, el1;
198 double vol0, vol1;
199 DoubleTab& prov_face = ref_cast_non_const(DoubleTab, prov_face_);
200 if (prov_face.size() == 0)
201 prov_face = eq_ns.inconnue().valeurs();
202 prov_face = 0.;
203
204 // Grad(C)
205 opgrad.calculer(c, prov_face);
206 eq_ns.solv_masse().appliquer(prov_face);
207
208 const DoubleTab& rhoPF = mil.rho().valeurs();
209 double rho_face;
210
211 if (boussi_ == 1)
212 prov_face *= fermeture.get_alpha() * rho0_; // Cas approximation de Boussinesq
213 else if (boussi_ == 0)
214 {
215 for (int fac = ndeb; fac < nbfaces; fac++)
216 {
217 el0 = face_voisins(fac, 0);
218 el1 = face_voisins(fac, 1);
219 vol0 = volumes(el0);
220 vol1 = volumes(el1);
221
222 rho_face = (vol0 * rhoPF(el0) + vol1 * rhoPF(el1)) / (vol0 + vol1);
223 prov_face(fac) *= fermeture.get_alpha() * rho_face;
224 }
225 }
226
227 // Div(alpha*rho*Grad(c))
228 opdiv.calculer(prov_face, div_alpha_rho_gradC);
229 eq_c.solv_masse().appliquer(div_alpha_rho_gradC);
230
231}
232
233/*! @brief Calcule le premier demi pas de temps dans le cas implicite Calcule le pas de temps dans le cas explicite
234 *
235 */
237{
238 const Domaine_VDF& domaine_VDF = le_dom_VDF_.valeur();
239 const int nb_elem = domaine_VDF.nb_elem_tot();
240
241 Convection_Diffusion_Phase_field& eq_c = ref_cast(Convection_Diffusion_Phase_field, pb_->equation(1));
242 DoubleTab& c = eq_c.inconnue().valeurs();
243
244 DoubleTab& mutilde = eq_c.set_mutilde_().valeurs();
245 DoubleTab& mutilde_demi = eq_c.set_mutilde_demi();
246 DoubleTab& c_demi = eq_c.set_c_demi();
247
248 Milieu_Phase_field& mil = ref_cast(Milieu_Phase_field, pb_->milieu());
249 Fermeture_Phase_field_base& fermeture = mil.get_fermeture();
250
251 // Utilise dans l'ancien modele de Didier Jamet
252
253 /* commente par mr264902 car pas utilise dans la version presente
254 //DoubleTab& alpha_gradC_carre=eq_c.set_alpha_gradC_carre();
255 //calculer_alpha_gradC_carre(alpha_gradC_carre);
256 //DoubleTab& div_alpha_rho_gradC=eq_c.set_div_alpha_rho_gradC();
257 //
258 //calculer_div_alpha_rho_grad(c, div_alpha_rho_gradC);
259 */
260 DoubleTab& div_alpha_gradC = eq_c.set_div_alpha_gradC();
261 calculer_div_alpha_grad(c, div_alpha_gradC);
262 // commente par mr264902 car pas utilise dans la version presente
263 //DoubleTab& pression_thermo=eq_c.set_pression_thermo();
264 //calculer_pression_thermo(pression_thermo);
265
266 accr_ = c; // on copie la structure // !!
267 c_demi = c; // on copie la structure // !!
268
269 accr_ = 0.; // initialise a 0
270 c_demi = 0.; // initialise a 0
271
272 if (implicitation_ == 1)
273 {
274 mutilde_demi = c; // on copie la structure // !!
275 mutilde_demi = 0.; // initialise a 0
276
277 // Pour le JFNK ----------------------------
278
279 // Commente par DJ
280 //----------------
281 // DoubleTab x1(2*nb_elem);
282 // x1=0.;
283 // if(gmres_==1)
284 // {
285
286 // // Ecriture de x1(0)
287 // for(int n_elem=0;n_elem<nb_elem;n_elem++)
288 // {
289 // x1(n_elem)=c(n_elem);
290 // x1(n_elem+nb_elem)=mutilde(n_elem);
291 // }
292 // }
293 //----------------
294 // ---------------------------------------------
295
297
298 // only once !
300 {
302// Cout << "Matrice avec alpha = " << finl;
303// matrice_alpha_.imprimer_formatte(Cout);
304 }
305
307 {
309// Cout << "Matrice avec kappa = " << finl;
310// matrice_kappa_.imprimer_formatte(Cout);
311 }
312
313 // Modifie par DJ
314 //---------------
315
316 // RESOLUTION JFNK
317 // =========================================================
318 resolution_jfnk(c, mutilde, c_demi, mutilde_demi);
319 // =========================================================
320
321 const double theta = 0.6;
322 // On stocke les nouveaux c et mutilde
323
324 for (int n_elem = 0; n_elem < nb_elem; n_elem++)
325 {
326 // Commente par DJ
327 //----------------
328 // c_demi(n_elem)=x1(n_elem);
329 //----------------
330 c_demi(n_elem) -= (1 - theta) * c(n_elem);
331 c_demi(n_elem) /= theta;
332
333 // Commente par DJ
334 //----------------
335 // mutilde_demi(n_elem)=x1(n_elem+nb_elem);
336 //----------------
337 //c=c_demi;
338
339 //---------- Calcul de mutilde_demi = dw/dc (c_demi)-div_alpha_gradC(c_demi) ------------
340 //calculer_mutilde_demi(mutilde_demi, c_demi);
341 //calculer_mutilde(mutilde_demi);
342 //mutilde=mutilde_demi;
343 mutilde_demi(n_elem) -= (1 - theta) * mutilde(n_elem);
344 mutilde_demi(n_elem) /= theta;
345 }
346
347 // ATTENTION : A VERIFIER
348 //=======================
349 // c_demi.echange_espace_virtuel();
350 // mutilde_demi.echange_espace_virtuel();
351 // c.echange_espace_virtuel();
352 // mutilde.echange_espace_virtuel();
353
354 // Mise a jour
355
356 if (couplage_ == 0)
357 {
358 // Si traitement explicite de mutilde dans le cas implicite
359 calculer_mutilde(mutilde);
360 }
361 else if (couplage_ == 1)
362 {
363 // Si traitement implicite de mutilde dans le cas implicite
364 mutilde = mutilde_demi;
365 }
366 mutilde.echange_espace_virtuel();
367
368 // Calcul de l'accroissement entre n et n+1/2
369 // Utile pour pouvoir utiliser n'importe quel dt
370 accr_ = 0.;
371
372 }
373 else if (implicitation_ == 0)
374 {
375 // Cerr<<"Schema explicite"<<finl;
377 calculer_mutilde(mutilde);
378 mutilde.echange_espace_virtuel();
379
380 DoubleTab& prov_elem = prov_elem_;
381 if (prov_elem.size() == 0)
382 prov_elem = mutilde;
383
384 if (fermeture.get_kappa_ind() == 1)
385 {
386 DoubleTab kappa_var(prov_elem);
387 kappa_var = 0.;
388 for (int ikappa = 0; ikappa < nb_elem; ikappa++)
389 kappa_var(ikappa) = fermeture.call_kappa_func_c(c(ikappa));
390 // Div(Kappa*Grad(mutilde))
391 div_kappa_grad(mutilde, kappa_var, prov_elem);
392 }
393 else if (fermeture.get_kappa_ind() == 0)
394 {
395 // Kappa*Laplacien(mutilde)
396 laplacien(mutilde, prov_elem);
397 prov_elem *= fermeture.get_kappa();
398 }
399
400 // Pour equation Allen-Cahn (kappa constant)
401 //------------------------------------------
402 // prov_elem=F;
403 // prov_elem*=-kappa;
404
405 accr_ += prov_elem;
406 //eq_c.solv_masse().appliquer(prov_elem);
407 //Cerr<<"masse de la force sur c "<<prov_elem.max_abs()<<finl;
408
409 // Utile pour pouvoir utiliser n'importe quel dt - voir Schema_Phase_Field
410 c_demi = c;
411 }
412 else
413 {
414 Cerr << "Type de schema errone !!" << finl;
415 }
416}
417
419{
420 const Convection_Diffusion_Phase_field& eq_c = ref_cast(Convection_Diffusion_Phase_field, pb_->equation(1));
421 const DoubleTab& c = eq_c.inconnue().valeurs();
422
423 kappa_tab_ = c; // on initialise la structure
424
425 /*
426 * Typage d'une operateur utile
427 */
428
429 ch_kappa_ou_alpha_ = eq_c.get_mutilde_(); // on copie la structure
430 ch_kappa_ou_alpha_->nommer("ch_kappa_ou_alpha");
431
432 terme_diffusif_vdf_.associer_eqn(eq_c);
433 terme_diffusif_vdf_.associer_diffusivite(ch_kappa_ou_alpha_.valeur());
434 EChaine diff( "{ }");
435 diff >> terme_diffusif_vdf_;
436 terme_diffusif_vdf_.associer_diffusivite_pour_pas_de_temps(ch_kappa_ou_alpha_.valeur());
437 terme_diffusif_vdf_->associer(le_dom_VDF_.valeur(), eq_c.domaine_Cl_dis(), eq_c.inconnue());
438 terme_diffusif_vdf_->completer();
439
440 terme_diffusif_vdf_.associer_diffusivite(ch_kappa_ou_alpha_.valeur());
441 terme_diffusif_vdf_->associer_diffusivite(ch_kappa_ou_alpha_.valeur());
442 terme_diffusif_vdf_->dimensionner(matrice_kappa_);
443 matrice_kappa_.sort_stencil(); // XXX sort tab2 ... au cas ou ...
445
447
448}
449
451{
452 const Convection_Diffusion_Phase_field& eq_c = ref_cast(Convection_Diffusion_Phase_field, pb_->equation(1));
453 const Milieu_Phase_field& mil = ref_cast(Milieu_Phase_field, pb_->milieu());
454 const auto& fermeture = mil.get_fermeture();
455 const DoubleTab& c = eq_c.inconnue().valeurs();
456
457 ch_kappa_ou_alpha_ = eq_c.get_mutilde_(); // on copie la structure
458 ch_kappa_ou_alpha_->nommer("ch_kappa_ou_alpha");
459
460 terme_diffusif_vdf_.associer_eqn(eq_c);
461 terme_diffusif_vdf_.associer_diffusivite(ch_kappa_ou_alpha_.valeur());
462 EChaine diff( "{ }");
463 diff >> terme_diffusif_vdf_;
464 terme_diffusif_vdf_.associer_diffusivite_pour_pas_de_temps(ch_kappa_ou_alpha_.valeur());
465 terme_diffusif_vdf_->associer(le_dom_VDF_.valeur(), eq_c.domaine_Cl_dis(), eq_c.inconnue());
466 terme_diffusif_vdf_->completer();
467
468 ch_kappa_ou_alpha_->valeurs() = -fermeture.get_alpha();
469
470 /*
471 * XXX Elie Saikali : attention la y a pas le solveur de masse qui va diviser par V apres ....
472 */
473 const DoubleVect& vol = le_dom_VDF_->volumes();
474 tab_divide_any_shape(ch_kappa_ou_alpha_->valeurs(), vol);
475 terme_diffusif_vdf_.associer_diffusivite(ch_kappa_ou_alpha_.valeur());
476 terme_diffusif_vdf_->associer_diffusivite(ch_kappa_ou_alpha_.valeur());
477 terme_diffusif_vdf_->dimensionner(matrice_alpha_);
478 matrice_alpha_.sort_stencil(); // XXX sort tab2 ... au cas ou ...
479 terme_diffusif_vdf_->contribuer_a_avec(c, matrice_alpha_);
480
481 // Vecteur contenant la contribution des conditions limites
482 vec_cl_ = c; // on initialise la structure
483 vec_cl_ = 0.;
484
485 terme_diffusif_vdf_->ajouter(c,vec_cl_);
486 matrice_alpha_.ajouter_multvect(c, vec_cl_); // Ajout de A*Inco(n)
487
488 Cout << "Vecteur de conditions limites = " << eq_c.domaine_Cl_dis();
489 Cout << "Vecteur de conditions limites vec_cl = " << vec_cl_;
490
492
493}
494
496{
497 const Milieu_Phase_field& mil = ref_cast(Milieu_Phase_field, pb_->milieu());
498 const auto& fermeture = mil.get_fermeture();
499 const int nb_elem = le_dom_VDF_->nb_elem_tot();
500
501 if (fermeture.get_kappa_ind() == 0)
502 kappa_tab_ = fermeture.get_kappa();
503 else
504 {
505 for (int elem = 0; elem < nb_elem; elem++)
506 kappa_tab_(elem) = fermeture.call_kappa_func_c(donne(elem));
507 }
508}
509
511{
512 const auto& fermeture = ref_cast(Milieu_Phase_field, pb_->milieu()).get_fermeture();
513
514 if (is_matrix_kappa_initialised_ && fermeture.get_type_kappa() ==0)
515 return;
516
517 update_tab_kappa(donne);
518
519 const Convection_Diffusion_Phase_field& eq_c = ref_cast(Convection_Diffusion_Phase_field, pb_->equation(1));
520 double dt = eq_c.schema_temps().pas_de_temps(); // on fait un calcul sur un demi pas de temps
521 const double theta = 0.6;
522
523 ch_kappa_ou_alpha_->valeurs() = kappa_tab_;
524 ch_kappa_ou_alpha_->valeurs() *= (theta * dt);
525 const DoubleVect& vol = le_dom_VDF_->volumes();
526 tab_divide_any_shape(ch_kappa_ou_alpha_->valeurs(), vol);
527
528 terme_diffusif_vdf_.associer_diffusivite(ch_kappa_ou_alpha_.valeur());
529 terme_diffusif_vdf_->associer_diffusivite(ch_kappa_ou_alpha_.valeur());
530 terme_diffusif_vdf_->contribuer_a_avec(eq_c.inconnue().valeurs(), matrice_kappa_);
531
532}
533
534/*! @brief Construire le residu du JFNK
535 *
536 */
537
538void Source_Con_Phase_field_Binaire_Compact::calculer_residu_jfnk(const DoubleTab& c, DoubleTab& v0, const DoubleTab& c_demi)
539{
540 const Milieu_Phase_field& mil = ref_cast(Milieu_Phase_field, pb_->milieu());
541 const auto& fermeture = mil.get_fermeture();
542 const int nb_elem = le_dom_VDF_->nb_elem_tot();
543
544 DoubleVect term_cin(nb_elem);
545 // Ceci correspond a u2/2*drhodc=mutilde_dyn-mutilde
546
547 DoubleVect second_membre(nb_elem);
548 DoubleTab B_c_demi(nb_elem);
549 DoubleTab A_B_c_demi_sec_membre(nb_elem);
550
551 for (int n_elem = 0; n_elem < nb_elem; n_elem++)
552 {
553 term_cin(n_elem) = 0.;
554 if (mutype_ == 1)
555 term_cin(n_elem) += (0.5 * u_carre_(n_elem)) * drhodc(n_elem);
556
557 second_membre(n_elem) = term_cin(n_elem) + fermeture.get_beta() * fermeture.call_dWdc(c_demi(n_elem));
558 }
559
560 // On calcule H(c_demi) = c_demi + A ( B . c_demi - beta*dW/dc(c_demi) ) - c
561 // Où A = matrice_kappa et B = matrice_alpha
562
563 // Calcul du premier produit matrice / vecteur B . c_demi
564 matrice_alpha_.multvect_(c_demi, B_c_demi);
565 // Calcul du second produit matrice / vecteur A . (B . c_demi - beta*dW/dc)
566 for (int n_elem = 0; n_elem < nb_elem; n_elem++)
567 {
568 second_membre(n_elem) = second_membre(n_elem) - B_c_demi(n_elem);
569 }
570 matrice_kappa_.multvect_(second_membre, A_B_c_demi_sec_membre);
571
572
573 for (int n_elem = 0; n_elem < nb_elem; n_elem++)
574 {
575 v0(n_elem) = c_demi(n_elem) - c(n_elem) + A_B_c_demi_sec_membre(n_elem);
576 }
577
578}
579
580/*! @brief Construire la jacobienne multipliée par un vecteur Y
581 *
582 */
583void Source_Con_Phase_field_Binaire_Compact::jacobian_vect(const DoubleTab& c, const DoubleTab& v0, const DoubleTab& x1, DoubleTab& v1)
584{
585 const double delta = 1.e-5;
586
587 DoubleTab v2(v1);
588 DoubleTab x1_(v0);
589
590 v1 = 0.;
591
592 x1_ = v0;
593 x1_ *= delta;
594 x1_ += x1;
595
596 // Construction de la differentielle (dans la direction v0)
597 calculer_residu_jfnk(c, v1, x1_);
598 calculer_residu_jfnk(c, v2, x1);
599
600 v1 -= v2;
601 v1 /= delta;
602}
603
604
605#ifdef PETSCKSP_H
606// Convertir DoubleTab -> PETSc Vec
607void tabToVecBis(const DoubleTab& tab, Vec& f)
608{
609 PetscScalar *f_array;
610 PetscInt size;
611 VecGetArray(f, &f_array);
612 VecGetSize(f, &size);
613 assert(size == tab.dimension_tot(0));
614 for (int i = 0; i < tab.dimension_tot(0); i++)
615 f_array[i] = tab(i);
616 VecRestoreArray(f, &f_array);
617}
618
619// Convertir PETSc Vec -> DoubleTab
620void vecToTabBis(const Vec& v, DoubleTab& result)
621{
622 PetscInt size;
623 const PetscScalar *array;
624 VecGetSize(v, &size);
625 VecGetArrayRead(v, &array);
626 assert((int)size == result.dimension_tot(0));
627 for (PetscInt i = 0; i < size; ++i)
628 result((int)i) = array[i];
629 VecRestoreArrayRead(v, &array);
630}
631
632
633/*! @brief FormFunction de PETSc : calcule le résidu du JFNK
634 *
635 */
636PetscErrorCode FormFunctionCompactOld(SNES snes, Vec x, Vec f, void* ctx)
637{
638 Equation_base* eqn = static_cast<Equation_base*>(ctx);
640 const DoubleTab& C = eq_c.inconnue().valeurs();
641
643 const int nb_elem = C.dimension_tot(0);
644 DoubleTab c_demi(nb_elem);
645
646 vecToTabBis(x,c_demi);
647
648
649 const Milieu_Phase_field& mil = ref_cast(Milieu_Phase_field, eq_c.milieu());
650 const auto& fermeture = mil.get_fermeture();
651 // Assemblage du second membre
652 DoubleTrav second_membre(c_demi);
653
654 for (int n_elem = 0; n_elem < nb_elem; n_elem++)
655 {
656 second_membre(n_elem) = fermeture.get_beta() * fermeture.call_dWdc(c_demi(n_elem));
657 }
658
659 DoubleTrav B_c_demi(nb_elem);
660 DoubleTrav A_B_c_demi_sec_membre(nb_elem);
661
662 // On calcule H(c_demi) = c_demi + A ( B . c_demi - beta*dW/dc(c_demi) ) - c
663 // Où A = matrice_kappa et B = matrice_alpha
664
665 // Calcul du premier produit matrice / vecteur B . c_demi
666 source.get_matrice_alpha().multvect_(c_demi, B_c_demi);
667 // Calcul du second produit matrice / vecteur A . (B . c_demi - beta*dW/dc)
668 for (int n_elem = 0; n_elem < nb_elem; n_elem++)
669 {
670 second_membre(n_elem) = second_membre(n_elem) - B_c_demi(n_elem);
671 }
672
673 source.get_matrice_kappa().multvect_(second_membre, A_B_c_demi_sec_membre);
674
675 for (int n_elem = 0; n_elem < nb_elem; n_elem++)
676 {
677 second_membre(n_elem) = c_demi(n_elem) - C(n_elem) + A_B_c_demi_sec_membre(n_elem);
678 }
679
680 tabToVecBis(second_membre, f);
681
682 return 0;
683}
684
685PetscErrorCode MySNESMonitorBis(SNES snes, PetscInt its, PetscReal norm, void* ctx)
686{
687 Equation_base* eqn = static_cast<Equation_base*>(ctx);
688 // statistiques().set_debug_level(9);
689 double temps_exec = statistics().get_time_since_last_open(STD_COUNTERS::total_execution_time);
690
691 Cout << "[SNES] Iteration " << its << " : ||F(x)|| = " << norm << finl;
692
693 if (!Process::me())
694 {
695 SFichier fichier_residu("residu.txt", ios::app);
696 fichier_residu << temps_exec << "\t" << eqn->schema_temps().temps_courant() << "\t" << (double)norm << finl;
697 }
698
699
700// Vec x;
701// SNESGetSolution(snes, &x);
702//
703// Vec r;
704// SNESGetFunction(snes, &r, nullptr, nullptr); // récupère F(x) courant
705// Facultatif : afficher x
706// Cerr << "Solution Iteration " << its << " : x = " << finl;
707// VecView(x, PETSC_VIEWER_STDOUT_WORLD);
708// Cerr << "Résidu Iteration " << its << " : r = " << finl;
709// VecView(r, PETSC_VIEWER_STDOUT_WORLD);
710
711 return 0;
712}
713
714PetscErrorCode LuisKSPMonitorBis(KSP ksp, PetscInt its, PetscReal rnorm, void* ctx)
715{
716 Cout << " [KSP] Iteration " << its << " : residu = " << rnorm << finl;
717 // Vec x;
718 // KSPBuildSolution(ksp, nullptr, &x); // récupère x courant (solution approx.)
719
720// VecView(x, PETSC_VIEWER_STDOUT_WORLD); // affiche le contenu de x
721
722 return 0;
723}
724
725int Source_Con_Phase_field_Binaire_Compact::petsc_snes(const DoubleTab& c, const DoubleTab& mutilde, DoubleTab& c_demi, DoubleTab& mutilde_demi)
726{
727
728 const int nb_elem_tot = c.size_totale();
729
730 Cout << "Size total = " << c.size_totale() << finl;
731
732 // Variables SNES ########################################
733 SNES snes; // Contexte SNES
734 Vec x, r; // Vecteurs : solution, résidu
735 KSP ksp;
736 Mat J;
737 PC pc;
738 // #######################################################
739
740 // INITIALISATION DU VECTEUR D'INCONNUES X
741 VecCreate(PETSC_COMM_WORLD, &x);
742 VecSetSizes(x, PETSC_DECIDE, nb_elem_tot);
743 VecSetFromOptions(x);
744
745 // INITIAL GUESS of X
746 tabToVecBis(c, x);
747
748 VecDuplicate(x, &r);
749
750 // Vérification tailles
751 PetscInt x_size, r_size;
752 VecGetSize(x, &x_size);
753 VecGetSize(r, &r_size);
754 assert(x_size == nb_elem_tot);
755 assert(r_size == nb_elem_tot);
756
757 // ---------------------- Compute real values of tolerances ---------------------------
758 // Appel explicite de ta fonction de résidu
759 FormFunctionCompactOld(nullptr, x, r, &equation());
760
761 // Affiche le résidu (par exemple sa norme)
762 PetscReal norm;
763 VecNorm(r, NORM_2, &norm);
764 PetscPrintf(PETSC_COMM_WORLD, "Résidu F(x) = %g\n", (double)norm);
765
766 // ------------------------------------ SNES ------------------------------------------
767 SNESCreate(PETSC_COMM_WORLD, &snes);
768
769 SNESSetType(snes, SNESNEWTONLS);
770
771 // ========== Associate the FormFunction to the SNES context ============
772 SNESSetFunction(snes, r, FormFunctionCompactOld, &equation());
773 // ======================================================================
774
775 SNESLineSearch linesearch;
776 SNESGetLineSearch(snes, &linesearch); // Newton Line Search ne marche pas dans notre cas
777 // C'est pour ça qu'on le désactive ici
778 SNESLineSearchSetType(linesearch, SNESLINESEARCHNONE); // Désactive la recherche de pas
779
780 // Checking if linesearch is desactivated
781 const char* ls_type;
782 SNESLineSearchGetType(linesearch, &ls_type);
783 PetscPrintf(PETSC_COMM_WORLD, "Type of Line Search used: %s\n", ls_type); // Printing linesearch type
784
785 // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
786
787 // Crée la matrice matrix-free à partir du SNES
788 MatCreateSNESMF(snes, &J);
789
790 // Fixe epsilon sur la vraie matrice MF
791 // MatMFFDSetBase(J, delta);
792 MatMFFDSetFunctionError(J, erel_);
793 MatMFFDSetType(J, "ds"); // default: ds (difference scaled), alternative: wp (Walker–Pernice)
794 MatMFFDDSSetUmin(J, umin_);
795
796 SNESSetJacobian(snes, J, J, MatMFFDComputeJacobian, nullptr);
797 // SNESSetJacobian(snes, J, nullptr, nullptr, nullptr);
798
799 MatView(J, PETSC_VIEWER_STDOUT_WORLD);
800
801 // Pas de Jacobien explicite => JFNK par défaut : SNES construit la matrice par DF entre colonnes
802 // SNESSetJacobian(snes, nullptr, nullptr, SNESComputeJacobianDefault, nullptr);
803 // SNESSetUseMatrixFree(snes, PETSC_TRUE, PETSC_TRUE); // Impose l'option Matrix-Free
804
805 // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
806
807 // Tolerance for Newton
808 SNESSetTolerances(snes, atol_, rtol_, stol_, maxit_newton_, 100000);
809
810 // TRES IMPORTANT : Force à continuer l'algorithme de Newton même si la méthode de Krylov n'a pas convergé
811 SNESSetForceIteration(snes, PETSC_TRUE);
812 SNESSetMaxLinearSolveFailures(snes, 200);
813
814 // Vérification
815 PetscBool force_it;
816 SNESGetForceIteration(snes, &force_it);
817 PetscPrintf(PETSC_COMM_WORLD, "Force iteration: %s\n", force_it ? "ON" : "OFF");
818
819 // --------------------------------------- KSP ---------------------------------------------
820 SNESGetKSP(snes, &ksp);
821 KSPSetType(ksp, KSPGMRES); // GMRES
822 KSPGMRESSetRestart(ksp, nkr_); // GMRES(m) avec m la dimension de l'espace de Krylov définie par l'utilisateur
823 // KSPSetType(ksp, KSPCG); // CG
824 // KSPSetInitialGuessNonzero(ksp, PETSC_TRUE); // XXX Luis : PAS BON DU TOUT
825 // PetscOptionsSetValue(nullptr, "-ksp_gmres_orthogonalization", "classical"); // Facultatif : dans notre config, on ne peut pas changer le type d'orthogonalisation
826 KSPSetTolerances(ksp, rtol_, atol_, 5000., maxit_gmres_);
827
828 // -------------------------------- Préconditionneur --------------------------------------
829 KSPGetPC(ksp, &pc);
830 PCSetType(pc, PCNONE); // No preconditionning
831 // PCSetFromOptions(pc);
832
833 // Monitoring
834 KSPMonitorSet(ksp, LuisKSPMonitorBis, nullptr, nullptr);
835 SNESMonitorSet(snes, MySNESMonitorBis, &equation(), nullptr);
836 //SNESMonitorSet(snes, MySNESMonitorBis, nullptr, nullptr);
837
838 // =============================== Setting from options ===================================
839 // KSPSetFromOptions(ksp); // Lire les options
840
841 // Injecte les options comme si elles venaient de la ligne de commande
842 // PetscOptionsSetValue(nullptr, "-pc_type", "none"); // désactive le préconditionneur
843 // PetscOptionsSetValue(nullptr, "-snes_mf", nullptr); // active matrix-free
844 // PetscOptionsSetValue(nullptr, "-snes_mf_relstep", "1e-5"); // contrôle l’epsilon de l’approximation par différences finies
845
846 PetscOptionsView(nullptr, PETSC_VIEWER_STDOUT_WORLD); // Visu de la liste des options
847 PetscOptionsLeft(nullptr); // Liste celles qui n'ont PAS été utilisées
848
849 // Lecture des options ligne de commande de SNES
850 SNESSetOptionsPrefix(snes, "mysolver_");
851
852 SNESSetFromOptions(snes);
853
854 SNESView(snes, PETSC_VIEWER_STDOUT_WORLD);
855
856 // ############################### SOLVING ################################################
857 SNESSolve(snes, nullptr, x); // #
858 // ########################################################################################
859
860 PetscInt nfunc;
861 SNESGetNumberFunctionEvals(snes, &nfunc);
862
863 if (!Process::me())
864 {
865 SFichier fichier_eval("eval.txt", ios::app);
866 fichier_eval << equation().schema_temps().temps_courant() << "\t" << nfunc << finl;
867 }
868
869
870 const char *reasonstr;
871 SNESGetConvergedReasonString(snes, &reasonstr);
872 Cout << "SNES converged for this reason: " << reasonstr << finl;
873
874 DoubleTrav solution(nb_elem_tot); // inconnue (vector de C et mutilde)
875
876 vecToTabBis(x,solution);
877
878 for (int n_elem = 0; n_elem < nb_elem_tot; n_elem++)
879 {
880 c_demi(n_elem) = solution(n_elem);
881 }
882
883 DoubleTrav mu_temp(nb_elem_tot);
884 DoubleTrav B_c_demi(nb_elem_tot);
885 const Milieu_Phase_field& mil = ref_cast(Milieu_Phase_field, equation().milieu());
886 const auto& fermeture = mil.get_fermeture();
887
888 for (int n_elem = 0; n_elem < nb_elem_tot; n_elem++)
889 {
890 mu_temp(n_elem) = fermeture.get_beta() * fermeture.call_dWdc(c_demi(n_elem));
891 }
892
893 // On calcule H(c_demi) = c_demi + A ( B . c_demi - beta*dW/dc(c_demi) ) - c
894 // Où A = matrice_kappa et B = matrice_alpha
895
896 // Calcul du produit matrice / vecteur B . c_demi, puis soustraction du vecteur beta*dW/dc
897 matrice_alpha_.multvect_(c_demi, B_c_demi);
898 for (int n_elem = 0; n_elem < nb_elem_tot; n_elem++)
899 {
900 mutilde_demi(n_elem) = mu_temp(n_elem) - B_c_demi(n_elem);
901 }
902
903 // Nettoyage
904 VecDestroy(&x);
905 VecDestroy(&r);
906 MatDestroy(&J);
907 SNESDestroy(&snes);
908
909 return 1;
910}
911#endif
912/*! @brief Algorithme JFNK (ancienne version de D. Jamet et nouvelle version de PETSc)
913 *
914 * @param (mutilde) inverse A x = b
915 * @return (int)
916 *
917 * Solves Ax = b by GMRES with nit iterations (reinitializations) and nkr Krilov vectors.
918 * Copied from Sch_Crank_Nicholson.cpp (scalar)//
919 *
920 */
921int Source_Con_Phase_field_Binaire_Compact::resolution_jfnk(const DoubleTab& c, const DoubleTab& mutilde, DoubleTab& c_demi, DoubleTab& mutilde_demi)
922{
923#ifdef PETSCKSP_H
924 if (with_petsc_ == 1)
925 return petsc_snes(c, mutilde, c_demi, mutilde_demi);
926 else if (with_petsc_ == 0)
927 {
928 int i, j, nk, i0, im, it, ii;
929 double tem = 1., res, ccos, ssin;
930 const int nb_elem_tot = c.size_totale();
931 double temps_exec = 0.;
932 int nfunc=0;
933 // statistiques().set_debug_level(9);
934
935 // Ajoute par DJ
936 //--------------
937 DoubleTrav x1(nb_elem_tot);
938
939 for (int n_elem = 0; n_elem < nb_elem_tot; n_elem++)
940 {
941 x1(n_elem) = c(n_elem);
942 }
943
944 DoubleTab v(nb_elem_tot, nkr_); // Krilov vectors
945 DoubleTab h(nkr_ + 1, nkr_); // Heisenberg maatrix of coefficients
946 DoubleVect r(nkr_ + 1);
947 DoubleTab v0(x1);
948 DoubleTab v1(x1);
949
950 // Initialisation
951 v = 0.;
952 v0 = 0.;
953 v1 = 0.;
954
955 // v0 = -1.*calculer_residu_jfnk(eqn, x1); // DJ
956
957 calculer_residu_jfnk(c, v0, x1);
958 nfunc++;
959 v0 *= -1.; // b - AX
960
961 res = 0.;
962 // Modifie par DJ
963 //---------------
964 for (ii = 0; ii < c.size(); ii++) // Partie c
965 res += v0(ii) * v0(ii);
966 for (ii = c.size_totale(); ii < c.size_totale() + c.size(); ii++) // Partie mutilde
967 res += v0(ii) * v0(ii);
968
969 res = mp_sum(res);
970 res = sqrt(res);
971
972 // Cout << "Premier vecteur v0 = " << v0 << finl;
973 Cout << "Norme du premier résidu = " << res << finl;
974
975 if (res < rtol_)
976 return 0; // nothing to do
977
978// rtol_ = (rtol_ < res * atol_) ? res * atol_ : rtol_;
979// rtol_ = (rtol_ < stol_) ? rtol_ : stol_;
980//
981// Cout << "Source Concentration Phase Field - JFNK" << finl;
982// Cout << "Stopping rule scalar : " << rtol_ << finl;
983
984 // iterations
985 for (it = 0; it < maxit_newton_; it++)
986 {
987 nk = nkr_;
988
989 //...Orthogonalisation of Arnoldi
990 v0 /= res;
991 r = 0.;
992 r[0] = res;
993 h = 0.;
994
995 for (j = 0; j < nkr_; j++)
996 {
997 for (ii = 0; ii < nb_elem_tot; ii++)
998 v(ii, j) = v0(ii);
999
1000 jacobian_vect(c, v0, x1, v1);
1001 nfunc++;
1002 nfunc++;
1003 v0 = v1;
1004
1005 // Modifie par DJ
1006 //---------------
1007 for (i = 0; i <= j; i++)
1008 {
1009 for (ii = 0; ii < c.size(); ii++)
1010 h(i, j) += v0(ii) * v(ii, i);
1011 for (ii = c.size_totale(); ii < c.size_totale() + c.size(); ii++)
1012 h(i, j) += v0(ii) * v(ii, i);
1013 h(i, j) = mp_sum(h(i, j));
1014
1015 for (ii = 0; ii < nb_elem_tot; ii++)
1016 v0(ii) -= h(i, j) * v(ii, i);
1017 }
1018 // tem = sqrt(v0 * v0);
1019 tem = 0.;
1020 // Modifie par DJ
1021 //---------------
1022 for (ii = 0; ii < c.size(); ii++)
1023 tem += v0(ii) * v0(ii);
1024 for (ii = c.size_totale(); ii < c.size_totale() + c.size(); ii++)
1025 tem += v0(ii) * v0(ii);
1026
1027 tem = mp_sum(tem);
1028 tem = sqrt(tem);
1029 h(j + 1, j) = tem;
1030 if (tem < rtol_)
1031 {
1032 nk = j + 1;
1033 goto l5;
1034 }
1035 v0 /= tem;
1036 }
1037
1038 //...Triangularisation QR de la matrice de Hessenberg
1039l5:
1040 for (i = 0; i < nk; i++)
1041 {
1042 im = i + 1;
1043 tem = 1. / sqrt(h(i, i) * h(i, i) + h(im, i) * h(im, i));
1044 ccos = h(i, i) * tem;
1045 ssin = -h(im, i) * tem;
1046 for (j = i; j < nk; j++)
1047 {
1048 tem = h(i, j);
1049 h(i, j) = ccos * tem - ssin * h(im, j);
1050 h(im, j) = ssin * tem + ccos * h(im, j);
1051 }
1052 r[im] = ssin * r[i];
1053 r[i] *= ccos;
1054 }
1055
1056 //...Solution of linear system
1057 for (i = nk - 1; i >= 0; i--)
1058 {
1059 r[i] /= h(i, i);
1060 for (i0 = i - 1; i0 >= 0; i0--)
1061 r[i0] -= h(i0, i) * r[i];
1062 }
1063 for (i = 0; i < nk; i++)
1064 for (ii = 0; ii < nb_elem_tot; ii++)
1065 x1(ii) += r[i] * v(ii, i);
1066
1067 if (mobilite_explicite_ == 0) /* implicite */
1068 {
1070 }
1071
1072 calculer_residu_jfnk(c, v0, x1);
1073 nfunc++;
1074 v0 *= -1.;
1075
1076 res = 0.;
1077 // Modifie par DJ
1078 //---------------
1079 for (ii = 0; ii < c.size(); ii++)
1080 res += v0(ii) * v0(ii);
1081 for (ii = c.size_totale(); ii < c.size_totale() + c.size(); ii++)
1082 res += v0(ii) * v0(ii);
1083
1084 res = mp_sum(res);
1085 res = sqrt(res);
1086
1087 Cout << " - At it = " << it << ", residu scalar = " << res << finl;
1088
1089 temps_exec = statistics().get_time_since_last_open(STD_COUNTERS::total_execution_time);
1090
1091 if (!Process::me())
1092 {
1093 SFichier fichier_residu("residu.txt", ios::app);
1094 fichier_residu << temps_exec << "\t" << equation().schema_temps().temps_courant() << "\t" << res << finl;
1095 }
1096
1097 if (res < rtol_ || it == maxit_newton_ - 1)
1098 {
1099 // Ajoute par DJ
1100 //--------------
1101 for (int n_elem = 0; n_elem < nb_elem_tot; n_elem++)
1102 {
1103 c_demi(n_elem) = x1(n_elem);
1104 }
1105
1106 DoubleTrav mu_temp(nb_elem_tot);
1107 DoubleTrav B_c_demi(nb_elem_tot);
1108 const Milieu_Phase_field& mil = ref_cast(Milieu_Phase_field, equation().milieu());
1109 const auto& fermeture = mil.get_fermeture();
1110
1111 for (int n_elem = 0; n_elem < nb_elem_tot; n_elem++)
1112 {
1113 mu_temp(n_elem) = fermeture.get_beta() * fermeture.call_dWdc(c_demi(n_elem));
1114 }
1115
1116 // On calcule H(c_demi) = c_demi + A ( B . c_demi - beta*dW/dc(c_demi) ) - c
1117 // Où A = matrice_kappa et B = matrice_alpha
1118
1119 // Calcul du produit matrice / vecteur B . c_demi, puis soustraction du vecteur beta*dW/dc
1120 matrice_alpha_.multvect_(c_demi, B_c_demi);
1121 for (int n_elem = 0; n_elem < nb_elem_tot; n_elem++)
1122 {
1123 mutilde_demi(n_elem) = mu_temp(n_elem) - B_c_demi(n_elem);
1124 }
1125 }
1126
1127 if (res < rtol_)
1128 {
1129 // L'echange espace virtuel est fait dans premier_demi_dt()
1130 Cout << "Number of iterations to reach convergence : " << it + 1 << finl;
1131 Cout << "" << finl;
1132
1133 return it;
1134 }
1135 else if (it == maxit_newton_ - 1)
1136 {
1137 Cout << "Stopped before convergence" << finl;
1138 Cout << "" << finl;
1139 }
1140 }
1141 if (!Process::me())
1142 {
1143 SFichier fichier_eval("eval.txt", ios::app);
1144 fichier_eval << equation().schema_temps().temps_courant() << "\t" << nfunc << finl;
1145 }
1146 }
1147 else
1148 {
1149 Cerr << "Error: Phase_field - Bad input for choosing between resolution with PETSc or not." << finl;
1150 Process::exit();
1151 }
1152#endif
1153 return -1;
1154
1155}
1156
1157/*! @brief Calcul de mutilde au centre des elements
1158 *
1159 * @param (mutilde) mutilde au centre des elements
1160 */
1162{
1163 const Convection_Diffusion_Phase_field& eq_c = ref_cast(Convection_Diffusion_Phase_field, pb_->equation(1));
1164 const DoubleTab& c = eq_c.inconnue().valeurs();
1165 const DoubleTab& div_alpha_gradC = eq_c.get_div_alpha_gradC();
1166 const Milieu_Phase_field& mil = ref_cast(Milieu_Phase_field, pb_->milieu());
1167 const auto& fermeture = mil.get_fermeture();
1168
1169 // Calcul de mutilde
1170
1171 mutilde = div_alpha_gradC;
1172 mutilde *= -1.;
1173
1174 //Cerr << "mutilde = -div_alpha_gradC " << mutilde << finl;
1175
1176 const int taille = mutilde.size();
1177 for (int i = 0; i < taille; i++)
1178 {
1179 mutilde(i) += fermeture.get_beta() * fermeture.call_dWdc(c(i));
1180 if (mutype_ == 1) //avec Ec
1181 mutilde(i) += (0.5 * u_carre_(i)) * drhodc(i);
1182 }
1183
1184// L'espace virtuel n'est pas a jour
1185 assert_invalide_items_non_calcules(mutilde);
1186
1187}
1188
1189void Source_Con_Phase_field_Binaire_Compact::calculer_mutilde_demi(DoubleTab& mutilde_demi, DoubleTab& c_demi) const
1190{
1191 const Convection_Diffusion_Phase_field& eq_c = ref_cast(Convection_Diffusion_Phase_field, pb_->equation(1));
1192 const Navier_Stokes_std& eq_ns = ref_cast(Navier_Stokes_std, pb_->equation(0));
1193 const Operateur_Grad& opgrad = eq_ns.operateur_gradient();
1194 const Operateur_Div& opdiv = eq_ns.operateur_divergence();
1195 const Milieu_Phase_field& mil = ref_cast(Milieu_Phase_field, pb_->milieu());
1196 const auto& fermeture = mil.get_fermeture();
1197
1198 mutilde_demi = 0.;
1199
1200 DoubleTab& prov_face = ref_cast_non_const(DoubleTab, prov_face_);
1201 if (prov_face.size() == 0)
1202 prov_face = eq_ns.inconnue().valeurs();
1203 prov_face = 0.;
1204
1205 // Grad(C)
1206 opgrad.calculer(c_demi, prov_face);
1207 eq_ns.solv_masse().appliquer(prov_face);
1208 prov_face *= fermeture.get_alpha();
1209
1210 // Div(alpha*Grad(c))
1211 opdiv.calculer(prov_face, mutilde_demi);
1212 eq_c.solv_masse().appliquer(mutilde_demi);
1213 //Cerr <<"div_alpha_gradC"<<div_alpha_gradC<<finl;
1214
1215 mutilde_demi *= -1.;
1216
1217 const int taille = mutilde_demi.size();
1218 for (int i = 0; i < taille; i++)
1219 {
1220 mutilde_demi(i) += fermeture.get_beta() * fermeture.call_dWdc(c_demi(i));
1221 if (mutype_ == 1) //avec Ec
1222 {
1223 mutilde_demi(i) += (0.5 * u_carre_(i)) * drhodc(i);
1224 }
1225 }
1226
1227// L'espace virtuel n'est pas a jour
1228 assert_invalide_items_non_calcules(mutilde_demi);
1229}
1230
DoubleTab & valeurs() override
Surcharge Champ_base::valeurs() Renvoie le tableau des valeurs.
DoubleTab & valeurs() override
Renvoie le tableau des valeurs du champ au temps courant.
const Champ_Inc_base & inconnue() const override
Renvoie le champ inconnue de l'equation: la concentration.
classe Convection_Diffusion_Phase_field Cas particulier de Convection_Diffusion_Concentration
const Milieu_base & milieu() const override
Renvoie le milieu physique de l'equation.
class Domaine_VDF
Definition Domaine_VDF.h:64
int nb_faces() const
renvoie le nombre global de faces.
Definition Domaine_VF.h:471
double volumes(int i) const
Definition Domaine_VF.h:113
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
int nb_elem_tot() const
Une entree dont la source est une chaine de caracteres.
Definition EChaine.h:31
Class defining operators and methods for all reading operation in an input flow (file,...
Definition Entree.h:42
classe Equation_base Le role d'une equation est le calcul d'un ou plusieurs champs....
Sources & sources()
Renvoie les termes sources asssocies a l'equation.
Solveur_Masse_base & solv_masse()
Renvoie le solveur de masse associe a l'equation.
virtual Domaine_Cl_dis_base & domaine_Cl_dis()
Renvoie le domaine des conditions aux limite discretisee associee a l'equation.
Schema_Temps_base & schema_temps()
Renvoie le schema en temps associe a l'equation.
double call_kappa_func_c(const double d) const
void nommer(const Nom &) override
Donne un nom au champ.
virtual DoubleVect & multvect_(const DoubleVect &, DoubleVect &) const
const Champ_Don_base & rho() const
const Fermeture_Phase_field_base & get_fermeture() const
const Equation_base & equation() const
Renvoie la reference sur l'equation pointe par MorEqn::mon_equation.
Definition MorEqn.h:62
classe Navier_Stokes_phase_field Cette classe porte les termes de l'equation de la dynamique
classe Navier_Stokes_std Cette classe porte les termes de l'equation de la dynamique
const Champ_Inc_base & inconnue() const override
Renvoie la vitesse (champ inconnue de l'equation) (version const).
Operateur_Div & operateur_divergence()
Renvoie l'operateur de calcul de la divergence associe a l'equation.
Operateur_Grad & operateur_gradient()
Renvoie l'operateur de calcul du gradient associe a l'equation.
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 Operateur_Div Classe generique de la hierarchie des operateurs calculant la divergence
DoubleTab & calculer(const DoubleTab &, DoubleTab &) const override
Initialise le tableau passe en parametre avec la contribution de l'operateur.
Classe Operateur_Grad Classe generique de la hierarchie des operateurs calculant le gradient.
DoubleTab & calculer(const DoubleTab &, DoubleTab &) const override
Initialise le tableau passe en parametre avec la contribution de l'operateur.
static double mp_sum(double)
Calcule la somme de x sur tous les processeurs du groupe courant.
Definition Process.cpp:146
static int me()
renvoie mon rang dans le groupe de communication courant.
Definition Process.cpp:125
static void exit(int exit_code=-1)
Routine de sortie de TRUST dans une region Kokkos.
Definition Process.cpp:455
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
double temps_courant() const
Renvoie le temps courant.
double pas_de_temps() const
Renvoie le pas de temps (delta_t) courant.
virtual DoubleTab & appliquer(DoubleTab &) const
renvoie appliquer_impl(x/coeffient_temporelle) si on a un coefficient temporel sinon renvoie applique...
Classe de base des flux de sortie.
Definition Sortie.h:52
void calculer_div_alpha_rho_grad(const DoubleTab &, DoubleTab &) const
Calcul de Div(alpha*rho*Grad((C)) au centre des elements.
void calculer_mutilde(DoubleTab &) const
Calcul de mutilde au centre des elements.
void calculer_div_alpha_grad(const DoubleTab &, DoubleTab &) const
Calcul de Div(alpha*rho*Grad((C)) au centre des elements.
int petsc_snes(const DoubleTab &, const DoubleTab &, DoubleTab &, DoubleTab &)
void premier_demi_dt() override
Calcule le premier demi pas de temps dans le cas implicite Calcule le pas de temps dans le cas explic...
DoubleTab & div_kappa_grad(const DoubleTab &, const DoubleTab &, DoubleTab &) const
DoubleTab & laplacien(const DoubleTab &, DoubleTab &) const
void jacobian_vect(const DoubleTab &, const DoubleTab &, const DoubleTab &, DoubleTab &)
Construire la jacobienne multipliée par un vecteur Y.
int resolution_jfnk(const DoubleTab &, const DoubleTab &, DoubleTab &, DoubleTab &)
Algorithme JFNK (ancienne version de D. Jamet et nouvelle version de PETSc).
void calculer_residu_jfnk(const DoubleTab &, DoubleTab &, const DoubleTab &)
Construire le residu du JFNK.
virtual void calculer_u2_elem(DoubleVect &)
double drhodc(const int n_elem) const
_SIZE_ dimension_tot(int) const override
Definition TRUSTTab.tpp:160
_SIZE_ size() const
Definition TRUSTVect.tpp:45
_SIZE_ size_totale() const
Definition TRUSTVect.tpp:61
virtual void echange_espace_virtuel(IsExchangeBlocking exchange_type=IsExchangeBlocking::DefaultBlocking, const std::string kernel_name="noname")