Distributed vectors and matrices
Distributed vectors and matrices are implemented in Seldon. Unitary tests are present in files src/Program/Unit/Algebra/distributed_vector.cc, src/Program/Unit/Algebra/distributed_matrix_test.cc and src/Program/Unit/Algebra/distributed_solver.cc for respectively distributed vectors, distributed matrices and distributed solvers. In Montjoie, distributed block-diagonal matrices are implemented. Below, we show a basic example with these matrices
// for the constructor, you use the local number of rows DistributedMatrix<double, General, BlockDiagRow> A(n, n); // then you need to initialise the arrays used for parallel functions (e.g. matrix-vector product) A.Init(nglob, &glob_number, &OverlapRow, &original_proc, n, 1, &SharingProc, &SharingRows, MPI::COMM_WORLD); // example with two processors // processor 0 owns rows 0, 2, 5, 6, 8 // processor 1 owns rows 1, 2, 3, 4, 6, 7 // block 0 : (0, 1, 4) // block 1 : (2, 3, 6) // block 2 : (5, 7, 8) Vector<IVect> pattern(3), proc(3); for (int k = 0; k < 3; k++) { pattern(k).Reallocate(3); proc(k).Reallocate(3); } if (MPI::COMM_WORLD.Get_rank() == 0) { // block 0 : (0, 1, 4) // rows 1 and 4 are owned by processor 1, we put global numbers pattern(0)(0) = 0; pattern(0)(1) = 1; pattern(0)(2) = 4; proc(0)(0) = 0; proc(0)(1) = 1; proc(0)(2) = 1; // block 1 : (2, 3, 6) // local numbers of rows 2, 6 : 1, 3 pattern(1)(0) = 1; pattern(1)(1) = 3; pattern(1)(2) = 3; proc(1)(0) = 0; proc(1)(1) = 1; proc(1)(2) = 0; // block 2 : (5, 7, 8) // local numbers of rows 5, 8 : 2, 4 pattern(2)(0) = 2; pattern(2)(1) = 7; pattern(2)(2) = 4; proc(2)(0) = 0; proc(2)(1) = 1; proc(2)(2) = 0; } else { // block 0 : (0, 1, 4) // local numbers of rows 1, 4 : 0 3 pattern(0)(0) = 0; pattern(0)(1) = 0; pattern(0)(2) = 3; proc(0)(0) = 0; proc(0)(1) = 1; proc(0)(2) = 1; // block 1 : (2, 3, 6) // local numbers of rows 2, 3, 6 : 1, 2, 4 pattern(1)(0) = 1; pattern(1)(1) = 2; pattern(1)(2) = 4; proc(1)(0) = 1; proc(1)(1) = 1; proc(1)(2) = 1; // block 2 : (5, 7, 8) // local number of row 7 : 5 pattern(2)(0) = 5; pattern(2)(1) = 5; pattern(2)(2) = 8; proc(2)(0) = 0; proc(2)(1) = 1; proc(2)(2) = 0; } A.SetPattern(pattern, proc); // once the pattern has been defined, you can add non-zero entries to the matrix A.AddInteraction(1, 3, -2.5); // if the column is distant => AddDistantInteraction A.AddDistantInteraction(0, 4, 1, 0.8); // another solution is to convert a distributed sparse matrix into a block-diagonal one // in that case SetPattern is not needed, you just call ConvertToBlockDiagonal // once the matrix is filled, you can compute its inverse GetInverse(A);
Methods for block-diagonal distributed matrices :
Clear | clears the matrix |
Init | sets pointers to the arrays containing global row numbers and overlapped rows |
GetCommunicator | returns the MPI communicator associated with the matrix |
GetGlobalM | returns the global number of rows |
GetNodlScalar | returns the number of rows for a scalar unknown |
GetNbScalarUnknowns | returns the number of scalar unknowns |
GetProcNumber | returns a pointer to the array containing the processor number associated with each row. |
GetGlobalRowNumber | returns local to global numbering |
GetOverlapRowNumber | returns the array containing the numbers of rows already handled by an another processor |
GetOverlapProcNumber | returns the array containing the processor numbers of rows already handled by an another processor |
GetProcessorSharingRows | returns the list of processors that share rows with the current processor |
GetSharingRowNumbers | returns the list of rows shared with each processor |
SetPattern | provides the structure of the block-diagonal matrix |
AddDistantInteraction | adds a value to A(i, j) where i is local and j global |
AddRowDistantInteraction | adds a value to A(i, j) where i is global and j local |
IndexGlobal | returns the global row number of row j of block i |
WriteText | writes the distributed matrix on several files (one per processor) in ascii format |
IsReadyForMltAdd | returns true if the structure is ready to perform a matrix vector without preparation |
Assemble | assembles the block-diagonal matrix |
Functions for distributed block-diagonal matrices :
Mlt | performs a matrix-vector product |
MltAdd | performs a matrix-vector product |
Add | adds a distributed matrix to another one |
ConvertToSparse | converts a block-diagonal matrix to a sparse matrix |
ConvertToBlockDiagonal | converts a sparse matrix to a block-diagonal matrix |
Copy | Copies/Converts a distributed matrix into another one |
GetInverse | replaces a block-diagonal matrix by its inverse |
GetCholesky | replaces a block-diagonal matrix by its Cholesky factorisation |
SolveCholesky | solves L x = b or L^T x = b for a block-diagonal matrix |
MltCholesky | performs product with Cholesky factor L (or its transpose) |
EraseRow | erases rows in the distributed matrix |
EraseCol | erases columns in the distributed matrix |
GetCommunicator
Syntax
MPI::Comm& GetCommunicator();
This method returns the MPI communicator used to distribute the matrix.
Location :
DistributedBlockDiagonalMatrix.hxx
DistributedBlockDiagonalMatrixInline.cxx
GetGlobalM
Syntax
int GetGlobalM() const;
This function returns the global number of rows.
Example :
// default constructor DistributedMatrix<double, General, BlockDiagRow> A; // after filling nglob, global_row, overlap_row and overlap_proc // calling Init in order to provide these datas A.Init(nglob, &glob_number, &OverlapRow, &original_proc, Nvol, nb_u, &ProcShared, &SharedRows, MPI::COMM_WORLD); // you can access to nglob by calling GetGlobalM nglob = A.GetGlobalM();
Location :
DistributedBlockDiagonalMatrix.hxx
DistributedBlockDiagonalMatrix.cxx
GetNodlScalar
Syntax
int GetNodlScalar() const;
This method returns the local number of rows for each scalar components. Several components can be specified when Init is called.
Example :
// default constructor DistributedMatrix<double, General, BlockDiagRow> A; // after filling nglob, global_row, overlap_row and overlap_proc // calling Init in order to provide these datas A.Init(nglob, &glob_number, &OverlapRow, &original_proc, Nvol, nb_u, &ProcShared, &SharedRows, MPI::COMM_WORLD); // you can access to Nvol by calling GetNodlScalar Nvol = A.GetNodlScalar();
Location :
DistributedBlockDiagonalMatrix.hxx
DistributedBlockDiagonalMatrix.cxx
GetNbScalarUnknowns
Syntax
int GetNbScalarUnknowns() const;
This method returns the local number of scalar components. Several components can be specified when Init is called.
Example :
// default constructor DistributedMatrix<double, General, BlockDiagRow> A; // after filling nglob, global_row, overlap_row and overlap_proc // calling Init in order to provide these datas A.Init(nglob, &glob_number, &OverlapRow, &original_proc, Nvol, nb_u, &ProcShared, &SharedRows, MPI::COMM_WORLD); // you can access to nb_u by calling GetNbScalarUnknowns nb_u = A.GetNbScalarUnknowns();
Location :
DistributedBlockDiagonalMatrix.hxx
DistributedBlockDiagonalMatrix.cxx
AddDistantInteraction
Syntax
void AddDistantInteraction(int i, int jglob, int proc, const T& val);
This member function adds val for the local row i, and the global row jglob, proc being the processor that treats the global row jglob.
Example :
// default constructor DistributedMatrix<double, General, BlockDiagRow> A; // after filling nglob, global_row, overlap_row and overlap_proc // calling Init in order to provide these datas A.Init(nglob, &global_row, &overlap_row, &overlap_proc, Nvol, nb_u, &ProcShared, &SharedRows, MPI::COMM_WORLD); // for local interaction, you have to use AddInteraction A.AddInteraction(i, j, val); // when the column is distant (ie located on another processor), you have to use AddDistantInteraction // jglob : global column number // proc : distant processor // val : value to add A.AddDistantInteraction(i, jglob, proc, val);
Location :
DistributedBlockDiagonalMatrix.hxx
DistributedBlockDiagonalMatrix.cxx
AddRowDistantInteraction
Syntax
void AddRowDistantInteraction(int iglob, int j, int proc, const T& val);
This member function adds val for the global row iglob, and the local column j, proc being the processor that treats the global row iglob.
Example :
// default constructor DistributedMatrix<double, General, BlockDiagRow> A; // after filling nglob, global_row, overlap_row and overlap_proc // calling Init in order to provide these datas A.Init(nglob, &global_row, &overlap_row, &overlap_proc, Nvol, nb_u, &ProcShared, &SharedRows, MPI::COMM_WORLD); // for a local interaction, you have to use AddInteraction A.AddInteraction(i, j, val); // when the column is distant (ie located on another processor), you have to use AddDistantInteraction // i : local row number // jglob : global column number // proc : distant processor // val : value to add // for the global matrix, it means that A_{global_row(i), jglob} is incremented with val A.AddDistantInteraction(i, jglob, proc, val); // when the row is distant, you have to use AddRowDistantInteraction // iglob : global row number // j : local column number // proc : distant processor // val : value to add // for the global matrix, it means that A_{iglob, global_row(j)} is incremented with val A.AddRowDistantInteraction(iglob, j, proc, val);
Location :
DistributedBlockDiagonalMatrix.hxx
DistributedBlockDiagonalMatrix.cxx
IsReadyForMltAdd
Syntax
bool IsReadyForMltAdd() const
This member function returns true if the structure is ready to perform a matrix-vector product. This function is not really useful since if the user performs a matrix-vector product with a structure that is not ready, the program will create all the arrays needed to perform the matrix-vector product. The function IsReadyForMltAdd can be used for informative purposes, for example to avoid taking into account the cost of constructing all these arrays (they induce MPI communications) if the structure was not ready.
Example :
// default constructor DistributedMatrix<double, General, BlockDiagRow> A; // after filling nglob, global_row, overlap_row and overlap_proc // calling Init in order to provide these datas A.Init(nglob, &global_row, &overlap_row, &overlap_proc, Nvol, nb_u, &ProcShared, &SharedRows, MPI::COMM_WORLD); // for a local interaction, you have to use AddInteraction A.AddInteraction(i, j, val); // when the column is distant (ie located on another processor), you have to use AddDistantInteraction // i : local row number // jglob : global column number // proc : distant processor // val : value to add // for the global matrix, it means that A_{global_row(i), jglob} is incremented with val A.AddDistantInteraction(i, jglob, proc, val); // when the row is distant, you have to use AddRowDistantInteraction // iglob : global row number // j : local column number // proc : distant processor // val : value to add // for the global matrix, it means that A_{iglob, global_row(j)} is incremented with val A.AddRowDistantInteraction(iglob, j, proc, val); // the structure will be said "ready" for a matrix-vector operation // if a first matrix-vector product has been performed bool struct_ready = A.IsReadyForMltAdd();
Location :
DistributedBlockDiagonalMatrix.hxx
DistributedBlockDiagonalMatrix.cxx
Clear
Syntax
void Clear();
This function clears the matrix.
Example :
// default constructor DistributedMatrix<double, General, BlockDiagRow> A; // the matrix is erased A.Clear();
Location :
DistributedBlockDiagonalMatrix.hxx
DistributedBlockDiagonalMatrix.cxx
GetGlobalRowNumber
Syntax
IVect& GetGlobalRowNumber() const;
This function returns the global row numbers (local to global numbering).
Example :
// default constructor DistributedMatrix<double, General, BlockDiagRow> A; // after filling nglob, global_row, overlap_row and overlap_proc // calling Init in order to provide these datas A.Init(nglob, &glob_number, &OverlapRow, &original_proc, n, 1, &SharingProc, &SharingRows, MPI::COMM_WORLD); // you can access to global_row by calling GetGlobalRowNumber IVect& global_row = A.GetGlobalRowNumber();
Location :
DistributedBlockDiagonalMatrix.hxx
DistributedBlockDiagonalMatrix.cxx
GetOverlapRowNumber
Syntax
IVect& GetOverlapRowNumber() const;
This function returns the overlapped row numbers, i.e. rows that are already treated by another processor.
Example :
// default constructor DistributedMatrix<double, General, BlockDiagRow> A; // after filling nglob, global_row, overlap_row and overlap_proc // calling Init in order to provide these datas A.Init(nglob, &glob_number, &OverlapRow, &original_proc, n, 1, &SharingProc, &SharingRows, MPI::COMM_WORLD); // you can access to overlap_row by calling GetOverlapRowNumber IVect& overlap_row = A.GetOverlapRowNumber();
Location :
DistributedBlockDiagonalMatrix.hxx
DistributedBlockDiagonalMatrix.cxx
GetOverlapProcNumber
Syntax
IVect& GetOverlapProcNumber() const;
This function returns the processor numbers associated with overlapped row numbers, i.e. rows that are already treated by another processor.
Example :
// default constructor DistributedMatrix<double, General, BlockDiagRow> A; // after filling nglob, global_row, overlap_row and overlap_proc // calling Init in order to provide these datas A.Init(nglob, &glob_number, &OverlapRow, &original_proc, n, 1, &SharingProc, &SharingRows, MPI::COMM_WORLD); // you can access to original_proc by calling GetOverlapProcNumber IVect& original_proc = A.GetOverlaProcNumber();
Location :
DistributedBlockDiagonalMatrix.hxx
DistributedBlockDiagonalMatrix.cxx
GetProcessorSharingRows
Syntax
IVect& GetProcessorSharingRows() const;
This function returns the processor numbers that share rows with the current processor.
Example :
// default constructor DistributedMatrix<double, General, BlockDiagRow> A; // after filling nglob, global_row, overlap_row and overlap_proc // calling Init in order to provide these datas A.Init(nglob, &glob_number, &OverlapRow, &original_proc, n, 1, &SharingProc, &SharingRows, MPI::COMM_WORLD); // you can access to SharingProc by calling GetProcessorSharingRows IVect& SharingProc = A.GetProcessorSharingRows();
Location :
DistributedBlockDiagonalMatrix.hxx
DistributedBlockDiagonalMatrix.cxx
GetSharingRowNumbers
Syntax
Vector<IVect>& GetSharingRowNumbers() const;
This function returns the row numbers that are shared with other processors.
Example :
// default constructor DistributedMatrix<double, General, BlockDiagRow> A; // after filling nglob, global_row, overlap_row and overlap_proc // calling Init in order to provide these datas A.Init(nglob, &glob_number, &OverlapRow, &original_proc, n, 1, &SharingProc, &SharingRows, MPI::COMM_WORLD); // you can access to SharingRows by calling GetSharingRowNumbers IVect& SharingProc = A.GetSharingRowNumbers();
Location :
DistributedBlockDiagonalMatrix.hxx
DistributedBlockDiagonalMatrix.cxx
WriteText
Syntax
void WriteText(string) const; void WriteText(ostream&) const;
This member function writes the matrix on files or output streams in text format. Each processor writes its part of the matrix on a different file (ending with _P0.dat, _P1.dat, etc).
Example :
// default constructor DistributedMatrix<double, General, BlockDiagRow> A; // you can write the matrix in files // the matrix here will be written in files mat_P0.dat, mat_P1.dat, etc A.WriteText("mat.dat");
Location :
DistributedBlockDiagonalMatrix.hxx
DistributedBlockDiagonalMatrix.cxx
MltAdd
Syntax
void MltAdd(const T& alpha, const DistributedMatrix<T>& A, const Vector<T>& x, const T& beta, Vector<T>& y, bool assemble); void MltAdd(const T& alpha, const SeldonTranspose&, const DistributedMatrix<T>& A, const Vector<T>& x, const T& beta, Vector<T>& y, bool assemble);
This function can perform matrix-vector product (with the original matrix or with its transpose). The matrix-matrix product is currently not implemented. If the communicator contains only one processor, the sequential function MltAdd (with the class Matrix) will be called, otherwise an error will be displayed during the execution.
Example :
// default constructor DistributedMatrix<double, General, BlockDiagRow> A; // global row numbers are provided with Init (glob_number) A.Init(nglob, &glob_number, &OverlapRow, &original_proc, Nvol, nb_u, &ProcShared, &SharedRows, MPI::COMM_WORLD); // once the matrix is constructed, matrix-vector products can be performed // each vector is stored as a usual Seldon vector (class Vector) // each processor is assumed to store the values of the vector for the // global rows given during the construction of the matrix (here, the array glob_number) Vector<double> x(n), y(n), z; // MltAdd will assume that the values of x for rows that are shared between processors are the same // which is here not the case when calling FillRand x.FillRand(); y.FillRand(); z = y; // a solution is to call AssembleVector to ensure this property AssembleVector(x, MPI::SUM, ProcShared, SharedRows, MPI::COMM_WORLD, Nvol, nb_u, 23); double alpha = 2.5, beta = 0.4; // matrix-vector product y = beta y + alpha A x // the default value of the last argument (assemble) is true // the result y is assembled and will contain the same result as a sequential matrix-vector product, // the values being distributed in the different processors MltAdd(alpha, A, x, beta, y); // assemble = true, induces a final call to the function AssembleVector (to add values of shared rows) // if the user wants to perform a matrix-vector product without performing this final assembling step, he puts false in the last optional argument MltAdd(alpha, A, x, beta, z, false); // and perform the assembling phase later AssembleVector(z, MPI::SUM, ProcShared, SharedRows, MPI::COMM_WORLD, Nvol, nb_u, 23); // MltAdd can be used to perform a matrix-vector with the transpose matrix or the transpose conjugate MltAdd(alpha, SeldonTrans, A, x, beta, y);
Location :
DistributedBlockDiagonalMatrix.hxx
DistributedBlockDiagonalMatrix.cxx
Add
Syntax
void Add(const T& alpha, const DistributedMatrix<T>& A, DistributedMatrix<T>& B);
This function adds a distributed matrix multiplied by a scalar to another distributed matrix. The two matrices are assumed to have the same global row numbers.
Example :
// default constructor DistributedMatrix<double, General, BlockDiagRow> A; // global row numbers are provided with Init (glob_number) A.Init(nglob, &glob_number, &OverlapRow, &original_proc, Nvol, nb_u, &ProcShared, &SharedRows, MPI::COMM_WORLD); // a way to have the same global row numbers // is to use Init with the matrix A DistributedMatrix<double, General, BlockDiagRow> B; B.Init(A); double alpha = 2.1; // we compute B = B + alpha A Add(alpha, A, B);
Location :
DistributedBlockDiagonalMatrix.hxx
DistributedBlockDiagonalMatrix.cxx
Copy
Syntax
void Copy(const DistributedMatrix<T>& A, DistributedMatrix<T>&);
This function converts a distributed sparse matrix into another one. The format can be different (RowSparse, ColSparse, ArrayRowSparse, etc), the local part of the matrix is converted by calling the appropriate Copy function (located in the file Matrix_Conversions.cxx), the distributed part is always stored with the same format.
Location :
DistributedBlockDiagonalMatrix.hxx
DistributedBlockDiagonalMatrix.cxx
EraseRow
Syntax
void EraseRow(IVect& num, DistributedMatrix& A);
This function erases some rows (local row numbers are provided in num) of the matrix A.
Example :
// default constructor DistributedMatrix<double, General, BlockDiagRow> A; // after filling nglob, global_row, overlap_row and overlap_proc // calling Init in order to provide these datas A.Init(nglob, &global_row, &overlap_row, &overlap_proc, MPI::COMM_WORLD); // then you can erase some rows IVect num(2); num(0) = 2; num(1) = 5; EraseRow(num, A);
Location :
DistributedBlockDiagonalMatrix.hxx
DistributedBlockDiagonalMatrix.cxx
EraseCol
Syntax
void EraseCol(IVect& num, DistributedMatrix& A);
This function erases some columns (local column numbers are provided in num) of the matrix A.
Example :
// default constructor DistributedMatrix<double, General, BlockDiagRow> A; // after filling nglob, global_row, overlap_row and overlap_proc // calling Init in order to provide these datas A.Init(nglob, &global_row, &overlap_row, &overlap_proc, MPI::COMM_WORLD); // then you can erase some columns IVect num(2); num(0) = 4; num(1) = 9; EraseCol(num, A);
Location :
DistributedBlockDiagonalMatrix.hxx
DistributedBlockDiagonalMatrix.cxx
Init
Syntax
void Init(int nglob, IVect* global_row, IVect* overlap_row, IVect* overlap_proc, int Nvol, int nb_u, IVect* SharingProc, Vector<IVect>* SharingRows, MPI::Comm& comm); void Init(const DistributedMatrix<T>&);
The function Init must be called after the constructor in order to provide the global row numbers (array global_row), the rows already treated by another processor (array overlap_row), the processors that treat originally these rows (array overlap_proc) and the MPI communicator. Nvol is the number of rows for a scalar component, nb_u the number of scalar components, SharingProc stores the processors that share rows with current processor, and SharingRows the local row numbers that are shared with processor SharingProc(i). These numbers are assumed to be sorted such that shared row numbers with processor j in processor i correspond to row numbers shared with processor i in processor j.
Example :
// on each processor, you specify rows that are already treated by another processor // for example if the processor 0 handles rows [0, 3, 5, 6] and // processor 1 the rows [1 2, 4, 5, 7], the row 5 is already treated by // processor 0. Of course, if each row is treated by a processor and only one // this array should be left empty IVect OverlapRow; int nglob = 8; int n = 4; if (MPI::COMM_WORLD.Get_rank() == 1) { n = 5; OverlapRow.Reallocate(1); // be careful because OverlapRow stores local numbers // here the global row 5 has a local number equal to 3 on processor 1 OverlapRow(0) = 3; } // for distributed matrices // we also need to know the global row numbers // and for each overlapped row, the original processor IVect glob_number, original_proc; // for shared rows, all the row numbers shared with processors IVect SharingProc(1); Vector<IVect> SharingRows(1); if (MPI::COMM_WORLD.Get_rank() == 0) { glob_number.Reallocate(4); glob_number(0) = 0; glob_number(1) = 3; glob_number(2) = 5; glob_number(3) = 6; // global row 5 is shared with processor 1 (local number = 2) SharingProc(0) = 1; SharingRows(0).PushBack(2); } else { glob_number.Reallocate(5); glob_number(0) = 1; glob_number(1) = 2; glob_number(2) = 4; glob_number(3) = 5; glob_number(4) = 7; // row 5 is already handled by processor 0 original_proc.Reallocate(1); original_proc(0) = 0; // here SharingRows is similar to OverlapRow because all shared dofs of this processor are already treated by processor 0 // global row 5 is shared with processor 0 (local number = 3) SharingProc(0) = 0; SharingRows(0).PushBack(3); } // for the constructor, you use the local number of rows DistributedMatrix<double, General, BlockDiagRow> A(n, n); // then you need to initialise the arrays used for parallel functions (e.g. matrix-vector product) A.Init(nglob, &glob_number, &OverlapRow, &original_proc, n, 1, &SharingProc, &SharingRows, MPI::COMM_WORLD);
Another example does not construct these arrays but calls the method Init of a sparse distributed matrix (not block-diagonal) to construct them automatically.
// local number of rows int n = 4; if (MPI::COMM_WORLD.Get_rank() == 1) n = 5; // each processor constructs its global numbers // rows [0, 3, 5, 6] for processor 0 // rows [1 2, 4, 5, 7] for processor 1 // you notice that global row 5 is here shared by the two processors IVect glob_number(n); if (MPI::COMM_WORLD.Get_rank() == 0) { glob_number(0) = 0; glob_number(1) = 3; glob_number(2) = 5; glob_number(3) = 6; } else { glob_number(0) = 1; glob_number(1) = 2; glob_number(2) = 4; glob_number(3) = 5; glob_number(4) = 7; } // for the constructor, you use the local number of rows DistributedMatrix<double, General, ArrayRowSparse> Asp(n, n); DistributedMatrix<double, General, BlockDiagRow> A(n, n); // arrays overlap_row, original_proc, SharingProc, SharingRows // are output arrays of Init here, they are constructed with the given global numbers IVect overlap_row, original_proc; IVect SharingProc; Vector<IVect> SharingRows; // these arrays are constructed by Init of a distributed sparse matrix (Asp here) Asp.Init(glob_number, overlap_row, original_proc, SharingProc, SharingRows, MPI::COMM_WORLD); // once these arrays have been constructed, you can use them for other distributed matrices that have the same distribution. DistributedMatrix<double, General, BlockDiagRow> B(n, n); B.Init(nglob, &glob_number, &OverlapRow, &original_proc, n, 1, &SharingProc, &SharingRows, MPI::COMM_WORLD); // another solution is to call Init with the original distributed matrix A.Init(Asp);
Location :
DistributedBlockDiagonalMatrix.hxx
DistributedBlockDiagonalMatrix.cxx
GetProcNumber
Syntax
int* GetProcNumber() const
This method returns a pointer storing the processor number for each "row". Here, we take into account all the rows that are coupled with the rows owned by the current processor.
Example :
// for the constructor, you use the local number of rows DistributedMatrix<double, General, BlockDiagRow> A(n, n); // then you need to initialise the arrays used for parallel functions (e.g. matrix-vector product) A.Init(nglob, &glob_number, &OverlapRow, &original_proc, n, 1, &SharingProc, &SharingRows, MPI::COMM_WORLD); A.SetPattern(pattern, proc); int* proc_row = A.GetProcNumber();
Location :
DistributedBlockDiagonalMatrix.hxx
DistributedBlockDiagonalMatrix.cxx
SetPattern
Syntax
void SetPattern(const Vector<IVect>& NumDof_Blocks); void SetPattern(const Vector<IVect>& NumDof_Blocks, const Vector<IVect>& ProcDofs);
This method specifies the profile of the block-diagonal matrix. In the first syntax, the blocks are not shared between processors, and the user provides the local row numbers for each block. In the second syntax, the blocks may be shared between processors, the second argument gives the processor number for each row of the block. If the processor is distant (different from the current processor), the row number is the global row number, otherwise it is the local row number.
Example :
// for the constructor, you use the local number of rows DistributedMatrix<double, General, BlockDiagRow> A(n, n); // then you need to initialise the arrays used for parallel functions (e.g. matrix-vector product) A.Init(nglob, &glob_number, &OverlapRow, &original_proc, n, 1, &SharingProc, &SharingRows, MPI::COMM_WORLD); // example with two processors // processor 0 owns rows 0, 2, 5, 6, 8 // processor 1 owns rows 1, 2, 3, 4, 6, 7 // block 0 : (0, 1, 4) // block 1 : (2, 3, 6) // block 2 : (5, 7, 8) Vector<IVect> pattern(3), proc(3); for (int k = 0; k < 3; k++) { pattern(k).Reallocate(3); proc(k).Reallocate(3); } if (MPI::COMM_WORLD.Get_rank() == 0) { // block 0 : (0, 1, 4) // rows 1 and 4 are owned by processor 1, we put global numbers pattern(0)(0) = 0; pattern(0)(1) = 1; pattern(0)(2) = 4; proc(0)(0) = 0; proc(0)(1) = 1; proc(0)(2) = 1; // block 1 : (2, 3, 6) // local numbers of rows 2, 6 : 1, 3 pattern(1)(0) = 1; pattern(1)(1) = 3; pattern(1)(2) = 3; proc(1)(0) = 0; proc(1)(1) = 1; proc(1)(2) = 0; // block 2 : (5, 7, 8) // local numbers of rows 5, 8 : 2, 4 pattern(2)(0) = 2; pattern(2)(1) = 7; pattern(2)(2) = 4; proc(2)(0) = 0; proc(2)(1) = 1; proc(2)(2) = 0; } else { // block 0 : (0, 1, 4) // local numbers of rows 1, 4 : 0 3 pattern(0)(0) = 0; pattern(0)(1) = 0; pattern(0)(2) = 3; proc(0)(0) = 0; proc(0)(1) = 1; proc(0)(2) = 1; // block 1 : (2, 3, 6) // local numbers of rows 2, 3, 6 : 1, 2, 4 pattern(1)(0) = 1; pattern(1)(1) = 2; pattern(1)(2) = 4; proc(1)(0) = 1; proc(1)(1) = 1; proc(1)(2) = 1; // block 2 : (5, 7, 8) // local number of row 7 : 5 pattern(2)(0) = 5; pattern(2)(1) = 5; pattern(2)(2) = 8; proc(2)(0) = 0; proc(2)(1) = 1; proc(2)(2) = 0; } A.SetPattern(pattern, proc);
Location :
DistributedBlockDiagonalMatrix.hxx
DistributedBlockDiagonalMatrix.cxx
IndexGlobal
Syntax
int IndexGlobal(int i, int j)
This method returns the global row number of row j of block i.
Example :
// for the constructor, you use the local number of rows DistributedMatrix<double, General, BlockDiagRow> A(n, n); // then you need to initialise the arrays used for parallel functions (e.g. matrix-vector product) A.Init(nglob, &glob_number, &OverlapRow, &original_proc, n, 1, &SharingProc, &SharingRows, MPI::COMM_WORLD); // example with two processors // processor 0 owns rows 0, 2, 5, 6, 8 // processor 1 owns rows 1, 2, 3, 4, 6, 7 // block 0 : (0, 1, 4) // block 1 : (2, 3, 6) // block 2 : (5, 7, 8) Vector<IVect> pattern(3), proc(3); for (int k = 0; k < 3; k++) { pattern(k).Reallocate(3); proc(k).Reallocate(3); } if (MPI::COMM_WORLD.Get_rank() == 0) { // block 0 : (0, 1, 4) // rows 1 and 4 are owned by processor 1, we put global numbers pattern(0)(0) = 0; pattern(0)(1) = 1; pattern(0)(2) = 4; proc(0)(0) = 0; proc(0)(1) = 1; proc(0)(2) = 1; // block 1 : (2, 3, 6) // local numbers of rows 2, 6 : 1, 3 pattern(1)(0) = 1; pattern(1)(1) = 3; pattern(1)(2) = 3; proc(1)(0) = 0; proc(1)(1) = 1; proc(1)(2) = 0; // block 2 : (5, 7, 8) // local numbers of rows 5, 8 : 2, 4 pattern(2)(0) = 2; pattern(2)(1) = 7; pattern(2)(2) = 4; proc(2)(0) = 0; proc(2)(1) = 1; proc(2)(2) = 0; } else { // block 0 : (0, 1, 4) // local numbers of rows 1, 4 : 0 3 pattern(0)(0) = 0; pattern(0)(1) = 0; pattern(0)(2) = 3; proc(0)(0) = 0; proc(0)(1) = 1; proc(0)(2) = 1; // block 1 : (2, 3, 6) // local numbers of rows 2, 3, 6 : 1, 2, 4 pattern(1)(0) = 1; pattern(1)(1) = 2; pattern(1)(2) = 4; proc(1)(0) = 1; proc(1)(1) = 1; proc(1)(2) = 1; // block 2 : (5, 7, 8) // local number of row 7 : 5 pattern(2)(0) = 5; pattern(2)(1) = 5; pattern(2)(2) = 8; proc(2)(0) = 0; proc(2)(1) = 1; proc(2)(2) = 0; } A.SetPattern(pattern, proc); if (MPI::COMM_WORLD.Get_rank() == 0) { // it should return 6 (global row number of row 2 of block 1) cout << A.IndexGlobal(1, 2) << endl; }
Location :
DistributedBlockDiagonalMatrix.hxx
DistributedBlockDiagonalMatrix.cxx
Assemble
Syntax
void Assemble()
This method assembles the block-diagonal matrix (values shared between processors are added).
Example :
// for the constructor, you use the local number of rows DistributedMatrix<double, General, BlockDiagRow> A(n, n); // then you need to initialise the arrays used for parallel functions (e.g. matrix-vector product) A.Init(nglob, &glob_number, &OverlapRow, &original_proc, n, 1, &SharingProc, &SharingRows, MPI::COMM_WORLD); // example with two processors // processor 0 owns rows 0, 2, 5, 6, 8 // processor 1 owns rows 1, 2, 3, 4, 6, 7 // block 0 : (0, 1, 4) // block 1 : (2, 3, 6) // block 2 : (5, 7, 8) Vector<IVect> pattern(3), proc(3); for (int k = 0; k < 3; k++) { pattern(k).Reallocate(3); proc(k).Reallocate(3); } if (MPI::COMM_WORLD.Get_rank() == 0) { // block 0 : (0, 1, 4) // rows 1 and 4 are owned by processor 1, we put global numbers pattern(0)(0) = 0; pattern(0)(1) = 1; pattern(0)(2) = 4; proc(0)(0) = 0; proc(0)(1) = 1; proc(0)(2) = 1; // block 1 : (2, 3, 6) // local numbers of rows 2, 6 : 1, 3 pattern(1)(0) = 1; pattern(1)(1) = 3; pattern(1)(2) = 3; proc(1)(0) = 0; proc(1)(1) = 1; proc(1)(2) = 0; // block 2 : (5, 7, 8) // local numbers of rows 5, 8 : 2, 4 pattern(2)(0) = 2; pattern(2)(1) = 7; pattern(2)(2) = 4; proc(2)(0) = 0; proc(2)(1) = 1; proc(2)(2) = 0; } else { // block 0 : (0, 1, 4) // local numbers of rows 1, 4 : 0 3 pattern(0)(0) = 0; pattern(0)(1) = 0; pattern(0)(2) = 3; proc(0)(0) = 0; proc(0)(1) = 1; proc(0)(2) = 1; // block 1 : (2, 3, 6) // local numbers of rows 2, 3, 6 : 1, 2, 4 pattern(1)(0) = 1; pattern(1)(1) = 2; pattern(1)(2) = 4; proc(1)(0) = 1; proc(1)(1) = 1; proc(1)(2) = 1; // block 2 : (5, 7, 8) // local number of row 7 : 5 pattern(2)(0) = 5; pattern(2)(1) = 5; pattern(2)(2) = 8; proc(2)(0) = 0; proc(2)(1) = 1; proc(2)(2) = 0; } A.SetPattern(pattern, proc); // values can be added to A with AddInteraction, AddDistantInteraction or AddRowDistantInteraction A.AddInteraction(0, 1, 2.3); // then the matrix can be assembled A.Assemble();
Location :
DistributedBlockDiagonalMatrix.hxx
DistributedBlockDiagonalMatrix.cxx
Mlt
Syntax
void Mlt(const DistributedMatrix<T>& A, const Vector<T>& x, Vector<T>& y, bool assemble); void Mlt(const SeldonTranspose& trans, const DistributedMatrix<T>& A, const Vector<T>& x, Vector<T>& y, bool assemble); void Mlt(const T& alpha, DistributedMatrix<T>& A); void Mlt(const DistributedMatrix<T>& A, Vector<T>& x, bool assemble);
This function can perform matrix-vector product (with the original matrix or with its transpose) and can be used to multiply the matrix by a scalar. The matrix-matrix product is currently not implemented. If the communicator contains only one processor, the sequential function Mlt (with the class Matrix) will be called, otherwise an error will be displayed during the execution.
Example :
// default constructor DistributedMatrix<double, General, BlockDiagRow> A; // global row numbers are provided with Init (glob_number) A.Init(nglob, &glob_number, &OverlapRow, &original_proc, Nvol, nb_u, &ProcShared, &SharedRows, MPI::COMM_WORLD); // SetPattern is called to provide the profile of A A.SetPattern(NumDofs, ProcDofs); // for local interaction, you can use AddInteraction A.AddInteraction(i, j, val); // when the column is distant, you can use AddDistantInteraction A.AddDistantInteraction(i, jglob, proc, val); // when the row is distant, you can use AddRowDistantInteraction A.AddRowDistantInteraction(iglob, j, proc, val); // once the matrix is constructed, matrix-vector products can be performed // each vector is stored as a usual Seldon vector (class Vector) // each processor is assumed to store the values of the vector for the // global rows given during the construction of the matrix (here, the array glob_number) Vector<double> x(n), y(n), z; // Mlt will assume that the values of x for rows that are shared between processors are the same // which is here not the case when calling FillRand x.FillRand(); y.FillRand(); z = y; // a solution is to call AssembleVector to ensure this property AssembleVector(x, MPI::SUM, ProcShared, SharedRows, MPI::COMM_WORLD, Nvol, nb_u, 23); // classical matrix-vector product y = A x // the default value of the last argument (assemble) is true // the result y is assembled and will contain the same result as a sequential matrix-vector product, // the values being distributed in the different processors Mlt(A, x, y); // assemble = true, induces a final call to the function AssembleVector (to add values of shared rows) // if the user wants to perform a matrix-vector product without performing this final assembling step, he puts false in the last optional argument Mlt(A, x, z, false); // and perform the assembling phase later AssembleVector(z, MPI::SUM, ProcShared, SharedRows, MPI::COMM_WORLD, Nvol, nb_u, 23); // Mlt can be used to perform a matrix-vector with the transpose matrix or the transpose conjugate Mlt(SeldonTrans, A, x, y); // Finally Mlt can be used to multiply a distributed matrix by a scalar coefficient Mlt(-2.1, A); // the last syntax performs y = A x, on input x is provided and overwritten with y y = x; Mlt(A, y);
Location :
DistributedBlockDiagonalMatrix.hxx
DistributedBlockDiagonalMatrix.cxx
ConvertToSparse
Syntax
void ConvertToSparse(const DistributedMatrix<T>& A, DistributedMatrix<T>& B);
This function converts a block-diagonal matrix to a sparse distributed matrix. It is equivalent to call the function Copy (which handles other conversions as well).
Example :
// default constructor DistributedMatrix<double, General, BlockDiagRow> A; // global row numbers are provided with Init (glob_number) A.Init(nglob, &glob_number, &OverlapRow, &original_proc, Nvol, nb_u, &ProcShared, &SharedRows, MPI::COMM_WORLD); // SetPattern is called to provide the profile of A A.SetPattern(NumDofs, ProcDofs); // for local interaction, you can use AddInteraction A.AddInteraction(i, j, val); // when the column is distant, you can use AddDistantInteraction A.AddDistantInteraction(i, jglob, proc, val); // when the row is distant, you can use AddRowDistantInteraction A.AddRowDistantInteraction(iglob, j, proc, val); // once the matrix is constructed, the matrix can be converted // with Copy or ConvertToSparse DistributedMatrix<double, General, ArrayRowSparse> B; ConvertToSparse(A, B);
Location :
DistributedBlockDiagonalMatrix.hxx
DistributedBlockDiagonalMatrix.cxx
ConvertToBlockDiagonal
Syntax
void ConvertToBlockDiagonal(const DistributedMatrix<T>& A, DistributedMatrix<T>& B);
This function converts a sparse distributed matrix to a block-diagonal matrix. It is equivalent to call the function Copy (which handles other conversions as well).
Example :
// default constructor DistributedMatrix<double, General, ArrayRowSparse> A; // global row numbers are provided with Init (glob_number) A.Init(nglob, &glob_number, &OverlapRow, &original_proc, Nvol, nb_u, &ProcShared, &SharedRows, MPI::COMM_WORLD); // A is allocated with the loca number of rows A.Reallocate(n, n); // for local interaction, you can use AddInteraction A.AddInteraction(i, j, val); // when the column is distant, you can use AddDistantInteraction A.AddDistantInteraction(i, jglob, proc, val); // when the row is distant, you can use AddRowDistantInteraction A.AddRowDistantInteraction(iglob, j, proc, val); // once the matrix is constructed, the matrix can be converted // with Copy or ConvertToBlockDiagonal DistributedMatrix<double, General, BlockDiagRow> B; ConvertToBlockDiagonal(A, B);
Location :
DistributedBlockDiagonalMatrix.hxx
DistributedBlockDiagonalMatrix.cxx
GetInverse
Syntax
void GetInverse(DistributedMatrix<T>& B);
This function replaces a block-diagonal matrix by its inverse.
Example :
// default constructor DistributedMatrix<double, General, BlockDiagRow> A; // global row numbers are provided with Init (glob_number) A.Init(nglob, &glob_number, &OverlapRow, &original_proc, Nvol, nb_u, &ProcShared, &SharedRows, MPI::COMM_WORLD); // SetPattern is called to provide the profile of A A.SetPattern(NumDofs, ProcDofs); // for local interaction, you can use AddInteraction A.AddInteraction(i, j, val); // when the column is distant, you can use AddDistantInteraction A.AddDistantInteraction(i, jglob, proc, val); // when the row is distant, you can use AddRowDistantInteraction A.AddRowDistantInteraction(iglob, j, proc, val); // once the matrix is constructed, the inverse can be computed GetInverse(A);
Location :
DistributedBlockDiagonalMatrix.hxx
DistributedBlockDiagonalMatrix.cxx
GetCholesky
Syntax
void GetCholesky(DistributedMatrix<T>& B);
This function replaces a block-diagonal matrix by its Cholesky factorization. It is only available for BlockDiagRowSym storage, since the matrix is assumed to be symmetric definite positive.
Example :
// default constructor DistributedMatrix<double, Symmetric, BlockDiagRowSym> A; // global row numbers are provided with Init (glob_number) A.Init(nglob, &glob_number, &OverlapRow, &original_proc, Nvol, nb_u, &ProcShared, &SharedRows, MPI::COMM_WORLD); // SetPattern is called to provide the profile of A A.SetPattern(NumDofs, ProcDofs); // for local interaction, you can use AddInteraction A.AddInteraction(i, j, val); // when the column is distant, you can use AddDistantInteraction A.AddDistantInteraction(i, jglob, proc, val); // when the row is distant, you can use AddRowDistantInteraction A.AddRowDistantInteraction(iglob, j, proc, val); // once the matrix is constructed, the Cholesky factorization can be computed GetCholesky(A);
Location :
DistributedBlockDiagonalMatrix.hxx
DistributedBlockDiagonalMatrix.cxx
SolveCholesky
Syntax
void SolveCholesky(const SeldonTranspose&, const DistributedMatrix<T>& A, Vector<T>& x);
This function solves system L x = b or L^T x = b, where A = L L^T (Cholesky factorization). GetCholesky is assumed to have been called previously such that A stores the Cholesky factor L.
Example :
// default constructor DistributedMatrix<double, Symmetric, BlockDiagRowSym> A; // global row numbers are provided with Init (glob_number) A.Init(nglob, &glob_number, &OverlapRow, &original_proc, Nvol, nb_u, &ProcShared, &SharedRows, MPI::COMM_WORLD); // SetPattern is called to provide the profile of A A.SetPattern(NumDofs, ProcDofs); // for local interaction, you can use AddInteraction A.AddInteraction(i, j, val); // when the column is distant, you can use AddDistantInteraction A.AddDistantInteraction(i, jglob, proc, val); // when the row is distant, you can use AddRowDistantInteraction A.AddRowDistantInteraction(iglob, j, proc, val); // once the matrix is constructed, the Cholesky factorization can be computed GetCholesky(A); // and used to solve L L^T x = b Vector<T> x, b(n); b.FillRand(); x = b; SolveCholesky(SeldonNoTrans, A, x); SolveCholesky(SeldonTrans, A, x);
Location :
DistributedBlockDiagonalMatrix.hxx
DistributedBlockDiagonalMatrix.cxx
MltCholesky
Syntax
void MltCholesky(const SeldonTranspose&, const DistributedMatrix<T>& A, Vector<T>& x);
This function computes matrix-vector product y = L x or y = L^T x, where A = L L^T (Cholesky factorization). GetCholesky is assumed to have been called previously such that A stores the Cholesky factor L.
Example :
// default constructor DistributedMatrix<double, Symmetric, BlockDiagRowSym> A; // global row numbers are provided with Init (glob_number) A.Init(nglob, &glob_number, &OverlapRow, &original_proc, Nvol, nb_u, &ProcShared, &SharedRows, MPI::COMM_WORLD); // SetPattern is called to provide the profile of A A.SetPattern(NumDofs, ProcDofs); // for local interaction, you can use AddInteraction A.AddInteraction(i, j, val); // when the column is distant, you can use AddDistantInteraction A.AddDistantInteraction(i, jglob, proc, val); // when the row is distant, you can use AddRowDistantInteraction A.AddRowDistantInteraction(iglob, j, proc, val); // once the matrix is constructed, the Cholesky factorization can be computed GetCholesky(A); // and used to compute y = L L^T x Vector<T> y, x(n); x.FillRand(); y = x; MltCholesky(SeldonTrans, A, y); MltCholesky(SeldonNoTrans, A, y);
Location :
DistributedBlockDiagonalMatrix.hxx
DistributedBlockDiagonalMatrix.cxx