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; }
int FormJacobian_Grid(GridCtx *grid,Mat *J) { Mat jac = *J; PetscErrorCode ierr; PetscInt i,j,row,mx,my,xs,ys,xm,ym,Xs,Ys,Xm,Ym,col[5]; PetscInt nloc,*ltog,grow; PetscScalar two = 2.0,one = 1.0,v[5],hx,hy,hxdhy,hydhx,value; mx = grid->mx; my = grid->my; hx = one/(PetscReal)(mx-1); hy = one/(PetscReal)(my-1); hxdhy = hx/hy; hydhx = hy/hx; /* Get ghost points */ ierr = DAGetCorners(grid->da,&xs,&ys,0,&xm,&ym,0);CHKERRQ(ierr); ierr = DAGetGhostCorners(grid->da,&Xs,&Ys,0,&Xm,&Ym,0);CHKERRQ(ierr); ierr = DAGetGlobalIndices(grid->da,&nloc,<og);CHKERRQ(ierr); /* Evaluate Jacobian of function */ for (j=ys; j<ys+ym; j++) { row = (j - Ys)*Xm + xs - Xs - 1; for (i=xs; i<xs+xm; i++) { row++; grow = ltog[row]; if (i > 0 && i < mx-1 && j > 0 && j < my-1) { v[0] = -hxdhy; col[0] = ltog[row - Xm]; v[1] = -hydhx; col[1] = ltog[row - 1]; v[2] = two*(hydhx + hxdhy); col[2] = grow; v[3] = -hydhx; col[3] = ltog[row + 1]; v[4] = -hxdhy; col[4] = ltog[row + Xm]; ierr = MatSetValues(jac,1,&grow,5,col,v,INSERT_VALUES);CHKERRQ(ierr); } else if ((i > 0 && i < mx-1) || (j > 0 && j < my-1)){ value = .5*two*(hydhx + hxdhy); ierr = MatSetValues(jac,1,&grow,1,&grow,&value,INSERT_VALUES);CHKERRQ(ierr); } else { value = .25*two*(hydhx + hxdhy); ierr = MatSetValues(jac,1,&grow,1,&grow,&value,INSERT_VALUES);CHKERRQ(ierr); } } } ierr = MatAssemblyBegin(jac,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = MatAssemblyEnd(jac,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); return 0; }
int ComputeB(AppCtx* user) { int info; PetscInt i,j,k; PetscInt nx,ny,xs,xm,gxs,gxm,ys,ym,gys,gym; PetscReal two=2.0, pi=4.0*atan(1.0); PetscReal hx,hy,ehxhy; PetscReal temp,*b; PetscReal ecc=user->ecc; nx=user->nx; ny=user->ny; hx=two*pi/(nx+1.0); hy=two*user->b/(ny+1.0); ehxhy = ecc*hx*hy; /* Get local grid boundaries */ info = DAGetCorners(user->da,&xs,&ys,TAO_NULL,&xm,&ym,TAO_NULL); CHKERRQ(info); info = DAGetGhostCorners(user->da,&gxs,&gys,TAO_NULL,&gxm,&gym,TAO_NULL); CHKERRQ(info); /* Compute the linear term in the objective function */ info = VecGetArray(user->B,&b); CHKERRQ(info); for (i=xs; i<xs+xm; i++){ temp=sin((i+1)*hx); for (j=ys; j<ys+ym; j++){ k=xm*(j-ys)+(i-xs); b[k]= - ehxhy*temp; } } info = VecRestoreArray(user->B,&b); CHKERRQ(info); info = PetscLogFlops(5*xm*ym+3*xm); CHKERRQ(info); return 0; }
PetscErrorCode FormInitialGuess1(AppCtx *user,Vec X) { PetscInt i,j,k,loc,mx,my,mz,xs,ys,zs,xm,ym,zm,Xm,Ym,Zm,Xs,Ys,Zs,base1; PetscErrorCode ierr; PetscReal one = 1.0,lambda,temp1,temp,Hx,Hy; PetscScalar *x; Vec localX = user->localX; mx = user->mx; my = user->my; mz = user->mz; lambda = user->param; Hx = one / (PetscReal)(mx-1); Hy = one / (PetscReal)(my-1); ierr = VecGetArray(localX,&x);CHKERRQ(ierr); temp1 = lambda/(lambda + one); 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++) { temp = (PetscReal)(PetscMin(j,my-j-1))*Hy; for (i=xs; i<xs+xm; i++) { loc = base1 + i-Xs + (j-Ys)*Xm; if (i == 0 || j == 0 || k == 0 || i==mx-1 || j==my-1 || k==mz-1) { x[loc] = 0.0; continue; } x[loc] = temp1*sqrt(PetscMin((PetscReal)(PetscMin(i,mx-i-1))*Hx,temp)); } } } ierr = VecRestoreArray(localX,&x);CHKERRQ(ierr); /* stick values into global vector */ ierr = DALocalToGlobal(user->da,localX,INSERT_VALUES,X);CHKERRQ(ierr); return 0; }/* -------------------- Evaluate Function F(x) --------------------- */
/* MSA_BoundaryConditions - Calculates the boundary conditions for the region. Input Parameter: . user - user-defined application context Output Parameter: . user - user-defined application context */ static int MSA_BoundaryConditions(AppCtx * user) { int info; PetscInt i,j,k,limit=0,maxits=5; PetscInt xs,ys,xm,ym,gxs,gys,gxm,gym; PetscInt mx=user->mx,my=user->my; PetscInt bsize=0, lsize=0, tsize=0, rsize=0; double one=1.0, two=2.0, three=3.0, tol=1e-10; double fnorm,det,hx,hy,xt=0,yt=0; double u1,u2,nf1,nf2,njac11,njac12,njac21,njac22; double b=-0.5, t=0.5, l=-0.5, r=0.5; double *boundary; PetscTruth flg; /* Get local mesh boundaries */ info = DAGetCorners(user->da,&xs,&ys,PETSC_NULL,&xm,&ym,PETSC_NULL); CHKERRQ(info); info = DAGetGhostCorners(user->da,&gxs,&gys,PETSC_NULL,&gxm,&gym,PETSC_NULL); CHKERRQ(info); bsize=xm+2; lsize=ym+2; rsize=ym+2; tsize=xm+2; info = PetscMalloc(bsize*sizeof(double),&user->bottom); CHKERRQ(info); info = PetscMalloc(tsize*sizeof(double),&user->top); CHKERRQ(info); info = PetscMalloc(lsize*sizeof(double),&user->left); CHKERRQ(info); info = PetscMalloc(rsize*sizeof(double),&user->right); CHKERRQ(info); hx= (r-l)/(mx+1); hy=(t-b)/(my+1); for (j=0; j<4; j++){ if (j==0){ yt=b; xt=l+hx*xs; limit=bsize; boundary=user->bottom; } else if (j==1){ yt=t; xt=l+hx*xs; limit=tsize; boundary=user->top; } else if (j==2){ yt=b+hy*ys; xt=l; limit=lsize; boundary=user->left; } else { //if (j==3) yt=b+hy*ys; xt=r; limit=rsize; boundary=user->right; } for (i=0; i<limit; i++){ u1=xt; u2=-yt; for (k=0; k<maxits; k++){ nf1=u1 + u1*u2*u2 - u1*u1*u1/three-xt; nf2=-u2 - u1*u1*u2 + u2*u2*u2/three-yt; fnorm=sqrt(nf1*nf1+nf2*nf2); if (fnorm <= tol) break; njac11=one+u2*u2-u1*u1; njac12=two*u1*u2; njac21=-two*u1*u2; njac22=-one - u1*u1 + u2*u2; det = njac11*njac22-njac21*njac12; u1 = u1-(njac22*nf1-njac12*nf2)/det; u2 = u2-(njac11*nf2-njac21*nf1)/det; } boundary[i]=u1*u1-u2*u2; if (j==0 || j==1) { xt=xt+hx; } else { // if (j==2 || j==3) yt=yt+hy; } } } /* Scale the boundary if desired */ if (1==1){ PetscReal scl = 1.0; info = PetscOptionsGetReal(PETSC_NULL,"-bottom",&scl,&flg); CHKERRQ(info); if (flg){ for (i=0;i<bsize;i++) user->bottom[i]*=scl; } info = PetscOptionsGetReal(PETSC_NULL,"-top",&scl,&flg); CHKERRQ(info); if (flg){ for (i=0;i<tsize;i++) user->top[i]*=scl; } info = PetscOptionsGetReal(PETSC_NULL,"-right",&scl,&flg); CHKERRQ(info); if (flg){ for (i=0;i<rsize;i++) user->right[i]*=scl; } info = PetscOptionsGetReal(PETSC_NULL,"-left",&scl,&flg); CHKERRQ(info); if (flg){ for (i=0;i<lsize;i++) user->left[i]*=scl; } } return 0; }
/* QuadraticH - Evaluates Hessian matrix. Input Parameters: . user - user-defined context, as set by TaoSetHessian() . X - input vector Output Parameter: . H - Hessian matrix */ int QuadraticH(AppCtx *user, Vec X, Mat Hessian) { int info; PetscInt i,j,k; PetscInt mx=user->mx, my=user->my; PetscInt xs,xm,gxs,gxm,ys,ym,gys,gym; double hx=1.0/(mx+1), hy=1.0/(my+1), hydhx=hy/hx, hxdhy=hx/hy; double f1,f2,f3,f4,f5,f6,d1,d2,d3,d4,d5,d6,d7,d8,xc,xl,xr,xt,xb,xlt,xrb; double hl,hr,ht,hb,hc,htl,hbr; PetscScalar **x, v[7]; MatStencil col[7],row; Vec localX; PetscTruth assembled; /* Get local mesh boundaries */ info = DAGetLocalVector(user->da,&localX);CHKERRQ(info); info = DAGetCorners(user->da,&xs,&ys,PETSC_NULL,&xm,&ym,PETSC_NULL); CHKERRQ(info); info = DAGetGhostCorners(user->da,&gxs,&gys,PETSC_NULL,&gxm,&gym,PETSC_NULL); CHKERRQ(info); /* Scatter ghost points to local vector */ info = DAGlobalToLocalBegin(user->da,X,INSERT_VALUES,localX); CHKERRQ(info); info = DAGlobalToLocalEnd(user->da,X,INSERT_VALUES,localX); CHKERRQ(info); /* Get pointers to vector data */ info = DAVecGetArray(user->da,localX,(void**)&x); /* Initialize matrix entries to zero */ info = MatAssembled(Hessian,&assembled); CHKERRQ(info); if (assembled){info = MatZeroEntries(Hessian); CHKERRQ(info);} /* Set various matrix options */ info = MatSetOption(Hessian,MAT_IGNORE_OFF_PROC_ENTRIES,PETSC_TRUE); CHKERRQ(info); /* Compute Hessian over the locally owned part of the mesh */ for (j=ys; j<ys+ym; j++){ for (i=xs; i< xs+xm; i++){ xc = x[j][i]; xlt=xrb=xl=xr=xb=xt=xc; /* Left side */ if (i==0){ xl = user->left[j-ys+1]; xlt = user->left[j-ys+2]; } else { xl = x[j][i-1]; } if (j==0){ xb = user->bottom[i-xs+1]; xrb = user->bottom[i-xs+2]; } else { xb = x[j-1][i]; } if (i+1 == mx){ xr = user->right[j-ys+1]; xrb = user->right[j-ys]; } else { xr = x[j][i+1]; } if (j+1==my){ xt = user->top[i-xs+1]; xlt = user->top[i-xs]; }else { xt = x[j+1][i]; } if (i>0 && j+1<my){ xlt = x[j+1][i-1]; } if (j>0 && i+1<mx){ xrb = x[j-1][i+1]; } d1 = (xc-xl)/hx; d2 = (xc-xr)/hx; d3 = (xc-xt)/hy; d4 = (xc-xb)/hy; d5 = (xrb-xr)/hy; d6 = (xrb-xb)/hx; d7 = (xlt-xl)/hy; d8 = (xlt-xt)/hx; f1 = sqrt( 1.0 + d1*d1 + d7*d7); f2 = sqrt( 1.0 + d1*d1 + d4*d4); f3 = sqrt( 1.0 + d3*d3 + d8*d8); f4 = sqrt( 1.0 + d3*d3 + d2*d2); f5 = sqrt( 1.0 + d2*d2 + d5*d5); f6 = sqrt( 1.0 + d4*d4 + d6*d6); hl = (-hydhx*(1.0+d7*d7)+d1*d7)/(f1*f1*f1)+ (-hydhx*(1.0+d4*d4)+d1*d4)/(f2*f2*f2); hr = (-hydhx*(1.0+d5*d5)+d2*d5)/(f5*f5*f5)+ (-hydhx*(1.0+d3*d3)+d2*d3)/(f4*f4*f4); ht = (-hxdhy*(1.0+d8*d8)+d3*d8)/(f3*f3*f3)+ (-hxdhy*(1.0+d2*d2)+d2*d3)/(f4*f4*f4); hb = (-hxdhy*(1.0+d6*d6)+d4*d6)/(f6*f6*f6)+ (-hxdhy*(1.0+d1*d1)+d1*d4)/(f2*f2*f2); hbr = -d2*d5/(f5*f5*f5) - d4*d6/(f6*f6*f6); htl = -d1*d7/(f1*f1*f1) - d3*d8/(f3*f3*f3); hc = hydhx*(1.0+d7*d7)/(f1*f1*f1) + hxdhy*(1.0+d8*d8)/(f3*f3*f3) + hydhx*(1.0+d5*d5)/(f5*f5*f5) + hxdhy*(1.0+d6*d6)/(f6*f6*f6) + (hxdhy*(1.0+d1*d1)+hydhx*(1.0+d4*d4)-2*d1*d4)/(f2*f2*f2) + (hxdhy*(1.0+d2*d2)+hydhx*(1.0+d3*d3)-2*d2*d3)/(f4*f4*f4); hl/=2.0; hr/=2.0; ht/=2.0; hb/=2.0; hbr/=2.0; htl/=2.0; hc/=2.0; row.j = j; row.i = i; k=0; if (j>0){ v[k]=hb; col[k].j = j - 1; col[k].i = i; k++; } if (j>0 && i < mx -1){ v[k]=hbr; col[k].j = j - 1; col[k].i = i+1; k++; } if (i>0){ v[k]= hl; col[k].j = j; col[k].i = i-1; k++; } v[k]= hc; col[k].j = j; col[k].i = i; k++; if (i < mx-1 ){ v[k]= hr; col[k].j = j; col[k].i = i+1; k++; } if (i>0 && j < my-1 ){ v[k]= htl; col[k].j = j+1; col[k].i = i-1; k++; } if (j < my-1 ){ v[k]= ht; col[k].j = j+1; col[k].i = i; k++; } /* Set matrix values using local numbering, which was defined earlier, in the main routine. */ info = MatSetValuesStencil(Hessian,1,&row,k,col,v,INSERT_VALUES); CHKERRQ(info); } } /* Restore vectors */ info = DAVecRestoreArray(user->da,localX,(void**)&x); info = DARestoreLocalVector(user->da,&localX); CHKERRQ(info); /* Assemble the matrix */ info = MatAssemblyBegin(Hessian,MAT_FINAL_ASSEMBLY); CHKERRQ(info); info = MatAssemblyEnd(Hessian,MAT_FINAL_ASSEMBLY); CHKERRQ(info); info = PetscLogFlops(199*xm*ym); CHKERRQ(info); return 0; }
/* FormFunctionGradient - Evaluates the function and corresponding gradient. Input Parameters: . taoapp - the TAO_APPLICATION context . XX - input vector . userCtx - optional user-defined context, as set by TaoSetFunctionGradient() Output Parameters: . fcn - the newly evaluated function . GG - vector containing the newly evaluated gradient */ int FormFunctionGradient(TAO_APPLICATION taoapp, Vec X, double *fcn,Vec G,void *userCtx){ AppCtx * user = (AppCtx *) userCtx; int info; PetscInt i,j; PetscInt mx=user->mx, my=user->my; PetscInt xs,xm,gxs,gxm,ys,ym,gys,gym; double ft=0; double hx=1.0/(mx+1),hy=1.0/(my+1), hydhx=hy/hx, hxdhy=hx/hy, area=0.5*hx*hy; double rhx=mx+1, rhy=my+1; double f1,f2,f3,f4,f5,f6,d1,d2,d3,d4,d5,d6,d7,d8,xc,xl,xr,xt,xb,xlt,xrb; double df1dxc,df2dxc,df3dxc,df4dxc,df5dxc,df6dxc; PetscScalar **g, **x; Vec localX; /* Get local mesh boundaries */ info = DAGetLocalVector(user->da,&localX);CHKERRQ(info); info = DAGetCorners(user->da,&xs,&ys,PETSC_NULL,&xm,&ym,PETSC_NULL); CHKERRQ(info); info = DAGetGhostCorners(user->da,&gxs,&gys,PETSC_NULL,&gxm,&gym,PETSC_NULL); CHKERRQ(info); /* Scatter ghost points to local vector */ info = DAGlobalToLocalBegin(user->da,X,INSERT_VALUES,localX); CHKERRQ(info); info = DAGlobalToLocalEnd(user->da,X,INSERT_VALUES,localX); CHKERRQ(info); /* Get pointers to vector data */ info = DAVecGetArray(user->da,localX,(void**)&x); info = DAVecGetArray(user->da,G,(void**)&g); /* Compute function and gradient over the locally owned part of the mesh */ for (j=ys; j<ys+ym; j++){ for (i=xs; i< xs+xm; i++){ xc = x[j][i]; xlt=xrb=xl=xr=xb=xt=xc; if (i==0){ /* left side */ xl= user->left[j-ys+1]; xlt = user->left[j-ys+2]; } else { xl = x[j][i-1]; } if (j==0){ /* bottom side */ xb=user->bottom[i-xs+1]; xrb =user->bottom[i-xs+2]; } else { xb = x[j-1][i]; } if (i+1 == gxs+gxm){ /* right side */ xr=user->right[j-ys+1]; xrb = user->right[j-ys]; } else { xr = x[j][i+1]; } if (j+1==gys+gym){ /* top side */ xt=user->top[i-xs+1]; xlt = user->top[i-xs]; }else { xt = x[j+1][i]; } if (i>gxs && j+1<gys+gym){ xlt = x[j+1][i-1]; } if (j>gys && i+1<gxs+gxm){ xrb = x[j-1][i+1]; } d1 = (xc-xl); d2 = (xc-xr); d3 = (xc-xt); d4 = (xc-xb); d5 = (xr-xrb); d6 = (xrb-xb); d7 = (xlt-xl); d8 = (xt-xlt); df1dxc = d1*hydhx; df2dxc = ( d1*hydhx + d4*hxdhy ); df3dxc = d3*hxdhy; df4dxc = ( d2*hydhx + d3*hxdhy ); df5dxc = d2*hydhx; df6dxc = d4*hxdhy; d1 *= rhx; d2 *= rhx; d3 *= rhy; d4 *= rhy; d5 *= rhy; d6 *= rhx; d7 *= rhy; d8 *= rhx; f1 = sqrt( 1.0 + d1*d1 + d7*d7); f2 = sqrt( 1.0 + d1*d1 + d4*d4); f3 = sqrt( 1.0 + d3*d3 + d8*d8); f4 = sqrt( 1.0 + d3*d3 + d2*d2); f5 = sqrt( 1.0 + d2*d2 + d5*d5); f6 = sqrt( 1.0 + d4*d4 + d6*d6); f2 = sqrt( 1.0 + d1*d1 + d4*d4); f4 = sqrt( 1.0 + d3*d3 + d2*d2); ft = ft + (f2 + f4); df1dxc /= f1; df2dxc /= f2; df3dxc /= f3; df4dxc /= f4; df5dxc /= f5; df6dxc /= f6; g[j][i] = (df1dxc+df2dxc+df3dxc+df4dxc+df5dxc+df6dxc ) * 0.5; } } /* Compute triangular areas along the border of the domain. */ if (xs==0){ /* left side */ for (j=ys; j<ys+ym; j++){ d3=(user->left[j-ys+1] - user->left[j-ys+2])*rhy; d2=(user->left[j-ys+1] - x[j][0]) *rhx; ft = ft+sqrt( 1.0 + d3*d3 + d2*d2); } } if (ys==0){ /* bottom side */ for (i=xs; i<xs+xm; i++){ d2=(user->bottom[i+1-xs]-user->bottom[i-xs+2])*rhx; d3=(user->bottom[i-xs+1]-x[0][i])*rhy; ft = ft+sqrt( 1.0 + d3*d3 + d2*d2); } } if (xs+xm==mx){ /* right side */ for (j=ys; j< ys+ym; j++){ d1=(x[j][mx-1] - user->right[j-ys+1])*rhx; d4=(user->right[j-ys]-user->right[j-ys+1])*rhy; ft = ft+sqrt( 1.0 + d1*d1 + d4*d4); } } if (ys+ym==my){ /* top side */ for (i=xs; i<xs+xm; i++){ d1=(x[my-1][i] - user->top[i-xs+1])*rhy; d4=(user->top[i-xs+1] - user->top[i-xs])*rhx; ft = ft+sqrt( 1.0 + d1*d1 + d4*d4); } } if (ys==0 && xs==0){ d1=(user->left[0]-user->left[1])/hy; d2=(user->bottom[0]-user->bottom[1])*rhx; ft +=sqrt( 1.0 + d1*d1 + d2*d2); } if (ys+ym == my && xs+xm == mx){ d1=(user->right[ym+1] - user->right[ym])*rhy; d2=(user->top[xm+1] - user->top[xm])*rhx; ft +=sqrt( 1.0 + d1*d1 + d2*d2); } ft=ft*area; info = MPI_Allreduce(&ft,fcn,1,MPI_DOUBLE,MPI_SUM,MPI_COMM_WORLD);CHKERRQ(info); /* Restore vectors */ info = DAVecRestoreArray(user->da,localX,(void**)&x); info = DAVecRestoreArray(user->da,G,(void**)&g); /* Scatter values to global vector */ info = DARestoreLocalVector(user->da,&localX); CHKERRQ(info); info = PetscLogFlops(67*xm*ym); CHKERRQ(info); return 0; }
/* FormHessian computes the quadratic term in the quadratic objective function Notice that the objective function in this problem is quadratic (therefore a constant hessian). If using a nonquadratic solver, then you might want to reconsider this function */ int FormHessian(TAO_APPLICATION taoapp,Vec X,Mat *H, Mat *Hpre, MatStructure *flg, void *ptr) { AppCtx* user=(AppCtx*)ptr; int info; PetscInt i,j,k; PetscInt col[5],row,nx,ny,xs,xm,gxs,gxm,ys,ym,gys,gym; PetscReal one=1.0, two=2.0, six=6.0,pi=4.0*atan(1.0); PetscReal hx,hy,hxhy,hxhx,hyhy; PetscReal xi,v[5]; PetscReal ecc=user->ecc, trule1,trule2,trule3,trule4,trule5,trule6; PetscReal vmiddle, vup, vdown, vleft, vright; Mat hes=*H; PetscTruth assembled; nx=user->nx; ny=user->ny; hx=two*pi/(nx+1.0); hy=two*user->b/(ny+1.0); hxhy=hx*hy; hxhx=one/(hx*hx); hyhy=one/(hy*hy); *flg=SAME_NONZERO_PATTERN; /* Get local grid boundaries */ info = DAGetCorners(user->da,&xs,&ys,TAO_NULL,&xm,&ym,TAO_NULL); CHKERRQ(info); info = DAGetGhostCorners(user->da,&gxs,&gys,TAO_NULL,&gxm,&gym,TAO_NULL); CHKERRQ(info); info = MatAssembled(hes,&assembled); CHKERRQ(info); if (assembled){info = MatZeroEntries(hes); CHKERRQ(info);} for (i=xs; i< xs+xm; i++){ xi=(i+1)*hx; trule1=hxhy*( p(xi,ecc) + p(xi+hx,ecc) + p(xi,ecc) ) / six; /* L(i,j) */ trule2=hxhy*( p(xi,ecc) + p(xi-hx,ecc) + p(xi,ecc) ) / six; /* U(i,j) */ trule3=hxhy*( p(xi,ecc) + p(xi+hx,ecc) + p(xi+hx,ecc) ) / six; /* U(i+1,j) */ trule4=hxhy*( p(xi,ecc) + p(xi-hx,ecc) + p(xi-hx,ecc) ) / six; /* L(i-1,j) */ trule5=trule1; /* L(i,j-1) */ trule6=trule2; /* U(i,j+1) */ vdown=-(trule5+trule2)*hyhy; vleft=-hxhx*(trule2+trule4); vright= -hxhx*(trule1+trule3); vup=-hyhy*(trule1+trule6); vmiddle=(hxhx)*(trule1+trule2+trule3+trule4)+hyhy*(trule1+trule2+trule5+trule6); v[0]=0; v[1]=0; v[2]=0; v[3]=0; v[4]=0; for (j=ys; j<ys+ym; j++){ row=(j-gys)*gxm + (i-gxs); k=0; if (j>gys){ v[k]=vdown; col[k]=row - gxm; k++; } if (i>gxs){ v[k]= vleft; col[k]=row - 1; k++; } v[k]= vmiddle; col[k]=row; k++; if (i+1 < gxs+gxm){ v[k]= vright; col[k]=row+1; k++; } if (j+1 <gys+gym){ v[k]= vup; col[k] = row+gxm; k++; } info = MatSetValuesLocal(hes,1,&row,k,col,v,INSERT_VALUES); CHKERRQ(info); } } /* Assemble matrix, using the 2-step process: MatAssemblyBegin(), MatAssemblyEnd(). By placing code between these two statements, computations can be done while messages are in transition. */ info = MatAssemblyBegin(hes,MAT_FINAL_ASSEMBLY); CHKERRQ(info); info = MatAssemblyEnd(hes,MAT_FINAL_ASSEMBLY); CHKERRQ(info); /* Tell the matrix we will never add a new nonzero location to the matrix. If we do it will generate an error. */ info = MatSetOption(hes,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_TRUE); CHKERRQ(info); info = MatSetOption(hes,MAT_SYMMETRIC,PETSC_TRUE); CHKERRQ(info); info = PetscLogFlops(9*xm*ym+49*xm); CHKERRQ(info); return 0; }
int FormFunctionGradient(TAO_APPLICATION taoapp, Vec X, double *fcn,Vec G,void *ptr) { AppCtx* user=(AppCtx*)ptr; int info; PetscInt i,j,k,kk; PetscInt col[5],row,nx,ny,xs,xm,gxs,gxm,ys,ym,gys,gym; PetscReal one=1.0, two=2.0, six=6.0,pi=4.0*atan(1.0); PetscReal hx,hy,hxhy,hxhx,hyhy; PetscReal xi,v[5]; PetscReal ecc=user->ecc, trule1,trule2,trule3,trule4,trule5,trule6; PetscReal vmiddle, vup, vdown, vleft, vright; PetscReal tt,f1,f2; PetscReal *x,*g,zero=0.0; Vec localX; nx=user->nx; ny=user->ny; hx=two*pi/(nx+1.0); hy=two*user->b/(ny+1.0); hxhy=hx*hy; hxhx=one/(hx*hx); hyhy=one/(hy*hy); info = DAGetLocalVector(user->da,&localX);CHKERRQ(info); info = DAGlobalToLocalBegin(user->da,X,INSERT_VALUES,localX); CHKERRQ(info); info = DAGlobalToLocalEnd(user->da,X,INSERT_VALUES,localX); CHKERRQ(info); info = VecSet(G, zero); CHKERRQ(info); /* Get local grid boundaries */ info = DAGetCorners(user->da,&xs,&ys,TAO_NULL,&xm,&ym,TAO_NULL); CHKERRQ(info); info = DAGetGhostCorners(user->da,&gxs,&gys,TAO_NULL,&gxm,&gym,TAO_NULL); CHKERRQ(info); info = VecGetArray(localX,&x); CHKERRQ(info); info = VecGetArray(G,&g); CHKERRQ(info); for (i=xs; i< xs+xm; i++){ xi=(i+1)*hx; trule1=hxhy*( p(xi,ecc) + p(xi+hx,ecc) + p(xi,ecc) ) / six; /* L(i,j) */ trule2=hxhy*( p(xi,ecc) + p(xi-hx,ecc) + p(xi,ecc) ) / six; /* U(i,j) */ trule3=hxhy*( p(xi,ecc) + p(xi+hx,ecc) + p(xi+hx,ecc) ) / six; /* U(i+1,j) */ trule4=hxhy*( p(xi,ecc) + p(xi-hx,ecc) + p(xi-hx,ecc) ) / six; /* L(i-1,j) */ trule5=trule1; /* L(i,j-1) */ trule6=trule2; /* U(i,j+1) */ vdown=-(trule5+trule2)*hyhy; vleft=-hxhx*(trule2+trule4); vright= -hxhx*(trule1+trule3); vup=-hyhy*(trule1+trule6); vmiddle=(hxhx)*(trule1+trule2+trule3+trule4)+hyhy*(trule1+trule2+trule5+trule6); for (j=ys; j<ys+ym; j++){ row=(j-gys)*gxm + (i-gxs); v[0]=0; v[1]=0; v[2]=0; v[3]=0; v[4]=0; k=0; if (j>gys){ v[k]=vdown; col[k]=row - gxm; k++; } if (i>gxs){ v[k]= vleft; col[k]=row - 1; k++; } v[k]= vmiddle; col[k]=row; k++; if (i+1 < gxs+gxm){ v[k]= vright; col[k]=row+1; k++; } if (j+1 <gys+gym){ v[k]= vup; col[k] = row+gxm; k++; } tt=0; for (kk=0;kk<k;kk++){ tt+=v[kk]*x[col[kk]]; } row=(j-ys)*xm + (i-xs); g[row]=tt; } } info = VecRestoreArray(localX,&x); CHKERRQ(info); info = VecRestoreArray(G,&g); CHKERRQ(info); info = DARestoreLocalVector(user->da,&localX); CHKERRQ(info); info = VecDot(X,G,&f1); CHKERRQ(info); info = VecDot(user->B,X,&f2); CHKERRQ(info); info = VecAXPY(G, one, user->B); CHKERRQ(info); *fcn = f1/2.0 + f2; info = PetscLogFlops((91 + 10*ym) * xm); CHKERRQ(info); return 0; }
/* FormJacobian - Evaluates Jacobian matrix. Input Parameters: . ot - the OT context . x - input vector . ptr - optional user-defined context, as set by OTSetJacobian() Output Parameters: . A - Jacobian matrix . B - optionally different preconditioning matrix . flag - flag indicating matrix structure Notes: Due to grid point reordering with DAs, we must always work with the local grid points, and then transform them to the new global numbering with the "ltog" mapping (via DAGetGlobalIndices()). We cannot work directly with the global numbers for the original uniprocessor grid! Two methods are available for imposing this transformation when setting matrix entries: (A) MatSetValuesLocal(), using the local ordering (including ghost points!) - Use DAGetGlobalIndices() to extract the local-to-global map - Associate this map with the matrix by calling MatSetLocalToGlobalMapping() once - Set matrix entries using the local ordering by calling MatSetValuesLocal() (B) MatSetValues(), using the global ordering - Use DAGetGlobalIndices() to extract the local-to-global map - Then apply this map explicitly yourself - Set matrix entries using the global ordering by calling MatSetValues() Option (A) seems cleaner/easier in many cases, and is the procedure used in this example. */ int FormJacobian(TAO_SOLVER ot,Vec X,Mat *JJ,void *ptr) { AppCtx *user = (AppCtx *) ptr; /* user-defined application context */ Mat jac=*JJ; Vec localX=user->localX; // local vector int info, i, j, row, mx, my, col[5]; int xs, ys, xm, ym, gxs, gys, gxm, gym; PetscScalar two = 2.0, one = 1.0, lambda, v[5], hx, hy, hxdhy, hydhx, sc, *x; mx = user->mx; my = user->my; lambda = user->param; hx = one/(double)(mx-1); hy = one/(double)(my-1); sc = hx*hy; hxdhy = hx/hy; hydhx = hy/hx; /* Scatter ghost points to local vector, using the 2-step process DAGlobalToLocalBegin(), DAGlobalToLocalEnd(). By placing code between these two statements, computations can be done while messages are in transition. */ // info = DAGetLocalVector(user->da,&(user->localX)); CHKERRQ(info); info = DAGlobalToLocalBegin(user->da,X,INSERT_VALUES,localX); CHKERRQ(info); info = DAGlobalToLocalEnd(user->da,X,INSERT_VALUES,localX); CHKERRQ(info); /* Get pointer to vector data */ info = VecGetArray(localX,&x); CHKERRQ(info); /* Get local grid boundaries */ info = DAGetCorners(user->da,&xs,&ys,PETSC_NULL,&xm,&ym,PETSC_NULL); CHKERRQ(info); info = DAGetGhostCorners(user->da,&gxs,&gys,PETSC_NULL,&gxm,&gym,PETSC_NULL); CHKERRQ(info); /* Compute entries for the locally owned part of the Jacobian. - Currently, all PETSc parallel matrix formats are partitioned by contiguous chunks of rows across the processors. - Each processor needs to insert only elements that it owns locally (but any non-local elements will be sent to the appropriate processor during matrix assembly). - Here, we set all entries for a particular row at once. - We can set matrix entries either using either MatSetValuesLocal() or MatSetValues(), as discussed above. */ for (j=ys; j<ys+ym; j++) { row = (j - gys)*gxm + xs - gxs - 1; for (i=xs; i<xs+xm; i++) { row++; /* boundary points */ if (i == 0 || j == 0 || i == mx-1 || j == my-1 ) { info = MatSetValuesLocal(jac,1,&row,1,&row,&one,INSERT_VALUES); CHKERRQ(info); continue; } /* interior grid points */ v[0] = -hxdhy; col[0] = row - gxm; v[1] = -hydhx; col[1] = row - 1; v[2] = two*(hydhx + hxdhy) - sc*lambda*exp(x[row]); col[2] = row; v[3] = -hydhx; col[3] = row + 1; v[4] = -hxdhy; col[4] = row + gxm; info = MatSetValuesLocal(jac,1,&row,5,col,v,INSERT_VALUES); CHKERRQ(info); } } /* Assemble matrix, using the 2-step process: MatAssemblyBegin(), MatAssemblyEnd(). By placing code between these two statements, computations can be done while messages are in transition. */ info = MatAssemblyBegin(jac,MAT_FINAL_ASSEMBLY); CHKERRQ(info); info = VecRestoreArray(localX,&x); CHKERRQ(info); info = MatAssemblyEnd(jac,MAT_FINAL_ASSEMBLY); CHKERRQ(info); /* Set flag to indicate that the Jacobian matrix retains an identical nonzero structure throughout all nonlinear iterations (although the values of the entries change). Thus, we can save some work in setting up the preconditioner (e.g., no need to redo symbolic factorization for ILU/ICC preconditioners). - If the nonzero structure of the matrix is different during successive linear solves, then the flag DIFFERENT_NONZERO_PATTERN must be used instead. If you are unsure whether the matrix structure has changed or not, use the flag DIFFERENT_NONZERO_PATTERN. - Caution: If you specify SAME_NONZERO_PATTERN, PETSc believes your assertion and does not check the structure of the matrix. If you erroneously claim that the structure is the same when it actually is not, the new preconditioner will not function correctly. Thus, use this optimization feature with caution! */ /* Tell the matrix we will never add a new nonzero location to the matrix. If we do it will generate an error. */ info = MatSetOption(jac,MAT_NEW_NONZERO_LOCATION_ERR);CHKERRQ(info); return 0; }
/* FormResidual - Evaluates nonlinear function, F(x). Input Parameters: . ot - the OT context . X - input vector . ptr - optional user-defined context, as set by OTSetFunction() Output Parameter: . F - function vector */ int FormResidual(TAO_SOLVER ot,Vec X,Vec F,void *ptr) { AppCtx *user = (AppCtx *) ptr; int info, i, j, row, mx, my, xs, ys, xm, ym, gxs, gys, gxm, gym; double two = 2.0, one = 1.0, lambda,hx, hy, hxdhy, hydhx,sc; PetscScalar u, uxx, uyy, *x,*f; Vec localX=user->localX,localF=user->localF; mx = user->mx; my = user->my; lambda = user->param; hx = one/(double)(mx-1); hy = one/(double)(my-1); sc = hx*hy*lambda; hxdhy = hx/hy; hydhx = hy/hx; /* Scatter ghost points to local vector, using the 2-step process DAGlobalToLocalBegin(), DAGlobalToLocalEnd(). By placing code between these two statements, computations can be done while messages are in transition. */ // info = DAGetLocalVector(user->da,&(user->localX)); CHKERRQ(info); info = DAGlobalToLocalBegin(user->da,X,INSERT_VALUES,localX); CHKERRQ(info); info = DAGlobalToLocalEnd(user->da,X,INSERT_VALUES,localX); CHKERRQ(info); /* Get pointers to vector data */ info = VecGetArray(localX,&x); CHKERRQ(info); info = VecGetArray(localF,&f); CHKERRQ(info); /* Get local grid boundaries */ info = DAGetCorners(user->da,&xs,&ys,PETSC_NULL,&xm,&ym,PETSC_NULL); CHKERRQ(info); info = DAGetGhostCorners(user->da,&gxs,&gys,PETSC_NULL,&gxm,&gym,PETSC_NULL); CHKERRQ(info); /* 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*exp(u); } } /* Restore vectors */ info = VecRestoreArray(localX,&x); CHKERRQ(info); info = VecRestoreArray(localF,&f); CHKERRQ(info); /* Insert values into global vector */ info = DALocalToGlobal(user->da,localF,INSERT_VALUES,F); CHKERRQ(info); PetscLogFlops(11*ym*xm); return 0; }
/* FormInitialGuess - Forms initial approximation. Input Parameters: user - user-defined application context X - vector Output Parameter: X - vector */ int FormInitialGuess(AppCtx *user,Vec X) { int i, j, row, mx, my, info, xs, ys, xm, ym, gxm, gym, gxs, gys; double one = 1.0, lambda, temp1, temp, hx, hy; PetscScalar *x; mx = user->mx; my = user->my; lambda = user->param; hx = one/(double)(mx-1); hy = one/(double)(my-1); temp1 = lambda/(lambda + one); /* Get a pointer to vector data. - For default PETSc vectors, VecGetArray() returns a pointer to the data array. Otherwise, the routine is implementation dependent. - You MUST call VecRestoreArray() when you no longer need access to the array. */ info = VecGetArray(user->localX,&x); CHKERRQ(info); /* Since we don't need the data from ghost points, we do not need to call DAGlobalToLocal functions */ /* Get local grid boundaries (for 2-dimensional DA): xs, ys - starting grid indices (no ghost points) xm, ym - widths of local grid (no ghost points) gxs, gys - starting grid indices (including ghost points) gxm, gym - widths of local grid (including ghost points) */ info = DAGetCorners(user->da,&xs,&ys,PETSC_NULL,&xm,&ym,PETSC_NULL); CHKERRQ(info); info = DAGetGhostCorners(user->da,&gxs,&gys,PETSC_NULL,&gxm,&gym,PETSC_NULL); CHKERRQ(info); /* Compute initial guess over the locally owned part of the grid */ for (j=ys; j<ys+ym; j++) { temp = (double)(PetscMin(j,my-j-1))*hy; for (i=xs; i<xs+xm; i++) { row = i - gxs + (j - gys)*gxm; if (i == 0 || j == 0 || i == mx-1 || j == my-1 ) { x[row] = 0.0; continue; } x[row] = temp1*sqrt( PetscMin( (double)(PetscMin(i,mx-i-1))*hx,temp) ); } } /* Restore vector */ info = VecRestoreArray(user->localX,&x); CHKERRQ(info); /* Insert values into global vector */ info = DALocalToGlobal(user->da,user->localX,INSERT_VALUES,X); CHKERRQ(info); return 0; }
static int TaoDA2dLoopADFunctionGradient(TAO_APPLICATION tao, DA da, Vec X, double *f, Vec G, void * ctx) { TaoDA2D1DOFADICFGCtx *myapp = (TaoDA2D1DOFADICFGCtx*) ctx; MPI_Comm comm; Vec localX, localG; int info, i, j, coor[2]; int xs, xm, gxs, gxm, xe, ys, ym, gys, gym, ye; PetscScalar **x, **g; PetscScalar floc = 0.0; PetscScalar zero = 0.0; DERIV_TYPE adF,*adX=myapp->adX; info = DAGetLocalVector(da, &localX); CHKERRQ(info); info = DAGetLocalVector(da, &localG); CHKERRQ(info); info = VecSet(G, zero); CHKERRQ(info); info = VecSet(localG, zero); CHKERRQ(info); info = DAGlobalToLocalBegin(da, X, INSERT_VALUES, localX); CHKERRQ(info); info = DAGlobalToLocalEnd(da, X, INSERT_VALUES, localX); CHKERRQ(info); info = DAVecGetArray(da, localX, (void**)&x); CHKERRQ(info); info = DAVecGetArray(da, localG, (void**)&g); CHKERRQ(info); info = DAGetCorners(da, &xs, &ys, PETSC_NULL, &xm, &ym, PETSC_NULL); CHKERRQ(info); info = DAGetGhostCorners(da, &gxs, &gys, PETSC_NULL, &gxm, &gym, PETSC_NULL); CHKERRQ(info); xe = gxs + gxm - 1; ye = gys + gym - 1; for (j = ys; j < ye; j++) { for (i = xs; i < xe; i++) { DERIV_val(adX[0]) = x[j][i]; DERIV_val(adX[1]) = x[j][i+1]; DERIV_val(adX[2]) = x[j+1][i]; DERIV_val(adX[3]) = x[j+1][i+1]; coor[0] = i; coor[1] = j; info = myapp->computeadicfunctiongradient(coor,adX,&adF,myapp->elementfgctx); CHKERRQ(info); floc += DERIV_val(adF); g[j][i] += DERIV_grad(adF)[0]; g[j][i+1] += DERIV_grad(adF)[1]; g[j+1][i] += DERIV_grad(adF)[2]; g[j+1][i+1] += DERIV_grad(adF)[3]; } } PetscLogFlops((ye-ys)*(xe-xs)*(myapp->elementfgflops + 5)); PetscObjectGetComm((PetscObject)da,&comm); CHKERRQ(info); info = MPI_Allreduce(&floc, f, 1, MPI_DOUBLE, MPI_SUM, comm); CHKERRQ(info); info = DAVecRestoreArray(da, localX, (void**)&x); CHKERRQ(info); info = DAVecRestoreArray(da, localG, (void**)&g); CHKERRQ(info); info = DALocalToGlobalBegin(da, localG, G); CHKERRQ(info); info = DALocalToGlobalEnd(da, localG, G); CHKERRQ(info); info = DARestoreLocalVector(da, &localX); CHKERRQ(info); info = DARestoreLocalVector(da, &localG); CHKERRQ(info); PetscFunctionReturn(0); } /* TaoDA2dLoopADFunctionGradient */
/* WholeMSurfHessian - Evaluates Hessian over the whole grid Input: daapplication - TAO application object da - distributed array X - the current point, at which the function and gradient are evaluated ptr - user-defined application context Output: H - Hessian at X */ static int WholeMSurfHessian(TAO_APPLICATION daapplication, DA da, Vec X, Mat H, void *ptr) { AppCtx *user = (AppCtx*)ptr; Vec localX; int info; PetscInt i, j, ind[4]; PetscInt xs, xm, gxs, gxm, xe, ys, ym, gys, gym, ye; double smallH[4][4]; double **x; double hx, hy, area, byhxhx, byhyhy; double dvdx, dvdy, flow, fup; double areadivf, areadivf3; PetscTruth assembled; hx = user->hx; hy = user->hy; area = user->area; byhxhx = 1.0 / (hx * hx); byhyhy = 1.0 / (hy * hy); info = DAGetLocalVector(da, &localX); CHKERRQ(info); info = MatAssembled(H,&assembled); CHKERRQ(info); if (assembled){info = MatZeroEntries(H); CHKERRQ(info);} info = DAGlobalToLocalBegin(da, X, INSERT_VALUES, localX); CHKERRQ(info); info = DAGlobalToLocalEnd(da, X, INSERT_VALUES, localX); CHKERRQ(info); info = DAVecGetArray(da, localX, (void**)&x); CHKERRQ(info); info = DAGetCorners(da, &xs, &ys, TAO_NULL, &xm, &ym, TAO_NULL); CHKERRQ(info); info = DAGetGhostCorners(da, &gxs, &gys, TAO_NULL, &gxm, &gym, TAO_NULL); CHKERRQ(info); xe = gxs + gxm - 1; ye = gys + gym - 1; for (j = ys; j < ye; j++) { for (i = xs; i < xe; i++) { /* 0 is 0,0; 1 is 1,0; 2 is 0,1; 3 is 1,1 */ dvdx = (x[j][i] - x[j][i+1]) / hx; /* lower triangle contribution */ dvdy = (x[j][i] - x[j+1][i]) / hy; flow = sqrt( 1 + dvdx * dvdx + dvdy * dvdy ); dvdx = dvdx / hx; dvdy = dvdy / hy; areadivf = area / flow; areadivf3 = areadivf / (flow * flow); smallH[0][0] = areadivf * (byhxhx + byhyhy) - areadivf3 * (dvdx + dvdy) * (dvdx + dvdy); smallH[0][1] = areadivf * (-byhxhx) + areadivf3 * (dvdx + dvdy) * (dvdx); smallH[0][2] = areadivf * (-byhyhy) + areadivf3 * (dvdx + dvdy) * (dvdy); smallH[0][3] = 0.0; smallH[1][1] = areadivf * byhxhx - areadivf3 * dvdx * dvdx; smallH[1][2] = areadivf3 * (-dvdx) * dvdy; smallH[2][2] = areadivf * byhyhy - areadivf3 * dvdy * dvdy; /* upper triangle contribution */ dvdx = (x[j+1][i+1] - x[j+1][i]) / hx; dvdy = (x[j+1][i+1] - x[j][i+1]) / hy; fup = sqrt( 1 + dvdx * dvdx + dvdy * dvdy ); dvdx = dvdx / hx; dvdy = dvdy / hy; areadivf = area / fup; areadivf3 = areadivf / (fup * fup); smallH[1][1] += areadivf * byhyhy - areadivf3 * dvdy * dvdy; smallH[1][2] += areadivf3 * (-dvdy) * dvdx; smallH[2][2] += areadivf * byhxhx - areadivf3 * (dvdx * dvdx); smallH[1][3] = areadivf * (-byhyhy) + areadivf3 * (dvdx + dvdy) * dvdy; smallH[2][3] = areadivf * (-byhxhx) + areadivf3 * (dvdx + dvdy) * dvdx; smallH[3][3] = areadivf * (byhxhx + byhyhy) - areadivf3 * (dvdx + dvdy) * (dvdx + dvdy); smallH[1][0] = smallH[0][1]; smallH[2][0] = smallH[0][2]; smallH[3][0] = smallH[0][3]; smallH[2][1] = smallH[1][2]; smallH[3][1] = smallH[1][3]; smallH[3][2] = smallH[2][3]; ind[0] = (j-gys) * gxm + (i-gxs); ind[1] = ind[0] + 1; ind[2] = ind[0] + gxm; ind[3] = ind[2] + 1; info = MatSetValuesLocal(H,4,ind,4,ind,(PetscScalar*)smallH,ADD_VALUES); CHKERRQ(info); } } info = DAVecRestoreArray(da, localX, (void**)&x); CHKERRQ(info); info = MatAssemblyBegin(H, MAT_FINAL_ASSEMBLY); CHKERRQ(info); info = MatAssemblyEnd(H, MAT_FINAL_ASSEMBLY); CHKERRQ(info); info = MatSetOption(H, MAT_SYMMETRIC, PETSC_TRUE); CHKERRQ(info); info = DARestoreLocalVector(da, &localX); CHKERRQ(info); info = PetscLogFlops((xe-xs) * (ye-ys) * 83 + 4); CHKERRQ(info); return 0; } /* WholeMSurfHessian */
/* WholeMSurfFunctionGradient - Evaluates function and gradient over the whole grid Input: daapplication - TAO application object da - distributed array X - the current point, at which the function and gradient are evaluated ptr - user-defined application context Output: f - value of the objective funtion at X G - gradient at X */ static int WholeMSurfFunctionGradient(TAO_APPLICATION daapplication, DA da, Vec X, double *f, Vec G, void *ptr) { AppCtx *user = (AppCtx*)ptr; Vec localX, localG; PetscInt i, j; int info; PetscInt xs, xm, gxs, gxm, xe, ys, ym, gys, gym, ye; double **x, **g; double floc = 0.0; PetscScalar zero = 0.0; double hx, hy, area; double dvdx, dvdy, flow, fup; double areadivf; hx = user->hx; hy = user->hy; area = user->area; info = DAGetLocalVector(da, &localX); CHKERRQ(info); info = DAGetLocalVector(da, &localG); CHKERRQ(info); info = VecSet(G, zero); CHKERRQ(info); info = VecSet(localG, zero); CHKERRQ(info); info = DAGlobalToLocalBegin(da, X, INSERT_VALUES, localX); CHKERRQ(info); info = DAGlobalToLocalEnd(da, X, INSERT_VALUES, localX); CHKERRQ(info); info = DAVecGetArray(da, localX, (void**)&x); CHKERRQ(info); info = DAVecGetArray(da, localG, (void**)&g); CHKERRQ(info); info = DAGetCorners(da, &xs, &ys, TAO_NULL, &xm, &ym, TAO_NULL); CHKERRQ(info); info = DAGetGhostCorners(da, &gxs, &gys, TAO_NULL, &gxm, &gym, TAO_NULL); CHKERRQ(info); xe = gxs + gxm - 1; ye = gys + gym - 1; for (j = ys; j < ye; j++) { for (i = xs; i < xe; i++) { /* lower triangle contribution */ dvdx = (x[j][i] - x[j][i+1]) / hx; dvdy = (x[j][i] - x[j+1][i]) / hy; flow = sqrt( 1 + dvdx * dvdx + dvdy * dvdy ); areadivf = area / flow; g[j][i] += (dvdx / hx + dvdy / hy) * areadivf; g[j][i+1] += (-dvdx / hx) * areadivf; g[j+1][i] += (-dvdy / hy) * areadivf; /* upper triangle contribution */ dvdx = (x[j+1][i+1] - x[j+1][i]) / hx; dvdy = (x[j+1][i+1] - x[j][i+1]) / hy; fup = sqrt( 1 + dvdx * dvdx + dvdy * dvdy ); areadivf = area / fup; g[j][i+1] += (-dvdy / hy) * areadivf; g[j+1][i] += (-dvdx / hx) * areadivf; g[j+1][i+1] += (dvdx / hx + dvdy / hy) * areadivf; floc += area * (flow + fup); } } info = MPI_Allreduce(&floc, f, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); CHKERRQ(info); info = DAVecRestoreArray(da, localX, (void**)&x); CHKERRQ(info); info = DAVecRestoreArray(da, localG, (void**)&g); CHKERRQ(info); info = DALocalToGlobalBegin(da, localG, G); CHKERRQ(info); info = DALocalToGlobalEnd(da, localG, G); CHKERRQ(info); info = DARestoreLocalVector(da, &localX); CHKERRQ(info); info = DARestoreLocalVector(da, &localG); CHKERRQ(info); info = PetscLogFlops((xe-xs) * (ye-ys) * 42); CHKERRQ(info); return 0; } /* WholeMSurfFunctionGradient */