Actual source code: jbearing2.c

  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: */

  8: #include <petsctao.h>
  9: #include <petscdmda.h>

 11: static char help[] = "This example demonstrates use of the TAO package to \n\
 12: solve a bound constrained minimization problem.  This example is based on \n\
 13: the problem DPJB from the MINPACK-2 test suite.  This pressure journal \n\
 14: bearing problem is an example of elliptic variational problem defined over \n\
 15: a two dimensional rectangle.  By discretizing the domain into triangular \n\
 16: elements, the pressure surrounding the journal bearing is defined as the \n\
 17: minimum of a quadratic function whose variables are bounded below by zero.\n\
 18: The command line options are:\n\
 19:   -mx <xg>, where <xg> = number of grid points in the 1st coordinate direction\n\
 20:   -my <yg>, where <yg> = number of grid points in the 2nd coordinate direction\n\
 21:  \n";

 23: /*
 24:    User-defined application context - contains data needed by the
 25:    application-provided call-back routines, FormFunctionGradient(),
 26:    FormHessian().
 27: */
 28: typedef struct {
 29:   /* problem parameters */
 30:   PetscReal ecc;    /* test problem parameter */
 31:   PetscReal b;      /* A dimension of journal bearing */
 32:   PetscInt  nx, ny; /* discretization in x, y directions */

 34:   /* Working space */
 35:   DM  dm; /* distributed array data structure */
 36:   Mat A;  /* Quadratic Objective term */
 37:   Vec B;  /* Linear Objective term */
 38: } AppCtx;

 40: /* User-defined routines */
 41: static PetscReal      p(PetscReal xi, PetscReal ecc);
 42: static PetscErrorCode FormFunctionGradient(Tao, Vec, PetscReal *, Vec, void *);
 43: static PetscErrorCode FormHessian(Tao, Vec, Mat, Mat, void *);
 44: static PetscErrorCode ComputeB(AppCtx *);
 45: static PetscErrorCode Monitor(Tao, void *);
 46: static PetscErrorCode ConvergenceTest(Tao, void *);

 48: int main(int argc, char **argv)
 49: {
 50:   PetscInt  Nx, Ny; /* number of processors in x- and y- directions */
 51:   PetscInt  m;      /* number of local elements in vectors */
 52:   Vec       x;      /* variables vector */
 53:   Vec       xl, xu; /* bounds vectors */
 54:   PetscReal d1000 = 1000;
 55:   PetscBool flg, testgetdiag; /* A return variable when checking for user options */
 56:   Tao       tao;              /* Tao solver context */
 57:   KSP       ksp;
 58:   AppCtx    user;       /* user-defined work context */
 59:   PetscReal zero = 0.0; /* lower bound on all variables */

 61:   /* Initialize PETSC and TAO */
 62:   PetscFunctionBeginUser;
 63:   PetscCall(PetscInitialize(&argc, &argv, NULL, help));

 65:   /* Set the default values for the problem parameters */
 66:   user.nx     = 50;
 67:   user.ny     = 50;
 68:   user.ecc    = 0.1;
 69:   user.b      = 10.0;
 70:   testgetdiag = PETSC_FALSE;

 72:   /* Check for any command line arguments that override defaults */
 73:   PetscCall(PetscOptionsGetInt(NULL, NULL, "-mx", &user.nx, &flg));
 74:   PetscCall(PetscOptionsGetInt(NULL, NULL, "-my", &user.ny, &flg));
 75:   PetscCall(PetscOptionsGetReal(NULL, NULL, "-ecc", &user.ecc, &flg));
 76:   PetscCall(PetscOptionsGetReal(NULL, NULL, "-b", &user.b, &flg));
 77:   PetscCall(PetscOptionsGetBool(NULL, NULL, "-test_getdiagonal", &testgetdiag, NULL));

 79:   PetscCall(PetscPrintf(PETSC_COMM_WORLD, "\n---- Journal Bearing Problem SHB-----\n"));
 80:   PetscCall(PetscPrintf(PETSC_COMM_WORLD, "mx: %" PetscInt_FMT ",  my: %" PetscInt_FMT ",  ecc: %g \n\n", user.nx, user.ny, (double)user.ecc));

 82:   /* Let Petsc determine the grid division */
 83:   Nx = PETSC_DECIDE;
 84:   Ny = PETSC_DECIDE;

 86:   /*
 87:      A two dimensional distributed array will help define this problem,
 88:      which derives from an elliptic PDE on two dimensional domain.  From
 89:      the distributed array, Create the vectors.
 90:   */
 91:   PetscCall(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));
 92:   PetscCall(DMSetFromOptions(user.dm));
 93:   PetscCall(DMSetUp(user.dm));

 95:   /*
 96:      Extract global and local vectors from DM; the vector user.B is
 97:      used solely as work space for the evaluation of the function,
 98:      gradient, and Hessian.  Duplicate for remaining vectors that are
 99:      the same types.
100:   */
101:   PetscCall(DMCreateGlobalVector(user.dm, &x)); /* Solution */
102:   PetscCall(VecDuplicate(x, &user.B));          /* Linear objective */

