Arcane  v3.14.10.0
Documentation développeur
Chargement...
Recherche...
Aucune correspondance
AlephTestModule.cc
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2024 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/* AlephUnitTest.cc (C) 2000-2024 */
9/* */
10/* Service du test du service Aleph. */
11/*---------------------------------------------------------------------------*/
12
13#include "arcane/aleph/tests/AlephTest.h"
14
15/*---------------------------------------------------------------------------*/
16/*---------------------------------------------------------------------------*/
17
18namespace ArcaneTest
19{
20
21/*---------------------------------------------------------------------------*/
22/*---------------------------------------------------------------------------*/
23
24using namespace Arcane;
25
26AlephTestModule::
27AlephTestModule(const ModuleBuildInfo& mbi)
28: ArcaneAlephTestModuleObject(mbi)
29, m_total_nb_cell(0)
30, m_local_nb_cell(0)
31, m_rows_nb_element(0)
32, m_vector_indexs(0)
33, m_vector_zeroes(0)
34, m_vector_rhs(0)
35, m_vector_lhs(0)
36, m_aleph_kernel(NULL)
37, m_aleph_factory(new AlephFactory(subDomain()->application(), traceMng()))
38, m_aleph_params(NULL)
39, m_aleph_mat(0)
40, m_aleph_rhs(0)
41, m_aleph_sol(0)
42, m_get_solution_idx(0)
43, m_fake_nb_iteration(0)
44{
45 debug() << "\33[37m[AlephTestModule::AlephTestModule] Loading AlephTestModule\33[0m";
46}
47
48AlephTestModule::
49~AlephTestModule()
50{
51 delete m_aleph_kernel;
52 delete m_aleph_params;
53 delete m_aleph_factory;
54}
55
56/***************************************************************************
57 * AlephTestModule::init *
58 ***************************************************************************/
59void AlephTestModule::
60init()
61{
62 ItacFunction(AlephTestModule);
63 m_aleph_mat.resize(options()->alephNumberOfSolvers);
64 m_aleph_rhs.resize(options()->alephNumberOfSolvers);
65 m_aleph_sol.resize(options()->alephNumberOfSolvers);
66
67 // On récupère le nombre de mailles
68 m_local_nb_cell = MESH_OWN_ACTIVE_CELLS(mesh()).size();
69 m_total_nb_cell = subDomain()->parallelMng()->reduce(Parallel::ReduceSum, m_local_nb_cell);
70 debug() << "\33[37m[AlephTestModule::init] m_total_nb_cell=" << m_total_nb_cell
71 << ", local=" << m_local_nb_cell << "\33[0m";
72
73 // On set notre pas de temps
74 m_global_deltat = options()->deltaT;
75
76 // initialisation de la temperature sur toutes les mailles et faces
77 ENUMERATE_CELL (icell, allCells())
78 m_cell_temperature[icell] = options()->initTemperature();
79 ENUMERATE_FACE (iFace, allFaces())
80 m_face_temperature[iFace] = options()->initTemperature();
81
82 // Mise à jour des variables UID et SDID
83 ENUMERATE_CELL (icell, allCells())
84 m_sub_domain_id[icell] = subDomain()->subDomainId();
85 ENUMERATE_CELL (icell, allCells())
86 m_unique_id[icell] = icell->uniqueId().asInteger();
87
88 // initialisation de la température aux limites
89 options()->schema()->boundaries(options());
90
91 // On raffine le ratio de mailles depuis le jeu de données
92 if ((options()->initAmr() < 0) || (options()->initAmr() > 1.0))
93 throw FatalErrorException("AlephTestModule::init()", "AMR ratio out of range");
94
95 initAmrRefineMesh((Integer)(mesh()->cellFamily()->allItems().own().size() * options()->initAmr()));
96 mesh()->checkValidMeshFull();
97
98 initAlgebra();
99}
100
101/***************************************************************************
102 *
103 ***************************************************************************/
104
105void AlephTestModule::
106initAlgebra()
107{
108 const Integer nb_row_size = m_total_nb_cell;
109 const Integer nb_row_rank = m_local_nb_cell;
110 ItacFunction(AlephTestModule);
111
112 Int32 underlying_solver = options()->alephUnderlyingSolver;
113
114 info() << "[AlephTestModule::initAlgebra] ALEPH init, " << nb_row_size
115 << " lines in total, " << nb_row_rank << " for me";
116 info() << "[AlephTestModule::initAlgebra] alephUnderlyingSolver="
118 info() << "[AlephTestModule::initAlgebra] alephNumberOfCores="
119 << options()->alephNumberOfCores;
120
121 delete m_aleph_factory;
122 m_aleph_factory = new AlephFactory(subDomain()->application(), traceMng());
123
124 // On créé en place notre politique de scheduling par rapport à la topologie décrite
125 if (m_aleph_kernel)
126 delete m_aleph_kernel;
127
128 m_aleph_kernel = new AlephKernel(traceMng(),
129 subDomain(),
130 m_aleph_factory,
132 options()->alephNumberOfCores,
133 options()->alephCellOrdering);
134 // Pour tester l'initialisation spécifique de PETSc, ajoute des arguments
135 // si le nombre de PE est pair
136
137 const bool use_is_even = (subDomain()->parallelMng()->commSize() % 2) == 0;
138 const bool use_petsc_args = (underlying_solver==AlephKernel::SOLVER_PETSC && use_is_even);
139 if (use_petsc_args){
141 slist1.add("-trmalloc");
142 slist1.add("-log_trace");
143 slist1.add("-help");
145 m_aleph_kernel->solverInitializeArgs().setCommandLineArguments(args);
146 }
147 m_aleph_kernel->initialize(nb_row_size, nb_row_rank);
148
149 delete m_aleph_params;
150 m_aleph_params = new AlephParams(traceMng(),
151 1.0e-10, // m_param_epsilon epsilon de convergence
152 2000, // m_param_max_iteration nb max iterations
153 TypesSolver::DIAGONAL, // m_param_preconditioner_method: DIAGONAL, AMG, IC
154 TypesSolver::PCG, // m_param_solver_method méthode de résolution
155 -1, // m_param_gamma
156 -1.0, // m_param_alpha
157 false, // m_param_xo_user par défaut Xo n'est pas égal à 0
158 false, // m_param_check_real_residue
159 false, // m_param_print_real_residue
160 false, // m_param_debug_info
161 1.e-20, // m_param_min_rhs_norm
162 false, // m_param_convergence_analyse
163 true, // m_param_stop_error_strategy
164 false, // m_param_write_matrix_to_file_error_strategy
165 "SolveErrorAlephMatrix.dbg", // m_param_write_matrix_name_error_strategy
166 false, // m_param_listing_output
167 0., // m_param_threshold
168 false, // m_param_print_cpu_time_resolution
169 0, // m_param_amg_coarsening_method: par défault celui de Sloop,
170 0, // m_param_output_level
171 1, // m_param_amg_cycle: 1=V, 2= W, 3=Full Multigrid V
172 1, // m_param_amg_solver_iterations
173 1, // m_param_amg_smoother_iterations
174 TypesSolver::SymHybGSJ_smoother, // m_param_amg_smootherOption
175 TypesSolver::ParallelRugeStuben, // m_param_amg_coarseningOption
176 TypesSolver::CG_coarse_solver, // m_param_amg_coarseSolverOption
177 false, // m_param_keep_solver_structure
178 false, // m_param_sequential_solver
179 TypesSolver::RB); // m_param_criteria_stop
180
181 // Calcul des indices globaux de la matrice mailles x mailles
182 // Et on prépare une fois pour toutes les indices des vecteurs
183 m_cell_matrix_idx.fill(-1);
184 {
185 AlephInt idx = 0;
186 // Tres important, car on y revient lors de la reconfiguration!!
187 m_vector_indexs.resize(0);
188 m_vector_zeroes.resize(0);
189 m_vector_lhs.resize(0);
190 const AlephInt row_offset = m_aleph_kernel->topology()->part()[m_aleph_kernel->rank()];
191 ENUMERATE_CELL (iCell, MESH_OWN_ACTIVE_CELLS(mesh())) {
192 m_cell_matrix_idx[iCell] = row_offset + idx;
193 m_vector_indexs.add(m_cell_matrix_idx[iCell] = row_offset + idx);
194 m_vector_zeroes.add(0.0);
195 m_vector_lhs.add(0.0);
196 idx += 1;
197 }
198 }
199 m_cell_matrix_idx.synchronize();
200
201 // Maintenant, on va compter le nombre d'éléments par lignes
202 // On fait un scan comme on devra en faire dans la boucle
203 //debug() << "\33[37m[AlephTestModule::initAlgebra] Comptage du nombre d'éléments des lignes locales"<<"\33[0m";
204 m_rows_nb_element.resize(nb_row_rank);
205 // Can now be forgotten
206 options()->schema()->preFetchNumElementsForEachRow(m_rows_nb_element,
207 m_aleph_kernel->topology()->part()[m_aleph_kernel->rank()]);
208 debug() << "\33[37m[AlephTestModule::initAlgebra] done\33[0m";
209}
210
211/***************************************************************************
212 * Entry points leads us here
213 ***************************************************************************/
214void AlephTestModule::
215compute()
216{
217 Integer delta_amr = 0;
220 debug() << "\33[37m[AlephTestModule::compute]\33[0m";
221 const Integer rank_offset = m_aleph_kernel->topology()->part()[m_aleph_kernel->rank()];
222 ItacFunction(AlephTestModule);
223
224 for (int i = 0; i < options()->alephNumberOfSolvers; i += 1)
225 postSolver(i);
226
227 // And should be able to get the solutions after the last resolution was fired
228 for (int i = options()->alephNumberOfSolvers - 1; i >= 0; i -= 1) {
229 debug() << "\33[37m[AlephTestModule::compute] Getting solution #" << i << "\33[0m";
230 AlephVector* solution = m_aleph_kernel->syncSolver(i, nb_iteration, &residual_norm[0]);
231 //if (i!=m_get_solution_idx) continue;
232 info() << "\33[37mSolved in \33[7m" << nb_iteration << "\33[m iterations,"
233 << "residuals=[\33[1m" << residual_norm[0] << "\33[m," << residual_norm[3] << "]";
234 debug() << "\33[37m[AlephTestModule::compute] Applying solution #" << m_get_solution_idx << "\33[0m";
235 solution->getLocalComponents(m_vector_indexs.size(), m_vector_indexs.view(), m_vector_lhs.view());
236 m_get_solution_idx += 1;
237 }
238 m_get_solution_idx %= options()->alephNumberOfSolvers;
239
241 // AMR COARSEN & REFINE //
243 /*if (options()->schema()->amrRefine(m_vector_lhs, options()->trigRefine)==true){
244 debug()<<"\33[37m[AlephTestModule::compute] AMR REFINE"<<"\33[0m";
245 initAlgebra();
246 delta_amr+=1;
247 return;
248 }
249 if (options()->schema()->amrCoarsen(m_vector_lhs, options()->trigCoarse)==true){
250 debug()<<"\33[37m[AlephTestModule::compute] AMR COARSEN"<<"\33[0m";
251 initAlgebra();
252 delta_amr+=1;
253 return;
254 }*/
255
257 // DELETE or NOT the KERNEL between each iteration //
259 if (options()->alephDeleteKernel() == true) {
260 debug() << "\33[37m[AlephTestModule::compute] DELETE the KERNEL between each iteration"
261 << "\33[0m";
262 initAlgebra();
263 }
264
265 // Sinon, on recopie les résultats
266 debug() << "\33[37m[AlephTestModule::compute] Now get our results"
267 << "\33[0m";
268 ENUMERATE_CELL (iCell, MESH_OWN_ACTIVE_CELLS(mesh())) {
269 m_cell_temperature[iCell] = m_vector_lhs[m_cell_matrix_idx[iCell] - rank_offset];
270 }
271
272 // Si on a atteint notre maximum d'itérations, on sort
273 if (subDomain()->commonVariables().globalIteration() >= options()->iterations + delta_amr)
274 subDomain()->timeLoopMng()->stopComputeLoop(true);
275
276 debug() << "\33[37m[AlephTestModule::compute] done"
277 << "\33[0m";
278}
279
280/***************************************************************************
281 * job
282 ***************************************************************************/
283void AlephTestModule::
284postSolver(const Integer i)
285{
286 ItacFunction(AlephTestModule);
287 debug() << "\33[37m[AlephTestModule::postSolver] #" << i << "\33[0m";
288 const Integer rank_offset = m_aleph_kernel->topology()->part()[m_aleph_kernel->rank()];
289
290 // Remplissage du second membre: conditions limites + second membre
291 debug() << "\33[37m[AlephTestModule::postSolver] Remplissage du second membre"
292 << "\33[0m";
293 m_vector_rhs.resize(0);
294 ENUMERATE_CELL (iCell, MESH_OWN_ACTIVE_CELLS(mesh())) {
295 m_vector_rhs.add(m_cell_temperature[iCell]);
296 }
297
298 debug() << "\33[37m[AlephTestModule::postSolver] ENUMERATE_FACE"
299 << "\33[0m";
300 ENUMERATE_FACE (iFace, OUTER_ACTIVE_FACE_GROUP(allCells())) {
301 if (!iFace->cell(0).isOwn())
302 continue;
303 m_vector_rhs[m_cell_matrix_idx[iFace->cell(0)] - rank_offset] +=
304 options()->deltaT * (m_face_temperature[iFace]) / geoFaceSurface(*iFace, nodesCoordinates());
305 }
306
307 // Création de la matrice MatVec et des besoins Aleph
308 m_aleph_mat.setAt(i, m_aleph_kernel->createSolverMatrix());
309 m_aleph_rhs.setAt(i, m_aleph_kernel->createSolverVector()); // First vector returned IS the rhs
310 m_aleph_sol.setAt(i, m_aleph_kernel->createSolverVector()); // Next one IS the solution
311
312 //m_aleph_mat.at(i)->create(m_rows_nb_element);
313 m_aleph_mat.at(i)->create();
314 m_aleph_rhs.at(i)->create();
315 m_aleph_sol.at(i)->create();
316
317 // Remplissage de la matrice et assemblage
318 options()->schema()->setValues(options()->deltaT, m_aleph_mat.at(i));
319 m_aleph_mat.at(i)->assemble();
320
321 debug() << "\33[37m[AlephTestModule::postSolver] setLocalComponents"
322 << "\33[0m";
323 m_aleph_rhs.at(i)->setLocalComponents(m_vector_indexs.size(), m_vector_indexs.view(), m_vector_rhs.view());
324 m_aleph_rhs.at(i)->assemble();
325
326 m_aleph_sol.at(i)->setLocalComponents(m_vector_indexs.size(), m_vector_indexs.view(), m_vector_zeroes.view());
327 m_aleph_sol.at(i)->assemble();
328
329 // Now solve with Aleph
330 debug() << "\33[37m[AlephTestModule::postSolver] Now solve with Aleph"
331 << "\33[0m";
332 m_aleph_mat.at(i)->solve(m_aleph_sol.at(i),
333 m_aleph_rhs.at(i),
334 m_fake_nb_iteration,
335 &m_fake_residual_norm[0],
336 m_aleph_params,
337 true); // On souhaite poster de façon asynchrone
338}
339
340/***************************************************************************
341 * geoFaceSurface
342 ***************************************************************************/
343Real AlephTestModule::
344geoFaceSurface(Face face, VariableItemReal3& nodes_coords)
345{
346 if (face.nbNode() == 4) {
347 const Real3 xyz0 = nodes_coords[face.node(0)];
348 const Real3 xyz1 = nodes_coords[face.node(1)];
349 const Real3 xyz3 = nodes_coords[face.node(3)];
350 return (xyz0 - xyz1).normL2() * (xyz0 - xyz3).normL2();
351 }
352 if (face.nbNode() == 2) {
353 const Real3 xyz0 = nodes_coords[face.node(0)];
354 const Real3 xyz1 = nodes_coords[face.node(1)];
355 return (xyz0 - xyz1).squareNormL2();
356 }
357 throw FatalErrorException("geoFace", "Nb nodes != 4 !=2");
358}
359
360/***************************************************************************
361 * amrRefineMesh *
362 ***************************************************************************/
363void AlephTestModule::
364initAmrRefineMesh(Integer nb_to_refine)
365{
366 ItacFunction(AlephTestModule);
367 if (nb_to_refine == 0)
368 return;
369
370 info() << "Refining nb_to_refine=" << nb_to_refine;
371
373 ENUMERATE_CELL (iCell, allCells()) {
374 Cell cell = *iCell;
375 if ((cell.type() == IT_Hexaedron8) || (cell.type() == IT_Quad4)) {
376 if (nb_to_refine-- <= 0)
377 break;
378 info(5) << "\t[amrRefineMesh] refine cell.uid=" << cell.uniqueId();
379 cells_local_id.add(cell.localId());
380 //iItem->setFlags(iItem->flags() | ItemInternal::II_Refine);
381 }
382 }
383
384 info() << "now refine";
385 mesh()->modifier()->flagCellToRefine(cells_local_id);
386 mesh()->modifier()->adapt();
387
388 //MESH_MODIFIER_REFINE_ITEMS(mesh());
389
390 // Now callBack the values
391 CellInfoListView cells(mesh()->cellFamily());
392 //ItemInternalList faces = mesh()->faceFamily()->itemsInternal();
393 for (Integer i = 0, is = cells_local_id.size(); i < is; ++i) {
395 Cell cell = cells[lid];
396 //debug()<<"[amrRefineMesh] focus on cell #"<<lid<<", nbHChildren="<<cell.nbHChildren();
397 for (Integer j = 0, js = CELL_NB_H_CHILDREN(cell); j < js; ++j) {
398 //debug()<<"\t\t[amrRefineMesh] child cell #"<<cell.hChild(j).localId();
399 m_cell_temperature[cells[CELL_H_CHILD(cell, j).localId()]] = m_cell_temperature[cells[lid]];
400 auto faces = allCells().view()[CELL_H_CHILD(cell, j).localId()].toCell().faces();
401 Integer index = 0;
402 for( Face face : faces ){
403 if (face.isSubDomainBoundary()) {
404 //debug() << "\t\t\t[amrRefineMesh] outer face #"<< (*iFace).localId()<<", index="<<iFace.index()<<", T="<<m_face_temperature[cell.face(iFace.index())];
405 m_face_temperature[face] = m_face_temperature[cell.face(index)];
406 }
407 else {
408 //debug() << "\t\t\t[amrRefineMesh] inner face #"<< (*iFace).localId();//<<", T="<<m_face_temperature[face.toFace()];
409 m_face_temperature[face] = 0;
410 }
411 ++index;
412 }
413 }
414 }
415}
416
417/*---------------------------------------------------------------------------*/
418/*---------------------------------------------------------------------------*/
419
420ARCANE_DEFINE_STANDARD_MODULE(AlephTestModule, AlephTest);
421
422/*---------------------------------------------------------------------------*/
423/*---------------------------------------------------------------------------*/
424
425}
426
427/*---------------------------------------------------------------------------*/
428/*---------------------------------------------------------------------------*/
#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.
Module de test pour Aleph.
Paramètres d'un système linéraire.
Definition AlephParams.h:34
Vecteur d'un système linéaire.
Definition AlephVector.h:33
Vue sur les informations des mailles.
Maille d'un maillage.
Definition Item.h:1178
FaceConnectedListViewType faces() const
Liste des faces de la maille.
Definition Item.h:1258
Face face(Int32 i) const
i-ème face de la maille
Definition Item.h:1255
Arguments de la ligne de commande.
Face d'une maille.
Definition Item.h:932
bool isSubDomainBoundary() const
Indique si la face est au bord du sous-domaine (i.e nbCell()==1)
Definition Item.h:1025
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
constexpr Int32 localId() const
Identifiant local de l'entité dans le sous-domaine du processeur.
Definition Item.h:210
Cell toCell() const
Converti l'entité en le genre Cell.
Definition Item.h:1654
ItemUniqueId uniqueId() const
Identifiant unique sur tous les domaines.
Definition Item.h:216
Int16 type() const
Type de l'entité
Definition Item.h:232
Lecteur des fichiers de maillage via la bibliothèque LIMA.
Definition Lima.cc:120
Informations pour construire un module.
Classe gérant un vecteur de réel de dimension 3.
Definition Real3.h:132
Exception lorsqu'une erreur fatale est survenue.
Vecteur 1D de données avec sémantique par valeur (style STL).
-*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
Int32 Integer
Type représentant un entier.