Arcane  v3.14.10.0
Documentation développeur
Chargement...
Recherche...
Aucune correspondance
AlephMultiTest.cc
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2022 CEA (www.cea.fr) IFPEN (www.ifpenergiesnouvelles.com)
4// See the top-level COPYRIGHT file for details.
5// SPDX-License-Identifier: Apache-2.0
6//-----------------------------------------------------------------------------
7/*---------------------------------------------------------------------------*/
8/* AlephMultiTest.cc (C) 2000-2015 */
9/* */
10/* Service du test du service Aleph+Multi. */
11/*---------------------------------------------------------------------------*/
12#include "arcane/aleph/tests/AlephTest.h"
13#include "arcane/aleph/tests/AlephMultiTest_axl.h"
14#include "arcane/aleph/tests/AlephMultiTest.h"
15
17using namespace Arcane;
18
19// ****************************************************************************
20// * Classe 'solver' qui va mimer ce qui est fait à plus haut niveau
21// ****************************************************************************
23: public TraceAccessor
24, public MeshAccessor
25{
26 public:
27 AlephSolver(ITraceMng* traceMng,
28 ISubDomain* subDomain,
30 Integer underlyingSolver,
32 Real deltaT)
33 : TraceAccessor(traceMng)
34 , MeshAccessor(subDomain->defaultMesh())
35 , m_sub_domain(subDomain)
36 , m_aleph_number_of_resolutions_per_solvers(numberOfResolutionsPerSolvers)
37 , m_delta_t(deltaT)
38 , m_aleph_params(new AlephParams())
39 ,
40 // On instancie un kernel minimaliste qui va prendre en charge l'init à notre place
41 m_aleph_kernel(new AlephKernel(subDomain, underlyingSolver, numberOfCores))
42 , m_aleph_mat(0)
43 , m_aleph_rhs(0)
44 , m_aleph_sol(0)
45 , m_vector_zeroes(0)
46 , m_get_solution_idx(0)
47 {
48 info() << Trace::Color::cyan() << "[AlephSolver] New solver "
49 << "with " << numberOfResolutionsPerSolvers << " resolutions, "
50 << "underlying solver is '" << underlyingSolver << "', "
51 << "and numberOfCores is " << numberOfCores;
52 m_aleph_mat.resize(numberOfResolutionsPerSolvers);
53 m_aleph_rhs.resize(numberOfResolutionsPerSolvers);
54 m_aleph_sol.resize(numberOfResolutionsPerSolvers);
55 ENUMERATE_CELL (cell, ownCells())
56 m_vector_zeroes.add(0.0);
57 }
58
60 {
61 info() << Trace::Color::cyan() << "[AlephSolver] Delet solver";
62 delete m_aleph_kernel;
63 delete m_aleph_params;
64 }
65
66 // ****************************************************************************
67 // * launchResolutions
68 // ****************************************************************************
69 void launchResolutions(VariableCellReal& cell_temperature,
71 {
76
77 indexs.resize(m_aleph_number_of_resolutions_per_solvers);
78 values.resize(m_aleph_number_of_resolutions_per_solvers);
79
80 for (int i = 0;
81 i < m_aleph_number_of_resolutions_per_solvers;
82 i += 1)
83 postSingleResolution(cell_temperature,
85 i, m_delta_t, values[i], indexs[i]);
86
87 // And should be able to get the solutions after the last resolution was fired
88 for (int i = m_aleph_number_of_resolutions_per_solvers - 1; i >= 0; i -= 1) {
89 debug() << Trace::Color::cyan() << "[AlephSolver::launchResolutions] Getting solution #" << i;
90 AlephVector* solution = m_aleph_kernel->syncSolver(i, nb_iteration, &residual_norm[0]);
91 if (i != m_get_solution_idx)
92 continue;
93 info() << Trace::Color::cyan() << "Solved in \33[7m" << nb_iteration << "\33[m iterations,"
94 << "residuals=[\33[1m" << residual_norm[0] << "\33[m," << residual_norm[3] << "]";
95 debug() << Trace::Color::cyan() << "[AlephSolver::launchResolutions] Applying solution #" << m_get_solution_idx;
96 solution->getLocalComponents(values[i]);
97 m_get_solution_idx += 1;
98 }
99 m_get_solution_idx %= m_aleph_number_of_resolutions_per_solvers;
100 // Sinon, on recopie les résultats
101 debug() << Trace::Color::cyan() << "[AlephSolver::launchResolutions] Now get our results";
102 ENUMERATE_CELL (cell, ownCells())
103 cell_temperature[cell] =
104 values[m_get_solution_idx][m_aleph_kernel->indexing()->get(cell_temperature, *cell)];
105 debug() << Trace::Color::cyan() << "[AlephSolver::launchResolutions] done";
106 }
107
108 // ****************************************************************************
109 // * postSingleResolution
110 // ****************************************************************************
111 void postSingleResolution(VariableCellReal& cell_temperature,
113 const Integer i,
115 Array<Real>& values,
117 {
118 // On force les deltaT à être différents pour avoir des temps de calculs que l'on pourra ordonnancer
119 Real deltaT = (1.0 + (Real)i) * optionDeltaT;
122
123 // Remplissage du second membre: conditions limites + second membre
124 debug() << Trace::Color::cyan()
125 << "[AlephSolver::postSingleResolution] Resize (" << m_vector_zeroes.size()
126 << ") + remplissage du second membre";
127 values.resize(m_vector_zeroes.size());
128 indexs.resize(m_vector_zeroes.size());
129 ENUMERATE_CELL (cell, ownCells()) {
130 Integer row = m_aleph_kernel->indexing()->get(cell_temperature, cell);
131 //info()<<Trace::Color::yellow()<<"[AlephSolver::postSingleResolution] row="<<row;
132 indexs[row] = row;
133 values[row] = cell_temperature[cell];
134 }
135
136 debug() << Trace::Color::cyan() << "[AlephSolver::postSingleResolution] ENUMERATE_FACE";
137 ENUMERATE_FACE (iFace, allCells().outerFaceGroup()) {
138 if (!iFace->cell(0).isOwn())
139 continue;
140 values[m_aleph_kernel->indexing()->get(cell_temperature, iFace->cell(0))] +=
141 deltaT * (face_temperature[iFace]) / geoFaceSurface(*iFace, nodesCoordinates());
142 }
143
144 // Création de la matrice MatVec et des besoins Aleph
145 m_aleph_mat.setAt(i, m_aleph_kernel->createSolverMatrix());
146 m_aleph_rhs.setAt(i, m_aleph_kernel->createSolverVector()); // First vector returned IS the rhs
147 m_aleph_sol.setAt(i, m_aleph_kernel->createSolverVector()); // Next one IS the solution
148
149 m_aleph_mat.at(i)->create();
150 m_aleph_rhs.at(i)->create();
151 m_aleph_sol.at(i)->create();
152 m_aleph_mat.at(i)->reset();
153
154 // Remplissage de la matrice et assemblage
155 setValues(cell_temperature, face_temperature, deltaT, m_aleph_mat.at(i));
156 m_aleph_mat.at(i)->assemble();
157
158 debug() << Trace::Color::cyan() << "[AlephSolver::postSingleResolution] setLocalComponents";
159 //m_aleph_rhs.at(i)->setLocalComponents(indexs.size(), indexs.view(), values.view());
160 m_aleph_rhs.at(i)->setLocalComponents(values.view());
161 m_aleph_rhs.at(i)->assemble();
162
163 //m_aleph_sol.at(i)->setLocalComponents(indexs.size(), indexs.view(), m_vector_zeroes.view());
164 m_aleph_sol.at(i)->setLocalComponents(m_vector_zeroes.view());
165 m_aleph_sol.at(i)->assemble();
166
167 debug() << Trace::Color::cyan() << "\33[37m[AlephSolver::postSingleResolution] Now solve with Aleph";
168 m_aleph_mat.at(i)->solve(m_aleph_sol.at(i),
169 m_aleph_rhs.at(i),
172 m_aleph_params,
173 true); // On souhaite poster de façon asynchrone
174 }
175
176 // ****************************************************************************
177 // * setValues for a matrix
178 // ****************************************************************************
179 void setValues(VariableCellReal& cell_temperature,
181 const Real deltaT, AlephMatrix* aleph_mat)
182 {
183 VariableCellReal coefs(VariableBuildInfo(m_sub_domain->defaultMesh(), "cellCoefs"));
184 // On flush les coefs
185 ENUMERATE_CELL (cell, ownCells())
186 coefs[cell] = 0.;
187 // Faces 'inner'
188 debug() << Trace::Color::cyan() << "[AlephSolver::setValues] inner-faces";
189 ENUMERATE_FACE (iFace, allCells().innerFaceGroup()) {
190 if (iFace->backCell().isOwn()) {
191 const Real surface = geoFaceSurface(*iFace, nodesCoordinates());
192 aleph_mat->setValue(cell_temperature, iFace->backCell(),
193 cell_temperature, iFace->frontCell(),
194 -deltaT / surface);
195 coefs[iFace->backCell()] += 1.0 / surface;
196 }
197 if (iFace->frontCell().isOwn()) {
198 const Real surface = geoFaceSurface(*iFace, nodesCoordinates());
199 aleph_mat->setValue(cell_temperature, iFace->frontCell(),
200 cell_temperature, iFace->backCell(),
201 -deltaT / surface);
202 coefs[iFace->frontCell()] += 1.0 / surface;
203 }
204 }
205 debug() << Trace::Color::cyan() << "[AlephSolver::setValues] outer-faces";
206 ENUMERATE_FACE (iFace, allCells().outerFaceGroup()) {
207 if (!iFace->cell(0).isOwn())
208 continue;
209 coefs[iFace->cell(0)] += 1.0 / geoFaceSurface(*iFace, nodesCoordinates());
210 }
211 debug() << Trace::Color::cyan() << "[AlephSolver::setValues] diagonale";
212 ENUMERATE_CELL (cell, ownCells()) {
213 aleph_mat->setValue(cell_temperature, cell,
214 cell_temperature, cell,
215 1.0 + deltaT * coefs[cell]);
216 }
217 debug() << Trace::Color::cyan() << "[AlephSolver::setValues] done";
218 }
219
220 private:
221 // ****************************************************************************
222 // * geoFaceSurface
223 // ****************************************************************************
224 Real geoFaceSurface(Face face, VariableItemReal3& nodes_coords)
225 {
226 if (face.nbNode() == 4) {
227 const Real3 xyz0 = nodes_coords[face.node(0)];
228 const Real3 xyz1 = nodes_coords[face.node(1)];
229 const Real3 xyz3 = nodes_coords[face.node(3)];
230 return (xyz0 - xyz1).normL2() * (xyz0 - xyz3).normL2();
231 }
232 if (face.nbNode() == 2) {
233 const Real3 xyz0 = nodes_coords[face.node(0)];
234 const Real3 xyz1 = nodes_coords[face.node(1)];
235 return (xyz0 - xyz1).normL2();
236 }
237 throw FatalErrorException("geoFace", "Nb nodes != 4 !=2");
238 }
239
240 private:
241 ISubDomain* m_sub_domain;
242 Integer m_aleph_number_of_resolutions_per_solvers;
243 Real m_delta_t;
244 AlephParams* m_aleph_params;
245 AlephKernel* m_aleph_kernel;
246 UniqueArray<AlephMatrix*> m_aleph_mat;
247 UniqueArray<AlephVector*> m_aleph_rhs;
248 UniqueArray<AlephVector*> m_aleph_sol;
249 UniqueArray<Real> m_vector_zeroes;
250 Integer m_get_solution_idx;
251};
252
253// ****************************************************************************
254// * Classe AlephMultiTest + deletes
255// ****************************************************************************
256AlephMultiTest::
257AlephMultiTest(const ModuleBuildInfo& mbi)
258: ArcaneAlephMultiTestObject(mbi)
259{
260}
261
262AlephMultiTest::
263~AlephMultiTest(void)
264{
265 // NOTE: il ne faut pas détruire les éléments de \a m_posted_solvers
266 delete m_aleph_factory;
267 debug() << Trace::Color::cyan() << "[AlephMultiTest::AlephMultiTest] Delete";
268 for (Integer i = 0, n = m_global_aleph_solver.size(); i < n; ++i)
269 delete m_global_aleph_solver[i];
270}
271
272// ****************************************************************************
273// * Point d'entrée d'initialisations
274// ****************************************************************************
275void AlephMultiTest::
276init(void)
277{
278 ISubDomain* sd = subDomain();
279 m_aleph_factory = new AlephFactory(sd->application(), sd->traceMng());
280
281 // Initialisation du pas de temps
282 m_global_deltat = options()->deltaT;
283 // Initialisation des temperatures des mailles et des faces extérieures
284 m_cell_temperature.fill(options()->iniTemperature());
285
286 ENUMERATE_FACE (iFace, outerFaces()) {
287 m_face_temperature[iFace] = options()->hotTemperature();
288 }
289 mesh()->checkValidMeshFull();
290
291 // Initialisation des solveurs globaux
292 for (Integer i = 0; i < options()->alephNumberOfSuccessiveSolvers(); ++i) {
293 SolverBuildInfo sbi;
294 Integer underlying_solver = (options()->alephUnderlyingSolver >> (4ul * i)) & 0xFul;
295 if (!m_aleph_factory->hasSolverImplementation(underlying_solver)) {
296 info() << "Skipping solver index " << underlying_solver
297 << " because implementation is not available";
298 continue;
299 }
300
301 sbi.m_number_of_resolution_per_solvers = (options()->alephNumberOfResolutionsPerSolvers >> (4ul * i)) & 0xFul;
302 sbi.m_underliying_solver = underlying_solver;
303 sbi.m_number_of_core = (options()->alephNumberOfCores >> (4ul * i)) & 0xFul;
304 m_solvers_build_info.add(sbi);
305 }
306
307 // Initialisation des solveurs globaux
308 for (Integer i = 0, n = m_solvers_build_info.size(); i < n; ++i) {
309 const SolverBuildInfo& sbi = m_solvers_build_info[i];
310 m_global_aleph_solver.add(new AlephSolver(traceMng(), subDomain(),
311 sbi.m_number_of_resolution_per_solvers,
312 sbi.m_underliying_solver,
313 sbi.m_number_of_core,
314 options()->deltaT));
315 }
316}
317
318// ****************************************************************************
319// * Point d'entrée de la boucle de calcul
320// ****************************************************************************
321void AlephMultiTest::
322compute(void)
323{
324 // Pour chaque solver, on lance les résolutions
325 for (Integer i = 0, n = m_solvers_build_info.size(); i < n; ++i) {
326 const SolverBuildInfo& sbi = m_solvers_build_info[i];
327 // Création et lancement des solveurs locaux les options shiftées
328 // Ceci afin de tester les deletes
329 AlephSolver* s = new AlephSolver(traceMng(), subDomain(),
330 sbi.m_number_of_resolution_per_solvers,
331 sbi.m_underliying_solver,
332 sbi.m_number_of_core,
333 options()->deltaT);
334 m_posted_solvers.add(s);
335 s->launchResolutions(m_cell_temperature, m_face_temperature);
336 // Lancement des solveurs globaux
337 m_global_aleph_solver.at(i)->launchResolutions(m_cell_temperature, m_face_temperature);
338 }
339
340 // Si on a atteint notre maximum d'itérations, on quitte
341 if (subDomain()->commonVariables().globalIteration() >= options()->iterations)
342 subDomain()->timeLoopMng()->stopComputeLoop(true);
343}
344
345// ****************************************************************************
346// * REGISTER + NAMESPACE
347// ****************************************************************************
348ARCANE_DEFINE_STANDARD_MODULE(AlephMultiTest, AlephMultiTest);
#define ENUMERATE_FACE(name, group)
Enumérateur générique d'un groupe de faces.
#define ENUMERATE_CELL(name, group)
Enumérateur générique d'un groupe de mailles.
AlephVector * createSolverVector(void)
AlephVector * syncSolver(Integer, Integer &, Real *)
Matrice d'un système linéaire.
Definition AlephMatrix.h:33
Paramètres d'un système linéraire.
Definition AlephParams.h:34
Vecteur d'un système linéaire.
Definition AlephVector.h:33
Face d'une maille.
Definition Item.h:932
Interface du gestionnaire d'un sous-domaine.
Definition ISubDomain.h:74
virtual IMesh * defaultMesh()=0
Maillage par défaut.
Node node(Int32 i) const
i-ème noeud de l'entité
Definition Item.h:768
Int32 nbNode() const
Nombre de noeuds de l'entité
Definition Item.h:765
Lecteur des fichiers de maillage via la bibliothèque LIMA.
Definition Lima.cc:120
Accès aux informations d'un maillage.
CellGroup allCells() const
Retourne le groupe contenant toutes les mailles.
CellGroup ownCells() const
Retourne le groupe contenant toutes les mailles propres à ce domaine.
VariableNodeReal3 & nodesCoordinates() const
Retourne les coordonnées des noeuds du maillage.
Informations pour construire un module.
Classe gérant un vecteur de réel de dimension 3.
Definition Real3.h:132
Paramètres nécessaires à la construction d'une variable.
Integer size() const
Nombre d'éléments du vecteur.
ArrayView< T > view() const
Vue mutable sur ce tableau.
void add(ConstReferenceType val)
Ajoute l'élément val à la fin du tableau.
Exception lorsqu'une erreur fatale est survenue.
Interface du gestionnaire de traces.
ITraceMng * traceMng() const
Gestionnaire de trace.
-*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
Int32 Integer
Type représentant un entier.