104:   /*  Create matrix user.A to store quadratic, Create a local ordering scheme. */
105:   PetscCall(VecGetLocalSize(x, &m));
106:   PetscCall(DMCreateMatrix(user.dm, &user.A));

108:   if (testgetdiag) PetscCall(MatSetOperation(user.A, MATOP_GET_DIAGONAL, NULL));

110:   /* User defined function -- compute linear term of quadratic */
111:   PetscCall(ComputeB(&user));

113:   /* The TAO code begins here */

115:   /*
116:      Create the optimization solver
117:      Suitable methods: TAOGPCG, TAOBQPIP, TAOTRON, TAOBLMVM
118:   */
119:   PetscCall(TaoCreate(PETSC_COMM_WORLD, &tao));
120:   PetscCall(TaoSetType(tao, TAOBLMVM));

122:   /* Set the initial vector */
123:   PetscCall(VecSet(x, zero));
124:   PetscCall(TaoSetSolution(tao, x));

126:   /* Set the user function, gradient, hessian evaluation routines and data structures */
127:   PetscCall(TaoSetObjectiveAndGradient(tao, NULL, FormFunctionGradient, (void *)&user));

129:   PetscCall(TaoSetHessian(tao, user.A, user.A, FormHessian, (void *)&user));

131:   /* Set a routine that defines the bounds */
132:   PetscCall(VecDuplicate(x, &xl));
133:   PetscCall(VecDuplicate(x, &xu));
134:   PetscCall(VecSet(xl, zero));
135:   PetscCall(VecSet(xu, d1000));
136:   PetscCall(TaoSetVariableBounds(tao, xl, xu));

138:   PetscCall(TaoGetKSP(tao, &ksp));
139:   if (ksp) PetscCall(KSPSetType(ksp, KSPCG));

141:   PetscCall(PetscOptionsHasName(NULL, NULL, "-testmonitor", &flg));
142:   if (flg) PetscCall(TaoMonitorSet(tao, Monitor, &user, NULL));
143:   PetscCall(PetscOptionsHasName(NULL, NULL, "-testconvergence", &flg));
144:   if (flg) PetscCall(TaoSetConvergenceTest(tao, ConvergenceTest, &user));

146:   /* Check for any tao command line options */
147:   PetscCall(TaoSetFromOptions(tao));

149:   /* Solve the bound constrained problem */
150:   PetscCall(TaoSolve(tao));

152:   /* Free PETSc data structures */
153:   PetscCall(VecDestroy(&x));
154:   PetscCall(VecDestroy(&xl));
155:   PetscCall(VecDestroy(&xu));
156:   PetscCall(MatDestroy(&user.A));
157:   PetscCall(VecDestroy(&user.B));

159:   /* Free TAO data structures */
160:   PetscCall(TaoDestroy(&tao));
161:   PetscCall(DMDestroy(&user.dm));
162:   PetscCall(PetscFinalize());
163:   return 0;
164: }

166: static PetscReal p(PetscReal xi, PetscReal ecc)
167: {
168:   PetscReal t = 1.0 + ecc * PetscCosScalar(xi);
169:   return t * t * t;
170: }

