Hello all,
First of all, thank you Matthew and Barry for your answers in July.
Your solution using PCKSP is fine.
Now it works perfectly with the examples I have tried for ksp and snes.
I made many tests with many processors.
I have implemented my own CGLS or LSQR method. In Petsc, I have seen
that CGNE and LSQR are already implemented. However, I cannot use them
because I have a problem of non square matrix.
In previous posts, I saw that the problem can come from the preconditioner.
In the attached code, I have my new solver (without preconditioner if I
made no mistake) which is based on
ierr = PCKSPGetKSP(pc,&sub_ksp);CHKERRQ(ierr);
and I need to use another ksp to minimize the residual (instead of my
own CGLS). The matrix AS is of size (n,10) with n very large.
I have tried with that (line 262 in the code)
{
KSP ksp3;
ierr = KSPCreate(PETSC_COMM_WORLD, &ksp3); CHKERRQ(ierr);
ierr = KSPSetType(ksp3, KSPLSQR); CHKERRQ(ierr);
ierr = KSPSetOperators(ksp3, AS, AS); CHKERRQ(ierr);
ierr = KSPSetTolerances(ksp3, PETSC_DEFAULT, PETSC_DEFAULT,
PETSC_DEFAULT, iter_max_minimization);
ierr = PCSetType(ksp,PCNONE);
ierr = KSPSolve(ksp3, b, Alpha); CHKERRQ(ierr);
}
The problem on all the processors is:
[0]PETSC ERROR: No support for this operation for this object type
[0]PETSC ERROR: Only square matrices supported.
[0]PETSC ERROR: See http://www.mcs.anl.gov/petsc/documentation/faq.html
for trouble shooting.
[0]PETSC ERROR: Petsc Release Version 3.6.1, Jul, 22, 2015
[0]PETSC ERROR: ./ex15 on a arch-linux2-c-debug named extinction by
couturie Thu Sep 3 13:22:03 2015
[0]PETSC ERROR: Configure options --download-openmpi --download-hypre
--download-f2cblaslapack --with-fc=0
[0]PETSC ERROR: #2 MatGetDiagonalBlock_MPIDense() line 78 in
/home/couturie/work/petsc-3.6.1/src/mat/impls/dense/mpi/mpidense.c
[0]PETSC ERROR: #3 MatGetDiagonalBlock() line 159 in
/home/couturie/work/petsc-3.6.1/src/mat/interface/matrix.c
[0]PETSC ERROR: #4 PCSetUp_BJacobi() line 126 in
/home/couturie/work/petsc-3.6.1/src/ksp/pc/impls/bjacobi/bjacobi.c
[0]PETSC ERROR: #5 PCSetUp() line 982 in
/home/couturie/work/petsc-3.6.1/src/ksp/pc/interface/precon.c
[0]PETSC ERROR: #6 KSPSetUp() line 332 in
/home/couturie/work/petsc-3.6.1/src/ksp/ksp/interface/itfunc.c
[0]PETSC ERROR: #7 KSPSolve() line 546 in
/home/couturie/work/petsc-3.6.1/src/ksp/ksp/interface/itfunc.c
[0]PETSC ERROR: #8 KSPSolve_TSIRM() line 269 in
/home/couturie/work/petsc-3.6.1/src/ksp/ksp/impls/gmres/tsirm.c
[0]PETSC ERROR: #9 KSPSolve() line 604 in
/home/couturie/work/petsc-3.6.1/src/ksp/ksp/interface/itfunc.c
[0]PETSC ERROR: #10 main() line 200 in
/home/couturie/work/petsc-3.6.1/src/ksp/ksp/examples/tutorials/ex15.c
Do you have an idea of the problem?
Is it a good idea to use the LSQR or CGLS method of Petsc?
Moreover I have another question. Do you think that the Petsc community
would be interested to use this solver. If yes, I would be glad to
improve it in order to integrate it in the source.
Thanks
Raphaël
#include <petsc/private/kspimpl.h> /*I "petscksp.h" I*/
#include <petscksp.h>
#undef __FUNCT__
#define __FUNCT__ "KSPSetUp_TSIRM"
static PetscErrorCode KSPSetUp_TSIRM(KSP ksp)
{
/* PetscErrorCode ierr;
PetscBool diagonalscale;
PetscFunctionBegin;
//Maybe this need to be improved, I copied this from other solvers
ierr = PCGetDiagonalScale(ksp->pc,&diagonalscale);CHKERRQ(ierr);
if (diagonalscale) SETERRQ1(PetscObjectComm((PetscObject)ksp),PETSC_ERR_SUP,"Krylov method %s does not support diagonal scaling",((PetscObject)ksp)->type_name);
ierr = KSPSetWorkVecs(ksp,9);CHKERRQ(ierr);*/
PetscFunctionReturn(0);
}
#undef __FUNCT__
#define __FUNCT__ "KSPSolve_TSIRM"
PetscErrorCode KSPSolve_TSIRM(KSP ksp) {
//Variables
PetscScalar gamma, alpha, oldgamma, beta;
PetscReal norm=20, cgprec=1e-40;
PetscInt ColS=12, col=0, iter_minimization=0, iter_max_minimization=15,outer_iter=0;
PetscErrorCode ierr;
PetscScalar T1, T2;
PetscInt total=0;
PetscInt size;
PetscInt Istart,Iend;
PetscInt i,its;
Vec residu;
Mat S, AS;
PetscScalar *array;
PetscInt *ind_row;
Vec Alpha, p, ss, vect, r, q, Ax,x, b;
Mat A;
PetscInt first_iteration=1;
PetscReal res=99999999;
PetscOptionsBegin(PETSC_COMM_WORLD,NULL,"Tsirm","");
{
ierr = PetscOptionsInt("-ksp_tsirm_outer_iter","Number of outer iterations before minimization","",ColS,&ColS,NULL);CHKERRQ(ierr);
ierr = PetscOptionsInt("-ksp_tsirm_iter_min","Maximum number of iterations in the minimization process","",iter_max_minimization,&iter_max_minimization,NULL);CHKERRQ(ierr);
}
PetscOptionsEnd();
ierr = PetscPrintf(PETSC_COMM_WORLD, "Enter tsirm\n"); CHKERRQ(ierr);
KSPGetRhs(ksp,&b);
KSPGetOperators(ksp,&A,NULL);
KSPGetSolution(ksp,&x);
VecGetSize(b,&size);
ierr = PetscPrintf(PETSC_COMM_WORLD, "Size of vector %D\n", size); CHKERRQ(ierr);
PetscInt aa,bb;
MatGetOwnershipRange(A,&aa,&bb);
ierr = MatCreate(PETSC_COMM_WORLD, &S);CHKERRQ(ierr);
ierr = MatSetSizes(S, bb-aa, PETSC_DECIDE, size, ColS); CHKERRQ(ierr);
ierr = MatSetType(S, MATMPIDENSE); CHKERRQ(ierr);
ierr = MatSetUp(S); CHKERRQ(ierr);
ierr = MatGetOwnershipRange(S, &Istart, &Iend); CHKERRQ(ierr);
ierr = VecCreate(PETSC_COMM_WORLD, &Alpha); CHKERRQ(ierr);
ierr = VecSetSizes(Alpha, PETSC_DECIDE, ColS); CHKERRQ(ierr);
ierr = VecSetFromOptions(Alpha); CHKERRQ(ierr);
ierr = VecDuplicate(Alpha, &vect); CHKERRQ(ierr);
ierr = VecDuplicate(Alpha, &p); CHKERRQ(ierr);
ierr = VecDuplicate(Alpha, &ss); CHKERRQ(ierr);
ierr = VecDuplicate(b, &r); CHKERRQ(ierr);
ierr = VecDuplicate(b, &q); CHKERRQ(ierr);
ierr = VecDuplicate(b, &Ax); CHKERRQ(ierr);
ierr = VecDuplicate(b,&residu);CHKERRQ(ierr);
//indexes of row (these indexes are global)
ind_row = (PetscInt*)malloc(sizeof(PetscInt)*(Iend-Istart));
for(i=0; i<Iend-Istart; i++) ind_row[i] = i + Istart;
PetscInt restart=30;
// PetscReal aa1,aa2,aa3;
//PetscInt old_maxits;
//ierr = KSPGetTolerances(ksp, &aa1, &aa2, &aa3, &old_maxits); CHKERRQ(ierr);
KSP sub_ksp;
PC pc;
PCType type;
ierr = KSPGetPC(ksp,&pc);CHKERRQ(ierr);
ierr = PCKSPGetKSP(pc,&sub_ksp);CHKERRQ(ierr);
ierr= KSPGetType(sub_ksp,&type);CHKERRQ(ierr);
ierr= PetscPrintf(PETSC_COMM_WORLD, "SUB KSP TYPE %s \n", type);CHKERRQ(ierr);
ierr = KSPSetFromOptions(ksp);CHKERRQ(ierr);
ierr = KSPSetFromOptions(sub_ksp);CHKERRQ(ierr);
ierr = KSPSetTolerances(sub_ksp, PETSC_DEFAULT, PETSC_DEFAULT, PETSC_DEFAULT, restart); CHKERRQ(ierr);
//GMRES WITH MINIMIZATION
T1 = MPI_Wtime();
// ierr = KSPSetUp(sub_ksp); CHKERRQ(ierr);
//previously it seemed good but with SNES it seems not good....
ierr = KSP_MatMult(sub_ksp,A,x,r);CHKERRQ(ierr);
VecAXPY(r,-1,b);
VecNorm(r, NORM_2, &res);
ksp->its=0;
KSPConvergedDefault(ksp,ksp->its,res,&ksp->reason,ksp->cnvP);
//ierr = (*ksp->converged)(ksp,ksp->its,res,&ksp->reason,ksp->cnvP);CHKERRQ(ierr);
ierr = PetscPrintf(PETSC_COMM_WORLD, "IIII converged %d residual norm %f its %d\n",ksp->reason,norm,ksp->its); CHKERRQ(ierr);
{
PetscReal rtol,abstol,dtol;
PetscInt maxits;
ierr = KSPGetTolerances(sub_ksp,&rtol,&abstol,&dtol,&maxits);CHKERRQ(ierr);
ierr = PetscPrintf(PETSC_COMM_WORLD, "sub ksp rtol %e abstol %e dtol %e maxits %d\n", rtol,abstol,dtol,maxits); CHKERRQ(ierr);
}
{
PetscReal rtol,abstol,dtol;
PetscInt maxits;
ierr = KSPGetTolerances(ksp,&rtol,&abstol,&dtol,&maxits);CHKERRQ(ierr);
ierr = PetscPrintf(PETSC_COMM_WORLD, "ksp rtol %e abstol %e dtol %e maxits %d\n", rtol,abstol,dtol,maxits); CHKERRQ(ierr);
}
ierr = KSPSetInitialGuessNonzero(sub_ksp, PETSC_TRUE); CHKERRQ(ierr);
// PetscFinalize();
//exit(0);
do{
for(col=0; col<ColS && ksp->reason==0 ; col++){
//Solve
ierr = KSPSolve(sub_ksp, b, x); CHKERRQ(ierr);
ierr = KSPGetIterationNumber(sub_ksp, &its); CHKERRQ(ierr);
total += its;
//Build S'
ierr = VecGetArray(x, &array);
ierr = MatSetValues(S, Iend-Istart, ind_row, 1, &col, array, INSERT_VALUES);
VecRestoreArray(x, &array);
//ierr = KSPLogResidualHistory(sub_ksp,res);CHKERRQ(ierr);
//ierr = KSPMonitor(sub_ksp,sub_ksp->its,res);CHKERRQ(ierr);
KSPGetResidualNorm(sub_ksp,&norm);
ksp->rnorm = norm;
res=norm;
ksp->its++;
KSPConvergedDefault(ksp,ksp->its,res,&ksp->reason,ksp->cnvP);
ierr = PetscPrintf(PETSC_COMM_WORLD, "Norm of error %g, minimization iteration %D %g reason %D \n", res, outer_iter,ksp->rnorm, ksp->reason); CHKERRQ(ierr);
}
//minimization step
if(ksp->reason==0)
{
MatAssemblyBegin(S, MAT_FINAL_ASSEMBLY);
MatAssemblyEnd(S, MAT_FINAL_ASSEMBLY);
//Build the AS matrix
if(first_iteration) {
MatMatMult(A,S, MAT_INITIAL_MATRIX,PETSC_DEFAULT,&AS);
first_iteration=0;
}
else
MatMatMult(A,S, MAT_REUSE_MATRIX,PETSC_DEFAULT,&AS);
//Minimization with the CGLS conjugate gradient least square method
/* MatMult(AS, Alpha, r); VecAYPX(r, -1, b); //r_0 = b-AS*x_0
MatMultTranspose(AS, r, p); //p_0 = AS'*r_0
iter_minimization = 0;
ierr = VecCopy(p, ss); CHKERRQ(ierr); //p_0 = s_0
VecNorm(ss, NORM_2, &gamma); gamma = gamma * gamma; //gamma = norm2(s)^2
while(gamma>cgprec && iter_minimization<iter_max_minimization){
MatMult(AS, p, q); //q = AS*p
VecNorm(q, NORM_2, &alpha); alpha = alpha * alpha; //alpha = norm2(q)^2
alpha = gamma / alpha;
VecAXPY(Alpha, alpha, p); //Alpha += alpha*p
VecAXPY(r, -alpha, q); //r -= alpha*q
MatMultTranspose(AS, r, ss); // ss = AS'*r
oldgamma = gamma;
VecNorm(ss, NORM_2, &gamma); gamma = gamma * gamma; //gamma = norm2(s)^2
beta = gamma / oldgamma;
VecAYPX(p, beta, ss); //p = s+beta*p;
iter_minimization ++;
}
*/
{
KSP ksp3;
ierr = KSPCreate(PETSC_COMM_WORLD, &ksp3); CHKERRQ(ierr);
ierr = KSPSetType(ksp3, KSPLSQR); CHKERRQ(ierr);
ierr = KSPSetOperators(ksp3, AS, AS); CHKERRQ(ierr);
ierr = KSPSetTolerances(ksp3, PETSC_DEFAULT, PETSC_DEFAULT, PETSC_DEFAULT, iter_max_minimization);
ierr = PCSetType(ksp,PCNONE);
ierr = KSPSolve(ksp3, b, Alpha); CHKERRQ(ierr);
}
outer_iter ++;
//Minimizer
MatMult(S, Alpha, x); //x = S*Alpha;
}
} while (iter_minimization<ksp->max_it && ksp->reason==0 );
ksp->its=total;
T2 = MPI_Wtime();
ierr = PetscPrintf(PETSC_COMM_WORLD, "\t\t\t -- Execution time : %g (s)\n", T2-T1); CHKERRQ(ierr);
ierr = PetscPrintf(PETSC_COMM_WORLD, "\t\t\t -- Total number of iterations : %D\n", total); CHKERRQ(ierr);
//free allocated variables
ierr = VecDestroy(&Alpha);CHKERRQ(ierr);
ierr = MatDestroy(&S);CHKERRQ(ierr);
ierr = VecDestroy(&vect);CHKERRQ(ierr);
ierr = VecDestroy(&p);CHKERRQ(ierr);
ierr = VecDestroy(&ss);CHKERRQ(ierr);
ierr = VecDestroy(&r);CHKERRQ(ierr);
ierr = VecDestroy(&q);CHKERRQ(ierr);
ierr = VecDestroy(&Ax);CHKERRQ(ierr);
ierr = VecDestroy(&residu);CHKERRQ(ierr);
PetscFunctionReturn(0);
}
#undef __FUNCT__
#define __FUNCT__ "KSPCreate_TSIRM"
PETSC_EXTERN PetscErrorCode KSPCreate_TSIRM(KSP ksp)
{
PetscErrorCode ierr;
PetscFunctionBegin;
ksp->data = (void*)0;
ierr = KSPSetSupportedNorm(ksp,KSP_NORM_PRECONDITIONED,PC_LEFT,2);CHKERRQ(ierr);
ierr = KSPSetSupportedNorm(ksp,KSP_NORM_UNPRECONDITIONED,PC_RIGHT,1);CHKERRQ(ierr);
ksp->ops->setup = KSPSetUp_TSIRM;
ksp->ops->solve = KSPSolve_TSIRM;
ksp->ops->destroy = KSPDestroyDefault;
ksp->ops->buildsolution = KSPBuildSolutionDefault;
ksp->ops->buildresidual = KSPBuildResidualDefault;
ksp->ops->setfromoptions = 0;
ksp->ops->view = 0;
#if defined(PETSC_USE_COMPLEX)
SETERRQ(PetscObjectComm((PetscObject)ksp),PETSC_ERR_SUP,"This is not supported for complex numbers");
#endif
PetscFunctionReturn(0);
}