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 162bd2b0e6SSatish Balay Level: advanced 172176524cSBarry Smith 18aab9d709SJed Brown @*/ 1977cdaf69SJed Brown PetscErrorCode SNESVISetComputeVariableBounds(SNES snes, PetscErrorCode (*compute)(SNES,Vec,Vec)) 202176524cSBarry Smith { 212176524cSBarry Smith PetscErrorCode ierr; 222176524cSBarry Smith SNES_VI *vi; 232176524cSBarry Smith 242176524cSBarry Smith PetscFunctionBegin; 252176524cSBarry Smith ierr = SNESSetType(snes,SNESVI);CHKERRQ(ierr); 262176524cSBarry Smith vi = (SNES_VI*)snes->data; 272176524cSBarry Smith vi->computevariablebounds = compute; 282176524cSBarry Smith PetscFunctionReturn(0); 292176524cSBarry Smith } 302176524cSBarry Smith 312176524cSBarry Smith 322176524cSBarry Smith #undef __FUNCT__ 33ed70e96aSJungho Lee #define __FUNCT__ "SNESVIComputeInactiveSetIS" 34d0af7cd3SBarry Smith /* 35ed70e96aSJungho Lee SNESVIComputeInactiveSetIS - Gets the global indices for the bogus inactive set variables 36d0af7cd3SBarry Smith 37d0af7cd3SBarry Smith Input parameter 38d0af7cd3SBarry Smith . snes - the SNES context 39d0af7cd3SBarry Smith . X - the snes solution vector 40d0af7cd3SBarry Smith 41d0af7cd3SBarry Smith Output parameter 42d0af7cd3SBarry Smith . ISact - active set index set 43d0af7cd3SBarry Smith 44d0af7cd3SBarry Smith */ 45ed70e96aSJungho Lee PetscErrorCode SNESVIComputeInactiveSetIS(Vec upper,Vec lower,Vec X,Vec F,IS* inact) 46d0af7cd3SBarry Smith { 47d0af7cd3SBarry Smith PetscErrorCode ierr; 48d0af7cd3SBarry Smith const PetscScalar *x,*xl,*xu,*f; 49d0af7cd3SBarry Smith PetscInt *idx_act,i,nlocal,nloc_isact=0,ilow,ihigh,i1=0; 50d0af7cd3SBarry Smith 51d0af7cd3SBarry Smith PetscFunctionBegin; 52d0af7cd3SBarry Smith ierr = VecGetLocalSize(X,&nlocal);CHKERRQ(ierr); 53d0af7cd3SBarry Smith ierr = VecGetOwnershipRange(X,&ilow,&ihigh);CHKERRQ(ierr); 54d0af7cd3SBarry Smith ierr = VecGetArrayRead(X,&x);CHKERRQ(ierr); 55d0af7cd3SBarry Smith ierr = VecGetArrayRead(lower,&xl);CHKERRQ(ierr); 56d0af7cd3SBarry Smith ierr = VecGetArrayRead(upper,&xu);CHKERRQ(ierr); 57d0af7cd3SBarry Smith ierr = VecGetArrayRead(F,&f);CHKERRQ(ierr); 58d0af7cd3SBarry Smith /* Compute inactive set size */ 59d0af7cd3SBarry Smith for (i=0; i < nlocal;i++) { 60d0af7cd3SBarry 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++; 61d0af7cd3SBarry Smith } 62d0af7cd3SBarry Smith 63d0af7cd3SBarry Smith ierr = PetscMalloc(nloc_isact*sizeof(PetscInt),&idx_act);CHKERRQ(ierr); 64d0af7cd3SBarry Smith 65d0af7cd3SBarry Smith /* Set inactive set indices */ 66d0af7cd3SBarry Smith for(i=0; i < nlocal; i++) { 67d0af7cd3SBarry 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; 68d0af7cd3SBarry Smith } 69d0af7cd3SBarry Smith 70d0af7cd3SBarry Smith /* Create inactive set IS */ 71d0af7cd3SBarry Smith ierr = ISCreateGeneral(((PetscObject)upper)->comm,nloc_isact,idx_act,PETSC_OWN_POINTER,inact);CHKERRQ(ierr); 72d0af7cd3SBarry Smith 73d0af7cd3SBarry Smith ierr = VecRestoreArrayRead(X,&x);CHKERRQ(ierr); 74d0af7cd3SBarry Smith ierr = VecRestoreArrayRead(lower,&xl);CHKERRQ(ierr); 75d0af7cd3SBarry Smith ierr = VecRestoreArrayRead(upper,&xu);CHKERRQ(ierr); 76d0af7cd3SBarry Smith ierr = VecRestoreArrayRead(F,&f);CHKERRQ(ierr); 77d0af7cd3SBarry Smith PetscFunctionReturn(0); 78d0af7cd3SBarry Smith } 79d0af7cd3SBarry Smith 803c0c59f3SBarry Smith /* 813c0c59f3SBarry 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 823c0c59f3SBarry Smith defined by the reduced space method. 833c0c59f3SBarry Smith 843c0c59f3SBarry Smith Simple calls the regular DM interpolation and restricts it to operation on the variables not associated with active constraints. 853c0c59f3SBarry Smith 86ed70e96aSJungho Lee <*/ 873c0c59f3SBarry Smith typedef struct { 883c0c59f3SBarry Smith PetscInt n; /* size of vectors in the reduced DM space */ 893c0c59f3SBarry Smith IS inactive; 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); 14000ac8be1SBarry Smith *vec = 0; 141d0af7cd3SBarry Smith PetscFunctionReturn(0); 142d0af7cd3SBarry Smith } 143d0af7cd3SBarry Smith 1449ce20c35SJungho Lee extern PetscErrorCode DMSetVI(DM,IS); 145d0af7cd3SBarry Smith 146d0af7cd3SBarry Smith #undef __FUNCT__ 147d0af7cd3SBarry Smith #define __FUNCT__ "DMCoarsen_SNESVI" 148d0af7cd3SBarry Smith /* 149d0af7cd3SBarry Smith DMCoarsen_SNESVI - Computes the regular coarsened DM then computes additional information about its inactive set 150d0af7cd3SBarry Smith 151d0af7cd3SBarry Smith */ 152d0af7cd3SBarry Smith PetscErrorCode DMCoarsen_SNESVI(DM dm1,MPI_Comm comm,DM *dm2) 153d0af7cd3SBarry Smith { 154d0af7cd3SBarry Smith PetscErrorCode ierr; 155d0af7cd3SBarry Smith PetscContainer isnes; 1563c0c59f3SBarry Smith DM_SNESVI *dmsnesvi1; 1579ce20c35SJungho Lee Vec finemarked,coarsemarked; 158d0af7cd3SBarry Smith IS inactive; 159d0af7cd3SBarry Smith VecScatter inject; 1609ce20c35SJungho Lee const PetscInt *index; 1619ce20c35SJungho Lee PetscInt n,k,cnt = 0,rstart,*coarseindex; 1629ce20c35SJungho Lee PetscScalar *marked; 163d0af7cd3SBarry Smith 164d0af7cd3SBarry Smith PetscFunctionBegin; 165d0af7cd3SBarry Smith ierr = PetscObjectQuery((PetscObject)dm1,"VI",(PetscObject *)&isnes);CHKERRQ(ierr); 1664c661befSBarry Smith if (!isnes) SETERRQ(((PetscObject)dm1)->comm,PETSC_ERR_PLIB,"Composed VI data structure is missing"); 167d0af7cd3SBarry Smith ierr = PetscContainerGetPointer(isnes,(void**)&dmsnesvi1);CHKERRQ(ierr); 168d0af7cd3SBarry Smith 169298cc208SBarry Smith /* get the original coarsen */ 170d0af7cd3SBarry Smith ierr = (*dmsnesvi1->coarsen)(dm1,comm,dm2);CHKERRQ(ierr); 171298cc208SBarry Smith 1723c0c59f3SBarry Smith /* not sure why this extra reference is needed, but without the dm2 disappears too early */ 1733c0c59f3SBarry Smith ierr = PetscObjectReference((PetscObject)*dm2);CHKERRQ(ierr); 1743c0c59f3SBarry Smith 175298cc208SBarry Smith /* need to set back global vectors in order to use the original injection */ 176298cc208SBarry Smith ierr = DMClearGlobalVectors(dm1);CHKERRQ(ierr); 177298cc208SBarry Smith dm1->ops->createglobalvector = dmsnesvi1->createglobalvector; 1789ce20c35SJungho Lee ierr = DMCreateGlobalVector(dm1,&finemarked);CHKERRQ(ierr); 1799ce20c35SJungho Lee ierr = DMCreateGlobalVector(*dm2,&coarsemarked);CHKERRQ(ierr); 1809ce20c35SJungho Lee 1819ce20c35SJungho Lee /* 1829ce20c35SJungho Lee fill finemarked with locations of inactive points 1839ce20c35SJungho Lee */ 1849ce20c35SJungho Lee ierr = ISGetIndices(dmsnesvi1->inactive,&index);CHKERRQ(ierr); 1859ce20c35SJungho Lee ierr = ISGetLocalSize(dmsnesvi1->inactive,&n);CHKERRQ(ierr); 1869ce20c35SJungho Lee ierr = VecSet(finemarked,0.0);CHKERRQ(ierr); 1879ce20c35SJungho Lee for (k=0;k<n;k++){ 1889ce20c35SJungho Lee ierr = VecSetValue(finemarked,index[k],1.0,INSERT_VALUES);CHKERRQ(ierr); 1899ce20c35SJungho Lee } 1909ce20c35SJungho Lee ierr = VecAssemblyBegin(finemarked);CHKERRQ(ierr); 1919ce20c35SJungho Lee ierr = VecAssemblyEnd(finemarked);CHKERRQ(ierr); 1929ce20c35SJungho Lee 193d0af7cd3SBarry Smith ierr = DMGetInjection(*dm2,dm1,&inject);CHKERRQ(ierr); 1949ce20c35SJungho Lee ierr = VecScatterBegin(inject,finemarked,coarsemarked,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1959ce20c35SJungho Lee ierr = VecScatterEnd(inject,finemarked,coarsemarked,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 196d0af7cd3SBarry Smith ierr = VecScatterDestroy(&inject);CHKERRQ(ierr); 1979ce20c35SJungho Lee 1989ce20c35SJungho Lee /* 1999ce20c35SJungho Lee create index set list of coarse inactive points from coarsemarked 2009ce20c35SJungho Lee */ 2019ce20c35SJungho Lee ierr = VecGetLocalSize(coarsemarked,&n);CHKERRQ(ierr); 2029ce20c35SJungho Lee ierr = VecGetOwnershipRange(coarsemarked,&rstart,PETSC_NULL);CHKERRQ(ierr); 2039ce20c35SJungho Lee ierr = VecGetArray(coarsemarked,&marked);CHKERRQ(ierr); 2049ce20c35SJungho Lee for (k=0; k<n; k++) { 205ff207688SJed Brown if (marked[k] != 0.0) cnt++; 2069ce20c35SJungho Lee } 2079ce20c35SJungho Lee ierr = PetscMalloc(cnt*sizeof(PetscInt),&coarseindex);CHKERRQ(ierr); 2089ce20c35SJungho Lee cnt = 0; 2099ce20c35SJungho Lee for (k=0; k<n; k++) { 210ff207688SJed Brown if (marked[k] != 0.0) coarseindex[cnt++] = k + rstart; 2119ce20c35SJungho Lee } 2129ce20c35SJungho Lee ierr = VecRestoreArray(coarsemarked,&marked);CHKERRQ(ierr); 2139ce20c35SJungho Lee ierr = ISCreateGeneral(PETSC_COMM_WORLD,cnt,coarseindex,PETSC_OWN_POINTER,&inactive);CHKERRQ(ierr); 2149ce20c35SJungho Lee 215298cc208SBarry Smith ierr = DMClearGlobalVectors(dm1);CHKERRQ(ierr); 216298cc208SBarry Smith dm1->ops->createglobalvector = DMCreateGlobalVector_SNESVI; 2179ce20c35SJungho Lee ierr = DMSetVI(*dm2,inactive);CHKERRQ(ierr); 2189ce20c35SJungho Lee 2199ce20c35SJungho Lee ierr = VecDestroy(&finemarked);CHKERRQ(ierr); 2209ce20c35SJungho Lee ierr = VecDestroy(&coarsemarked);CHKERRQ(ierr); 2213c0c59f3SBarry Smith ierr = ISDestroy(&inactive);CHKERRQ(ierr); 222d0af7cd3SBarry Smith PetscFunctionReturn(0); 223d0af7cd3SBarry Smith } 224d0af7cd3SBarry Smith 225d0af7cd3SBarry Smith #undef __FUNCT__ 2263c0c59f3SBarry Smith #define __FUNCT__ "DMDestroy_SNESVI" 2273c0c59f3SBarry Smith PetscErrorCode DMDestroy_SNESVI(DM_SNESVI *dmsnesvi) 228d0af7cd3SBarry Smith { 229d0af7cd3SBarry Smith PetscErrorCode ierr; 230d0af7cd3SBarry Smith 231d0af7cd3SBarry Smith PetscFunctionBegin; 2324c661befSBarry Smith /* reset the base methods in the DM object that were changed when the DM_SNESVI was reset */ 2334c661befSBarry Smith dmsnesvi->dm->ops->getinterpolation = dmsnesvi->getinterpolation; 2344c661befSBarry Smith dmsnesvi->dm->ops->coarsen = dmsnesvi->coarsen; 2354c661befSBarry Smith dmsnesvi->dm->ops->createglobalvector = dmsnesvi->createglobalvector; 23600ac8be1SBarry Smith /* need to clear out this vectors because some of them may not have a reference to the DM 23700ac8be1SBarry Smith but they are counted as having references to the DM in DMDestroy() */ 23800ac8be1SBarry Smith ierr = DMClearGlobalVectors(dmsnesvi->dm);CHKERRQ(ierr); 2394c661befSBarry Smith 240d0af7cd3SBarry Smith ierr = ISDestroy(&dmsnesvi->inactive);CHKERRQ(ierr); 241d0af7cd3SBarry Smith ierr = PetscFree(dmsnesvi);CHKERRQ(ierr); 242d0af7cd3SBarry Smith PetscFunctionReturn(0); 243d0af7cd3SBarry Smith } 244d0af7cd3SBarry Smith 245d0af7cd3SBarry Smith #undef __FUNCT__ 246d0af7cd3SBarry Smith #define __FUNCT__ "DMSetVI" 247d0af7cd3SBarry Smith /* 248d0af7cd3SBarry Smith DMSetVI - Marks a DM as associated with a VI problem. This causes the interpolation/restriction operators to 249d0af7cd3SBarry Smith be restricted to only those variables NOT associated with active constraints. 250d0af7cd3SBarry Smith 251d0af7cd3SBarry Smith */ 2529ce20c35SJungho Lee PetscErrorCode DMSetVI(DM dm,IS inactive) 253d0af7cd3SBarry Smith { 254d0af7cd3SBarry Smith PetscErrorCode ierr; 255d0af7cd3SBarry Smith PetscContainer isnes; 2563c0c59f3SBarry Smith DM_SNESVI *dmsnesvi; 257d0af7cd3SBarry Smith 258d0af7cd3SBarry Smith PetscFunctionBegin; 2594dcab191SBarry Smith if (!dm) PetscFunctionReturn(0); 2601c0a9e84SBarry Smith 261d0af7cd3SBarry Smith ierr = PetscObjectReference((PetscObject)inactive);CHKERRQ(ierr); 262d0af7cd3SBarry Smith 263d0af7cd3SBarry Smith ierr = PetscObjectQuery((PetscObject)dm,"VI",(PetscObject *)&isnes);CHKERRQ(ierr); 264d0af7cd3SBarry Smith if (!isnes) { 265d0af7cd3SBarry Smith ierr = PetscContainerCreate(((PetscObject)dm)->comm,&isnes);CHKERRQ(ierr); 2663c0c59f3SBarry Smith ierr = PetscContainerSetUserDestroy(isnes,(PetscErrorCode (*)(void*))DMDestroy_SNESVI);CHKERRQ(ierr); 2673c0c59f3SBarry Smith ierr = PetscNew(DM_SNESVI,&dmsnesvi);CHKERRQ(ierr); 268d0af7cd3SBarry Smith ierr = PetscContainerSetPointer(isnes,(void*)dmsnesvi);CHKERRQ(ierr); 269d0af7cd3SBarry Smith ierr = PetscObjectCompose((PetscObject)dm,"VI",(PetscObject)isnes);CHKERRQ(ierr); 2703c0c59f3SBarry Smith ierr = PetscContainerDestroy(&isnes);CHKERRQ(ierr); 271d0af7cd3SBarry Smith dmsnesvi->getinterpolation = dm->ops->getinterpolation; 272d0af7cd3SBarry Smith dm->ops->getinterpolation = DMGetInterpolation_SNESVI; 273d0af7cd3SBarry Smith dmsnesvi->coarsen = dm->ops->coarsen; 274d0af7cd3SBarry Smith dm->ops->coarsen = DMCoarsen_SNESVI; 275298cc208SBarry Smith dmsnesvi->createglobalvector = dm->ops->createglobalvector; 2764dcab191SBarry Smith dm->ops->createglobalvector = DMCreateGlobalVector_SNESVI; 277d0af7cd3SBarry Smith } else { 278d0af7cd3SBarry Smith ierr = PetscContainerGetPointer(isnes,(void**)&dmsnesvi);CHKERRQ(ierr); 279d0af7cd3SBarry Smith ierr = ISDestroy(&dmsnesvi->inactive);CHKERRQ(ierr); 280d0af7cd3SBarry Smith } 2814dcab191SBarry Smith ierr = DMClearGlobalVectors(dm);CHKERRQ(ierr); 2824dcab191SBarry Smith ierr = ISGetLocalSize(inactive,&dmsnesvi->n);CHKERRQ(ierr); 283d0af7cd3SBarry Smith dmsnesvi->inactive = inactive; 2841a223a97SBarry Smith dmsnesvi->dm = dm; 285d0af7cd3SBarry Smith PetscFunctionReturn(0); 286d0af7cd3SBarry Smith } 287d0af7cd3SBarry Smith 2884c661befSBarry Smith #undef __FUNCT__ 2894c661befSBarry Smith #define __FUNCT__ "DMDestroyVI" 2904c661befSBarry Smith /* 2914c661befSBarry Smith DMDestroyVI - Frees the DM_SNESVI object contained in the DM 2924c661befSBarry Smith - also resets the function pointers in the DM for getinterpolation() etc to use the original DM 2934c661befSBarry Smith */ 2944c661befSBarry Smith PetscErrorCode DMDestroyVI(DM dm) 2954c661befSBarry Smith { 2964c661befSBarry Smith PetscErrorCode ierr; 2974c661befSBarry Smith 2984c661befSBarry Smith PetscFunctionBegin; 2994c661befSBarry Smith if (!dm) PetscFunctionReturn(0); 3004c661befSBarry Smith ierr = PetscObjectCompose((PetscObject)dm,"VI",(PetscObject)PETSC_NULL);CHKERRQ(ierr); 3014c661befSBarry Smith PetscFunctionReturn(0); 3024c661befSBarry Smith } 3034c661befSBarry Smith 3043c0c59f3SBarry Smith /* --------------------------------------------------------------------------------------------------------*/ 3052b4ed282SShri Abhyankar 3069308c137SBarry Smith #undef __FUNCT__ 3079308c137SBarry Smith #define __FUNCT__ "SNESMonitorVI" 3087087cfbeSBarry Smith PetscErrorCode SNESMonitorVI(SNES snes,PetscInt its,PetscReal fgnorm,void *dummy) 3099308c137SBarry Smith { 3109308c137SBarry Smith PetscErrorCode ierr; 3119308c137SBarry Smith SNES_VI *vi = (SNES_VI*)snes->data; 312649052a6SBarry Smith PetscViewer viewer = dummy ? (PetscViewer) dummy : PETSC_VIEWER_STDOUT_(((PetscObject)snes)->comm); 3139308c137SBarry Smith const PetscScalar *x,*xl,*xu,*f; 3146fd67740SBarry Smith PetscInt i,n,act[2] = {0,0},fact[2],N; 3156a9e2d46SJungho Lee /* Number of components that actually hit the bounds (c.f. active variables) */ 3166a9e2d46SJungho Lee PetscInt act_bound[2] = {0,0},fact_bound[2]; 3179308c137SBarry Smith PetscReal rnorm,fnorm; 3189308c137SBarry Smith 3199308c137SBarry Smith PetscFunctionBegin; 3209308c137SBarry Smith ierr = VecGetLocalSize(snes->vec_sol,&n);CHKERRQ(ierr); 3216fd67740SBarry Smith ierr = VecGetSize(snes->vec_sol,&N);CHKERRQ(ierr); 3229308c137SBarry Smith ierr = VecGetArrayRead(vi->xl,&xl);CHKERRQ(ierr); 3239308c137SBarry Smith ierr = VecGetArrayRead(vi->xu,&xu);CHKERRQ(ierr); 3249308c137SBarry Smith ierr = VecGetArrayRead(snes->vec_sol,&x);CHKERRQ(ierr); 3253f731af5SBarry Smith ierr = VecGetArrayRead(snes->vec_func,&f);CHKERRQ(ierr); 3269308c137SBarry Smith 3279308c137SBarry Smith rnorm = 0.0; 3289308c137SBarry Smith for (i=0; i<n; i++) { 32910f5ae6bSBarry 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]); 330e400df7aSBarry Smith else if (PetscRealPart(x[i]) <= PetscRealPart(xl[i]) + 1.e-8 && PetscRealPart(f[i]) >= 0.0) act[0]++; 331e400df7aSBarry Smith else if (PetscRealPart(x[i]) >= PetscRealPart(xu[i]) - 1.e-8 && PetscRealPart(f[i]) <= 0.0) act[1]++; 332e400df7aSBarry Smith else SETERRQ(((PetscObject)snes)->comm,PETSC_ERR_PLIB,"Can never get here"); 3339308c137SBarry Smith } 3346a9e2d46SJungho Lee 3356a9e2d46SJungho Lee for (i=0; i<n; i++) { 3366a9e2d46SJungho Lee if (PetscRealPart(x[i]) <= PetscRealPart(xl[i]) + 1.e-8) act_bound[0]++; 3376a9e2d46SJungho Lee else if (PetscRealPart(x[i]) >= PetscRealPart(xu[i]) - 1.e-8) act_bound[1]++; 3386a9e2d46SJungho Lee } 3393f731af5SBarry Smith ierr = VecRestoreArrayRead(snes->vec_func,&f);CHKERRQ(ierr); 3409308c137SBarry Smith ierr = VecRestoreArrayRead(vi->xl,&xl);CHKERRQ(ierr); 3419308c137SBarry Smith ierr = VecRestoreArrayRead(vi->xu,&xu);CHKERRQ(ierr); 3429308c137SBarry Smith ierr = VecRestoreArrayRead(snes->vec_sol,&x);CHKERRQ(ierr); 343d9822059SBarry Smith ierr = MPI_Allreduce(&rnorm,&fnorm,1,MPIU_REAL,MPIU_SUM,((PetscObject)snes)->comm);CHKERRQ(ierr); 34421a4c9b1SBarry Smith ierr = MPI_Allreduce(act,fact,2,MPIU_INT,MPIU_SUM,((PetscObject)snes)->comm);CHKERRQ(ierr); 3456a9e2d46SJungho Lee ierr = MPI_Allreduce(act_bound,fact_bound,2,MPIU_INT,MPIU_SUM,((PetscObject)snes)->comm);CHKERRQ(ierr); 346f137e44dSBarry Smith fnorm = PetscSqrtReal(fnorm); 3476fd67740SBarry Smith 348649052a6SBarry Smith ierr = PetscViewerASCIIAddTab(viewer,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 349*4839bfe8SBarry Smith ierr = PetscViewerASCIIPrintf(viewer,"%3D SNES VI Function norm %14.12e Active lower constraints %D/%D upper constraints %D/%D Percent of total %g Percent of bounded %g\n",its,(double)fnorm,fact[0],fact_bound[0],fact[1],fact_bound[1],((double)(fact[0]+fact[1]))/((double)N),((double)(fact[0]+fact[1]))/((double)vi->ntruebounds));CHKERRQ(ierr); 3506a9e2d46SJungho Lee 351649052a6SBarry Smith ierr = PetscViewerASCIISubtractTab(viewer,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 3529308c137SBarry Smith PetscFunctionReturn(0); 3539308c137SBarry Smith } 3549308c137SBarry Smith 3552b4ed282SShri Abhyankar /* 3562b4ed282SShri Abhyankar Checks if J^T F = 0 which implies we've found a local minimum of the norm of the function, 3572b4ed282SShri 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 3582b4ed282SShri Abhyankar 0 = (J^T F)^T W = F^T J W iff W not in the null space of J. Thanks for Jorge More 3592b4ed282SShri Abhyankar for this trick. One assumes that the probability that W is in the null space of J is very, very small. 3602b4ed282SShri Abhyankar */ 3612b4ed282SShri Abhyankar #undef __FUNCT__ 3622b4ed282SShri Abhyankar #define __FUNCT__ "SNESVICheckLocalMin_Private" 363ace3abfcSBarry Smith PetscErrorCode SNESVICheckLocalMin_Private(SNES snes,Mat A,Vec F,Vec W,PetscReal fnorm,PetscBool *ismin) 3642b4ed282SShri Abhyankar { 3652b4ed282SShri Abhyankar PetscReal a1; 3662b4ed282SShri Abhyankar PetscErrorCode ierr; 367ace3abfcSBarry Smith PetscBool hastranspose; 3682b4ed282SShri Abhyankar 3692b4ed282SShri Abhyankar PetscFunctionBegin; 3702b4ed282SShri Abhyankar *ismin = PETSC_FALSE; 3712b4ed282SShri Abhyankar ierr = MatHasOperation(A,MATOP_MULT_TRANSPOSE,&hastranspose);CHKERRQ(ierr); 3722b4ed282SShri Abhyankar if (hastranspose) { 3732b4ed282SShri Abhyankar /* Compute || J^T F|| */ 3742b4ed282SShri Abhyankar ierr = MatMultTranspose(A,F,W);CHKERRQ(ierr); 3752b4ed282SShri Abhyankar ierr = VecNorm(W,NORM_2,&a1);CHKERRQ(ierr); 376*4839bfe8SBarry Smith ierr = PetscInfo1(snes,"|| J^T F|| %g near zero implies found a local minimum\n",(double)(a1/fnorm));CHKERRQ(ierr); 3772b4ed282SShri Abhyankar if (a1/fnorm < 1.e-4) *ismin = PETSC_TRUE; 3782b4ed282SShri Abhyankar } else { 3792b4ed282SShri Abhyankar Vec work; 3802b4ed282SShri Abhyankar PetscScalar result; 3812b4ed282SShri Abhyankar PetscReal wnorm; 3822b4ed282SShri Abhyankar 3832b4ed282SShri Abhyankar ierr = VecSetRandom(W,PETSC_NULL);CHKERRQ(ierr); 3842b4ed282SShri Abhyankar ierr = VecNorm(W,NORM_2,&wnorm);CHKERRQ(ierr); 3852b4ed282SShri Abhyankar ierr = VecDuplicate(W,&work);CHKERRQ(ierr); 3862b4ed282SShri Abhyankar ierr = MatMult(A,W,work);CHKERRQ(ierr); 3872b4ed282SShri Abhyankar ierr = VecDot(F,work,&result);CHKERRQ(ierr); 3886bf464f9SBarry Smith ierr = VecDestroy(&work);CHKERRQ(ierr); 3892b4ed282SShri Abhyankar a1 = PetscAbsScalar(result)/(fnorm*wnorm); 390*4839bfe8SBarry Smith ierr = PetscInfo1(snes,"(F^T J random)/(|| F ||*||random|| %g near zero implies found a local minimum\n",(double)a1);CHKERRQ(ierr); 3912b4ed282SShri Abhyankar if (a1 < 1.e-4) *ismin = PETSC_TRUE; 3922b4ed282SShri Abhyankar } 3932b4ed282SShri Abhyankar PetscFunctionReturn(0); 3942b4ed282SShri Abhyankar } 3952b4ed282SShri Abhyankar 3962b4ed282SShri Abhyankar /* 3972b4ed282SShri Abhyankar Checks if J^T(F - J*X) = 0 3982b4ed282SShri Abhyankar */ 3992b4ed282SShri Abhyankar #undef __FUNCT__ 4002b4ed282SShri Abhyankar #define __FUNCT__ "SNESVICheckResidual_Private" 4012b4ed282SShri Abhyankar PetscErrorCode SNESVICheckResidual_Private(SNES snes,Mat A,Vec F,Vec X,Vec W1,Vec W2) 4022b4ed282SShri Abhyankar { 4032b4ed282SShri Abhyankar PetscReal a1,a2; 4042b4ed282SShri Abhyankar PetscErrorCode ierr; 405ace3abfcSBarry Smith PetscBool hastranspose; 4062b4ed282SShri Abhyankar 4072b4ed282SShri Abhyankar PetscFunctionBegin; 4082b4ed282SShri Abhyankar ierr = MatHasOperation(A,MATOP_MULT_TRANSPOSE,&hastranspose);CHKERRQ(ierr); 4092b4ed282SShri Abhyankar if (hastranspose) { 4102b4ed282SShri Abhyankar ierr = MatMult(A,X,W1);CHKERRQ(ierr); 4112b4ed282SShri Abhyankar ierr = VecAXPY(W1,-1.0,F);CHKERRQ(ierr); 4122b4ed282SShri Abhyankar 4132b4ed282SShri Abhyankar /* Compute || J^T W|| */ 4142b4ed282SShri Abhyankar ierr = MatMultTranspose(A,W1,W2);CHKERRQ(ierr); 4152b4ed282SShri Abhyankar ierr = VecNorm(W1,NORM_2,&a1);CHKERRQ(ierr); 4162b4ed282SShri Abhyankar ierr = VecNorm(W2,NORM_2,&a2);CHKERRQ(ierr); 4172b4ed282SShri Abhyankar if (a1 != 0.0) { 418*4839bfe8SBarry Smith ierr = PetscInfo1(snes,"||J^T(F-Ax)||/||F-AX|| %g near zero implies inconsistent rhs\n",(double)(a2/a1));CHKERRQ(ierr); 4192b4ed282SShri Abhyankar } 4202b4ed282SShri Abhyankar } 4212b4ed282SShri Abhyankar PetscFunctionReturn(0); 4222b4ed282SShri Abhyankar } 4232b4ed282SShri Abhyankar 4242b4ed282SShri Abhyankar /* 4252b4ed282SShri Abhyankar SNESDefaultConverged_VI - Checks the convergence of the semismooth newton algorithm. 4262b4ed282SShri Abhyankar 4272b4ed282SShri Abhyankar Notes: 4282b4ed282SShri Abhyankar The convergence criterion currently implemented is 4292b4ed282SShri Abhyankar merit < abstol 4302b4ed282SShri Abhyankar merit < rtol*merit_initial 4312b4ed282SShri Abhyankar */ 4322b4ed282SShri Abhyankar #undef __FUNCT__ 4332b4ed282SShri Abhyankar #define __FUNCT__ "SNESDefaultConverged_VI" 4347fe79bc4SShri Abhyankar PetscErrorCode SNESDefaultConverged_VI(SNES snes,PetscInt it,PetscReal xnorm,PetscReal gradnorm,PetscReal fnorm,SNESConvergedReason *reason,void *dummy) 4352b4ed282SShri Abhyankar { 4362b4ed282SShri Abhyankar PetscErrorCode ierr; 4372b4ed282SShri Abhyankar 4382b4ed282SShri Abhyankar PetscFunctionBegin; 4392b4ed282SShri Abhyankar PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 4402b4ed282SShri Abhyankar PetscValidPointer(reason,6); 4412b4ed282SShri Abhyankar 4422b4ed282SShri Abhyankar *reason = SNES_CONVERGED_ITERATING; 4432b4ed282SShri Abhyankar 4442b4ed282SShri Abhyankar if (!it) { 4452b4ed282SShri Abhyankar /* set parameter for default relative tolerance convergence test */ 4467fe79bc4SShri Abhyankar snes->ttol = fnorm*snes->rtol; 4472b4ed282SShri Abhyankar } 4487fe79bc4SShri Abhyankar if (fnorm != fnorm) { 4492b4ed282SShri Abhyankar ierr = PetscInfo(snes,"Failed to converged, function norm is NaN\n");CHKERRQ(ierr); 4502b4ed282SShri Abhyankar *reason = SNES_DIVERGED_FNORM_NAN; 4517fe79bc4SShri Abhyankar } else if (fnorm < snes->abstol) { 452*4839bfe8SBarry Smith ierr = PetscInfo2(snes,"Converged due to function norm %g < %g\n",(double)fnorm,(double)snes->abstol);CHKERRQ(ierr); 4532b4ed282SShri Abhyankar *reason = SNES_CONVERGED_FNORM_ABS; 4542b4ed282SShri Abhyankar } else if (snes->nfuncs >= snes->max_funcs) { 4552b4ed282SShri Abhyankar ierr = PetscInfo2(snes,"Exceeded maximum number of function evaluations: %D > %D\n",snes->nfuncs,snes->max_funcs);CHKERRQ(ierr); 4562b4ed282SShri Abhyankar *reason = SNES_DIVERGED_FUNCTION_COUNT; 4572b4ed282SShri Abhyankar } 4582b4ed282SShri Abhyankar 4592b4ed282SShri Abhyankar if (it && !*reason) { 4607fe79bc4SShri Abhyankar if (fnorm < snes->ttol) { 461*4839bfe8SBarry Smith ierr = PetscInfo2(snes,"Converged due to function norm %g < %g (relative tolerance)\n",(double)fnorm,(double)snes->ttol);CHKERRQ(ierr); 4622b4ed282SShri Abhyankar *reason = SNES_CONVERGED_FNORM_RELATIVE; 4632b4ed282SShri Abhyankar } 4642b4ed282SShri Abhyankar } 4652b4ed282SShri Abhyankar PetscFunctionReturn(0); 4662b4ed282SShri Abhyankar } 4672b4ed282SShri Abhyankar 4682b4ed282SShri Abhyankar /* 4692b4ed282SShri Abhyankar SNESVIComputeMeritFunction - Evaluates the merit function for the mixed complementarity problem. 4702b4ed282SShri Abhyankar 4712b4ed282SShri Abhyankar Input Parameter: 4722b4ed282SShri Abhyankar . phi - the semismooth function 4732b4ed282SShri Abhyankar 4742b4ed282SShri Abhyankar Output Parameter: 4752b4ed282SShri Abhyankar . merit - the merit function 4762b4ed282SShri Abhyankar . phinorm - ||phi|| 4772b4ed282SShri Abhyankar 4782b4ed282SShri Abhyankar Notes: 4792b4ed282SShri Abhyankar The merit function for the mixed complementarity problem is defined as 4802b4ed282SShri Abhyankar merit = 0.5*phi^T*phi 4812b4ed282SShri Abhyankar */ 4822b4ed282SShri Abhyankar #undef __FUNCT__ 4832b4ed282SShri Abhyankar #define __FUNCT__ "SNESVIComputeMeritFunction" 4842b4ed282SShri Abhyankar static PetscErrorCode SNESVIComputeMeritFunction(Vec phi, PetscReal* merit,PetscReal* phinorm) 4852b4ed282SShri Abhyankar { 4862b4ed282SShri Abhyankar PetscErrorCode ierr; 4872b4ed282SShri Abhyankar 4882b4ed282SShri Abhyankar PetscFunctionBegin; 4895f48b12bSBarry Smith ierr = VecNormBegin(phi,NORM_2,phinorm);CHKERRQ(ierr); 4905f48b12bSBarry Smith ierr = VecNormEnd(phi,NORM_2,phinorm);CHKERRQ(ierr); 4912b4ed282SShri Abhyankar 4922b4ed282SShri Abhyankar *merit = 0.5*(*phinorm)*(*phinorm); 4932b4ed282SShri Abhyankar PetscFunctionReturn(0); 4942b4ed282SShri Abhyankar } 4952b4ed282SShri Abhyankar 4967f6f51e9SSatish Balay PETSC_STATIC_INLINE PetscScalar Phi(PetscScalar a,PetscScalar b) 4974c21c6cdSBarry Smith { 498bec29f96SSatish Balay return a + b - PetscSqrtScalar(a*a + b*b); 4994c21c6cdSBarry Smith } 5004c21c6cdSBarry Smith 5017f6f51e9SSatish Balay PETSC_STATIC_INLINE PetscScalar DPhi(PetscScalar a,PetscScalar b) 5024c21c6cdSBarry Smith { 503bec29f96SSatish Balay if ((PetscAbsScalar(a) >= 1.e-6) || (PetscAbsScalar(b) >= 1.e-6)) return 1.0 - a/ PetscSqrtScalar(a*a + b*b); 5045559b345SBarry Smith else return .5; 5054c21c6cdSBarry Smith } 5064c21c6cdSBarry Smith 5072b4ed282SShri Abhyankar /* 5081f79c099SShri Abhyankar SNESVIComputeFunction - Reformulates a system of nonlinear equations in mixed complementarity form to a system of nonlinear equations in semismooth form. 5092b4ed282SShri Abhyankar 5102b4ed282SShri Abhyankar Input Parameters: 5112b4ed282SShri Abhyankar . snes - the SNES context 5122b4ed282SShri Abhyankar . x - current iterate 5132b4ed282SShri Abhyankar . functx - user defined function context 5142b4ed282SShri Abhyankar 5152b4ed282SShri Abhyankar Output Parameters: 5162b4ed282SShri Abhyankar . phi - Semismooth function 5172b4ed282SShri Abhyankar 5182b4ed282SShri Abhyankar */ 5192b4ed282SShri Abhyankar #undef __FUNCT__ 5201f79c099SShri Abhyankar #define __FUNCT__ "SNESVIComputeFunction" 5211f79c099SShri Abhyankar static PetscErrorCode SNESVIComputeFunction(SNES snes,Vec X,Vec phi,void* functx) 5222b4ed282SShri Abhyankar { 5232b4ed282SShri Abhyankar PetscErrorCode ierr; 5242b4ed282SShri Abhyankar SNES_VI *vi = (SNES_VI*)snes->data; 5252b4ed282SShri Abhyankar Vec Xl = vi->xl,Xu = vi->xu,F = snes->vec_func; 5264c21c6cdSBarry Smith PetscScalar *phi_arr,*x_arr,*f_arr,*l,*u; 5272b4ed282SShri Abhyankar PetscInt i,nlocal; 5282b4ed282SShri Abhyankar 5292b4ed282SShri Abhyankar PetscFunctionBegin; 5302b4ed282SShri Abhyankar ierr = (*vi->computeuserfunction)(snes,X,F,functx);CHKERRQ(ierr); 5312b4ed282SShri Abhyankar ierr = VecGetLocalSize(X,&nlocal);CHKERRQ(ierr); 5322b4ed282SShri Abhyankar ierr = VecGetArray(X,&x_arr);CHKERRQ(ierr); 5332b4ed282SShri Abhyankar ierr = VecGetArray(F,&f_arr);CHKERRQ(ierr); 5342b4ed282SShri Abhyankar ierr = VecGetArray(Xl,&l);CHKERRQ(ierr); 5352b4ed282SShri Abhyankar ierr = VecGetArray(Xu,&u);CHKERRQ(ierr); 5362b4ed282SShri Abhyankar ierr = VecGetArray(phi,&phi_arr);CHKERRQ(ierr); 5372b4ed282SShri Abhyankar 5382b4ed282SShri Abhyankar for (i=0;i < nlocal;i++) { 53910f5ae6bSBarry Smith if ((PetscRealPart(l[i]) <= SNES_VI_NINF) && (PetscRealPart(u[i]) >= SNES_VI_INF)) { /* no constraints on variable */ 5404c21c6cdSBarry Smith phi_arr[i] = f_arr[i]; 54110f5ae6bSBarry Smith } else if (PetscRealPart(l[i]) <= SNES_VI_NINF) { /* upper bound on variable only */ 5424c21c6cdSBarry Smith phi_arr[i] = -Phi(u[i] - x_arr[i],-f_arr[i]); 54310f5ae6bSBarry Smith } else if (PetscRealPart(u[i]) >= SNES_VI_INF) { /* lower bound on variable only */ 5444c21c6cdSBarry Smith phi_arr[i] = Phi(x_arr[i] - l[i],f_arr[i]); 5455559b345SBarry Smith } else if (l[i] == u[i]) { 5462b4ed282SShri Abhyankar phi_arr[i] = l[i] - x_arr[i]; 5475559b345SBarry Smith } else { /* both bounds on variable */ 5484c21c6cdSBarry Smith phi_arr[i] = Phi(x_arr[i] - l[i],-Phi(u[i] - x_arr[i],-f_arr[i])); 5492b4ed282SShri Abhyankar } 5502b4ed282SShri Abhyankar } 5512b4ed282SShri Abhyankar 5522b4ed282SShri Abhyankar ierr = VecRestoreArray(X,&x_arr);CHKERRQ(ierr); 5532b4ed282SShri Abhyankar ierr = VecRestoreArray(F,&f_arr);CHKERRQ(ierr); 5542b4ed282SShri Abhyankar ierr = VecRestoreArray(Xl,&l);CHKERRQ(ierr); 5552b4ed282SShri Abhyankar ierr = VecRestoreArray(Xu,&u);CHKERRQ(ierr); 5562b4ed282SShri Abhyankar ierr = VecRestoreArray(phi,&phi_arr);CHKERRQ(ierr); 5572b4ed282SShri Abhyankar PetscFunctionReturn(0); 5582b4ed282SShri Abhyankar } 5592b4ed282SShri Abhyankar 5602b4ed282SShri Abhyankar /* 561a79edbefSShri Abhyankar SNESVIComputeBsubdifferentialVectors - Computes the diagonal shift (Da) and row scaling (Db) vectors needed for the 562a79edbefSShri Abhyankar the semismooth jacobian. 5632b4ed282SShri Abhyankar */ 5642b4ed282SShri Abhyankar #undef __FUNCT__ 565a79edbefSShri Abhyankar #define __FUNCT__ "SNESVIComputeBsubdifferentialVectors" 566a79edbefSShri Abhyankar PetscErrorCode SNESVIComputeBsubdifferentialVectors(SNES snes,Vec X,Vec F,Mat jac,Vec Da,Vec Db) 5672b4ed282SShri Abhyankar { 5682b4ed282SShri Abhyankar PetscErrorCode ierr; 5692b4ed282SShri Abhyankar SNES_VI *vi = (SNES_VI*)snes->data; 5704c21c6cdSBarry Smith PetscScalar *l,*u,*x,*f,*da,*db,da1,da2,db1,db2; 5712b4ed282SShri Abhyankar PetscInt i,nlocal; 5722b4ed282SShri Abhyankar 5732b4ed282SShri Abhyankar PetscFunctionBegin; 5742b4ed282SShri Abhyankar 5752b4ed282SShri Abhyankar ierr = VecGetArray(X,&x);CHKERRQ(ierr); 5762b4ed282SShri Abhyankar ierr = VecGetArray(F,&f);CHKERRQ(ierr); 5772b4ed282SShri Abhyankar ierr = VecGetArray(vi->xl,&l);CHKERRQ(ierr); 5782b4ed282SShri Abhyankar ierr = VecGetArray(vi->xu,&u);CHKERRQ(ierr); 579a79edbefSShri Abhyankar ierr = VecGetArray(Da,&da);CHKERRQ(ierr); 580a79edbefSShri Abhyankar ierr = VecGetArray(Db,&db);CHKERRQ(ierr); 5812b4ed282SShri Abhyankar ierr = VecGetLocalSize(X,&nlocal);CHKERRQ(ierr); 5824c21c6cdSBarry Smith 5832b4ed282SShri Abhyankar for (i=0;i< nlocal;i++) { 58410f5ae6bSBarry Smith if ((PetscRealPart(l[i]) <= SNES_VI_NINF) && (PetscRealPart(u[i]) >= SNES_VI_INF)) {/* no constraints on variable */ 5854c21c6cdSBarry Smith da[i] = 0; 5862b4ed282SShri Abhyankar db[i] = 1; 58710f5ae6bSBarry Smith } else if (PetscRealPart(l[i]) <= SNES_VI_NINF) { /* upper bound on variable only */ 5884c21c6cdSBarry Smith da[i] = DPhi(u[i] - x[i], -f[i]); 5894c21c6cdSBarry Smith db[i] = DPhi(-f[i],u[i] - x[i]); 59010f5ae6bSBarry Smith } else if (PetscRealPart(u[i]) >= SNES_VI_INF) { /* lower bound on variable only */ 5915559b345SBarry Smith da[i] = DPhi(x[i] - l[i], f[i]); 5925559b345SBarry Smith db[i] = DPhi(f[i],x[i] - l[i]); 5935559b345SBarry Smith } else if (l[i] == u[i]) { /* fixed variable */ 5944c21c6cdSBarry Smith da[i] = 1; 5952b4ed282SShri Abhyankar db[i] = 0; 5965559b345SBarry Smith } else { /* upper and lower bounds on variable */ 5974c21c6cdSBarry Smith da1 = DPhi(x[i] - l[i], -Phi(u[i] - x[i], -f[i])); 5984c21c6cdSBarry Smith db1 = DPhi(-Phi(u[i] - x[i], -f[i]),x[i] - l[i]); 5994c21c6cdSBarry Smith da2 = DPhi(u[i] - x[i], -f[i]); 6004c21c6cdSBarry Smith db2 = DPhi(-f[i],u[i] - x[i]); 6014c21c6cdSBarry Smith da[i] = da1 + db1*da2; 6024c21c6cdSBarry Smith db[i] = db1*db2; 6032b4ed282SShri Abhyankar } 6042b4ed282SShri Abhyankar } 6055559b345SBarry Smith 6062b4ed282SShri Abhyankar ierr = VecRestoreArray(X,&x);CHKERRQ(ierr); 6072b4ed282SShri Abhyankar ierr = VecRestoreArray(F,&f);CHKERRQ(ierr); 6082b4ed282SShri Abhyankar ierr = VecRestoreArray(vi->xl,&l);CHKERRQ(ierr); 6092b4ed282SShri Abhyankar ierr = VecRestoreArray(vi->xu,&u);CHKERRQ(ierr); 610a79edbefSShri Abhyankar ierr = VecRestoreArray(Da,&da);CHKERRQ(ierr); 611a79edbefSShri Abhyankar ierr = VecRestoreArray(Db,&db);CHKERRQ(ierr); 612a79edbefSShri Abhyankar PetscFunctionReturn(0); 613a79edbefSShri Abhyankar } 614a79edbefSShri Abhyankar 615a79edbefSShri Abhyankar /* 616a79edbefSShri 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. 617a79edbefSShri Abhyankar 618a79edbefSShri Abhyankar Input Parameters: 619a79edbefSShri Abhyankar . Da - Diagonal shift vector for the semismooth jacobian. 620a79edbefSShri Abhyankar . Db - Row scaling vector for the semismooth jacobian. 621a79edbefSShri Abhyankar 622a79edbefSShri Abhyankar Output Parameters: 623a79edbefSShri Abhyankar . jac - semismooth jacobian 624a79edbefSShri Abhyankar . jac_pre - optional preconditioning matrix 625a79edbefSShri Abhyankar 626a79edbefSShri Abhyankar Notes: 627a79edbefSShri Abhyankar The semismooth jacobian matrix is given by 628a79edbefSShri Abhyankar jac = Da + Db*jacfun 629a79edbefSShri Abhyankar where Db is the row scaling matrix stored as a vector, 630a79edbefSShri Abhyankar Da is the diagonal perturbation matrix stored as a vector 631a79edbefSShri Abhyankar and jacfun is the jacobian of the original nonlinear function. 632a79edbefSShri Abhyankar */ 633a79edbefSShri Abhyankar #undef __FUNCT__ 634a79edbefSShri Abhyankar #define __FUNCT__ "SNESVIComputeJacobian" 635a79edbefSShri Abhyankar PetscErrorCode SNESVIComputeJacobian(Mat jac, Mat jac_pre,Vec Da, Vec Db) 636a79edbefSShri Abhyankar { 637a79edbefSShri Abhyankar PetscErrorCode ierr; 638a79edbefSShri Abhyankar 6392b4ed282SShri Abhyankar /* Do row scaling and add diagonal perturbation */ 640a79edbefSShri Abhyankar ierr = MatDiagonalScale(jac,Db,PETSC_NULL);CHKERRQ(ierr); 641a79edbefSShri Abhyankar ierr = MatDiagonalSet(jac,Da,ADD_VALUES);CHKERRQ(ierr); 642a79edbefSShri Abhyankar if (jac != jac_pre) { /* If jac and jac_pre are different */ 643a79edbefSShri Abhyankar ierr = MatDiagonalScale(jac_pre,Db,PETSC_NULL); 644a79edbefSShri Abhyankar ierr = MatDiagonalSet(jac_pre,Da,ADD_VALUES);CHKERRQ(ierr); 6452b4ed282SShri Abhyankar } 6462b4ed282SShri Abhyankar PetscFunctionReturn(0); 6472b4ed282SShri Abhyankar } 6482b4ed282SShri Abhyankar 6492b4ed282SShri Abhyankar /* 650ee657d29SShri Abhyankar SNESVIComputeMeritFunctionGradient - Computes the gradient of the merit function psi. 651ee657d29SShri Abhyankar 652ee657d29SShri Abhyankar Input Parameters: 653ee657d29SShri Abhyankar phi - semismooth function. 654ee657d29SShri Abhyankar H - semismooth jacobian 655ee657d29SShri Abhyankar 656ee657d29SShri Abhyankar Output Parameters: 657ee657d29SShri Abhyankar dpsi - merit function gradient 658ee657d29SShri Abhyankar 659ee657d29SShri Abhyankar Notes: 660ee657d29SShri Abhyankar The merit function gradient is computed as follows 661ee657d29SShri Abhyankar dpsi = H^T*phi 662ee657d29SShri Abhyankar */ 663ee657d29SShri Abhyankar #undef __FUNCT__ 664ee657d29SShri Abhyankar #define __FUNCT__ "SNESVIComputeMeritFunctionGradient" 665ee657d29SShri Abhyankar PetscErrorCode SNESVIComputeMeritFunctionGradient(Mat H, Vec phi, Vec dpsi) 666ee657d29SShri Abhyankar { 667ee657d29SShri Abhyankar PetscErrorCode ierr; 668ee657d29SShri Abhyankar 669ee657d29SShri Abhyankar PetscFunctionBegin; 6705f48b12bSBarry Smith ierr = MatMultTranspose(H,phi,dpsi);CHKERRQ(ierr); 671ee657d29SShri Abhyankar PetscFunctionReturn(0); 672ee657d29SShri Abhyankar } 673ee657d29SShri Abhyankar 674c1a5e521SShri Abhyankar /* -------------------------------------------------------------------------- */ 675c1a5e521SShri Abhyankar /* 676c1a5e521SShri Abhyankar SNESVIProjectOntoBounds - Projects X onto the feasible region so that Xl[i] <= X[i] <= Xu[i] for i = 1...n. 677c1a5e521SShri Abhyankar 678c1a5e521SShri Abhyankar Input Parameters: 679c1a5e521SShri Abhyankar . SNES - nonlinear solver context 680c1a5e521SShri Abhyankar 681c1a5e521SShri Abhyankar Output Parameters: 682c1a5e521SShri Abhyankar . X - Bound projected X 683c1a5e521SShri Abhyankar 684c1a5e521SShri Abhyankar */ 685c1a5e521SShri Abhyankar 686c1a5e521SShri Abhyankar #undef __FUNCT__ 687c1a5e521SShri Abhyankar #define __FUNCT__ "SNESVIProjectOntoBounds" 688c1a5e521SShri Abhyankar PetscErrorCode SNESVIProjectOntoBounds(SNES snes,Vec X) 689c1a5e521SShri Abhyankar { 690c1a5e521SShri Abhyankar PetscErrorCode ierr; 691c1a5e521SShri Abhyankar SNES_VI *vi = (SNES_VI*)snes->data; 692c1a5e521SShri Abhyankar const PetscScalar *xl,*xu; 693c1a5e521SShri Abhyankar PetscScalar *x; 694c1a5e521SShri Abhyankar PetscInt i,n; 695c1a5e521SShri Abhyankar 696c1a5e521SShri Abhyankar PetscFunctionBegin; 697c1a5e521SShri Abhyankar ierr = VecGetLocalSize(X,&n);CHKERRQ(ierr); 698c1a5e521SShri Abhyankar ierr = VecGetArray(X,&x);CHKERRQ(ierr); 699c1a5e521SShri Abhyankar ierr = VecGetArrayRead(vi->xl,&xl);CHKERRQ(ierr); 700c1a5e521SShri Abhyankar ierr = VecGetArrayRead(vi->xu,&xu);CHKERRQ(ierr); 701c1a5e521SShri Abhyankar 702c1a5e521SShri Abhyankar for(i = 0;i<n;i++) { 70310f5ae6bSBarry Smith if (PetscRealPart(x[i]) < PetscRealPart(xl[i])) x[i] = xl[i]; 70410f5ae6bSBarry Smith else if (PetscRealPart(x[i]) > PetscRealPart(xu[i])) x[i] = xu[i]; 705c1a5e521SShri Abhyankar } 706c1a5e521SShri Abhyankar ierr = VecRestoreArray(X,&x);CHKERRQ(ierr); 707c1a5e521SShri Abhyankar ierr = VecRestoreArrayRead(vi->xl,&xl);CHKERRQ(ierr); 708c1a5e521SShri Abhyankar ierr = VecRestoreArrayRead(vi->xu,&xu);CHKERRQ(ierr); 709c1a5e521SShri Abhyankar PetscFunctionReturn(0); 710c1a5e521SShri Abhyankar } 711c1a5e521SShri Abhyankar 7122b4ed282SShri Abhyankar /* -------------------------------------------------------------------- 7132b4ed282SShri Abhyankar 7142b4ed282SShri Abhyankar This file implements a semismooth truncated Newton method with a line search, 7152b4ed282SShri Abhyankar for solving a system of nonlinear equations in complementarity form, using the KSP, Vec, 7162b4ed282SShri Abhyankar and Mat interfaces for linear solvers, vectors, and matrices, 7172b4ed282SShri Abhyankar respectively. 7182b4ed282SShri Abhyankar 7192b4ed282SShri Abhyankar The following basic routines are required for each nonlinear solver: 7202b4ed282SShri Abhyankar SNESCreate_XXX() - Creates a nonlinear solver context 7212b4ed282SShri Abhyankar SNESSetFromOptions_XXX() - Sets runtime options 7222b4ed282SShri Abhyankar SNESSolve_XXX() - Solves the nonlinear system 7232b4ed282SShri Abhyankar SNESDestroy_XXX() - Destroys the nonlinear solver context 7242b4ed282SShri Abhyankar The suffix "_XXX" denotes a particular implementation, in this case 7252b4ed282SShri Abhyankar we use _VI (e.g., SNESCreate_VI, SNESSolve_VI) for solving 7262b4ed282SShri Abhyankar systems of nonlinear equations with a line search (LS) method. 7272b4ed282SShri Abhyankar These routines are actually called via the common user interface 7282b4ed282SShri Abhyankar routines SNESCreate(), SNESSetFromOptions(), SNESSolve(), and 7292b4ed282SShri Abhyankar SNESDestroy(), so the application code interface remains identical 7302b4ed282SShri Abhyankar for all nonlinear solvers. 7312b4ed282SShri Abhyankar 7322b4ed282SShri Abhyankar Another key routine is: 7332b4ed282SShri Abhyankar SNESSetUp_XXX() - Prepares for the use of a nonlinear solver 7342b4ed282SShri Abhyankar by setting data structures and options. The interface routine SNESSetUp() 7352b4ed282SShri Abhyankar is not usually called directly by the user, but instead is called by 7362b4ed282SShri Abhyankar SNESSolve() if necessary. 7372b4ed282SShri Abhyankar 7382b4ed282SShri Abhyankar Additional basic routines are: 7392b4ed282SShri Abhyankar SNESView_XXX() - Prints details of runtime options that 7402b4ed282SShri Abhyankar have actually been used. 7412b4ed282SShri Abhyankar These are called by application codes via the interface routines 7422b4ed282SShri Abhyankar SNESView(). 7432b4ed282SShri Abhyankar 7442b4ed282SShri Abhyankar The various types of solvers (preconditioners, Krylov subspace methods, 7452b4ed282SShri Abhyankar nonlinear solvers, timesteppers) are all organized similarly, so the 7462b4ed282SShri Abhyankar above description applies to these categories also. 7472b4ed282SShri Abhyankar 7482b4ed282SShri Abhyankar -------------------------------------------------------------------- */ 7492b4ed282SShri Abhyankar /* 75069c03620SShri Abhyankar SNESSolveVI_SS - Solves the complementarity problem with a semismooth Newton 7512b4ed282SShri Abhyankar method using a line search. 7522b4ed282SShri Abhyankar 7532b4ed282SShri Abhyankar Input Parameters: 7542b4ed282SShri Abhyankar . snes - the SNES context 7552b4ed282SShri Abhyankar 7562b4ed282SShri Abhyankar Output Parameter: 7572b4ed282SShri Abhyankar . outits - number of iterations until termination 7582b4ed282SShri Abhyankar 7592b4ed282SShri Abhyankar Application Interface Routine: SNESSolve() 7602b4ed282SShri Abhyankar 7612b4ed282SShri Abhyankar Notes: 7622b4ed282SShri Abhyankar This implements essentially a semismooth Newton method with a 76351defd01SShri Abhyankar line search. The default line search does not do any line seach 76451defd01SShri Abhyankar but rather takes a full newton step. 7652b4ed282SShri Abhyankar */ 7662b4ed282SShri Abhyankar #undef __FUNCT__ 76769c03620SShri Abhyankar #define __FUNCT__ "SNESSolveVI_SS" 76869c03620SShri Abhyankar PetscErrorCode SNESSolveVI_SS(SNES snes) 7692b4ed282SShri Abhyankar { 7702b4ed282SShri Abhyankar SNES_VI *vi = (SNES_VI*)snes->data; 7712b4ed282SShri Abhyankar PetscErrorCode ierr; 7722b4ed282SShri Abhyankar PetscInt maxits,i,lits; 7733b336b49SShri Abhyankar PetscBool lssucceed; 7742b4ed282SShri Abhyankar MatStructure flg = DIFFERENT_NONZERO_PATTERN; 7752b4ed282SShri Abhyankar PetscReal gnorm,xnorm=0,ynorm; 7762b4ed282SShri Abhyankar Vec Y,X,F,G,W; 7772b4ed282SShri Abhyankar KSPConvergedReason kspreason; 7782b4ed282SShri Abhyankar 7792b4ed282SShri Abhyankar PetscFunctionBegin; 7809ce7406fSBarry Smith vi->computeuserfunction = snes->ops->computefunction; 7819ce7406fSBarry Smith snes->ops->computefunction = SNESVIComputeFunction; 7829ce7406fSBarry Smith 7832b4ed282SShri Abhyankar snes->numFailures = 0; 7842b4ed282SShri Abhyankar snes->numLinearSolveFailures = 0; 7852b4ed282SShri Abhyankar snes->reason = SNES_CONVERGED_ITERATING; 7862b4ed282SShri Abhyankar 7872b4ed282SShri Abhyankar maxits = snes->max_its; /* maximum number of iterations */ 7882b4ed282SShri Abhyankar X = snes->vec_sol; /* solution vector */ 7892b4ed282SShri Abhyankar F = snes->vec_func; /* residual vector */ 7902b4ed282SShri Abhyankar Y = snes->work[0]; /* work vectors */ 7912b4ed282SShri Abhyankar G = snes->work[1]; 7922b4ed282SShri Abhyankar W = snes->work[2]; 7932b4ed282SShri Abhyankar 7942b4ed282SShri Abhyankar ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 7952b4ed282SShri Abhyankar snes->iter = 0; 7962b4ed282SShri Abhyankar snes->norm = 0.0; 7972b4ed282SShri Abhyankar ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 7982b4ed282SShri Abhyankar 7997fe79bc4SShri Abhyankar ierr = SNESVIProjectOntoBounds(snes,X);CHKERRQ(ierr); 8002b4ed282SShri Abhyankar ierr = SNESComputeFunction(snes,X,vi->phi);CHKERRQ(ierr); 8012b4ed282SShri Abhyankar if (snes->domainerror) { 8022b4ed282SShri Abhyankar snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN; 8039ce7406fSBarry Smith snes->ops->computefunction = vi->computeuserfunction; 8042b4ed282SShri Abhyankar PetscFunctionReturn(0); 8052b4ed282SShri Abhyankar } 8062b4ed282SShri Abhyankar /* Compute Merit function */ 8072b4ed282SShri Abhyankar ierr = SNESVIComputeMeritFunction(vi->phi,&vi->merit,&vi->phinorm);CHKERRQ(ierr); 8082b4ed282SShri Abhyankar 8092b4ed282SShri Abhyankar ierr = VecNormBegin(X,NORM_2,&xnorm);CHKERRQ(ierr); /* xnorm <- ||x|| */ 8102b4ed282SShri Abhyankar ierr = VecNormEnd(X,NORM_2,&xnorm);CHKERRQ(ierr); 81162cbcd01SMatthew G Knepley if (PetscIsInfOrNanReal(vi->merit)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number"); 8122b4ed282SShri Abhyankar 8132b4ed282SShri Abhyankar ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 8142b4ed282SShri Abhyankar snes->norm = vi->phinorm; 8152b4ed282SShri Abhyankar ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 8162b4ed282SShri Abhyankar SNESLogConvHistory(snes,vi->phinorm,0); 8177a03ce2fSLisandro Dalcin ierr = SNESMonitor(snes,0,vi->phinorm);CHKERRQ(ierr); 8182b4ed282SShri Abhyankar 8192b4ed282SShri Abhyankar /* set parameter for default relative tolerance convergence test */ 8202b4ed282SShri Abhyankar snes->ttol = vi->phinorm*snes->rtol; 8212b4ed282SShri Abhyankar /* test convergence */ 8222b4ed282SShri Abhyankar ierr = (*snes->ops->converged)(snes,0,0.0,0.0,vi->phinorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); 8239ce7406fSBarry Smith if (snes->reason) { 8249ce7406fSBarry Smith snes->ops->computefunction = vi->computeuserfunction; 8259ce7406fSBarry Smith PetscFunctionReturn(0); 8269ce7406fSBarry Smith } 8272b4ed282SShri Abhyankar 8282b4ed282SShri Abhyankar for (i=0; i<maxits; i++) { 8292b4ed282SShri Abhyankar 8302b4ed282SShri Abhyankar /* Call general purpose update function */ 8312b4ed282SShri Abhyankar if (snes->ops->update) { 8322b4ed282SShri Abhyankar ierr = (*snes->ops->update)(snes, snes->iter);CHKERRQ(ierr); 8332b4ed282SShri Abhyankar } 8342b4ed282SShri Abhyankar 8352b4ed282SShri Abhyankar /* Solve J Y = Phi, where J is the semismooth jacobian */ 836a79edbefSShri Abhyankar /* Get the nonlinear function jacobian */ 8372b4ed282SShri Abhyankar ierr = SNESComputeJacobian(snes,X,&snes->jacobian,&snes->jacobian_pre,&flg);CHKERRQ(ierr); 838a79edbefSShri Abhyankar /* Get the diagonal shift and row scaling vectors */ 839a79edbefSShri Abhyankar ierr = SNESVIComputeBsubdifferentialVectors(snes,X,F,snes->jacobian,vi->Da,vi->Db);CHKERRQ(ierr); 840a79edbefSShri Abhyankar /* Compute the semismooth jacobian */ 841a79edbefSShri Abhyankar ierr = SNESVIComputeJacobian(snes->jacobian,snes->jacobian_pre,vi->Da,vi->Db);CHKERRQ(ierr); 842ee657d29SShri Abhyankar /* Compute the merit function gradient */ 843ee657d29SShri Abhyankar ierr = SNESVIComputeMeritFunctionGradient(snes->jacobian,vi->phi,vi->dpsi);CHKERRQ(ierr); 8442b4ed282SShri Abhyankar ierr = KSPSetOperators(snes->ksp,snes->jacobian,snes->jacobian_pre,flg);CHKERRQ(ierr); 8452b4ed282SShri Abhyankar ierr = SNES_KSPSolve(snes,snes->ksp,vi->phi,Y);CHKERRQ(ierr); 8462b4ed282SShri Abhyankar ierr = KSPGetConvergedReason(snes->ksp,&kspreason);CHKERRQ(ierr); 8473b336b49SShri Abhyankar 8483b336b49SShri Abhyankar if (kspreason < 0) { 8492b4ed282SShri Abhyankar if (++snes->numLinearSolveFailures >= snes->maxLinearSolveFailures) { 8502b4ed282SShri 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); 8512b4ed282SShri Abhyankar snes->reason = SNES_DIVERGED_LINEAR_SOLVE; 8522b4ed282SShri Abhyankar break; 8532b4ed282SShri Abhyankar } 8542b4ed282SShri Abhyankar } 8552b4ed282SShri Abhyankar ierr = KSPGetIterationNumber(snes->ksp,&lits);CHKERRQ(ierr); 8562b4ed282SShri Abhyankar snes->linear_its += lits; 8572b4ed282SShri Abhyankar ierr = PetscInfo2(snes,"iter=%D, linear solve iterations=%D\n",snes->iter,lits);CHKERRQ(ierr); 8582b4ed282SShri Abhyankar /* 8590661309fSPeter Brune if (snes->ops->precheckstep) { 860ace3abfcSBarry Smith PetscBool changed_y = PETSC_FALSE; 8610661309fSPeter Brune ierr = (*snes->ops->precheckstep)(snes,X,Y,snes->precheck,&changed_y);CHKERRQ(ierr); 8622b4ed282SShri Abhyankar } 8632b4ed282SShri Abhyankar 8642b4ed282SShri Abhyankar if (PetscLogPrintInfo){ 8652b4ed282SShri Abhyankar ierr = SNESVICheckResidual_Private(snes,snes->jacobian,F,Y,G,W);CHKERRQ(ierr); 8662b4ed282SShri Abhyankar } 8672b4ed282SShri Abhyankar */ 8682b4ed282SShri Abhyankar /* Compute a (scaled) negative update in the line search routine: 8692b4ed282SShri Abhyankar Y <- X - lambda*Y 8702b4ed282SShri Abhyankar and evaluate G = function(Y) (depends on the line search). 8712b4ed282SShri Abhyankar */ 8722b4ed282SShri Abhyankar ierr = VecCopy(Y,snes->vec_sol_update);CHKERRQ(ierr); 8732b4ed282SShri Abhyankar ynorm = 1; gnorm = vi->phinorm; 8740661309fSPeter Brune ierr = (*snes->ops->linesearch)(snes,snes->lsP,X,vi->phi,Y,vi->phinorm,xnorm,G,W,&ynorm,&gnorm,&lssucceed);CHKERRQ(ierr); 875*4839bfe8SBarry Smith ierr = PetscInfo4(snes,"fnorm=%18.16e, gnorm=%18.16e, ynorm=%18.16e, lssucceed=%d\n",(double)vi->phinorm,(double)gnorm,(double)ynorm,(int)lssucceed);CHKERRQ(ierr); 8762b4ed282SShri Abhyankar if (snes->reason == SNES_DIVERGED_FUNCTION_COUNT) break; 8772b4ed282SShri Abhyankar if (snes->domainerror) { 8782b4ed282SShri Abhyankar snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN; 8799ce7406fSBarry Smith snes->ops->computefunction = vi->computeuserfunction; 8802b4ed282SShri Abhyankar PetscFunctionReturn(0); 8812b4ed282SShri Abhyankar } 8822b4ed282SShri Abhyankar if (!lssucceed) { 8832b4ed282SShri Abhyankar if (++snes->numFailures >= snes->maxFailures) { 884ace3abfcSBarry Smith PetscBool ismin; 8852b4ed282SShri Abhyankar snes->reason = SNES_DIVERGED_LINE_SEARCH; 8862b4ed282SShri Abhyankar ierr = SNESVICheckLocalMin_Private(snes,snes->jacobian,G,W,gnorm,&ismin);CHKERRQ(ierr); 8872b4ed282SShri Abhyankar if (ismin) snes->reason = SNES_DIVERGED_LOCAL_MIN; 8882b4ed282SShri Abhyankar break; 8892b4ed282SShri Abhyankar } 8902b4ed282SShri Abhyankar } 8912b4ed282SShri Abhyankar /* Update function and solution vectors */ 8922b4ed282SShri Abhyankar vi->phinorm = gnorm; 8932b4ed282SShri Abhyankar vi->merit = 0.5*vi->phinorm*vi->phinorm; 8942b4ed282SShri Abhyankar ierr = VecCopy(G,vi->phi);CHKERRQ(ierr); 8952b4ed282SShri Abhyankar ierr = VecCopy(W,X);CHKERRQ(ierr); 8962b4ed282SShri Abhyankar /* Monitor convergence */ 8972b4ed282SShri Abhyankar ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 8982b4ed282SShri Abhyankar snes->iter = i+1; 8992b4ed282SShri Abhyankar snes->norm = vi->phinorm; 9002b4ed282SShri Abhyankar ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 9012b4ed282SShri Abhyankar SNESLogConvHistory(snes,snes->norm,lits); 9027a03ce2fSLisandro Dalcin ierr = SNESMonitor(snes,snes->iter,snes->norm);CHKERRQ(ierr); 9032b4ed282SShri Abhyankar /* Test for convergence, xnorm = || X || */ 9042b4ed282SShri Abhyankar if (snes->ops->converged != SNESSkipConverged) { ierr = VecNorm(X,NORM_2,&xnorm);CHKERRQ(ierr); } 9052b4ed282SShri Abhyankar ierr = (*snes->ops->converged)(snes,snes->iter,xnorm,ynorm,vi->phinorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); 9062b4ed282SShri Abhyankar if (snes->reason) break; 9072b4ed282SShri Abhyankar } 9082b4ed282SShri Abhyankar if (i == maxits) { 9092b4ed282SShri Abhyankar ierr = PetscInfo1(snes,"Maximum number of iterations has been reached: %D\n",maxits);CHKERRQ(ierr); 9102b4ed282SShri Abhyankar if(!snes->reason) snes->reason = SNES_DIVERGED_MAX_IT; 9112b4ed282SShri Abhyankar } 9129ce7406fSBarry Smith snes->ops->computefunction = vi->computeuserfunction; 9132b4ed282SShri Abhyankar PetscFunctionReturn(0); 9142b4ed282SShri Abhyankar } 91569c03620SShri Abhyankar 91669c03620SShri Abhyankar #undef __FUNCT__ 917693ddf92SShri Abhyankar #define __FUNCT__ "SNESVIGetActiveSetIS" 918693ddf92SShri Abhyankar /* 919693ddf92SShri Abhyankar SNESVIGetActiveSetIndices - Gets the global indices for the active set variables 920693ddf92SShri Abhyankar 921693ddf92SShri Abhyankar Input parameter 922693ddf92SShri Abhyankar . snes - the SNES context 923693ddf92SShri Abhyankar . X - the snes solution vector 924693ddf92SShri Abhyankar . F - the nonlinear function vector 925693ddf92SShri Abhyankar 926693ddf92SShri Abhyankar Output parameter 927693ddf92SShri Abhyankar . ISact - active set index set 928693ddf92SShri Abhyankar */ 929693ddf92SShri Abhyankar PetscErrorCode SNESVIGetActiveSetIS(SNES snes,Vec X,Vec F,IS* ISact) 930d950fb63SShri Abhyankar { 931d950fb63SShri Abhyankar PetscErrorCode ierr; 932693ddf92SShri Abhyankar SNES_VI *vi = (SNES_VI*)snes->data; 933693ddf92SShri Abhyankar Vec Xl=vi->xl,Xu=vi->xu; 934693ddf92SShri Abhyankar const PetscScalar *x,*f,*xl,*xu; 935693ddf92SShri Abhyankar PetscInt *idx_act,i,nlocal,nloc_isact=0,ilow,ihigh,i1=0; 936d950fb63SShri Abhyankar 937d950fb63SShri Abhyankar PetscFunctionBegin; 938d950fb63SShri Abhyankar ierr = VecGetLocalSize(X,&nlocal);CHKERRQ(ierr); 939d950fb63SShri Abhyankar ierr = VecGetOwnershipRange(X,&ilow,&ihigh);CHKERRQ(ierr); 940fe835674SShri Abhyankar ierr = VecGetArrayRead(X,&x);CHKERRQ(ierr); 941fe835674SShri Abhyankar ierr = VecGetArrayRead(Xl,&xl);CHKERRQ(ierr); 942fe835674SShri Abhyankar ierr = VecGetArrayRead(Xu,&xu);CHKERRQ(ierr); 943fe835674SShri Abhyankar ierr = VecGetArrayRead(F,&f);CHKERRQ(ierr); 944693ddf92SShri Abhyankar /* Compute active set size */ 945d950fb63SShri Abhyankar for (i=0; i < nlocal;i++) { 946e6337399SBarry Smith if (!vi->ignorefunctionsign) { 94710f5ae6bSBarry 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++; 948e6337399SBarry Smith } else { 949e6337399SBarry Smith if (!(PetscRealPart(x[i]) > PetscRealPart(xl[i]) + 1.e-8 && PetscRealPart(x[i]) < PetscRealPart(xu[i]) - 1.e-8)) nloc_isact++; 950e6337399SBarry Smith } 951d950fb63SShri Abhyankar } 952693ddf92SShri Abhyankar 953d950fb63SShri Abhyankar ierr = PetscMalloc(nloc_isact*sizeof(PetscInt),&idx_act);CHKERRQ(ierr); 954d950fb63SShri Abhyankar 955693ddf92SShri Abhyankar /* Set active set indices */ 956d950fb63SShri Abhyankar for(i=0; i < nlocal; i++) { 957e6337399SBarry Smith if (!vi->ignorefunctionsign) { 95810f5ae6bSBarry 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; 959e6337399SBarry Smith } else { 960e6337399SBarry Smith if (!(PetscRealPart(x[i]) > PetscRealPart(xl[i]) + 1.e-8 && PetscRealPart(x[i]) < PetscRealPart(xu[i]) - 1.e-8)) idx_act[i1++] = ilow+i; 961e6337399SBarry Smith } 962d950fb63SShri Abhyankar } 963d950fb63SShri Abhyankar 964693ddf92SShri Abhyankar /* Create active set IS */ 96562298a1eSBarry Smith ierr = ISCreateGeneral(((PetscObject)snes)->comm,nloc_isact,idx_act,PETSC_OWN_POINTER,ISact);CHKERRQ(ierr); 966d950fb63SShri Abhyankar 967fe835674SShri Abhyankar ierr = VecRestoreArrayRead(X,&x);CHKERRQ(ierr); 968fe835674SShri Abhyankar ierr = VecRestoreArrayRead(Xl,&xl);CHKERRQ(ierr); 969fe835674SShri Abhyankar ierr = VecRestoreArrayRead(Xu,&xu);CHKERRQ(ierr); 970fe835674SShri Abhyankar ierr = VecRestoreArrayRead(F,&f);CHKERRQ(ierr); 971d950fb63SShri Abhyankar PetscFunctionReturn(0); 972d950fb63SShri Abhyankar } 973d950fb63SShri Abhyankar 974693ddf92SShri Abhyankar #undef __FUNCT__ 975693ddf92SShri Abhyankar #define __FUNCT__ "SNESVICreateIndexSets_RS" 976693ddf92SShri Abhyankar PetscErrorCode SNESVICreateIndexSets_RS(SNES snes,Vec X,Vec F,IS* ISact,IS* ISinact) 977693ddf92SShri Abhyankar { 978693ddf92SShri Abhyankar PetscErrorCode ierr; 979693ddf92SShri Abhyankar 980693ddf92SShri Abhyankar PetscFunctionBegin; 981693ddf92SShri Abhyankar ierr = SNESVIGetActiveSetIS(snes,X,F,ISact);CHKERRQ(ierr); 982693ddf92SShri Abhyankar ierr = ISComplement(*ISact,X->map->rstart,X->map->rend,ISinact);CHKERRQ(ierr); 983693ddf92SShri Abhyankar PetscFunctionReturn(0); 984693ddf92SShri Abhyankar } 985693ddf92SShri Abhyankar 986dbd914b8SShri Abhyankar /* Create active and inactive set vectors. The local size of this vector is set and petsc computes the global size */ 987dbd914b8SShri Abhyankar #undef __FUNCT__ 988fe835674SShri Abhyankar #define __FUNCT__ "SNESVICreateSubVectors" 989fe835674SShri Abhyankar PetscErrorCode SNESVICreateSubVectors(SNES snes,PetscInt n,Vec* newv) 990dbd914b8SShri Abhyankar { 991dbd914b8SShri Abhyankar PetscErrorCode ierr; 992dbd914b8SShri Abhyankar Vec v; 993dbd914b8SShri Abhyankar 994dbd914b8SShri Abhyankar PetscFunctionBegin; 995dbd914b8SShri Abhyankar ierr = VecCreate(((PetscObject)snes)->comm,&v);CHKERRQ(ierr); 996dbd914b8SShri Abhyankar ierr = VecSetSizes(v,n,PETSC_DECIDE);CHKERRQ(ierr); 997dbd914b8SShri Abhyankar ierr = VecSetFromOptions(v);CHKERRQ(ierr); 998dbd914b8SShri Abhyankar *newv = v; 999dbd914b8SShri Abhyankar 1000dbd914b8SShri Abhyankar PetscFunctionReturn(0); 1001dbd914b8SShri Abhyankar } 1002dbd914b8SShri Abhyankar 1003732bb160SShri Abhyankar /* Resets the snes PC and KSP when the active set sizes change */ 1004732bb160SShri Abhyankar #undef __FUNCT__ 1005732bb160SShri Abhyankar #define __FUNCT__ "SNESVIResetPCandKSP" 1006732bb160SShri Abhyankar PetscErrorCode SNESVIResetPCandKSP(SNES snes,Mat Amat,Mat Pmat) 1007732bb160SShri Abhyankar { 1008732bb160SShri Abhyankar PetscErrorCode ierr; 1009d0af7cd3SBarry Smith KSP snesksp; 1010dbd914b8SShri Abhyankar 1011732bb160SShri Abhyankar PetscFunctionBegin; 1012732bb160SShri Abhyankar ierr = SNESGetKSP(snes,&snesksp);CHKERRQ(ierr); 1013d0af7cd3SBarry Smith ierr = KSPReset(snesksp);CHKERRQ(ierr); 1014c2efdce3SBarry Smith 1015c2efdce3SBarry Smith /* 1016d0af7cd3SBarry Smith KSP kspnew; 1017d0af7cd3SBarry Smith PC pcnew; 1018d0af7cd3SBarry Smith const MatSolverPackage stype; 1019d0af7cd3SBarry Smith 1020c2efdce3SBarry Smith 1021732bb160SShri Abhyankar ierr = KSPCreate(((PetscObject)snes)->comm,&kspnew);CHKERRQ(ierr); 1022732bb160SShri Abhyankar kspnew->pc_side = snesksp->pc_side; 1023732bb160SShri Abhyankar kspnew->rtol = snesksp->rtol; 1024732bb160SShri Abhyankar kspnew->abstol = snesksp->abstol; 1025732bb160SShri Abhyankar kspnew->max_it = snesksp->max_it; 1026732bb160SShri Abhyankar ierr = KSPSetType(kspnew,((PetscObject)snesksp)->type_name);CHKERRQ(ierr); 1027732bb160SShri Abhyankar ierr = KSPGetPC(kspnew,&pcnew);CHKERRQ(ierr); 1028732bb160SShri Abhyankar ierr = PCSetType(kspnew->pc,((PetscObject)snesksp->pc)->type_name);CHKERRQ(ierr); 1029732bb160SShri Abhyankar ierr = PCSetOperators(kspnew->pc,Amat,Pmat,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr); 1030732bb160SShri Abhyankar ierr = PCFactorGetMatSolverPackage(snesksp->pc,&stype);CHKERRQ(ierr); 1031732bb160SShri Abhyankar ierr = PCFactorSetMatSolverPackage(kspnew->pc,stype);CHKERRQ(ierr); 10326bf464f9SBarry Smith ierr = KSPDestroy(&snesksp);CHKERRQ(ierr); 1033732bb160SShri Abhyankar snes->ksp = kspnew; 1034732bb160SShri Abhyankar ierr = PetscLogObjectParent(snes,kspnew);CHKERRQ(ierr); 1035d0af7cd3SBarry Smith ierr = KSPSetFromOptions(kspnew);CHKERRQ(ierr);*/ 1036732bb160SShri Abhyankar PetscFunctionReturn(0); 1037732bb160SShri Abhyankar } 103869c03620SShri Abhyankar 103969c03620SShri Abhyankar 1040fe835674SShri Abhyankar #undef __FUNCT__ 1041fe835674SShri Abhyankar #define __FUNCT__ "SNESVIComputeInactiveSetFnorm" 104210f5ae6bSBarry Smith PetscErrorCode SNESVIComputeInactiveSetFnorm(SNES snes,Vec F,Vec X,PetscReal *fnorm) 1043fe835674SShri Abhyankar { 1044fe835674SShri Abhyankar PetscErrorCode ierr; 1045fe835674SShri Abhyankar SNES_VI *vi = (SNES_VI*)snes->data; 1046fe835674SShri Abhyankar const PetscScalar *x,*xl,*xu,*f; 1047fe835674SShri Abhyankar PetscInt i,n; 1048fe835674SShri Abhyankar PetscReal rnorm; 1049fe835674SShri Abhyankar 1050fe835674SShri Abhyankar PetscFunctionBegin; 1051fe835674SShri Abhyankar ierr = VecGetLocalSize(X,&n);CHKERRQ(ierr); 1052fe835674SShri Abhyankar ierr = VecGetArrayRead(vi->xl,&xl);CHKERRQ(ierr); 1053fe835674SShri Abhyankar ierr = VecGetArrayRead(vi->xu,&xu);CHKERRQ(ierr); 1054fe835674SShri Abhyankar ierr = VecGetArrayRead(X,&x);CHKERRQ(ierr); 1055fe835674SShri Abhyankar ierr = VecGetArrayRead(F,&f);CHKERRQ(ierr); 1056fe835674SShri Abhyankar rnorm = 0.0; 1057e007de34SBarry Smith if (!vi->ignorefunctionsign) { 1058fe835674SShri Abhyankar for (i=0; i<n; i++) { 105910f5ae6bSBarry 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]); 1060fe835674SShri Abhyankar } 1061e007de34SBarry Smith } else { 1062e007de34SBarry Smith for (i=0; i<n; i++) { 1063e007de34SBarry Smith if ((PetscRealPart(x[i]) > PetscRealPart(xl[i]) + 1.e-8) && (PetscRealPart(x[i]) < PetscRealPart(xu[i]) - 1.e-8)) rnorm += PetscRealPart(PetscConj(f[i])*f[i]); 1064e007de34SBarry Smith } 1065e007de34SBarry Smith } 1066fe835674SShri Abhyankar ierr = VecRestoreArrayRead(F,&f);CHKERRQ(ierr); 1067fe835674SShri Abhyankar ierr = VecRestoreArrayRead(vi->xl,&xl);CHKERRQ(ierr); 1068fe835674SShri Abhyankar ierr = VecRestoreArrayRead(vi->xu,&xu);CHKERRQ(ierr); 1069fe835674SShri Abhyankar ierr = VecRestoreArrayRead(X,&x);CHKERRQ(ierr); 1070d9822059SBarry Smith ierr = MPI_Allreduce(&rnorm,fnorm,1,MPIU_REAL,MPIU_SUM,((PetscObject)snes)->comm);CHKERRQ(ierr); 107162d1f40fSBarry Smith *fnorm = PetscSqrtReal(*fnorm); 1072fe835674SShri Abhyankar PetscFunctionReturn(0); 1073fe835674SShri Abhyankar } 1074fe835674SShri Abhyankar 1075fe835674SShri Abhyankar /* Variational Inequality solver using reduce space method. No semismooth algorithm is 1076c2efdce3SBarry Smith implemented in this algorithm. It basically identifies the active constraints and does 1077c2efdce3SBarry Smith a linear solve on the other variables (those not associated with the active constraints). */ 1078d950fb63SShri Abhyankar #undef __FUNCT__ 1079d950fb63SShri Abhyankar #define __FUNCT__ "SNESSolveVI_RS" 1080d950fb63SShri Abhyankar PetscErrorCode SNESSolveVI_RS(SNES snes) 1081d950fb63SShri Abhyankar { 1082d950fb63SShri Abhyankar SNES_VI *vi = (SNES_VI*)snes->data; 1083d950fb63SShri Abhyankar PetscErrorCode ierr; 1084abcba341SShri Abhyankar PetscInt maxits,i,lits; 1085d950fb63SShri Abhyankar PetscBool lssucceed; 1086d950fb63SShri Abhyankar MatStructure flg = DIFFERENT_NONZERO_PATTERN; 1087fe835674SShri Abhyankar PetscReal fnorm,gnorm,xnorm=0,ynorm; 1088d950fb63SShri Abhyankar Vec Y,X,F,G,W; 1089d950fb63SShri Abhyankar KSPConvergedReason kspreason; 1090d950fb63SShri Abhyankar 1091d950fb63SShri Abhyankar PetscFunctionBegin; 1092d950fb63SShri Abhyankar snes->numFailures = 0; 1093d950fb63SShri Abhyankar snes->numLinearSolveFailures = 0; 1094d950fb63SShri Abhyankar snes->reason = SNES_CONVERGED_ITERATING; 1095d950fb63SShri Abhyankar 1096d950fb63SShri Abhyankar maxits = snes->max_its; /* maximum number of iterations */ 1097d950fb63SShri Abhyankar X = snes->vec_sol; /* solution vector */ 1098d950fb63SShri Abhyankar F = snes->vec_func; /* residual vector */ 1099d950fb63SShri Abhyankar Y = snes->work[0]; /* work vectors */ 1100d950fb63SShri Abhyankar G = snes->work[1]; 1101d950fb63SShri Abhyankar W = snes->work[2]; 1102d950fb63SShri Abhyankar 1103d950fb63SShri Abhyankar ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 1104d950fb63SShri Abhyankar snes->iter = 0; 1105d950fb63SShri Abhyankar snes->norm = 0.0; 1106d950fb63SShri Abhyankar ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 1107d950fb63SShri Abhyankar 11087fe79bc4SShri Abhyankar ierr = SNESVIProjectOntoBounds(snes,X);CHKERRQ(ierr); 1109fe835674SShri Abhyankar ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr); 1110d950fb63SShri Abhyankar if (snes->domainerror) { 1111d950fb63SShri Abhyankar snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN; 1112d950fb63SShri Abhyankar PetscFunctionReturn(0); 1113d950fb63SShri Abhyankar } 1114fe835674SShri Abhyankar ierr = SNESVIComputeInactiveSetFnorm(snes,F,X,&fnorm);CHKERRQ(ierr); 1115d950fb63SShri Abhyankar ierr = VecNormBegin(X,NORM_2,&xnorm);CHKERRQ(ierr); /* xnorm <- ||x|| */ 1116d950fb63SShri Abhyankar ierr = VecNormEnd(X,NORM_2,&xnorm);CHKERRQ(ierr); 111762cbcd01SMatthew G Knepley if (PetscIsInfOrNanReal(fnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number"); 1118d950fb63SShri Abhyankar 1119d950fb63SShri Abhyankar ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 1120fe835674SShri Abhyankar snes->norm = fnorm; 1121d950fb63SShri Abhyankar ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 1122fe835674SShri Abhyankar SNESLogConvHistory(snes,fnorm,0); 11237a03ce2fSLisandro Dalcin ierr = SNESMonitor(snes,0,fnorm);CHKERRQ(ierr); 1124d950fb63SShri Abhyankar 1125d950fb63SShri Abhyankar /* set parameter for default relative tolerance convergence test */ 1126fe835674SShri Abhyankar snes->ttol = fnorm*snes->rtol; 1127d950fb63SShri Abhyankar /* test convergence */ 1128fe835674SShri Abhyankar ierr = (*snes->ops->converged)(snes,0,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); 1129d950fb63SShri Abhyankar if (snes->reason) PetscFunctionReturn(0); 1130d950fb63SShri Abhyankar 11319ce20c35SJungho Lee 1132d950fb63SShri Abhyankar for (i=0; i<maxits; i++) { 1133d950fb63SShri Abhyankar 1134d950fb63SShri Abhyankar IS IS_act,IS_inact; /* _act -> active set _inact -> inactive set */ 1135a6b72b01SJungho Lee IS IS_redact; /* redundant active set */ 1136d950fb63SShri Abhyankar VecScatter scat_act,scat_inact; 1137abcba341SShri Abhyankar PetscInt nis_act,nis_inact; 1138fe835674SShri Abhyankar Vec Y_act,Y_inact,F_inact; 1139d950fb63SShri Abhyankar Mat jac_inact_inact,prejac_inact_inact; 114062298a1eSBarry Smith IS keptrows; 1141abcba341SShri Abhyankar PetscBool isequal; 1142d950fb63SShri Abhyankar 1143d950fb63SShri Abhyankar /* Call general purpose update function */ 1144d950fb63SShri Abhyankar if (snes->ops->update) { 1145d950fb63SShri Abhyankar ierr = (*snes->ops->update)(snes, snes->iter);CHKERRQ(ierr); 1146d950fb63SShri Abhyankar } 1147d950fb63SShri Abhyankar ierr = SNESComputeJacobian(snes,X,&snes->jacobian,&snes->jacobian_pre,&flg);CHKERRQ(ierr); 114862298a1eSBarry Smith 11499ce20c35SJungho Lee 1150d950fb63SShri Abhyankar /* Create active and inactive index sets */ 1151a6b72b01SJungho Lee 1152a6b72b01SJungho Lee /*original 1153693ddf92SShri Abhyankar ierr = SNESVICreateIndexSets_RS(snes,X,F,&IS_act,&IS_inact);CHKERRQ(ierr); 1154a6b72b01SJungho Lee */ 1155a6b72b01SJungho Lee ierr = SNESVIGetActiveSetIS(snes,X,F,&IS_act);CHKERRQ(ierr); 1156a6b72b01SJungho Lee 1157a6b72b01SJungho Lee if (vi->checkredundancy) { 1158a6b72b01SJungho Lee (*vi->checkredundancy)(snes,IS_act,&IS_redact,vi->ctxP);CHKERRQ(ierr); 1159ed70e96aSJungho Lee if (IS_redact){ 1160ed70e96aSJungho Lee ierr = ISSort(IS_redact);CHKERRQ(ierr); 1161a6b72b01SJungho Lee ierr = ISComplement(IS_redact,X->map->rstart,X->map->rend,&IS_inact);CHKERRQ(ierr); 1162a6b72b01SJungho Lee ierr = ISDestroy(&IS_redact);CHKERRQ(ierr); 1163ed70e96aSJungho Lee } 1164ed70e96aSJungho Lee else { 1165ed70e96aSJungho Lee ierr = ISComplement(IS_act,X->map->rstart,X->map->rend,&IS_inact);CHKERRQ(ierr); 1166ed70e96aSJungho Lee } 1167a6b72b01SJungho Lee } else { 1168a6b72b01SJungho Lee ierr = ISComplement(IS_act,X->map->rstart,X->map->rend,&IS_inact);CHKERRQ(ierr); 1169a6b72b01SJungho Lee } 1170d950fb63SShri Abhyankar 11714dcab191SBarry Smith 1172abcba341SShri Abhyankar /* Create inactive set submatrix */ 117362298a1eSBarry Smith ierr = MatGetSubMatrix(snes->jacobian,IS_inact,IS_inact,MAT_INITIAL_MATRIX,&jac_inact_inact);CHKERRQ(ierr); 1174a6b72b01SJungho Lee 1175b3a44c85SBarry Smith ierr = MatFindNonzeroRows(jac_inact_inact,&keptrows);CHKERRQ(ierr); 11769ce20c35SJungho Lee if (0 && keptrows) { 117762298a1eSBarry Smith PetscInt cnt,*nrows,k; 117862298a1eSBarry Smith const PetscInt *krows,*inact; 117927d4218bSShri Abhyankar PetscInt rstart=jac_inact_inact->rmap->rstart; 118062298a1eSBarry Smith 11816bf464f9SBarry Smith ierr = MatDestroy(&jac_inact_inact);CHKERRQ(ierr); 11826bf464f9SBarry Smith ierr = ISDestroy(&IS_act);CHKERRQ(ierr); 118362298a1eSBarry Smith 118462298a1eSBarry Smith ierr = ISGetLocalSize(keptrows,&cnt);CHKERRQ(ierr); 118562298a1eSBarry Smith ierr = ISGetIndices(keptrows,&krows);CHKERRQ(ierr); 118662298a1eSBarry Smith ierr = ISGetIndices(IS_inact,&inact);CHKERRQ(ierr); 118762298a1eSBarry Smith ierr = PetscMalloc(cnt*sizeof(PetscInt),&nrows);CHKERRQ(ierr); 118862298a1eSBarry Smith for (k=0; k<cnt; k++) { 118927d4218bSShri Abhyankar nrows[k] = inact[krows[k]-rstart]; 119062298a1eSBarry Smith } 119162298a1eSBarry Smith ierr = ISRestoreIndices(keptrows,&krows);CHKERRQ(ierr); 119262298a1eSBarry Smith ierr = ISRestoreIndices(IS_inact,&inact);CHKERRQ(ierr); 11936bf464f9SBarry Smith ierr = ISDestroy(&keptrows);CHKERRQ(ierr); 11946bf464f9SBarry Smith ierr = ISDestroy(&IS_inact);CHKERRQ(ierr); 119562298a1eSBarry Smith 119627d4218bSShri Abhyankar ierr = ISCreateGeneral(PETSC_COMM_WORLD,cnt,nrows,PETSC_OWN_POINTER,&IS_inact);CHKERRQ(ierr); 119727d4218bSShri Abhyankar ierr = ISComplement(IS_inact,F->map->rstart,F->map->rend,&IS_act);CHKERRQ(ierr); 119862298a1eSBarry Smith ierr = MatGetSubMatrix(snes->jacobian,IS_inact,IS_inact,MAT_INITIAL_MATRIX,&jac_inact_inact);CHKERRQ(ierr); 119962298a1eSBarry Smith } 12009ce20c35SJungho Lee ierr = DMSetVI(snes->dm,IS_inact);CHKERRQ(ierr); 12019ce20c35SJungho Lee /* remove later */ 12029ce20c35SJungho Lee 12039ce20c35SJungho Lee /* 12049ce20c35SJungho Lee ierr = VecView(vi->xu,PETSC_VIEWER_BINARY_(PETSC_COMM_WORLD));CHKERRQ(ierr); 12059ce20c35SJungho Lee ierr = VecView(vi->xl,PETSC_VIEWER_BINARY_(PETSC_COMM_WORLD));CHKERRQ(ierr); 12069ce20c35SJungho Lee ierr = VecView(X,PETSC_VIEWER_BINARY_(PETSC_COMM_WORLD));CHKERRQ(ierr); 12079ce20c35SJungho Lee ierr = VecView(F,PETSC_VIEWER_BINARY_(PETSC_COMM_WORLD));CHKERRQ(ierr); 12089ce20c35SJungho Lee ierr = ISView(IS_inact,PETSC_VIEWER_BINARY_(PETSC_COMM_WORLD));CHKERRQ(ierr); 12099ce20c35SJungho Lee */ 121062298a1eSBarry Smith 1211d950fb63SShri Abhyankar /* Get sizes of active and inactive sets */ 1212d950fb63SShri Abhyankar ierr = ISGetLocalSize(IS_act,&nis_act);CHKERRQ(ierr); 1213d950fb63SShri Abhyankar ierr = ISGetLocalSize(IS_inact,&nis_inact);CHKERRQ(ierr); 1214d950fb63SShri Abhyankar 1215d950fb63SShri Abhyankar /* Create active and inactive set vectors */ 1216fe835674SShri Abhyankar ierr = SNESVICreateSubVectors(snes,nis_inact,&F_inact);CHKERRQ(ierr); 1217fe835674SShri Abhyankar ierr = SNESVICreateSubVectors(snes,nis_act,&Y_act);CHKERRQ(ierr); 1218fe835674SShri Abhyankar ierr = SNESVICreateSubVectors(snes,nis_inact,&Y_inact);CHKERRQ(ierr); 1219d950fb63SShri Abhyankar 1220d950fb63SShri Abhyankar /* Create scatter contexts */ 1221d950fb63SShri Abhyankar ierr = VecScatterCreate(Y,IS_act,Y_act,PETSC_NULL,&scat_act);CHKERRQ(ierr); 1222d950fb63SShri Abhyankar ierr = VecScatterCreate(Y,IS_inact,Y_inact,PETSC_NULL,&scat_inact);CHKERRQ(ierr); 1223d950fb63SShri Abhyankar 1224d950fb63SShri Abhyankar /* Do a vec scatter to active and inactive set vectors */ 1225fe835674SShri Abhyankar ierr = VecScatterBegin(scat_inact,F,F_inact,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1226fe835674SShri Abhyankar ierr = VecScatterEnd(scat_inact,F,F_inact,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1227d950fb63SShri Abhyankar 1228d950fb63SShri Abhyankar ierr = VecScatterBegin(scat_act,Y,Y_act,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1229d950fb63SShri Abhyankar ierr = VecScatterEnd(scat_act,Y,Y_act,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1230d950fb63SShri Abhyankar 1231d950fb63SShri Abhyankar ierr = VecScatterBegin(scat_inact,Y,Y_inact,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1232d950fb63SShri Abhyankar ierr = VecScatterEnd(scat_inact,Y,Y_inact,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1233d950fb63SShri Abhyankar 1234d950fb63SShri Abhyankar /* Active set direction = 0 */ 1235d950fb63SShri Abhyankar ierr = VecSet(Y_act,0);CHKERRQ(ierr); 1236d950fb63SShri Abhyankar if (snes->jacobian != snes->jacobian_pre) { 1237d950fb63SShri Abhyankar ierr = MatGetSubMatrix(snes->jacobian_pre,IS_inact,IS_inact,MAT_INITIAL_MATRIX,&prejac_inact_inact);CHKERRQ(ierr); 1238d950fb63SShri Abhyankar } else prejac_inact_inact = jac_inact_inact; 1239d950fb63SShri Abhyankar 1240abcba341SShri Abhyankar ierr = ISEqual(vi->IS_inact_prev,IS_inact,&isequal);CHKERRQ(ierr); 1241abcba341SShri Abhyankar if (!isequal) { 1242732bb160SShri Abhyankar ierr = SNESVIResetPCandKSP(snes,jac_inact_inact,prejac_inact_inact);CHKERRQ(ierr); 1243c58c0d17SBarry Smith flg = DIFFERENT_NONZERO_PATTERN; 1244d950fb63SShri Abhyankar } 1245d950fb63SShri Abhyankar 124613e0d083SBarry Smith /* ierr = ISView(IS_inact,0);CHKERRQ(ierr); */ 124713e0d083SBarry Smith /* ierr = ISView(IS_act,0);CHKERRQ(ierr);*/ 124813e0d083SBarry Smith /* ierr = MatView(snes->jacobian_pre,0); */ 124913e0d083SBarry Smith 1250f15307b4SJungho Lee 12519ce20c35SJungho Lee 1252d950fb63SShri Abhyankar ierr = KSPSetOperators(snes->ksp,jac_inact_inact,prejac_inact_inact,flg);CHKERRQ(ierr); 125313e0d083SBarry Smith ierr = KSPSetUp(snes->ksp);CHKERRQ(ierr); 125413e0d083SBarry Smith { 125513e0d083SBarry Smith PC pc; 125613e0d083SBarry Smith PetscBool flg; 125713e0d083SBarry Smith ierr = KSPGetPC(snes->ksp,&pc);CHKERRQ(ierr); 125813e0d083SBarry Smith ierr = PetscTypeCompare((PetscObject)pc,PCFIELDSPLIT,&flg);CHKERRQ(ierr); 125913e0d083SBarry Smith if (flg) { 126013e0d083SBarry Smith KSP *subksps; 126113e0d083SBarry Smith ierr = PCFieldSplitGetSubKSP(pc,PETSC_NULL,&subksps);CHKERRQ(ierr); 126213e0d083SBarry Smith ierr = KSPGetPC(subksps[0],&pc);CHKERRQ(ierr); 126313e0d083SBarry Smith ierr = PetscFree(subksps);CHKERRQ(ierr); 126413e0d083SBarry Smith ierr = PetscTypeCompare((PetscObject)pc,PCBJACOBI,&flg);CHKERRQ(ierr); 126513e0d083SBarry Smith if (flg) { 126613e0d083SBarry Smith PetscInt n,N = 101*101,j,cnts[3] = {0,0,0}; 126713e0d083SBarry Smith const PetscInt *ii; 126813e0d083SBarry Smith 126913e0d083SBarry Smith ierr = ISGetSize(IS_inact,&n);CHKERRQ(ierr); 127013e0d083SBarry Smith ierr = ISGetIndices(IS_inact,&ii);CHKERRQ(ierr); 127113e0d083SBarry Smith for (j=0; j<n; j++) { 127213e0d083SBarry Smith if (ii[j] < N) cnts[0]++; 127313e0d083SBarry Smith else if (ii[j] < 2*N) cnts[1]++; 127413e0d083SBarry Smith else if (ii[j] < 3*N) cnts[2]++; 127513e0d083SBarry Smith } 127613e0d083SBarry Smith ierr = ISRestoreIndices(IS_inact,&ii);CHKERRQ(ierr); 127713e0d083SBarry Smith 127813e0d083SBarry Smith ierr = PCBJacobiSetTotalBlocks(pc,3,cnts);CHKERRQ(ierr); 127913e0d083SBarry Smith } 128013e0d083SBarry Smith } 128113e0d083SBarry Smith } 128213e0d083SBarry Smith 1283fe835674SShri Abhyankar ierr = SNES_KSPSolve(snes,snes->ksp,F_inact,Y_inact);CHKERRQ(ierr); 1284d950fb63SShri Abhyankar ierr = KSPGetConvergedReason(snes->ksp,&kspreason);CHKERRQ(ierr); 1285d950fb63SShri Abhyankar if (kspreason < 0) { 1286d950fb63SShri Abhyankar if (++snes->numLinearSolveFailures >= snes->maxLinearSolveFailures) { 1287d950fb63SShri 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); 1288d950fb63SShri Abhyankar snes->reason = SNES_DIVERGED_LINEAR_SOLVE; 1289d950fb63SShri Abhyankar break; 1290d950fb63SShri Abhyankar } 1291d950fb63SShri Abhyankar } 1292d950fb63SShri Abhyankar 1293d950fb63SShri Abhyankar ierr = VecScatterBegin(scat_act,Y_act,Y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1294d950fb63SShri Abhyankar ierr = VecScatterEnd(scat_act,Y_act,Y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1295d950fb63SShri Abhyankar ierr = VecScatterBegin(scat_inact,Y_inact,Y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1296d950fb63SShri Abhyankar ierr = VecScatterEnd(scat_inact,Y_inact,Y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1297d950fb63SShri Abhyankar 12986bf464f9SBarry Smith ierr = VecDestroy(&F_inact);CHKERRQ(ierr); 12996bf464f9SBarry Smith ierr = VecDestroy(&Y_act);CHKERRQ(ierr); 13006bf464f9SBarry Smith ierr = VecDestroy(&Y_inact);CHKERRQ(ierr); 13016bf464f9SBarry Smith ierr = VecScatterDestroy(&scat_act);CHKERRQ(ierr); 13026bf464f9SBarry Smith ierr = VecScatterDestroy(&scat_inact);CHKERRQ(ierr); 13036bf464f9SBarry Smith ierr = ISDestroy(&IS_act);CHKERRQ(ierr); 1304abcba341SShri Abhyankar if (!isequal) { 13056bf464f9SBarry Smith ierr = ISDestroy(&vi->IS_inact_prev);CHKERRQ(ierr); 1306abcba341SShri Abhyankar ierr = ISDuplicate(IS_inact,&vi->IS_inact_prev);CHKERRQ(ierr); 1307abcba341SShri Abhyankar } 13086bf464f9SBarry Smith ierr = ISDestroy(&IS_inact);CHKERRQ(ierr); 13096bf464f9SBarry Smith ierr = MatDestroy(&jac_inact_inact);CHKERRQ(ierr); 1310d950fb63SShri Abhyankar if (snes->jacobian != snes->jacobian_pre) { 13116bf464f9SBarry Smith ierr = MatDestroy(&prejac_inact_inact);CHKERRQ(ierr); 1312d950fb63SShri Abhyankar } 1313d950fb63SShri Abhyankar ierr = KSPGetIterationNumber(snes->ksp,&lits);CHKERRQ(ierr); 1314d950fb63SShri Abhyankar snes->linear_its += lits; 1315d950fb63SShri Abhyankar ierr = PetscInfo2(snes,"iter=%D, linear solve iterations=%D\n",snes->iter,lits);CHKERRQ(ierr); 1316d950fb63SShri Abhyankar /* 13170661309fSPeter Brune if (snes->ops->precheckstep) { 1318d950fb63SShri Abhyankar PetscBool changed_y = PETSC_FALSE; 13190661309fSPeter Brune ierr = (*snes->ops->precheckstep)(snes,X,Y,snes->precheck,&changed_y);CHKERRQ(ierr); 1320d950fb63SShri Abhyankar } 1321d950fb63SShri Abhyankar 1322d950fb63SShri Abhyankar if (PetscLogPrintInfo){ 1323d950fb63SShri Abhyankar ierr = SNESVICheckResidual_Private(snes,snes->jacobian,F,Y,G,W);CHKERRQ(ierr); 1324d950fb63SShri Abhyankar } 1325d950fb63SShri Abhyankar */ 1326d950fb63SShri Abhyankar /* Compute a (scaled) negative update in the line search routine: 1327d950fb63SShri Abhyankar Y <- X - lambda*Y 1328d950fb63SShri Abhyankar and evaluate G = function(Y) (depends on the line search). 1329d950fb63SShri Abhyankar */ 1330d950fb63SShri Abhyankar ierr = VecCopy(Y,snes->vec_sol_update);CHKERRQ(ierr); 1331fe835674SShri Abhyankar ynorm = 1; gnorm = fnorm; 13320661309fSPeter Brune ierr = (*snes->ops->linesearch)(snes,snes->lsP,X,F,Y,fnorm,xnorm,G,W,&ynorm,&gnorm,&lssucceed);CHKERRQ(ierr); 1333*4839bfe8SBarry Smith ierr = PetscInfo4(snes,"fnorm=%18.16e, gnorm=%18.16e, ynorm=%18.16e, lssucceed=%d\n",(double)fnorm,(double)gnorm,(double)ynorm,(int)lssucceed);CHKERRQ(ierr); 13342b4ed282SShri Abhyankar if (snes->reason == SNES_DIVERGED_FUNCTION_COUNT) break; 13352b4ed282SShri Abhyankar if (snes->domainerror) { 13362b4ed282SShri Abhyankar snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN; 13374c661befSBarry Smith ierr = DMDestroyVI(snes->dm);CHKERRQ(ierr); 13382b4ed282SShri Abhyankar PetscFunctionReturn(0); 13392b4ed282SShri Abhyankar } 13402b4ed282SShri Abhyankar if (!lssucceed) { 13412b4ed282SShri Abhyankar if (++snes->numFailures >= snes->maxFailures) { 13422b4ed282SShri Abhyankar PetscBool ismin; 13432b4ed282SShri Abhyankar snes->reason = SNES_DIVERGED_LINE_SEARCH; 13442b4ed282SShri Abhyankar ierr = SNESVICheckLocalMin_Private(snes,snes->jacobian,G,W,gnorm,&ismin);CHKERRQ(ierr); 13452b4ed282SShri Abhyankar if (ismin) snes->reason = SNES_DIVERGED_LOCAL_MIN; 13462b4ed282SShri Abhyankar break; 13472b4ed282SShri Abhyankar } 13482b4ed282SShri Abhyankar } 13492b4ed282SShri Abhyankar /* Update function and solution vectors */ 1350fe835674SShri Abhyankar fnorm = gnorm; 1351fe835674SShri Abhyankar ierr = VecCopy(G,F);CHKERRQ(ierr); 13522b4ed282SShri Abhyankar ierr = VecCopy(W,X);CHKERRQ(ierr); 13532b4ed282SShri Abhyankar /* Monitor convergence */ 13542b4ed282SShri Abhyankar ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 13552b4ed282SShri Abhyankar snes->iter = i+1; 1356fe835674SShri Abhyankar snes->norm = fnorm; 13572b4ed282SShri Abhyankar ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 13582b4ed282SShri Abhyankar SNESLogConvHistory(snes,snes->norm,lits); 13597a03ce2fSLisandro Dalcin ierr = SNESMonitor(snes,snes->iter,snes->norm);CHKERRQ(ierr); 13602b4ed282SShri Abhyankar /* Test for convergence, xnorm = || X || */ 13612b4ed282SShri Abhyankar if (snes->ops->converged != SNESSkipConverged) { ierr = VecNorm(X,NORM_2,&xnorm);CHKERRQ(ierr); } 1362fe835674SShri Abhyankar ierr = (*snes->ops->converged)(snes,snes->iter,xnorm,ynorm,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); 13632b4ed282SShri Abhyankar if (snes->reason) break; 13642b4ed282SShri Abhyankar } 13654c661befSBarry Smith ierr = DMDestroyVI(snes->dm);CHKERRQ(ierr); 13662b4ed282SShri Abhyankar if (i == maxits) { 13672b4ed282SShri Abhyankar ierr = PetscInfo1(snes,"Maximum number of iterations has been reached: %D\n",maxits);CHKERRQ(ierr); 13682b4ed282SShri Abhyankar if(!snes->reason) snes->reason = SNES_DIVERGED_MAX_IT; 13692b4ed282SShri Abhyankar } 13702b4ed282SShri Abhyankar PetscFunctionReturn(0); 13712b4ed282SShri Abhyankar } 13722b4ed282SShri Abhyankar 13732f63a38cSShri Abhyankar #undef __FUNCT__ 1374720c9a41SShri Abhyankar #define __FUNCT__ "SNESVISetRedundancyCheck" 1375cb5fe31bSShri Abhyankar PetscErrorCode SNESVISetRedundancyCheck(SNES snes,PetscErrorCode (*func)(SNES,IS,IS*,void*),void *ctx) 13762f63a38cSShri Abhyankar { 13772f63a38cSShri Abhyankar SNES_VI *vi = (SNES_VI*)snes->data; 13782f63a38cSShri Abhyankar 13792f63a38cSShri Abhyankar PetscFunctionBegin; 13802f63a38cSShri Abhyankar PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 13812f63a38cSShri Abhyankar vi->checkredundancy = func; 1382cb5fe31bSShri Abhyankar vi->ctxP = ctx; 13832f63a38cSShri Abhyankar PetscFunctionReturn(0); 13842f63a38cSShri Abhyankar } 13852f63a38cSShri Abhyankar 1386ff596062SShri Abhyankar #if defined(PETSC_HAVE_MATLAB_ENGINE) 1387ff596062SShri Abhyankar #include <engine.h> 1388ff596062SShri Abhyankar #include <mex.h> 1389cb5fe31bSShri Abhyankar typedef struct {char *funcname; mxArray *ctx;} SNESMatlabContext; 1390ff596062SShri Abhyankar 1391ff596062SShri Abhyankar #undef __FUNCT__ 1392ff596062SShri Abhyankar #define __FUNCT__ "SNESVIRedundancyCheck_Matlab" 1393ff596062SShri Abhyankar PetscErrorCode SNESVIRedundancyCheck_Matlab(SNES snes,IS is_act,IS* is_redact,void* ctx) 1394ff596062SShri Abhyankar { 1395ff596062SShri Abhyankar PetscErrorCode ierr; 1396cb5fe31bSShri Abhyankar SNESMatlabContext *sctx = (SNESMatlabContext*)ctx; 1397cb5fe31bSShri Abhyankar int nlhs = 1, nrhs = 5; 1398cb5fe31bSShri Abhyankar mxArray *plhs[1], *prhs[5]; 1399cb5fe31bSShri Abhyankar long long int l1 = 0, l2 = 0, ls = 0; 1400fcb1c9afSShri Abhyankar PetscInt *indices=PETSC_NULL; 1401ff596062SShri Abhyankar 1402ff596062SShri Abhyankar PetscFunctionBegin; 1403ff596062SShri Abhyankar PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 1404ff596062SShri Abhyankar PetscValidHeaderSpecific(is_act,IS_CLASSID,2); 1405ff596062SShri Abhyankar PetscValidPointer(is_redact,3); 1406ff596062SShri Abhyankar PetscCheckSameComm(snes,1,is_act,2); 1407ff596062SShri Abhyankar 140809db5ad8SShri Abhyankar /* Create IS for reduced active set of size 0, its size and indices will 140909db5ad8SShri Abhyankar bet set by the Matlab function */ 1410fcb1c9afSShri Abhyankar ierr = ISCreateGeneral(((PetscObject)snes)->comm,0,indices,PETSC_OWN_POINTER,is_redact);CHKERRQ(ierr); 1411cb5fe31bSShri Abhyankar /* call Matlab function in ctx */ 1412ff596062SShri Abhyankar ierr = PetscMemcpy(&ls,&snes,sizeof(snes));CHKERRQ(ierr); 1413ff596062SShri Abhyankar ierr = PetscMemcpy(&l1,&is_act,sizeof(is_act));CHKERRQ(ierr); 1414cb5fe31bSShri Abhyankar ierr = PetscMemcpy(&l2,is_redact,sizeof(is_act));CHKERRQ(ierr); 1415ff596062SShri Abhyankar prhs[0] = mxCreateDoubleScalar((double)ls); 1416ff596062SShri Abhyankar prhs[1] = mxCreateDoubleScalar((double)l1); 1417cb5fe31bSShri Abhyankar prhs[2] = mxCreateDoubleScalar((double)l2); 1418cb5fe31bSShri Abhyankar prhs[3] = mxCreateString(sctx->funcname); 1419cb5fe31bSShri Abhyankar prhs[4] = sctx->ctx; 1420ff596062SShri Abhyankar ierr = mexCallMATLAB(nlhs,plhs,nrhs,prhs,"PetscSNESVIRedundancyCheckInternal");CHKERRQ(ierr); 1421ff596062SShri Abhyankar ierr = mxGetScalar(plhs[0]);CHKERRQ(ierr); 1422ff596062SShri Abhyankar mxDestroyArray(prhs[0]); 1423ff596062SShri Abhyankar mxDestroyArray(prhs[1]); 1424ff596062SShri Abhyankar mxDestroyArray(prhs[2]); 1425ff596062SShri Abhyankar mxDestroyArray(prhs[3]); 1426ff596062SShri Abhyankar mxDestroyArray(plhs[0]); 1427ff596062SShri Abhyankar PetscFunctionReturn(0); 1428ff596062SShri Abhyankar } 1429ff596062SShri Abhyankar 1430ff596062SShri Abhyankar #undef __FUNCT__ 1431ff596062SShri Abhyankar #define __FUNCT__ "SNESVISetRedundancyCheckMatlab" 1432ff596062SShri Abhyankar PetscErrorCode SNESVISetRedundancyCheckMatlab(SNES snes,const char* func,mxArray* ctx) 1433ff596062SShri Abhyankar { 1434ff596062SShri Abhyankar PetscErrorCode ierr; 1435cb5fe31bSShri Abhyankar SNESMatlabContext *sctx; 1436ff596062SShri Abhyankar 1437ff596062SShri Abhyankar PetscFunctionBegin; 1438ff596062SShri Abhyankar /* currently sctx is memory bleed */ 1439cb5fe31bSShri Abhyankar ierr = PetscMalloc(sizeof(SNESMatlabContext),&sctx);CHKERRQ(ierr); 1440ff596062SShri Abhyankar ierr = PetscStrallocpy(func,&sctx->funcname);CHKERRQ(ierr); 1441ff596062SShri Abhyankar sctx->ctx = mxDuplicateArray(ctx); 1442cb5fe31bSShri Abhyankar ierr = SNESVISetRedundancyCheck(snes,SNESVIRedundancyCheck_Matlab,sctx);CHKERRQ(ierr); 1443ff596062SShri Abhyankar PetscFunctionReturn(0); 1444ff596062SShri Abhyankar } 1445ff596062SShri Abhyankar 1446ff596062SShri Abhyankar #endif 1447ff596062SShri Abhyankar 1448ff596062SShri Abhyankar 14492f63a38cSShri Abhyankar /* Variational Inequality solver using augmented space method. It does the opposite of the 14502f63a38cSShri Abhyankar reduced space method i.e. it identifies the active set variables and instead of discarding 1451720c9a41SShri Abhyankar them it augments the original system by introducing additional equality 145256a221efSShri Abhyankar constraint equations for active set variables. The user can optionally provide an IS for 145356a221efSShri Abhyankar a subset of 'redundant' active set variables which will treated as free variables. 14542f63a38cSShri Abhyankar Specific implementation for Allen-Cahn problem 14552f63a38cSShri Abhyankar */ 14562f63a38cSShri Abhyankar #undef __FUNCT__ 1457b350b9c9SBarry Smith #define __FUNCT__ "SNESSolveVI_RSAUG" 1458b350b9c9SBarry Smith PetscErrorCode SNESSolveVI_RSAUG(SNES snes) 14592f63a38cSShri Abhyankar { 14602f63a38cSShri Abhyankar SNES_VI *vi = (SNES_VI*)snes->data; 14612f63a38cSShri Abhyankar PetscErrorCode ierr; 14622f63a38cSShri Abhyankar PetscInt maxits,i,lits; 14632f63a38cSShri Abhyankar PetscBool lssucceed; 14642f63a38cSShri Abhyankar MatStructure flg = DIFFERENT_NONZERO_PATTERN; 14652f63a38cSShri Abhyankar PetscReal fnorm,gnorm,xnorm=0,ynorm; 14662f63a38cSShri Abhyankar Vec Y,X,F,G,W; 14672f63a38cSShri Abhyankar KSPConvergedReason kspreason; 14682f63a38cSShri Abhyankar 14692f63a38cSShri Abhyankar PetscFunctionBegin; 14702f63a38cSShri Abhyankar snes->numFailures = 0; 14712f63a38cSShri Abhyankar snes->numLinearSolveFailures = 0; 14722f63a38cSShri Abhyankar snes->reason = SNES_CONVERGED_ITERATING; 14732f63a38cSShri Abhyankar 14742f63a38cSShri Abhyankar maxits = snes->max_its; /* maximum number of iterations */ 14752f63a38cSShri Abhyankar X = snes->vec_sol; /* solution vector */ 14762f63a38cSShri Abhyankar F = snes->vec_func; /* residual vector */ 14772f63a38cSShri Abhyankar Y = snes->work[0]; /* work vectors */ 14782f63a38cSShri Abhyankar G = snes->work[1]; 14792f63a38cSShri Abhyankar W = snes->work[2]; 14802f63a38cSShri Abhyankar 14812f63a38cSShri Abhyankar ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 14822f63a38cSShri Abhyankar snes->iter = 0; 14832f63a38cSShri Abhyankar snes->norm = 0.0; 14842f63a38cSShri Abhyankar ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 14852f63a38cSShri Abhyankar 14862f63a38cSShri Abhyankar ierr = SNESVIProjectOntoBounds(snes,X);CHKERRQ(ierr); 14872f63a38cSShri Abhyankar ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr); 14882f63a38cSShri Abhyankar if (snes->domainerror) { 14892f63a38cSShri Abhyankar snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN; 14902f63a38cSShri Abhyankar PetscFunctionReturn(0); 14912f63a38cSShri Abhyankar } 14922f63a38cSShri Abhyankar ierr = SNESVIComputeInactiveSetFnorm(snes,F,X,&fnorm);CHKERRQ(ierr); 14932f63a38cSShri Abhyankar ierr = VecNormBegin(X,NORM_2,&xnorm);CHKERRQ(ierr); /* xnorm <- ||x|| */ 14942f63a38cSShri Abhyankar ierr = VecNormEnd(X,NORM_2,&xnorm);CHKERRQ(ierr); 149562cbcd01SMatthew G Knepley if (PetscIsInfOrNanReal(fnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number"); 14962f63a38cSShri Abhyankar 14972f63a38cSShri Abhyankar ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 14982f63a38cSShri Abhyankar snes->norm = fnorm; 14992f63a38cSShri Abhyankar ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 15002f63a38cSShri Abhyankar SNESLogConvHistory(snes,fnorm,0); 15017a03ce2fSLisandro Dalcin ierr = SNESMonitor(snes,0,fnorm);CHKERRQ(ierr); 15022f63a38cSShri Abhyankar 15032f63a38cSShri Abhyankar /* set parameter for default relative tolerance convergence test */ 15042f63a38cSShri Abhyankar snes->ttol = fnorm*snes->rtol; 15052f63a38cSShri Abhyankar /* test convergence */ 15062f63a38cSShri Abhyankar ierr = (*snes->ops->converged)(snes,0,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); 15072f63a38cSShri Abhyankar if (snes->reason) PetscFunctionReturn(0); 15082f63a38cSShri Abhyankar 15092f63a38cSShri Abhyankar for (i=0; i<maxits; i++) { 15102f63a38cSShri Abhyankar IS IS_act,IS_inact; /* _act -> active set _inact -> inactive set */ 1511cb5fe31bSShri Abhyankar IS IS_redact; /* redundant active set */ 151256a221efSShri Abhyankar Mat J_aug,Jpre_aug; 151356a221efSShri Abhyankar Vec F_aug,Y_aug; 151456a221efSShri Abhyankar PetscInt nis_redact,nis_act; 151556a221efSShri Abhyankar const PetscInt *idx_redact,*idx_act; 151656a221efSShri Abhyankar PetscInt k; 151763ee972cSSatish Balay PetscInt *idx_actkept=PETSC_NULL,nkept=0; /* list of kept active set */ 151856a221efSShri Abhyankar PetscScalar *f,*f2; 15192f63a38cSShri Abhyankar PetscBool isequal; 152056a221efSShri Abhyankar PetscInt i1=0,j1=0; 15212f63a38cSShri Abhyankar 15222f63a38cSShri Abhyankar /* Call general purpose update function */ 15232f63a38cSShri Abhyankar if (snes->ops->update) { 15242f63a38cSShri Abhyankar ierr = (*snes->ops->update)(snes, snes->iter);CHKERRQ(ierr); 15252f63a38cSShri Abhyankar } 15262f63a38cSShri Abhyankar ierr = SNESComputeJacobian(snes,X,&snes->jacobian,&snes->jacobian_pre,&flg);CHKERRQ(ierr); 15272f63a38cSShri Abhyankar 15282f63a38cSShri Abhyankar /* Create active and inactive index sets */ 15292f63a38cSShri Abhyankar ierr = SNESVICreateIndexSets_RS(snes,X,F,&IS_act,&IS_inact);CHKERRQ(ierr); 15302f63a38cSShri Abhyankar 153156a221efSShri Abhyankar /* Get local active set size */ 15322f63a38cSShri Abhyankar ierr = ISGetLocalSize(IS_act,&nis_act);CHKERRQ(ierr); 153356a221efSShri Abhyankar if (nis_act) { 1534e63076c7SBarry Smith ierr = ISGetIndices(IS_act,&idx_act);CHKERRQ(ierr); 1535e63076c7SBarry Smith IS_redact = PETSC_NULL; 153656a221efSShri Abhyankar if(vi->checkredundancy) { 1537cb5fe31bSShri Abhyankar (*vi->checkredundancy)(snes,IS_act,&IS_redact,vi->ctxP); 153856a221efSShri Abhyankar } 15392f63a38cSShri Abhyankar 154056a221efSShri Abhyankar if(!IS_redact) { 154156a221efSShri Abhyankar /* User called checkredundancy function but didn't create IS_redact because 154256a221efSShri Abhyankar there were no redundant active set variables */ 154356a221efSShri Abhyankar /* Copy over all active set indices to the list */ 154456a221efSShri Abhyankar ierr = PetscMalloc(nis_act*sizeof(PetscInt),&idx_actkept);CHKERRQ(ierr); 154556a221efSShri Abhyankar for(k=0;k < nis_act;k++) idx_actkept[k] = idx_act[k]; 154656a221efSShri Abhyankar nkept = nis_act; 154756a221efSShri Abhyankar } else { 154856a221efSShri Abhyankar ierr = ISGetLocalSize(IS_redact,&nis_redact);CHKERRQ(ierr); 154956a221efSShri Abhyankar ierr = PetscMalloc((nis_act-nis_redact)*sizeof(PetscInt),&idx_actkept);CHKERRQ(ierr); 15502f63a38cSShri Abhyankar 155156a221efSShri Abhyankar /* Create reduced active set list */ 155256a221efSShri Abhyankar ierr = ISGetIndices(IS_act,&idx_act);CHKERRQ(ierr); 155356a221efSShri Abhyankar ierr = ISGetIndices(IS_redact,&idx_redact);CHKERRQ(ierr); 1554cb5fe31bSShri Abhyankar j1 = 0;nkept = 0; 155556a221efSShri Abhyankar for(k=0;k<nis_act;k++) { 155656a221efSShri Abhyankar if(j1 < nis_redact && idx_act[k] == idx_redact[j1]) j1++; 155756a221efSShri Abhyankar else idx_actkept[nkept++] = idx_act[k]; 155856a221efSShri Abhyankar } 155956a221efSShri Abhyankar ierr = ISRestoreIndices(IS_act,&idx_act);CHKERRQ(ierr); 156056a221efSShri Abhyankar ierr = ISRestoreIndices(IS_redact,&idx_redact);CHKERRQ(ierr); 1561cb5fe31bSShri Abhyankar 1562cb5fe31bSShri Abhyankar ierr = ISDestroy(&IS_redact);CHKERRQ(ierr); 156356a221efSShri Abhyankar } 15642f63a38cSShri Abhyankar 156556a221efSShri Abhyankar /* Create augmented F and Y */ 156656a221efSShri Abhyankar ierr = VecCreate(((PetscObject)snes)->comm,&F_aug);CHKERRQ(ierr); 156756a221efSShri Abhyankar ierr = VecSetSizes(F_aug,F->map->n+nkept,PETSC_DECIDE);CHKERRQ(ierr); 156856a221efSShri Abhyankar ierr = VecSetFromOptions(F_aug);CHKERRQ(ierr); 156956a221efSShri Abhyankar ierr = VecDuplicate(F_aug,&Y_aug);CHKERRQ(ierr); 15702f63a38cSShri Abhyankar 157156a221efSShri Abhyankar /* Copy over F to F_aug in the first n locations */ 157256a221efSShri Abhyankar ierr = VecGetArray(F,&f);CHKERRQ(ierr); 157356a221efSShri Abhyankar ierr = VecGetArray(F_aug,&f2);CHKERRQ(ierr); 157456a221efSShri Abhyankar ierr = PetscMemcpy(f2,f,F->map->n*sizeof(PetscScalar));CHKERRQ(ierr); 157556a221efSShri Abhyankar ierr = VecRestoreArray(F,&f);CHKERRQ(ierr); 157656a221efSShri Abhyankar ierr = VecRestoreArray(F_aug,&f2);CHKERRQ(ierr); 15772f63a38cSShri Abhyankar 157856a221efSShri Abhyankar /* Create the augmented jacobian matrix */ 157956a221efSShri Abhyankar ierr = MatCreate(((PetscObject)snes)->comm,&J_aug);CHKERRQ(ierr); 158056a221efSShri Abhyankar ierr = MatSetSizes(J_aug,X->map->n+nkept,X->map->n+nkept,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr); 158156a221efSShri Abhyankar ierr = MatSetFromOptions(J_aug);CHKERRQ(ierr); 15822f63a38cSShri Abhyankar 158356a221efSShri Abhyankar 15849521db3cSSatish Balay { /* local vars */ 1585493a4f3dSShri Abhyankar /* Preallocate augmented matrix and set values in it...Doing only sequential case first*/ 158656a221efSShri Abhyankar PetscInt ncols; 158756a221efSShri Abhyankar const PetscInt *cols; 158856a221efSShri Abhyankar const PetscScalar *vals; 15892969f145SShri Abhyankar PetscScalar value[2]; 15902969f145SShri Abhyankar PetscInt row,col[2]; 1591493a4f3dSShri Abhyankar PetscInt *d_nnz; 15922969f145SShri Abhyankar value[0] = 1.0; value[1] = 0.0; 1593493a4f3dSShri Abhyankar ierr = PetscMalloc((X->map->n+nkept)*sizeof(PetscInt),&d_nnz);CHKERRQ(ierr); 1594493a4f3dSShri Abhyankar ierr = PetscMemzero(d_nnz,(X->map->n+nkept)*sizeof(PetscInt));CHKERRQ(ierr); 1595493a4f3dSShri Abhyankar for(row=0;row<snes->jacobian->rmap->n;row++) { 1596493a4f3dSShri Abhyankar ierr = MatGetRow(snes->jacobian,row,&ncols,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr); 1597493a4f3dSShri Abhyankar d_nnz[row] += ncols; 1598493a4f3dSShri Abhyankar ierr = MatRestoreRow(snes->jacobian,row,&ncols,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr); 1599493a4f3dSShri Abhyankar } 1600493a4f3dSShri Abhyankar 1601493a4f3dSShri Abhyankar for(k=0;k<nkept;k++) { 1602493a4f3dSShri Abhyankar d_nnz[idx_actkept[k]] += 1; 16032969f145SShri Abhyankar d_nnz[snes->jacobian->rmap->n+k] += 2; 1604493a4f3dSShri Abhyankar } 1605493a4f3dSShri Abhyankar ierr = MatSeqAIJSetPreallocation(J_aug,PETSC_NULL,d_nnz);CHKERRQ(ierr); 1606493a4f3dSShri Abhyankar 1607493a4f3dSShri Abhyankar ierr = PetscFree(d_nnz);CHKERRQ(ierr); 160856a221efSShri Abhyankar 160956a221efSShri Abhyankar /* Set the original jacobian matrix in J_aug */ 161056a221efSShri Abhyankar for(row=0;row<snes->jacobian->rmap->n;row++) { 161156a221efSShri Abhyankar ierr = MatGetRow(snes->jacobian,row,&ncols,&cols,&vals);CHKERRQ(ierr); 161256a221efSShri Abhyankar ierr = MatSetValues(J_aug,1,&row,ncols,cols,vals,INSERT_VALUES);CHKERRQ(ierr); 161356a221efSShri Abhyankar ierr = MatRestoreRow(snes->jacobian,row,&ncols,&cols,&vals);CHKERRQ(ierr); 161456a221efSShri Abhyankar } 161556a221efSShri Abhyankar /* Add the augmented part */ 161656a221efSShri Abhyankar for(k=0;k<nkept;k++) { 16172969f145SShri Abhyankar row = snes->jacobian->rmap->n+k; 16182969f145SShri Abhyankar col[0] = idx_actkept[k]; col[1] = snes->jacobian->rmap->n+k; 16192969f145SShri Abhyankar ierr = MatSetValues(J_aug,1,&row,1,col,value,INSERT_VALUES);CHKERRQ(ierr); 16202969f145SShri Abhyankar ierr = MatSetValues(J_aug,1,&col[0],1,&row,&value[0],INSERT_VALUES);CHKERRQ(ierr); 162156a221efSShri Abhyankar } 162256a221efSShri Abhyankar ierr = MatAssemblyBegin(J_aug,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 162356a221efSShri Abhyankar ierr = MatAssemblyEnd(J_aug,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 162456a221efSShri Abhyankar /* Only considering prejac = jac for now */ 162556a221efSShri Abhyankar Jpre_aug = J_aug; 16269521db3cSSatish Balay } /* local vars*/ 1627e63076c7SBarry Smith ierr = ISRestoreIndices(IS_act,&idx_act);CHKERRQ(ierr); 1628e63076c7SBarry Smith ierr = ISDestroy(&IS_act);CHKERRQ(ierr); 162956a221efSShri Abhyankar } else { 163056a221efSShri Abhyankar F_aug = F; J_aug = snes->jacobian; Y_aug = Y; Jpre_aug = snes->jacobian_pre; 163156a221efSShri Abhyankar } 16322f63a38cSShri Abhyankar 16332f63a38cSShri Abhyankar ierr = ISEqual(vi->IS_inact_prev,IS_inact,&isequal);CHKERRQ(ierr); 16342f63a38cSShri Abhyankar if (!isequal) { 163556a221efSShri Abhyankar ierr = SNESVIResetPCandKSP(snes,J_aug,Jpre_aug);CHKERRQ(ierr); 16362f63a38cSShri Abhyankar } 163756a221efSShri Abhyankar ierr = KSPSetOperators(snes->ksp,J_aug,Jpre_aug,flg);CHKERRQ(ierr); 16382f63a38cSShri Abhyankar ierr = KSPSetUp(snes->ksp);CHKERRQ(ierr); 163956a221efSShri Abhyankar /* { 16402f63a38cSShri Abhyankar PC pc; 16412f63a38cSShri Abhyankar PetscBool flg; 16422f63a38cSShri Abhyankar ierr = KSPGetPC(snes->ksp,&pc);CHKERRQ(ierr); 16432f63a38cSShri Abhyankar ierr = PetscTypeCompare((PetscObject)pc,PCFIELDSPLIT,&flg);CHKERRQ(ierr); 16442f63a38cSShri Abhyankar if (flg) { 16452f63a38cSShri Abhyankar KSP *subksps; 16462f63a38cSShri Abhyankar ierr = PCFieldSplitGetSubKSP(pc,PETSC_NULL,&subksps);CHKERRQ(ierr); 16472f63a38cSShri Abhyankar ierr = KSPGetPC(subksps[0],&pc);CHKERRQ(ierr); 16482f63a38cSShri Abhyankar ierr = PetscFree(subksps);CHKERRQ(ierr); 16492f63a38cSShri Abhyankar ierr = PetscTypeCompare((PetscObject)pc,PCBJACOBI,&flg);CHKERRQ(ierr); 16502f63a38cSShri Abhyankar if (flg) { 16512f63a38cSShri Abhyankar PetscInt n,N = 101*101,j,cnts[3] = {0,0,0}; 16522f63a38cSShri Abhyankar const PetscInt *ii; 16532f63a38cSShri Abhyankar 16542f63a38cSShri Abhyankar ierr = ISGetSize(IS_inact,&n);CHKERRQ(ierr); 16552f63a38cSShri Abhyankar ierr = ISGetIndices(IS_inact,&ii);CHKERRQ(ierr); 16562f63a38cSShri Abhyankar for (j=0; j<n; j++) { 16572f63a38cSShri Abhyankar if (ii[j] < N) cnts[0]++; 16582f63a38cSShri Abhyankar else if (ii[j] < 2*N) cnts[1]++; 16592f63a38cSShri Abhyankar else if (ii[j] < 3*N) cnts[2]++; 16602f63a38cSShri Abhyankar } 16612f63a38cSShri Abhyankar ierr = ISRestoreIndices(IS_inact,&ii);CHKERRQ(ierr); 16622f63a38cSShri Abhyankar 16632f63a38cSShri Abhyankar ierr = PCBJacobiSetTotalBlocks(pc,3,cnts);CHKERRQ(ierr); 16642f63a38cSShri Abhyankar } 16652f63a38cSShri Abhyankar } 16662f63a38cSShri Abhyankar } 166756a221efSShri Abhyankar */ 166856a221efSShri Abhyankar ierr = SNES_KSPSolve(snes,snes->ksp,F_aug,Y_aug);CHKERRQ(ierr); 16692f63a38cSShri Abhyankar ierr = KSPGetConvergedReason(snes->ksp,&kspreason);CHKERRQ(ierr); 16702f63a38cSShri Abhyankar if (kspreason < 0) { 16712f63a38cSShri Abhyankar if (++snes->numLinearSolveFailures >= snes->maxLinearSolveFailures) { 16722f63a38cSShri 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); 16732f63a38cSShri Abhyankar snes->reason = SNES_DIVERGED_LINEAR_SOLVE; 16742f63a38cSShri Abhyankar break; 16752f63a38cSShri Abhyankar } 16762f63a38cSShri Abhyankar } 16772f63a38cSShri Abhyankar 167856a221efSShri Abhyankar if(nis_act) { 167956a221efSShri Abhyankar PetscScalar *y1,*y2; 168056a221efSShri Abhyankar ierr = VecGetArray(Y,&y1);CHKERRQ(ierr); 168156a221efSShri Abhyankar ierr = VecGetArray(Y_aug,&y2);CHKERRQ(ierr); 168256a221efSShri Abhyankar /* Copy over inactive Y_aug to Y */ 168356a221efSShri Abhyankar j1 = 0; 168456a221efSShri Abhyankar for(i1=Y->map->rstart;i1 < Y->map->rend;i1++) { 168556a221efSShri Abhyankar if(j1 < nkept && idx_actkept[j1] == i1) j1++; 168656a221efSShri Abhyankar else y1[i1-Y->map->rstart] = y2[i1-Y->map->rstart]; 168756a221efSShri Abhyankar } 168856a221efSShri Abhyankar ierr = VecRestoreArray(Y,&y1);CHKERRQ(ierr); 168956a221efSShri Abhyankar ierr = VecRestoreArray(Y_aug,&y2);CHKERRQ(ierr); 16902f63a38cSShri Abhyankar 16916bf464f9SBarry Smith ierr = VecDestroy(&F_aug);CHKERRQ(ierr); 16926bf464f9SBarry Smith ierr = VecDestroy(&Y_aug);CHKERRQ(ierr); 16936bf464f9SBarry Smith ierr = MatDestroy(&J_aug);CHKERRQ(ierr); 169456a221efSShri Abhyankar ierr = PetscFree(idx_actkept);CHKERRQ(ierr); 169556a221efSShri Abhyankar } 169656a221efSShri Abhyankar 16972f63a38cSShri Abhyankar if (!isequal) { 16986bf464f9SBarry Smith ierr = ISDestroy(&vi->IS_inact_prev);CHKERRQ(ierr); 16992f63a38cSShri Abhyankar ierr = ISDuplicate(IS_inact,&vi->IS_inact_prev);CHKERRQ(ierr); 17002f63a38cSShri Abhyankar } 17016bf464f9SBarry Smith ierr = ISDestroy(&IS_inact);CHKERRQ(ierr); 170256a221efSShri Abhyankar 17032f63a38cSShri Abhyankar ierr = KSPGetIterationNumber(snes->ksp,&lits);CHKERRQ(ierr); 17042f63a38cSShri Abhyankar snes->linear_its += lits; 17052f63a38cSShri Abhyankar ierr = PetscInfo2(snes,"iter=%D, linear solve iterations=%D\n",snes->iter,lits);CHKERRQ(ierr); 17062f63a38cSShri Abhyankar /* 17070661309fSPeter Brune if (snes->ops->precheckstep) { 17082f63a38cSShri Abhyankar PetscBool changed_y = PETSC_FALSE; 17090661309fSPeter Brune ierr = (*snes->ops->precheckstep)(snes,X,Y,snes->precheck,&changed_y);CHKERRQ(ierr); 17102f63a38cSShri Abhyankar } 17112f63a38cSShri Abhyankar 17122f63a38cSShri Abhyankar if (PetscLogPrintInfo){ 17132f63a38cSShri Abhyankar ierr = SNESVICheckResidual_Private(snes,snes->jacobian,F,Y,G,W);CHKERRQ(ierr); 17142f63a38cSShri Abhyankar } 17152f63a38cSShri Abhyankar */ 17162f63a38cSShri Abhyankar /* Compute a (scaled) negative update in the line search routine: 17172f63a38cSShri Abhyankar Y <- X - lambda*Y 17182f63a38cSShri Abhyankar and evaluate G = function(Y) (depends on the line search). 17192f63a38cSShri Abhyankar */ 17202f63a38cSShri Abhyankar ierr = VecCopy(Y,snes->vec_sol_update);CHKERRQ(ierr); 17212f63a38cSShri Abhyankar ynorm = 1; gnorm = fnorm; 17220661309fSPeter Brune ierr = (*snes->ops->linesearch)(snes,snes->lsP,X,F,Y,fnorm,xnorm,G,W,&ynorm,&gnorm,&lssucceed);CHKERRQ(ierr); 1723*4839bfe8SBarry Smith ierr = PetscInfo4(snes,"fnorm=%18.16e, gnorm=%18.16e, ynorm=%18.16e, lssucceed=%d\n",(double)fnorm,(double)gnorm,(double)ynorm,(int)lssucceed);CHKERRQ(ierr); 17242f63a38cSShri Abhyankar if (snes->reason == SNES_DIVERGED_FUNCTION_COUNT) break; 17252f63a38cSShri Abhyankar if (snes->domainerror) { 17262f63a38cSShri Abhyankar snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN; 17272f63a38cSShri Abhyankar PetscFunctionReturn(0); 17282f63a38cSShri Abhyankar } 17292f63a38cSShri Abhyankar if (!lssucceed) { 17302f63a38cSShri Abhyankar if (++snes->numFailures >= snes->maxFailures) { 17312f63a38cSShri Abhyankar PetscBool ismin; 17322f63a38cSShri Abhyankar snes->reason = SNES_DIVERGED_LINE_SEARCH; 17332f63a38cSShri Abhyankar ierr = SNESVICheckLocalMin_Private(snes,snes->jacobian,G,W,gnorm,&ismin);CHKERRQ(ierr); 17342f63a38cSShri Abhyankar if (ismin) snes->reason = SNES_DIVERGED_LOCAL_MIN; 17352f63a38cSShri Abhyankar break; 17362f63a38cSShri Abhyankar } 17372f63a38cSShri Abhyankar } 17382f63a38cSShri Abhyankar /* Update function and solution vectors */ 17392f63a38cSShri Abhyankar fnorm = gnorm; 17402f63a38cSShri Abhyankar ierr = VecCopy(G,F);CHKERRQ(ierr); 17412f63a38cSShri Abhyankar ierr = VecCopy(W,X);CHKERRQ(ierr); 17422f63a38cSShri Abhyankar /* Monitor convergence */ 17432f63a38cSShri Abhyankar ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 17442f63a38cSShri Abhyankar snes->iter = i+1; 17452f63a38cSShri Abhyankar snes->norm = fnorm; 17462f63a38cSShri Abhyankar ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 17472f63a38cSShri Abhyankar SNESLogConvHistory(snes,snes->norm,lits); 17487a03ce2fSLisandro Dalcin ierr = SNESMonitor(snes,snes->iter,snes->norm);CHKERRQ(ierr); 17492f63a38cSShri Abhyankar /* Test for convergence, xnorm = || X || */ 17502f63a38cSShri Abhyankar if (snes->ops->converged != SNESSkipConverged) { ierr = VecNorm(X,NORM_2,&xnorm);CHKERRQ(ierr); } 17512f63a38cSShri Abhyankar ierr = (*snes->ops->converged)(snes,snes->iter,xnorm,ynorm,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); 17522f63a38cSShri Abhyankar if (snes->reason) break; 17532f63a38cSShri Abhyankar } 17542f63a38cSShri Abhyankar if (i == maxits) { 17552f63a38cSShri Abhyankar ierr = PetscInfo1(snes,"Maximum number of iterations has been reached: %D\n",maxits);CHKERRQ(ierr); 17562f63a38cSShri Abhyankar if(!snes->reason) snes->reason = SNES_DIVERGED_MAX_IT; 17572f63a38cSShri Abhyankar } 17582f63a38cSShri Abhyankar PetscFunctionReturn(0); 17592f63a38cSShri Abhyankar } 17602f63a38cSShri Abhyankar 17612b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */ 17622b4ed282SShri Abhyankar /* 17632b4ed282SShri Abhyankar SNESSetUp_VI - Sets up the internal data structures for the later use 17642b4ed282SShri Abhyankar of the SNESVI nonlinear solver. 17652b4ed282SShri Abhyankar 17662b4ed282SShri Abhyankar Input Parameter: 17672b4ed282SShri Abhyankar . snes - the SNES context 17682b4ed282SShri Abhyankar . x - the solution vector 17692b4ed282SShri Abhyankar 17702b4ed282SShri Abhyankar Application Interface Routine: SNESSetUp() 17712b4ed282SShri Abhyankar 17722b4ed282SShri Abhyankar Notes: 17732b4ed282SShri Abhyankar For basic use of the SNES solvers, the user need not explicitly call 17742b4ed282SShri Abhyankar SNESSetUp(), since these actions will automatically occur during 17752b4ed282SShri Abhyankar the call to SNESSolve(). 17762b4ed282SShri Abhyankar */ 17772b4ed282SShri Abhyankar #undef __FUNCT__ 17782b4ed282SShri Abhyankar #define __FUNCT__ "SNESSetUp_VI" 17792b4ed282SShri Abhyankar PetscErrorCode SNESSetUp_VI(SNES snes) 17802b4ed282SShri Abhyankar { 17812b4ed282SShri Abhyankar PetscErrorCode ierr; 17822b4ed282SShri Abhyankar SNES_VI *vi = (SNES_VI*) snes->data; 17832b4ed282SShri Abhyankar PetscInt i_start[3],i_end[3]; 17842b4ed282SShri Abhyankar 17852b4ed282SShri Abhyankar PetscFunctionBegin; 178658c9b817SLisandro Dalcin 178758c9b817SLisandro Dalcin ierr = SNESDefaultGetWork(snes,3);CHKERRQ(ierr); 17882b4ed282SShri Abhyankar 17892176524cSBarry Smith if (vi->computevariablebounds) { 179077cdaf69SJed Brown if (!vi->xl) {ierr = VecDuplicate(snes->vec_sol,&vi->xl);CHKERRQ(ierr);} 179177cdaf69SJed Brown if (!vi->xu) {ierr = VecDuplicate(snes->vec_sol,&vi->xu);CHKERRQ(ierr);} 179277cdaf69SJed Brown ierr = (*vi->computevariablebounds)(snes,vi->xl,vi->xu);CHKERRQ(ierr); 17932176524cSBarry Smith } else if (!vi->xl && !vi->xu) { 17942176524cSBarry Smith /* If the lower and upper bound on variables are not set, set it to -Inf and Inf */ 17952b4ed282SShri Abhyankar ierr = VecDuplicate(snes->vec_sol, &vi->xl);CHKERRQ(ierr); 179601f0b76bSBarry Smith ierr = VecSet(vi->xl,SNES_VI_NINF);CHKERRQ(ierr); 17972b4ed282SShri Abhyankar ierr = VecDuplicate(snes->vec_sol, &vi->xu);CHKERRQ(ierr); 179801f0b76bSBarry Smith ierr = VecSet(vi->xu,SNES_VI_INF);CHKERRQ(ierr); 17992b4ed282SShri Abhyankar } else { 18002b4ed282SShri Abhyankar /* Check if lower bound, upper bound and solution vector distribution across the processors is identical */ 18012b4ed282SShri Abhyankar ierr = VecGetOwnershipRange(snes->vec_sol,i_start,i_end);CHKERRQ(ierr); 18022b4ed282SShri Abhyankar ierr = VecGetOwnershipRange(vi->xl,i_start+1,i_end+1);CHKERRQ(ierr); 18032b4ed282SShri Abhyankar ierr = VecGetOwnershipRange(vi->xu,i_start+2,i_end+2);CHKERRQ(ierr); 18042b4ed282SShri 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])) 18052b4ed282SShri 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."); 18062b4ed282SShri Abhyankar } 18072f63a38cSShri Abhyankar if (snes->ops->solve != SNESSolveVI_SS) { 1808abcba341SShri Abhyankar /* Set up previous active index set for the first snes solve 1809abcba341SShri Abhyankar vi->IS_inact_prev = 0,1,2,....N */ 1810abcba341SShri Abhyankar PetscInt *indices; 1811abcba341SShri Abhyankar PetscInt i,n,rstart,rend; 1812abcba341SShri Abhyankar 1813abcba341SShri Abhyankar ierr = VecGetOwnershipRange(snes->vec_sol,&rstart,&rend);CHKERRQ(ierr); 1814abcba341SShri Abhyankar ierr = VecGetLocalSize(snes->vec_sol,&n);CHKERRQ(ierr); 1815abcba341SShri Abhyankar ierr = PetscMalloc(n*sizeof(PetscInt),&indices);CHKERRQ(ierr); 1816abcba341SShri Abhyankar for(i=0;i < n; i++) indices[i] = rstart + i; 1817abcba341SShri Abhyankar ierr = ISCreateGeneral(((PetscObject)snes)->comm,n,indices,PETSC_OWN_POINTER,&vi->IS_inact_prev); 1818abcba341SShri Abhyankar } 18192b4ed282SShri Abhyankar 18202f63a38cSShri Abhyankar if (snes->ops->solve == SNESSolveVI_SS) { 1821fe835674SShri Abhyankar ierr = VecDuplicate(snes->vec_sol, &vi->dpsi);CHKERRQ(ierr); 1822fe835674SShri Abhyankar ierr = VecDuplicate(snes->vec_sol, &vi->phi);CHKERRQ(ierr); 1823fe835674SShri Abhyankar ierr = VecDuplicate(snes->vec_sol, &vi->Da);CHKERRQ(ierr); 1824fe835674SShri Abhyankar ierr = VecDuplicate(snes->vec_sol, &vi->Db);CHKERRQ(ierr); 1825fe835674SShri Abhyankar ierr = VecDuplicate(snes->vec_sol, &vi->z);CHKERRQ(ierr); 1826fe835674SShri Abhyankar ierr = VecDuplicate(snes->vec_sol, &vi->t);CHKERRQ(ierr); 1827fe835674SShri Abhyankar } 18282b4ed282SShri Abhyankar PetscFunctionReturn(0); 18292b4ed282SShri Abhyankar } 18302b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */ 18312176524cSBarry Smith #undef __FUNCT__ 18322176524cSBarry Smith #define __FUNCT__ "SNESReset_VI" 18332176524cSBarry Smith PetscErrorCode SNESReset_VI(SNES snes) 18342176524cSBarry Smith { 18352176524cSBarry Smith SNES_VI *vi = (SNES_VI*) snes->data; 18362176524cSBarry Smith PetscErrorCode ierr; 18372176524cSBarry Smith 18382176524cSBarry Smith PetscFunctionBegin; 18392176524cSBarry Smith ierr = VecDestroy(&vi->xl);CHKERRQ(ierr); 18402176524cSBarry Smith ierr = VecDestroy(&vi->xu);CHKERRQ(ierr); 1841d655a5daSBarry Smith if (snes->ops->solve != SNESSolveVI_SS) { 1842d655a5daSBarry Smith ierr = ISDestroy(&vi->IS_inact_prev);CHKERRQ(ierr); 1843d655a5daSBarry Smith } 18442176524cSBarry Smith PetscFunctionReturn(0); 18452176524cSBarry Smith } 18462176524cSBarry Smith 18472b4ed282SShri Abhyankar /* 18482b4ed282SShri Abhyankar SNESDestroy_VI - Destroys the private SNES_VI context that was created 18492b4ed282SShri Abhyankar with SNESCreate_VI(). 18502b4ed282SShri Abhyankar 18512b4ed282SShri Abhyankar Input Parameter: 18522b4ed282SShri Abhyankar . snes - the SNES context 18532b4ed282SShri Abhyankar 18542b4ed282SShri Abhyankar Application Interface Routine: SNESDestroy() 18552b4ed282SShri Abhyankar */ 18562b4ed282SShri Abhyankar #undef __FUNCT__ 18572b4ed282SShri Abhyankar #define __FUNCT__ "SNESDestroy_VI" 18582b4ed282SShri Abhyankar PetscErrorCode SNESDestroy_VI(SNES snes) 18592b4ed282SShri Abhyankar { 18602b4ed282SShri Abhyankar SNES_VI *vi = (SNES_VI*) snes->data; 18612b4ed282SShri Abhyankar PetscErrorCode ierr; 18622b4ed282SShri Abhyankar 18632b4ed282SShri Abhyankar PetscFunctionBegin; 18642b4ed282SShri Abhyankar 18652f63a38cSShri Abhyankar if (snes->ops->solve == SNESSolveVI_SS) { 18662b4ed282SShri Abhyankar /* clear vectors */ 18676bf464f9SBarry Smith ierr = VecDestroy(&vi->dpsi);CHKERRQ(ierr); 18686bf464f9SBarry Smith ierr = VecDestroy(&vi->phi);CHKERRQ(ierr); 18696bf464f9SBarry Smith ierr = VecDestroy(&vi->Da);CHKERRQ(ierr); 18706bf464f9SBarry Smith ierr = VecDestroy(&vi->Db);CHKERRQ(ierr); 18716bf464f9SBarry Smith ierr = VecDestroy(&vi->z);CHKERRQ(ierr); 18726bf464f9SBarry Smith ierr = VecDestroy(&vi->t);CHKERRQ(ierr); 18737fe79bc4SShri Abhyankar } 18742b4ed282SShri Abhyankar ierr = PetscFree(snes->data);CHKERRQ(ierr); 18752b4ed282SShri Abhyankar 18762b4ed282SShri Abhyankar /* clear composed functions */ 18772b4ed282SShri Abhyankar ierr = PetscObjectComposeFunctionDynamic((PetscObject)snes,"SNESLineSearchSet_C","",PETSC_NULL);CHKERRQ(ierr); 1878c92abb8aSShri Abhyankar ierr = PetscObjectComposeFunctionDynamic((PetscObject)snes,"SNESLineSearchSetMonitor_C","",PETSC_NULL);CHKERRQ(ierr); 18792b4ed282SShri Abhyankar PetscFunctionReturn(0); 18802b4ed282SShri Abhyankar } 18817fe79bc4SShri Abhyankar 18822b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */ 18832b4ed282SShri Abhyankar #undef __FUNCT__ 18842b4ed282SShri Abhyankar #define __FUNCT__ "SNESLineSearchNo_VI" 18852b4ed282SShri Abhyankar 18862b4ed282SShri Abhyankar /* 18877fe79bc4SShri Abhyankar This routine does not actually do a line search but it takes a full newton 18887fe79bc4SShri Abhyankar step while ensuring that the new iterates remain within the constraints. 18892b4ed282SShri Abhyankar 18902b4ed282SShri Abhyankar */ 18911e633543SBarry Smith PetscErrorCode SNESLineSearchNo_VI(SNES snes,void *lsctx,Vec x,Vec f,Vec y,PetscReal fnorm,PetscReal xnorm,Vec g,Vec w,PetscReal *ynorm,PetscReal *gnorm,PetscBool *flag) 18922b4ed282SShri Abhyankar { 18932b4ed282SShri Abhyankar PetscErrorCode ierr; 1894ace3abfcSBarry Smith PetscBool changed_w = PETSC_FALSE,changed_y = PETSC_FALSE; 18952b4ed282SShri Abhyankar 18962b4ed282SShri Abhyankar PetscFunctionBegin; 18972b4ed282SShri Abhyankar *flag = PETSC_TRUE; 18982b4ed282SShri Abhyankar ierr = PetscLogEventBegin(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); 18992b4ed282SShri Abhyankar ierr = VecNorm(y,NORM_2,ynorm);CHKERRQ(ierr); /* ynorm = || y || */ 19002b4ed282SShri Abhyankar ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr); /* w <- x - y */ 1901c1a5e521SShri Abhyankar ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr); 19020661309fSPeter Brune if (snes->ops->postcheckstep) { 19030661309fSPeter Brune ierr = (*snes->ops->postcheckstep)(snes,x,y,w,snes->postcheck,&changed_y,&changed_w);CHKERRQ(ierr); 1904c1a5e521SShri Abhyankar } 1905c1a5e521SShri Abhyankar if (changed_y) { 1906c1a5e521SShri Abhyankar ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr); /* w <- x - y */ 19077fe79bc4SShri Abhyankar ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr); 1908c1a5e521SShri Abhyankar } 1909c1a5e521SShri Abhyankar ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr); 1910c1a5e521SShri Abhyankar ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr); 1911c1a5e521SShri Abhyankar if (!snes->domainerror) { 19122f63a38cSShri Abhyankar if (snes->ops->solve != SNESSolveVI_SS) { 19137fe79bc4SShri Abhyankar ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr); 19147fe79bc4SShri Abhyankar } else { 1915c1a5e521SShri Abhyankar ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr); /* gnorm = || g || */ 19167fe79bc4SShri Abhyankar } 191762cbcd01SMatthew G Knepley if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number"); 1918c1a5e521SShri Abhyankar } 19190661309fSPeter Brune if (snes->ls_monitor) { 19200661309fSPeter Brune ierr = PetscViewerASCIIAddTab(snes->ls_monitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 19210661309fSPeter Brune ierr = PetscViewerASCIIPrintf(snes->ls_monitor," Line search: Using full step: fnorm %g gnorm %g\n",(double)fnorm,(double)*gnorm);CHKERRQ(ierr); 19220661309fSPeter Brune ierr = PetscViewerASCIISubtractTab(snes->ls_monitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 1923c1a5e521SShri Abhyankar } 1924c1a5e521SShri Abhyankar ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); 1925c1a5e521SShri Abhyankar PetscFunctionReturn(0); 1926c1a5e521SShri Abhyankar } 1927c1a5e521SShri Abhyankar 1928c1a5e521SShri Abhyankar /* -------------------------------------------------------------------------- */ 1929c1a5e521SShri Abhyankar #undef __FUNCT__ 19302b4ed282SShri Abhyankar #define __FUNCT__ "SNESLineSearchNoNorms_VI" 19312b4ed282SShri Abhyankar 19322b4ed282SShri Abhyankar /* 19332b4ed282SShri Abhyankar This routine is a copy of SNESLineSearchNoNorms in snes/impls/ls/ls.c 19342b4ed282SShri Abhyankar */ 19351e633543SBarry Smith PetscErrorCode SNESLineSearchNoNorms_VI(SNES snes,void *lsctx,Vec x,Vec f,Vec y,PetscReal fnorm,PetscReal xnorm,Vec g,Vec w,PetscReal *ynorm,PetscReal *gnorm,PetscBool *flag) 19362b4ed282SShri Abhyankar { 19372b4ed282SShri Abhyankar PetscErrorCode ierr; 1938ace3abfcSBarry Smith PetscBool changed_w = PETSC_FALSE,changed_y = PETSC_FALSE; 19392b4ed282SShri Abhyankar 19402b4ed282SShri Abhyankar PetscFunctionBegin; 19412b4ed282SShri Abhyankar *flag = PETSC_TRUE; 19422b4ed282SShri Abhyankar ierr = PetscLogEventBegin(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); 19432b4ed282SShri Abhyankar ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr); /* w <- x - y */ 19447fe79bc4SShri Abhyankar ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr); 19450661309fSPeter Brune if (snes->ops->postcheckstep) { 19460661309fSPeter Brune ierr = (*snes->ops->postcheckstep)(snes,x,y,w,snes->postcheck,&changed_y,&changed_w);CHKERRQ(ierr); 19472b4ed282SShri Abhyankar } 19482b4ed282SShri Abhyankar if (changed_y) { 19492b4ed282SShri Abhyankar ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr); /* w <- x - y */ 19507fe79bc4SShri Abhyankar ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr); 19512b4ed282SShri Abhyankar } 19522b4ed282SShri Abhyankar 19532b4ed282SShri Abhyankar /* don't evaluate function the last time through */ 19542b4ed282SShri Abhyankar if (snes->iter < snes->max_its-1) { 19552b4ed282SShri Abhyankar ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr); 19562b4ed282SShri Abhyankar } 19572b4ed282SShri Abhyankar ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); 19582b4ed282SShri Abhyankar PetscFunctionReturn(0); 19592b4ed282SShri Abhyankar } 19607fe79bc4SShri Abhyankar 19612b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */ 19622b4ed282SShri Abhyankar #undef __FUNCT__ 19632b4ed282SShri Abhyankar #define __FUNCT__ "SNESLineSearchCubic_VI" 19642b4ed282SShri Abhyankar /* 19657fe79bc4SShri Abhyankar This routine implements a cubic line search while doing a projection on the variable bounds 19662b4ed282SShri Abhyankar */ 19671e633543SBarry Smith PetscErrorCode SNESLineSearchCubic_VI(SNES snes,void *lsctx,Vec x,Vec f,Vec y,PetscReal fnorm,PetscReal xnorm,Vec g,Vec w,PetscReal *ynorm,PetscReal *gnorm,PetscBool *flag) 19682b4ed282SShri Abhyankar { 1969fe835674SShri Abhyankar PetscReal initslope,lambdaprev,gnormprev,a,b,d,t1,t2,rellength; 1970fe835674SShri Abhyankar PetscReal minlambda,lambda,lambdatemp; 1971fe835674SShri Abhyankar #if defined(PETSC_USE_COMPLEX) 1972fe835674SShri Abhyankar PetscScalar cinitslope; 1973fe835674SShri Abhyankar #endif 1974fe835674SShri Abhyankar PetscErrorCode ierr; 1975fe835674SShri Abhyankar PetscInt count; 1976fe835674SShri Abhyankar PetscBool changed_w = PETSC_FALSE,changed_y = PETSC_FALSE; 1977fe835674SShri Abhyankar MPI_Comm comm; 1978fe835674SShri Abhyankar 1979fe835674SShri Abhyankar PetscFunctionBegin; 1980fe835674SShri Abhyankar ierr = PetscObjectGetComm((PetscObject)snes,&comm);CHKERRQ(ierr); 1981fe835674SShri Abhyankar ierr = PetscLogEventBegin(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); 1982fe835674SShri Abhyankar *flag = PETSC_TRUE; 1983fe835674SShri Abhyankar 1984fe835674SShri Abhyankar ierr = VecNorm(y,NORM_2,ynorm);CHKERRQ(ierr); 1985fe835674SShri Abhyankar if (*ynorm == 0.0) { 19860661309fSPeter Brune if (snes->ls_monitor) { 19870661309fSPeter Brune ierr = PetscViewerASCIIAddTab(snes->ls_monitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 19880661309fSPeter Brune ierr = PetscViewerASCIIPrintf(snes->ls_monitor," Line search: Initial direction and size is 0\n");CHKERRQ(ierr); 19890661309fSPeter Brune ierr = PetscViewerASCIISubtractTab(snes->ls_monitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 1990fe835674SShri Abhyankar } 1991fe835674SShri Abhyankar *gnorm = fnorm; 1992fe835674SShri Abhyankar ierr = VecCopy(x,w);CHKERRQ(ierr); 1993fe835674SShri Abhyankar ierr = VecCopy(f,g);CHKERRQ(ierr); 1994fe835674SShri Abhyankar *flag = PETSC_FALSE; 1995fe835674SShri Abhyankar goto theend1; 1996fe835674SShri Abhyankar } 19970661309fSPeter Brune if (*ynorm > snes->maxstep) { /* Step too big, so scale back */ 19980661309fSPeter Brune if (snes->ls_monitor) { 19990661309fSPeter Brune ierr = PetscViewerASCIIAddTab(snes->ls_monitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 200062d1f40fSBarry Smith ierr = PetscViewerASCIIPrintf(snes->ls_monitor," Line search: Scaling step by %g old ynorm %g\n",(double)(snes->maxstep/(*ynorm)),(double)(*ynorm));CHKERRQ(ierr); 20010661309fSPeter Brune ierr = PetscViewerASCIISubtractTab(snes->ls_monitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 2002fe835674SShri Abhyankar } 20030661309fSPeter Brune ierr = VecScale(y,snes->maxstep/(*ynorm));CHKERRQ(ierr); 20040661309fSPeter Brune *ynorm = snes->maxstep; 2005fe835674SShri Abhyankar } 2006fe835674SShri Abhyankar ierr = VecMaxPointwiseDivide(y,x,&rellength);CHKERRQ(ierr); 20070661309fSPeter Brune minlambda = snes->steptol/rellength; 2008fe835674SShri Abhyankar ierr = MatMult(snes->jacobian,y,w);CHKERRQ(ierr); 2009fe835674SShri Abhyankar #if defined(PETSC_USE_COMPLEX) 2010fe835674SShri Abhyankar ierr = VecDot(f,w,&cinitslope);CHKERRQ(ierr); 2011fe835674SShri Abhyankar initslope = PetscRealPart(cinitslope); 2012fe835674SShri Abhyankar #else 2013fe835674SShri Abhyankar ierr = VecDot(f,w,&initslope);CHKERRQ(ierr); 2014fe835674SShri Abhyankar #endif 2015fe835674SShri Abhyankar if (initslope > 0.0) initslope = -initslope; 2016fe835674SShri Abhyankar if (initslope == 0.0) initslope = -1.0; 2017fe835674SShri Abhyankar 2018fe835674SShri Abhyankar ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr); 2019fe835674SShri Abhyankar ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr); 2020fe835674SShri Abhyankar if (snes->nfuncs >= snes->max_funcs) { 2021fe835674SShri Abhyankar ierr = PetscInfo(snes,"Exceeded maximum function evaluations, while checking full step length!\n");CHKERRQ(ierr); 2022fe835674SShri Abhyankar *flag = PETSC_FALSE; 2023fe835674SShri Abhyankar snes->reason = SNES_DIVERGED_FUNCTION_COUNT; 2024fe835674SShri Abhyankar goto theend1; 2025fe835674SShri Abhyankar } 2026fe835674SShri Abhyankar ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr); 20272f63a38cSShri Abhyankar if (snes->ops->solve != SNESSolveVI_SS) { 2028fe835674SShri Abhyankar ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr); 20297fe79bc4SShri Abhyankar } else { 20307fe79bc4SShri Abhyankar ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr); 20317fe79bc4SShri Abhyankar } 2032fe835674SShri Abhyankar if (snes->domainerror) { 2033fe835674SShri Abhyankar ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); 2034fe835674SShri Abhyankar PetscFunctionReturn(0); 2035fe835674SShri Abhyankar } 203662cbcd01SMatthew G Knepley if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number"); 20370661309fSPeter Brune ierr = PetscInfo4(snes,"Initial fnorm %g gnorm %g alpha %g initslope %g\n",(double)fnorm,(double)*gnorm,(double)snes->ls_alpha,(double)initslope);CHKERRQ(ierr); 20380661309fSPeter Brune if ((*gnorm)*(*gnorm) <= (1.0 - snes->ls_alpha)*fnorm*fnorm ) { /* Sufficient reduction */ 20390661309fSPeter Brune if (snes->ls_monitor) { 20400661309fSPeter Brune ierr = PetscViewerASCIIAddTab(snes->ls_monitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 204162d1f40fSBarry Smith ierr = PetscViewerASCIIPrintf(snes->ls_monitor," Line search: Using full step: fnorm %g gnorm %g\n",(double)fnorm,(double)(*gnorm));CHKERRQ(ierr); 20420661309fSPeter Brune ierr = PetscViewerASCIISubtractTab(snes->ls_monitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 2043fe835674SShri Abhyankar } 2044fe835674SShri Abhyankar goto theend1; 2045fe835674SShri Abhyankar } 2046fe835674SShri Abhyankar 2047fe835674SShri Abhyankar /* Fit points with quadratic */ 2048fe835674SShri Abhyankar lambda = 1.0; 2049fe835674SShri Abhyankar lambdatemp = -initslope/((*gnorm)*(*gnorm) - fnorm*fnorm - 2.0*initslope); 2050fe835674SShri Abhyankar lambdaprev = lambda; 2051fe835674SShri Abhyankar gnormprev = *gnorm; 2052fe835674SShri Abhyankar if (lambdatemp > .5*lambda) lambdatemp = .5*lambda; 2053fe835674SShri Abhyankar if (lambdatemp <= .1*lambda) lambda = .1*lambda; 2054fe835674SShri Abhyankar else lambda = lambdatemp; 2055fe835674SShri Abhyankar 2056fe835674SShri Abhyankar ierr = VecWAXPY(w,-lambda,y,x);CHKERRQ(ierr); 2057fe835674SShri Abhyankar ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr); 2058fe835674SShri Abhyankar if (snes->nfuncs >= snes->max_funcs) { 2059fe835674SShri Abhyankar ierr = PetscInfo1(snes,"Exceeded maximum function evaluations, while attempting quadratic backtracking! %D \n",snes->nfuncs);CHKERRQ(ierr); 2060fe835674SShri Abhyankar *flag = PETSC_FALSE; 2061fe835674SShri Abhyankar snes->reason = SNES_DIVERGED_FUNCTION_COUNT; 2062fe835674SShri Abhyankar goto theend1; 2063fe835674SShri Abhyankar } 2064fe835674SShri Abhyankar ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr); 20652f63a38cSShri Abhyankar if (snes->ops->solve != SNESSolveVI_SS) { 2066fe835674SShri Abhyankar ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr); 20677fe79bc4SShri Abhyankar } else { 20687fe79bc4SShri Abhyankar ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr); 20697fe79bc4SShri Abhyankar } 2070fe835674SShri Abhyankar if (snes->domainerror) { 2071fe835674SShri Abhyankar ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); 2072fe835674SShri Abhyankar PetscFunctionReturn(0); 2073fe835674SShri Abhyankar } 207462cbcd01SMatthew G Knepley if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number"); 20750661309fSPeter Brune if (snes->ls_monitor) { 20760661309fSPeter Brune ierr = PetscViewerASCIIAddTab(snes->ls_monitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 207762d1f40fSBarry Smith ierr = PetscViewerASCIIPrintf(snes->ls_monitor," Line search: gnorm after quadratic fit %g\n",(double)(*gnorm));CHKERRQ(ierr); 20780661309fSPeter Brune ierr = PetscViewerASCIISubtractTab(snes->ls_monitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 2079fe835674SShri Abhyankar } 20800661309fSPeter Brune if ((*gnorm)*(*gnorm) < (1.0 - snes->ls_alpha)*fnorm*fnorm ) { /* sufficient reduction */ 20810661309fSPeter Brune if (snes->ls_monitor) { 20820661309fSPeter Brune ierr = PetscViewerASCIIAddTab(snes->ls_monitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 2083*4839bfe8SBarry Smith ierr = PetscViewerASCIIPrintf(snes->ls_monitor," Line search: Quadratically determined step, lambda=%18.16e\n",(double)lambda);CHKERRQ(ierr); 20840661309fSPeter Brune ierr = PetscViewerASCIISubtractTab(snes->ls_monitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 2085fe835674SShri Abhyankar } 2086fe835674SShri Abhyankar goto theend1; 2087fe835674SShri Abhyankar } 2088fe835674SShri Abhyankar 2089fe835674SShri Abhyankar /* Fit points with cubic */ 2090fe835674SShri Abhyankar count = 1; 2091fe835674SShri Abhyankar while (PETSC_TRUE) { 2092fe835674SShri Abhyankar if (lambda <= minlambda) { 20930661309fSPeter Brune if (snes->ls_monitor) { 20940661309fSPeter Brune ierr = PetscViewerASCIIAddTab(snes->ls_monitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 20950661309fSPeter Brune ierr = PetscViewerASCIIPrintf(snes->ls_monitor," Line search: unable to find good step length! After %D tries \n",count);CHKERRQ(ierr); 209662d1f40fSBarry Smith ierr = PetscViewerASCIIPrintf(snes->ls_monitor," Line search: fnorm=%18.16e, gnorm=%18.16e, ynorm=%18.16e, minlambda=%18.16e, lambda=%18.16e, initial slope=%18.16e\n",(double)fnorm,(double)(*gnorm),(double)(*ynorm),(double)minlambda,(double)lambda,(double)initslope);CHKERRQ(ierr); 20970661309fSPeter Brune ierr = PetscViewerASCIISubtractTab(snes->ls_monitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 2098fe835674SShri Abhyankar } 2099fe835674SShri Abhyankar *flag = PETSC_FALSE; 2100fe835674SShri Abhyankar break; 2101fe835674SShri Abhyankar } 2102fe835674SShri Abhyankar t1 = .5*((*gnorm)*(*gnorm) - fnorm*fnorm) - lambda*initslope; 2103fe835674SShri Abhyankar t2 = .5*(gnormprev*gnormprev - fnorm*fnorm) - lambdaprev*initslope; 2104fe835674SShri Abhyankar a = (t1/(lambda*lambda) - t2/(lambdaprev*lambdaprev))/(lambda-lambdaprev); 2105fe835674SShri Abhyankar b = (-lambdaprev*t1/(lambda*lambda) + lambda*t2/(lambdaprev*lambdaprev))/(lambda-lambdaprev); 2106fe835674SShri Abhyankar d = b*b - 3*a*initslope; 2107fe835674SShri Abhyankar if (d < 0.0) d = 0.0; 2108fe835674SShri Abhyankar if (a == 0.0) { 2109fe835674SShri Abhyankar lambdatemp = -initslope/(2.0*b); 2110fe835674SShri Abhyankar } else { 211162d1f40fSBarry Smith lambdatemp = (-b + PetscSqrtReal(d))/(3.0*a); 2112fe835674SShri Abhyankar } 2113fe835674SShri Abhyankar lambdaprev = lambda; 2114fe835674SShri Abhyankar gnormprev = *gnorm; 2115fe835674SShri Abhyankar if (lambdatemp > .5*lambda) lambdatemp = .5*lambda; 2116fe835674SShri Abhyankar if (lambdatemp <= .1*lambda) lambda = .1*lambda; 2117fe835674SShri Abhyankar else lambda = lambdatemp; 2118fe835674SShri Abhyankar ierr = VecWAXPY(w,-lambda,y,x);CHKERRQ(ierr); 2119fe835674SShri Abhyankar ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr); 2120fe835674SShri Abhyankar if (snes->nfuncs >= snes->max_funcs) { 2121fe835674SShri Abhyankar ierr = PetscInfo1(snes,"Exceeded maximum function evaluations, while looking for good step length! %D \n",count);CHKERRQ(ierr); 2122*4839bfe8SBarry Smith ierr = PetscInfo5(snes,"fnorm=%18.16e, gnorm=%18.16e, ynorm=%18.16e, lambda=%18.16e, initial slope=%18.16e\n",(double)fnorm,(double)(*gnorm),(double)(*ynorm),(double)lambda,(double)initslope);CHKERRQ(ierr); 2123fe835674SShri Abhyankar *flag = PETSC_FALSE; 2124fe835674SShri Abhyankar snes->reason = SNES_DIVERGED_FUNCTION_COUNT; 2125fe835674SShri Abhyankar break; 2126fe835674SShri Abhyankar } 2127fe835674SShri Abhyankar ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr); 21282f63a38cSShri Abhyankar if (snes->ops->solve != SNESSolveVI_SS) { 2129fe835674SShri Abhyankar ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr); 21307fe79bc4SShri Abhyankar } else { 21317fe79bc4SShri Abhyankar ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr); 21327fe79bc4SShri Abhyankar } 2133fe835674SShri Abhyankar if (snes->domainerror) { 2134fe835674SShri Abhyankar ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); 2135fe835674SShri Abhyankar PetscFunctionReturn(0); 2136fe835674SShri Abhyankar } 213762cbcd01SMatthew G Knepley if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number"); 21380661309fSPeter Brune if ((*gnorm)*(*gnorm) < (1.0 - snes->ls_alpha)*fnorm*fnorm) { /* is reduction enough? */ 21390661309fSPeter Brune if (snes->ls_monitor) { 214062d1f40fSBarry Smith ierr = PetscPrintf(comm," Line search: Cubically determined step, current gnorm %g lambda=%18.16e\n",(double)(*gnorm),(double)lambda);CHKERRQ(ierr); 2141fe835674SShri Abhyankar } 2142fe835674SShri Abhyankar break; 2143fe835674SShri Abhyankar } else { 21440661309fSPeter Brune if (snes->ls_monitor) { 214562d1f40fSBarry Smith ierr = PetscPrintf(comm," Line search: Cubic step no good, shrinking lambda, current gnorm %g lambda=%18.16e\n",(double)(*gnorm),(double)lambda);CHKERRQ(ierr); 2146fe835674SShri Abhyankar } 2147fe835674SShri Abhyankar } 2148fe835674SShri Abhyankar count++; 2149fe835674SShri Abhyankar } 2150fe835674SShri Abhyankar theend1: 2151fe835674SShri Abhyankar /* Optional user-defined check for line search step validity */ 21520661309fSPeter Brune if (snes->ops->postcheckstep && *flag) { 21530661309fSPeter Brune ierr = (*snes->ops->postcheckstep)(snes,x,y,w,snes->postcheck,&changed_y,&changed_w);CHKERRQ(ierr); 2154fe835674SShri Abhyankar if (changed_y) { 2155fe835674SShri Abhyankar ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr); 2156fe835674SShri Abhyankar ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr); 2157fe835674SShri Abhyankar } 2158fe835674SShri Abhyankar if (changed_y || changed_w) { /* recompute the function if the step has changed */ 2159fe835674SShri Abhyankar ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr); 21602f63a38cSShri Abhyankar if (snes->ops->solve != SNESSolveVI_SS) { 2161fe835674SShri Abhyankar ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr); 21627fe79bc4SShri Abhyankar } else { 21637fe79bc4SShri Abhyankar ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr); 21647fe79bc4SShri Abhyankar } 2165fe835674SShri Abhyankar if (snes->domainerror) { 2166fe835674SShri Abhyankar ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); 2167fe835674SShri Abhyankar PetscFunctionReturn(0); 2168fe835674SShri Abhyankar } 216962cbcd01SMatthew G Knepley if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number"); 2170fe835674SShri Abhyankar ierr = VecNormBegin(y,NORM_2,ynorm);CHKERRQ(ierr); 2171fe835674SShri Abhyankar ierr = VecNormEnd(y,NORM_2,ynorm);CHKERRQ(ierr); 2172fe835674SShri Abhyankar } 2173fe835674SShri Abhyankar } 2174fe835674SShri Abhyankar ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); 2175fe835674SShri Abhyankar PetscFunctionReturn(0); 2176fe835674SShri Abhyankar } 2177fe835674SShri Abhyankar 21782b4ed282SShri Abhyankar #undef __FUNCT__ 21792b4ed282SShri Abhyankar #define __FUNCT__ "SNESLineSearchQuadratic_VI" 21802b4ed282SShri Abhyankar /* 21817fe79bc4SShri Abhyankar This routine does a quadratic line search while keeping the iterates within the variable bounds 21822b4ed282SShri Abhyankar */ 21831e633543SBarry Smith PetscErrorCode SNESLineSearchQuadratic_VI(SNES snes,void *lsctx,Vec x,Vec f,Vec y,PetscReal fnorm,PetscReal xnorm,Vec g,Vec w,PetscReal *ynorm,PetscReal *gnorm,PetscBool *flag) 21842b4ed282SShri Abhyankar { 21852b4ed282SShri Abhyankar /* 21862b4ed282SShri Abhyankar Note that for line search purposes we work with with the related 21872b4ed282SShri Abhyankar minimization problem: 21882b4ed282SShri Abhyankar min z(x): R^n -> R, 21892b4ed282SShri Abhyankar where z(x) = .5 * fnorm*fnorm,and fnorm = || f ||_2. 21902b4ed282SShri Abhyankar */ 21912b4ed282SShri Abhyankar PetscReal initslope,minlambda,lambda,lambdatemp,rellength; 21922b4ed282SShri Abhyankar #if defined(PETSC_USE_COMPLEX) 21932b4ed282SShri Abhyankar PetscScalar cinitslope; 21942b4ed282SShri Abhyankar #endif 21952b4ed282SShri Abhyankar PetscErrorCode ierr; 21962b4ed282SShri Abhyankar PetscInt count; 2197ace3abfcSBarry Smith PetscBool changed_w = PETSC_FALSE,changed_y = PETSC_FALSE; 21982b4ed282SShri Abhyankar 21992b4ed282SShri Abhyankar PetscFunctionBegin; 22002b4ed282SShri Abhyankar ierr = PetscLogEventBegin(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); 22012b4ed282SShri Abhyankar *flag = PETSC_TRUE; 22022b4ed282SShri Abhyankar 22032b4ed282SShri Abhyankar ierr = VecNorm(y,NORM_2,ynorm);CHKERRQ(ierr); 22042b4ed282SShri Abhyankar if (*ynorm == 0.0) { 22050661309fSPeter Brune if (snes->ls_monitor) { 22060661309fSPeter Brune ierr = PetscViewerASCIIAddTab(snes->ls_monitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 22070661309fSPeter Brune ierr = PetscViewerASCIIPrintf(snes->ls_monitor,"Line search: Direction and size is 0\n");CHKERRQ(ierr); 22080661309fSPeter Brune ierr = PetscViewerASCIISubtractTab(snes->ls_monitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 22092b4ed282SShri Abhyankar } 22102b4ed282SShri Abhyankar *gnorm = fnorm; 22112b4ed282SShri Abhyankar ierr = VecCopy(x,w);CHKERRQ(ierr); 22122b4ed282SShri Abhyankar ierr = VecCopy(f,g);CHKERRQ(ierr); 22132b4ed282SShri Abhyankar *flag = PETSC_FALSE; 22142b4ed282SShri Abhyankar goto theend2; 22152b4ed282SShri Abhyankar } 22160661309fSPeter Brune if (*ynorm > snes->maxstep) { /* Step too big, so scale back */ 22170661309fSPeter Brune ierr = VecScale(y,snes->maxstep/(*ynorm));CHKERRQ(ierr); 22180661309fSPeter Brune *ynorm = snes->maxstep; 22192b4ed282SShri Abhyankar } 22202b4ed282SShri Abhyankar ierr = VecMaxPointwiseDivide(y,x,&rellength);CHKERRQ(ierr); 22210661309fSPeter Brune minlambda = snes->steptol/rellength; 22227fe79bc4SShri Abhyankar ierr = MatMult(snes->jacobian,y,w);CHKERRQ(ierr); 22232b4ed282SShri Abhyankar #if defined(PETSC_USE_COMPLEX) 22247fe79bc4SShri Abhyankar ierr = VecDot(f,w,&cinitslope);CHKERRQ(ierr); 22252b4ed282SShri Abhyankar initslope = PetscRealPart(cinitslope); 22262b4ed282SShri Abhyankar #else 22277fe79bc4SShri Abhyankar ierr = VecDot(f,w,&initslope);CHKERRQ(ierr); 22282b4ed282SShri Abhyankar #endif 22292b4ed282SShri Abhyankar if (initslope > 0.0) initslope = -initslope; 22302b4ed282SShri Abhyankar if (initslope == 0.0) initslope = -1.0; 2231*4839bfe8SBarry Smith ierr = PetscInfo1(snes,"Initslope %g \n",(double)initslope);CHKERRQ(ierr); 22322b4ed282SShri Abhyankar 22332b4ed282SShri Abhyankar ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr); 22347fe79bc4SShri Abhyankar ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr); 22352b4ed282SShri Abhyankar if (snes->nfuncs >= snes->max_funcs) { 22362b4ed282SShri Abhyankar ierr = PetscInfo(snes,"Exceeded maximum function evaluations, while checking full step length!\n");CHKERRQ(ierr); 22372b4ed282SShri Abhyankar *flag = PETSC_FALSE; 22382b4ed282SShri Abhyankar snes->reason = SNES_DIVERGED_FUNCTION_COUNT; 22392b4ed282SShri Abhyankar goto theend2; 22402b4ed282SShri Abhyankar } 22412b4ed282SShri Abhyankar ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr); 22422f63a38cSShri Abhyankar if (snes->ops->solve != SNESSolveVI_SS) { 22437fe79bc4SShri Abhyankar ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr); 22447fe79bc4SShri Abhyankar } else { 22457fe79bc4SShri Abhyankar ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr); 22467fe79bc4SShri Abhyankar } 22472b4ed282SShri Abhyankar if (snes->domainerror) { 22482b4ed282SShri Abhyankar ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); 22492b4ed282SShri Abhyankar PetscFunctionReturn(0); 22502b4ed282SShri Abhyankar } 225162cbcd01SMatthew G Knepley if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number"); 22520661309fSPeter Brune if ((*gnorm)*(*gnorm) <= (1.0 - snes->ls_alpha)*fnorm*fnorm) { /* Sufficient reduction */ 22530661309fSPeter Brune if (snes->ls_monitor) { 22540661309fSPeter Brune ierr = PetscViewerASCIIAddTab(snes->ls_monitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 225562d1f40fSBarry Smith ierr = PetscViewerASCIIPrintf(snes->ls_monitor," Line search: Using full step: fnorm %g gnorm %g\n",(double)fnorm,(double)(*gnorm));CHKERRQ(ierr); 22560661309fSPeter Brune ierr = PetscViewerASCIISubtractTab(snes->ls_monitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 22572b4ed282SShri Abhyankar } 22582b4ed282SShri Abhyankar goto theend2; 22592b4ed282SShri Abhyankar } 22602b4ed282SShri Abhyankar 22612b4ed282SShri Abhyankar /* Fit points with quadratic */ 22622b4ed282SShri Abhyankar lambda = 1.0; 22632b4ed282SShri Abhyankar count = 1; 22642b4ed282SShri Abhyankar while (PETSC_TRUE) { 22652b4ed282SShri Abhyankar if (lambda <= minlambda) { /* bad luck; use full step */ 22660661309fSPeter Brune if (snes->ls_monitor) { 22670661309fSPeter Brune ierr = PetscViewerASCIIAddTab(snes->ls_monitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 22680661309fSPeter Brune ierr = PetscViewerASCIIPrintf(snes->ls_monitor,"Line search: Unable to find good step length! %D \n",count);CHKERRQ(ierr); 226962d1f40fSBarry Smith ierr = PetscViewerASCIIPrintf(snes->ls_monitor,"Line search: fnorm=%g, gnorm=%g, ynorm=%g, lambda=%g, initial slope=%g\n",(double)fnorm,(double)(*gnorm),(double)(*ynorm),(double)lambda,(double)initslope);CHKERRQ(ierr); 22700661309fSPeter Brune ierr = PetscViewerASCIISubtractTab(snes->ls_monitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 22712b4ed282SShri Abhyankar } 22722b4ed282SShri Abhyankar ierr = VecCopy(x,w);CHKERRQ(ierr); 22732b4ed282SShri Abhyankar *flag = PETSC_FALSE; 22742b4ed282SShri Abhyankar break; 22752b4ed282SShri Abhyankar } 22762b4ed282SShri Abhyankar lambdatemp = -initslope/((*gnorm)*(*gnorm) - fnorm*fnorm - 2.0*initslope); 22772b4ed282SShri Abhyankar if (lambdatemp > .5*lambda) lambdatemp = .5*lambda; 22782b4ed282SShri Abhyankar if (lambdatemp <= .1*lambda) lambda = .1*lambda; 22792b4ed282SShri Abhyankar else lambda = lambdatemp; 22802b4ed282SShri Abhyankar 22812b4ed282SShri Abhyankar ierr = VecWAXPY(w,-lambda,y,x);CHKERRQ(ierr); 22827fe79bc4SShri Abhyankar ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr); 22832b4ed282SShri Abhyankar if (snes->nfuncs >= snes->max_funcs) { 22842b4ed282SShri Abhyankar ierr = PetscInfo1(snes,"Exceeded maximum function evaluations, while looking for good step length! %D \n",count);CHKERRQ(ierr); 2285*4839bfe8SBarry Smith ierr = PetscInfo5(snes,"fnorm=%18.16e, gnorm=%18.16e, ynorm=%18.16e, lambda=%18.16e, initial slope=%18.16e\n",(double)fnorm,(double)(*gnorm),(double)(*ynorm),(double)lambda,(double)initslope);CHKERRQ(ierr); 22862b4ed282SShri Abhyankar *flag = PETSC_FALSE; 22872b4ed282SShri Abhyankar snes->reason = SNES_DIVERGED_FUNCTION_COUNT; 22882b4ed282SShri Abhyankar break; 22892b4ed282SShri Abhyankar } 22902b4ed282SShri Abhyankar ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr); 22912b4ed282SShri Abhyankar if (snes->domainerror) { 22922b4ed282SShri Abhyankar ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); 22932b4ed282SShri Abhyankar PetscFunctionReturn(0); 22942b4ed282SShri Abhyankar } 22952f63a38cSShri Abhyankar if (snes->ops->solve != SNESSolveVI_SS) { 22967fe79bc4SShri Abhyankar ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr); 22977fe79bc4SShri Abhyankar } else { 22982b4ed282SShri Abhyankar ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr); 22997fe79bc4SShri Abhyankar } 230062cbcd01SMatthew G Knepley if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number"); 23010661309fSPeter Brune if ((*gnorm)*(*gnorm) < (1.0 - snes->ls_alpha)*fnorm*fnorm) { /* sufficient reduction */ 23020661309fSPeter Brune if (snes->ls_monitor) { 23030661309fSPeter Brune ierr = PetscViewerASCIIAddTab(snes->ls_monitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 230462d1f40fSBarry Smith ierr = PetscViewerASCIIPrintf(snes->ls_monitor," Line Search: Quadratically determined step, lambda=%g\n",(double)lambda);CHKERRQ(ierr); 23050661309fSPeter Brune ierr = PetscViewerASCIISubtractTab(snes->ls_monitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 23062b4ed282SShri Abhyankar } 23072b4ed282SShri Abhyankar break; 23082b4ed282SShri Abhyankar } 23092b4ed282SShri Abhyankar count++; 23102b4ed282SShri Abhyankar } 23112b4ed282SShri Abhyankar theend2: 23122b4ed282SShri Abhyankar /* Optional user-defined check for line search step validity */ 23130661309fSPeter Brune if (snes->ops->postcheckstep) { 23140661309fSPeter Brune ierr = (*snes->ops->postcheckstep)(snes,x,y,w,snes->postcheck,&changed_y,&changed_w);CHKERRQ(ierr); 23152b4ed282SShri Abhyankar if (changed_y) { 23162b4ed282SShri Abhyankar ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr); 23177fe79bc4SShri Abhyankar ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr); 23182b4ed282SShri Abhyankar } 23192b4ed282SShri Abhyankar if (changed_y || changed_w) { /* recompute the function if the step has changed */ 23202b4ed282SShri Abhyankar ierr = SNESComputeFunction(snes,w,g); 23212b4ed282SShri Abhyankar if (snes->domainerror) { 23222b4ed282SShri Abhyankar ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); 23232b4ed282SShri Abhyankar PetscFunctionReturn(0); 23242b4ed282SShri Abhyankar } 23252f63a38cSShri Abhyankar if (snes->ops->solve != SNESSolveVI_SS) { 23267fe79bc4SShri Abhyankar ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr); 23277fe79bc4SShri Abhyankar } else { 23287fe79bc4SShri Abhyankar ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr); 23297fe79bc4SShri Abhyankar } 23307fe79bc4SShri Abhyankar 23312b4ed282SShri Abhyankar ierr = VecNormBegin(y,NORM_2,ynorm);CHKERRQ(ierr); 23322b4ed282SShri Abhyankar ierr = VecNormEnd(y,NORM_2,ynorm);CHKERRQ(ierr); 233362cbcd01SMatthew G Knepley if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number"); 23342b4ed282SShri Abhyankar } 23352b4ed282SShri Abhyankar } 23362b4ed282SShri Abhyankar ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); 23372b4ed282SShri Abhyankar PetscFunctionReturn(0); 23382b4ed282SShri Abhyankar } 23392b4ed282SShri Abhyankar 23402b4ed282SShri Abhyankar /* 23412b4ed282SShri Abhyankar SNESView_VI - Prints info from the SNESVI data structure. 23422b4ed282SShri Abhyankar 23432b4ed282SShri Abhyankar Input Parameters: 23442b4ed282SShri Abhyankar . SNES - the SNES context 23452b4ed282SShri Abhyankar . viewer - visualization context 23462b4ed282SShri Abhyankar 23472b4ed282SShri Abhyankar Application Interface Routine: SNESView() 23482b4ed282SShri Abhyankar */ 23492b4ed282SShri Abhyankar #undef __FUNCT__ 23502b4ed282SShri Abhyankar #define __FUNCT__ "SNESView_VI" 23512b4ed282SShri Abhyankar static PetscErrorCode SNESView_VI(SNES snes,PetscViewer viewer) 23522b4ed282SShri Abhyankar { 235378c4b9d3SShri Abhyankar const char *cstr,*tstr; 23542b4ed282SShri Abhyankar PetscErrorCode ierr; 2355ace3abfcSBarry Smith PetscBool iascii; 23562b4ed282SShri Abhyankar 23572b4ed282SShri Abhyankar PetscFunctionBegin; 23582b4ed282SShri Abhyankar ierr = PetscTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); 23592b4ed282SShri Abhyankar if (iascii) { 23600661309fSPeter Brune cstr = SNESLineSearchTypeName(snes->ls_type); 236178c4b9d3SShri Abhyankar if (snes->ops->solve == SNESSolveVI_SS) tstr = "Semismooth"; 23620a7c7af0SShri Abhyankar else if (snes->ops->solve == SNESSolveVI_RS) tstr = "Reduced Space"; 2363b350b9c9SBarry Smith else if (snes->ops->solve == SNESSolveVI_RSAUG) tstr = "Reduced space with augmented variables"; 236478c4b9d3SShri Abhyankar else tstr = "unknown"; 236578c4b9d3SShri Abhyankar ierr = PetscViewerASCIIPrintf(viewer," VI algorithm: %s\n",tstr);CHKERRQ(ierr); 23662b4ed282SShri Abhyankar ierr = PetscViewerASCIIPrintf(viewer," line search variant: %s\n",cstr);CHKERRQ(ierr); 2367*4839bfe8SBarry Smith ierr = PetscViewerASCIIPrintf(viewer," alpha=%g, maxstep=%g, minlambda=%g\n",(double)snes->ls_alpha,(double)snes->maxstep,(double)snes->steptol);CHKERRQ(ierr); 23682b4ed282SShri Abhyankar } 23692b4ed282SShri Abhyankar PetscFunctionReturn(0); 23702b4ed282SShri Abhyankar } 23712b4ed282SShri Abhyankar 23725559b345SBarry Smith #undef __FUNCT__ 23735559b345SBarry Smith #define __FUNCT__ "SNESVISetVariableBounds" 23745559b345SBarry Smith /*@ 23752b4ed282SShri Abhyankar SNESVISetVariableBounds - Sets the lower and upper bounds for the solution vector. xl <= x <= xu. 23762b4ed282SShri Abhyankar 23772b4ed282SShri Abhyankar Input Parameters: 23782b4ed282SShri Abhyankar . snes - the SNES context. 23792b4ed282SShri Abhyankar . xl - lower bound. 23802b4ed282SShri Abhyankar . xu - upper bound. 23812b4ed282SShri Abhyankar 23822b4ed282SShri Abhyankar Notes: 23832b4ed282SShri Abhyankar If this routine is not called then the lower and upper bounds are set to 238401f0b76bSBarry Smith SNES_VI_INF and SNES_VI_NINF respectively during SNESSetUp(). 238584c105d7SBarry Smith 23862bd2b0e6SSatish Balay Level: advanced 23872bd2b0e6SSatish Balay 23885559b345SBarry Smith @*/ 238969c03620SShri Abhyankar PetscErrorCode SNESVISetVariableBounds(SNES snes, Vec xl, Vec xu) 23902b4ed282SShri Abhyankar { 2391d923200aSJungho Lee SNES_VI *vi; 2392d923200aSJungho Lee PetscErrorCode ierr; 23936fd67740SBarry Smith const PetscScalar *xxl,*xxu; 23946fd67740SBarry Smith PetscInt i,n, cnt = 0; 23952b4ed282SShri Abhyankar 23962b4ed282SShri Abhyankar PetscFunctionBegin; 23972b4ed282SShri Abhyankar PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 23982b4ed282SShri Abhyankar PetscValidHeaderSpecific(xl,VEC_CLASSID,2); 23992b4ed282SShri Abhyankar PetscValidHeaderSpecific(xu,VEC_CLASSID,3); 24002b4ed282SShri Abhyankar if (!snes->vec_func) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Must call SNESSetFunction() first"); 24012b4ed282SShri 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); 24022b4ed282SShri 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); 2403d923200aSJungho Lee ierr = SNESSetType(snes,SNESVI);CHKERRQ(ierr); 2404d923200aSJungho Lee vi = (SNES_VI*)snes->data; 24052176524cSBarry Smith ierr = PetscObjectReference((PetscObject)xl);CHKERRQ(ierr); 24062176524cSBarry Smith ierr = PetscObjectReference((PetscObject)xu);CHKERRQ(ierr); 24072176524cSBarry Smith ierr = VecDestroy(&vi->xl);CHKERRQ(ierr); 24082176524cSBarry Smith ierr = VecDestroy(&vi->xu);CHKERRQ(ierr); 24092b4ed282SShri Abhyankar vi->xl = xl; 24102b4ed282SShri Abhyankar vi->xu = xu; 24116fd67740SBarry Smith ierr = VecGetLocalSize(xl,&n);CHKERRQ(ierr); 24126fd67740SBarry Smith ierr = VecGetArrayRead(xl,&xxl);CHKERRQ(ierr); 24136fd67740SBarry Smith ierr = VecGetArrayRead(xu,&xxu);CHKERRQ(ierr); 24146fd67740SBarry Smith for (i=0; i<n; i++) { 24156fd67740SBarry Smith cnt += ((xxl[i] != SNES_VI_NINF) || (xxu[i] != SNES_VI_INF)); 24166fd67740SBarry Smith } 24176fd67740SBarry Smith ierr = MPI_Allreduce(&cnt,&vi->ntruebounds,1,MPIU_INT,MPI_SUM,((PetscObject)snes)->comm);CHKERRQ(ierr); 24186fd67740SBarry Smith ierr = VecRestoreArrayRead(xl,&xxl);CHKERRQ(ierr); 24196fd67740SBarry Smith ierr = VecRestoreArrayRead(xu,&xxu);CHKERRQ(ierr); 24202b4ed282SShri Abhyankar PetscFunctionReturn(0); 24212b4ed282SShri Abhyankar } 2422693ddf92SShri Abhyankar 24232b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */ 24242b4ed282SShri Abhyankar /* 24252b4ed282SShri Abhyankar SNESSetFromOptions_VI - Sets various parameters for the SNESVI method. 24262b4ed282SShri Abhyankar 24272b4ed282SShri Abhyankar Input Parameter: 24282b4ed282SShri Abhyankar . snes - the SNES context 24292b4ed282SShri Abhyankar 24302b4ed282SShri Abhyankar Application Interface Routine: SNESSetFromOptions() 24312b4ed282SShri Abhyankar */ 24322b4ed282SShri Abhyankar #undef __FUNCT__ 24332b4ed282SShri Abhyankar #define __FUNCT__ "SNESSetFromOptions_VI" 24342b4ed282SShri Abhyankar static PetscErrorCode SNESSetFromOptions_VI(SNES snes) 24352b4ed282SShri Abhyankar { 24362b4ed282SShri Abhyankar SNES_VI *vi = (SNES_VI *)snes->data; 2437b350b9c9SBarry Smith const char *vies[] = {"ss","rs","rsaug"}; 24382b4ed282SShri Abhyankar PetscErrorCode ierr; 24392b4ed282SShri Abhyankar PetscInt indx; 24400661309fSPeter Brune PetscBool flg,flg2; 24412b4ed282SShri Abhyankar 24422b4ed282SShri Abhyankar PetscFunctionBegin; 24432b4ed282SShri Abhyankar ierr = PetscOptionsHead("SNES semismooth method options");CHKERRQ(ierr); 24449308c137SBarry Smith ierr = PetscOptionsBool("-snes_vi_monitor","Monitor all non-active variables","None",PETSC_FALSE,&flg,0);CHKERRQ(ierr); 24459308c137SBarry Smith if (flg) { 24469308c137SBarry Smith ierr = SNESMonitorSet(snes,SNESMonitorVI,0,0);CHKERRQ(ierr); 24479308c137SBarry Smith } 24482b4ed282SShri Abhyankar ierr = PetscOptionsReal("-snes_vi_const_tol","constraint tolerance","None",vi->const_tol,&vi->const_tol,0);CHKERRQ(ierr); 24495b071b1aSBarry Smith ierr = PetscOptionsEList("-snes_vi_type","Semismooth algorithm used","",vies,3,"rs",&indx,&flg2);CHKERRQ(ierr); 245069c03620SShri Abhyankar if (flg2) { 245169c03620SShri Abhyankar switch (indx) { 245269c03620SShri Abhyankar case 0: 245369c03620SShri Abhyankar snes->ops->solve = SNESSolveVI_SS; 245469c03620SShri Abhyankar break; 245569c03620SShri Abhyankar case 1: 2456d950fb63SShri Abhyankar snes->ops->solve = SNESSolveVI_RS; 2457d950fb63SShri Abhyankar break; 24582f63a38cSShri Abhyankar case 2: 2459b350b9c9SBarry Smith snes->ops->solve = SNESSolveVI_RSAUG; 246069c03620SShri Abhyankar } 246169c03620SShri Abhyankar } 2462e6337399SBarry Smith ierr = PetscOptionsBool("-snes_vi_ignore_function_sign","Ignore the sign of function for active constraints","None",vi->ignorefunctionsign,&vi->ignorefunctionsign,PETSC_NULL);CHKERRQ(ierr); 24632b4ed282SShri Abhyankar ierr = PetscOptionsTail();CHKERRQ(ierr); 24642b4ed282SShri Abhyankar PetscFunctionReturn(0); 24652b4ed282SShri Abhyankar } 246692c02d66SPeter Brune 246792c02d66SPeter Brune EXTERN_C_BEGIN 246892c02d66SPeter Brune #undef __FUNCT__ 246992c02d66SPeter Brune #define __FUNCT__ "SNESLineSearchSetType_VI" 247092c02d66SPeter Brune PetscErrorCode SNESLineSearchSetType_VI(SNES snes, SNESLineSearchType type) 247192c02d66SPeter Brune { 247292c02d66SPeter Brune PetscErrorCode ierr; 247392c02d66SPeter Brune PetscFunctionBegin; 247492c02d66SPeter Brune 247592c02d66SPeter Brune switch (type) { 247692c02d66SPeter Brune case SNES_LS_BASIC: 247792c02d66SPeter Brune ierr = SNESLineSearchSet(snes,SNESLineSearchNo_VI,PETSC_NULL);CHKERRQ(ierr); 247892c02d66SPeter Brune break; 247992c02d66SPeter Brune case SNES_LS_BASIC_NONORMS: 248092c02d66SPeter Brune ierr = SNESLineSearchSet(snes,SNESLineSearchNoNorms_VI,PETSC_NULL);CHKERRQ(ierr); 248192c02d66SPeter Brune break; 248292c02d66SPeter Brune case SNES_LS_QUADRATIC: 248392c02d66SPeter Brune ierr = SNESLineSearchSet(snes,SNESLineSearchQuadratic_VI,PETSC_NULL);CHKERRQ(ierr); 248492c02d66SPeter Brune break; 248592c02d66SPeter Brune case SNES_LS_CUBIC: 248692c02d66SPeter Brune ierr = SNESLineSearchSet(snes,SNESLineSearchCubic_VI,PETSC_NULL);CHKERRQ(ierr); 248792c02d66SPeter Brune break; 248892c02d66SPeter Brune default: 248992c02d66SPeter Brune SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP,"Unknown line search type"); 249092c02d66SPeter Brune break; 249192c02d66SPeter Brune } 249292c02d66SPeter Brune snes->ls_type = type; 249392c02d66SPeter Brune PetscFunctionReturn(0); 249492c02d66SPeter Brune } 249592c02d66SPeter Brune EXTERN_C_END 249692c02d66SPeter Brune 24972b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */ 24982b4ed282SShri Abhyankar /*MC 24998b4c83edSBarry Smith SNESVI - Various solvers for variational inequalities based on Newton's method 25002b4ed282SShri Abhyankar 25012b4ed282SShri Abhyankar Options Database: 25028b4c83edSBarry 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 25038b4c83edSBarry Smith additional variables that enforce the constraints 25048b4c83edSBarry Smith - -snes_vi_monitor - prints the number of active constraints at each iteration. 25052b4ed282SShri Abhyankar 25062b4ed282SShri Abhyankar 25072b4ed282SShri Abhyankar Level: beginner 25082b4ed282SShri Abhyankar 25092b4ed282SShri Abhyankar .seealso: SNESCreate(), SNES, SNESSetType(), SNESTR, SNESLineSearchSet(), 25102b4ed282SShri Abhyankar SNESLineSearchSetPostCheck(), SNESLineSearchNo(), SNESLineSearchCubic(), SNESLineSearchQuadratic(), 25112b4ed282SShri Abhyankar SNESLineSearchSet(), SNESLineSearchNoNorms(), SNESLineSearchSetPreCheck(), SNESLineSearchSetParams(), SNESLineSearchGetParams() 25122b4ed282SShri Abhyankar 25132b4ed282SShri Abhyankar M*/ 25142b4ed282SShri Abhyankar EXTERN_C_BEGIN 25152b4ed282SShri Abhyankar #undef __FUNCT__ 25162b4ed282SShri Abhyankar #define __FUNCT__ "SNESCreate_VI" 25177087cfbeSBarry Smith PetscErrorCode SNESCreate_VI(SNES snes) 25182b4ed282SShri Abhyankar { 25192b4ed282SShri Abhyankar PetscErrorCode ierr; 25202b4ed282SShri Abhyankar SNES_VI *vi; 25212b4ed282SShri Abhyankar 25222b4ed282SShri Abhyankar PetscFunctionBegin; 25232176524cSBarry Smith snes->ops->reset = SNESReset_VI; 25242b4ed282SShri Abhyankar snes->ops->setup = SNESSetUp_VI; 2525edafb9efSBarry Smith snes->ops->solve = SNESSolveVI_RS; 25262b4ed282SShri Abhyankar snes->ops->destroy = SNESDestroy_VI; 25272b4ed282SShri Abhyankar snes->ops->setfromoptions = SNESSetFromOptions_VI; 25282b4ed282SShri Abhyankar snes->ops->view = SNESView_VI; 25292b4ed282SShri Abhyankar snes->ops->converged = SNESDefaultConverged_VI; 25302b4ed282SShri Abhyankar 253142f4f86dSBarry Smith snes->usesksp = PETSC_TRUE; 253242f4f86dSBarry Smith snes->usespc = PETSC_FALSE; 253342f4f86dSBarry Smith 25342b4ed282SShri Abhyankar ierr = PetscNewLog(snes,SNES_VI,&vi);CHKERRQ(ierr); 25352b4ed282SShri Abhyankar snes->data = (void*)vi; 25360661309fSPeter Brune snes->ls_alpha = 1.e-4; 25370661309fSPeter Brune snes->maxstep = 1.e8; 25380661309fSPeter Brune snes->steptol = 1.e-12; 25392b4ed282SShri Abhyankar vi->const_tol = 2.2204460492503131e-16; 25402f63a38cSShri Abhyankar vi->checkredundancy = PETSC_NULL; 254192c02d66SPeter Brune 254292c02d66SPeter Brune ierr = PetscObjectComposeFunctionDynamic((PetscObject)snes,"SNESLineSearchSetType_C","SNESLineSearchSetType_VI",SNESLineSearchSetType_VI);CHKERRQ(ierr); 254392c02d66SPeter Brune ierr = SNESLineSearchSetType(snes, SNES_LS_CUBIC);CHKERRQ(ierr); 254492c02d66SPeter Brune 25452b4ed282SShri Abhyankar PetscFunctionReturn(0); 25462b4ed282SShri Abhyankar } 25472b4ed282SShri Abhyankar EXTERN_C_END 2548ed70e96aSJungho Lee 2549ed70e96aSJungho Lee #undef __FUNCT__ 2550ed70e96aSJungho Lee #define __FUNCT__ "SNESVIGetInactiveSet" 2551ed70e96aSJungho Lee /* 2552ed70e96aSJungho Lee SNESVIGetInactiveSet - Gets the global indices for the inactive set variables (these correspond to the degrees of freedom the linear 2553ed70e96aSJungho Lee system is solved on) 2554ed70e96aSJungho Lee 2555ed70e96aSJungho Lee Input parameter 2556ed70e96aSJungho Lee . snes - the SNES context 2557ed70e96aSJungho Lee 2558ed70e96aSJungho Lee Output parameter 2559ed70e96aSJungho Lee . ISact - active set index set 2560ed70e96aSJungho Lee 2561ed70e96aSJungho Lee */ 2562ed70e96aSJungho Lee PetscErrorCode SNESVIGetInactiveSet(SNES snes,IS* inact) 2563ed70e96aSJungho Lee { 2564ed70e96aSJungho Lee SNES_VI *vi = (SNES_VI*)snes->data; 2565ed70e96aSJungho Lee PetscFunctionBegin; 2566ed70e96aSJungho Lee *inact = vi->IS_inact_prev; 2567ed70e96aSJungho Lee PetscFunctionReturn(0); 2568ed70e96aSJungho Lee } 2569