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> 5d0af7cd3SBarry Smith #include <../include/private/dmimpl.h> 6d0af7cd3SBarry Smith 7d0af7cd3SBarry Smith #undef __FUNCT__ 82176524cSBarry Smith #define __FUNCT__ "SNESVISetComputeVariableBounds" 92176524cSBarry Smith /*@C 102176524cSBarry Smith SNESVISetComputeVariableBounds - Sets a function that is called to compute the variable bounds 112176524cSBarry Smith 122176524cSBarry Smith Input parameter 132176524cSBarry Smith + snes - the SNES context 142176524cSBarry Smith - compute - computes the bounds 152176524cSBarry Smith 162176524cSBarry Smith 17aab9d709SJed Brown @*/ 182176524cSBarry Smith PetscErrorCode SNESVISetComputeVariableBounds(SNES snes, PetscErrorCode (*compute)(SNES,Vec*,Vec*)) 192176524cSBarry Smith { 202176524cSBarry Smith PetscErrorCode ierr; 212176524cSBarry Smith SNES_VI *vi; 222176524cSBarry Smith 232176524cSBarry Smith PetscFunctionBegin; 242176524cSBarry Smith ierr = SNESSetType(snes,SNESVI);CHKERRQ(ierr); 252176524cSBarry Smith vi = (SNES_VI*)snes->data; 262176524cSBarry Smith vi->computevariablebounds = compute; 272176524cSBarry Smith PetscFunctionReturn(0); 282176524cSBarry Smith } 292176524cSBarry Smith 302176524cSBarry Smith 312176524cSBarry Smith #undef __FUNCT__ 32d0af7cd3SBarry Smith #define __FUNCT__ "SNESVIGetInActiveSetIS" 33d0af7cd3SBarry Smith /* 34d0af7cd3SBarry Smith SNESVIGetInActiveSetIS - Gets the global indices for the bogus inactive set variables 35d0af7cd3SBarry Smith 36d0af7cd3SBarry Smith Input parameter 37d0af7cd3SBarry Smith . snes - the SNES context 38d0af7cd3SBarry Smith . X - the snes solution vector 39d0af7cd3SBarry Smith 40d0af7cd3SBarry Smith Output parameter 41d0af7cd3SBarry Smith . ISact - active set index set 42d0af7cd3SBarry Smith 43d0af7cd3SBarry Smith */ 44d0af7cd3SBarry Smith PetscErrorCode SNESVIGetInActiveSetIS(Vec upper,Vec lower,Vec X,Vec F,IS* inact) 45d0af7cd3SBarry Smith { 46d0af7cd3SBarry Smith PetscErrorCode ierr; 47d0af7cd3SBarry Smith const PetscScalar *x,*xl,*xu,*f; 48d0af7cd3SBarry Smith PetscInt *idx_act,i,nlocal,nloc_isact=0,ilow,ihigh,i1=0; 49d0af7cd3SBarry Smith 50d0af7cd3SBarry Smith PetscFunctionBegin; 51d0af7cd3SBarry Smith ierr = VecGetLocalSize(X,&nlocal);CHKERRQ(ierr); 52d0af7cd3SBarry Smith ierr = VecGetOwnershipRange(X,&ilow,&ihigh);CHKERRQ(ierr); 53d0af7cd3SBarry Smith ierr = VecGetArrayRead(X,&x);CHKERRQ(ierr); 54d0af7cd3SBarry Smith ierr = VecGetArrayRead(lower,&xl);CHKERRQ(ierr); 55d0af7cd3SBarry Smith ierr = VecGetArrayRead(upper,&xu);CHKERRQ(ierr); 56d0af7cd3SBarry Smith ierr = VecGetArrayRead(F,&f);CHKERRQ(ierr); 57d0af7cd3SBarry Smith /* Compute inactive set size */ 58d0af7cd3SBarry Smith for (i=0; i < nlocal;i++) { 59d0af7cd3SBarry 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++; 60d0af7cd3SBarry Smith } 61d0af7cd3SBarry Smith 62d0af7cd3SBarry Smith ierr = PetscMalloc(nloc_isact*sizeof(PetscInt),&idx_act);CHKERRQ(ierr); 63d0af7cd3SBarry Smith 64d0af7cd3SBarry Smith /* Set inactive set indices */ 65d0af7cd3SBarry Smith for(i=0; i < nlocal; i++) { 66d0af7cd3SBarry 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; 67d0af7cd3SBarry Smith } 68d0af7cd3SBarry Smith 69d0af7cd3SBarry Smith /* Create inactive set IS */ 70d0af7cd3SBarry Smith ierr = ISCreateGeneral(((PetscObject)upper)->comm,nloc_isact,idx_act,PETSC_OWN_POINTER,inact);CHKERRQ(ierr); 71d0af7cd3SBarry Smith 72d0af7cd3SBarry Smith ierr = VecRestoreArrayRead(X,&x);CHKERRQ(ierr); 73d0af7cd3SBarry Smith ierr = VecRestoreArrayRead(lower,&xl);CHKERRQ(ierr); 74d0af7cd3SBarry Smith ierr = VecRestoreArrayRead(upper,&xu);CHKERRQ(ierr); 75d0af7cd3SBarry Smith ierr = VecRestoreArrayRead(F,&f);CHKERRQ(ierr); 76d0af7cd3SBarry Smith PetscFunctionReturn(0); 77d0af7cd3SBarry Smith } 78d0af7cd3SBarry Smith 793c0c59f3SBarry Smith /* 803c0c59f3SBarry Smith Provides a wrapper to a DM to allow it to be used to generated the interpolation/restriction from the DM for the smaller matrices and vectors 813c0c59f3SBarry Smith defined by the reduced space method. 823c0c59f3SBarry Smith 833c0c59f3SBarry Smith Simple calls the regular DM interpolation and restricts it to operation on the variables not associated with active constraints. 843c0c59f3SBarry Smith 853c0c59f3SBarry Smith */ 863c0c59f3SBarry Smith typedef struct { 873c0c59f3SBarry Smith PetscInt n; /* size of vectors in the reduced DM space */ 883c0c59f3SBarry Smith IS inactive; 893c0c59f3SBarry Smith Vec upper,lower,values,F; /* upper and lower bounds of all variables on this level, the values and the function values */ 903c0c59f3SBarry Smith PetscErrorCode (*getinterpolation)(DM,DM,Mat*,Vec*); /* DM's original routines */ 913c0c59f3SBarry Smith PetscErrorCode (*coarsen)(DM, MPI_Comm, DM*); 923c0c59f3SBarry Smith PetscErrorCode (*createglobalvector)(DM,Vec*); 934c661befSBarry Smith DM dm; /* when destroying this object we need to reset the above function into the base DM */ 943c0c59f3SBarry Smith } DM_SNESVI; 953c0c59f3SBarry Smith 96d0af7cd3SBarry Smith #undef __FUNCT__ 974dcab191SBarry Smith #define __FUNCT__ "DMCreateGlobalVector_SNESVI" 984dcab191SBarry Smith /* 994dcab191SBarry Smith DMCreateGlobalVector_SNESVI - Creates global vector of the size of the reduced space 1004dcab191SBarry Smith 1014dcab191SBarry Smith */ 1024dcab191SBarry Smith PetscErrorCode DMCreateGlobalVector_SNESVI(DM dm,Vec *vec) 1034dcab191SBarry Smith { 1044dcab191SBarry Smith PetscErrorCode ierr; 1054dcab191SBarry Smith PetscContainer isnes; 1063c0c59f3SBarry Smith DM_SNESVI *dmsnesvi; 1074dcab191SBarry Smith 1084dcab191SBarry Smith PetscFunctionBegin; 1094dcab191SBarry Smith ierr = PetscObjectQuery((PetscObject)dm,"VI",(PetscObject *)&isnes);CHKERRQ(ierr); 1104dcab191SBarry Smith if (!isnes) SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_PLIB,"Composed SNES is missing"); 1114dcab191SBarry Smith ierr = PetscContainerGetPointer(isnes,(void**)&dmsnesvi);CHKERRQ(ierr); 1124dcab191SBarry Smith ierr = VecCreateMPI(((PetscObject)dm)->comm,dmsnesvi->n,PETSC_DETERMINE,vec);CHKERRQ(ierr); 1134dcab191SBarry Smith PetscFunctionReturn(0); 1144dcab191SBarry Smith } 1154dcab191SBarry Smith 1164dcab191SBarry Smith #undef __FUNCT__ 117d0af7cd3SBarry Smith #define __FUNCT__ "DMGetInterpolation_SNESVI" 118d0af7cd3SBarry Smith /* 119d0af7cd3SBarry Smith DMGetInterpolation_SNESVI - Modifieds the interpolation obtained from the DM by removing all rows and columns associated with active constraints. 120d0af7cd3SBarry Smith 121d0af7cd3SBarry Smith */ 122d0af7cd3SBarry Smith PetscErrorCode DMGetInterpolation_SNESVI(DM dm1,DM dm2,Mat *mat,Vec *vec) 123d0af7cd3SBarry Smith { 124d0af7cd3SBarry Smith PetscErrorCode ierr; 125d0af7cd3SBarry Smith PetscContainer isnes; 1263c0c59f3SBarry Smith DM_SNESVI *dmsnesvi1,*dmsnesvi2; 127d0af7cd3SBarry Smith Mat interp; 128d0af7cd3SBarry Smith 129d0af7cd3SBarry Smith PetscFunctionBegin; 130d0af7cd3SBarry Smith ierr = PetscObjectQuery((PetscObject)dm1,"VI",(PetscObject *)&isnes);CHKERRQ(ierr); 1314c661befSBarry Smith if (!isnes) SETERRQ(((PetscObject)dm1)->comm,PETSC_ERR_PLIB,"Composed VI data structure is missing"); 132d0af7cd3SBarry Smith ierr = PetscContainerGetPointer(isnes,(void**)&dmsnesvi1);CHKERRQ(ierr); 133d0af7cd3SBarry Smith ierr = PetscObjectQuery((PetscObject)dm2,"VI",(PetscObject *)&isnes);CHKERRQ(ierr); 1344c661befSBarry Smith if (!isnes) SETERRQ(((PetscObject)dm2)->comm,PETSC_ERR_PLIB,"Composed VI data structure is missing"); 135d0af7cd3SBarry Smith ierr = PetscContainerGetPointer(isnes,(void**)&dmsnesvi2);CHKERRQ(ierr); 136d0af7cd3SBarry Smith 137d0af7cd3SBarry Smith ierr = (*dmsnesvi1->getinterpolation)(dm1,dm2,&interp,PETSC_NULL);CHKERRQ(ierr); 1384dcab191SBarry Smith ierr = MatGetSubMatrix(interp,dmsnesvi2->inactive,dmsnesvi1->inactive,MAT_INITIAL_MATRIX,mat);CHKERRQ(ierr); 139d0af7cd3SBarry Smith ierr = MatDestroy(&interp);CHKERRQ(ierr); 140d0af7cd3SBarry Smith PetscFunctionReturn(0); 141d0af7cd3SBarry Smith } 142d0af7cd3SBarry Smith 143d0af7cd3SBarry Smith extern PetscErrorCode DMSetVI(DM,Vec,Vec,Vec,Vec,IS); 144d0af7cd3SBarry Smith 145d0af7cd3SBarry Smith #undef __FUNCT__ 146d0af7cd3SBarry Smith #define __FUNCT__ "DMCoarsen_SNESVI" 147d0af7cd3SBarry Smith /* 148d0af7cd3SBarry Smith DMCoarsen_SNESVI - Computes the regular coarsened DM then computes additional information about its inactive set 149d0af7cd3SBarry Smith 150d0af7cd3SBarry Smith */ 151d0af7cd3SBarry Smith PetscErrorCode DMCoarsen_SNESVI(DM dm1,MPI_Comm comm,DM *dm2) 152d0af7cd3SBarry Smith { 153d0af7cd3SBarry Smith PetscErrorCode ierr; 154d0af7cd3SBarry Smith PetscContainer isnes; 1553c0c59f3SBarry Smith DM_SNESVI *dmsnesvi1; 156d0af7cd3SBarry Smith Vec upper,lower,values,F; 157d0af7cd3SBarry Smith IS inactive; 158d0af7cd3SBarry Smith VecScatter inject; 159d0af7cd3SBarry Smith 160d0af7cd3SBarry Smith PetscFunctionBegin; 161d0af7cd3SBarry Smith ierr = PetscObjectQuery((PetscObject)dm1,"VI",(PetscObject *)&isnes);CHKERRQ(ierr); 1624c661befSBarry Smith if (!isnes) SETERRQ(((PetscObject)dm1)->comm,PETSC_ERR_PLIB,"Composed VI data structure is missing"); 163d0af7cd3SBarry Smith ierr = PetscContainerGetPointer(isnes,(void**)&dmsnesvi1);CHKERRQ(ierr); 164d0af7cd3SBarry Smith 165298cc208SBarry Smith /* get the original coarsen */ 166d0af7cd3SBarry Smith ierr = (*dmsnesvi1->coarsen)(dm1,comm,dm2);CHKERRQ(ierr); 167298cc208SBarry Smith 1683c0c59f3SBarry Smith /* not sure why this extra reference is needed, but without the dm2 disappears too early */ 1693c0c59f3SBarry Smith ierr = PetscObjectReference((PetscObject)*dm2);CHKERRQ(ierr); 1703c0c59f3SBarry Smith 171298cc208SBarry Smith /* need to set back global vectors in order to use the original injection */ 172298cc208SBarry Smith ierr = DMClearGlobalVectors(dm1);CHKERRQ(ierr); 173298cc208SBarry Smith dm1->ops->createglobalvector = dmsnesvi1->createglobalvector; 174d0af7cd3SBarry Smith ierr = DMGetInjection(*dm2,dm1,&inject);CHKERRQ(ierr); 175d0af7cd3SBarry Smith ierr = DMCreateGlobalVector(*dm2,&upper);CHKERRQ(ierr); 176d0af7cd3SBarry Smith ierr = VecScatterBegin(inject,dmsnesvi1->upper,upper,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 177d0af7cd3SBarry Smith ierr = VecScatterEnd(inject,dmsnesvi1->upper,upper,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 178d0af7cd3SBarry Smith ierr = DMCreateGlobalVector(*dm2,&lower);CHKERRQ(ierr); 179d0af7cd3SBarry Smith ierr = VecScatterBegin(inject,dmsnesvi1->lower,lower,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 180d0af7cd3SBarry Smith ierr = VecScatterEnd(inject,dmsnesvi1->lower,lower,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 181d0af7cd3SBarry Smith ierr = DMCreateGlobalVector(*dm2,&values);CHKERRQ(ierr); 182d0af7cd3SBarry Smith ierr = VecScatterBegin(inject,dmsnesvi1->values,values,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 183d0af7cd3SBarry Smith ierr = VecScatterEnd(inject,dmsnesvi1->values,values,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 184d0af7cd3SBarry Smith ierr = DMCreateGlobalVector(*dm2,&F);CHKERRQ(ierr); 185d0af7cd3SBarry Smith ierr = VecScatterBegin(inject,dmsnesvi1->F,F,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 186d0af7cd3SBarry Smith ierr = VecScatterEnd(inject,dmsnesvi1->F,F,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 187d0af7cd3SBarry Smith ierr = VecScatterDestroy(&inject);CHKERRQ(ierr); 188298cc208SBarry Smith ierr = DMClearGlobalVectors(dm1);CHKERRQ(ierr); 189298cc208SBarry Smith dm1->ops->createglobalvector = DMCreateGlobalVector_SNESVI; 190d0af7cd3SBarry Smith ierr = SNESVIGetInActiveSetIS(upper,lower,values,F,&inactive);CHKERRQ(ierr); 191d0af7cd3SBarry Smith ierr = DMSetVI(*dm2,upper,lower,values,F,inactive);CHKERRQ(ierr); 1923c0c59f3SBarry Smith ierr = VecDestroy(&upper);CHKERRQ(ierr); 1933c0c59f3SBarry Smith ierr = VecDestroy(&lower);CHKERRQ(ierr); 1943c0c59f3SBarry Smith ierr = VecDestroy(&values);CHKERRQ(ierr); 1953c0c59f3SBarry Smith ierr = VecDestroy(&F);CHKERRQ(ierr); 1963c0c59f3SBarry Smith ierr = ISDestroy(&inactive);CHKERRQ(ierr); 197d0af7cd3SBarry Smith PetscFunctionReturn(0); 198d0af7cd3SBarry Smith } 199d0af7cd3SBarry Smith 200d0af7cd3SBarry Smith #undef __FUNCT__ 2013c0c59f3SBarry Smith #define __FUNCT__ "DMDestroy_SNESVI" 2023c0c59f3SBarry Smith PetscErrorCode DMDestroy_SNESVI(DM_SNESVI *dmsnesvi) 203d0af7cd3SBarry Smith { 204d0af7cd3SBarry Smith PetscErrorCode ierr; 205d0af7cd3SBarry Smith 206d0af7cd3SBarry Smith PetscFunctionBegin; 2074c661befSBarry Smith /* reset the base methods in the DM object that were changed when the DM_SNESVI was reset */ 2084c661befSBarry Smith dmsnesvi->dm->ops->getinterpolation = dmsnesvi->getinterpolation; 2094c661befSBarry Smith dmsnesvi->dm->ops->coarsen = dmsnesvi->coarsen; 2104c661befSBarry Smith dmsnesvi->dm->ops->createglobalvector = dmsnesvi->createglobalvector; 2114c661befSBarry Smith 212d0af7cd3SBarry Smith ierr = VecDestroy(&dmsnesvi->upper);CHKERRQ(ierr); 213d0af7cd3SBarry Smith ierr = VecDestroy(&dmsnesvi->lower);CHKERRQ(ierr); 214d0af7cd3SBarry Smith ierr = VecDestroy(&dmsnesvi->values);CHKERRQ(ierr); 215d0af7cd3SBarry Smith ierr = VecDestroy(&dmsnesvi->F);CHKERRQ(ierr); 216d0af7cd3SBarry Smith ierr = ISDestroy(&dmsnesvi->inactive);CHKERRQ(ierr); 217d0af7cd3SBarry Smith ierr = PetscFree(dmsnesvi);CHKERRQ(ierr); 218d0af7cd3SBarry Smith PetscFunctionReturn(0); 219d0af7cd3SBarry Smith } 220d0af7cd3SBarry Smith 221d0af7cd3SBarry Smith #undef __FUNCT__ 222d0af7cd3SBarry Smith #define __FUNCT__ "DMSetVI" 223d0af7cd3SBarry Smith /* 224d0af7cd3SBarry Smith DMSetVI - Marks a DM as associated with a VI problem. This causes the interpolation/restriction operators to 225d0af7cd3SBarry Smith be restricted to only those variables NOT associated with active constraints. 226d0af7cd3SBarry Smith 227d0af7cd3SBarry Smith */ 228d0af7cd3SBarry Smith PetscErrorCode DMSetVI(DM dm,Vec upper,Vec lower,Vec values,Vec F,IS inactive) 229d0af7cd3SBarry Smith { 230d0af7cd3SBarry Smith PetscErrorCode ierr; 231d0af7cd3SBarry Smith PetscContainer isnes; 2323c0c59f3SBarry Smith DM_SNESVI *dmsnesvi; 233*1c0a9e84SBarry Smith PetscInt Ni,Nu; 234d0af7cd3SBarry Smith 235d0af7cd3SBarry Smith PetscFunctionBegin; 2364dcab191SBarry Smith if (!dm) PetscFunctionReturn(0); 237*1c0a9e84SBarry Smith ierr = ISGetSize(inactive,&Ni);CHKERRQ(ierr); 238*1c0a9e84SBarry Smith ierr = VecGetSize(upper,&Nu);CHKERRQ(ierr); 239*1c0a9e84SBarry Smith if (Ni == Nu) PetscFunctionReturn(0); 240*1c0a9e84SBarry Smith 241d0af7cd3SBarry Smith ierr = PetscObjectReference((PetscObject)upper);CHKERRQ(ierr); 242d0af7cd3SBarry Smith ierr = PetscObjectReference((PetscObject)lower);CHKERRQ(ierr); 243d0af7cd3SBarry Smith ierr = PetscObjectReference((PetscObject)values);CHKERRQ(ierr); 244d0af7cd3SBarry Smith ierr = PetscObjectReference((PetscObject)F);CHKERRQ(ierr); 245d0af7cd3SBarry Smith ierr = PetscObjectReference((PetscObject)inactive);CHKERRQ(ierr); 246d0af7cd3SBarry Smith 247d0af7cd3SBarry Smith ierr = PetscObjectQuery((PetscObject)dm,"VI",(PetscObject *)&isnes);CHKERRQ(ierr); 248d0af7cd3SBarry Smith if (!isnes) { 249d0af7cd3SBarry Smith ierr = PetscContainerCreate(((PetscObject)dm)->comm,&isnes);CHKERRQ(ierr); 2503c0c59f3SBarry Smith ierr = PetscContainerSetUserDestroy(isnes,(PetscErrorCode (*)(void*))DMDestroy_SNESVI);CHKERRQ(ierr); 2513c0c59f3SBarry Smith ierr = PetscNew(DM_SNESVI,&dmsnesvi);CHKERRQ(ierr); 252d0af7cd3SBarry Smith ierr = PetscContainerSetPointer(isnes,(void*)dmsnesvi);CHKERRQ(ierr); 253d0af7cd3SBarry Smith ierr = PetscObjectCompose((PetscObject)dm,"VI",(PetscObject)isnes);CHKERRQ(ierr); 2543c0c59f3SBarry Smith ierr = PetscContainerDestroy(&isnes);CHKERRQ(ierr); 255d0af7cd3SBarry Smith dmsnesvi->getinterpolation = dm->ops->getinterpolation; 256d0af7cd3SBarry Smith dm->ops->getinterpolation = DMGetInterpolation_SNESVI; 257d0af7cd3SBarry Smith dmsnesvi->coarsen = dm->ops->coarsen; 258d0af7cd3SBarry Smith dm->ops->coarsen = DMCoarsen_SNESVI; 259298cc208SBarry Smith dmsnesvi->createglobalvector = dm->ops->createglobalvector; 2604dcab191SBarry Smith dm->ops->createglobalvector = DMCreateGlobalVector_SNESVI; 2616ba4bc90SBarry Smith /* since these vectors may reference the DM, need to remove circle referencing */ 2626ba4bc90SBarry Smith ierr = PetscObjectRemoveReference((PetscObject)upper,"DM");CHKERRQ(ierr); 2636ba4bc90SBarry Smith ierr = PetscObjectRemoveReference((PetscObject)lower,"DM");CHKERRQ(ierr); 2646ba4bc90SBarry Smith ierr = PetscObjectRemoveReference((PetscObject)values,"DM");CHKERRQ(ierr); 2656ba4bc90SBarry Smith ierr = PetscObjectRemoveReference((PetscObject)F,"DM");CHKERRQ(ierr); 266d0af7cd3SBarry Smith } else { 267d0af7cd3SBarry Smith ierr = PetscContainerGetPointer(isnes,(void**)&dmsnesvi);CHKERRQ(ierr); 268d0af7cd3SBarry Smith ierr = VecDestroy(&dmsnesvi->upper);CHKERRQ(ierr); 269d0af7cd3SBarry Smith ierr = VecDestroy(&dmsnesvi->lower);CHKERRQ(ierr); 270d0af7cd3SBarry Smith ierr = VecDestroy(&dmsnesvi->values);CHKERRQ(ierr); 271d0af7cd3SBarry Smith ierr = VecDestroy(&dmsnesvi->F);CHKERRQ(ierr); 272d0af7cd3SBarry Smith ierr = ISDestroy(&dmsnesvi->inactive);CHKERRQ(ierr); 273d0af7cd3SBarry Smith } 2744dcab191SBarry Smith ierr = DMClearGlobalVectors(dm);CHKERRQ(ierr); 2754dcab191SBarry Smith ierr = ISGetLocalSize(inactive,&dmsnesvi->n);CHKERRQ(ierr); 276d0af7cd3SBarry Smith dmsnesvi->upper = upper; 277d0af7cd3SBarry Smith dmsnesvi->lower = lower; 278d0af7cd3SBarry Smith dmsnesvi->values = values; 279d0af7cd3SBarry Smith dmsnesvi->F = F; 280d0af7cd3SBarry Smith dmsnesvi->inactive = inactive; 2811a223a97SBarry Smith dmsnesvi->dm = dm; 282d0af7cd3SBarry Smith PetscFunctionReturn(0); 283d0af7cd3SBarry Smith } 284d0af7cd3SBarry Smith 2854c661befSBarry Smith #undef __FUNCT__ 2864c661befSBarry Smith #define __FUNCT__ "DMDestroyVI" 2874c661befSBarry Smith /* 2884c661befSBarry Smith DMDestroyVI - Frees the DM_SNESVI object contained in the DM 2894c661befSBarry Smith - also resets the function pointers in the DM for getinterpolation() etc to use the original DM 2904c661befSBarry Smith */ 2914c661befSBarry Smith PetscErrorCode DMDestroyVI(DM dm) 2924c661befSBarry Smith { 2934c661befSBarry Smith PetscErrorCode ierr; 2944c661befSBarry Smith 2954c661befSBarry Smith PetscFunctionBegin; 2964c661befSBarry Smith if (!dm) PetscFunctionReturn(0); 2974c661befSBarry Smith ierr = PetscObjectCompose((PetscObject)dm,"VI",(PetscObject)PETSC_NULL);CHKERRQ(ierr); 2984c661befSBarry Smith PetscFunctionReturn(0); 2994c661befSBarry Smith } 3004c661befSBarry Smith 3013c0c59f3SBarry Smith /* --------------------------------------------------------------------------------------------------------*/ 3022b4ed282SShri Abhyankar 3039308c137SBarry Smith #undef __FUNCT__ 3049308c137SBarry Smith #define __FUNCT__ "SNESMonitorVI" 3057087cfbeSBarry Smith PetscErrorCode SNESMonitorVI(SNES snes,PetscInt its,PetscReal fgnorm,void *dummy) 3069308c137SBarry Smith { 3079308c137SBarry Smith PetscErrorCode ierr; 3089308c137SBarry Smith SNES_VI *vi = (SNES_VI*)snes->data; 3099308c137SBarry Smith PetscViewerASCIIMonitor viewer = (PetscViewerASCIIMonitor) dummy; 3109308c137SBarry Smith const PetscScalar *x,*xl,*xu,*f; 31109573ac7SBarry Smith PetscInt i,n,act = 0; 3129308c137SBarry Smith PetscReal rnorm,fnorm; 3139308c137SBarry Smith 3149308c137SBarry Smith PetscFunctionBegin; 3159308c137SBarry Smith if (!dummy) { 3169308c137SBarry Smith ierr = PetscViewerASCIIMonitorCreate(((PetscObject)snes)->comm,"stdout",0,&viewer);CHKERRQ(ierr); 3179308c137SBarry Smith } 3189308c137SBarry Smith ierr = VecGetLocalSize(snes->vec_sol,&n);CHKERRQ(ierr); 3199308c137SBarry Smith ierr = VecGetArrayRead(vi->xl,&xl);CHKERRQ(ierr); 3209308c137SBarry Smith ierr = VecGetArrayRead(vi->xu,&xu);CHKERRQ(ierr); 3219308c137SBarry Smith ierr = VecGetArrayRead(snes->vec_sol,&x);CHKERRQ(ierr); 3223f731af5SBarry Smith ierr = VecGetArrayRead(snes->vec_func,&f);CHKERRQ(ierr); 3239308c137SBarry Smith 3249308c137SBarry Smith rnorm = 0.0; 3259308c137SBarry Smith for (i=0; i<n; i++) { 32610f5ae6bSBarry 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]); 32709573ac7SBarry Smith else act++; 3289308c137SBarry Smith } 3293f731af5SBarry Smith ierr = VecRestoreArrayRead(snes->vec_func,&f);CHKERRQ(ierr); 3309308c137SBarry Smith ierr = VecRestoreArrayRead(vi->xl,&xl);CHKERRQ(ierr); 3319308c137SBarry Smith ierr = VecRestoreArrayRead(vi->xu,&xu);CHKERRQ(ierr); 3329308c137SBarry Smith ierr = VecRestoreArrayRead(snes->vec_sol,&x);CHKERRQ(ierr); 333d9822059SBarry Smith ierr = MPI_Allreduce(&rnorm,&fnorm,1,MPIU_REAL,MPIU_SUM,((PetscObject)snes)->comm);CHKERRQ(ierr); 3349308c137SBarry Smith fnorm = sqrt(fnorm); 33509573ac7SBarry Smith ierr = PetscViewerASCIIMonitorPrintf(viewer,"%3D SNES VI Function norm %14.12e Active constraints %D\n",its,fnorm,act);CHKERRQ(ierr); 3369308c137SBarry Smith if (!dummy) { 3376bf464f9SBarry Smith ierr = PetscViewerASCIIMonitorDestroy(&viewer);CHKERRQ(ierr); 3389308c137SBarry Smith } 3399308c137SBarry Smith PetscFunctionReturn(0); 3409308c137SBarry Smith } 3419308c137SBarry Smith 3422b4ed282SShri Abhyankar /* 3432b4ed282SShri Abhyankar Checks if J^T F = 0 which implies we've found a local minimum of the norm of the function, 3442b4ed282SShri 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 3452b4ed282SShri Abhyankar 0 = (J^T F)^T W = F^T J W iff W not in the null space of J. Thanks for Jorge More 3462b4ed282SShri Abhyankar for this trick. One assumes that the probability that W is in the null space of J is very, very small. 3472b4ed282SShri Abhyankar */ 3482b4ed282SShri Abhyankar #undef __FUNCT__ 3492b4ed282SShri Abhyankar #define __FUNCT__ "SNESVICheckLocalMin_Private" 350ace3abfcSBarry Smith PetscErrorCode SNESVICheckLocalMin_Private(SNES snes,Mat A,Vec F,Vec W,PetscReal fnorm,PetscBool *ismin) 3512b4ed282SShri Abhyankar { 3522b4ed282SShri Abhyankar PetscReal a1; 3532b4ed282SShri Abhyankar PetscErrorCode ierr; 354ace3abfcSBarry Smith PetscBool hastranspose; 3552b4ed282SShri Abhyankar 3562b4ed282SShri Abhyankar PetscFunctionBegin; 3572b4ed282SShri Abhyankar *ismin = PETSC_FALSE; 3582b4ed282SShri Abhyankar ierr = MatHasOperation(A,MATOP_MULT_TRANSPOSE,&hastranspose);CHKERRQ(ierr); 3592b4ed282SShri Abhyankar if (hastranspose) { 3602b4ed282SShri Abhyankar /* Compute || J^T F|| */ 3612b4ed282SShri Abhyankar ierr = MatMultTranspose(A,F,W);CHKERRQ(ierr); 3622b4ed282SShri Abhyankar ierr = VecNorm(W,NORM_2,&a1);CHKERRQ(ierr); 3632b4ed282SShri Abhyankar ierr = PetscInfo1(snes,"|| J^T F|| %G near zero implies found a local minimum\n",a1/fnorm);CHKERRQ(ierr); 3642b4ed282SShri Abhyankar if (a1/fnorm < 1.e-4) *ismin = PETSC_TRUE; 3652b4ed282SShri Abhyankar } else { 3662b4ed282SShri Abhyankar Vec work; 3672b4ed282SShri Abhyankar PetscScalar result; 3682b4ed282SShri Abhyankar PetscReal wnorm; 3692b4ed282SShri Abhyankar 3702b4ed282SShri Abhyankar ierr = VecSetRandom(W,PETSC_NULL);CHKERRQ(ierr); 3712b4ed282SShri Abhyankar ierr = VecNorm(W,NORM_2,&wnorm);CHKERRQ(ierr); 3722b4ed282SShri Abhyankar ierr = VecDuplicate(W,&work);CHKERRQ(ierr); 3732b4ed282SShri Abhyankar ierr = MatMult(A,W,work);CHKERRQ(ierr); 3742b4ed282SShri Abhyankar ierr = VecDot(F,work,&result);CHKERRQ(ierr); 3756bf464f9SBarry Smith ierr = VecDestroy(&work);CHKERRQ(ierr); 3762b4ed282SShri Abhyankar a1 = PetscAbsScalar(result)/(fnorm*wnorm); 3772b4ed282SShri Abhyankar ierr = PetscInfo1(snes,"(F^T J random)/(|| F ||*||random|| %G near zero implies found a local minimum\n",a1);CHKERRQ(ierr); 3782b4ed282SShri Abhyankar if (a1 < 1.e-4) *ismin = PETSC_TRUE; 3792b4ed282SShri Abhyankar } 3802b4ed282SShri Abhyankar PetscFunctionReturn(0); 3812b4ed282SShri Abhyankar } 3822b4ed282SShri Abhyankar 3832b4ed282SShri Abhyankar /* 3842b4ed282SShri Abhyankar Checks if J^T(F - J*X) = 0 3852b4ed282SShri Abhyankar */ 3862b4ed282SShri Abhyankar #undef __FUNCT__ 3872b4ed282SShri Abhyankar #define __FUNCT__ "SNESVICheckResidual_Private" 3882b4ed282SShri Abhyankar PetscErrorCode SNESVICheckResidual_Private(SNES snes,Mat A,Vec F,Vec X,Vec W1,Vec W2) 3892b4ed282SShri Abhyankar { 3902b4ed282SShri Abhyankar PetscReal a1,a2; 3912b4ed282SShri Abhyankar PetscErrorCode ierr; 392ace3abfcSBarry Smith PetscBool hastranspose; 3932b4ed282SShri Abhyankar 3942b4ed282SShri Abhyankar PetscFunctionBegin; 3952b4ed282SShri Abhyankar ierr = MatHasOperation(A,MATOP_MULT_TRANSPOSE,&hastranspose);CHKERRQ(ierr); 3962b4ed282SShri Abhyankar if (hastranspose) { 3972b4ed282SShri Abhyankar ierr = MatMult(A,X,W1);CHKERRQ(ierr); 3982b4ed282SShri Abhyankar ierr = VecAXPY(W1,-1.0,F);CHKERRQ(ierr); 3992b4ed282SShri Abhyankar 4002b4ed282SShri Abhyankar /* Compute || J^T W|| */ 4012b4ed282SShri Abhyankar ierr = MatMultTranspose(A,W1,W2);CHKERRQ(ierr); 4022b4ed282SShri Abhyankar ierr = VecNorm(W1,NORM_2,&a1);CHKERRQ(ierr); 4032b4ed282SShri Abhyankar ierr = VecNorm(W2,NORM_2,&a2);CHKERRQ(ierr); 4042b4ed282SShri Abhyankar if (a1 != 0.0) { 4052b4ed282SShri Abhyankar ierr = PetscInfo1(snes,"||J^T(F-Ax)||/||F-AX|| %G near zero implies inconsistent rhs\n",a2/a1);CHKERRQ(ierr); 4062b4ed282SShri Abhyankar } 4072b4ed282SShri Abhyankar } 4082b4ed282SShri Abhyankar PetscFunctionReturn(0); 4092b4ed282SShri Abhyankar } 4102b4ed282SShri Abhyankar 4112b4ed282SShri Abhyankar /* 4122b4ed282SShri Abhyankar SNESDefaultConverged_VI - Checks the convergence of the semismooth newton algorithm. 4132b4ed282SShri Abhyankar 4142b4ed282SShri Abhyankar Notes: 4152b4ed282SShri Abhyankar The convergence criterion currently implemented is 4162b4ed282SShri Abhyankar merit < abstol 4172b4ed282SShri Abhyankar merit < rtol*merit_initial 4182b4ed282SShri Abhyankar */ 4192b4ed282SShri Abhyankar #undef __FUNCT__ 4202b4ed282SShri Abhyankar #define __FUNCT__ "SNESDefaultConverged_VI" 4217fe79bc4SShri Abhyankar PetscErrorCode SNESDefaultConverged_VI(SNES snes,PetscInt it,PetscReal xnorm,PetscReal gradnorm,PetscReal fnorm,SNESConvergedReason *reason,void *dummy) 4222b4ed282SShri Abhyankar { 4232b4ed282SShri Abhyankar PetscErrorCode ierr; 4242b4ed282SShri Abhyankar 4252b4ed282SShri Abhyankar PetscFunctionBegin; 4262b4ed282SShri Abhyankar PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 4272b4ed282SShri Abhyankar PetscValidPointer(reason,6); 4282b4ed282SShri Abhyankar 4292b4ed282SShri Abhyankar *reason = SNES_CONVERGED_ITERATING; 4302b4ed282SShri Abhyankar 4312b4ed282SShri Abhyankar if (!it) { 4322b4ed282SShri Abhyankar /* set parameter for default relative tolerance convergence test */ 4337fe79bc4SShri Abhyankar snes->ttol = fnorm*snes->rtol; 4342b4ed282SShri Abhyankar } 4357fe79bc4SShri Abhyankar if (fnorm != fnorm) { 4362b4ed282SShri Abhyankar ierr = PetscInfo(snes,"Failed to converged, function norm is NaN\n");CHKERRQ(ierr); 4372b4ed282SShri Abhyankar *reason = SNES_DIVERGED_FNORM_NAN; 4387fe79bc4SShri Abhyankar } else if (fnorm < snes->abstol) { 4397fe79bc4SShri Abhyankar ierr = PetscInfo2(snes,"Converged due to function norm %G < %G\n",fnorm,snes->abstol);CHKERRQ(ierr); 4402b4ed282SShri Abhyankar *reason = SNES_CONVERGED_FNORM_ABS; 4412b4ed282SShri Abhyankar } else if (snes->nfuncs >= snes->max_funcs) { 4422b4ed282SShri Abhyankar ierr = PetscInfo2(snes,"Exceeded maximum number of function evaluations: %D > %D\n",snes->nfuncs,snes->max_funcs);CHKERRQ(ierr); 4432b4ed282SShri Abhyankar *reason = SNES_DIVERGED_FUNCTION_COUNT; 4442b4ed282SShri Abhyankar } 4452b4ed282SShri Abhyankar 4462b4ed282SShri Abhyankar if (it && !*reason) { 4477fe79bc4SShri Abhyankar if (fnorm < snes->ttol) { 4487fe79bc4SShri Abhyankar ierr = PetscInfo2(snes,"Converged due to function norm %G < %G (relative tolerance)\n",fnorm,snes->ttol);CHKERRQ(ierr); 4492b4ed282SShri Abhyankar *reason = SNES_CONVERGED_FNORM_RELATIVE; 4502b4ed282SShri Abhyankar } 4512b4ed282SShri Abhyankar } 4522b4ed282SShri Abhyankar PetscFunctionReturn(0); 4532b4ed282SShri Abhyankar } 4542b4ed282SShri Abhyankar 4552b4ed282SShri Abhyankar /* 4562b4ed282SShri Abhyankar SNESVIComputeMeritFunction - Evaluates the merit function for the mixed complementarity problem. 4572b4ed282SShri Abhyankar 4582b4ed282SShri Abhyankar Input Parameter: 4592b4ed282SShri Abhyankar . phi - the semismooth function 4602b4ed282SShri Abhyankar 4612b4ed282SShri Abhyankar Output Parameter: 4622b4ed282SShri Abhyankar . merit - the merit function 4632b4ed282SShri Abhyankar . phinorm - ||phi|| 4642b4ed282SShri Abhyankar 4652b4ed282SShri Abhyankar Notes: 4662b4ed282SShri Abhyankar The merit function for the mixed complementarity problem is defined as 4672b4ed282SShri Abhyankar merit = 0.5*phi^T*phi 4682b4ed282SShri Abhyankar */ 4692b4ed282SShri Abhyankar #undef __FUNCT__ 4702b4ed282SShri Abhyankar #define __FUNCT__ "SNESVIComputeMeritFunction" 4712b4ed282SShri Abhyankar static PetscErrorCode SNESVIComputeMeritFunction(Vec phi, PetscReal* merit,PetscReal* phinorm) 4722b4ed282SShri Abhyankar { 4732b4ed282SShri Abhyankar PetscErrorCode ierr; 4742b4ed282SShri Abhyankar 4752b4ed282SShri Abhyankar PetscFunctionBegin; 4765f48b12bSBarry Smith ierr = VecNormBegin(phi,NORM_2,phinorm);CHKERRQ(ierr); 4775f48b12bSBarry Smith ierr = VecNormEnd(phi,NORM_2,phinorm);CHKERRQ(ierr); 4782b4ed282SShri Abhyankar 4792b4ed282SShri Abhyankar *merit = 0.5*(*phinorm)*(*phinorm); 4802b4ed282SShri Abhyankar PetscFunctionReturn(0); 4812b4ed282SShri Abhyankar } 4822b4ed282SShri Abhyankar 4837f6f51e9SSatish Balay PETSC_STATIC_INLINE PetscScalar Phi(PetscScalar a,PetscScalar b) 4844c21c6cdSBarry Smith { 4854c21c6cdSBarry Smith return a + b - sqrt(a*a + b*b); 4864c21c6cdSBarry Smith } 4874c21c6cdSBarry Smith 4887f6f51e9SSatish Balay PETSC_STATIC_INLINE PetscScalar DPhi(PetscScalar a,PetscScalar b) 4894c21c6cdSBarry Smith { 4905559b345SBarry Smith if ((PetscAbsScalar(a) >= 1.e-6) || (PetscAbsScalar(b) >= 1.e-6)) return 1.0 - a/ sqrt(a*a + b*b); 4915559b345SBarry Smith else return .5; 4924c21c6cdSBarry Smith } 4934c21c6cdSBarry Smith 4942b4ed282SShri Abhyankar /* 4951f79c099SShri Abhyankar SNESVIComputeFunction - Reformulates a system of nonlinear equations in mixed complementarity form to a system of nonlinear equations in semismooth form. 4962b4ed282SShri Abhyankar 4972b4ed282SShri Abhyankar Input Parameters: 4982b4ed282SShri Abhyankar . snes - the SNES context 4992b4ed282SShri Abhyankar . x - current iterate 5002b4ed282SShri Abhyankar . functx - user defined function context 5012b4ed282SShri Abhyankar 5022b4ed282SShri Abhyankar Output Parameters: 5032b4ed282SShri Abhyankar . phi - Semismooth function 5042b4ed282SShri Abhyankar 5052b4ed282SShri Abhyankar */ 5062b4ed282SShri Abhyankar #undef __FUNCT__ 5071f79c099SShri Abhyankar #define __FUNCT__ "SNESVIComputeFunction" 5081f79c099SShri Abhyankar static PetscErrorCode SNESVIComputeFunction(SNES snes,Vec X,Vec phi,void* functx) 5092b4ed282SShri Abhyankar { 5102b4ed282SShri Abhyankar PetscErrorCode ierr; 5112b4ed282SShri Abhyankar SNES_VI *vi = (SNES_VI*)snes->data; 5122b4ed282SShri Abhyankar Vec Xl = vi->xl,Xu = vi->xu,F = snes->vec_func; 5134c21c6cdSBarry Smith PetscScalar *phi_arr,*x_arr,*f_arr,*l,*u; 5142b4ed282SShri Abhyankar PetscInt i,nlocal; 5152b4ed282SShri Abhyankar 5162b4ed282SShri Abhyankar PetscFunctionBegin; 5172b4ed282SShri Abhyankar ierr = (*vi->computeuserfunction)(snes,X,F,functx);CHKERRQ(ierr); 5182b4ed282SShri Abhyankar ierr = VecGetLocalSize(X,&nlocal);CHKERRQ(ierr); 5192b4ed282SShri Abhyankar ierr = VecGetArray(X,&x_arr);CHKERRQ(ierr); 5202b4ed282SShri Abhyankar ierr = VecGetArray(F,&f_arr);CHKERRQ(ierr); 5212b4ed282SShri Abhyankar ierr = VecGetArray(Xl,&l);CHKERRQ(ierr); 5222b4ed282SShri Abhyankar ierr = VecGetArray(Xu,&u);CHKERRQ(ierr); 5232b4ed282SShri Abhyankar ierr = VecGetArray(phi,&phi_arr);CHKERRQ(ierr); 5242b4ed282SShri Abhyankar 5252b4ed282SShri Abhyankar for (i=0;i < nlocal;i++) { 52610f5ae6bSBarry Smith if ((PetscRealPart(l[i]) <= SNES_VI_NINF) && (PetscRealPart(u[i]) >= SNES_VI_INF)) { /* no constraints on variable */ 5274c21c6cdSBarry Smith phi_arr[i] = f_arr[i]; 52810f5ae6bSBarry Smith } else if (PetscRealPart(l[i]) <= SNES_VI_NINF) { /* upper bound on variable only */ 5294c21c6cdSBarry Smith phi_arr[i] = -Phi(u[i] - x_arr[i],-f_arr[i]); 53010f5ae6bSBarry Smith } else if (PetscRealPart(u[i]) >= SNES_VI_INF) { /* lower bound on variable only */ 5314c21c6cdSBarry Smith phi_arr[i] = Phi(x_arr[i] - l[i],f_arr[i]); 5325559b345SBarry Smith } else if (l[i] == u[i]) { 5332b4ed282SShri Abhyankar phi_arr[i] = l[i] - x_arr[i]; 5345559b345SBarry Smith } else { /* both bounds on variable */ 5354c21c6cdSBarry Smith phi_arr[i] = Phi(x_arr[i] - l[i],-Phi(u[i] - x_arr[i],-f_arr[i])); 5362b4ed282SShri Abhyankar } 5372b4ed282SShri Abhyankar } 5382b4ed282SShri Abhyankar 5392b4ed282SShri Abhyankar ierr = VecRestoreArray(X,&x_arr);CHKERRQ(ierr); 5402b4ed282SShri Abhyankar ierr = VecRestoreArray(F,&f_arr);CHKERRQ(ierr); 5412b4ed282SShri Abhyankar ierr = VecRestoreArray(Xl,&l);CHKERRQ(ierr); 5422b4ed282SShri Abhyankar ierr = VecRestoreArray(Xu,&u);CHKERRQ(ierr); 5432b4ed282SShri Abhyankar ierr = VecRestoreArray(phi,&phi_arr);CHKERRQ(ierr); 5442b4ed282SShri Abhyankar PetscFunctionReturn(0); 5452b4ed282SShri Abhyankar } 5462b4ed282SShri Abhyankar 5472b4ed282SShri Abhyankar /* 548a79edbefSShri Abhyankar SNESVIComputeBsubdifferentialVectors - Computes the diagonal shift (Da) and row scaling (Db) vectors needed for the 549a79edbefSShri Abhyankar the semismooth jacobian. 5502b4ed282SShri Abhyankar */ 5512b4ed282SShri Abhyankar #undef __FUNCT__ 552a79edbefSShri Abhyankar #define __FUNCT__ "SNESVIComputeBsubdifferentialVectors" 553a79edbefSShri Abhyankar PetscErrorCode SNESVIComputeBsubdifferentialVectors(SNES snes,Vec X,Vec F,Mat jac,Vec Da,Vec Db) 5542b4ed282SShri Abhyankar { 5552b4ed282SShri Abhyankar PetscErrorCode ierr; 5562b4ed282SShri Abhyankar SNES_VI *vi = (SNES_VI*)snes->data; 5574c21c6cdSBarry Smith PetscScalar *l,*u,*x,*f,*da,*db,da1,da2,db1,db2; 5582b4ed282SShri Abhyankar PetscInt i,nlocal; 5592b4ed282SShri Abhyankar 5602b4ed282SShri Abhyankar PetscFunctionBegin; 5612b4ed282SShri Abhyankar 5622b4ed282SShri Abhyankar ierr = VecGetArray(X,&x);CHKERRQ(ierr); 5632b4ed282SShri Abhyankar ierr = VecGetArray(F,&f);CHKERRQ(ierr); 5642b4ed282SShri Abhyankar ierr = VecGetArray(vi->xl,&l);CHKERRQ(ierr); 5652b4ed282SShri Abhyankar ierr = VecGetArray(vi->xu,&u);CHKERRQ(ierr); 566a79edbefSShri Abhyankar ierr = VecGetArray(Da,&da);CHKERRQ(ierr); 567a79edbefSShri Abhyankar ierr = VecGetArray(Db,&db);CHKERRQ(ierr); 5682b4ed282SShri Abhyankar ierr = VecGetLocalSize(X,&nlocal);CHKERRQ(ierr); 5694c21c6cdSBarry Smith 5702b4ed282SShri Abhyankar for (i=0;i< nlocal;i++) { 57110f5ae6bSBarry Smith if ((PetscRealPart(l[i]) <= SNES_VI_NINF) && (PetscRealPart(u[i]) >= SNES_VI_INF)) {/* no constraints on variable */ 5724c21c6cdSBarry Smith da[i] = 0; 5732b4ed282SShri Abhyankar db[i] = 1; 57410f5ae6bSBarry Smith } else if (PetscRealPart(l[i]) <= SNES_VI_NINF) { /* upper bound on variable only */ 5754c21c6cdSBarry Smith da[i] = DPhi(u[i] - x[i], -f[i]); 5764c21c6cdSBarry Smith db[i] = DPhi(-f[i],u[i] - x[i]); 57710f5ae6bSBarry Smith } else if (PetscRealPart(u[i]) >= SNES_VI_INF) { /* lower bound on variable only */ 5785559b345SBarry Smith da[i] = DPhi(x[i] - l[i], f[i]); 5795559b345SBarry Smith db[i] = DPhi(f[i],x[i] - l[i]); 5805559b345SBarry Smith } else if (l[i] == u[i]) { /* fixed variable */ 5814c21c6cdSBarry Smith da[i] = 1; 5822b4ed282SShri Abhyankar db[i] = 0; 5835559b345SBarry Smith } else { /* upper and lower bounds on variable */ 5844c21c6cdSBarry Smith da1 = DPhi(x[i] - l[i], -Phi(u[i] - x[i], -f[i])); 5854c21c6cdSBarry Smith db1 = DPhi(-Phi(u[i] - x[i], -f[i]),x[i] - l[i]); 5864c21c6cdSBarry Smith da2 = DPhi(u[i] - x[i], -f[i]); 5874c21c6cdSBarry Smith db2 = DPhi(-f[i],u[i] - x[i]); 5884c21c6cdSBarry Smith da[i] = da1 + db1*da2; 5894c21c6cdSBarry Smith db[i] = db1*db2; 5902b4ed282SShri Abhyankar } 5912b4ed282SShri Abhyankar } 5925559b345SBarry Smith 5932b4ed282SShri Abhyankar ierr = VecRestoreArray(X,&x);CHKERRQ(ierr); 5942b4ed282SShri Abhyankar ierr = VecRestoreArray(F,&f);CHKERRQ(ierr); 5952b4ed282SShri Abhyankar ierr = VecRestoreArray(vi->xl,&l);CHKERRQ(ierr); 5962b4ed282SShri Abhyankar ierr = VecRestoreArray(vi->xu,&u);CHKERRQ(ierr); 597a79edbefSShri Abhyankar ierr = VecRestoreArray(Da,&da);CHKERRQ(ierr); 598a79edbefSShri Abhyankar ierr = VecRestoreArray(Db,&db);CHKERRQ(ierr); 599a79edbefSShri Abhyankar PetscFunctionReturn(0); 600a79edbefSShri Abhyankar } 601a79edbefSShri Abhyankar 602a79edbefSShri Abhyankar /* 603a79edbefSShri 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. 604a79edbefSShri Abhyankar 605a79edbefSShri Abhyankar Input Parameters: 606a79edbefSShri Abhyankar . Da - Diagonal shift vector for the semismooth jacobian. 607a79edbefSShri Abhyankar . Db - Row scaling vector for the semismooth jacobian. 608a79edbefSShri Abhyankar 609a79edbefSShri Abhyankar Output Parameters: 610a79edbefSShri Abhyankar . jac - semismooth jacobian 611a79edbefSShri Abhyankar . jac_pre - optional preconditioning matrix 612a79edbefSShri Abhyankar 613a79edbefSShri Abhyankar Notes: 614a79edbefSShri Abhyankar The semismooth jacobian matrix is given by 615a79edbefSShri Abhyankar jac = Da + Db*jacfun 616a79edbefSShri Abhyankar where Db is the row scaling matrix stored as a vector, 617a79edbefSShri Abhyankar Da is the diagonal perturbation matrix stored as a vector 618a79edbefSShri Abhyankar and jacfun is the jacobian of the original nonlinear function. 619a79edbefSShri Abhyankar */ 620a79edbefSShri Abhyankar #undef __FUNCT__ 621a79edbefSShri Abhyankar #define __FUNCT__ "SNESVIComputeJacobian" 622a79edbefSShri Abhyankar PetscErrorCode SNESVIComputeJacobian(Mat jac, Mat jac_pre,Vec Da, Vec Db) 623a79edbefSShri Abhyankar { 624a79edbefSShri Abhyankar PetscErrorCode ierr; 625a79edbefSShri Abhyankar 6262b4ed282SShri Abhyankar /* Do row scaling and add diagonal perturbation */ 627a79edbefSShri Abhyankar ierr = MatDiagonalScale(jac,Db,PETSC_NULL);CHKERRQ(ierr); 628a79edbefSShri Abhyankar ierr = MatDiagonalSet(jac,Da,ADD_VALUES);CHKERRQ(ierr); 629a79edbefSShri Abhyankar if (jac != jac_pre) { /* If jac and jac_pre are different */ 630a79edbefSShri Abhyankar ierr = MatDiagonalScale(jac_pre,Db,PETSC_NULL); 631a79edbefSShri Abhyankar ierr = MatDiagonalSet(jac_pre,Da,ADD_VALUES);CHKERRQ(ierr); 6322b4ed282SShri Abhyankar } 6332b4ed282SShri Abhyankar PetscFunctionReturn(0); 6342b4ed282SShri Abhyankar } 6352b4ed282SShri Abhyankar 6362b4ed282SShri Abhyankar /* 637ee657d29SShri Abhyankar SNESVIComputeMeritFunctionGradient - Computes the gradient of the merit function psi. 638ee657d29SShri Abhyankar 639ee657d29SShri Abhyankar Input Parameters: 640ee657d29SShri Abhyankar phi - semismooth function. 641ee657d29SShri Abhyankar H - semismooth jacobian 642ee657d29SShri Abhyankar 643ee657d29SShri Abhyankar Output Parameters: 644ee657d29SShri Abhyankar dpsi - merit function gradient 645ee657d29SShri Abhyankar 646ee657d29SShri Abhyankar Notes: 647ee657d29SShri Abhyankar The merit function gradient is computed as follows 648ee657d29SShri Abhyankar dpsi = H^T*phi 649ee657d29SShri Abhyankar */ 650ee657d29SShri Abhyankar #undef __FUNCT__ 651ee657d29SShri Abhyankar #define __FUNCT__ "SNESVIComputeMeritFunctionGradient" 652ee657d29SShri Abhyankar PetscErrorCode SNESVIComputeMeritFunctionGradient(Mat H, Vec phi, Vec dpsi) 653ee657d29SShri Abhyankar { 654ee657d29SShri Abhyankar PetscErrorCode ierr; 655ee657d29SShri Abhyankar 656ee657d29SShri Abhyankar PetscFunctionBegin; 6575f48b12bSBarry Smith ierr = MatMultTranspose(H,phi,dpsi);CHKERRQ(ierr); 658ee657d29SShri Abhyankar PetscFunctionReturn(0); 659ee657d29SShri Abhyankar } 660ee657d29SShri Abhyankar 661c1a5e521SShri Abhyankar /* -------------------------------------------------------------------------- */ 662c1a5e521SShri Abhyankar /* 663c1a5e521SShri Abhyankar SNESVIProjectOntoBounds - Projects X onto the feasible region so that Xl[i] <= X[i] <= Xu[i] for i = 1...n. 664c1a5e521SShri Abhyankar 665c1a5e521SShri Abhyankar Input Parameters: 666c1a5e521SShri Abhyankar . SNES - nonlinear solver context 667c1a5e521SShri Abhyankar 668c1a5e521SShri Abhyankar Output Parameters: 669c1a5e521SShri Abhyankar . X - Bound projected X 670c1a5e521SShri Abhyankar 671c1a5e521SShri Abhyankar */ 672c1a5e521SShri Abhyankar 673c1a5e521SShri Abhyankar #undef __FUNCT__ 674c1a5e521SShri Abhyankar #define __FUNCT__ "SNESVIProjectOntoBounds" 675c1a5e521SShri Abhyankar PetscErrorCode SNESVIProjectOntoBounds(SNES snes,Vec X) 676c1a5e521SShri Abhyankar { 677c1a5e521SShri Abhyankar PetscErrorCode ierr; 678c1a5e521SShri Abhyankar SNES_VI *vi = (SNES_VI*)snes->data; 679c1a5e521SShri Abhyankar const PetscScalar *xl,*xu; 680c1a5e521SShri Abhyankar PetscScalar *x; 681c1a5e521SShri Abhyankar PetscInt i,n; 682c1a5e521SShri Abhyankar 683c1a5e521SShri Abhyankar PetscFunctionBegin; 684c1a5e521SShri Abhyankar ierr = VecGetLocalSize(X,&n);CHKERRQ(ierr); 685c1a5e521SShri Abhyankar ierr = VecGetArray(X,&x);CHKERRQ(ierr); 686c1a5e521SShri Abhyankar ierr = VecGetArrayRead(vi->xl,&xl);CHKERRQ(ierr); 687c1a5e521SShri Abhyankar ierr = VecGetArrayRead(vi->xu,&xu);CHKERRQ(ierr); 688c1a5e521SShri Abhyankar 689c1a5e521SShri Abhyankar for(i = 0;i<n;i++) { 69010f5ae6bSBarry Smith if (PetscRealPart(x[i]) < PetscRealPart(xl[i])) x[i] = xl[i]; 69110f5ae6bSBarry Smith else if (PetscRealPart(x[i]) > PetscRealPart(xu[i])) x[i] = xu[i]; 692c1a5e521SShri Abhyankar } 693c1a5e521SShri Abhyankar ierr = VecRestoreArray(X,&x);CHKERRQ(ierr); 694c1a5e521SShri Abhyankar ierr = VecRestoreArrayRead(vi->xl,&xl);CHKERRQ(ierr); 695c1a5e521SShri Abhyankar ierr = VecRestoreArrayRead(vi->xu,&xu);CHKERRQ(ierr); 696c1a5e521SShri Abhyankar PetscFunctionReturn(0); 697c1a5e521SShri Abhyankar } 698c1a5e521SShri Abhyankar 6992b4ed282SShri Abhyankar /* -------------------------------------------------------------------- 7002b4ed282SShri Abhyankar 7012b4ed282SShri Abhyankar This file implements a semismooth truncated Newton method with a line search, 7022b4ed282SShri Abhyankar for solving a system of nonlinear equations in complementarity form, using the KSP, Vec, 7032b4ed282SShri Abhyankar and Mat interfaces for linear solvers, vectors, and matrices, 7042b4ed282SShri Abhyankar respectively. 7052b4ed282SShri Abhyankar 7062b4ed282SShri Abhyankar The following basic routines are required for each nonlinear solver: 7072b4ed282SShri Abhyankar SNESCreate_XXX() - Creates a nonlinear solver context 7082b4ed282SShri Abhyankar SNESSetFromOptions_XXX() - Sets runtime options 7092b4ed282SShri Abhyankar SNESSolve_XXX() - Solves the nonlinear system 7102b4ed282SShri Abhyankar SNESDestroy_XXX() - Destroys the nonlinear solver context 7112b4ed282SShri Abhyankar The suffix "_XXX" denotes a particular implementation, in this case 7122b4ed282SShri Abhyankar we use _VI (e.g., SNESCreate_VI, SNESSolve_VI) for solving 7132b4ed282SShri Abhyankar systems of nonlinear equations with a line search (LS) method. 7142b4ed282SShri Abhyankar These routines are actually called via the common user interface 7152b4ed282SShri Abhyankar routines SNESCreate(), SNESSetFromOptions(), SNESSolve(), and 7162b4ed282SShri Abhyankar SNESDestroy(), so the application code interface remains identical 7172b4ed282SShri Abhyankar for all nonlinear solvers. 7182b4ed282SShri Abhyankar 7192b4ed282SShri Abhyankar Another key routine is: 7202b4ed282SShri Abhyankar SNESSetUp_XXX() - Prepares for the use of a nonlinear solver 7212b4ed282SShri Abhyankar by setting data structures and options. The interface routine SNESSetUp() 7222b4ed282SShri Abhyankar is not usually called directly by the user, but instead is called by 7232b4ed282SShri Abhyankar SNESSolve() if necessary. 7242b4ed282SShri Abhyankar 7252b4ed282SShri Abhyankar Additional basic routines are: 7262b4ed282SShri Abhyankar SNESView_XXX() - Prints details of runtime options that 7272b4ed282SShri Abhyankar have actually been used. 7282b4ed282SShri Abhyankar These are called by application codes via the interface routines 7292b4ed282SShri Abhyankar SNESView(). 7302b4ed282SShri Abhyankar 7312b4ed282SShri Abhyankar The various types of solvers (preconditioners, Krylov subspace methods, 7322b4ed282SShri Abhyankar nonlinear solvers, timesteppers) are all organized similarly, so the 7332b4ed282SShri Abhyankar above description applies to these categories also. 7342b4ed282SShri Abhyankar 7352b4ed282SShri Abhyankar -------------------------------------------------------------------- */ 7362b4ed282SShri Abhyankar /* 73769c03620SShri Abhyankar SNESSolveVI_SS - Solves the complementarity problem with a semismooth Newton 7382b4ed282SShri Abhyankar method using a line search. 7392b4ed282SShri Abhyankar 7402b4ed282SShri Abhyankar Input Parameters: 7412b4ed282SShri Abhyankar . snes - the SNES context 7422b4ed282SShri Abhyankar 7432b4ed282SShri Abhyankar Output Parameter: 7442b4ed282SShri Abhyankar . outits - number of iterations until termination 7452b4ed282SShri Abhyankar 7462b4ed282SShri Abhyankar Application Interface Routine: SNESSolve() 7472b4ed282SShri Abhyankar 7482b4ed282SShri Abhyankar Notes: 7492b4ed282SShri Abhyankar This implements essentially a semismooth Newton method with a 75051defd01SShri Abhyankar line search. The default line search does not do any line seach 75151defd01SShri Abhyankar but rather takes a full newton step. 7522b4ed282SShri Abhyankar */ 7532b4ed282SShri Abhyankar #undef __FUNCT__ 75469c03620SShri Abhyankar #define __FUNCT__ "SNESSolveVI_SS" 75569c03620SShri Abhyankar PetscErrorCode SNESSolveVI_SS(SNES snes) 7562b4ed282SShri Abhyankar { 7572b4ed282SShri Abhyankar SNES_VI *vi = (SNES_VI*)snes->data; 7582b4ed282SShri Abhyankar PetscErrorCode ierr; 7592b4ed282SShri Abhyankar PetscInt maxits,i,lits; 7603b336b49SShri Abhyankar PetscBool lssucceed; 7612b4ed282SShri Abhyankar MatStructure flg = DIFFERENT_NONZERO_PATTERN; 7622b4ed282SShri Abhyankar PetscReal gnorm,xnorm=0,ynorm; 7632b4ed282SShri Abhyankar Vec Y,X,F,G,W; 7642b4ed282SShri Abhyankar KSPConvergedReason kspreason; 7652b4ed282SShri Abhyankar 7662b4ed282SShri Abhyankar PetscFunctionBegin; 7679ce7406fSBarry Smith vi->computeuserfunction = snes->ops->computefunction; 7689ce7406fSBarry Smith snes->ops->computefunction = SNESVIComputeFunction; 7699ce7406fSBarry Smith 7702b4ed282SShri Abhyankar snes->numFailures = 0; 7712b4ed282SShri Abhyankar snes->numLinearSolveFailures = 0; 7722b4ed282SShri Abhyankar snes->reason = SNES_CONVERGED_ITERATING; 7732b4ed282SShri Abhyankar 7742b4ed282SShri Abhyankar maxits = snes->max_its; /* maximum number of iterations */ 7752b4ed282SShri Abhyankar X = snes->vec_sol; /* solution vector */ 7762b4ed282SShri Abhyankar F = snes->vec_func; /* residual vector */ 7772b4ed282SShri Abhyankar Y = snes->work[0]; /* work vectors */ 7782b4ed282SShri Abhyankar G = snes->work[1]; 7792b4ed282SShri Abhyankar W = snes->work[2]; 7802b4ed282SShri Abhyankar 7812b4ed282SShri Abhyankar ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 7822b4ed282SShri Abhyankar snes->iter = 0; 7832b4ed282SShri Abhyankar snes->norm = 0.0; 7842b4ed282SShri Abhyankar ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 7852b4ed282SShri Abhyankar 7867fe79bc4SShri Abhyankar ierr = SNESVIProjectOntoBounds(snes,X);CHKERRQ(ierr); 7872b4ed282SShri Abhyankar ierr = SNESComputeFunction(snes,X,vi->phi);CHKERRQ(ierr); 7882b4ed282SShri Abhyankar if (snes->domainerror) { 7892b4ed282SShri Abhyankar snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN; 7909ce7406fSBarry Smith snes->ops->computefunction = vi->computeuserfunction; 7912b4ed282SShri Abhyankar PetscFunctionReturn(0); 7922b4ed282SShri Abhyankar } 7932b4ed282SShri Abhyankar /* Compute Merit function */ 7942b4ed282SShri Abhyankar ierr = SNESVIComputeMeritFunction(vi->phi,&vi->merit,&vi->phinorm);CHKERRQ(ierr); 7952b4ed282SShri Abhyankar 7962b4ed282SShri Abhyankar ierr = VecNormBegin(X,NORM_2,&xnorm);CHKERRQ(ierr); /* xnorm <- ||x|| */ 7972b4ed282SShri Abhyankar ierr = VecNormEnd(X,NORM_2,&xnorm);CHKERRQ(ierr); 79862cbcd01SMatthew G Knepley if (PetscIsInfOrNanReal(vi->merit)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number"); 7992b4ed282SShri Abhyankar 8002b4ed282SShri Abhyankar ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 8012b4ed282SShri Abhyankar snes->norm = vi->phinorm; 8022b4ed282SShri Abhyankar ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 8032b4ed282SShri Abhyankar SNESLogConvHistory(snes,vi->phinorm,0); 8047a03ce2fSLisandro Dalcin ierr = SNESMonitor(snes,0,vi->phinorm);CHKERRQ(ierr); 8052b4ed282SShri Abhyankar 8062b4ed282SShri Abhyankar /* set parameter for default relative tolerance convergence test */ 8072b4ed282SShri Abhyankar snes->ttol = vi->phinorm*snes->rtol; 8082b4ed282SShri Abhyankar /* test convergence */ 8092b4ed282SShri Abhyankar ierr = (*snes->ops->converged)(snes,0,0.0,0.0,vi->phinorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); 8109ce7406fSBarry Smith if (snes->reason) { 8119ce7406fSBarry Smith snes->ops->computefunction = vi->computeuserfunction; 8129ce7406fSBarry Smith PetscFunctionReturn(0); 8139ce7406fSBarry Smith } 8142b4ed282SShri Abhyankar 8152b4ed282SShri Abhyankar for (i=0; i<maxits; i++) { 8162b4ed282SShri Abhyankar 8172b4ed282SShri Abhyankar /* Call general purpose update function */ 8182b4ed282SShri Abhyankar if (snes->ops->update) { 8192b4ed282SShri Abhyankar ierr = (*snes->ops->update)(snes, snes->iter);CHKERRQ(ierr); 8202b4ed282SShri Abhyankar } 8212b4ed282SShri Abhyankar 8222b4ed282SShri Abhyankar /* Solve J Y = Phi, where J is the semismooth jacobian */ 823a79edbefSShri Abhyankar /* Get the nonlinear function jacobian */ 8242b4ed282SShri Abhyankar ierr = SNESComputeJacobian(snes,X,&snes->jacobian,&snes->jacobian_pre,&flg);CHKERRQ(ierr); 825a79edbefSShri Abhyankar /* Get the diagonal shift and row scaling vectors */ 826a79edbefSShri Abhyankar ierr = SNESVIComputeBsubdifferentialVectors(snes,X,F,snes->jacobian,vi->Da,vi->Db);CHKERRQ(ierr); 827a79edbefSShri Abhyankar /* Compute the semismooth jacobian */ 828a79edbefSShri Abhyankar ierr = SNESVIComputeJacobian(snes->jacobian,snes->jacobian_pre,vi->Da,vi->Db);CHKERRQ(ierr); 829ee657d29SShri Abhyankar /* Compute the merit function gradient */ 830ee657d29SShri Abhyankar ierr = SNESVIComputeMeritFunctionGradient(snes->jacobian,vi->phi,vi->dpsi);CHKERRQ(ierr); 8312b4ed282SShri Abhyankar ierr = KSPSetOperators(snes->ksp,snes->jacobian,snes->jacobian_pre,flg);CHKERRQ(ierr); 8322b4ed282SShri Abhyankar ierr = SNES_KSPSolve(snes,snes->ksp,vi->phi,Y);CHKERRQ(ierr); 8332b4ed282SShri Abhyankar ierr = KSPGetConvergedReason(snes->ksp,&kspreason);CHKERRQ(ierr); 8343b336b49SShri Abhyankar 8353b336b49SShri Abhyankar if (kspreason < 0) { 8362b4ed282SShri Abhyankar if (++snes->numLinearSolveFailures >= snes->maxLinearSolveFailures) { 8372b4ed282SShri 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); 8382b4ed282SShri Abhyankar snes->reason = SNES_DIVERGED_LINEAR_SOLVE; 8392b4ed282SShri Abhyankar break; 8402b4ed282SShri Abhyankar } 8412b4ed282SShri Abhyankar } 8422b4ed282SShri Abhyankar ierr = KSPGetIterationNumber(snes->ksp,&lits);CHKERRQ(ierr); 8432b4ed282SShri Abhyankar snes->linear_its += lits; 8442b4ed282SShri Abhyankar ierr = PetscInfo2(snes,"iter=%D, linear solve iterations=%D\n",snes->iter,lits);CHKERRQ(ierr); 8452b4ed282SShri Abhyankar /* 8462b4ed282SShri Abhyankar if (vi->precheckstep) { 847ace3abfcSBarry Smith PetscBool changed_y = PETSC_FALSE; 8482b4ed282SShri Abhyankar ierr = (*vi->precheckstep)(snes,X,Y,vi->precheck,&changed_y);CHKERRQ(ierr); 8492b4ed282SShri Abhyankar } 8502b4ed282SShri Abhyankar 8512b4ed282SShri Abhyankar if (PetscLogPrintInfo){ 8522b4ed282SShri Abhyankar ierr = SNESVICheckResidual_Private(snes,snes->jacobian,F,Y,G,W);CHKERRQ(ierr); 8532b4ed282SShri Abhyankar } 8542b4ed282SShri Abhyankar */ 8552b4ed282SShri Abhyankar /* Compute a (scaled) negative update in the line search routine: 8562b4ed282SShri Abhyankar Y <- X - lambda*Y 8572b4ed282SShri Abhyankar and evaluate G = function(Y) (depends on the line search). 8582b4ed282SShri Abhyankar */ 8592b4ed282SShri Abhyankar ierr = VecCopy(Y,snes->vec_sol_update);CHKERRQ(ierr); 8602b4ed282SShri Abhyankar ynorm = 1; gnorm = vi->phinorm; 8612b4ed282SShri Abhyankar ierr = (*vi->LineSearch)(snes,vi->lsP,X,vi->phi,G,Y,W,vi->phinorm,xnorm,&ynorm,&gnorm,&lssucceed);CHKERRQ(ierr); 8622b4ed282SShri Abhyankar ierr = PetscInfo4(snes,"fnorm=%18.16e, gnorm=%18.16e, ynorm=%18.16e, lssucceed=%d\n",vi->phinorm,gnorm,ynorm,(int)lssucceed);CHKERRQ(ierr); 8632b4ed282SShri Abhyankar if (snes->reason == SNES_DIVERGED_FUNCTION_COUNT) break; 8642b4ed282SShri Abhyankar if (snes->domainerror) { 8652b4ed282SShri Abhyankar snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN; 8669ce7406fSBarry Smith snes->ops->computefunction = vi->computeuserfunction; 8672b4ed282SShri Abhyankar PetscFunctionReturn(0); 8682b4ed282SShri Abhyankar } 8692b4ed282SShri Abhyankar if (!lssucceed) { 8702b4ed282SShri Abhyankar if (++snes->numFailures >= snes->maxFailures) { 871ace3abfcSBarry Smith PetscBool ismin; 8722b4ed282SShri Abhyankar snes->reason = SNES_DIVERGED_LINE_SEARCH; 8732b4ed282SShri Abhyankar ierr = SNESVICheckLocalMin_Private(snes,snes->jacobian,G,W,gnorm,&ismin);CHKERRQ(ierr); 8742b4ed282SShri Abhyankar if (ismin) snes->reason = SNES_DIVERGED_LOCAL_MIN; 8752b4ed282SShri Abhyankar break; 8762b4ed282SShri Abhyankar } 8772b4ed282SShri Abhyankar } 8782b4ed282SShri Abhyankar /* Update function and solution vectors */ 8792b4ed282SShri Abhyankar vi->phinorm = gnorm; 8802b4ed282SShri Abhyankar vi->merit = 0.5*vi->phinorm*vi->phinorm; 8812b4ed282SShri Abhyankar ierr = VecCopy(G,vi->phi);CHKERRQ(ierr); 8822b4ed282SShri Abhyankar ierr = VecCopy(W,X);CHKERRQ(ierr); 8832b4ed282SShri Abhyankar /* Monitor convergence */ 8842b4ed282SShri Abhyankar ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 8852b4ed282SShri Abhyankar snes->iter = i+1; 8862b4ed282SShri Abhyankar snes->norm = vi->phinorm; 8872b4ed282SShri Abhyankar ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 8882b4ed282SShri Abhyankar SNESLogConvHistory(snes,snes->norm,lits); 8897a03ce2fSLisandro Dalcin ierr = SNESMonitor(snes,snes->iter,snes->norm);CHKERRQ(ierr); 8902b4ed282SShri Abhyankar /* Test for convergence, xnorm = || X || */ 8912b4ed282SShri Abhyankar if (snes->ops->converged != SNESSkipConverged) { ierr = VecNorm(X,NORM_2,&xnorm);CHKERRQ(ierr); } 8922b4ed282SShri Abhyankar ierr = (*snes->ops->converged)(snes,snes->iter,xnorm,ynorm,vi->phinorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); 8932b4ed282SShri Abhyankar if (snes->reason) break; 8942b4ed282SShri Abhyankar } 8952b4ed282SShri Abhyankar if (i == maxits) { 8962b4ed282SShri Abhyankar ierr = PetscInfo1(snes,"Maximum number of iterations has been reached: %D\n",maxits);CHKERRQ(ierr); 8972b4ed282SShri Abhyankar if(!snes->reason) snes->reason = SNES_DIVERGED_MAX_IT; 8982b4ed282SShri Abhyankar } 8999ce7406fSBarry Smith snes->ops->computefunction = vi->computeuserfunction; 9002b4ed282SShri Abhyankar PetscFunctionReturn(0); 9012b4ed282SShri Abhyankar } 90269c03620SShri Abhyankar 90369c03620SShri Abhyankar #undef __FUNCT__ 904693ddf92SShri Abhyankar #define __FUNCT__ "SNESVIGetActiveSetIS" 905693ddf92SShri Abhyankar /* 906693ddf92SShri Abhyankar SNESVIGetActiveSetIndices - Gets the global indices for the active set variables 907693ddf92SShri Abhyankar 908693ddf92SShri Abhyankar Input parameter 909693ddf92SShri Abhyankar . snes - the SNES context 910693ddf92SShri Abhyankar . X - the snes solution vector 911693ddf92SShri Abhyankar . F - the nonlinear function vector 912693ddf92SShri Abhyankar 913693ddf92SShri Abhyankar Output parameter 914693ddf92SShri Abhyankar . ISact - active set index set 915693ddf92SShri Abhyankar */ 916693ddf92SShri Abhyankar PetscErrorCode SNESVIGetActiveSetIS(SNES snes,Vec X,Vec F,IS* ISact) 917d950fb63SShri Abhyankar { 918d950fb63SShri Abhyankar PetscErrorCode ierr; 919693ddf92SShri Abhyankar SNES_VI *vi = (SNES_VI*)snes->data; 920693ddf92SShri Abhyankar Vec Xl=vi->xl,Xu=vi->xu; 921693ddf92SShri Abhyankar const PetscScalar *x,*f,*xl,*xu; 922693ddf92SShri Abhyankar PetscInt *idx_act,i,nlocal,nloc_isact=0,ilow,ihigh,i1=0; 923d950fb63SShri Abhyankar 924d950fb63SShri Abhyankar PetscFunctionBegin; 925d950fb63SShri Abhyankar ierr = VecGetLocalSize(X,&nlocal);CHKERRQ(ierr); 926d950fb63SShri Abhyankar ierr = VecGetOwnershipRange(X,&ilow,&ihigh);CHKERRQ(ierr); 927fe835674SShri Abhyankar ierr = VecGetArrayRead(X,&x);CHKERRQ(ierr); 928fe835674SShri Abhyankar ierr = VecGetArrayRead(Xl,&xl);CHKERRQ(ierr); 929fe835674SShri Abhyankar ierr = VecGetArrayRead(Xu,&xu);CHKERRQ(ierr); 930fe835674SShri Abhyankar ierr = VecGetArrayRead(F,&f);CHKERRQ(ierr); 931693ddf92SShri Abhyankar /* Compute active set size */ 932d950fb63SShri Abhyankar for (i=0; i < nlocal;i++) { 93310f5ae6bSBarry 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++; 934d950fb63SShri Abhyankar } 935693ddf92SShri Abhyankar 936d950fb63SShri Abhyankar ierr = PetscMalloc(nloc_isact*sizeof(PetscInt),&idx_act);CHKERRQ(ierr); 937d950fb63SShri Abhyankar 938693ddf92SShri Abhyankar /* Set active set indices */ 939d950fb63SShri Abhyankar for(i=0; i < nlocal; i++) { 94010f5ae6bSBarry 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; 941d950fb63SShri Abhyankar } 942d950fb63SShri Abhyankar 943693ddf92SShri Abhyankar /* Create active set IS */ 94462298a1eSBarry Smith ierr = ISCreateGeneral(((PetscObject)snes)->comm,nloc_isact,idx_act,PETSC_OWN_POINTER,ISact);CHKERRQ(ierr); 945d950fb63SShri Abhyankar 946fe835674SShri Abhyankar ierr = VecRestoreArrayRead(X,&x);CHKERRQ(ierr); 947fe835674SShri Abhyankar ierr = VecRestoreArrayRead(Xl,&xl);CHKERRQ(ierr); 948fe835674SShri Abhyankar ierr = VecRestoreArrayRead(Xu,&xu);CHKERRQ(ierr); 949fe835674SShri Abhyankar ierr = VecRestoreArrayRead(F,&f);CHKERRQ(ierr); 950d950fb63SShri Abhyankar PetscFunctionReturn(0); 951d950fb63SShri Abhyankar } 952d950fb63SShri Abhyankar 953693ddf92SShri Abhyankar #undef __FUNCT__ 954693ddf92SShri Abhyankar #define __FUNCT__ "SNESVICreateIndexSets_RS" 955693ddf92SShri Abhyankar PetscErrorCode SNESVICreateIndexSets_RS(SNES snes,Vec X,Vec F,IS* ISact,IS* ISinact) 956693ddf92SShri Abhyankar { 957693ddf92SShri Abhyankar PetscErrorCode ierr; 958693ddf92SShri Abhyankar 959693ddf92SShri Abhyankar PetscFunctionBegin; 960693ddf92SShri Abhyankar ierr = SNESVIGetActiveSetIS(snes,X,F,ISact);CHKERRQ(ierr); 961693ddf92SShri Abhyankar ierr = ISComplement(*ISact,X->map->rstart,X->map->rend,ISinact);CHKERRQ(ierr); 962693ddf92SShri Abhyankar PetscFunctionReturn(0); 963693ddf92SShri Abhyankar } 964693ddf92SShri Abhyankar 965dbd914b8SShri Abhyankar /* Create active and inactive set vectors. The local size of this vector is set and petsc computes the global size */ 966dbd914b8SShri Abhyankar #undef __FUNCT__ 967fe835674SShri Abhyankar #define __FUNCT__ "SNESVICreateSubVectors" 968fe835674SShri Abhyankar PetscErrorCode SNESVICreateSubVectors(SNES snes,PetscInt n,Vec* newv) 969dbd914b8SShri Abhyankar { 970dbd914b8SShri Abhyankar PetscErrorCode ierr; 971dbd914b8SShri Abhyankar Vec v; 972dbd914b8SShri Abhyankar 973dbd914b8SShri Abhyankar PetscFunctionBegin; 974dbd914b8SShri Abhyankar ierr = VecCreate(((PetscObject)snes)->comm,&v);CHKERRQ(ierr); 975dbd914b8SShri Abhyankar ierr = VecSetSizes(v,n,PETSC_DECIDE);CHKERRQ(ierr); 976dbd914b8SShri Abhyankar ierr = VecSetFromOptions(v);CHKERRQ(ierr); 977dbd914b8SShri Abhyankar *newv = v; 978dbd914b8SShri Abhyankar 979dbd914b8SShri Abhyankar PetscFunctionReturn(0); 980dbd914b8SShri Abhyankar } 981dbd914b8SShri Abhyankar 982732bb160SShri Abhyankar /* Resets the snes PC and KSP when the active set sizes change */ 983732bb160SShri Abhyankar #undef __FUNCT__ 984732bb160SShri Abhyankar #define __FUNCT__ "SNESVIResetPCandKSP" 985732bb160SShri Abhyankar PetscErrorCode SNESVIResetPCandKSP(SNES snes,Mat Amat,Mat Pmat) 986732bb160SShri Abhyankar { 987732bb160SShri Abhyankar PetscErrorCode ierr; 988d0af7cd3SBarry Smith KSP snesksp; 989dbd914b8SShri Abhyankar 990732bb160SShri Abhyankar PetscFunctionBegin; 991732bb160SShri Abhyankar ierr = SNESGetKSP(snes,&snesksp);CHKERRQ(ierr); 992d0af7cd3SBarry Smith ierr = KSPReset(snesksp);CHKERRQ(ierr); 993c2efdce3SBarry Smith 994c2efdce3SBarry Smith /* 995d0af7cd3SBarry Smith KSP kspnew; 996d0af7cd3SBarry Smith PC pcnew; 997d0af7cd3SBarry Smith const MatSolverPackage stype; 998d0af7cd3SBarry Smith 999c2efdce3SBarry Smith 1000732bb160SShri Abhyankar ierr = KSPCreate(((PetscObject)snes)->comm,&kspnew);CHKERRQ(ierr); 1001732bb160SShri Abhyankar kspnew->pc_side = snesksp->pc_side; 1002732bb160SShri Abhyankar kspnew->rtol = snesksp->rtol; 1003732bb160SShri Abhyankar kspnew->abstol = snesksp->abstol; 1004732bb160SShri Abhyankar kspnew->max_it = snesksp->max_it; 1005732bb160SShri Abhyankar ierr = KSPSetType(kspnew,((PetscObject)snesksp)->type_name);CHKERRQ(ierr); 1006732bb160SShri Abhyankar ierr = KSPGetPC(kspnew,&pcnew);CHKERRQ(ierr); 1007732bb160SShri Abhyankar ierr = PCSetType(kspnew->pc,((PetscObject)snesksp->pc)->type_name);CHKERRQ(ierr); 1008732bb160SShri Abhyankar ierr = PCSetOperators(kspnew->pc,Amat,Pmat,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr); 1009732bb160SShri Abhyankar ierr = PCFactorGetMatSolverPackage(snesksp->pc,&stype);CHKERRQ(ierr); 1010732bb160SShri Abhyankar ierr = PCFactorSetMatSolverPackage(kspnew->pc,stype);CHKERRQ(ierr); 10116bf464f9SBarry Smith ierr = KSPDestroy(&snesksp);CHKERRQ(ierr); 1012732bb160SShri Abhyankar snes->ksp = kspnew; 1013732bb160SShri Abhyankar ierr = PetscLogObjectParent(snes,kspnew);CHKERRQ(ierr); 1014d0af7cd3SBarry Smith ierr = KSPSetFromOptions(kspnew);CHKERRQ(ierr);*/ 1015732bb160SShri Abhyankar PetscFunctionReturn(0); 1016732bb160SShri Abhyankar } 101769c03620SShri Abhyankar 101869c03620SShri Abhyankar 1019fe835674SShri Abhyankar #undef __FUNCT__ 1020fe835674SShri Abhyankar #define __FUNCT__ "SNESVIComputeInactiveSetFnorm" 102110f5ae6bSBarry Smith PetscErrorCode SNESVIComputeInactiveSetFnorm(SNES snes,Vec F,Vec X,PetscReal *fnorm) 1022fe835674SShri Abhyankar { 1023fe835674SShri Abhyankar PetscErrorCode ierr; 1024fe835674SShri Abhyankar SNES_VI *vi = (SNES_VI*)snes->data; 1025fe835674SShri Abhyankar const PetscScalar *x,*xl,*xu,*f; 1026fe835674SShri Abhyankar PetscInt i,n; 1027fe835674SShri Abhyankar PetscReal rnorm; 1028fe835674SShri Abhyankar 1029fe835674SShri Abhyankar PetscFunctionBegin; 1030fe835674SShri Abhyankar ierr = VecGetLocalSize(X,&n);CHKERRQ(ierr); 1031fe835674SShri Abhyankar ierr = VecGetArrayRead(vi->xl,&xl);CHKERRQ(ierr); 1032fe835674SShri Abhyankar ierr = VecGetArrayRead(vi->xu,&xu);CHKERRQ(ierr); 1033fe835674SShri Abhyankar ierr = VecGetArrayRead(X,&x);CHKERRQ(ierr); 1034fe835674SShri Abhyankar ierr = VecGetArrayRead(F,&f);CHKERRQ(ierr); 1035fe835674SShri Abhyankar rnorm = 0.0; 1036fe835674SShri Abhyankar for (i=0; i<n; i++) { 103710f5ae6bSBarry 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]); 1038fe835674SShri Abhyankar } 1039fe835674SShri Abhyankar ierr = VecRestoreArrayRead(F,&f);CHKERRQ(ierr); 1040fe835674SShri Abhyankar ierr = VecRestoreArrayRead(vi->xl,&xl);CHKERRQ(ierr); 1041fe835674SShri Abhyankar ierr = VecRestoreArrayRead(vi->xu,&xu);CHKERRQ(ierr); 1042fe835674SShri Abhyankar ierr = VecRestoreArrayRead(X,&x);CHKERRQ(ierr); 1043d9822059SBarry Smith ierr = MPI_Allreduce(&rnorm,fnorm,1,MPIU_REAL,MPIU_SUM,((PetscObject)snes)->comm);CHKERRQ(ierr); 1044fe835674SShri Abhyankar *fnorm = sqrt(*fnorm); 1045fe835674SShri Abhyankar PetscFunctionReturn(0); 1046fe835674SShri Abhyankar } 1047fe835674SShri Abhyankar 1048fe835674SShri Abhyankar /* Variational Inequality solver using reduce space method. No semismooth algorithm is 1049c2efdce3SBarry Smith implemented in this algorithm. It basically identifies the active constraints and does 1050c2efdce3SBarry Smith a linear solve on the other variables (those not associated with the active constraints). */ 1051d950fb63SShri Abhyankar #undef __FUNCT__ 1052d950fb63SShri Abhyankar #define __FUNCT__ "SNESSolveVI_RS" 1053d950fb63SShri Abhyankar PetscErrorCode SNESSolveVI_RS(SNES snes) 1054d950fb63SShri Abhyankar { 1055d950fb63SShri Abhyankar SNES_VI *vi = (SNES_VI*)snes->data; 1056d950fb63SShri Abhyankar PetscErrorCode ierr; 1057abcba341SShri Abhyankar PetscInt maxits,i,lits; 1058d950fb63SShri Abhyankar PetscBool lssucceed; 1059d950fb63SShri Abhyankar MatStructure flg = DIFFERENT_NONZERO_PATTERN; 1060fe835674SShri Abhyankar PetscReal fnorm,gnorm,xnorm=0,ynorm; 1061d950fb63SShri Abhyankar Vec Y,X,F,G,W; 1062d950fb63SShri Abhyankar KSPConvergedReason kspreason; 1063d950fb63SShri Abhyankar 1064d950fb63SShri Abhyankar PetscFunctionBegin; 1065d950fb63SShri Abhyankar snes->numFailures = 0; 1066d950fb63SShri Abhyankar snes->numLinearSolveFailures = 0; 1067d950fb63SShri Abhyankar snes->reason = SNES_CONVERGED_ITERATING; 1068d950fb63SShri Abhyankar 1069d950fb63SShri Abhyankar maxits = snes->max_its; /* maximum number of iterations */ 1070d950fb63SShri Abhyankar X = snes->vec_sol; /* solution vector */ 1071d950fb63SShri Abhyankar F = snes->vec_func; /* residual vector */ 1072d950fb63SShri Abhyankar Y = snes->work[0]; /* work vectors */ 1073d950fb63SShri Abhyankar G = snes->work[1]; 1074d950fb63SShri Abhyankar W = snes->work[2]; 1075d950fb63SShri Abhyankar 1076d950fb63SShri Abhyankar ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 1077d950fb63SShri Abhyankar snes->iter = 0; 1078d950fb63SShri Abhyankar snes->norm = 0.0; 1079d950fb63SShri Abhyankar ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 1080d950fb63SShri Abhyankar 10817fe79bc4SShri Abhyankar ierr = SNESVIProjectOntoBounds(snes,X);CHKERRQ(ierr); 1082fe835674SShri Abhyankar ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr); 1083d950fb63SShri Abhyankar if (snes->domainerror) { 1084d950fb63SShri Abhyankar snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN; 1085d950fb63SShri Abhyankar PetscFunctionReturn(0); 1086d950fb63SShri Abhyankar } 1087fe835674SShri Abhyankar ierr = SNESVIComputeInactiveSetFnorm(snes,F,X,&fnorm);CHKERRQ(ierr); 1088d950fb63SShri Abhyankar ierr = VecNormBegin(X,NORM_2,&xnorm);CHKERRQ(ierr); /* xnorm <- ||x|| */ 1089d950fb63SShri Abhyankar ierr = VecNormEnd(X,NORM_2,&xnorm);CHKERRQ(ierr); 109062cbcd01SMatthew G Knepley if (PetscIsInfOrNanReal(fnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number"); 1091d950fb63SShri Abhyankar 1092d950fb63SShri Abhyankar ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 1093fe835674SShri Abhyankar snes->norm = fnorm; 1094d950fb63SShri Abhyankar ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 1095fe835674SShri Abhyankar SNESLogConvHistory(snes,fnorm,0); 10967a03ce2fSLisandro Dalcin ierr = SNESMonitor(snes,0,fnorm);CHKERRQ(ierr); 1097d950fb63SShri Abhyankar 1098d950fb63SShri Abhyankar /* set parameter for default relative tolerance convergence test */ 1099fe835674SShri Abhyankar snes->ttol = fnorm*snes->rtol; 1100d950fb63SShri Abhyankar /* test convergence */ 1101fe835674SShri Abhyankar ierr = (*snes->ops->converged)(snes,0,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); 1102d950fb63SShri Abhyankar if (snes->reason) PetscFunctionReturn(0); 1103d950fb63SShri Abhyankar 1104d950fb63SShri Abhyankar for (i=0; i<maxits; i++) { 1105d950fb63SShri Abhyankar 1106d950fb63SShri Abhyankar IS IS_act,IS_inact; /* _act -> active set _inact -> inactive set */ 1107d950fb63SShri Abhyankar VecScatter scat_act,scat_inact; 1108abcba341SShri Abhyankar PetscInt nis_act,nis_inact; 1109fe835674SShri Abhyankar Vec Y_act,Y_inact,F_inact; 1110d950fb63SShri Abhyankar Mat jac_inact_inact,prejac_inact_inact; 111162298a1eSBarry Smith IS keptrows; 1112abcba341SShri Abhyankar PetscBool isequal; 1113d950fb63SShri Abhyankar 1114d950fb63SShri Abhyankar /* Call general purpose update function */ 1115d950fb63SShri Abhyankar if (snes->ops->update) { 1116d950fb63SShri Abhyankar ierr = (*snes->ops->update)(snes, snes->iter);CHKERRQ(ierr); 1117d950fb63SShri Abhyankar } 1118d950fb63SShri Abhyankar ierr = SNESComputeJacobian(snes,X,&snes->jacobian,&snes->jacobian_pre,&flg);CHKERRQ(ierr); 111962298a1eSBarry Smith 1120d950fb63SShri Abhyankar /* Create active and inactive index sets */ 1121693ddf92SShri Abhyankar ierr = SNESVICreateIndexSets_RS(snes,X,F,&IS_act,&IS_inact);CHKERRQ(ierr); 1122d950fb63SShri Abhyankar 11234dcab191SBarry Smith 1124abcba341SShri Abhyankar /* Create inactive set submatrix */ 112562298a1eSBarry Smith ierr = MatGetSubMatrix(snes->jacobian,IS_inact,IS_inact,MAT_INITIAL_MATRIX,&jac_inact_inact);CHKERRQ(ierr); 1126b3a44c85SBarry Smith ierr = MatFindNonzeroRows(jac_inact_inact,&keptrows);CHKERRQ(ierr); 112762298a1eSBarry Smith if (keptrows) { 112862298a1eSBarry Smith PetscInt cnt,*nrows,k; 112962298a1eSBarry Smith const PetscInt *krows,*inact; 113027d4218bSShri Abhyankar PetscInt rstart=jac_inact_inact->rmap->rstart; 113162298a1eSBarry Smith 11326bf464f9SBarry Smith ierr = MatDestroy(&jac_inact_inact);CHKERRQ(ierr); 11336bf464f9SBarry Smith ierr = ISDestroy(&IS_act);CHKERRQ(ierr); 113462298a1eSBarry Smith 113562298a1eSBarry Smith ierr = ISGetLocalSize(keptrows,&cnt);CHKERRQ(ierr); 113662298a1eSBarry Smith ierr = ISGetIndices(keptrows,&krows);CHKERRQ(ierr); 113762298a1eSBarry Smith ierr = ISGetIndices(IS_inact,&inact);CHKERRQ(ierr); 113862298a1eSBarry Smith ierr = PetscMalloc(cnt*sizeof(PetscInt),&nrows);CHKERRQ(ierr); 113962298a1eSBarry Smith for (k=0; k<cnt; k++) { 114027d4218bSShri Abhyankar nrows[k] = inact[krows[k]-rstart]; 114162298a1eSBarry Smith } 114262298a1eSBarry Smith ierr = ISRestoreIndices(keptrows,&krows);CHKERRQ(ierr); 114362298a1eSBarry Smith ierr = ISRestoreIndices(IS_inact,&inact);CHKERRQ(ierr); 11446bf464f9SBarry Smith ierr = ISDestroy(&keptrows);CHKERRQ(ierr); 11456bf464f9SBarry Smith ierr = ISDestroy(&IS_inact);CHKERRQ(ierr); 114662298a1eSBarry Smith 114727d4218bSShri Abhyankar ierr = ISCreateGeneral(PETSC_COMM_WORLD,cnt,nrows,PETSC_OWN_POINTER,&IS_inact);CHKERRQ(ierr); 114827d4218bSShri Abhyankar ierr = ISComplement(IS_inact,F->map->rstart,F->map->rend,&IS_act);CHKERRQ(ierr); 114962298a1eSBarry Smith ierr = MatGetSubMatrix(snes->jacobian,IS_inact,IS_inact,MAT_INITIAL_MATRIX,&jac_inact_inact);CHKERRQ(ierr); 115062298a1eSBarry Smith } 11519e516c8fSBarry Smith ierr = DMSetVI(snes->dm,vi->xu,vi->xl,X,F,IS_inact);CHKERRQ(ierr); 115262298a1eSBarry Smith 1153d950fb63SShri Abhyankar /* Get sizes of active and inactive sets */ 1154d950fb63SShri Abhyankar ierr = ISGetLocalSize(IS_act,&nis_act);CHKERRQ(ierr); 1155d950fb63SShri Abhyankar ierr = ISGetLocalSize(IS_inact,&nis_inact);CHKERRQ(ierr); 1156d950fb63SShri Abhyankar 1157d950fb63SShri Abhyankar /* Create active and inactive set vectors */ 1158fe835674SShri Abhyankar ierr = SNESVICreateSubVectors(snes,nis_inact,&F_inact);CHKERRQ(ierr); 1159fe835674SShri Abhyankar ierr = SNESVICreateSubVectors(snes,nis_act,&Y_act);CHKERRQ(ierr); 1160fe835674SShri Abhyankar ierr = SNESVICreateSubVectors(snes,nis_inact,&Y_inact);CHKERRQ(ierr); 1161d950fb63SShri Abhyankar 1162d950fb63SShri Abhyankar /* Create scatter contexts */ 1163d950fb63SShri Abhyankar ierr = VecScatterCreate(Y,IS_act,Y_act,PETSC_NULL,&scat_act);CHKERRQ(ierr); 1164d950fb63SShri Abhyankar ierr = VecScatterCreate(Y,IS_inact,Y_inact,PETSC_NULL,&scat_inact);CHKERRQ(ierr); 1165d950fb63SShri Abhyankar 1166d950fb63SShri Abhyankar /* Do a vec scatter to active and inactive set vectors */ 1167fe835674SShri Abhyankar ierr = VecScatterBegin(scat_inact,F,F_inact,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1168fe835674SShri Abhyankar ierr = VecScatterEnd(scat_inact,F,F_inact,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1169d950fb63SShri Abhyankar 1170d950fb63SShri Abhyankar ierr = VecScatterBegin(scat_act,Y,Y_act,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1171d950fb63SShri Abhyankar ierr = VecScatterEnd(scat_act,Y,Y_act,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1172d950fb63SShri Abhyankar 1173d950fb63SShri Abhyankar ierr = VecScatterBegin(scat_inact,Y,Y_inact,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1174d950fb63SShri Abhyankar ierr = VecScatterEnd(scat_inact,Y,Y_inact,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1175d950fb63SShri Abhyankar 1176d950fb63SShri Abhyankar /* Active set direction = 0 */ 1177d950fb63SShri Abhyankar ierr = VecSet(Y_act,0);CHKERRQ(ierr); 1178d950fb63SShri Abhyankar if (snes->jacobian != snes->jacobian_pre) { 1179d950fb63SShri Abhyankar ierr = MatGetSubMatrix(snes->jacobian_pre,IS_inact,IS_inact,MAT_INITIAL_MATRIX,&prejac_inact_inact);CHKERRQ(ierr); 1180d950fb63SShri Abhyankar } else prejac_inact_inact = jac_inact_inact; 1181d950fb63SShri Abhyankar 1182abcba341SShri Abhyankar ierr = ISEqual(vi->IS_inact_prev,IS_inact,&isequal);CHKERRQ(ierr); 1183abcba341SShri Abhyankar if (!isequal) { 1184732bb160SShri Abhyankar ierr = SNESVIResetPCandKSP(snes,jac_inact_inact,prejac_inact_inact);CHKERRQ(ierr); 1185d950fb63SShri Abhyankar } 1186d950fb63SShri Abhyankar 118713e0d083SBarry Smith /* ierr = ISView(IS_inact,0);CHKERRQ(ierr); */ 118813e0d083SBarry Smith /* ierr = ISView(IS_act,0);CHKERRQ(ierr);*/ 118913e0d083SBarry Smith /* ierr = MatView(snes->jacobian_pre,0); */ 119013e0d083SBarry Smith 1191d950fb63SShri Abhyankar ierr = KSPSetOperators(snes->ksp,jac_inact_inact,prejac_inact_inact,flg);CHKERRQ(ierr); 119213e0d083SBarry Smith ierr = KSPSetUp(snes->ksp);CHKERRQ(ierr); 119313e0d083SBarry Smith { 119413e0d083SBarry Smith PC pc; 119513e0d083SBarry Smith PetscBool flg; 119613e0d083SBarry Smith ierr = KSPGetPC(snes->ksp,&pc);CHKERRQ(ierr); 119713e0d083SBarry Smith ierr = PetscTypeCompare((PetscObject)pc,PCFIELDSPLIT,&flg);CHKERRQ(ierr); 119813e0d083SBarry Smith if (flg) { 119913e0d083SBarry Smith KSP *subksps; 120013e0d083SBarry Smith ierr = PCFieldSplitGetSubKSP(pc,PETSC_NULL,&subksps);CHKERRQ(ierr); 120113e0d083SBarry Smith ierr = KSPGetPC(subksps[0],&pc);CHKERRQ(ierr); 120213e0d083SBarry Smith ierr = PetscFree(subksps);CHKERRQ(ierr); 120313e0d083SBarry Smith ierr = PetscTypeCompare((PetscObject)pc,PCBJACOBI,&flg);CHKERRQ(ierr); 120413e0d083SBarry Smith if (flg) { 120513e0d083SBarry Smith PetscInt n,N = 101*101,j,cnts[3] = {0,0,0}; 120613e0d083SBarry Smith const PetscInt *ii; 120713e0d083SBarry Smith 120813e0d083SBarry Smith ierr = ISGetSize(IS_inact,&n);CHKERRQ(ierr); 120913e0d083SBarry Smith ierr = ISGetIndices(IS_inact,&ii);CHKERRQ(ierr); 121013e0d083SBarry Smith for (j=0; j<n; j++) { 121113e0d083SBarry Smith if (ii[j] < N) cnts[0]++; 121213e0d083SBarry Smith else if (ii[j] < 2*N) cnts[1]++; 121313e0d083SBarry Smith else if (ii[j] < 3*N) cnts[2]++; 121413e0d083SBarry Smith } 121513e0d083SBarry Smith ierr = ISRestoreIndices(IS_inact,&ii);CHKERRQ(ierr); 121613e0d083SBarry Smith 121713e0d083SBarry Smith ierr = PCBJacobiSetTotalBlocks(pc,3,cnts);CHKERRQ(ierr); 121813e0d083SBarry Smith } 121913e0d083SBarry Smith } 122013e0d083SBarry Smith } 122113e0d083SBarry Smith 1222fe835674SShri Abhyankar ierr = SNES_KSPSolve(snes,snes->ksp,F_inact,Y_inact);CHKERRQ(ierr); 1223d950fb63SShri Abhyankar ierr = KSPGetConvergedReason(snes->ksp,&kspreason);CHKERRQ(ierr); 1224d950fb63SShri Abhyankar if (kspreason < 0) { 1225d950fb63SShri Abhyankar if (++snes->numLinearSolveFailures >= snes->maxLinearSolveFailures) { 1226d950fb63SShri 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); 1227d950fb63SShri Abhyankar snes->reason = SNES_DIVERGED_LINEAR_SOLVE; 1228d950fb63SShri Abhyankar break; 1229d950fb63SShri Abhyankar } 1230d950fb63SShri Abhyankar } 1231d950fb63SShri Abhyankar 1232d950fb63SShri Abhyankar ierr = VecScatterBegin(scat_act,Y_act,Y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1233d950fb63SShri Abhyankar ierr = VecScatterEnd(scat_act,Y_act,Y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1234d950fb63SShri Abhyankar ierr = VecScatterBegin(scat_inact,Y_inact,Y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1235d950fb63SShri Abhyankar ierr = VecScatterEnd(scat_inact,Y_inact,Y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1236d950fb63SShri Abhyankar 12376bf464f9SBarry Smith ierr = VecDestroy(&F_inact);CHKERRQ(ierr); 12386bf464f9SBarry Smith ierr = VecDestroy(&Y_act);CHKERRQ(ierr); 12396bf464f9SBarry Smith ierr = VecDestroy(&Y_inact);CHKERRQ(ierr); 12406bf464f9SBarry Smith ierr = VecScatterDestroy(&scat_act);CHKERRQ(ierr); 12416bf464f9SBarry Smith ierr = VecScatterDestroy(&scat_inact);CHKERRQ(ierr); 12426bf464f9SBarry Smith ierr = ISDestroy(&IS_act);CHKERRQ(ierr); 1243abcba341SShri Abhyankar if (!isequal) { 12446bf464f9SBarry Smith ierr = ISDestroy(&vi->IS_inact_prev);CHKERRQ(ierr); 1245abcba341SShri Abhyankar ierr = ISDuplicate(IS_inact,&vi->IS_inact_prev);CHKERRQ(ierr); 1246abcba341SShri Abhyankar } 12476bf464f9SBarry Smith ierr = ISDestroy(&IS_inact);CHKERRQ(ierr); 12486bf464f9SBarry Smith ierr = MatDestroy(&jac_inact_inact);CHKERRQ(ierr); 1249d950fb63SShri Abhyankar if (snes->jacobian != snes->jacobian_pre) { 12506bf464f9SBarry Smith ierr = MatDestroy(&prejac_inact_inact);CHKERRQ(ierr); 1251d950fb63SShri Abhyankar } 1252d950fb63SShri Abhyankar ierr = KSPGetIterationNumber(snes->ksp,&lits);CHKERRQ(ierr); 1253d950fb63SShri Abhyankar snes->linear_its += lits; 1254d950fb63SShri Abhyankar ierr = PetscInfo2(snes,"iter=%D, linear solve iterations=%D\n",snes->iter,lits);CHKERRQ(ierr); 1255d950fb63SShri Abhyankar /* 1256d950fb63SShri Abhyankar if (vi->precheckstep) { 1257d950fb63SShri Abhyankar PetscBool changed_y = PETSC_FALSE; 1258d950fb63SShri Abhyankar ierr = (*vi->precheckstep)(snes,X,Y,vi->precheck,&changed_y);CHKERRQ(ierr); 1259d950fb63SShri Abhyankar } 1260d950fb63SShri Abhyankar 1261d950fb63SShri Abhyankar if (PetscLogPrintInfo){ 1262d950fb63SShri Abhyankar ierr = SNESVICheckResidual_Private(snes,snes->jacobian,F,Y,G,W);CHKERRQ(ierr); 1263d950fb63SShri Abhyankar } 1264d950fb63SShri Abhyankar */ 1265d950fb63SShri Abhyankar /* Compute a (scaled) negative update in the line search routine: 1266d950fb63SShri Abhyankar Y <- X - lambda*Y 1267d950fb63SShri Abhyankar and evaluate G = function(Y) (depends on the line search). 1268d950fb63SShri Abhyankar */ 1269d950fb63SShri Abhyankar ierr = VecCopy(Y,snes->vec_sol_update);CHKERRQ(ierr); 1270fe835674SShri Abhyankar ynorm = 1; gnorm = fnorm; 1271fe835674SShri Abhyankar ierr = (*vi->LineSearch)(snes,vi->lsP,X,F,G,Y,W,fnorm,xnorm,&ynorm,&gnorm,&lssucceed);CHKERRQ(ierr); 1272fe835674SShri Abhyankar ierr = PetscInfo4(snes,"fnorm=%18.16e, gnorm=%18.16e, ynorm=%18.16e, lssucceed=%d\n",fnorm,gnorm,ynorm,(int)lssucceed);CHKERRQ(ierr); 12732b4ed282SShri Abhyankar if (snes->reason == SNES_DIVERGED_FUNCTION_COUNT) break; 12742b4ed282SShri Abhyankar if (snes->domainerror) { 12752b4ed282SShri Abhyankar snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN; 12764c661befSBarry Smith ierr = DMDestroyVI(snes->dm);CHKERRQ(ierr); 12772b4ed282SShri Abhyankar PetscFunctionReturn(0); 12782b4ed282SShri Abhyankar } 12792b4ed282SShri Abhyankar if (!lssucceed) { 12802b4ed282SShri Abhyankar if (++snes->numFailures >= snes->maxFailures) { 12812b4ed282SShri Abhyankar PetscBool ismin; 12822b4ed282SShri Abhyankar snes->reason = SNES_DIVERGED_LINE_SEARCH; 12832b4ed282SShri Abhyankar ierr = SNESVICheckLocalMin_Private(snes,snes->jacobian,G,W,gnorm,&ismin);CHKERRQ(ierr); 12842b4ed282SShri Abhyankar if (ismin) snes->reason = SNES_DIVERGED_LOCAL_MIN; 12852b4ed282SShri Abhyankar break; 12862b4ed282SShri Abhyankar } 12872b4ed282SShri Abhyankar } 12882b4ed282SShri Abhyankar /* Update function and solution vectors */ 1289fe835674SShri Abhyankar fnorm = gnorm; 1290fe835674SShri Abhyankar ierr = VecCopy(G,F);CHKERRQ(ierr); 12912b4ed282SShri Abhyankar ierr = VecCopy(W,X);CHKERRQ(ierr); 12922b4ed282SShri Abhyankar /* Monitor convergence */ 12932b4ed282SShri Abhyankar ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 12942b4ed282SShri Abhyankar snes->iter = i+1; 1295fe835674SShri Abhyankar snes->norm = fnorm; 12962b4ed282SShri Abhyankar ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 12972b4ed282SShri Abhyankar SNESLogConvHistory(snes,snes->norm,lits); 12987a03ce2fSLisandro Dalcin ierr = SNESMonitor(snes,snes->iter,snes->norm);CHKERRQ(ierr); 12992b4ed282SShri Abhyankar /* Test for convergence, xnorm = || X || */ 13002b4ed282SShri Abhyankar if (snes->ops->converged != SNESSkipConverged) { ierr = VecNorm(X,NORM_2,&xnorm);CHKERRQ(ierr); } 1301fe835674SShri Abhyankar ierr = (*snes->ops->converged)(snes,snes->iter,xnorm,ynorm,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); 13022b4ed282SShri Abhyankar if (snes->reason) break; 13032b4ed282SShri Abhyankar } 13044c661befSBarry Smith ierr = DMDestroyVI(snes->dm);CHKERRQ(ierr); 13052b4ed282SShri Abhyankar if (i == maxits) { 13062b4ed282SShri Abhyankar ierr = PetscInfo1(snes,"Maximum number of iterations has been reached: %D\n",maxits);CHKERRQ(ierr); 13072b4ed282SShri Abhyankar if(!snes->reason) snes->reason = SNES_DIVERGED_MAX_IT; 13082b4ed282SShri Abhyankar } 13092b4ed282SShri Abhyankar PetscFunctionReturn(0); 13102b4ed282SShri Abhyankar } 13112b4ed282SShri Abhyankar 13122f63a38cSShri Abhyankar #undef __FUNCT__ 1313720c9a41SShri Abhyankar #define __FUNCT__ "SNESVISetRedundancyCheck" 1314cb5fe31bSShri Abhyankar PetscErrorCode SNESVISetRedundancyCheck(SNES snes,PetscErrorCode (*func)(SNES,IS,IS*,void*),void *ctx) 13152f63a38cSShri Abhyankar { 13162f63a38cSShri Abhyankar SNES_VI *vi = (SNES_VI*)snes->data; 13172f63a38cSShri Abhyankar 13182f63a38cSShri Abhyankar PetscFunctionBegin; 13192f63a38cSShri Abhyankar PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 13202f63a38cSShri Abhyankar vi->checkredundancy = func; 1321cb5fe31bSShri Abhyankar vi->ctxP = ctx; 13222f63a38cSShri Abhyankar PetscFunctionReturn(0); 13232f63a38cSShri Abhyankar } 13242f63a38cSShri Abhyankar 1325ff596062SShri Abhyankar #if defined(PETSC_HAVE_MATLAB_ENGINE) 1326ff596062SShri Abhyankar #include <engine.h> 1327ff596062SShri Abhyankar #include <mex.h> 1328cb5fe31bSShri Abhyankar typedef struct {char *funcname; mxArray *ctx;} SNESMatlabContext; 1329ff596062SShri Abhyankar 1330ff596062SShri Abhyankar #undef __FUNCT__ 1331ff596062SShri Abhyankar #define __FUNCT__ "SNESVIRedundancyCheck_Matlab" 1332ff596062SShri Abhyankar PetscErrorCode SNESVIRedundancyCheck_Matlab(SNES snes,IS is_act,IS* is_redact,void* ctx) 1333ff596062SShri Abhyankar { 1334ff596062SShri Abhyankar PetscErrorCode ierr; 1335cb5fe31bSShri Abhyankar SNESMatlabContext *sctx = (SNESMatlabContext*)ctx; 1336cb5fe31bSShri Abhyankar int nlhs = 1, nrhs = 5; 1337cb5fe31bSShri Abhyankar mxArray *plhs[1], *prhs[5]; 1338cb5fe31bSShri Abhyankar long long int l1 = 0, l2 = 0, ls = 0; 1339fcb1c9afSShri Abhyankar PetscInt *indices=PETSC_NULL; 1340ff596062SShri Abhyankar 1341ff596062SShri Abhyankar PetscFunctionBegin; 1342ff596062SShri Abhyankar PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 1343ff596062SShri Abhyankar PetscValidHeaderSpecific(is_act,IS_CLASSID,2); 1344ff596062SShri Abhyankar PetscValidPointer(is_redact,3); 1345ff596062SShri Abhyankar PetscCheckSameComm(snes,1,is_act,2); 1346ff596062SShri Abhyankar 134709db5ad8SShri Abhyankar /* Create IS for reduced active set of size 0, its size and indices will 134809db5ad8SShri Abhyankar bet set by the Matlab function */ 1349fcb1c9afSShri Abhyankar ierr = ISCreateGeneral(((PetscObject)snes)->comm,0,indices,PETSC_OWN_POINTER,is_redact);CHKERRQ(ierr); 1350cb5fe31bSShri Abhyankar /* call Matlab function in ctx */ 1351ff596062SShri Abhyankar ierr = PetscMemcpy(&ls,&snes,sizeof(snes));CHKERRQ(ierr); 1352ff596062SShri Abhyankar ierr = PetscMemcpy(&l1,&is_act,sizeof(is_act));CHKERRQ(ierr); 1353cb5fe31bSShri Abhyankar ierr = PetscMemcpy(&l2,is_redact,sizeof(is_act));CHKERRQ(ierr); 1354ff596062SShri Abhyankar prhs[0] = mxCreateDoubleScalar((double)ls); 1355ff596062SShri Abhyankar prhs[1] = mxCreateDoubleScalar((double)l1); 1356cb5fe31bSShri Abhyankar prhs[2] = mxCreateDoubleScalar((double)l2); 1357cb5fe31bSShri Abhyankar prhs[3] = mxCreateString(sctx->funcname); 1358cb5fe31bSShri Abhyankar prhs[4] = sctx->ctx; 1359ff596062SShri Abhyankar ierr = mexCallMATLAB(nlhs,plhs,nrhs,prhs,"PetscSNESVIRedundancyCheckInternal");CHKERRQ(ierr); 1360ff596062SShri Abhyankar ierr = mxGetScalar(plhs[0]);CHKERRQ(ierr); 1361ff596062SShri Abhyankar mxDestroyArray(prhs[0]); 1362ff596062SShri Abhyankar mxDestroyArray(prhs[1]); 1363ff596062SShri Abhyankar mxDestroyArray(prhs[2]); 1364ff596062SShri Abhyankar mxDestroyArray(prhs[3]); 1365ff596062SShri Abhyankar mxDestroyArray(plhs[0]); 1366ff596062SShri Abhyankar PetscFunctionReturn(0); 1367ff596062SShri Abhyankar } 1368ff596062SShri Abhyankar 1369ff596062SShri Abhyankar #undef __FUNCT__ 1370ff596062SShri Abhyankar #define __FUNCT__ "SNESVISetRedundancyCheckMatlab" 1371ff596062SShri Abhyankar PetscErrorCode SNESVISetRedundancyCheckMatlab(SNES snes,const char* func,mxArray* ctx) 1372ff596062SShri Abhyankar { 1373ff596062SShri Abhyankar PetscErrorCode ierr; 1374cb5fe31bSShri Abhyankar SNESMatlabContext *sctx; 1375ff596062SShri Abhyankar 1376ff596062SShri Abhyankar PetscFunctionBegin; 1377ff596062SShri Abhyankar /* currently sctx is memory bleed */ 1378cb5fe31bSShri Abhyankar ierr = PetscMalloc(sizeof(SNESMatlabContext),&sctx);CHKERRQ(ierr); 1379ff596062SShri Abhyankar ierr = PetscStrallocpy(func,&sctx->funcname);CHKERRQ(ierr); 1380ff596062SShri Abhyankar sctx->ctx = mxDuplicateArray(ctx); 1381cb5fe31bSShri Abhyankar ierr = SNESVISetRedundancyCheck(snes,SNESVIRedundancyCheck_Matlab,sctx);CHKERRQ(ierr); 1382ff596062SShri Abhyankar PetscFunctionReturn(0); 1383ff596062SShri Abhyankar } 1384ff596062SShri Abhyankar 1385ff596062SShri Abhyankar #endif 1386ff596062SShri Abhyankar 1387ff596062SShri Abhyankar 13882f63a38cSShri Abhyankar /* Variational Inequality solver using augmented space method. It does the opposite of the 13892f63a38cSShri Abhyankar reduced space method i.e. it identifies the active set variables and instead of discarding 1390720c9a41SShri Abhyankar them it augments the original system by introducing additional equality 139156a221efSShri Abhyankar constraint equations for active set variables. The user can optionally provide an IS for 139256a221efSShri Abhyankar a subset of 'redundant' active set variables which will treated as free variables. 13932f63a38cSShri Abhyankar Specific implementation for Allen-Cahn problem 13942f63a38cSShri Abhyankar */ 13952f63a38cSShri Abhyankar #undef __FUNCT__ 1396b350b9c9SBarry Smith #define __FUNCT__ "SNESSolveVI_RSAUG" 1397b350b9c9SBarry Smith PetscErrorCode SNESSolveVI_RSAUG(SNES snes) 13982f63a38cSShri Abhyankar { 13992f63a38cSShri Abhyankar SNES_VI *vi = (SNES_VI*)snes->data; 14002f63a38cSShri Abhyankar PetscErrorCode ierr; 14012f63a38cSShri Abhyankar PetscInt maxits,i,lits; 14022f63a38cSShri Abhyankar PetscBool lssucceed; 14032f63a38cSShri Abhyankar MatStructure flg = DIFFERENT_NONZERO_PATTERN; 14042f63a38cSShri Abhyankar PetscReal fnorm,gnorm,xnorm=0,ynorm; 14052f63a38cSShri Abhyankar Vec Y,X,F,G,W; 14062f63a38cSShri Abhyankar KSPConvergedReason kspreason; 14072f63a38cSShri Abhyankar 14082f63a38cSShri Abhyankar PetscFunctionBegin; 14092f63a38cSShri Abhyankar snes->numFailures = 0; 14102f63a38cSShri Abhyankar snes->numLinearSolveFailures = 0; 14112f63a38cSShri Abhyankar snes->reason = SNES_CONVERGED_ITERATING; 14122f63a38cSShri Abhyankar 14132f63a38cSShri Abhyankar maxits = snes->max_its; /* maximum number of iterations */ 14142f63a38cSShri Abhyankar X = snes->vec_sol; /* solution vector */ 14152f63a38cSShri Abhyankar F = snes->vec_func; /* residual vector */ 14162f63a38cSShri Abhyankar Y = snes->work[0]; /* work vectors */ 14172f63a38cSShri Abhyankar G = snes->work[1]; 14182f63a38cSShri Abhyankar W = snes->work[2]; 14192f63a38cSShri Abhyankar 14202f63a38cSShri Abhyankar ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 14212f63a38cSShri Abhyankar snes->iter = 0; 14222f63a38cSShri Abhyankar snes->norm = 0.0; 14232f63a38cSShri Abhyankar ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 14242f63a38cSShri Abhyankar 14252f63a38cSShri Abhyankar ierr = SNESVIProjectOntoBounds(snes,X);CHKERRQ(ierr); 14262f63a38cSShri Abhyankar ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr); 14272f63a38cSShri Abhyankar if (snes->domainerror) { 14282f63a38cSShri Abhyankar snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN; 14292f63a38cSShri Abhyankar PetscFunctionReturn(0); 14302f63a38cSShri Abhyankar } 14312f63a38cSShri Abhyankar ierr = SNESVIComputeInactiveSetFnorm(snes,F,X,&fnorm);CHKERRQ(ierr); 14322f63a38cSShri Abhyankar ierr = VecNormBegin(X,NORM_2,&xnorm);CHKERRQ(ierr); /* xnorm <- ||x|| */ 14332f63a38cSShri Abhyankar ierr = VecNormEnd(X,NORM_2,&xnorm);CHKERRQ(ierr); 143462cbcd01SMatthew G Knepley if (PetscIsInfOrNanReal(fnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number"); 14352f63a38cSShri Abhyankar 14362f63a38cSShri Abhyankar ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 14372f63a38cSShri Abhyankar snes->norm = fnorm; 14382f63a38cSShri Abhyankar ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 14392f63a38cSShri Abhyankar SNESLogConvHistory(snes,fnorm,0); 14407a03ce2fSLisandro Dalcin ierr = SNESMonitor(snes,0,fnorm);CHKERRQ(ierr); 14412f63a38cSShri Abhyankar 14422f63a38cSShri Abhyankar /* set parameter for default relative tolerance convergence test */ 14432f63a38cSShri Abhyankar snes->ttol = fnorm*snes->rtol; 14442f63a38cSShri Abhyankar /* test convergence */ 14452f63a38cSShri Abhyankar ierr = (*snes->ops->converged)(snes,0,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); 14462f63a38cSShri Abhyankar if (snes->reason) PetscFunctionReturn(0); 14472f63a38cSShri Abhyankar 14482f63a38cSShri Abhyankar for (i=0; i<maxits; i++) { 14492f63a38cSShri Abhyankar IS IS_act,IS_inact; /* _act -> active set _inact -> inactive set */ 1450cb5fe31bSShri Abhyankar IS IS_redact; /* redundant active set */ 145156a221efSShri Abhyankar Mat J_aug,Jpre_aug; 145256a221efSShri Abhyankar Vec F_aug,Y_aug; 145356a221efSShri Abhyankar PetscInt nis_redact,nis_act; 145456a221efSShri Abhyankar const PetscInt *idx_redact,*idx_act; 145556a221efSShri Abhyankar PetscInt k; 145663ee972cSSatish Balay PetscInt *idx_actkept=PETSC_NULL,nkept=0; /* list of kept active set */ 145756a221efSShri Abhyankar PetscScalar *f,*f2; 14582f63a38cSShri Abhyankar PetscBool isequal; 145956a221efSShri Abhyankar PetscInt i1=0,j1=0; 14602f63a38cSShri Abhyankar 14612f63a38cSShri Abhyankar /* Call general purpose update function */ 14622f63a38cSShri Abhyankar if (snes->ops->update) { 14632f63a38cSShri Abhyankar ierr = (*snes->ops->update)(snes, snes->iter);CHKERRQ(ierr); 14642f63a38cSShri Abhyankar } 14652f63a38cSShri Abhyankar ierr = SNESComputeJacobian(snes,X,&snes->jacobian,&snes->jacobian_pre,&flg);CHKERRQ(ierr); 14662f63a38cSShri Abhyankar 14672f63a38cSShri Abhyankar /* Create active and inactive index sets */ 14682f63a38cSShri Abhyankar ierr = SNESVICreateIndexSets_RS(snes,X,F,&IS_act,&IS_inact);CHKERRQ(ierr); 14692f63a38cSShri Abhyankar 147056a221efSShri Abhyankar /* Get local active set size */ 14712f63a38cSShri Abhyankar ierr = ISGetLocalSize(IS_act,&nis_act);CHKERRQ(ierr); 147256a221efSShri Abhyankar if (nis_act) { 1473e63076c7SBarry Smith ierr = ISGetIndices(IS_act,&idx_act);CHKERRQ(ierr); 1474e63076c7SBarry Smith IS_redact = PETSC_NULL; 147556a221efSShri Abhyankar if(vi->checkredundancy) { 1476cb5fe31bSShri Abhyankar (*vi->checkredundancy)(snes,IS_act,&IS_redact,vi->ctxP); 147756a221efSShri Abhyankar } 14782f63a38cSShri Abhyankar 147956a221efSShri Abhyankar if(!IS_redact) { 148056a221efSShri Abhyankar /* User called checkredundancy function but didn't create IS_redact because 148156a221efSShri Abhyankar there were no redundant active set variables */ 148256a221efSShri Abhyankar /* Copy over all active set indices to the list */ 148356a221efSShri Abhyankar ierr = PetscMalloc(nis_act*sizeof(PetscInt),&idx_actkept);CHKERRQ(ierr); 148456a221efSShri Abhyankar for(k=0;k < nis_act;k++) idx_actkept[k] = idx_act[k]; 148556a221efSShri Abhyankar nkept = nis_act; 148656a221efSShri Abhyankar } else { 148756a221efSShri Abhyankar ierr = ISGetLocalSize(IS_redact,&nis_redact);CHKERRQ(ierr); 148856a221efSShri Abhyankar ierr = PetscMalloc((nis_act-nis_redact)*sizeof(PetscInt),&idx_actkept);CHKERRQ(ierr); 14892f63a38cSShri Abhyankar 149056a221efSShri Abhyankar /* Create reduced active set list */ 149156a221efSShri Abhyankar ierr = ISGetIndices(IS_act,&idx_act);CHKERRQ(ierr); 149256a221efSShri Abhyankar ierr = ISGetIndices(IS_redact,&idx_redact);CHKERRQ(ierr); 1493cb5fe31bSShri Abhyankar j1 = 0;nkept = 0; 149456a221efSShri Abhyankar for(k=0;k<nis_act;k++) { 149556a221efSShri Abhyankar if(j1 < nis_redact && idx_act[k] == idx_redact[j1]) j1++; 149656a221efSShri Abhyankar else idx_actkept[nkept++] = idx_act[k]; 149756a221efSShri Abhyankar } 149856a221efSShri Abhyankar ierr = ISRestoreIndices(IS_act,&idx_act);CHKERRQ(ierr); 149956a221efSShri Abhyankar ierr = ISRestoreIndices(IS_redact,&idx_redact);CHKERRQ(ierr); 1500cb5fe31bSShri Abhyankar 1501cb5fe31bSShri Abhyankar ierr = ISDestroy(&IS_redact);CHKERRQ(ierr); 150256a221efSShri Abhyankar } 15032f63a38cSShri Abhyankar 150456a221efSShri Abhyankar /* Create augmented F and Y */ 150556a221efSShri Abhyankar ierr = VecCreate(((PetscObject)snes)->comm,&F_aug);CHKERRQ(ierr); 150656a221efSShri Abhyankar ierr = VecSetSizes(F_aug,F->map->n+nkept,PETSC_DECIDE);CHKERRQ(ierr); 150756a221efSShri Abhyankar ierr = VecSetFromOptions(F_aug);CHKERRQ(ierr); 150856a221efSShri Abhyankar ierr = VecDuplicate(F_aug,&Y_aug);CHKERRQ(ierr); 15092f63a38cSShri Abhyankar 151056a221efSShri Abhyankar /* Copy over F to F_aug in the first n locations */ 151156a221efSShri Abhyankar ierr = VecGetArray(F,&f);CHKERRQ(ierr); 151256a221efSShri Abhyankar ierr = VecGetArray(F_aug,&f2);CHKERRQ(ierr); 151356a221efSShri Abhyankar ierr = PetscMemcpy(f2,f,F->map->n*sizeof(PetscScalar));CHKERRQ(ierr); 151456a221efSShri Abhyankar ierr = VecRestoreArray(F,&f);CHKERRQ(ierr); 151556a221efSShri Abhyankar ierr = VecRestoreArray(F_aug,&f2);CHKERRQ(ierr); 15162f63a38cSShri Abhyankar 151756a221efSShri Abhyankar /* Create the augmented jacobian matrix */ 151856a221efSShri Abhyankar ierr = MatCreate(((PetscObject)snes)->comm,&J_aug);CHKERRQ(ierr); 151956a221efSShri Abhyankar ierr = MatSetSizes(J_aug,X->map->n+nkept,X->map->n+nkept,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr); 152056a221efSShri Abhyankar ierr = MatSetFromOptions(J_aug);CHKERRQ(ierr); 15212f63a38cSShri Abhyankar 152256a221efSShri Abhyankar 15239521db3cSSatish Balay { /* local vars */ 1524493a4f3dSShri Abhyankar /* Preallocate augmented matrix and set values in it...Doing only sequential case first*/ 152556a221efSShri Abhyankar PetscInt ncols; 152656a221efSShri Abhyankar const PetscInt *cols; 152756a221efSShri Abhyankar const PetscScalar *vals; 15282969f145SShri Abhyankar PetscScalar value[2]; 15292969f145SShri Abhyankar PetscInt row,col[2]; 1530493a4f3dSShri Abhyankar PetscInt *d_nnz; 15312969f145SShri Abhyankar value[0] = 1.0; value[1] = 0.0; 1532493a4f3dSShri Abhyankar ierr = PetscMalloc((X->map->n+nkept)*sizeof(PetscInt),&d_nnz);CHKERRQ(ierr); 1533493a4f3dSShri Abhyankar ierr = PetscMemzero(d_nnz,(X->map->n+nkept)*sizeof(PetscInt));CHKERRQ(ierr); 1534493a4f3dSShri Abhyankar for(row=0;row<snes->jacobian->rmap->n;row++) { 1535493a4f3dSShri Abhyankar ierr = MatGetRow(snes->jacobian,row,&ncols,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr); 1536493a4f3dSShri Abhyankar d_nnz[row] += ncols; 1537493a4f3dSShri Abhyankar ierr = MatRestoreRow(snes->jacobian,row,&ncols,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr); 1538493a4f3dSShri Abhyankar } 1539493a4f3dSShri Abhyankar 1540493a4f3dSShri Abhyankar for(k=0;k<nkept;k++) { 1541493a4f3dSShri Abhyankar d_nnz[idx_actkept[k]] += 1; 15422969f145SShri Abhyankar d_nnz[snes->jacobian->rmap->n+k] += 2; 1543493a4f3dSShri Abhyankar } 1544493a4f3dSShri Abhyankar ierr = MatSeqAIJSetPreallocation(J_aug,PETSC_NULL,d_nnz);CHKERRQ(ierr); 1545493a4f3dSShri Abhyankar 1546493a4f3dSShri Abhyankar ierr = PetscFree(d_nnz);CHKERRQ(ierr); 154756a221efSShri Abhyankar 154856a221efSShri Abhyankar /* Set the original jacobian matrix in J_aug */ 154956a221efSShri Abhyankar for(row=0;row<snes->jacobian->rmap->n;row++) { 155056a221efSShri Abhyankar ierr = MatGetRow(snes->jacobian,row,&ncols,&cols,&vals);CHKERRQ(ierr); 155156a221efSShri Abhyankar ierr = MatSetValues(J_aug,1,&row,ncols,cols,vals,INSERT_VALUES);CHKERRQ(ierr); 155256a221efSShri Abhyankar ierr = MatRestoreRow(snes->jacobian,row,&ncols,&cols,&vals);CHKERRQ(ierr); 155356a221efSShri Abhyankar } 155456a221efSShri Abhyankar /* Add the augmented part */ 155556a221efSShri Abhyankar for(k=0;k<nkept;k++) { 15562969f145SShri Abhyankar row = snes->jacobian->rmap->n+k; 15572969f145SShri Abhyankar col[0] = idx_actkept[k]; col[1] = snes->jacobian->rmap->n+k; 15582969f145SShri Abhyankar ierr = MatSetValues(J_aug,1,&row,1,col,value,INSERT_VALUES);CHKERRQ(ierr); 15592969f145SShri Abhyankar ierr = MatSetValues(J_aug,1,&col[0],1,&row,&value[0],INSERT_VALUES);CHKERRQ(ierr); 156056a221efSShri Abhyankar } 156156a221efSShri Abhyankar ierr = MatAssemblyBegin(J_aug,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 156256a221efSShri Abhyankar ierr = MatAssemblyEnd(J_aug,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 156356a221efSShri Abhyankar /* Only considering prejac = jac for now */ 156456a221efSShri Abhyankar Jpre_aug = J_aug; 15659521db3cSSatish Balay } /* local vars*/ 1566e63076c7SBarry Smith ierr = ISRestoreIndices(IS_act,&idx_act);CHKERRQ(ierr); 1567e63076c7SBarry Smith ierr = ISDestroy(&IS_act);CHKERRQ(ierr); 156856a221efSShri Abhyankar } else { 156956a221efSShri Abhyankar F_aug = F; J_aug = snes->jacobian; Y_aug = Y; Jpre_aug = snes->jacobian_pre; 157056a221efSShri Abhyankar } 15712f63a38cSShri Abhyankar 15722f63a38cSShri Abhyankar ierr = ISEqual(vi->IS_inact_prev,IS_inact,&isequal);CHKERRQ(ierr); 15732f63a38cSShri Abhyankar if (!isequal) { 157456a221efSShri Abhyankar ierr = SNESVIResetPCandKSP(snes,J_aug,Jpre_aug);CHKERRQ(ierr); 15752f63a38cSShri Abhyankar } 157656a221efSShri Abhyankar ierr = KSPSetOperators(snes->ksp,J_aug,Jpre_aug,flg);CHKERRQ(ierr); 15772f63a38cSShri Abhyankar ierr = KSPSetUp(snes->ksp);CHKERRQ(ierr); 157856a221efSShri Abhyankar /* { 15792f63a38cSShri Abhyankar PC pc; 15802f63a38cSShri Abhyankar PetscBool flg; 15812f63a38cSShri Abhyankar ierr = KSPGetPC(snes->ksp,&pc);CHKERRQ(ierr); 15822f63a38cSShri Abhyankar ierr = PetscTypeCompare((PetscObject)pc,PCFIELDSPLIT,&flg);CHKERRQ(ierr); 15832f63a38cSShri Abhyankar if (flg) { 15842f63a38cSShri Abhyankar KSP *subksps; 15852f63a38cSShri Abhyankar ierr = PCFieldSplitGetSubKSP(pc,PETSC_NULL,&subksps);CHKERRQ(ierr); 15862f63a38cSShri Abhyankar ierr = KSPGetPC(subksps[0],&pc);CHKERRQ(ierr); 15872f63a38cSShri Abhyankar ierr = PetscFree(subksps);CHKERRQ(ierr); 15882f63a38cSShri Abhyankar ierr = PetscTypeCompare((PetscObject)pc,PCBJACOBI,&flg);CHKERRQ(ierr); 15892f63a38cSShri Abhyankar if (flg) { 15902f63a38cSShri Abhyankar PetscInt n,N = 101*101,j,cnts[3] = {0,0,0}; 15912f63a38cSShri Abhyankar const PetscInt *ii; 15922f63a38cSShri Abhyankar 15932f63a38cSShri Abhyankar ierr = ISGetSize(IS_inact,&n);CHKERRQ(ierr); 15942f63a38cSShri Abhyankar ierr = ISGetIndices(IS_inact,&ii);CHKERRQ(ierr); 15952f63a38cSShri Abhyankar for (j=0; j<n; j++) { 15962f63a38cSShri Abhyankar if (ii[j] < N) cnts[0]++; 15972f63a38cSShri Abhyankar else if (ii[j] < 2*N) cnts[1]++; 15982f63a38cSShri Abhyankar else if (ii[j] < 3*N) cnts[2]++; 15992f63a38cSShri Abhyankar } 16002f63a38cSShri Abhyankar ierr = ISRestoreIndices(IS_inact,&ii);CHKERRQ(ierr); 16012f63a38cSShri Abhyankar 16022f63a38cSShri Abhyankar ierr = PCBJacobiSetTotalBlocks(pc,3,cnts);CHKERRQ(ierr); 16032f63a38cSShri Abhyankar } 16042f63a38cSShri Abhyankar } 16052f63a38cSShri Abhyankar } 160656a221efSShri Abhyankar */ 160756a221efSShri Abhyankar ierr = SNES_KSPSolve(snes,snes->ksp,F_aug,Y_aug);CHKERRQ(ierr); 16082f63a38cSShri Abhyankar ierr = KSPGetConvergedReason(snes->ksp,&kspreason);CHKERRQ(ierr); 16092f63a38cSShri Abhyankar if (kspreason < 0) { 16102f63a38cSShri Abhyankar if (++snes->numLinearSolveFailures >= snes->maxLinearSolveFailures) { 16112f63a38cSShri 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); 16122f63a38cSShri Abhyankar snes->reason = SNES_DIVERGED_LINEAR_SOLVE; 16132f63a38cSShri Abhyankar break; 16142f63a38cSShri Abhyankar } 16152f63a38cSShri Abhyankar } 16162f63a38cSShri Abhyankar 161756a221efSShri Abhyankar if(nis_act) { 161856a221efSShri Abhyankar PetscScalar *y1,*y2; 161956a221efSShri Abhyankar ierr = VecGetArray(Y,&y1);CHKERRQ(ierr); 162056a221efSShri Abhyankar ierr = VecGetArray(Y_aug,&y2);CHKERRQ(ierr); 162156a221efSShri Abhyankar /* Copy over inactive Y_aug to Y */ 162256a221efSShri Abhyankar j1 = 0; 162356a221efSShri Abhyankar for(i1=Y->map->rstart;i1 < Y->map->rend;i1++) { 162456a221efSShri Abhyankar if(j1 < nkept && idx_actkept[j1] == i1) j1++; 162556a221efSShri Abhyankar else y1[i1-Y->map->rstart] = y2[i1-Y->map->rstart]; 162656a221efSShri Abhyankar } 162756a221efSShri Abhyankar ierr = VecRestoreArray(Y,&y1);CHKERRQ(ierr); 162856a221efSShri Abhyankar ierr = VecRestoreArray(Y_aug,&y2);CHKERRQ(ierr); 16292f63a38cSShri Abhyankar 16306bf464f9SBarry Smith ierr = VecDestroy(&F_aug);CHKERRQ(ierr); 16316bf464f9SBarry Smith ierr = VecDestroy(&Y_aug);CHKERRQ(ierr); 16326bf464f9SBarry Smith ierr = MatDestroy(&J_aug);CHKERRQ(ierr); 163356a221efSShri Abhyankar ierr = PetscFree(idx_actkept);CHKERRQ(ierr); 163456a221efSShri Abhyankar } 163556a221efSShri Abhyankar 16362f63a38cSShri Abhyankar if (!isequal) { 16376bf464f9SBarry Smith ierr = ISDestroy(&vi->IS_inact_prev);CHKERRQ(ierr); 16382f63a38cSShri Abhyankar ierr = ISDuplicate(IS_inact,&vi->IS_inact_prev);CHKERRQ(ierr); 16392f63a38cSShri Abhyankar } 16406bf464f9SBarry Smith ierr = ISDestroy(&IS_inact);CHKERRQ(ierr); 164156a221efSShri Abhyankar 16422f63a38cSShri Abhyankar ierr = KSPGetIterationNumber(snes->ksp,&lits);CHKERRQ(ierr); 16432f63a38cSShri Abhyankar snes->linear_its += lits; 16442f63a38cSShri Abhyankar ierr = PetscInfo2(snes,"iter=%D, linear solve iterations=%D\n",snes->iter,lits);CHKERRQ(ierr); 16452f63a38cSShri Abhyankar /* 16462f63a38cSShri Abhyankar if (vi->precheckstep) { 16472f63a38cSShri Abhyankar PetscBool changed_y = PETSC_FALSE; 16482f63a38cSShri Abhyankar ierr = (*vi->precheckstep)(snes,X,Y,vi->precheck,&changed_y);CHKERRQ(ierr); 16492f63a38cSShri Abhyankar } 16502f63a38cSShri Abhyankar 16512f63a38cSShri Abhyankar if (PetscLogPrintInfo){ 16522f63a38cSShri Abhyankar ierr = SNESVICheckResidual_Private(snes,snes->jacobian,F,Y,G,W);CHKERRQ(ierr); 16532f63a38cSShri Abhyankar } 16542f63a38cSShri Abhyankar */ 16552f63a38cSShri Abhyankar /* Compute a (scaled) negative update in the line search routine: 16562f63a38cSShri Abhyankar Y <- X - lambda*Y 16572f63a38cSShri Abhyankar and evaluate G = function(Y) (depends on the line search). 16582f63a38cSShri Abhyankar */ 16592f63a38cSShri Abhyankar ierr = VecCopy(Y,snes->vec_sol_update);CHKERRQ(ierr); 16602f63a38cSShri Abhyankar ynorm = 1; gnorm = fnorm; 16612f63a38cSShri Abhyankar ierr = (*vi->LineSearch)(snes,vi->lsP,X,F,G,Y,W,fnorm,xnorm,&ynorm,&gnorm,&lssucceed);CHKERRQ(ierr); 16622f63a38cSShri Abhyankar ierr = PetscInfo4(snes,"fnorm=%18.16e, gnorm=%18.16e, ynorm=%18.16e, lssucceed=%d\n",fnorm,gnorm,ynorm,(int)lssucceed);CHKERRQ(ierr); 16632f63a38cSShri Abhyankar if (snes->reason == SNES_DIVERGED_FUNCTION_COUNT) break; 16642f63a38cSShri Abhyankar if (snes->domainerror) { 16652f63a38cSShri Abhyankar snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN; 16662f63a38cSShri Abhyankar PetscFunctionReturn(0); 16672f63a38cSShri Abhyankar } 16682f63a38cSShri Abhyankar if (!lssucceed) { 16692f63a38cSShri Abhyankar if (++snes->numFailures >= snes->maxFailures) { 16702f63a38cSShri Abhyankar PetscBool ismin; 16712f63a38cSShri Abhyankar snes->reason = SNES_DIVERGED_LINE_SEARCH; 16722f63a38cSShri Abhyankar ierr = SNESVICheckLocalMin_Private(snes,snes->jacobian,G,W,gnorm,&ismin);CHKERRQ(ierr); 16732f63a38cSShri Abhyankar if (ismin) snes->reason = SNES_DIVERGED_LOCAL_MIN; 16742f63a38cSShri Abhyankar break; 16752f63a38cSShri Abhyankar } 16762f63a38cSShri Abhyankar } 16772f63a38cSShri Abhyankar /* Update function and solution vectors */ 16782f63a38cSShri Abhyankar fnorm = gnorm; 16792f63a38cSShri Abhyankar ierr = VecCopy(G,F);CHKERRQ(ierr); 16802f63a38cSShri Abhyankar ierr = VecCopy(W,X);CHKERRQ(ierr); 16812f63a38cSShri Abhyankar /* Monitor convergence */ 16822f63a38cSShri Abhyankar ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 16832f63a38cSShri Abhyankar snes->iter = i+1; 16842f63a38cSShri Abhyankar snes->norm = fnorm; 16852f63a38cSShri Abhyankar ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 16862f63a38cSShri Abhyankar SNESLogConvHistory(snes,snes->norm,lits); 16877a03ce2fSLisandro Dalcin ierr = SNESMonitor(snes,snes->iter,snes->norm);CHKERRQ(ierr); 16882f63a38cSShri Abhyankar /* Test for convergence, xnorm = || X || */ 16892f63a38cSShri Abhyankar if (snes->ops->converged != SNESSkipConverged) { ierr = VecNorm(X,NORM_2,&xnorm);CHKERRQ(ierr); } 16902f63a38cSShri Abhyankar ierr = (*snes->ops->converged)(snes,snes->iter,xnorm,ynorm,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); 16912f63a38cSShri Abhyankar if (snes->reason) break; 16922f63a38cSShri Abhyankar } 16932f63a38cSShri Abhyankar if (i == maxits) { 16942f63a38cSShri Abhyankar ierr = PetscInfo1(snes,"Maximum number of iterations has been reached: %D\n",maxits);CHKERRQ(ierr); 16952f63a38cSShri Abhyankar if(!snes->reason) snes->reason = SNES_DIVERGED_MAX_IT; 16962f63a38cSShri Abhyankar } 16972f63a38cSShri Abhyankar PetscFunctionReturn(0); 16982f63a38cSShri Abhyankar } 16992f63a38cSShri Abhyankar 17002b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */ 17012b4ed282SShri Abhyankar /* 17022b4ed282SShri Abhyankar SNESSetUp_VI - Sets up the internal data structures for the later use 17032b4ed282SShri Abhyankar of the SNESVI nonlinear solver. 17042b4ed282SShri Abhyankar 17052b4ed282SShri Abhyankar Input Parameter: 17062b4ed282SShri Abhyankar . snes - the SNES context 17072b4ed282SShri Abhyankar . x - the solution vector 17082b4ed282SShri Abhyankar 17092b4ed282SShri Abhyankar Application Interface Routine: SNESSetUp() 17102b4ed282SShri Abhyankar 17112b4ed282SShri Abhyankar Notes: 17122b4ed282SShri Abhyankar For basic use of the SNES solvers, the user need not explicitly call 17132b4ed282SShri Abhyankar SNESSetUp(), since these actions will automatically occur during 17142b4ed282SShri Abhyankar the call to SNESSolve(). 17152b4ed282SShri Abhyankar */ 17162b4ed282SShri Abhyankar #undef __FUNCT__ 17172b4ed282SShri Abhyankar #define __FUNCT__ "SNESSetUp_VI" 17182b4ed282SShri Abhyankar PetscErrorCode SNESSetUp_VI(SNES snes) 17192b4ed282SShri Abhyankar { 17202b4ed282SShri Abhyankar PetscErrorCode ierr; 17212b4ed282SShri Abhyankar SNES_VI *vi = (SNES_VI*) snes->data; 17222b4ed282SShri Abhyankar PetscInt i_start[3],i_end[3]; 17232b4ed282SShri Abhyankar 17242b4ed282SShri Abhyankar PetscFunctionBegin; 172558c9b817SLisandro Dalcin 172658c9b817SLisandro Dalcin ierr = SNESDefaultGetWork(snes,3);CHKERRQ(ierr); 17272b4ed282SShri Abhyankar 17282176524cSBarry Smith if (vi->computevariablebounds) { 17292176524cSBarry Smith ierr = VecDestroy(&vi->xl);CHKERRQ(ierr); 17302176524cSBarry Smith ierr = VecDestroy(&vi->xu);CHKERRQ(ierr); 17312176524cSBarry Smith ierr = (*vi->computevariablebounds)(snes,&vi->xl,&vi->xu);CHKERRQ(ierr); 17322176524cSBarry Smith } else if (!vi->xl && !vi->xu) { 17332176524cSBarry Smith /* If the lower and upper bound on variables are not set, set it to -Inf and Inf */ 17342b4ed282SShri Abhyankar ierr = VecDuplicate(snes->vec_sol, &vi->xl);CHKERRQ(ierr); 173501f0b76bSBarry Smith ierr = VecSet(vi->xl,SNES_VI_NINF);CHKERRQ(ierr); 17362b4ed282SShri Abhyankar ierr = VecDuplicate(snes->vec_sol, &vi->xu);CHKERRQ(ierr); 173701f0b76bSBarry Smith ierr = VecSet(vi->xu,SNES_VI_INF);CHKERRQ(ierr); 17382b4ed282SShri Abhyankar } else { 17392b4ed282SShri Abhyankar /* Check if lower bound, upper bound and solution vector distribution across the processors is identical */ 17402b4ed282SShri Abhyankar ierr = VecGetOwnershipRange(snes->vec_sol,i_start,i_end);CHKERRQ(ierr); 17412b4ed282SShri Abhyankar ierr = VecGetOwnershipRange(vi->xl,i_start+1,i_end+1);CHKERRQ(ierr); 17422b4ed282SShri Abhyankar ierr = VecGetOwnershipRange(vi->xu,i_start+2,i_end+2);CHKERRQ(ierr); 17432b4ed282SShri 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])) 17442b4ed282SShri 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."); 17452b4ed282SShri Abhyankar } 17462f63a38cSShri Abhyankar if (snes->ops->solve != SNESSolveVI_SS) { 1747abcba341SShri Abhyankar /* Set up previous active index set for the first snes solve 1748abcba341SShri Abhyankar vi->IS_inact_prev = 0,1,2,....N */ 1749abcba341SShri Abhyankar PetscInt *indices; 1750abcba341SShri Abhyankar PetscInt i,n,rstart,rend; 1751abcba341SShri Abhyankar 1752abcba341SShri Abhyankar ierr = VecGetOwnershipRange(snes->vec_sol,&rstart,&rend);CHKERRQ(ierr); 1753abcba341SShri Abhyankar ierr = VecGetLocalSize(snes->vec_sol,&n);CHKERRQ(ierr); 1754abcba341SShri Abhyankar ierr = PetscMalloc(n*sizeof(PetscInt),&indices);CHKERRQ(ierr); 1755abcba341SShri Abhyankar for(i=0;i < n; i++) indices[i] = rstart + i; 1756abcba341SShri Abhyankar ierr = ISCreateGeneral(((PetscObject)snes)->comm,n,indices,PETSC_OWN_POINTER,&vi->IS_inact_prev); 1757abcba341SShri Abhyankar } 17582b4ed282SShri Abhyankar 17592f63a38cSShri Abhyankar if (snes->ops->solve == SNESSolveVI_SS) { 1760fe835674SShri Abhyankar ierr = VecDuplicate(snes->vec_sol, &vi->dpsi);CHKERRQ(ierr); 1761fe835674SShri Abhyankar ierr = VecDuplicate(snes->vec_sol, &vi->phi);CHKERRQ(ierr); 1762fe835674SShri Abhyankar ierr = VecDuplicate(snes->vec_sol, &vi->Da);CHKERRQ(ierr); 1763fe835674SShri Abhyankar ierr = VecDuplicate(snes->vec_sol, &vi->Db);CHKERRQ(ierr); 1764fe835674SShri Abhyankar ierr = VecDuplicate(snes->vec_sol, &vi->z);CHKERRQ(ierr); 1765fe835674SShri Abhyankar ierr = VecDuplicate(snes->vec_sol, &vi->t);CHKERRQ(ierr); 1766fe835674SShri Abhyankar } 17672b4ed282SShri Abhyankar PetscFunctionReturn(0); 17682b4ed282SShri Abhyankar } 17692b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */ 17702176524cSBarry Smith #undef __FUNCT__ 17712176524cSBarry Smith #define __FUNCT__ "SNESReset_VI" 17722176524cSBarry Smith PetscErrorCode SNESReset_VI(SNES snes) 17732176524cSBarry Smith { 17742176524cSBarry Smith SNES_VI *vi = (SNES_VI*) snes->data; 17752176524cSBarry Smith PetscErrorCode ierr; 17762176524cSBarry Smith 17772176524cSBarry Smith PetscFunctionBegin; 17782176524cSBarry Smith ierr = VecDestroy(&vi->xl);CHKERRQ(ierr); 17792176524cSBarry Smith ierr = VecDestroy(&vi->xu);CHKERRQ(ierr); 1780d655a5daSBarry Smith if (snes->ops->solve != SNESSolveVI_SS) { 1781d655a5daSBarry Smith ierr = ISDestroy(&vi->IS_inact_prev);CHKERRQ(ierr); 1782d655a5daSBarry Smith } 17832176524cSBarry Smith PetscFunctionReturn(0); 17842176524cSBarry Smith } 17852176524cSBarry Smith 17862b4ed282SShri Abhyankar /* 17872b4ed282SShri Abhyankar SNESDestroy_VI - Destroys the private SNES_VI context that was created 17882b4ed282SShri Abhyankar with SNESCreate_VI(). 17892b4ed282SShri Abhyankar 17902b4ed282SShri Abhyankar Input Parameter: 17912b4ed282SShri Abhyankar . snes - the SNES context 17922b4ed282SShri Abhyankar 17932b4ed282SShri Abhyankar Application Interface Routine: SNESDestroy() 17942b4ed282SShri Abhyankar */ 17952b4ed282SShri Abhyankar #undef __FUNCT__ 17962b4ed282SShri Abhyankar #define __FUNCT__ "SNESDestroy_VI" 17972b4ed282SShri Abhyankar PetscErrorCode SNESDestroy_VI(SNES snes) 17982b4ed282SShri Abhyankar { 17992b4ed282SShri Abhyankar SNES_VI *vi = (SNES_VI*) snes->data; 18002b4ed282SShri Abhyankar PetscErrorCode ierr; 18012b4ed282SShri Abhyankar 18022b4ed282SShri Abhyankar PetscFunctionBegin; 18032b4ed282SShri Abhyankar 18042f63a38cSShri Abhyankar if (snes->ops->solve == SNESSolveVI_SS) { 18052b4ed282SShri Abhyankar /* clear vectors */ 18066bf464f9SBarry Smith ierr = VecDestroy(&vi->dpsi);CHKERRQ(ierr); 18076bf464f9SBarry Smith ierr = VecDestroy(&vi->phi);CHKERRQ(ierr); 18086bf464f9SBarry Smith ierr = VecDestroy(&vi->Da);CHKERRQ(ierr); 18096bf464f9SBarry Smith ierr = VecDestroy(&vi->Db);CHKERRQ(ierr); 18106bf464f9SBarry Smith ierr = VecDestroy(&vi->z);CHKERRQ(ierr); 18116bf464f9SBarry Smith ierr = VecDestroy(&vi->t);CHKERRQ(ierr); 18127fe79bc4SShri Abhyankar } 18137fe79bc4SShri Abhyankar 18146bf464f9SBarry Smith ierr = PetscViewerASCIIMonitorDestroy(&vi->lsmonitor);CHKERRQ(ierr); 18152b4ed282SShri Abhyankar ierr = PetscFree(snes->data);CHKERRQ(ierr); 18162b4ed282SShri Abhyankar 18172b4ed282SShri Abhyankar /* clear composed functions */ 18182b4ed282SShri Abhyankar ierr = PetscObjectComposeFunctionDynamic((PetscObject)snes,"SNESLineSearchSet_C","",PETSC_NULL);CHKERRQ(ierr); 1819c92abb8aSShri Abhyankar ierr = PetscObjectComposeFunctionDynamic((PetscObject)snes,"SNESLineSearchSetMonitor_C","",PETSC_NULL);CHKERRQ(ierr); 18202b4ed282SShri Abhyankar PetscFunctionReturn(0); 18212b4ed282SShri Abhyankar } 18227fe79bc4SShri Abhyankar 18232b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */ 18242b4ed282SShri Abhyankar #undef __FUNCT__ 18252b4ed282SShri Abhyankar #define __FUNCT__ "SNESLineSearchNo_VI" 18262b4ed282SShri Abhyankar 18272b4ed282SShri Abhyankar /* 18287fe79bc4SShri Abhyankar This routine does not actually do a line search but it takes a full newton 18297fe79bc4SShri Abhyankar step while ensuring that the new iterates remain within the constraints. 18302b4ed282SShri Abhyankar 18312b4ed282SShri Abhyankar */ 1832ace3abfcSBarry 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) 18332b4ed282SShri Abhyankar { 18342b4ed282SShri Abhyankar PetscErrorCode ierr; 18352b4ed282SShri Abhyankar SNES_VI *vi = (SNES_VI*)snes->data; 1836ace3abfcSBarry Smith PetscBool changed_w = PETSC_FALSE,changed_y = PETSC_FALSE; 18372b4ed282SShri Abhyankar 18382b4ed282SShri Abhyankar PetscFunctionBegin; 18392b4ed282SShri Abhyankar *flag = PETSC_TRUE; 18402b4ed282SShri Abhyankar ierr = PetscLogEventBegin(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); 18412b4ed282SShri Abhyankar ierr = VecNorm(y,NORM_2,ynorm);CHKERRQ(ierr); /* ynorm = || y || */ 18422b4ed282SShri Abhyankar ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr); /* w <- x - y */ 1843c1a5e521SShri Abhyankar ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr); 1844c1a5e521SShri Abhyankar if (vi->postcheckstep) { 1845c1a5e521SShri Abhyankar ierr = (*vi->postcheckstep)(snes,x,y,w,vi->postcheck,&changed_y,&changed_w);CHKERRQ(ierr); 1846c1a5e521SShri Abhyankar } 1847c1a5e521SShri Abhyankar if (changed_y) { 1848c1a5e521SShri Abhyankar ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr); /* w <- x - y */ 18497fe79bc4SShri Abhyankar ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr); 1850c1a5e521SShri Abhyankar } 1851c1a5e521SShri Abhyankar ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr); 1852c1a5e521SShri Abhyankar ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr); 1853c1a5e521SShri Abhyankar if (!snes->domainerror) { 18542f63a38cSShri Abhyankar if (snes->ops->solve != SNESSolveVI_SS) { 18557fe79bc4SShri Abhyankar ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr); 18567fe79bc4SShri Abhyankar } else { 1857c1a5e521SShri Abhyankar ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr); /* gnorm = || g || */ 18587fe79bc4SShri Abhyankar } 185962cbcd01SMatthew G Knepley if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number"); 1860c1a5e521SShri Abhyankar } 1861c1a5e521SShri Abhyankar if (vi->lsmonitor) { 1862c1a5e521SShri Abhyankar ierr = PetscViewerASCIIMonitorPrintf(vi->lsmonitor," Line search: Using full step: fnorm %G gnorm %G\n",fnorm,*gnorm);CHKERRQ(ierr); 1863c1a5e521SShri Abhyankar } 1864c1a5e521SShri Abhyankar ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); 1865c1a5e521SShri Abhyankar PetscFunctionReturn(0); 1866c1a5e521SShri Abhyankar } 1867c1a5e521SShri Abhyankar 1868c1a5e521SShri Abhyankar /* -------------------------------------------------------------------------- */ 1869c1a5e521SShri Abhyankar #undef __FUNCT__ 18702b4ed282SShri Abhyankar #define __FUNCT__ "SNESLineSearchNoNorms_VI" 18712b4ed282SShri Abhyankar 18722b4ed282SShri Abhyankar /* 18732b4ed282SShri Abhyankar This routine is a copy of SNESLineSearchNoNorms in snes/impls/ls/ls.c 18742b4ed282SShri Abhyankar */ 1875ace3abfcSBarry 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) 18762b4ed282SShri Abhyankar { 18772b4ed282SShri Abhyankar PetscErrorCode ierr; 18782b4ed282SShri Abhyankar SNES_VI *vi = (SNES_VI*)snes->data; 1879ace3abfcSBarry Smith PetscBool changed_w = PETSC_FALSE,changed_y = PETSC_FALSE; 18802b4ed282SShri Abhyankar 18812b4ed282SShri Abhyankar PetscFunctionBegin; 18822b4ed282SShri Abhyankar *flag = PETSC_TRUE; 18832b4ed282SShri Abhyankar ierr = PetscLogEventBegin(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); 18842b4ed282SShri Abhyankar ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr); /* w <- x - y */ 18857fe79bc4SShri Abhyankar ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr); 18862b4ed282SShri Abhyankar if (vi->postcheckstep) { 18872b4ed282SShri Abhyankar ierr = (*vi->postcheckstep)(snes,x,y,w,vi->postcheck,&changed_y,&changed_w);CHKERRQ(ierr); 18882b4ed282SShri Abhyankar } 18892b4ed282SShri Abhyankar if (changed_y) { 18902b4ed282SShri Abhyankar ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr); /* w <- x - y */ 18917fe79bc4SShri Abhyankar ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr); 18922b4ed282SShri Abhyankar } 18932b4ed282SShri Abhyankar 18942b4ed282SShri Abhyankar /* don't evaluate function the last time through */ 18952b4ed282SShri Abhyankar if (snes->iter < snes->max_its-1) { 18962b4ed282SShri Abhyankar ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr); 18972b4ed282SShri Abhyankar } 18982b4ed282SShri Abhyankar ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); 18992b4ed282SShri Abhyankar PetscFunctionReturn(0); 19002b4ed282SShri Abhyankar } 19017fe79bc4SShri Abhyankar 19022b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */ 19032b4ed282SShri Abhyankar #undef __FUNCT__ 19042b4ed282SShri Abhyankar #define __FUNCT__ "SNESLineSearchCubic_VI" 19052b4ed282SShri Abhyankar /* 19067fe79bc4SShri Abhyankar This routine implements a cubic line search while doing a projection on the variable bounds 19072b4ed282SShri Abhyankar */ 1908ace3abfcSBarry 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) 19092b4ed282SShri Abhyankar { 1910fe835674SShri Abhyankar PetscReal initslope,lambdaprev,gnormprev,a,b,d,t1,t2,rellength; 1911fe835674SShri Abhyankar PetscReal minlambda,lambda,lambdatemp; 1912fe835674SShri Abhyankar #if defined(PETSC_USE_COMPLEX) 1913fe835674SShri Abhyankar PetscScalar cinitslope; 1914fe835674SShri Abhyankar #endif 1915fe835674SShri Abhyankar PetscErrorCode ierr; 1916fe835674SShri Abhyankar PetscInt count; 1917fe835674SShri Abhyankar SNES_VI *vi = (SNES_VI*)snes->data; 1918fe835674SShri Abhyankar PetscBool changed_w = PETSC_FALSE,changed_y = PETSC_FALSE; 1919fe835674SShri Abhyankar MPI_Comm comm; 1920fe835674SShri Abhyankar 1921fe835674SShri Abhyankar PetscFunctionBegin; 1922fe835674SShri Abhyankar ierr = PetscObjectGetComm((PetscObject)snes,&comm);CHKERRQ(ierr); 1923fe835674SShri Abhyankar ierr = PetscLogEventBegin(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); 1924fe835674SShri Abhyankar *flag = PETSC_TRUE; 1925fe835674SShri Abhyankar 1926fe835674SShri Abhyankar ierr = VecNorm(y,NORM_2,ynorm);CHKERRQ(ierr); 1927fe835674SShri Abhyankar if (*ynorm == 0.0) { 1928fe835674SShri Abhyankar if (vi->lsmonitor) { 1929fe835674SShri Abhyankar ierr = PetscViewerASCIIMonitorPrintf(vi->lsmonitor," Line search: Initial direction and size is 0\n");CHKERRQ(ierr); 1930fe835674SShri Abhyankar } 1931fe835674SShri Abhyankar *gnorm = fnorm; 1932fe835674SShri Abhyankar ierr = VecCopy(x,w);CHKERRQ(ierr); 1933fe835674SShri Abhyankar ierr = VecCopy(f,g);CHKERRQ(ierr); 1934fe835674SShri Abhyankar *flag = PETSC_FALSE; 1935fe835674SShri Abhyankar goto theend1; 1936fe835674SShri Abhyankar } 1937fe835674SShri Abhyankar if (*ynorm > vi->maxstep) { /* Step too big, so scale back */ 1938fe835674SShri Abhyankar if (vi->lsmonitor) { 1939fe835674SShri Abhyankar ierr = PetscViewerASCIIMonitorPrintf(vi->lsmonitor," Line search: Scaling step by %G old ynorm %G\n",vi->maxstep/(*ynorm),*ynorm);CHKERRQ(ierr); 1940fe835674SShri Abhyankar } 1941fe835674SShri Abhyankar ierr = VecScale(y,vi->maxstep/(*ynorm));CHKERRQ(ierr); 1942fe835674SShri Abhyankar *ynorm = vi->maxstep; 1943fe835674SShri Abhyankar } 1944fe835674SShri Abhyankar ierr = VecMaxPointwiseDivide(y,x,&rellength);CHKERRQ(ierr); 1945fe835674SShri Abhyankar minlambda = vi->minlambda/rellength; 1946fe835674SShri Abhyankar ierr = MatMult(snes->jacobian,y,w);CHKERRQ(ierr); 1947fe835674SShri Abhyankar #if defined(PETSC_USE_COMPLEX) 1948fe835674SShri Abhyankar ierr = VecDot(f,w,&cinitslope);CHKERRQ(ierr); 1949fe835674SShri Abhyankar initslope = PetscRealPart(cinitslope); 1950fe835674SShri Abhyankar #else 1951fe835674SShri Abhyankar ierr = VecDot(f,w,&initslope);CHKERRQ(ierr); 1952fe835674SShri Abhyankar #endif 1953fe835674SShri Abhyankar if (initslope > 0.0) initslope = -initslope; 1954fe835674SShri Abhyankar if (initslope == 0.0) initslope = -1.0; 1955fe835674SShri Abhyankar 1956fe835674SShri Abhyankar ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr); 1957fe835674SShri Abhyankar ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr); 1958fe835674SShri Abhyankar if (snes->nfuncs >= snes->max_funcs) { 1959fe835674SShri Abhyankar ierr = PetscInfo(snes,"Exceeded maximum function evaluations, while checking full step length!\n");CHKERRQ(ierr); 1960fe835674SShri Abhyankar *flag = PETSC_FALSE; 1961fe835674SShri Abhyankar snes->reason = SNES_DIVERGED_FUNCTION_COUNT; 1962fe835674SShri Abhyankar goto theend1; 1963fe835674SShri Abhyankar } 1964fe835674SShri Abhyankar ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr); 19652f63a38cSShri Abhyankar if (snes->ops->solve != SNESSolveVI_SS) { 1966fe835674SShri Abhyankar ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr); 19677fe79bc4SShri Abhyankar } else { 19687fe79bc4SShri Abhyankar ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr); 19697fe79bc4SShri Abhyankar } 1970fe835674SShri Abhyankar if (snes->domainerror) { 1971fe835674SShri Abhyankar ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); 1972fe835674SShri Abhyankar PetscFunctionReturn(0); 1973fe835674SShri Abhyankar } 197462cbcd01SMatthew G Knepley if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number"); 1975fe835674SShri Abhyankar ierr = PetscInfo2(snes,"Initial fnorm %G gnorm %G\n",fnorm,*gnorm);CHKERRQ(ierr); 1976fe835674SShri Abhyankar if (.5*(*gnorm)*(*gnorm) <= .5*fnorm*fnorm + vi->alpha*initslope) { /* Sufficient reduction */ 1977fe835674SShri Abhyankar if (vi->lsmonitor) { 1978fe835674SShri Abhyankar ierr = PetscViewerASCIIMonitorPrintf(vi->lsmonitor," Line search: Using full step: fnorm %G gnorm %G\n",fnorm,*gnorm);CHKERRQ(ierr); 1979fe835674SShri Abhyankar } 1980fe835674SShri Abhyankar goto theend1; 1981fe835674SShri Abhyankar } 1982fe835674SShri Abhyankar 1983fe835674SShri Abhyankar /* Fit points with quadratic */ 1984fe835674SShri Abhyankar lambda = 1.0; 1985fe835674SShri Abhyankar lambdatemp = -initslope/((*gnorm)*(*gnorm) - fnorm*fnorm - 2.0*initslope); 1986fe835674SShri Abhyankar lambdaprev = lambda; 1987fe835674SShri Abhyankar gnormprev = *gnorm; 1988fe835674SShri Abhyankar if (lambdatemp > .5*lambda) lambdatemp = .5*lambda; 1989fe835674SShri Abhyankar if (lambdatemp <= .1*lambda) lambda = .1*lambda; 1990fe835674SShri Abhyankar else lambda = lambdatemp; 1991fe835674SShri Abhyankar 1992fe835674SShri Abhyankar ierr = VecWAXPY(w,-lambda,y,x);CHKERRQ(ierr); 1993fe835674SShri Abhyankar ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr); 1994fe835674SShri Abhyankar if (snes->nfuncs >= snes->max_funcs) { 1995fe835674SShri Abhyankar ierr = PetscInfo1(snes,"Exceeded maximum function evaluations, while attempting quadratic backtracking! %D \n",snes->nfuncs);CHKERRQ(ierr); 1996fe835674SShri Abhyankar *flag = PETSC_FALSE; 1997fe835674SShri Abhyankar snes->reason = SNES_DIVERGED_FUNCTION_COUNT; 1998fe835674SShri Abhyankar goto theend1; 1999fe835674SShri Abhyankar } 2000fe835674SShri Abhyankar ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr); 20012f63a38cSShri Abhyankar if (snes->ops->solve != SNESSolveVI_SS) { 2002fe835674SShri Abhyankar ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr); 20037fe79bc4SShri Abhyankar } else { 20047fe79bc4SShri Abhyankar ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr); 20057fe79bc4SShri Abhyankar } 2006fe835674SShri Abhyankar if (snes->domainerror) { 2007fe835674SShri Abhyankar ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); 2008fe835674SShri Abhyankar PetscFunctionReturn(0); 2009fe835674SShri Abhyankar } 201062cbcd01SMatthew G Knepley if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number"); 2011fe835674SShri Abhyankar if (vi->lsmonitor) { 2012fe835674SShri Abhyankar ierr = PetscViewerASCIIMonitorPrintf(vi->lsmonitor," Line search: gnorm after quadratic fit %G\n",*gnorm);CHKERRQ(ierr); 2013fe835674SShri Abhyankar } 2014fe835674SShri Abhyankar if (.5*(*gnorm)*(*gnorm) < .5*fnorm*fnorm + lambda*vi->alpha*initslope) { /* sufficient reduction */ 2015fe835674SShri Abhyankar if (vi->lsmonitor) { 2016fe835674SShri Abhyankar ierr = PetscViewerASCIIMonitorPrintf(vi->lsmonitor," Line search: Quadratically determined step, lambda=%18.16e\n",lambda);CHKERRQ(ierr); 2017fe835674SShri Abhyankar } 2018fe835674SShri Abhyankar goto theend1; 2019fe835674SShri Abhyankar } 2020fe835674SShri Abhyankar 2021fe835674SShri Abhyankar /* Fit points with cubic */ 2022fe835674SShri Abhyankar count = 1; 2023fe835674SShri Abhyankar while (PETSC_TRUE) { 2024fe835674SShri Abhyankar if (lambda <= minlambda) { 2025fe835674SShri Abhyankar if (vi->lsmonitor) { 2026fe835674SShri Abhyankar ierr = PetscViewerASCIIMonitorPrintf(vi->lsmonitor," Line search: unable to find good step length! After %D tries \n",count);CHKERRQ(ierr); 2027fe835674SShri 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); 2028fe835674SShri Abhyankar } 2029fe835674SShri Abhyankar *flag = PETSC_FALSE; 2030fe835674SShri Abhyankar break; 2031fe835674SShri Abhyankar } 2032fe835674SShri Abhyankar t1 = .5*((*gnorm)*(*gnorm) - fnorm*fnorm) - lambda*initslope; 2033fe835674SShri Abhyankar t2 = .5*(gnormprev*gnormprev - fnorm*fnorm) - lambdaprev*initslope; 2034fe835674SShri Abhyankar a = (t1/(lambda*lambda) - t2/(lambdaprev*lambdaprev))/(lambda-lambdaprev); 2035fe835674SShri Abhyankar b = (-lambdaprev*t1/(lambda*lambda) + lambda*t2/(lambdaprev*lambdaprev))/(lambda-lambdaprev); 2036fe835674SShri Abhyankar d = b*b - 3*a*initslope; 2037fe835674SShri Abhyankar if (d < 0.0) d = 0.0; 2038fe835674SShri Abhyankar if (a == 0.0) { 2039fe835674SShri Abhyankar lambdatemp = -initslope/(2.0*b); 2040fe835674SShri Abhyankar } else { 2041fe835674SShri Abhyankar lambdatemp = (-b + sqrt(d))/(3.0*a); 2042fe835674SShri Abhyankar } 2043fe835674SShri Abhyankar lambdaprev = lambda; 2044fe835674SShri Abhyankar gnormprev = *gnorm; 2045fe835674SShri Abhyankar if (lambdatemp > .5*lambda) lambdatemp = .5*lambda; 2046fe835674SShri Abhyankar if (lambdatemp <= .1*lambda) lambda = .1*lambda; 2047fe835674SShri Abhyankar else lambda = lambdatemp; 2048fe835674SShri Abhyankar ierr = VecWAXPY(w,-lambda,y,x);CHKERRQ(ierr); 2049fe835674SShri Abhyankar ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr); 2050fe835674SShri Abhyankar if (snes->nfuncs >= snes->max_funcs) { 2051fe835674SShri Abhyankar ierr = PetscInfo1(snes,"Exceeded maximum function evaluations, while looking for good step length! %D \n",count);CHKERRQ(ierr); 2052fe835674SShri 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); 2053fe835674SShri Abhyankar *flag = PETSC_FALSE; 2054fe835674SShri Abhyankar snes->reason = SNES_DIVERGED_FUNCTION_COUNT; 2055fe835674SShri Abhyankar break; 2056fe835674SShri Abhyankar } 2057fe835674SShri Abhyankar ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr); 20582f63a38cSShri Abhyankar if (snes->ops->solve != SNESSolveVI_SS) { 2059fe835674SShri Abhyankar ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr); 20607fe79bc4SShri Abhyankar } else { 20617fe79bc4SShri Abhyankar ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr); 20627fe79bc4SShri Abhyankar } 2063fe835674SShri Abhyankar if (snes->domainerror) { 2064fe835674SShri Abhyankar ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); 2065fe835674SShri Abhyankar PetscFunctionReturn(0); 2066fe835674SShri Abhyankar } 206762cbcd01SMatthew G Knepley if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number"); 2068fe835674SShri Abhyankar if (.5*(*gnorm)*(*gnorm) < .5*fnorm*fnorm + lambda*vi->alpha*initslope) { /* is reduction enough? */ 2069fe835674SShri Abhyankar if (vi->lsmonitor) { 2070fe835674SShri Abhyankar ierr = PetscPrintf(comm," Line search: Cubically determined step, current gnorm %G lambda=%18.16e\n",*gnorm,lambda);CHKERRQ(ierr); 2071fe835674SShri Abhyankar } 2072fe835674SShri Abhyankar break; 2073fe835674SShri Abhyankar } else { 2074fe835674SShri Abhyankar if (vi->lsmonitor) { 2075fe835674SShri Abhyankar ierr = PetscPrintf(comm," Line search: Cubic step no good, shrinking lambda, current gnorm %G lambda=%18.16e\n",*gnorm,lambda);CHKERRQ(ierr); 2076fe835674SShri Abhyankar } 2077fe835674SShri Abhyankar } 2078fe835674SShri Abhyankar count++; 2079fe835674SShri Abhyankar } 2080fe835674SShri Abhyankar theend1: 2081fe835674SShri Abhyankar /* Optional user-defined check for line search step validity */ 2082fe835674SShri Abhyankar if (vi->postcheckstep && *flag) { 2083fe835674SShri Abhyankar ierr = (*vi->postcheckstep)(snes,x,y,w,vi->postcheck,&changed_y,&changed_w);CHKERRQ(ierr); 2084fe835674SShri Abhyankar if (changed_y) { 2085fe835674SShri Abhyankar ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr); 2086fe835674SShri Abhyankar ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr); 2087fe835674SShri Abhyankar } 2088fe835674SShri Abhyankar if (changed_y || changed_w) { /* recompute the function if the step has changed */ 2089fe835674SShri Abhyankar ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr); 20902f63a38cSShri Abhyankar if (snes->ops->solve != SNESSolveVI_SS) { 2091fe835674SShri Abhyankar ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr); 20927fe79bc4SShri Abhyankar } else { 20937fe79bc4SShri Abhyankar ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr); 20947fe79bc4SShri Abhyankar } 2095fe835674SShri Abhyankar if (snes->domainerror) { 2096fe835674SShri Abhyankar ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); 2097fe835674SShri Abhyankar PetscFunctionReturn(0); 2098fe835674SShri Abhyankar } 209962cbcd01SMatthew G Knepley if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number"); 2100fe835674SShri Abhyankar ierr = VecNormBegin(y,NORM_2,ynorm);CHKERRQ(ierr); 2101fe835674SShri Abhyankar ierr = VecNormEnd(y,NORM_2,ynorm);CHKERRQ(ierr); 2102fe835674SShri Abhyankar } 2103fe835674SShri Abhyankar } 2104fe835674SShri Abhyankar ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); 2105fe835674SShri Abhyankar PetscFunctionReturn(0); 2106fe835674SShri Abhyankar } 2107fe835674SShri Abhyankar 21082b4ed282SShri Abhyankar #undef __FUNCT__ 21092b4ed282SShri Abhyankar #define __FUNCT__ "SNESLineSearchQuadratic_VI" 21102b4ed282SShri Abhyankar /* 21117fe79bc4SShri Abhyankar This routine does a quadratic line search while keeping the iterates within the variable bounds 21122b4ed282SShri Abhyankar */ 2113ace3abfcSBarry 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) 21142b4ed282SShri Abhyankar { 21152b4ed282SShri Abhyankar /* 21162b4ed282SShri Abhyankar Note that for line search purposes we work with with the related 21172b4ed282SShri Abhyankar minimization problem: 21182b4ed282SShri Abhyankar min z(x): R^n -> R, 21192b4ed282SShri Abhyankar where z(x) = .5 * fnorm*fnorm,and fnorm = || f ||_2. 21202b4ed282SShri Abhyankar */ 21212b4ed282SShri Abhyankar PetscReal initslope,minlambda,lambda,lambdatemp,rellength; 21222b4ed282SShri Abhyankar #if defined(PETSC_USE_COMPLEX) 21232b4ed282SShri Abhyankar PetscScalar cinitslope; 21242b4ed282SShri Abhyankar #endif 21252b4ed282SShri Abhyankar PetscErrorCode ierr; 21262b4ed282SShri Abhyankar PetscInt count; 21272b4ed282SShri Abhyankar SNES_VI *vi = (SNES_VI*)snes->data; 2128ace3abfcSBarry Smith PetscBool changed_w = PETSC_FALSE,changed_y = PETSC_FALSE; 21292b4ed282SShri Abhyankar 21302b4ed282SShri Abhyankar PetscFunctionBegin; 21312b4ed282SShri Abhyankar ierr = PetscLogEventBegin(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); 21322b4ed282SShri Abhyankar *flag = PETSC_TRUE; 21332b4ed282SShri Abhyankar 21342b4ed282SShri Abhyankar ierr = VecNorm(y,NORM_2,ynorm);CHKERRQ(ierr); 21352b4ed282SShri Abhyankar if (*ynorm == 0.0) { 2136c92abb8aSShri Abhyankar if (vi->lsmonitor) { 2137c92abb8aSShri Abhyankar ierr = PetscViewerASCIIMonitorPrintf(vi->lsmonitor,"Line search: Direction and size is 0\n");CHKERRQ(ierr); 21382b4ed282SShri Abhyankar } 21392b4ed282SShri Abhyankar *gnorm = fnorm; 21402b4ed282SShri Abhyankar ierr = VecCopy(x,w);CHKERRQ(ierr); 21412b4ed282SShri Abhyankar ierr = VecCopy(f,g);CHKERRQ(ierr); 21422b4ed282SShri Abhyankar *flag = PETSC_FALSE; 21432b4ed282SShri Abhyankar goto theend2; 21442b4ed282SShri Abhyankar } 21452b4ed282SShri Abhyankar if (*ynorm > vi->maxstep) { /* Step too big, so scale back */ 21462b4ed282SShri Abhyankar ierr = VecScale(y,vi->maxstep/(*ynorm));CHKERRQ(ierr); 21472b4ed282SShri Abhyankar *ynorm = vi->maxstep; 21482b4ed282SShri Abhyankar } 21492b4ed282SShri Abhyankar ierr = VecMaxPointwiseDivide(y,x,&rellength);CHKERRQ(ierr); 21502b4ed282SShri Abhyankar minlambda = vi->minlambda/rellength; 21517fe79bc4SShri Abhyankar ierr = MatMult(snes->jacobian,y,w);CHKERRQ(ierr); 21522b4ed282SShri Abhyankar #if defined(PETSC_USE_COMPLEX) 21537fe79bc4SShri Abhyankar ierr = VecDot(f,w,&cinitslope);CHKERRQ(ierr); 21542b4ed282SShri Abhyankar initslope = PetscRealPart(cinitslope); 21552b4ed282SShri Abhyankar #else 21567fe79bc4SShri Abhyankar ierr = VecDot(f,w,&initslope);CHKERRQ(ierr); 21572b4ed282SShri Abhyankar #endif 21582b4ed282SShri Abhyankar if (initslope > 0.0) initslope = -initslope; 21592b4ed282SShri Abhyankar if (initslope == 0.0) initslope = -1.0; 21602b4ed282SShri Abhyankar ierr = PetscInfo1(snes,"Initslope %G \n",initslope);CHKERRQ(ierr); 21612b4ed282SShri Abhyankar 21622b4ed282SShri Abhyankar ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr); 21637fe79bc4SShri Abhyankar ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr); 21642b4ed282SShri Abhyankar if (snes->nfuncs >= snes->max_funcs) { 21652b4ed282SShri Abhyankar ierr = PetscInfo(snes,"Exceeded maximum function evaluations, while checking full step length!\n");CHKERRQ(ierr); 21662b4ed282SShri Abhyankar *flag = PETSC_FALSE; 21672b4ed282SShri Abhyankar snes->reason = SNES_DIVERGED_FUNCTION_COUNT; 21682b4ed282SShri Abhyankar goto theend2; 21692b4ed282SShri Abhyankar } 21702b4ed282SShri Abhyankar ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr); 21712f63a38cSShri Abhyankar if (snes->ops->solve != SNESSolveVI_SS) { 21727fe79bc4SShri Abhyankar ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr); 21737fe79bc4SShri Abhyankar } else { 21747fe79bc4SShri Abhyankar ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr); 21757fe79bc4SShri Abhyankar } 21762b4ed282SShri Abhyankar if (snes->domainerror) { 21772b4ed282SShri Abhyankar ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); 21782b4ed282SShri Abhyankar PetscFunctionReturn(0); 21792b4ed282SShri Abhyankar } 218062cbcd01SMatthew G Knepley if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number"); 21812b4ed282SShri Abhyankar if (.5*(*gnorm)*(*gnorm) <= .5*fnorm*fnorm + vi->alpha*initslope) { /* Sufficient reduction */ 2182c92abb8aSShri Abhyankar if (vi->lsmonitor) { 2183c92abb8aSShri Abhyankar ierr = PetscViewerASCIIMonitorPrintf(vi->lsmonitor," Line search: Using full step: fnorm %G gnorm %G\n",fnorm,*gnorm);CHKERRQ(ierr); 21842b4ed282SShri Abhyankar } 21852b4ed282SShri Abhyankar goto theend2; 21862b4ed282SShri Abhyankar } 21872b4ed282SShri Abhyankar 21882b4ed282SShri Abhyankar /* Fit points with quadratic */ 21892b4ed282SShri Abhyankar lambda = 1.0; 21902b4ed282SShri Abhyankar count = 1; 21912b4ed282SShri Abhyankar while (PETSC_TRUE) { 21922b4ed282SShri Abhyankar if (lambda <= minlambda) { /* bad luck; use full step */ 2193c92abb8aSShri Abhyankar if (vi->lsmonitor) { 2194c92abb8aSShri Abhyankar ierr = PetscViewerASCIIMonitorPrintf(vi->lsmonitor,"Line search: Unable to find good step length! %D \n",count);CHKERRQ(ierr); 2195c92abb8aSShri 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); 21962b4ed282SShri Abhyankar } 21972b4ed282SShri Abhyankar ierr = VecCopy(x,w);CHKERRQ(ierr); 21982b4ed282SShri Abhyankar *flag = PETSC_FALSE; 21992b4ed282SShri Abhyankar break; 22002b4ed282SShri Abhyankar } 22012b4ed282SShri Abhyankar lambdatemp = -initslope/((*gnorm)*(*gnorm) - fnorm*fnorm - 2.0*initslope); 22022b4ed282SShri Abhyankar if (lambdatemp > .5*lambda) lambdatemp = .5*lambda; 22032b4ed282SShri Abhyankar if (lambdatemp <= .1*lambda) lambda = .1*lambda; 22042b4ed282SShri Abhyankar else lambda = lambdatemp; 22052b4ed282SShri Abhyankar 22062b4ed282SShri Abhyankar ierr = VecWAXPY(w,-lambda,y,x);CHKERRQ(ierr); 22077fe79bc4SShri Abhyankar ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr); 22082b4ed282SShri Abhyankar if (snes->nfuncs >= snes->max_funcs) { 22092b4ed282SShri Abhyankar ierr = PetscInfo1(snes,"Exceeded maximum function evaluations, while looking for good step length! %D \n",count);CHKERRQ(ierr); 22102b4ed282SShri 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); 22112b4ed282SShri Abhyankar *flag = PETSC_FALSE; 22122b4ed282SShri Abhyankar snes->reason = SNES_DIVERGED_FUNCTION_COUNT; 22132b4ed282SShri Abhyankar break; 22142b4ed282SShri Abhyankar } 22152b4ed282SShri Abhyankar ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr); 22162b4ed282SShri Abhyankar if (snes->domainerror) { 22172b4ed282SShri Abhyankar ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); 22182b4ed282SShri Abhyankar PetscFunctionReturn(0); 22192b4ed282SShri Abhyankar } 22202f63a38cSShri Abhyankar if (snes->ops->solve != SNESSolveVI_SS) { 22217fe79bc4SShri Abhyankar ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr); 22227fe79bc4SShri Abhyankar } else { 22232b4ed282SShri Abhyankar ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr); 22247fe79bc4SShri Abhyankar } 222562cbcd01SMatthew G Knepley if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number"); 22262b4ed282SShri Abhyankar if (.5*(*gnorm)*(*gnorm) < .5*fnorm*fnorm + lambda*vi->alpha*initslope) { /* sufficient reduction */ 2227c92abb8aSShri Abhyankar if (vi->lsmonitor) { 2228c92abb8aSShri Abhyankar ierr = PetscViewerASCIIMonitorPrintf(vi->lsmonitor," Line Search: Quadratically determined step, lambda=%G\n",lambda);CHKERRQ(ierr); 22292b4ed282SShri Abhyankar } 22302b4ed282SShri Abhyankar break; 22312b4ed282SShri Abhyankar } 22322b4ed282SShri Abhyankar count++; 22332b4ed282SShri Abhyankar } 22342b4ed282SShri Abhyankar theend2: 22352b4ed282SShri Abhyankar /* Optional user-defined check for line search step validity */ 22362b4ed282SShri Abhyankar if (vi->postcheckstep) { 22372b4ed282SShri Abhyankar ierr = (*vi->postcheckstep)(snes,x,y,w,vi->postcheck,&changed_y,&changed_w);CHKERRQ(ierr); 22382b4ed282SShri Abhyankar if (changed_y) { 22392b4ed282SShri Abhyankar ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr); 22407fe79bc4SShri Abhyankar ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr); 22412b4ed282SShri Abhyankar } 22422b4ed282SShri Abhyankar if (changed_y || changed_w) { /* recompute the function if the step has changed */ 22432b4ed282SShri Abhyankar ierr = SNESComputeFunction(snes,w,g); 22442b4ed282SShri Abhyankar if (snes->domainerror) { 22452b4ed282SShri Abhyankar ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); 22462b4ed282SShri Abhyankar PetscFunctionReturn(0); 22472b4ed282SShri Abhyankar } 22482f63a38cSShri Abhyankar if (snes->ops->solve != SNESSolveVI_SS) { 22497fe79bc4SShri Abhyankar ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr); 22507fe79bc4SShri Abhyankar } else { 22517fe79bc4SShri Abhyankar ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr); 22527fe79bc4SShri Abhyankar } 22537fe79bc4SShri Abhyankar 22542b4ed282SShri Abhyankar ierr = VecNormBegin(y,NORM_2,ynorm);CHKERRQ(ierr); 22552b4ed282SShri Abhyankar ierr = VecNormEnd(y,NORM_2,ynorm);CHKERRQ(ierr); 225662cbcd01SMatthew G Knepley if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number"); 22572b4ed282SShri Abhyankar } 22582b4ed282SShri Abhyankar } 22592b4ed282SShri Abhyankar ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); 22602b4ed282SShri Abhyankar PetscFunctionReturn(0); 22612b4ed282SShri Abhyankar } 22622b4ed282SShri Abhyankar 2263ace3abfcSBarry 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*/ 22642b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */ 22652b4ed282SShri Abhyankar EXTERN_C_BEGIN 22662b4ed282SShri Abhyankar #undef __FUNCT__ 22672b4ed282SShri Abhyankar #define __FUNCT__ "SNESLineSearchSet_VI" 22687087cfbeSBarry Smith PetscErrorCode SNESLineSearchSet_VI(SNES snes,FCN2 func,void *lsctx) 22692b4ed282SShri Abhyankar { 22702b4ed282SShri Abhyankar PetscFunctionBegin; 22712b4ed282SShri Abhyankar ((SNES_VI *)(snes->data))->LineSearch = func; 22722b4ed282SShri Abhyankar ((SNES_VI *)(snes->data))->lsP = lsctx; 22732b4ed282SShri Abhyankar PetscFunctionReturn(0); 22742b4ed282SShri Abhyankar } 22752b4ed282SShri Abhyankar EXTERN_C_END 22762b4ed282SShri Abhyankar 22772b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */ 22782b4ed282SShri Abhyankar EXTERN_C_BEGIN 22792b4ed282SShri Abhyankar #undef __FUNCT__ 22802b4ed282SShri Abhyankar #define __FUNCT__ "SNESLineSearchSetMonitor_VI" 22817087cfbeSBarry Smith PetscErrorCode SNESLineSearchSetMonitor_VI(SNES snes,PetscBool flg) 22822b4ed282SShri Abhyankar { 22832b4ed282SShri Abhyankar SNES_VI *vi = (SNES_VI*)snes->data; 22842b4ed282SShri Abhyankar PetscErrorCode ierr; 22852b4ed282SShri Abhyankar 22862b4ed282SShri Abhyankar PetscFunctionBegin; 2287c92abb8aSShri Abhyankar if (flg && !vi->lsmonitor) { 2288c92abb8aSShri Abhyankar ierr = PetscViewerASCIIMonitorCreate(((PetscObject)snes)->comm,"stdout",((PetscObject)snes)->tablevel,&vi->lsmonitor);CHKERRQ(ierr); 2289c92abb8aSShri Abhyankar } else if (!flg && vi->lsmonitor) { 22906bf464f9SBarry Smith ierr = PetscViewerASCIIMonitorDestroy(&vi->lsmonitor);CHKERRQ(ierr); 22912b4ed282SShri Abhyankar } 22922b4ed282SShri Abhyankar PetscFunctionReturn(0); 22932b4ed282SShri Abhyankar } 22942b4ed282SShri Abhyankar EXTERN_C_END 22952b4ed282SShri Abhyankar 22962b4ed282SShri Abhyankar /* 22972b4ed282SShri Abhyankar SNESView_VI - Prints info from the SNESVI data structure. 22982b4ed282SShri Abhyankar 22992b4ed282SShri Abhyankar Input Parameters: 23002b4ed282SShri Abhyankar . SNES - the SNES context 23012b4ed282SShri Abhyankar . viewer - visualization context 23022b4ed282SShri Abhyankar 23032b4ed282SShri Abhyankar Application Interface Routine: SNESView() 23042b4ed282SShri Abhyankar */ 23052b4ed282SShri Abhyankar #undef __FUNCT__ 23062b4ed282SShri Abhyankar #define __FUNCT__ "SNESView_VI" 23072b4ed282SShri Abhyankar static PetscErrorCode SNESView_VI(SNES snes,PetscViewer viewer) 23082b4ed282SShri Abhyankar { 23092b4ed282SShri Abhyankar SNES_VI *vi = (SNES_VI *)snes->data; 231078c4b9d3SShri Abhyankar const char *cstr,*tstr; 23112b4ed282SShri Abhyankar PetscErrorCode ierr; 2312ace3abfcSBarry Smith PetscBool iascii; 23132b4ed282SShri Abhyankar 23142b4ed282SShri Abhyankar PetscFunctionBegin; 23152b4ed282SShri Abhyankar ierr = PetscTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); 23162b4ed282SShri Abhyankar if (iascii) { 23172b4ed282SShri Abhyankar if (vi->LineSearch == SNESLineSearchNo_VI) cstr = "SNESLineSearchNo"; 23182b4ed282SShri Abhyankar else if (vi->LineSearch == SNESLineSearchQuadratic_VI) cstr = "SNESLineSearchQuadratic"; 23192b4ed282SShri Abhyankar else if (vi->LineSearch == SNESLineSearchCubic_VI) cstr = "SNESLineSearchCubic"; 23202b4ed282SShri Abhyankar else cstr = "unknown"; 232178c4b9d3SShri Abhyankar if (snes->ops->solve == SNESSolveVI_SS) tstr = "Semismooth"; 23220a7c7af0SShri Abhyankar else if (snes->ops->solve == SNESSolveVI_RS) tstr = "Reduced Space"; 2323b350b9c9SBarry Smith else if (snes->ops->solve == SNESSolveVI_RSAUG) tstr = "Reduced space with augmented variables"; 232478c4b9d3SShri Abhyankar else tstr = "unknown"; 232578c4b9d3SShri Abhyankar ierr = PetscViewerASCIIPrintf(viewer," VI algorithm: %s\n",tstr);CHKERRQ(ierr); 23262b4ed282SShri Abhyankar ierr = PetscViewerASCIIPrintf(viewer," line search variant: %s\n",cstr);CHKERRQ(ierr); 23272b4ed282SShri Abhyankar ierr = PetscViewerASCIIPrintf(viewer," alpha=%G, maxstep=%G, minlambda=%G\n",vi->alpha,vi->maxstep,vi->minlambda);CHKERRQ(ierr); 23282b4ed282SShri Abhyankar } else { 23292b4ed282SShri Abhyankar SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Viewer type %s not supported for SNES EQ VI",((PetscObject)viewer)->type_name); 23302b4ed282SShri Abhyankar } 23312b4ed282SShri Abhyankar PetscFunctionReturn(0); 23322b4ed282SShri Abhyankar } 23332b4ed282SShri Abhyankar 23345559b345SBarry Smith #undef __FUNCT__ 23355559b345SBarry Smith #define __FUNCT__ "SNESVISetVariableBounds" 23365559b345SBarry Smith /*@ 23372b4ed282SShri Abhyankar SNESVISetVariableBounds - Sets the lower and upper bounds for the solution vector. xl <= x <= xu. 23382b4ed282SShri Abhyankar 23392b4ed282SShri Abhyankar Input Parameters: 23402b4ed282SShri Abhyankar . snes - the SNES context. 23412b4ed282SShri Abhyankar . xl - lower bound. 23422b4ed282SShri Abhyankar . xu - upper bound. 23432b4ed282SShri Abhyankar 23442b4ed282SShri Abhyankar Notes: 23452b4ed282SShri Abhyankar If this routine is not called then the lower and upper bounds are set to 234601f0b76bSBarry Smith SNES_VI_INF and SNES_VI_NINF respectively during SNESSetUp(). 234784c105d7SBarry Smith 23485559b345SBarry Smith @*/ 234969c03620SShri Abhyankar PetscErrorCode SNESVISetVariableBounds(SNES snes, Vec xl, Vec xu) 23502b4ed282SShri Abhyankar { 2351d923200aSJungho Lee SNES_VI *vi; 2352d923200aSJungho Lee PetscErrorCode ierr; 23532b4ed282SShri Abhyankar 23542b4ed282SShri Abhyankar PetscFunctionBegin; 23552b4ed282SShri Abhyankar PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 23562b4ed282SShri Abhyankar PetscValidHeaderSpecific(xl,VEC_CLASSID,2); 23572b4ed282SShri Abhyankar PetscValidHeaderSpecific(xu,VEC_CLASSID,3); 23582b4ed282SShri Abhyankar if (!snes->vec_func) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Must call SNESSetFunction() first"); 23592b4ed282SShri 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); 23602b4ed282SShri 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); 2361d923200aSJungho Lee ierr = SNESSetType(snes,SNESVI);CHKERRQ(ierr); 2362d923200aSJungho Lee vi = (SNES_VI*)snes->data; 23632176524cSBarry Smith ierr = PetscObjectReference((PetscObject)xl);CHKERRQ(ierr); 23642176524cSBarry Smith ierr = PetscObjectReference((PetscObject)xu);CHKERRQ(ierr); 23652176524cSBarry Smith ierr = VecDestroy(&vi->xl);CHKERRQ(ierr); 23662176524cSBarry Smith ierr = VecDestroy(&vi->xu);CHKERRQ(ierr); 23672b4ed282SShri Abhyankar vi->xl = xl; 23682b4ed282SShri Abhyankar vi->xu = xu; 23692b4ed282SShri Abhyankar PetscFunctionReturn(0); 23702b4ed282SShri Abhyankar } 2371693ddf92SShri Abhyankar 23722b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */ 23732b4ed282SShri Abhyankar /* 23742b4ed282SShri Abhyankar SNESSetFromOptions_VI - Sets various parameters for the SNESVI method. 23752b4ed282SShri Abhyankar 23762b4ed282SShri Abhyankar Input Parameter: 23772b4ed282SShri Abhyankar . snes - the SNES context 23782b4ed282SShri Abhyankar 23792b4ed282SShri Abhyankar Application Interface Routine: SNESSetFromOptions() 23802b4ed282SShri Abhyankar */ 23812b4ed282SShri Abhyankar #undef __FUNCT__ 23822b4ed282SShri Abhyankar #define __FUNCT__ "SNESSetFromOptions_VI" 23832b4ed282SShri Abhyankar static PetscErrorCode SNESSetFromOptions_VI(SNES snes) 23842b4ed282SShri Abhyankar { 23852b4ed282SShri Abhyankar SNES_VI *vi = (SNES_VI *)snes->data; 23867fe79bc4SShri Abhyankar const char *lses[] = {"basic","basicnonorms","quadratic","cubic"}; 2387b350b9c9SBarry Smith const char *vies[] = {"ss","rs","rsaug"}; 23882b4ed282SShri Abhyankar PetscErrorCode ierr; 23892b4ed282SShri Abhyankar PetscInt indx; 239069c03620SShri Abhyankar PetscBool flg,set,flg2; 23912b4ed282SShri Abhyankar 23922b4ed282SShri Abhyankar PetscFunctionBegin; 23932b4ed282SShri Abhyankar ierr = PetscOptionsHead("SNES semismooth method options");CHKERRQ(ierr); 23949308c137SBarry Smith ierr = PetscOptionsBool("-snes_vi_monitor","Monitor all non-active variables","None",PETSC_FALSE,&flg,0);CHKERRQ(ierr); 23959308c137SBarry Smith if (flg) { 23969308c137SBarry Smith ierr = SNESMonitorSet(snes,SNESMonitorVI,0,0);CHKERRQ(ierr); 23979308c137SBarry Smith } 2398be6adb11SBarry Smith ierr = PetscOptionsReal("-snes_ls_alpha","Function norm must decrease by","None",vi->alpha,&vi->alpha,0);CHKERRQ(ierr); 2399be6adb11SBarry Smith ierr = PetscOptionsReal("-snes_ls_maxstep","Step must be less than","None",vi->maxstep,&vi->maxstep,0);CHKERRQ(ierr); 2400be6adb11SBarry Smith ierr = PetscOptionsReal("-snes_ls_minlambda","Minimum lambda allowed","None",vi->minlambda,&vi->minlambda,0);CHKERRQ(ierr); 24012b4ed282SShri Abhyankar ierr = PetscOptionsReal("-snes_vi_const_tol","constraint tolerance","None",vi->const_tol,&vi->const_tol,0);CHKERRQ(ierr); 2402be6adb11SBarry Smith ierr = PetscOptionsBool("-snes_ls_monitor","Print progress of line searches","SNESLineSearchSetMonitor",vi->lsmonitor ? PETSC_TRUE : PETSC_FALSE,&flg,&set);CHKERRQ(ierr); 24032b4ed282SShri Abhyankar if (set) {ierr = SNESLineSearchSetMonitor(snes,flg);CHKERRQ(ierr);} 24042f63a38cSShri Abhyankar ierr = PetscOptionsEList("-snes_vi_type","Semismooth algorithm used","",vies,3,"ss",&indx,&flg2);CHKERRQ(ierr); 240569c03620SShri Abhyankar if (flg2) { 240669c03620SShri Abhyankar switch (indx) { 240769c03620SShri Abhyankar case 0: 240869c03620SShri Abhyankar snes->ops->solve = SNESSolveVI_SS; 240969c03620SShri Abhyankar break; 241069c03620SShri Abhyankar case 1: 2411d950fb63SShri Abhyankar snes->ops->solve = SNESSolveVI_RS; 2412d950fb63SShri Abhyankar break; 24132f63a38cSShri Abhyankar case 2: 2414b350b9c9SBarry Smith snes->ops->solve = SNESSolveVI_RSAUG; 241569c03620SShri Abhyankar } 241669c03620SShri Abhyankar } 2417be6adb11SBarry Smith ierr = PetscOptionsEList("-snes_ls","Line search used","SNESLineSearchSet",lses,4,"basic",&indx,&flg);CHKERRQ(ierr); 24182b4ed282SShri Abhyankar if (flg) { 24192b4ed282SShri Abhyankar switch (indx) { 24202b4ed282SShri Abhyankar case 0: 24212b4ed282SShri Abhyankar ierr = SNESLineSearchSet(snes,SNESLineSearchNo_VI,PETSC_NULL);CHKERRQ(ierr); 24222b4ed282SShri Abhyankar break; 24232b4ed282SShri Abhyankar case 1: 24242b4ed282SShri Abhyankar ierr = SNESLineSearchSet(snes,SNESLineSearchNoNorms_VI,PETSC_NULL);CHKERRQ(ierr); 24252b4ed282SShri Abhyankar break; 24262b4ed282SShri Abhyankar case 2: 24272b4ed282SShri Abhyankar ierr = SNESLineSearchSet(snes,SNESLineSearchQuadratic_VI,PETSC_NULL);CHKERRQ(ierr); 24282b4ed282SShri Abhyankar break; 24292b4ed282SShri Abhyankar case 3: 24302b4ed282SShri Abhyankar ierr = SNESLineSearchSet(snes,SNESLineSearchCubic_VI,PETSC_NULL);CHKERRQ(ierr); 24312b4ed282SShri Abhyankar break; 24322b4ed282SShri Abhyankar } 2433fe835674SShri Abhyankar } 24342b4ed282SShri Abhyankar ierr = PetscOptionsTail();CHKERRQ(ierr); 24352b4ed282SShri Abhyankar PetscFunctionReturn(0); 24362b4ed282SShri Abhyankar } 24372b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */ 24382b4ed282SShri Abhyankar /*MC 24398b4c83edSBarry Smith SNESVI - Various solvers for variational inequalities based on Newton's method 24402b4ed282SShri Abhyankar 24412b4ed282SShri Abhyankar Options Database: 24428b4c83edSBarry 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 24438b4c83edSBarry Smith additional variables that enforce the constraints 24448b4c83edSBarry Smith - -snes_vi_monitor - prints the number of active constraints at each iteration. 24452b4ed282SShri Abhyankar 24462b4ed282SShri Abhyankar 24472b4ed282SShri Abhyankar Level: beginner 24482b4ed282SShri Abhyankar 24492b4ed282SShri Abhyankar .seealso: SNESCreate(), SNES, SNESSetType(), SNESTR, SNESLineSearchSet(), 24502b4ed282SShri Abhyankar SNESLineSearchSetPostCheck(), SNESLineSearchNo(), SNESLineSearchCubic(), SNESLineSearchQuadratic(), 24512b4ed282SShri Abhyankar SNESLineSearchSet(), SNESLineSearchNoNorms(), SNESLineSearchSetPreCheck(), SNESLineSearchSetParams(), SNESLineSearchGetParams() 24522b4ed282SShri Abhyankar 24532b4ed282SShri Abhyankar M*/ 24542b4ed282SShri Abhyankar EXTERN_C_BEGIN 24552b4ed282SShri Abhyankar #undef __FUNCT__ 24562b4ed282SShri Abhyankar #define __FUNCT__ "SNESCreate_VI" 24577087cfbeSBarry Smith PetscErrorCode SNESCreate_VI(SNES snes) 24582b4ed282SShri Abhyankar { 24592b4ed282SShri Abhyankar PetscErrorCode ierr; 24602b4ed282SShri Abhyankar SNES_VI *vi; 24612b4ed282SShri Abhyankar 24622b4ed282SShri Abhyankar PetscFunctionBegin; 24632176524cSBarry Smith snes->ops->reset = SNESReset_VI; 24642b4ed282SShri Abhyankar snes->ops->setup = SNESSetUp_VI; 2465edafb9efSBarry Smith snes->ops->solve = SNESSolveVI_RS; 24662b4ed282SShri Abhyankar snes->ops->destroy = SNESDestroy_VI; 24672b4ed282SShri Abhyankar snes->ops->setfromoptions = SNESSetFromOptions_VI; 24682b4ed282SShri Abhyankar snes->ops->view = SNESView_VI; 24692b4ed282SShri Abhyankar snes->ops->converged = SNESDefaultConverged_VI; 24702b4ed282SShri Abhyankar 24712b4ed282SShri Abhyankar ierr = PetscNewLog(snes,SNES_VI,&vi);CHKERRQ(ierr); 24722b4ed282SShri Abhyankar snes->data = (void*)vi; 24732b4ed282SShri Abhyankar vi->alpha = 1.e-4; 24742b4ed282SShri Abhyankar vi->maxstep = 1.e8; 24752b4ed282SShri Abhyankar vi->minlambda = 1.e-12; 24767fe79bc4SShri Abhyankar vi->LineSearch = SNESLineSearchNo_VI; 24772b4ed282SShri Abhyankar vi->lsP = PETSC_NULL; 24782b4ed282SShri Abhyankar vi->postcheckstep = PETSC_NULL; 24792b4ed282SShri Abhyankar vi->postcheck = PETSC_NULL; 24802b4ed282SShri Abhyankar vi->precheckstep = PETSC_NULL; 24812b4ed282SShri Abhyankar vi->precheck = PETSC_NULL; 24822b4ed282SShri Abhyankar vi->const_tol = 2.2204460492503131e-16; 24832f63a38cSShri Abhyankar vi->checkredundancy = PETSC_NULL; 24842b4ed282SShri Abhyankar 24852b4ed282SShri Abhyankar ierr = PetscObjectComposeFunctionDynamic((PetscObject)snes,"SNESLineSearchSetMonitor_C","SNESLineSearchSetMonitor_VI",SNESLineSearchSetMonitor_VI);CHKERRQ(ierr); 24862b4ed282SShri Abhyankar ierr = PetscObjectComposeFunctionDynamic((PetscObject)snes,"SNESLineSearchSet_C","SNESLineSearchSet_VI",SNESLineSearchSet_VI);CHKERRQ(ierr); 24872b4ed282SShri Abhyankar 24882b4ed282SShri Abhyankar PetscFunctionReturn(0); 24892b4ed282SShri Abhyankar } 24902b4ed282SShri Abhyankar EXTERN_C_END 2491