1 2 #include <../src/snes/impls/vi/ss/vissimpl.h> /*I "petscsnes.h" I*/ 3 4 /* 5 SNESVIComputeMeritFunction - Evaluates the merit function for the mixed complementarity problem. 6 7 Input Parameter: 8 . phi - the semismooth function 9 10 Output Parameter: 11 . merit - the merit function 12 . phinorm - ||phi|| 13 14 Notes: 15 The merit function for the mixed complementarity problem is defined as 16 merit = 0.5*phi^T*phi 17 */ 18 static PetscErrorCode SNESVIComputeMeritFunction(Vec phi, PetscReal *merit,PetscReal *phinorm) 19 { 20 PetscErrorCode ierr; 21 22 PetscFunctionBegin; 23 ierr = VecNormBegin(phi,NORM_2,phinorm);CHKERRQ(ierr); 24 ierr = VecNormEnd(phi,NORM_2,phinorm);CHKERRQ(ierr); 25 26 *merit = 0.5*(*phinorm)*(*phinorm); 27 PetscFunctionReturn(0); 28 } 29 30 PETSC_STATIC_INLINE PetscScalar Phi(PetscScalar a,PetscScalar b) 31 { 32 return a + b - PetscSqrtScalar(a*a + b*b); 33 } 34 35 PETSC_STATIC_INLINE PetscScalar DPhi(PetscScalar a,PetscScalar b) 36 { 37 if ((PetscAbsScalar(a) >= 1.e-6) || (PetscAbsScalar(b) >= 1.e-6)) return 1.0 - a/ PetscSqrtScalar(a*a + b*b); 38 else return .5; 39 } 40 41 /* 42 SNESVIComputeFunction - Reformulates a system of nonlinear equations in mixed complementarity form to a system of nonlinear equations in semismooth form. 43 44 Input Parameters: 45 . snes - the SNES context 46 . X - current iterate 47 . functx - user defined function context 48 49 Output Parameters: 50 . phi - Semismooth function 51 52 */ 53 static PetscErrorCode SNESVIComputeFunction(SNES snes,Vec X,Vec phi,void *functx) 54 { 55 PetscErrorCode ierr; 56 SNES_VINEWTONSSLS *vi = (SNES_VINEWTONSSLS*)snes->data; 57 Vec Xl = snes->xl,Xu = snes->xu,F = snes->vec_func; 58 PetscScalar *phi_arr,*f_arr,*l,*u; 59 const PetscScalar *x_arr; 60 PetscInt i,nlocal; 61 62 PetscFunctionBegin; 63 ierr = (*vi->computeuserfunction)(snes,X,F,functx);CHKERRQ(ierr); 64 ierr = VecGetLocalSize(X,&nlocal);CHKERRQ(ierr); 65 ierr = VecGetArrayRead(X,&x_arr);CHKERRQ(ierr); 66 ierr = VecGetArray(F,&f_arr);CHKERRQ(ierr); 67 ierr = VecGetArray(Xl,&l);CHKERRQ(ierr); 68 ierr = VecGetArray(Xu,&u);CHKERRQ(ierr); 69 ierr = VecGetArray(phi,&phi_arr);CHKERRQ(ierr); 70 71 for (i=0; i < nlocal; i++) { 72 if ((PetscRealPart(l[i]) <= PETSC_NINFINITY) && (PetscRealPart(u[i]) >= PETSC_INFINITY)) { /* no constraints on variable */ 73 phi_arr[i] = f_arr[i]; 74 } else if (PetscRealPart(l[i]) <= PETSC_NINFINITY) { /* upper bound on variable only */ 75 phi_arr[i] = -Phi(u[i] - x_arr[i],-f_arr[i]); 76 } else if (PetscRealPart(u[i]) >= PETSC_INFINITY) { /* lower bound on variable only */ 77 phi_arr[i] = Phi(x_arr[i] - l[i],f_arr[i]); 78 } else if (l[i] == u[i]) { 79 phi_arr[i] = l[i] - x_arr[i]; 80 } else { /* both bounds on variable */ 81 phi_arr[i] = Phi(x_arr[i] - l[i],-Phi(u[i] - x_arr[i],-f_arr[i])); 82 } 83 } 84 85 ierr = VecRestoreArrayRead(X,&x_arr);CHKERRQ(ierr); 86 ierr = VecRestoreArray(F,&f_arr);CHKERRQ(ierr); 87 ierr = VecRestoreArray(Xl,&l);CHKERRQ(ierr); 88 ierr = VecRestoreArray(Xu,&u);CHKERRQ(ierr); 89 ierr = VecRestoreArray(phi,&phi_arr);CHKERRQ(ierr); 90 PetscFunctionReturn(0); 91 } 92 93 /* 94 SNESVIComputeBsubdifferentialVectors - Computes the diagonal shift (Da) and row scaling (Db) vectors needed for the 95 the semismooth jacobian. 96 */ 97 PetscErrorCode SNESVIComputeBsubdifferentialVectors(SNES snes,Vec X,Vec F,Mat jac,Vec Da,Vec Db) 98 { 99 PetscErrorCode ierr; 100 PetscScalar *l,*u,*x,*f,*da,*db,da1,da2,db1,db2; 101 PetscInt i,nlocal; 102 103 PetscFunctionBegin; 104 ierr = VecGetArray(X,&x);CHKERRQ(ierr); 105 ierr = VecGetArray(F,&f);CHKERRQ(ierr); 106 ierr = VecGetArray(snes->xl,&l);CHKERRQ(ierr); 107 ierr = VecGetArray(snes->xu,&u);CHKERRQ(ierr); 108 ierr = VecGetArray(Da,&da);CHKERRQ(ierr); 109 ierr = VecGetArray(Db,&db);CHKERRQ(ierr); 110 ierr = VecGetLocalSize(X,&nlocal);CHKERRQ(ierr); 111 112 for (i=0; i< nlocal; i++) { 113 if ((PetscRealPart(l[i]) <= PETSC_NINFINITY) && (PetscRealPart(u[i]) >= PETSC_INFINITY)) { /* no constraints on variable */ 114 da[i] = 0; 115 db[i] = 1; 116 } else if (PetscRealPart(l[i]) <= PETSC_NINFINITY) { /* upper bound on variable only */ 117 da[i] = DPhi(u[i] - x[i], -f[i]); 118 db[i] = DPhi(-f[i],u[i] - x[i]); 119 } else if (PetscRealPart(u[i]) >= PETSC_INFINITY) { /* lower bound on variable only */ 120 da[i] = DPhi(x[i] - l[i], f[i]); 121 db[i] = DPhi(f[i],x[i] - l[i]); 122 } else if (l[i] == u[i]) { /* fixed variable */ 123 da[i] = 1; 124 db[i] = 0; 125 } else { /* upper and lower bounds on variable */ 126 da1 = DPhi(x[i] - l[i], -Phi(u[i] - x[i], -f[i])); 127 db1 = DPhi(-Phi(u[i] - x[i], -f[i]),x[i] - l[i]); 128 da2 = DPhi(u[i] - x[i], -f[i]); 129 db2 = DPhi(-f[i],u[i] - x[i]); 130 da[i] = da1 + db1*da2; 131 db[i] = db1*db2; 132 } 133 } 134 135 ierr = VecRestoreArray(X,&x);CHKERRQ(ierr); 136 ierr = VecRestoreArray(F,&f);CHKERRQ(ierr); 137 ierr = VecRestoreArray(snes->xl,&l);CHKERRQ(ierr); 138 ierr = VecRestoreArray(snes->xu,&u);CHKERRQ(ierr); 139 ierr = VecRestoreArray(Da,&da);CHKERRQ(ierr); 140 ierr = VecRestoreArray(Db,&db);CHKERRQ(ierr); 141 PetscFunctionReturn(0); 142 } 143 144 /* 145 SNESVIComputeJacobian - Computes the jacobian of the semismooth function.The Jacobian for the semismooth function is an element of the B-subdifferential of the Fischer-Burmeister function for complementarity problems. 146 147 Input Parameters: 148 . Da - Diagonal shift vector for the semismooth jacobian. 149 . Db - Row scaling vector for the semismooth jacobian. 150 151 Output Parameters: 152 . jac - semismooth jacobian 153 . jac_pre - optional preconditioning matrix 154 155 Notes: 156 The semismooth jacobian matrix is given by 157 jac = Da + Db*jacfun 158 where Db is the row scaling matrix stored as a vector, 159 Da is the diagonal perturbation matrix stored as a vector 160 and jacfun is the jacobian of the original nonlinear function. 161 */ 162 PetscErrorCode SNESVIComputeJacobian(Mat jac, Mat jac_pre,Vec Da, Vec Db) 163 { 164 PetscErrorCode ierr; 165 166 /* Do row scaling and add diagonal perturbation */ 167 ierr = MatDiagonalScale(jac,Db,NULL);CHKERRQ(ierr); 168 ierr = MatDiagonalSet(jac,Da,ADD_VALUES);CHKERRQ(ierr); 169 if (jac != jac_pre) { /* If jac and jac_pre are different */ 170 ierr = MatDiagonalScale(jac_pre,Db,NULL);CHKERRQ(ierr); 171 ierr = MatDiagonalSet(jac_pre,Da,ADD_VALUES);CHKERRQ(ierr); 172 } 173 PetscFunctionReturn(0); 174 } 175 176 /* 177 SNESVIComputeMeritFunctionGradient - Computes the gradient of the merit function psi. 178 179 Input Parameters: 180 phi - semismooth function. 181 H - semismooth jacobian 182 183 Output Parameters: 184 dpsi - merit function gradient 185 186 Notes: 187 The merit function gradient is computed as follows 188 dpsi = H^T*phi 189 */ 190 PetscErrorCode SNESVIComputeMeritFunctionGradient(Mat H, Vec phi, Vec dpsi) 191 { 192 PetscErrorCode ierr; 193 194 PetscFunctionBegin; 195 ierr = MatMultTranspose(H,phi,dpsi);CHKERRQ(ierr); 196 PetscFunctionReturn(0); 197 } 198 199 200 201 /* 202 SNESSolve_VINEWTONSSLS - Solves the complementarity problem with a semismooth Newton 203 method using a line search. 204 205 Input Parameters: 206 . snes - the SNES context 207 208 Application Interface Routine: SNESSolve() 209 210 Notes: 211 This implements essentially a semismooth Newton method with a 212 line search. The default line search does not do any line search 213 but rather takes a full Newton step. 214 215 Developer Note: the code in this file should be slightly modified so that this routine need not exist and the SNESSolve_NEWTONLS() routine is called directly with the appropriate wrapped function and Jacobian evaluations 216 217 */ 218 PetscErrorCode SNESSolve_VINEWTONSSLS(SNES snes) 219 { 220 SNES_VINEWTONSSLS *vi = (SNES_VINEWTONSSLS*)snes->data; 221 PetscErrorCode ierr; 222 PetscInt maxits,i,lits; 223 SNESLineSearchReason lssucceed; 224 PetscReal gnorm,xnorm=0,ynorm; 225 Vec Y,X,F; 226 KSPConvergedReason kspreason; 227 DM dm; 228 DMSNES sdm; 229 230 PetscFunctionBegin; 231 ierr = SNESGetDM(snes,&dm);CHKERRQ(ierr); 232 ierr = DMGetDMSNES(dm,&sdm);CHKERRQ(ierr); 233 234 vi->computeuserfunction = sdm->ops->computefunction; 235 sdm->ops->computefunction = SNESVIComputeFunction; 236 237 snes->numFailures = 0; 238 snes->numLinearSolveFailures = 0; 239 snes->reason = SNES_CONVERGED_ITERATING; 240 241 maxits = snes->max_its; /* maximum number of iterations */ 242 X = snes->vec_sol; /* solution vector */ 243 F = snes->vec_func; /* residual vector */ 244 Y = snes->work[0]; /* work vectors */ 245 246 ierr = PetscObjectSAWsTakeAccess((PetscObject)snes);CHKERRQ(ierr); 247 snes->iter = 0; 248 snes->norm = 0.0; 249 ierr = PetscObjectSAWsGrantAccess((PetscObject)snes);CHKERRQ(ierr); 250 251 ierr = SNESVIProjectOntoBounds(snes,X);CHKERRQ(ierr); 252 ierr = SNESComputeFunction(snes,X,vi->phi);CHKERRQ(ierr); 253 if (snes->domainerror) { 254 snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN; 255 sdm->ops->computefunction = vi->computeuserfunction; 256 PetscFunctionReturn(0); 257 } 258 /* Compute Merit function */ 259 ierr = SNESVIComputeMeritFunction(vi->phi,&vi->merit,&vi->phinorm);CHKERRQ(ierr); 260 261 ierr = VecNormBegin(X,NORM_2,&xnorm);CHKERRQ(ierr); /* xnorm <- ||x|| */ 262 ierr = VecNormEnd(X,NORM_2,&xnorm);CHKERRQ(ierr); 263 SNESCheckFunctionNorm(snes,vi->merit); 264 265 ierr = PetscObjectSAWsTakeAccess((PetscObject)snes);CHKERRQ(ierr); 266 snes->norm = vi->phinorm; 267 ierr = PetscObjectSAWsGrantAccess((PetscObject)snes);CHKERRQ(ierr); 268 ierr = SNESLogConvergenceHistory(snes,vi->phinorm,0);CHKERRQ(ierr); 269 ierr = SNESMonitor(snes,0,vi->phinorm);CHKERRQ(ierr); 270 271 /* test convergence */ 272 ierr = (*snes->ops->converged)(snes,0,0.0,0.0,vi->phinorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); 273 if (snes->reason) { 274 sdm->ops->computefunction = vi->computeuserfunction; 275 PetscFunctionReturn(0); 276 } 277 278 for (i=0; i<maxits; i++) { 279 280 /* Call general purpose update function */ 281 if (snes->ops->update) { 282 ierr = (*snes->ops->update)(snes, snes->iter);CHKERRQ(ierr); 283 } 284 285 /* Solve J Y = Phi, where J is the semismooth jacobian */ 286 287 /* Get the jacobian -- note that the function must be the original function for snes_fd and snes_fd_color to work for this*/ 288 sdm->ops->computefunction = vi->computeuserfunction; 289 ierr = SNESComputeJacobian(snes,X,snes->jacobian,snes->jacobian_pre);CHKERRQ(ierr); 290 sdm->ops->computefunction = SNESVIComputeFunction; 291 292 /* Get the diagonal shift and row scaling vectors */ 293 ierr = SNESVIComputeBsubdifferentialVectors(snes,X,F,snes->jacobian,vi->Da,vi->Db);CHKERRQ(ierr); 294 /* Compute the semismooth jacobian */ 295 ierr = SNESVIComputeJacobian(snes->jacobian,snes->jacobian_pre,vi->Da,vi->Db);CHKERRQ(ierr); 296 /* Compute the merit function gradient */ 297 ierr = SNESVIComputeMeritFunctionGradient(snes->jacobian,vi->phi,vi->dpsi);CHKERRQ(ierr); 298 ierr = KSPSetOperators(snes->ksp,snes->jacobian,snes->jacobian_pre);CHKERRQ(ierr); 299 ierr = KSPSolve(snes->ksp,vi->phi,Y);CHKERRQ(ierr); 300 ierr = KSPGetConvergedReason(snes->ksp,&kspreason);CHKERRQ(ierr); 301 302 if (kspreason < 0) { 303 if (++snes->numLinearSolveFailures >= snes->maxLinearSolveFailures) { 304 ierr = PetscInfo2(snes,"iter=%D, number linear solve failures %D greater than current SNES allowed, stopping solve\n",snes->iter,snes->numLinearSolveFailures);CHKERRQ(ierr); 305 snes->reason = SNES_DIVERGED_LINEAR_SOLVE; 306 break; 307 } 308 } 309 ierr = KSPGetIterationNumber(snes->ksp,&lits);CHKERRQ(ierr); 310 snes->linear_its += lits; 311 ierr = PetscInfo2(snes,"iter=%D, linear solve iterations=%D\n",snes->iter,lits);CHKERRQ(ierr); 312 /* 313 if (snes->ops->precheck) { 314 PetscBool changed_y = PETSC_FALSE; 315 ierr = (*snes->ops->precheck)(snes,X,Y,snes->precheck,&changed_y);CHKERRQ(ierr); 316 } 317 318 if (PetscLogPrintInfo) { 319 ierr = SNESVICheckResidual_Private(snes,snes->jacobian,F,Y,G,W);CHKERRQ(ierr); 320 } 321 */ 322 /* Compute a (scaled) negative update in the line search routine: 323 Y <- X - lambda*Y 324 and evaluate G = function(Y) (depends on the line search). 325 */ 326 ierr = VecCopy(Y,snes->vec_sol_update);CHKERRQ(ierr); 327 ynorm = 1; gnorm = vi->phinorm; 328 ierr = SNESLineSearchApply(snes->linesearch, X, vi->phi, &gnorm, Y);CHKERRQ(ierr); 329 ierr = SNESLineSearchGetReason(snes->linesearch, &lssucceed);CHKERRQ(ierr); 330 ierr = SNESLineSearchGetNorms(snes->linesearch, &xnorm, &gnorm, &ynorm);CHKERRQ(ierr); 331 ierr = PetscInfo4(snes,"fnorm=%18.16e, gnorm=%18.16e, ynorm=%18.16e, lssucceed=%d\n",(double)vi->phinorm,(double)gnorm,(double)ynorm,(int)lssucceed);CHKERRQ(ierr); 332 if (snes->reason == SNES_DIVERGED_FUNCTION_COUNT) break; 333 if (snes->domainerror) { 334 snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN; 335 sdm->ops->computefunction = vi->computeuserfunction; 336 PetscFunctionReturn(0); 337 } 338 if (lssucceed) { 339 if (++snes->numFailures >= snes->maxFailures) { 340 PetscBool ismin; 341 snes->reason = SNES_DIVERGED_LINE_SEARCH; 342 ierr = SNESVICheckLocalMin_Private(snes,snes->jacobian,vi->phi,X,gnorm,&ismin);CHKERRQ(ierr); 343 if (ismin) snes->reason = SNES_DIVERGED_LOCAL_MIN; 344 break; 345 } 346 } 347 /* Update function and solution vectors */ 348 vi->phinorm = gnorm; 349 vi->merit = 0.5*vi->phinorm*vi->phinorm; 350 /* Monitor convergence */ 351 ierr = PetscObjectSAWsTakeAccess((PetscObject)snes);CHKERRQ(ierr); 352 snes->iter = i+1; 353 snes->norm = vi->phinorm; 354 ierr = PetscObjectSAWsGrantAccess((PetscObject)snes);CHKERRQ(ierr); 355 ierr = SNESLogConvergenceHistory(snes,snes->norm,lits);CHKERRQ(ierr); 356 ierr = SNESMonitor(snes,snes->iter,snes->norm);CHKERRQ(ierr); 357 /* Test for convergence, xnorm = || X || */ 358 if (snes->ops->converged != SNESConvergedSkip) { ierr = VecNorm(X,NORM_2,&xnorm);CHKERRQ(ierr); } 359 ierr = (*snes->ops->converged)(snes,snes->iter,xnorm,ynorm,vi->phinorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); 360 if (snes->reason) break; 361 } 362 if (i == maxits) { 363 ierr = PetscInfo1(snes,"Maximum number of iterations has been reached: %D\n",maxits);CHKERRQ(ierr); 364 if (!snes->reason) snes->reason = SNES_DIVERGED_MAX_IT; 365 } 366 sdm->ops->computefunction = vi->computeuserfunction; 367 PetscFunctionReturn(0); 368 } 369 370 /* -------------------------------------------------------------------------- */ 371 /* 372 SNESSetUp_VINEWTONSSLS - Sets up the internal data structures for the later use 373 of the SNES nonlinear solver. 374 375 Input Parameter: 376 . snes - the SNES context 377 378 Application Interface Routine: SNESSetUp() 379 380 Notes: 381 For basic use of the SNES solvers, the user need not explicitly call 382 SNESSetUp(), since these actions will automatically occur during 383 the call to SNESSolve(). 384 */ 385 PetscErrorCode SNESSetUp_VINEWTONSSLS(SNES snes) 386 { 387 PetscErrorCode ierr; 388 SNES_VINEWTONSSLS *vi = (SNES_VINEWTONSSLS*) snes->data; 389 390 PetscFunctionBegin; 391 ierr = SNESSetUp_VI(snes);CHKERRQ(ierr); 392 ierr = VecDuplicate(snes->vec_sol, &vi->dpsi);CHKERRQ(ierr); 393 ierr = VecDuplicate(snes->vec_sol, &vi->phi);CHKERRQ(ierr); 394 ierr = VecDuplicate(snes->vec_sol, &vi->Da);CHKERRQ(ierr); 395 ierr = VecDuplicate(snes->vec_sol, &vi->Db);CHKERRQ(ierr); 396 ierr = VecDuplicate(snes->vec_sol, &vi->z);CHKERRQ(ierr); 397 ierr = VecDuplicate(snes->vec_sol, &vi->t);CHKERRQ(ierr); 398 PetscFunctionReturn(0); 399 } 400 /* -------------------------------------------------------------------------- */ 401 PetscErrorCode SNESReset_VINEWTONSSLS(SNES snes) 402 { 403 SNES_VINEWTONSSLS *vi = (SNES_VINEWTONSSLS*) snes->data; 404 PetscErrorCode ierr; 405 406 PetscFunctionBegin; 407 ierr = SNESReset_VI(snes);CHKERRQ(ierr); 408 ierr = VecDestroy(&vi->dpsi);CHKERRQ(ierr); 409 ierr = VecDestroy(&vi->phi);CHKERRQ(ierr); 410 ierr = VecDestroy(&vi->Da);CHKERRQ(ierr); 411 ierr = VecDestroy(&vi->Db);CHKERRQ(ierr); 412 ierr = VecDestroy(&vi->z);CHKERRQ(ierr); 413 ierr = VecDestroy(&vi->t);CHKERRQ(ierr); 414 PetscFunctionReturn(0); 415 } 416 417 /* -------------------------------------------------------------------------- */ 418 /* 419 SNESSetFromOptions_VINEWTONSSLS - Sets various parameters for the SNESVI method. 420 421 Input Parameter: 422 . snes - the SNES context 423 424 Application Interface Routine: SNESSetFromOptions() 425 */ 426 static PetscErrorCode SNESSetFromOptions_VINEWTONSSLS(PetscOptionItems *PetscOptionsObject,SNES snes) 427 { 428 PetscErrorCode ierr; 429 SNESLineSearch linesearch; 430 431 PetscFunctionBegin; 432 ierr = SNESSetFromOptions_VI(PetscOptionsObject,snes);CHKERRQ(ierr); 433 ierr = PetscOptionsHead(PetscOptionsObject,"SNES semismooth method options");CHKERRQ(ierr); 434 ierr = PetscOptionsTail();CHKERRQ(ierr); 435 /* set up the default line search */ 436 if (!snes->linesearch) { 437 ierr = SNESGetLineSearch(snes, &linesearch);CHKERRQ(ierr); 438 ierr = SNESLineSearchSetType(linesearch, SNESLINESEARCHBT);CHKERRQ(ierr); 439 ierr = SNESLineSearchBTSetAlpha(linesearch, 0.0);CHKERRQ(ierr); 440 } 441 PetscFunctionReturn(0); 442 } 443 444 445 /* -------------------------------------------------------------------------- */ 446 /*MC 447 SNESVINEWTONSSLS - Semi-smooth solver for variational inequalities based on Newton's method 448 449 Options Database: 450 + -snes_type <vinewtonssls,vinewtonrsls> a semi-smooth solver, a reduced space active set method 451 - -snes_vi_monitor - prints the number of active constraints at each iteration. 452 453 Level: beginner 454 455 References: 456 + 1. - T. S. Munson, F. Facchinei, M. C. Ferris, A. Fischer, and C. Kanzow. The semismooth 457 algorithm for large scale complementarity problems. INFORMS Journal on Computing, 13 (2001). 458 - 2. - T. S. Munson, and S. Benson. Flexible Complementarity Solvers for Large Scale 459 Applications, Optimization Methods and Software, 21 (2006). 460 461 .seealso: SNESVISetVariableBounds(), SNESVISetComputeVariableBounds(), SNESCreate(), SNES, SNESSetType(), SNESVINEWTONRSLS, SNESNEWTONTR, SNESLineSearchSetType(),SNESLineSearchSetPostCheck(), SNESLineSearchSetPreCheck() 462 463 M*/ 464 PETSC_EXTERN PetscErrorCode SNESCreate_VINEWTONSSLS(SNES snes) 465 { 466 PetscErrorCode ierr; 467 SNES_VINEWTONSSLS *vi; 468 469 PetscFunctionBegin; 470 snes->ops->reset = SNESReset_VINEWTONSSLS; 471 snes->ops->setup = SNESSetUp_VINEWTONSSLS; 472 snes->ops->solve = SNESSolve_VINEWTONSSLS; 473 snes->ops->destroy = SNESDestroy_VI; 474 snes->ops->setfromoptions = SNESSetFromOptions_VINEWTONSSLS; 475 snes->ops->view = NULL; 476 477 snes->usesksp = PETSC_TRUE; 478 snes->usesnpc = PETSC_FALSE; 479 480 snes->alwayscomputesfinalresidual = PETSC_FALSE; 481 482 ierr = PetscNewLog(snes,&vi);CHKERRQ(ierr); 483 snes->data = (void*)vi; 484 485 ierr = PetscObjectComposeFunction((PetscObject)snes,"SNESVISetVariableBounds_C",SNESVISetVariableBounds_VI);CHKERRQ(ierr); 486 ierr = PetscObjectComposeFunction((PetscObject)snes,"SNESVISetComputeVariableBounds_C",SNESVISetComputeVariableBounds_VI);CHKERRQ(ierr); 487 PetscFunctionReturn(0); 488 } 489 490