Hello PETSc team,

firtst of all sorry if this is not the right email where I can address my
question to.

I was looking for an IDR(s) implementation on PETSc since it would be
needed for the research I was performing.

I did not find it (I don't know if it is on-working or not contemplated) so
I tried to implement it by myself (since I have Matlab code available)

Code works (solution is exact) but performance are not good as expected
(not so bad, but lightly higher than BicGSTAB)

I would like to share with you and, if someone has a little bit of time to
spend on, I would be grateful if he could help me

I share my preliminary code, sorry for bad "informatic" implementation, I'm
sure is much improvable from this point of view.
It works only in serial mode for the moment

Thank you all for the time

Regards
Simone Cammarasana
___________________________________

Saluti / Regards

*Simone Cammarasana*

Tel. +39 340 0029498
void idrSolve(Mat *A, Vec *b) {
PetscErrorCode  ierr;
PetscInt        one = 1.0, zero = 0.0;
PetscViewer     viewer;
int             i,j,k;
PetscInt        sizeMat;
PetscScalar     alfa = 1, beta = 0;
PetscInt        s = 4; 
PetscReal       tol = 1e-12;
PetscReal       angle = 0.7;
PetscReal       om = 1;
PetscReal       Alpha,Beta;
PetscInt        iter = 0;
PetscInt        maxIteration = 10000;

Mat             P,G,U,M;
PetscScalar     *aP, *aG, *aU, *aM, *ar, *af, *aGapp, *aUapp, *ax, *at; /* scalar from array */
PetscScalar     *ac, *av;
Vec             x0; /* initial solution */
Vec             menox;
Vec             r,f; 
Vec             D; /* Diagonal ones */
Vec             Gapp, Uapp;
Vec             t;
Vec             v;
Vec             c;
Vec             x;

PetscReal       normb;
PetscReal       normr;
PetscReal       tolb;

/*Read sizeMat */

ierr = VecGetSize(b,&sizeMat);

/*Create Matrix and Vectors */


ierr =  MatCreateDense(PETSC_COMM_WORLD,PETSC_DECIDE,PETSC_DECIDE,sizeMat,s,NULL,&P); ierr = MatSetFromOptions(P);
ierr = VecCreate(PETSC_COMM_WORLD, &x0); ierr = VecSetSizes(x0,PETSC_DECIDE,sizeMat); ierr = VecSetFromOptions(x0); ierr = VecSet(x0,zero);
ierr = VecCreate(PETSC_COMM_WORLD, &r); ierr = VecSetSizes(r,PETSC_DECIDE,sizeMat); ierr = VecSetFromOptions(r);
ierr = VecCreate(PETSC_COMM_WORLD, &menox); ierr = VecSetSizes(menox,PETSC_DECIDE,sizeMat); ierr = VecSetFromOptions(menox);
ierr =  MatCreateDense(PETSC_COMM_WORLD,PETSC_DECIDE,PETSC_DECIDE,sizeMat,s,NULL,&G); ierr = MatSetFromOptions(G);
ierr =  MatCreateDense(PETSC_COMM_WORLD,PETSC_DECIDE,PETSC_DECIDE,sizeMat,s,NULL,&U); ierr = MatSetFromOptions(U);
ierr =  MatCreateDense(PETSC_COMM_WORLD,PETSC_DECIDE,PETSC_DECIDE,s,s,NULL,&M); ierr = MatSetFromOptions(M);
ierr = VecCreate(PETSC_COMM_WORLD, &D); ierr = VecSetSizes(D,PETSC_DECIDE,s); ierr = VecSetFromOptions(D); ierr = VecSet(D,one);
ierr = VecCreate(PETSC_COMM_WORLD, &f); ierr = VecSetSizes(f,PETSC_DECIDE,s); ierr = VecSetFromOptions(f); ierr = VecSet(f,zero);
ierr = VecCreate(PETSC_COMM_WORLD, &Gapp); ierr = VecSetSizes(Gapp,PETSC_DECIDE,sizeMat); ierr = VecSetFromOptions(Gapp); 
ierr = VecCreate(PETSC_COMM_WORLD, &Uapp); ierr = VecSetSizes(Uapp,PETSC_DECIDE,sizeMat); ierr = VecSetFromOptions(Uapp); 
ierr = VecCreate(PETSC_COMM_WORLD, &t); ierr = VecSetSizes(t,PETSC_DECIDE,sizeMat); ierr = VecSetFromOptions(t);
ierr = VecCreate(PETSC_COMM_WORLD, &v); ierr = VecSetSizes(v,PETSC_DECIDE,sizeMat); ierr = VecSetFromOptions(v);
ierr = VecCreate(PETSC_COMM_WORLD, &c); ierr = VecSetSizes(c,PETSC_DECIDE,s); ierr = VecSetFromOptions(c);
ierr = VecCreate(PETSC_COMM_WORLD, &x); ierr = VecSetSizes(x,PETSC_DECIDE,sizeMat); ierr = VecSetFromOptions(x);

/*Create Random Object for P */

ierr = PetscMalloc1(sizeMat*s,&aP);
for(i = 0; i < sizeMat*s;i++) aP[i] = rand()/(double)RAND_MAX;

/*P Orthnorm to be performed here */

/* initialize x to x0 */
x = x0;

/* norm and relative tolerance */

ierr = VecNorm(b,NORM_2,&normb);
tolb = tol*normb;

/* Residual Calculation */
menox = x; /* surely to be optimize */
ierr =  VecScale(menox, -1);

ierr = MatMultAdd(A,menox,b,r);
ierr = VecNorm(r,NORM_2,&normr);

/* Create M */
ierr = MatZeroEntries(M);
ierr = MatDiagonalSet(M,D,INSERT_VALUES);

/* Extract Arrays */
ierr = VecGetArray(r,&ar);
ierr = VecGetArray(f,&af);
ierr = VecGetArray(x,&ax);
ierr = MatDenseGetArray(M,&aM);
ierr = MatDenseGetArray(U,&aU);
ierr = MatDenseGetArray(G,&aG);
ierr = VecGetArray(Uapp,&aUapp);
ierr = VecGetArray(t,&at);
ierr = VecGetArray(v,&av);
ierr = VecGetArray(c,&ac);

while( (iter < maxIteration) && (normr > tolb) ) {

 cblas_dgemm(CblasColMajor, CblasNoTrans, CblasNoTrans,
             1, s, sizeMat, alfa, ar,1, aP, sizeMat, beta, af, 1); /*(m,n,k,alfa,A,lda,B,ldb,beta,C,ldc) */

 for(k = 0; k < s; k++) {

/* Initialize ac */
  for(i = k; i< s; i++) ac[i] = 0;
/* Solve M\f */ 
  ac[k] = af[k]/aM[k*s+k];
  for(i = k+1; i < s; i++) {
   for(j = k; j < i; j++)   {
    ac[i] = ac[i]+(aM[j*s+i]*ac[j])/aM[i*s+i];
   }
   ac[i] = af[i]/aM[i*s+i]-ac[i]; 
  }

/* Calculate v */
  cblas_dcopy(sizeMat,ar,1,av,1);

  cblas_dgemv(CblasColMajor, CblasNoTrans,
              sizeMat, s-k,  -1, aG+sizeMat*k,sizeMat, ac+k,1, 1, av, 1); /*layout, trans, m(A),n(A),alfa,A,lda,x,incx,beta,y,incy */

/* Compute new U */
  cblas_dgemv(CblasColMajor, CblasNoTrans,
              sizeMat, s-k,  +1, aU+sizeMat*k,sizeMat, ac+k,1, om, av, 1); /*layout, trans, m(A),n(A),alfa,A,lda,x,incx,beta,y,incy --> y = alfa*Ax + beta*y */

  cblas_dcopy(sizeMat,av,1,aU+sizeMat*k,1);

/*Compute new G */
  cblas_dcopy(sizeMat,aU+k*sizeMat,1,aUapp,1);  
  ierr = VecRestoreArray(Uapp,&aUapp);

  ierr = MatMult(A,Uapp,Gapp);

  ierr = VecGetArray(Gapp,&aGapp);
  ierr = VecGetArray(Uapp,&aUapp);

  cblas_dcopy(sizeMat,aGapp,1,aG+sizeMat*k,1);

/*BiOrthogonalise the new basis vectors */
  for(i = 0; i < k-1; i++) {

   Alpha = cblas_ddot(sizeMat,aP+sizeMat*i,1,aG+sizeMat*k,1)/aM[i*s+i]; /*n,x,incx,y,incy */

   cblas_daxpy(sizeMat,-Alpha,aG+i*sizeMat,1,aG+k*sizeMat,1);/* n,alfa,x,incx,y,incy --> y = ax+y */
   cblas_daxpy(sizeMat,-Alpha,aU+i*sizeMat,1,aU+k*sizeMat,1);/* n,alfa,x,incx,y,incy --> y = ax+y */

  }

/* New column of M */
  cblas_dgemm(CblasColMajor, CblasNoTrans, CblasNoTrans,
              1, s-k, sizeMat, alfa, aG+k*sizeMat,1, aP+k*sizeMat, sizeMat, 0, aM+k*s+k, 1); /*(m,n,k,alfa,A,lda,B,ldb,beta,C,ldc)-->C = alfaAB+betaC */

/* Make r ortoghonal */
  Beta = af[k]/aM[k*s+k];
  cblas_daxpy(sizeMat,-Beta,aG+k*sizeMat,1,ar,1);/* n,alfa,x,incx,y,incy --> y = ax+y */
  cblas_daxpy(sizeMat,Beta,aU+k*sizeMat,1,ax,1);/* n,alfa,x,incx,y,incy --> y = ax+y */
  normr = calcNorm(ar,sizeMat);

/* New f = P'*r */
  if(k < s-1) cblas_daxpy(s-k-1,-Beta,aM+k*s+k+1,1,af+k+1,1); /*n,alfa,x,incx,y,incy --> y = ax+y*/

  } 
/*Calculate t = A*v */
 cblas_dcopy(sizeMat,ar,1,av,1);
 ierr = VecRestoreArray(v,&av);
 ierr = MatMult(A,v,t);
 ierr = VecGetArray(v,&av);

/*Calculate Omega */
 om = omega(at,ar,angle,sizeMat);

/* Calculate r and x */
 cblas_daxpy(sizeMat,-om,at,1,ar,1);/*n,alfa,x,incx,y,incy --> y = ax+y */
 cblas_daxpy(sizeMat,+om,av,1,ax,1);/*n,alfa,x,incx,y,incy --> y = ax+y */

 normr = calcNorm(ar,sizeMat);

 iter++;
 }
/* RESTORE */
 ierr = VecRestoreArray(x,&ax);

/* STDOUT PRINT */
 printf("iterations = %i\n",iter); 
 VecView(x,PETSC_VIEWER_STDOUT_WORLD);

return;
}

PetscReal omega(PetscScalar *at, PetscScalar *ar, PetscReal angle, PetscInt sizeMat) {
 PetscReal ns,nt,ts;
 PetscReal rho,om;

 ns = calcNorm(ar,sizeMat);
 nt = calcNorm(at,sizeMat);

 ts = cblas_ddot(sizeMat,at,1,ar,1);

 rho = fabs(ts/(nt*ns));
 om = ts/(nt*nt);
 if(rho < angle)  om = om*angle/rho;

 return om;
}

PetscReal calcNorm(PetscScalar *array, PetscInt size) {
 int       i;
 PetscReal somma = 0;
 for(i = 0; i < size; i++) somma = somma + array[i]*array[i];
 return sqrt(somma);
}

Reply via email to