Arcane  v3.14.10.0
Documentation développeur
Chargement...
Recherche...
Aucune correspondance
AlephMatrix.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/* AlephMatrix.cc (C) 2000-2024 */
9/* */
10/*---------------------------------------------------------------------------*/
11/*---------------------------------------------------------------------------*/
12
13#include "arcane/aleph/AlephArcane.h"
14#include "arcane/MeshVariableScalarRef.h"
15
16/*---------------------------------------------------------------------------*/
17/*---------------------------------------------------------------------------*/
18
19namespace Arcane
20{
21
22/*---------------------------------------------------------------------------*/
23/*---------------------------------------------------------------------------*/
24
25/******************************************************************************
26 *****************************************************************************/
27AlephMatrix::
28AlephMatrix(AlephKernel* kernel)
29: TraceAccessor(kernel->parallel()->traceMng())
30, m_kernel(kernel)
31, m_index(kernel->index())
32, m_setValue_idx(0)
33, m_addValue_idx(0)
34{
35 ItacFunction(AlephMatrix);
36 if (kernel->isInitialized() == false) {
37 debug() << "\33[1;32m[AlephMatrix::AlephMatrix] New Aleph matrix, but kernel is not initialized!\33[0m";
38 return;
39 }
40 // Récupération des rangs utilisés pour cette résolution
41 m_ranks = kernel->solverRanks(m_index);
42 // Booléen pour savoir si on participe ou pas
43 m_participating_in_solver = kernel->subParallelMng(m_index) != NULL;
44 debug() << "\33[1;32m[AlephMatrix::AlephMatrix] New Aleph matrix\33[0m";
45 if (!m_participating_in_solver) {
46 debug() << "\33[1;32m[AlephMatrix::AlephMatrix] Not concerned by this one!\33[0m";
47 return;
48 }
49 debug() << "\33[1;32m[AlephMatrix::AlephMatrix] site size="
50 << m_kernel->subParallelMng(m_index)->commSize()
51 << " @"
52 << m_kernel->subParallelMng(m_index)->commRank() << "\33[0m";
53 // On va chercher une matrice depuis la factory qui fait l'interface aux bibliothèques externes
54 m_implementation = m_kernel->factory()->GetMatrix(m_kernel, m_index);
55 traceMng()->flush();
56}
57
58/******************************************************************************
59 *****************************************************************************/
60AlephMatrix::
61~AlephMatrix()
62{
63 ItacFunction(AlephMatrix);
64 debug() << "\33[1;32m\t\t[~AlephMatrix]\33[0m";
65 rowColMap::const_iterator i = m_row_col_map.begin();
66 for (; i != m_row_col_map.end(); ++i)
67 delete i->second;
68}
69
70/******************************************************************************
71 * Matrix 'create' avec l'API 'void'
72 * BaseForm[Hash["AlephMatrix::create(void)", "CRC32"], 16] = fff06e2
73 *****************************************************************************/
74void AlephMatrix::create(void)
75{
76 Timer::Action ta(m_kernel->subDomain(), "AlephMatrix::create");
77 debug() << "\33[1;32m[AlephMatrix::create(void)]\33[0m";
78 // Si le kernel n'est pas initialisé, on a rien à faire
79 if (!m_kernel->isInitialized())
80 return;
81 // S'il y a des 'autres' et qu'on en fait pas partie,
82 // on broadcast qu'un 'create' est à faire
83 if (m_kernel->thereIsOthers() && !m_kernel->isAnOther())
84 m_kernel->world()->broadcast(UniqueArray<unsigned long>(1, 0xfff06e2l).view(), 0);
85 // On flush en prévision du remplissage, il faut le faire même étant configuré
86 // Par contre, on ne flush pas celui du addValue
87 m_setValue_idx = 0;
88}
89
90/******************************************************************************
91 * Matrix 'create' avec l'API qui spécifie le nombre d'éléments non nuls pas lignes
92 * BaseForm[Hash["AlephMatrix::create(IntegerConstArrayView,bool)", "CRC32"], 16] = 5c3111b1
93 *****************************************************************************/
94void AlephMatrix::
95create(IntegerConstArrayView row_nb_element, bool has_many_elements)
96{
97 ARCANE_UNUSED(row_nb_element);
98 ARCANE_UNUSED(has_many_elements);
99 debug() << "\33[1;32m[AlephMatrix::create(old API)] API with row_nb_element + has_many_elements\33[0m";
100 this->create();
101}
102
106void AlephMatrix::
107reset(void)
108{
109 Timer::Action ta(m_kernel->subDomain(), "AlephMatrix::reset");
110 debug() << "\33[1;32m[AlephMatrix::reset]\33[0m";
111 m_setValue_val.fill(0.0);
112 m_addValue_val.fill(0.0);
113}
114
118void AlephMatrix::
119addValue(const VariableRef& rowVar, const ItemEnumerator& rowItm,
121 const Real val)
122{
123 addValue(rowVar, *rowItm, colVar, *colItm, val);
124}
125void AlephMatrix::addValue(const VariableRef& rowVar, const Item& rowItm,
126 const VariableRef& colVar, const Item& colItm,
127 const Real val)
128{
129 AlephInt row = m_kernel->indexing()->get(rowVar, rowItm);
130 AlephInt col = m_kernel->indexing()->get(colVar, colItm);
131 if (m_kernel->isInitialized()) {
132 const AlephInt row_offset = m_kernel->topology()->part()[m_kernel->rank()];
133 row += row_offset;
134 col += row_offset;
135 }
136 //debug()<<"[AlephMatrix::addValue] IVariable/Item add @ ["<<row<<","<<col<<"]="<<val;
137 addValue(row, col, val);
138}
139
140void AlephMatrix::
141updateKnownRowCol(Integer row,
142 Integer col,
143 Real val)
144{
145 //debug()<<"\33[1;32m[AlephMatrix::updateKnownRowCol]\33[0m";
146 m_addValue_row.add(row);
147 m_addValue_col.add(col);
148 m_addValue_val.add(val);
149 m_addValue_idx += 1;
150 // On fait de même coté 'set' pour avoir la bonne taille
151 m_setValue_row.add(row);
152 m_setValue_col.add(col);
153 m_setValue_val.add(0.);
154}
155
156void AlephMatrix::
157rowMapMapCol(Integer row,
158 Integer col,
159 Real val)
160{
161 rowColMap::const_iterator iRowMap = m_row_col_map.find(row);
162 // Si la row n'est même pas encore connue
163 // On rajoute une entrée map(map(m_addValue_idx))
164 if (iRowMap == m_row_col_map.end()) {
165 colMap* jMap = new colMap();
166 /*debug()<<"\33[1;32m[AlephMatrix::rowMapMapCol] row "
167 <<row<<" inconue, m_addValue_idx="
168 <<m_addValue_idx<<"\33[0m";*/
169 m_row_col_map.insert(std::make_pair(row, jMap));
170 jMap->insert(std::make_pair(col, m_addValue_idx));
171 updateKnownRowCol(row, col, val);
172 return;
173 }
174 // On focus sur la seconde dimension
175 colMap* jMap = iRowMap->second;
176 colMap::const_iterator iColMap = jMap->find(col);
177 // Si cet col n'est pas connue de cette row
178 // On rajoute une entrée
179 if (iColMap == jMap->end()) {
180 /*debug()<<"\33[1;32m[AlephMatrix::rowMapMapCol] col "
181 <<col<<" inconue, m_addValue_idx="
182 <<m_addValue_idx<<"\33[0m";*/
183 jMap->insert(std::make_pair(col, m_addValue_idx));
184 updateKnownRowCol(row, col, val);
185 return;
186 }
187 // Sinon on ajoute
188 //debug()<<"\33[1;32m[AlephMatrix::rowMapMapCol] hit\33[0m";
189 //debug()<<"[AlephMatrix::rowMapMapCol] += for ["<<row<<","<<col<<"]="<<val; traceMng()->flush();
190 m_addValue_val[iColMap->second] += val;
191}
192
196void AlephMatrix::
197addValue(Integer row, Integer col, Real val)
198{
199 //debug()<<"\33[32m[AlephMatrix::addValue] addValue("<<row<<","<<col<<")="<<val<<"\33[0m";
200 row = m_kernel->ordering()->swap(row);
201 col = m_kernel->ordering()->swap(col);
202 // Recherche de la case (row,j) si elle existe déjà
203 rowMapMapCol(row, col, val);
204}
205
209void AlephMatrix::
210setValue(const VariableRef& rowVar, const ItemEnumerator& rowItm,
212 const Real val)
213{
214 setValue(rowVar, *rowItm, colVar, *colItm, val);
215}
216
220void AlephMatrix::
221setValue(const VariableRef& rowVar, const Item& rowItm,
222 const VariableRef& colVar, const Item& colItm,
223 const Real val)
224{
225 Integer row = m_kernel->indexing()->get(rowVar, rowItm);
226 Integer col = m_kernel->indexing()->get(colVar, colItm);
227 //debug()<<"[AlephMatrix::setValue] dof #"<<m_setValue_idx<<" ["<<row<<","<<col<<"]="<<val;
228 if (m_kernel->isInitialized()) {
229 const Integer row_offset = m_kernel->topology()->part()[m_kernel->rank()];
230 row += row_offset;
231 col += row_offset;
232 }
233 setValue(row, col, val);
234}
235
239void AlephMatrix::
240setValue(Integer row, Integer col, Real val)
241{
242 // Re-ordering si besoin
243 row = m_kernel->ordering()->swap(row);
244 col = m_kernel->ordering()->swap(col);
245 // Si le kernel a déjà été configuré,
246 // on s'assure que la 'géométrie/support' n'a pas changée entre les résolutions
247 if (m_kernel->configured()) {
248 if ((m_setValue_row[m_setValue_idx] != row) ||
249 (m_setValue_col[m_setValue_idx] != col))
250 throw FatalErrorException("Aleph::setValue", "Row|Col have changed!");
251 m_setValue_row[m_setValue_idx] = row;
252 m_setValue_col[m_setValue_idx] = col;
253 m_setValue_val[m_setValue_idx] = val;
254 }
255 else {
256 m_setValue_row.add(row);
257 m_setValue_col.add(col);
258 m_setValue_val.add(val);
259 }
260 m_setValue_idx += 1;
261}
262
266Int32 AlephMatrix::
267reIdx(Integer ij,
269{
271}
272
276void AlephMatrix::
277reSetValuesIn(AlephMatrix* thisMatrix,
279{
280 for (Integer k = 0, kMx = m_setValue_idx; k < kMx; k += 1) {
281 Integer i = reIdx(m_setValue_row[k], known_items_own_address);
282 Integer j = reIdx(m_setValue_col[k], known_items_own_address);
283 thisMatrix->setValue(i, j, m_setValue_val[k]);
284 }
285}
286
290void AlephMatrix::
291reAddValuesIn(AlephMatrix* thisMatrix,
293{
294 for (Integer k = 0, kMx = m_addValue_row.size(); k < kMx; k += 1) {
295 const Integer row = reIdx(m_addValue_row[k], known_items_own_address);
296 const Integer col = reIdx(m_addValue_col[k], known_items_own_address);
297 const Real val = m_addValue_val[k];
298 thisMatrix->addValue(row, col, val);
299 }
300}
301
305void AlephMatrix::
306assemble(void)
307{
308 ItacFunction(AlephMatrix);
309 Timer::Action ta(m_kernel->subDomain(), "AlephMatrix::assemble");
310 // Si le kernel n'est pas initialisé, on ne fait toujours rien
311 if (!m_kernel->isInitialized()) {
312 debug() << "\33[1;32m[AlephMatrix::assemble] Trying to assemble a matrix"
313 << "from an uninitialized kernel!\33[0m";
314 return;
315 }
316 // Si aucun [set|add]Value n'a été perçu, ce n'est pas normal
317 if (m_addValue_idx != 0 && m_setValue_idx != 0)
318 throw FatalErrorException("AlephMatrix::assemble", "Still exclusives [add||set]Value required!");
319 // Si des addValue ont été captés, il faut les 'rejouer'
320 // Attention: pour l'instant les add et les set sont disjoints!
321 if (m_addValue_idx != 0) {
322 debug() << "\33[1;32m[AlephMatrix::assemble] m_addValue_idx!=0\33[0m";
323 // On flush notre index des setValues
324 m_setValue_idx = 0;
325 Timer::Action ta(m_kernel->subDomain(), "Flatenning addValues");
326 debug() << "\t\33[32m[AlephMatrix::assemble] Flatenning addValues size=" << m_addValue_row.size() << "\33[0m";
327 for (Integer k = 0, kMx = m_addValue_row.size(); k < kMx; ++k) {
328 m_setValue_row[k] = m_addValue_row[k];
329 m_setValue_col[k] = m_addValue_col[k];
330 m_setValue_val[k] = m_addValue_val[k];
331 /*debug()<<"\t\33[32m[AlephMatrix::assemble] setValue ("<<m_setValue_row[k]
332 <<","<<m_setValue_col[k]<<")="<<m_setValue_val[k]<<"\33[0m";*/
333 m_setValue_idx += 1;
334 }
335 }
336 // S'il y a des 'autres' et qu'on en fait pas parti, on les informe de l'assemblage
337 if (m_kernel->thereIsOthers() && !m_kernel->isAnOther()) {
338 debug() << "\33[1;32m[AlephMatrix::assemble] On informe les autres kappa que l'on assemble"
339 << "\33[0m";
340 m_kernel->world()->broadcast(UniqueArray<unsigned long>(1, 0x74f253cal).view(), 0);
341 // Et on leur donne l'info du m_setValue_idx
342 m_kernel->world()->broadcast(UniqueArray<Integer>(1, m_setValue_idx).view(), 0);
343 }
344 // On initialise la topologie si cela n'a pas été déjà fait
345 if (!m_kernel->isAnOther()) {
346 debug() << "\33[1;32m[AlephMatrix::assemble] Initializing topology"
347 << "\33[0m";
348 ItacRegion(topology->create, AlephMatrix);
349 m_kernel->topology()->create(m_setValue_idx);
350 }
351 // Si on a pas déjà calculé le nombre d'éléments non nuls par lignes
352 // c'est le moment de le déclencher
353 debug() << "\33[1;32m[AlephMatrix::assemble] Updating row_nb_element"
354 << "\33[0m";
355 if (!m_kernel->topology()->hasSetRowNbElements()) {
357 row_nb_element.resize(m_kernel->topology()->nb_row_rank());
358 row_nb_element.fill(0);
359 // Quand on est pas un Autre, il faut mettre à jour le row_nb_element si cela n'a pas été spécifié lors du matrice->create
360 if (m_kernel->thereIsOthers() && !m_kernel->isAnOther()) {
361 debug() << "\33[1;32m[AlephMatrix::assemble] Kernel's topology has not set its nb_row_elements, now doing it!"
362 << "\33[0m";
363 const Integer row_offset = m_kernel->topology()->part()[m_kernel->rank()];
364 debug() << "\33[1;32m[AlephMatrix::assemble] row_offset=" << row_offset << "\33[0m";
365 debug() << "\33[1;32m[AlephMatrix::assemble] filled, row_nb_element.size=" << row_nb_element.size() << "\33[0m";
366 // On le fait pour l'instant en une passe pour avoir une borne max
367 for (Integer i = 0, iMx = m_setValue_row.size(); i < iMx; ++i)
368 row_nb_element[m_setValue_row.at(i) - row_offset] += 1;
369 }
370 m_kernel->topology()->setRowNbElements(row_nb_element);
371 debug() << "\33[1;32m[AlephMatrix::assemble] done hasSetRowNbElements"
372 << "\33[0m";
373 }
374 // Dans le cas //, le solveur se prépare à récupérer les parties de matrices venant des autres
375 debug() << "\33[1;32m[AlephMatrix::assemble] Récupération des parties de matrices"
376 << "\33[0m";
377 if (m_participating_in_solver && (!m_kernel->configured())) {
378 UniqueArray<Integer> nbValues(m_kernel->size());
379 {
380 ItacRegion(gathered_nb_setValued, AlephMatrix);
381 nbValues.fill(0);
382 for (Integer iCpu = 0; iCpu < m_kernel->size(); ++iCpu) {
383 if (m_kernel->rank() != m_ranks[iCpu])
384 continue;
385 //debug()<<"\33[1;32m[AlephMatrix::assemble] Adding nb_values from iCpu "<<iCpu<<"\33[0m";
386 nbValues[iCpu] = m_kernel->topology()->gathered_nb_setValued(iCpu);
387 }
388 }
389 {
390 ItacRegion(resize, AlephMatrix);
391 m_aleph_matrix_buffer_rows.resize(nbValues);
392 m_aleph_matrix_buffer_cols.resize(nbValues);
393 m_aleph_matrix_buffer_vals.resize(nbValues);
394 }
395 }
396 // Si on est pas en //, on a rien d'autre à faire
397 if (!m_kernel->isParallel())
398 return;
399 // Si je participe à la résolution, je reçois les contributions des autres participants
400 if (m_participating_in_solver) {
401 ItacRegion(iRecv, AlephMatrix);
402 debug() << "\33[1;32m[AlephMatrix::assemble] I am part of the solver, let's iRecv"
403 << "\33[0m";
404 // Si je suis le solveur, je recv le reste des matrices provenant soit des autres coeurs, soit de moi-même
405 for (Integer iCpu = 0; iCpu < m_kernel->size(); ++iCpu) {
406 // Sauf de moi-même
407 if (iCpu == m_kernel->rank())
408 continue;
409 // Sauf de ceux qui ne participent pas
410 if (m_kernel->rank() != m_ranks[iCpu])
411 continue;
412 debug() << "\33[1;32m[AlephMatrix::assemble] "
413 << " recv " << m_kernel->rank()
414 << " <= " << iCpu
415 << " size=" << m_aleph_matrix_buffer_cols[iCpu].size() << "\33[0m";
416 m_aleph_matrix_mpi_data_requests.add(m_kernel->world()->recv(m_aleph_matrix_buffer_vals[iCpu], iCpu, false));
417 // Une fois configuré, nous connaissons tous les (i,j): pas besoin de les renvoyer
418 if (!m_kernel->configured()) {
419 m_aleph_matrix_mpi_data_requests.add(m_kernel->world()->recv(m_aleph_matrix_buffer_rows[iCpu], iCpu, false));
420 m_aleph_matrix_mpi_data_requests.add(m_kernel->world()->recv(m_aleph_matrix_buffer_cols[iCpu], iCpu, false));
421 }
422 }
423 }
424 // Si je suis un rang Arcane qui a des données à envoyer, je le fais
425 if ((m_kernel->rank() != m_ranks[m_kernel->rank()]) && (!m_kernel->isAnOther())) {
426 ItacRegion(iSend, AlephMatrix);
427 debug() << "\33[1;32m[AlephMatrix::assemble]"
428 << " send " << m_kernel->rank()
429 << " => " << m_ranks[m_kernel->rank()]
430 << " for " << m_setValue_val.size() << "\33[0m";
431 m_aleph_matrix_mpi_data_requests.add(m_kernel->world()->send(m_setValue_val, m_ranks[m_kernel->rank()], false));
432 if (!m_kernel->configured()) {
433 debug() << "\33[1;32m[AlephMatrix::assemble] iSend my row to " << m_ranks[m_kernel->rank()] << "\33[0m";
434 m_aleph_matrix_mpi_data_requests.add(m_kernel->world()->send(m_setValue_row, m_ranks[m_kernel->rank()], false));
435 debug() << "\33[1;32m[AlephMatrix::assemble] iSend my col to " << m_ranks[m_kernel->rank()] << "\33[0m";
436 m_aleph_matrix_mpi_data_requests.add(m_kernel->world()->send(m_setValue_col, m_ranks[m_kernel->rank()], false));
437 }
438 }
439}
440
444void AlephMatrix::
445create_really(void)
446{
447 ItacFunction(AlephMatrix);
448 Timer::Action ta(m_kernel->subDomain(), "AlephMatrix::create_really");
449 debug() << "\33[1;32m[AlephMatrix::create_really]"
450 << "\33[0m";
451 // Il nous faut alors dans tous les cas une matrice de travail
452 debug() << "\33[1;32m[AlephMatrix::create_really] new MATRIX"
453 << "\33[0m";
454 // et on déclenche la création au sein de l'implémentation
455 m_implementation->AlephMatrixCreate();
456 debug() << "\33[1;32m[AlephMatrix::create_really] done"
457 << "\33[0m";
458}
459
463void AlephMatrix::
464assemble_waitAndFill(void)
465{
466 ItacFunction(AlephMatrix);
467 Timer::Action ta(m_kernel->subDomain(), "AlephMatrix::assemble_waitAndFill");
468 debug() << "\33[1;32m[AlephMatrix::assemble_waitAndFill]"
469 << "\33[0m";
470 if (m_kernel->isParallel()) {
471 ItacRegion(Wait, AlephMatrix);
472 debug() << "\33[1;32m[AlephMatrix::assemble_waitAndFill] wait for "
473 << m_aleph_matrix_mpi_data_requests.size() << " Requests"
474 << "\33[0m";
475 m_kernel->world()->waitAllRequests(m_aleph_matrix_mpi_data_requests);
476 m_aleph_matrix_mpi_data_requests.clear();
477 debug() << "\33[1;32m[AlephMatrix::assemble_waitAndFill] clear"
478 << "\33[0m";
479 if (m_participating_in_solver == false) {
480 debug() << "\33[1;32m[AlephMatrix::assemble_waitAndFill] nothing more to do"
481 << "\33[0m";
482 }
483 }
484 // Si je ne participe pas, je ne participe pas
485 if (!m_participating_in_solver)
486 return;
487 // Sinon, on prend le temps de construire la matrice, les autres devraient le faire aussi
488 if (!m_kernel->configured()) {
489 ItacRegion(Create, AlephMatrix);
490 debug() << "\33[1;32m[AlephMatrix::assemble_waitAndFill] solver " << m_index << " create_really"
491 << "\33[0m";
492 create_really();
493 }
494 // Et on enchaîne alors avec le remplissage de la matrice
495 {
496 ItacRegion(Fill, AlephMatrix);
497 if (m_kernel->configured())
498 m_implementation->AlephMatrixSetFilled(false); // Activation de la protection de remplissage
499 debug() << "\33[1;32m[AlephMatrix::assemble_waitAndFill] " << m_index << " fill"
500 << "\33[0m";
503 double* bfr_val_implem;
504 for (int iCpu = 0; iCpu < m_kernel->size(); ++iCpu) {
505 if (m_kernel->rank() != m_ranks[iCpu])
506 continue;
507 if (iCpu == m_kernel->rank()) {
508 bfr_row_implem = m_setValue_row.data();
509 bfr_col_implem = m_setValue_col.data();
510 bfr_val_implem = m_setValue_val.data();
511 m_implementation->AlephMatrixFill(m_setValue_val.size(),
515 }
516 else {
517 bfr_row_implem = m_aleph_matrix_buffer_rows[iCpu].data();
518 bfr_col_implem = m_aleph_matrix_buffer_cols[iCpu].data();
519 bfr_val_implem = m_aleph_matrix_buffer_vals[iCpu].data();
520 m_implementation->AlephMatrixFill(m_aleph_matrix_buffer_vals[iCpu].size(),
524 }
525 }
526 }
527 { // On déclare alors la matrice comme remplie, et on lance la configuration
528 ItacRegion(Cfg, AlephMatrix);
529 m_implementation->AlephMatrixSetFilled(true); // Désactivation de la protection de remplissage
530 if (!m_kernel->configured()) {
531 debug() << "\33[1;32m[AlephMatrix::assemble_waitAndFill] " << m_index << " MATRIX ASSEMBLE"
532 << "\33[0m";
533 int assrtnd = 0;
534 assrtnd = m_implementation->AlephMatrixAssemble();
535 debug() << "\33[1;32m[AlephMatrix::assemble_waitAndFill] AlephMatrixAssemble=" << assrtnd << "\33[0m";
536 // throw FatalErrorException("AlephMatrix::assemble_waitAndFill", "configuration failed");
537 }
538 }
539 debug() << "\33[1;32m[AlephMatrix::assemble_waitAndFill] done"
540 << "\33[0m";
541}
542
546void AlephMatrix::
547solve(AlephVector* x,
548 AlephVector* b,
549 Integer& nb_iteration,
550 Real* residual_norm,
552 bool async)
553{
554 ItacFunction(AlephMatrix);
555 Timer::Action ta(m_kernel->subDomain(), "AlephMatrix::solve");
556 debug() << "\33[1;32m[AlephMatrix::solve] Queuing solver " << m_index << "\33[0m";
557 m_kernel->postSolver(solver_param, this, x, b);
558 // Si on nous a spécifié le post, on ne déclenche pas le mode synchrone
559 if (async)
560 return;
561 debug() << "\33[1;32m[AlephMatrix::solve] SYNCHRONOUS MODE has been requested, syncing!"
562 << "\33[0m";
563 m_kernel->syncSolver(0, nb_iteration, residual_norm);
564 return;
565}
566
576void AlephMatrix::
577solveNow(AlephVector* x,
578 AlephVector* b,
580 Integer& nb_iteration,
581 Real* residual_norm,
582 AlephParams* params)
583{
584 Timer::Action ta(m_kernel->subDomain(), "AlephMatrix::solveNow");
585 const bool dump_to_compare =
586 (m_index == 0) && // Si on est à la première résolution
587 (m_kernel->rank() == 0) && // et qu'on est le 'master'
588 (params->writeMatrixToFileErrorStrategy()) && // et qu'on a demandé un write_matrix !
589 (m_kernel->subDomain()->commonVariables().globalIteration() == 1) && // et la première itération ou la deuxième
590 (m_kernel->nbRanksPerSolver() == 1);
591 ItacFunction(AlephMatrix);
592 if (!m_participating_in_solver) {
593 debug() << "\33[1;32m[AlephMatrix::solveNow] Nothing to do here!"
594 << "\33[0m";
595 return;
596 }
597 debug() << "\33[1;32m[AlephMatrix::solveNow]"
598 << "\33[0m";
599 if (dump_to_compare) {
600 const Integer globalIteration = m_kernel->subDomain()->commonVariables().globalIteration();
601 String mtxFilename = String("m_aleph_matrix_A_") + globalIteration;
602 String rhsFilename = String("m_aleph_vector_b_") + globalIteration;
603 warning() << "[AlephMatrix::solveNow] mtxFileName rhsFileName write_to_file";
604 writeToFile(mtxFilename.localstr());
605 b->writeToFile(rhsFilename.localstr());
606 }
607 // Déclenche la résolution au sein de la bibliothèque externe
608 m_implementation->AlephMatrixSolve(x, b, tmp,
611 params);
612 if (dump_to_compare) {
613 const Integer globalIteration = m_kernel->subDomain()->commonVariables().globalIteration();
614 String lhsFilename = String("m_aleph_vector_x_") + globalIteration;
615 x->writeToFile(lhsFilename.localstr());
616 }
617 if (m_kernel->isCellOrdering())
618 debug() << "\33[1;32m[AlephMatrix::solveSync_waitAndFill] // nb_iteration="
619 << nb_iteration << ", residual_norm=" << *residual_norm << "\33[0m";
620 if (m_kernel->isParallel())
621 return;
622 debug() << "\33[1;32m[AlephMatrix::solveSync_waitAndFill] // nb_iteration="
623 << nb_iteration << ", residual_norm=" << *residual_norm << "\33[0m";
624 return;
625}
626
630void AlephMatrix::
631reassemble(Integer& nb_iteration,
632 Real* residual_norm)
633{
634 ItacFunction(AlephMatrix);
635 Timer::Action ta(m_kernel->subDomain(), "AlephMatrix::reassemble");
636 // Si on est pas en mode parallèle, on en a finit pour le solve
637 if (!m_kernel->isParallel())
638 return;
639 m_aleph_matrix_buffer_n_iteration.resize(1);
640 m_aleph_matrix_buffer_n_iteration[0] = nb_iteration;
641 m_aleph_matrix_buffer_residual_norm.resize(4);
642 m_aleph_matrix_buffer_residual_norm[0] = residual_norm[0];
643 m_aleph_matrix_buffer_residual_norm[1] = residual_norm[1];
644 m_aleph_matrix_buffer_residual_norm[2] = residual_norm[2];
645 m_aleph_matrix_buffer_residual_norm[3] = residual_norm[3];
646 // Il faut recevoir des données
647 if (m_kernel->rank() != m_ranks[m_kernel->rank()] && !m_kernel->isAnOther()) {
648 debug() << "\33[1;32m[AlephMatrix::REassemble] " << m_kernel->rank()
649 << "<=" << m_ranks[m_kernel->rank()] << "\33[0m";
650 m_aleph_matrix_mpi_results_requests.add(m_kernel->world()->recv(m_aleph_matrix_buffer_n_iteration,
651 m_ranks[m_kernel->rank()], false));
652 m_aleph_matrix_mpi_results_requests.add(m_kernel->world()->recv(m_aleph_matrix_buffer_residual_norm,
653 m_ranks[m_kernel->rank()], false));
654 }
655 if (m_participating_in_solver) {
656 debug() << "\33[1;32m[AlephMatrix::REassemble] have participated, should send:"
657 << "\33[0m";
658 for (Integer iCpu = 0; iCpu < m_kernel->size(); ++iCpu) {
659 if (iCpu == m_kernel->rank())
660 continue;
661 if (m_kernel->rank() != m_ranks[iCpu])
662 continue;
663 debug() << "\33[1;32m[AlephMatrix::REassemble] " << m_kernel->rank() << " => " << iCpu << "\33[0m";
664 m_aleph_matrix_mpi_results_requests.add(m_kernel->world()->send(m_aleph_matrix_buffer_n_iteration,
665 iCpu, false));
666 m_aleph_matrix_mpi_results_requests.add(m_kernel->world()->send(m_aleph_matrix_buffer_residual_norm,
667 iCpu, false));
668 }
669 }
670}
671
675void AlephMatrix::
676reassemble_waitAndFill(Integer& nb_iteration, Real* residual_norm)
677{
678 ItacFunction(AlephMatrix);
679 Timer::Action ta(m_kernel->subDomain(), "AlephMatrix::reassemble_waitAndFill");
680 if (!m_kernel->isParallel())
681 return;
682 debug() << "\33[1;32m[AlephMatrix::REassemble_waitAndFill]"
683 << "\33[0m";
684 //if (m_kernel->isAnOther()) return;
685 m_kernel->world()->waitAllRequests(m_aleph_matrix_mpi_results_requests);
686 m_aleph_matrix_mpi_results_requests.clear();
687 if (!m_participating_in_solver) {
688 nb_iteration = m_aleph_matrix_buffer_n_iteration[0];
689 residual_norm[0] = m_aleph_matrix_buffer_residual_norm[0];
690 residual_norm[1] = m_aleph_matrix_buffer_residual_norm[1];
691 residual_norm[2] = m_aleph_matrix_buffer_residual_norm[2];
692 residual_norm[3] = m_aleph_matrix_buffer_residual_norm[3];
693 }
694 debug() << "\33[1;32m[AlephMatrix::REassemble_waitAndFill] // nb_iteration="
695 << nb_iteration << ", residual_norm=" << *residual_norm << "\33[0m";
696}
697
701void AlephMatrix::
702startFilling()
703{
704 ItacFunction(AlephMatrix);
705 /* Nothing here to do with this m_implementation */
706 debug() << "[AlephMatrix::startFilling] void"
707 << "\33[0m";
708}
709
713void AlephMatrix::
714writeToFile(const String file_name)
715{
716 ItacFunction(AlephMatrix);
717 debug() << "\33[1;32m[AlephMatrix::writeToFile] Dumping matrix to " << file_name << "\33[0m";
718 m_implementation->writeToFile(file_name);
719}
720
721/*---------------------------------------------------------------------------*/
722/*---------------------------------------------------------------------------*/
723
724} // namespace Arcane
725
726/*---------------------------------------------------------------------------*/
727/*---------------------------------------------------------------------------*/
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
Enumérateur sur une liste d'entités.
Classe de base d'un élément de maillage.
Definition Item.h:83
Lecteur des fichiers de maillage via la bibliothèque LIMA.
Definition Lima.cc:120
Postionne le nom de l'action en cours d'exécution.
Definition Timer.h:110
Référence à une variable.
Definition VariableRef.h:56
Exception lorsqu'une erreur fatale est survenue.
Chaîne de caractères unicode.
-*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-