/*
 * Jacobi smoother.
 *
 *   Implement using phgMatvec
 *   ref: phgSolverJacobi, solver-phg.c
 * */
void 
mg_Jacobi(MAT *A, VEC *x, VEC *b, int nsmooth, void *ctx)
{
    VEC *r;
    INT i, k; 
    FLOAT dx, omega = _p->smooth_damp;

    if (A->diag == NULL)
	phgMatSetupDiagonal(A);

    r = phgMapCreateVec(b->map, 1);
    for (k = 0; k < nsmooth; k++) {
	phgVecCopy(b, &r);
	phgMatVec(MAT_OP_N, -1.0, A, x, 1.0, &r);
	for (i = 0; i < A->cmap->nlocal; i++) {
	    assert(fabs(A->diag[i]) > 1e-12);
	    dx = r->data[i] / A->diag[i]; 
	    x->data[i] += omega * dx;
	}
    }
    phgVecDestroy(&r);
    
    return;
}
示例#2
0
static void
build_matrices(MAT *matA, MAT *matM, MAT *matC, MAT *S, FLOAT s,
		DOF *u_h, DOF *p_h)
/* S is used to store s*diag(M(p_h))^(-1) */
{
    int N = u_h->type->nbas;	/* number of basis functions in an element */
    int M = p_h->type->nbas;
    int i, j;
    GRID *g = u_h->g;
    ELEMENT *e;
    FLOAT A[N][N], B[N][N], C[N][M];
    INT I[N], Ip[M];
    INT k, n0;
    VEC *V = phgMapCreateVec(S->rmap, 1);

    phgVecDisassemble(V);	/* for phgVecAddEntry */
    ForAllElements(g, e) {
	for (i = 0; i < N; i++) {
	    I[i] = phgMapE2L(matA->rmap, 0, e, i);
	    for (k = 0; k < M; k++) {
		/* \int \grad\psi_k\cdot\phi_i */
		C[i][k] = phgQuadGradBasDotBas(e, p_h, k, u_h, i, QUAD_DEFAULT);
	    }
	    for (j = 0; j <= i; j++) {
		/* \int \phi_i\cdot\phi_j */
		B[j][i] = B[i][j] = 
		    phgQuadBasDotBas(e, u_h, j, u_h, i, QUAD_DEFAULT);
		/* \int \curl\phi_i\cdot\curl\phi_j */
		A[j][i] = A[i][j] =
		    phgQuadCurlBasDotCurlBas(e, u_h, j, u_h, i, QUAD_DEFAULT);
	    }
	}

	for (i = 0; i < M; i++) {
	    Ip[i] = phgMapE2L(matC->cmap, 0, e, i);
	    if (Ip[i] < 0)	/* boundary entry */
		continue;
	    phgVecAddEntry(V, 0, Ip[i],
			phgQuadBasDotBas(e, p_h, i, p_h, i, QUAD_DEFAULT));
	}

	/* loop on basis functions */
	for (i = 0; i < N; i++) {
	    if (phgDofDirichletBC(u_h, e, i, NULL, NULL, NULL, DOF_PROJ_CROSS))
		continue;
	    phgMatAddEntries(matA, 1, I + i, N, I, A[i]); 
	    phgMatAddEntries(matM, 1, I + i, N, I, B[i]); 
	    phgMatAddEntries(matC, 1, I + i, M, Ip, C[i]); 
	}
    }

    phgVecAssemble(V);
    n0 = V->map->partition[V->map->rank];
    for (k = 0; k < V->map->nlocal; k++)
	phgMatAddGlobalEntry(S, k + n0, k + n0, s / V->data[k]);
    phgVecDestroy(&V);
    phgMatAssemble(S);
    phgMatSetupDiagonal(S);
    phgMatAssemble(matA);
    phgMatAssemble(matM);
    phgMatAssemble(matC);
}