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) const
541 EPS eps; /* eigenproblem solver context */
546 PetscInt i,maxit,its, nconv;
548 SlepcInitialize(0, (char ***)"", PETSC_NULL, PETSC_NULL);
550 MatAssemblyBegin(_mat,MAT_FINAL_ASSEMBLY);
551 MatAssemblyEnd(_mat,MAT_FINAL_ASSEMBLY);
553 MatCreateVecs(_mat,&xr,NULL);
554 MatCreateVecs(_mat,&xi,NULL);
556 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
557 Create the eigensolver and set various options
558 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
560 Create eigensolver context
562 EPSCreate(PETSC_COMM_WORLD,&eps);
565 Set operators. In this case, it is a standard eigenvalue problem
567 EPSSetOperators(eps,_mat,NULL);
568 //if(isSymmetric(tol))
569 //EPSSetProblemType(eps,EPS_HEP);
571 EPSSetProblemType(eps,EPS_NHEP);
572 EPSSetWhichEigenpairs(eps,which);
573 EPSSetDimensions(eps,nev,PETSC_DEFAULT,PETSC_DEFAULT);
574 EPSSetTolerances(eps,tol,PETSC_DEFAULT);
577 Set solver parameters at runtime
579 EPSSetFromOptions(eps);
581 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
582 Solve the eigensystem
583 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
587 Optional: Get some information from the solver and display it
589 EPSGetIterationNumber(eps,&its);
590 PetscPrintf(PETSC_COMM_WORLD," Number of iterations of the method: %D\n",its);
591 EPSGetType(eps,&type);
592 PetscPrintf(PETSC_COMM_WORLD," Solution method: %s\n\n",type);
593 EPSGetDimensions(eps,&nev,NULL,NULL);
594 PetscPrintf(PETSC_COMM_WORLD," Number of requested eigenvalues: %D\n",nev);
595 EPSGetTolerances(eps,&tol,&maxit);
596 PetscPrintf(PETSC_COMM_WORLD," Stopping condition: tol=%.4g, maxit=%D\n",(double)tol,maxit);
598 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
599 Display solution and clean up
600 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
602 Get number of converged approximate eigenpairs
604 EPSGetConverged(eps,&nconv);
605 PetscPrintf(PETSC_COMM_WORLD," Number of converged eigenpairs: %D\n\n",nconv);
607 *valP=new double[nconv];
608 *vecP=new double * [nconv];
613 Display eigenvalues and relative errors
615 PetscPrintf(PETSC_COMM_WORLD,
616 " k ||Ax-kx||/||kx||\n"
617 " ----------------- ------------------\n");
619 for (int i=0;i<nconv;i++) {
621 Get converged eigenpairs: i-th eigenvalue is stored in kr (real part) and
624 EPSGetEigenpair(eps,i,&kr,&ki,xr,xi);
626 Compute the relative error associated to each eigenpair
628 if(fabs(kr)>tol || fabs(ki)>tol)
630 EPSComputeError(eps,i,EPS_ERROR_RELATIVE,&error);
633 PetscPrintf(PETSC_COMM_WORLD," %9f%+9fi %12g\n",(double)kr,(double)ki,(double)error);
635 PetscPrintf(PETSC_COMM_WORLD," %12f %12g\n",(double)kr,(double)error);
640 PetscPrintf(PETSC_COMM_WORLD," %9f%+9fi %12s\n",(double)kr,(double)ki,"Null eigenvalue");
642 PetscPrintf(PETSC_COMM_WORLD," %12f %12s\n",(double)kr,"Null eigenvalue");
646 VecGetArray(xr,&myVecp);
647 *(*vecP+ i)=new double [_numberOfRows];
648 memcpy(*(*vecP+ i),myVecp,_numberOfRows*sizeof(double)) ;
650 PetscPrintf(PETSC_COMM_WORLD,"\n");
671 throw CdmathException("SparseMatrixPetsc::computeSpectrum : No eigenvector found");
676 SparseMatrixPetsc::computeSVD(int nsv, double ** valS, double ***vecS, SVDWhich which, double tol) const
678 SVD svd; /* Singular value decomposition solver context */
683 PetscInt i,maxit,its, nconv;
685 SlepcInitialize(0, (char ***)"", PETSC_NULL, PETSC_NULL);
687 MatAssemblyBegin(_mat,MAT_FINAL_ASSEMBLY);
688 MatAssemblyEnd( _mat,MAT_FINAL_ASSEMBLY);
690 MatCreateVecs(_mat,&u,NULL);
691 MatCreateVecs(_mat,NULL,&v);
693 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
694 Create the singular value solver and set various options
695 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
697 Create singular value decomposition context
699 SVDCreate(PETSC_COMM_WORLD,&svd);
702 Set operators. In this case, it is a standard singular value problem
704 #if (SLEPC_VERSION_MAJOR==3) && (SLEPC_VERSION_MINOR > 14)
705 SVDSetOperators(svd,_mat,NULL);
707 SVDSetOperator(svd,_mat);
710 SVDSetWhichSingularTriplets(svd,which);
711 SVDSetDimensions(svd,nsv,PETSC_DEFAULT,PETSC_DEFAULT);
712 SVDSetTolerances(svd,tol,PETSC_DEFAULT);
715 Set solver parameters at runtime
717 SVDSetFromOptions(svd);
719 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
720 Solve the SVD problem
721 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
725 Optional: Get some information from the solver and display it
727 SVDGetIterationNumber(svd,&its);
728 PetscPrintf(PETSC_COMM_WORLD," Number of iterations of the method: %D\n",its);
729 SVDGetType(svd,&type);
730 PetscPrintf(PETSC_COMM_WORLD," Solution method: %s\n\n",type);
731 SVDGetDimensions(svd,&nsv,NULL,NULL);
732 PetscPrintf(PETSC_COMM_WORLD," Number of requested singular values: %D\n",nsv);
733 SVDGetTolerances(svd,&tol,&maxit);
734 PetscPrintf(PETSC_COMM_WORLD," Stopping condition: tol=%.4g, maxit=%D\n",(double)tol,maxit);
736 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
737 Display solution and clean up
738 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
740 Get number of converged approximate singular values
742 SVDGetConverged(svd,&nconv);
743 PetscPrintf(PETSC_COMM_WORLD," Number of converged singular values: %D\n\n",nconv);
745 *valS=new double[nconv];
746 *vecS=new double * [2*nconv];
751 Display eigenvalues and relative errors
753 PetscPrintf(PETSC_COMM_WORLD,
754 " k ||Ax-kx||/||kx||\n"
755 " ----------------- ------------------\n");
757 for (int i=0;i<nconv;i++) {
759 Get converged singular values: i-th eigenvalue is stored in valS
761 SVDGetSingularTriplet(svd,i,*valS+i, u, v);
762 if(fabs(*(*valS+i))>tol)
765 Compute the relative error associated to each singular value
767 SVDComputeError( svd, i, SVD_ERROR_RELATIVE, &error );
769 PetscPrintf(PETSC_COMM_WORLD," %12f %12g\n",(double)*(*valS+i),(double)error);
772 PetscPrintf(PETSC_COMM_WORLD," %12f %12s\n",(double)*(*valS+i),"Null singular value");
774 VecGetArray(u,&myVecS);
775 *(*vecS + i)=new double [_numberOfRows];
776 memcpy(*(*vecS + i),myVecS,_numberOfRows*sizeof(double)) ;
777 VecGetArray(v,&myVecS);
778 *(*vecS + i + nconv)=new double [_numberOfColumns];
779 memcpy(*(*vecS + i + nconv),myVecS,_numberOfColumns*sizeof(double)) ;
781 PetscPrintf(PETSC_COMM_WORLD,"\n");
802 throw CdmathException("SparseMatrixPetsc::computeSVD : singular value decomposition failed");
806 std::vector< double >
807 SparseMatrixPetsc::getEigenvalues(int nev, EPSWhich which, double tol) const
813 nconv=computeSpectrum(nev, &valP, &vecP, which, tol);
815 std::vector< double > result(nconv);
817 for (int i=0;i<nconv;i++)
821 for (int i=0;i<nconv;i++)
828 std::vector< Vector >
829 SparseMatrixPetsc::getEigenvectors(int nev, EPSWhich which, double tol) const
835 nconv=computeSpectrum(nev, &valP, &vecP, which, tol);
837 std::vector< Vector > result(nconv);
839 for (int i=0;i<nconv;i++)
841 DoubleTab values (_numberOfRows,vecP[i]);
842 Vector myVecP(_numberOfRows);
843 myVecP.setValues(values);
848 for (int i=0;i<nconv;i++)
855 MEDCoupling::DataArrayDouble *
856 SparseMatrixPetsc::getEigenvectorsDataArrayDouble(int nev, EPSWhich which, double tol) const
862 nconv=computeSpectrum(nev, &valP, &vecP, which, tol);
864 #ifdef MEDCoupling_VERSION_VERSION_GREATER_9_4
865 std::vector< long unsigned int > compoId(1);
867 std::vector< int > compoId(1);
869 MEDCoupling::DataArrayDouble *arrays=MEDCoupling::DataArrayDouble::New();
870 MEDCoupling::DataArrayDouble *array =MEDCoupling::DataArrayDouble::New();
871 arrays->alloc(_numberOfRows,nconv);
873 for (int i=0;i<nconv;i++)
875 array->useArray(vecP[i],true, MEDCoupling::DeallocType::CPP_DEALLOC, _numberOfRows,1);
877 arrays->setSelectedComponents(array,compoId);
878 arrays->setInfoOnComponent(i,std::to_string(valP[i]));
887 SparseMatrixPetsc::getConditionNumber(bool isSingular, double tol) const
889 if(isSymmetric(tol))//Eigenvalues computation is more robust that singular values computation
892 double lambda_max, lambda_min;
893 std::vector< double > my_ev;
895 /*** Lowest eigenvalue, first check if matrix is singular ***/
901 my_ev=getEigenvalues( nev, EPS_SMALLEST_MAGNITUDE, tol);
904 throw CdmathException("SparseMatrixPetsc::getConditionNumber could not find the smallest eigenvalue");
905 lambda_min=my_ev[nev-1];
907 /*** Largest eigenvalue ***/
909 my_ev=getEigenvalues( nev, EPS_LARGEST_MAGNITUDE, tol);
912 throw CdmathException("SparseMatrixPetsc::getConditionNumber could not find the largest eigenvalue");
913 lambda_max=my_ev[nev-1];
915 return fabs(lambda_max)/fabs(lambda_min);
917 else//Singular values computation is more robust than eigenvalues computation
922 double sigma_max, sigma_min;
924 /*** Lowest singular value, first check if matrix is singular ***/
930 nconv=computeSVD(nsv, &valS, &vecS, SVD_SMALLEST, tol);
932 throw CdmathException("SparseMatrixPetsc::getConditionNumber could not find the smallest singular value");
933 sigma_min=valS[nsv-1];
936 /*** Largest singular value ***/
938 nconv=computeSVD(nsv, &valS, &vecS, SVD_LARGEST, tol);
940 throw CdmathException("SparseMatrixPetsc::getConditionNumber could not find the largest singular value");
941 sigma_max=valS[nsv-1];
944 return sigma_max/sigma_min;
948 std::vector< double >
949 SparseMatrixPetsc::getSingularValues(int nsv, SVDWhich which, double tol) const
955 nconv=computeSVD(nsv, &valS, &vecS, which, tol);
957 std::vector< double > result(nconv);
959 for (int i=0;i<nconv;i++)
967 std::vector< Vector >
968 SparseMatrixPetsc::getSingularVectors(int nsv, SVDWhich which, double tol) const
974 nconv=computeSVD(nsv, &valS, &vecS, which, tol);
976 std::vector< Vector > result(2*nconv);
978 for (int i=0;i<nconv;i++)
980 DoubleTab values_left (_numberOfRows,vecS[i]);
981 Vector myVecS_left(_numberOfRows);
982 myVecS_left.setValues(values_left);
983 result[i]=myVecS_left;
984 DoubleTab values_right (_numberOfColumns,vecS[i+nconv]);
985 Vector myVecS_right(_numberOfColumns);
986 myVecS_right.setValues(values_right);
987 result[i+nconv]=myVecS_right;
991 for (int i=0;i<nconv;i++)
999 SparseMatrixPetsc::leftDiagonalScale(Vector v)
1001 Vec vec=vectorToVec(v);
1003 MatAssemblyBegin(_mat, MAT_FINAL_ASSEMBLY);
1004 MatAssemblyEnd(_mat, MAT_FINAL_ASSEMBLY);
1006 MatDiagonalScale(_mat, vec, NULL);
1009 SparseMatrixPetsc::rightDiagonalScale(Vector v)
1011 Vec vec=vectorToVec(v);
1013 MatAssemblyBegin(_mat, MAT_FINAL_ASSEMBLY);
1014 MatAssemblyEnd(_mat, MAT_FINAL_ASSEMBLY);
1016 MatDiagonalScale(_mat, NULL, vec);