TrioCFD 1.9.8
TrioCFD documentation
Loading...
Searching...
No Matches
Cahn_Hilliard.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 <Cahn_Hilliard.h>
17#include <Schema_Cahn_Hilliard.h>
18#include <Discretisation_base.h>
19#include <Domaine_VDF.h>
20#include <Discret_Thyd.h>
21#include <Probleme_base.h>
22#include <Cond_lim_base.h>
23#include <Cond_lim.h>
24#include <Champ_front_uniforme.h>
25#include <CL_Types_include.h>
26#include <Courant_impose.h>
27#include <EChaine.h>
28#include <Avanc.h>
29#include <Debog.h>
30#include <TRUST_2_PDI.h>
31#include <Milieu_Incompressible_Phase_Field.h>
32
33Implemente_instanciable(Cahn_Hilliard,"Cahn_Hilliard",Equation_base);
34
36{
37 os << le_dom_Cl_dis_mutilde_ << finl;
38 os << mutilde_ << finl;
40 os << " -- mobilite explicite = TRUE " << finl;
41 else
42 os << " -- mobilite explicite = FALSE " << finl;
43 return Equation_base::printOn(os);
44}
45
47{
49
50 // Ici on peut rajouter des set_fichier(...) pour sortir les valeurs des termes diffusifs de l'équation
51// terme_mobilite_.set_fichier("Convection_Cahn_Hilliard");
52// terme_mobilite_.set_description("Momentum flow rate [N] if SI units used");
53
54 // XXX HYPER IMPORTANT : On fixe set_diffusion_multiscalaire à TRUE
56 Cerr << "EQUATION CAHN HILLIARD : Setting multiscalar boolean to TRUE." << finl;
57
58 return is;
59
60}
61
63{
65 // Spécifiques à l'équation de Cahn-Hilliard :
66 param.ajouter_flag("mobilite_explicite",&mobilite_explicite_);
67 param.ajouter_flag("passer_par_ajouter_kappa",&passer_par_ajouter_kappa_);
68 param.ajouter_flag("passer_par_ajouter_mobilite",&passer_par_ajouter_mobilite_);
69 param.ajouter_non_std("conditions_limites_potentiel|boundary_conditions_potential",(this),Param::REQUIRED);
70}
71
73{
74 if (mot=="conditions_limites_potentiel|boundary_conditions_potential")
75 {
78 return 1;
79 }
80 else
82}
83
84/*! @brief Lecture des conditions limites sur un flot d'entree.
85 *
86 * voir Domaine_Cl_dis_base::readOn
87 *
88 * @param (Entree& is) le flot d'entree
89 * @return (Entree&) le flot d'entree modifie
90 * @throws le domaine des conditions aux limites discretisee est vide
91 */
93{
94 Cerr << "Reading of boundaries conditions on chemical potential \n";
95 if(!le_dom_Cl_dis_mutilde_)
96 {
97 Cerr << "Error while reading boundaries conditions : " <<
98 que_suis_je() << finl;
99 Cerr << "The Domaine_Cl_dis_base corresponding to mutilde is empty ..." << finl;
100 exit();
101 }
102 is >> le_dom_Cl_dis_mutilde_.valeur();
103 return is;
104}
105
106
107/*! @brief Renvoie le nombre d'operateurs de l'equation: Pour Cahn-Hilliard c'est 2.
108 *
109 * @return (int) le nombre d'operateur de l'equation
110 */
112{
113 return 2;
114}
115
120
121/*! @brief Renvoie le i-eme operateur de l'equation:
122 *
123 * @param (int i) l'index de l'operateur a renvoyer
124 * @return (Operateur&) l'operateur indexe par i
125 */
127{
128 switch(i)
129 {
130 case 0:
131 return terme_mobilite_;
132 case 1:
133 return terme_kappa_;
134 default :
135 Cerr << "Error for Cahn_Hilliard::operateur(int i)" << finl;
136 Cerr << "Cahn_Hilliard has " << nombre_d_operateurs() <<" operators "<<finl;
137 Cerr << "and you are trying to access the " << i <<" th one."<< finl;
138 exit();
139 }
140 // Pour les compilos!!
141 return terme_mobilite_;
142}
143
144/*! @brief Renvoie le i-eme operateur de l'equation:
145 * @param (int i) l'index de l'operateur a renvoyer
146 * @return (Operateur&) l'operateur indexe par i
147 */
149{
150 switch(i)
151 {
152 case 0:
153 return terme_mobilite_;
154 case 1:
155 return terme_kappa_;
156 default :
157 Cerr << "Error for Cahn_Hilliard::operateur(int i)" << finl;
158 Cerr << "Cahn_Hilliard has " << nombre_d_operateurs() <<" operators "<<finl;
159 Cerr << "and you are trying to access the " << i <<" th one."<< finl;
160 exit();
161 }
162 // Pour les compilos!!
163 return terme_mobilite_;
164}
165
166/*! @brief Renvoie le nom du domaine d'application: "Cahn_Hilliard".
167 *
168 * @return (Motcle&) lenom representant le domaine d'application
169 */
171{
172 static Motcle domaine = "Cahn_Hilliard";
173 return domaine;
174}
175
176/*! @brief Renvoie la concentration (champ inconnue de l'equation) (version const)
177 *
178 * @return (Champ_Inc_base&) le champ inconnue representant la concentration
179 */
181{
182 return concentration_.valeur();
183}
184
185/*! @brief Renvoie la concentration (champ inconnue de l'equation)
186 *
187 * @return (Champ_Inc_base&) le champ inconnue representant la concentration
188 */
190{
191 return concentration_.valeur();
192}
193
194/*! @brief S'associe au probleme: apelle Equation_base::associer_pb_base(const Probleme_base&)
195 * les deux termes diffusifs doivent aussi être initialisés puisqu'ils ne sont pas lus dans le JDD
196 * @param (Probleme_base& pb) le probleme auquel s'associer
197 */
202
203/*! @brief Associe un mileu physique a l'equation en construisant dynamiquement (cast) un objet de type Milieu_Incompressible_Phase_Field
204 *
205 * a partir de l'objet Milieu_base passe en parametre.
206 *
207 * @param (Milieu_base& un_milieu) le milieu a associer a l'equation
208 */
210{
211 if (sub_type(Milieu_Incompressible_Phase_Field, un_milieu))
212 {
213 const Milieu_Incompressible_Phase_Field& un_fluide_ch = ref_cast(Milieu_Incompressible_Phase_Field,un_milieu);
214 milieu_ = un_fluide_ch;
215 fermeture_ = un_fluide_ch.fermeture();
216 }
217 else
218 {
219 Cerr << "Error of medium type for the method Cahn_Hilliard::associer_milieu_base." << finl;
220 Cerr << "You have to implement a new compatible kind of Milieu_base." << finl;
221 exit();
222 }
223}
224
225/*! @brief Renvoie le milieu physique de l'equation
226 *
227 * @return (Milieu_base&) Le milieu
228 */
230{
231 if (!milieu_)
232 {
233 Cerr << "You forgot to associate a phase-field medium to the problem named " << probleme().le_nom() << finl;
235 }
236 return milieu_.valeur();
237}
238
239/*! @brief Renvoie le milieu physique de l'equation
240 *
241 * @return (Milieu_base&) Le milieu
242 */
244{
245 if (!milieu_)
246 {
247 Cerr << "You forgot to associate a phase-field medium to the problem named " << probleme().le_nom() << finl;
249 }
250 return milieu_.valeur();
251}
252
253/*! @brief Dicretise l'equation.
254 *
255 */
257{
258 Cerr << "!! WARNING !! : for now, equation discretization (Cahn_Hilliard::discretiser) is only for hydraulic problems." << finl;
259
260 // C'est ici qu'est initialisé le nombre de paramètres d'ordre par rapport aux fermeture du système
262 Cerr << "Number of components for each field = " << nb_parametres_d_ordre_ << finl;
263
264 // Discretiser la concentration
266 champs_compris_.ajoute_champ(concentration_);
267
268 // Discretiser mutilde
270 champs_compris_.ajoute_champ(mutilde_);
271
272 if (!kappa_)
274 champs_compris_.ajoute_champ(kappa_);
275
276 if (!mobilite_)
278 champs_compris_.ajoute_champ(mobilite_);
279
280 Cerr << "Discretizing of the boundary conditions of mutilde... ";
281 le_dom_Cl_dis_mutilde_.typer(discretisation().domaine_cl_dis_type());
282 le_dom_Cl_dis_mutilde_->associer(domaine_dis());
283 Cerr << " OK " << finl;
284
285 le_dom_Cl_dis_mutilde_->associer_eqn(*this);
286 le_dom_Cl_dis_mutilde_->associer_inconnue(mutilde_);
287
289
290}
291
293{
294 const Discret_Thyd& dis=ref_cast(Discret_Thyd, discretisation());
295 // Le nombre de paramètres d'ordre définit le nombre de composantes des champs vectoriels d'inconnues
296 Cerr << "Concentration discretization... " << finl;
297 // Remarque : je ne passe pas par la méthode "concentration" de Discret_Thyd
298 dis.discretiser_champ("champ_elem", domaine_dis(), "concentration", ".", nb_parametres_d_ordre_, schema_temps().nb_valeurs_temporelles(), schema_temps().temps_courant(), concentration_);
299 concentration_->nommer("concentration");
300 concentration_->fixer_nature_du_champ(multi_scalaire); // Important !
301
302}
303
305{
306 const Discret_Thyd& dis=ref_cast(Discret_Thyd, discretisation());
307 Cerr << "Mutilde discretization... " << finl;
308 // On force mutilde à n'avoir qu'une valeur temporelle (pas besoin de passé et futur)
309 // Ça reste un Champ_Inc car il est associé à un opérateur de diffusion
310 dis.discretiser_champ("champ_elem", domaine_dis(), "potentiel_chimique_generalise", ".", nb_parametres_d_ordre_, 1, schema_temps().temps_courant(), mutilde_);
311 mutilde_->nommer("potentiel_chimique_generalise");
312 mutilde_->fixer_nature_du_champ(multi_scalaire); // Important !
313
314}
315
317{
318 const Discret_Thyd& dis=ref_cast(Discret_Thyd, discretisation());
319 Cerr << "Kappa discretization... " << finl;
320 // Autre possibilité : "Champ_sommets"
322 kappa_->nommer("capillarite");
323 kappa_->fixer_nature_du_champ(multi_scalaire); // Important !
324
325}
326
327
329{
330 const Discret_Thyd& dis=ref_cast(Discret_Thyd, discretisation());
331 Cerr << "Mobility discretization... " << finl;
332 dis.discretiser_champ("champ_elem",domaine_dis(),"mobilite",".",nb_parametres_d_ordre_*nb_parametres_d_ordre_,0.,mobilite_);
333 mobilite_->nommer("mobilite");
334 mobilite_->fixer_nature_du_champ(multi_scalaire); // Important !
335
336}
337
339{
340 // Cerr << "Kappa field is built..." << finl;
341 // Cerr << "Dimension of Kappa = " << kappa_->valeurs().dimension(0) << " x " << kappa_->valeurs().dimension(1) << finl;
342 for (int x = 0; x < domaine_dis().nb_elem(); x++)
343 for (int j = 0; j < nb_parametres_d_ordre_*nb_parametres_d_ordre_; j++)
344 kappa_->valeurs()(x, j) = fermeture().kappa()(j);
345
346 kappa_->valeurs().echange_espace_virtuel();
347 // Cerr << "Kappa field well computed !" << finl;
348}
349
351{
352 DoubleTrav result_mob = fermeture().mobilite(c);
353 result_mob = fermeture().mobilite(c);
354 for (int x = 0; x < domaine_dis().nb_elem(); x++)
355 for (int j = 0; j < nb_parametres_d_ordre_*nb_parametres_d_ordre_; j++)
356 mobilite_->valeurs()(x,j) = result_mob(x,j);
357
358 mobilite_->valeurs().echange_espace_virtuel();
359}
360
362{
363 // Opérateur 1 : mobilité
364 terme_mobilite_.associer_eqn(*this);
365 terme_mobilite_.associer_diffusivite(mobilite_);
366
367 Cerr << "[COMPLETER()] Typing of the diffusion operator of mobility... " << finl;
368 // Manière adhoc de lire le type d'opérateur de diffusion (soit { } soit { negligeable }
369 EChaine diff("{ }");
370 diff >> terme_mobilite_;
371
372 terme_mobilite_.associer_diffusivite_pour_pas_de_temps(mobilite_);
373 // XXX Luis : ATTENTION, big probleme quand on associe un champ avec un nom différent de l'inconnue de l'équation
374 // Plus tard il faut utiliser ajouter_blocs et non pas contribuer_a_avec, ni calculer
375 terme_mobilite_.associer_champ(mutilde_,"potentiel_chimique_generalise");
376
377}
378
380{
381 // Opérateur 2 : capillarité
382 terme_kappa_.associer_eqn(*this);
383 terme_kappa_.associer_diffusivite(kappa_);
384
385 Cerr << "[COMPLETER()] Typing of the diffusion operator of capillarity... " << finl;
386 EChaine diff2("{ }");
387 diff2 >> terme_kappa_;
388
389 terme_kappa_.associer_diffusivite_pour_pas_de_temps(kappa_);
390 terme_kappa_.associer_champ(concentration_,"concentration");
391}
392
393/*! @brief Complete l'equation base, associe le potentiel chimique généralisé a l'equation,
394 * initialise le vecteur résidu et construit les opérateurs de diffusion.
395 */
397{
398 // On bypass la méthode completer de Equation_base
399 Cerr << "####### CAHN_HILLIARD::COMPLETER() ########" << finl;
400
401 inconnue().associer_eqn(*this);
402 inconnue().completer(le_dom_Cl_dis.valeur());
403
404 // CL sur la concentration
405 if (le_dom_Cl_dis)
406 le_dom_Cl_dis->completer();
407
408 mutilde_->associer_eqn(*this);
409 mutilde_->completer(le_dom_Cl_dis_mutilde_.valeur());
410
411 // CL sur mutilde
412 if (le_dom_Cl_dis_mutilde_)
413 le_dom_Cl_dis_mutilde_->completer();
414
415 // Association du champ d'inconnue (concentration) à son domaine
416 inconnue().associer_domaine_cl_dis(le_dom_Cl_dis);
417 Cerr << "[COMPLETER()] The unknown field c is associated to boundary conditions." << finl;
418
419 // Association du champ mutilde à son domaine
420 mutilde_->associer_domaine_cl_dis(le_dom_Cl_dis_mutilde_);
421 Cerr << "[COMPLETER()] The potential field mutilde is associated to boundary conditions." << finl;
422
423 if (mon_probleme->is_coupled())
424 {
425 Cerr << "Cahn_Hilliard :: Coupled problem not coded..." << finl;
426 exit();
427 }
428
429 //Ajout d un element vide qui sera renvoye si pas de modele trouve
430 RefObjU mod;
431 if (liste_modeles_.size()==0)
432 liste_modeles_.add(mod);
433
434
435 Debog::verifier("Cahn_Hilliard::completer() avant concentration ", concentration_->valeurs());
436 Debog::verifier("Cahn_Hilliard::completer() avant mobilite ", mobilite_->valeurs());
437 Debog::verifier("Cahn_Hilliard::completer() avant kappa ", kappa_->valeurs());
438
439 Cerr << "Mobility field is built..." << finl;
440 construire_mobilite(concentration_->valeurs()); // Construit le CHAMP de mobilité
441 Cerr << "Mobility field well computed !" << finl;
442 Cerr << "Kappa field is built..." << finl;
443 construire_kappa(); // Construit le CHAMP de kappa
444 Cerr << "Kappa field well computed !" << finl;
445
448
449 Debog::verifier("Cahn_Hilliard::completer() apres concentration ", concentration_->valeurs());
450 Debog::verifier("Cahn_Hilliard::completer() apres mobilite ", mobilite_->valeurs());
451 Debog::verifier("Cahn_Hilliard::completer() apres kappa ", kappa_->valeurs());
452
453
454 // CE QU'IL Y A DANS COMPLETER DE OPERATEUR_BASE
455 // On decline le residu par composante, qui correspondent au nombre de paramètres d'ordre (et donc d'équations de Cahn-Hilliard)
457 int nb_op=nombre_d_operateurs();
458 Cerr << "Number of operators = " << nb_op << finl;
459 Nom msg="Equation_base::completer(), nb_op = " ;
460 Debog::verifier(msg, nb_op);
461 for(int i=0; i<nb_op; i++)
462 operateur(i).completer();
463
464 if (solveur_masse)
466
467 les_sources.completer();
469
470// Schema_Cahn_Hilliard schee = ref_cast(Schema_Cahn_Hilliard,schema_temps());
471// if (abs(schee.coeff_theta()) < 1.e-12)
472 implicite_=0;
473// else
474// implicite_=1;
475
476}
477
478/*! @brief cf Equation_base::preparer_calcul()
479 *
480 * @return (int) renvoie toujours 1
481 */
483{
484 const double temps = schema_temps().temps_courant();
486 sources().mettre_a_jour(temps);
487
489 mutilde().changer_temps(temps);
490 le_dom_Cl_dis_mutilde_->initialiser(temps);
491
494
495 le_dom_Cl_dis->mettre_a_jour(temps);
496 le_dom_Cl_dis_mutilde_->mettre_a_jour(temps);
497
498 // Mise a jour mutilde
499 mutilde_->changer_temps(temps);
500
501 Debog::verifier("Cahn_Hilliard::preparer_calcul, concentration", inconnue());
502 Debog::verifier("Cahn_Hilliard::preparer_calcul, mutilde", mutilde());
503
504 return 1;
505}
506
512
513/* @brief Override. Reset mutilde too !
514 */
516{
517 mutilde().resetTime(time);
520}
521
523{
524
525 const Schema_Temps_base& sch_tps = le_schema_en_temps.valeur();
526
527 for (int i=1; i<=sch_tps.nb_valeurs_futures(); i++)
528 if (i <= mutilde().nb_valeurs_temporelles())
529 {
530 double tps=sch_tps.temps_futur(i);
531 // Mise a jour du temps dans les champs de potentiel chimique
533 mutilde().futur(i)=mutilde().valeurs();
534 // Mise a jour du temps dans les CL
536 }
537
538 // Mise a jour du temps par defaut des CLs
540
541 bool ddt = Equation_base::initTimeStep(dt);
542
543 return ddt;
544}
545
546/*! @brief cf Equation_base::updateGivenFields()
547 *
548 * On rajoute ici les mises à jour des CL sur mutilde. Utile ? Je ne sais pas.
549 */
551{
553 double temps_present=sch.temps_courant();
554 double temps_futur=temps_present+sch.pas_de_temps();
555
556 // Pour chaque temps futur
557 for (int i=1; i<=sch.nb_valeurs_futures(); i++)
558 {
559 double tps=sch.temps_futur(i);
560 // Calcul des CLs a ce temps.
562 }
563 // Calcul du taux d'accroissement des CLs entre les temps present et futur.
564 domaine_Cl_dis_mutilde().calculer_derivee_en_temps(temps_present,temps_futur);
565
567}
568
569/*! @brief for PDI IO: retrieve name, type and dimensions of the fields to save/restore
570 *
571 */
572std::vector<YAML_data> Cahn_Hilliard::data_a_sauvegarder() const
573{
574 std::vector<YAML_data> data = Equation_base::data_a_sauvegarder();
575 std::vector<YAML_data> mutilde_sauv = mutilde_->data_a_sauvegarder();
576 data.insert(data.end(), mutilde_sauv.begin(), mutilde_sauv.end());
577 return data;
578}
579
580/*! @brief Appelle Equation_base::sauvegarder(Sortie&) et sauvegarde le potentiel chimique sur un flot de sortie.
581 *
582 * @param (Sortie& os) un flot de sortie sur lequel sauvegarder
583 * @return (int) renvoie toujours 1
584 */
586{
587 int bytes=0;
588 bytes += Equation_base::sauvegarder(os);
589 bytes += mutilde_->sauvegarder(os);
590 return bytes;
591}
592
593/*! @brief Effectue une reprise a partir d'un flot d'entree.
594 *
595 * Appelle Equation_base::reprendre()
596 * et reprend mutilde.
597 *
598 * @param (Entree& is) un flot d'entree
599 * @return (int) renvoie toujours 1
600 * @throws la reprise a echoue, identificateur du potentiel chimique non trouve
601 */
603{
606 {
607 double temps = schema_temps().temps_courant();
608 Nom ident_mutilde(mutilde_->le_nom());
609 ident_mutilde += mutilde_->que_suis_je();
610 ident_mutilde += probleme().domaine().le_nom();
611 ident_mutilde += Nom(temps,probleme().reprise_format_temps());
612 avancer_fichier(is, ident_mutilde);
613 }
614 mutilde_->reprendre(is);
615
616 return 1;
617}
618
619/*! @brief S'associe au schema_en_temps : peut seulement être Schema_CH_Semi_Implicite
620 * pour l'instant.
621 * @param (Schema_Temps_base& un_schema_en_temps) le schema en temps a associer a l'equation
622 */
624{
625 if (sub_type(Schema_Cahn_Hilliard,un_schema_en_temps))
626 {
627 le_schema_en_temps=un_schema_en_temps;
628 }
629 else
630 {
631 Cerr << "Error : " << que_suis_je()
632 << " cannot support other time scheme than Schema_Cahn_Hilliard." << finl;
633 exit();
634 }
635}
636
637/*! @brief Effectue une mise a jour en temps de l'equation.
638 *
639 * Appelle Equation_base::mettre_a_jour(double)
640 * et met a jour le potentiel chimique généralisé.
641 *
642 * @param (double temps) le temps de mise a jour
643 */
645{
646 // Mise a jour de la classe mere (on tourne la roue).
648
649 // Mise a jour de mutilde
650 mutilde_->mettre_a_jour(temps);
651 // Mise a jour conditions limites de mutilde
652 if (temps > schema_temps().temps_courant()) domaine_Cl_dis_mutilde().avancer(temps);
653}
654
655/*! @brief Calcul du prochain pas de temps.
656 *
657 * Luis : Pour l'instant, dt = dt_min, je ne sais pas quel est le pas de temps optimal pour l'équation de Cahn-Hilliard
658 *
659 * @return (double)
660 */
662{
663 // On peut chercher à augmenter le pas de temps en fonction de la norme |c^n+1 - c^n| qui indique si on atteint un niveau stationnaire
664 // Mais attention, il peut se passer des mécanismes rapides même après une évolution très lente...
665 // On reste sur dt_max pour l'instant
666 return le_schema_en_temps->pas_temps_max();
667}
668
669/*! @brief Returns the time derivative of the unknown I of the equation: dI/dt = M-1*(sum(operators(I) + sources))
670 *
671 * In : derivee contains I (but immediatly set to 0)
672 * Out: derivee contains dI/dt
673 *
674 */
675DoubleTab& Cahn_Hilliard::derivee_en_temps_inco(DoubleTab& derivee)
676{
677 derivee = 0.;
678
679 DoubleTrav secmem(derivee);
680 // secmem = sum(operators) + sources + equation specific terms
681
682 if (implicite_==0)
683 {
684 // On cherche à construire : dc/dt = M-1 * (D mutilde^n)
685 // avec mutilde^n = beta*dW/dc^n - Kc^n
686 // où D est la matrice de l'opérateur lié à mu (terme_mobilite_)
687 // et K est la matirce de l'opérateur lié à kappa (terme_kappa_)
688
689 // On calcule d'abord mutilde^n = beta*dW/dc^n - Kc^n (fonction compute_mutilde)
691 // Ici normalement les valeurs de mutilde (qui est l'inconnue de l'opérateur 0) sont mises à jour
692 operateur(0).calculer(secmem); // secmem = D mutilde^n
693 les_sources.ajouter(secmem); // secmem += sources
694 solveur_masse->appliquer(secmem); // M-1 * secmem
695 derivee = secmem;
696 derivee.echange_espace_virtuel();
697
698 }
699 else if (implicite_>0)
700 {
701// // En implicite
702// // M dc/dt + D*mutilde^# = f;
703// // où # désigne le temps futur (souvent n+1)
704// // On va d'abord construire la fonction de forme :
705// // H(c) = c^# - c^n - dt * M_c^-1 * D * (M_mu^-1 K c^# + dW/dc^#)
706// // Puis résoudre le problème non linéaire par méthode de Newton : H(c^#) = 0
707// // Enfin, dc/dt = (c^# - c^n) / dt
708// double dt=schema_temps().pas_de_temps();
709//
710// // On stocke les valeurs du temps présent dans le tableau du temps passé
711// concentration_->passe() = concentration_->valeurs();
712// compute_mutilde();
713// mutilde_->passe() = mutilde_->valeurs();
714//
715// derivee-=concentration_->passe();
716// derivee/=dt;
717 Cerr << "[Cahn_Hilliard] Warning: Be careful with implicit part in derivative computation." << finl;
719 }
720 else
721 {
722 Cerr << "Error in Cahn_Hilliard::derivee_en_temps_inco" << finl;
723 Cerr << "implicite_ = " << implicite_ << " has not been initialized!" << finl;
724 Cerr << "May be " << que_suis_je() << "::completer() method doesn't call Cahn_Hilliard::completer()" << finl;
726 }
727
728 return derivee;
729}
730
731/*! @brief Calcul de mutilde = beta*dW/dc - ∇. kappa ∇c
732 */
734{
735 Debog::verifier("Cahn_Hilliard::compute_mutilde() avant mutilde_ ", mutilde_->valeurs());
736 Debog::verifier("Cahn_Hilliard::compute_mutilde() avant concentration_ ", concentration_->valeurs());
737
738 DoubleTrav terme_non_lin(concentration_->valeurs());
739
740 const int nb_elem = terme_non_lin.dimension(0); // reel
741 const int nb_param = terme_non_lin.line_size();
742
744 {
745 // operateur(1) = l'opérateur de diffusion lié à kappa
746 // calculer renvoie : mutilde = CL(c) - K*c
747 operateur(1).calculer(mutilde_->valeurs());
748
749 // Division par le volume des voxels
750 tab_divide_any_shape(mutilde_->valeurs(), ref_cast(Domaine_VF,domaine_dis()).volumes());
751
752 // On ajoute la partie liée au potentiel chimique
753 terme_non_lin = fermeture().potentiel_chimique().dWdc(concentration_->valeurs());
754
755 for (int elem = 0; elem < nb_elem; elem++)
756 for (int p = 0; p < nb_param; p++)
757 {
758 terme_non_lin(elem,p) *= fermeture().beta()(p);
759 mutilde_->valeurs()(elem,p) = terme_non_lin(elem,p) - mutilde_->valeurs()(elem,p);
760 }
761 }
762 else // On ne passe pas par la méthode ajouter() de l'opérateur, mais par un produit matrice-vecteur
763 {
764 DoubleTrav second_terme(concentration_->valeurs());
765
766 terme_non_lin = fermeture().potentiel_chimique().dWdc(concentration_->valeurs());
767
768 // Calcul du produit matrice / vecteur utilise
769 mat_kappa_.multvect_(concentration_->valeurs(), second_terme);
770
771 for (int elem = 0; elem < nb_elem; elem++)
772 for (int p = 0; p < nb_param; p++)
773 {
774 terme_non_lin(elem,p) *= fermeture().beta()(p);
775 // Attention au signe devant le terme K.c
776 mutilde_->valeurs()(elem,p) = terme_non_lin(elem,p) + second_terme(elem,p) - contribution_CL_concentration_(elem,p);
777 }
778 }
779
780 mutilde_->valeurs().echange_espace_virtuel();
781 Debog::verifier("Cahn_Hilliard::compute_mutilde() apres mutilde_ ", mutilde_->valeurs());
782 Debog::verifier("Cahn_Hilliard::compute_mutilde() apres concentration_ ", concentration_->valeurs());
783}
784
785
786/*! @brief Calcul de mutilde = beta*dW/dc - ∇. kappa ∇c
787 * Stockage dans un autre vecteur
788 */
789DoubleTab Cahn_Hilliard::compute_mutilde(const DoubleTab& c)
790{
791 Debog::verifier("Cahn_Hilliard::compute_mutilde_tab() avant mutilde_ ", mutilde_->valeurs());
792 DoubleTrav terme_non_lin(concentration_->valeurs());
793
794 const int nb_elem = terme_non_lin.dimension(0); // reel
795 const int nb_param = terme_non_lin.line_size();
796
797 DoubleTrav muti(concentration_->valeurs());
798
800 {
801 // operateur(1) = l'opérateur de diffusion lié à kappa
802 // calculer renvoie : mutilde = CL(c) - K*c
803 operateur(1).calculer(c,muti);
804
805 // Division par le volume des voxels
806 tab_divide_any_shape(muti, ref_cast(Domaine_VF,domaine_dis()).volumes());
807
808 // On ajoute la partie liée au potentiel chimique
809 terme_non_lin = fermeture().potentiel_chimique().dWdc(c);
810
811 for (int elem = 0; elem < nb_elem; elem++)
812 for (int p = 0; p < nb_param; p++)
813 {
814 terme_non_lin(elem,p) *= fermeture().beta()(p);
815 muti(elem,p) = terme_non_lin(elem,p) - muti(elem,p);
816 }
817 }
818 else // On ne passe pas par la méthode ajouter() de l'opérateur, mais par un produit matrice-vecteur
819 {
820 DoubleTrav second_terme(concentration_->valeurs()) ;
821
822 terme_non_lin = fermeture().potentiel_chimique().dWdc(c);
823
824 // Calcul du produit matrice / vecteur utilise
825 mat_kappa_.multvect_(c, second_terme);
826
827 for (int elem = 0; elem < nb_elem; elem++)
828 for (int p = 0; p < nb_param; p++)
829 {
830 terme_non_lin(elem,p) *= fermeture().beta()(p);
831 // Attention au signe devant le terme K.c
832 muti(elem,p) = terme_non_lin(elem,p) + second_terme(elem,p) - contribution_CL_concentration_(elem,p);
833 }
834 }
835
837 Debog::verifier("Cahn_Hilliard::compute_mutilde_tab() apres mutilde_ ", mutilde_->valeurs());
838 return muti;
839}
840
841/*! @brief Construit la fonction résidu pour un algorithme de Newton :
842 *
843 * En schéma Euler implicite
844 * c^n+1 - c^n - Δt M^-1 D mu^n+1 + CL(mu)^n+1 = 0
845 * avec mu^n+1 = beta*dW/dc^n+1 - M^-1 K c^n+1 - CL(c)^n+1
846 *
847 * Nécessite d'être généralisé à toute équation et tout schéma en temps
848 *
849 */
850DoubleTab Cahn_Hilliard::fonction_residu(const DoubleTab& c)
851{
852 // Variables temporelles
853 double dt=schema_temps().pas_de_temps();
854 double theta=ref_cast(Schema_Cahn_Hilliard,schema_temps()).coeff_theta();
855
856 const int nb_elem = domaine_dis().nb_elem(); // reel
857 const int nb_param = nb_parametres_d_ordre();
858
859 const DoubleTab& c_n = inconnue().passe(); // Concentration au temps n
860
861 DoubleTrav mutilde_theta(concentration_->valeurs());
862 DoubleTrav residu(concentration_->valeurs());
863
866
867 // On calcule d'abord mutilde^theta = beta*dW/dc^n - Kc^n
868 // Normalement, mutilde est calculé par rapport aux valeurs de inconnues().valeurs()
869 mutilde_theta = compute_mutilde(c);
870// Cerr << "mutilde = " << mutilde_theta << finl;
871
872 Debog::verifier("Cahn_Hilliard::fonction_residu() avant c ", c);
873
874 // TRES IMPORTANT : La contribution des conditions limites sur mutilde doit être
875 // calculée par rapport au mutilde de l'itération de Newton PRÉCÉDENTE !!!
876 // C'est dans le cas où les CL de mutilde dépendent de mutilde ou de c (Courant_impose)
877
878 // Vraiment ? Je ne suis pas sûr à 100% de ce que j'écris ici.
879 // mu(c) est une fonction de c. On le met à jour avec le c de l'itération de Newton précédente.
880 for (int i=0; i<le_dom_Cl_dis_mutilde_->nb_cond_lim(); i++)
881 {
882 Cond_lim& la_cl=le_dom_Cl_dis_mutilde_->les_conditions_limites(i);
883 if (sub_type(Courant_impose,la_cl.valeur()))
884 {
885// Cerr << "On rentre dans la condition sur la CL et on met à jour le courant !" << finl;
886 ref_cast(Courant_impose, la_cl.valeur()).mettre_a_jour_courant(c, mutilde_theta);
888 }
889 }
890
892 {
893 // Ici normalement l'opérateur op(0) lié à la mobilité doit s'appliquer à mutilde_theta
894 // operateur(0).calculer(mutilde_theta,tab_residu); // residu = D mutilde^theta
895 // Ce n'est pas ce qui est fait !!
896 // Car le nom de l'inconnue de l'équation n'est pas le même que celui de l'opérateur.
897 // On bypass la méthode surchargée calculer() et on appelle directement ajouter_bloc avec le bon tag.
898 terme_mobilite_->ajouter_blocs( { }, residu, { { "potentiel_chimique_generalise", mutilde_theta } });
899
900 solv_masse().appliquer(residu); // M-1 * residu
901
902 for (int elem = 0; elem < nb_elem; elem++)
903 for (int p = 0; p < nb_param; p++)
904 residu(elem, p) = c(elem, p) - c_n(elem, p) - theta * dt * residu(elem, p);
905 }
906 else
907 {
908 matrice_mobilite().multvect_(mutilde_theta, residu);
909
910 for (int elem = 0; elem < nb_elem; elem++)
911 for (int p = 0; p < nb_param; p++)
912 {
913 residu(elem, p) = c(elem, p) - c_n(elem, p) + theta * dt * (residu(elem, p) - contribution_CL_mutilde_(elem, p));
914 // Attention au signe devant le terme D.mu (:= intermediaire)
915 }
916 }
917
918 residu.echange_espace_virtuel();
919
920 Debog::verifier("Cahn_Hilliard::fonction_residu() apres c ", c);
921 Debog::verifier("Cahn_Hilliard::fonction_residu() apres residu ", residu);
922
923 return residu;
924}
925
926/*! @brief Renvoie la contribution des conditions limites sur la concentration
927 * sous forme d'un vecteur (multi-composantes)
928 */
930{
931 DoubleTrav temp(inco), temp2(inco); // inco ne sert qu'à dimensionner
932
934 {
935 Cerr << "[Cahn_Hilliard] You cannot add a BC contribution without calling the initialisation of matrices before." << finl;
936 exit();
937 }
938
939 // C'est tordu de récupérer les CL comme ça... Beaucoup d'opérations
940 terme_kappa_.calculer(temp2,temp); // Calcule b = [CL]^n - K.c^n
941 tab_divide_any_shape(temp, ref_cast(Domaine_VF,domaine_dis()).volumes()); // b = M^-1 ([CL]^n - K.c^n)
942
944 contribution_CL_concentration_.echange_espace_virtuel();
945}
946
947/*! @brief Renvoie la contribution des conditions limites sur le potentiel chimique
948 * sous forme d'un vecteur (multi-composantes)
949 */
951{
952 DoubleTrav temp(inco), temp2(inco); // inco ne sert qu'à dimensionner
953
955 {
956 Cerr << "[Cahn_Hilliard] You cannot add a BC contribution without calling the initialisation of matrices before." << finl;
957 exit();
958 }
959
960 // C'est tordu de récupérer les CL comme ça... Beaucoup d'opérations
961 terme_mobilite_.valeur().ajouter_blocs({}, temp, {{ "potentiel_chimique_generalise",temp2 }} );
962 solveur_masse->appliquer(temp); // b = M^-1 ([CL]^n - D.mu^n)
963
965 contribution_CL_mutilde_.echange_espace_virtuel();
966}
967
969{
970 const Domaine_VF& zvf = ref_cast(Domaine_VF,domaine_dis());
971 const DoubleVect& vol = zvf.volumes();
972 DoubleTrav inv_vol(vol.size_totale()*nb_parametres_d_ordre_);
973
974// Cerr << "Domain discretization: dx = " << ref_cast(Domaine_VDF,zvf).h_x() << " ; dy = " << ref_cast(Domaine_VDF,zvf).h_y() << finl;
975// Cerr << "Voxel volume V = " << vol(0) << finl;
976
977 // Définir un tableau temporaire pour construire la matrice (équivalent de contribuer_a_avec)
978 DoubleTrav temp(concentration_->valeurs());
979 temp = concentration_->valeurs();
980
981 Cerr << " . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ." << finl;
982 Cerr << ". . . . . . . . . . . INITIALIZATION: Mobility matrix & Kappa matrix . . . . . . . . . ." << finl;
983 Cerr << " . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ." << finl;
984
985 terme_kappa_.associer_diffusivite(kappa_);
986 terme_kappa_->associer_diffusivite(kappa_);
987 terme_kappa_->dimensionner_blocs( { { "concentration", &mat_kappa_ } });
988 Cerr << "Dimensions of matrix K = " << mat_kappa_.nb_lignes() << " x " << mat_kappa_.nb_colonnes() << finl;
989
990 mat_kappa_.sort_stencil(); // XXX sort tab2 ... au cas ou ...
991 terme_kappa_->ajouter_blocs( { { "concentration", &mat_kappa_ } }, temp, { });
992
993 // Initialisation des valeurs de mutilde à 0
994 mutilde_->valeurs() = 0.;
995 temp = mutilde_->valeurs();
996
997 terme_mobilite_.associer_diffusivite(mobilite_);
998 terme_mobilite_->associer_diffusivite(mobilite_);
999 terme_mobilite_->dimensionner_blocs( { { "concentration", &mat_mobilite_ } }); // Attention ! On dimensionne pareil que la concentration
1000 // mais la matrice mat_mobilite_ doit être associée à mutilde
1001 Cerr << "Dimensions of matrix M = " << mat_mobilite_.nb_lignes() << " x " << mat_mobilite_.nb_colonnes() << finl;
1002
1003 mat_mobilite_.sort_stencil(); // XXX sort tab2 ... au cas ou ...
1004 terme_mobilite_->ajouter_blocs( { { "potentiel_chimique_generalise", &mat_mobilite_ } }, temp, { });
1005
1006 // Stockage de l'inverse des volumes de chaque élément de domaine
1007 for (int i=0; i<vol.size_totale(); i++)
1008 for (int p=0; p<nb_parametres_d_ordre_; p++)
1009 inv_vol(p+i*nb_parametres_d_ordre_) = 1./vol(i);
1010
1011 // Division par les volumes
1012 mat_mobilite_.diagmulmat(inv_vol);
1013
1014// Cerr << "Matrice M = ";
1015// mat_mobilite_.imprimer_formatte(Cerr);
1016
1017 // Division par les volumes
1018 mat_kappa_.diagmulmat(inv_vol);
1019
1020// Cerr << "Matrice K = ";
1021// mat_kappa_.imprimer_formatte(Cerr);
1022
1024 // Initialisation taille des tableaux des contributions
1025 contribution_CL_concentration_ = concentration_->valeurs();
1027
1028 // Initialisation des contributions aux CLs
1029 calculer_contribution_CL_concentration(concentration_->valeurs());
1031}
1032
1034{
1035 construire_mobilite(c); // Construit le champ de mobilité en fonction d'un champ de concentration c (peut être c^n ou c^theta)
1036 terme_mobilite_.associer_diffusivite(mobilite_);
1037 terme_mobilite_->associer_diffusivite(mobilite_);
1038
1040 {
1041 const Domaine_VF& zvf = ref_cast(Domaine_VF,domaine_dis());
1042 const DoubleVect& vol = zvf.volumes();
1043 DoubleTrav inv_vol(vol.size_totale()*nb_parametres_d_ordre_);
1044
1045 // IMPORTANT : Remettre la matrice à 0
1046 mat_mobilite_.clean();
1047
1048 DoubleTrav temp(mutilde_->valeurs());
1049 // Met à jours la matrice mat_mobilite_
1050 mat_mobilite_.sort_stencil(); // XXX sort tab2 ... au cas ou ...
1051 terme_mobilite_->ajouter_blocs({ { "potentiel_chimique_generalise", &mat_mobilite_ } }, temp, { });
1052
1053 // Stockage de l'inverse des volumes de chaque élément de domaine
1054 for (int i=0; i<vol.size_totale(); i++)
1055 for (int p=0; p<nb_parametres_d_ordre_; p++)
1056 inv_vol(p+i*nb_parametres_d_ordre_) = 1./vol(i);
1057
1058 // Division par les volumes
1059 mat_mobilite_.diagmulmat(inv_vol);
1060 }
1061}
1062
1063/*! @brief Méthode pour vérifier la compatibilité entre les CL de la concentration
1064 * et les CL du potentiel
1065 */
1067{
1068 // D'abord check si les CL de mutilde sont compatibles avec l'équation de Cahn-Hilliard
1069 le_dom_Cl_dis_mutilde_->les_conditions_limites().compatible_avec_eqn(*this);
1070
1071 // A ce stade, les CL de la concentration sont connues, et celles de mutilde aussi.
1072 // Test de compatibilité inter-conditions (entre c et mutilde).
1073 // Les seules CL acceptées pour cette équations pour l'instant sont :
1074 // 1) Periodique
1075 // 2) Scalaire_impose_paroi (Dirichlet)
1076 // 3) Neumann_paroi (flux imposé)
1077
1078 Cerr << "** Checking compatibility between boundary conditions on concentration and potential... **" << finl;
1079
1080 // Boucle sur les frontières du domaine
1081 for (int n_cl = 0 ; n_cl < domaine_dis().domaine().nb_front_Cl() ; n_cl++)
1082 {
1083 const Cond_lim& cl_c=le_dom_Cl_dis->les_conditions_limites(n_cl);
1084 Nom nom_frontiere = domaine_dis().domaine().bord(n_cl).le_nom();
1085 const Cond_lim& cl_mutilde=le_dom_Cl_dis_mutilde_->les_conditions_limites(n_cl);
1086
1087 // 1) c periodique, mutilde periodique
1088 if (sub_type(Periodique,cl_c.valeur()) && sub_type(Periodique,cl_mutilde.valeur()))
1089 {
1090 Cerr << "---------↧ " << finl;
1091 Cerr << " [" << nom_frontiere << "] Boundary conditions on c and mutilde are compatible: both are PERIODIC." << finl;
1092 Cerr << " ↪" << finl;
1093 }
1094 // 2) c Neumann
1095 else if (sub_type(Neumann_paroi,cl_c.valeur()))
1096 {
1097 Cerr << "---------↧ " << finl;
1098 if (sub_type(Neumann_paroi,cl_mutilde.valeur())) // 2.1) mutilde Neumann
1099 Cerr << " [" << nom_frontiere << "] Boundary conditions on c and mutilde are compatible: both are NEUMANN." << finl;
1100 else if (sub_type(Scalaire_impose_paroi,cl_mutilde.valeur())) // 2.2) mutilde Dirichlet
1101 Cerr << " [" << nom_frontiere << "] Boundary conditions on c and mutilde are compatible: NEUMANN on c / DIRICHLET on mutilde." << finl;
1102 else
1103 {
1104 Cerr << " [" << nom_frontiere << "] Problem of compatibility between boundary conditions." << finl;
1105 Cerr << " Please check your dataset and the physics behind Cahn-Hilliard equation." << finl;
1106 Cerr << " Stop..." << finl;
1107 exit();
1108 }
1109 Cerr << " ↪" << finl;
1110 }
1111 // 2bis) c courant imposé (pas possible sur c)
1112 else if (sub_type(Courant_impose,cl_c.valeur()))
1113 {
1114 Cerr << " [" << nom_frontiere << "] Impossible to impose a current on the concentration." << finl;
1115 Cerr << " Please check your dataset and the physics behind Cahn-Hilliard equation." << finl;
1116 Cerr << " Stop..." << finl;
1117 exit();
1118 }
1119 // 3) c Dirichlet
1120 else if (sub_type(Scalaire_impose_paroi,cl_c.valeur()))
1121 {
1122 Cerr << "---------↧ " << finl;
1123 if (sub_type(Scalaire_impose_paroi,cl_mutilde.valeur()))
1124 {
1125 Cerr << " [" << nom_frontiere << "] Boundary conditions are DIRICHLET on c / DIRICHLET on mutilde." << finl;
1126 Cerr << " To keep consistance of the Cahn-Hilliard equation, BC on mutilde are computed again "
1127 "depending on BC on c." << finl;
1128
1129 Cerr << " CANNOT CHANGE VALUES THAT ARE NOT UNIFORM. Stop..." << finl;
1130 exit();
1131
1132 }
1133 else if (sub_type(Neumann_paroi,cl_mutilde.valeur()))
1134 Cerr << " [" << nom_frontiere << "] Boundary conditions on c and mutilde are compatible: DIRICHLET on c / NEUMANN on mutilde." << finl;
1135 else
1136 {
1137 Cerr << " [" << nom_frontiere << "] Problem of compatibility between boundary conditions." << finl;
1138 Cerr << " Please check your dataset and the physics behind Cahn-Hilliard equation." << finl;
1139 Cerr << " Stop..." << finl;
1140 exit();
1141 }
1142 Cerr << " ↪" << finl;
1143 }
1144 else
1145 {
1146 Cerr << "---------↧ " << finl;
1147 Cerr << " [" << nom_frontiere << "] Problem of compatibility between boundary conditions." << finl;
1148 Cerr << " Please check your dataset and the physics behind Cahn-Hilliard equation." << finl;
1149 Cerr << " Stop..." << finl;
1150 exit();
1151 }
1152 }
1153 return 1;
1154}
classe Cahn_Hilliard
int nb_parametres_d_ordre()
bool passer_par_ajouter_mobilite_
int preparer_calcul() override
cf Equation_base::preparer_calcul()
void discretiser_mobilite()
DoubleTab contribution_CL_concentration_
void calculer_contribution_CL_concentration(const DoubleTab &)
Renvoie la contribution des conditions limites sur la concentration sous forme d'un vecteur (multi-co...
DoubleTab contribution_CL_mutilde_
virtual DoubleTab fonction_residu(const DoubleTab &)
Construit la fonction résidu pour un algorithme de Newton :
void discretiser() override
Dicretise l'equation.
void completer() override
Complete l'equation base, associe le potentiel chimique généralisé a l'equation, initialise le vecteu...
void associer_sch_tps_base(const Schema_Temps_base &) override
S'associe au schema_en_temps : peut seulement être Schema_CH_Semi_Implicite pour l'instant.
void mettre_a_jour(double temps) override
Effectue une mise a jour en temps de l'equation.
int lire_motcle_non_standard(const Motcle &, Entree &) override
Lecture des parametres de type non simple d'un objet_U a partir d'un flot d'entree.
const Milieu_base & milieu() const override
Renvoie le milieu physique de l'equation.
int verif_Cl_mutilde() const
Méthode pour vérifier la compatibilité entre les CL de la concentration et les CL du potentiel.
int sauvegarder(Sortie &) const override
Appelle Equation_base::sauvegarder(Sortie&) et sauvegarde le potentiel chimique sur un flot de sortie...
const Fermeture_Thermo_base & fermeture() const
void associer_milieu_base(const Milieu_base &) override
Associe un mileu physique a l'equation en construisant dynamiquement (cast) un objet de type Milieu_I...
void resetTime(double time) override
Reset current time of the equation. Used from ICoCo. See documentation of Problem_base::resetTime().
void compute_mutilde()
Calcul de mutilde = beta*dW/dc - ∇. kappa ∇c.
std::vector< YAML_data > data_a_sauvegarder() const override
for PDI IO: retrieve name, type and dimensions of the fields to save/restore
bool passer_par_ajouter_kappa_
bool updateGivenFields() override
cf Equation_base::updateGivenFields()
void set_param(Param &) const override
void abortTimeStep() override
Reinitialiser ce qui doit l'etre.
void construire_mobilite(const DoubleTab &)
Operateur_Diff terme_mobilite_
Operateur_Diff terme_kappa_
Entree & lire_cl_potentiel(Entree &)
Lecture des conditions limites sur un flot d'entree.
int nombre_d_operateurs_tot() const override
bool initTimeStep(double dt) override
Allocation et initialisation de l'inconnue et des CLs jusqu'a present+dt.
void initialiser_matrices()
const Operateur & operateur(int) const override
Renvoie le i-eme operateur de l'equation:
void discretiser_mutilde()
void associer_pb_base(const Probleme_base &) override
S'associe au probleme: apelle Equation_base::associer_pb_base(const Probleme_base&) les deux termes d...
void calculer_contribution_CL_mutilde(const DoubleTab &)
Renvoie la contribution des conditions limites sur le potentiel chimique sous forme d'un vecteur (mul...
bool matrices_initialisees_
int reprendre(Entree &) override
Effectue une reprise a partir d'un flot d'entree.
void lire_terme_mobilite()
const Champ_Inc_base & mutilde() const
Matrice_Morse mat_mobilite_
const Motcle & domaine_application() const override
Renvoie le nom du domaine d'application: "Cahn_Hilliard".
int nombre_d_operateurs() const override
Renvoie le nombre d'operateurs de l'equation: Pour Cahn-Hilliard c'est 2.
DoubleTab & derivee_en_temps_inco(DoubleTab &) override
Returns the time derivative of the unknown I of the equation: dI/dt = M-1*(sum(operators(I) + sources...
Domaine_Cl_dis_base & domaine_Cl_dis_mutilde()
void update_terme_mobilite(const DoubleTab &)
Matrice_Morse mat_kappa_
double calculer_pas_de_temps() const override
Calcul du prochain pas de temps.
void discretiser_concentration()
Matrice_Morse & matrice_mobilite()
const Champ_Inc_base & inconnue() const override
Renvoie la concentration (champ inconnue de l'equation) (version const).
Classe Champ_Inc_base.
DoubleTab & futur(int i=1) override
Renvoie les valeurs du champs a l'instant t+i.
virtual void associer_domaine_cl_dis(const Domaine_Cl_dis_base &)
DoubleTab & passe(int i=1) override
Renvoie les valeurs du champs a l'instant t-i.
void resetTime(double time) override
double changer_temps(const double temps) override
Fixe le temps du champ.
DoubleTab & valeurs() override
Renvoie le tableau des valeurs du champ au temps courant.
virtual void associer_eqn(const Equation_base &)
Associe le champ a l'equation dont il represente une inconnue.
virtual void verifie_valeurs_cl()
double changer_temps_futur(double, int i=1)
Fixe le temps du ieme champ futur.
virtual void completer(const Domaine_Cl_dis_base &zcl)
virtual void abortTimeStep()
classe Cond_lim Classe generique servant a representer n'importe quelle classe
Definition Cond_lim.h:31
Classe Courant_impose Cette condition limite correspond a un courant imposé. Utile uniquement dans le...
static void verifier(const char *const msg, double)
Definition Debog.cpp:21
classe Discret_Thyd Cette classe est la classe de base representant une discretisation
void discretiser_champ(const Motcle &directive, const Domaine_dis_base &z, const Nom &nom, const Nom &unite, int nb_comp, int nb_pas_dt, double temps, OWN_PTR(Champ_Inc_base)&champ, const Nom &sous_type=NOM_VIDE) const
int nb_front_Cl() const
Definition Domaine.h:236
Bord_t & bord(int i)
Definition Domaine.h:193
void calculer_derivee_en_temps(double t1, double t2)
Calcule le taux d'accroissement des CLs instationnaires entre t1 et t2.
virtual void imposer_cond_lim(Champ_Inc_base &, double)=0
void resetTime(double time)
void set_temps_defaut(double temps)
Change le i-eme temps futur de toutes les CLs.
virtual void mettre_a_jour(double temps)
Effectue une mise a jour en temps de toutes les conditions aux limites.
int avancer(double temps)
Tourne la roue des CLs jusqu'au temps donne.
void changer_temps_futur(double temps, int i)
Change le i-eme temps futur de toutes les CLs.
class Domaine_VF
Definition Domaine_VF.h:44
double volumes(int i) const
Definition Domaine_VF.h:113
const Nom & le_nom() const override
Donne le nom de l'Objet_U Methode a surcharger : renvoie "neant" dans cette implementation.
const Domaine & domaine() 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....
virtual void set_param(Param &titi) const override
int reprendre(Entree &) override
On reprend l'inconnue a partir d'un flot d'entree.
virtual std::vector< YAML_data > data_a_sauvegarder() const
for PDI IO: retrieve name, type and dimensions of the data to save/restore. This has to be overrode f...
virtual void associer_pb_base(const Probleme_base &)
S'associe au Probleme passe en parametre.
Sources & sources()
Renvoie les termes sources asssocies a l'equation.
const Discretisation_base & discretisation() const
Renvoie la discretisation associee a l'equation.
Solveur_Masse_base & solv_masse()
Renvoie le solveur de masse associe a l'equation.
void set_diffusion_multi_scalaire(bool flg=true)
virtual void mettre_a_jour(double temps)
La valeur de l'inconnue sur le pas de temps a ete calculee.
virtual void abortTimeStep()
Reinitialiser ce qui doit l'etre.
Sources les_sources
virtual int preparer_calcul()
Tout ce qui ne depend pas des autres problemes eventuels.
virtual bool updateGivenFields()
void initialise_residu(int=0)
int sauvegarder(Sortie &) const override
On sauvegarde l'inconnue, puis les sources sur un flot de sortie.
Probleme_base & probleme()
Renvoie le probleme associe a l'equation.
int lire_motcle_non_standard(const Motcle &, Entree &) override
Lecture des parametres de type non simple d'un objet_U a partir d'un flot d'entree.
Schema_Temps_base & schema_temps()
Renvoie le schema en temps associe a l'equation.
virtual bool initTimeStep(double dt)
Allocation et initialisation de l'inconnue et des CLs jusqu'a present+dt.
virtual void discretiser()
Discretise l'equation.
virtual void resetTime(double time)
Reset current time of the equation. Used from ICoCo. See documentation of Problem_base::resetTime().
Champs_compris champs_compris_
Domaine_dis_base & domaine_dis()
Renvoie le domaine discretise associe a l'equation.
Potentiel_Chimique_base & potentiel_chimique()
DoubleTab mobilite(const DoubleTab &d) const
const Nom & le_nom() const override
Donne le nom de l'Objet_U Methode a surcharger : renvoie "neant" dans cette implementation.
Definition Frontiere.h:49
virtual DoubleVect & multvect_(const DoubleVect &, DoubleVect &) const
const Fermeture_Thermo_base & fermeture() const
classe Milieu_base Cette classe est la base de la hierarchie des milieux (physiques)
Definition Milieu_base.h:50
Une chaine de caractere (Nom) en majuscules.
Definition Motcle.h:26
Classe Neumann_paroi Cette condition limite correspond a un flux impose pour l'equation de.
class Nom Une chaine de caractere pour nommer les objets de TRUST
Definition Nom.h:31
friend class Entree
Definition Objet_U.h:76
friend class Sortie
Definition Objet_U.h:75
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 Classe generique de la hierarchie des operateurs.
Definition Operateur.h:39
virtual DoubleTab & calculer(const DoubleTab &, DoubleTab &) const =0
virtual void completer()
Met a jour les references des objets associes a l'operateur.
Helper class to factorize the readOn method of Objet_U classes.
Definition Param.h:112
void ajouter_flag(const char *keyword, const bool *value)
Register a boolean flag whose mere presence switches it to true.
Definition Param.cpp:474
@ REQUIRED
Definition Param.h:115
void ajouter_non_std(const char *keyword, const Objet_U *value, Param::Nature nat=Param::OPTIONAL)
Register a keyword handled by Objet_U::lire_motcle_non_standard.
Definition Param.cpp:489
classe Periodique Cette classe represente une condition aux limites periodique.
Definition Periodique.h:31
virtual DoubleTab dWdc(const DoubleTab &)
const Nom & le_nom() const override
Donne le nom de l'Objet_U Methode a surcharger : renvoie "neant" dans cette implementation.
Definition Probleme_U.h:109
classe Probleme_base C'est un Probleme_U qui n'est pas un couplage.
const Domaine & domaine() const
Renvoie le domaine associe au probleme.
static void exit(int exit_code=-1)
Routine de sortie de TRUST dans une region Kokkos.
Definition Process.cpp:455
classe Scalaire_impose_paroi Impose un scalaire a la paroi dans une equation de type Convection-Difus...
class Schema_Cahn_Hilliard. Il herite de schema Euler semi implicite et ne s'applique qu'à Cahn-Hilli...
class Schema_Temps_base
double temps_courant() const
Renvoie le temps courant.
virtual double temps_futur(int i) const =0
double pas_de_temps() const
Renvoie le pas de temps (delta_t) courant.
virtual int nb_valeurs_futures() const =0
virtual double temps_defaut() const =0
virtual void completer()=0
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 mettre_a_jour(double temps)
Mise a jour en temps, de toute les sources de la liste.
Definition Sources.cpp:109
_SIZE_ dimension(int d) const
Definition TRUSTTab.tpp:133
_SIZE_ size_totale() const
Definition TRUSTVect.tpp:61
int line_size() const
Definition TRUSTVect.tpp:67
virtual void echange_espace_virtuel(IsExchangeBlocking exchange_type=IsExchangeBlocking::DefaultBlocking, const std::string kernel_name="noname")
static int is_PDI_restart()