TrioCFD 1.9.8
TrioCFD documentation
Loading...
Searching...
No Matches
ALE_BeamCoupling.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#include <ALE_BeamCoupling.h>
16#include <Domaine_VEF.h>
17#include <Navier_Stokes_std.h>
18#include <Operateur_Diff.h>
19#include <Operateur_Grad.h>
20#include <Equation_base.h>
21#include <Process.h>
22#include <communications.h>
23#include <Objet_U.h>
24
25void ALE_BeamCoupling::read(Entree& is, int nb_bords_ALE, const Bords& les_bords_ALE)
26{
27 Motcle accolade_ouverte("{"), accolade_fermee("}"), motlu;
28 Nom nomlu, beam_name = "none";
29
30 is >> motlu;
31 if (motlu != accolade_ouverte)
32 {
33 Cerr << "Error reading the beam model block: expected "
34 << accolade_ouverte << ", got " << motlu << finl;
36 }
37
38 is >> nomlu;
39 motlu = nomlu;
40 if (motlu == "nb_beam")
41 {
42 is >> nbBeam_;
43 if (nbBeam_ > 0) beam_ = std::vector<Beam_model>(nbBeam_);
44 Cerr << "Beam number : " << nbBeam_ << finl;
45 }
46 else
47 {
48 Cerr << "Error reading the beam model block: expected 'nb_beam', got "
49 << motlu << finl;
51 }
52
53 int count = 0;
54 while (1)
55 {
56 is >> nomlu;
57 motlu = nomlu;
58 if (motlu == "Name")
59 {
60 is >> beam_name;
61 // Verify the beam name matches a declared moving boundary
62 bool found = false;
63 for (int n = 0; n < nb_bords_ALE; n++)
64 if (les_bords_ALE(n).le_nom() == beam_name)
65 found = true;
66
67 if (!found)
68 {
69 Cerr << "Beam name '" << beam_name
70 << "' must match a moving boundary declared in 'Imposer_vit_bords_ALE'." << finl;
72 }
73
74 beam_[count].setBeamName(beam_name);
75 Cerr << "Beam name : " << beam_[count].getBeamName() << finl;
76 beam_[count].read_beam(is);
77 count++;
78 }
79 else if (motlu == accolade_fermee)
80 {
81 if (count != nbBeam_)
82 {
83 Cerr << "Read " << count << " beam model(s) but expected " << nbBeam_ << finl;
85 }
86 break;
87 }
88 else
89 {
90 Cerr << "Error reading the beam model: unexpected keyword " << motlu << finl;
92 }
93 }
94}
95
96DoubleTab& ALE_BeamCoupling::getVelocity(const int& i, const double& tps, const double& dt,
97 Equation_base* eqn, bool is_resumption,
98 int nb_bords_ALE, const Bords& les_bords_ALE)
99{
100 const double tempsLast = beam_[i].getTempsComputeForceOnBeam();
101 if (tps != tempsLast && dt != 0.)
102 {
103 // eqn is guaranteed non-null when dt != 0 (Domaine_ALE::initialiser has run by then)
104 assert(eqn != nullptr);
105 computeFluidForce(i, *eqn, is_resumption, nb_bords_ALE, les_bords_ALE);
106 beam_[i].setTempsComputeForceOnBeam(tps);
107 }
108 return beam_[i].getVelocity(tps, dt);
109}
110
111
113 bool is_resumption,
114 int nb_bords_ALE, const Bords& les_bords_ALE)
115{
116 const Navier_Stokes_std& eqn_hydr = ref_cast(Navier_Stokes_std, eqn);
117 const Operateur_base& op_grad = eqn_hydr.operateur_gradient().l_op_base();
118 const Operateur_base& op_diff = eqn_hydr.operateur_diff().l_op_base();
119 const Domaine_VEF& le_dom_vef = ref_cast(Domaine_VEF, op_grad.equation().domaine_dis());
120 const DoubleTab& xv = le_dom_vef.xv();
121 DoubleTab& flux_bords_grad = op_grad.flux_bords();
122 DoubleTab& flux_bords_diff = op_diff.flux_bords();
123
124 const int nbModes = getNbModes(i);
125 const int nb_planes = getNbPlanes(i);
126 const int modes_per_plane = nbModes / nb_planes;
127
128 // On resumption the diffusive flux is zero until the end of the first time step.
129 // Force an update via op_diff.ajouter() to get a meaningful value.
130 if (is_resumption && mp_norme_vect(flux_bords_diff) == 0.)
131 {
132 DoubleTab resu = eqn_hydr.vitesse().valeurs();
133 resu = 0.;
134 op_diff.ajouter(eqn_hydr.vitesse().valeurs(), resu);
135 }
136
137 // Accumulate modal force contributions [modes_per_plane, nb_planes]
138 DoubleTab fluidForceOnBeam(modes_per_plane, nb_planes);
139 fluidForceOnBeam = 0.;
140
141 if (flux_bords_grad.size() == flux_bords_diff.size() && flux_bords_grad.size() > 0)
142 {
143 for (int n = 0; n < nb_bords_ALE; n++)
144 {
145 if (les_bords_ALE(n).le_nom() != beam_[i].getBeamName()) continue;
146
147 const int ndeb = les_bords_ALE(n).num_premiere_face();
148 const int nfin = ndeb + les_bords_ALE(n).nb_faces();
149
150 for (int face = ndeb; face < nfin; face++)
151 for (int plane = 0; plane < nb_planes; ++plane)
152 for (int mode = 0; mode < modes_per_plane; ++mode)
153 {
154 const DoubleTab& u = getDisplacement(i, mode);
155 const int comp = getBendingDirection(i, plane);
156 const double phi = interpolationPhiOnThe3DSurface(
157 i, xv(face,0), xv(face,1), xv(face,2), plane, u);
158 fluidForceOnBeam(mode, plane) +=
159 (flux_bords_grad(face, comp) + flux_bords_diff(face, comp)) * phi;
160 }
161 }
162 }
163
164 Process::mp_sum_for_each_item(fluidForceOnBeam);
165 beam_[i].setFluidForceOnBeam(fluidForceOnBeam);
166
168 beam_[i].printOutputFluidForceOnBeam();
169}
170
171
172double ALE_BeamCoupling::computeDt(Domaine_dis_base& le_domaine_dis, const int& i) const
173{
174 const Domaine_VEF& domaine_VEF = ref_cast(Domaine_VEF, le_domaine_dis);
175 const DoubleVect& surfaces = domaine_VEF.face_surfaces();
176 const double minSurf = Process::mp_min(mp_min_vect(surfaces));
177 // getSoundSpeed() is not const in Beam_model; const_cast is safe (read-only).
178 return 0.5 * (minSurf / const_cast<Beam_model&>(beam_[i]).getSoundSpeed());
179}
180
181
183 const int& i, const double& x, const double& y, const double& z,
184 const DoubleTab& u, const DoubleTab& R) const
185{
186 return beam_[i].interpolationOnThe3DSurface(x, y, z, u, R);
187}
188
190 const int& i, const double& x, const double& y, const double& z,
191 const int& comp, const DoubleTab& u) const
192{
193 return beam_[i].interpolationPhiOnThe3DSurface(x, y, z, comp, u);
194}
DoubleTab interpolationOnThe3DSurface(const int &i, const double &x, const double &y, const double &z, const DoubleTab &u, const DoubleTab &R) const
void read(Entree &is, int nb_bords_ALE, const Bords &les_bords_ALE)
const DoubleTab & getDisplacement(const int &i, const int &j) const
DoubleTab & getVelocity(const int &i, const double &tps, const double &dt, Equation_base *eqn, bool is_resumption, int nb_bords_ALE, const Bords &les_bords_ALE)
double interpolationPhiOnThe3DSurface(const int &i, const double &x, const double &y, const double &z, const int &comp, const DoubleTab &u) const
const int & getBendingDirection(const int &i, const int &idx) const
void computeFluidForce(const int &i, Equation_base &eqn, bool is_resumption, int nb_bords_ALE, const Bords &les_bords_ALE)
const int & getNbPlanes(const int &i) const
double computeDt(Domaine_dis_base &le_domaine_dis, const int &i) const
const int & getNbModes(const int &i) const
double getSoundSpeed()
Definition Beam_model.h:216
int_t nb_faces() const
Renvoie le nombre total de faces de tous les bords de la liste.
Definition Bords.cpp:42
DoubleTab & valeurs() override
Renvoie le tableau des valeurs du champ au temps courant.
class Domaine_VEF
Definition Domaine_VEF.h:54
virtual const DoubleVect & face_surfaces() const
Definition Domaine_VF.h:51
double xv(int num_face, int k) const
Definition Domaine_VF.h:76
classe Domaine_dis_base Cette classe est la base de la hierarchie des domaines discretisees.
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....
Domaine_dis_base & domaine_dis()
Renvoie le domaine discretise associe a l'equation.
const Equation_base & equation() const
Renvoie la reference sur l'equation pointe par MorEqn::mon_equation.
Definition MorEqn.h:62
Une chaine de caractere (Nom) en majuscules.
Definition Motcle.h:26
classe Navier_Stokes_std Cette classe porte les termes de l'equation de la dynamique
virtual const Champ_Inc_base & vitesse() const
Operateur_Grad & operateur_gradient()
Renvoie l'operateur de calcul du gradient associe a l'equation.
Operateur_Diff & operateur_diff()
class Nom Une chaine de caractere pour nommer les objets de TRUST
Definition Nom.h:31
Operateur_base & l_op_base() override
Renvoie l'objet sous-jacent upcaste en Operateur_base.
Operateur_base & l_op_base() override
Renvoie l'objet sous-jacent upcaste en Operateur_base.
classe Operateur_base Classe est la base de la hierarchie des objets representant un
virtual DoubleTab & ajouter(const DoubleTab &, DoubleTab &) const
DoubleTab & flux_bords()
static double mp_min(double)
Definition Process.cpp:386
static void mp_sum_for_each_item(TRUSTArray< _TYPE_ > &x, int n=-1)
Definition Process.cpp:193
static void exit(int exit_code=-1)
Routine de sortie de TRUST dans une region Kokkos.
Definition Process.cpp:455
static int je_suis_maitre()
renvoie 1 si on est sur le processeur maitre du groupe courant (c'est a dire me() == 0),...
Definition Process.cpp:86
_SIZE_ size() const
Definition TRUSTVect.tpp:45