TrioCFD 1.9.8
TrioCFD documentation
Loading...
Searching...
No Matches
Courant_impose.cpp
1/****************************************************************************
2* Copyright (c) 2025, 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 <Courant_impose.h>
17#include <Domaine_Cl_dis_base.h>
18#include <Equation_base.h>
19#include <Cahn_Hilliard.h>
20#include <Probleme_base.h>
21#include <Milieu_base.h>
22#include <Espece_intercalee.h>
23#include <EChaine.h>
24
25Implemente_instanciable(Courant_impose, "Courant_impose", Neumann_paroi);
26// XD Courant_impose condlim_base Courant_impose INHERITS_BRACE Neumann boundary condition for imposed courant
27// XD_CONT (multiphase problem)
28// XD attr ch front_field_base ch REQ Boundary field type.
29
30Sortie& Courant_impose::printOn(Sortie& s) const { return s << que_suis_je() << finl; }
31
33{
34 if (app_domains.size() == 0) app_domains = { Motcle("Cahn_Hilliard"), Motcle("indetermine") };
35 Cerr << "*** Boundary conditions : Imposed courant for Lithium-ion Batteries case (only Cahn-Hilliard has been added yet) ***" << finl;
36
37 if (supp_discs.size() == 0) supp_discs = { Nom("VDF") };
38
39 // Lecture de la valeur uniforme du champ de courant imposé
40 s >> Iimp_;
41
42// Cerr << "Après lecture : Iimp = " << Iimp_ << finl;
43
44 // Dimensionnement du champ de flux à la frontière et initialisation à 0
45 // Type : champ variable en espace et en temps
46 le_champ_front.typer("Champ_front_fonc");
47 le_champ_front->nommer("Courant_impose");
48// Cerr << "Après typer." << finl;
49
50// Cerr << "[Courant_impose] Sortie du readOn." << finl;
51 return s;
52}
53
55{
56 mon_dom_cl_dis = zcl;
57
58 Equation_base& eq = mon_dom_cl_dis->equation();
59 const int dim_champ = eq.inconnue().nb_comp();
60
61// Cerr << "dim_champ = " << dim_champ << finl;
62// Cerr << "Temps = " << eq.schema_temps().temps_courant() << finl;
63 // le_champ_front->set_temps_defaut(eq.schema_temps().temps_courant());
64 le_champ_front->fixer_nb_comp(dim_champ);
65// Cerr << "Après avoir fixé le nombre de composantes." << finl;
66
67 le_champ_front->verifier(*this);
68
69// Cerr << "PREMIER PRINT = " << le_champ_front << finl;
70}
71
73{
74 Cerr << "[Courant_impose::verifie_ch_init_nb_comp()] ..." << finl;
75
76 if (le_champ_front)
77 {
79 const int nb_comp = le_champ_front->nb_comp();
80 eq.verifie_ch_init_nb_comp_cl(eq.inconnue(), nb_comp, *this);
81 }
82}
83
85{
86 Equation_base& eq = mon_dom_cl_dis->equation();
87 const int dim_champ = eq.inconnue().nb_comp();
88
89 Cerr << "[Courant_impose::completer()] ..." << finl;
90
91 int i;
92 ndeb_ = ref_cast(Front_VF,frontiere_dis()).num_premiere_face();
93// Cerr << "ndeb_ = " << ndeb_ << finl;
94 nb_faces_ = ref_cast(Front_VF,frontiere_dis()).nb_faces();
95// Cerr << "nb_faces_ = " << nb_faces_ << finl;
96 le_champ_front->valeurs().resize(nb_faces_,dim_champ);
97// Cerr << "Dimension of le_champ_front = " << le_champ_front->valeurs().dimension(0) << " x "
98// << le_champ_front->valeurs().dimension(1) << finl;
99
100 le_champ_front->set_instationnaire(true);
101
102// Cerr << "Après set_instationnaire." << finl;
103 if (le_champ_front->instationnaire())
104 Cerr << "[Courant_impose] : Instationnary field OK." << finl;
105 else
106 {
107 Cerr << "[Courant_impose] : Stationnary field... Not normal." << finl;
108 exit();
109 }
110
111 surfaces_.resize(nb_faces_);
112
113 Domaine_VF& zvf = ref_cast(Domaine_VF, mon_dom_cl_dis->domaine_dis());
114 for (i = 0; i < nb_faces_; i++)
115 {
116 surfaces_(i) = zvf.face_surfaces(i + ndeb_);
117 }
118
120
121// Cerr << "SECOND PRINT = " << le_champ_front->valeurs() << finl;
122
123}
124
125/*! @brief Met a jour les conditions aux limites sur le courant (spécifique à cette classe)
126 *
127 */
128void Courant_impose::mettre_a_jour_courant(const DoubleTab& c, const DoubleTab& mutilde)
129{
130 // Potentiel de l'électrolyte
131 double mu_el(0.), numer(0.), denom(0.), numer_tot(0.), denom_tot(0.);
132
133 DoubleTab& courant(le_champ_front->valeurs());
134 int nb_couches = courant.line_size();
135
136 Espece_intercalee& mil = ref_cast(Espece_intercalee, mon_dom_cl_dis->equation().milieu());
137 double i0 = mil.i0();
138 double damkohler = mil.damkohler();
139 double T_sur_Tref = mil.T_sur_Tref();
140
141 double S(0.), S_tot(0.), ds(0.);
142
143// Cerr << "surfaces = " << surfaces_ << finl;
144
145 for (int j=0; j<nb_couches; j++)
146 for (int face = 0; face < nb_faces_; face++)
147 {
148 int facegl = face + ndeb_; // indice de face global
149 int elem = face_voisins_(facegl, 0);
150 if (elem == -1)
151 elem = face_voisins_(facegl, 1);
152 ds = surfaces_(face);
153// Cerr << "ds = " << ds << finl;
154 S += ds;
155 numer += c(elem,j)*(1.-c(elem,j))*mutilde(elem,j)*ds;
156 denom += c(elem,j)*(1.-c(elem,j))*ds;
157 }
158// Cerr << "S = " << S << finl;
159// Cerr << "numer = " << numer << finl;
160// Cerr << "denom = " << denom << finl;
161
162 S_tot = mp_sum(S); // N_couches * L_y (ou L_x)
163// Cerr << "S_tot = " << S_tot << finl;
164 numer_tot = mp_sum(numer);
165// Cerr << "numer_tot = " << numer_tot << finl;
166 numer_tot /= S_tot; // C'est une moyenne sur la surface d'entrée : N_couches * L_y (ou L_x)
167 denom_tot = mp_sum(denom);
168// Cerr << "denom_tot = " << denom_tot << finl;
169 denom_tot /= S_tot; // C'est aussi une moyenne sur la surface d'entrée
170// Cerr << "deuxieme terme du numerateur = " << (S_tot * (Iimp_)/i0) << finl;
171 // Multiplication par la surface totale (qui comprend aussi l'indice j des couches)
172// if (abs(denom_tot) < 1.E-12)
173// mu_el = 0.;
174// else
175 mu_el = ( ((Iimp_/i0) * T_sur_Tref) + numer_tot ) / denom_tot;
176
177// Cerr << "mu_el = " << mu_el << finl;
178
179 const double constante = damkohler/(T_sur_Tref);
180
181 // Boucle sur les couches
182 for (int j=0; j<nb_couches; j++)
183 for (int face = 0; face < nb_faces_; face++)
184 {
185 int facegl = face + ndeb_;
186 int elem = face_voisins_(facegl, 0);
187 if (elem == -1)
188 elem = face_voisins_(facegl, 1);
189 courant(face,j) = constante * c(elem,j)*(1.-c(elem,j))*(mu_el - mutilde(elem,j));
190 }
191
192// Cerr << "courant imposé = " << courant << finl;
193}
194
195/*! @brief Renvoie la valeur du flux impose sur la i-eme composante du champ representant le flux a la frontiere.
196 *
197 * Le champ a la frontiere est considere constant sur tous
198 * les elements de la frontiere.
199 * La valeur du flux impose a la frontiere est egale
200 * a la valeur du champ (considere constant) a la frontiere divise par d_rho.
201 *
202 * @param (int i) indice suivant la premiere dimension du champ
203 * @return (double) la valeur imposee sur la composante du champ specifiee
204 * @throws deuxieme dimension du champ de frontiere superieur a 1
205 */
207{
208 return Neumann::flux_impose(i);
209}
210
211/*! @brief Renvoie la valeur du flux impose sur la (i,j)-eme composante du champ representant le flux a la frontiere.
212 *
213 * Le champ a la frontiere n'est PAS constant sur tous les elements
214 * la frontiere.
215 *
216 * @param (int i) indice suivant la premiere dimension du champ
217 * @param (int j) indice suivant la deuxieme dimension du champ
218 * @return (double) la valeur imposee sur la composante du champ specifiee
219 */
220double Courant_impose::flux_impose(int i, int j) const
221{
222 return Neumann::flux_impose(i,j);
223}
224
std::vector< Nom > supp_discs
Domaine_Cl_dis_base & domaine_Cl_dis()
Renvoie le domaine des conditions aux limites discretisee dont l'objet fait partie.
std::vector< Motcle > app_domains
virtual Frontiere_dis_base & frontiere_dis()
Renvoie la frontiere discretisee a laquelle les conditions aux limites s'appliquent.
Classe Courant_impose Cette condition limite correspond a un courant imposé. Utile uniquement dans le...
void verifie_ch_init_nb_comp() const override
Appel la verification du champ lu par l intermediaire de l equation pour laquelle on considere la con...
void mettre_a_jour_courant(const DoubleTab &, const DoubleTab &)
Met a jour les conditions aux limites sur le courant (spécifique à cette classe).
double flux_impose(int i) const override
Renvoie la valeur du flux impose sur la i-eme composante du champ representant le flux a la frontiere...
void completer() override
NE FAIT RIEN A surcharger dans les classes derivees.
DoubleVect surfaces_
void associer_domaine_cl_dis_base(const Domaine_Cl_dis_base &) override
Associe le Domaine_Cl_dis_base (Domaine des conditions aux limites discretisees) a l'objet.
classe Domaine_Cl_dis_base Les objets Domaine_Cl_dis_base representent les conditions aux limites
class Domaine_VF
Definition Domaine_VF.h:44
virtual const DoubleVect & face_surfaces() const
Definition Domaine_VF.h:51
int face_voisins(int num_face, int i) const
renvoie l'element voisin de numface dans la direction i.
Definition Domaine_VF.h:418
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 const Milieu_base & milieu() const =0
virtual const Champ_Inc_base & inconnue() const =0
virtual void verifie_ch_init_nb_comp_cl(const Champ_Inc_base &ch_ref, const int nb_comp, const Cond_lim_base &cl) const
virtual int nb_comp() const
Definition Field_base.h:56
class Front_VF
Definition Front_VF.h:36
virtual const Equation_base & equation(const std::string &nom_inc) const
const Equation_base & equation() const
Renvoie la reference sur l'equation pointe par MorEqn::mon_equation.
Definition MorEqn.h:62
Classe Neumann_paroi Cette condition limite correspond a un flux impose pour l'equation de.
virtual double flux_impose(int i) const
Renvoie la valeur du flux impose sur la i-eme composante du champ representant le flux a la frontiere...
Definition Neumann.cpp:35
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
static double mp_sum(double)
Calcule la somme de x sur tous les processeurs du groupe courant.
Definition Process.cpp:146
static void exit(int exit_code=-1)
Routine de sortie de TRUST dans une region Kokkos.
Definition Process.cpp:455
Classe de base des flux de sortie.
Definition Sortie.h:52
int line_size() const
Definition TRUSTVect.tpp:67