static char help[] = "Solves 2D inhomogeneous Laplacian using multigrid.\n\n"; #include #include #include typedef struct { PassiveReal mu; // viscosity Vec phi; // level set function } Stokesparas; typedef struct { PassiveReal x_min,x_max,y_min,y_max; } resolpara; typedef struct { PetscScalar u,v,p; } Field; typedef struct { KSP ksp; // linear Krylov solver Stokesparas para; } Stokes2D; extern PetscErrorCode Stokes2D_initial(Stokes2D *s, DM da, resolpara *rp); extern PetscErrorCode Stokes2D_solve(Stokes2D *s); extern PetscErrorCode Stokes2D_finalize(Stokes2D *s); PetscErrorCode printSol(Stokes2D* s, resolpara *rp); extern PetscErrorCode ComputeMatrix(KSP,Mat,Mat,MatStructure*,void*); extern PetscErrorCode ComputeRHS(KSP,Vec,void*); int main(int argc,char **argv) { Stokes2D stokes; DM da; PetscErrorCode ierr; PetscReal t0,t1,t2,t3; resolpara rp; ierr = PetscTime(&t0);CHKERRQ(ierr); PetscInitialize(&argc,&argv,(char*)0,help); ierr = DMDACreate2d(PETSC_COMM_WORLD, DMDA_BOUNDARY_NONE, DMDA_BOUNDARY_NONE,DMDA_STENCIL_BOX,-3,-3,PETSC_DECIDE,PETSC_DECIDE,3,3,0,0,&da);CHKERRQ(ierr); Stokes2D_initial(&stokes, da, &rp); ierr = PetscTime(&t1);CHKERRQ(ierr); Stokes2D_solve(&stokes); ierr = PetscTime(&t2);CHKERRQ(ierr); printSol(&stokes, &rp); ierr = PetscTime(&t3);CHKERRQ(ierr); ierr = PetscPrintf(PETSC_COMM_WORLD,"Time cost for creating solver context %g s, and for solving %g s, and for printing %g s.\n",t1-t0,t2-t1,t3-t2);CHKERRQ(ierr); ierr = Stokes2D_finalize(&stokes);CHKERRQ(ierr); ierr = PetscFinalize();CHKERRQ(ierr); return 0; } PetscScalar phiEvalAt(PetscScalar x, PetscScalar y) { return PetscSqrtScalar(PetscPowScalar(x-.5,2.0)+PetscPowScalar(y-.5,2.0))-.2; } PetscScalar phixEvalAt(PetscScalar x, PetscScalar y) { PetscScalar h = 1e-6; return (phiEvalAt(x+h/2,y)-phiEvalAt(x-h/2,y))/h; } PetscScalar phiyEvalAt(PetscScalar x, PetscScalar y) { PetscScalar h = 1e-6; return (phiEvalAt(x,y+h/2)-phiEvalAt(x,y-h/2))/h; } PetscErrorCode normal_phiEvalAt(PetscScalar x, PetscScalar y, PetscScalar *n1, PetscScalar *n2) { PetscScalar px = phixEvalAt(x,y), py = phiyEvalAt(x,y); PetscFunctionBeginUser; *n1 = px/PetscSqrtScalar(px*px+py*py); *n2 = py/PetscSqrtScalar(px*px+py*py); PetscFunctionReturn(0); } PetscScalar u_exact(PetscScalar x, PetscScalar y) { return PetscSinScalar(2*PETSC_PI*x)*PetscCosScalar(2*PETSC_PI*y); } PetscScalar v_exact(PetscScalar x, PetscScalar y) { return -PetscCosScalar(2*PETSC_PI*x)*PetscSinScalar(2*PETSC_PI*y); } PetscScalar p_exact(PetscScalar x, PetscScalar y) { return -PetscSinScalar(2*PETSC_PI*x)*PetscSinScalar(2*PETSC_PI*y); } PetscScalar f1_exact(PetscScalar x, PetscScalar y) { PetscScalar h = 1e-6; return -(u_exact(x+h,y)+u_exact(x-h,y)+u_exact(x,y+h)+u_exact(x,y-h)-4*u_exact(x,y))/h/h+(p_exact(x+h/2.0,y)-p_exact(x-h/2.0,y))/h; } PetscScalar f2_exact(PetscScalar x, PetscScalar y) { PetscScalar h = 1e-6; return -(v_exact(x+h,y)+v_exact(x-h,y)+v_exact(x,y+h)+v_exact(x,y-h)-4*v_exact(x,y))/h/h+(p_exact(x,y+h/2.0)-p_exact(x,y-h/2.0))/h; } PetscErrorCode bdry_force(PetscScalar x, PetscScalar y, PetscScalar n1, PetscScalar n2, PetscScalar *g1, PetscScalar *g2) { PetscScalar h = 1e-6, ux, uy, vx, vy; PetscFunctionBeginUser; ux = (u_exact(x+h/2,y)-u_exact(x-h/2,y))/h; uy = (u_exact(x,y+h/2)-u_exact(x,y-h/2))/h; vx = (v_exact(x+h/2,y)-v_exact(x-h/2,y))/h; vy = (v_exact(x,y+h/2)-v_exact(x,y-h/2))/h; *g1 = (n1*n1-n2*n2)*(uy+vx)+2*n1*n2*(vy-ux); *g2 = 2*(n1*n1-n2*n2)*ux+2*n1*n2*(uy+vx)-p_exact(x,y); PetscFunctionReturn(0); } PetscErrorCode x_exact(KSP ksp,Vec x, resolpara *rp) { PetscErrorCode ierr; PetscInt i,j,mx,my,xm,ym,xs,ys; PetscScalar hx,hy; Field **array; DM da; PetscFunctionBeginUser; ierr = KSPGetDM(ksp,&da);CHKERRQ(ierr); ierr = DMDAGetInfo(da, 0, &mx, &my, 0,0,0,0,0,0,0,0,0,0);CHKERRQ(ierr); hx = (rp->x_max-rp->x_min) / (PetscReal)(mx-1); hy = (rp->y_max-rp->y_min) / (PetscReal)(my-1); ierr = DMDAGetCorners(da,&xs,&ys,0,&xm,&ym,0);CHKERRQ(ierr); ierr = DMDAVecGetArray(da, x, &array);CHKERRQ(ierr); for (j=ys; jx_min = 0; rp->x_max = 1; rp->y_min = 0; rp->y_max = 1; ierr = PetscOptionsGetReal(NULL,"-x_min",&(rp->x_min),NULL);CHKERRQ(ierr); ierr = PetscOptionsGetReal(NULL,"-x_max",&(rp->x_max),NULL);CHKERRQ(ierr); ierr = PetscOptionsGetReal(NULL,"-y_min",&(rp->y_min),NULL);CHKERRQ(ierr); ierr = PetscOptionsGetReal(NULL,"-y_max",&(rp->y_max),NULL);CHKERRQ(ierr); ierr = KSPCreate(PETSC_COMM_WORLD,&(s->ksp));CHKERRQ(ierr); ierr = KSPSetComputeRHS(s->ksp,ComputeRHS,rp);CHKERRQ(ierr); ierr = KSPSetComputeOperators(s->ksp,ComputeMatrix,rp);CHKERRQ(ierr); ierr = KSPSetDM(s->ksp,da);CHKERRQ(ierr); PetscFunctionReturn(0); } PetscErrorCode Stokes2D_solve(Stokes2D *s) { PetscErrorCode ierr; PetscFunctionBeginUser; ierr = KSPSetFromOptions(s->ksp);CHKERRQ(ierr); ierr = KSPSetUp(s->ksp);CHKERRQ(ierr); ierr = KSPSolve(s->ksp,NULL,NULL);CHKERRQ(ierr); PetscFunctionReturn(0); } PetscErrorCode Stokes2D_finalize(Stokes2D *s) { PetscErrorCode ierr; PetscFunctionBeginUser; ierr = KSPDestroy(&(s->ksp));CHKERRQ(ierr); PetscFunctionReturn(0); } PetscErrorCode printSol(Stokes2D* s, resolpara *rp) { PetscErrorCode ierr; PetscViewer viewer; Vec b,x,zero; Mat A; PetscScalar r,hx,hy; PetscInt mx, my; DM da; PetscFunctionBeginUser; ierr = KSPGetSolution(s->ksp,&x);CHKERRQ(ierr); ierr = KSPGetRhs(s->ksp,&b);CHKERRQ(ierr); ierr = PetscViewerASCIIOpen(PETSC_COMM_WORLD, "output/ksp_x.txt", &viewer);CHKERRQ(ierr); ierr = VecView(x, viewer);CHKERRQ(ierr); ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr); ierr = PetscViewerASCIIOpen(PETSC_COMM_WORLD, "output/ksp_b.txt", &viewer);CHKERRQ(ierr); ierr = VecView(b, viewer);CHKERRQ(ierr); ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr); ierr = x_exact(s->ksp, b, rp);CHKERRQ(ierr); ierr = PetscViewerASCIIOpen(PETSC_COMM_WORLD, "output/ksp_sol.txt", &viewer);CHKERRQ(ierr); ierr = VecView(b, viewer);CHKERRQ(ierr); ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr); ierr = KSPGetOperators(s->ksp,&A,NULL,NULL);CHKERRQ(ierr); ierr = VecDuplicate(b,&zero);CHKERRQ(ierr); ierr = MatMult(A,b,zero); ierr = PetscViewerASCIIOpen(PETSC_COMM_WORLD, "output/ksp_zero.txt", &viewer);CHKERRQ(ierr); ierr = VecView(zero, viewer);CHKERRQ(ierr); ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr); ierr = PetscViewerASCIIOpen(PETSC_COMM_WORLD, "output/ksp_A.txt", &viewer);CHKERRQ(ierr); ierr = MatView(A, viewer);CHKERRQ(ierr); ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr); VecAXPY(x,-1,b); VecNorm(x,NORM_2,&r); ierr = KSPGetDM(s->ksp,&da);CHKERRQ(ierr); ierr = DMDAGetInfo(da, 0, &mx, &my, 0,0,0,0,0,0,0,0,0,0);CHKERRQ(ierr); hx = (rp->x_max-rp->x_min) / (PetscReal)(mx-1); hy = (rp->y_max-rp->y_min) / (PetscReal)(my-1); ierr = PetscPrintf(PETSC_COMM_WORLD,"Norm error %g %g.\n",r,r*PetscSqrtScalar(hx*hy));CHKERRQ(ierr); PetscFunctionReturn(0); } PetscErrorCode ComputeRHS(KSP ksp,Vec b,void *ctx) { PetscErrorCode ierr; PetscInt i,j,mx,my,xm,ym,xs,ys; PetscScalar hx,hy; Field **array; DM da; resolpara *rp; PetscFunctionBeginUser; rp = ctx; ierr = KSPGetDM(ksp,&da);CHKERRQ(ierr); ierr = DMDAGetInfo(da, 0, &mx, &my, 0,0,0,0,0,0,0,0,0,0);CHKERRQ(ierr); hx = (rp->x_max-rp->x_min) / (PetscReal)(mx-1); hy = (rp->y_max-rp->y_min) / (PetscReal)(my-1); ierr = DMDAGetCorners(da,&xs,&ys,0,&xm,&ym,0);CHKERRQ(ierr); ierr = DMDAVecGetArray(da, b, &array);CHKERRQ(ierr); for (j=ys; jx_max-rp->x_min) / (PetscReal)(mx-1); hy = (rp->y_max-rp->y_min) / (PetscReal)(my-1); dhx = 1/hx; dhy = 1/hy; dhx2 = 1/hx/hx; dhy2 = 1/hy/hy; hxdhy = hx/hy; hydhx = hy/hx; ierr = DMDAGetCorners(da,&xs,&ys,0,&xm,&ym,0);CHKERRQ(ierr); for (j=ys; j