172: PetscErrorCode ComputeB(AppCtx *user)
173: {
174:   PetscInt  i, j, k;
175:   PetscInt  nx, ny, xs, xm, gxs, gxm, ys, ym, gys, gym;
176:   PetscReal two = 2.0, pi = 4.0 * atan(1.0);
177:   PetscReal hx, hy, ehxhy;
178:   PetscReal temp, *b;
179:   PetscReal ecc = user->ecc;

181:   PetscFunctionBegin;
182:   nx    = user->nx;
183:   ny    = user->ny;
184:   hx    = two * pi / (nx + 1.0);
185:   hy    = two * user->b / (ny + 1.0);
186:   ehxhy = ecc * hx * hy;

188:   /*
189:      Get local grid boundaries
190:   */
191:   PetscCall(DMDAGetCorners(user->dm, &xs, &ys, NULL, &xm, &ym, NULL));
192:   PetscCall(DMDAGetGhostCorners(user->dm, &gxs, &gys, NULL, &gxm, &gym, NULL));

194:   /* Compute the linear term in the objective function */
195:   PetscCall(VecGetArray(user->B, &b));
196:   for (i = xs; i < xs + xm; i++) {
197:     temp = PetscSinScalar((i + 1) * hx);
198:     for (j = ys; j < ys + ym; j++) {
199:       k    = xm * (j - ys) + (i - xs);
200:       b[k] = -ehxhy * temp;
201:     }
202:   }
203:   PetscCall(VecRestoreArray(user->B, &b));
204:   PetscCall(PetscLogFlops(5.0 * xm * ym + 3.0 * xm));
205:   PetscFunctionReturn(PETSC_SUCCESS);
206: }

208: PetscErrorCode FormFunctionGradient(Tao tao, Vec X, PetscReal *fcn, Vec G, void *ptr)
209: {
210:   AppCtx    *user = (AppCtx *)ptr;
211:   PetscInt   i, j, k, kk;
212:   PetscInt   col[5], row, nx, ny, xs, xm, gxs, gxm, ys, ym, gys, gym;
213:   PetscReal  one = 1.0, two = 2.0, six = 6.0, pi = 4.0 * atan(1.0);
214:   PetscReal  hx, hy, hxhy, hxhx, hyhy;
215:   PetscReal  xi, v[5];
216:   PetscReal  ecc = user->ecc, trule1, trule2, trule3, trule4, trule5, trule6;
217:   PetscReal  vmiddle, vup, vdown, vleft, vright;
218:   PetscReal  tt, f1, f2;
219:   PetscReal *x, *g, zero = 0.0;
220:   Vec        localX;

222:   PetscFunctionBegin;
223:   nx   = user->nx;
224:   ny   = user->ny;
225:   hx   = two * pi / (nx + 1.0);
226:   hy   = two * user->b / (ny + 1.0);
227:   hxhy = hx * hy;
228:   hxhx = one / (hx * hx);
229:   hyhy = one / (hy * hy);

231:   PetscCall(DMGetLocalVector(user->dm, &localX));

233:   PetscCall(DMGlobalToLocalBegin(user->dm, X, INSERT_VALUES, localX));
234:   PetscCall(DMGlobalToLocalEnd(user->dm, X, INSERT_VALUES, localX));

236:   PetscCall(VecSet(G, zero));
237:   /*
238:     Get local grid boundaries
239:   */
240:   PetscCall(DMDAGetCorners(user->dm, &xs, &ys, NULL, &xm, &ym, NULL));
241:   PetscCall(DMDAGetGhostCorners(user->dm, &gxs, &gys, NULL, &gxm, &gym, NULL));

243:   PetscCall(VecGetArray(localX, &x));
244:   PetscCall(VecGetArray(G, &g));

246:   for (i = xs; i < xs + xm; i++) {
247:     xi     = (i + 1) * hx;
248:     trule1 = hxhy * (p(xi, ecc) + p(xi + hx, ecc) + p(xi, ecc)) / six;      /* L(i,j) */
249:     trule2 = hxhy * (p(xi, ecc) + p(xi - hx, ecc) + p(xi, ecc)) / six;      /* U(i,j) */
250:     trule3 = hxhy * (p(xi, ecc) + p(xi + hx, ecc) + p(xi + hx, ecc)) / six; /* U(i+1,j) */
251:     trule4 = hxhy * (p(xi, ecc) + p(xi - hx, ecc) + p(xi - hx, ecc)) / six; /* L(i-1,j) */
252:     trule5 = trule1;                                                        /* L(i,j-1) */
253:     trule6 = trule2;                                                        /* U(i,j+1) */

255:     vdown   = -(trule5 + trule2) * hyhy;
256:     vleft   = -hxhx * (trule2 + trule4);
257:     vright  = -hxhx * (trule1 + trule3);
258:     vup     = -hyhy * (trule1 + trule6);
259:     vmiddle = (hxhx) * (trule1 + trule2 + trule3 + trule4) + hyhy * (trule1 + trule2 + trule5 + trule6);

261:     for (j = ys; j < ys + ym; j++) {
262:       row  = (j - gys) * gxm + (i - gxs);
263:       v[0] = 0;
264:       v[1] = 0;
265:       v[2] = 0;
266:       v[3] = 0;
267:       v[4] = 0;

269:       k = 0;
270:       if (j > gys) {
271:         v[k]   = vdown;
272:         col[k] = row - gxm;
273:         k++;
274:       }

276:       if (i > gxs) {
277:         v[k]   = vleft;
278:         col[k] = row - 1;
279:         k++;
280:       }

282:       v[k]   = vmiddle;
283:       col[k] = row;
284:       k++;

286:       if (i + 1 < gxs + gxm) {
287:         v[k]   = vright;
288:         col[k] = row + 1;
289:         k++;
290:       }

292:       if (j + 1 < gys + gym) {
293:         v[k]   = vup;
294:         col[k] = row + gxm;
295:         k++;
296:       }
297:       tt = 0;
298:       for (kk = 0; kk < k; kk++) tt += v[kk] * x[col[kk]];
299:       row    = (j - ys) * xm + (i - xs);
300:       g[row] = tt;
301:     }
302:   }

304:   PetscCall(VecRestoreArray(localX, &x));
305:   PetscCall(VecRestoreArray(G, &g));

307:   PetscCall(DMRestoreLocalVector(user->dm, &localX));

309:   PetscCall(VecDot(X, G, &f1));
310:   PetscCall(VecDot(user->B, X, &f2));
311:   PetscCall(VecAXPY(G, one, user->B));
312:   *fcn = f1 / 2.0 + f2;

314:   PetscCall(PetscLogFlops((91 + 10.0 * ym) * xm));
315:   PetscFunctionReturn(PETSC_SUCCESS);
316: }

