xref: /petsc/src/tao/bound/tutorials/jbearing2.c (revision c4762a1b19cd2af06abeed90e8f9d34fb975dd94)
1*c4762a1bSJed Brown /*
2*c4762a1bSJed Brown   Include "petsctao.h" so we can use TAO solvers
3*c4762a1bSJed Brown   Include "petscdmda.h" so that we can use distributed arrays (DMs) for managing
4*c4762a1bSJed Brown   Include "petscksp.h" so we can set KSP type
5*c4762a1bSJed Brown   the parallel mesh.
6*c4762a1bSJed Brown */
7*c4762a1bSJed Brown 
8*c4762a1bSJed Brown #include <petsctao.h>
9*c4762a1bSJed Brown #include <petscdmda.h>
10*c4762a1bSJed Brown 
11*c4762a1bSJed Brown static  char help[]=
12*c4762a1bSJed Brown "This example demonstrates use of the TAO package to \n\
13*c4762a1bSJed Brown solve a bound constrained minimization problem.  This example is based on \n\
14*c4762a1bSJed Brown the problem DPJB from the MINPACK-2 test suite.  This pressure journal \n\
15*c4762a1bSJed Brown bearing problem is an example of elliptic variational problem defined over \n\
16*c4762a1bSJed Brown a two dimensional rectangle.  By discretizing the domain into triangular \n\
17*c4762a1bSJed Brown elements, the pressure surrounding the journal bearing is defined as the \n\
18*c4762a1bSJed Brown minimum of a quadratic function whose variables are bounded below by zero.\n\
19*c4762a1bSJed Brown The command line options are:\n\
20*c4762a1bSJed Brown   -mx <xg>, where <xg> = number of grid points in the 1st coordinate direction\n\
21*c4762a1bSJed Brown   -my <yg>, where <yg> = number of grid points in the 2nd coordinate direction\n\
22*c4762a1bSJed Brown  \n";
23*c4762a1bSJed Brown 
24*c4762a1bSJed Brown /*T
25*c4762a1bSJed Brown    Concepts: TAO^Solving a bound constrained minimization problem
26*c4762a1bSJed Brown    Routines: TaoCreate();
27*c4762a1bSJed Brown    Routines: TaoSetType(); TaoSetObjectiveAndGradientRoutine();
28*c4762a1bSJed Brown    Routines: TaoSetHessianRoutine();
29*c4762a1bSJed Brown    Routines: TaoSetVariableBounds();
30*c4762a1bSJed Brown    Routines: TaoSetMonitor(); TaoSetConvergenceTest();
31*c4762a1bSJed Brown    Routines: TaoSetInitialVector();
32*c4762a1bSJed Brown    Routines: TaoSetFromOptions();
33*c4762a1bSJed Brown    Routines: TaoSolve();
34*c4762a1bSJed Brown    Routines: TaoDestroy();
35*c4762a1bSJed Brown    Processors: n
36*c4762a1bSJed Brown T*/
37*c4762a1bSJed Brown 
38*c4762a1bSJed Brown 
39*c4762a1bSJed Brown 
40*c4762a1bSJed Brown /*
41*c4762a1bSJed Brown    User-defined application context - contains data needed by the
42*c4762a1bSJed Brown    application-provided call-back routines, FormFunctionGradient(),
43*c4762a1bSJed Brown    FormHessian().
44*c4762a1bSJed Brown */
45*c4762a1bSJed Brown typedef struct {
46*c4762a1bSJed Brown   /* problem parameters */
47*c4762a1bSJed Brown   PetscReal      ecc;          /* test problem parameter */
48*c4762a1bSJed Brown   PetscReal      b;            /* A dimension of journal bearing */
49*c4762a1bSJed Brown   PetscInt       nx,ny;        /* discretization in x, y directions */
50*c4762a1bSJed Brown 
51*c4762a1bSJed Brown   /* Working space */
52*c4762a1bSJed Brown   DM          dm;           /* distributed array data structure */
53*c4762a1bSJed Brown   Mat         A;            /* Quadratic Objective term */
54*c4762a1bSJed Brown   Vec         B;            /* Linear Objective term */
55*c4762a1bSJed Brown } AppCtx;
56*c4762a1bSJed Brown 
57*c4762a1bSJed Brown /* User-defined routines */
58*c4762a1bSJed Brown static PetscReal p(PetscReal xi, PetscReal ecc);
59*c4762a1bSJed Brown static PetscErrorCode FormFunctionGradient(Tao, Vec, PetscReal *,Vec,void *);
60*c4762a1bSJed Brown static PetscErrorCode FormHessian(Tao,Vec,Mat, Mat, void *);
61*c4762a1bSJed Brown static PetscErrorCode ComputeB(AppCtx*);
62*c4762a1bSJed Brown static PetscErrorCode Monitor(Tao, void*);
63*c4762a1bSJed Brown static PetscErrorCode ConvergenceTest(Tao, void*);
64*c4762a1bSJed Brown 
65*c4762a1bSJed Brown int main( int argc, char **argv )
66*c4762a1bSJed Brown {
67*c4762a1bSJed Brown   PetscErrorCode     ierr;            /* used to check for functions returning nonzeros */
68*c4762a1bSJed Brown   PetscInt           Nx, Ny;          /* number of processors in x- and y- directions */
69*c4762a1bSJed Brown   PetscInt           m;               /* number of local elements in vectors */
70*c4762a1bSJed Brown   Vec                x;               /* variables vector */
71*c4762a1bSJed Brown   Vec                xl,xu;           /* bounds vectors */
72*c4762a1bSJed Brown   PetscReal          d1000 = 1000;
73*c4762a1bSJed Brown   PetscBool          flg,testgetdiag; /* A return variable when checking for user options */
74*c4762a1bSJed Brown   Tao                tao;             /* Tao solver context */
75*c4762a1bSJed Brown   KSP                ksp;
76*c4762a1bSJed Brown   AppCtx             user;            /* user-defined work context */
77*c4762a1bSJed Brown   PetscReal          zero = 0.0;      /* lower bound on all variables */
78*c4762a1bSJed Brown 
79*c4762a1bSJed Brown   /* Initialize PETSC and TAO */
80*c4762a1bSJed Brown   ierr = PetscInitialize( &argc, &argv,(char *)0,help );if (ierr) return ierr;
81*c4762a1bSJed Brown 
82*c4762a1bSJed Brown   /* Set the default values for the problem parameters */
83*c4762a1bSJed Brown   user.nx = 50; user.ny = 50; user.ecc = 0.1; user.b = 10.0;
84*c4762a1bSJed Brown   testgetdiag = PETSC_FALSE;
85*c4762a1bSJed Brown 
86*c4762a1bSJed Brown   /* Check for any command line arguments that override defaults */
87*c4762a1bSJed Brown   ierr = PetscOptionsGetInt(NULL,NULL,"-mx",&user.nx,&flg);CHKERRQ(ierr);
88*c4762a1bSJed Brown   ierr = PetscOptionsGetInt(NULL,NULL,"-my",&user.ny,&flg);CHKERRQ(ierr);
89*c4762a1bSJed Brown   ierr = PetscOptionsGetReal(NULL,NULL,"-ecc",&user.ecc,&flg);CHKERRQ(ierr);
90*c4762a1bSJed Brown   ierr = PetscOptionsGetReal(NULL,NULL,"-b",&user.b,&flg);CHKERRQ(ierr);
91*c4762a1bSJed Brown   ierr = PetscOptionsGetBool(NULL,NULL,"-test_getdiagonal",&testgetdiag,NULL);CHKERRQ(ierr);
92*c4762a1bSJed Brown 
93*c4762a1bSJed Brown   ierr = PetscPrintf(PETSC_COMM_WORLD,"\n---- Journal Bearing Problem SHB-----\n");CHKERRQ(ierr);
94*c4762a1bSJed Brown   ierr = PetscPrintf(PETSC_COMM_WORLD,"mx: %D,  my: %D,  ecc: %g \n\n",user.nx,user.ny,(double)user.ecc);CHKERRQ(ierr);
95*c4762a1bSJed Brown 
96*c4762a1bSJed Brown   /* Let Petsc determine the grid division */
97*c4762a1bSJed Brown   Nx = PETSC_DECIDE; Ny = PETSC_DECIDE;
98*c4762a1bSJed Brown 
99*c4762a1bSJed Brown   /*
100*c4762a1bSJed Brown      A two dimensional distributed array will help define this problem,
101*c4762a1bSJed Brown      which derives from an elliptic PDE on two dimensional domain.  From
102*c4762a1bSJed Brown      the distributed array, Create the vectors.
103*c4762a1bSJed Brown   */
104*c4762a1bSJed Brown   ierr = DMDACreate2d(PETSC_COMM_WORLD,DM_BOUNDARY_NONE,DM_BOUNDARY_NONE,DMDA_STENCIL_STAR,user.nx,user.ny,Nx,Ny,1,1,NULL,NULL,&user.dm);CHKERRQ(ierr);
105*c4762a1bSJed Brown   ierr = DMSetFromOptions(user.dm);CHKERRQ(ierr);
106*c4762a1bSJed Brown   ierr = DMSetUp(user.dm);CHKERRQ(ierr);
107*c4762a1bSJed Brown 
108*c4762a1bSJed Brown   /*
109*c4762a1bSJed Brown      Extract global and local vectors from DM; the vector user.B is
110*c4762a1bSJed Brown      used solely as work space for the evaluation of the function,
111*c4762a1bSJed Brown      gradient, and Hessian.  Duplicate for remaining vectors that are
112*c4762a1bSJed Brown      the same types.
113*c4762a1bSJed Brown   */
114*c4762a1bSJed Brown   ierr = DMCreateGlobalVector(user.dm,&x);CHKERRQ(ierr); /* Solution */
115*c4762a1bSJed Brown   ierr = VecDuplicate(x,&user.B);CHKERRQ(ierr); /* Linear objective */
116*c4762a1bSJed Brown 
117*c4762a1bSJed Brown 
118*c4762a1bSJed Brown   /*  Create matrix user.A to store quadratic, Create a local ordering scheme. */
119*c4762a1bSJed Brown   ierr = VecGetLocalSize(x,&m);CHKERRQ(ierr);
120*c4762a1bSJed Brown   ierr = DMCreateMatrix(user.dm,&user.A);CHKERRQ(ierr);
121*c4762a1bSJed Brown 
122*c4762a1bSJed Brown   if (testgetdiag) {
123*c4762a1bSJed Brown     ierr = MatSetOperation(user.A,MATOP_GET_DIAGONAL,NULL);CHKERRQ(ierr);
124*c4762a1bSJed Brown   }
125*c4762a1bSJed Brown 
126*c4762a1bSJed Brown   /* User defined function -- compute linear term of quadratic */
127*c4762a1bSJed Brown   ierr = ComputeB(&user);CHKERRQ(ierr);
128*c4762a1bSJed Brown 
129*c4762a1bSJed Brown   /* The TAO code begins here */
130*c4762a1bSJed Brown 
131*c4762a1bSJed Brown   /*
132*c4762a1bSJed Brown      Create the optimization solver
133*c4762a1bSJed Brown      Suitable methods: TAOGPCG, TAOBQPIP, TAOTRON, TAOBLMVM
134*c4762a1bSJed Brown   */
135*c4762a1bSJed Brown   ierr = TaoCreate(PETSC_COMM_WORLD,&tao);CHKERRQ(ierr);
136*c4762a1bSJed Brown   ierr = TaoSetType(tao,TAOBLMVM);CHKERRQ(ierr);
137*c4762a1bSJed Brown 
138*c4762a1bSJed Brown 
139*c4762a1bSJed Brown   /* Set the initial vector */
140*c4762a1bSJed Brown   ierr = VecSet(x, zero);CHKERRQ(ierr);
141*c4762a1bSJed Brown   ierr = TaoSetInitialVector(tao,x);CHKERRQ(ierr);
142*c4762a1bSJed Brown 
143*c4762a1bSJed Brown   /* Set the user function, gradient, hessian evaluation routines and data structures */
144*c4762a1bSJed Brown   ierr = TaoSetObjectiveAndGradientRoutine(tao,FormFunctionGradient,(void*) &user);CHKERRQ(ierr);
145*c4762a1bSJed Brown 
146*c4762a1bSJed Brown   ierr = TaoSetHessianRoutine(tao,user.A,user.A,FormHessian,(void*)&user);CHKERRQ(ierr);
147*c4762a1bSJed Brown 
148*c4762a1bSJed Brown   /* Set a routine that defines the bounds */
149*c4762a1bSJed Brown   ierr = VecDuplicate(x,&xl);CHKERRQ(ierr);
150*c4762a1bSJed Brown   ierr = VecDuplicate(x,&xu);CHKERRQ(ierr);
151*c4762a1bSJed Brown   ierr = VecSet(xl, zero);CHKERRQ(ierr);
152*c4762a1bSJed Brown   ierr = VecSet(xu, d1000);CHKERRQ(ierr);
153*c4762a1bSJed Brown   ierr = TaoSetVariableBounds(tao,xl,xu);CHKERRQ(ierr);
154*c4762a1bSJed Brown 
155*c4762a1bSJed Brown   ierr = TaoGetKSP(tao,&ksp);CHKERRQ(ierr);
156*c4762a1bSJed Brown   if (ksp) {
157*c4762a1bSJed Brown     ierr = KSPSetType(ksp,KSPCG);CHKERRQ(ierr);
158*c4762a1bSJed Brown   }
159*c4762a1bSJed Brown 
160*c4762a1bSJed Brown   ierr = PetscOptionsHasName(NULL,NULL,"-testmonitor",&flg);CHKERRQ(ierr);
161*c4762a1bSJed Brown   if (flg) {
162*c4762a1bSJed Brown     ierr = TaoSetMonitor(tao,Monitor,&user,NULL);CHKERRQ(ierr);
163*c4762a1bSJed Brown   }
164*c4762a1bSJed Brown   ierr = PetscOptionsHasName(NULL,NULL,"-testconvergence",&flg);CHKERRQ(ierr);
165*c4762a1bSJed Brown   if (flg) {
166*c4762a1bSJed Brown     ierr = TaoSetConvergenceTest(tao,ConvergenceTest,&user);CHKERRQ(ierr);
167*c4762a1bSJed Brown   }
168*c4762a1bSJed Brown 
169*c4762a1bSJed Brown   /* Check for any tao command line options */
170*c4762a1bSJed Brown   ierr = TaoSetFromOptions(tao);CHKERRQ(ierr);
171*c4762a1bSJed Brown 
172*c4762a1bSJed Brown   /* Solve the bound constrained problem */
173*c4762a1bSJed Brown   ierr = TaoSolve(tao);CHKERRQ(ierr);
174*c4762a1bSJed Brown 
175*c4762a1bSJed Brown   /* Free PETSc data structures */
176*c4762a1bSJed Brown   ierr = VecDestroy(&x);CHKERRQ(ierr);
177*c4762a1bSJed Brown   ierr = VecDestroy(&xl);CHKERRQ(ierr);
178*c4762a1bSJed Brown   ierr = VecDestroy(&xu);CHKERRQ(ierr);
179*c4762a1bSJed Brown   ierr = MatDestroy(&user.A);CHKERRQ(ierr);
180*c4762a1bSJed Brown   ierr = VecDestroy(&user.B);CHKERRQ(ierr);
181*c4762a1bSJed Brown 
182*c4762a1bSJed Brown   /* Free TAO data structures */
183*c4762a1bSJed Brown   ierr = TaoDestroy(&tao);CHKERRQ(ierr);
184*c4762a1bSJed Brown   ierr = DMDestroy(&user.dm);CHKERRQ(ierr);
185*c4762a1bSJed Brown   ierr = PetscFinalize();
186*c4762a1bSJed Brown   return ierr;
187*c4762a1bSJed Brown }
188*c4762a1bSJed Brown 
189*c4762a1bSJed Brown 
190*c4762a1bSJed Brown static PetscReal p(PetscReal xi, PetscReal ecc)
191*c4762a1bSJed Brown {
192*c4762a1bSJed Brown   PetscReal t=1.0+ecc*PetscCosScalar(xi);
193*c4762a1bSJed Brown   return (t*t*t);
194*c4762a1bSJed Brown }
195*c4762a1bSJed Brown 
196*c4762a1bSJed Brown PetscErrorCode ComputeB(AppCtx* user)
197*c4762a1bSJed Brown {
198*c4762a1bSJed Brown   PetscErrorCode ierr;
199*c4762a1bSJed Brown   PetscInt       i,j,k;
200*c4762a1bSJed Brown   PetscInt       nx,ny,xs,xm,gxs,gxm,ys,ym,gys,gym;
201*c4762a1bSJed Brown   PetscReal      two=2.0, pi=4.0*atan(1.0);
202*c4762a1bSJed Brown   PetscReal      hx,hy,ehxhy;
203*c4762a1bSJed Brown   PetscReal      temp,*b;
204*c4762a1bSJed Brown   PetscReal      ecc=user->ecc;
205*c4762a1bSJed Brown 
206*c4762a1bSJed Brown   nx=user->nx;
207*c4762a1bSJed Brown   ny=user->ny;
208*c4762a1bSJed Brown   hx=two*pi/(nx+1.0);
209*c4762a1bSJed Brown   hy=two*user->b/(ny+1.0);
210*c4762a1bSJed Brown   ehxhy = ecc*hx*hy;
211*c4762a1bSJed Brown 
212*c4762a1bSJed Brown 
213*c4762a1bSJed Brown   /*
214*c4762a1bSJed Brown      Get local grid boundaries
215*c4762a1bSJed Brown   */
216*c4762a1bSJed Brown   ierr = DMDAGetCorners(user->dm,&xs,&ys,NULL,&xm,&ym,NULL);CHKERRQ(ierr);
217*c4762a1bSJed Brown   ierr = DMDAGetGhostCorners(user->dm,&gxs,&gys,NULL,&gxm,&gym,NULL);CHKERRQ(ierr);
218*c4762a1bSJed Brown 
219*c4762a1bSJed Brown   /* Compute the linear term in the objective function */
220*c4762a1bSJed Brown   ierr = VecGetArray(user->B,&b);CHKERRQ(ierr);
221*c4762a1bSJed Brown   for (i=xs; i<xs+xm; i++){
222*c4762a1bSJed Brown     temp=PetscSinScalar((i+1)*hx);
223*c4762a1bSJed Brown     for (j=ys; j<ys+ym; j++){
224*c4762a1bSJed Brown       k=xm*(j-ys)+(i-xs);
225*c4762a1bSJed Brown       b[k]=  - ehxhy*temp;
226*c4762a1bSJed Brown     }
227*c4762a1bSJed Brown   }
228*c4762a1bSJed Brown   ierr = VecRestoreArray(user->B,&b);CHKERRQ(ierr);
229*c4762a1bSJed Brown   ierr = PetscLogFlops(5*xm*ym+3*xm);CHKERRQ(ierr);
230*c4762a1bSJed Brown 
231*c4762a1bSJed Brown   return 0;
232*c4762a1bSJed Brown }
233*c4762a1bSJed Brown 
234*c4762a1bSJed Brown PetscErrorCode FormFunctionGradient(Tao tao, Vec X, PetscReal *fcn,Vec G,void *ptr)
235*c4762a1bSJed Brown {
236*c4762a1bSJed Brown   AppCtx*        user=(AppCtx*)ptr;
237*c4762a1bSJed Brown   PetscErrorCode ierr;
238*c4762a1bSJed Brown   PetscInt       i,j,k,kk;
239*c4762a1bSJed Brown   PetscInt       col[5],row,nx,ny,xs,xm,gxs,gxm,ys,ym,gys,gym;
240*c4762a1bSJed Brown   PetscReal      one=1.0, two=2.0, six=6.0,pi=4.0*atan(1.0);
241*c4762a1bSJed Brown   PetscReal      hx,hy,hxhy,hxhx,hyhy;
242*c4762a1bSJed Brown   PetscReal      xi,v[5];
243*c4762a1bSJed Brown   PetscReal      ecc=user->ecc, trule1,trule2,trule3,trule4,trule5,trule6;
244*c4762a1bSJed Brown   PetscReal      vmiddle, vup, vdown, vleft, vright;
245*c4762a1bSJed Brown   PetscReal      tt,f1,f2;
246*c4762a1bSJed Brown   PetscReal      *x,*g,zero=0.0;
247*c4762a1bSJed Brown   Vec            localX;
248*c4762a1bSJed Brown 
249*c4762a1bSJed Brown   nx=user->nx;
250*c4762a1bSJed Brown   ny=user->ny;
251*c4762a1bSJed Brown   hx=two*pi/(nx+1.0);
252*c4762a1bSJed Brown   hy=two*user->b/(ny+1.0);
253*c4762a1bSJed Brown   hxhy=hx*hy;
254*c4762a1bSJed Brown   hxhx=one/(hx*hx);
255*c4762a1bSJed Brown   hyhy=one/(hy*hy);
256*c4762a1bSJed Brown 
257*c4762a1bSJed Brown   ierr = DMGetLocalVector(user->dm,&localX);CHKERRQ(ierr);
258*c4762a1bSJed Brown 
259*c4762a1bSJed Brown   ierr = DMGlobalToLocalBegin(user->dm,X,INSERT_VALUES,localX);CHKERRQ(ierr);
260*c4762a1bSJed Brown   ierr = DMGlobalToLocalEnd(user->dm,X,INSERT_VALUES,localX);CHKERRQ(ierr);
261*c4762a1bSJed Brown 
262*c4762a1bSJed Brown   ierr = VecSet(G, zero);CHKERRQ(ierr);
263*c4762a1bSJed Brown   /*
264*c4762a1bSJed Brown     Get local grid boundaries
265*c4762a1bSJed Brown   */
266*c4762a1bSJed Brown   ierr = DMDAGetCorners(user->dm,&xs,&ys,NULL,&xm,&ym,NULL);CHKERRQ(ierr);
267*c4762a1bSJed Brown   ierr = DMDAGetGhostCorners(user->dm,&gxs,&gys,NULL,&gxm,&gym,NULL);CHKERRQ(ierr);
268*c4762a1bSJed Brown 
269*c4762a1bSJed Brown   ierr = VecGetArray(localX,&x);CHKERRQ(ierr);
270*c4762a1bSJed Brown   ierr = VecGetArray(G,&g);CHKERRQ(ierr);
271*c4762a1bSJed Brown 
272*c4762a1bSJed Brown   for (i=xs; i< xs+xm; i++){
273*c4762a1bSJed Brown     xi=(i+1)*hx;
274*c4762a1bSJed Brown     trule1=hxhy*( p(xi,ecc) + p(xi+hx,ecc) + p(xi,ecc) ) / six; /* L(i,j) */
275*c4762a1bSJed Brown     trule2=hxhy*( p(xi,ecc) + p(xi-hx,ecc) + p(xi,ecc) ) / six; /* U(i,j) */
276*c4762a1bSJed Brown     trule3=hxhy*( p(xi,ecc) + p(xi+hx,ecc) + p(xi+hx,ecc) ) / six; /* U(i+1,j) */
277*c4762a1bSJed Brown     trule4=hxhy*( p(xi,ecc) + p(xi-hx,ecc) + p(xi-hx,ecc) ) / six; /* L(i-1,j) */
278*c4762a1bSJed Brown     trule5=trule1; /* L(i,j-1) */
279*c4762a1bSJed Brown     trule6=trule2; /* U(i,j+1) */
280*c4762a1bSJed Brown 
281*c4762a1bSJed Brown     vdown=-(trule5+trule2)*hyhy;
282*c4762a1bSJed Brown     vleft=-hxhx*(trule2+trule4);
283*c4762a1bSJed Brown     vright= -hxhx*(trule1+trule3);
284*c4762a1bSJed Brown     vup=-hyhy*(trule1+trule6);
285*c4762a1bSJed Brown     vmiddle=(hxhx)*(trule1+trule2+trule3+trule4)+hyhy*(trule1+trule2+trule5+trule6);
286*c4762a1bSJed Brown 
287*c4762a1bSJed Brown     for (j=ys; j<ys+ym; j++){
288*c4762a1bSJed Brown 
289*c4762a1bSJed Brown       row=(j-gys)*gxm + (i-gxs);
290*c4762a1bSJed Brown        v[0]=0; v[1]=0; v[2]=0; v[3]=0; v[4]=0;
291*c4762a1bSJed Brown 
292*c4762a1bSJed Brown        k=0;
293*c4762a1bSJed Brown        if (j>gys){
294*c4762a1bSJed Brown          v[k]=vdown; col[k]=row - gxm; k++;
295*c4762a1bSJed Brown        }
296*c4762a1bSJed Brown 
297*c4762a1bSJed Brown        if (i>gxs){
298*c4762a1bSJed Brown          v[k]= vleft; col[k]=row - 1; k++;
299*c4762a1bSJed Brown        }
300*c4762a1bSJed Brown 
301*c4762a1bSJed Brown        v[k]= vmiddle; col[k]=row; k++;
302*c4762a1bSJed Brown 
303*c4762a1bSJed Brown        if (i+1 < gxs+gxm){
304*c4762a1bSJed Brown          v[k]= vright; col[k]=row+1; k++;
305*c4762a1bSJed Brown        }
306*c4762a1bSJed Brown 
307*c4762a1bSJed Brown        if (j+1 <gys+gym){
308*c4762a1bSJed Brown          v[k]= vup; col[k] = row+gxm; k++;
309*c4762a1bSJed Brown        }
310*c4762a1bSJed Brown        tt=0;
311*c4762a1bSJed Brown        for (kk=0;kk<k;kk++){
312*c4762a1bSJed Brown          tt+=v[kk]*x[col[kk]];
313*c4762a1bSJed Brown        }
314*c4762a1bSJed Brown        row=(j-ys)*xm + (i-xs);
315*c4762a1bSJed Brown        g[row]=tt;
316*c4762a1bSJed Brown 
317*c4762a1bSJed Brown      }
318*c4762a1bSJed Brown 
319*c4762a1bSJed Brown   }
320*c4762a1bSJed Brown 
321*c4762a1bSJed Brown   ierr = VecRestoreArray(localX,&x);CHKERRQ(ierr);
322*c4762a1bSJed Brown   ierr = VecRestoreArray(G,&g);CHKERRQ(ierr);
323*c4762a1bSJed Brown 
324*c4762a1bSJed Brown   ierr = DMRestoreLocalVector(user->dm,&localX);CHKERRQ(ierr);
325*c4762a1bSJed Brown 
326*c4762a1bSJed Brown   ierr = VecDot(X,G,&f1);CHKERRQ(ierr);
327*c4762a1bSJed Brown   ierr = VecDot(user->B,X,&f2);CHKERRQ(ierr);
328*c4762a1bSJed Brown   ierr = VecAXPY(G, one, user->B);CHKERRQ(ierr);
329*c4762a1bSJed Brown   *fcn = f1/2.0 + f2;
330*c4762a1bSJed Brown 
331*c4762a1bSJed Brown 
332*c4762a1bSJed Brown   ierr = PetscLogFlops((91 + 10*ym) * xm);CHKERRQ(ierr);
333*c4762a1bSJed Brown   return 0;
334*c4762a1bSJed Brown 
335*c4762a1bSJed Brown }
336*c4762a1bSJed Brown 
337*c4762a1bSJed Brown 
338*c4762a1bSJed Brown /*
339*c4762a1bSJed Brown    FormHessian computes the quadratic term in the quadratic objective function
340*c4762a1bSJed Brown    Notice that the objective function in this problem is quadratic (therefore a constant
341*c4762a1bSJed Brown    hessian).  If using a nonquadratic solver, then you might want to reconsider this function
342*c4762a1bSJed Brown */
343*c4762a1bSJed Brown PetscErrorCode FormHessian(Tao tao,Vec X,Mat hes, Mat Hpre, void *ptr)
344*c4762a1bSJed Brown {
345*c4762a1bSJed Brown   AppCtx*        user=(AppCtx*)ptr;
346*c4762a1bSJed Brown   PetscErrorCode ierr;
347*c4762a1bSJed Brown   PetscInt       i,j,k;
348*c4762a1bSJed Brown   PetscInt       col[5],row,nx,ny,xs,xm,gxs,gxm,ys,ym,gys,gym;
349*c4762a1bSJed Brown   PetscReal      one=1.0, two=2.0, six=6.0,pi=4.0*atan(1.0);
350*c4762a1bSJed Brown   PetscReal      hx,hy,hxhy,hxhx,hyhy;
351*c4762a1bSJed Brown   PetscReal      xi,v[5];
352*c4762a1bSJed Brown   PetscReal      ecc=user->ecc, trule1,trule2,trule3,trule4,trule5,trule6;
353*c4762a1bSJed Brown   PetscReal      vmiddle, vup, vdown, vleft, vright;
354*c4762a1bSJed Brown   PetscBool      assembled;
355*c4762a1bSJed Brown 
356*c4762a1bSJed Brown   nx=user->nx;
357*c4762a1bSJed Brown   ny=user->ny;
358*c4762a1bSJed Brown   hx=two*pi/(nx+1.0);
359*c4762a1bSJed Brown   hy=two*user->b/(ny+1.0);
360*c4762a1bSJed Brown   hxhy=hx*hy;
361*c4762a1bSJed Brown   hxhx=one/(hx*hx);
362*c4762a1bSJed Brown   hyhy=one/(hy*hy);
363*c4762a1bSJed Brown 
364*c4762a1bSJed Brown   /*
365*c4762a1bSJed Brown     Get local grid boundaries
366*c4762a1bSJed Brown   */
367*c4762a1bSJed Brown   ierr = DMDAGetCorners(user->dm,&xs,&ys,NULL,&xm,&ym,NULL);CHKERRQ(ierr);
368*c4762a1bSJed Brown   ierr = DMDAGetGhostCorners(user->dm,&gxs,&gys,NULL,&gxm,&gym,NULL);CHKERRQ(ierr);
369*c4762a1bSJed Brown   ierr = MatAssembled(hes,&assembled);CHKERRQ(ierr);
370*c4762a1bSJed Brown   if (assembled){ierr = MatZeroEntries(hes);CHKERRQ(ierr);}
371*c4762a1bSJed Brown 
372*c4762a1bSJed Brown   for (i=xs; i< xs+xm; i++){
373*c4762a1bSJed Brown     xi=(i+1)*hx;
374*c4762a1bSJed Brown     trule1=hxhy*( p(xi,ecc) + p(xi+hx,ecc) + p(xi,ecc) ) / six; /* L(i,j) */
375*c4762a1bSJed Brown     trule2=hxhy*( p(xi,ecc) + p(xi-hx,ecc) + p(xi,ecc) ) / six; /* U(i,j) */
376*c4762a1bSJed Brown     trule3=hxhy*( p(xi,ecc) + p(xi+hx,ecc) + p(xi+hx,ecc) ) / six; /* U(i+1,j) */
377*c4762a1bSJed Brown     trule4=hxhy*( p(xi,ecc) + p(xi-hx,ecc) + p(xi-hx,ecc) ) / six; /* L(i-1,j) */
378*c4762a1bSJed Brown     trule5=trule1; /* L(i,j-1) */
379*c4762a1bSJed Brown     trule6=trule2; /* U(i,j+1) */
380*c4762a1bSJed Brown 
381*c4762a1bSJed Brown     vdown=-(trule5+trule2)*hyhy;
382*c4762a1bSJed Brown     vleft=-hxhx*(trule2+trule4);
383*c4762a1bSJed Brown     vright= -hxhx*(trule1+trule3);
384*c4762a1bSJed Brown     vup=-hyhy*(trule1+trule6);
385*c4762a1bSJed Brown     vmiddle=(hxhx)*(trule1+trule2+trule3+trule4)+hyhy*(trule1+trule2+trule5+trule6);
386*c4762a1bSJed Brown     v[0]=0; v[1]=0; v[2]=0; v[3]=0; v[4]=0;
387*c4762a1bSJed Brown 
388*c4762a1bSJed Brown     for (j=ys; j<ys+ym; j++){
389*c4762a1bSJed Brown       row=(j-gys)*gxm + (i-gxs);
390*c4762a1bSJed Brown 
391*c4762a1bSJed Brown       k=0;
392*c4762a1bSJed Brown       if (j>gys){
393*c4762a1bSJed Brown         v[k]=vdown; col[k]=row - gxm; k++;
394*c4762a1bSJed Brown       }
395*c4762a1bSJed Brown 
396*c4762a1bSJed Brown       if (i>gxs){
397*c4762a1bSJed Brown         v[k]= vleft; col[k]=row - 1; k++;
398*c4762a1bSJed Brown       }
399*c4762a1bSJed Brown 
400*c4762a1bSJed Brown       v[k]= vmiddle; col[k]=row; k++;
401*c4762a1bSJed Brown 
402*c4762a1bSJed Brown       if (i+1 < gxs+gxm){
403*c4762a1bSJed Brown         v[k]= vright; col[k]=row+1; k++;
404*c4762a1bSJed Brown       }
405*c4762a1bSJed Brown 
406*c4762a1bSJed Brown       if (j+1 <gys+gym){
407*c4762a1bSJed Brown         v[k]= vup; col[k] = row+gxm; k++;
408*c4762a1bSJed Brown       }
409*c4762a1bSJed Brown       ierr = MatSetValuesLocal(hes,1,&row,k,col,v,INSERT_VALUES);CHKERRQ(ierr);
410*c4762a1bSJed Brown 
411*c4762a1bSJed Brown     }
412*c4762a1bSJed Brown 
413*c4762a1bSJed Brown   }
414*c4762a1bSJed Brown 
415*c4762a1bSJed Brown   /*
416*c4762a1bSJed Brown      Assemble matrix, using the 2-step process:
417*c4762a1bSJed Brown      MatAssemblyBegin(), MatAssemblyEnd().
418*c4762a1bSJed Brown      By placing code between these two statements, computations can be
419*c4762a1bSJed Brown      done while messages are in transition.
420*c4762a1bSJed Brown   */
421*c4762a1bSJed Brown   ierr = MatAssemblyBegin(hes,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
422*c4762a1bSJed Brown   ierr = MatAssemblyEnd(hes,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
423*c4762a1bSJed Brown 
424*c4762a1bSJed Brown   /*
425*c4762a1bSJed Brown     Tell the matrix we will never add a new nonzero location to the
426*c4762a1bSJed Brown     matrix. If we do it will generate an error.
427*c4762a1bSJed Brown   */
428*c4762a1bSJed Brown   ierr = MatSetOption(hes,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr);
429*c4762a1bSJed Brown   ierr = MatSetOption(hes,MAT_SYMMETRIC,PETSC_TRUE);CHKERRQ(ierr);
430*c4762a1bSJed Brown 
431*c4762a1bSJed Brown   ierr = PetscLogFlops(9*xm*ym+49*xm);CHKERRQ(ierr);
432*c4762a1bSJed Brown   ierr = MatNorm(hes,NORM_1,&hx);CHKERRQ(ierr);
433*c4762a1bSJed Brown   return 0;
434*c4762a1bSJed Brown }
435*c4762a1bSJed Brown 
436*c4762a1bSJed Brown PetscErrorCode Monitor(Tao tao, void *ctx)
437*c4762a1bSJed Brown {
438*c4762a1bSJed Brown   PetscErrorCode     ierr;
439*c4762a1bSJed Brown   PetscInt           its;
440*c4762a1bSJed Brown   PetscReal          f,gnorm,cnorm,xdiff;
441*c4762a1bSJed Brown   TaoConvergedReason reason;
442*c4762a1bSJed Brown 
443*c4762a1bSJed Brown   PetscFunctionBegin;
444*c4762a1bSJed Brown   ierr = TaoGetSolutionStatus(tao, &its, &f, &gnorm, &cnorm, &xdiff, &reason);CHKERRQ(ierr);
445*c4762a1bSJed Brown   if (!(its%5)) {
446*c4762a1bSJed Brown     ierr = PetscPrintf(PETSC_COMM_WORLD,"iteration=%D\tf=%g\n",its,(double)f);CHKERRQ(ierr);
447*c4762a1bSJed Brown   }
448*c4762a1bSJed Brown   PetscFunctionReturn(0);
449*c4762a1bSJed Brown }
450*c4762a1bSJed Brown 
451*c4762a1bSJed Brown PetscErrorCode ConvergenceTest(Tao tao, void *ctx)
452*c4762a1bSJed Brown {
453*c4762a1bSJed Brown   PetscErrorCode     ierr;
454*c4762a1bSJed Brown   PetscInt           its;
455*c4762a1bSJed Brown   PetscReal          f,gnorm,cnorm,xdiff;
456*c4762a1bSJed Brown   TaoConvergedReason reason;
457*c4762a1bSJed Brown 
458*c4762a1bSJed Brown   PetscFunctionBegin;
459*c4762a1bSJed Brown   ierr = TaoGetSolutionStatus(tao, &its, &f, &gnorm, &cnorm, &xdiff, &reason);CHKERRQ(ierr);
460*c4762a1bSJed Brown   if (its == 100) {
461*c4762a1bSJed Brown     ierr = TaoSetConvergedReason(tao,TAO_DIVERGED_MAXITS);CHKERRQ(ierr);
462*c4762a1bSJed Brown   }
463*c4762a1bSJed Brown   PetscFunctionReturn(0);
464*c4762a1bSJed Brown 
465*c4762a1bSJed Brown }
466*c4762a1bSJed Brown 
467*c4762a1bSJed Brown 
468*c4762a1bSJed Brown /*TEST
469*c4762a1bSJed Brown 
470*c4762a1bSJed Brown    build:
471*c4762a1bSJed Brown       requires: !complex
472*c4762a1bSJed Brown 
473*c4762a1bSJed Brown    test:
474*c4762a1bSJed Brown       args: -tao_smonitor -mx 8 -my 12 -tao_type tron -tao_gatol 1.e-5
475*c4762a1bSJed Brown       requires: !single
476*c4762a1bSJed Brown 
477*c4762a1bSJed Brown    test:
478*c4762a1bSJed Brown       suffix: 2
479*c4762a1bSJed Brown       nsize: 2
480*c4762a1bSJed Brown       args: -tao_smonitor -mx 50 -my 50 -ecc 0.99 -tao_type gpcg -tao_gatol 1.e-5
481*c4762a1bSJed Brown       requires: !single
482*c4762a1bSJed Brown 
483*c4762a1bSJed Brown    test:
484*c4762a1bSJed Brown       suffix: 3
485*c4762a1bSJed Brown       nsize: 2
486*c4762a1bSJed Brown       args: -tao_smonitor -mx 10 -my 16 -ecc 0.9 -tao_type bqpip -tao_gatol 1.e-4
487*c4762a1bSJed Brown       requires: !single
488*c4762a1bSJed Brown 
489*c4762a1bSJed Brown    test:
490*c4762a1bSJed Brown       suffix: 4
491*c4762a1bSJed Brown       nsize: 2
492*c4762a1bSJed Brown       args: -tao_smonitor -mx 10 -my 16 -ecc 0.9 -tao_type bqpip -tao_gatol 1.e-4 -test_getdiagonal
493*c4762a1bSJed Brown       output_file: output/jbearing2_3.out
494*c4762a1bSJed Brown       requires: !single
495*c4762a1bSJed Brown 
496*c4762a1bSJed Brown    test:
497*c4762a1bSJed Brown       suffix: 5
498*c4762a1bSJed Brown       args: -tao_smonitor -mx 8 -my 12 -tao_type bncg -tao_bncg_type gd -tao_gatol 1e-4
499*c4762a1bSJed Brown       requires: !single
500*c4762a1bSJed Brown 
501*c4762a1bSJed Brown    test:
502*c4762a1bSJed Brown       suffix: 6
503*c4762a1bSJed Brown       args: -tao_smonitor -mx 8 -my 12 -tao_type bncg -tao_gatol 1e-4
504*c4762a1bSJed Brown       requires: !single
505*c4762a1bSJed Brown 
506*c4762a1bSJed Brown    test:
507*c4762a1bSJed Brown       suffix: 7
508*c4762a1bSJed Brown       args: -tao_smonitor -mx 8 -my 12 -tao_type bnls -tao_gatol 1e-5
509*c4762a1bSJed Brown       requires: !single
510*c4762a1bSJed Brown 
511*c4762a1bSJed Brown    test:
512*c4762a1bSJed Brown       suffix: 8
513*c4762a1bSJed Brown       args: -tao_smonitor -mx 8 -my 12 -tao_type bntr -tao_gatol 1e-5
514*c4762a1bSJed Brown       requires: !single
515*c4762a1bSJed Brown 
516*c4762a1bSJed Brown    test:
517*c4762a1bSJed Brown       suffix: 9
518*c4762a1bSJed Brown       args: -tao_smonitor -mx 8 -my 12 -tao_type bntl -tao_gatol 1e-5
519*c4762a1bSJed Brown       requires: !single
520*c4762a1bSJed Brown 
521*c4762a1bSJed Brown    test:
522*c4762a1bSJed Brown       suffix: 10
523*c4762a1bSJed Brown       args: -tao_smonitor -mx 8 -my 12 -tao_type bnls -tao_gatol 1e-5 -tao_bnk_max_cg_its 3
524*c4762a1bSJed Brown       requires: !single
525*c4762a1bSJed Brown 
526*c4762a1bSJed Brown    test:
527*c4762a1bSJed Brown       suffix: 11
528*c4762a1bSJed Brown       args: -tao_smonitor -mx 8 -my 12 -tao_type bntr -tao_gatol 1e-5 -tao_bnk_max_cg_its 3
529*c4762a1bSJed Brown       requires: !single
530*c4762a1bSJed Brown 
531*c4762a1bSJed Brown    test:
532*c4762a1bSJed Brown       suffix: 12
533*c4762a1bSJed Brown       args: -tao_smonitor -mx 8 -my 12 -tao_type bntl -tao_gatol 1e-5 -tao_bnk_max_cg_its 3
534*c4762a1bSJed Brown       requires: !single
535*c4762a1bSJed Brown 
536*c4762a1bSJed Brown    test:
537*c4762a1bSJed Brown      suffix: 13
538*c4762a1bSJed Brown      args: -tao_smonitor -mx 8 -my 12 -tao_gatol 1e-4 -tao_type bqnls
539*c4762a1bSJed Brown      requires: !single
540*c4762a1bSJed Brown 
541*c4762a1bSJed Brown    test:
542*c4762a1bSJed Brown      suffix: 14
543*c4762a1bSJed Brown      args: -tao_smonitor -mx 8 -my 12 -tao_gatol 1e-4 -tao_type blmvm
544*c4762a1bSJed Brown      requires: !single
545*c4762a1bSJed Brown 
546*c4762a1bSJed Brown    test:
547*c4762a1bSJed Brown      suffix: 15
548*c4762a1bSJed Brown      args: -tao_smonitor -mx 8 -my 12 -tao_gatol 1e-4 -tao_type bqnkls -tao_bqnk_mat_type lmvmbfgs
549*c4762a1bSJed Brown      requires: !single
550*c4762a1bSJed Brown 
551*c4762a1bSJed Brown    test:
552*c4762a1bSJed Brown      suffix: 16
553*c4762a1bSJed Brown      args: -tao_smonitor -mx 8 -my 12 -tao_gatol 1e-4 -tao_type bqnktr -tao_bqnk_mat_type lmvmsr1
554*c4762a1bSJed Brown      requires: !single
555*c4762a1bSJed Brown 
556*c4762a1bSJed Brown    test:
557*c4762a1bSJed Brown      suffix: 17
558*c4762a1bSJed Brown      args: -tao_smonitor -mx 8 -my 12 -tao_gatol 1e-4 -tao_type bqnls -tao_bqnls_mat_lmvm_scale_type scalar
559*c4762a1bSJed Brown      requires: !single
560*c4762a1bSJed Brown 
561*c4762a1bSJed Brown    test:
562*c4762a1bSJed Brown      suffix: 18
563*c4762a1bSJed Brown      args: -tao_smonitor -mx 8 -my 12 -tao_gatol 1e-4 -tao_type bqnls -tao_bqnls_mat_lmvm_scale_type none
564*c4762a1bSJed Brown      requires: !single
565*c4762a1bSJed Brown 
566*c4762a1bSJed Brown TEST*/
567