13#include "arcane/aleph/AlephArcane.h"
14#include "arcane/core/MeshVariableScalarRef.h"
31, m_index(kernel->index())
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";
41 m_ranks = kernel->solverRanks(m_index);
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";
49 debug() <<
"\33[1;32m[AlephMatrix::AlephMatrix] site size="
50 << m_kernel->subParallelMng(m_index)->commSize()
52 << m_kernel->subParallelMng(m_index)->commRank() <<
"\33[0m";
54 m_implementation = m_kernel->factory()->GetMatrix(m_kernel, m_index);
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)
74void AlephMatrix::create(
void)
76 Timer::Action ta(m_kernel->subDomain(),
"AlephMatrix::create");
77 debug() <<
"\33[1;32m[AlephMatrix::create(void)]\33[0m";
79 if (!m_kernel->isInitialized())
83 if (m_kernel->thereIsOthers() && !m_kernel->isAnOther())
84 m_kernel->world()->broadcast(UniqueArray<unsigned long>(1, 0xfff06e2l).view(), 0);
95create(IntegerConstArrayView row_nb_element,
bool has_many_elements)
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";
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);
123 addValue(rowVar, *rowItm, colVar, *colItm, val);
125void AlephMatrix::addValue(
const VariableRef& rowVar,
const Item& rowItm,
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()];
137 addValue(row, col, val);
141updateKnownRowCol(Integer row,
146 m_addValue_row.add(row);
147 m_addValue_col.add(col);
148 m_addValue_val.add(val);
151 m_setValue_row.add(row);
152 m_setValue_col.add(col);
153 m_setValue_val.add(0.);
157rowMapMapCol(Integer row,
161 rowColMap::const_iterator iRowMap = m_row_col_map.find(row);
164 if (iRowMap == m_row_col_map.end()) {
165 colMap* jMap =
new colMap();
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);
175 colMap* jMap = iRowMap->second;
176 colMap::const_iterator iColMap = jMap->find(col);
179 if (iColMap == jMap->end()) {
183 jMap->insert(std::make_pair(col, m_addValue_idx));
184 updateKnownRowCol(row, col, val);
190 m_addValue_val[iColMap->second] += val;
200 row = m_kernel->ordering()->swap(row);
201 col = m_kernel->ordering()->swap(col);
203 rowMapMapCol(row, col, val);
214 setValue(rowVar, *rowItm, colVar, *colItm, val);
225 Integer row = m_kernel->indexing()->get(rowVar, rowItm);
226 Integer col = m_kernel->indexing()->get(colVar, colItm);
228 if (m_kernel->isInitialized()) {
229 const Integer row_offset = m_kernel->topology()->part()[m_kernel->rank()];
243 row = m_kernel->ordering()->swap(row);
244 col = m_kernel->ordering()->swap(col);
247 if (m_kernel->configured()) {
248 if ((m_setValue_row[m_setValue_idx] != row) ||
249 (m_setValue_col[m_setValue_idx] != col))
251 m_setValue_row[m_setValue_idx] = row;
252 m_setValue_col[m_setValue_idx] = col;
253 m_setValue_val[m_setValue_idx] = val;
256 m_setValue_row.add(row);
257 m_setValue_col.add(col);
258 m_setValue_val.add(val);
270 return *known_items_own_address[ij];
277reSetValuesIn(AlephMatrix* thisMatrix,
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]);
291reAddValuesIn(AlephMatrix* thisMatrix,
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);
308 ItacFunction(AlephMatrix);
309 Timer::Action ta(m_kernel->subDomain(),
"AlephMatrix::assemble");
311 if (!m_kernel->isInitialized()) {
312 debug() <<
"\33[1;32m[AlephMatrix::assemble] Trying to assemble a matrix"
313 <<
"from an uninitialized kernel!\33[0m";
317 if (m_addValue_idx != 0 && m_setValue_idx != 0)
318 throw FatalErrorException(
"AlephMatrix::assemble",
"Still exclusives [add||set]Value required!");
321 if (m_addValue_idx != 0) {
322 debug() <<
"\33[1;32m[AlephMatrix::assemble] m_addValue_idx!=0\33[0m";
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];
337 if (m_kernel->thereIsOthers() && !m_kernel->isAnOther()) {
338 debug() <<
"\33[1;32m[AlephMatrix::assemble] We inform the other kappas that we are assembling"
345 if (!m_kernel->isAnOther()) {
346 debug() <<
"\33[1;32m[AlephMatrix::assemble] Initializing topology"
348 ItacRegion(topology->create, AlephMatrix);
349 m_kernel->topology()->create(m_setValue_idx);
353 debug() <<
"\33[1;32m[AlephMatrix::assemble] Updating row_nb_element"
355 if (!m_kernel->topology()->hasSetRowNbElements()) {
357 row_nb_element.
resize(m_kernel->topology()->nb_row_rank());
358 row_nb_element.
fill(0);
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!"
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";
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;
370 m_kernel->topology()->setRowNbElements(row_nb_element);
371 debug() <<
"\33[1;32m[AlephMatrix::assemble] done hasSetRowNbElements"
375 debug() <<
"\33[1;32m[AlephMatrix::assemble] Récupération des parties de matrices"
377 if (m_participating_in_solver && (!m_kernel->configured())) {
380 ItacRegion(gathered_nb_setValued, AlephMatrix);
382 for (
Integer iCpu = 0; iCpu < m_kernel->size(); ++iCpu) {
383 if (m_kernel->rank() != m_ranks[iCpu])
386 nbValues[iCpu] = m_kernel->topology()->gathered_nb_setValued(iCpu);
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);
397 if (!m_kernel->isParallel())
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"
405 for (
Integer iCpu = 0; iCpu < m_kernel->size(); ++iCpu) {
407 if (iCpu == m_kernel->rank())
410 if (m_kernel->rank() != m_ranks[iCpu])
412 debug() <<
"\33[1;32m[AlephMatrix::assemble] "
413 <<
" recv " << m_kernel->rank()
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));
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));
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));
447 ItacFunction(AlephMatrix);
448 Timer::Action ta(m_kernel->subDomain(),
"AlephMatrix::create_really");
449 debug() <<
"\33[1;32m[AlephMatrix::create_really]"
452 debug() <<
"\33[1;32m[AlephMatrix::create_really] new MATRIX"
455 m_implementation->AlephMatrixCreate();
456 debug() <<
"\33[1;32m[AlephMatrix::create_really] done"
464assemble_waitAndFill(
void)
466 ItacFunction(AlephMatrix);
467 Timer::Action ta(m_kernel->subDomain(),
"AlephMatrix::assemble_waitAndFill");
468 debug() <<
"\33[1;32m[AlephMatrix::assemble_waitAndFill]"
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"
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"
479 if (m_participating_in_solver ==
false) {
480 debug() <<
"\33[1;32m[AlephMatrix::assemble_waitAndFill] nothing more to do"
485 if (!m_participating_in_solver)
488 if (!m_kernel->configured()) {
489 ItacRegion(Create, AlephMatrix);
490 debug() <<
"\33[1;32m[AlephMatrix::assemble_waitAndFill] solver " << m_index <<
" create_really"
496 ItacRegion(Fill, AlephMatrix);
497 if (m_kernel->configured())
498 m_implementation->AlephMatrixSetFilled(
false);
499 debug() <<
"\33[1;32m[AlephMatrix::assemble_waitAndFill] " << m_index <<
" fill"
503 double* bfr_val_implem;
504 for (
int iCpu = 0; iCpu < m_kernel->size(); ++iCpu) {
505 if (m_kernel->rank() != m_ranks[iCpu])
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(),
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(),
528 ItacRegion(Cfg, AlephMatrix);
529 m_implementation->AlephMatrixSetFilled(
true);
530 if (!m_kernel->configured()) {
531 debug() <<
"\33[1;32m[AlephMatrix::assemble_waitAndFill] " << m_index <<
" MATRIX ASSEMBLE"
534 assrtnd = m_implementation->AlephMatrixAssemble();
535 debug() <<
"\33[1;32m[AlephMatrix::assemble_waitAndFill] AlephMatrixAssemble=" << assrtnd <<
"\33[0m";
539 debug() <<
"\33[1;32m[AlephMatrix::assemble_waitAndFill] done"
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);
561 debug() <<
"\33[1;32m[AlephMatrix::solve] SYNCHRONOUS MODE has been requested, syncing!"
563 m_kernel->syncSolver(0, nb_iteration, residual_norm);
584 Timer::Action ta(m_kernel->subDomain(),
"AlephMatrix::solveNow");
585 const bool dump_to_compare =
587 (m_kernel->rank() == 0) &&
588 (params->writeMatrixToFileErrorStrategy()) &&
589 (m_kernel->subDomain()->commonVariables().globalIteration() == 1) &&
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!"
597 debug() <<
"\33[1;32m[AlephMatrix::solveNow]"
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";
605 b->writeToFile(rhsFilename.
localstr());
608 m_implementation->AlephMatrixSolve(x, b, tmp,
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());
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())
622 debug() <<
"\33[1;32m[AlephMatrix::solveSync_waitAndFill] // nb_iteration="
623 << nb_iteration <<
", residual_norm=" << *residual_norm <<
"\33[0m";
631reassemble(
Integer& nb_iteration,
634 ItacFunction(AlephMatrix);
635 Timer::Action ta(m_kernel->subDomain(),
"AlephMatrix::reassemble");
637 if (!m_kernel->isParallel())
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];
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));
655 if (m_participating_in_solver) {
656 debug() <<
"\33[1;32m[AlephMatrix::REassemble] have participated, should send:"
658 for (
Integer iCpu = 0; iCpu < m_kernel->size(); ++iCpu) {
659 if (iCpu == m_kernel->rank())
661 if (m_kernel->rank() != m_ranks[iCpu])
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,
666 m_aleph_matrix_mpi_results_requests.add(m_kernel->world()->send(m_aleph_matrix_buffer_residual_norm,
676reassemble_waitAndFill(
Integer& nb_iteration,
Real* residual_norm)
678 ItacFunction(AlephMatrix);
679 Timer::Action ta(m_kernel->subDomain(),
"AlephMatrix::reassemble_waitAndFill");
680 if (!m_kernel->isParallel())
682 debug() <<
"\33[1;32m[AlephMatrix::REassemble_waitAndFill]"
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];
694 debug() <<
"\33[1;32m[AlephMatrix::REassemble_waitAndFill] // nb_iteration="
695 << nb_iteration <<
", residual_norm=" << *residual_norm <<
"\33[0m";
704 ItacFunction(AlephMatrix);
706 debug() <<
"[AlephMatrix::startFilling] void"
714writeToFile(
const String file_name)
716 ItacFunction(AlephMatrix);
717 debug() <<
"\33[1;32m[AlephMatrix::writeToFile] Dumping matrix to " << file_name <<
"\33[0m";
718 m_implementation->writeToFile(file_name);
Integer size() const
Number of elements in the vector.
void create_really(void)
create_really transmits the creation order to the external library
void setValue(const VariableRef &, const Item &, const VariableRef &, const Item &, const Real)
setValue from arguments in IVariables, Items, and Real
void writeToFile(const String)
Triggers the writing of the matrix to a file.
Integer reIdx(Integer, Array< Int32 * > &)
reIdx searches for the correspondence of the AlephIndexing
Parameters of a linear system.
Vector of a linear system.
Base class for 1D data vectors.
void fill(ConstReferenceType value)
Fills the array with the value value.
void resize(Int64 s)
Changes the number of elements in the array to s.
Exception when a fatal error has occurred.
Base class for a mesh element.
Unicode character string.
const char * localstr() const
Returns the conversion of the instance into UTF-8 encoding.
Positions the name of the currently executing action.
TraceMessageDbg debug(Trace::eDebugLevel=Trace::Medium) const
Flow for a debug message.
TraceMessage warning() const
Flow for a warning message.
1D data vector with value semantics (STL style).
-- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature --
Int32 Integer
Type representing an integer.
double Real
Type representing a real number.
int AlephInt
Default type for indexing rows and columns of matrices and vectors.
std::int32_t Int32
Signed integer type of 32 bits.