318: /*
319:    FormHessian computes the quadratic term in the quadratic objective function
320:    Notice that the objective function in this problem is quadratic (therefore a constant
321:    hessian).  If using a nonquadratic solver, then you might want to reconsider this function
322: */
323: PetscErrorCode FormHessian(Tao tao, Vec X, Mat hes, Mat Hpre, void *ptr)
324: {
325:   AppCtx   *user = (AppCtx *)ptr;
326:   PetscInt  i, j, k;
327:   PetscInt  col[5], row, nx, ny, xs, xm, gxs, gxm, ys, ym, gys, gym;
328:   PetscReal one = 1.0, two = 2.0, six = 6.0, pi = 4.0 * atan(1.0);
329:   PetscReal hx, hy, hxhy, hxhx, hyhy;
330:   PetscReal xi, v[5];
331:   PetscReal ecc = user->ecc, trule1, trule2, trule3, trule4, trule5, trule6;
332:   PetscReal vmiddle, vup, vdown, vleft, vright;
333:   PetscBool assembled;

335:   PetscFunctionBegin;
336:   nx   = user->nx;
337:   ny   = user->ny;
338:   hx   = two * pi / (nx + 1.0);
339:   hy   = two * user->b / (ny + 1.0);
340:   hxhy = hx * hy;
341:   hxhx = one / (hx * hx);
342:   hyhy = one / (hy * hy);

344:   /*
345:     Get local grid boundaries
346:   */
347:   PetscCall(DMDAGetCorners(user->dm, &xs, &ys, NULL, &xm, &ym, NULL));
348:   PetscCall(DMDAGetGhostCorners(user->dm, &gxs, &gys, NULL, &gxm, &gym, NULL));
349:   PetscCall(MatAssembled(hes, &assembled));
350:   if (assembled) PetscCall(MatZeroEntries(hes));

352:   for (i = xs; i < xs + xm; i++) {
353:     xi     = (i + 1) * hx;
354:     trule1 = hxhy * (p(xi, ecc) + p(xi + hx, ecc) + p(xi, ecc)) / six;      /* L(i,j) */
355:     trule2 = hxhy * (p(xi, ecc) + p(xi - hx, ecc) + p(xi, ecc)) / six;      /* U(i,j) */
356:     trule3 = hxhy * (p(xi, ecc) + p(xi + hx, ecc) + p(xi + hx, ecc)) / six; /* U(i+1,j) */
357:     trule4 = hxhy * (p(xi, ecc) + p(xi - hx, ecc) + p(xi - hx, ecc)) / six; /* L(i-1,j) */
358:     trule5 = trule1;                                                        /* L(i,j-1) */
359:     trule6 = trule2;                                                        /* U(i,j+1) */

361:     vdown   = -(trule5 + trule2) * hyhy;
362:     vleft   = -hxhx * (trule2 + trule4);
363:     vright  = -hxhx * (trule1 + trule3);
364:     vup     = -hyhy * (trule1 + trule6);
365:     vmiddle = (hxhx) * (trule1 + trule2 + trule3 + trule4) + hyhy * (trule1 + trule2 + trule5 + trule6);
366:     v[0]    = 0;
367:     v[1]    = 0;
368:     v[2]    = 0;
369:     v[3]    = 0;
370:     v[4]    = 0;

372:     for (j = ys; j < ys + ym; j++) {
373:       row = (j - gys) * gxm + (i - gxs);

375:       k = 0;
376:       if (j > gys) {
377:         v[k]   = vdown;
378:         col[k] = row - gxm;
379:         k++;
380:       }

382:       if (i > gxs) {
383:         v[k]   = vleft;
384:         col[k] = row - 1;
385:         k++;
386:       }

388:       v[k]   = vmiddle;
389:       col[k] = row;
390:       k++;

392:       if (i + 1 < gxs + gxm) {
393:         v[k]   = vright;
394:         col[k] = row + 1;
395:         k++;
396:       }

398:       if (j + 1 < gys + gym) {
399:         v[k]   = vup;
400:         col[k] = row + gxm;
401:         k++;
402:       }
403:       PetscCall(MatSetValuesLocal(hes, 1, &row, k, col, v, INSERT_VALUES));
404:     }
405:   }

407:   /*
408:      Assemble matrix, using the 2-step process:
409:      MatAssemblyBegin(), MatAssemblyEnd().
410:      By placing code between these two statements, computations can be
411:      done while messages are in transition.
412:   */
413:   PetscCall(MatAssemblyBegin(hes, MAT_FINAL_ASSEMBLY));
414:   PetscCall(MatAssemblyEnd(hes, MAT_FINAL_ASSEMBLY));

416:   /*
417:     Tell the matrix we will never add a new nonzero location to the
418:     matrix. If we do it will generate an error.
419:   */
420:   PetscCall(MatSetOption(hes, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_TRUE));
421:   PetscCall(MatSetOption(hes, MAT_SYMMETRIC, PETSC_TRUE));

423:   PetscCall(PetscLogFlops(9.0 * xm * ym + 49.0 * xm));
424:   PetscFunctionReturn(PETSC_SUCCESS);
425: }

