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