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