TrioCFD 1.9.8
TrioCFD documentation
Loading...
Searching...
No Matches
Domaine_ALE.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 <Scatter.h>
17#include <MD_Vector_tools.h>
18#include <MD_Vector_std.h>
19#include <Debog.h>
20#include <Domaine_ALE.h>
21#include <Probleme_base.h>
22#include <Schema_Temps_base.h>
23#include <Domaine_VEF.h>
24#include <Domaine_EF.h>
25#include <Domaine_Poly_base.h>
26#include <Motcle.h>
27#include <EFichier.h>
28#include <Champ_front_ALE.h>
29#include <Ch_front_input_ALE.h>
30#include <Champ_front_ALE_Beam.h>
31#include <Equation_base.h>
32#include <Noms.h>
33#include <Navier_Stokes_std.h>
34#include <Operateur_Diff.h>
35#include <Operateur_Grad.h>
36#include <communications.h>
37#include <Faces.h>
38#include <CL_Types_include.h>
39#include <Entree_fluide_vitesse_imposee_ALE.h>
40#include <Interprete_bloc.h>
41#include <NettoieNoeuds.h>
42#include <TRUST_2_MED.h>
43#include <Matrix_tools.h>
44#include <Array_tools.h>
45#include <Champ_front_ALE_lag.h>
46#include <EcritureLectureSpecial.h>
47#include <Avanc.h>
48#include <TRUST_2_PDI.h>
49
50#include <medcoupling++.h>
51#ifdef MEDCOUPLING_
52#include <MEDCouplingMemArray.hxx>
53using namespace MEDCoupling;
54#endif
55
56
57
58
59// (ALE convection grammar is declared as `convection_ale` near
60// Op_Conv_ALE_VEF::Implemente_instanciable — the earlier
61// `bloc_convection_ALE convection_deriv ALE NO_BRACE` + recursive
62// `operateur convection_deriv` shape modelled `convection { ALE
63// muscl }` but tripped on `convection { ALE muscl vanleer 2 }`
64// because the inner muscl had no attrs to absorb the limiter and
65// order. Replaced by the flat positional shape used by
66// convection_generic.)
67
68
69// Large penalization coefficient to enforce Dirichlet-like constraints in the Laplacian system
70namespace { static constexpr double ALE_PENALIZATION = 1.e14; }
71
72Implemente_instanciable_sans_constructeur(Domaine_ALE, "Domaine_ALE", Domaine);
73// XD domaine_ale domaine domaine_ale INHERITS_BRACE Domain with nodes at the interior of the domain which are
74// XD_CONT displaced in an arbitrarily prescribed way thanks to ALE (Arbitrary Lagrangian-Eulerian) description.
75
76
81
83{
85 deformable_ = true;
86
87 dt_ = 0.;
88 ALE_mesh_velocity.reset();
89 vf.reset();
90 som_faces_bords.reset();
91 solv = SolveurSys();
93 nb_bords_ALE = 0;
94 les_bords_ALE.vide();
95 resumption = 0;
96 eq = OBS_PTR(Equation_base)();
101 UpdateTheGrid = true;
103 volumes_old_.reset();
104 volumes_entrelaces_old_.reset();
105 coord_old_.reset();
106
107 beam_coupling_.clear();
108 projection_manager_.clear();
109}
110
112{
114 return os;
115}
116
118{
119 Domaine::readOn(is);
120 return is;
121}
122
123
124void Domaine_ALE::mettre_a_jour(double temps, Domaine_dis_base& le_domaine_dis,
125 Probleme_base& pb)
126{
128
129 // Initialization of the ICoCo coupling method on first call
130 if (Coupling_ICoCo_method == -1)
131 {
132 int res = getCouplingMethod();
133 Cout << "Initialization of Coupling_ICoCo_Method " << res << finl;
134 }
135
136 //--------------------------------------------------------------------------
137 // ICoCo implicit sub-iteration handling: save/reset state at iteration boundaries
138 //--------------------------------------------------------------------------
139 int iCoCoImplicitIteration = -1; // -1 = no ICoCo implicit coupling
140 bool resetCoordinates = false;
141
142 if ((eq.valeur()).probleme().checkOutputIntEntry("iCoCoImplicitIteration"))
143 {
144 iCoCoImplicitIteration = (eq.valeur()).probleme().getOutputIntValue("iCoCoImplicitIteration");
145 Cerr << "Domaine_ALE::mettre_a_jour, iCoCoImplicitIteration: "
146 << iCoCoImplicitIteration << finl;
147 if (meshMotionModel_ == 1)
148 str_mesh_model.iCoCoImplicitIteration = iCoCoImplicitIteration;
149 }
150
151 if (meshMotionModel_ == 1)
152 {
153 str_mesh_model.acceleratedSolution = 0; // Reset to default each step
154 if ((eq.valeur()).probleme().checkOutputIntEntry("acceleratedGridMode"))
155 str_mesh_model.acceleratedSolution =
156 (eq.valeur()).probleme().getOutputIntValue("acceleratedGridMode");
157 }
158
159 if (iCoCoImplicitIteration == 0)
160 {
161 saveSommetsCoordinates(); // Save coordinates at first ICoCo sub-iteration
162 if (meshMotionModel_ == 1) str_mesh_model.saveBeginning_of_stepVariables();
163 }
164 else if (iCoCoImplicitIteration > 0)
165 {
166 resetSommetsCoordinates(); // Reset to beginning-of-step for subsequent iterations
167 resetCoordinates = true;
168 if (meshMotionModel_ == 1)
169 {
170 if (str_mesh_model.acceleratedSolution == 0)
171 str_mesh_model.resetVariablestoBeginning_of_step();
172 else
173 str_mesh_model.gridTime = str_mesh_model.gridTime_n; // Accelerated mode: reset time only
174 }
175 }
176
177 compute_vertex_velocities(temps, pb);
178
179 if (!(mesh_update_required_ || resetCoordinates)) return;
180
181 Cout << "Updating the mesh!" << finl;
182 const double dt = pb.schema_temps().pas_de_temps();
183 update_vertex_coordinates(dt);
184
185 // Recompute all geometric metrics after mesh motion
186 updateMetrics(le_domaine_dis, pb);
187
188 // Recompute face velocities from updated vertex velocities
189 Domaine_VF& le_dom_VF = ref_cast(Domaine_VF, le_domaine_dis);
191 le_dom_VF.nb_som_face(), le_dom_VF.face_sommets());
192
193 update_post_fields(temps, dt);
194
195 // Enforce exact periodicity at periodic face pairs.
196 // Calling verifie_valeurs_cl() here (before the NS operators
197 // run) keeps the periodic constraint tight at every time step.
198 if (eq)
199 {
200 const Domaine_Cl_dis_base& zcl = eq.valeur().domaine_Cl_dis();
201 bool has_periodic = false;
202 for (int cl = 0; cl < zcl.nb_cond_lim() && !has_periodic; cl++)
203 if (sub_type(Periodique, zcl.les_conditions_limites(cl).valeur()))
204 has_periodic = true;
205 if (has_periodic)
206 eq.valeur().inconnue().verifie_valeurs_cl();
207 }
208}
209
210
212{
213 if (!eq) eq = pb.equation(0);
214 metrics_updater_.update(le_domaine_dis, pb, *this);
215}
216
217
219{
220 // Compute and write modal fluid forces for all projection boundaries
222}
223
224
225
226void Domaine_ALE::update_ALE_projection(double temps, Nom& name_ALE_boundary_projection,
227 Champ_front_ALE_projection& field_ALE_projection,
228 int nb_mode)
229{
230 projection_manager_.update(temps, name_ALE_boundary_projection, field_ALE_projection,
231 nb_mode, nb_bords_ALE, les_bords_ALE,
233}
234
239
240
241
242void Domaine_ALE::update_post_fields(double temps, double dt)
243{
244 const DoubleTab& ALEMeshVelocity = vitesse_faces();
245
246 if (ALEMeshVelocity_)
247 {
248 ALEMeshVelocity_->valeurs() = ALEMeshVelocity;
249 ALEMeshVelocity_->mettre_a_jour(temps);
250 }
251
252 if (ALEMeshTotalDisplacement_)
253 {
254 // Integrate mesh velocity: disp_{n+1} = disp_n + dt * v_mesh
255 const int D = dimension;
256 const int N = ALEMeshVelocity.size() / D;
257 DoubleTab& disp = ALEMeshTotalDisplacement_->valeurs();
258 for (int i = 0; i < N; i++)
259 for (int d = 0; d < D; d++)
260 disp(i, d) += ALEMeshVelocity(i, d) * dt;
262 ALEMeshTotalDisplacement_->mettre_a_jour(temps);
263 }
264
265 if (meshMotionModel_ == 1)
266 {
267 if (ALEMeshStructuralPressure_)
268 ALEMeshStructuralPressure_->valeurs() = getMeshPbPressure();
269 if (ALEMeshStructuralVonMises_)
270 ALEMeshStructuralVonMises_->valeurs() = getMeshPbVonMises();
271 if (ALEMeshStructuralForces_)
272 ALEMeshStructuralForces_->valeurs() = getMeshPbForceFace();
273 }
274}
275
276
277void Domaine_ALE::validate_ale_setup(const Probleme_base& pb) const
278{
279 // Ensure Neumann boundaries are not also declared as moving boundaries
281 for (int i = 0; i < neumann.size(); i++)
282 for (int j = 0; j < nb_bords_ALE; j++)
283 if (les_bords_ALE(j).le_nom() == neumann[i])
284 {
285 Cerr << "In 'ALE_Neumann_BC_for_grid_problem', boundary " << neumann[i]
286 << " is already declared as a moving boundary in 'Imposer_vit_bords_ALE'." << finl;
288 }
289
290 // Check discretization compatibility
291 if (!(sub_type(Domaine_VEF, pb.domaine_dis()) ||
293 pb.discretisation().is_ef()))
294 {
295 Cerr << "Discretization not recognized by ALE!" << finl;
296 Cerr << "Use VEFPreP1B, PolyMAC_P0 or EF and restart." << finl;
298 }
299
300 // Check that moving boundaries use the correct boundary condition type
301 const Domaine_Cl_dis_base& dom_cl = pb.equation(0).domaine_Cl_dis();
302 for (int j = 0; j < nb_bords_ALE; j++)
303 {
304 const Nom& le_nom = les_bords_ALE(j).le_nom();
305 const int rang = rang_frontiere(le_nom);
306 if (rang >= faces_bord().size()) continue; // internal boundary, skip
307 const Cond_lim& la_cl = dom_cl.les_conditions_limites(rang);
308 if (!sub_type(Entree_fluide_vitesse_imposee_ALE, la_cl.valeur()))
309 Cerr << "Mobile ALE boundary: replace " << la_cl->que_suis_je()
310 << " on " << le_nom << " with Frontiere_ouverte_vitesse_imposee_ALE" << finl;
311 }
312
313 if (les_champs_front.size() == 0)
314 Cerr << "Warning: ALE simulation without any moving boundary!" << finl;
315}
316
317void Domaine_ALE::initialiser(double temps, Domaine_dis_base& le_domaine_dis,
318 Probleme_base& pb)
319{
320 const bool initialized = (vf.size_array() != 0);
321 if (initialized) return;
322
323 Cerr << "Domaine_ALE::initialize" << finl;
324 validate_ale_setup(pb);
326 eq = pb.equation(0);
327
328 Domaine_VF& le_dom_VF = ref_cast(Domaine_VF, le_domaine_dis);
329 const int nb_faces = le_dom_VF.nb_faces();
330 const int nb_faces_tot = le_dom_VF.nb_faces_tot();
331 const int nb_som_face = le_dom_VF.nb_som_face();
332 IntTab& face_sommets = le_dom_VF.face_sommets();
333
334 // Initialize vertex and face velocity arrays with proper parallel distribution
335 const MD_Vector& mds = md_vector_sommets();
336 MD_Vector_tools::creer_tableau_distribue(mds, laplacian_rhs_);
337 ALE_mesh_velocity.resize(0, dimension);
339 vf.resize(nb_faces, dimension);
341
342 // Snapshot initial metrics for the first time step's volume corrections
343 coord_old_ = sommets_;
344 volumes_old_ = le_dom_VF.volumes();
345 volumes_entrelaces_old_ = le_dom_VF.volumes_entrelaces();
346 if (pb.discretisation().is_ef())
347 volumes_sommets_thilde_old_ = ref_cast(Domaine_EF, le_dom_VF).volumes_sommets_thilde();
348
349 if (meshMotionModel_ == 1)
350 {
351 // Initialize the fictitious structural problem for mesh motion
352 str_mesh_model.initMfrontBehaviour();
353 str_mesh_model.initDynamicMeshProblem(
354 temps, nb_som(), nb_elem(), nb_faces,
355 mds, md_vector_elements(), le_dom_VF.md_vector_faces());
356 }
357
358 if (lagrangian_velocity_imposed_)
359 {
360#ifdef MEDCOUPLING_
361 const Probleme_base& pb_v = ref_cast(Probleme_base, interprete().objet(external_pb_name_));
362 const Champ_base& champ = pb_v.get_champ(external_velocity_field_name_);
363 build_lagrangian_vertex_mapping(pb_v, champ);
364#else
365 Cerr << "Domaine_ALE::initialiser : MEDCoupling required for imposed Lagrangian velocity." << finl;
367#endif
368 }
369
370 // Compute initial mesh velocities (using resumption time if restarting)
371 if (resumption)
372 compute_vertex_velocities(pb.schema_temps().temps_courant(), pb);
373 else
374 compute_vertex_velocities(temps, pb);
375
376 calculer_vitesse_faces(ALE_mesh_velocity, nb_faces_tot, nb_som_face, face_sommets);
377
378 // Initialize Ch_front_input_ALE fields if present
379 for (int i = 0; i < les_champs_front.size(); i++)
380 {
381 Champ_front_base& field = les_champs_front[i].valeur();
382 if (sub_type(Ch_front_input_ALE, field))
383 {
384 const Champ_Inc_base& vit = ref_cast(Champ_Inc_base, pb.get_champ("VITESSE"));
385 ref_cast(Ch_front_input_ALE, field).initialiser(temps, vit);
386 }
387 }
388}
389
390DoubleTab& Domaine_ALE::calculer_vitesse_faces(DoubleTab& vit_maillage, int nb_faces,
391 int nb_som_face, IntTab& face_sommets)
392{
393 vf = 0.;
394 // If the mesh velocity is essentially zero, face velocity stays zero (default).
395 if (vit_maillage.mp_max_abs_vect() >= 1.e-12)
396 for (int j = 0; j < dimension; j++)
397 for (int i = 0; i < nb_faces; i++)
398 {
399 for (int s = 0; s < nb_som_face; s++)
400 vf(i, j) += vit_maillage(face_sommets(i, s), j);
401 vf(i, j) /= nb_som_face;
402 }
403
404 vf.echange_espace_virtuel();
405 Debog::verifier("Domaine_ALE::calculer_vitesse_faces", vf);
406 return vf;
407}
408
409void Domaine_ALE::set_dt(double& dt) { dt_ = dt; }
410
411
413{
415 if (eq)
416 {
417 // Snapshot metrics so that volume corrections use V_n while the solver uses V_{n+1}
418 Domaine_VF& le_dom_VF = ref_cast(Domaine_VF, eq->domaine_dis());
419 coord_old_ = sommets_;
420 volumes_old_ = le_dom_VF.volumes();
421 if (!eq->probleme().discretisation().is_ef())
422 volumes_entrelaces_old_ = le_dom_VF.volumes_entrelaces();
423 else
424 volumes_sommets_thilde_old_ = ref_cast(Domaine_EF, le_dom_VF).volumes_sommets_thilde();
425 }
426 resumption = 0;
427}
428
429
430void Domaine_ALE::ajouter_correctif_volumique(const DoubleTab& v, const DoubleTab& derivee,
431 double dt, DoubleTab& deriveeALE) const
432{
433 // ALE volume correction: (V_n / V_{n+1}) * (U_n / dt) + derivee
434 const DoubleVect& volumes_entrelaces =
435 ref_cast(Domaine_VF, eq->domaine_dis()).volumes_entrelaces();
436 const int nf_tot = v.dimension_tot(0);
437 for (int f = 0; f < nf_tot; f++)
438 for (int d = 0; d < dimension; d++)
439 deriveeALE(f, d) = v(f, d) * volumes_entrelaces_old_(f) / volumes_entrelaces(f) / dt
440 + derivee(f, d);
441
442 // Enforce periodicity: the V_old/V_new ratio can differ slightly between periodic
443 // partner faces when the ALE mesh deforms non-uniformly, breaking the symmetry that
444 // Op_Div_VEFP1B_Elem::ajouter requires. Average each periodic pair so that both
445 // partners carry the same value, consistent with how verifie_valeurs_cl treats velocity.
446 if (eq)
447 {
448 const Domaine_Cl_dis_base& zcl = eq.valeur().domaine_Cl_dis();
449 for (int i = 0; i < zcl.nb_cond_lim(); i++)
450 {
451 const Cond_lim_base& la_cl = zcl.les_conditions_limites(i).valeur();
452 if (sub_type(Periodique, la_cl))
453 {
454 const Periodique& la_cl_perio = ref_cast(Periodique, la_cl);
455 const Front_VF& le_bord = ref_cast(Front_VF, la_cl.frontiere_dis());
456 int ndeb = le_bord.num_premiere_face();
457 int nfin = ndeb + le_bord.nb_faces();
458 for (int f = ndeb; f < nfin; f++)
459 {
460 int fass = la_cl_perio.face_associee(f - ndeb) + ndeb;
461 for (int d = 0; d < dimension; d++)
462 {
463 double moy = 0.5 * (deriveeALE(f, d) + deriveeALE(fass, d));
464 deriveeALE(f, d) = moy;
465 deriveeALE(fass, d) = moy;
466 }
467 }
468 }
469 }
470 }
471}
472
474 const Domaine_dis_base& ddb) const
475{
476 const Domaine_VF& dvf = ref_cast(Domaine_VF, ddb);
477 const int I = inco.dimension_tot(0);
478 const int N = inco.dimension(1);
479
480 if (I == nb_elem_tot())
481 {
482 // Cell-centered: scale by V_n / V_{n+1}
483 const DoubleVect& volumes = dvf.volumes();
484 for (int e = 0; e < I; e++)
485 for (int n = 0; n < N; n++)
486 inco(e, n) *= volumes_old_(e) / volumes(e);
487 }
488 else if (I == dvf.nb_faces_tot())
489 {
490 const DoubleVect& ve = dvf.volumes_entrelaces();
491 for (int f = 0; f < I; f++)
492 for (int n = 0; n < N; n++)
493 inco(f, n) *= volumes_entrelaces_old_(f) / ve(f);
494 }
495 else if (I == dvf.nb_som_tot())
496 {
497 const DoubleVect& vs = ref_cast(Domaine_EF, dvf).volumes_sommets_thilde();
498 for (int s = 0; s < I; s++)
499 for (int n = 0; n < N; n++)
500 inco(s, n) *= volumes_sommets_thilde_old_(s) / vs(s);
501 }
502 else
503 {
504 Cerr << "Domaine_ALE::apply_old_to_new_volume_scaling: incompatible dimension "
505 << I << " (expected " << nb_elem_tot() << ", " << dvf.nb_faces_tot() << ")." << finl;
507 }
508}
509
510//////////////////////////////////////////////////////////////////////////////
511// Structural dynamics field accessors (forwarded to str_mesh_model)
512//////////////////////////////////////////////////////////////////////////////
513
515 double tinit, DoubleTab& u_n, DoubleTab& v_n, DoubleTab& a_n,
516 DoubleTab& x_n, DoubleTab& B0_n, DoubleTab& Ft_n, DoubleTab& Stress_n)
517{
518 str_mesh_model.resumptionMesh(tinit, u_n, v_n, a_n, x_n, B0_n, Ft_n, Stress_n);
519}
520
521const DoubleVect& Domaine_ALE::getMeshPbPressure() const { return str_mesh_model.getMeshPbPressure(); }
522const DoubleVect& Domaine_ALE::getMeshPbVonMises() const { return str_mesh_model.getMeshPbVonMises(); }
523const DoubleTab& Domaine_ALE::getMeshPbForceFace() const { return str_mesh_model.getMeshPbForceFace(); }
524const DoubleTab& Domaine_ALE::getMeshDisplacement() const { return str_mesh_model.getMeshDisplacement(); }
525const DoubleTab& Domaine_ALE::getMeshVelocity() const { return str_mesh_model.getMeshVelocity(); }
526const DoubleTab& Domaine_ALE::getMeshAcceleration() const { return str_mesh_model.getMeshAcceleration(); }
527const DoubleTab& Domaine_ALE::getMeshPosition() const { return str_mesh_model.getMeshPosition(); }
528const DoubleTab& Domaine_ALE::getMeshReferenceConfiguration() const { return str_mesh_model.getMeshReferenceConfiguration(); }
529const DoubleTab& Domaine_ALE::getMeshTransformationGradient() const { return str_mesh_model.getMeshTransformationGradient(); }
530const DoubleTab& Domaine_ALE::getMeshStress() const { return str_mesh_model.getMeshStress(); }
531const int& Domaine_ALE::getMeshReferenceConfigurationNbComp() const { return str_mesh_model.getMeshReferenceConfigurationNbComp(); }
532const int& Domaine_ALE::getMeshTransformationGradientNbComp() const { return str_mesh_model.getMeshTransformationGradientNbComp(); }
533const int& Domaine_ALE::getMeshStressNbComp() const { return str_mesh_model.getMeshStressNbComp(); }
534
535//////////////////////////////////////////////////////////////////////////////
536// Beam accessors (forwarded to beam_coupling_)
537//////////////////////////////////////////////////////////////////////////////
538
539const Nom& Domaine_ALE::getBeamName (const int& i) const { return beam_coupling_.getName(i); }
540const int& Domaine_ALE::getBeamNbModes (const int& i) const { return beam_coupling_.getNbModes(i); }
541const int& Domaine_ALE::getBeamNbPlanes (const int& i) const { return beam_coupling_.getNbPlanes(i); }
542const int& Domaine_ALE::getBeamNbBeam () const { return beam_coupling_.getNbBeam(); }
543const int& Domaine_ALE::getBeamLongitudinalAxis(const int& i) const { return beam_coupling_.getLongitudinalAxis(i); }
544const int& Domaine_ALE::getBeamBendingDirection(const int& i, const int& idx) const { return beam_coupling_.getBendingDirection(i, idx); }
545const DoubleTab& Domaine_ALE::getBeamDisplacement(const int& i, const int& j) const { return beam_coupling_.getDisplacement(i, j); }
546const DoubleTab& Domaine_ALE::getBeamRotation (const int& i, const int& j) const { return beam_coupling_.getRotation(i, j); }
547
548DoubleTab& Domaine_ALE::getBeamVelocity(const int& i, const double& tps, const double& dt)
549{
550 // eq may be null during BC initialization at t=0 (before Domaine_ALE::initialiser runs).
551 // getVelocity only dereferences eqn when dt != 0, so passing nullptr is safe here.
552 Equation_base* eqn = eq ? &eq.valeur() : nullptr;
553 return beam_coupling_.getVelocity(i, tps, dt, eqn, is_resumption(), nb_bords_ALE, les_bords_ALE);
554}
555
557{
559}
560
561double Domaine_ALE::computeDtBeam(Domaine_dis_base& le_domaine_dis, const int& i)
562{
563 return beam_coupling_.computeDt(le_domaine_dis, i);
564}
565
567 const int& i, const double& x, const double& y, const double& z,
568 const DoubleTab& u, const DoubleTab& R) const
569{
570 return beam_coupling_.interpolationOnThe3DSurface(i, x, y, z, u, R);
571}
572
574 const int& i, const double& x, const double& y, const double& z,
575 const int& comp, const DoubleTab& u) const
576{
577 return beam_coupling_.interpolationPhiOnThe3DSurface(i, x, y, z, comp, u);
578}
579
581{
582 return eq;
583}
584
586{
587 return eq;
588}
589
590//////////////////////////////////////////////////////////////////////////////
591// Checkpoint delegates
592//////////////////////////////////////////////////////////////////////////////
593
594std::vector<YAML_data> Domaine_ALE::data_a_sauvegarder(const Probleme_base& pb) const
595{
596 return checkpoint_manager_.data_a_sauvegarder(pb, *this);
597}
598
600{
601 if (!eq) eq = pb.equation(0);
602 return checkpoint_manager_.save(os, pb, *this);
603}
604
606{
607 resumption = 1;
608 if (!eq) eq = pb.equation(0);
609 return checkpoint_manager_.restore(is, pb, *this);
610}
611
613 const Probleme_base& pb) const
614{
615 return checkpoint_manager_.generate_field_tag(champ, pb);
616}
617
618YAML_data Domaine_ALE::make_yaml(const std::string& suffix, int nb_dim,
619 const Probleme_base& pb) const
620{
621 return checkpoint_manager_.make_yaml(suffix, nb_dim, pb);
622}
623
624void Domaine_ALE::create_field(OWN_PTR(Champ_Inc_base)& champ, const std::string& name,
625 int nbComp, const Motcle& directive,
626 const Probleme_base& pb) const
627{
628
629 checkpoint_manager_.create_field(champ, name, nbComp, directive, pb,
630 const_cast<Domaine_ALE&>(*this));
631}
632
633//////////////////////////////////////////////////////////////////////////////
634// Resumption Coordinates
635//////////////////////////////////////////////////////////////////////////////
636
637
638void Domaine_ALE::resumptionCoords(DoubleTab& ValueOf_MeshCoords)
639{
640 coord_old_ = sommets_;
641 const int nbValues = ValueOf_MeshCoords.size() / dimension;
642 for (int i = 0; i < nbValues; i++)
643 for (int k = 0; k < dimension; k++)
644 coord(i, k) = ValueOf_MeshCoords(i, k);
645}
646
647
649{
650 Motcle accolade_ouverte("{"), accolade_fermee("}"), motlu;
651 Nom nomlu;
652
653 is >> motlu;
654 if (motlu != accolade_ouverte)
655 {
656 Cerr << "Error reading moving boundary velocities: expected "
657 << accolade_ouverte << ", got " << motlu << finl;
659 }
660
661 is >> nb_bords_ALE;
662 Cerr << "Number of ALE boundaries : " << nb_bords_ALE << finl;
663 les_champs_front.dimensionner(nb_bords_ALE);
664
665 int compteur = 0;
666 while (1)
667 {
668 is >> nomlu;
669 motlu = nomlu;
670 if (motlu == accolade_fermee) break;
671 Cerr << "Reading velocity imposed on " << nomlu << "..." << finl;
673 is >> les_champs_front[compteur++];
674 }
675}
676
678{
679 Motcle accolade_ouverte("{"), accolade_fermee("}"), motlu;
680 Nom nomlu;
681
682 is >> motlu;
683 if (motlu != accolade_ouverte)
684 {
685 Cerr << "Error reading ALE mesh solver: expected "
686 << accolade_ouverte << ", got " << motlu << finl;
688 }
689
690 is >> solv;
691 solv.nommer("ALE_solver");
692
693 while (1)
694 {
695 is >> nomlu;
696 motlu = nomlu;
697 if (motlu == accolade_fermee) break;
698 }
699}
700
705
707{
708 projection_manager_.read_projection_boundary(is);
709}
710
715
717{
719
720 Motcle accolade_ouverte("{"), accolade_fermee("}"), motlu;
721 Nom nomlu;
722 double var_double;
723 std::vector<double> val_prop;
724
725 is >> motlu;
726 if (motlu != accolade_ouverte)
727 {
728 Cerr << "Error reading structural dynamic mesh model: expected "
729 << accolade_ouverte << ", got " << motlu << finl;
731 }
732
733 while (1)
734 {
735 is >> nomlu;
736 motlu = nomlu;
737
738 if (motlu == "Mfront_library")
739 { is >> nomlu; str_mesh_model.setMfrontLibraryPath(nomlu.getString()); continue; }
740 if (motlu == "Mfront_model_name")
741 { is >> nomlu; str_mesh_model.setMfrontModelName(nomlu.getString()); continue; }
742 if (motlu == "Mfront_hypothesis")
743 { is >> nomlu; str_mesh_model.setMfrontHypothesis(nomlu.getString()); continue; }
744 if (motlu == "Mfront_material_property")
745 {
746 is >> motlu;
747 if (motlu != accolade_ouverte)
748 { Cerr << "Error: expected { in Mfront_material_property" << finl; Process::exit(); }
749 is >> nomlu;
750 std::string nom_prop(nomlu);
751 val_prop.clear();
752 is >> var_double;
753 while (1)
754 {
755 val_prop.push_back(var_double);
756 is >> motlu;
757 if (motlu == accolade_fermee) break;
758 var_double = std::stod(motlu.getString());
759 }
760 str_mesh_model.addMaterialProperty(nom_prop, val_prop);
761 continue;
762 }
763 if (motlu == "Density")
764 { is >> var_double; str_mesh_model.setDensity(var_double); continue; }
765 if (motlu == "Inertial_Damping")
766 { is >> var_double; str_mesh_model.setInertialDamping(var_double); continue; }
767 if (motlu == "Time_Step_Safety_Coefficient")
768 { is >> var_double; str_mesh_model.setDtSafetyCoefficient(var_double); continue; }
769 if (motlu == "Grid_Dt_Min")
770 { is >> var_double; str_mesh_model.setGridDtMin(var_double); continue; }
771 if (motlu == "Configuration_Reset_Dt")
772 { is >> var_double; str_mesh_model.setConfigurationResetDt(var_double); continue; }
773 if (motlu == "Max_Added_Mass_Ratio")
774 { is >> var_double; str_mesh_model.setMaxAddedMassRatio(var_double); continue; }
775 if (motlu == accolade_fermee) break;
776 }
777
778 if (str_mesh_model.getDensity() == 0.)
779 { Cerr << "Error: density not provided in structural dynamic mesh model." << finl; Process::exit(); }
780}
781
782//////////////////////////////////////////////////////////////////////////////
783// ICoCo coupling
784//////////////////////////////////////////////////////////////////////////////
785
787{
788 if (Coupling_ICoCo_method == -1) // First call: initialize from ICoCo or use default
789 {
790 Probleme_base& pb_base = (eq.valeur()).probleme();
791 if (pb_base.checkOutputIntEntry("CouplingMethod"))
792 {
793 Coupling_ICoCo_method = pb_base.getOutputIntValue("CouplingMethod");
794 Cerr << "Coupling Method set to " << Coupling_ICoCo_method << " from ICoCo" << finl;
795 }
796 else
797 {
799 Cerr << "Coupling Method set to " << Coupling_ICoCo_method << " (default)" << finl;
800 }
801 }
803}
804
806{
807 return (Coupling_ICoCo_method == 1);
808}
809
811{
812 Probleme_base& pb_base = (eq.valeur()).probleme();
813 if (pb_base.checkOutputIntEntry("UpdateTheGrid"))
814 if (pb_base.getOutputIntValue("UpdateTheGrid") == 1)
815 {
816 Cerr << "Update of the fluid grid forced from ICoCo" << finl;
817 UpdateTheGrid = true;
818 }
819 return UpdateTheGrid;
820}
821
823
824//////////////////////////////////////////////////////////////////////////////
825// Lagrangian external velocity coupling
826//////////////////////////////////////////////////////////////////////////////
827
828void Domaine_ALE::associer_vitesse_lagrangienne(const Nom& nom_pb, const Nom& nom_champ)
829{
830 external_pb_name_ = nom_pb;
831 external_velocity_field_name_ = nom_champ;
832 lagrangian_velocity_imposed_ = true;
833}
834
835void Domaine_ALE::check_external_vertex_velocity_compatibility(const DoubleTab& valeurs) const
836{
837 if (valeurs.line_size() != dimension)
838 {
839 Cerr << "Domaine_ALE: Lagrangian velocity field must have " << dimension
840 << " components per node (line_size=" << valeurs.line_size() << ")." << finl;
842 }
843}
844
845void Domaine_ALE::build_lagrangian_vertex_mapping(const Probleme_base& pb_v,
846 const Champ_base& champ)
847{
848#ifndef MEDCOUPLING_
849 Cerr << "Domaine_ALE::build_lagrangian_vertex_mapping: MEDCoupling required." << finl;
851#else
852 const DoubleTab& ext_coords = pb_v.domaine().les_sommets();
853 const DoubleTab& ale_coords = sommets_;
854 const DoubleTab& valeurs = champ.valeurs();
855
856 check_external_vertex_velocity_compatibility(valeurs);
857 if (valeurs.dimension(0) != ext_coords.dimension(0))
858 {
859 Cerr << "Domaine_ALE: external velocity field has " << valeurs.dimension(0)
860 << " nodes but domain has " << ext_coords.dimension(0) << " nodes." << finl;
862 }
863
864 const int nb_ext = ext_coords.dimension(0);
865 const int nb_ale = ale_coords.dimension(0);
866 const int dim = dimension;
867 const double tol = Objet_U::precision_geom * 100.;
868
869 external_vertex_id_for_ale_vertex_.resize(nb_ale);
870 external_vertex_id_for_ale_vertex_ = -1;
871
872 int unmatched = 0;
873 if (nb_ext == 0)
874 {
875 unmatched = nb_ale;
876 }
877 else
878 {
879 // Use MEDCoupling nearest-neighbor search for efficiency
880 MCAuto<DataArrayDouble> ext_pts(DataArrayDouble::New());
881 MCAuto<DataArrayDouble> ale_pts(DataArrayDouble::New());
882 ext_pts->alloc(nb_ext, dim);
883 ale_pts->alloc(nb_ale, dim);
884
885 double* ext_ptr = ext_pts->getPointer();
886 for (int i = 0; i < nb_ext; i++)
887 for (int d = 0; d < dim; d++)
888 ext_ptr[i * dim + d] = ext_coords(i, d);
889
890 double* ale_ptr = ale_pts->getPointer();
891 for (int i = 0; i < nb_ale; i++)
892 for (int d = 0; d < dim; d++)
893 ale_ptr[i * dim + d] = ale_coords(i, d);
894
895 MCAuto<DataArrayIdType> closest(ext_pts->findClosestTupleId(ale_pts));
896 const double tol2 = tol * tol;
897
898 for (int i = 0; i < nb_ale; i++)
899 {
900 const int j = static_cast<int>(closest->getIJ(i, 0));
901 double dist2 = 0.;
902 for (int d = 0; d < dim; d++)
903 {
904 const double diff = ale_coords(i, d) - ext_coords(j, d);
905 dist2 += diff * diff;
906 }
907 if (dist2 <= tol2)
908 external_vertex_id_for_ale_vertex_[i] = j;
909 else
910 unmatched++;
911 }
912 }
913
914 const int total_unmatched = static_cast<int>(mp_sum(unmatched));
915 if (total_unmatched > 0)
916 Cerr << "Domaine_ALE: " << total_unmatched
917 << " ALE nodes have no external match (tol=" << tol << ")." << finl;
918#endif
919}
920
921
922void Domaine_ALE::compute_vertex_velocities(double temps, const Probleme_base& pb)
923{
924 if (lagrangian_velocity_imposed_)
925 {
926#ifdef MEDCOUPLING_
927 const Probleme_base& pb_v = ref_cast(Probleme_base, interprete().objet(external_pb_name_));
928 const DoubleTab& valeurs = pb_v.get_champ(external_velocity_field_name_).valeurs();
930 for (int i = 0; i < nb_som(); i++)
931 {
932 const int j = external_vertex_id_for_ale_vertex_[i];
933 if (j < 0) continue;
934 for (int d = 0; d < dimension; d++)
935 ALE_mesh_velocity(i, d) = valeurs(j, d);
936 }
937 ALE_mesh_velocity.echange_espace_virtuel();
938 mesh_update_required_ = (ALE_mesh_velocity.mp_max_abs_vect() >= 1.e-12);
939 return;
940#else
941 Cerr << "Domaine_ALE::compute_vertex_velocities: MEDCoupling required." << finl;
943#endif
944 }
945
946 DoubleTab vit_bords(ALE_mesh_velocity);
947 remplir_vitesse_bord(pb, temps, vit_bords);
948 mesh_update_required_ = (vit_bords.mp_max_abs_vect() >= 1.e-12);
949 if (!mesh_update_required_ && pb.schema_temps().nb_pas_dt() > 1) return;
950
951 switch (meshMotionModel_)
952 {
953 case -1: // Boundary-only: interior nodes stay fixed
954 ALE_mesh_velocity = vit_bords;
955 break;
956 case 0: // Laplacian propagation
957 laplacien(pb, vit_bords);
958 break;
959 case 1: // Structural dynamics propagation
960 structural_dynamics(pb, vit_bords, temps);
961 break;
962 default:
963 Cerr << "Unknown ALE mesh motion model: " << meshMotionModel_ << finl;
965 }
966
967 Debog::verifier("Domaine_ALE::compute_vertex_velocities", ALE_mesh_velocity);
968}
969
970void Domaine_ALE::remplir_vitesse_bord(const Probleme_base& pb, double temps,
971 DoubleTab& vit_bords)
972{
973 const int N_som = nb_som_tot();
974 vit_bords = 0.;
975
976 for (int n = 0; n < nb_bords_ALE; n++)
977 {
978 const Nom& le_nom = les_bords_ALE(n).le_nom();
979 const int rang = rang_frontiere(le_nom);
980 les_champs_front[n]->associer_fr_dis_base(pb.domaine_dis().frontiere_dis(rang));
981
982 DoubleTab vit_bord_ale;
983 const Nom& type = les_champs_front[n]->que_suis_je();
984
985 if (type == "Champ_front_ALE")
986 {
987 auto& c = ref_cast(Champ_front_ALE, les_champs_front[n].valeur());
988 c.remplir_vit_som_bord_ALE(temps);
989 vit_bord_ale = c.get_vit_som_bord_ALE();
990 }
991 else if (type == "Champ_front_ALE_lag")
992 {
993 auto& c = ref_cast(Champ_front_ALE_lag, les_champs_front[n].valeur());
994 c.remplir_vit_som_bord_ALE(temps);
995 vit_bord_ale = c.get_vit_som_bord_ALE();
996 }
997 else if (type == "Ch_front_input_ALE")
998 {
999 auto& c = ref_cast(Ch_front_input_ALE, les_champs_front[n].valeur());
1000 c.remplir_vit_som_bord_ALE(temps);
1001 vit_bord_ale = c.get_vit_som_bord_ALE();
1002 }
1003 else if (type == "Champ_front_ALE_Beam")
1004 {
1005 if (!eq) eq = pb.equation(0);
1006 auto& c = ref_cast(Champ_front_ALE_Beam, les_champs_front[n].valeur());
1007 c.remplir_vit_som_bord_ALE(temps);
1008 vit_bord_ale = c.get_vit_som_bord_ALE();
1009 }
1010 else
1011 {
1012 Cerr << "Unknown Champ_front_base type for moving boundary "
1013 << le_nom << ": " << type << finl;
1014 Process::exit();
1015 }
1016
1017 // Accumulate: if multiple boundaries share nodes, only the first non-zero value is kept
1018 for (int dim = 0; dim < dimension; dim++)
1019 for (int i = 0; i < N_som; i++)
1020 if (les_champs_front.size() == 1 || vit_bords(i, dim) == 0.)
1021 vit_bords(i, dim) += vit_bord_ale(i, dim);
1022 }
1023
1024 vit_bords.echange_espace_virtuel();
1025}
1026
1027void Domaine_ALE::update_vertex_coordinates(double dt)
1028{
1029 // Explicit Euler update: X_{n+1} = X_n + dt * v_mesh
1030 sommets_ = coord_old_;
1031 const int N_som = nb_som_tot();
1032 for (int i = 0; i < N_som; i++)
1033 for (int d = 0; d < dimension; d++)
1034 coord(i, d) += ALE_mesh_velocity(i, d) * dt;
1035}
1036
1037//////////////////////////////////////////////////////////////////////////////
1038// Laplacian mesh motion
1039//////////////////////////////////////////////////////////////////////////////
1040
1041void Domaine_ALE::laplacien(const Probleme_base& pb, const DoubleTab& vit_bords)
1042{
1043 const Domaine_VF& dom_VF = ref_cast(Domaine_VF, pb.domaine_dis());
1044 const Domaine_Cl_dis_base& cl = pb.equation(0).domaine_Cl_dis();
1045 fill_laplacian_matrix(dom_VF, cl);
1046 laplacien_compute_vertex_velocity(dom_VF, cl, vit_bords);
1047 Debog::verifier("Domaine_ALE::laplacien", ALE_mesh_velocity);
1048}
1049
1050void Domaine_ALE::build_laplacian_matrix(const Domaine_VF& le_dom_VF,
1051 const Domaine_Cl_dis_base& dom_cl)
1052{
1053 const int ne_tot = nb_elem_tot();
1054 const int nb_som_ele = nb_som_elem();
1055 const IntTab& e_s = les_elems();
1056
1057 // Build sparsity pattern from vertex pairs sharing an element
1058 Stencil stencil(0, 2);
1059 for (int e = 0; e < ne_tot; e++)
1060 for (int is = 0; is < nb_som_ele; is++)
1061 for (int js = is + 1; js < nb_som_ele; js++)
1062 {
1063 int i = e_s(e, is), j = e_s(e, js);
1064 if (i > j) { int tmp = i; i = j; j = tmp; }
1065 stencil.append_line(i, j);
1066 stencil.append_line(j, i);
1067 stencil.append_line(i, i);
1068 stencil.append_line(j, j);
1069 }
1070
1071 tableau_trier_retirer_doublons(stencil);
1072 Matrice_Morse mat;
1074 laplacian_matrix_ = Matrice_Morse_Sym(mat);
1075 laplacian_matrix_.set_est_definie(1);
1076 Cout << "Domaine_ALE::build_laplacian_matrix: " << laplacian_matrix_.nb_lignes()
1077 << " rows, " << laplacian_matrix_.nb_colonnes() << " columns." << finl;
1078}
1079
1080void Domaine_ALE::fill_laplacian_matrix(const Domaine_VF& le_dom_VF,
1081 const Domaine_Cl_dis_base& dom_cl)
1082{
1083 if (laplacian_matrix_.nb_lignes() != nb_som_tot())
1084 build_laplacian_matrix(le_dom_VF, dom_cl);
1085
1086 laplacian_matrix_.get_set_coeff() = 0.0;
1087
1088 const int ne_tot = nb_elem_tot();
1089 const int nb_som_ele = nb_som_elem();
1090 const IntTab& e_f = le_dom_VF.elem_faces();
1091 const IntTab& e_s = les_elems();
1092 const DoubleTab& normales = le_dom_VF.face_normales();
1093 // In P1 vertex-based FEM on simplices, the gradient of shape function phi_i (associated
1094 // with node i, opposite to face i) is: grad(phi_i) = -n_i / (d * |K|)
1095 // where n_i is the outward face normal (with magnitude = face area) and d = space dimension.
1096 // The stiffness integral gives: int_K grad(phi_i).grad(phi_j) dK = (n_i.n_j) / (d^2 * |K|)
1097 // hence mijK = 1/d^2: 1/4 in 2D (triangles), 1/9 in 3D (tetrahedra).
1098 const double mijK = (dimension == 2) ? 1. / 4. : 1. / 9.;
1099
1100 // Assemble variable-diffusivity Laplacian stiffness matrix element by element.
1101 // The diffusivity mu(K) = 1/|K| makes smaller cells stiffer, concentrating mesh
1102 // deformation in larger cells and preserving quality near walls and refined regions.
1103 // The element contribution is: coeffij = mu(K) * (n_i . n_j) * sign_i * sign_j * mijK / |K|
1104 // = (n_i . n_j) * sign_i * sign_j * mijK / |K|^2
1105 for (int e = 0; e < ne_tot; e++)
1106 {
1107 const double volume = le_dom_VF.volumes(e);
1108 for (int isom = 0; isom < nb_som_ele; isom++)
1109 {
1110 int facei = e_f(e, isom), ii = e_s(e, isom);
1111 for (int jsom = isom + 1; jsom < nb_som_ele; jsom++)
1112 {
1113 int i = ii, facej = e_f(e, jsom), j = e_s(e, jsom);
1114 if (i > j) { int tmp = i; i = j; j = tmp; }
1115
1116 double coeffij = 0.0;
1117 for (int d = 0; d < dimension; d++)
1118 coeffij += normales(facei, d) * normales(facej, d);
1119 coeffij *= le_dom_VF.oriente_normale(facei, e) * le_dom_VF.oriente_normale(facej, e);
1120 coeffij *= mijK / (volume * volume); // mu = 1/volume absorbed: mijK / |K|^2
1121
1122 laplacian_matrix_(i, j) += coeffij;
1123 laplacian_matrix_(i, i) -= coeffij;
1124 laplacian_matrix_(j, j) -= coeffij;
1125 }
1126 }
1127 }
1128
1129 // Enforce Dirichlet-like condition on all non-Neumann, non-periodic boundaries via penalization.
1130 // Periodic boundary nodes are left free: the Laplacian naturally interpolates the correct mesh
1131 // velocity for them. Penalizing them to zero would force zero mesh displacement in all directions,
1132 // causing mesh tearing when the domain moves (e.g. beam in x with periodic BC in z).
1133 for (int n_bord = 0; n_bord < le_dom_VF.nb_front_Cl(); n_bord++)
1134 {
1135 const Cond_lim& la_cl = dom_cl.les_conditions_limites(n_bord);
1136 const Front_VF& le_bord = ref_cast(Front_VF, la_cl->frontiere_dis());
1137 if (!projection_manager_.is_neumann_boundary(le_bord.le_nom())
1138 && !sub_type(Periodique, la_cl.valeur()))
1139 {
1140 const int num1 = le_bord.num_premiere_face();
1141 const int num2 = num1 + le_bord.nb_faces();
1142 for (int face = num1; face < num2; face++)
1143 for (int isom = 0; isom < dimension; isom++)
1144 laplacian_matrix_(le_dom_VF.face_sommets(face, isom),
1145 le_dom_VF.face_sommets(face, isom)) = ALE_PENALIZATION;
1146 }
1147 }
1148
1149 // Also penalize nodes on internal ALE boundaries (moving solid interfaces, except Neumann)
1150 for (int n = 0; n < nb_bords_ALE; n++)
1151 {
1152 const Nom& le_nom = les_bords_ALE(n).le_nom();
1153 const int rang = rang_frontiere(le_nom);
1154 if (rang < faces_bord().size() && projection_manager_.is_neumann_boundary(le_nom))
1155 continue;
1156
1157 const IntTab& sommets = frontiere(le_nom).faces().les_sommets();
1158 const int nf = sommets.dimension(0);
1159 const int nspf = sommets.dimension(1);
1160 for (int i = 0; i < nf; i++)
1161 for (int k = 0; k < nspf; k++)
1162 laplacian_matrix_(sommets(i, k), sommets(i, k)) = ALE_PENALIZATION;
1163 }
1164}
1165
1166void Domaine_ALE::laplacien_compute_vertex_velocity(const Domaine_VF& le_dom_VF,
1167 const Domaine_Cl_dis_base& dom_cl,
1168 const DoubleTab& vit_bords)
1169{
1170 DoubleVect solution(laplacian_rhs_);
1171 const int nb_comp = ALE_mesh_velocity.dimension(1);
1172 const int nbsom = nb_som();
1173
1174 for (int comp = 0; comp < nb_comp; comp++)
1175 {
1176 laplacian_rhs_ = 0.;
1177 solution = 0.;
1178
1179 // Build RHS: penalized boundary values
1180 for (int n = 0; n < nb_bords_ALE; n++)
1181 {
1182 const Nom& le_nom = les_bords_ALE(n).le_nom();
1183 const int rang = rang_frontiere(le_nom);
1184 if (rang < faces_bord().size() && projection_manager_.is_neumann_boundary(le_nom))
1185 continue;
1186
1187 const IntTab& sommets = frontiere(le_nom).faces().les_sommets();
1188 const int nf = sommets.dimension(0);
1189 const int nspf = sommets.dimension(1);
1190 for (int i = 0; i < nf; i++)
1191 for (int k = 0; k < nspf; k++)
1192 laplacian_rhs_(sommets(i, k)) = ALE_PENALIZATION * vit_bords(sommets(i, k), comp);
1193 }
1194
1195 laplacian_rhs_.echange_espace_virtuel();
1196 Debog::verifier("Domaine_ALE::laplacien - secmem", laplacian_rhs_);
1197
1198 if (laplacian_rhs_.mp_max_abs_vect() >= 1.e-15)
1199 {
1200 solv.resoudre_systeme(laplacian_matrix_, laplacian_rhs_, solution);
1201 for (int som = 0; som < nbsom; som++)
1202 ALE_mesh_velocity(som, comp) = solution(som);
1203 }
1204 else
1205 for (int som = 0; som < nbsom; som++)
1206 ALE_mesh_velocity(som, comp) = 0.0;
1207 }
1208
1209 // Enforce exact periodicity of the mesh velocity on periodic boundary node pairs.
1210 // Without this, the Laplacian gives slightly different values on the two sides of each
1211 // periodic pair (different ghost-element stencils on each process), causing mesh-coordinate
1212 // drift and breaking the periodicity check in the fluid operators.
1213 {
1214 const int nb_faces_tot = le_dom_VF.face_sommets().dimension_tot(0);
1215 const int nb_som_face = le_dom_VF.nb_som_face();
1216 IntVect fait(nb_faces_tot);
1217 fait = 0;
1218 for (int n_bord = 0; n_bord < le_dom_VF.nb_front_Cl(); n_bord++)
1219 {
1220 const Cond_lim& la_cl = dom_cl.les_conditions_limites(n_bord);
1221 if (!sub_type(Periodique, la_cl.valeur())) continue;
1222 const Periodique& la_cl_period = ref_cast(Periodique, la_cl.valeur());
1223 const Front_VF& le_bord = ref_cast(Front_VF, la_cl->frontiere_dis());
1224 const int nfin = le_bord.nb_faces_tot();
1225 for (int num_face = 0; num_face < nfin; num_face++)
1226 {
1227 int face = le_bord.num_face(num_face);
1228 if (fait(face) == 0)
1229 {
1230 int faassociee = le_bord.num_face(la_cl_period.face_associee(num_face));
1231 fait(face) = 1;
1232 fait(faassociee) = 1;
1233 for (int isom = 0; isom < nb_som_face; isom++)
1234 {
1235 int node_src = le_dom_VF.face_sommets(face, isom);
1236 int node_dst = le_dom_VF.face_sommets(faassociee, isom);
1237 for (int comp = 0; comp < nb_comp; comp++)
1238 ALE_mesh_velocity(node_dst, comp) = ALE_mesh_velocity(node_src, comp);
1239 }
1240 }
1241 }
1242 }
1243 }
1244
1245 ALE_mesh_velocity.echange_espace_virtuel();
1246}
1247
1248//////////////////////////////////////////////////////////////////////////////
1249// Structural dynamics mesh motion
1250//////////////////////////////////////////////////////////////////////////////
1251
1252void Domaine_ALE::structural_dynamics(const Probleme_base& pb, const DoubleTab& vit_bords,
1253 double temps)
1254{
1255 const Domaine_VEF& domaine_VEF = ref_cast(Domaine_VEF, pb.domaine_dis());
1256 const Domaine_Cl_VEF& domaine_Cl_VEF = ref_cast(Domaine_Cl_VEF,
1257 pb.equation(0).domaine_Cl_dis());
1258 const MD_Vector& md = md_vector_sommets();
1259
1260 // Tag nodes with imposed velocity (all nodes on any boundary face)
1261 IntVect tag_nodes_bords(nb_som());
1262 MD_Vector_tools::creer_tableau_distribue(md, tag_nodes_bords);
1263 tag_nodes_bords = 0;
1264
1265 for (int n_bord = 0; n_bord < domaine_VEF.nb_front_Cl(); n_bord++)
1266 {
1267 const Front_VF& le_bord = ref_cast(Front_VF,
1268 domaine_Cl_VEF.les_conditions_limites(n_bord)->frontiere_dis());
1269 const int num1 = le_bord.num_premiere_face();
1270 const int num2 = num1 + le_bord.nb_faces();
1271 for (int face = num1; face < num2; face++)
1272 for (int isom = 0; isom < dimension; isom++)
1273 tag_nodes_bords[domaine_VEF.face_sommets(face, isom)] = 1;
1274 }
1275 tag_nodes_bords.echange_espace_virtuel();
1276
1277 // Pass current coordinates to the structural model
1278 for (int i = 0; i < nb_som(); i++)
1279 for (int k = 0; k < dimension; k++)
1280 str_mesh_model.x(i, k) = coord(i, k);
1281
1282 // Solve explicit dynamic problem: outputs ALE_mesh_velocity
1283 str_mesh_model.solveDynamicMeshProblem(
1284 temps, vit_bords, tag_nodes_bords, ALE_mesh_velocity,
1286 domaine_VEF.nb_faces(), domaine_VEF.nb_som_face(),
1287 domaine_VEF.face_sommets(), *this);
1288
1289 // Enable grid acceleration for subsequent ICoCo sub-iterations
1290 if (str_mesh_model.iCoCoImplicitIteration == 0)
1291 str_mesh_model.acceleratedSolutionEnabled = true;
1292}
1293
1294//////////////////////////////////////////////////////////////////////////////
1295// Post-processing fields (creer_champ / get_champ / has_champ)
1296//////////////////////////////////////////////////////////////////////////////
1297
1298void Domaine_ALE::creer_champ(const Motcle& motlu, const Probleme_base& pb)
1299{
1300 Domaine::creer_champ(motlu, pb);
1301 const double t = pb.schema_temps().temps_courant();
1302
1303 auto disc = [&](const Nom& type, const Nom& name, const Nom& unit,
1304 int nbComp, OWN_PTR(Champ_Inc_base)& field)
1305 {
1306 pb.discretisation().discretiser_champ(type, pb.domaine_dis(), name, unit, nbComp, 1, t, field);
1307 champs_compris_.ajoute_champ(field);
1308 field->add_synonymous(name);
1309 };
1310
1311 if (motlu == "ALEMeshVelocity" && !ALEMeshVelocity_)
1312 disc("vitesse", "ALEMeshVelocity", "m/s", dimension, ALEMeshVelocity_);
1313 else if (motlu == "ALEMeshTotalDisplacement" && !ALEMeshTotalDisplacement_)
1314 disc("vitesse", "ALEMeshTotalDisplacement", "m", dimension, ALEMeshTotalDisplacement_);
1315 else if (motlu == "ALEMeshStructuralPressure" && !ALEMeshStructuralPressure_)
1316 { assert(getMeshMotionModel() == 1); disc("champ_elem", "ALEMeshStructuralPressure", "Pa", 1, ALEMeshStructuralPressure_); }
1317 else if (motlu == "ALEMeshStructuralVonMises" && !ALEMeshStructuralVonMises_)
1318 { assert(getMeshMotionModel() == 1); disc("champ_elem", "ALEMeshStructuralVonMises", "Pa", 1, ALEMeshStructuralVonMises_); }
1319 else if (motlu == "ALEMeshStructuralForces" && !ALEMeshStructuralForces_)
1320 {
1321 // Note: "vitesse" discretization is used here rather than "champ_sommets"
1322 // to avoid an error with unknown "Champ_P1_VEF" in VEF field discretization.
1323 assert(getMeshMotionModel() == 1);
1324 disc("vitesse", "ALEMeshStructuralForces", "N", dimension, ALEMeshStructuralForces_);
1325 }
1326}
1327
1328const Champ_base& Domaine_ALE::get_champ(const Motcle& un_nom) const
1329{
1330 if (un_nom == "ALEMeshVelocity" && ALEMeshVelocity_) return ALEMeshVelocity_.valeur();
1331 if (un_nom == "ALEMeshTotalDisplacement" && ALEMeshTotalDisplacement_) return ALEMeshTotalDisplacement_.valeur();
1332 if (un_nom == "ALEMeshStructuralPressure"&& ALEMeshStructuralPressure_) return ALEMeshStructuralPressure_.valeur();
1333 if (un_nom == "ALEMeshStructuralVonMises"&& ALEMeshStructuralVonMises_) return ALEMeshStructuralVonMises_.valeur();
1334 if (un_nom == "ALEMeshStructuralForces" && ALEMeshStructuralForces_) return ALEMeshStructuralForces_.valeur();
1335 throw std::runtime_error(std::string("Field ") + un_nom.getString() + " not found!");
1336}
1337
1338bool Domaine_ALE::has_champ(const Motcle& un_nom, OBS_PTR(Champ_base)& ref_champ) const
1339{
1340 if (un_nom == "ALEMeshVelocity" && ALEMeshVelocity_) { ref_champ = ALEMeshVelocity_.valeur(); return true; }
1341 if (un_nom == "ALEMeshTotalDisplacement" && ALEMeshTotalDisplacement_) { ref_champ = ALEMeshTotalDisplacement_.valeur(); return true; }
1342 if (un_nom == "ALEMeshStructuralPressure"&& ALEMeshStructuralPressure_) { ref_champ = ALEMeshStructuralPressure_.valeur(); return true; }
1343 if (un_nom == "ALEMeshStructuralVonMises"&& ALEMeshStructuralVonMises_) { ref_champ = ALEMeshStructuralVonMises_.valeur(); return true; }
1344 if (un_nom == "ALEMeshStructuralForces" && ALEMeshStructuralForces_) { ref_champ = ALEMeshStructuralForces_.valeur(); return true; }
1345 return false;
1346}
1347
1348bool Domaine_ALE::has_champ(const Motcle& un_nom) const
1349{
1350 OBS_PTR(Champ_base) dummy;
1351 return has_champ(un_nom, dummy);
1352}
1353
1355{
1356 Noms noms_compris = champs_compris_.liste_noms_compris();
1357 if (ALEMeshVelocity_) noms_compris.add("ALEMeshVelocity");
1358 if (ALEMeshTotalDisplacement_) noms_compris.add("ALEMeshTotalDisplacement");
1359 if (ALEMeshStructuralPressure_) noms_compris.add("ALEMeshStructuralPressure");
1360 if (ALEMeshStructuralVonMises_) noms_compris.add("ALEMeshStructuralVonMises");
1361 if (ALEMeshStructuralForces_) noms_compris.add("ALEMeshStructuralForces");
1362
1363 if (opt == DESCRIPTION)
1364 Cerr << que_suis_je() << " : " << noms_compris << finl;
1365 else
1366 nom.add(noms_compris);
1367}
1368
1369
1371{
1372 // Update vertex coordinates of any sub-domain extracted from a deformable moving boundary
1374 const Noms& noms = interp.les_noms();
1375 for (int i = 0; i < noms.size(); i++)
1376 {
1377 if (strcmp(interprete().objet(noms[i]).le_type(), "Domaine") != 0) continue;
1378 Domaine& dom_new = ref_cast(Domaine, interprete().objet(noms[i]));
1379 if (!sub_type(Domaine_ALE, dom_new)) continue;
1380 Domaine_ALE& dom_new_ale = ref_cast(Domaine_ALE, dom_new);
1381 if (!dom_new_ale.extrait_surf_dom_deformable_) continue;
1382
1384 dom_new_ale.les_sommets() = coord_sommets();
1385 dom_new_ale.les_elems() = dom_new_ale.les_elems_extrait_surf_reference();
1386 NettoieNoeuds::nettoie(dom_new_ale);
1387 }
1388}
const Noms & neumann_boundary_names() const
class Ch_front_input_ALE
Classe Champ_Inc_base.
virtual void verifie_valeurs_cl()
virtual DoubleTab & valeurs()=0
classe Champ_base Cette classe est la base de la hierarchie des champs.
Definition Champ_base.h:43
classe Champ_front_base Classe de base pour la hierarchie des champs aux frontieres.
virtual void creer_champ(const Motcle &motlu)=0
classe Cond_lim_base Classe de base pour la hierarchie des classes qui representent les differentes c...
virtual Frontiere_dis_base & frontiere_dis()
Renvoie la frontiere discretisee a laquelle les conditions aux limites s'appliquent.
static void verifier(const char *const msg, double)
Definition Debog.cpp:21
virtual bool is_ef() const
virtual bool is_PolyMAC_MPFA() const
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
virtual void clear()
virtual const MD_Vector & md_vector_sommets() const
Definition Domaine.h:369
int nb_som_elem() const
int_t nb_elem_tot() const
Definition Domaine.h:132
DoubleTab_t & les_sommets()
Definition Domaine.h:113
int rang_frontiere(const Nom &) const
Bords_t & faces_bord()
Definition Domaine.h:198
const Frontiere_t & frontiere(int i) const
IntTab_t & les_elems()
Definition Domaine.h:129
int_t nb_elem() const
Definition Domaine.h:131
void resetSommetsCoordinates()
Definition Domaine.h:116
DoubleTab_t sommets_
Definition Domaine.h:386
const DoubleTab_t & coord_sommets() const
Definition Domaine.h:112
void saveSommetsCoordinates()
Definition Domaine.h:115
virtual const MD_Vector & md_vector_elements() const
int_t nb_som_tot() const
Definition Domaine.h:123
double coord(int_t i, int j) const
Definition Domaine.h:110
int_t nb_som() const
Definition Domaine.h:121
const int & getBeamNbModes(const int &) const
DoubleTab interpolationOnThe3DSurface(const int &, const double &x, const double &y, const double &z, const DoubleTab &u, const DoubleTab &R) const
int getCouplingMethod()
void update_coord_dom_extrait_surface()
const DoubleTab & getMeshTransformationGradient() const
const DoubleTab & getMeshPosition() const
const int & getBeamNbBeam() const
void reading_vit_bords_ALE(Entree &is)
int getMeshMotionModel() const
Definition Domaine_ALE.h:84
void reading_projection_ALE_boundary(Entree &is)
void reading_beam_model(Entree &is)
bool extrait_surf_dom_deformable_
const int & getBeamNbPlanes(const int &) const
void updateMetrics(Domaine_dis_base &, Probleme_base &)
int meshMotionModel_
void initialiser(double temps, Domaine_dis_base &, Probleme_base &) override
void create_field(OWN_PTR(Champ_Inc_base)&, const std::string &, int, const Motcle &, const Probleme_base &) const
DoubleTab vf
void update_after_post(double temps) override
const DoubleTab & getBeamRotation(const int &, const int &) const
const DoubleTab & getMeshStress() const
void apply_old_to_new_volume_scaling(DoubleTab &, const Domaine_dis_base &) const override
void validateTimeStep() override
const IntTab & les_elems_extrait_surf_reference() const
void update_post_fields(double temps, double dt)
IntTab som_faces_bords
Bords les_bords_ALE
void reading_solver_moving_mesh_ALE(Entree &is)
int save_additional_state(Sortie &, const Probleme_base &) const override
const DoubleVect & getMeshPbVonMises() const
YAML_data make_yaml(const std::string &, int, const Probleme_base &) const
void resumptionCoords(DoubleTab &)
const DoubleTab & getMeshDisplacement() const
Structural_dynamic_mesh_model str_mesh_model
SolveurSys solv
std::vector< YAML_data > data_a_sauvegarder(const Probleme_base &) const override
const Champ_base & get_champ(const Motcle &) const override
ALE_CheckpointManager checkpoint_manager_
bool has_champ(const Motcle &nom, OBS_PTR(Champ_base)&ref_champ) const override
void set_dt(double &dt) override
double interpolationPhiOnThe3DSurface(const int &, const double &x, const double &y, const double &z, const int &comp, const DoubleTab &u) const
const int & getBeamLongitudinalAxis(const int &) const
IntTab les_elems_extrait_surf_reference_
ALE_ProjectionManager projection_manager_
void mettre_a_jour(double temps, Domaine_dis_base &, Probleme_base &) override
void update_ALE_projection(double, Nom &, Champ_front_ALE_projection &, int)
const int & getMeshStressNbComp() const
void associer_vitesse_lagrangienne(const Nom &nom_pb, const Nom &nom_champ)
void reading_structural_dynamic_mesh_model(Entree &is)
void reading_ALE_Neumann_BC_for_grid_problem(Entree &is)
OBS_PTR(Equation_base) eq
const DoubleTab & getMeshPbForceFace() const
const int & getMeshTransformationGradientNbComp() const
int Coupling_ICoCo_method
const DoubleTab & getBeamDisplacement(const int &, const int &) const
void get_noms_champs_postraitables(Noms &nom, Option opt=NONE) const override
Equation_base & getEquation()
const DoubleTab & getMeshVelocity() const
TRUST_Vector< OWN_PTR(Champ_front_base)> les_champs_front
OWN_PTR(Champ_Inc_base) ALEMeshVelocity_
const Nom & getBeamName(const int &) const
DoubleTab & vitesse_faces()
bool is_resumption() const
Nom generate_field_tag(const Champ_Inc_base &, const Probleme_base &) const
ALE_MetricsUpdater metrics_updater_
void computeFluidForceOnBeam(const int &)
const int & getMeshReferenceConfigurationNbComp() const
void clear() override
Reset the Domaine completely except for its name.
DoubleTab & getBeamVelocity(const int &, const double &tps, const double &dt)
DoubleTab ALE_mesh_velocity
void ajouter_correctif_volumique(const DoubleTab &, const DoubleTab &, double, DoubleTab &) const override
void resumptionStructuralDynamicsMesh(double, DoubleTab &, DoubleTab &, DoubleTab &, DoubleTab &, DoubleTab &, DoubleTab &, DoubleTab &)
int restore_additional_state(Entree &, Probleme_base &) override
void creer_champ(const Motcle &, const Probleme_base &) override
bool getUpdateTheGrid() override
const DoubleTab & getMeshReferenceConfiguration() const
const int & getBeamBendingDirection(const int &, const int &) const
bool UpdateTheGrid
ALE_BeamCoupling beam_coupling_
DoubleTab & calculer_vitesse_faces(DoubleTab &, int, int, IntTab &)
void setUpdateTheGrid(bool) override
const DoubleTab & getMeshAcceleration() const
double computeDtBeam(Domaine_dis_base &, const int &)
const DoubleVect & getMeshPbPressure() const
Champs_compris champs_compris_
classe Domaine_Cl_dis_base Les objets Domaine_Cl_dis_base representent les conditions aux limites
virtual const Champ_Inc_base & inconnue() const
int nb_cond_lim() const
Renvoie le nombre de conditions aux limites.
const Cond_lim & les_conditions_limites(int) const
Renvoie la i-ieme condition aux limites.
class Domaine_EF
Definition Domaine_EF.h:59
class Domaine_VF
Definition Domaine_VF.h:44
int nb_faces() const
renvoie le nombre global de faces.
Definition Domaine_VF.h:471
const MD_Vector & md_vector_faces() const
Definition Domaine_VF.h:158
DoubleVect & volumes_entrelaces()
Definition Domaine_VF.h:99
int nb_faces_tot() const
renvoie le nombre total de faces.
Definition Domaine_VF.h:481
virtual double face_normales(int face, int comp) const
Definition Domaine_VF.h:47
double volumes(int i) const
Definition Domaine_VF.h:113
int face_sommets(int i, int j) const
renvoie le numero du ieme sommet de la face num_face.
Definition Domaine_VF.h:583
int nb_som_face() const
renvoie le nombre de sommets par face.
Definition Domaine_VF.h:494
int elem_faces(int i, int j) const
renvoie le numero de le ieme face de la maille num_elem la facon dont ces faces sont numerotees est
Definition Domaine_VF.h:543
int oriente_normale(int f, int e) const
Definition Domaine_VF.h:194
virtual void validateTimeStep()
const Nom & le_nom() const override
Donne le nom de l'Objet_U Methode a surcharger : renvoie "neant" dans cette implementation.
bool mesh_update_required_
classe Domaine_dis_base Cette classe est la base de la hierarchie des domaines discretisees.
const Frontiere_dis_base & frontiere_dis(const Nom &) const
Renvoie la frontiere de Nom nom.
int nb_front_Cl() const
int nb_som_tot() const
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 Domaine_Cl_dis_base & domaine_Cl_dis()
Renvoie le domaine des conditions aux limite discretisee associee a l'equation.
const IntTab_t & les_sommets() const
Renvoie le tableau des sommets de toutes les faces.
Definition Faces.h:74
class Front_VF
Definition Front_VF.h:36
int nb_faces() const
Definition Front_VF.h:53
int num_premiere_face() const
Definition Front_VF.h:63
int nb_faces_tot() const
Definition Front_VF.h:58
int num_face(const int) const
Definition Front_VF.h:68
const Faces_t & faces() const
Definition Frontiere.h:54
const Nom & le_nom() const override
Renvoie le nom de la frontiere geometrique.
Interprete un bloc d'instructions dans le jeu de donnees.
static Interprete_bloc & interprete_courant()
renvoie l'interprete_bloc en train d'etre lu dans le jeu de donnees.
const Noms & les_noms() const
static void creer_tableau_distribue(const MD_Vector &, Array_base &, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT)
transforme v en un tableau parallele ayant la structure md.
: Cette classe est un OWN_PTR mais l'objet pointe est partage entre plusieurs
Definition MD_Vector.h:48
static void allocate_morse_matrix(const int nb_lines, const int nb_columns, const Stencil &stencil, Matrice_Morse &matrix, const bool &attach_stencil_to_matrix=false)
Une chaine de caractere (Nom) en majuscules.
Definition Motcle.h:26
static void nettoie(Domaine_t &)
class Nom Une chaine de caractere pour nommer les objets de TRUST
Definition Nom.h:31
const std::string & getString() const
Definition Nom.h:92
Un tableau de chaine de caracteres (VECT(Nom)).
Definition Noms.h:26
friend class Entree
Definition Objet_U.h:76
const Interprete & interprete() const
Definition Objet_U.cpp:212
static int dimension
Definition Objet_U.h:99
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
static double precision_geom
Definition Objet_U.h:86
static const Nom & nom_du_cas()
Renvoie une reference constante vers le nom du cas.
Definition Objet_U.cpp:146
const char * le_type() const
Donne le nom du type de l'Objet_U.
Definition Objet_U.cpp:191
virtual Sortie & printOn(Sortie &) const
Ecriture de l'objet sur un flot de sortie Methode a surcharger.
Definition Objet_U.cpp:282
classe Periodique Cette classe represente une condition aux limites periodique.
Definition Periodique.h:31
int face_associee(int i) const
Definition Periodique.h:35
virtual bool checkOutputIntEntry(const Nom &name) const
virtual int getOutputIntValue(const Nom &name) const
classe Probleme_base C'est un Probleme_U qui n'est pas un couplage.
const Domaine & domaine() const
Renvoie le domaine associe au probleme.
const Champ_base & get_champ(const Motcle &nom) const override
const Discretisation_base & discretisation() const
Renvoie la discretisation associee au probleme.
const Schema_Temps_base & schema_temps() const
Renvoie le schema en temps associe au probleme.
virtual const Equation_base & equation(int) const =0
const Domaine_dis_base & domaine_dis() const
Renvoie le domaine discretise associe au probleme.
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
static void uninit_sequential_domain(Domaine_32_64< _SIZE_ > &dom)
methode utilisee par les interpretes qui modifient le domaine (sequentiel), detruit les descripteurs ...
Definition Scatter.cpp:2757
double temps_courant() const
Renvoie le temps courant.
double pas_de_temps() const
Renvoie le pas de temps (delta_t) courant.
int nb_pas_dt() const
Renvoie le nombre de pas de temps effectues.
class SolveurSys Un SolveurSys represente n'importe qu'elle classe
Definition SolveurSys.h:32
Classe de base des flux de sortie.
Definition Sortie.h:52
_SIZE_ dimension_tot(int) const override
Definition TRUSTTab.tpp:160
_SIZE_ dimension(int d) const
Definition TRUSTTab.tpp:133
_SIZE_ size() const
Definition TRUSTVect.tpp:45
int line_size() const
Definition TRUSTVect.tpp:67
_TYPE_ mp_max_abs_vect(Mp_vect_options opt=VECT_REAL_ITEMS) const
Definition TRUSTVect.h:160
virtual void echange_espace_virtuel(IsExchangeBlocking exchange_type=IsExchangeBlocking::DefaultBlocking, const std::string kernel_name="noname")
classe TRUST_Vector
classe YAML_data : collection of all needed information for data to save/restore in order to write th...
Definition YAML_data.h:26