12b4ed282SShri Abhyankar 2c6db04a5SJed Brown #include <../src/snes/impls/vi/viimpl.h> /*I "petscsnes.h" I*/ 3c6db04a5SJed Brown #include <../include/private/kspimpl.h> 4c6db04a5SJed Brown #include <../include/private/matimpl.h> 5*d0af7cd3SBarry Smith #include <../include/private/dmimpl.h> 6*d0af7cd3SBarry Smith 7*d0af7cd3SBarry Smith typedef struct { 8*d0af7cd3SBarry Smith IS inactive; 9*d0af7cd3SBarry Smith Vec upper,lower,values,F; /* upper and lower bounds of all variables on this level, the values and the function values */ 10*d0af7cd3SBarry Smith PetscErrorCode (*getinterpolation)(DM,DM,Mat*,Vec*); /* DM's original routines */ 11*d0af7cd3SBarry Smith PetscErrorCode (*coarsen)(DM, MPI_Comm, DM*); 12*d0af7cd3SBarry Smith } DMSNESVI; 13*d0af7cd3SBarry Smith 14*d0af7cd3SBarry Smith #undef __FUNCT__ 15*d0af7cd3SBarry Smith #define __FUNCT__ "SNESVIGetInActiveSetIS" 16*d0af7cd3SBarry Smith /* 17*d0af7cd3SBarry Smith SNESVIGetInActiveSetIS - Gets the global indices for the bogus inactive set variables 18*d0af7cd3SBarry Smith 19*d0af7cd3SBarry Smith Input parameter 20*d0af7cd3SBarry Smith . snes - the SNES context 21*d0af7cd3SBarry Smith . X - the snes solution vector 22*d0af7cd3SBarry Smith 23*d0af7cd3SBarry Smith Output parameter 24*d0af7cd3SBarry Smith . ISact - active set index set 25*d0af7cd3SBarry Smith 26*d0af7cd3SBarry Smith */ 27*d0af7cd3SBarry Smith PetscErrorCode SNESVIGetInActiveSetIS(Vec upper,Vec lower,Vec X,Vec F,IS* inact) 28*d0af7cd3SBarry Smith { 29*d0af7cd3SBarry Smith PetscErrorCode ierr; 30*d0af7cd3SBarry Smith const PetscScalar *x,*xl,*xu,*f; 31*d0af7cd3SBarry Smith PetscInt *idx_act,i,nlocal,nloc_isact=0,ilow,ihigh,i1=0; 32*d0af7cd3SBarry Smith 33*d0af7cd3SBarry Smith PetscFunctionBegin; 34*d0af7cd3SBarry Smith ierr = VecGetLocalSize(X,&nlocal);CHKERRQ(ierr); 35*d0af7cd3SBarry Smith ierr = VecGetOwnershipRange(X,&ilow,&ihigh);CHKERRQ(ierr); 36*d0af7cd3SBarry Smith ierr = VecGetArrayRead(X,&x);CHKERRQ(ierr); 37*d0af7cd3SBarry Smith ierr = VecGetArrayRead(lower,&xl);CHKERRQ(ierr); 38*d0af7cd3SBarry Smith ierr = VecGetArrayRead(upper,&xu);CHKERRQ(ierr); 39*d0af7cd3SBarry Smith ierr = VecGetArrayRead(F,&f);CHKERRQ(ierr); 40*d0af7cd3SBarry Smith /* Compute inactive set size */ 41*d0af7cd3SBarry Smith for (i=0; i < nlocal;i++) { 42*d0af7cd3SBarry Smith if (((PetscRealPart(x[i]) > PetscRealPart(xl[i]) + 1.e-8 || (PetscRealPart(f[i]) < 0.0)) && ((PetscRealPart(x[i]) < PetscRealPart(xu[i]) - 1.e-8) || PetscRealPart(f[i]) > 0.0))) nloc_isact++; 43*d0af7cd3SBarry Smith } 44*d0af7cd3SBarry Smith 45*d0af7cd3SBarry Smith ierr = PetscMalloc(nloc_isact*sizeof(PetscInt),&idx_act);CHKERRQ(ierr); 46*d0af7cd3SBarry Smith 47*d0af7cd3SBarry Smith /* Set inactive set indices */ 48*d0af7cd3SBarry Smith for(i=0; i < nlocal; i++) { 49*d0af7cd3SBarry Smith if (((PetscRealPart(x[i]) > PetscRealPart(xl[i]) + 1.e-8 || (PetscRealPart(f[i]) < 0.0)) && ((PetscRealPart(x[i]) < PetscRealPart(xu[i]) - 1.e-8) || PetscRealPart(f[i]) > 0.0))) idx_act[i1++] = ilow+i; 50*d0af7cd3SBarry Smith } 51*d0af7cd3SBarry Smith 52*d0af7cd3SBarry Smith /* Create inactive set IS */ 53*d0af7cd3SBarry Smith ierr = ISCreateGeneral(((PetscObject)upper)->comm,nloc_isact,idx_act,PETSC_OWN_POINTER,inact);CHKERRQ(ierr); 54*d0af7cd3SBarry Smith 55*d0af7cd3SBarry Smith ierr = VecRestoreArrayRead(X,&x);CHKERRQ(ierr); 56*d0af7cd3SBarry Smith ierr = VecRestoreArrayRead(lower,&xl);CHKERRQ(ierr); 57*d0af7cd3SBarry Smith ierr = VecRestoreArrayRead(upper,&xu);CHKERRQ(ierr); 58*d0af7cd3SBarry Smith ierr = VecRestoreArrayRead(F,&f);CHKERRQ(ierr); 59*d0af7cd3SBarry Smith PetscFunctionReturn(0); 60*d0af7cd3SBarry Smith } 61*d0af7cd3SBarry Smith 62*d0af7cd3SBarry Smith #undef __FUNCT__ 63*d0af7cd3SBarry Smith #define __FUNCT__ "DMGetInterpolation_SNESVI" 64*d0af7cd3SBarry Smith /* 65*d0af7cd3SBarry Smith DMGetInterpolation_SNESVI - Modifieds the interpolation obtained from the DM by removing all rows and columns associated with active constraints. 66*d0af7cd3SBarry Smith 67*d0af7cd3SBarry Smith */ 68*d0af7cd3SBarry Smith PetscErrorCode DMGetInterpolation_SNESVI(DM dm1,DM dm2,Mat *mat,Vec *vec) 69*d0af7cd3SBarry Smith { 70*d0af7cd3SBarry Smith PetscErrorCode ierr; 71*d0af7cd3SBarry Smith PetscContainer isnes; 72*d0af7cd3SBarry Smith DMSNESVI *dmsnesvi1,*dmsnesvi2; 73*d0af7cd3SBarry Smith Mat interp; 74*d0af7cd3SBarry Smith 75*d0af7cd3SBarry Smith PetscFunctionBegin; 76*d0af7cd3SBarry Smith ierr = PetscObjectQuery((PetscObject)dm1,"VI",(PetscObject *)&isnes);CHKERRQ(ierr); 77*d0af7cd3SBarry Smith if (isnes) SETERRQ(((PetscObject)dm1)->comm,PETSC_ERR_PLIB,"Composed SNES is missing"); 78*d0af7cd3SBarry Smith ierr = PetscContainerGetPointer(isnes,(void**)&dmsnesvi1);CHKERRQ(ierr); 79*d0af7cd3SBarry Smith ierr = PetscObjectQuery((PetscObject)dm2,"VI",(PetscObject *)&isnes);CHKERRQ(ierr); 80*d0af7cd3SBarry Smith if (isnes) SETERRQ(((PetscObject)dm2)->comm,PETSC_ERR_PLIB,"Composed SNES is missing"); 81*d0af7cd3SBarry Smith ierr = PetscContainerGetPointer(isnes,(void**)&dmsnesvi2);CHKERRQ(ierr); 82*d0af7cd3SBarry Smith 83*d0af7cd3SBarry Smith ierr = (*dmsnesvi1->getinterpolation)(dm1,dm2,&interp,PETSC_NULL);CHKERRQ(ierr); 84*d0af7cd3SBarry Smith ierr = MatGetSubMatrix(interp,dmsnesvi1->inactive,dmsnesvi2->inactive,MAT_INITIAL_MATRIX,mat);CHKERRQ(ierr); 85*d0af7cd3SBarry Smith ierr = MatDestroy(&interp);CHKERRQ(ierr); 86*d0af7cd3SBarry Smith PetscFunctionReturn(0); 87*d0af7cd3SBarry Smith } 88*d0af7cd3SBarry Smith 89*d0af7cd3SBarry Smith extern PetscErrorCode DMSetVI(DM,Vec,Vec,Vec,Vec,IS); 90*d0af7cd3SBarry Smith 91*d0af7cd3SBarry Smith #undef __FUNCT__ 92*d0af7cd3SBarry Smith #define __FUNCT__ "DMCoarsen_SNESVI" 93*d0af7cd3SBarry Smith /* 94*d0af7cd3SBarry Smith DMCoarsen_SNESVI - Computes the regular coarsened DM then computes additional information about its inactive set 95*d0af7cd3SBarry Smith 96*d0af7cd3SBarry Smith */ 97*d0af7cd3SBarry Smith PetscErrorCode DMCoarsen_SNESVI(DM dm1,MPI_Comm comm,DM *dm2) 98*d0af7cd3SBarry Smith { 99*d0af7cd3SBarry Smith PetscErrorCode ierr; 100*d0af7cd3SBarry Smith PetscContainer isnes; 101*d0af7cd3SBarry Smith DMSNESVI *dmsnesvi1; 102*d0af7cd3SBarry Smith Vec upper,lower,values,F; 103*d0af7cd3SBarry Smith IS inactive; 104*d0af7cd3SBarry Smith VecScatter inject; 105*d0af7cd3SBarry Smith 106*d0af7cd3SBarry Smith PetscFunctionBegin; 107*d0af7cd3SBarry Smith ierr = PetscObjectQuery((PetscObject)dm1,"VI",(PetscObject *)&isnes);CHKERRQ(ierr); 108*d0af7cd3SBarry Smith if (isnes) SETERRQ(((PetscObject)dm1)->comm,PETSC_ERR_PLIB,"Composed SNES is missing"); 109*d0af7cd3SBarry Smith ierr = PetscContainerGetPointer(isnes,(void**)&dmsnesvi1);CHKERRQ(ierr); 110*d0af7cd3SBarry Smith 111*d0af7cd3SBarry Smith ierr = (*dmsnesvi1->coarsen)(dm1,comm,dm2);CHKERRQ(ierr); 112*d0af7cd3SBarry Smith ierr = DMGetInjection(*dm2,dm1,&inject);CHKERRQ(ierr); 113*d0af7cd3SBarry Smith ierr = DMCreateGlobalVector(*dm2,&upper);CHKERRQ(ierr); 114*d0af7cd3SBarry Smith ierr = VecScatterBegin(inject,dmsnesvi1->upper,upper,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 115*d0af7cd3SBarry Smith ierr = VecScatterEnd(inject,dmsnesvi1->upper,upper,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 116*d0af7cd3SBarry Smith ierr = DMCreateGlobalVector(*dm2,&lower);CHKERRQ(ierr); 117*d0af7cd3SBarry Smith ierr = VecScatterBegin(inject,dmsnesvi1->lower,lower,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 118*d0af7cd3SBarry Smith ierr = VecScatterEnd(inject,dmsnesvi1->lower,lower,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 119*d0af7cd3SBarry Smith ierr = DMCreateGlobalVector(*dm2,&values);CHKERRQ(ierr); 120*d0af7cd3SBarry Smith ierr = VecScatterBegin(inject,dmsnesvi1->values,values,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 121*d0af7cd3SBarry Smith ierr = VecScatterEnd(inject,dmsnesvi1->values,values,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 122*d0af7cd3SBarry Smith ierr = DMCreateGlobalVector(*dm2,&F);CHKERRQ(ierr); 123*d0af7cd3SBarry Smith ierr = VecScatterBegin(inject,dmsnesvi1->F,F,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 124*d0af7cd3SBarry Smith ierr = VecScatterEnd(inject,dmsnesvi1->F,F,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 125*d0af7cd3SBarry Smith ierr = VecScatterDestroy(&inject);CHKERRQ(ierr); 126*d0af7cd3SBarry Smith ierr = SNESVIGetInActiveSetIS(upper,lower,values,F,&inactive);CHKERRQ(ierr); 127*d0af7cd3SBarry Smith ierr = DMSetVI(*dm2,upper,lower,values,F,inactive);CHKERRQ(ierr); 128*d0af7cd3SBarry Smith PetscFunctionReturn(0); 129*d0af7cd3SBarry Smith } 130*d0af7cd3SBarry Smith 131*d0af7cd3SBarry Smith #undef __FUNCT__ 132*d0af7cd3SBarry Smith #define __FUNCT__ "DMSNESVIDestroy" 133*d0af7cd3SBarry Smith PetscErrorCode DMSNESVIDestroy(DMSNESVI *dmsnesvi) 134*d0af7cd3SBarry Smith { 135*d0af7cd3SBarry Smith PetscErrorCode ierr; 136*d0af7cd3SBarry Smith 137*d0af7cd3SBarry Smith PetscFunctionBegin; 138*d0af7cd3SBarry Smith ierr = VecDestroy(&dmsnesvi->upper);CHKERRQ(ierr); 139*d0af7cd3SBarry Smith ierr = VecDestroy(&dmsnesvi->lower);CHKERRQ(ierr); 140*d0af7cd3SBarry Smith ierr = VecDestroy(&dmsnesvi->values);CHKERRQ(ierr); 141*d0af7cd3SBarry Smith ierr = VecDestroy(&dmsnesvi->F);CHKERRQ(ierr); 142*d0af7cd3SBarry Smith ierr = ISDestroy(&dmsnesvi->inactive);CHKERRQ(ierr); 143*d0af7cd3SBarry Smith ierr = PetscFree(dmsnesvi);CHKERRQ(ierr); 144*d0af7cd3SBarry Smith PetscFunctionReturn(0); 145*d0af7cd3SBarry Smith } 146*d0af7cd3SBarry Smith 147*d0af7cd3SBarry Smith #undef __FUNCT__ 148*d0af7cd3SBarry Smith #define __FUNCT__ "DMSetVI" 149*d0af7cd3SBarry Smith /* 150*d0af7cd3SBarry Smith DMSetVI - Marks a DM as associated with a VI problem. This causes the interpolation/restriction operators to 151*d0af7cd3SBarry Smith be restricted to only those variables NOT associated with active constraints. 152*d0af7cd3SBarry Smith 153*d0af7cd3SBarry Smith */ 154*d0af7cd3SBarry Smith PetscErrorCode DMSetVI(DM dm,Vec upper,Vec lower,Vec values,Vec F,IS inactive) 155*d0af7cd3SBarry Smith { 156*d0af7cd3SBarry Smith PetscErrorCode ierr; 157*d0af7cd3SBarry Smith PetscContainer isnes; 158*d0af7cd3SBarry Smith DMSNESVI *dmsnesvi; 159*d0af7cd3SBarry Smith 160*d0af7cd3SBarry Smith PetscFunctionBegin; 161*d0af7cd3SBarry Smith ierr = PetscObjectReference((PetscObject)upper);CHKERRQ(ierr); 162*d0af7cd3SBarry Smith ierr = PetscObjectReference((PetscObject)lower);CHKERRQ(ierr); 163*d0af7cd3SBarry Smith ierr = PetscObjectReference((PetscObject)values);CHKERRQ(ierr); 164*d0af7cd3SBarry Smith ierr = PetscObjectReference((PetscObject)F);CHKERRQ(ierr); 165*d0af7cd3SBarry Smith ierr = PetscObjectReference((PetscObject)inactive);CHKERRQ(ierr); 166*d0af7cd3SBarry Smith 167*d0af7cd3SBarry Smith ierr = PetscObjectQuery((PetscObject)dm,"VI",(PetscObject *)&isnes);CHKERRQ(ierr); 168*d0af7cd3SBarry Smith if (!isnes) { 169*d0af7cd3SBarry Smith /* cannot just compose snes into dm because that will cause circular reference */ 170*d0af7cd3SBarry Smith ierr = PetscContainerCreate(((PetscObject)dm)->comm,&isnes);CHKERRQ(ierr); 171*d0af7cd3SBarry Smith ierr = PetscContainerSetUserDestroy(isnes,(PetscErrorCode (*)(void*))DMSNESVIDestroy);CHKERRQ(ierr); 172*d0af7cd3SBarry Smith ierr = PetscNew(DMSNESVI,&dmsnesvi);CHKERRQ(ierr); 173*d0af7cd3SBarry Smith ierr = PetscContainerSetPointer(isnes,(void*)dmsnesvi);CHKERRQ(ierr); 174*d0af7cd3SBarry Smith ierr = PetscObjectCompose((PetscObject)dm,"VI",(PetscObject)isnes);CHKERRQ(ierr); 175*d0af7cd3SBarry Smith dmsnesvi->getinterpolation = dm->ops->getinterpolation; 176*d0af7cd3SBarry Smith dm->ops->getinterpolation = DMGetInterpolation_SNESVI; 177*d0af7cd3SBarry Smith dmsnesvi->coarsen = dm->ops->coarsen; 178*d0af7cd3SBarry Smith dm->ops->coarsen = DMCoarsen_SNESVI; 179*d0af7cd3SBarry Smith } else { 180*d0af7cd3SBarry Smith ierr = PetscContainerGetPointer(isnes,(void**)&dmsnesvi);CHKERRQ(ierr); 181*d0af7cd3SBarry Smith ierr = VecDestroy(&dmsnesvi->upper);CHKERRQ(ierr); 182*d0af7cd3SBarry Smith ierr = VecDestroy(&dmsnesvi->lower);CHKERRQ(ierr); 183*d0af7cd3SBarry Smith ierr = VecDestroy(&dmsnesvi->values);CHKERRQ(ierr); 184*d0af7cd3SBarry Smith ierr = VecDestroy(&dmsnesvi->F);CHKERRQ(ierr); 185*d0af7cd3SBarry Smith ierr = ISDestroy(&dmsnesvi->inactive);CHKERRQ(ierr); 186*d0af7cd3SBarry Smith } 187*d0af7cd3SBarry Smith dmsnesvi->upper = upper; 188*d0af7cd3SBarry Smith dmsnesvi->lower = lower; 189*d0af7cd3SBarry Smith dmsnesvi->values = values; 190*d0af7cd3SBarry Smith dmsnesvi->F = F; 191*d0af7cd3SBarry Smith dmsnesvi->inactive = inactive; 192*d0af7cd3SBarry Smith PetscFunctionReturn(0); 193*d0af7cd3SBarry Smith } 194*d0af7cd3SBarry Smith 195*d0af7cd3SBarry Smith 1962b4ed282SShri Abhyankar 1979308c137SBarry Smith #undef __FUNCT__ 1989308c137SBarry Smith #define __FUNCT__ "SNESMonitorVI" 1997087cfbeSBarry Smith PetscErrorCode SNESMonitorVI(SNES snes,PetscInt its,PetscReal fgnorm,void *dummy) 2009308c137SBarry Smith { 2019308c137SBarry Smith PetscErrorCode ierr; 2029308c137SBarry Smith SNES_VI *vi = (SNES_VI*)snes->data; 2039308c137SBarry Smith PetscViewerASCIIMonitor viewer = (PetscViewerASCIIMonitor) dummy; 2049308c137SBarry Smith const PetscScalar *x,*xl,*xu,*f; 20509573ac7SBarry Smith PetscInt i,n,act = 0; 2069308c137SBarry Smith PetscReal rnorm,fnorm; 2079308c137SBarry Smith 2089308c137SBarry Smith PetscFunctionBegin; 2099308c137SBarry Smith if (!dummy) { 2109308c137SBarry Smith ierr = PetscViewerASCIIMonitorCreate(((PetscObject)snes)->comm,"stdout",0,&viewer);CHKERRQ(ierr); 2119308c137SBarry Smith } 2129308c137SBarry Smith ierr = VecGetLocalSize(snes->vec_sol,&n);CHKERRQ(ierr); 2139308c137SBarry Smith ierr = VecGetArrayRead(vi->xl,&xl);CHKERRQ(ierr); 2149308c137SBarry Smith ierr = VecGetArrayRead(vi->xu,&xu);CHKERRQ(ierr); 2159308c137SBarry Smith ierr = VecGetArrayRead(snes->vec_sol,&x);CHKERRQ(ierr); 2163f731af5SBarry Smith ierr = VecGetArrayRead(snes->vec_func,&f);CHKERRQ(ierr); 2179308c137SBarry Smith 2189308c137SBarry Smith rnorm = 0.0; 2199308c137SBarry Smith for (i=0; i<n; i++) { 22010f5ae6bSBarry Smith if (((PetscRealPart(x[i]) > PetscRealPart(xl[i]) + 1.e-8 || (PetscRealPart(f[i]) < 0.0)) && ((PetscRealPart(x[i]) < PetscRealPart(xu[i]) - 1.e-8) || PetscRealPart(f[i]) > 0.0))) rnorm += PetscRealPart(PetscConj(f[i])*f[i]); 22109573ac7SBarry Smith else act++; 2229308c137SBarry Smith } 2233f731af5SBarry Smith ierr = VecRestoreArrayRead(snes->vec_func,&f);CHKERRQ(ierr); 2249308c137SBarry Smith ierr = VecRestoreArrayRead(vi->xl,&xl);CHKERRQ(ierr); 2259308c137SBarry Smith ierr = VecRestoreArrayRead(vi->xu,&xu);CHKERRQ(ierr); 2269308c137SBarry Smith ierr = VecRestoreArrayRead(snes->vec_sol,&x);CHKERRQ(ierr); 227d9822059SBarry Smith ierr = MPI_Allreduce(&rnorm,&fnorm,1,MPIU_REAL,MPIU_SUM,((PetscObject)snes)->comm);CHKERRQ(ierr); 2289308c137SBarry Smith fnorm = sqrt(fnorm); 22909573ac7SBarry Smith ierr = PetscViewerASCIIMonitorPrintf(viewer,"%3D SNES VI Function norm %14.12e Active constraints %D\n",its,fnorm,act);CHKERRQ(ierr); 2309308c137SBarry Smith if (!dummy) { 2316bf464f9SBarry Smith ierr = PetscViewerASCIIMonitorDestroy(&viewer);CHKERRQ(ierr); 2329308c137SBarry Smith } 2339308c137SBarry Smith PetscFunctionReturn(0); 2349308c137SBarry Smith } 2359308c137SBarry Smith 2362b4ed282SShri Abhyankar /* 2372b4ed282SShri Abhyankar Checks if J^T F = 0 which implies we've found a local minimum of the norm of the function, 2382b4ed282SShri Abhyankar || F(u) ||_2 but not a zero, F(u) = 0. In the case when one cannot compute J^T F we use the fact that 2392b4ed282SShri Abhyankar 0 = (J^T F)^T W = F^T J W iff W not in the null space of J. Thanks for Jorge More 2402b4ed282SShri Abhyankar for this trick. One assumes that the probability that W is in the null space of J is very, very small. 2412b4ed282SShri Abhyankar */ 2422b4ed282SShri Abhyankar #undef __FUNCT__ 2432b4ed282SShri Abhyankar #define __FUNCT__ "SNESVICheckLocalMin_Private" 244ace3abfcSBarry Smith PetscErrorCode SNESVICheckLocalMin_Private(SNES snes,Mat A,Vec F,Vec W,PetscReal fnorm,PetscBool *ismin) 2452b4ed282SShri Abhyankar { 2462b4ed282SShri Abhyankar PetscReal a1; 2472b4ed282SShri Abhyankar PetscErrorCode ierr; 248ace3abfcSBarry Smith PetscBool hastranspose; 2492b4ed282SShri Abhyankar 2502b4ed282SShri Abhyankar PetscFunctionBegin; 2512b4ed282SShri Abhyankar *ismin = PETSC_FALSE; 2522b4ed282SShri Abhyankar ierr = MatHasOperation(A,MATOP_MULT_TRANSPOSE,&hastranspose);CHKERRQ(ierr); 2532b4ed282SShri Abhyankar if (hastranspose) { 2542b4ed282SShri Abhyankar /* Compute || J^T F|| */ 2552b4ed282SShri Abhyankar ierr = MatMultTranspose(A,F,W);CHKERRQ(ierr); 2562b4ed282SShri Abhyankar ierr = VecNorm(W,NORM_2,&a1);CHKERRQ(ierr); 2572b4ed282SShri Abhyankar ierr = PetscInfo1(snes,"|| J^T F|| %G near zero implies found a local minimum\n",a1/fnorm);CHKERRQ(ierr); 2582b4ed282SShri Abhyankar if (a1/fnorm < 1.e-4) *ismin = PETSC_TRUE; 2592b4ed282SShri Abhyankar } else { 2602b4ed282SShri Abhyankar Vec work; 2612b4ed282SShri Abhyankar PetscScalar result; 2622b4ed282SShri Abhyankar PetscReal wnorm; 2632b4ed282SShri Abhyankar 2642b4ed282SShri Abhyankar ierr = VecSetRandom(W,PETSC_NULL);CHKERRQ(ierr); 2652b4ed282SShri Abhyankar ierr = VecNorm(W,NORM_2,&wnorm);CHKERRQ(ierr); 2662b4ed282SShri Abhyankar ierr = VecDuplicate(W,&work);CHKERRQ(ierr); 2672b4ed282SShri Abhyankar ierr = MatMult(A,W,work);CHKERRQ(ierr); 2682b4ed282SShri Abhyankar ierr = VecDot(F,work,&result);CHKERRQ(ierr); 2696bf464f9SBarry Smith ierr = VecDestroy(&work);CHKERRQ(ierr); 2702b4ed282SShri Abhyankar a1 = PetscAbsScalar(result)/(fnorm*wnorm); 2712b4ed282SShri Abhyankar ierr = PetscInfo1(snes,"(F^T J random)/(|| F ||*||random|| %G near zero implies found a local minimum\n",a1);CHKERRQ(ierr); 2722b4ed282SShri Abhyankar if (a1 < 1.e-4) *ismin = PETSC_TRUE; 2732b4ed282SShri Abhyankar } 2742b4ed282SShri Abhyankar PetscFunctionReturn(0); 2752b4ed282SShri Abhyankar } 2762b4ed282SShri Abhyankar 2772b4ed282SShri Abhyankar /* 2782b4ed282SShri Abhyankar Checks if J^T(F - J*X) = 0 2792b4ed282SShri Abhyankar */ 2802b4ed282SShri Abhyankar #undef __FUNCT__ 2812b4ed282SShri Abhyankar #define __FUNCT__ "SNESVICheckResidual_Private" 2822b4ed282SShri Abhyankar PetscErrorCode SNESVICheckResidual_Private(SNES snes,Mat A,Vec F,Vec X,Vec W1,Vec W2) 2832b4ed282SShri Abhyankar { 2842b4ed282SShri Abhyankar PetscReal a1,a2; 2852b4ed282SShri Abhyankar PetscErrorCode ierr; 286ace3abfcSBarry Smith PetscBool hastranspose; 2872b4ed282SShri Abhyankar 2882b4ed282SShri Abhyankar PetscFunctionBegin; 2892b4ed282SShri Abhyankar ierr = MatHasOperation(A,MATOP_MULT_TRANSPOSE,&hastranspose);CHKERRQ(ierr); 2902b4ed282SShri Abhyankar if (hastranspose) { 2912b4ed282SShri Abhyankar ierr = MatMult(A,X,W1);CHKERRQ(ierr); 2922b4ed282SShri Abhyankar ierr = VecAXPY(W1,-1.0,F);CHKERRQ(ierr); 2932b4ed282SShri Abhyankar 2942b4ed282SShri Abhyankar /* Compute || J^T W|| */ 2952b4ed282SShri Abhyankar ierr = MatMultTranspose(A,W1,W2);CHKERRQ(ierr); 2962b4ed282SShri Abhyankar ierr = VecNorm(W1,NORM_2,&a1);CHKERRQ(ierr); 2972b4ed282SShri Abhyankar ierr = VecNorm(W2,NORM_2,&a2);CHKERRQ(ierr); 2982b4ed282SShri Abhyankar if (a1 != 0.0) { 2992b4ed282SShri Abhyankar ierr = PetscInfo1(snes,"||J^T(F-Ax)||/||F-AX|| %G near zero implies inconsistent rhs\n",a2/a1);CHKERRQ(ierr); 3002b4ed282SShri Abhyankar } 3012b4ed282SShri Abhyankar } 3022b4ed282SShri Abhyankar PetscFunctionReturn(0); 3032b4ed282SShri Abhyankar } 3042b4ed282SShri Abhyankar 3052b4ed282SShri Abhyankar /* 3062b4ed282SShri Abhyankar SNESDefaultConverged_VI - Checks the convergence of the semismooth newton algorithm. 3072b4ed282SShri Abhyankar 3082b4ed282SShri Abhyankar Notes: 3092b4ed282SShri Abhyankar The convergence criterion currently implemented is 3102b4ed282SShri Abhyankar merit < abstol 3112b4ed282SShri Abhyankar merit < rtol*merit_initial 3122b4ed282SShri Abhyankar */ 3132b4ed282SShri Abhyankar #undef __FUNCT__ 3142b4ed282SShri Abhyankar #define __FUNCT__ "SNESDefaultConverged_VI" 3157fe79bc4SShri Abhyankar PetscErrorCode SNESDefaultConverged_VI(SNES snes,PetscInt it,PetscReal xnorm,PetscReal gradnorm,PetscReal fnorm,SNESConvergedReason *reason,void *dummy) 3162b4ed282SShri Abhyankar { 3172b4ed282SShri Abhyankar PetscErrorCode ierr; 3182b4ed282SShri Abhyankar 3192b4ed282SShri Abhyankar PetscFunctionBegin; 3202b4ed282SShri Abhyankar PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 3212b4ed282SShri Abhyankar PetscValidPointer(reason,6); 3222b4ed282SShri Abhyankar 3232b4ed282SShri Abhyankar *reason = SNES_CONVERGED_ITERATING; 3242b4ed282SShri Abhyankar 3252b4ed282SShri Abhyankar if (!it) { 3262b4ed282SShri Abhyankar /* set parameter for default relative tolerance convergence test */ 3277fe79bc4SShri Abhyankar snes->ttol = fnorm*snes->rtol; 3282b4ed282SShri Abhyankar } 3297fe79bc4SShri Abhyankar if (fnorm != fnorm) { 3302b4ed282SShri Abhyankar ierr = PetscInfo(snes,"Failed to converged, function norm is NaN\n");CHKERRQ(ierr); 3312b4ed282SShri Abhyankar *reason = SNES_DIVERGED_FNORM_NAN; 3327fe79bc4SShri Abhyankar } else if (fnorm < snes->abstol) { 3337fe79bc4SShri Abhyankar ierr = PetscInfo2(snes,"Converged due to function norm %G < %G\n",fnorm,snes->abstol);CHKERRQ(ierr); 3342b4ed282SShri Abhyankar *reason = SNES_CONVERGED_FNORM_ABS; 3352b4ed282SShri Abhyankar } else if (snes->nfuncs >= snes->max_funcs) { 3362b4ed282SShri Abhyankar ierr = PetscInfo2(snes,"Exceeded maximum number of function evaluations: %D > %D\n",snes->nfuncs,snes->max_funcs);CHKERRQ(ierr); 3372b4ed282SShri Abhyankar *reason = SNES_DIVERGED_FUNCTION_COUNT; 3382b4ed282SShri Abhyankar } 3392b4ed282SShri Abhyankar 3402b4ed282SShri Abhyankar if (it && !*reason) { 3417fe79bc4SShri Abhyankar if (fnorm < snes->ttol) { 3427fe79bc4SShri Abhyankar ierr = PetscInfo2(snes,"Converged due to function norm %G < %G (relative tolerance)\n",fnorm,snes->ttol);CHKERRQ(ierr); 3432b4ed282SShri Abhyankar *reason = SNES_CONVERGED_FNORM_RELATIVE; 3442b4ed282SShri Abhyankar } 3452b4ed282SShri Abhyankar } 3462b4ed282SShri Abhyankar PetscFunctionReturn(0); 3472b4ed282SShri Abhyankar } 3482b4ed282SShri Abhyankar 3492b4ed282SShri Abhyankar /* 3502b4ed282SShri Abhyankar SNESVIComputeMeritFunction - Evaluates the merit function for the mixed complementarity problem. 3512b4ed282SShri Abhyankar 3522b4ed282SShri Abhyankar Input Parameter: 3532b4ed282SShri Abhyankar . phi - the semismooth function 3542b4ed282SShri Abhyankar 3552b4ed282SShri Abhyankar Output Parameter: 3562b4ed282SShri Abhyankar . merit - the merit function 3572b4ed282SShri Abhyankar . phinorm - ||phi|| 3582b4ed282SShri Abhyankar 3592b4ed282SShri Abhyankar Notes: 3602b4ed282SShri Abhyankar The merit function for the mixed complementarity problem is defined as 3612b4ed282SShri Abhyankar merit = 0.5*phi^T*phi 3622b4ed282SShri Abhyankar */ 3632b4ed282SShri Abhyankar #undef __FUNCT__ 3642b4ed282SShri Abhyankar #define __FUNCT__ "SNESVIComputeMeritFunction" 3652b4ed282SShri Abhyankar static PetscErrorCode SNESVIComputeMeritFunction(Vec phi, PetscReal* merit,PetscReal* phinorm) 3662b4ed282SShri Abhyankar { 3672b4ed282SShri Abhyankar PetscErrorCode ierr; 3682b4ed282SShri Abhyankar 3692b4ed282SShri Abhyankar PetscFunctionBegin; 3705f48b12bSBarry Smith ierr = VecNormBegin(phi,NORM_2,phinorm);CHKERRQ(ierr); 3715f48b12bSBarry Smith ierr = VecNormEnd(phi,NORM_2,phinorm);CHKERRQ(ierr); 3722b4ed282SShri Abhyankar 3732b4ed282SShri Abhyankar *merit = 0.5*(*phinorm)*(*phinorm); 3742b4ed282SShri Abhyankar PetscFunctionReturn(0); 3752b4ed282SShri Abhyankar } 3762b4ed282SShri Abhyankar 3777f6f51e9SSatish Balay PETSC_STATIC_INLINE PetscScalar Phi(PetscScalar a,PetscScalar b) 3784c21c6cdSBarry Smith { 3794c21c6cdSBarry Smith return a + b - sqrt(a*a + b*b); 3804c21c6cdSBarry Smith } 3814c21c6cdSBarry Smith 3827f6f51e9SSatish Balay PETSC_STATIC_INLINE PetscScalar DPhi(PetscScalar a,PetscScalar b) 3834c21c6cdSBarry Smith { 3845559b345SBarry Smith if ((PetscAbsScalar(a) >= 1.e-6) || (PetscAbsScalar(b) >= 1.e-6)) return 1.0 - a/ sqrt(a*a + b*b); 3855559b345SBarry Smith else return .5; 3864c21c6cdSBarry Smith } 3874c21c6cdSBarry Smith 3882b4ed282SShri Abhyankar /* 3891f79c099SShri Abhyankar SNESVIComputeFunction - Reformulates a system of nonlinear equations in mixed complementarity form to a system of nonlinear equations in semismooth form. 3902b4ed282SShri Abhyankar 3912b4ed282SShri Abhyankar Input Parameters: 3922b4ed282SShri Abhyankar . snes - the SNES context 3932b4ed282SShri Abhyankar . x - current iterate 3942b4ed282SShri Abhyankar . functx - user defined function context 3952b4ed282SShri Abhyankar 3962b4ed282SShri Abhyankar Output Parameters: 3972b4ed282SShri Abhyankar . phi - Semismooth function 3982b4ed282SShri Abhyankar 3992b4ed282SShri Abhyankar */ 4002b4ed282SShri Abhyankar #undef __FUNCT__ 4011f79c099SShri Abhyankar #define __FUNCT__ "SNESVIComputeFunction" 4021f79c099SShri Abhyankar static PetscErrorCode SNESVIComputeFunction(SNES snes,Vec X,Vec phi,void* functx) 4032b4ed282SShri Abhyankar { 4042b4ed282SShri Abhyankar PetscErrorCode ierr; 4052b4ed282SShri Abhyankar SNES_VI *vi = (SNES_VI*)snes->data; 4062b4ed282SShri Abhyankar Vec Xl = vi->xl,Xu = vi->xu,F = snes->vec_func; 4074c21c6cdSBarry Smith PetscScalar *phi_arr,*x_arr,*f_arr,*l,*u; 4082b4ed282SShri Abhyankar PetscInt i,nlocal; 4092b4ed282SShri Abhyankar 4102b4ed282SShri Abhyankar PetscFunctionBegin; 4112b4ed282SShri Abhyankar ierr = (*vi->computeuserfunction)(snes,X,F,functx);CHKERRQ(ierr); 4122b4ed282SShri Abhyankar ierr = VecGetLocalSize(X,&nlocal);CHKERRQ(ierr); 4132b4ed282SShri Abhyankar ierr = VecGetArray(X,&x_arr);CHKERRQ(ierr); 4142b4ed282SShri Abhyankar ierr = VecGetArray(F,&f_arr);CHKERRQ(ierr); 4152b4ed282SShri Abhyankar ierr = VecGetArray(Xl,&l);CHKERRQ(ierr); 4162b4ed282SShri Abhyankar ierr = VecGetArray(Xu,&u);CHKERRQ(ierr); 4172b4ed282SShri Abhyankar ierr = VecGetArray(phi,&phi_arr);CHKERRQ(ierr); 4182b4ed282SShri Abhyankar 4192b4ed282SShri Abhyankar for (i=0;i < nlocal;i++) { 42010f5ae6bSBarry Smith if ((PetscRealPart(l[i]) <= SNES_VI_NINF) && (PetscRealPart(u[i]) >= SNES_VI_INF)) { /* no constraints on variable */ 4214c21c6cdSBarry Smith phi_arr[i] = f_arr[i]; 42210f5ae6bSBarry Smith } else if (PetscRealPart(l[i]) <= SNES_VI_NINF) { /* upper bound on variable only */ 4234c21c6cdSBarry Smith phi_arr[i] = -Phi(u[i] - x_arr[i],-f_arr[i]); 42410f5ae6bSBarry Smith } else if (PetscRealPart(u[i]) >= SNES_VI_INF) { /* lower bound on variable only */ 4254c21c6cdSBarry Smith phi_arr[i] = Phi(x_arr[i] - l[i],f_arr[i]); 4265559b345SBarry Smith } else if (l[i] == u[i]) { 4272b4ed282SShri Abhyankar phi_arr[i] = l[i] - x_arr[i]; 4285559b345SBarry Smith } else { /* both bounds on variable */ 4294c21c6cdSBarry Smith phi_arr[i] = Phi(x_arr[i] - l[i],-Phi(u[i] - x_arr[i],-f_arr[i])); 4302b4ed282SShri Abhyankar } 4312b4ed282SShri Abhyankar } 4322b4ed282SShri Abhyankar 4332b4ed282SShri Abhyankar ierr = VecRestoreArray(X,&x_arr);CHKERRQ(ierr); 4342b4ed282SShri Abhyankar ierr = VecRestoreArray(F,&f_arr);CHKERRQ(ierr); 4352b4ed282SShri Abhyankar ierr = VecRestoreArray(Xl,&l);CHKERRQ(ierr); 4362b4ed282SShri Abhyankar ierr = VecRestoreArray(Xu,&u);CHKERRQ(ierr); 4372b4ed282SShri Abhyankar ierr = VecRestoreArray(phi,&phi_arr);CHKERRQ(ierr); 4382b4ed282SShri Abhyankar PetscFunctionReturn(0); 4392b4ed282SShri Abhyankar } 4402b4ed282SShri Abhyankar 4412b4ed282SShri Abhyankar /* 442a79edbefSShri Abhyankar SNESVIComputeBsubdifferentialVectors - Computes the diagonal shift (Da) and row scaling (Db) vectors needed for the 443a79edbefSShri Abhyankar the semismooth jacobian. 4442b4ed282SShri Abhyankar */ 4452b4ed282SShri Abhyankar #undef __FUNCT__ 446a79edbefSShri Abhyankar #define __FUNCT__ "SNESVIComputeBsubdifferentialVectors" 447a79edbefSShri Abhyankar PetscErrorCode SNESVIComputeBsubdifferentialVectors(SNES snes,Vec X,Vec F,Mat jac,Vec Da,Vec Db) 4482b4ed282SShri Abhyankar { 4492b4ed282SShri Abhyankar PetscErrorCode ierr; 4502b4ed282SShri Abhyankar SNES_VI *vi = (SNES_VI*)snes->data; 4514c21c6cdSBarry Smith PetscScalar *l,*u,*x,*f,*da,*db,da1,da2,db1,db2; 4522b4ed282SShri Abhyankar PetscInt i,nlocal; 4532b4ed282SShri Abhyankar 4542b4ed282SShri Abhyankar PetscFunctionBegin; 4552b4ed282SShri Abhyankar 4562b4ed282SShri Abhyankar ierr = VecGetArray(X,&x);CHKERRQ(ierr); 4572b4ed282SShri Abhyankar ierr = VecGetArray(F,&f);CHKERRQ(ierr); 4582b4ed282SShri Abhyankar ierr = VecGetArray(vi->xl,&l);CHKERRQ(ierr); 4592b4ed282SShri Abhyankar ierr = VecGetArray(vi->xu,&u);CHKERRQ(ierr); 460a79edbefSShri Abhyankar ierr = VecGetArray(Da,&da);CHKERRQ(ierr); 461a79edbefSShri Abhyankar ierr = VecGetArray(Db,&db);CHKERRQ(ierr); 4622b4ed282SShri Abhyankar ierr = VecGetLocalSize(X,&nlocal);CHKERRQ(ierr); 4634c21c6cdSBarry Smith 4642b4ed282SShri Abhyankar for (i=0;i< nlocal;i++) { 46510f5ae6bSBarry Smith if ((PetscRealPart(l[i]) <= SNES_VI_NINF) && (PetscRealPart(u[i]) >= SNES_VI_INF)) {/* no constraints on variable */ 4664c21c6cdSBarry Smith da[i] = 0; 4672b4ed282SShri Abhyankar db[i] = 1; 46810f5ae6bSBarry Smith } else if (PetscRealPart(l[i]) <= SNES_VI_NINF) { /* upper bound on variable only */ 4694c21c6cdSBarry Smith da[i] = DPhi(u[i] - x[i], -f[i]); 4704c21c6cdSBarry Smith db[i] = DPhi(-f[i],u[i] - x[i]); 47110f5ae6bSBarry Smith } else if (PetscRealPart(u[i]) >= SNES_VI_INF) { /* lower bound on variable only */ 4725559b345SBarry Smith da[i] = DPhi(x[i] - l[i], f[i]); 4735559b345SBarry Smith db[i] = DPhi(f[i],x[i] - l[i]); 4745559b345SBarry Smith } else if (l[i] == u[i]) { /* fixed variable */ 4754c21c6cdSBarry Smith da[i] = 1; 4762b4ed282SShri Abhyankar db[i] = 0; 4775559b345SBarry Smith } else { /* upper and lower bounds on variable */ 4784c21c6cdSBarry Smith da1 = DPhi(x[i] - l[i], -Phi(u[i] - x[i], -f[i])); 4794c21c6cdSBarry Smith db1 = DPhi(-Phi(u[i] - x[i], -f[i]),x[i] - l[i]); 4804c21c6cdSBarry Smith da2 = DPhi(u[i] - x[i], -f[i]); 4814c21c6cdSBarry Smith db2 = DPhi(-f[i],u[i] - x[i]); 4824c21c6cdSBarry Smith da[i] = da1 + db1*da2; 4834c21c6cdSBarry Smith db[i] = db1*db2; 4842b4ed282SShri Abhyankar } 4852b4ed282SShri Abhyankar } 4865559b345SBarry Smith 4872b4ed282SShri Abhyankar ierr = VecRestoreArray(X,&x);CHKERRQ(ierr); 4882b4ed282SShri Abhyankar ierr = VecRestoreArray(F,&f);CHKERRQ(ierr); 4892b4ed282SShri Abhyankar ierr = VecRestoreArray(vi->xl,&l);CHKERRQ(ierr); 4902b4ed282SShri Abhyankar ierr = VecRestoreArray(vi->xu,&u);CHKERRQ(ierr); 491a79edbefSShri Abhyankar ierr = VecRestoreArray(Da,&da);CHKERRQ(ierr); 492a79edbefSShri Abhyankar ierr = VecRestoreArray(Db,&db);CHKERRQ(ierr); 493a79edbefSShri Abhyankar PetscFunctionReturn(0); 494a79edbefSShri Abhyankar } 495a79edbefSShri Abhyankar 496a79edbefSShri Abhyankar /* 497a79edbefSShri Abhyankar 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. 498a79edbefSShri Abhyankar 499a79edbefSShri Abhyankar Input Parameters: 500a79edbefSShri Abhyankar . Da - Diagonal shift vector for the semismooth jacobian. 501a79edbefSShri Abhyankar . Db - Row scaling vector for the semismooth jacobian. 502a79edbefSShri Abhyankar 503a79edbefSShri Abhyankar Output Parameters: 504a79edbefSShri Abhyankar . jac - semismooth jacobian 505a79edbefSShri Abhyankar . jac_pre - optional preconditioning matrix 506a79edbefSShri Abhyankar 507a79edbefSShri Abhyankar Notes: 508a79edbefSShri Abhyankar The semismooth jacobian matrix is given by 509a79edbefSShri Abhyankar jac = Da + Db*jacfun 510a79edbefSShri Abhyankar where Db is the row scaling matrix stored as a vector, 511a79edbefSShri Abhyankar Da is the diagonal perturbation matrix stored as a vector 512a79edbefSShri Abhyankar and jacfun is the jacobian of the original nonlinear function. 513a79edbefSShri Abhyankar */ 514a79edbefSShri Abhyankar #undef __FUNCT__ 515a79edbefSShri Abhyankar #define __FUNCT__ "SNESVIComputeJacobian" 516a79edbefSShri Abhyankar PetscErrorCode SNESVIComputeJacobian(Mat jac, Mat jac_pre,Vec Da, Vec Db) 517a79edbefSShri Abhyankar { 518a79edbefSShri Abhyankar PetscErrorCode ierr; 519a79edbefSShri Abhyankar 5202b4ed282SShri Abhyankar /* Do row scaling and add diagonal perturbation */ 521a79edbefSShri Abhyankar ierr = MatDiagonalScale(jac,Db,PETSC_NULL);CHKERRQ(ierr); 522a79edbefSShri Abhyankar ierr = MatDiagonalSet(jac,Da,ADD_VALUES);CHKERRQ(ierr); 523a79edbefSShri Abhyankar if (jac != jac_pre) { /* If jac and jac_pre are different */ 524a79edbefSShri Abhyankar ierr = MatDiagonalScale(jac_pre,Db,PETSC_NULL); 525a79edbefSShri Abhyankar ierr = MatDiagonalSet(jac_pre,Da,ADD_VALUES);CHKERRQ(ierr); 5262b4ed282SShri Abhyankar } 5272b4ed282SShri Abhyankar PetscFunctionReturn(0); 5282b4ed282SShri Abhyankar } 5292b4ed282SShri Abhyankar 5302b4ed282SShri Abhyankar /* 531ee657d29SShri Abhyankar SNESVIComputeMeritFunctionGradient - Computes the gradient of the merit function psi. 532ee657d29SShri Abhyankar 533ee657d29SShri Abhyankar Input Parameters: 534ee657d29SShri Abhyankar phi - semismooth function. 535ee657d29SShri Abhyankar H - semismooth jacobian 536ee657d29SShri Abhyankar 537ee657d29SShri Abhyankar Output Parameters: 538ee657d29SShri Abhyankar dpsi - merit function gradient 539ee657d29SShri Abhyankar 540ee657d29SShri Abhyankar Notes: 541ee657d29SShri Abhyankar The merit function gradient is computed as follows 542ee657d29SShri Abhyankar dpsi = H^T*phi 543ee657d29SShri Abhyankar */ 544ee657d29SShri Abhyankar #undef __FUNCT__ 545ee657d29SShri Abhyankar #define __FUNCT__ "SNESVIComputeMeritFunctionGradient" 546ee657d29SShri Abhyankar PetscErrorCode SNESVIComputeMeritFunctionGradient(Mat H, Vec phi, Vec dpsi) 547ee657d29SShri Abhyankar { 548ee657d29SShri Abhyankar PetscErrorCode ierr; 549ee657d29SShri Abhyankar 550ee657d29SShri Abhyankar PetscFunctionBegin; 5515f48b12bSBarry Smith ierr = MatMultTranspose(H,phi,dpsi);CHKERRQ(ierr); 552ee657d29SShri Abhyankar PetscFunctionReturn(0); 553ee657d29SShri Abhyankar } 554ee657d29SShri Abhyankar 555c1a5e521SShri Abhyankar /* -------------------------------------------------------------------------- */ 556c1a5e521SShri Abhyankar /* 557c1a5e521SShri Abhyankar SNESVIProjectOntoBounds - Projects X onto the feasible region so that Xl[i] <= X[i] <= Xu[i] for i = 1...n. 558c1a5e521SShri Abhyankar 559c1a5e521SShri Abhyankar Input Parameters: 560c1a5e521SShri Abhyankar . SNES - nonlinear solver context 561c1a5e521SShri Abhyankar 562c1a5e521SShri Abhyankar Output Parameters: 563c1a5e521SShri Abhyankar . X - Bound projected X 564c1a5e521SShri Abhyankar 565c1a5e521SShri Abhyankar */ 566c1a5e521SShri Abhyankar 567c1a5e521SShri Abhyankar #undef __FUNCT__ 568c1a5e521SShri Abhyankar #define __FUNCT__ "SNESVIProjectOntoBounds" 569c1a5e521SShri Abhyankar PetscErrorCode SNESVIProjectOntoBounds(SNES snes,Vec X) 570c1a5e521SShri Abhyankar { 571c1a5e521SShri Abhyankar PetscErrorCode ierr; 572c1a5e521SShri Abhyankar SNES_VI *vi = (SNES_VI*)snes->data; 573c1a5e521SShri Abhyankar const PetscScalar *xl,*xu; 574c1a5e521SShri Abhyankar PetscScalar *x; 575c1a5e521SShri Abhyankar PetscInt i,n; 576c1a5e521SShri Abhyankar 577c1a5e521SShri Abhyankar PetscFunctionBegin; 578c1a5e521SShri Abhyankar ierr = VecGetLocalSize(X,&n);CHKERRQ(ierr); 579c1a5e521SShri Abhyankar ierr = VecGetArray(X,&x);CHKERRQ(ierr); 580c1a5e521SShri Abhyankar ierr = VecGetArrayRead(vi->xl,&xl);CHKERRQ(ierr); 581c1a5e521SShri Abhyankar ierr = VecGetArrayRead(vi->xu,&xu);CHKERRQ(ierr); 582c1a5e521SShri Abhyankar 583c1a5e521SShri Abhyankar for(i = 0;i<n;i++) { 58410f5ae6bSBarry Smith if (PetscRealPart(x[i]) < PetscRealPart(xl[i])) x[i] = xl[i]; 58510f5ae6bSBarry Smith else if (PetscRealPart(x[i]) > PetscRealPart(xu[i])) x[i] = xu[i]; 586c1a5e521SShri Abhyankar } 587c1a5e521SShri Abhyankar ierr = VecRestoreArray(X,&x);CHKERRQ(ierr); 588c1a5e521SShri Abhyankar ierr = VecRestoreArrayRead(vi->xl,&xl);CHKERRQ(ierr); 589c1a5e521SShri Abhyankar ierr = VecRestoreArrayRead(vi->xu,&xu);CHKERRQ(ierr); 590c1a5e521SShri Abhyankar PetscFunctionReturn(0); 591c1a5e521SShri Abhyankar } 592c1a5e521SShri Abhyankar 5932b4ed282SShri Abhyankar /* -------------------------------------------------------------------- 5942b4ed282SShri Abhyankar 5952b4ed282SShri Abhyankar This file implements a semismooth truncated Newton method with a line search, 5962b4ed282SShri Abhyankar for solving a system of nonlinear equations in complementarity form, using the KSP, Vec, 5972b4ed282SShri Abhyankar and Mat interfaces for linear solvers, vectors, and matrices, 5982b4ed282SShri Abhyankar respectively. 5992b4ed282SShri Abhyankar 6002b4ed282SShri Abhyankar The following basic routines are required for each nonlinear solver: 6012b4ed282SShri Abhyankar SNESCreate_XXX() - Creates a nonlinear solver context 6022b4ed282SShri Abhyankar SNESSetFromOptions_XXX() - Sets runtime options 6032b4ed282SShri Abhyankar SNESSolve_XXX() - Solves the nonlinear system 6042b4ed282SShri Abhyankar SNESDestroy_XXX() - Destroys the nonlinear solver context 6052b4ed282SShri Abhyankar The suffix "_XXX" denotes a particular implementation, in this case 6062b4ed282SShri Abhyankar we use _VI (e.g., SNESCreate_VI, SNESSolve_VI) for solving 6072b4ed282SShri Abhyankar systems of nonlinear equations with a line search (LS) method. 6082b4ed282SShri Abhyankar These routines are actually called via the common user interface 6092b4ed282SShri Abhyankar routines SNESCreate(), SNESSetFromOptions(), SNESSolve(), and 6102b4ed282SShri Abhyankar SNESDestroy(), so the application code interface remains identical 6112b4ed282SShri Abhyankar for all nonlinear solvers. 6122b4ed282SShri Abhyankar 6132b4ed282SShri Abhyankar Another key routine is: 6142b4ed282SShri Abhyankar SNESSetUp_XXX() - Prepares for the use of a nonlinear solver 6152b4ed282SShri Abhyankar by setting data structures and options. The interface routine SNESSetUp() 6162b4ed282SShri Abhyankar is not usually called directly by the user, but instead is called by 6172b4ed282SShri Abhyankar SNESSolve() if necessary. 6182b4ed282SShri Abhyankar 6192b4ed282SShri Abhyankar Additional basic routines are: 6202b4ed282SShri Abhyankar SNESView_XXX() - Prints details of runtime options that 6212b4ed282SShri Abhyankar have actually been used. 6222b4ed282SShri Abhyankar These are called by application codes via the interface routines 6232b4ed282SShri Abhyankar SNESView(). 6242b4ed282SShri Abhyankar 6252b4ed282SShri Abhyankar The various types of solvers (preconditioners, Krylov subspace methods, 6262b4ed282SShri Abhyankar nonlinear solvers, timesteppers) are all organized similarly, so the 6272b4ed282SShri Abhyankar above description applies to these categories also. 6282b4ed282SShri Abhyankar 6292b4ed282SShri Abhyankar -------------------------------------------------------------------- */ 6302b4ed282SShri Abhyankar /* 63169c03620SShri Abhyankar SNESSolveVI_SS - Solves the complementarity problem with a semismooth Newton 6322b4ed282SShri Abhyankar method using a line search. 6332b4ed282SShri Abhyankar 6342b4ed282SShri Abhyankar Input Parameters: 6352b4ed282SShri Abhyankar . snes - the SNES context 6362b4ed282SShri Abhyankar 6372b4ed282SShri Abhyankar Output Parameter: 6382b4ed282SShri Abhyankar . outits - number of iterations until termination 6392b4ed282SShri Abhyankar 6402b4ed282SShri Abhyankar Application Interface Routine: SNESSolve() 6412b4ed282SShri Abhyankar 6422b4ed282SShri Abhyankar Notes: 6432b4ed282SShri Abhyankar This implements essentially a semismooth Newton method with a 64451defd01SShri Abhyankar line search. The default line search does not do any line seach 64551defd01SShri Abhyankar but rather takes a full newton step. 6462b4ed282SShri Abhyankar */ 6472b4ed282SShri Abhyankar #undef __FUNCT__ 64869c03620SShri Abhyankar #define __FUNCT__ "SNESSolveVI_SS" 64969c03620SShri Abhyankar PetscErrorCode SNESSolveVI_SS(SNES snes) 6502b4ed282SShri Abhyankar { 6512b4ed282SShri Abhyankar SNES_VI *vi = (SNES_VI*)snes->data; 6522b4ed282SShri Abhyankar PetscErrorCode ierr; 6532b4ed282SShri Abhyankar PetscInt maxits,i,lits; 6543b336b49SShri Abhyankar PetscBool lssucceed; 6552b4ed282SShri Abhyankar MatStructure flg = DIFFERENT_NONZERO_PATTERN; 6562b4ed282SShri Abhyankar PetscReal gnorm,xnorm=0,ynorm; 6572b4ed282SShri Abhyankar Vec Y,X,F,G,W; 6582b4ed282SShri Abhyankar KSPConvergedReason kspreason; 6592b4ed282SShri Abhyankar 6602b4ed282SShri Abhyankar PetscFunctionBegin; 6619ce7406fSBarry Smith vi->computeuserfunction = snes->ops->computefunction; 6629ce7406fSBarry Smith snes->ops->computefunction = SNESVIComputeFunction; 6639ce7406fSBarry Smith 6642b4ed282SShri Abhyankar snes->numFailures = 0; 6652b4ed282SShri Abhyankar snes->numLinearSolveFailures = 0; 6662b4ed282SShri Abhyankar snes->reason = SNES_CONVERGED_ITERATING; 6672b4ed282SShri Abhyankar 6682b4ed282SShri Abhyankar maxits = snes->max_its; /* maximum number of iterations */ 6692b4ed282SShri Abhyankar X = snes->vec_sol; /* solution vector */ 6702b4ed282SShri Abhyankar F = snes->vec_func; /* residual vector */ 6712b4ed282SShri Abhyankar Y = snes->work[0]; /* work vectors */ 6722b4ed282SShri Abhyankar G = snes->work[1]; 6732b4ed282SShri Abhyankar W = snes->work[2]; 6742b4ed282SShri Abhyankar 6752b4ed282SShri Abhyankar ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 6762b4ed282SShri Abhyankar snes->iter = 0; 6772b4ed282SShri Abhyankar snes->norm = 0.0; 6782b4ed282SShri Abhyankar ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 6792b4ed282SShri Abhyankar 6807fe79bc4SShri Abhyankar ierr = SNESVIProjectOntoBounds(snes,X);CHKERRQ(ierr); 6812b4ed282SShri Abhyankar ierr = SNESComputeFunction(snes,X,vi->phi);CHKERRQ(ierr); 6822b4ed282SShri Abhyankar if (snes->domainerror) { 6832b4ed282SShri Abhyankar snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN; 6849ce7406fSBarry Smith snes->ops->computefunction = vi->computeuserfunction; 6852b4ed282SShri Abhyankar PetscFunctionReturn(0); 6862b4ed282SShri Abhyankar } 6872b4ed282SShri Abhyankar /* Compute Merit function */ 6882b4ed282SShri Abhyankar ierr = SNESVIComputeMeritFunction(vi->phi,&vi->merit,&vi->phinorm);CHKERRQ(ierr); 6892b4ed282SShri Abhyankar 6902b4ed282SShri Abhyankar ierr = VecNormBegin(X,NORM_2,&xnorm);CHKERRQ(ierr); /* xnorm <- ||x|| */ 6912b4ed282SShri Abhyankar ierr = VecNormEnd(X,NORM_2,&xnorm);CHKERRQ(ierr); 69262cbcd01SMatthew G Knepley if (PetscIsInfOrNanReal(vi->merit)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number"); 6932b4ed282SShri Abhyankar 6942b4ed282SShri Abhyankar ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 6952b4ed282SShri Abhyankar snes->norm = vi->phinorm; 6962b4ed282SShri Abhyankar ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 6972b4ed282SShri Abhyankar SNESLogConvHistory(snes,vi->phinorm,0); 6987a03ce2fSLisandro Dalcin ierr = SNESMonitor(snes,0,vi->phinorm);CHKERRQ(ierr); 6992b4ed282SShri Abhyankar 7002b4ed282SShri Abhyankar /* set parameter for default relative tolerance convergence test */ 7012b4ed282SShri Abhyankar snes->ttol = vi->phinorm*snes->rtol; 7022b4ed282SShri Abhyankar /* test convergence */ 7032b4ed282SShri Abhyankar ierr = (*snes->ops->converged)(snes,0,0.0,0.0,vi->phinorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); 7049ce7406fSBarry Smith if (snes->reason) { 7059ce7406fSBarry Smith snes->ops->computefunction = vi->computeuserfunction; 7069ce7406fSBarry Smith PetscFunctionReturn(0); 7079ce7406fSBarry Smith } 7082b4ed282SShri Abhyankar 7092b4ed282SShri Abhyankar for (i=0; i<maxits; i++) { 7102b4ed282SShri Abhyankar 7112b4ed282SShri Abhyankar /* Call general purpose update function */ 7122b4ed282SShri Abhyankar if (snes->ops->update) { 7132b4ed282SShri Abhyankar ierr = (*snes->ops->update)(snes, snes->iter);CHKERRQ(ierr); 7142b4ed282SShri Abhyankar } 7152b4ed282SShri Abhyankar 7162b4ed282SShri Abhyankar /* Solve J Y = Phi, where J is the semismooth jacobian */ 717a79edbefSShri Abhyankar /* Get the nonlinear function jacobian */ 7182b4ed282SShri Abhyankar ierr = SNESComputeJacobian(snes,X,&snes->jacobian,&snes->jacobian_pre,&flg);CHKERRQ(ierr); 719a79edbefSShri Abhyankar /* Get the diagonal shift and row scaling vectors */ 720a79edbefSShri Abhyankar ierr = SNESVIComputeBsubdifferentialVectors(snes,X,F,snes->jacobian,vi->Da,vi->Db);CHKERRQ(ierr); 721a79edbefSShri Abhyankar /* Compute the semismooth jacobian */ 722a79edbefSShri Abhyankar ierr = SNESVIComputeJacobian(snes->jacobian,snes->jacobian_pre,vi->Da,vi->Db);CHKERRQ(ierr); 723ee657d29SShri Abhyankar /* Compute the merit function gradient */ 724ee657d29SShri Abhyankar ierr = SNESVIComputeMeritFunctionGradient(snes->jacobian,vi->phi,vi->dpsi);CHKERRQ(ierr); 7252b4ed282SShri Abhyankar ierr = KSPSetOperators(snes->ksp,snes->jacobian,snes->jacobian_pre,flg);CHKERRQ(ierr); 7262b4ed282SShri Abhyankar ierr = SNES_KSPSolve(snes,snes->ksp,vi->phi,Y);CHKERRQ(ierr); 7272b4ed282SShri Abhyankar ierr = KSPGetConvergedReason(snes->ksp,&kspreason);CHKERRQ(ierr); 7283b336b49SShri Abhyankar 7293b336b49SShri Abhyankar if (kspreason < 0) { 7302b4ed282SShri Abhyankar if (++snes->numLinearSolveFailures >= snes->maxLinearSolveFailures) { 7312b4ed282SShri Abhyankar ierr = PetscInfo2(snes,"iter=%D, number linear solve failures %D greater than current SNES allowed, stopping solve\n",snes->iter,snes->numLinearSolveFailures);CHKERRQ(ierr); 7322b4ed282SShri Abhyankar snes->reason = SNES_DIVERGED_LINEAR_SOLVE; 7332b4ed282SShri Abhyankar break; 7342b4ed282SShri Abhyankar } 7352b4ed282SShri Abhyankar } 7362b4ed282SShri Abhyankar ierr = KSPGetIterationNumber(snes->ksp,&lits);CHKERRQ(ierr); 7372b4ed282SShri Abhyankar snes->linear_its += lits; 7382b4ed282SShri Abhyankar ierr = PetscInfo2(snes,"iter=%D, linear solve iterations=%D\n",snes->iter,lits);CHKERRQ(ierr); 7392b4ed282SShri Abhyankar /* 7402b4ed282SShri Abhyankar if (vi->precheckstep) { 741ace3abfcSBarry Smith PetscBool changed_y = PETSC_FALSE; 7422b4ed282SShri Abhyankar ierr = (*vi->precheckstep)(snes,X,Y,vi->precheck,&changed_y);CHKERRQ(ierr); 7432b4ed282SShri Abhyankar } 7442b4ed282SShri Abhyankar 7452b4ed282SShri Abhyankar if (PetscLogPrintInfo){ 7462b4ed282SShri Abhyankar ierr = SNESVICheckResidual_Private(snes,snes->jacobian,F,Y,G,W);CHKERRQ(ierr); 7472b4ed282SShri Abhyankar } 7482b4ed282SShri Abhyankar */ 7492b4ed282SShri Abhyankar /* Compute a (scaled) negative update in the line search routine: 7502b4ed282SShri Abhyankar Y <- X - lambda*Y 7512b4ed282SShri Abhyankar and evaluate G = function(Y) (depends on the line search). 7522b4ed282SShri Abhyankar */ 7532b4ed282SShri Abhyankar ierr = VecCopy(Y,snes->vec_sol_update);CHKERRQ(ierr); 7542b4ed282SShri Abhyankar ynorm = 1; gnorm = vi->phinorm; 7552b4ed282SShri Abhyankar ierr = (*vi->LineSearch)(snes,vi->lsP,X,vi->phi,G,Y,W,vi->phinorm,xnorm,&ynorm,&gnorm,&lssucceed);CHKERRQ(ierr); 7562b4ed282SShri Abhyankar ierr = PetscInfo4(snes,"fnorm=%18.16e, gnorm=%18.16e, ynorm=%18.16e, lssucceed=%d\n",vi->phinorm,gnorm,ynorm,(int)lssucceed);CHKERRQ(ierr); 7572b4ed282SShri Abhyankar if (snes->reason == SNES_DIVERGED_FUNCTION_COUNT) break; 7582b4ed282SShri Abhyankar if (snes->domainerror) { 7592b4ed282SShri Abhyankar snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN; 7609ce7406fSBarry Smith snes->ops->computefunction = vi->computeuserfunction; 7612b4ed282SShri Abhyankar PetscFunctionReturn(0); 7622b4ed282SShri Abhyankar } 7632b4ed282SShri Abhyankar if (!lssucceed) { 7642b4ed282SShri Abhyankar if (++snes->numFailures >= snes->maxFailures) { 765ace3abfcSBarry Smith PetscBool ismin; 7662b4ed282SShri Abhyankar snes->reason = SNES_DIVERGED_LINE_SEARCH; 7672b4ed282SShri Abhyankar ierr = SNESVICheckLocalMin_Private(snes,snes->jacobian,G,W,gnorm,&ismin);CHKERRQ(ierr); 7682b4ed282SShri Abhyankar if (ismin) snes->reason = SNES_DIVERGED_LOCAL_MIN; 7692b4ed282SShri Abhyankar break; 7702b4ed282SShri Abhyankar } 7712b4ed282SShri Abhyankar } 7722b4ed282SShri Abhyankar /* Update function and solution vectors */ 7732b4ed282SShri Abhyankar vi->phinorm = gnorm; 7742b4ed282SShri Abhyankar vi->merit = 0.5*vi->phinorm*vi->phinorm; 7752b4ed282SShri Abhyankar ierr = VecCopy(G,vi->phi);CHKERRQ(ierr); 7762b4ed282SShri Abhyankar ierr = VecCopy(W,X);CHKERRQ(ierr); 7772b4ed282SShri Abhyankar /* Monitor convergence */ 7782b4ed282SShri Abhyankar ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 7792b4ed282SShri Abhyankar snes->iter = i+1; 7802b4ed282SShri Abhyankar snes->norm = vi->phinorm; 7812b4ed282SShri Abhyankar ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 7822b4ed282SShri Abhyankar SNESLogConvHistory(snes,snes->norm,lits); 7837a03ce2fSLisandro Dalcin ierr = SNESMonitor(snes,snes->iter,snes->norm);CHKERRQ(ierr); 7842b4ed282SShri Abhyankar /* Test for convergence, xnorm = || X || */ 7852b4ed282SShri Abhyankar if (snes->ops->converged != SNESSkipConverged) { ierr = VecNorm(X,NORM_2,&xnorm);CHKERRQ(ierr); } 7862b4ed282SShri Abhyankar ierr = (*snes->ops->converged)(snes,snes->iter,xnorm,ynorm,vi->phinorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); 7872b4ed282SShri Abhyankar if (snes->reason) break; 7882b4ed282SShri Abhyankar } 7892b4ed282SShri Abhyankar if (i == maxits) { 7902b4ed282SShri Abhyankar ierr = PetscInfo1(snes,"Maximum number of iterations has been reached: %D\n",maxits);CHKERRQ(ierr); 7912b4ed282SShri Abhyankar if(!snes->reason) snes->reason = SNES_DIVERGED_MAX_IT; 7922b4ed282SShri Abhyankar } 7939ce7406fSBarry Smith snes->ops->computefunction = vi->computeuserfunction; 7942b4ed282SShri Abhyankar PetscFunctionReturn(0); 7952b4ed282SShri Abhyankar } 79669c03620SShri Abhyankar 79769c03620SShri Abhyankar #undef __FUNCT__ 798693ddf92SShri Abhyankar #define __FUNCT__ "SNESVIGetActiveSetIS" 799693ddf92SShri Abhyankar /* 800693ddf92SShri Abhyankar SNESVIGetActiveSetIndices - Gets the global indices for the active set variables 801693ddf92SShri Abhyankar 802693ddf92SShri Abhyankar Input parameter 803693ddf92SShri Abhyankar . snes - the SNES context 804693ddf92SShri Abhyankar . X - the snes solution vector 805693ddf92SShri Abhyankar . F - the nonlinear function vector 806693ddf92SShri Abhyankar 807693ddf92SShri Abhyankar Output parameter 808693ddf92SShri Abhyankar . ISact - active set index set 809693ddf92SShri Abhyankar */ 810693ddf92SShri Abhyankar PetscErrorCode SNESVIGetActiveSetIS(SNES snes,Vec X,Vec F,IS* ISact) 811d950fb63SShri Abhyankar { 812d950fb63SShri Abhyankar PetscErrorCode ierr; 813693ddf92SShri Abhyankar SNES_VI *vi = (SNES_VI*)snes->data; 814693ddf92SShri Abhyankar Vec Xl=vi->xl,Xu=vi->xu; 815693ddf92SShri Abhyankar const PetscScalar *x,*f,*xl,*xu; 816693ddf92SShri Abhyankar PetscInt *idx_act,i,nlocal,nloc_isact=0,ilow,ihigh,i1=0; 817d950fb63SShri Abhyankar 818d950fb63SShri Abhyankar PetscFunctionBegin; 819d950fb63SShri Abhyankar ierr = VecGetLocalSize(X,&nlocal);CHKERRQ(ierr); 820d950fb63SShri Abhyankar ierr = VecGetOwnershipRange(X,&ilow,&ihigh);CHKERRQ(ierr); 821fe835674SShri Abhyankar ierr = VecGetArrayRead(X,&x);CHKERRQ(ierr); 822fe835674SShri Abhyankar ierr = VecGetArrayRead(Xl,&xl);CHKERRQ(ierr); 823fe835674SShri Abhyankar ierr = VecGetArrayRead(Xu,&xu);CHKERRQ(ierr); 824fe835674SShri Abhyankar ierr = VecGetArrayRead(F,&f);CHKERRQ(ierr); 825693ddf92SShri Abhyankar /* Compute active set size */ 826d950fb63SShri Abhyankar for (i=0; i < nlocal;i++) { 82710f5ae6bSBarry Smith if (!((PetscRealPart(x[i]) > PetscRealPart(xl[i]) + 1.e-8 || (PetscRealPart(f[i]) < 0.0)) && ((PetscRealPart(x[i]) < PetscRealPart(xu[i]) - 1.e-8) || PetscRealPart(f[i]) > 0.0))) nloc_isact++; 828d950fb63SShri Abhyankar } 829693ddf92SShri Abhyankar 830d950fb63SShri Abhyankar ierr = PetscMalloc(nloc_isact*sizeof(PetscInt),&idx_act);CHKERRQ(ierr); 831d950fb63SShri Abhyankar 832693ddf92SShri Abhyankar /* Set active set indices */ 833d950fb63SShri Abhyankar for(i=0; i < nlocal; i++) { 83410f5ae6bSBarry Smith if (!((PetscRealPart(x[i]) > PetscRealPart(xl[i]) + 1.e-8 || (PetscRealPart(f[i]) < 0.0)) && ((PetscRealPart(x[i]) < PetscRealPart(xu[i]) - 1.e-8) || PetscRealPart(f[i]) > 0.0))) idx_act[i1++] = ilow+i; 835d950fb63SShri Abhyankar } 836d950fb63SShri Abhyankar 837693ddf92SShri Abhyankar /* Create active set IS */ 83862298a1eSBarry Smith ierr = ISCreateGeneral(((PetscObject)snes)->comm,nloc_isact,idx_act,PETSC_OWN_POINTER,ISact);CHKERRQ(ierr); 839d950fb63SShri Abhyankar 840fe835674SShri Abhyankar ierr = VecRestoreArrayRead(X,&x);CHKERRQ(ierr); 841fe835674SShri Abhyankar ierr = VecRestoreArrayRead(Xl,&xl);CHKERRQ(ierr); 842fe835674SShri Abhyankar ierr = VecRestoreArrayRead(Xu,&xu);CHKERRQ(ierr); 843fe835674SShri Abhyankar ierr = VecRestoreArrayRead(F,&f);CHKERRQ(ierr); 844d950fb63SShri Abhyankar PetscFunctionReturn(0); 845d950fb63SShri Abhyankar } 846d950fb63SShri Abhyankar 847693ddf92SShri Abhyankar #undef __FUNCT__ 848693ddf92SShri Abhyankar #define __FUNCT__ "SNESVICreateIndexSets_RS" 849693ddf92SShri Abhyankar PetscErrorCode SNESVICreateIndexSets_RS(SNES snes,Vec X,Vec F,IS* ISact,IS* ISinact) 850693ddf92SShri Abhyankar { 851693ddf92SShri Abhyankar PetscErrorCode ierr; 852693ddf92SShri Abhyankar 853693ddf92SShri Abhyankar PetscFunctionBegin; 854693ddf92SShri Abhyankar ierr = SNESVIGetActiveSetIS(snes,X,F,ISact);CHKERRQ(ierr); 855693ddf92SShri Abhyankar ierr = ISComplement(*ISact,X->map->rstart,X->map->rend,ISinact);CHKERRQ(ierr); 856693ddf92SShri Abhyankar PetscFunctionReturn(0); 857693ddf92SShri Abhyankar } 858693ddf92SShri Abhyankar 859dbd914b8SShri Abhyankar /* Create active and inactive set vectors. The local size of this vector is set and petsc computes the global size */ 860dbd914b8SShri Abhyankar #undef __FUNCT__ 861fe835674SShri Abhyankar #define __FUNCT__ "SNESVICreateSubVectors" 862fe835674SShri Abhyankar PetscErrorCode SNESVICreateSubVectors(SNES snes,PetscInt n,Vec* newv) 863dbd914b8SShri Abhyankar { 864dbd914b8SShri Abhyankar PetscErrorCode ierr; 865dbd914b8SShri Abhyankar Vec v; 866dbd914b8SShri Abhyankar 867dbd914b8SShri Abhyankar PetscFunctionBegin; 868dbd914b8SShri Abhyankar ierr = VecCreate(((PetscObject)snes)->comm,&v);CHKERRQ(ierr); 869dbd914b8SShri Abhyankar ierr = VecSetSizes(v,n,PETSC_DECIDE);CHKERRQ(ierr); 870dbd914b8SShri Abhyankar ierr = VecSetFromOptions(v);CHKERRQ(ierr); 871dbd914b8SShri Abhyankar *newv = v; 872dbd914b8SShri Abhyankar 873dbd914b8SShri Abhyankar PetscFunctionReturn(0); 874dbd914b8SShri Abhyankar } 875dbd914b8SShri Abhyankar 876732bb160SShri Abhyankar /* Resets the snes PC and KSP when the active set sizes change */ 877732bb160SShri Abhyankar #undef __FUNCT__ 878732bb160SShri Abhyankar #define __FUNCT__ "SNESVIResetPCandKSP" 879732bb160SShri Abhyankar PetscErrorCode SNESVIResetPCandKSP(SNES snes,Mat Amat,Mat Pmat) 880732bb160SShri Abhyankar { 881732bb160SShri Abhyankar PetscErrorCode ierr; 882*d0af7cd3SBarry Smith KSP snesksp; 883dbd914b8SShri Abhyankar 884732bb160SShri Abhyankar PetscFunctionBegin; 885732bb160SShri Abhyankar ierr = SNESGetKSP(snes,&snesksp);CHKERRQ(ierr); 886*d0af7cd3SBarry Smith ierr = KSPReset(snesksp);CHKERRQ(ierr); 887c2efdce3SBarry Smith 888c2efdce3SBarry Smith /* 889*d0af7cd3SBarry Smith KSP kspnew; 890*d0af7cd3SBarry Smith PC pcnew; 891*d0af7cd3SBarry Smith const MatSolverPackage stype; 892*d0af7cd3SBarry Smith 893c2efdce3SBarry Smith 894732bb160SShri Abhyankar ierr = KSPCreate(((PetscObject)snes)->comm,&kspnew);CHKERRQ(ierr); 895732bb160SShri Abhyankar kspnew->pc_side = snesksp->pc_side; 896732bb160SShri Abhyankar kspnew->rtol = snesksp->rtol; 897732bb160SShri Abhyankar kspnew->abstol = snesksp->abstol; 898732bb160SShri Abhyankar kspnew->max_it = snesksp->max_it; 899732bb160SShri Abhyankar ierr = KSPSetType(kspnew,((PetscObject)snesksp)->type_name);CHKERRQ(ierr); 900732bb160SShri Abhyankar ierr = KSPGetPC(kspnew,&pcnew);CHKERRQ(ierr); 901732bb160SShri Abhyankar ierr = PCSetType(kspnew->pc,((PetscObject)snesksp->pc)->type_name);CHKERRQ(ierr); 902732bb160SShri Abhyankar ierr = PCSetOperators(kspnew->pc,Amat,Pmat,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr); 903732bb160SShri Abhyankar ierr = PCFactorGetMatSolverPackage(snesksp->pc,&stype);CHKERRQ(ierr); 904732bb160SShri Abhyankar ierr = PCFactorSetMatSolverPackage(kspnew->pc,stype);CHKERRQ(ierr); 9056bf464f9SBarry Smith ierr = KSPDestroy(&snesksp);CHKERRQ(ierr); 906732bb160SShri Abhyankar snes->ksp = kspnew; 907732bb160SShri Abhyankar ierr = PetscLogObjectParent(snes,kspnew);CHKERRQ(ierr); 908*d0af7cd3SBarry Smith ierr = KSPSetFromOptions(kspnew);CHKERRQ(ierr);*/ 909732bb160SShri Abhyankar PetscFunctionReturn(0); 910732bb160SShri Abhyankar } 91169c03620SShri Abhyankar 91269c03620SShri Abhyankar 913fe835674SShri Abhyankar #undef __FUNCT__ 914fe835674SShri Abhyankar #define __FUNCT__ "SNESVIComputeInactiveSetFnorm" 91510f5ae6bSBarry Smith PetscErrorCode SNESVIComputeInactiveSetFnorm(SNES snes,Vec F,Vec X,PetscReal *fnorm) 916fe835674SShri Abhyankar { 917fe835674SShri Abhyankar PetscErrorCode ierr; 918fe835674SShri Abhyankar SNES_VI *vi = (SNES_VI*)snes->data; 919fe835674SShri Abhyankar const PetscScalar *x,*xl,*xu,*f; 920fe835674SShri Abhyankar PetscInt i,n; 921fe835674SShri Abhyankar PetscReal rnorm; 922fe835674SShri Abhyankar 923fe835674SShri Abhyankar PetscFunctionBegin; 924fe835674SShri Abhyankar ierr = VecGetLocalSize(X,&n);CHKERRQ(ierr); 925fe835674SShri Abhyankar ierr = VecGetArrayRead(vi->xl,&xl);CHKERRQ(ierr); 926fe835674SShri Abhyankar ierr = VecGetArrayRead(vi->xu,&xu);CHKERRQ(ierr); 927fe835674SShri Abhyankar ierr = VecGetArrayRead(X,&x);CHKERRQ(ierr); 928fe835674SShri Abhyankar ierr = VecGetArrayRead(F,&f);CHKERRQ(ierr); 929fe835674SShri Abhyankar rnorm = 0.0; 930fe835674SShri Abhyankar for (i=0; i<n; i++) { 93110f5ae6bSBarry Smith if (((PetscRealPart(x[i]) > PetscRealPart(xl[i]) + 1.e-8 || (PetscRealPart(f[i]) < 0.0)) && ((PetscRealPart(x[i]) < PetscRealPart(xu[i]) - 1.e-8) || PetscRealPart(f[i]) > 0.0))) rnorm += PetscRealPart(PetscConj(f[i])*f[i]); 932fe835674SShri Abhyankar } 933fe835674SShri Abhyankar ierr = VecRestoreArrayRead(F,&f);CHKERRQ(ierr); 934fe835674SShri Abhyankar ierr = VecRestoreArrayRead(vi->xl,&xl);CHKERRQ(ierr); 935fe835674SShri Abhyankar ierr = VecRestoreArrayRead(vi->xu,&xu);CHKERRQ(ierr); 936fe835674SShri Abhyankar ierr = VecRestoreArrayRead(X,&x);CHKERRQ(ierr); 937d9822059SBarry Smith ierr = MPI_Allreduce(&rnorm,fnorm,1,MPIU_REAL,MPIU_SUM,((PetscObject)snes)->comm);CHKERRQ(ierr); 938fe835674SShri Abhyankar *fnorm = sqrt(*fnorm); 939fe835674SShri Abhyankar PetscFunctionReturn(0); 940fe835674SShri Abhyankar } 941fe835674SShri Abhyankar 942fe835674SShri Abhyankar /* Variational Inequality solver using reduce space method. No semismooth algorithm is 943c2efdce3SBarry Smith implemented in this algorithm. It basically identifies the active constraints and does 944c2efdce3SBarry Smith a linear solve on the other variables (those not associated with the active constraints). */ 945d950fb63SShri Abhyankar #undef __FUNCT__ 946d950fb63SShri Abhyankar #define __FUNCT__ "SNESSolveVI_RS" 947d950fb63SShri Abhyankar PetscErrorCode SNESSolveVI_RS(SNES snes) 948d950fb63SShri Abhyankar { 949d950fb63SShri Abhyankar SNES_VI *vi = (SNES_VI*)snes->data; 950d950fb63SShri Abhyankar PetscErrorCode ierr; 951abcba341SShri Abhyankar PetscInt maxits,i,lits; 952d950fb63SShri Abhyankar PetscBool lssucceed; 953d950fb63SShri Abhyankar MatStructure flg = DIFFERENT_NONZERO_PATTERN; 954fe835674SShri Abhyankar PetscReal fnorm,gnorm,xnorm=0,ynorm; 955d950fb63SShri Abhyankar Vec Y,X,F,G,W; 956d950fb63SShri Abhyankar KSPConvergedReason kspreason; 957d950fb63SShri Abhyankar 958d950fb63SShri Abhyankar PetscFunctionBegin; 959d950fb63SShri Abhyankar snes->numFailures = 0; 960d950fb63SShri Abhyankar snes->numLinearSolveFailures = 0; 961d950fb63SShri Abhyankar snes->reason = SNES_CONVERGED_ITERATING; 962d950fb63SShri Abhyankar 963d950fb63SShri Abhyankar maxits = snes->max_its; /* maximum number of iterations */ 964d950fb63SShri Abhyankar X = snes->vec_sol; /* solution vector */ 965d950fb63SShri Abhyankar F = snes->vec_func; /* residual vector */ 966d950fb63SShri Abhyankar Y = snes->work[0]; /* work vectors */ 967d950fb63SShri Abhyankar G = snes->work[1]; 968d950fb63SShri Abhyankar W = snes->work[2]; 969d950fb63SShri Abhyankar 970d950fb63SShri Abhyankar ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 971d950fb63SShri Abhyankar snes->iter = 0; 972d950fb63SShri Abhyankar snes->norm = 0.0; 973d950fb63SShri Abhyankar ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 974d950fb63SShri Abhyankar 9757fe79bc4SShri Abhyankar ierr = SNESVIProjectOntoBounds(snes,X);CHKERRQ(ierr); 976fe835674SShri Abhyankar ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr); 977d950fb63SShri Abhyankar if (snes->domainerror) { 978d950fb63SShri Abhyankar snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN; 979d950fb63SShri Abhyankar PetscFunctionReturn(0); 980d950fb63SShri Abhyankar } 981fe835674SShri Abhyankar ierr = SNESVIComputeInactiveSetFnorm(snes,F,X,&fnorm);CHKERRQ(ierr); 982d950fb63SShri Abhyankar ierr = VecNormBegin(X,NORM_2,&xnorm);CHKERRQ(ierr); /* xnorm <- ||x|| */ 983d950fb63SShri Abhyankar ierr = VecNormEnd(X,NORM_2,&xnorm);CHKERRQ(ierr); 98462cbcd01SMatthew G Knepley if (PetscIsInfOrNanReal(fnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number"); 985d950fb63SShri Abhyankar 986d950fb63SShri Abhyankar ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 987fe835674SShri Abhyankar snes->norm = fnorm; 988d950fb63SShri Abhyankar ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 989fe835674SShri Abhyankar SNESLogConvHistory(snes,fnorm,0); 9907a03ce2fSLisandro Dalcin ierr = SNESMonitor(snes,0,fnorm);CHKERRQ(ierr); 991d950fb63SShri Abhyankar 992d950fb63SShri Abhyankar /* set parameter for default relative tolerance convergence test */ 993fe835674SShri Abhyankar snes->ttol = fnorm*snes->rtol; 994d950fb63SShri Abhyankar /* test convergence */ 995fe835674SShri Abhyankar ierr = (*snes->ops->converged)(snes,0,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); 996d950fb63SShri Abhyankar if (snes->reason) PetscFunctionReturn(0); 997d950fb63SShri Abhyankar 998d950fb63SShri Abhyankar for (i=0; i<maxits; i++) { 999d950fb63SShri Abhyankar 1000d950fb63SShri Abhyankar IS IS_act,IS_inact; /* _act -> active set _inact -> inactive set */ 1001d950fb63SShri Abhyankar VecScatter scat_act,scat_inact; 1002abcba341SShri Abhyankar PetscInt nis_act,nis_inact; 1003fe835674SShri Abhyankar Vec Y_act,Y_inact,F_inact; 1004d950fb63SShri Abhyankar Mat jac_inact_inact,prejac_inact_inact; 100562298a1eSBarry Smith IS keptrows; 1006abcba341SShri Abhyankar PetscBool isequal; 1007d950fb63SShri Abhyankar 1008d950fb63SShri Abhyankar /* Call general purpose update function */ 1009d950fb63SShri Abhyankar if (snes->ops->update) { 1010d950fb63SShri Abhyankar ierr = (*snes->ops->update)(snes, snes->iter);CHKERRQ(ierr); 1011d950fb63SShri Abhyankar } 1012d950fb63SShri Abhyankar ierr = SNESComputeJacobian(snes,X,&snes->jacobian,&snes->jacobian_pre,&flg);CHKERRQ(ierr); 101362298a1eSBarry Smith 1014d950fb63SShri Abhyankar /* Create active and inactive index sets */ 1015693ddf92SShri Abhyankar ierr = SNESVICreateIndexSets_RS(snes,X,F,&IS_act,&IS_inact);CHKERRQ(ierr); 1016d950fb63SShri Abhyankar 1017abcba341SShri Abhyankar /* Create inactive set submatrix */ 101862298a1eSBarry Smith ierr = MatGetSubMatrix(snes->jacobian,IS_inact,IS_inact,MAT_INITIAL_MATRIX,&jac_inact_inact);CHKERRQ(ierr); 1019b3a44c85SBarry Smith ierr = MatFindNonzeroRows(jac_inact_inact,&keptrows);CHKERRQ(ierr); 102062298a1eSBarry Smith if (keptrows) { 102162298a1eSBarry Smith PetscInt cnt,*nrows,k; 102262298a1eSBarry Smith const PetscInt *krows,*inact; 102327d4218bSShri Abhyankar PetscInt rstart=jac_inact_inact->rmap->rstart; 102462298a1eSBarry Smith 10256bf464f9SBarry Smith ierr = MatDestroy(&jac_inact_inact);CHKERRQ(ierr); 10266bf464f9SBarry Smith ierr = ISDestroy(&IS_act);CHKERRQ(ierr); 102762298a1eSBarry Smith 102862298a1eSBarry Smith ierr = ISGetLocalSize(keptrows,&cnt);CHKERRQ(ierr); 102962298a1eSBarry Smith ierr = ISGetIndices(keptrows,&krows);CHKERRQ(ierr); 103062298a1eSBarry Smith ierr = ISGetIndices(IS_inact,&inact);CHKERRQ(ierr); 103162298a1eSBarry Smith ierr = PetscMalloc(cnt*sizeof(PetscInt),&nrows);CHKERRQ(ierr); 103262298a1eSBarry Smith for (k=0; k<cnt; k++) { 103327d4218bSShri Abhyankar nrows[k] = inact[krows[k]-rstart]; 103462298a1eSBarry Smith } 103562298a1eSBarry Smith ierr = ISRestoreIndices(keptrows,&krows);CHKERRQ(ierr); 103662298a1eSBarry Smith ierr = ISRestoreIndices(IS_inact,&inact);CHKERRQ(ierr); 10376bf464f9SBarry Smith ierr = ISDestroy(&keptrows);CHKERRQ(ierr); 10386bf464f9SBarry Smith ierr = ISDestroy(&IS_inact);CHKERRQ(ierr); 103962298a1eSBarry Smith 104027d4218bSShri Abhyankar ierr = ISCreateGeneral(PETSC_COMM_WORLD,cnt,nrows,PETSC_OWN_POINTER,&IS_inact);CHKERRQ(ierr); 104127d4218bSShri Abhyankar ierr = ISComplement(IS_inact,F->map->rstart,F->map->rend,&IS_act);CHKERRQ(ierr); 104262298a1eSBarry Smith ierr = MatGetSubMatrix(snes->jacobian,IS_inact,IS_inact,MAT_INITIAL_MATRIX,&jac_inact_inact);CHKERRQ(ierr); 104362298a1eSBarry Smith } 104462298a1eSBarry Smith 1045d950fb63SShri Abhyankar /* Get sizes of active and inactive sets */ 1046d950fb63SShri Abhyankar ierr = ISGetLocalSize(IS_act,&nis_act);CHKERRQ(ierr); 1047d950fb63SShri Abhyankar ierr = ISGetLocalSize(IS_inact,&nis_inact);CHKERRQ(ierr); 1048d950fb63SShri Abhyankar 1049d950fb63SShri Abhyankar /* Create active and inactive set vectors */ 1050fe835674SShri Abhyankar ierr = SNESVICreateSubVectors(snes,nis_inact,&F_inact);CHKERRQ(ierr); 1051fe835674SShri Abhyankar ierr = SNESVICreateSubVectors(snes,nis_act,&Y_act);CHKERRQ(ierr); 1052fe835674SShri Abhyankar ierr = SNESVICreateSubVectors(snes,nis_inact,&Y_inact);CHKERRQ(ierr); 1053d950fb63SShri Abhyankar 1054d950fb63SShri Abhyankar /* Create scatter contexts */ 1055d950fb63SShri Abhyankar ierr = VecScatterCreate(Y,IS_act,Y_act,PETSC_NULL,&scat_act);CHKERRQ(ierr); 1056d950fb63SShri Abhyankar ierr = VecScatterCreate(Y,IS_inact,Y_inact,PETSC_NULL,&scat_inact);CHKERRQ(ierr); 1057d950fb63SShri Abhyankar 1058d950fb63SShri Abhyankar /* Do a vec scatter to active and inactive set vectors */ 1059fe835674SShri Abhyankar ierr = VecScatterBegin(scat_inact,F,F_inact,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1060fe835674SShri Abhyankar ierr = VecScatterEnd(scat_inact,F,F_inact,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1061d950fb63SShri Abhyankar 1062d950fb63SShri Abhyankar ierr = VecScatterBegin(scat_act,Y,Y_act,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1063d950fb63SShri Abhyankar ierr = VecScatterEnd(scat_act,Y,Y_act,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1064d950fb63SShri Abhyankar 1065d950fb63SShri Abhyankar ierr = VecScatterBegin(scat_inact,Y,Y_inact,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1066d950fb63SShri Abhyankar ierr = VecScatterEnd(scat_inact,Y,Y_inact,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1067d950fb63SShri Abhyankar 1068d950fb63SShri Abhyankar /* Active set direction = 0 */ 1069d950fb63SShri Abhyankar ierr = VecSet(Y_act,0);CHKERRQ(ierr); 1070d950fb63SShri Abhyankar if (snes->jacobian != snes->jacobian_pre) { 1071d950fb63SShri Abhyankar ierr = MatGetSubMatrix(snes->jacobian_pre,IS_inact,IS_inact,MAT_INITIAL_MATRIX,&prejac_inact_inact);CHKERRQ(ierr); 1072d950fb63SShri Abhyankar } else prejac_inact_inact = jac_inact_inact; 1073d950fb63SShri Abhyankar 1074abcba341SShri Abhyankar ierr = ISEqual(vi->IS_inact_prev,IS_inact,&isequal);CHKERRQ(ierr); 1075abcba341SShri Abhyankar if (!isequal) { 1076732bb160SShri Abhyankar ierr = SNESVIResetPCandKSP(snes,jac_inact_inact,prejac_inact_inact);CHKERRQ(ierr); 1077d950fb63SShri Abhyankar } 1078d950fb63SShri Abhyankar 107913e0d083SBarry Smith /* ierr = ISView(IS_inact,0);CHKERRQ(ierr); */ 108013e0d083SBarry Smith /* ierr = ISView(IS_act,0);CHKERRQ(ierr);*/ 108113e0d083SBarry Smith /* ierr = MatView(snes->jacobian_pre,0); */ 108213e0d083SBarry Smith 1083d950fb63SShri Abhyankar ierr = KSPSetOperators(snes->ksp,jac_inact_inact,prejac_inact_inact,flg);CHKERRQ(ierr); 108413e0d083SBarry Smith ierr = KSPSetUp(snes->ksp);CHKERRQ(ierr); 108513e0d083SBarry Smith { 108613e0d083SBarry Smith PC pc; 108713e0d083SBarry Smith PetscBool flg; 108813e0d083SBarry Smith ierr = KSPGetPC(snes->ksp,&pc);CHKERRQ(ierr); 108913e0d083SBarry Smith ierr = PetscTypeCompare((PetscObject)pc,PCFIELDSPLIT,&flg);CHKERRQ(ierr); 109013e0d083SBarry Smith if (flg) { 109113e0d083SBarry Smith KSP *subksps; 109213e0d083SBarry Smith ierr = PCFieldSplitGetSubKSP(pc,PETSC_NULL,&subksps);CHKERRQ(ierr); 109313e0d083SBarry Smith ierr = KSPGetPC(subksps[0],&pc);CHKERRQ(ierr); 109413e0d083SBarry Smith ierr = PetscFree(subksps);CHKERRQ(ierr); 109513e0d083SBarry Smith ierr = PetscTypeCompare((PetscObject)pc,PCBJACOBI,&flg);CHKERRQ(ierr); 109613e0d083SBarry Smith if (flg) { 109713e0d083SBarry Smith PetscInt n,N = 101*101,j,cnts[3] = {0,0,0}; 109813e0d083SBarry Smith const PetscInt *ii; 109913e0d083SBarry Smith 110013e0d083SBarry Smith ierr = ISGetSize(IS_inact,&n);CHKERRQ(ierr); 110113e0d083SBarry Smith ierr = ISGetIndices(IS_inact,&ii);CHKERRQ(ierr); 110213e0d083SBarry Smith for (j=0; j<n; j++) { 110313e0d083SBarry Smith if (ii[j] < N) cnts[0]++; 110413e0d083SBarry Smith else if (ii[j] < 2*N) cnts[1]++; 110513e0d083SBarry Smith else if (ii[j] < 3*N) cnts[2]++; 110613e0d083SBarry Smith } 110713e0d083SBarry Smith ierr = ISRestoreIndices(IS_inact,&ii);CHKERRQ(ierr); 110813e0d083SBarry Smith 110913e0d083SBarry Smith ierr = PCBJacobiSetTotalBlocks(pc,3,cnts);CHKERRQ(ierr); 111013e0d083SBarry Smith } 111113e0d083SBarry Smith } 111213e0d083SBarry Smith } 111313e0d083SBarry Smith 1114fe835674SShri Abhyankar ierr = SNES_KSPSolve(snes,snes->ksp,F_inact,Y_inact);CHKERRQ(ierr); 1115d950fb63SShri Abhyankar ierr = KSPGetConvergedReason(snes->ksp,&kspreason);CHKERRQ(ierr); 1116d950fb63SShri Abhyankar if (kspreason < 0) { 1117d950fb63SShri Abhyankar if (++snes->numLinearSolveFailures >= snes->maxLinearSolveFailures) { 1118d950fb63SShri Abhyankar ierr = PetscInfo2(snes,"iter=%D, number linear solve failures %D greater than current SNES allowed, stopping solve\n",snes->iter,snes->numLinearSolveFailures);CHKERRQ(ierr); 1119d950fb63SShri Abhyankar snes->reason = SNES_DIVERGED_LINEAR_SOLVE; 1120d950fb63SShri Abhyankar break; 1121d950fb63SShri Abhyankar } 1122d950fb63SShri Abhyankar } 1123d950fb63SShri Abhyankar 1124d950fb63SShri Abhyankar ierr = VecScatterBegin(scat_act,Y_act,Y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1125d950fb63SShri Abhyankar ierr = VecScatterEnd(scat_act,Y_act,Y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1126d950fb63SShri Abhyankar ierr = VecScatterBegin(scat_inact,Y_inact,Y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1127d950fb63SShri Abhyankar ierr = VecScatterEnd(scat_inact,Y_inact,Y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1128d950fb63SShri Abhyankar 11296bf464f9SBarry Smith ierr = VecDestroy(&F_inact);CHKERRQ(ierr); 11306bf464f9SBarry Smith ierr = VecDestroy(&Y_act);CHKERRQ(ierr); 11316bf464f9SBarry Smith ierr = VecDestroy(&Y_inact);CHKERRQ(ierr); 11326bf464f9SBarry Smith ierr = VecScatterDestroy(&scat_act);CHKERRQ(ierr); 11336bf464f9SBarry Smith ierr = VecScatterDestroy(&scat_inact);CHKERRQ(ierr); 11346bf464f9SBarry Smith ierr = ISDestroy(&IS_act);CHKERRQ(ierr); 1135abcba341SShri Abhyankar if (!isequal) { 11366bf464f9SBarry Smith ierr = ISDestroy(&vi->IS_inact_prev);CHKERRQ(ierr); 1137abcba341SShri Abhyankar ierr = ISDuplicate(IS_inact,&vi->IS_inact_prev);CHKERRQ(ierr); 1138abcba341SShri Abhyankar } 11396bf464f9SBarry Smith ierr = ISDestroy(&IS_inact);CHKERRQ(ierr); 11406bf464f9SBarry Smith ierr = MatDestroy(&jac_inact_inact);CHKERRQ(ierr); 1141d950fb63SShri Abhyankar if (snes->jacobian != snes->jacobian_pre) { 11426bf464f9SBarry Smith ierr = MatDestroy(&prejac_inact_inact);CHKERRQ(ierr); 1143d950fb63SShri Abhyankar } 1144d950fb63SShri Abhyankar ierr = KSPGetIterationNumber(snes->ksp,&lits);CHKERRQ(ierr); 1145d950fb63SShri Abhyankar snes->linear_its += lits; 1146d950fb63SShri Abhyankar ierr = PetscInfo2(snes,"iter=%D, linear solve iterations=%D\n",snes->iter,lits);CHKERRQ(ierr); 1147d950fb63SShri Abhyankar /* 1148d950fb63SShri Abhyankar if (vi->precheckstep) { 1149d950fb63SShri Abhyankar PetscBool changed_y = PETSC_FALSE; 1150d950fb63SShri Abhyankar ierr = (*vi->precheckstep)(snes,X,Y,vi->precheck,&changed_y);CHKERRQ(ierr); 1151d950fb63SShri Abhyankar } 1152d950fb63SShri Abhyankar 1153d950fb63SShri Abhyankar if (PetscLogPrintInfo){ 1154d950fb63SShri Abhyankar ierr = SNESVICheckResidual_Private(snes,snes->jacobian,F,Y,G,W);CHKERRQ(ierr); 1155d950fb63SShri Abhyankar } 1156d950fb63SShri Abhyankar */ 1157d950fb63SShri Abhyankar /* Compute a (scaled) negative update in the line search routine: 1158d950fb63SShri Abhyankar Y <- X - lambda*Y 1159d950fb63SShri Abhyankar and evaluate G = function(Y) (depends on the line search). 1160d950fb63SShri Abhyankar */ 1161d950fb63SShri Abhyankar ierr = VecCopy(Y,snes->vec_sol_update);CHKERRQ(ierr); 1162fe835674SShri Abhyankar ynorm = 1; gnorm = fnorm; 1163fe835674SShri Abhyankar ierr = (*vi->LineSearch)(snes,vi->lsP,X,F,G,Y,W,fnorm,xnorm,&ynorm,&gnorm,&lssucceed);CHKERRQ(ierr); 1164fe835674SShri Abhyankar ierr = PetscInfo4(snes,"fnorm=%18.16e, gnorm=%18.16e, ynorm=%18.16e, lssucceed=%d\n",fnorm,gnorm,ynorm,(int)lssucceed);CHKERRQ(ierr); 11652b4ed282SShri Abhyankar if (snes->reason == SNES_DIVERGED_FUNCTION_COUNT) break; 11662b4ed282SShri Abhyankar if (snes->domainerror) { 11672b4ed282SShri Abhyankar snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN; 11682b4ed282SShri Abhyankar PetscFunctionReturn(0); 11692b4ed282SShri Abhyankar } 11702b4ed282SShri Abhyankar if (!lssucceed) { 11712b4ed282SShri Abhyankar if (++snes->numFailures >= snes->maxFailures) { 11722b4ed282SShri Abhyankar PetscBool ismin; 11732b4ed282SShri Abhyankar snes->reason = SNES_DIVERGED_LINE_SEARCH; 11742b4ed282SShri Abhyankar ierr = SNESVICheckLocalMin_Private(snes,snes->jacobian,G,W,gnorm,&ismin);CHKERRQ(ierr); 11752b4ed282SShri Abhyankar if (ismin) snes->reason = SNES_DIVERGED_LOCAL_MIN; 11762b4ed282SShri Abhyankar break; 11772b4ed282SShri Abhyankar } 11782b4ed282SShri Abhyankar } 11792b4ed282SShri Abhyankar /* Update function and solution vectors */ 1180fe835674SShri Abhyankar fnorm = gnorm; 1181fe835674SShri Abhyankar ierr = VecCopy(G,F);CHKERRQ(ierr); 11822b4ed282SShri Abhyankar ierr = VecCopy(W,X);CHKERRQ(ierr); 11832b4ed282SShri Abhyankar /* Monitor convergence */ 11842b4ed282SShri Abhyankar ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 11852b4ed282SShri Abhyankar snes->iter = i+1; 1186fe835674SShri Abhyankar snes->norm = fnorm; 11872b4ed282SShri Abhyankar ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 11882b4ed282SShri Abhyankar SNESLogConvHistory(snes,snes->norm,lits); 11897a03ce2fSLisandro Dalcin ierr = SNESMonitor(snes,snes->iter,snes->norm);CHKERRQ(ierr); 11902b4ed282SShri Abhyankar /* Test for convergence, xnorm = || X || */ 11912b4ed282SShri Abhyankar if (snes->ops->converged != SNESSkipConverged) { ierr = VecNorm(X,NORM_2,&xnorm);CHKERRQ(ierr); } 1192fe835674SShri Abhyankar ierr = (*snes->ops->converged)(snes,snes->iter,xnorm,ynorm,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); 11932b4ed282SShri Abhyankar if (snes->reason) break; 11942b4ed282SShri Abhyankar } 11952b4ed282SShri Abhyankar if (i == maxits) { 11962b4ed282SShri Abhyankar ierr = PetscInfo1(snes,"Maximum number of iterations has been reached: %D\n",maxits);CHKERRQ(ierr); 11972b4ed282SShri Abhyankar if(!snes->reason) snes->reason = SNES_DIVERGED_MAX_IT; 11982b4ed282SShri Abhyankar } 11992b4ed282SShri Abhyankar PetscFunctionReturn(0); 12002b4ed282SShri Abhyankar } 12012b4ed282SShri Abhyankar 12022f63a38cSShri Abhyankar #undef __FUNCT__ 1203720c9a41SShri Abhyankar #define __FUNCT__ "SNESVISetRedundancyCheck" 1204cb5fe31bSShri Abhyankar PetscErrorCode SNESVISetRedundancyCheck(SNES snes,PetscErrorCode (*func)(SNES,IS,IS*,void*),void *ctx) 12052f63a38cSShri Abhyankar { 12062f63a38cSShri Abhyankar SNES_VI *vi = (SNES_VI*)snes->data; 12072f63a38cSShri Abhyankar 12082f63a38cSShri Abhyankar PetscFunctionBegin; 12092f63a38cSShri Abhyankar PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 12102f63a38cSShri Abhyankar vi->checkredundancy = func; 1211cb5fe31bSShri Abhyankar vi->ctxP = ctx; 12122f63a38cSShri Abhyankar PetscFunctionReturn(0); 12132f63a38cSShri Abhyankar } 12142f63a38cSShri Abhyankar 1215ff596062SShri Abhyankar #if defined(PETSC_HAVE_MATLAB_ENGINE) 1216ff596062SShri Abhyankar #include <engine.h> 1217ff596062SShri Abhyankar #include <mex.h> 1218cb5fe31bSShri Abhyankar typedef struct {char *funcname; mxArray *ctx;} SNESMatlabContext; 1219ff596062SShri Abhyankar 1220ff596062SShri Abhyankar #undef __FUNCT__ 1221ff596062SShri Abhyankar #define __FUNCT__ "SNESVIRedundancyCheck_Matlab" 1222ff596062SShri Abhyankar PetscErrorCode SNESVIRedundancyCheck_Matlab(SNES snes,IS is_act,IS* is_redact,void* ctx) 1223ff596062SShri Abhyankar { 1224ff596062SShri Abhyankar PetscErrorCode ierr; 1225cb5fe31bSShri Abhyankar SNESMatlabContext *sctx = (SNESMatlabContext*)ctx; 1226cb5fe31bSShri Abhyankar int nlhs = 1, nrhs = 5; 1227cb5fe31bSShri Abhyankar mxArray *plhs[1], *prhs[5]; 1228cb5fe31bSShri Abhyankar long long int l1 = 0, l2 = 0, ls = 0; 1229fcb1c9afSShri Abhyankar PetscInt *indices=PETSC_NULL; 1230ff596062SShri Abhyankar 1231ff596062SShri Abhyankar PetscFunctionBegin; 1232ff596062SShri Abhyankar PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 1233ff596062SShri Abhyankar PetscValidHeaderSpecific(is_act,IS_CLASSID,2); 1234ff596062SShri Abhyankar PetscValidPointer(is_redact,3); 1235ff596062SShri Abhyankar PetscCheckSameComm(snes,1,is_act,2); 1236ff596062SShri Abhyankar 123709db5ad8SShri Abhyankar /* Create IS for reduced active set of size 0, its size and indices will 123809db5ad8SShri Abhyankar bet set by the Matlab function */ 1239fcb1c9afSShri Abhyankar ierr = ISCreateGeneral(((PetscObject)snes)->comm,0,indices,PETSC_OWN_POINTER,is_redact);CHKERRQ(ierr); 1240cb5fe31bSShri Abhyankar /* call Matlab function in ctx */ 1241ff596062SShri Abhyankar ierr = PetscMemcpy(&ls,&snes,sizeof(snes));CHKERRQ(ierr); 1242ff596062SShri Abhyankar ierr = PetscMemcpy(&l1,&is_act,sizeof(is_act));CHKERRQ(ierr); 1243cb5fe31bSShri Abhyankar ierr = PetscMemcpy(&l2,is_redact,sizeof(is_act));CHKERRQ(ierr); 1244ff596062SShri Abhyankar prhs[0] = mxCreateDoubleScalar((double)ls); 1245ff596062SShri Abhyankar prhs[1] = mxCreateDoubleScalar((double)l1); 1246cb5fe31bSShri Abhyankar prhs[2] = mxCreateDoubleScalar((double)l2); 1247cb5fe31bSShri Abhyankar prhs[3] = mxCreateString(sctx->funcname); 1248cb5fe31bSShri Abhyankar prhs[4] = sctx->ctx; 1249ff596062SShri Abhyankar ierr = mexCallMATLAB(nlhs,plhs,nrhs,prhs,"PetscSNESVIRedundancyCheckInternal");CHKERRQ(ierr); 1250ff596062SShri Abhyankar ierr = mxGetScalar(plhs[0]);CHKERRQ(ierr); 1251ff596062SShri Abhyankar mxDestroyArray(prhs[0]); 1252ff596062SShri Abhyankar mxDestroyArray(prhs[1]); 1253ff596062SShri Abhyankar mxDestroyArray(prhs[2]); 1254ff596062SShri Abhyankar mxDestroyArray(prhs[3]); 1255ff596062SShri Abhyankar mxDestroyArray(plhs[0]); 1256ff596062SShri Abhyankar PetscFunctionReturn(0); 1257ff596062SShri Abhyankar } 1258ff596062SShri Abhyankar 1259ff596062SShri Abhyankar #undef __FUNCT__ 1260ff596062SShri Abhyankar #define __FUNCT__ "SNESVISetRedundancyCheckMatlab" 1261ff596062SShri Abhyankar PetscErrorCode SNESVISetRedundancyCheckMatlab(SNES snes,const char* func,mxArray* ctx) 1262ff596062SShri Abhyankar { 1263ff596062SShri Abhyankar PetscErrorCode ierr; 1264cb5fe31bSShri Abhyankar SNESMatlabContext *sctx; 1265ff596062SShri Abhyankar 1266ff596062SShri Abhyankar PetscFunctionBegin; 1267ff596062SShri Abhyankar /* currently sctx is memory bleed */ 1268cb5fe31bSShri Abhyankar ierr = PetscMalloc(sizeof(SNESMatlabContext),&sctx);CHKERRQ(ierr); 1269ff596062SShri Abhyankar ierr = PetscStrallocpy(func,&sctx->funcname);CHKERRQ(ierr); 1270ff596062SShri Abhyankar sctx->ctx = mxDuplicateArray(ctx); 1271cb5fe31bSShri Abhyankar ierr = SNESVISetRedundancyCheck(snes,SNESVIRedundancyCheck_Matlab,sctx);CHKERRQ(ierr); 1272ff596062SShri Abhyankar PetscFunctionReturn(0); 1273ff596062SShri Abhyankar } 1274ff596062SShri Abhyankar 1275ff596062SShri Abhyankar #endif 1276ff596062SShri Abhyankar 1277ff596062SShri Abhyankar 12782f63a38cSShri Abhyankar /* Variational Inequality solver using augmented space method. It does the opposite of the 12792f63a38cSShri Abhyankar reduced space method i.e. it identifies the active set variables and instead of discarding 1280720c9a41SShri Abhyankar them it augments the original system by introducing additional equality 128156a221efSShri Abhyankar constraint equations for active set variables. The user can optionally provide an IS for 128256a221efSShri Abhyankar a subset of 'redundant' active set variables which will treated as free variables. 12832f63a38cSShri Abhyankar Specific implementation for Allen-Cahn problem 12842f63a38cSShri Abhyankar */ 12852f63a38cSShri Abhyankar #undef __FUNCT__ 1286b350b9c9SBarry Smith #define __FUNCT__ "SNESSolveVI_RSAUG" 1287b350b9c9SBarry Smith PetscErrorCode SNESSolveVI_RSAUG(SNES snes) 12882f63a38cSShri Abhyankar { 12892f63a38cSShri Abhyankar SNES_VI *vi = (SNES_VI*)snes->data; 12902f63a38cSShri Abhyankar PetscErrorCode ierr; 12912f63a38cSShri Abhyankar PetscInt maxits,i,lits; 12922f63a38cSShri Abhyankar PetscBool lssucceed; 12932f63a38cSShri Abhyankar MatStructure flg = DIFFERENT_NONZERO_PATTERN; 12942f63a38cSShri Abhyankar PetscReal fnorm,gnorm,xnorm=0,ynorm; 12952f63a38cSShri Abhyankar Vec Y,X,F,G,W; 12962f63a38cSShri Abhyankar KSPConvergedReason kspreason; 12972f63a38cSShri Abhyankar 12982f63a38cSShri Abhyankar PetscFunctionBegin; 12992f63a38cSShri Abhyankar snes->numFailures = 0; 13002f63a38cSShri Abhyankar snes->numLinearSolveFailures = 0; 13012f63a38cSShri Abhyankar snes->reason = SNES_CONVERGED_ITERATING; 13022f63a38cSShri Abhyankar 13032f63a38cSShri Abhyankar maxits = snes->max_its; /* maximum number of iterations */ 13042f63a38cSShri Abhyankar X = snes->vec_sol; /* solution vector */ 13052f63a38cSShri Abhyankar F = snes->vec_func; /* residual vector */ 13062f63a38cSShri Abhyankar Y = snes->work[0]; /* work vectors */ 13072f63a38cSShri Abhyankar G = snes->work[1]; 13082f63a38cSShri Abhyankar W = snes->work[2]; 13092f63a38cSShri Abhyankar 13102f63a38cSShri Abhyankar ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 13112f63a38cSShri Abhyankar snes->iter = 0; 13122f63a38cSShri Abhyankar snes->norm = 0.0; 13132f63a38cSShri Abhyankar ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 13142f63a38cSShri Abhyankar 13152f63a38cSShri Abhyankar ierr = SNESVIProjectOntoBounds(snes,X);CHKERRQ(ierr); 13162f63a38cSShri Abhyankar ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr); 13172f63a38cSShri Abhyankar if (snes->domainerror) { 13182f63a38cSShri Abhyankar snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN; 13192f63a38cSShri Abhyankar PetscFunctionReturn(0); 13202f63a38cSShri Abhyankar } 13212f63a38cSShri Abhyankar ierr = SNESVIComputeInactiveSetFnorm(snes,F,X,&fnorm);CHKERRQ(ierr); 13222f63a38cSShri Abhyankar ierr = VecNormBegin(X,NORM_2,&xnorm);CHKERRQ(ierr); /* xnorm <- ||x|| */ 13232f63a38cSShri Abhyankar ierr = VecNormEnd(X,NORM_2,&xnorm);CHKERRQ(ierr); 132462cbcd01SMatthew G Knepley if (PetscIsInfOrNanReal(fnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number"); 13252f63a38cSShri Abhyankar 13262f63a38cSShri Abhyankar ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 13272f63a38cSShri Abhyankar snes->norm = fnorm; 13282f63a38cSShri Abhyankar ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 13292f63a38cSShri Abhyankar SNESLogConvHistory(snes,fnorm,0); 13307a03ce2fSLisandro Dalcin ierr = SNESMonitor(snes,0,fnorm);CHKERRQ(ierr); 13312f63a38cSShri Abhyankar 13322f63a38cSShri Abhyankar /* set parameter for default relative tolerance convergence test */ 13332f63a38cSShri Abhyankar snes->ttol = fnorm*snes->rtol; 13342f63a38cSShri Abhyankar /* test convergence */ 13352f63a38cSShri Abhyankar ierr = (*snes->ops->converged)(snes,0,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); 13362f63a38cSShri Abhyankar if (snes->reason) PetscFunctionReturn(0); 13372f63a38cSShri Abhyankar 13382f63a38cSShri Abhyankar for (i=0; i<maxits; i++) { 13392f63a38cSShri Abhyankar IS IS_act,IS_inact; /* _act -> active set _inact -> inactive set */ 1340cb5fe31bSShri Abhyankar IS IS_redact; /* redundant active set */ 134156a221efSShri Abhyankar Mat J_aug,Jpre_aug; 134256a221efSShri Abhyankar Vec F_aug,Y_aug; 134356a221efSShri Abhyankar PetscInt nis_redact,nis_act; 134456a221efSShri Abhyankar const PetscInt *idx_redact,*idx_act; 134556a221efSShri Abhyankar PetscInt k; 134663ee972cSSatish Balay PetscInt *idx_actkept=PETSC_NULL,nkept=0; /* list of kept active set */ 134756a221efSShri Abhyankar PetscScalar *f,*f2; 13482f63a38cSShri Abhyankar PetscBool isequal; 134956a221efSShri Abhyankar PetscInt i1=0,j1=0; 13502f63a38cSShri Abhyankar 13512f63a38cSShri Abhyankar /* Call general purpose update function */ 13522f63a38cSShri Abhyankar if (snes->ops->update) { 13532f63a38cSShri Abhyankar ierr = (*snes->ops->update)(snes, snes->iter);CHKERRQ(ierr); 13542f63a38cSShri Abhyankar } 13552f63a38cSShri Abhyankar ierr = SNESComputeJacobian(snes,X,&snes->jacobian,&snes->jacobian_pre,&flg);CHKERRQ(ierr); 13562f63a38cSShri Abhyankar 13572f63a38cSShri Abhyankar /* Create active and inactive index sets */ 13582f63a38cSShri Abhyankar ierr = SNESVICreateIndexSets_RS(snes,X,F,&IS_act,&IS_inact);CHKERRQ(ierr); 13592f63a38cSShri Abhyankar 136056a221efSShri Abhyankar /* Get local active set size */ 13612f63a38cSShri Abhyankar ierr = ISGetLocalSize(IS_act,&nis_act);CHKERRQ(ierr); 136256a221efSShri Abhyankar if (nis_act) { 1363e63076c7SBarry Smith ierr = ISGetIndices(IS_act,&idx_act);CHKERRQ(ierr); 1364e63076c7SBarry Smith IS_redact = PETSC_NULL; 136556a221efSShri Abhyankar if(vi->checkredundancy) { 1366cb5fe31bSShri Abhyankar (*vi->checkredundancy)(snes,IS_act,&IS_redact,vi->ctxP); 136756a221efSShri Abhyankar } 13682f63a38cSShri Abhyankar 136956a221efSShri Abhyankar if(!IS_redact) { 137056a221efSShri Abhyankar /* User called checkredundancy function but didn't create IS_redact because 137156a221efSShri Abhyankar there were no redundant active set variables */ 137256a221efSShri Abhyankar /* Copy over all active set indices to the list */ 137356a221efSShri Abhyankar ierr = PetscMalloc(nis_act*sizeof(PetscInt),&idx_actkept);CHKERRQ(ierr); 137456a221efSShri Abhyankar for(k=0;k < nis_act;k++) idx_actkept[k] = idx_act[k]; 137556a221efSShri Abhyankar nkept = nis_act; 137656a221efSShri Abhyankar } else { 137756a221efSShri Abhyankar ierr = ISGetLocalSize(IS_redact,&nis_redact);CHKERRQ(ierr); 137856a221efSShri Abhyankar ierr = PetscMalloc((nis_act-nis_redact)*sizeof(PetscInt),&idx_actkept);CHKERRQ(ierr); 13792f63a38cSShri Abhyankar 138056a221efSShri Abhyankar /* Create reduced active set list */ 138156a221efSShri Abhyankar ierr = ISGetIndices(IS_act,&idx_act);CHKERRQ(ierr); 138256a221efSShri Abhyankar ierr = ISGetIndices(IS_redact,&idx_redact);CHKERRQ(ierr); 1383cb5fe31bSShri Abhyankar j1 = 0;nkept = 0; 138456a221efSShri Abhyankar for(k=0;k<nis_act;k++) { 138556a221efSShri Abhyankar if(j1 < nis_redact && idx_act[k] == idx_redact[j1]) j1++; 138656a221efSShri Abhyankar else idx_actkept[nkept++] = idx_act[k]; 138756a221efSShri Abhyankar } 138856a221efSShri Abhyankar ierr = ISRestoreIndices(IS_act,&idx_act);CHKERRQ(ierr); 138956a221efSShri Abhyankar ierr = ISRestoreIndices(IS_redact,&idx_redact);CHKERRQ(ierr); 1390cb5fe31bSShri Abhyankar 1391cb5fe31bSShri Abhyankar ierr = ISDestroy(&IS_redact);CHKERRQ(ierr); 139256a221efSShri Abhyankar } 13932f63a38cSShri Abhyankar 139456a221efSShri Abhyankar /* Create augmented F and Y */ 139556a221efSShri Abhyankar ierr = VecCreate(((PetscObject)snes)->comm,&F_aug);CHKERRQ(ierr); 139656a221efSShri Abhyankar ierr = VecSetSizes(F_aug,F->map->n+nkept,PETSC_DECIDE);CHKERRQ(ierr); 139756a221efSShri Abhyankar ierr = VecSetFromOptions(F_aug);CHKERRQ(ierr); 139856a221efSShri Abhyankar ierr = VecDuplicate(F_aug,&Y_aug);CHKERRQ(ierr); 13992f63a38cSShri Abhyankar 140056a221efSShri Abhyankar /* Copy over F to F_aug in the first n locations */ 140156a221efSShri Abhyankar ierr = VecGetArray(F,&f);CHKERRQ(ierr); 140256a221efSShri Abhyankar ierr = VecGetArray(F_aug,&f2);CHKERRQ(ierr); 140356a221efSShri Abhyankar ierr = PetscMemcpy(f2,f,F->map->n*sizeof(PetscScalar));CHKERRQ(ierr); 140456a221efSShri Abhyankar ierr = VecRestoreArray(F,&f);CHKERRQ(ierr); 140556a221efSShri Abhyankar ierr = VecRestoreArray(F_aug,&f2);CHKERRQ(ierr); 14062f63a38cSShri Abhyankar 140756a221efSShri Abhyankar /* Create the augmented jacobian matrix */ 140856a221efSShri Abhyankar ierr = MatCreate(((PetscObject)snes)->comm,&J_aug);CHKERRQ(ierr); 140956a221efSShri Abhyankar ierr = MatSetSizes(J_aug,X->map->n+nkept,X->map->n+nkept,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr); 141056a221efSShri Abhyankar ierr = MatSetFromOptions(J_aug);CHKERRQ(ierr); 14112f63a38cSShri Abhyankar 141256a221efSShri Abhyankar 14139521db3cSSatish Balay { /* local vars */ 1414493a4f3dSShri Abhyankar /* Preallocate augmented matrix and set values in it...Doing only sequential case first*/ 141556a221efSShri Abhyankar PetscInt ncols; 141656a221efSShri Abhyankar const PetscInt *cols; 141756a221efSShri Abhyankar const PetscScalar *vals; 14182969f145SShri Abhyankar PetscScalar value[2]; 14192969f145SShri Abhyankar PetscInt row,col[2]; 1420493a4f3dSShri Abhyankar PetscInt *d_nnz; 14212969f145SShri Abhyankar value[0] = 1.0; value[1] = 0.0; 1422493a4f3dSShri Abhyankar ierr = PetscMalloc((X->map->n+nkept)*sizeof(PetscInt),&d_nnz);CHKERRQ(ierr); 1423493a4f3dSShri Abhyankar ierr = PetscMemzero(d_nnz,(X->map->n+nkept)*sizeof(PetscInt));CHKERRQ(ierr); 1424493a4f3dSShri Abhyankar for(row=0;row<snes->jacobian->rmap->n;row++) { 1425493a4f3dSShri Abhyankar ierr = MatGetRow(snes->jacobian,row,&ncols,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr); 1426493a4f3dSShri Abhyankar d_nnz[row] += ncols; 1427493a4f3dSShri Abhyankar ierr = MatRestoreRow(snes->jacobian,row,&ncols,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr); 1428493a4f3dSShri Abhyankar } 1429493a4f3dSShri Abhyankar 1430493a4f3dSShri Abhyankar for(k=0;k<nkept;k++) { 1431493a4f3dSShri Abhyankar d_nnz[idx_actkept[k]] += 1; 14322969f145SShri Abhyankar d_nnz[snes->jacobian->rmap->n+k] += 2; 1433493a4f3dSShri Abhyankar } 1434493a4f3dSShri Abhyankar ierr = MatSeqAIJSetPreallocation(J_aug,PETSC_NULL,d_nnz);CHKERRQ(ierr); 1435493a4f3dSShri Abhyankar 1436493a4f3dSShri Abhyankar ierr = PetscFree(d_nnz);CHKERRQ(ierr); 143756a221efSShri Abhyankar 143856a221efSShri Abhyankar /* Set the original jacobian matrix in J_aug */ 143956a221efSShri Abhyankar for(row=0;row<snes->jacobian->rmap->n;row++) { 144056a221efSShri Abhyankar ierr = MatGetRow(snes->jacobian,row,&ncols,&cols,&vals);CHKERRQ(ierr); 144156a221efSShri Abhyankar ierr = MatSetValues(J_aug,1,&row,ncols,cols,vals,INSERT_VALUES);CHKERRQ(ierr); 144256a221efSShri Abhyankar ierr = MatRestoreRow(snes->jacobian,row,&ncols,&cols,&vals);CHKERRQ(ierr); 144356a221efSShri Abhyankar } 144456a221efSShri Abhyankar /* Add the augmented part */ 144556a221efSShri Abhyankar for(k=0;k<nkept;k++) { 14462969f145SShri Abhyankar row = snes->jacobian->rmap->n+k; 14472969f145SShri Abhyankar col[0] = idx_actkept[k]; col[1] = snes->jacobian->rmap->n+k; 14482969f145SShri Abhyankar ierr = MatSetValues(J_aug,1,&row,1,col,value,INSERT_VALUES);CHKERRQ(ierr); 14492969f145SShri Abhyankar ierr = MatSetValues(J_aug,1,&col[0],1,&row,&value[0],INSERT_VALUES);CHKERRQ(ierr); 145056a221efSShri Abhyankar } 145156a221efSShri Abhyankar ierr = MatAssemblyBegin(J_aug,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 145256a221efSShri Abhyankar ierr = MatAssemblyEnd(J_aug,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 145356a221efSShri Abhyankar /* Only considering prejac = jac for now */ 145456a221efSShri Abhyankar Jpre_aug = J_aug; 14559521db3cSSatish Balay } /* local vars*/ 1456e63076c7SBarry Smith ierr = ISRestoreIndices(IS_act,&idx_act);CHKERRQ(ierr); 1457e63076c7SBarry Smith ierr = ISDestroy(&IS_act);CHKERRQ(ierr); 145856a221efSShri Abhyankar } else { 145956a221efSShri Abhyankar F_aug = F; J_aug = snes->jacobian; Y_aug = Y; Jpre_aug = snes->jacobian_pre; 146056a221efSShri Abhyankar } 14612f63a38cSShri Abhyankar 14622f63a38cSShri Abhyankar ierr = ISEqual(vi->IS_inact_prev,IS_inact,&isequal);CHKERRQ(ierr); 14632f63a38cSShri Abhyankar if (!isequal) { 146456a221efSShri Abhyankar ierr = SNESVIResetPCandKSP(snes,J_aug,Jpre_aug);CHKERRQ(ierr); 14652f63a38cSShri Abhyankar } 146656a221efSShri Abhyankar ierr = KSPSetOperators(snes->ksp,J_aug,Jpre_aug,flg);CHKERRQ(ierr); 14672f63a38cSShri Abhyankar ierr = KSPSetUp(snes->ksp);CHKERRQ(ierr); 146856a221efSShri Abhyankar /* { 14692f63a38cSShri Abhyankar PC pc; 14702f63a38cSShri Abhyankar PetscBool flg; 14712f63a38cSShri Abhyankar ierr = KSPGetPC(snes->ksp,&pc);CHKERRQ(ierr); 14722f63a38cSShri Abhyankar ierr = PetscTypeCompare((PetscObject)pc,PCFIELDSPLIT,&flg);CHKERRQ(ierr); 14732f63a38cSShri Abhyankar if (flg) { 14742f63a38cSShri Abhyankar KSP *subksps; 14752f63a38cSShri Abhyankar ierr = PCFieldSplitGetSubKSP(pc,PETSC_NULL,&subksps);CHKERRQ(ierr); 14762f63a38cSShri Abhyankar ierr = KSPGetPC(subksps[0],&pc);CHKERRQ(ierr); 14772f63a38cSShri Abhyankar ierr = PetscFree(subksps);CHKERRQ(ierr); 14782f63a38cSShri Abhyankar ierr = PetscTypeCompare((PetscObject)pc,PCBJACOBI,&flg);CHKERRQ(ierr); 14792f63a38cSShri Abhyankar if (flg) { 14802f63a38cSShri Abhyankar PetscInt n,N = 101*101,j,cnts[3] = {0,0,0}; 14812f63a38cSShri Abhyankar const PetscInt *ii; 14822f63a38cSShri Abhyankar 14832f63a38cSShri Abhyankar ierr = ISGetSize(IS_inact,&n);CHKERRQ(ierr); 14842f63a38cSShri Abhyankar ierr = ISGetIndices(IS_inact,&ii);CHKERRQ(ierr); 14852f63a38cSShri Abhyankar for (j=0; j<n; j++) { 14862f63a38cSShri Abhyankar if (ii[j] < N) cnts[0]++; 14872f63a38cSShri Abhyankar else if (ii[j] < 2*N) cnts[1]++; 14882f63a38cSShri Abhyankar else if (ii[j] < 3*N) cnts[2]++; 14892f63a38cSShri Abhyankar } 14902f63a38cSShri Abhyankar ierr = ISRestoreIndices(IS_inact,&ii);CHKERRQ(ierr); 14912f63a38cSShri Abhyankar 14922f63a38cSShri Abhyankar ierr = PCBJacobiSetTotalBlocks(pc,3,cnts);CHKERRQ(ierr); 14932f63a38cSShri Abhyankar } 14942f63a38cSShri Abhyankar } 14952f63a38cSShri Abhyankar } 149656a221efSShri Abhyankar */ 149756a221efSShri Abhyankar ierr = SNES_KSPSolve(snes,snes->ksp,F_aug,Y_aug);CHKERRQ(ierr); 14982f63a38cSShri Abhyankar ierr = KSPGetConvergedReason(snes->ksp,&kspreason);CHKERRQ(ierr); 14992f63a38cSShri Abhyankar if (kspreason < 0) { 15002f63a38cSShri Abhyankar if (++snes->numLinearSolveFailures >= snes->maxLinearSolveFailures) { 15012f63a38cSShri Abhyankar ierr = PetscInfo2(snes,"iter=%D, number linear solve failures %D greater than current SNES allowed, stopping solve\n",snes->iter,snes->numLinearSolveFailures);CHKERRQ(ierr); 15022f63a38cSShri Abhyankar snes->reason = SNES_DIVERGED_LINEAR_SOLVE; 15032f63a38cSShri Abhyankar break; 15042f63a38cSShri Abhyankar } 15052f63a38cSShri Abhyankar } 15062f63a38cSShri Abhyankar 150756a221efSShri Abhyankar if(nis_act) { 150856a221efSShri Abhyankar PetscScalar *y1,*y2; 150956a221efSShri Abhyankar ierr = VecGetArray(Y,&y1);CHKERRQ(ierr); 151056a221efSShri Abhyankar ierr = VecGetArray(Y_aug,&y2);CHKERRQ(ierr); 151156a221efSShri Abhyankar /* Copy over inactive Y_aug to Y */ 151256a221efSShri Abhyankar j1 = 0; 151356a221efSShri Abhyankar for(i1=Y->map->rstart;i1 < Y->map->rend;i1++) { 151456a221efSShri Abhyankar if(j1 < nkept && idx_actkept[j1] == i1) j1++; 151556a221efSShri Abhyankar else y1[i1-Y->map->rstart] = y2[i1-Y->map->rstart]; 151656a221efSShri Abhyankar } 151756a221efSShri Abhyankar ierr = VecRestoreArray(Y,&y1);CHKERRQ(ierr); 151856a221efSShri Abhyankar ierr = VecRestoreArray(Y_aug,&y2);CHKERRQ(ierr); 15192f63a38cSShri Abhyankar 15206bf464f9SBarry Smith ierr = VecDestroy(&F_aug);CHKERRQ(ierr); 15216bf464f9SBarry Smith ierr = VecDestroy(&Y_aug);CHKERRQ(ierr); 15226bf464f9SBarry Smith ierr = MatDestroy(&J_aug);CHKERRQ(ierr); 152356a221efSShri Abhyankar ierr = PetscFree(idx_actkept);CHKERRQ(ierr); 152456a221efSShri Abhyankar } 152556a221efSShri Abhyankar 15262f63a38cSShri Abhyankar if (!isequal) { 15276bf464f9SBarry Smith ierr = ISDestroy(&vi->IS_inact_prev);CHKERRQ(ierr); 15282f63a38cSShri Abhyankar ierr = ISDuplicate(IS_inact,&vi->IS_inact_prev);CHKERRQ(ierr); 15292f63a38cSShri Abhyankar } 15306bf464f9SBarry Smith ierr = ISDestroy(&IS_inact);CHKERRQ(ierr); 153156a221efSShri Abhyankar 15322f63a38cSShri Abhyankar ierr = KSPGetIterationNumber(snes->ksp,&lits);CHKERRQ(ierr); 15332f63a38cSShri Abhyankar snes->linear_its += lits; 15342f63a38cSShri Abhyankar ierr = PetscInfo2(snes,"iter=%D, linear solve iterations=%D\n",snes->iter,lits);CHKERRQ(ierr); 15352f63a38cSShri Abhyankar /* 15362f63a38cSShri Abhyankar if (vi->precheckstep) { 15372f63a38cSShri Abhyankar PetscBool changed_y = PETSC_FALSE; 15382f63a38cSShri Abhyankar ierr = (*vi->precheckstep)(snes,X,Y,vi->precheck,&changed_y);CHKERRQ(ierr); 15392f63a38cSShri Abhyankar } 15402f63a38cSShri Abhyankar 15412f63a38cSShri Abhyankar if (PetscLogPrintInfo){ 15422f63a38cSShri Abhyankar ierr = SNESVICheckResidual_Private(snes,snes->jacobian,F,Y,G,W);CHKERRQ(ierr); 15432f63a38cSShri Abhyankar } 15442f63a38cSShri Abhyankar */ 15452f63a38cSShri Abhyankar /* Compute a (scaled) negative update in the line search routine: 15462f63a38cSShri Abhyankar Y <- X - lambda*Y 15472f63a38cSShri Abhyankar and evaluate G = function(Y) (depends on the line search). 15482f63a38cSShri Abhyankar */ 15492f63a38cSShri Abhyankar ierr = VecCopy(Y,snes->vec_sol_update);CHKERRQ(ierr); 15502f63a38cSShri Abhyankar ynorm = 1; gnorm = fnorm; 15512f63a38cSShri Abhyankar ierr = (*vi->LineSearch)(snes,vi->lsP,X,F,G,Y,W,fnorm,xnorm,&ynorm,&gnorm,&lssucceed);CHKERRQ(ierr); 15522f63a38cSShri Abhyankar ierr = PetscInfo4(snes,"fnorm=%18.16e, gnorm=%18.16e, ynorm=%18.16e, lssucceed=%d\n",fnorm,gnorm,ynorm,(int)lssucceed);CHKERRQ(ierr); 15532f63a38cSShri Abhyankar if (snes->reason == SNES_DIVERGED_FUNCTION_COUNT) break; 15542f63a38cSShri Abhyankar if (snes->domainerror) { 15552f63a38cSShri Abhyankar snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN; 15562f63a38cSShri Abhyankar PetscFunctionReturn(0); 15572f63a38cSShri Abhyankar } 15582f63a38cSShri Abhyankar if (!lssucceed) { 15592f63a38cSShri Abhyankar if (++snes->numFailures >= snes->maxFailures) { 15602f63a38cSShri Abhyankar PetscBool ismin; 15612f63a38cSShri Abhyankar snes->reason = SNES_DIVERGED_LINE_SEARCH; 15622f63a38cSShri Abhyankar ierr = SNESVICheckLocalMin_Private(snes,snes->jacobian,G,W,gnorm,&ismin);CHKERRQ(ierr); 15632f63a38cSShri Abhyankar if (ismin) snes->reason = SNES_DIVERGED_LOCAL_MIN; 15642f63a38cSShri Abhyankar break; 15652f63a38cSShri Abhyankar } 15662f63a38cSShri Abhyankar } 15672f63a38cSShri Abhyankar /* Update function and solution vectors */ 15682f63a38cSShri Abhyankar fnorm = gnorm; 15692f63a38cSShri Abhyankar ierr = VecCopy(G,F);CHKERRQ(ierr); 15702f63a38cSShri Abhyankar ierr = VecCopy(W,X);CHKERRQ(ierr); 15712f63a38cSShri Abhyankar /* Monitor convergence */ 15722f63a38cSShri Abhyankar ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 15732f63a38cSShri Abhyankar snes->iter = i+1; 15742f63a38cSShri Abhyankar snes->norm = fnorm; 15752f63a38cSShri Abhyankar ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 15762f63a38cSShri Abhyankar SNESLogConvHistory(snes,snes->norm,lits); 15777a03ce2fSLisandro Dalcin ierr = SNESMonitor(snes,snes->iter,snes->norm);CHKERRQ(ierr); 15782f63a38cSShri Abhyankar /* Test for convergence, xnorm = || X || */ 15792f63a38cSShri Abhyankar if (snes->ops->converged != SNESSkipConverged) { ierr = VecNorm(X,NORM_2,&xnorm);CHKERRQ(ierr); } 15802f63a38cSShri Abhyankar ierr = (*snes->ops->converged)(snes,snes->iter,xnorm,ynorm,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); 15812f63a38cSShri Abhyankar if (snes->reason) break; 15822f63a38cSShri Abhyankar } 15832f63a38cSShri Abhyankar if (i == maxits) { 15842f63a38cSShri Abhyankar ierr = PetscInfo1(snes,"Maximum number of iterations has been reached: %D\n",maxits);CHKERRQ(ierr); 15852f63a38cSShri Abhyankar if(!snes->reason) snes->reason = SNES_DIVERGED_MAX_IT; 15862f63a38cSShri Abhyankar } 15872f63a38cSShri Abhyankar PetscFunctionReturn(0); 15882f63a38cSShri Abhyankar } 15892f63a38cSShri Abhyankar 15902b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */ 15912b4ed282SShri Abhyankar /* 15922b4ed282SShri Abhyankar SNESSetUp_VI - Sets up the internal data structures for the later use 15932b4ed282SShri Abhyankar of the SNESVI nonlinear solver. 15942b4ed282SShri Abhyankar 15952b4ed282SShri Abhyankar Input Parameter: 15962b4ed282SShri Abhyankar . snes - the SNES context 15972b4ed282SShri Abhyankar . x - the solution vector 15982b4ed282SShri Abhyankar 15992b4ed282SShri Abhyankar Application Interface Routine: SNESSetUp() 16002b4ed282SShri Abhyankar 16012b4ed282SShri Abhyankar Notes: 16022b4ed282SShri Abhyankar For basic use of the SNES solvers, the user need not explicitly call 16032b4ed282SShri Abhyankar SNESSetUp(), since these actions will automatically occur during 16042b4ed282SShri Abhyankar the call to SNESSolve(). 16052b4ed282SShri Abhyankar */ 16062b4ed282SShri Abhyankar #undef __FUNCT__ 16072b4ed282SShri Abhyankar #define __FUNCT__ "SNESSetUp_VI" 16082b4ed282SShri Abhyankar PetscErrorCode SNESSetUp_VI(SNES snes) 16092b4ed282SShri Abhyankar { 16102b4ed282SShri Abhyankar PetscErrorCode ierr; 16112b4ed282SShri Abhyankar SNES_VI *vi = (SNES_VI*) snes->data; 16122b4ed282SShri Abhyankar PetscInt i_start[3],i_end[3]; 16132b4ed282SShri Abhyankar 16142b4ed282SShri Abhyankar PetscFunctionBegin; 161558c9b817SLisandro Dalcin 161658c9b817SLisandro Dalcin ierr = SNESDefaultGetWork(snes,3);CHKERRQ(ierr); 16172b4ed282SShri Abhyankar 16182b4ed282SShri Abhyankar /* If the lower and upper bound on variables are not set, set it to 16192b4ed282SShri Abhyankar -Inf and Inf */ 16202b4ed282SShri Abhyankar if (!vi->xl && !vi->xu) { 16212b4ed282SShri Abhyankar vi->usersetxbounds = PETSC_FALSE; 16222b4ed282SShri Abhyankar ierr = VecDuplicate(snes->vec_sol, &vi->xl); CHKERRQ(ierr); 162301f0b76bSBarry Smith ierr = VecSet(vi->xl,SNES_VI_NINF);CHKERRQ(ierr); 16242b4ed282SShri Abhyankar ierr = VecDuplicate(snes->vec_sol, &vi->xu); CHKERRQ(ierr); 162501f0b76bSBarry Smith ierr = VecSet(vi->xu,SNES_VI_INF);CHKERRQ(ierr); 16262b4ed282SShri Abhyankar } else { 16272b4ed282SShri Abhyankar /* Check if lower bound, upper bound and solution vector distribution across the processors is identical */ 16282b4ed282SShri Abhyankar ierr = VecGetOwnershipRange(snes->vec_sol,i_start,i_end);CHKERRQ(ierr); 16292b4ed282SShri Abhyankar ierr = VecGetOwnershipRange(vi->xl,i_start+1,i_end+1);CHKERRQ(ierr); 16302b4ed282SShri Abhyankar ierr = VecGetOwnershipRange(vi->xu,i_start+2,i_end+2);CHKERRQ(ierr); 16312b4ed282SShri Abhyankar if ((i_start[0] != i_start[1]) || (i_start[0] != i_start[2]) || (i_end[0] != i_end[1]) || (i_end[0] != i_end[2])) 16322b4ed282SShri Abhyankar SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Distribution of lower bound, upper bound and the solution vector should be identical across all the processors."); 16332b4ed282SShri Abhyankar } 16342f63a38cSShri Abhyankar if (snes->ops->solve != SNESSolveVI_SS) { 1635abcba341SShri Abhyankar /* Set up previous active index set for the first snes solve 1636abcba341SShri Abhyankar vi->IS_inact_prev = 0,1,2,....N */ 1637abcba341SShri Abhyankar PetscInt *indices; 1638abcba341SShri Abhyankar PetscInt i,n,rstart,rend; 1639abcba341SShri Abhyankar 1640abcba341SShri Abhyankar ierr = VecGetOwnershipRange(snes->vec_sol,&rstart,&rend);CHKERRQ(ierr); 1641abcba341SShri Abhyankar ierr = VecGetLocalSize(snes->vec_sol,&n);CHKERRQ(ierr); 1642abcba341SShri Abhyankar ierr = PetscMalloc(n*sizeof(PetscInt),&indices);CHKERRQ(ierr); 1643abcba341SShri Abhyankar for(i=0;i < n; i++) indices[i] = rstart + i; 1644abcba341SShri Abhyankar ierr = ISCreateGeneral(((PetscObject)snes)->comm,n,indices,PETSC_OWN_POINTER,&vi->IS_inact_prev); 1645abcba341SShri Abhyankar } 16462b4ed282SShri Abhyankar 16472f63a38cSShri Abhyankar if (snes->ops->solve == SNESSolveVI_SS) { 1648fe835674SShri Abhyankar ierr = VecDuplicate(snes->vec_sol, &vi->dpsi);CHKERRQ(ierr); 1649fe835674SShri Abhyankar ierr = VecDuplicate(snes->vec_sol, &vi->phi); CHKERRQ(ierr); 1650fe835674SShri Abhyankar ierr = VecDuplicate(snes->vec_sol, &vi->Da); CHKERRQ(ierr); 1651fe835674SShri Abhyankar ierr = VecDuplicate(snes->vec_sol, &vi->Db); CHKERRQ(ierr); 1652fe835674SShri Abhyankar ierr = VecDuplicate(snes->vec_sol, &vi->z);CHKERRQ(ierr); 1653fe835674SShri Abhyankar ierr = VecDuplicate(snes->vec_sol, &vi->t); CHKERRQ(ierr); 1654fe835674SShri Abhyankar } 16552b4ed282SShri Abhyankar PetscFunctionReturn(0); 16562b4ed282SShri Abhyankar } 16572b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */ 16582b4ed282SShri Abhyankar /* 16592b4ed282SShri Abhyankar SNESDestroy_VI - Destroys the private SNES_VI context that was created 16602b4ed282SShri Abhyankar with SNESCreate_VI(). 16612b4ed282SShri Abhyankar 16622b4ed282SShri Abhyankar Input Parameter: 16632b4ed282SShri Abhyankar . snes - the SNES context 16642b4ed282SShri Abhyankar 16652b4ed282SShri Abhyankar Application Interface Routine: SNESDestroy() 16662b4ed282SShri Abhyankar */ 16672b4ed282SShri Abhyankar #undef __FUNCT__ 16682b4ed282SShri Abhyankar #define __FUNCT__ "SNESDestroy_VI" 16692b4ed282SShri Abhyankar PetscErrorCode SNESDestroy_VI(SNES snes) 16702b4ed282SShri Abhyankar { 16712b4ed282SShri Abhyankar SNES_VI *vi = (SNES_VI*) snes->data; 16722b4ed282SShri Abhyankar PetscErrorCode ierr; 16732b4ed282SShri Abhyankar 16742b4ed282SShri Abhyankar PetscFunctionBegin; 16752f63a38cSShri Abhyankar if (snes->ops->solve != SNESSolveVI_SS) { 16766bf464f9SBarry Smith ierr = ISDestroy(&vi->IS_inact_prev); 1677abcba341SShri Abhyankar } 16782b4ed282SShri Abhyankar 16792f63a38cSShri Abhyankar if (snes->ops->solve == SNESSolveVI_SS) { 16802b4ed282SShri Abhyankar /* clear vectors */ 16816bf464f9SBarry Smith ierr = VecDestroy(&vi->dpsi);CHKERRQ(ierr); 16826bf464f9SBarry Smith ierr = VecDestroy(&vi->phi); CHKERRQ(ierr); 16836bf464f9SBarry Smith ierr = VecDestroy(&vi->Da); CHKERRQ(ierr); 16846bf464f9SBarry Smith ierr = VecDestroy(&vi->Db); CHKERRQ(ierr); 16856bf464f9SBarry Smith ierr = VecDestroy(&vi->z); CHKERRQ(ierr); 16866bf464f9SBarry Smith ierr = VecDestroy(&vi->t); CHKERRQ(ierr); 16877fe79bc4SShri Abhyankar } 16887fe79bc4SShri Abhyankar 16892b4ed282SShri Abhyankar if (!vi->usersetxbounds) { 16906bf464f9SBarry Smith ierr = VecDestroy(&vi->xl); CHKERRQ(ierr); 16916bf464f9SBarry Smith ierr = VecDestroy(&vi->xu); CHKERRQ(ierr); 16922b4ed282SShri Abhyankar } 16937fe79bc4SShri Abhyankar 16946bf464f9SBarry Smith ierr = PetscViewerASCIIMonitorDestroy(&vi->lsmonitor);CHKERRQ(ierr); 16952b4ed282SShri Abhyankar ierr = PetscFree(snes->data);CHKERRQ(ierr); 16962b4ed282SShri Abhyankar 16972b4ed282SShri Abhyankar /* clear composed functions */ 16982b4ed282SShri Abhyankar ierr = PetscObjectComposeFunctionDynamic((PetscObject)snes,"SNESLineSearchSet_C","",PETSC_NULL);CHKERRQ(ierr); 1699c92abb8aSShri Abhyankar ierr = PetscObjectComposeFunctionDynamic((PetscObject)snes,"SNESLineSearchSetMonitor_C","",PETSC_NULL);CHKERRQ(ierr); 17002b4ed282SShri Abhyankar PetscFunctionReturn(0); 17012b4ed282SShri Abhyankar } 17027fe79bc4SShri Abhyankar 17032b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */ 17042b4ed282SShri Abhyankar #undef __FUNCT__ 17052b4ed282SShri Abhyankar #define __FUNCT__ "SNESLineSearchNo_VI" 17062b4ed282SShri Abhyankar 17072b4ed282SShri Abhyankar /* 17087fe79bc4SShri Abhyankar This routine does not actually do a line search but it takes a full newton 17097fe79bc4SShri Abhyankar step while ensuring that the new iterates remain within the constraints. 17102b4ed282SShri Abhyankar 17112b4ed282SShri Abhyankar */ 1712ace3abfcSBarry Smith PetscErrorCode SNESLineSearchNo_VI(SNES snes,void *lsctx,Vec x,Vec f,Vec g,Vec y,Vec w,PetscReal fnorm,PetscReal xnorm,PetscReal *ynorm,PetscReal *gnorm,PetscBool *flag) 17132b4ed282SShri Abhyankar { 17142b4ed282SShri Abhyankar PetscErrorCode ierr; 17152b4ed282SShri Abhyankar SNES_VI *vi = (SNES_VI*)snes->data; 1716ace3abfcSBarry Smith PetscBool changed_w = PETSC_FALSE,changed_y = PETSC_FALSE; 17172b4ed282SShri Abhyankar 17182b4ed282SShri Abhyankar PetscFunctionBegin; 17192b4ed282SShri Abhyankar *flag = PETSC_TRUE; 17202b4ed282SShri Abhyankar ierr = PetscLogEventBegin(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); 17212b4ed282SShri Abhyankar ierr = VecNorm(y,NORM_2,ynorm);CHKERRQ(ierr); /* ynorm = || y || */ 17222b4ed282SShri Abhyankar ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr); /* w <- x - y */ 1723c1a5e521SShri Abhyankar ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr); 1724c1a5e521SShri Abhyankar if (vi->postcheckstep) { 1725c1a5e521SShri Abhyankar ierr = (*vi->postcheckstep)(snes,x,y,w,vi->postcheck,&changed_y,&changed_w);CHKERRQ(ierr); 1726c1a5e521SShri Abhyankar } 1727c1a5e521SShri Abhyankar if (changed_y) { 1728c1a5e521SShri Abhyankar ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr); /* w <- x - y */ 17297fe79bc4SShri Abhyankar ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr); 1730c1a5e521SShri Abhyankar } 1731c1a5e521SShri Abhyankar ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr); 1732c1a5e521SShri Abhyankar ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr); 1733c1a5e521SShri Abhyankar if (!snes->domainerror) { 17342f63a38cSShri Abhyankar if (snes->ops->solve != SNESSolveVI_SS) { 17357fe79bc4SShri Abhyankar ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr); 17367fe79bc4SShri Abhyankar } else { 1737c1a5e521SShri Abhyankar ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr); /* gnorm = || g || */ 17387fe79bc4SShri Abhyankar } 173962cbcd01SMatthew G Knepley if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number"); 1740c1a5e521SShri Abhyankar } 1741c1a5e521SShri Abhyankar if (vi->lsmonitor) { 1742c1a5e521SShri Abhyankar ierr = PetscViewerASCIIMonitorPrintf(vi->lsmonitor," Line search: Using full step: fnorm %G gnorm %G\n",fnorm,*gnorm);CHKERRQ(ierr); 1743c1a5e521SShri Abhyankar } 1744c1a5e521SShri Abhyankar ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); 1745c1a5e521SShri Abhyankar PetscFunctionReturn(0); 1746c1a5e521SShri Abhyankar } 1747c1a5e521SShri Abhyankar 1748c1a5e521SShri Abhyankar /* -------------------------------------------------------------------------- */ 1749c1a5e521SShri Abhyankar #undef __FUNCT__ 17502b4ed282SShri Abhyankar #define __FUNCT__ "SNESLineSearchNoNorms_VI" 17512b4ed282SShri Abhyankar 17522b4ed282SShri Abhyankar /* 17532b4ed282SShri Abhyankar This routine is a copy of SNESLineSearchNoNorms in snes/impls/ls/ls.c 17542b4ed282SShri Abhyankar */ 1755ace3abfcSBarry Smith PetscErrorCode SNESLineSearchNoNorms_VI(SNES snes,void *lsctx,Vec x,Vec f,Vec g,Vec y,Vec w,PetscReal fnorm,PetscReal xnorm,PetscReal *ynorm,PetscReal *gnorm,PetscBool *flag) 17562b4ed282SShri Abhyankar { 17572b4ed282SShri Abhyankar PetscErrorCode ierr; 17582b4ed282SShri Abhyankar SNES_VI *vi = (SNES_VI*)snes->data; 1759ace3abfcSBarry Smith PetscBool changed_w = PETSC_FALSE,changed_y = PETSC_FALSE; 17602b4ed282SShri Abhyankar 17612b4ed282SShri Abhyankar PetscFunctionBegin; 17622b4ed282SShri Abhyankar *flag = PETSC_TRUE; 17632b4ed282SShri Abhyankar ierr = PetscLogEventBegin(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); 17642b4ed282SShri Abhyankar ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr); /* w <- x - y */ 17657fe79bc4SShri Abhyankar ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr); 17662b4ed282SShri Abhyankar if (vi->postcheckstep) { 17672b4ed282SShri Abhyankar ierr = (*vi->postcheckstep)(snes,x,y,w,vi->postcheck,&changed_y,&changed_w);CHKERRQ(ierr); 17682b4ed282SShri Abhyankar } 17692b4ed282SShri Abhyankar if (changed_y) { 17702b4ed282SShri Abhyankar ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr); /* w <- x - y */ 17717fe79bc4SShri Abhyankar ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr); 17722b4ed282SShri Abhyankar } 17732b4ed282SShri Abhyankar 17742b4ed282SShri Abhyankar /* don't evaluate function the last time through */ 17752b4ed282SShri Abhyankar if (snes->iter < snes->max_its-1) { 17762b4ed282SShri Abhyankar ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr); 17772b4ed282SShri Abhyankar } 17782b4ed282SShri Abhyankar ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); 17792b4ed282SShri Abhyankar PetscFunctionReturn(0); 17802b4ed282SShri Abhyankar } 17817fe79bc4SShri Abhyankar 17822b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */ 17832b4ed282SShri Abhyankar #undef __FUNCT__ 17842b4ed282SShri Abhyankar #define __FUNCT__ "SNESLineSearchCubic_VI" 17852b4ed282SShri Abhyankar /* 17867fe79bc4SShri Abhyankar This routine implements a cubic line search while doing a projection on the variable bounds 17872b4ed282SShri Abhyankar */ 1788ace3abfcSBarry Smith PetscErrorCode SNESLineSearchCubic_VI(SNES snes,void *lsctx,Vec x,Vec f,Vec g,Vec y,Vec w,PetscReal fnorm,PetscReal xnorm,PetscReal *ynorm,PetscReal *gnorm,PetscBool *flag) 17892b4ed282SShri Abhyankar { 1790fe835674SShri Abhyankar PetscReal initslope,lambdaprev,gnormprev,a,b,d,t1,t2,rellength; 1791fe835674SShri Abhyankar PetscReal minlambda,lambda,lambdatemp; 1792fe835674SShri Abhyankar #if defined(PETSC_USE_COMPLEX) 1793fe835674SShri Abhyankar PetscScalar cinitslope; 1794fe835674SShri Abhyankar #endif 1795fe835674SShri Abhyankar PetscErrorCode ierr; 1796fe835674SShri Abhyankar PetscInt count; 1797fe835674SShri Abhyankar SNES_VI *vi = (SNES_VI*)snes->data; 1798fe835674SShri Abhyankar PetscBool changed_w = PETSC_FALSE,changed_y = PETSC_FALSE; 1799fe835674SShri Abhyankar MPI_Comm comm; 1800fe835674SShri Abhyankar 1801fe835674SShri Abhyankar PetscFunctionBegin; 1802fe835674SShri Abhyankar ierr = PetscObjectGetComm((PetscObject)snes,&comm);CHKERRQ(ierr); 1803fe835674SShri Abhyankar ierr = PetscLogEventBegin(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); 1804fe835674SShri Abhyankar *flag = PETSC_TRUE; 1805fe835674SShri Abhyankar 1806fe835674SShri Abhyankar ierr = VecNorm(y,NORM_2,ynorm);CHKERRQ(ierr); 1807fe835674SShri Abhyankar if (*ynorm == 0.0) { 1808fe835674SShri Abhyankar if (vi->lsmonitor) { 1809fe835674SShri Abhyankar ierr = PetscViewerASCIIMonitorPrintf(vi->lsmonitor," Line search: Initial direction and size is 0\n");CHKERRQ(ierr); 1810fe835674SShri Abhyankar } 1811fe835674SShri Abhyankar *gnorm = fnorm; 1812fe835674SShri Abhyankar ierr = VecCopy(x,w);CHKERRQ(ierr); 1813fe835674SShri Abhyankar ierr = VecCopy(f,g);CHKERRQ(ierr); 1814fe835674SShri Abhyankar *flag = PETSC_FALSE; 1815fe835674SShri Abhyankar goto theend1; 1816fe835674SShri Abhyankar } 1817fe835674SShri Abhyankar if (*ynorm > vi->maxstep) { /* Step too big, so scale back */ 1818fe835674SShri Abhyankar if (vi->lsmonitor) { 1819fe835674SShri Abhyankar ierr = PetscViewerASCIIMonitorPrintf(vi->lsmonitor," Line search: Scaling step by %G old ynorm %G\n",vi->maxstep/(*ynorm),*ynorm);CHKERRQ(ierr); 1820fe835674SShri Abhyankar } 1821fe835674SShri Abhyankar ierr = VecScale(y,vi->maxstep/(*ynorm));CHKERRQ(ierr); 1822fe835674SShri Abhyankar *ynorm = vi->maxstep; 1823fe835674SShri Abhyankar } 1824fe835674SShri Abhyankar ierr = VecMaxPointwiseDivide(y,x,&rellength);CHKERRQ(ierr); 1825fe835674SShri Abhyankar minlambda = vi->minlambda/rellength; 1826fe835674SShri Abhyankar ierr = MatMult(snes->jacobian,y,w);CHKERRQ(ierr); 1827fe835674SShri Abhyankar #if defined(PETSC_USE_COMPLEX) 1828fe835674SShri Abhyankar ierr = VecDot(f,w,&cinitslope);CHKERRQ(ierr); 1829fe835674SShri Abhyankar initslope = PetscRealPart(cinitslope); 1830fe835674SShri Abhyankar #else 1831fe835674SShri Abhyankar ierr = VecDot(f,w,&initslope);CHKERRQ(ierr); 1832fe835674SShri Abhyankar #endif 1833fe835674SShri Abhyankar if (initslope > 0.0) initslope = -initslope; 1834fe835674SShri Abhyankar if (initslope == 0.0) initslope = -1.0; 1835fe835674SShri Abhyankar 1836fe835674SShri Abhyankar ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr); 1837fe835674SShri Abhyankar ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr); 1838fe835674SShri Abhyankar if (snes->nfuncs >= snes->max_funcs) { 1839fe835674SShri Abhyankar ierr = PetscInfo(snes,"Exceeded maximum function evaluations, while checking full step length!\n");CHKERRQ(ierr); 1840fe835674SShri Abhyankar *flag = PETSC_FALSE; 1841fe835674SShri Abhyankar snes->reason = SNES_DIVERGED_FUNCTION_COUNT; 1842fe835674SShri Abhyankar goto theend1; 1843fe835674SShri Abhyankar } 1844fe835674SShri Abhyankar ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr); 18452f63a38cSShri Abhyankar if (snes->ops->solve != SNESSolveVI_SS) { 1846fe835674SShri Abhyankar ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr); 18477fe79bc4SShri Abhyankar } else { 18487fe79bc4SShri Abhyankar ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr); 18497fe79bc4SShri Abhyankar } 1850fe835674SShri Abhyankar if (snes->domainerror) { 1851fe835674SShri Abhyankar ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); 1852fe835674SShri Abhyankar PetscFunctionReturn(0); 1853fe835674SShri Abhyankar } 185462cbcd01SMatthew G Knepley if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number"); 1855fe835674SShri Abhyankar ierr = PetscInfo2(snes,"Initial fnorm %G gnorm %G\n",fnorm,*gnorm);CHKERRQ(ierr); 1856fe835674SShri Abhyankar if (.5*(*gnorm)*(*gnorm) <= .5*fnorm*fnorm + vi->alpha*initslope) { /* Sufficient reduction */ 1857fe835674SShri Abhyankar if (vi->lsmonitor) { 1858fe835674SShri Abhyankar ierr = PetscViewerASCIIMonitorPrintf(vi->lsmonitor," Line search: Using full step: fnorm %G gnorm %G\n",fnorm,*gnorm);CHKERRQ(ierr); 1859fe835674SShri Abhyankar } 1860fe835674SShri Abhyankar goto theend1; 1861fe835674SShri Abhyankar } 1862fe835674SShri Abhyankar 1863fe835674SShri Abhyankar /* Fit points with quadratic */ 1864fe835674SShri Abhyankar lambda = 1.0; 1865fe835674SShri Abhyankar lambdatemp = -initslope/((*gnorm)*(*gnorm) - fnorm*fnorm - 2.0*initslope); 1866fe835674SShri Abhyankar lambdaprev = lambda; 1867fe835674SShri Abhyankar gnormprev = *gnorm; 1868fe835674SShri Abhyankar if (lambdatemp > .5*lambda) lambdatemp = .5*lambda; 1869fe835674SShri Abhyankar if (lambdatemp <= .1*lambda) lambda = .1*lambda; 1870fe835674SShri Abhyankar else lambda = lambdatemp; 1871fe835674SShri Abhyankar 1872fe835674SShri Abhyankar ierr = VecWAXPY(w,-lambda,y,x);CHKERRQ(ierr); 1873fe835674SShri Abhyankar ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr); 1874fe835674SShri Abhyankar if (snes->nfuncs >= snes->max_funcs) { 1875fe835674SShri Abhyankar ierr = PetscInfo1(snes,"Exceeded maximum function evaluations, while attempting quadratic backtracking! %D \n",snes->nfuncs);CHKERRQ(ierr); 1876fe835674SShri Abhyankar *flag = PETSC_FALSE; 1877fe835674SShri Abhyankar snes->reason = SNES_DIVERGED_FUNCTION_COUNT; 1878fe835674SShri Abhyankar goto theend1; 1879fe835674SShri Abhyankar } 1880fe835674SShri Abhyankar ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr); 18812f63a38cSShri Abhyankar if (snes->ops->solve != SNESSolveVI_SS) { 1882fe835674SShri Abhyankar ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr); 18837fe79bc4SShri Abhyankar } else { 18847fe79bc4SShri Abhyankar ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr); 18857fe79bc4SShri Abhyankar } 1886fe835674SShri Abhyankar if (snes->domainerror) { 1887fe835674SShri Abhyankar ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); 1888fe835674SShri Abhyankar PetscFunctionReturn(0); 1889fe835674SShri Abhyankar } 189062cbcd01SMatthew G Knepley if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number"); 1891fe835674SShri Abhyankar if (vi->lsmonitor) { 1892fe835674SShri Abhyankar ierr = PetscViewerASCIIMonitorPrintf(vi->lsmonitor," Line search: gnorm after quadratic fit %G\n",*gnorm);CHKERRQ(ierr); 1893fe835674SShri Abhyankar } 1894fe835674SShri Abhyankar if (.5*(*gnorm)*(*gnorm) < .5*fnorm*fnorm + lambda*vi->alpha*initslope) { /* sufficient reduction */ 1895fe835674SShri Abhyankar if (vi->lsmonitor) { 1896fe835674SShri Abhyankar ierr = PetscViewerASCIIMonitorPrintf(vi->lsmonitor," Line search: Quadratically determined step, lambda=%18.16e\n",lambda);CHKERRQ(ierr); 1897fe835674SShri Abhyankar } 1898fe835674SShri Abhyankar goto theend1; 1899fe835674SShri Abhyankar } 1900fe835674SShri Abhyankar 1901fe835674SShri Abhyankar /* Fit points with cubic */ 1902fe835674SShri Abhyankar count = 1; 1903fe835674SShri Abhyankar while (PETSC_TRUE) { 1904fe835674SShri Abhyankar if (lambda <= minlambda) { 1905fe835674SShri Abhyankar if (vi->lsmonitor) { 1906fe835674SShri Abhyankar ierr = PetscViewerASCIIMonitorPrintf(vi->lsmonitor," Line search: unable to find good step length! After %D tries \n",count);CHKERRQ(ierr); 1907fe835674SShri Abhyankar ierr = PetscViewerASCIIMonitorPrintf(vi->lsmonitor," Line search: fnorm=%18.16e, gnorm=%18.16e, ynorm=%18.16e, minlambda=%18.16e, lambda=%18.16e, initial slope=%18.16e\n",fnorm,*gnorm,*ynorm,minlambda,lambda,initslope);CHKERRQ(ierr); 1908fe835674SShri Abhyankar } 1909fe835674SShri Abhyankar *flag = PETSC_FALSE; 1910fe835674SShri Abhyankar break; 1911fe835674SShri Abhyankar } 1912fe835674SShri Abhyankar t1 = .5*((*gnorm)*(*gnorm) - fnorm*fnorm) - lambda*initslope; 1913fe835674SShri Abhyankar t2 = .5*(gnormprev*gnormprev - fnorm*fnorm) - lambdaprev*initslope; 1914fe835674SShri Abhyankar a = (t1/(lambda*lambda) - t2/(lambdaprev*lambdaprev))/(lambda-lambdaprev); 1915fe835674SShri Abhyankar b = (-lambdaprev*t1/(lambda*lambda) + lambda*t2/(lambdaprev*lambdaprev))/(lambda-lambdaprev); 1916fe835674SShri Abhyankar d = b*b - 3*a*initslope; 1917fe835674SShri Abhyankar if (d < 0.0) d = 0.0; 1918fe835674SShri Abhyankar if (a == 0.0) { 1919fe835674SShri Abhyankar lambdatemp = -initslope/(2.0*b); 1920fe835674SShri Abhyankar } else { 1921fe835674SShri Abhyankar lambdatemp = (-b + sqrt(d))/(3.0*a); 1922fe835674SShri Abhyankar } 1923fe835674SShri Abhyankar lambdaprev = lambda; 1924fe835674SShri Abhyankar gnormprev = *gnorm; 1925fe835674SShri Abhyankar if (lambdatemp > .5*lambda) lambdatemp = .5*lambda; 1926fe835674SShri Abhyankar if (lambdatemp <= .1*lambda) lambda = .1*lambda; 1927fe835674SShri Abhyankar else lambda = lambdatemp; 1928fe835674SShri Abhyankar ierr = VecWAXPY(w,-lambda,y,x);CHKERRQ(ierr); 1929fe835674SShri Abhyankar ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr); 1930fe835674SShri Abhyankar if (snes->nfuncs >= snes->max_funcs) { 1931fe835674SShri Abhyankar ierr = PetscInfo1(snes,"Exceeded maximum function evaluations, while looking for good step length! %D \n",count);CHKERRQ(ierr); 1932fe835674SShri Abhyankar ierr = PetscInfo5(snes,"fnorm=%18.16e, gnorm=%18.16e, ynorm=%18.16e, lambda=%18.16e, initial slope=%18.16e\n",fnorm,*gnorm,*ynorm,lambda,initslope);CHKERRQ(ierr); 1933fe835674SShri Abhyankar *flag = PETSC_FALSE; 1934fe835674SShri Abhyankar snes->reason = SNES_DIVERGED_FUNCTION_COUNT; 1935fe835674SShri Abhyankar break; 1936fe835674SShri Abhyankar } 1937fe835674SShri Abhyankar ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr); 19382f63a38cSShri Abhyankar if (snes->ops->solve != SNESSolveVI_SS) { 1939fe835674SShri Abhyankar ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr); 19407fe79bc4SShri Abhyankar } else { 19417fe79bc4SShri Abhyankar ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr); 19427fe79bc4SShri Abhyankar } 1943fe835674SShri Abhyankar if (snes->domainerror) { 1944fe835674SShri Abhyankar ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); 1945fe835674SShri Abhyankar PetscFunctionReturn(0); 1946fe835674SShri Abhyankar } 194762cbcd01SMatthew G Knepley if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number"); 1948fe835674SShri Abhyankar if (.5*(*gnorm)*(*gnorm) < .5*fnorm*fnorm + lambda*vi->alpha*initslope) { /* is reduction enough? */ 1949fe835674SShri Abhyankar if (vi->lsmonitor) { 1950fe835674SShri Abhyankar ierr = PetscPrintf(comm," Line search: Cubically determined step, current gnorm %G lambda=%18.16e\n",*gnorm,lambda);CHKERRQ(ierr); 1951fe835674SShri Abhyankar } 1952fe835674SShri Abhyankar break; 1953fe835674SShri Abhyankar } else { 1954fe835674SShri Abhyankar if (vi->lsmonitor) { 1955fe835674SShri Abhyankar ierr = PetscPrintf(comm," Line search: Cubic step no good, shrinking lambda, current gnorm %G lambda=%18.16e\n",*gnorm,lambda);CHKERRQ(ierr); 1956fe835674SShri Abhyankar } 1957fe835674SShri Abhyankar } 1958fe835674SShri Abhyankar count++; 1959fe835674SShri Abhyankar } 1960fe835674SShri Abhyankar theend1: 1961fe835674SShri Abhyankar /* Optional user-defined check for line search step validity */ 1962fe835674SShri Abhyankar if (vi->postcheckstep && *flag) { 1963fe835674SShri Abhyankar ierr = (*vi->postcheckstep)(snes,x,y,w,vi->postcheck,&changed_y,&changed_w);CHKERRQ(ierr); 1964fe835674SShri Abhyankar if (changed_y) { 1965fe835674SShri Abhyankar ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr); 1966fe835674SShri Abhyankar ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr); 1967fe835674SShri Abhyankar } 1968fe835674SShri Abhyankar if (changed_y || changed_w) { /* recompute the function if the step has changed */ 1969fe835674SShri Abhyankar ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr); 19702f63a38cSShri Abhyankar if (snes->ops->solve != SNESSolveVI_SS) { 1971fe835674SShri Abhyankar ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr); 19727fe79bc4SShri Abhyankar } else { 19737fe79bc4SShri Abhyankar ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr); 19747fe79bc4SShri Abhyankar } 1975fe835674SShri Abhyankar if (snes->domainerror) { 1976fe835674SShri Abhyankar ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); 1977fe835674SShri Abhyankar PetscFunctionReturn(0); 1978fe835674SShri Abhyankar } 197962cbcd01SMatthew G Knepley if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number"); 1980fe835674SShri Abhyankar ierr = VecNormBegin(y,NORM_2,ynorm);CHKERRQ(ierr); 1981fe835674SShri Abhyankar ierr = VecNormEnd(y,NORM_2,ynorm);CHKERRQ(ierr); 1982fe835674SShri Abhyankar } 1983fe835674SShri Abhyankar } 1984fe835674SShri Abhyankar ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); 1985fe835674SShri Abhyankar PetscFunctionReturn(0); 1986fe835674SShri Abhyankar } 1987fe835674SShri Abhyankar 19882b4ed282SShri Abhyankar #undef __FUNCT__ 19892b4ed282SShri Abhyankar #define __FUNCT__ "SNESLineSearchQuadratic_VI" 19902b4ed282SShri Abhyankar /* 19917fe79bc4SShri Abhyankar This routine does a quadratic line search while keeping the iterates within the variable bounds 19922b4ed282SShri Abhyankar */ 1993ace3abfcSBarry Smith PetscErrorCode SNESLineSearchQuadratic_VI(SNES snes,void *lsctx,Vec x,Vec f,Vec g,Vec y,Vec w,PetscReal fnorm,PetscReal xnorm,PetscReal *ynorm,PetscReal *gnorm,PetscBool *flag) 19942b4ed282SShri Abhyankar { 19952b4ed282SShri Abhyankar /* 19962b4ed282SShri Abhyankar Note that for line search purposes we work with with the related 19972b4ed282SShri Abhyankar minimization problem: 19982b4ed282SShri Abhyankar min z(x): R^n -> R, 19992b4ed282SShri Abhyankar where z(x) = .5 * fnorm*fnorm,and fnorm = || f ||_2. 20002b4ed282SShri Abhyankar */ 20012b4ed282SShri Abhyankar PetscReal initslope,minlambda,lambda,lambdatemp,rellength; 20022b4ed282SShri Abhyankar #if defined(PETSC_USE_COMPLEX) 20032b4ed282SShri Abhyankar PetscScalar cinitslope; 20042b4ed282SShri Abhyankar #endif 20052b4ed282SShri Abhyankar PetscErrorCode ierr; 20062b4ed282SShri Abhyankar PetscInt count; 20072b4ed282SShri Abhyankar SNES_VI *vi = (SNES_VI*)snes->data; 2008ace3abfcSBarry Smith PetscBool changed_w = PETSC_FALSE,changed_y = PETSC_FALSE; 20092b4ed282SShri Abhyankar 20102b4ed282SShri Abhyankar PetscFunctionBegin; 20112b4ed282SShri Abhyankar ierr = PetscLogEventBegin(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); 20122b4ed282SShri Abhyankar *flag = PETSC_TRUE; 20132b4ed282SShri Abhyankar 20142b4ed282SShri Abhyankar ierr = VecNorm(y,NORM_2,ynorm);CHKERRQ(ierr); 20152b4ed282SShri Abhyankar if (*ynorm == 0.0) { 2016c92abb8aSShri Abhyankar if (vi->lsmonitor) { 2017c92abb8aSShri Abhyankar ierr = PetscViewerASCIIMonitorPrintf(vi->lsmonitor,"Line search: Direction and size is 0\n");CHKERRQ(ierr); 20182b4ed282SShri Abhyankar } 20192b4ed282SShri Abhyankar *gnorm = fnorm; 20202b4ed282SShri Abhyankar ierr = VecCopy(x,w);CHKERRQ(ierr); 20212b4ed282SShri Abhyankar ierr = VecCopy(f,g);CHKERRQ(ierr); 20222b4ed282SShri Abhyankar *flag = PETSC_FALSE; 20232b4ed282SShri Abhyankar goto theend2; 20242b4ed282SShri Abhyankar } 20252b4ed282SShri Abhyankar if (*ynorm > vi->maxstep) { /* Step too big, so scale back */ 20262b4ed282SShri Abhyankar ierr = VecScale(y,vi->maxstep/(*ynorm));CHKERRQ(ierr); 20272b4ed282SShri Abhyankar *ynorm = vi->maxstep; 20282b4ed282SShri Abhyankar } 20292b4ed282SShri Abhyankar ierr = VecMaxPointwiseDivide(y,x,&rellength);CHKERRQ(ierr); 20302b4ed282SShri Abhyankar minlambda = vi->minlambda/rellength; 20317fe79bc4SShri Abhyankar ierr = MatMult(snes->jacobian,y,w);CHKERRQ(ierr); 20322b4ed282SShri Abhyankar #if defined(PETSC_USE_COMPLEX) 20337fe79bc4SShri Abhyankar ierr = VecDot(f,w,&cinitslope);CHKERRQ(ierr); 20342b4ed282SShri Abhyankar initslope = PetscRealPart(cinitslope); 20352b4ed282SShri Abhyankar #else 20367fe79bc4SShri Abhyankar ierr = VecDot(f,w,&initslope);CHKERRQ(ierr); 20372b4ed282SShri Abhyankar #endif 20382b4ed282SShri Abhyankar if (initslope > 0.0) initslope = -initslope; 20392b4ed282SShri Abhyankar if (initslope == 0.0) initslope = -1.0; 20402b4ed282SShri Abhyankar ierr = PetscInfo1(snes,"Initslope %G \n",initslope);CHKERRQ(ierr); 20412b4ed282SShri Abhyankar 20422b4ed282SShri Abhyankar ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr); 20437fe79bc4SShri Abhyankar ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr); 20442b4ed282SShri Abhyankar if (snes->nfuncs >= snes->max_funcs) { 20452b4ed282SShri Abhyankar ierr = PetscInfo(snes,"Exceeded maximum function evaluations, while checking full step length!\n");CHKERRQ(ierr); 20462b4ed282SShri Abhyankar *flag = PETSC_FALSE; 20472b4ed282SShri Abhyankar snes->reason = SNES_DIVERGED_FUNCTION_COUNT; 20482b4ed282SShri Abhyankar goto theend2; 20492b4ed282SShri Abhyankar } 20502b4ed282SShri Abhyankar ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr); 20512f63a38cSShri Abhyankar if (snes->ops->solve != SNESSolveVI_SS) { 20527fe79bc4SShri Abhyankar ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr); 20537fe79bc4SShri Abhyankar } else { 20547fe79bc4SShri Abhyankar ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr); 20557fe79bc4SShri Abhyankar } 20562b4ed282SShri Abhyankar if (snes->domainerror) { 20572b4ed282SShri Abhyankar ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); 20582b4ed282SShri Abhyankar PetscFunctionReturn(0); 20592b4ed282SShri Abhyankar } 206062cbcd01SMatthew G Knepley if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number"); 20612b4ed282SShri Abhyankar if (.5*(*gnorm)*(*gnorm) <= .5*fnorm*fnorm + vi->alpha*initslope) { /* Sufficient reduction */ 2062c92abb8aSShri Abhyankar if (vi->lsmonitor) { 2063c92abb8aSShri Abhyankar ierr = PetscViewerASCIIMonitorPrintf(vi->lsmonitor," Line search: Using full step: fnorm %G gnorm %G\n",fnorm,*gnorm);CHKERRQ(ierr); 20642b4ed282SShri Abhyankar } 20652b4ed282SShri Abhyankar goto theend2; 20662b4ed282SShri Abhyankar } 20672b4ed282SShri Abhyankar 20682b4ed282SShri Abhyankar /* Fit points with quadratic */ 20692b4ed282SShri Abhyankar lambda = 1.0; 20702b4ed282SShri Abhyankar count = 1; 20712b4ed282SShri Abhyankar while (PETSC_TRUE) { 20722b4ed282SShri Abhyankar if (lambda <= minlambda) { /* bad luck; use full step */ 2073c92abb8aSShri Abhyankar if (vi->lsmonitor) { 2074c92abb8aSShri Abhyankar ierr = PetscViewerASCIIMonitorPrintf(vi->lsmonitor,"Line search: Unable to find good step length! %D \n",count);CHKERRQ(ierr); 2075c92abb8aSShri Abhyankar ierr = PetscViewerASCIIMonitorPrintf(vi->lsmonitor,"Line search: fnorm=%G, gnorm=%G, ynorm=%G, lambda=%G, initial slope=%G\n",fnorm,*gnorm,*ynorm,lambda,initslope);CHKERRQ(ierr); 20762b4ed282SShri Abhyankar } 20772b4ed282SShri Abhyankar ierr = VecCopy(x,w);CHKERRQ(ierr); 20782b4ed282SShri Abhyankar *flag = PETSC_FALSE; 20792b4ed282SShri Abhyankar break; 20802b4ed282SShri Abhyankar } 20812b4ed282SShri Abhyankar lambdatemp = -initslope/((*gnorm)*(*gnorm) - fnorm*fnorm - 2.0*initslope); 20822b4ed282SShri Abhyankar if (lambdatemp > .5*lambda) lambdatemp = .5*lambda; 20832b4ed282SShri Abhyankar if (lambdatemp <= .1*lambda) lambda = .1*lambda; 20842b4ed282SShri Abhyankar else lambda = lambdatemp; 20852b4ed282SShri Abhyankar 20862b4ed282SShri Abhyankar ierr = VecWAXPY(w,-lambda,y,x);CHKERRQ(ierr); 20877fe79bc4SShri Abhyankar ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr); 20882b4ed282SShri Abhyankar if (snes->nfuncs >= snes->max_funcs) { 20892b4ed282SShri Abhyankar ierr = PetscInfo1(snes,"Exceeded maximum function evaluations, while looking for good step length! %D \n",count);CHKERRQ(ierr); 20902b4ed282SShri Abhyankar ierr = PetscInfo5(snes,"fnorm=%18.16e, gnorm=%18.16e, ynorm=%18.16e, lambda=%18.16e, initial slope=%18.16e\n",fnorm,*gnorm,*ynorm,lambda,initslope);CHKERRQ(ierr); 20912b4ed282SShri Abhyankar *flag = PETSC_FALSE; 20922b4ed282SShri Abhyankar snes->reason = SNES_DIVERGED_FUNCTION_COUNT; 20932b4ed282SShri Abhyankar break; 20942b4ed282SShri Abhyankar } 20952b4ed282SShri Abhyankar ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr); 20962b4ed282SShri Abhyankar if (snes->domainerror) { 20972b4ed282SShri Abhyankar ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); 20982b4ed282SShri Abhyankar PetscFunctionReturn(0); 20992b4ed282SShri Abhyankar } 21002f63a38cSShri Abhyankar if (snes->ops->solve != SNESSolveVI_SS) { 21017fe79bc4SShri Abhyankar ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr); 21027fe79bc4SShri Abhyankar } else { 21032b4ed282SShri Abhyankar ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr); 21047fe79bc4SShri Abhyankar } 210562cbcd01SMatthew G Knepley if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number"); 21062b4ed282SShri Abhyankar if (.5*(*gnorm)*(*gnorm) < .5*fnorm*fnorm + lambda*vi->alpha*initslope) { /* sufficient reduction */ 2107c92abb8aSShri Abhyankar if (vi->lsmonitor) { 2108c92abb8aSShri Abhyankar ierr = PetscViewerASCIIMonitorPrintf(vi->lsmonitor," Line Search: Quadratically determined step, lambda=%G\n",lambda);CHKERRQ(ierr); 21092b4ed282SShri Abhyankar } 21102b4ed282SShri Abhyankar break; 21112b4ed282SShri Abhyankar } 21122b4ed282SShri Abhyankar count++; 21132b4ed282SShri Abhyankar } 21142b4ed282SShri Abhyankar theend2: 21152b4ed282SShri Abhyankar /* Optional user-defined check for line search step validity */ 21162b4ed282SShri Abhyankar if (vi->postcheckstep) { 21172b4ed282SShri Abhyankar ierr = (*vi->postcheckstep)(snes,x,y,w,vi->postcheck,&changed_y,&changed_w);CHKERRQ(ierr); 21182b4ed282SShri Abhyankar if (changed_y) { 21192b4ed282SShri Abhyankar ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr); 21207fe79bc4SShri Abhyankar ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr); 21212b4ed282SShri Abhyankar } 21222b4ed282SShri Abhyankar if (changed_y || changed_w) { /* recompute the function if the step has changed */ 21232b4ed282SShri Abhyankar ierr = SNESComputeFunction(snes,w,g); 21242b4ed282SShri Abhyankar if (snes->domainerror) { 21252b4ed282SShri Abhyankar ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); 21262b4ed282SShri Abhyankar PetscFunctionReturn(0); 21272b4ed282SShri Abhyankar } 21282f63a38cSShri Abhyankar if (snes->ops->solve != SNESSolveVI_SS) { 21297fe79bc4SShri Abhyankar ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr); 21307fe79bc4SShri Abhyankar } else { 21317fe79bc4SShri Abhyankar ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr); 21327fe79bc4SShri Abhyankar } 21337fe79bc4SShri Abhyankar 21342b4ed282SShri Abhyankar ierr = VecNormBegin(y,NORM_2,ynorm);CHKERRQ(ierr); 21352b4ed282SShri Abhyankar ierr = VecNormEnd(y,NORM_2,ynorm);CHKERRQ(ierr); 213662cbcd01SMatthew G Knepley if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number"); 21372b4ed282SShri Abhyankar } 21382b4ed282SShri Abhyankar } 21392b4ed282SShri Abhyankar ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); 21402b4ed282SShri Abhyankar PetscFunctionReturn(0); 21412b4ed282SShri Abhyankar } 21422b4ed282SShri Abhyankar 2143ace3abfcSBarry Smith typedef PetscErrorCode (*FCN2)(SNES,void*,Vec,Vec,Vec,Vec,Vec,PetscReal,PetscReal,PetscReal*,PetscReal*,PetscBool*); /* force argument to next function to not be extern C*/ 21442b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */ 21452b4ed282SShri Abhyankar EXTERN_C_BEGIN 21462b4ed282SShri Abhyankar #undef __FUNCT__ 21472b4ed282SShri Abhyankar #define __FUNCT__ "SNESLineSearchSet_VI" 21487087cfbeSBarry Smith PetscErrorCode SNESLineSearchSet_VI(SNES snes,FCN2 func,void *lsctx) 21492b4ed282SShri Abhyankar { 21502b4ed282SShri Abhyankar PetscFunctionBegin; 21512b4ed282SShri Abhyankar ((SNES_VI *)(snes->data))->LineSearch = func; 21522b4ed282SShri Abhyankar ((SNES_VI *)(snes->data))->lsP = lsctx; 21532b4ed282SShri Abhyankar PetscFunctionReturn(0); 21542b4ed282SShri Abhyankar } 21552b4ed282SShri Abhyankar EXTERN_C_END 21562b4ed282SShri Abhyankar 21572b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */ 21582b4ed282SShri Abhyankar EXTERN_C_BEGIN 21592b4ed282SShri Abhyankar #undef __FUNCT__ 21602b4ed282SShri Abhyankar #define __FUNCT__ "SNESLineSearchSetMonitor_VI" 21617087cfbeSBarry Smith PetscErrorCode SNESLineSearchSetMonitor_VI(SNES snes,PetscBool flg) 21622b4ed282SShri Abhyankar { 21632b4ed282SShri Abhyankar SNES_VI *vi = (SNES_VI*)snes->data; 21642b4ed282SShri Abhyankar PetscErrorCode ierr; 21652b4ed282SShri Abhyankar 21662b4ed282SShri Abhyankar PetscFunctionBegin; 2167c92abb8aSShri Abhyankar if (flg && !vi->lsmonitor) { 2168c92abb8aSShri Abhyankar ierr = PetscViewerASCIIMonitorCreate(((PetscObject)snes)->comm,"stdout",((PetscObject)snes)->tablevel,&vi->lsmonitor);CHKERRQ(ierr); 2169c92abb8aSShri Abhyankar } else if (!flg && vi->lsmonitor) { 21706bf464f9SBarry Smith ierr = PetscViewerASCIIMonitorDestroy(&vi->lsmonitor);CHKERRQ(ierr); 21712b4ed282SShri Abhyankar } 21722b4ed282SShri Abhyankar PetscFunctionReturn(0); 21732b4ed282SShri Abhyankar } 21742b4ed282SShri Abhyankar EXTERN_C_END 21752b4ed282SShri Abhyankar 21762b4ed282SShri Abhyankar /* 21772b4ed282SShri Abhyankar SNESView_VI - Prints info from the SNESVI data structure. 21782b4ed282SShri Abhyankar 21792b4ed282SShri Abhyankar Input Parameters: 21802b4ed282SShri Abhyankar . SNES - the SNES context 21812b4ed282SShri Abhyankar . viewer - visualization context 21822b4ed282SShri Abhyankar 21832b4ed282SShri Abhyankar Application Interface Routine: SNESView() 21842b4ed282SShri Abhyankar */ 21852b4ed282SShri Abhyankar #undef __FUNCT__ 21862b4ed282SShri Abhyankar #define __FUNCT__ "SNESView_VI" 21872b4ed282SShri Abhyankar static PetscErrorCode SNESView_VI(SNES snes,PetscViewer viewer) 21882b4ed282SShri Abhyankar { 21892b4ed282SShri Abhyankar SNES_VI *vi = (SNES_VI *)snes->data; 219078c4b9d3SShri Abhyankar const char *cstr,*tstr; 21912b4ed282SShri Abhyankar PetscErrorCode ierr; 2192ace3abfcSBarry Smith PetscBool iascii; 21932b4ed282SShri Abhyankar 21942b4ed282SShri Abhyankar PetscFunctionBegin; 21952b4ed282SShri Abhyankar ierr = PetscTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); 21962b4ed282SShri Abhyankar if (iascii) { 21972b4ed282SShri Abhyankar if (vi->LineSearch == SNESLineSearchNo_VI) cstr = "SNESLineSearchNo"; 21982b4ed282SShri Abhyankar else if (vi->LineSearch == SNESLineSearchQuadratic_VI) cstr = "SNESLineSearchQuadratic"; 21992b4ed282SShri Abhyankar else if (vi->LineSearch == SNESLineSearchCubic_VI) cstr = "SNESLineSearchCubic"; 22002b4ed282SShri Abhyankar else cstr = "unknown"; 220178c4b9d3SShri Abhyankar if (snes->ops->solve == SNESSolveVI_SS) tstr = "Semismooth"; 22020a7c7af0SShri Abhyankar else if (snes->ops->solve == SNESSolveVI_RS) tstr = "Reduced Space"; 2203b350b9c9SBarry Smith else if (snes->ops->solve == SNESSolveVI_RSAUG) tstr = "Reduced space with augmented variables"; 220478c4b9d3SShri Abhyankar else tstr = "unknown"; 220578c4b9d3SShri Abhyankar ierr = PetscViewerASCIIPrintf(viewer," VI algorithm: %s\n",tstr);CHKERRQ(ierr); 22062b4ed282SShri Abhyankar ierr = PetscViewerASCIIPrintf(viewer," line search variant: %s\n",cstr);CHKERRQ(ierr); 22072b4ed282SShri Abhyankar ierr = PetscViewerASCIIPrintf(viewer," alpha=%G, maxstep=%G, minlambda=%G\n",vi->alpha,vi->maxstep,vi->minlambda);CHKERRQ(ierr); 22082b4ed282SShri Abhyankar } else { 22092b4ed282SShri Abhyankar SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Viewer type %s not supported for SNES EQ VI",((PetscObject)viewer)->type_name); 22102b4ed282SShri Abhyankar } 22112b4ed282SShri Abhyankar PetscFunctionReturn(0); 22122b4ed282SShri Abhyankar } 22132b4ed282SShri Abhyankar 22145559b345SBarry Smith #undef __FUNCT__ 22155559b345SBarry Smith #define __FUNCT__ "SNESVISetVariableBounds" 22165559b345SBarry Smith /*@ 22172b4ed282SShri Abhyankar SNESVISetVariableBounds - Sets the lower and upper bounds for the solution vector. xl <= x <= xu. 22182b4ed282SShri Abhyankar 22192b4ed282SShri Abhyankar Input Parameters: 22202b4ed282SShri Abhyankar . snes - the SNES context. 22212b4ed282SShri Abhyankar . xl - lower bound. 22222b4ed282SShri Abhyankar . xu - upper bound. 22232b4ed282SShri Abhyankar 22242b4ed282SShri Abhyankar Notes: 22252b4ed282SShri Abhyankar If this routine is not called then the lower and upper bounds are set to 222601f0b76bSBarry Smith SNES_VI_INF and SNES_VI_NINF respectively during SNESSetUp(). 222784c105d7SBarry Smith 22285559b345SBarry Smith @*/ 222969c03620SShri Abhyankar PetscErrorCode SNESVISetVariableBounds(SNES snes, Vec xl, Vec xu) 22302b4ed282SShri Abhyankar { 2231d923200aSJungho Lee SNES_VI *vi; 2232d923200aSJungho Lee PetscErrorCode ierr; 22332b4ed282SShri Abhyankar 22342b4ed282SShri Abhyankar PetscFunctionBegin; 22352b4ed282SShri Abhyankar PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 22362b4ed282SShri Abhyankar PetscValidHeaderSpecific(xl,VEC_CLASSID,2); 22372b4ed282SShri Abhyankar PetscValidHeaderSpecific(xu,VEC_CLASSID,3); 22382b4ed282SShri Abhyankar if (!snes->vec_func) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Must call SNESSetFunction() first"); 22392b4ed282SShri Abhyankar if (xl->map->N != snes->vec_func->map->N) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Incompatible vector lengths lower bound = %D solution vector = %D",xl->map->N,snes->vec_func->map->N); 22402b4ed282SShri Abhyankar if (xu->map->N != snes->vec_func->map->N) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Incompatible vector lengths: upper bound = %D solution vector = %D",xu->map->N,snes->vec_func->map->N); 2241d923200aSJungho Lee ierr = SNESSetType(snes,SNESVI);CHKERRQ(ierr); 2242d923200aSJungho Lee vi = (SNES_VI*)snes->data; 22432b4ed282SShri Abhyankar vi->usersetxbounds = PETSC_TRUE; 22442b4ed282SShri Abhyankar vi->xl = xl; 22452b4ed282SShri Abhyankar vi->xu = xu; 22462b4ed282SShri Abhyankar PetscFunctionReturn(0); 22472b4ed282SShri Abhyankar } 2248693ddf92SShri Abhyankar 22492b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */ 22502b4ed282SShri Abhyankar /* 22512b4ed282SShri Abhyankar SNESSetFromOptions_VI - Sets various parameters for the SNESVI method. 22522b4ed282SShri Abhyankar 22532b4ed282SShri Abhyankar Input Parameter: 22542b4ed282SShri Abhyankar . snes - the SNES context 22552b4ed282SShri Abhyankar 22562b4ed282SShri Abhyankar Application Interface Routine: SNESSetFromOptions() 22572b4ed282SShri Abhyankar */ 22582b4ed282SShri Abhyankar #undef __FUNCT__ 22592b4ed282SShri Abhyankar #define __FUNCT__ "SNESSetFromOptions_VI" 22602b4ed282SShri Abhyankar static PetscErrorCode SNESSetFromOptions_VI(SNES snes) 22612b4ed282SShri Abhyankar { 22622b4ed282SShri Abhyankar SNES_VI *vi = (SNES_VI *)snes->data; 22637fe79bc4SShri Abhyankar const char *lses[] = {"basic","basicnonorms","quadratic","cubic"}; 2264b350b9c9SBarry Smith const char *vies[] = {"ss","rs","rsaug"}; 22652b4ed282SShri Abhyankar PetscErrorCode ierr; 22662b4ed282SShri Abhyankar PetscInt indx; 226769c03620SShri Abhyankar PetscBool flg,set,flg2; 22682b4ed282SShri Abhyankar 22692b4ed282SShri Abhyankar PetscFunctionBegin; 22702b4ed282SShri Abhyankar ierr = PetscOptionsHead("SNES semismooth method options");CHKERRQ(ierr); 22719308c137SBarry Smith ierr = PetscOptionsBool("-snes_vi_monitor","Monitor all non-active variables","None",PETSC_FALSE,&flg,0);CHKERRQ(ierr); 22729308c137SBarry Smith if (flg) { 22739308c137SBarry Smith ierr = SNESMonitorSet(snes,SNESMonitorVI,0,0);CHKERRQ(ierr); 22749308c137SBarry Smith } 2275be6adb11SBarry Smith ierr = PetscOptionsReal("-snes_ls_alpha","Function norm must decrease by","None",vi->alpha,&vi->alpha,0);CHKERRQ(ierr); 2276be6adb11SBarry Smith ierr = PetscOptionsReal("-snes_ls_maxstep","Step must be less than","None",vi->maxstep,&vi->maxstep,0);CHKERRQ(ierr); 2277be6adb11SBarry Smith ierr = PetscOptionsReal("-snes_ls_minlambda","Minimum lambda allowed","None",vi->minlambda,&vi->minlambda,0);CHKERRQ(ierr); 22782b4ed282SShri Abhyankar ierr = PetscOptionsReal("-snes_vi_const_tol","constraint tolerance","None",vi->const_tol,&vi->const_tol,0);CHKERRQ(ierr); 2279be6adb11SBarry Smith ierr = PetscOptionsBool("-snes_ls_monitor","Print progress of line searches","SNESLineSearchSetMonitor",vi->lsmonitor ? PETSC_TRUE : PETSC_FALSE,&flg,&set);CHKERRQ(ierr); 22802b4ed282SShri Abhyankar if (set) {ierr = SNESLineSearchSetMonitor(snes,flg);CHKERRQ(ierr);} 22812f63a38cSShri Abhyankar ierr = PetscOptionsEList("-snes_vi_type","Semismooth algorithm used","",vies,3,"ss",&indx,&flg2);CHKERRQ(ierr); 228269c03620SShri Abhyankar if (flg2) { 228369c03620SShri Abhyankar switch (indx) { 228469c03620SShri Abhyankar case 0: 228569c03620SShri Abhyankar snes->ops->solve = SNESSolveVI_SS; 228669c03620SShri Abhyankar break; 228769c03620SShri Abhyankar case 1: 2288d950fb63SShri Abhyankar snes->ops->solve = SNESSolveVI_RS; 2289d950fb63SShri Abhyankar break; 22902f63a38cSShri Abhyankar case 2: 2291b350b9c9SBarry Smith snes->ops->solve = SNESSolveVI_RSAUG; 229269c03620SShri Abhyankar } 229369c03620SShri Abhyankar } 2294be6adb11SBarry Smith ierr = PetscOptionsEList("-snes_ls","Line search used","SNESLineSearchSet",lses,4,"basic",&indx,&flg);CHKERRQ(ierr); 22952b4ed282SShri Abhyankar if (flg) { 22962b4ed282SShri Abhyankar switch (indx) { 22972b4ed282SShri Abhyankar case 0: 22982b4ed282SShri Abhyankar ierr = SNESLineSearchSet(snes,SNESLineSearchNo_VI,PETSC_NULL);CHKERRQ(ierr); 22992b4ed282SShri Abhyankar break; 23002b4ed282SShri Abhyankar case 1: 23012b4ed282SShri Abhyankar ierr = SNESLineSearchSet(snes,SNESLineSearchNoNorms_VI,PETSC_NULL);CHKERRQ(ierr); 23022b4ed282SShri Abhyankar break; 23032b4ed282SShri Abhyankar case 2: 23042b4ed282SShri Abhyankar ierr = SNESLineSearchSet(snes,SNESLineSearchQuadratic_VI,PETSC_NULL);CHKERRQ(ierr); 23052b4ed282SShri Abhyankar break; 23062b4ed282SShri Abhyankar case 3: 23072b4ed282SShri Abhyankar ierr = SNESLineSearchSet(snes,SNESLineSearchCubic_VI,PETSC_NULL);CHKERRQ(ierr); 23082b4ed282SShri Abhyankar break; 23092b4ed282SShri Abhyankar } 2310fe835674SShri Abhyankar } 23112b4ed282SShri Abhyankar ierr = PetscOptionsTail();CHKERRQ(ierr); 23122b4ed282SShri Abhyankar PetscFunctionReturn(0); 23132b4ed282SShri Abhyankar } 23142b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */ 23152b4ed282SShri Abhyankar /*MC 23168b4c83edSBarry Smith SNESVI - Various solvers for variational inequalities based on Newton's method 23172b4ed282SShri Abhyankar 23182b4ed282SShri Abhyankar Options Database: 23198b4c83edSBarry Smith + -snes_vi_type <ss,rs,rsaug> a semi-smooth solver, a reduced space active set method and a reduced space active set method that does not eliminate the active constraints from the Jacobian instead augments the Jacobian with 23208b4c83edSBarry Smith additional variables that enforce the constraints 23218b4c83edSBarry Smith - -snes_vi_monitor - prints the number of active constraints at each iteration. 23222b4ed282SShri Abhyankar 23232b4ed282SShri Abhyankar 23242b4ed282SShri Abhyankar Level: beginner 23252b4ed282SShri Abhyankar 23262b4ed282SShri Abhyankar .seealso: SNESCreate(), SNES, SNESSetType(), SNESTR, SNESLineSearchSet(), 23272b4ed282SShri Abhyankar SNESLineSearchSetPostCheck(), SNESLineSearchNo(), SNESLineSearchCubic(), SNESLineSearchQuadratic(), 23282b4ed282SShri Abhyankar SNESLineSearchSet(), SNESLineSearchNoNorms(), SNESLineSearchSetPreCheck(), SNESLineSearchSetParams(), SNESLineSearchGetParams() 23292b4ed282SShri Abhyankar 23302b4ed282SShri Abhyankar M*/ 23312b4ed282SShri Abhyankar EXTERN_C_BEGIN 23322b4ed282SShri Abhyankar #undef __FUNCT__ 23332b4ed282SShri Abhyankar #define __FUNCT__ "SNESCreate_VI" 23347087cfbeSBarry Smith PetscErrorCode SNESCreate_VI(SNES snes) 23352b4ed282SShri Abhyankar { 23362b4ed282SShri Abhyankar PetscErrorCode ierr; 23372b4ed282SShri Abhyankar SNES_VI *vi; 23382b4ed282SShri Abhyankar 23392b4ed282SShri Abhyankar PetscFunctionBegin; 23402b4ed282SShri Abhyankar snes->ops->setup = SNESSetUp_VI; 2341edafb9efSBarry Smith snes->ops->solve = SNESSolveVI_RS; 23422b4ed282SShri Abhyankar snes->ops->destroy = SNESDestroy_VI; 23432b4ed282SShri Abhyankar snes->ops->setfromoptions = SNESSetFromOptions_VI; 23442b4ed282SShri Abhyankar snes->ops->view = SNESView_VI; 234537596af1SLisandro Dalcin snes->ops->reset = 0; /* XXX Implement!!! */ 23462b4ed282SShri Abhyankar snes->ops->converged = SNESDefaultConverged_VI; 23472b4ed282SShri Abhyankar 23482b4ed282SShri Abhyankar ierr = PetscNewLog(snes,SNES_VI,&vi);CHKERRQ(ierr); 23492b4ed282SShri Abhyankar snes->data = (void*)vi; 23502b4ed282SShri Abhyankar vi->alpha = 1.e-4; 23512b4ed282SShri Abhyankar vi->maxstep = 1.e8; 23522b4ed282SShri Abhyankar vi->minlambda = 1.e-12; 23537fe79bc4SShri Abhyankar vi->LineSearch = SNESLineSearchNo_VI; 23542b4ed282SShri Abhyankar vi->lsP = PETSC_NULL; 23552b4ed282SShri Abhyankar vi->postcheckstep = PETSC_NULL; 23562b4ed282SShri Abhyankar vi->postcheck = PETSC_NULL; 23572b4ed282SShri Abhyankar vi->precheckstep = PETSC_NULL; 23582b4ed282SShri Abhyankar vi->precheck = PETSC_NULL; 23592b4ed282SShri Abhyankar vi->const_tol = 2.2204460492503131e-16; 23602f63a38cSShri Abhyankar vi->checkredundancy = PETSC_NULL; 23612b4ed282SShri Abhyankar 23622b4ed282SShri Abhyankar ierr = PetscObjectComposeFunctionDynamic((PetscObject)snes,"SNESLineSearchSetMonitor_C","SNESLineSearchSetMonitor_VI",SNESLineSearchSetMonitor_VI);CHKERRQ(ierr); 23632b4ed282SShri Abhyankar ierr = PetscObjectComposeFunctionDynamic((PetscObject)snes,"SNESLineSearchSet_C","SNESLineSearchSet_VI",SNESLineSearchSet_VI);CHKERRQ(ierr); 23642b4ed282SShri Abhyankar 23652b4ed282SShri Abhyankar PetscFunctionReturn(0); 23662b4ed282SShri Abhyankar } 23672b4ed282SShri Abhyankar EXTERN_C_END 2368