示例#1
0
/* Scatter the points from u to U using the map in B->bmap */
static void ScatrBndry_Stokes(double *u, Element_List **V, Bsystem **B)
{
	register int j,k;
	int      eDIM = V[0]->flist[0]->dim();
	int      nel = B[0]->nel, Nbmodes, *bmap;
	double  *hj;
	double  *sc = B[0]->signchange;

	for(k = 0; k < nel; ++k)
	{
		bmap    = B[eDIM]->bmap[k];

		Nbmodes = V[0]->flist[k]->Nbmodes;

		for(j = 0; j < eDIM; ++j)
		{
			hj = V[j]->flist[k]->vert->hj;
			dgathr(Nbmodes,  u, bmap + j*Nbmodes, hj);
			dvmul (Nbmodes, sc, 1, hj, 1, hj,1);
		}

		V[eDIM]->flist[k]->vert[0].hj[0] = u[bmap[eDIM*Nbmodes]];

		sc += Nbmodes;
	}
}
示例#2
0
void A_Stokes(Element_List **V, Bsystem **B, double *p, double *w, double **wk)
{

	int      eDIM = V[0]->flist[0]->dim();
	int      nel = B[0]->nel, Nbmodes;
	double   **a = B[eDIM]->Gmat->a;
	int      **bmap = B[eDIM]->bmap;
	double   *sc = B[0]->signchange;
	register int i,j,k;

	dzero(B[eDIM]->nsolve,w,1);

	for(k = 0; k < nel; ++k)
	{
		Nbmodes = V[0]->flist[k]->Nbmodes;

		/* Put p boundary modes into wk[0] and impose continuity */
		dgathr(eDIM*Nbmodes+1,  p, bmap[k], wk[0]);
		for(j = 0; j < eDIM; ++j)
			dvmul (Nbmodes, sc, 1, wk[0] + j*Nbmodes, 1, wk[0] + j*Nbmodes,1);

		dspmv('U',eDIM*Nbmodes+1,1.0,a[V[0]->flist[k]->geom->id],
		      wk[0],1,0.0,wk[1],1);

		/* do sign change back and put into w */
		for(j = 0; j < eDIM; ++j)
			for(i = 0; i < Nbmodes; ++i)
				w[bmap[k][i+j*Nbmodes]] += sc[i]*wk[1][i+j*Nbmodes];
		w[bmap[k][eDIM*Nbmodes]] += wk[1][eDIM*Nbmodes];

		sc += Nbmodes;
	}

	/* set first pressure constant to zero */
	if(B[eDIM]->singular)
		w[eDIM*B[0]->nsolve] = 0.0;
}
示例#3
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);
  }
}
示例#4
0
static void divergence_free_init(Element_List **V, double *u0, double *r,
         Bsystem **B, double **wk){
  register int i,j,k,cnt;
  int      eDIM = V[0]->fhead->dim();
  int      asize,info,Nbmodes;
  int      **bmap  = B[eDIM]->bmap;
  int      nel     = B[eDIM]->nel;
  int      nglobal = B[eDIM]->nglobal;
  int      nsolve  = B[eDIM]->nsolve;
  int      vsolve  = B[0]->nsolve;
  double   **a  = B[eDIM]->Gmat->a,*x,*b,*sc,*sc1;
  static double *invb;

  x = dvector(0,nel-1);

  /* form and invert B' B system */
  if(!invb){
    invb = dvector(0,nel*(nel+1)/2-1);

    sc = B[0]->signchange;
    for(cnt = 0,k = 0; k < nel; ++k){
      /* gather B from local systems */
      Nbmodes = V[0]->flist[k]->Nbmodes;
      asize   = Nbmodes*eDIM+1;
      b       = a[V[0]->flist[k]->geom->id] + asize*(asize-1)/2;

      dzero(nglobal,u0,1);
      for(j = 0; j < eDIM; ++j){
  for(i = 0; i < Nbmodes; ++i)
    u0[bmap[k][i+j*Nbmodes]] += sc[i]*b[i+j*Nbmodes];
      }
      dzero(nglobal-nsolve,u0+nsolve,1);

      /* take inner product with B' */
      sc1 = B[0]->signchange;
      for(j = k; j < nel; ++j,cnt++){
  dzero(asize,wk[0],1);
  dgathr(asize-1,  u0, bmap[j],  wk[0]);
  for(i = 0; i < eDIM; ++i)
    dvmul (Nbmodes, sc1, 1, wk[0]+i*Nbmodes, 1, wk[0]+i*Nbmodes, 1);

  Nbmodes   = V[0]->flist[j]->Nbmodes;
  asize     = Nbmodes*eDIM+1;
  b         = a[V[0]->flist[j]->geom->id] + asize*(asize-1)/2;
  invb[cnt] = ddot(asize-1,b,1,wk[0],1);
  sc1      += Nbmodes;
      }
      sc += V[0]->flist[k]->Nbmodes;
    }
    /* take out first row to deal with singularity  */
    if(B[eDIM]->singular)
      dzero(nel,invb,1);  invb[0] = 1.0;

    dpptrf('L', nel, invb, info);
  }

  /* solve B' B x = r */
  dcopy (nel,r+eDIM*vsolve,1,x,1);
  dpptrs('L', nel, 1, invb, x, nel, info);

  dzero(B[eDIM]->nglobal,u0,1);

  /* generate initial vector as u0 = B x */
  sc = B[0]->signchange;
  for(k = 0; k < nel; ++k){
    Nbmodes = V[0]->flist[k]->Nbmodes;
    asize   = Nbmodes*eDIM+1;
    b       = a[V[0]->flist[k]->geom->id] + asize*(asize-1)/2;

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

    for(j = 0; j < eDIM; ++j){
      for(i = 0; i < Nbmodes; ++i)
  u0[bmap[k][i+j*Nbmodes]] += sc[i]*wk[0][i+j*Nbmodes];
    }
    sc += Nbmodes;
  }

  dzero(nglobal-eDIM*vsolve, u0 + eDIM*vsolve, 1);

  /* subtract off a*u0 from r */
  sc      = B[0]->signchange;
  for(k = 0; k < nel; ++k){
    Nbmodes = V[0]->flist[k]->Nbmodes;

    dzero(eDIM*Nbmodes+1,wk[0],1);
    dgathr(eDIM*Nbmodes+1, u0, bmap[k], wk[0]);
    for(j = 0; j < eDIM; ++j)
      dvmul (Nbmodes, sc, 1, wk[0] + j*Nbmodes, 1, wk[0] + j*Nbmodes,1);

    dspmv('U',eDIM*Nbmodes+1,1.0,a[V[0]->flist[k]->geom->id],
    wk[0],1,0.0,wk[1],1);

    for(j = 0; j < eDIM; ++j)
      for(i = 0; i < Nbmodes; ++i)
  r[bmap[k][i+j*Nbmodes]] -= sc[i]*wk[1][i+j*Nbmodes];
    r[bmap[k][eDIM*Nbmodes]] -= wk[1][eDIM*Nbmodes];

    sc += Nbmodes;
  }

  r[eDIM*vsolve] = 0.0;
  dzero(nglobal-nsolve, r + nsolve, 1);

  free(x);
}