Example #1
0
PetscErrorCode FillExact(Vec uexact, unfemCtx *ctx) {
    PetscErrorCode ierr;
    const Node   *aloc;
    double       *auexact;
    int          i;
    ierr = UMGetNodeCoordArrayRead(ctx->mesh,&aloc); CHKERRQ(ierr);
    ierr = VecGetArray(uexact,&auexact); CHKERRQ(ierr);
    for (i = 0; i < ctx->mesh->N; i++) {
        auexact[i] = ctx->uexact_fcn(aloc[i].x,aloc[i].y);
    }
    ierr = VecRestoreArray(uexact,&auexact); CHKERRQ(ierr);
    ierr = UMRestoreNodeCoordArrayRead(ctx->mesh,&aloc); CHKERRQ(ierr);
    return 0;
}
Example #2
0
PetscErrorCode UMStats(UM *mesh, double *maxh, double *meanh, double *maxa, double *meana) {
    PetscErrorCode ierr;
    const int   *ae;
    const Node  *aloc;
    int         k;
    double      x[3], y[3], ax, ay, bx, by, cx, cy, h, a,
                Maxh = 0.0, Maxa = 0.0, Sumh = 0.0, Suma = 0.0;
    if ((mesh->K == 0) || (mesh->e == NULL)) {
        SETERRQ(PETSC_COMM_WORLD,1,
                "number of elements unknown; call UMReadElements() first\n");
    }
    if (mesh->N == 0) {
        SETERRQ(PETSC_COMM_WORLD,2,
                "node size unknown so element check impossible; call UMReadNodes() first\n");
    }
    ierr = UMGetNodeCoordArrayRead(mesh,&aloc); CHKERRQ(ierr);
    ierr = ISGetIndices(mesh->e,&ae); CHKERRQ(ierr);
    for (k = 0; k < mesh->K; k++) {
        x[0] = aloc[ae[3*k]].x;
        y[0] = aloc[ae[3*k]].y;
        x[1] = aloc[ae[3*k+1]].x;
        y[1] = aloc[ae[3*k+1]].y;
        x[2] = aloc[ae[3*k+2]].x;
        y[2] = aloc[ae[3*k+2]].y;
        ax = x[1] - x[0];
        ay = y[1] - y[0];
        bx = x[2] - x[0];
        by = y[2] - y[0];
        cx = x[1] - x[2];
        cy = y[1] - y[2];
        h = PetscMax(ax*ax+ay*ay, PetscMax(bx*bx+by*by, cx*cx+cy*cy));
        h = sqrt(h);
        a = 0.5 * PetscAbs(ax*by-ay*bx);
        Maxh = PetscMax(Maxh,h);
        Sumh += h;
        Maxa = PetscMax(Maxa,a);
        Suma += a;
    }
    ierr = ISRestoreIndices(mesh->e,&ae); CHKERRQ(ierr);
    ierr = UMRestoreNodeCoordArrayRead(mesh,&aloc); CHKERRQ(ierr);
    if (maxh)  *maxh = Maxh;
    if (maxa)  *maxa = Maxa;
    if (meanh)  *meanh = Sumh / mesh->K;
    if (meana)  *meana = Suma / mesh->K;
    return 0;
}
Example #3
0
//STARTBDRYRESIDUALS
PetscErrorCode FormFunction(SNES snes, Vec u, Vec F, void *ctx) {
    PetscErrorCode ierr;
    unfemCtx     *user = (unfemCtx*)ctx;
    const int    *abfn, *ae, *as, *abfs, *en, deg = user->quaddeg - 1;
    const Node   *aloc;
    const double *au;
    double       *aF, unode[3], gradu[2], gradpsi[3][2], uquad[4], aquad[4],
                 fquad[4], dx, dy, dx1, dx2, dy1, dy2, detJ,
                 ls, xmid, ymid, sint, xx, yy, sum;
    int          n, p, na, nb, k, l, q;

    PetscLogStagePush(user->resstage);  //STRIP
    ierr = VecGetArrayRead(u,&au); CHKERRQ(ierr);
    ierr = VecSet(F,0.0); CHKERRQ(ierr);
    ierr = VecGetArray(F,&aF); CHKERRQ(ierr);
    ierr = UMGetNodeCoordArrayRead(user->mesh,&aloc); CHKERRQ(ierr);

    // Dirichlet node residuals
    ierr = ISGetIndices(user->mesh->bfn,&abfn); CHKERRQ(ierr);
    for (n = 0; n < user->mesh->N; n++) {
        if (abfn[n] == 2)  // node is Dirichlet
            aF[n] = au[n] - user->gD_fcn(aloc[n].x,aloc[n].y);
    }

    // Neumann segment contributions
    ierr = ISGetIndices(user->mesh->s,&as); CHKERRQ(ierr);
    ierr = ISGetIndices(user->mesh->bfs,&abfs); CHKERRQ(ierr);
    for (p = 0; p < user->mesh->P; p++) {
        if (abfs[p] == 1) {  // segment is Neumann
            na = as[2*p+0];  // nodes at end of segment
            nb = as[2*p+1];
            // length of segment
            dx = aloc[na].x-aloc[nb].x;
            dy = aloc[na].y-aloc[nb].y;
            ls = sqrt(dx * dx + dy * dy);
            // midpoint rule; psi_na=psi_nb=0.5 at midpoint of segment
            xmid = 0.5*(aloc[na].x+aloc[nb].x);
            ymid = 0.5*(aloc[na].y+aloc[nb].y);
            sint = 0.5 * user->gN_fcn(xmid,ymid) * ls;
            // nodes at end of segment could be Dirichlet
            if (abfn[na] != 2)
                aF[na] -= sint;
            if (abfn[nb] != 2)
                aF[nb] -= sint;
        }
    }
    ierr = ISRestoreIndices(user->mesh->s,&as); CHKERRQ(ierr);
    ierr = ISRestoreIndices(user->mesh->bfs,&abfs); CHKERRQ(ierr);
//ENDBDRYRESIDUALS

//STARTELEMENTRESIDUALS
    // element contributions
    ierr = ISGetIndices(user->mesh->e,&ae); CHKERRQ(ierr);
    for (k = 0; k < user->mesh->K; k++) {
        en = ae + 3*k;  // en[0], en[1], en[2] are nodes of element k
        // geometry of element
        dx1 = aloc[en[1]].x - aloc[en[0]].x;
        dx2 = aloc[en[2]].x - aloc[en[0]].x;
        dy1 = aloc[en[1]].y - aloc[en[0]].y;
        dy2 = aloc[en[2]].y - aloc[en[0]].y;
        detJ = dx1 * dy2 - dx2 * dy1;
        // gradients of hat functions
        for (l = 0; l < 3; l++) {
            gradpsi[l][0] = ( dy2 * dchi[l][0] - dy1 * dchi[l][1]) / detJ;
            gradpsi[l][1] = (-dx2 * dchi[l][0] + dx1 * dchi[l][1]) / detJ;
        }
        // u and grad u on element
        gradu[0] = 0.0;
        gradu[1] = 0.0;
        for (l = 0; l < 3; l++) {
            if (abfn[en[l]] == 2)
                unode[l] = user->gD_fcn(aloc[en[l]].x,aloc[en[l]].y);
            else
                unode[l] = au[en[l]];
            gradu[0] += unode[l] * gradpsi[l][0];
            gradu[1] += unode[l] * gradpsi[l][1];
        }
        // function values at quadrature points on element
        for (q = 0; q < Q[deg]; q++) {
            uquad[q] = eval(unode,xi[deg][q],eta[deg][q]);
            xx = aloc[en[0]].x + dx1 * xi[deg][q] + dx2 * eta[deg][q];
            yy = aloc[en[0]].y + dy1 * xi[deg][q] + dy2 * eta[deg][q];
            aquad[q] = user->a_fcn(uquad[q],xx,yy);
            fquad[q] = user->f_fcn(uquad[q],xx,yy);
        }
        // residual contribution for each node of element
        for (l = 0; l < 3; l++) {
            if (abfn[en[l]] < 2) { // if NOT a Dirichlet node
                sum = 0.0;
                for (q = 0; q < Q[deg]; q++)
                    sum += w[deg][q]
                             * ( aquad[q] * InnerProd(gradu,gradpsi[l])
                                 - fquad[q] * chi(l,xi[deg][q],eta[deg][q]) );
                aF[en[l]] += fabs(detJ) * sum;
            }
        }
    }

    ierr = ISRestoreIndices(user->mesh->e,&ae); CHKERRQ(ierr);
    ierr = ISRestoreIndices(user->mesh->bfn,&abfn); CHKERRQ(ierr);
    ierr = UMRestoreNodeCoordArrayRead(user->mesh,&aloc); CHKERRQ(ierr);
    ierr = VecRestoreArrayRead(u,&au); CHKERRQ(ierr);
    ierr = VecRestoreArray(F,&aF); CHKERRQ(ierr);
    PetscLogStagePop();  //STRIP
    return 0;
}
Example #4
0
PetscErrorCode FormPicard(SNES snes, Vec u, Mat A, Mat P, void *ctx) {
    PetscErrorCode ierr;
    unfemCtx     *user = (unfemCtx*)ctx;
    const int    *abfn, *ae, *en, deg = user->quaddeg - 1;
    const Node   *aloc;
    const double *au;
    double       unode[3], gradpsi[3][2],
                 uquad[4], aquad[4], v[9],
                 dx1, dx2, dy1, dy2, detJ, xx, yy, sum;
    int          n, k, l, m, q, cr, cv, row[3];

    PetscLogStagePush(user->jacstage);  //STRIP
    ierr = MatZeroEntries(P); CHKERRQ(ierr);
    ierr = ISGetIndices(user->mesh->bfn,&abfn); CHKERRQ(ierr);
    for (n = 0; n < user->mesh->N; n++) {
        if (abfn[n] == 2) {
            v[0] = 1.0;
            ierr = MatSetValues(P,1,&n,1,&n,v,ADD_VALUES); CHKERRQ(ierr);
        }
    }
    ierr = ISGetIndices(user->mesh->e,&ae); CHKERRQ(ierr);
    ierr = VecGetArrayRead(u,&au); CHKERRQ(ierr);
    ierr = UMGetNodeCoordArrayRead(user->mesh,&aloc); CHKERRQ(ierr);
    for (k = 0; k < user->mesh->K; k++) {
        en = ae + 3*k;  // en[0], en[1], en[2] are nodes of element k
        // geometry of element
        dx1 = aloc[en[1]].x - aloc[en[0]].x;
        dx2 = aloc[en[2]].x - aloc[en[0]].x;
        dy1 = aloc[en[1]].y - aloc[en[0]].y;
        dy2 = aloc[en[2]].y - aloc[en[0]].y;
        detJ = dx1 * dy2 - dx2 * dy1;
        // gradients of hat functions and u on element
        for (l = 0; l < 3; l++) {
            gradpsi[l][0] = ( dy2 * dchi[l][0] - dy1 * dchi[l][1]) / detJ;
            gradpsi[l][1] = (-dx2 * dchi[l][0] + dx1 * dchi[l][1]) / detJ;
            if (abfn[en[l]] == 2)
                unode[l] = user->gD_fcn(aloc[en[l]].x,aloc[en[l]].y);
            else
                unode[l] = au[en[l]];
        }
        // function values at quadrature points on element
        for (q = 0; q < Q[deg]; q++) {
            uquad[q] = eval(unode,xi[deg][q],eta[deg][q]);
            xx = aloc[en[0]].x + dx1 * xi[deg][q] + dx2 * eta[deg][q];
            yy = aloc[en[0]].y + dy1 * xi[deg][q] + dy2 * eta[deg][q];
            aquad[q] = user->a_fcn(uquad[q],xx,yy);
        }
        // generate 3x3 element stiffness matrix
        cr = 0; // count rows
        cv = 0; // count values
        for (l = 0; l < 3; l++) {
            if (abfn[en[l]] != 2) {
                row[cr] = en[l];
                cr++;
                for (m = 0; m < 3; m++) {
                    if (abfn[en[m]] != 2) {
                        sum = 0.0;
                        for (q = 0; q < Q[deg]; q++) {
                            sum += w[deg][q] * aquad[q]
                                       * InnerProd(gradpsi[l],gradpsi[m]);
                        }
                        v[cv] = fabs(detJ) * sum;
                        cv++;
                    }
                }
            }
        }
        // insert element stiffness matrix
        ierr = MatSetValues(P,cr,row,cr,row,v,ADD_VALUES); CHKERRQ(ierr);
    }
    ierr = ISRestoreIndices(user->mesh->e,&ae); CHKERRQ(ierr);
    ierr = ISRestoreIndices(user->mesh->bfn,&abfn); CHKERRQ(ierr);
    ierr = VecRestoreArrayRead(u,&au); CHKERRQ(ierr);
    ierr = UMRestoreNodeCoordArrayRead(user->mesh,&aloc); CHKERRQ(ierr);

    ierr = MatAssemblyBegin(P,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
    ierr = MatAssemblyEnd(P,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
    if (A != P) {
        ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
        ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
    }
    ierr = MatSetOption(P,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_TRUE); CHKERRQ(ierr);
    PetscLogStagePop();  //STRIP
    return 0;
}