2 * SparseMatrixPetsc.cxx
4 * Created on: 04/11/2017
8 #include "SparseMatrixPetsc.hxx"
9 #include "CdmathException.hxx"
13 //----------------------------------------------------------------------
14 SparseMatrixPetsc::SparseMatrixPetsc()
15 //----------------------------------------------------------------------
22 PetscInitialize(0, (char ***)"", PETSC_NULL, PETSC_NULL);
25 //----------------------------------------------------------------------
26 SparseMatrixPetsc::SparseMatrixPetsc( int numberOfRows, int numberOfColumns)
27 //----------------------------------------------------------------------
29 _numberOfRows = numberOfRows;
30 _numberOfColumns=numberOfColumns;
32 PetscInitialize(0, (char ***)"", PETSC_NULL, PETSC_NULL);
33 MatCreateSeqAIJ(MPI_COMM_SELF,_numberOfRows,_numberOfColumns,PETSC_DEFAULT,NULL,&_mat);
36 //----------------------------------------------------------------------
37 SparseMatrixPetsc::SparseMatrixPetsc( Mat mat )
38 //----------------------------------------------------------------------
40 PetscInitialize(0, (char ***)"", PETSC_NULL, PETSC_NULL);
43 //extract number of row and column
44 MatGetSize(mat,&_numberOfRows,&_numberOfColumns);
46 //extract an upper bound for the total number of non zero coefficients
48 MatGetInfo(mat,MAT_LOCAL,&info);
49 _numberOfNonZeros = info.nz_allocated;
52 //----------------------------------------------------------------------
53 SparseMatrixPetsc::SparseMatrixPetsc( int numberOfRows, int numberOfColumns, int nnz )
54 //----------------------------------------------------------------------
56 _numberOfRows = numberOfRows;
57 _numberOfColumns=numberOfColumns;
58 _numberOfNonZeros=nnz;
61 PetscInitialize(0, (char ***)"", PETSC_NULL, PETSC_NULL);
62 MatCreateSeqAIJ(MPI_COMM_SELF,_numberOfRows,_numberOfColumns,_numberOfNonZeros,NULL,&_mat);
65 //----------------------------------------------------------------------
66 SparseMatrixPetsc::SparseMatrixPetsc( int blockSize, int numberOfRows, int numberOfColumns, int nnz )
67 //----------------------------------------------------------------------
69 _numberOfRows = numberOfRows;
70 _numberOfColumns=numberOfColumns;
71 _numberOfNonZeros=nnz;
74 PetscInitialize(0, (char ***)"", PETSC_NULL, PETSC_NULL);
75 MatCreateSeqBAIJ(MPI_COMM_SELF,blockSize, _numberOfRows,_numberOfColumns,_numberOfNonZeros,NULL,&_mat);
78 //----------------------------------------------------------------------
79 SparseMatrixPetsc::SparseMatrixPetsc(const SparseMatrixPetsc& matrix)
80 //----------------------------------------------------------------------
82 _isSparseMatrix=matrix.isSparseMatrix();
83 MatDuplicate(matrix.getPetscMatrix(), MAT_COPY_VALUES,&_mat);
84 MatGetSize(_mat,&_numberOfRows,&_numberOfColumns);
85 //extract an upper bound for the total number of non zero coefficients
87 MatGetInfo(_mat,MAT_LOCAL,&info);
88 _numberOfNonZeros = info.nz_allocated;
92 SparseMatrixPetsc::transpose() const
95 MatAssemblyBegin(_mat, MAT_FINAL_ASSEMBLY);
96 MatAssemblyEnd(_mat, MAT_FINAL_ASSEMBLY);
98 MatTranspose(_mat,MAT_INITIAL_MATRIX, &mattranspose);
99 return SparseMatrixPetsc(mattranspose);
103 SparseMatrixPetsc::setValue( int i, int j, double value )
105 MatSetValues(_mat,1, &i, 1, &j, &value, INSERT_VALUES);
109 SparseMatrixPetsc::addValue( int i, int j, double value )
111 MatSetValues(_mat,1, &i, 1, &j, &value, ADD_VALUES);
115 SparseMatrixPetsc::setValue( int i, int j, Matrix M )
118 for (int k=0; k<M.getNumberOfRows(); k++)
119 for (int l=0; l<M.getNumberOfColumns(); l++)
123 MatSetValues(_mat,1, &I, 1, &J, &M(k,l), INSERT_VALUES);
128 SparseMatrixPetsc::addValue( int i, int j, Matrix M )
131 for (int k=0; k<M.getNumberOfRows(); k++)
132 for (int l=0; l<M.getNumberOfColumns(); l++)
136 MatSetValues(_mat,1, &I, 1, &J, &M(k,l), ADD_VALUES);
141 SparseMatrixPetsc::setValuesBlocked( int i, int j, Matrix M )
144 MatGetBlockSize(_mat,&blockSize);
145 if(blockSize!=M.getNumberOfRows() || blockSize!=M.getNumberOfColumns())
146 throw CdmathException("SparseMatrixPetsc::setValuesBlocked : matrix size is different from sparse matrix block structure");
147 double petscValues[blockSize*blockSize];
148 for (int k=0; k<M.getNumberOfRows(); k++)
149 for (int l=0; l<M.getNumberOfColumns(); l++)
150 petscValues[k*blockSize+l]=M(k,l);
151 MatSetValuesBlocked(_mat,1, &i, 1, &j, petscValues, INSERT_VALUES);
155 SparseMatrixPetsc::addValuesBlocked( int i, int j, Matrix M )
158 MatGetBlockSize(_mat,&blockSize);
159 if(blockSize!=M.getNumberOfRows() || blockSize!=M.getNumberOfColumns())
160 throw CdmathException("SparseMatrixPetsc::addValuesBlocked : matrix size is different from sparse matrix block structure");
161 double petscValues[blockSize*blockSize];
162 for (int k=0; k<M.getNumberOfRows(); k++)
163 for (int l=0; l<M.getNumberOfColumns(); l++)
164 petscValues[k*blockSize+l]=M(k,l);
165 MatSetValuesBlocked(_mat,1, &i, 1, &j, petscValues, ADD_VALUES);
168 //----------------------------------------------------------------------
170 SparseMatrixPetsc::operator()( int i, int j ) const
171 //----------------------------------------------------------------------
175 MatAssemblyBegin(_mat, MAT_FINAL_ASSEMBLY);
176 MatAssemblyEnd(_mat, MAT_FINAL_ASSEMBLY);
178 MatGetValues(_mat,1,&idxm,1, &idxn,&res);
182 //----------------------------------------------------------------------
183 SparseMatrixPetsc::~SparseMatrixPetsc()
184 //----------------------------------------------------------------------
192 SparseMatrixPetsc::getPetscMatrix() const
194 MatAssemblyBegin(_mat, MAT_FINAL_ASSEMBLY);
195 MatAssemblyEnd(_mat, MAT_FINAL_ASSEMBLY);
201 SparseMatrixPetsc::containsPetscMatrix() const
205 //----------------------------------------------------------------------
206 const SparseMatrixPetsc&
207 SparseMatrixPetsc::operator= ( const SparseMatrixPetsc& matrix )
208 //----------------------------------------------------------------------
210 _isSparseMatrix=matrix.isSparseMatrix();
211 MatDuplicate(matrix.getPetscMatrix(), MAT_COPY_VALUES,&_mat);
212 MatGetSize(_mat,&_numberOfRows,&_numberOfColumns);
213 //extract an upper bound for the total number of non zero coefficients
215 MatGetInfo(_mat,MAT_LOCAL,&info);
216 _numberOfNonZeros = info.nz_allocated;
221 operator+ (const SparseMatrixPetsc& matrix1, const SparseMatrixPetsc& matrix2)
223 int numberOfRows = matrix1.getNumberOfRows();
224 int numberOfColumns = matrix1.getNumberOfColumns();
225 int numberOfRows2 = matrix2.getNumberOfRows();
226 int numberOfColumns2 = matrix2.getNumberOfColumns();
228 if(numberOfRows2!=numberOfRows || numberOfColumns2!=numberOfColumns)
230 string msg="SparseMatrixPetsc::operator()+(const SparseMatrixPetsc& matrix1, const SparseMatrixPetsc& matrix2): number of rows or columns of the matrices is different!";
231 throw CdmathException(msg);
234 Mat mat1=matrix1.getPetscMatrix();
235 Mat mat2=matrix2.getPetscMatrix();
237 MatDuplicate(mat1, MAT_COPY_VALUES,&mat);
238 MatAXPY(mat,1,mat2,DIFFERENT_NONZERO_PATTERN);
240 return SparseMatrixPetsc(mat);
244 operator- (const SparseMatrixPetsc& matrix1, const SparseMatrixPetsc& matrix2)
246 int numberOfRows = matrix1.getNumberOfRows();
247 int numberOfColumns = matrix1.getNumberOfColumns();
248 int numberOfRows2 = matrix2.getNumberOfRows();
249 int numberOfColumns2 = matrix2.getNumberOfColumns();
251 if(numberOfRows2!=numberOfRows || numberOfColumns2!=numberOfColumns)
253 string msg="SparseMatrixPetsc::operator()-(const SparseMatrixPetsc& matrix1, const SparseMatrixPetsc& matrix2): number of rows or columns of the matrices is different!";
254 throw CdmathException(msg);
256 Mat mat1=matrix1.getPetscMatrix();
257 Mat mat2=matrix2.getPetscMatrix();
259 MatDuplicate(mat1, MAT_COPY_VALUES,&mat);
260 MatAXPY(mat,-1,mat2,DIFFERENT_NONZERO_PATTERN);
262 return SparseMatrixPetsc(mat);
266 operator* (double value , const SparseMatrixPetsc& matrix )
269 MatDuplicate(matrix.getPetscMatrix(), MAT_COPY_VALUES,&mat);
270 MatScale(mat, value);
272 return SparseMatrixPetsc(mat);
276 operator* (const SparseMatrixPetsc& matrix, double value )
279 MatDuplicate(matrix.getPetscMatrix(), MAT_COPY_VALUES,&mat);
280 MatScale(mat, value);
282 return SparseMatrixPetsc(mat);
286 operator/ (const SparseMatrixPetsc& matrix, double value)
290 string msg="SparseMatrixPetsc SparseMatrixPetsc::operator()/(const SparseMatrixPetsc& matrix1, const SparseMatrixPetsc& matrix2): division by zero";
291 throw CdmathException(msg);
294 MatDuplicate(matrix.getPetscMatrix(), MAT_COPY_VALUES,&mat);
295 MatScale(mat, 1/value);
297 return SparseMatrixPetsc(mat);
301 operator*(const SparseMatrixPetsc& matrix1, const SparseMatrixPetsc& matrix2)
303 Mat mat1=matrix1.getPetscMatrix();
304 Mat mat2=matrix2.getPetscMatrix();
306 MatMatMult(mat1, mat2, MAT_INITIAL_MATRIX,PETSC_DEFAULT,&mat);
308 return SparseMatrixPetsc(mat);
312 SparseMatrixPetsc::operator*= (const SparseMatrixPetsc& matrix)
314 Mat mat1=matrix.getPetscMatrix();
315 MatAssemblyBegin(_mat, MAT_FINAL_ASSEMBLY);
316 MatAssemblyEnd(_mat, MAT_FINAL_ASSEMBLY);
319 MatMatMult(_mat, mat1, MAT_INITIAL_MATRIX,PETSC_DEFAULT,&mat2);
323 MatGetSize(_mat,&_numberOfRows,&_numberOfColumns);
324 //extract an upper bound for the total number of non zero coefficients
326 MatGetInfo(_mat,MAT_LOCAL,&info);
327 _numberOfNonZeros = info.nz_allocated;
332 SparseMatrixPetsc::operator* (const Vector& vec) const
334 int numberOfRows=vec.getNumberOfRows();
335 Vec X=vectorToVec(vec);
338 MatAssemblyBegin(_mat, MAT_FINAL_ASSEMBLY);
339 MatAssemblyEnd(_mat, MAT_FINAL_ASSEMBLY);
345 Vector result=vecToVector(Y);
354 SparseMatrixPetsc::operator+= (const SparseMatrixPetsc& matrix)
356 Mat mat1=matrix.getPetscMatrix();
357 MatAssemblyBegin(_mat, MAT_FINAL_ASSEMBLY);
358 MatAssemblyEnd(_mat, MAT_FINAL_ASSEMBLY);
359 MatAXPY(_mat,1,mat1,DIFFERENT_NONZERO_PATTERN);
361 //extract an upper bound for the total number of non zero coefficients
363 MatGetInfo(_mat,MAT_LOCAL,&info);
364 _numberOfNonZeros = info.nz_allocated;
370 SparseMatrixPetsc::operator-= (const SparseMatrixPetsc& matrix)
372 Mat mat1=matrix.getPetscMatrix();
373 MatAssemblyBegin(_mat, MAT_FINAL_ASSEMBLY);
374 MatAssemblyEnd(_mat, MAT_FINAL_ASSEMBLY);
375 MatAXPY(_mat,-1,mat1,DIFFERENT_NONZERO_PATTERN);
377 //extract an upper bound for the total number of non zero coefficients
379 MatGetInfo(_mat,MAT_LOCAL,&info);
380 _numberOfNonZeros = info.nz_allocated;
386 SparseMatrixPetsc::operator*= (double value)
388 MatAssemblyBegin(_mat, MAT_FINAL_ASSEMBLY);
389 MatAssemblyEnd(_mat, MAT_FINAL_ASSEMBLY);
390 MatScale(_mat, value);
395 SparseMatrixPetsc::operator/= (double value)
399 string msg="SparseMatrixPetsc SparseMatrixPetsc::operator()/=(const SparseMatrixPetsc& matrix1, const SparseMatrixPetsc& matrix2): division by zero";
400 throw CdmathException(msg);
402 MatAssemblyBegin(_mat, MAT_FINAL_ASSEMBLY);
403 MatAssemblyEnd(_mat, MAT_FINAL_ASSEMBLY);
404 MatScale(_mat, 1/value);
409 SparseMatrixPetsc::viewMatrix() const
411 MatAssemblyBegin(_mat, MAT_FINAL_ASSEMBLY);
412 MatAssemblyEnd(_mat, MAT_FINAL_ASSEMBLY);
414 MatView(_mat,PETSC_VIEWER_STDOUT_SELF);
418 SparseMatrixPetsc::saveMatrix(string filename, bool binaryMode) const
420 MatAssemblyBegin(_mat, MAT_FINAL_ASSEMBLY);
421 MatAssemblyEnd(_mat, MAT_FINAL_ASSEMBLY);
423 PetscViewer fileViewer;
424 PetscViewerCreate(PETSC_COMM_WORLD,&fileViewer);
425 PetscViewerFileSetMode(fileViewer,FILE_MODE_WRITE);
426 PetscViewerFileSetName(fileViewer,filename.c_str());
430 PetscViewerSetType(fileViewer, PETSCVIEWERBINARY);
431 PetscViewerASCIIOpen(PETSC_COMM_WORLD, filename.c_str(), &fileViewer);
435 PetscViewerSetType(fileViewer, PETSCVIEWERASCII);
436 PetscViewerBinaryOpen(PETSC_COMM_WORLD, filename.c_str(), FILE_MODE_WRITE, &fileViewer);
439 MatView(_mat,fileViewer);
443 SparseMatrixPetsc::getMatrixCoeff(int i, int j) const
447 MatAssemblyBegin(_mat, MAT_FINAL_ASSEMBLY);
448 MatAssemblyEnd(_mat, MAT_FINAL_ASSEMBLY);
450 MatGetValues(_mat,1,&idxm,1, &idxn,&res);
454 std::vector< double >
455 SparseMatrixPetsc::getArray()
457 int size=_numberOfRows*_numberOfColumns;
459 vector< double > result(size);
460 double* values = result.data();
462 int * idxm = new int[_numberOfRows];
463 int * idxn = new int[_numberOfColumns];
464 for (int i=0;i<_numberOfRows;i++)
466 for (int i=0;i<_numberOfColumns;i++)
469 MatAssemblyBegin(_mat, MAT_FINAL_ASSEMBLY);
470 MatAssemblyEnd(_mat, MAT_FINAL_ASSEMBLY);
472 MatGetValues(_mat,_numberOfRows, idxm,_numberOfColumns, idxn,values);
478 SparseMatrixPetsc::diagonalShift(double lambda)
480 MatAssemblyBegin(_mat, MAT_FINAL_ASSEMBLY);
481 MatAssemblyEnd(_mat, MAT_FINAL_ASSEMBLY);
483 MatShift(_mat, lambda);
487 SparseMatrixPetsc::zeroEntries()
489 MatZeroEntries(_mat);
493 SparseMatrixPetsc::vecToVector(const Vec& vec) const
495 PetscInt numberOfRows;
496 VecGetSize(vec,&numberOfRows);
497 double * petscValues;
498 VecGetArray(vec,&petscValues);
500 DoubleTab values (numberOfRows,petscValues);
501 Vector result(numberOfRows);
502 result.setValues(values);
507 SparseMatrixPetsc::vectorToVec(const Vector& myVector) const
509 int numberOfRows=myVector.getNumberOfRows();
510 const double* values = myVector.getValues().getValues();
513 VecCreate(PETSC_COMM_WORLD,&result);
514 VecSetSizes(result,PETSC_DECIDE,numberOfRows);
515 VecSetBlockSize(result,numberOfRows);
516 VecSetFromOptions(result);
517 int idx=0;//Index where to add the block of values
518 VecSetValuesBlocked(result,1,&idx,values,INSERT_VALUES);
520 VecAssemblyBegin(result);
521 VecAssemblyEnd(result);
526 bool SparseMatrixPetsc::isSymmetric(double tol) const
528 MatAssemblyBegin(_mat, MAT_FINAL_ASSEMBLY);
529 MatAssemblyEnd(_mat, MAT_FINAL_ASSEMBLY);
531 //Check that the matrix is symmetric
532 PetscBool isSymetric;
533 MatIsSymmetric(_mat,tol,&isSymetric);
539 SparseMatrixPetsc::computeSpectrum(int nev, double ** valP, double ***vecP, EPSWhich which, double tol, EPSType type) const
541 EPS eps; /* eigenproblem solver context */
545 PetscInt i,maxit,its, nconv;
547 SlepcInitialize(0, (char ***)"", PETSC_NULL, PETSC_NULL);
549 MatAssemblyBegin(_mat,MAT_FINAL_ASSEMBLY);
550 MatAssemblyEnd(_mat,MAT_FINAL_ASSEMBLY);
552 MatCreateVecs(_mat,&xr,NULL);
553 MatCreateVecs(_mat,&xi,NULL);
555 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
556 Create the eigensolver and set various options
557 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
559 Create eigensolver context
561 EPSCreate(PETSC_COMM_WORLD,&eps);
564 Set operators. In this case, it is a standard eigenvalue problem
566 EPSSetOperators(eps,_mat,NULL);
567 //if(isSymmetric(tol))
568 //EPSSetProblemType(eps,EPS_HEP);
570 EPSSetProblemType(eps,EPS_NHEP);
571 EPSSetWhichEigenpairs(eps,which);
572 EPSSetDimensions(eps,nev,PETSC_DEFAULT,PETSC_DEFAULT);
573 EPSSetTolerances(eps,tol,PETSC_DEFAULT);
574 EPSSetType(eps,type);
576 Set solver parameters at runtime
578 EPSSetFromOptions(eps);
580 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
581 Solve the eigensystem
582 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
586 Optional: Get some information from the solver and display it
588 EPSGetIterationNumber(eps,&its);
589 PetscPrintf(PETSC_COMM_WORLD," Number of iterations of the method: %D\n",its);
590 EPSGetType(eps,&type);
591 PetscPrintf(PETSC_COMM_WORLD," Solution method: %s\n\n",type);
592 EPSGetDimensions(eps,&nev,NULL,NULL);
593 PetscPrintf(PETSC_COMM_WORLD," Number of requested eigenvalues: %D\n",nev);
594 EPSGetTolerances(eps,&tol,&maxit);
595 PetscPrintf(PETSC_COMM_WORLD," Stopping condition: tol=%.4g, maxit=%D\n",(double)tol,maxit);
597 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
598 Display solution and clean up
599 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
601 Get number of converged approximate eigenpairs
603 EPSGetConverged(eps,&nconv);
604 PetscPrintf(PETSC_COMM_WORLD," Number of converged eigenpairs: %D\n\n",nconv);
606 *valP=new double[nconv];
607 *vecP=new double * [nconv];
612 Display eigenvalues and relative errors
614 PetscPrintf(PETSC_COMM_WORLD,
615 " k ||Ax-kx||/||kx||\n"
616 " ----------------- ------------------\n");
618 for (int i=0;i<nconv;i++) {
620 Get converged eigenpairs: i-th eigenvalue is stored in kr (real part) and
623 EPSGetEigenpair(eps,i,&kr,&ki,xr,xi);
625 Compute the relative error associated to each eigenpair
627 if(fabs(kr)>tol || fabs(ki)>tol)
629 EPSComputeError(eps,i,EPS_ERROR_RELATIVE,&error);
632 PetscPrintf(PETSC_COMM_WORLD," %9f%+9fi %12g\n",(double)kr,(double)ki,(double)error);
634 PetscPrintf(PETSC_COMM_WORLD," %12f %12g\n",(double)kr,(double)error);
639 PetscPrintf(PETSC_COMM_WORLD," %9f%+9fi %12s\n",(double)kr,(double)ki,"Null eigenvalue");
641 PetscPrintf(PETSC_COMM_WORLD," %12f %12s\n",(double)kr,"Null eigenvalue");
645 VecGetArray(xr,&myVecp);
646 *(*vecP+ i)=new double [_numberOfRows];
647 memcpy(*(*vecP+ i),myVecp,_numberOfRows*sizeof(double)) ;
649 PetscPrintf(PETSC_COMM_WORLD,"\n");
670 throw CdmathException("SparseMatrixPetsc::computeSpectrum : No eigenvector found");
675 SparseMatrixPetsc::computeSVD(int nsv, double ** valS, double ***vecS, SVDWhich which, double tol, SVDType type) const
677 SVD svd; /* Singular value decomposition solver context */
681 PetscInt i,maxit,its, nconv;
683 SlepcInitialize(0, (char ***)"", PETSC_NULL, PETSC_NULL);
685 MatAssemblyBegin(_mat,MAT_FINAL_ASSEMBLY);
686 MatAssemblyEnd( _mat,MAT_FINAL_ASSEMBLY);
688 MatCreateVecs(_mat,&u,NULL);
689 MatCreateVecs(_mat,NULL,&v);
691 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
692 Create the singular value solver and set various options
693 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
695 Create singular value decomposition context
697 SVDCreate(PETSC_COMM_WORLD,&svd);
700 Set operators. In this case, it is a standard singular value problem
702 #if (SLEPC_VERSION_MAJOR==3) && (SLEPC_VERSION_MINOR > 14)
703 SVDSetOperators(svd,_mat,NULL);
705 SVDSetOperator(svd,_mat);
708 SVDSetWhichSingularTriplets(svd,which);
709 SVDSetDimensions(svd,nsv,PETSC_DEFAULT,PETSC_DEFAULT);
710 SVDSetType(svd, type);
711 SVDSetTolerances(svd,tol,PETSC_DEFAULT);
714 Set solver parameters at runtime
716 SVDSetFromOptions(svd);
718 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
719 Solve the SVD problem
720 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
724 Optional: Get some information from the solver and display it
726 SVDGetIterationNumber(svd,&its);
727 PetscPrintf(PETSC_COMM_WORLD," Number of iterations of the method: %D\n",its);
728 SVDGetType(svd,&type);
729 PetscPrintf(PETSC_COMM_WORLD," Solution method: %s\n\n",type);
730 SVDGetDimensions(svd,&nsv,NULL,NULL);
731 PetscPrintf(PETSC_COMM_WORLD," Number of requested singular values: %D\n",nsv);
732 SVDGetTolerances(svd,&tol,&maxit);
733 PetscPrintf(PETSC_COMM_WORLD," Stopping condition: tol=%.4g, maxit=%D\n",(double)tol,maxit);
735 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
736 Display solution and clean up
737 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
739 Get number of converged approximate singular values
741 SVDGetConverged(svd,&nconv);
742 PetscPrintf(PETSC_COMM_WORLD," Number of converged singular values: %D\n\n",nconv);
744 *valS=new double[nconv];
745 *vecS=new double * [2*nconv];
750 Display eigenvalues and relative errors
752 PetscPrintf(PETSC_COMM_WORLD,
753 " k ||Ax-kx||/||kx||\n"
754 " ----------------- ------------------\n");
756 for (int i=0;i<nconv;i++) {
758 Get converged singular values: i-th eigenvalue is stored in valS
760 SVDGetSingularTriplet(svd,i,*valS+i, u, v);
761 if(fabs(*(*valS+i))>tol)
764 Compute the relative error associated to each singular value
766 SVDComputeError( svd, i, SVD_ERROR_RELATIVE, &error );
768 PetscPrintf(PETSC_COMM_WORLD," %12f %12g\n",(double)*(*valS+i),(double)error);
771 PetscPrintf(PETSC_COMM_WORLD," %12f %12s\n",(double)*(*valS+i),"Null singular value");
773 VecGetArray(u,&myVecS);
774 *(*vecS + i)=new double [_numberOfRows];
775 memcpy(*(*vecS + i),myVecS,_numberOfRows*sizeof(double)) ;
776 VecGetArray(v,&myVecS);
777 *(*vecS + i + nconv)=new double [_numberOfColumns];
778 memcpy(*(*vecS + i + nconv),myVecS,_numberOfColumns*sizeof(double)) ;
780 PetscPrintf(PETSC_COMM_WORLD,"\n");
801 throw CdmathException("SparseMatrixPetsc::computeSVD : singular value decomposition failed");
805 std::vector< double >
806 SparseMatrixPetsc::getEigenvalues(int nev, EPSWhich which, double tol, EPSType type) const
812 nconv=computeSpectrum(nev, &valP, &vecP, which, tol,type);
814 std::vector< double > result(nconv);
816 for (int i=0;i<nconv;i++)
820 for (int i=0;i<nconv;i++)
827 std::vector< Vector >
828 SparseMatrixPetsc::getEigenvectors(int nev, EPSWhich which, double tol, EPSType type) const
834 nconv=computeSpectrum(nev, &valP, &vecP, which, tol,type);
836 std::vector< Vector > result(nconv);
838 for (int i=0;i<nconv;i++)
840 DoubleTab values (_numberOfRows,vecP[i]);
841 Vector myVecP(_numberOfRows);
842 myVecP.setValues(values);
847 for (int i=0;i<nconv;i++)
854 MEDCoupling::DataArrayDouble *
855 SparseMatrixPetsc::getEigenvectorsDataArrayDouble(int nev, EPSWhich which, double tol, EPSType type) const
861 nconv=computeSpectrum(nev, &valP, &vecP, which, tol);
863 #ifdef MEDCoupling_VERSION_VERSION_GREATER_9_4
864 std::vector< long unsigned int > compoId(1);
866 std::vector< int > compoId(1);
868 MEDCoupling::DataArrayDouble *arrays=MEDCoupling::DataArrayDouble::New();
869 MEDCoupling::DataArrayDouble *array =MEDCoupling::DataArrayDouble::New();
870 arrays->alloc(_numberOfRows,nconv);
872 for (int i=0;i<nconv;i++)
874 array->useArray(vecP[i],true, MEDCoupling::DeallocType::CPP_DEALLOC, _numberOfRows,1);
876 arrays->setSelectedComponents(array,compoId);
877 arrays->setInfoOnComponent(i,std::to_string(valP[i]));
886 SparseMatrixPetsc::getConditionNumber(bool isSingular, double tol) const
888 if(isSymmetric(tol))//Eigenvalues computation is more robust that singular values computation
891 double lambda_max, lambda_min;
892 std::vector< double > my_ev;
894 /*** Lowest eigenvalue, first check if matrix is singular ***/
900 my_ev=getEigenvalues( nev, EPS_SMALLEST_MAGNITUDE, tol);
903 throw CdmathException("SparseMatrixPetsc::getConditionNumber could not find the smallest eigenvalue");
904 lambda_min=my_ev[nev-1];
906 /*** Largest eigenvalue ***/
908 my_ev=getEigenvalues( nev, EPS_LARGEST_MAGNITUDE, tol);
911 throw CdmathException("SparseMatrixPetsc::getConditionNumber could not find the largest eigenvalue");
912 lambda_max=my_ev[nev-1];
914 return fabs(lambda_max)/fabs(lambda_min);
916 else//Singular values computation is more robust than eigenvalues computation
921 double sigma_max, sigma_min;
923 /*** Lowest singular value, first check if matrix is singular ***/
929 nconv=computeSVD(nsv, &valS, &vecS, SVD_SMALLEST, tol,SVDCYCLIC);
931 throw CdmathException("SparseMatrixPetsc::getConditionNumber could not find the smallest singular value");
932 sigma_min=valS[nsv-1];
935 /*** Largest singular value ***/
937 nconv=computeSVD(nsv, &valS, &vecS, SVD_LARGEST, tol,SVDCYCLIC);
939 throw CdmathException("SparseMatrixPetsc::getConditionNumber could not find the largest singular value");
940 sigma_max=valS[nsv-1];
943 return sigma_max/sigma_min;
947 std::vector< double >
948 SparseMatrixPetsc::getSingularValues(int nsv, SVDWhich which, double tol, SVDType type) const
954 nconv=computeSVD(nsv, &valS, &vecS, which, tol, type);
956 std::vector< double > result(nconv);
958 for (int i=0;i<nconv;i++)
966 std::vector< Vector >
967 SparseMatrixPetsc::getSingularVectors(int nsv, SVDWhich which, double tol, SVDType type) const
973 nconv=computeSVD(nsv, &valS, &vecS, which, tol, type);
975 std::vector< Vector > result(2*nconv);
977 for (int i=0;i<nconv;i++)
979 DoubleTab values_left (_numberOfRows,vecS[i]);
980 Vector myVecS_left(_numberOfRows);
981 myVecS_left.setValues(values_left);
982 result[i]=myVecS_left;
983 DoubleTab values_right (_numberOfColumns,vecS[i+nconv]);
984 Vector myVecS_right(_numberOfColumns);
985 myVecS_right.setValues(values_right);
986 result[i+nconv]=myVecS_right;
990 for (int i=0;i<nconv;i++)
998 SparseMatrixPetsc::leftDiagonalScale(Vector v)
1000 Vec vec=vectorToVec(v);
1002 MatAssemblyBegin(_mat, MAT_FINAL_ASSEMBLY);
1003 MatAssemblyEnd(_mat, MAT_FINAL_ASSEMBLY);
1005 MatDiagonalScale(_mat, vec, NULL);
1008 SparseMatrixPetsc::rightDiagonalScale(Vector v)
1010 Vec vec=vectorToVec(v);
1012 MatAssemblyBegin(_mat, MAT_FINAL_ASSEMBLY);
1013 MatAssemblyEnd(_mat, MAT_FINAL_ASSEMBLY);
1015 MatDiagonalScale(_mat, NULL, vec);