PetscErrorCode FormFunctionLocal(DMDALocalInfo *info, PetscReal **u, PetscReal **F, Ctx *usr) { PetscInt i, j; const PetscReal e = usr->eps; PetscReal x, y, uu, uxx, uyy, Wux, Wuy; Wind W; Spacings s; getSpacings(info,&s); for (j=info->ys; j<info->ys+info->ym; j++) { y = -1.0 + j * s.hy; for (i=info->xs; i<info->xs+info->xm; i++) { x = -1.0 + i * s.hx; if (i == info->mx-1) { F[j][i] = u[j][i] - 1.0; } else if (i == 0 || j == 0 || j == info->my-1) { F[j][i] = u[j][i]; } else { uu = u[j][i]; uxx = (u[j][i-1] - 2.0 * uu + u[j][i+1]) / s.hx2; uyy = (u[j-1][i] - 2.0 * uu + u[j+1][i]) / s.hy2; W = getWind(x,y); Wux = W.x * (u[j][i+1] - u[j][i-1]) / (2.0 * s.hx); Wuy = W.y * (u[j+1][i] - u[j-1][i]) / (2.0 * s.hy); F[j][i] = - e * (uxx + uyy) + Wux + Wuy; } } } return 0; }
PetscErrorCode FormJacobianLocal(DMDALocalInfo *info, PetscScalar ***u, Mat J, Mat Jpre, Ctx *usr) { PetscErrorCode ierr; PetscInt i,j,q; PetscReal v[5],diag,x,y; const PetscReal e = usr->eps; MatStencil col[5],row; Spacings s; Wind W; getSpacings(info,&s); diag = e * 2.0 * (1.0/s.hx2 + 1.0/s.hy2); for (j=info->ys; j<info->ys+info->ym; j++) { y = -1.0 + j * s.hy; row.j = j; col[0].j = j; for (i=info->xs; i<info->xs+info->xm; i++) { x = -1.0 + i * s.hx; row.i = i; col[0].i = i; q = 1; if (i == 0 || j == 0 || i == info->mx-1 || j == info->my-1) { v[0] = 1.0; } else { W = getWind(x,y); v[0] = diag; if (i-1 != 0) { v[q] = - e / s.hx2 - W.x / (2.0 * s.hx); col[q].j = j; col[q].i = i-1; q++; } if (i+1 != info->mx-1) { v[q] = - e / s.hx2 + W.x / (2.0 * s.hx); col[q].j = j; col[q].i = i+1; q++; } if (j-1 != 0) { v[q] = - e / s.hy2 - W.y / (2.0 * s.hy); col[q].j = j-1; col[q].i = i; q++; } if (j+1 != info->my-1) { v[q] = - e / s.hy2 + W.y / (2.0 * s.hy); col[q].j = j+1; col[q].i = i; q++; } } ierr = MatSetValuesStencil(Jpre,1,&row,q,col,v,INSERT_VALUES); CHKERRQ(ierr); } } ierr = MatAssemblyBegin(Jpre,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = MatAssemblyEnd(Jpre,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); if (J != Jpre) { ierr = MatAssemblyBegin(J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = MatAssemblyEnd(J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); } return 0; }
//STARTFUNCTION PetscErrorCode FormFunctionLocal(DMDALocalInfo *info, double ***u, double ***F, Ctx *usr) { PetscErrorCode ierr; int i, j, k; const double e = usr->eps; double x, y, z, uu, uxx, uyy, uzz, Wux, Wuy, Wuz, ***af, ***ag; Wind W; Spacings s; getSpacings(info,&s); ierr = DMDAVecGetArray(usr->da, usr->f, &af); CHKERRQ(ierr); ierr = DMDAVecGetArray(usr->da, usr->g, &ag); CHKERRQ(ierr); for (k=info->zs; k<info->zs+info->zm; k++) { z = -1.0 + k * s.hz; for (j=info->ys; j<info->ys+info->ym; j++) { y = -1.0 + j * s.hy; for (i=info->xs; i<info->xs+info->xm; i++) { x = -1.0 + i * s.hx; if (i == info->mx-1) { F[k][j][i] = u[k][j][i] - ag[k][j][i]; } else if (i == 0 || j == 0 || j == info->my-1) { F[k][j][i] = u[k][j][i]; } else { uu = u[k][j][i]; uxx = (u[k][j][i-1] - 2.0 * uu + u[k][j][i+1]) / s.hx2; uyy = (u[k][j-1][i] - 2.0 * uu + u[k][j+1][i]) / s.hy2; uzz = (u[k-1][j][i] - 2.0 * uu + u[k+1][j][i]) / s.hz2; W = getWind(x,y,z); if (usr->upwind) { Wux = (W.x > 0) ? uu - u[k][j][i-1] : u[k][j][i+1] - uu; Wux *= W.x / s.hx; Wuy = (W.y > 0) ? uu - u[k][j-1][i] : u[k][j+1][i] - uu; Wuy *= W.y / s.hy; Wuz = (W.z > 0) ? uu - u[k-1][j][i] : u[k+1][j][i] - uu; Wuz *= W.z / s.hz; } else { Wux = W.x * (u[k][j][i+1] - u[k][j][i-1]) / (2.0*s.hx); Wuy = W.y * (u[k][j+1][i] - u[k][j-1][i]) / (2.0*s.hy); Wuz = W.z * (u[k+1][j][i] - u[k-1][j][i]) / (2.0*s.hz); } F[k][j][i] = - e * (uxx + uyy + uzz) + Wux + Wuy + Wuz - af[k][j][i]; } } } } ierr = DMDAVecRestoreArray(usr->da, usr->f, &af); CHKERRQ(ierr); ierr = DMDAVecRestoreArray(usr->da, usr->g, &ag); CHKERRQ(ierr); return 0; }
PetscErrorCode formUexFG(DMDALocalInfo *info, Ctx *usr, Vec uex) { PetscErrorCode ierr; int i, j, k; Spacings s; const double E = PETSC_PI / 2.0, F = 2.0 * PETSC_PI, lam2 = E*E + F*F; // lambda = sqrt(17.0) * PETSC_PI / 2.0 double x, y, z, QQ, UU, ***auex, ***af, ***ag; getSpacings(info,&s); ierr = DMDAVecGetArray(usr->da, uex, &auex); CHKERRQ(ierr); ierr = DMDAVecGetArray(usr->da, usr->f, &af); CHKERRQ(ierr); ierr = DMDAVecGetArray(usr->da, usr->g, &ag); CHKERRQ(ierr); for (k=info->zs; k<info->zs+info->zm; k++) { z = -1.0 + k * s.hz; for (j=info->ys; j<info->ys+info->ym; j++) { y = -1.0 + j * s.hy; QQ = sin(E*(y+1.0)) * sin(F*(z+1.0)); for (i=info->xs; i<info->xs+info->xm; i++) { x = -1.0 + i * s.hx; UU = exp((x+1)/usr->eps) - 1.0; UU /= exp(2.0/usr->eps) - 1.0; auex[k][j][i] = UU * QQ; af[k][j][i] = usr->eps * lam2 * auex[k][j][i]; if (i == info->mx-1) ag[k][j][i] = QQ; else ag[k][j][i] = 0.0; } } } ierr = DMDAVecRestoreArray(usr->da, uex, &auex); CHKERRQ(ierr); ierr = DMDAVecRestoreArray(usr->da, usr->f, &af); CHKERRQ(ierr); ierr = DMDAVecRestoreArray(usr->da, usr->g, &ag); CHKERRQ(ierr); return 0; }
PetscErrorCode FormJacobianLocal(DMDALocalInfo *info, PetscScalar ***u, Mat J, Mat Jpre, Ctx *usr) { PetscErrorCode ierr; int i,j,k,q; double v[7],diag,x,y,z; const double e = usr->eps; MatStencil col[7],row; Spacings s; Wind W; getSpacings(info,&s); diag = e * 2.0 * (1.0/s.hx2 + 1.0/s.hy2 + 1.0/s.hz2); for (k=info->zs; k<info->zs+info->zm; k++) { z = -1.0 + k * s.hz; row.k = k; col[0].k = k; for (j=info->ys; j<info->ys+info->ym; j++) { y = -1.0 + j * s.hy; row.j = j; col[0].j = j; for (i=info->xs; i<info->xs+info->xm; i++) { x = -1.0 + i * s.hx; row.i = i; col[0].i = i; if (i == 0 || j == 0 || i == info->mx-1 || j == info->my-1) { v[0] = 1.0; q = 1; } else { W = getWind(x,y,z); v[0] = diag; if (usr->upwind) { v[0] += (W.x / s.hx) * ((W.x > 0.0) ? 1.0 : -1.0); v[0] += (W.y / s.hy) * ((W.y > 0.0) ? 1.0 : -1.0); v[0] += (W.z / s.hz) * ((W.z > 0.0) ? 1.0 : -1.0); } v[1] = - e / s.hz2; if (usr->upwind) { if (W.z > 0.0) v[q] -= W.z / s.hz; } else v[q] -= W.z / (2.0 * s.hz); col[1].k = k-1; col[1].j = j; col[1].i = i; v[2] = - e / s.hz2; if (usr->upwind) { if (W.z <= 0.0) v[q] += W.z / s.hz; } else v[q] += W.z / (2.0 * s.hz); col[2].k = k+1; col[2].j = j; col[2].i = i; q = 3; if (i-1 != 0) { v[q] = - e / s.hx2; if (usr->upwind) { if (W.x > 0.0) v[q] -= W.x / s.hx; } else v[q] -= W.x / (2.0 * s.hx); col[q].k = k; col[q].j = j; col[q].i = i-1; q++; } if (i+1 != info->mx-1) { v[q] = - e / s.hx2; if (usr->upwind) { if (W.x <= 0.0) v[q] += W.x / s.hx; } else v[q] += W.x / (2.0 * s.hx); col[q].k = k; col[q].j = j; col[q].i = i+1; q++; } if (j-1 != 0) { v[q] = - e / s.hy2; if (usr->upwind) { if (W.y > 0.0) v[q] -= W.y / s.hy; } else v[q] -= W.y / (2.0 * s.hy); col[q].k = k; col[q].j = j-1; col[q].i = i; q++; } if (j+1 != info->my-1) { v[q] = - e / s.hy2; if (usr->upwind) { if (W.y <= 0.0) v[q] += W.y / s.hy; } else v[q] += W.y / (2.0 * s.hy); col[q].k = k; col[q].j = j+1; col[q].i = i; q++; } } ierr = MatSetValuesStencil(Jpre,1,&row,q,col,v,INSERT_VALUES); CHKERRQ(ierr); } } } ierr = MatAssemblyBegin(Jpre,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr); ierr = MatAssemblyEnd(Jpre,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr); if (J != Jpre) { ierr = MatAssemblyBegin(J,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr); ierr = MatAssemblyEnd(J,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr); } return 0; }