TrioCFD 1.9.9_beta
TrioCFD documentation
Loading...
Searching...
No Matches
Equation_IBM_proto.cpp
1/****************************************************************************
2* Copyright (c) 2026, 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 <Discretisation_base.h>
17#include <Equation_IBM_proto.h>
18#include <Schema_Temps_base.h>
19#include <Source_PDF_base.h>
20#include <Operateur_base.h>
21#include <Probleme_base.h>
22#include <Equation_base.h>
23#include <Operateur.h>
24#include <Param.h>
25#include <Nom.h>
26#include <Perf_counters.h>
27
29{
30 param.ajouter("correction_variable_initiale",&correction_variable_initiale_,Param::OPTIONAL);
31}
32
34{
35 eq_IBM_ = eq;
36
37 int i_source = -1;
38 int nb_source_pdf = 0;
39 int nb_source = eq.sources().size();
40 Cerr << "nb_source : " << nb_source << finl;
41 for(int i = 0; i<nb_source; i++)
42 {
43 //Cerr << (sources())[i]->que_suis_je() << ", " << (sources())[i]->que_suis_je().find("gne") << finl;
44 if ((eq.sources())[i]->que_suis_je().find("Source_PDF") > -1)
45 {
46 i_source = i;
47 nb_source_pdf++;
48 }
49 }
50 if (nb_source_pdf>1)
51 {
52 Cerr<<"(IBM) More than one Source_PDF_base detected."<<finl;
53 Cerr<<"(IBM) Case not supported."<<finl;
54 Cerr<<"Aborting..."<<finl;
55 abort();
56 }
57 i_source_pdf_ = i_source;
58 if (i_source_pdf_ != -1)
59 {
60 Cerr<<"(IBM) Immersed Interface with Source_PDF_base for equation : "<< eq_IBM_->le_nom()<<finl;
61 eq.sources()[i_source_pdf_]->set_description((Nom)"Sum of the PDF source term on the obstacle (~= force/power induced by the obstacle under some assumptions)");
62 Nom the_suffix = eq_IBM_->le_nom().getSuffix(eq_IBM_->probleme().le_nom());
63 eq.sources()[i_source_pdf_]->set_fichier((Nom)the_suffix+"_Bilan_term_induced_by_obstacle");
64 }
65
66 // XXX Elie Saikali
67 // ok for temperature for now (test case Comte_Bellot_EF_IBC in trio ! to be corrected later Michel !)
68 if (i_source_pdf_ == -1 && eq_IBM_->que_suis_je().debute_par("Navier_Stokes"))
69 {
70 Cerr << "No PDF source term read in your equation " << eq_IBM_->que_suis_je() << " !!!"<< finl;
71 Cerr << "Either add this source term or use a non_IBM problem !!!"<< finl;
73 }
74
75 return is;
76}
77
79{
80 if (i_source_pdf_ == -1) return false;
81 Cerr<<"(IBM) initTimeStep_IBM: update of immersed values for equation : "<< eq_IBM_->le_nom() <<finl;
82 Source_PDF_base& src = dynamic_cast<Source_PDF_base&>((eq_IBM_->sources())[i_source_pdf_].valeur());
84
86 {
87 Cerr<<"(IBM) PDF_mobile : updating the shape following shape velocity"<<finl;
88 const Probleme_base& pb = eq_IBM_->probleme();
89 const Domaine_dis_base& le_dom_dis = pb.domaine_dis();
90 const DoubleTab& coords = le_dom_dis.domaine().coord_sommets();
91 Domaine_VF& le_dom_VF = ref_cast_non_const(Domaine_VF, pb.domaine_dis());
92 double delta_t = eq_IBM_->schema_temps().pas_de_temps();
93 double temps= eq_IBM_->schema_temps().temps_courant();
94
95 // Boundary displacement
96 PDF_model& my_model = ref_cast_non_const(PDF_model, src.get_modele());
97 my_model.affecter_vitesse_shape_IBM(le_dom_VF, coords, temps);
98 DoubleTab& vitesse = ref_cast_non_const(DoubleTab, src.get_modele().get_vitesse_shape_IBM()) ;
99 double raid = my_model.raid();
100 src.update_elem_IBM(vitesse, delta_t,raid);
101 }
102 return true;
103}
104
106{
107 if (i_source_pdf_ == -1) return derivee;
108 Cerr<<"(IBM) Immersed Interface: Dirichlet value in Equation for PDF (if any)."<<finl;
109 Source_PDF_base& src = dynamic_cast<Source_PDF_base&>((eq_IBM_->sources())[i_source_pdf_].valeur());
110
111 // PDF IB value term : -rho/delta_t ksi_gamma/epsilon U_gamma
112 DoubleTab secmem_pdf(derivee);
113 src.calculer_pdf(secmem_pdf);
114 derivee -= secmem_pdf;
115 derivee.echange_espace_virtuel();
116
117 // Time term : -rho/delta_t ksi_gamma Un
118 int pdf_bilan = src.get_modele().pdf_bilan();
119 if (pdf_bilan == 1|| pdf_bilan == 2)
120 {
121 int i_traitement_special = 101;
122 int nb_comp = derivee.dimension(1);
123 if (nb_comp == Objet_U::dimension)
124 {
125 //vector; NS
126 // Navier_Stokes_std& eq_NS = ref_cast_non_const(Navier_Stokes_std, eq_IBM);
127 if (eq_IBM_->nombre_d_operateurs() > 1)
128 {
129 // if (eq_NS.vitesse_pour_transport().le_nom()=="rho_u") i_traitement_special = 1;
130 i_traitement_special = 101;
131 }
132 }
133 else if (nb_comp == 1)
134 {
135 //scalar; time term in rho
136 i_traitement_special = 1;
137 }
138 else
139 {
140 Cerr << "Equation_IBM_proto: for scalar or vector only; dim = " <<nb_comp<< finl;
142 }
143
144 DoubleTrav secmem_pdf_time(derivee);
145 src.calculer(secmem_pdf_time, i_traitement_special);
146 secmem_pdf += secmem_pdf_time;
147 }
148 else if(pdf_bilan != 0 )
149 {
150 Cerr<<"Source_PDF_EF: Model pdf_bilan must be 0; 1 or 2 only"<<finl;
152 }
153
154 // Save secmem_pdf
155 secmem_pdf.echange_espace_virtuel();
156 src.set_sec_mem_pdf(secmem_pdf);
157
158 return derivee;
159}
160
162{
163 if (i_source_pdf_ == -1) return;
164
165 Source_PDF_base& src = dynamic_cast<Source_PDF_base&>((eq_IBM_->sources())[i_source_pdf_].valeur());
166 src.updateChampRho();
167 DoubleTab coeff;
168 coeff = src.compute_coeff_matrice();
170 Cerr<<"(IBM) preparer_calcul_IBM: Min/max coeff : "<< mp_min_vect(coeff) << " " << mp_max_vect(coeff) <<finl;
171 champ_coeff_pdf_som_ = coeff;
172 modify_initial_variable_ibm_proto(eq_IBM_->inconnue().valeurs());
173}
174
176{
178 {
179 Cerr<<"(IBM) Immersed Interface: modified initial variable."<<finl;
180 const Source_PDF_base& src = dynamic_cast<Source_PDF_base&>((eq_IBM_->sources())[i_source_pdf_].valeur());
182 variable.echange_espace_virtuel();
183 }
184}
185
186// adds the contributions of operators and sources
187void Equation_IBM_proto::assembler_ibm_proto(Matrice_Morse& matrice, const DoubleTab& inco, DoubleTab& resu)
188{
189 const double rhoCp = eq_IBM_->get_time_factor();
190 int size_s = eq_IBM_->sources().size();
191
192 // Verification test of the contribuer_a_avec method
193 for (int op=0; op<eq_IBM_->nombre_d_operateurs(); op++)
194 eq_IBM_->operateur(op).l_op_base().tester_contribuer_a_avec(inco, matrice);
195
196 // Contribution of operators and sources:
197 // [Vol/dt+A]Inco(n+1)=sum(residual)+Vol/dt*Inco(n)
198 // Typically: if Op=flux(Inco) then the implicit matrix A contains a contribution -dflux/dInco
199 // Example: convective flux Op in VDF:
200 // Op=T*u*S and A=-d(T*u*S)/dT=-u*S
201 const Discretisation_base::type_calcul_du_residu& type_codage=eq_IBM_->probleme().discretisation().codage_du_calcul_du_residu();
203 {
204 if ( eq_IBM_->probleme().discretisation().que_suis_je() == "EF")
205 {
206 // We compute sum(residual) via contribuer_au_second_membre (typically non-implicitized BCs)
207 // This approach requires coding 3 methods (contribuer_a_avec, contribuer_au_second_membre and ajouter for the explicit case)
208 if (!is_IBM())
209 eq_IBM_->sources().contribuer_a_avec(inco, matrice);
210 else
211 {
212 for (int i = 0; i < size_s; i++)
213 {
214 if (eq_IBM_->sources()(i).valeur().que_suis_je().find("Source_PDF") <= -1)
215 {
216 const Source_base& src_base = eq_IBM_->sources()(i).valeur();
217 src_base.contribuer_a_avec(inco, matrice);
218 }
219 }
220 }
221 statistics().end_count(STD_COUNTERS::matrix_assembly);
222 if (!is_IBM())
223 eq_IBM_->sources().ajouter(resu);
224 else
225 {
226 for (int i = 0; i < size_s; i++)
227 if (eq_IBM_->sources()(i).valeur().que_suis_je().find("Source_PDF") <= -1)
228 eq_IBM_->sources()(i).ajouter(resu);
229 }
230 statistics().begin_count(STD_COUNTERS::matrix_assembly,statistics().get_last_opened_counter_level()+1);
231 matrice.ajouter_multvect(inco, resu); // Add source residual first
232 for (int op = 0; op < eq_IBM_->nombre_d_operateurs(); op++)
233 {
234 eq_IBM_->operateur(op).l_op_base().contribuer_a_avec(inco, matrice);
235 eq_IBM_->operateur(op).l_op_base().contribuer_au_second_membre(resu);
236 }
237 }
238 else
239 {
240 Cerr << "VIA_CONTRIBUER_AU_SECOND_MEMBRE not coded for " << eq_IBM_->que_suis_je() << ":assembler" << finl;
241 Cerr << "with discretisation " << eq_IBM_->probleme().discretisation().que_suis_je() << "" << finl;
243 }
244 // // We compute sum(residual) via contribuer_au_second_membre (typically non-implicitized BCs)
245 // // This approach requires coding 3 methods (contribuer_a_avec, contribuer_au_second_membre and ajouter for the explicit case)
246 // sources().contribuer_a_avec(inco,matrice);
247 // sources().ajouter(resu);
248 // matrice.ajouter_multvect(inco, resu); // Add source residual first
249 // for (int op = 0; op < nombre_d_operateurs(); op++)
250 // {
251 // operateur(op).l_op_base().contribuer_a_avec(inco, matrice);
252 // operateur(op).l_op_base().contribuer_au_second_membre(resu);
253 // }
254 }
255 else if (type_codage==Discretisation_base::VIA_AJOUTER)
256 {
257 // We compute sum(residual) via sum(operator)+sources+A*Inco(n)
258 // This approach requires coding only two methods (contribuer_a_avec and ajouter)
259 // So slightly more expensive in computation time but less code to write/maintain
260 for (int op=0; op<eq_IBM_->nombre_d_operateurs(); op++)
261 {
262 Matrice_Morse mat(matrice);
263 mat.get_set_coeff() = 0.0;
264 eq_IBM_->operateur(op).l_op_base().contribuer_a_avec(inco, mat);
265 if (op == 1) mat *= rhoCp; // the derivative is multiplied by rhoCp for convection
266 matrice += mat;
267 statistics().end_count(STD_COUNTERS::matrix_assembly);
268 {
269 DoubleTab resu_tmp(resu);
270 resu_tmp = 0.;
271 eq_IBM_->operateur(op).ajouter(inco, resu_tmp);
272 if (op == 1) resu_tmp *= rhoCp;
273 resu += resu_tmp;
274 }
275 statistics().begin_count(STD_COUNTERS::matrix_assembly,statistics().get_last_opened_counter_level()+1);
276 }
277 if (! is_IBM() )
278 eq_IBM_->sources().contribuer_a_avec(inco,matrice);
279 else
280 {
281 for (int i = 0; i < size_s; i++)
282 if (eq_IBM_->sources()(i).valeur().que_suis_je().find("Source_PDF") <= -1)
283 {
284 const Source_base& src_base = eq_IBM_->sources()(i).valeur();
285 src_base.contribuer_a_avec(inco, matrice);
286 }
287 }
288 statistics().end_count(STD_COUNTERS::matrix_assembly);
289 if (!is_IBM())
290 eq_IBM_->sources().ajouter(resu);
291 else
292 {
293 for (int i = 0; i < size_s; i++)
294 if (eq_IBM_->sources()(i).valeur().que_suis_je().find("Source_PDF") <= -1)
295 eq_IBM_->sources()(i).ajouter(resu);
296 }
297 statistics().begin_count(STD_COUNTERS::matrix_assembly,statistics().get_last_opened_counter_level()+1);
298 matrice.ajouter_multvect(inco, resu); // Adding A*Inco(n)
299 // PL (11/04/2018): We would like to compute the source contribution first
300 // as in the VIA_CONTRIBUER_AU_SECOND_MEMBRE case but the Canal_perio_3D case (keps
301 // periodic crashes: there is a periodicity error in the source terms of the KEps model...
302 }
303 else
304 {
305 Cerr << "Unknown value in Convection_Diffusion_Temperature_IBM::assembler for " << (int)type_codage << finl;
307 }
308
309 // to avoid infinite PDF terms when adding A*Inco(n)
310 if ( is_IBM() )
311 for (int i = 0; i < size_s; i++)
312 {
313 if (eq_IBM_->sources()(i).valeur().que_suis_je().find("Source_PDF") > -1)
314 {
315 const Source_base& src_base = eq_IBM_->sources()(i).valeur();
316 src_base.contribuer_a_avec(inco,matrice);
317 }
318 }
319 // add PDF source with the correct sign
321}
const DoubleTab_t & coord_sommets() const
Definition Domaine.h:112
class Domaine_VF
Definition Domaine_VF.h:44
class Domaine_dis_base This class is the base of the hierarchy of discretized domains.
const Domaine & domaine() const
Class defining operators and methods for all reading operation in an input flow (file,...
Definition Entree.h:42
bool initTimeStep_ibm_proto(double ddt)
void modify_initial_variable_ibm_proto(DoubleTab &)
Entree & readOn_ibm_proto(Entree &is, Equation_base &eq)
void assembler_ibm_proto(Matrice_Morse &mat_morse, const DoubleTab &present, DoubleTab &secmem)
void set_param_ibm_proto(Param &param) const
DoubleTab & derivee_en_temps_inco_ibm_proto(DoubleTab &)
class Equation_base The role of an equation is the calculation of one or more fields....
Sources & sources()
Returns the source terms associated with the equation.
virtual DoubleVect & ajouter_multvect(const DoubleVect &x, DoubleVect &r) const
Matrix-vector multiply-accumulate operation (saxpy).
Matrice_Morse class - Represents a (sparse) matrix M, not necessarily square,.
auto & get_set_coeff()
class Nom: a character string for naming TRUST objects.
Definition Nom.h:31
const Nom getSuffix(const char *const) const
Definition Nom.cpp:276
const Nom & le_nom() const override
Returns *this.
Definition Nom.cpp:555
static int dimension
Definition Objet_U.h:94
: class PDF_model
Definition PDF_model.h:34
int pdf_bilan() const
Definition PDF_model.h:41
void affecter_vitesse_shape_IBM(Domaine_VF &, const DoubleTab &, double)
const DoubleTab & get_vitesse_shape_IBM() const
Definition PDF_model.h:46
bool get_PDF_mobile() const
Definition PDF_model.h:42
double raid() const
Definition PDF_model.h:49
int is_vitesse_PDF_donnee() const
Definition PDF_model.h:48
Helper class to factorize the readOn method of Objet_U classes.
Definition Param.h:112
void ajouter(const char *keyword, const int *value, Param::Nature nat=Param::OPTIONAL)
Register an integer parameter.
Definition Param.cpp:364
@ OPTIONAL
Definition Param.h:115
class Probleme_base It is a Probleme_U that is not a coupling.
const Domaine_dis_base & domaine_dis() const
Returns the discretized domain associated with the problem (const version).
static void exit(int exit_code=-1)
Exit routine for TRUST within a Kokkos region.
Definition Process.cpp:466
class Source_PDF_base Base class for the source terms for the penalisation of the momentum in the Imm...
const PDF_model & get_modele() const
void set_sec_mem_pdf(DoubleTab &it)
void update_elem_IBM(DoubleTab &, double, double)
DoubleTab & calculer_pdf(DoubleTab &) const
virtual DoubleTab compute_coeff_matrice() const
virtual void correct_variable(const DoubleTab &, DoubleTab &) const
DoubleTab & calculer(DoubleTab &) const override
Source_base A Source_base object is a term appearing on the right-hand side of an.
Definition Source_base.h:42
virtual void contribuer_a_avec(const DoubleTab &, Matrice_Morse &) const
contribution to the implicit matrix of source terms, by default no contribution
_SIZE_ dimension(int d) const
Definition TRUSTTab.tpp:133
virtual void echange_espace_virtuel(IsExchangeBlocking exchange_type=IsExchangeBlocking::DefaultBlocking, const std::string kernel_name="noname")