/* Solution - Computes the exact solution at a given time. Input Parameters: t - current time solution - vector in which exact solution will be computed appctx - user-defined application context Output Parameter: solution - vector with the newly computed exact solution */ PetscErrorCode Solution(TS ts,PetscReal t,Vec U,AppCtx *appctx) { PetscScalar *u,ex1,ex2,sc1,sc2,h; PetscErrorCode ierr; PetscInt i,mstart,mend,xm,M; DM da; ierr = TSGetDM(ts,&da);CHKERRQ(ierr); ierr = DMDAGetCorners(da,&mstart,0,0,&xm,0,0);CHKERRQ(ierr); ierr = DMDAGetInfo(da,PETSC_IGNORE,&M,0,0,0,0,0,0,0,0,0,0,0);CHKERRQ(ierr); h = 1.0/M; mend = mstart + xm; /* Get a pointer to vector data. */ ierr = DMDAVecGetArray(da,U,&u);CHKERRQ(ierr); /* Simply write the solution directly into the array locations. Alternatively, we culd use VecSetValues() or VecSetValuesLocal(). */ ex1 = PetscExpScalar(-36.*PETSC_PI*PETSC_PI*appctx->d*t); ex2 = PetscExpScalar(-4.*PETSC_PI*PETSC_PI*appctx->d*t); sc1 = PETSC_PI*6.*h; sc2 = PETSC_PI*2.*h; for (i=mstart; i<mend; i++) u[i] = PetscSinScalar(sc1*(PetscReal)i + appctx->a*PETSC_PI*6.*t)*ex1 + 3.*PetscSinScalar(sc2*(PetscReal)i + appctx->a*PETSC_PI*2.*t)*ex2; /* Restore vector */ ierr = DMDAVecRestoreArray(da,U,&u);CHKERRQ(ierr); return 0; }
/* ExactSolution - Computes the exact solution at a given time. Input Parameters: t - current time solution - vector in which exact solution will be computed appctx - user-defined application context Output Parameter: solution - vector with the newly computed exact solution */ PetscErrorCode ExactSolution(PetscReal t,Vec solution,AppCtx *appctx) { PetscScalar *s_localptr,h = appctx->h,ex1,ex2,sc1,sc2,tc = t; PetscInt i; PetscErrorCode ierr; /* Get a pointer to vector data. */ ierr = VecGetArray(solution,&s_localptr);CHKERRQ(ierr); /* Simply write the solution directly into the array locations. Alternatively, we culd use VecSetValues() or VecSetValuesLocal(). */ ex1 = PetscExpScalar(-36.*PETSC_PI*PETSC_PI*tc); ex2 = PetscExpScalar(-4.*PETSC_PI*PETSC_PI*tc); sc1 = PETSC_PI*6.*h; sc2 = PETSC_PI*2.*h; for (i=0; i<appctx->m; i++) s_localptr[i] = PetscCosScalar(sc1*(PetscReal)i)*ex1 + 3.*PetscCosScalar(sc2*(PetscReal)i)*ex2; /* Restore vector */ ierr = VecRestoreArray(solution,&s_localptr);CHKERRQ(ierr); return 0; }
PetscErrorCode nonlinearResidual(PetscReal lambda, Field u[], Field r[]) { Field rLocal[3] = {{0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}}; PetscScalar phi[3] = {0.0, 0.0, 0.0}; Field res; PetscInt q; PetscFunctionBeginUser; for (q = 0; q < 4; q++) { phi[0] = 1.0 - quadPoints[q*2] - quadPoints[q*2+1]; phi[1] = quadPoints[q*2]; phi[2] = quadPoints[q*2+1]; res.u = quadWeights[q]*PetscExpScalar(u[0].u*phi[0] + u[1].u*phi[1] + u[2].u*phi[2]); res.v = quadWeights[q]*PetscExpScalar(u[0].v*phi[0] + u[1].v*phi[1] + u[2].v*phi[2]); rLocal[0].u += phi[0]*res.u; rLocal[0].v += phi[0]*res.v; rLocal[1].u += phi[1]*res.u; rLocal[1].v += phi[1]*res.v; rLocal[2].u += phi[2]*res.u; rLocal[2].v += phi[2]*res.v; } r[0].u += lambda*rLocal[0].u; r[0].v += lambda*rLocal[0].v; r[1].u += lambda*rLocal[1].u; r[1].v += lambda*rLocal[1].v; r[2].u += lambda*rLocal[2].u; r[2].v += lambda*rLocal[2].v; PetscFunctionReturn(0); }
PetscErrorCode RunSimulation(PetscReal *x, PetscInt i, PetscReal*f, AppCtx *user) { PetscReal *t = user->t; PetscReal *y = user->y; *f = y[i] - PetscExpScalar(-x[0]*t[i])/(x[1] + x[2]*t[i]); return(0); }
PetscErrorCode FormInitialSolution(TS ts, Vec U, void *ctx) { /* User user = (User) ctx; */ DM dm, cdm; DMDALocalInfo info; Vec C; Field *u; PetscScalar *x; const PetscReal sigma = 1.0; PetscInt i; PetscErrorCode ierr; PetscFunctionBeginUser; ierr = TSGetDM(ts, &dm); ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); ierr = DMGetCoordinatesLocal(dm, &C);CHKERRQ(ierr); ierr = DMDAGetLocalInfo(dm, &info);CHKERRQ(ierr); ierr = DMDAVecGetArray(dm, U, &u);CHKERRQ(ierr); ierr = DMDAVecGetArrayRead(cdm, C, &x);CHKERRQ(ierr); for (i = info.xs; i < info.xs+info.xm; ++i) { u[i].u = 1.5 * PetscExpScalar(-PetscSqr(x[i] - 10)/PetscSqr(sigma)); u[i].v = 0.0; u[i].th = 0.0; } ierr = DMDAVecRestoreArray(dm, U, &u);CHKERRQ(ierr); ierr = DMDAVecRestoreArrayRead(cdm, C, &x);CHKERRQ(ierr); PetscFunctionReturn(0); }
PetscErrorCode EvaluateJacobian(Tao tao, Vec X, Mat J, Mat Jpre, void *ptr) { AppCtx *user = (AppCtx *)ptr; PetscInt i; PetscReal *x,*t=user->t; PetscReal base; PetscErrorCode ierr; PetscFunctionBegin; ierr = VecGetArray(X,&x);CHKERRQ(ierr); for (i=0;i<NOBSERVATIONS;i++) { base = PetscExpScalar(-x[0]*t[i])/(x[1] + x[2]*t[i]); user->j[i][0] = t[i]*base; user->j[i][1] = base/(x[1] + x[2]*t[i]); user->j[i][2] = base*t[i]/(x[1] + x[2]*t[i]); } /* Assemble the matrix */ ierr = MatSetValues(J,NOBSERVATIONS,user->idm, NPARAMETERS, user->idn,(PetscReal *)user->j,INSERT_VALUES);CHKERRQ(ierr); ierr = MatAssemblyBegin(J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = MatAssemblyEnd(J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = VecRestoreArray(X,&x);CHKERRQ(ierr); PetscLogFlops(NOBSERVATIONS * 13); PetscFunctionReturn(0); }
/* ComputeFunction - Evaluates nonlinear function, F(x). Input Parameters: . X - input vector . user - user-defined application context Output Parameter: . F - function vector */ PetscErrorCode ComputeFunction(AppCtx *user,Vec X,Vec F) { PetscErrorCode ierr; PetscInt i,j,row,mx,my,xs,ys,xm,ym,gxs,gys,gxm,gym; PetscReal two = 2.0,one = 1.0,lambda,hx,hy,hxdhy,hydhx,sc; PetscScalar u,uxx,uyy,*x,*f; Vec localX = user->localX; mx = user->mx; my = user->my; lambda = user->param; hx = one/(PetscReal)(mx-1); hy = one/(PetscReal)(my-1); sc = hx*hy*lambda; hxdhy = hx/hy; hydhx = hy/hx; /* Scatter ghost points to local vector, using the 2-step process DMGlobalToLocalBegin(), DMGlobalToLocalEnd(). By placing code between these two statements, computations can be done while messages are in transition. */ ierr = DMGlobalToLocalBegin(user->da,X,INSERT_VALUES,localX);CHKERRQ(ierr); ierr = DMGlobalToLocalEnd(user->da,X,INSERT_VALUES,localX);CHKERRQ(ierr); /* Get pointers to vector data */ ierr = VecGetArray(localX,&x);CHKERRQ(ierr); ierr = VecGetArray(F,&f);CHKERRQ(ierr); /* Get local grid boundaries */ ierr = DMDAGetCorners(user->da,&xs,&ys,NULL,&xm,&ym,NULL);CHKERRQ(ierr); ierr = DMDAGetGhostCorners(user->da,&gxs,&gys,NULL,&gxm,&gym,NULL);CHKERRQ(ierr); /* Compute function over the locally owned part of the grid */ for (j=ys; j<ys+ym; j++) { row = (j - gys)*gxm + xs - gxs - 1; for (i=xs; i<xs+xm; i++) { row++; if (i == 0 || j == 0 || i == mx-1 || j == my-1) { f[row] = x[row]; continue; } u = x[row]; uxx = (two*u - x[row-1] - x[row+1])*hydhx; uyy = (two*u - x[row-gxm] - x[row+gxm])*hxdhy; f[row] = uxx + uyy - sc*PetscExpScalar(u); } } /* Restore vectors */ ierr = VecRestoreArray(localX,&x);CHKERRQ(ierr); ierr = VecRestoreArray(F,&f);CHKERRQ(ierr); ierr = PetscLogFlops(11.0*ym*xm);CHKERRQ(ierr); return 0; }
PetscErrorCode ini_bou(Vec X,AppCtx* user) { PetscErrorCode ierr; DM cda; DMDACoor2d **coors; PetscScalar **p; Vec gc; PetscInt i,j; PetscInt xs,ys,xm,ym,M,N; PetscScalar xi,yi; PetscScalar sigmax=user->sigmax,sigmay=user->sigmay; PetscScalar rho =user->rho; PetscScalar mux =user->mux,muy=user->muy; PetscMPIInt rank; PetscScalar sum; PetscFunctionBeginUser; ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&rank);CHKERRQ(ierr); ierr = DMDAGetInfo(user->da,NULL,&M,&N,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL); user->dx = (user->xmax - user->xmin)/(M-1); user->dy = (user->ymax - user->ymin)/(N-1); ierr = DMGetCoordinateDM(user->da,&cda);CHKERRQ(ierr); ierr = DMGetCoordinates(user->da,&gc);CHKERRQ(ierr); ierr = DMDAVecGetArray(cda,gc,&coors);CHKERRQ(ierr); ierr = DMDAVecGetArray(user->da,X,&p);CHKERRQ(ierr); ierr = DMDAGetCorners(cda,&xs,&ys,0,&xm,&ym,0);CHKERRQ(ierr); /* mux and muy need to be grid points in the x and y-direction otherwise the solution goes unstable muy is set by choosing the y domain, no. of grid points along y-direction so that muy is a grid point in the y-direction. We only modify mux here */ mux = user->mux = coors[0][M/2+10].x; /* For -pi < x < pi, this should be some angle between 0 and pi/2 */ if (user->nonoiseinitial) { for (i=xs; i < xs+xm; i++) { for (j=ys; j < ys+ym; j++) { xi = coors[j][i].x; yi = coors[j][i].y; if ((xi == mux) && (yi == muy)) { p[j][i] = 1.0; } } } } else { /* Change PM_min accordingly */ user->PM_min = user->Pmax*sin(mux); for (i=xs; i < xs+xm; i++) { for (j=ys; j < ys+ym; j++) { xi = coors[j][i].x; yi = coors[j][i].y; p[j][i] = (0.5/(PETSC_PI*sigmax*sigmay*PetscSqrtScalar(1.0-rho*rho)))*PetscExpScalar(-0.5/(1-rho*rho)*(PetscPowScalar((xi-mux)/sigmax,2) + PetscPowScalar((yi-muy)/sigmay,2) - 2*rho*(xi-mux)*(yi-muy)/(sigmax*sigmay))); } } } ierr = DMDAVecRestoreArray(cda,gc,&coors);CHKERRQ(ierr); ierr = DMDAVecRestoreArray(user->da,X,&p);CHKERRQ(ierr); ierr = VecSum(X,&sum);CHKERRQ(ierr); ierr = VecScale(X,1.0/sum);CHKERRQ(ierr); PetscFunctionReturn(0); }
PetscErrorCode IFunction(TS ts,PetscReal t,Vec X,Vec Xdot,Vec F,void *ctx) { PetscErrorCode ierr; AppCtx *user=(AppCtx*)ctx; DM cda; DMDACoor2d **coors; PetscScalar **p,**f,**pdot; PetscInt i,j; PetscInt xs,ys,xm,ym,M,N; Vec localX,gc,localXdot; PetscScalar p_adv1,p_adv2,p_diff; PetscFunctionBeginUser; ierr = DMDAGetInfo(user->da,NULL,&M,&N,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL); ierr = DMGetCoordinateDM(user->da,&cda);CHKERRQ(ierr); ierr = DMDAGetCorners(cda,&xs,&ys,0,&xm,&ym,0);CHKERRQ(ierr); ierr = DMGetLocalVector(user->da,&localX);CHKERRQ(ierr); ierr = DMGetLocalVector(user->da,&localXdot);CHKERRQ(ierr); ierr = DMGlobalToLocalBegin(user->da,X,INSERT_VALUES,localX);CHKERRQ(ierr); ierr = DMGlobalToLocalEnd(user->da,X,INSERT_VALUES,localX);CHKERRQ(ierr); ierr = DMGlobalToLocalBegin(user->da,Xdot,INSERT_VALUES,localXdot);CHKERRQ(ierr); ierr = DMGlobalToLocalEnd(user->da,Xdot,INSERT_VALUES,localXdot);CHKERRQ(ierr); ierr = DMGetCoordinatesLocal(user->da,&gc);CHKERRQ(ierr); ierr = DMDAVecGetArrayRead(cda,gc,&coors);CHKERRQ(ierr); ierr = DMDAVecGetArrayRead(user->da,localX,&p);CHKERRQ(ierr); ierr = DMDAVecGetArrayRead(user->da,localXdot,&pdot);CHKERRQ(ierr); ierr = DMDAVecGetArray(user->da,F,&f);CHKERRQ(ierr); PetscScalar diffuse1,gamma; gamma = user->D*user->ws/(2*user->H); diffuse1 = user->lambda*user->lambda*user->q/(user->lambda*gamma+1)*(1.0 - PetscExpScalar(-t*(gamma+1.0)/user->lambda)); user->disper_coe = user->ws*user->ws/(4*user->H*user->H)*diffuse1; for (i=xs; i < xs+xm; i++) { for (j=ys; j < ys+ym; j++) { ierr = adv1(p,coors[j][i].y,i,j,M,&p_adv1,user);CHKERRQ(ierr); ierr = adv2(p,coors[j][i].x,coors[j][i].y,i,j,N,&p_adv2,user);CHKERRQ(ierr); ierr = diffuse(p,i,j,t,&p_diff,user);CHKERRQ(ierr); f[j][i] = -p_adv1 - p_adv2 + p_diff - pdot[j][i]; } } ierr = DMDAVecRestoreArrayRead(user->da,localX,&p);CHKERRQ(ierr); ierr = DMDAVecRestoreArrayRead(user->da,localX,&pdot);CHKERRQ(ierr); ierr = DMRestoreLocalVector(user->da,&localX);CHKERRQ(ierr); ierr = DMRestoreLocalVector(user->da,&localXdot);CHKERRQ(ierr); ierr = DMDAVecRestoreArray(user->da,F,&f);CHKERRQ(ierr); ierr = DMDAVecRestoreArrayRead(cda,gc,&coors);CHKERRQ(ierr); PetscFunctionReturn(0); }
/* Computes the power extracted from wind */ PetscErrorCode GetWindPower(PetscScalar wm,PetscScalar vw,PetscScalar *Pw,AppCtx *user) { PetscScalar temp,lambda,lambda_i,cp; PetscFunctionBegin; temp = user->nGB*2*user->Rt*ws/user->np; lambda = temp*wm/vw; lambda_i = 1/(1/lambda + 0.002); cp = 0.44*(125/lambda_i - 6.94)*PetscExpScalar(-16.5/lambda_i); *Pw = 0.5*user->rho*cp*user->Ar*vw*vw*vw/(MVAbase*1e6); PetscFunctionReturn(0); }
/* Define the analytic solution for check method easily */ static PetscErrorCode sol_true(PetscReal t, Vec U,AppCtx *ctx) { PetscErrorCode ierr; PetscScalar *u; PetscFunctionBegin; ierr = VecGetArray(U,&u);CHKERRQ(ierr); u[0] = PetscExpScalar(t/ctx->a); u[1] = (ctx->a*PetscCosScalar(ctx->b*t)+ctx->a*ctx->a*ctx->b*PetscSinScalar(ctx->b*t))*PetscExpScalar(t/ctx->a)/(1+ctx->a*ctx->a*ctx->b*ctx->b); ierr = VecRestoreArray(U,&u);CHKERRQ(ierr); PetscFunctionReturn(0); }
/*! \brief Gets the phase associated with the specified rotation. Given the amount to rotate and the sector we are currently in this function returns the phases associated with the rotation for a given rotation sector. This is usually a complex number and so a complex build of PETSc should be used. */ PetscScalar get_rotation_phase(struct parameter_struct *parameters,PetscInt sector, int rot_op_idx) { PetscScalar phase; PetscScalar k; struct rotation_information *rot_info; rot_info = ¶meters->rotation_info[rot_op_idx]; // This feature requires a complex build so only adding directive so that DoQO will compile but this feature should not be used without complex support. #if defined(PETSC_USE_COMPLEX) k = ((PetscScalar)sector)*2.0*PETSC_PI*((PetscScalar)rot_info->real_sector)/(PetscScalar)rot_info->num_sectors*PETSC_i; #endif phase = PetscExpScalar(k); return phase; }
/* FormFunctionLocalMMS2 - Evaluates nonlinear function, F(x) on local process patch */ PetscErrorCode FormFunctionLocalMMS2(DMDALocalInfo *info,PetscScalar **vx,PetscScalar **f,AppCtx *user) { PetscErrorCode ierr; PetscInt i,j; PetscReal lambda,hx,hy,hxdhy,hydhx; PetscScalar u,ue,uw,un,us,uxx,uyy; PetscReal x,y; DM coordDA; Vec coordinates; DMDACoor2d **coords; PetscFunctionBeginUser; lambda = user->param; hx = 1.0/(PetscReal)(info->mx-1); hy = 1.0/(PetscReal)(info->my-1); hxdhy = hx/hy; hydhx = hy/hx; /* Extract coordinates */ ierr = DMGetCoordinateDM(info->da, &coordDA);CHKERRQ(ierr); ierr = DMGetCoordinates(info->da, &coordinates);CHKERRQ(ierr); ierr = DMDAVecGetArray(coordDA, coordinates, &coords);CHKERRQ(ierr); /* Compute function over the locally owned part of the grid */ for (j=info->ys; j<info->ys+info->ym; j++) { for (i=info->xs; i<info->xs+info->xm; i++) { if (i == 0 || j == 0 || i == info->mx-1 || j == info->my-1) { f[j][i] = 2.0*(hydhx+hxdhy)*vx[j][i]; } else { x = PetscRealPart(coords[j][i].x); y = PetscRealPart(coords[j][i].y); u = vx[j][i]; uw = vx[j][i-1]; ue = vx[j][i+1]; un = vx[j-1][i]; us = vx[j+1][i]; if (i-1 == 0) uw = 0.; if (i+1 == info->mx-1) ue = 0.; if (j-1 == 0) un = 0.; if (j+1 == info->my-1) us = 0.; uxx = (2.0*u - uw - ue)*hydhx; uyy = (2.0*u - un - us)*hxdhy; f[j][i] = uxx + uyy - hx*hy*(lambda*PetscExpScalar(u) + 2*PetscSqr(PETSC_PI)*PetscSinReal(PETSC_PI*x)*PetscSinReal(PETSC_PI*y) - lambda*exp(PetscSinReal(PETSC_PI*x)*PetscSinReal(PETSC_PI*y))); } } } ierr = DMDAVecRestoreArray(coordDA, coordinates, &coords);CHKERRQ(ierr); ierr = PetscLogFlops(11.0*info->ym*info->xm);CHKERRQ(ierr); PetscFunctionReturn(0); }
PetscErrorCode ComputeFunction(SNES snes,Vec x,Vec f,void *ctx) { PetscInt i,Mx,xs,xm; PetscScalar *xx,*ff,hx; DA da = (DA) ctx; Vec xlocal; DAGetInfo(da,PETSC_IGNORE,&Mx,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE); hx = 1.0/(PetscReal)(Mx-1); DAGetLocalVector(da,&xlocal);DAGlobalToLocalBegin(da,x,INSERT_VALUES,xlocal); DAGlobalToLocalEnd(da,x,INSERT_VALUES,xlocal); DAVecGetArray(da,xlocal,&xx); DAVecGetArray(da,f,&ff); DAGetCorners(da,&xs,PETSC_NULL,PETSC_NULL,&xm,PETSC_NULL,PETSC_NULL); for (i=xs; i<xs+xm; i++) { if (i == 0 || i == Mx-1) ff[i] = xx[i]/hx; else ff[i] = (2.0*xx[i] - xx[i-1] - xx[i+1])/hx - hx*PetscExpScalar(xx[i]); } DAVecRestoreArray(da,xlocal,&xx); DARestoreLocalVector(da,&xlocal);DAVecRestoreArray(da,f,&ff); return 0;}
PetscErrorCode FormFunction1(SNES snes,Vec X,Vec F,void *ptr) { AppCtx *user = (AppCtx*)ptr; PetscErrorCode ierr; PetscInt i,j,k,loc,mx,my,mz,xs,ys,zs,xm,ym,zm,Xs,Ys,Zs,Xm,Ym,Zm,base1,base2; PetscReal two = 2.0,one = 1.0,lambda,Hx,Hy,Hz,HxHzdHy,HyHzdHx,HxHydHz; PetscScalar u,uxx,uyy,sc,*x,*f,uzz; Vec localX = user->localX,localF = user->localF; mx = user->mx; my = user->my; mz = user->mz; lambda = user->param; Hx = one / (PetscReal)(mx-1); Hy = one / (PetscReal)(my-1); Hz = one / (PetscReal)(mz-1); sc = Hx*Hy*Hz*lambda; HxHzdHy = Hx*Hz/Hy; HyHzdHx = Hy*Hz/Hx; HxHydHz = Hx*Hy/Hz; ierr = DAGlobalToLocalBegin(user->da,X,INSERT_VALUES,localX); ierr = DAGlobalToLocalEnd(user->da,X,INSERT_VALUES,localX); ierr = VecGetArray(localX,&x);CHKERRQ(ierr); ierr = VecGetArray(localF,&f);CHKERRQ(ierr); ierr = DAGetCorners(user->da,&xs,&ys,&zs,&xm,&ym,&zm);CHKERRQ(ierr); ierr = DAGetGhostCorners(user->da,&Xs,&Ys,&Zs,&Xm,&Ym,&Zm);CHKERRQ(ierr); for (k=zs; k<zs+zm; k++) { base1 = (Xm*Ym)*(k-Zs); for (j=ys; j<ys+ym; j++) { base2 = base1 + (j-Ys)*Xm; for (i=xs; i<xs+xm; i++) { loc = base2 + (i-Xs); if (i == 0 || j == 0 || k== 0 || i == mx-1 || j == my-1 || k == mz-1) { f[loc] = x[loc]; } else { u = x[loc]; uxx = (two*u - x[loc-1] - x[loc+1])*HyHzdHx; uyy = (two*u - x[loc-Xm] - x[loc+Xm])*HxHzdHy; uzz = (two*u - x[loc-Xm*Ym] - x[loc+Xm*Ym])*HxHydHz; f[loc] = uxx + uyy + uzz - sc*PetscExpScalar(u); } } } } ierr = VecRestoreArray(localX,&x);CHKERRQ(ierr); ierr = VecRestoreArray(localF,&f);CHKERRQ(ierr); /* stick values into global vector */ ierr = DALocalToGlobal(user->da,localF,INSERT_VALUES,F);CHKERRQ(ierr); ierr = PetscLogFlops(11.0*ym*xm*zm);CHKERRQ(ierr); return 0; }
static PetscErrorCode FormJacobianLocal_K(User user,DMDALocalInfo *info,const PetscScalar u[],const PetscScalar k[],Mat Bkk) { PetscReal hx = 1./info->mx; PetscErrorCode ierr; PetscInt i; PetscFunctionBeginUser; for (i=info->xs; i<info->xs+info->xm; i++) { PetscInt row = i-info->gxs; PetscScalar vals[] = {hx*(PetscExpScalar(k[i]-1.)+1.)}; ierr = MatSetValuesLocal(Bkk,1,&row,1,&row,vals,INSERT_VALUES);CHKERRQ(ierr); } PetscFunctionReturn(0); }
/* FormObjectiveLocal - Evaluates nonlinear function, F(x) on local process patch */ PetscErrorCode FormObjectiveLocal(DMDALocalInfo *info,PetscScalar **x,PetscReal *obj,AppCtx *user) { PetscErrorCode ierr; PetscInt i,j; PetscReal lambda,hx,hy,hxdhy,hydhx,sc,lobj=0; PetscScalar u,ue,uw,un,us,uxux,uyuy; MPI_Comm comm; PetscFunctionBeginUser; *obj = 0; ierr = PetscObjectGetComm((PetscObject)info,&comm);CHKERRQ(ierr); lambda = user->param; hx = 1.0/(PetscReal)(info->mx-1); hy = 1.0/(PetscReal)(info->my-1); sc = hx*hy*lambda; hxdhy = hx/hy; hydhx = hy/hx; /* Compute function over the locally owned part of the grid */ for (j=info->ys; j<info->ys+info->ym; j++) { for (i=info->xs; i<info->xs+info->xm; i++) { if (i == 0 || j == 0 || i == info->mx-1 || j == info->my-1) { lobj += PetscRealPart((hydhx + hxdhy)*x[j][i]*x[j][i]); } else { u = x[j][i]; uw = x[j][i-1]; ue = x[j][i+1]; un = x[j-1][i]; us = x[j+1][i]; if (i-1 == 0) uw = 0.; if (i+1 == info->mx-1) ue = 0.; if (j-1 == 0) un = 0.; if (j+1 == info->my-1) us = 0.; /* F[u] = 1/2\int_{\omega}\nabla^2u(x)*u(x)*dx */ uxux = u*(2.*u - ue - uw)*hydhx; uyuy = u*(2.*u - un - us)*hxdhy; lobj += PetscRealPart(0.5*(uxux + uyuy) - sc*PetscExpScalar(u)); } } } ierr = PetscLogFlops(12.0*info->ym*info->xm);CHKERRQ(ierr); ierr = MPI_Allreduce(&lobj,obj,1,MPIU_REAL,MPIU_SUM,comm);CHKERRQ(ierr); PetscFunctionReturn(0); }
PetscErrorCode ComputeRHS(KSP ksp,Vec b,void *ctx) { UserContext *user = (UserContext*)ctx; PetscErrorCode ierr; PetscInt i,j,mx,my,xm,ym,xs,ys; PetscScalar Hx,Hy; PetscScalar **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 = 1.0 / (PetscReal)(mx-1); Hy = 1.0 / (PetscReal)(my-1); ierr = DMDAGetCorners(da,&xs,&ys,0,&xm,&ym,0);CHKERRQ(ierr); ierr = DMDAVecGetArray(da, b, &array);CHKERRQ(ierr); for (j=ys; j<ys+ym; j++) { for (i=xs; i<xs+xm; i++) { array[j][i] = PetscExpScalar(-((PetscReal)i*Hx)*((PetscReal)i*Hx)/user->nu)*PetscExpScalar(-((PetscReal)j*Hy)*((PetscReal)j*Hy)/user->nu)*Hx*Hy; } } ierr = DMDAVecRestoreArray(da, b, &array);CHKERRQ(ierr); ierr = VecAssemblyBegin(b);CHKERRQ(ierr); ierr = VecAssemblyEnd(b);CHKERRQ(ierr); /* force right hand side to be consistent for singular matrix */ /* note this is really a hack, normally the model would provide you with a consistent right handside */ if (user->bcType == NEUMANN) { MatNullSpace nullspace; ierr = MatNullSpaceCreate(PETSC_COMM_WORLD,PETSC_TRUE,0,0,&nullspace);CHKERRQ(ierr); ierr = MatNullSpaceRemove(nullspace,b);CHKERRQ(ierr); ierr = MatNullSpaceDestroy(&nullspace);CHKERRQ(ierr); } PetscFunctionReturn(0); }
PetscErrorCode ComputeRHS(DM da, Vec b, PetscScalar nu) { PetscErrorCode ierr; PetscInt i, j, mx, my, xm, ym, xs, ys; PetscScalar Hx, Hy; PetscScalar** array; PetscFunctionBeginUser; ierr = DMDAGetInfo(da, 0, &mx, &my, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); CHKERRQ(ierr); Hx = 1.0 / (PetscReal)(mx); Hy = 1.0 / (PetscReal)(my); ierr = DMDAGetCorners(da, &xs, &ys, 0, &xm, &ym, 0); CHKERRQ(ierr); ierr = DMDAVecGetArray(da, b, &array); CHKERRQ(ierr); for (j = ys; j < ys + ym; j++) { for (i = xs; i < xs + xm; i++) { array[j][i] = PetscExpScalar(-(((PetscReal)i + 0.5) * Hx) * (((PetscReal)i + 0.5) * Hx) / nu) * PetscExpScalar(-(((PetscReal)j + 0.5) * Hy) * (((PetscReal)j + 0.5) * Hy) / nu) * Hx * Hy * nu; } } ierr = DMDAVecRestoreArray(da, b, &array); CHKERRQ(ierr); ierr = VecAssemblyBegin(b); CHKERRQ(ierr); ierr = VecAssemblyEnd(b); CHKERRQ(ierr); MatNullSpace nullspace; ierr = MatNullSpaceCreate(PETSC_COMM_WORLD, PETSC_TRUE, 0, 0, &nullspace); CHKERRQ(ierr); ierr = MatNullSpaceRemove(nullspace, b); CHKERRQ(ierr); ierr = MatNullSpaceDestroy(&nullspace); CHKERRQ(ierr); PetscFunctionReturn(0); }
static PetscErrorCode FormFunctionLocal_K(User user,DMDALocalInfo *info,const PetscScalar u[],const PetscScalar k[],PetscScalar f[]) { PetscReal hx = 1./info->mx; PetscInt i; PetscFunctionBeginUser; for (i=info->xs; i<info->xs+info->xm; i++) { const PetscScalar ubar = 0.5*(u[i+1]+u[i]), gradu = (u[i+1]-u[i])/hx, g = 1. + gradu*gradu, w = 1./(1.+ubar) + 1./g; f[i] = hx*(PetscExpScalar(k[i]-1.0) + k[i] - 1./w); } PetscFunctionReturn(0); }
/* FormFunctionLocal - Evaluates nonlinear function, F(x). */ static PetscErrorCode FormFunctionLocal(DMDALocalInfo *info,PetscScalar **x,PetscScalar **f,AppCtx *user) { PetscReal hx,hy,dhx,dhy,sc,source; PetscInt i,j; PetscFunctionBegin; hx = 1.0/(PetscReal)(info->mx-1); hy = 1.0/(PetscReal)(info->my-1); sc = hx*hy*user->lambda; source = hx*hy*user->source; dhx = 1/hx; dhy = 1/hy; /* Compute function over the locally owned part of the grid */ for (j=info->ys; j<info->ys+info->ym; j++) { for (i=info->xs; i<info->xs+info->xm; i++) { if (i == 0 || j == 0 || i == info->mx-1 || j == info->my-1) { f[j][i] = x[j][i]; } else { const PetscScalar u = x[j][i], ux_E = dhx*(x[j][i+1]-x[j][i]), uy_E = 0.25*dhy*(x[j+1][i]+x[j+1][i+1]-x[j-1][i]-x[j-1][i+1]), ux_W = dhx*(x[j][i]-x[j][i-1]), uy_W = 0.25*dhy*(x[j+1][i-1]+x[j+1][i]-x[j-1][i-1]-x[j-1][i]), ux_N = 0.25*dhx*(x[j][i+1]+x[j+1][i+1]-x[j][i-1]-x[j+1][i-1]), uy_N = dhy*(x[j+1][i]-x[j][i]), ux_S = 0.25*dhx*(x[j-1][i+1]+x[j][i+1]-x[j-1][i-1]-x[j][i-1]), uy_S = dhy*(x[j][i]-x[j-1][i]), e_E = eta(user,ux_E,uy_E), e_W = eta(user,ux_W,uy_W), e_N = eta(user,ux_N,uy_N), e_S = eta(user,ux_S,uy_S), uxx = -hy * (e_E*ux_E - e_W*ux_W), uyy = -hx * (e_N*uy_N - e_S*uy_S); /** For p=2, these terms decay to: * uxx = (2.0*u - x[j][i-1] - x[j][i+1])*hydhx * uyy = (2.0*u - x[j-1][i] - x[j+1][i])*hxdhy **/ f[j][i] = uxx + uyy - sc*PetscExpScalar(u) - source; } } } PetscFunctionReturn(0); }
/* Calculate the Jacobian matrix J(X,t). Note: We put the Jacobian in the preconditioner storage B instead of J. This way we can give the -snes_mf_operator flag to check our work. This replaces J with a finite difference approximation, using our analytic Jacobian B for the preconditioner. */ PetscErrorCode FormJacobian(TS ts,PetscReal t,Vec X,Mat J,Mat B,void *ptr) { AppCtx *user = (AppCtx*)ptr; PetscInt i,j,row,mx,my,col[5]; PetscErrorCode ierr; PetscScalar two = 2.0,one = 1.0,lambda,v[5],sc,*x; PetscReal hx,hy,hxdhy,hydhx; mx = user->mx; my = user->my; lambda = user->param; hx = 1.0 / (PetscReal)(mx-1); hy = 1.0 / (PetscReal)(my-1); sc = hx*hy; hxdhy = hx/hy; hydhx = hy/hx; ierr = VecGetArray(X,&x);CHKERRQ(ierr); for (j=0; j<my; j++) { for (i=0; i<mx; i++) { row = i + j*mx; if (i == 0 || j == 0 || i == mx-1 || j == my-1) { ierr = MatSetValues(B,1,&row,1,&row,&one,INSERT_VALUES);CHKERRQ(ierr); continue; } v[0] = hxdhy; col[0] = row - mx; v[1] = hydhx; col[1] = row - 1; v[2] = -two*(hydhx + hxdhy) + sc*lambda*PetscExpScalar(x[row]); col[2] = row; v[3] = hydhx; col[3] = row + 1; v[4] = hxdhy; col[4] = row + mx; ierr = MatSetValues(B,1,&row,5,col,v,INSERT_VALUES);CHKERRQ(ierr); } } ierr = VecRestoreArray(X,&x);CHKERRQ(ierr); ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); if (J != B) { ierr = MatAssemblyBegin(J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = MatAssemblyEnd(J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); } return 0; }
/* Defines the exact (analytic) solution to the ODE */ static PetscErrorCode Solution(TS ts,PetscReal t,Vec U,AppCtx *ctx) { PetscErrorCode ierr; const PetscScalar *uinit; PetscScalar *u,d0,q; PetscFunctionBegin; ierr = VecGetArrayRead(ctx->initialsolution,&uinit);CHKERRQ(ierr); ierr = VecGetArray(U,&u);CHKERRQ(ierr); d0 = uinit[0] - uinit[1]; if (d0 == 0.0) q = ctx->k*t; else q = (1.0 - PetscExpScalar(-ctx->k*t*d0))/d0; u[0] = uinit[0]/(1.0 + uinit[1]*q); u[1] = u[0] - d0; u[2] = uinit[1] + uinit[2] - u[1]; ierr = VecRestoreArray(U,&u);CHKERRQ(ierr); ierr = VecRestoreArrayRead(ctx->initialsolution,&uinit);CHKERRQ(ierr); PetscFunctionReturn(0); }
PetscErrorCode EvaluateFunction(Tao tao, Vec X, Vec F, void *ptr) { AppCtx *user = (AppCtx *)ptr; PetscInt i; PetscReal *y=user->y,*x,*f,*t=user->t; PetscErrorCode ierr; PetscFunctionBegin; ierr = VecGetArray(X,&x);CHKERRQ(ierr); ierr = VecGetArray(F,&f);CHKERRQ(ierr); for (i=0;i<NOBSERVATIONS;i++) { f[i] = y[i] - PetscExpScalar(-x[0]*t[i])/(x[1] + x[2]*t[i]); } ierr = VecRestoreArray(X,&x);CHKERRQ(ierr); ierr = VecRestoreArray(F,&f);CHKERRQ(ierr); PetscLogFlops(6*NOBSERVATIONS); PetscFunctionReturn(0); }
PetscErrorCode ComputeJacobian(SNES snes,Vec x,Mat *J,Mat *B,MatStructure *flag,void *ctx){ DA da = (DA) ctx; PetscInt i,Mx,xm,xs; PetscScalar hx,*xx; Vec xlocal; DAGetInfo(da,PETSC_IGNORE,&Mx,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE); hx = 1.0/(PetscReal)(Mx-1); DAGetLocalVector(da,&xlocal);DAGlobalToLocalBegin(da,x,INSERT_VALUES,xlocal); DAGlobalToLocalEnd(da,x,INSERT_VALUES,xlocal); DAVecGetArray(da,xlocal,&xx); DAGetCorners(da,&xs,PETSC_NULL,PETSC_NULL,&xm,PETSC_NULL,PETSC_NULL); for (i=xs; i<xs+xm; i++) { if (i == 0 || i == Mx-1) { MatSetValue(*J,i,i,1.0/hx,INSERT_VALUES);} else { MatSetValue(*J,i,i-1,-1.0/hx,INSERT_VALUES); MatSetValue(*J,i,i,2.0/hx - hx*PetscExpScalar(xx[i]),INSERT_VALUES); MatSetValue(*J,i,i+1,-1.0/hx,INSERT_VALUES); } } MatAssemblyBegin(*J,MAT_FINAL_ASSEMBLY); MatAssemblyEnd(*J,MAT_FINAL_ASSEMBLY); *flag = SAME_NONZERO_PATTERN; DAVecRestoreArray(da,xlocal,&xx);DARestoreLocalVector(da,&xlocal); return 0;}
PetscErrorCode FormFunction(TS ts,PetscReal t,Vec X,Vec F,void *ptr) { AppCtx *user = (AppCtx*)ptr; PetscErrorCode ierr; PetscInt i,j,row,mx,my; PetscReal two = 2.0,one = 1.0,lambda; PetscReal hx,hy,hxdhy,hydhx; PetscScalar ut,ub,ul,ur,u,uxx,uyy,sc,*x,*f; mx = user->mx; my = user->my; lambda = user->param; hx = one / (PetscReal)(mx-1); hy = one / (PetscReal)(my-1); sc = hx*hy; hxdhy = hx/hy; hydhx = hy/hx; ierr = VecGetArray(X,&x);CHKERRQ(ierr); ierr = VecGetArray(F,&f);CHKERRQ(ierr); for (j=0; j<my; j++) { for (i=0; i<mx; i++) { row = i + j*mx; if (i == 0 || j == 0 || i == mx-1 || j == my-1) { f[row] = x[row]; continue; } u = x[row]; ub = x[row - mx]; ul = x[row - 1]; ut = x[row + mx]; ur = x[row + 1]; uxx = (-ur + two*u - ul)*hydhx; uyy = (-ut + two*u - ub)*hxdhy; f[row] = -uxx + -uyy + sc*lambda*PetscExpScalar(u); } } ierr = VecRestoreArray(X,&x);CHKERRQ(ierr); ierr = VecRestoreArray(F,&f);CHKERRQ(ierr); return 0; }
/* FormFunctionLocal - Evaluates nonlinear function, F(x) on local process patch */ PetscErrorCode FormFunctionLocal(DMDALocalInfo *info,PetscScalar **x,PetscScalar **f,AppCtx *user) { PetscErrorCode ierr; PetscInt i,j; PetscReal lambda,hx,hy,hxdhy,hydhx,sc; PetscScalar u,ue,uw,un,us,uxx,uyy; PetscFunctionBeginUser; lambda = user->param; hx = 1.0/(PetscReal)(info->mx-1); hy = 1.0/(PetscReal)(info->my-1); sc = hx*hy*lambda; hxdhy = hx/hy; hydhx = hy/hx; /* Compute function over the locally owned part of the grid */ for (j=info->ys; j<info->ys+info->ym; j++) { for (i=info->xs; i<info->xs+info->xm; i++) { if (i == 0 || j == 0 || i == info->mx-1 || j == info->my-1) { f[j][i] = 2.0*(hydhx+hxdhy)*x[j][i]; } else { u = x[j][i]; uw = x[j][i-1]; ue = x[j][i+1]; un = x[j-1][i]; us = x[j+1][i]; if (i-1 == 0) uw = 0.; if (i+1 == info->mx-1) ue = 0.; if (j-1 == 0) un = 0.; if (j+1 == info->my-1) us = 0.; uxx = (2.0*u - uw - ue)*hydhx; uyy = (2.0*u - un - us)*hxdhy; f[j][i] = uxx + uyy - sc*PetscExpScalar(u); } } } ierr = PetscLogFlops(11.0*info->ym*info->xm);CHKERRQ(ierr); PetscFunctionReturn(0); }
PetscErrorCode FormInitialSolution(Vec U,void* ptr) { AppCtx *user=(AppCtx*)ptr; DM da=user->da; PetscReal c=user->c; PetscErrorCode ierr; PetscInt i,j,xs,ys,xm,ym,Mx,My; PetscScalar **u; PetscReal hx,hy,x,y,r; PetscFunctionBeginUser; ierr = DMDAGetInfo(da,PETSC_IGNORE,&Mx,&My,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE, PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE); hx = 1.0/(PetscReal)(Mx-1); hy = 1.0/(PetscReal)(My-1); /* Get pointers to vector data */ ierr = DMDAVecGetArray(da,U,&u);CHKERRQ(ierr); /* Get local grid boundaries */ ierr = DMDAGetCorners(da,&xs,&ys,PETSC_NULL,&xm,&ym,PETSC_NULL);CHKERRQ(ierr); /* Compute function over the locally owned part of the grid */ for (j=ys; j<ys+ym; j++) { y = j*hy; for (i=xs; i<xs+xm; i++) { x = i*hx; r = PetscSqrtScalar((x-.5)*(x-.5) + (y-.5)*(y-.5)); if (r < .125) { u[j][i] = PetscExpScalar(c*r*r*r); } else { u[j][i] = 0.0; } } } /* Restore vectors */ ierr = DMDAVecRestoreArray(da,U,&u);CHKERRQ(ierr); PetscFunctionReturn(0); }
PetscErrorCode FormInitialSolution(TS ts,Vec U,void *ptr) { AppCtx *user=(AppCtx*)ptr; PetscReal c =user->c; DM da; PetscErrorCode ierr; PetscInt i,xs,xm,Mx; PetscScalar *u; PetscReal hx,x,r; PetscFunctionBeginUser; ierr = TSGetDM(ts,&da); CHKERRQ(ierr); ierr = DMDAGetInfo(da,PETSC_IGNORE,&Mx,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE, PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE); hx = 1.0/(PetscReal)(Mx-1); /* Get pointers to vector data */ ierr = DMDAVecGetArray(da,U,&u); CHKERRQ(ierr); /* Get local grid boundaries */ ierr = DMDAGetCorners(da,&xs,NULL,NULL,&xm,NULL,NULL); CHKERRQ(ierr); /* Compute function over the locally owned part of the grid */ for (i=xs; i<xs+xm; i++) { x = i*hx; r = PetscSqrtScalar((x-.5)*(x-.5)); if (r < .125) u[i] = PetscExpScalar(c*r*r*r); else u[i] = 0.0; } /* Restore vectors */ ierr = DMDAVecRestoreArray(da,U,&u); CHKERRQ(ierr); PetscFunctionReturn(0); }
/* This is the opposite sign of the part of FormFunctionLocal that excludes the A(x) x part of the operation, that is FormFunction applies A(x) x - b(x) while this applies b(x) because for Picard we think of it as solving A(x) x = b(x) */ static PetscErrorCode FormFunctionPicardLocal(DMDALocalInfo *info,PetscScalar **x,PetscScalar **f,AppCtx *user) { PetscReal hx,hy,sc,source; PetscInt i,j; PetscFunctionBegin; hx = 1.0/(PetscReal)(info->mx-1); hy = 1.0/(PetscReal)(info->my-1); sc = hx*hy*user->lambda; source = hx*hy*user->source; /* Compute function over the locally owned part of the grid */ for (j=info->ys; j<info->ys+info->ym; j++) { for (i=info->xs; i<info->xs+info->xm; i++) { if (!(i == 0 || j == 0 || i == info->mx-1 || j == info->my-1)) { const PetscScalar u = x[j][i]; f[j][i] = sc*PetscExpScalar(u) + source; } } } PetscFunctionReturn(0); }