Example #1
0
static void solve_pressure(Element_List **V, double *rhs, Bsystem **Vbsys)
{
	register int i;
	int    eDIM = V[0]->flist[0]->dim();
	int    info,N,nbl,nblv,id,*bmap;
	Bsystem *B = Vbsys[0], *PB = Vbsys[eDIM];
	Element *E;
	double  *hj,*tmp;
	double  *sc = B->signchange;

	if(eDIM == 2)
		tmp = dvector(0,8*LGmax);
	else
		tmp = dvector(0,18*(LGmax-1)*(LGmax-1));


	/* back solve for pressure */
	for(E=V[eDIM]->fhead;E;E=E->next)
	{
		N   = E->Nmodes - 1;
		id  = E->geom->id;
		hj  = E->vert->hj + 1;

		E->state = 't';

		/* solve interior and negate */
		if(PB->lambda->wave)
		{
			dgetrs('N', N, 1, PB->Gmat->invc[id], N, PB->Gmat->cipiv[id],hj, N,
					info);
		}
		else
		{
			dpptrs('L', N, 1, PB->Gmat->invc[id], hj, N, info);
			dneg(N,hj,1);
		}

		bmap  = PB->bmap[E->id];
		nblv  = V[0]->flist[E->id]->Nbmodes;
		nbl   = eDIM*nblv+1;

		for(i = 0; i < nbl;  ++i)
			tmp[i] = rhs[bmap[i]];
		for(i = 0; i < eDIM; ++i)
			dvmul(nblv,sc,1,tmp+nblv*i,1,tmp+nblv*i,1);

		if(PB->lambda->wave)
			dgemv('N', N, nbl,-1.0, PB->Gmat->invcd[id], N, tmp, 1, 1.,hj,1);
		else
			dgemv('N', N, nbl,-1.0, PB->Gmat->binvc[id], N, tmp, 1, 1.,hj,1);

		sc += nblv;
	}

	free(tmp);
}
Example #2
0
void  Precon_Stokes(Element_List *U, Bsystem *B, double *r, double *z){

  switch(B->Precon){
  case Pre_Diag:
    dvmul(B->Pmat->info.diag.ndiag,B->Pmat->info.diag.idiag,1,r,1,z,1);
    break;
  case Pre_Block:{
    register int i;
    int eDIM = U->fhead->dim();
    int nedge = B->Pmat->info.block.nedge;
    int info,l,cnt;
    double *tmp = dvector(0,LGmax-1);
    static double *pinv;

    dcopy(B->nsolve,r,1,z,1);

#ifdef BVERT
    dpptrs('U',B->Pmat->info.block.nvert,1,B->Pmat->info.block.ivert,
     z,B->Pmat->info.block.nvert,info);
#else
    dvmul(B->Pmat->info.block.nvert,B->Pmat->info.block.ivert,1,z,1,z,1);
#endif

    cnt = B->Pmat->info.block.nvert;
    for(i = 0; i < nedge; ++i){
      l = B->Pmat->info.block.Ledge[i];
      dpptrs('U',l,1,B->Pmat->info.block.iedge[i],z+cnt,l,info);
      cnt += l;
    }

    if(!pinv){
      pinv = dvector(0,B->nsolve-cnt-1);
      for(i = 0; i < B->nsolve-cnt; ++i)
  pinv[i] = U->flist[i]->get_1diag_massmat(0);
      dvrecp(B->nsolve-cnt,pinv,1,pinv,1);
    }
    /* finally multiply pressure dof by inverse of mass matrix */
    dvmul(B->nsolve-cnt,pinv,1,r+cnt,1,z+cnt,1);

    free(tmp);
  }
    break;
  case Pre_None:
    dcopy(B->nsolve,r,1,z,1);
    break;
  case Pre_Diag_Stokes:{
    register int i,j,k;
    double *tmp = dvector(0,B->nglobal-1),*sc,*b,*p,*wk;
    int eDIM = U->fhead->dim();
    int **bmap = B->bmap;
    int nel = B->nel,asize,Nbmodes,info;

    if(eDIM == 2)
      wk = dvector(0,eDIM*4*LGmax);
    else
      wk = dvector(0,eDIM*6*LGmax*LGmax);

    dzero(B->nglobal,tmp,1);
    dcopy(B->nsolve-nel,r,1,tmp,1);

    /* multiply by invc */
    dvmul(B->nsolve-nel,B->Pmat->info.diagst.idiag,1,tmp,1,tmp,1);

    /* multiply by b^T */
    sc = B->signchange;
    p  = z + B->nsolve-nel;
    dcopy(nel,r+B->nsolve-nel,1,p,1);
    dneg (nel-1,p+1,1);
    /* start at 1 to omit singular pressure point */
    if(!(B->singular))
      error_msg(issue in setting singular modes in Stokes_Precon not resolved);

    for(j = 1; j < nel; ++j){
      Nbmodes   = U->flist[j]->Nbmodes;
      asize     = Nbmodes*eDIM+1;

      dzero (asize,wk,1);
      dgathr(eDIM*Nbmodes,  tmp, bmap[j],  wk);
      dvmul (eDIM*Nbmodes, sc, 1, wk, 1, wk, 1);

      b     = B->Gmat->a[U->flist[j]->geom->id] + asize*(asize-1)/2;
      p[j] += ddot(asize-1,b,1,wk,1);
      sc   += asize;
    }

    /* solve for p */
    dpptrs('L', nel, 1, B->Pmat->info.diagst.binvcb,p,nel,info);

    /* generate initial vector as tmp = B p */
    sc = B->signchange;
    dzero(B->nglobal,tmp,1);
    /* start from 1 due to  singular pressure  system */
    for(k = 1; k < nel; ++k){
      Nbmodes = U->flist[k]->Nbmodes;
      asize   = Nbmodes*eDIM+1;
      b       = B->Gmat->a[U->flist[k]->geom->id] + asize*(asize-1)/2;

      dsmul(asize-1,p[k],b,1,wk,1);

      for(i = 0; i < eDIM*Nbmodes; ++i)
  tmp[bmap[k][i]] += sc[i]*wk[i];

      sc += asize;
    }

    /* set z = r - tmp */
    dvsub(B->nsolve-nel,r,1,tmp,1,z,1);
    /* u = invc*z */
    dvmul(B->nsolve-nel,B->Pmat->info.diagst.idiag,1,z,1,z,1);

    free(tmp); free(wk);
  }
    break;
  case Pre_Block_Stokes:{
    register int i,j,k;
    double  *tmp = dvector(0,B->nglobal-1),*sc,*b,*p,*wk;
    int   eDIM = U->fhead->dim(),cnt,l;
    int **bmap = B->bmap;
    int   nel = B->nel,asize,Nbmodes,info;
    int   nedge = B->Pmat->info.blockst.nedge;

    if(eDIM == 2)
      wk = dvector(0,eDIM*4*LGmax);
    else
      wk = dvector(0,eDIM*6*LGmax*LGmax);

    dzero(B->nglobal,tmp,1);
    dcopy(B->nsolve-nel,r,1,tmp,1);

    /* multiply by invc */
#ifdef BVERT
    dpptrs('U',B->Pmat->info.blockst.nvert,1,B->Pmat->info.blockst.ivert,
    tmp,B->Pmat->info.blockst.nvert,info);
#else
    dvmul(B->Pmat->info.blockst.nvert,B->Pmat->info.blockst.ivert,1,
    tmp,1,tmp,1);
#endif

    cnt = B->Pmat->info.blockst.nvert;

    for(i = 0; i < nedge; ++i){
      l = B->Pmat->info.blockst.Ledge[i];
      dpptrs('U',l,1,B->Pmat->info.blockst.iedge[i],tmp+cnt,l,info);
      cnt += l;
    }

    /* multiply by b^T */
    sc = B->signchange;
    p  = z + B->nsolve-nel;
    dcopy(nel,r+B->nsolve-nel,1,p,1);
    dneg(nel-1,p+1,1);
    if(!(B->singular))
      error_msg(issue in setting singular modes in Stokes_Precon not resolved);
    /* start at 1 to omit singular pressure point */
    for(j = 1; j < nel; ++j){
      Nbmodes   = U->flist[j]->Nbmodes;
      asize     = Nbmodes*eDIM+1;

      dzero (asize,wk,1);
      dgathr(eDIM*Nbmodes,  tmp, bmap[j],  wk);
      dvmul (eDIM*Nbmodes, sc, 1, wk, 1, wk, 1);

      b     = B->Gmat->a[U->flist[j]->geom->id] + asize*(asize-1)/2;
      p[j] += ddot(asize-1,b,1,wk,1);
      sc   += asize;
    }

    /* solve for p */
    dpptrs('L', nel, 1, B->Pmat->info.blockst.binvcb,p,nel,info);

    /* generate initial vector as tmp = B p */
    sc = B->signchange;
    dzero(B->nglobal,tmp,1);
    /* start from 1 due to  singular pressure  system */
    for(k = 1; k < nel; ++k){
      Nbmodes = U->flist[k]->Nbmodes;
      asize   = Nbmodes*eDIM+1;
      b       = B->Gmat->a[U->flist[k]->geom->id] + asize*(asize-1)/2;

      dsmul(asize-1,p[k],b,1,wk,1);

      for(i = 0; i < eDIM*Nbmodes; ++i)
  tmp[bmap[k][i]] += sc[i]*wk[i];

      sc += asize;
    }

    /* set z = r - tmp */
    dvsub(B->nsolve-nel,r,1,tmp,1,z,1);

    /* u = invc*z */
#ifdef BVERT
    dpptrs('U',B->Pmat->info.blockst.nvert,1,B->Pmat->info.blockst.ivert,
    z,B->Pmat->info.blockst.nvert,info);
#else
    dvmul(B->Pmat->info.blockst.nvert,B->Pmat->info.blockst.ivert,1,z,1,z,1);
#endif
    cnt = B->Pmat->info.blockst.nvert;

    for(i = 0; i < nedge; ++i){
      l = B->Pmat->info.blockst.Ledge[i];
      dpptrs('U',l,1,B->Pmat->info.blockst.iedge[i],z+cnt,l,info);
      cnt += l;
    }

    free(tmp); free(wk);
  }
    break;
  default:
    fprintf(stderr,"Preconditioner (Precon=%d) not known\n",B->Precon);
    exit(-1);
  }
}