427: PetscErrorCode Monitor(Tao tao, void *ctx)
428: {
429:   PetscInt           its;
430:   PetscReal          f, gnorm, cnorm, xdiff;
431:   TaoConvergedReason reason;

433:   PetscFunctionBegin;
434:   PetscCall(TaoGetSolutionStatus(tao, &its, &f, &gnorm, &cnorm, &xdiff, &reason));
435:   if (!(its % 5)) PetscCall(PetscPrintf(PETSC_COMM_WORLD, "iteration=%" PetscInt_FMT "\tf=%g\n", its, (double)f));
436:   PetscFunctionReturn(PETSC_SUCCESS);
437: }

439: PetscErrorCode ConvergenceTest(Tao tao, void *ctx)
440: {
441:   PetscInt           its;
442:   PetscReal          f, gnorm, cnorm, xdiff;
443:   TaoConvergedReason reason;

445:   PetscFunctionBegin;
446:   PetscCall(TaoGetSolutionStatus(tao, &its, &f, &gnorm, &cnorm, &xdiff, &reason));
447:   if (its == 100) PetscCall(TaoSetConvergedReason(tao, TAO_DIVERGED_MAXITS));
448:   PetscFunctionReturn(PETSC_SUCCESS);
449: }

451: /*TEST

453:    build:
454:       requires: !complex

456:    test:
457:       args: -tao_monitor_short -mx 8 -my 12 -tao_type tron -tao_gatol 1.e-5
458:       requires: !single

460:    test:
461:       suffix: 2
462:       nsize: 2
463:       args: -tao_monitor_short -mx 50 -my 50 -ecc 0.99 -tao_type gpcg -tao_gatol 1.e-5
464:       requires: !single

466:    test:
467:       suffix: 3
468:       nsize: 2
469:       args: -tao_monitor_short -mx 10 -my 16 -ecc 0.9 -tao_type bqpip -tao_gatol 1.e-4
470:       requires: !single

472:    test:
473:       suffix: 4
474:       nsize: 2
475:       args: -tao_monitor_short -mx 10 -my 16 -ecc 0.9 -tao_type bqpip -tao_gatol 1.e-4 -test_getdiagonal
476:       output_file: output/jbearing2_3.out
477:       requires: !single

479:    test:
480:       suffix: 5
481:       args: -tao_monitor_short -mx 8 -my 12 -tao_type bncg -tao_bncg_type gd -tao_gatol 1e-4
482:       requires: !single

484:    test:
485:       suffix: 6
486:       args: -tao_monitor_short -mx 8 -my 12 -tao_type bncg -tao_gatol 1e-4
487:       requires: !single

489:    test:
490:       suffix: 7
491:       args: -tao_monitor_short -mx 8 -my 12 -tao_type bnls -tao_gatol 1e-5
492:       requires: !single

494:    test:
495:       suffix: 8
496:       args: -tao_monitor_short -mx 8 -my 12 -tao_type bntr -tao_gatol 1e-5
497:       requires: !single

499:    test:
500:       suffix: 9
501:       args: -tao_monitor_short -mx 8 -my 12 -tao_type bntl -tao_gatol 1e-5
502:       requires: !single

504:    test:
505:       suffix: 10
506:       args: -tao_monitor_short -mx 8 -my 12 -tao_type bnls -tao_gatol 1e-5 -tao_bnk_max_cg_its 3
507:       requires: !single

509:    test:
510:       suffix: 11
511:       args: -tao_monitor_short -mx 8 -my 12 -tao_type bntr -tao_gatol 1e-5 -tao_bnk_max_cg_its 3
512:       requires: !single

514:    test:
515:       suffix: 12
516:       args: -tao_monitor_short -mx 8 -my 12 -tao_type bntl -tao_gatol 1e-5 -tao_bnk_max_cg_its 3
517:       requires: !single

519:    test:
520:      suffix: 13
521:      args: -tao_monitor_short -mx 8 -my 12 -tao_gatol 1e-4 -tao_type bqnls
522:      requires: !single

524:    test:
525:      suffix: 14
526:      args: -tao_monitor_short -mx 8 -my 12 -tao_gatol 1e-4 -tao_type blmvm
527:      requires: !single

529:    test:
530:      suffix: 15
531:      args: -tao_monitor_short -mx 8 -my 12 -tao_gatol 1e-4 -tao_type bqnkls -tao_bqnk_mat_type lmvmbfgs
532:      requires: !single

534:    test:
535:      suffix: 16
536:      args: -tao_monitor_short -mx 8 -my 12 -tao_gatol 1e-4 -tao_type bqnktr -tao_bqnk_mat_type lmvmsr1
537:      requires: !single

539:    test:
540:      suffix: 17
541:      args: -tao_monitor_short -mx 8 -my 12 -tao_gatol 1e-4 -tao_type bqnls -tao_bqnls_mat_lmvm_scale_type scalar -tao_view
542:      requires: !single

544:    test:
545:      suffix: 18
546:      args: -tao_monitor_short -mx 8 -my 12 -tao_gatol 1e-4 -tao_type bqnls -tao_bqnls_mat_lmvm_scale_type none -tao_view
547:      requires: !single

549:    test:
550:      suffix: 19
551:      args: -tao_monitor_short -mx 8 -my 12 -tao_type bnls -tao_gatol 1e-5 -tao_mf_hessian
552:      requires: !single

554:    test:
555:       suffix: 20
556:       args: -tao_monitor_short -mx 8 -my 12 -tao_type bntr -tao_gatol 1e-5 -tao_mf_hessian
557:       requires: !single

559:    test:
560:       suffix: 21
561:       args: -tao_monitor_short -mx 8 -my 12 -tao_type bntl -tao_gatol 1e-5 -tao_mf_hessian
562:       requires: !single
563: TEST*/