12b4ed282SShri Abhyankar 2c6db04a5SJed Brown #include <../src/snes/impls/vi/viimpl.h> /*I "petscsnes.h" I*/ 3c6db04a5SJed Brown #include <../include/private/kspimpl.h> 4c6db04a5SJed Brown #include <../include/private/matimpl.h> 5d0af7cd3SBarry Smith #include <../include/private/dmimpl.h> 6d0af7cd3SBarry Smith 7d0af7cd3SBarry Smith #undef __FUNCT__ 82176524cSBarry Smith #define __FUNCT__ "SNESVISetComputeVariableBounds" 92176524cSBarry Smith /*@C 102176524cSBarry Smith SNESVISetComputeVariableBounds - Sets a function that is called to compute the variable bounds 112176524cSBarry Smith 122176524cSBarry Smith Input parameter 132176524cSBarry Smith + snes - the SNES context 142176524cSBarry Smith - compute - computes the bounds 152176524cSBarry Smith 162176524cSBarry Smith 17aab9d709SJed Brown @*/ 1877cdaf69SJed Brown PetscErrorCode SNESVISetComputeVariableBounds(SNES snes, PetscErrorCode (*compute)(SNES,Vec,Vec)) 192176524cSBarry Smith { 202176524cSBarry Smith PetscErrorCode ierr; 212176524cSBarry Smith SNES_VI *vi; 222176524cSBarry Smith 232176524cSBarry Smith PetscFunctionBegin; 242176524cSBarry Smith ierr = SNESSetType(snes,SNESVI);CHKERRQ(ierr); 252176524cSBarry Smith vi = (SNES_VI*)snes->data; 262176524cSBarry Smith vi->computevariablebounds = compute; 272176524cSBarry Smith PetscFunctionReturn(0); 282176524cSBarry Smith } 292176524cSBarry Smith 302176524cSBarry Smith 312176524cSBarry Smith #undef __FUNCT__ 32ed70e96aSJungho Lee #define __FUNCT__ "SNESVIComputeInactiveSetIS" 33d0af7cd3SBarry Smith /* 34ed70e96aSJungho Lee SNESVIComputeInactiveSetIS - Gets the global indices for the bogus inactive set variables 35d0af7cd3SBarry Smith 36d0af7cd3SBarry Smith Input parameter 37d0af7cd3SBarry Smith . snes - the SNES context 38d0af7cd3SBarry Smith . X - the snes solution vector 39d0af7cd3SBarry Smith 40d0af7cd3SBarry Smith Output parameter 41d0af7cd3SBarry Smith . ISact - active set index set 42d0af7cd3SBarry Smith 43d0af7cd3SBarry Smith */ 44ed70e96aSJungho Lee PetscErrorCode SNESVIComputeInactiveSetIS(Vec upper,Vec lower,Vec X,Vec F,IS* inact) 45d0af7cd3SBarry Smith { 46d0af7cd3SBarry Smith PetscErrorCode ierr; 47d0af7cd3SBarry Smith const PetscScalar *x,*xl,*xu,*f; 48d0af7cd3SBarry Smith PetscInt *idx_act,i,nlocal,nloc_isact=0,ilow,ihigh,i1=0; 49d0af7cd3SBarry Smith 50d0af7cd3SBarry Smith PetscFunctionBegin; 51d0af7cd3SBarry Smith ierr = VecGetLocalSize(X,&nlocal);CHKERRQ(ierr); 52d0af7cd3SBarry Smith ierr = VecGetOwnershipRange(X,&ilow,&ihigh);CHKERRQ(ierr); 53d0af7cd3SBarry Smith ierr = VecGetArrayRead(X,&x);CHKERRQ(ierr); 54d0af7cd3SBarry Smith ierr = VecGetArrayRead(lower,&xl);CHKERRQ(ierr); 55d0af7cd3SBarry Smith ierr = VecGetArrayRead(upper,&xu);CHKERRQ(ierr); 56d0af7cd3SBarry Smith ierr = VecGetArrayRead(F,&f);CHKERRQ(ierr); 57d0af7cd3SBarry Smith /* Compute inactive set size */ 58d0af7cd3SBarry Smith for (i=0; i < nlocal;i++) { 59d0af7cd3SBarry Smith if (((PetscRealPart(x[i]) > PetscRealPart(xl[i]) + 1.e-8 || (PetscRealPart(f[i]) < 0.0)) && ((PetscRealPart(x[i]) < PetscRealPart(xu[i]) - 1.e-8) || PetscRealPart(f[i]) > 0.0))) nloc_isact++; 60d0af7cd3SBarry Smith } 61d0af7cd3SBarry Smith 62d0af7cd3SBarry Smith ierr = PetscMalloc(nloc_isact*sizeof(PetscInt),&idx_act);CHKERRQ(ierr); 63d0af7cd3SBarry Smith 64d0af7cd3SBarry Smith /* Set inactive set indices */ 65d0af7cd3SBarry Smith for(i=0; i < nlocal; i++) { 66d0af7cd3SBarry Smith if (((PetscRealPart(x[i]) > PetscRealPart(xl[i]) + 1.e-8 || (PetscRealPart(f[i]) < 0.0)) && ((PetscRealPart(x[i]) < PetscRealPart(xu[i]) - 1.e-8) || PetscRealPart(f[i]) > 0.0))) idx_act[i1++] = ilow+i; 67d0af7cd3SBarry Smith } 68d0af7cd3SBarry Smith 69d0af7cd3SBarry Smith /* Create inactive set IS */ 70d0af7cd3SBarry Smith ierr = ISCreateGeneral(((PetscObject)upper)->comm,nloc_isact,idx_act,PETSC_OWN_POINTER,inact);CHKERRQ(ierr); 71d0af7cd3SBarry Smith 72d0af7cd3SBarry Smith ierr = VecRestoreArrayRead(X,&x);CHKERRQ(ierr); 73d0af7cd3SBarry Smith ierr = VecRestoreArrayRead(lower,&xl);CHKERRQ(ierr); 74d0af7cd3SBarry Smith ierr = VecRestoreArrayRead(upper,&xu);CHKERRQ(ierr); 75d0af7cd3SBarry Smith ierr = VecRestoreArrayRead(F,&f);CHKERRQ(ierr); 76d0af7cd3SBarry Smith PetscFunctionReturn(0); 77d0af7cd3SBarry Smith } 78d0af7cd3SBarry Smith 793c0c59f3SBarry Smith /* 803c0c59f3SBarry Smith Provides a wrapper to a DM to allow it to be used to generated the interpolation/restriction from the DM for the smaller matrices and vectors 813c0c59f3SBarry Smith defined by the reduced space method. 823c0c59f3SBarry Smith 833c0c59f3SBarry Smith Simple calls the regular DM interpolation and restricts it to operation on the variables not associated with active constraints. 843c0c59f3SBarry Smith 85ed70e96aSJungho Lee <*/ 863c0c59f3SBarry Smith typedef struct { 873c0c59f3SBarry Smith PetscInt n; /* size of vectors in the reduced DM space */ 883c0c59f3SBarry Smith IS inactive; 893c0c59f3SBarry Smith PetscErrorCode (*getinterpolation)(DM,DM,Mat*,Vec*); /* DM's original routines */ 903c0c59f3SBarry Smith PetscErrorCode (*coarsen)(DM, MPI_Comm, DM*); 913c0c59f3SBarry Smith PetscErrorCode (*createglobalvector)(DM,Vec*); 924c661befSBarry Smith DM dm; /* when destroying this object we need to reset the above function into the base DM */ 933c0c59f3SBarry Smith } DM_SNESVI; 943c0c59f3SBarry Smith 95d0af7cd3SBarry Smith #undef __FUNCT__ 964dcab191SBarry Smith #define __FUNCT__ "DMCreateGlobalVector_SNESVI" 974dcab191SBarry Smith /* 984dcab191SBarry Smith DMCreateGlobalVector_SNESVI - Creates global vector of the size of the reduced space 994dcab191SBarry Smith 1004dcab191SBarry Smith */ 1014dcab191SBarry Smith PetscErrorCode DMCreateGlobalVector_SNESVI(DM dm,Vec *vec) 1024dcab191SBarry Smith { 1034dcab191SBarry Smith PetscErrorCode ierr; 1044dcab191SBarry Smith PetscContainer isnes; 1053c0c59f3SBarry Smith DM_SNESVI *dmsnesvi; 1064dcab191SBarry Smith 1074dcab191SBarry Smith PetscFunctionBegin; 1084dcab191SBarry Smith ierr = PetscObjectQuery((PetscObject)dm,"VI",(PetscObject *)&isnes);CHKERRQ(ierr); 1094dcab191SBarry Smith if (!isnes) SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_PLIB,"Composed SNES is missing"); 1104dcab191SBarry Smith ierr = PetscContainerGetPointer(isnes,(void**)&dmsnesvi);CHKERRQ(ierr); 1114dcab191SBarry Smith ierr = VecCreateMPI(((PetscObject)dm)->comm,dmsnesvi->n,PETSC_DETERMINE,vec);CHKERRQ(ierr); 1124dcab191SBarry Smith PetscFunctionReturn(0); 1134dcab191SBarry Smith } 1144dcab191SBarry Smith 1154dcab191SBarry Smith #undef __FUNCT__ 116d0af7cd3SBarry Smith #define __FUNCT__ "DMGetInterpolation_SNESVI" 117d0af7cd3SBarry Smith /* 118d0af7cd3SBarry Smith DMGetInterpolation_SNESVI - Modifieds the interpolation obtained from the DM by removing all rows and columns associated with active constraints. 119d0af7cd3SBarry Smith 120d0af7cd3SBarry Smith */ 121d0af7cd3SBarry Smith PetscErrorCode DMGetInterpolation_SNESVI(DM dm1,DM dm2,Mat *mat,Vec *vec) 122d0af7cd3SBarry Smith { 123d0af7cd3SBarry Smith PetscErrorCode ierr; 124d0af7cd3SBarry Smith PetscContainer isnes; 1253c0c59f3SBarry Smith DM_SNESVI *dmsnesvi1,*dmsnesvi2; 126d0af7cd3SBarry Smith Mat interp; 127d0af7cd3SBarry Smith 128d0af7cd3SBarry Smith PetscFunctionBegin; 129d0af7cd3SBarry Smith ierr = PetscObjectQuery((PetscObject)dm1,"VI",(PetscObject *)&isnes);CHKERRQ(ierr); 1304c661befSBarry Smith if (!isnes) SETERRQ(((PetscObject)dm1)->comm,PETSC_ERR_PLIB,"Composed VI data structure is missing"); 131d0af7cd3SBarry Smith ierr = PetscContainerGetPointer(isnes,(void**)&dmsnesvi1);CHKERRQ(ierr); 132d0af7cd3SBarry Smith ierr = PetscObjectQuery((PetscObject)dm2,"VI",(PetscObject *)&isnes);CHKERRQ(ierr); 1334c661befSBarry Smith if (!isnes) SETERRQ(((PetscObject)dm2)->comm,PETSC_ERR_PLIB,"Composed VI data structure is missing"); 134d0af7cd3SBarry Smith ierr = PetscContainerGetPointer(isnes,(void**)&dmsnesvi2);CHKERRQ(ierr); 135d0af7cd3SBarry Smith 136d0af7cd3SBarry Smith ierr = (*dmsnesvi1->getinterpolation)(dm1,dm2,&interp,PETSC_NULL);CHKERRQ(ierr); 1374dcab191SBarry Smith ierr = MatGetSubMatrix(interp,dmsnesvi2->inactive,dmsnesvi1->inactive,MAT_INITIAL_MATRIX,mat);CHKERRQ(ierr); 138d0af7cd3SBarry Smith ierr = MatDestroy(&interp);CHKERRQ(ierr); 13900ac8be1SBarry Smith *vec = 0; 140d0af7cd3SBarry Smith PetscFunctionReturn(0); 141d0af7cd3SBarry Smith } 142d0af7cd3SBarry Smith 1439ce20c35SJungho Lee extern PetscErrorCode DMSetVI(DM,IS); 144d0af7cd3SBarry Smith 145d0af7cd3SBarry Smith #undef __FUNCT__ 146d0af7cd3SBarry Smith #define __FUNCT__ "DMCoarsen_SNESVI" 147d0af7cd3SBarry Smith /* 148d0af7cd3SBarry Smith DMCoarsen_SNESVI - Computes the regular coarsened DM then computes additional information about its inactive set 149d0af7cd3SBarry Smith 150d0af7cd3SBarry Smith */ 151d0af7cd3SBarry Smith PetscErrorCode DMCoarsen_SNESVI(DM dm1,MPI_Comm comm,DM *dm2) 152d0af7cd3SBarry Smith { 153d0af7cd3SBarry Smith PetscErrorCode ierr; 154d0af7cd3SBarry Smith PetscContainer isnes; 1553c0c59f3SBarry Smith DM_SNESVI *dmsnesvi1; 1569ce20c35SJungho Lee Vec finemarked,coarsemarked; 157d0af7cd3SBarry Smith IS inactive; 158d0af7cd3SBarry Smith VecScatter inject; 1599ce20c35SJungho Lee const PetscInt *index; 1609ce20c35SJungho Lee PetscInt n,k,cnt = 0,rstart,*coarseindex; 1619ce20c35SJungho Lee PetscScalar *marked; 162d0af7cd3SBarry Smith 163d0af7cd3SBarry Smith PetscFunctionBegin; 164d0af7cd3SBarry Smith ierr = PetscObjectQuery((PetscObject)dm1,"VI",(PetscObject *)&isnes);CHKERRQ(ierr); 1654c661befSBarry Smith if (!isnes) SETERRQ(((PetscObject)dm1)->comm,PETSC_ERR_PLIB,"Composed VI data structure is missing"); 166d0af7cd3SBarry Smith ierr = PetscContainerGetPointer(isnes,(void**)&dmsnesvi1);CHKERRQ(ierr); 167d0af7cd3SBarry Smith 168298cc208SBarry Smith /* get the original coarsen */ 169d0af7cd3SBarry Smith ierr = (*dmsnesvi1->coarsen)(dm1,comm,dm2);CHKERRQ(ierr); 170298cc208SBarry Smith 1713c0c59f3SBarry Smith /* not sure why this extra reference is needed, but without the dm2 disappears too early */ 1723c0c59f3SBarry Smith ierr = PetscObjectReference((PetscObject)*dm2);CHKERRQ(ierr); 1733c0c59f3SBarry Smith 174298cc208SBarry Smith /* need to set back global vectors in order to use the original injection */ 175298cc208SBarry Smith ierr = DMClearGlobalVectors(dm1);CHKERRQ(ierr); 176298cc208SBarry Smith dm1->ops->createglobalvector = dmsnesvi1->createglobalvector; 1779ce20c35SJungho Lee ierr = DMCreateGlobalVector(dm1,&finemarked);CHKERRQ(ierr); 1789ce20c35SJungho Lee ierr = DMCreateGlobalVector(*dm2,&coarsemarked);CHKERRQ(ierr); 1799ce20c35SJungho Lee 1809ce20c35SJungho Lee /* 1819ce20c35SJungho Lee fill finemarked with locations of inactive points 1829ce20c35SJungho Lee */ 1839ce20c35SJungho Lee ierr = ISGetIndices(dmsnesvi1->inactive,&index);CHKERRQ(ierr); 1849ce20c35SJungho Lee ierr = ISGetLocalSize(dmsnesvi1->inactive,&n);CHKERRQ(ierr); 1859ce20c35SJungho Lee ierr = VecSet(finemarked,0.0);CHKERRQ(ierr); 1869ce20c35SJungho Lee for (k=0;k<n;k++){ 1879ce20c35SJungho Lee ierr = VecSetValue(finemarked,index[k],1.0,INSERT_VALUES);CHKERRQ(ierr); 1889ce20c35SJungho Lee } 1899ce20c35SJungho Lee ierr = VecAssemblyBegin(finemarked);CHKERRQ(ierr); 1909ce20c35SJungho Lee ierr = VecAssemblyEnd(finemarked);CHKERRQ(ierr); 1919ce20c35SJungho Lee 192d0af7cd3SBarry Smith ierr = DMGetInjection(*dm2,dm1,&inject);CHKERRQ(ierr); 1939ce20c35SJungho Lee ierr = VecScatterBegin(inject,finemarked,coarsemarked,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1949ce20c35SJungho Lee ierr = VecScatterEnd(inject,finemarked,coarsemarked,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 195d0af7cd3SBarry Smith ierr = VecScatterDestroy(&inject);CHKERRQ(ierr); 1969ce20c35SJungho Lee 1979ce20c35SJungho Lee /* 1989ce20c35SJungho Lee create index set list of coarse inactive points from coarsemarked 1999ce20c35SJungho Lee */ 2009ce20c35SJungho Lee ierr = VecGetLocalSize(coarsemarked,&n);CHKERRQ(ierr); 2019ce20c35SJungho Lee ierr = VecGetOwnershipRange(coarsemarked,&rstart,PETSC_NULL);CHKERRQ(ierr); 2029ce20c35SJungho Lee ierr = VecGetArray(coarsemarked,&marked);CHKERRQ(ierr); 2039ce20c35SJungho Lee for (k=0; k<n; k++) { 204ff207688SJed Brown if (marked[k] != 0.0) cnt++; 2059ce20c35SJungho Lee } 2069ce20c35SJungho Lee ierr = PetscMalloc(cnt*sizeof(PetscInt),&coarseindex);CHKERRQ(ierr); 2079ce20c35SJungho Lee cnt = 0; 2089ce20c35SJungho Lee for (k=0; k<n; k++) { 209ff207688SJed Brown if (marked[k] != 0.0) coarseindex[cnt++] = k + rstart; 2109ce20c35SJungho Lee } 2119ce20c35SJungho Lee ierr = VecRestoreArray(coarsemarked,&marked);CHKERRQ(ierr); 2129ce20c35SJungho Lee ierr = ISCreateGeneral(PETSC_COMM_WORLD,cnt,coarseindex,PETSC_OWN_POINTER,&inactive);CHKERRQ(ierr); 2139ce20c35SJungho Lee 214298cc208SBarry Smith ierr = DMClearGlobalVectors(dm1);CHKERRQ(ierr); 215298cc208SBarry Smith dm1->ops->createglobalvector = DMCreateGlobalVector_SNESVI; 2169ce20c35SJungho Lee ierr = DMSetVI(*dm2,inactive);CHKERRQ(ierr); 2179ce20c35SJungho Lee 2189ce20c35SJungho Lee ierr = VecDestroy(&finemarked);CHKERRQ(ierr); 2199ce20c35SJungho Lee ierr = VecDestroy(&coarsemarked);CHKERRQ(ierr); 2203c0c59f3SBarry Smith ierr = ISDestroy(&inactive);CHKERRQ(ierr); 221d0af7cd3SBarry Smith PetscFunctionReturn(0); 222d0af7cd3SBarry Smith } 223d0af7cd3SBarry Smith 224d0af7cd3SBarry Smith #undef __FUNCT__ 2253c0c59f3SBarry Smith #define __FUNCT__ "DMDestroy_SNESVI" 2263c0c59f3SBarry Smith PetscErrorCode DMDestroy_SNESVI(DM_SNESVI *dmsnesvi) 227d0af7cd3SBarry Smith { 228d0af7cd3SBarry Smith PetscErrorCode ierr; 229d0af7cd3SBarry Smith 230d0af7cd3SBarry Smith PetscFunctionBegin; 2314c661befSBarry Smith /* reset the base methods in the DM object that were changed when the DM_SNESVI was reset */ 2324c661befSBarry Smith dmsnesvi->dm->ops->getinterpolation = dmsnesvi->getinterpolation; 2334c661befSBarry Smith dmsnesvi->dm->ops->coarsen = dmsnesvi->coarsen; 2344c661befSBarry Smith dmsnesvi->dm->ops->createglobalvector = dmsnesvi->createglobalvector; 23500ac8be1SBarry Smith /* need to clear out this vectors because some of them may not have a reference to the DM 23600ac8be1SBarry Smith but they are counted as having references to the DM in DMDestroy() */ 23700ac8be1SBarry Smith ierr = DMClearGlobalVectors(dmsnesvi->dm);CHKERRQ(ierr); 2384c661befSBarry Smith 239d0af7cd3SBarry Smith ierr = ISDestroy(&dmsnesvi->inactive);CHKERRQ(ierr); 240d0af7cd3SBarry Smith ierr = PetscFree(dmsnesvi);CHKERRQ(ierr); 241d0af7cd3SBarry Smith PetscFunctionReturn(0); 242d0af7cd3SBarry Smith } 243d0af7cd3SBarry Smith 244d0af7cd3SBarry Smith #undef __FUNCT__ 245d0af7cd3SBarry Smith #define __FUNCT__ "DMSetVI" 246d0af7cd3SBarry Smith /* 247d0af7cd3SBarry Smith DMSetVI - Marks a DM as associated with a VI problem. This causes the interpolation/restriction operators to 248d0af7cd3SBarry Smith be restricted to only those variables NOT associated with active constraints. 249d0af7cd3SBarry Smith 250d0af7cd3SBarry Smith */ 2519ce20c35SJungho Lee PetscErrorCode DMSetVI(DM dm,IS inactive) 252d0af7cd3SBarry Smith { 253d0af7cd3SBarry Smith PetscErrorCode ierr; 254d0af7cd3SBarry Smith PetscContainer isnes; 2553c0c59f3SBarry Smith DM_SNESVI *dmsnesvi; 256d0af7cd3SBarry Smith 257d0af7cd3SBarry Smith PetscFunctionBegin; 2584dcab191SBarry Smith if (!dm) PetscFunctionReturn(0); 2591c0a9e84SBarry Smith 260d0af7cd3SBarry Smith ierr = PetscObjectReference((PetscObject)inactive);CHKERRQ(ierr); 261d0af7cd3SBarry Smith 262d0af7cd3SBarry Smith ierr = PetscObjectQuery((PetscObject)dm,"VI",(PetscObject *)&isnes);CHKERRQ(ierr); 263d0af7cd3SBarry Smith if (!isnes) { 264d0af7cd3SBarry Smith ierr = PetscContainerCreate(((PetscObject)dm)->comm,&isnes);CHKERRQ(ierr); 2653c0c59f3SBarry Smith ierr = PetscContainerSetUserDestroy(isnes,(PetscErrorCode (*)(void*))DMDestroy_SNESVI);CHKERRQ(ierr); 2663c0c59f3SBarry Smith ierr = PetscNew(DM_SNESVI,&dmsnesvi);CHKERRQ(ierr); 267d0af7cd3SBarry Smith ierr = PetscContainerSetPointer(isnes,(void*)dmsnesvi);CHKERRQ(ierr); 268d0af7cd3SBarry Smith ierr = PetscObjectCompose((PetscObject)dm,"VI",(PetscObject)isnes);CHKERRQ(ierr); 2693c0c59f3SBarry Smith ierr = PetscContainerDestroy(&isnes);CHKERRQ(ierr); 270d0af7cd3SBarry Smith dmsnesvi->getinterpolation = dm->ops->getinterpolation; 271d0af7cd3SBarry Smith dm->ops->getinterpolation = DMGetInterpolation_SNESVI; 272d0af7cd3SBarry Smith dmsnesvi->coarsen = dm->ops->coarsen; 273d0af7cd3SBarry Smith dm->ops->coarsen = DMCoarsen_SNESVI; 274298cc208SBarry Smith dmsnesvi->createglobalvector = dm->ops->createglobalvector; 2754dcab191SBarry Smith dm->ops->createglobalvector = DMCreateGlobalVector_SNESVI; 276d0af7cd3SBarry Smith } else { 277d0af7cd3SBarry Smith ierr = PetscContainerGetPointer(isnes,(void**)&dmsnesvi);CHKERRQ(ierr); 278d0af7cd3SBarry Smith ierr = ISDestroy(&dmsnesvi->inactive);CHKERRQ(ierr); 279d0af7cd3SBarry Smith } 2804dcab191SBarry Smith ierr = DMClearGlobalVectors(dm);CHKERRQ(ierr); 2814dcab191SBarry Smith ierr = ISGetLocalSize(inactive,&dmsnesvi->n);CHKERRQ(ierr); 282d0af7cd3SBarry Smith dmsnesvi->inactive = inactive; 2831a223a97SBarry Smith dmsnesvi->dm = dm; 284d0af7cd3SBarry Smith PetscFunctionReturn(0); 285d0af7cd3SBarry Smith } 286d0af7cd3SBarry Smith 2874c661befSBarry Smith #undef __FUNCT__ 2884c661befSBarry Smith #define __FUNCT__ "DMDestroyVI" 2894c661befSBarry Smith /* 2904c661befSBarry Smith DMDestroyVI - Frees the DM_SNESVI object contained in the DM 2914c661befSBarry Smith - also resets the function pointers in the DM for getinterpolation() etc to use the original DM 2924c661befSBarry Smith */ 2934c661befSBarry Smith PetscErrorCode DMDestroyVI(DM dm) 2944c661befSBarry Smith { 2954c661befSBarry Smith PetscErrorCode ierr; 2964c661befSBarry Smith 2974c661befSBarry Smith PetscFunctionBegin; 2984c661befSBarry Smith if (!dm) PetscFunctionReturn(0); 2994c661befSBarry Smith ierr = PetscObjectCompose((PetscObject)dm,"VI",(PetscObject)PETSC_NULL);CHKERRQ(ierr); 3004c661befSBarry Smith PetscFunctionReturn(0); 3014c661befSBarry Smith } 3024c661befSBarry Smith 3033c0c59f3SBarry Smith /* --------------------------------------------------------------------------------------------------------*/ 3042b4ed282SShri Abhyankar 3059308c137SBarry Smith #undef __FUNCT__ 3069308c137SBarry Smith #define __FUNCT__ "SNESMonitorVI" 3077087cfbeSBarry Smith PetscErrorCode SNESMonitorVI(SNES snes,PetscInt its,PetscReal fgnorm,void *dummy) 3089308c137SBarry Smith { 3099308c137SBarry Smith PetscErrorCode ierr; 3109308c137SBarry Smith SNES_VI *vi = (SNES_VI*)snes->data; 311649052a6SBarry Smith PetscViewer viewer = dummy ? (PetscViewer) dummy : PETSC_VIEWER_STDOUT_(((PetscObject)snes)->comm); 3129308c137SBarry Smith const PetscScalar *x,*xl,*xu,*f; 313*6fd67740SBarry Smith PetscInt i,n,act[2] = {0,0},fact[2],N; 3149308c137SBarry Smith PetscReal rnorm,fnorm; 3159308c137SBarry Smith 3169308c137SBarry Smith PetscFunctionBegin; 3179308c137SBarry Smith ierr = VecGetLocalSize(snes->vec_sol,&n);CHKERRQ(ierr); 318*6fd67740SBarry Smith ierr = VecGetSize(snes->vec_sol,&N);CHKERRQ(ierr); 3199308c137SBarry Smith ierr = VecGetArrayRead(vi->xl,&xl);CHKERRQ(ierr); 3209308c137SBarry Smith ierr = VecGetArrayRead(vi->xu,&xu);CHKERRQ(ierr); 3219308c137SBarry Smith ierr = VecGetArrayRead(snes->vec_sol,&x);CHKERRQ(ierr); 3223f731af5SBarry Smith ierr = VecGetArrayRead(snes->vec_func,&f);CHKERRQ(ierr); 3239308c137SBarry Smith 3249308c137SBarry Smith rnorm = 0.0; 3259308c137SBarry Smith for (i=0; i<n; i++) { 32610f5ae6bSBarry Smith if (((PetscRealPart(x[i]) > PetscRealPart(xl[i]) + 1.e-8 || (PetscRealPart(f[i]) < 0.0)) && ((PetscRealPart(x[i]) < PetscRealPart(xu[i]) - 1.e-8) || PetscRealPart(f[i]) > 0.0))) rnorm += PetscRealPart(PetscConj(f[i])*f[i]); 327e400df7aSBarry Smith else if (PetscRealPart(x[i]) <= PetscRealPart(xl[i]) + 1.e-8 && PetscRealPart(f[i]) >= 0.0) act[0]++; 328e400df7aSBarry Smith else if (PetscRealPart(x[i]) >= PetscRealPart(xu[i]) - 1.e-8 && PetscRealPart(f[i]) <= 0.0) act[1]++; 329e400df7aSBarry Smith else SETERRQ(((PetscObject)snes)->comm,PETSC_ERR_PLIB,"Can never get here"); 3309308c137SBarry Smith } 3313f731af5SBarry Smith ierr = VecRestoreArrayRead(snes->vec_func,&f);CHKERRQ(ierr); 3329308c137SBarry Smith ierr = VecRestoreArrayRead(vi->xl,&xl);CHKERRQ(ierr); 3339308c137SBarry Smith ierr = VecRestoreArrayRead(vi->xu,&xu);CHKERRQ(ierr); 3349308c137SBarry Smith ierr = VecRestoreArrayRead(snes->vec_sol,&x);CHKERRQ(ierr); 335d9822059SBarry Smith ierr = MPI_Allreduce(&rnorm,&fnorm,1,MPIU_REAL,MPIU_SUM,((PetscObject)snes)->comm);CHKERRQ(ierr); 33621a4c9b1SBarry Smith ierr = MPI_Allreduce(act,fact,2,MPIU_INT,MPIU_SUM,((PetscObject)snes)->comm);CHKERRQ(ierr); 3379308c137SBarry Smith fnorm = sqrt(fnorm); 338*6fd67740SBarry Smith 339649052a6SBarry Smith ierr = PetscViewerASCIIAddTab(viewer,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 340*6fd67740SBarry Smith ierr = PetscViewerASCIIPrintf(viewer,"%3D SNES VI Function norm %14.12e Active lower constraints %D upper constraints %D Percent of total %g Percent of bounded %g\n",its,fnorm,fact[0],fact[1],((double)(fact[0]+fact[1]))/((double)N),((double)(fact[0]+fact[1]))/((double)vi->ntruebounds));CHKERRQ(ierr); 341649052a6SBarry Smith ierr = PetscViewerASCIISubtractTab(viewer,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 3429308c137SBarry Smith PetscFunctionReturn(0); 3439308c137SBarry Smith } 3449308c137SBarry Smith 3452b4ed282SShri Abhyankar /* 3462b4ed282SShri Abhyankar Checks if J^T F = 0 which implies we've found a local minimum of the norm of the function, 3472b4ed282SShri 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 3482b4ed282SShri Abhyankar 0 = (J^T F)^T W = F^T J W iff W not in the null space of J. Thanks for Jorge More 3492b4ed282SShri Abhyankar for this trick. One assumes that the probability that W is in the null space of J is very, very small. 3502b4ed282SShri Abhyankar */ 3512b4ed282SShri Abhyankar #undef __FUNCT__ 3522b4ed282SShri Abhyankar #define __FUNCT__ "SNESVICheckLocalMin_Private" 353ace3abfcSBarry Smith PetscErrorCode SNESVICheckLocalMin_Private(SNES snes,Mat A,Vec F,Vec W,PetscReal fnorm,PetscBool *ismin) 3542b4ed282SShri Abhyankar { 3552b4ed282SShri Abhyankar PetscReal a1; 3562b4ed282SShri Abhyankar PetscErrorCode ierr; 357ace3abfcSBarry Smith PetscBool hastranspose; 3582b4ed282SShri Abhyankar 3592b4ed282SShri Abhyankar PetscFunctionBegin; 3602b4ed282SShri Abhyankar *ismin = PETSC_FALSE; 3612b4ed282SShri Abhyankar ierr = MatHasOperation(A,MATOP_MULT_TRANSPOSE,&hastranspose);CHKERRQ(ierr); 3622b4ed282SShri Abhyankar if (hastranspose) { 3632b4ed282SShri Abhyankar /* Compute || J^T F|| */ 3642b4ed282SShri Abhyankar ierr = MatMultTranspose(A,F,W);CHKERRQ(ierr); 3652b4ed282SShri Abhyankar ierr = VecNorm(W,NORM_2,&a1);CHKERRQ(ierr); 3662b4ed282SShri Abhyankar ierr = PetscInfo1(snes,"|| J^T F|| %G near zero implies found a local minimum\n",a1/fnorm);CHKERRQ(ierr); 3672b4ed282SShri Abhyankar if (a1/fnorm < 1.e-4) *ismin = PETSC_TRUE; 3682b4ed282SShri Abhyankar } else { 3692b4ed282SShri Abhyankar Vec work; 3702b4ed282SShri Abhyankar PetscScalar result; 3712b4ed282SShri Abhyankar PetscReal wnorm; 3722b4ed282SShri Abhyankar 3732b4ed282SShri Abhyankar ierr = VecSetRandom(W,PETSC_NULL);CHKERRQ(ierr); 3742b4ed282SShri Abhyankar ierr = VecNorm(W,NORM_2,&wnorm);CHKERRQ(ierr); 3752b4ed282SShri Abhyankar ierr = VecDuplicate(W,&work);CHKERRQ(ierr); 3762b4ed282SShri Abhyankar ierr = MatMult(A,W,work);CHKERRQ(ierr); 3772b4ed282SShri Abhyankar ierr = VecDot(F,work,&result);CHKERRQ(ierr); 3786bf464f9SBarry Smith ierr = VecDestroy(&work);CHKERRQ(ierr); 3792b4ed282SShri Abhyankar a1 = PetscAbsScalar(result)/(fnorm*wnorm); 3802b4ed282SShri Abhyankar ierr = PetscInfo1(snes,"(F^T J random)/(|| F ||*||random|| %G near zero implies found a local minimum\n",a1);CHKERRQ(ierr); 3812b4ed282SShri Abhyankar if (a1 < 1.e-4) *ismin = PETSC_TRUE; 3822b4ed282SShri Abhyankar } 3832b4ed282SShri Abhyankar PetscFunctionReturn(0); 3842b4ed282SShri Abhyankar } 3852b4ed282SShri Abhyankar 3862b4ed282SShri Abhyankar /* 3872b4ed282SShri Abhyankar Checks if J^T(F - J*X) = 0 3882b4ed282SShri Abhyankar */ 3892b4ed282SShri Abhyankar #undef __FUNCT__ 3902b4ed282SShri Abhyankar #define __FUNCT__ "SNESVICheckResidual_Private" 3912b4ed282SShri Abhyankar PetscErrorCode SNESVICheckResidual_Private(SNES snes,Mat A,Vec F,Vec X,Vec W1,Vec W2) 3922b4ed282SShri Abhyankar { 3932b4ed282SShri Abhyankar PetscReal a1,a2; 3942b4ed282SShri Abhyankar PetscErrorCode ierr; 395ace3abfcSBarry Smith PetscBool hastranspose; 3962b4ed282SShri Abhyankar 3972b4ed282SShri Abhyankar PetscFunctionBegin; 3982b4ed282SShri Abhyankar ierr = MatHasOperation(A,MATOP_MULT_TRANSPOSE,&hastranspose);CHKERRQ(ierr); 3992b4ed282SShri Abhyankar if (hastranspose) { 4002b4ed282SShri Abhyankar ierr = MatMult(A,X,W1);CHKERRQ(ierr); 4012b4ed282SShri Abhyankar ierr = VecAXPY(W1,-1.0,F);CHKERRQ(ierr); 4022b4ed282SShri Abhyankar 4032b4ed282SShri Abhyankar /* Compute || J^T W|| */ 4042b4ed282SShri Abhyankar ierr = MatMultTranspose(A,W1,W2);CHKERRQ(ierr); 4052b4ed282SShri Abhyankar ierr = VecNorm(W1,NORM_2,&a1);CHKERRQ(ierr); 4062b4ed282SShri Abhyankar ierr = VecNorm(W2,NORM_2,&a2);CHKERRQ(ierr); 4072b4ed282SShri Abhyankar if (a1 != 0.0) { 4082b4ed282SShri Abhyankar ierr = PetscInfo1(snes,"||J^T(F-Ax)||/||F-AX|| %G near zero implies inconsistent rhs\n",a2/a1);CHKERRQ(ierr); 4092b4ed282SShri Abhyankar } 4102b4ed282SShri Abhyankar } 4112b4ed282SShri Abhyankar PetscFunctionReturn(0); 4122b4ed282SShri Abhyankar } 4132b4ed282SShri Abhyankar 4142b4ed282SShri Abhyankar /* 4152b4ed282SShri Abhyankar SNESDefaultConverged_VI - Checks the convergence of the semismooth newton algorithm. 4162b4ed282SShri Abhyankar 4172b4ed282SShri Abhyankar Notes: 4182b4ed282SShri Abhyankar The convergence criterion currently implemented is 4192b4ed282SShri Abhyankar merit < abstol 4202b4ed282SShri Abhyankar merit < rtol*merit_initial 4212b4ed282SShri Abhyankar */ 4222b4ed282SShri Abhyankar #undef __FUNCT__ 4232b4ed282SShri Abhyankar #define __FUNCT__ "SNESDefaultConverged_VI" 4247fe79bc4SShri Abhyankar PetscErrorCode SNESDefaultConverged_VI(SNES snes,PetscInt it,PetscReal xnorm,PetscReal gradnorm,PetscReal fnorm,SNESConvergedReason *reason,void *dummy) 4252b4ed282SShri Abhyankar { 4262b4ed282SShri Abhyankar PetscErrorCode ierr; 4272b4ed282SShri Abhyankar 4282b4ed282SShri Abhyankar PetscFunctionBegin; 4292b4ed282SShri Abhyankar PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 4302b4ed282SShri Abhyankar PetscValidPointer(reason,6); 4312b4ed282SShri Abhyankar 4322b4ed282SShri Abhyankar *reason = SNES_CONVERGED_ITERATING; 4332b4ed282SShri Abhyankar 4342b4ed282SShri Abhyankar if (!it) { 4352b4ed282SShri Abhyankar /* set parameter for default relative tolerance convergence test */ 4367fe79bc4SShri Abhyankar snes->ttol = fnorm*snes->rtol; 4372b4ed282SShri Abhyankar } 4387fe79bc4SShri Abhyankar if (fnorm != fnorm) { 4392b4ed282SShri Abhyankar ierr = PetscInfo(snes,"Failed to converged, function norm is NaN\n");CHKERRQ(ierr); 4402b4ed282SShri Abhyankar *reason = SNES_DIVERGED_FNORM_NAN; 4417fe79bc4SShri Abhyankar } else if (fnorm < snes->abstol) { 4427fe79bc4SShri Abhyankar ierr = PetscInfo2(snes,"Converged due to function norm %G < %G\n",fnorm,snes->abstol);CHKERRQ(ierr); 4432b4ed282SShri Abhyankar *reason = SNES_CONVERGED_FNORM_ABS; 4442b4ed282SShri Abhyankar } else if (snes->nfuncs >= snes->max_funcs) { 4452b4ed282SShri Abhyankar ierr = PetscInfo2(snes,"Exceeded maximum number of function evaluations: %D > %D\n",snes->nfuncs,snes->max_funcs);CHKERRQ(ierr); 4462b4ed282SShri Abhyankar *reason = SNES_DIVERGED_FUNCTION_COUNT; 4472b4ed282SShri Abhyankar } 4482b4ed282SShri Abhyankar 4492b4ed282SShri Abhyankar if (it && !*reason) { 4507fe79bc4SShri Abhyankar if (fnorm < snes->ttol) { 4517fe79bc4SShri Abhyankar ierr = PetscInfo2(snes,"Converged due to function norm %G < %G (relative tolerance)\n",fnorm,snes->ttol);CHKERRQ(ierr); 4522b4ed282SShri Abhyankar *reason = SNES_CONVERGED_FNORM_RELATIVE; 4532b4ed282SShri Abhyankar } 4542b4ed282SShri Abhyankar } 4552b4ed282SShri Abhyankar PetscFunctionReturn(0); 4562b4ed282SShri Abhyankar } 4572b4ed282SShri Abhyankar 4582b4ed282SShri Abhyankar /* 4592b4ed282SShri Abhyankar SNESVIComputeMeritFunction - Evaluates the merit function for the mixed complementarity problem. 4602b4ed282SShri Abhyankar 4612b4ed282SShri Abhyankar Input Parameter: 4622b4ed282SShri Abhyankar . phi - the semismooth function 4632b4ed282SShri Abhyankar 4642b4ed282SShri Abhyankar Output Parameter: 4652b4ed282SShri Abhyankar . merit - the merit function 4662b4ed282SShri Abhyankar . phinorm - ||phi|| 4672b4ed282SShri Abhyankar 4682b4ed282SShri Abhyankar Notes: 4692b4ed282SShri Abhyankar The merit function for the mixed complementarity problem is defined as 4702b4ed282SShri Abhyankar merit = 0.5*phi^T*phi 4712b4ed282SShri Abhyankar */ 4722b4ed282SShri Abhyankar #undef __FUNCT__ 4732b4ed282SShri Abhyankar #define __FUNCT__ "SNESVIComputeMeritFunction" 4742b4ed282SShri Abhyankar static PetscErrorCode SNESVIComputeMeritFunction(Vec phi, PetscReal* merit,PetscReal* phinorm) 4752b4ed282SShri Abhyankar { 4762b4ed282SShri Abhyankar PetscErrorCode ierr; 4772b4ed282SShri Abhyankar 4782b4ed282SShri Abhyankar PetscFunctionBegin; 4795f48b12bSBarry Smith ierr = VecNormBegin(phi,NORM_2,phinorm);CHKERRQ(ierr); 4805f48b12bSBarry Smith ierr = VecNormEnd(phi,NORM_2,phinorm);CHKERRQ(ierr); 4812b4ed282SShri Abhyankar 4822b4ed282SShri Abhyankar *merit = 0.5*(*phinorm)*(*phinorm); 4832b4ed282SShri Abhyankar PetscFunctionReturn(0); 4842b4ed282SShri Abhyankar } 4852b4ed282SShri Abhyankar 4867f6f51e9SSatish Balay PETSC_STATIC_INLINE PetscScalar Phi(PetscScalar a,PetscScalar b) 4874c21c6cdSBarry Smith { 4884c21c6cdSBarry Smith return a + b - sqrt(a*a + b*b); 4894c21c6cdSBarry Smith } 4904c21c6cdSBarry Smith 4917f6f51e9SSatish Balay PETSC_STATIC_INLINE PetscScalar DPhi(PetscScalar a,PetscScalar b) 4924c21c6cdSBarry Smith { 4935559b345SBarry Smith if ((PetscAbsScalar(a) >= 1.e-6) || (PetscAbsScalar(b) >= 1.e-6)) return 1.0 - a/ sqrt(a*a + b*b); 4945559b345SBarry Smith else return .5; 4954c21c6cdSBarry Smith } 4964c21c6cdSBarry Smith 4972b4ed282SShri Abhyankar /* 4981f79c099SShri Abhyankar SNESVIComputeFunction - Reformulates a system of nonlinear equations in mixed complementarity form to a system of nonlinear equations in semismooth form. 4992b4ed282SShri Abhyankar 5002b4ed282SShri Abhyankar Input Parameters: 5012b4ed282SShri Abhyankar . snes - the SNES context 5022b4ed282SShri Abhyankar . x - current iterate 5032b4ed282SShri Abhyankar . functx - user defined function context 5042b4ed282SShri Abhyankar 5052b4ed282SShri Abhyankar Output Parameters: 5062b4ed282SShri Abhyankar . phi - Semismooth function 5072b4ed282SShri Abhyankar 5082b4ed282SShri Abhyankar */ 5092b4ed282SShri Abhyankar #undef __FUNCT__ 5101f79c099SShri Abhyankar #define __FUNCT__ "SNESVIComputeFunction" 5111f79c099SShri Abhyankar static PetscErrorCode SNESVIComputeFunction(SNES snes,Vec X,Vec phi,void* functx) 5122b4ed282SShri Abhyankar { 5132b4ed282SShri Abhyankar PetscErrorCode ierr; 5142b4ed282SShri Abhyankar SNES_VI *vi = (SNES_VI*)snes->data; 5152b4ed282SShri Abhyankar Vec Xl = vi->xl,Xu = vi->xu,F = snes->vec_func; 5164c21c6cdSBarry Smith PetscScalar *phi_arr,*x_arr,*f_arr,*l,*u; 5172b4ed282SShri Abhyankar PetscInt i,nlocal; 5182b4ed282SShri Abhyankar 5192b4ed282SShri Abhyankar PetscFunctionBegin; 5202b4ed282SShri Abhyankar ierr = (*vi->computeuserfunction)(snes,X,F,functx);CHKERRQ(ierr); 5212b4ed282SShri Abhyankar ierr = VecGetLocalSize(X,&nlocal);CHKERRQ(ierr); 5222b4ed282SShri Abhyankar ierr = VecGetArray(X,&x_arr);CHKERRQ(ierr); 5232b4ed282SShri Abhyankar ierr = VecGetArray(F,&f_arr);CHKERRQ(ierr); 5242b4ed282SShri Abhyankar ierr = VecGetArray(Xl,&l);CHKERRQ(ierr); 5252b4ed282SShri Abhyankar ierr = VecGetArray(Xu,&u);CHKERRQ(ierr); 5262b4ed282SShri Abhyankar ierr = VecGetArray(phi,&phi_arr);CHKERRQ(ierr); 5272b4ed282SShri Abhyankar 5282b4ed282SShri Abhyankar for (i=0;i < nlocal;i++) { 52910f5ae6bSBarry Smith if ((PetscRealPart(l[i]) <= SNES_VI_NINF) && (PetscRealPart(u[i]) >= SNES_VI_INF)) { /* no constraints on variable */ 5304c21c6cdSBarry Smith phi_arr[i] = f_arr[i]; 53110f5ae6bSBarry Smith } else if (PetscRealPart(l[i]) <= SNES_VI_NINF) { /* upper bound on variable only */ 5324c21c6cdSBarry Smith phi_arr[i] = -Phi(u[i] - x_arr[i],-f_arr[i]); 53310f5ae6bSBarry Smith } else if (PetscRealPart(u[i]) >= SNES_VI_INF) { /* lower bound on variable only */ 5344c21c6cdSBarry Smith phi_arr[i] = Phi(x_arr[i] - l[i],f_arr[i]); 5355559b345SBarry Smith } else if (l[i] == u[i]) { 5362b4ed282SShri Abhyankar phi_arr[i] = l[i] - x_arr[i]; 5375559b345SBarry Smith } else { /* both bounds on variable */ 5384c21c6cdSBarry Smith phi_arr[i] = Phi(x_arr[i] - l[i],-Phi(u[i] - x_arr[i],-f_arr[i])); 5392b4ed282SShri Abhyankar } 5402b4ed282SShri Abhyankar } 5412b4ed282SShri Abhyankar 5422b4ed282SShri Abhyankar ierr = VecRestoreArray(X,&x_arr);CHKERRQ(ierr); 5432b4ed282SShri Abhyankar ierr = VecRestoreArray(F,&f_arr);CHKERRQ(ierr); 5442b4ed282SShri Abhyankar ierr = VecRestoreArray(Xl,&l);CHKERRQ(ierr); 5452b4ed282SShri Abhyankar ierr = VecRestoreArray(Xu,&u);CHKERRQ(ierr); 5462b4ed282SShri Abhyankar ierr = VecRestoreArray(phi,&phi_arr);CHKERRQ(ierr); 5472b4ed282SShri Abhyankar PetscFunctionReturn(0); 5482b4ed282SShri Abhyankar } 5492b4ed282SShri Abhyankar 5502b4ed282SShri Abhyankar /* 551a79edbefSShri Abhyankar SNESVIComputeBsubdifferentialVectors - Computes the diagonal shift (Da) and row scaling (Db) vectors needed for the 552a79edbefSShri Abhyankar the semismooth jacobian. 5532b4ed282SShri Abhyankar */ 5542b4ed282SShri Abhyankar #undef __FUNCT__ 555a79edbefSShri Abhyankar #define __FUNCT__ "SNESVIComputeBsubdifferentialVectors" 556a79edbefSShri Abhyankar PetscErrorCode SNESVIComputeBsubdifferentialVectors(SNES snes,Vec X,Vec F,Mat jac,Vec Da,Vec Db) 5572b4ed282SShri Abhyankar { 5582b4ed282SShri Abhyankar PetscErrorCode ierr; 5592b4ed282SShri Abhyankar SNES_VI *vi = (SNES_VI*)snes->data; 5604c21c6cdSBarry Smith PetscScalar *l,*u,*x,*f,*da,*db,da1,da2,db1,db2; 5612b4ed282SShri Abhyankar PetscInt i,nlocal; 5622b4ed282SShri Abhyankar 5632b4ed282SShri Abhyankar PetscFunctionBegin; 5642b4ed282SShri Abhyankar 5652b4ed282SShri Abhyankar ierr = VecGetArray(X,&x);CHKERRQ(ierr); 5662b4ed282SShri Abhyankar ierr = VecGetArray(F,&f);CHKERRQ(ierr); 5672b4ed282SShri Abhyankar ierr = VecGetArray(vi->xl,&l);CHKERRQ(ierr); 5682b4ed282SShri Abhyankar ierr = VecGetArray(vi->xu,&u);CHKERRQ(ierr); 569a79edbefSShri Abhyankar ierr = VecGetArray(Da,&da);CHKERRQ(ierr); 570a79edbefSShri Abhyankar ierr = VecGetArray(Db,&db);CHKERRQ(ierr); 5712b4ed282SShri Abhyankar ierr = VecGetLocalSize(X,&nlocal);CHKERRQ(ierr); 5724c21c6cdSBarry Smith 5732b4ed282SShri Abhyankar for (i=0;i< nlocal;i++) { 57410f5ae6bSBarry Smith if ((PetscRealPart(l[i]) <= SNES_VI_NINF) && (PetscRealPart(u[i]) >= SNES_VI_INF)) {/* no constraints on variable */ 5754c21c6cdSBarry Smith da[i] = 0; 5762b4ed282SShri Abhyankar db[i] = 1; 57710f5ae6bSBarry Smith } else if (PetscRealPart(l[i]) <= SNES_VI_NINF) { /* upper bound on variable only */ 5784c21c6cdSBarry Smith da[i] = DPhi(u[i] - x[i], -f[i]); 5794c21c6cdSBarry Smith db[i] = DPhi(-f[i],u[i] - x[i]); 58010f5ae6bSBarry Smith } else if (PetscRealPart(u[i]) >= SNES_VI_INF) { /* lower bound on variable only */ 5815559b345SBarry Smith da[i] = DPhi(x[i] - l[i], f[i]); 5825559b345SBarry Smith db[i] = DPhi(f[i],x[i] - l[i]); 5835559b345SBarry Smith } else if (l[i] == u[i]) { /* fixed variable */ 5844c21c6cdSBarry Smith da[i] = 1; 5852b4ed282SShri Abhyankar db[i] = 0; 5865559b345SBarry Smith } else { /* upper and lower bounds on variable */ 5874c21c6cdSBarry Smith da1 = DPhi(x[i] - l[i], -Phi(u[i] - x[i], -f[i])); 5884c21c6cdSBarry Smith db1 = DPhi(-Phi(u[i] - x[i], -f[i]),x[i] - l[i]); 5894c21c6cdSBarry Smith da2 = DPhi(u[i] - x[i], -f[i]); 5904c21c6cdSBarry Smith db2 = DPhi(-f[i],u[i] - x[i]); 5914c21c6cdSBarry Smith da[i] = da1 + db1*da2; 5924c21c6cdSBarry Smith db[i] = db1*db2; 5932b4ed282SShri Abhyankar } 5942b4ed282SShri Abhyankar } 5955559b345SBarry Smith 5962b4ed282SShri Abhyankar ierr = VecRestoreArray(X,&x);CHKERRQ(ierr); 5972b4ed282SShri Abhyankar ierr = VecRestoreArray(F,&f);CHKERRQ(ierr); 5982b4ed282SShri Abhyankar ierr = VecRestoreArray(vi->xl,&l);CHKERRQ(ierr); 5992b4ed282SShri Abhyankar ierr = VecRestoreArray(vi->xu,&u);CHKERRQ(ierr); 600a79edbefSShri Abhyankar ierr = VecRestoreArray(Da,&da);CHKERRQ(ierr); 601a79edbefSShri Abhyankar ierr = VecRestoreArray(Db,&db);CHKERRQ(ierr); 602a79edbefSShri Abhyankar PetscFunctionReturn(0); 603a79edbefSShri Abhyankar } 604a79edbefSShri Abhyankar 605a79edbefSShri Abhyankar /* 606a79edbefSShri 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. 607a79edbefSShri Abhyankar 608a79edbefSShri Abhyankar Input Parameters: 609a79edbefSShri Abhyankar . Da - Diagonal shift vector for the semismooth jacobian. 610a79edbefSShri Abhyankar . Db - Row scaling vector for the semismooth jacobian. 611a79edbefSShri Abhyankar 612a79edbefSShri Abhyankar Output Parameters: 613a79edbefSShri Abhyankar . jac - semismooth jacobian 614a79edbefSShri Abhyankar . jac_pre - optional preconditioning matrix 615a79edbefSShri Abhyankar 616a79edbefSShri Abhyankar Notes: 617a79edbefSShri Abhyankar The semismooth jacobian matrix is given by 618a79edbefSShri Abhyankar jac = Da + Db*jacfun 619a79edbefSShri Abhyankar where Db is the row scaling matrix stored as a vector, 620a79edbefSShri Abhyankar Da is the diagonal perturbation matrix stored as a vector 621a79edbefSShri Abhyankar and jacfun is the jacobian of the original nonlinear function. 622a79edbefSShri Abhyankar */ 623a79edbefSShri Abhyankar #undef __FUNCT__ 624a79edbefSShri Abhyankar #define __FUNCT__ "SNESVIComputeJacobian" 625a79edbefSShri Abhyankar PetscErrorCode SNESVIComputeJacobian(Mat jac, Mat jac_pre,Vec Da, Vec Db) 626a79edbefSShri Abhyankar { 627a79edbefSShri Abhyankar PetscErrorCode ierr; 628a79edbefSShri Abhyankar 6292b4ed282SShri Abhyankar /* Do row scaling and add diagonal perturbation */ 630a79edbefSShri Abhyankar ierr = MatDiagonalScale(jac,Db,PETSC_NULL);CHKERRQ(ierr); 631a79edbefSShri Abhyankar ierr = MatDiagonalSet(jac,Da,ADD_VALUES);CHKERRQ(ierr); 632a79edbefSShri Abhyankar if (jac != jac_pre) { /* If jac and jac_pre are different */ 633a79edbefSShri Abhyankar ierr = MatDiagonalScale(jac_pre,Db,PETSC_NULL); 634a79edbefSShri Abhyankar ierr = MatDiagonalSet(jac_pre,Da,ADD_VALUES);CHKERRQ(ierr); 6352b4ed282SShri Abhyankar } 6362b4ed282SShri Abhyankar PetscFunctionReturn(0); 6372b4ed282SShri Abhyankar } 6382b4ed282SShri Abhyankar 6392b4ed282SShri Abhyankar /* 640ee657d29SShri Abhyankar SNESVIComputeMeritFunctionGradient - Computes the gradient of the merit function psi. 641ee657d29SShri Abhyankar 642ee657d29SShri Abhyankar Input Parameters: 643ee657d29SShri Abhyankar phi - semismooth function. 644ee657d29SShri Abhyankar H - semismooth jacobian 645ee657d29SShri Abhyankar 646ee657d29SShri Abhyankar Output Parameters: 647ee657d29SShri Abhyankar dpsi - merit function gradient 648ee657d29SShri Abhyankar 649ee657d29SShri Abhyankar Notes: 650ee657d29SShri Abhyankar The merit function gradient is computed as follows 651ee657d29SShri Abhyankar dpsi = H^T*phi 652ee657d29SShri Abhyankar */ 653ee657d29SShri Abhyankar #undef __FUNCT__ 654ee657d29SShri Abhyankar #define __FUNCT__ "SNESVIComputeMeritFunctionGradient" 655ee657d29SShri Abhyankar PetscErrorCode SNESVIComputeMeritFunctionGradient(Mat H, Vec phi, Vec dpsi) 656ee657d29SShri Abhyankar { 657ee657d29SShri Abhyankar PetscErrorCode ierr; 658ee657d29SShri Abhyankar 659ee657d29SShri Abhyankar PetscFunctionBegin; 6605f48b12bSBarry Smith ierr = MatMultTranspose(H,phi,dpsi);CHKERRQ(ierr); 661ee657d29SShri Abhyankar PetscFunctionReturn(0); 662ee657d29SShri Abhyankar } 663ee657d29SShri Abhyankar 664c1a5e521SShri Abhyankar /* -------------------------------------------------------------------------- */ 665c1a5e521SShri Abhyankar /* 666c1a5e521SShri Abhyankar SNESVIProjectOntoBounds - Projects X onto the feasible region so that Xl[i] <= X[i] <= Xu[i] for i = 1...n. 667c1a5e521SShri Abhyankar 668c1a5e521SShri Abhyankar Input Parameters: 669c1a5e521SShri Abhyankar . SNES - nonlinear solver context 670c1a5e521SShri Abhyankar 671c1a5e521SShri Abhyankar Output Parameters: 672c1a5e521SShri Abhyankar . X - Bound projected X 673c1a5e521SShri Abhyankar 674c1a5e521SShri Abhyankar */ 675c1a5e521SShri Abhyankar 676c1a5e521SShri Abhyankar #undef __FUNCT__ 677c1a5e521SShri Abhyankar #define __FUNCT__ "SNESVIProjectOntoBounds" 678c1a5e521SShri Abhyankar PetscErrorCode SNESVIProjectOntoBounds(SNES snes,Vec X) 679c1a5e521SShri Abhyankar { 680c1a5e521SShri Abhyankar PetscErrorCode ierr; 681c1a5e521SShri Abhyankar SNES_VI *vi = (SNES_VI*)snes->data; 682c1a5e521SShri Abhyankar const PetscScalar *xl,*xu; 683c1a5e521SShri Abhyankar PetscScalar *x; 684c1a5e521SShri Abhyankar PetscInt i,n; 685c1a5e521SShri Abhyankar 686c1a5e521SShri Abhyankar PetscFunctionBegin; 687c1a5e521SShri Abhyankar ierr = VecGetLocalSize(X,&n);CHKERRQ(ierr); 688c1a5e521SShri Abhyankar ierr = VecGetArray(X,&x);CHKERRQ(ierr); 689c1a5e521SShri Abhyankar ierr = VecGetArrayRead(vi->xl,&xl);CHKERRQ(ierr); 690c1a5e521SShri Abhyankar ierr = VecGetArrayRead(vi->xu,&xu);CHKERRQ(ierr); 691c1a5e521SShri Abhyankar 692c1a5e521SShri Abhyankar for(i = 0;i<n;i++) { 69310f5ae6bSBarry Smith if (PetscRealPart(x[i]) < PetscRealPart(xl[i])) x[i] = xl[i]; 69410f5ae6bSBarry Smith else if (PetscRealPart(x[i]) > PetscRealPart(xu[i])) x[i] = xu[i]; 695c1a5e521SShri Abhyankar } 696c1a5e521SShri Abhyankar ierr = VecRestoreArray(X,&x);CHKERRQ(ierr); 697c1a5e521SShri Abhyankar ierr = VecRestoreArrayRead(vi->xl,&xl);CHKERRQ(ierr); 698c1a5e521SShri Abhyankar ierr = VecRestoreArrayRead(vi->xu,&xu);CHKERRQ(ierr); 699c1a5e521SShri Abhyankar PetscFunctionReturn(0); 700c1a5e521SShri Abhyankar } 701c1a5e521SShri Abhyankar 7022b4ed282SShri Abhyankar /* -------------------------------------------------------------------- 7032b4ed282SShri Abhyankar 7042b4ed282SShri Abhyankar This file implements a semismooth truncated Newton method with a line search, 7052b4ed282SShri Abhyankar for solving a system of nonlinear equations in complementarity form, using the KSP, Vec, 7062b4ed282SShri Abhyankar and Mat interfaces for linear solvers, vectors, and matrices, 7072b4ed282SShri Abhyankar respectively. 7082b4ed282SShri Abhyankar 7092b4ed282SShri Abhyankar The following basic routines are required for each nonlinear solver: 7102b4ed282SShri Abhyankar SNESCreate_XXX() - Creates a nonlinear solver context 7112b4ed282SShri Abhyankar SNESSetFromOptions_XXX() - Sets runtime options 7122b4ed282SShri Abhyankar SNESSolve_XXX() - Solves the nonlinear system 7132b4ed282SShri Abhyankar SNESDestroy_XXX() - Destroys the nonlinear solver context 7142b4ed282SShri Abhyankar The suffix "_XXX" denotes a particular implementation, in this case 7152b4ed282SShri Abhyankar we use _VI (e.g., SNESCreate_VI, SNESSolve_VI) for solving 7162b4ed282SShri Abhyankar systems of nonlinear equations with a line search (LS) method. 7172b4ed282SShri Abhyankar These routines are actually called via the common user interface 7182b4ed282SShri Abhyankar routines SNESCreate(), SNESSetFromOptions(), SNESSolve(), and 7192b4ed282SShri Abhyankar SNESDestroy(), so the application code interface remains identical 7202b4ed282SShri Abhyankar for all nonlinear solvers. 7212b4ed282SShri Abhyankar 7222b4ed282SShri Abhyankar Another key routine is: 7232b4ed282SShri Abhyankar SNESSetUp_XXX() - Prepares for the use of a nonlinear solver 7242b4ed282SShri Abhyankar by setting data structures and options. The interface routine SNESSetUp() 7252b4ed282SShri Abhyankar is not usually called directly by the user, but instead is called by 7262b4ed282SShri Abhyankar SNESSolve() if necessary. 7272b4ed282SShri Abhyankar 7282b4ed282SShri Abhyankar Additional basic routines are: 7292b4ed282SShri Abhyankar SNESView_XXX() - Prints details of runtime options that 7302b4ed282SShri Abhyankar have actually been used. 7312b4ed282SShri Abhyankar These are called by application codes via the interface routines 7322b4ed282SShri Abhyankar SNESView(). 7332b4ed282SShri Abhyankar 7342b4ed282SShri Abhyankar The various types of solvers (preconditioners, Krylov subspace methods, 7352b4ed282SShri Abhyankar nonlinear solvers, timesteppers) are all organized similarly, so the 7362b4ed282SShri Abhyankar above description applies to these categories also. 7372b4ed282SShri Abhyankar 7382b4ed282SShri Abhyankar -------------------------------------------------------------------- */ 7392b4ed282SShri Abhyankar /* 74069c03620SShri Abhyankar SNESSolveVI_SS - Solves the complementarity problem with a semismooth Newton 7412b4ed282SShri Abhyankar method using a line search. 7422b4ed282SShri Abhyankar 7432b4ed282SShri Abhyankar Input Parameters: 7442b4ed282SShri Abhyankar . snes - the SNES context 7452b4ed282SShri Abhyankar 7462b4ed282SShri Abhyankar Output Parameter: 7472b4ed282SShri Abhyankar . outits - number of iterations until termination 7482b4ed282SShri Abhyankar 7492b4ed282SShri Abhyankar Application Interface Routine: SNESSolve() 7502b4ed282SShri Abhyankar 7512b4ed282SShri Abhyankar Notes: 7522b4ed282SShri Abhyankar This implements essentially a semismooth Newton method with a 75351defd01SShri Abhyankar line search. The default line search does not do any line seach 75451defd01SShri Abhyankar but rather takes a full newton step. 7552b4ed282SShri Abhyankar */ 7562b4ed282SShri Abhyankar #undef __FUNCT__ 75769c03620SShri Abhyankar #define __FUNCT__ "SNESSolveVI_SS" 75869c03620SShri Abhyankar PetscErrorCode SNESSolveVI_SS(SNES snes) 7592b4ed282SShri Abhyankar { 7602b4ed282SShri Abhyankar SNES_VI *vi = (SNES_VI*)snes->data; 7612b4ed282SShri Abhyankar PetscErrorCode ierr; 7622b4ed282SShri Abhyankar PetscInt maxits,i,lits; 7633b336b49SShri Abhyankar PetscBool lssucceed; 7642b4ed282SShri Abhyankar MatStructure flg = DIFFERENT_NONZERO_PATTERN; 7652b4ed282SShri Abhyankar PetscReal gnorm,xnorm=0,ynorm; 7662b4ed282SShri Abhyankar Vec Y,X,F,G,W; 7672b4ed282SShri Abhyankar KSPConvergedReason kspreason; 7682b4ed282SShri Abhyankar 7692b4ed282SShri Abhyankar PetscFunctionBegin; 7709ce7406fSBarry Smith vi->computeuserfunction = snes->ops->computefunction; 7719ce7406fSBarry Smith snes->ops->computefunction = SNESVIComputeFunction; 7729ce7406fSBarry Smith 7732b4ed282SShri Abhyankar snes->numFailures = 0; 7742b4ed282SShri Abhyankar snes->numLinearSolveFailures = 0; 7752b4ed282SShri Abhyankar snes->reason = SNES_CONVERGED_ITERATING; 7762b4ed282SShri Abhyankar 7772b4ed282SShri Abhyankar maxits = snes->max_its; /* maximum number of iterations */ 7782b4ed282SShri Abhyankar X = snes->vec_sol; /* solution vector */ 7792b4ed282SShri Abhyankar F = snes->vec_func; /* residual vector */ 7802b4ed282SShri Abhyankar Y = snes->work[0]; /* work vectors */ 7812b4ed282SShri Abhyankar G = snes->work[1]; 7822b4ed282SShri Abhyankar W = snes->work[2]; 7832b4ed282SShri Abhyankar 7842b4ed282SShri Abhyankar ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 7852b4ed282SShri Abhyankar snes->iter = 0; 7862b4ed282SShri Abhyankar snes->norm = 0.0; 7872b4ed282SShri Abhyankar ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 7882b4ed282SShri Abhyankar 7897fe79bc4SShri Abhyankar ierr = SNESVIProjectOntoBounds(snes,X);CHKERRQ(ierr); 7902b4ed282SShri Abhyankar ierr = SNESComputeFunction(snes,X,vi->phi);CHKERRQ(ierr); 7912b4ed282SShri Abhyankar if (snes->domainerror) { 7922b4ed282SShri Abhyankar snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN; 7939ce7406fSBarry Smith snes->ops->computefunction = vi->computeuserfunction; 7942b4ed282SShri Abhyankar PetscFunctionReturn(0); 7952b4ed282SShri Abhyankar } 7962b4ed282SShri Abhyankar /* Compute Merit function */ 7972b4ed282SShri Abhyankar ierr = SNESVIComputeMeritFunction(vi->phi,&vi->merit,&vi->phinorm);CHKERRQ(ierr); 7982b4ed282SShri Abhyankar 7992b4ed282SShri Abhyankar ierr = VecNormBegin(X,NORM_2,&xnorm);CHKERRQ(ierr); /* xnorm <- ||x|| */ 8002b4ed282SShri Abhyankar ierr = VecNormEnd(X,NORM_2,&xnorm);CHKERRQ(ierr); 80162cbcd01SMatthew G Knepley if (PetscIsInfOrNanReal(vi->merit)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number"); 8022b4ed282SShri Abhyankar 8032b4ed282SShri Abhyankar ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 8042b4ed282SShri Abhyankar snes->norm = vi->phinorm; 8052b4ed282SShri Abhyankar ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 8062b4ed282SShri Abhyankar SNESLogConvHistory(snes,vi->phinorm,0); 8077a03ce2fSLisandro Dalcin ierr = SNESMonitor(snes,0,vi->phinorm);CHKERRQ(ierr); 8082b4ed282SShri Abhyankar 8092b4ed282SShri Abhyankar /* set parameter for default relative tolerance convergence test */ 8102b4ed282SShri Abhyankar snes->ttol = vi->phinorm*snes->rtol; 8112b4ed282SShri Abhyankar /* test convergence */ 8122b4ed282SShri Abhyankar ierr = (*snes->ops->converged)(snes,0,0.0,0.0,vi->phinorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); 8139ce7406fSBarry Smith if (snes->reason) { 8149ce7406fSBarry Smith snes->ops->computefunction = vi->computeuserfunction; 8159ce7406fSBarry Smith PetscFunctionReturn(0); 8169ce7406fSBarry Smith } 8172b4ed282SShri Abhyankar 8182b4ed282SShri Abhyankar for (i=0; i<maxits; i++) { 8192b4ed282SShri Abhyankar 8202b4ed282SShri Abhyankar /* Call general purpose update function */ 8212b4ed282SShri Abhyankar if (snes->ops->update) { 8222b4ed282SShri Abhyankar ierr = (*snes->ops->update)(snes, snes->iter);CHKERRQ(ierr); 8232b4ed282SShri Abhyankar } 8242b4ed282SShri Abhyankar 8252b4ed282SShri Abhyankar /* Solve J Y = Phi, where J is the semismooth jacobian */ 826a79edbefSShri Abhyankar /* Get the nonlinear function jacobian */ 8272b4ed282SShri Abhyankar ierr = SNESComputeJacobian(snes,X,&snes->jacobian,&snes->jacobian_pre,&flg);CHKERRQ(ierr); 828a79edbefSShri Abhyankar /* Get the diagonal shift and row scaling vectors */ 829a79edbefSShri Abhyankar ierr = SNESVIComputeBsubdifferentialVectors(snes,X,F,snes->jacobian,vi->Da,vi->Db);CHKERRQ(ierr); 830a79edbefSShri Abhyankar /* Compute the semismooth jacobian */ 831a79edbefSShri Abhyankar ierr = SNESVIComputeJacobian(snes->jacobian,snes->jacobian_pre,vi->Da,vi->Db);CHKERRQ(ierr); 832ee657d29SShri Abhyankar /* Compute the merit function gradient */ 833ee657d29SShri Abhyankar ierr = SNESVIComputeMeritFunctionGradient(snes->jacobian,vi->phi,vi->dpsi);CHKERRQ(ierr); 8342b4ed282SShri Abhyankar ierr = KSPSetOperators(snes->ksp,snes->jacobian,snes->jacobian_pre,flg);CHKERRQ(ierr); 8352b4ed282SShri Abhyankar ierr = SNES_KSPSolve(snes,snes->ksp,vi->phi,Y);CHKERRQ(ierr); 8362b4ed282SShri Abhyankar ierr = KSPGetConvergedReason(snes->ksp,&kspreason);CHKERRQ(ierr); 8373b336b49SShri Abhyankar 8383b336b49SShri Abhyankar if (kspreason < 0) { 8392b4ed282SShri Abhyankar if (++snes->numLinearSolveFailures >= snes->maxLinearSolveFailures) { 8402b4ed282SShri 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); 8412b4ed282SShri Abhyankar snes->reason = SNES_DIVERGED_LINEAR_SOLVE; 8422b4ed282SShri Abhyankar break; 8432b4ed282SShri Abhyankar } 8442b4ed282SShri Abhyankar } 8452b4ed282SShri Abhyankar ierr = KSPGetIterationNumber(snes->ksp,&lits);CHKERRQ(ierr); 8462b4ed282SShri Abhyankar snes->linear_its += lits; 8472b4ed282SShri Abhyankar ierr = PetscInfo2(snes,"iter=%D, linear solve iterations=%D\n",snes->iter,lits);CHKERRQ(ierr); 8482b4ed282SShri Abhyankar /* 8492b4ed282SShri Abhyankar if (vi->precheckstep) { 850ace3abfcSBarry Smith PetscBool changed_y = PETSC_FALSE; 8512b4ed282SShri Abhyankar ierr = (*vi->precheckstep)(snes,X,Y,vi->precheck,&changed_y);CHKERRQ(ierr); 8522b4ed282SShri Abhyankar } 8532b4ed282SShri Abhyankar 8542b4ed282SShri Abhyankar if (PetscLogPrintInfo){ 8552b4ed282SShri Abhyankar ierr = SNESVICheckResidual_Private(snes,snes->jacobian,F,Y,G,W);CHKERRQ(ierr); 8562b4ed282SShri Abhyankar } 8572b4ed282SShri Abhyankar */ 8582b4ed282SShri Abhyankar /* Compute a (scaled) negative update in the line search routine: 8592b4ed282SShri Abhyankar Y <- X - lambda*Y 8602b4ed282SShri Abhyankar and evaluate G = function(Y) (depends on the line search). 8612b4ed282SShri Abhyankar */ 8622b4ed282SShri Abhyankar ierr = VecCopy(Y,snes->vec_sol_update);CHKERRQ(ierr); 8632b4ed282SShri Abhyankar ynorm = 1; gnorm = vi->phinorm; 8642b4ed282SShri Abhyankar ierr = (*vi->LineSearch)(snes,vi->lsP,X,vi->phi,G,Y,W,vi->phinorm,xnorm,&ynorm,&gnorm,&lssucceed);CHKERRQ(ierr); 8652b4ed282SShri Abhyankar ierr = PetscInfo4(snes,"fnorm=%18.16e, gnorm=%18.16e, ynorm=%18.16e, lssucceed=%d\n",vi->phinorm,gnorm,ynorm,(int)lssucceed);CHKERRQ(ierr); 8662b4ed282SShri Abhyankar if (snes->reason == SNES_DIVERGED_FUNCTION_COUNT) break; 8672b4ed282SShri Abhyankar if (snes->domainerror) { 8682b4ed282SShri Abhyankar snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN; 8699ce7406fSBarry Smith snes->ops->computefunction = vi->computeuserfunction; 8702b4ed282SShri Abhyankar PetscFunctionReturn(0); 8712b4ed282SShri Abhyankar } 8722b4ed282SShri Abhyankar if (!lssucceed) { 8732b4ed282SShri Abhyankar if (++snes->numFailures >= snes->maxFailures) { 874ace3abfcSBarry Smith PetscBool ismin; 8752b4ed282SShri Abhyankar snes->reason = SNES_DIVERGED_LINE_SEARCH; 8762b4ed282SShri Abhyankar ierr = SNESVICheckLocalMin_Private(snes,snes->jacobian,G,W,gnorm,&ismin);CHKERRQ(ierr); 8772b4ed282SShri Abhyankar if (ismin) snes->reason = SNES_DIVERGED_LOCAL_MIN; 8782b4ed282SShri Abhyankar break; 8792b4ed282SShri Abhyankar } 8802b4ed282SShri Abhyankar } 8812b4ed282SShri Abhyankar /* Update function and solution vectors */ 8822b4ed282SShri Abhyankar vi->phinorm = gnorm; 8832b4ed282SShri Abhyankar vi->merit = 0.5*vi->phinorm*vi->phinorm; 8842b4ed282SShri Abhyankar ierr = VecCopy(G,vi->phi);CHKERRQ(ierr); 8852b4ed282SShri Abhyankar ierr = VecCopy(W,X);CHKERRQ(ierr); 8862b4ed282SShri Abhyankar /* Monitor convergence */ 8872b4ed282SShri Abhyankar ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 8882b4ed282SShri Abhyankar snes->iter = i+1; 8892b4ed282SShri Abhyankar snes->norm = vi->phinorm; 8902b4ed282SShri Abhyankar ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 8912b4ed282SShri Abhyankar SNESLogConvHistory(snes,snes->norm,lits); 8927a03ce2fSLisandro Dalcin ierr = SNESMonitor(snes,snes->iter,snes->norm);CHKERRQ(ierr); 8932b4ed282SShri Abhyankar /* Test for convergence, xnorm = || X || */ 8942b4ed282SShri Abhyankar if (snes->ops->converged != SNESSkipConverged) { ierr = VecNorm(X,NORM_2,&xnorm);CHKERRQ(ierr); } 8952b4ed282SShri Abhyankar ierr = (*snes->ops->converged)(snes,snes->iter,xnorm,ynorm,vi->phinorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); 8962b4ed282SShri Abhyankar if (snes->reason) break; 8972b4ed282SShri Abhyankar } 8982b4ed282SShri Abhyankar if (i == maxits) { 8992b4ed282SShri Abhyankar ierr = PetscInfo1(snes,"Maximum number of iterations has been reached: %D\n",maxits);CHKERRQ(ierr); 9002b4ed282SShri Abhyankar if(!snes->reason) snes->reason = SNES_DIVERGED_MAX_IT; 9012b4ed282SShri Abhyankar } 9029ce7406fSBarry Smith snes->ops->computefunction = vi->computeuserfunction; 9032b4ed282SShri Abhyankar PetscFunctionReturn(0); 9042b4ed282SShri Abhyankar } 90569c03620SShri Abhyankar 90669c03620SShri Abhyankar #undef __FUNCT__ 907693ddf92SShri Abhyankar #define __FUNCT__ "SNESVIGetActiveSetIS" 908693ddf92SShri Abhyankar /* 909693ddf92SShri Abhyankar SNESVIGetActiveSetIndices - Gets the global indices for the active set variables 910693ddf92SShri Abhyankar 911693ddf92SShri Abhyankar Input parameter 912693ddf92SShri Abhyankar . snes - the SNES context 913693ddf92SShri Abhyankar . X - the snes solution vector 914693ddf92SShri Abhyankar . F - the nonlinear function vector 915693ddf92SShri Abhyankar 916693ddf92SShri Abhyankar Output parameter 917693ddf92SShri Abhyankar . ISact - active set index set 918693ddf92SShri Abhyankar */ 919693ddf92SShri Abhyankar PetscErrorCode SNESVIGetActiveSetIS(SNES snes,Vec X,Vec F,IS* ISact) 920d950fb63SShri Abhyankar { 921d950fb63SShri Abhyankar PetscErrorCode ierr; 922693ddf92SShri Abhyankar SNES_VI *vi = (SNES_VI*)snes->data; 923693ddf92SShri Abhyankar Vec Xl=vi->xl,Xu=vi->xu; 924693ddf92SShri Abhyankar const PetscScalar *x,*f,*xl,*xu; 925693ddf92SShri Abhyankar PetscInt *idx_act,i,nlocal,nloc_isact=0,ilow,ihigh,i1=0; 926d950fb63SShri Abhyankar 927d950fb63SShri Abhyankar PetscFunctionBegin; 928d950fb63SShri Abhyankar ierr = VecGetLocalSize(X,&nlocal);CHKERRQ(ierr); 929d950fb63SShri Abhyankar ierr = VecGetOwnershipRange(X,&ilow,&ihigh);CHKERRQ(ierr); 930fe835674SShri Abhyankar ierr = VecGetArrayRead(X,&x);CHKERRQ(ierr); 931fe835674SShri Abhyankar ierr = VecGetArrayRead(Xl,&xl);CHKERRQ(ierr); 932fe835674SShri Abhyankar ierr = VecGetArrayRead(Xu,&xu);CHKERRQ(ierr); 933fe835674SShri Abhyankar ierr = VecGetArrayRead(F,&f);CHKERRQ(ierr); 934693ddf92SShri Abhyankar /* Compute active set size */ 935d950fb63SShri Abhyankar for (i=0; i < nlocal;i++) { 93610f5ae6bSBarry 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++; 937d950fb63SShri Abhyankar } 938693ddf92SShri Abhyankar 939d950fb63SShri Abhyankar ierr = PetscMalloc(nloc_isact*sizeof(PetscInt),&idx_act);CHKERRQ(ierr); 940d950fb63SShri Abhyankar 941693ddf92SShri Abhyankar /* Set active set indices */ 942d950fb63SShri Abhyankar for(i=0; i < nlocal; i++) { 94310f5ae6bSBarry 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; 944d950fb63SShri Abhyankar } 945d950fb63SShri Abhyankar 946693ddf92SShri Abhyankar /* Create active set IS */ 94762298a1eSBarry Smith ierr = ISCreateGeneral(((PetscObject)snes)->comm,nloc_isact,idx_act,PETSC_OWN_POINTER,ISact);CHKERRQ(ierr); 948d950fb63SShri Abhyankar 949fe835674SShri Abhyankar ierr = VecRestoreArrayRead(X,&x);CHKERRQ(ierr); 950fe835674SShri Abhyankar ierr = VecRestoreArrayRead(Xl,&xl);CHKERRQ(ierr); 951fe835674SShri Abhyankar ierr = VecRestoreArrayRead(Xu,&xu);CHKERRQ(ierr); 952fe835674SShri Abhyankar ierr = VecRestoreArrayRead(F,&f);CHKERRQ(ierr); 953d950fb63SShri Abhyankar PetscFunctionReturn(0); 954d950fb63SShri Abhyankar } 955d950fb63SShri Abhyankar 956693ddf92SShri Abhyankar #undef __FUNCT__ 957693ddf92SShri Abhyankar #define __FUNCT__ "SNESVICreateIndexSets_RS" 958693ddf92SShri Abhyankar PetscErrorCode SNESVICreateIndexSets_RS(SNES snes,Vec X,Vec F,IS* ISact,IS* ISinact) 959693ddf92SShri Abhyankar { 960693ddf92SShri Abhyankar PetscErrorCode ierr; 961693ddf92SShri Abhyankar 962693ddf92SShri Abhyankar PetscFunctionBegin; 963693ddf92SShri Abhyankar ierr = SNESVIGetActiveSetIS(snes,X,F,ISact);CHKERRQ(ierr); 964693ddf92SShri Abhyankar ierr = ISComplement(*ISact,X->map->rstart,X->map->rend,ISinact);CHKERRQ(ierr); 965693ddf92SShri Abhyankar PetscFunctionReturn(0); 966693ddf92SShri Abhyankar } 967693ddf92SShri Abhyankar 968dbd914b8SShri Abhyankar /* Create active and inactive set vectors. The local size of this vector is set and petsc computes the global size */ 969dbd914b8SShri Abhyankar #undef __FUNCT__ 970fe835674SShri Abhyankar #define __FUNCT__ "SNESVICreateSubVectors" 971fe835674SShri Abhyankar PetscErrorCode SNESVICreateSubVectors(SNES snes,PetscInt n,Vec* newv) 972dbd914b8SShri Abhyankar { 973dbd914b8SShri Abhyankar PetscErrorCode ierr; 974dbd914b8SShri Abhyankar Vec v; 975dbd914b8SShri Abhyankar 976dbd914b8SShri Abhyankar PetscFunctionBegin; 977dbd914b8SShri Abhyankar ierr = VecCreate(((PetscObject)snes)->comm,&v);CHKERRQ(ierr); 978dbd914b8SShri Abhyankar ierr = VecSetSizes(v,n,PETSC_DECIDE);CHKERRQ(ierr); 979dbd914b8SShri Abhyankar ierr = VecSetFromOptions(v);CHKERRQ(ierr); 980dbd914b8SShri Abhyankar *newv = v; 981dbd914b8SShri Abhyankar 982dbd914b8SShri Abhyankar PetscFunctionReturn(0); 983dbd914b8SShri Abhyankar } 984dbd914b8SShri Abhyankar 985732bb160SShri Abhyankar /* Resets the snes PC and KSP when the active set sizes change */ 986732bb160SShri Abhyankar #undef __FUNCT__ 987732bb160SShri Abhyankar #define __FUNCT__ "SNESVIResetPCandKSP" 988732bb160SShri Abhyankar PetscErrorCode SNESVIResetPCandKSP(SNES snes,Mat Amat,Mat Pmat) 989732bb160SShri Abhyankar { 990732bb160SShri Abhyankar PetscErrorCode ierr; 991d0af7cd3SBarry Smith KSP snesksp; 992dbd914b8SShri Abhyankar 993732bb160SShri Abhyankar PetscFunctionBegin; 994732bb160SShri Abhyankar ierr = SNESGetKSP(snes,&snesksp);CHKERRQ(ierr); 995d0af7cd3SBarry Smith ierr = KSPReset(snesksp);CHKERRQ(ierr); 996c2efdce3SBarry Smith 997c2efdce3SBarry Smith /* 998d0af7cd3SBarry Smith KSP kspnew; 999d0af7cd3SBarry Smith PC pcnew; 1000d0af7cd3SBarry Smith const MatSolverPackage stype; 1001d0af7cd3SBarry Smith 1002c2efdce3SBarry Smith 1003732bb160SShri Abhyankar ierr = KSPCreate(((PetscObject)snes)->comm,&kspnew);CHKERRQ(ierr); 1004732bb160SShri Abhyankar kspnew->pc_side = snesksp->pc_side; 1005732bb160SShri Abhyankar kspnew->rtol = snesksp->rtol; 1006732bb160SShri Abhyankar kspnew->abstol = snesksp->abstol; 1007732bb160SShri Abhyankar kspnew->max_it = snesksp->max_it; 1008732bb160SShri Abhyankar ierr = KSPSetType(kspnew,((PetscObject)snesksp)->type_name);CHKERRQ(ierr); 1009732bb160SShri Abhyankar ierr = KSPGetPC(kspnew,&pcnew);CHKERRQ(ierr); 1010732bb160SShri Abhyankar ierr = PCSetType(kspnew->pc,((PetscObject)snesksp->pc)->type_name);CHKERRQ(ierr); 1011732bb160SShri Abhyankar ierr = PCSetOperators(kspnew->pc,Amat,Pmat,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr); 1012732bb160SShri Abhyankar ierr = PCFactorGetMatSolverPackage(snesksp->pc,&stype);CHKERRQ(ierr); 1013732bb160SShri Abhyankar ierr = PCFactorSetMatSolverPackage(kspnew->pc,stype);CHKERRQ(ierr); 10146bf464f9SBarry Smith ierr = KSPDestroy(&snesksp);CHKERRQ(ierr); 1015732bb160SShri Abhyankar snes->ksp = kspnew; 1016732bb160SShri Abhyankar ierr = PetscLogObjectParent(snes,kspnew);CHKERRQ(ierr); 1017d0af7cd3SBarry Smith ierr = KSPSetFromOptions(kspnew);CHKERRQ(ierr);*/ 1018732bb160SShri Abhyankar PetscFunctionReturn(0); 1019732bb160SShri Abhyankar } 102069c03620SShri Abhyankar 102169c03620SShri Abhyankar 1022fe835674SShri Abhyankar #undef __FUNCT__ 1023fe835674SShri Abhyankar #define __FUNCT__ "SNESVIComputeInactiveSetFnorm" 102410f5ae6bSBarry Smith PetscErrorCode SNESVIComputeInactiveSetFnorm(SNES snes,Vec F,Vec X,PetscReal *fnorm) 1025fe835674SShri Abhyankar { 1026fe835674SShri Abhyankar PetscErrorCode ierr; 1027fe835674SShri Abhyankar SNES_VI *vi = (SNES_VI*)snes->data; 1028fe835674SShri Abhyankar const PetscScalar *x,*xl,*xu,*f; 1029fe835674SShri Abhyankar PetscInt i,n; 1030fe835674SShri Abhyankar PetscReal rnorm; 1031fe835674SShri Abhyankar 1032fe835674SShri Abhyankar PetscFunctionBegin; 1033fe835674SShri Abhyankar ierr = VecGetLocalSize(X,&n);CHKERRQ(ierr); 1034fe835674SShri Abhyankar ierr = VecGetArrayRead(vi->xl,&xl);CHKERRQ(ierr); 1035fe835674SShri Abhyankar ierr = VecGetArrayRead(vi->xu,&xu);CHKERRQ(ierr); 1036fe835674SShri Abhyankar ierr = VecGetArrayRead(X,&x);CHKERRQ(ierr); 1037fe835674SShri Abhyankar ierr = VecGetArrayRead(F,&f);CHKERRQ(ierr); 1038fe835674SShri Abhyankar rnorm = 0.0; 1039fe835674SShri Abhyankar for (i=0; i<n; i++) { 104010f5ae6bSBarry 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]); 1041fe835674SShri Abhyankar } 1042fe835674SShri Abhyankar ierr = VecRestoreArrayRead(F,&f);CHKERRQ(ierr); 1043fe835674SShri Abhyankar ierr = VecRestoreArrayRead(vi->xl,&xl);CHKERRQ(ierr); 1044fe835674SShri Abhyankar ierr = VecRestoreArrayRead(vi->xu,&xu);CHKERRQ(ierr); 1045fe835674SShri Abhyankar ierr = VecRestoreArrayRead(X,&x);CHKERRQ(ierr); 1046d9822059SBarry Smith ierr = MPI_Allreduce(&rnorm,fnorm,1,MPIU_REAL,MPIU_SUM,((PetscObject)snes)->comm);CHKERRQ(ierr); 1047fe835674SShri Abhyankar *fnorm = sqrt(*fnorm); 1048fe835674SShri Abhyankar PetscFunctionReturn(0); 1049fe835674SShri Abhyankar } 1050fe835674SShri Abhyankar 1051fe835674SShri Abhyankar /* Variational Inequality solver using reduce space method. No semismooth algorithm is 1052c2efdce3SBarry Smith implemented in this algorithm. It basically identifies the active constraints and does 1053c2efdce3SBarry Smith a linear solve on the other variables (those not associated with the active constraints). */ 1054d950fb63SShri Abhyankar #undef __FUNCT__ 1055d950fb63SShri Abhyankar #define __FUNCT__ "SNESSolveVI_RS" 1056d950fb63SShri Abhyankar PetscErrorCode SNESSolveVI_RS(SNES snes) 1057d950fb63SShri Abhyankar { 1058d950fb63SShri Abhyankar SNES_VI *vi = (SNES_VI*)snes->data; 1059d950fb63SShri Abhyankar PetscErrorCode ierr; 1060abcba341SShri Abhyankar PetscInt maxits,i,lits; 1061d950fb63SShri Abhyankar PetscBool lssucceed; 1062d950fb63SShri Abhyankar MatStructure flg = DIFFERENT_NONZERO_PATTERN; 1063fe835674SShri Abhyankar PetscReal fnorm,gnorm,xnorm=0,ynorm; 1064d950fb63SShri Abhyankar Vec Y,X,F,G,W; 1065d950fb63SShri Abhyankar KSPConvergedReason kspreason; 1066d950fb63SShri Abhyankar 1067d950fb63SShri Abhyankar PetscFunctionBegin; 1068d950fb63SShri Abhyankar snes->numFailures = 0; 1069d950fb63SShri Abhyankar snes->numLinearSolveFailures = 0; 1070d950fb63SShri Abhyankar snes->reason = SNES_CONVERGED_ITERATING; 1071d950fb63SShri Abhyankar 1072d950fb63SShri Abhyankar maxits = snes->max_its; /* maximum number of iterations */ 1073d950fb63SShri Abhyankar X = snes->vec_sol; /* solution vector */ 1074d950fb63SShri Abhyankar F = snes->vec_func; /* residual vector */ 1075d950fb63SShri Abhyankar Y = snes->work[0]; /* work vectors */ 1076d950fb63SShri Abhyankar G = snes->work[1]; 1077d950fb63SShri Abhyankar W = snes->work[2]; 1078d950fb63SShri Abhyankar 1079d950fb63SShri Abhyankar ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 1080d950fb63SShri Abhyankar snes->iter = 0; 1081d950fb63SShri Abhyankar snes->norm = 0.0; 1082d950fb63SShri Abhyankar ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 1083d950fb63SShri Abhyankar 10847fe79bc4SShri Abhyankar ierr = SNESVIProjectOntoBounds(snes,X);CHKERRQ(ierr); 1085fe835674SShri Abhyankar ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr); 1086d950fb63SShri Abhyankar if (snes->domainerror) { 1087d950fb63SShri Abhyankar snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN; 1088d950fb63SShri Abhyankar PetscFunctionReturn(0); 1089d950fb63SShri Abhyankar } 1090fe835674SShri Abhyankar ierr = SNESVIComputeInactiveSetFnorm(snes,F,X,&fnorm);CHKERRQ(ierr); 1091d950fb63SShri Abhyankar ierr = VecNormBegin(X,NORM_2,&xnorm);CHKERRQ(ierr); /* xnorm <- ||x|| */ 1092d950fb63SShri Abhyankar ierr = VecNormEnd(X,NORM_2,&xnorm);CHKERRQ(ierr); 109362cbcd01SMatthew G Knepley if (PetscIsInfOrNanReal(fnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number"); 1094d950fb63SShri Abhyankar 1095d950fb63SShri Abhyankar ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 1096fe835674SShri Abhyankar snes->norm = fnorm; 1097d950fb63SShri Abhyankar ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 1098fe835674SShri Abhyankar SNESLogConvHistory(snes,fnorm,0); 10997a03ce2fSLisandro Dalcin ierr = SNESMonitor(snes,0,fnorm);CHKERRQ(ierr); 1100d950fb63SShri Abhyankar 1101d950fb63SShri Abhyankar /* set parameter for default relative tolerance convergence test */ 1102fe835674SShri Abhyankar snes->ttol = fnorm*snes->rtol; 1103d950fb63SShri Abhyankar /* test convergence */ 1104fe835674SShri Abhyankar ierr = (*snes->ops->converged)(snes,0,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); 1105d950fb63SShri Abhyankar if (snes->reason) PetscFunctionReturn(0); 1106d950fb63SShri Abhyankar 11079ce20c35SJungho Lee 1108d950fb63SShri Abhyankar for (i=0; i<maxits; i++) { 1109d950fb63SShri Abhyankar 1110d950fb63SShri Abhyankar IS IS_act,IS_inact; /* _act -> active set _inact -> inactive set */ 1111a6b72b01SJungho Lee IS IS_redact; /* redundant active set */ 1112d950fb63SShri Abhyankar VecScatter scat_act,scat_inact; 1113abcba341SShri Abhyankar PetscInt nis_act,nis_inact; 1114fe835674SShri Abhyankar Vec Y_act,Y_inact,F_inact; 1115d950fb63SShri Abhyankar Mat jac_inact_inact,prejac_inact_inact; 111662298a1eSBarry Smith IS keptrows; 1117abcba341SShri Abhyankar PetscBool isequal; 1118d950fb63SShri Abhyankar 1119d950fb63SShri Abhyankar /* Call general purpose update function */ 1120d950fb63SShri Abhyankar if (snes->ops->update) { 1121d950fb63SShri Abhyankar ierr = (*snes->ops->update)(snes, snes->iter);CHKERRQ(ierr); 1122d950fb63SShri Abhyankar } 1123d950fb63SShri Abhyankar ierr = SNESComputeJacobian(snes,X,&snes->jacobian,&snes->jacobian_pre,&flg);CHKERRQ(ierr); 112462298a1eSBarry Smith 11259ce20c35SJungho Lee 1126d950fb63SShri Abhyankar /* Create active and inactive index sets */ 1127a6b72b01SJungho Lee 1128a6b72b01SJungho Lee /*original 1129693ddf92SShri Abhyankar ierr = SNESVICreateIndexSets_RS(snes,X,F,&IS_act,&IS_inact);CHKERRQ(ierr); 1130a6b72b01SJungho Lee */ 1131a6b72b01SJungho Lee ierr = SNESVIGetActiveSetIS(snes,X,F,&IS_act);CHKERRQ(ierr); 1132a6b72b01SJungho Lee 1133a6b72b01SJungho Lee if (vi->checkredundancy) { 1134a6b72b01SJungho Lee (*vi->checkredundancy)(snes,IS_act,&IS_redact,vi->ctxP);CHKERRQ(ierr); 1135ed70e96aSJungho Lee if (IS_redact){ 1136ed70e96aSJungho Lee ierr = ISSort(IS_redact);CHKERRQ(ierr); 1137a6b72b01SJungho Lee ierr = ISComplement(IS_redact,X->map->rstart,X->map->rend,&IS_inact);CHKERRQ(ierr); 1138a6b72b01SJungho Lee ierr = ISDestroy(&IS_redact);CHKERRQ(ierr); 1139ed70e96aSJungho Lee } 1140ed70e96aSJungho Lee else { 1141ed70e96aSJungho Lee ierr = ISComplement(IS_act,X->map->rstart,X->map->rend,&IS_inact);CHKERRQ(ierr); 1142ed70e96aSJungho Lee } 1143a6b72b01SJungho Lee } else { 1144a6b72b01SJungho Lee ierr = ISComplement(IS_act,X->map->rstart,X->map->rend,&IS_inact);CHKERRQ(ierr); 1145a6b72b01SJungho Lee } 1146d950fb63SShri Abhyankar 11474dcab191SBarry Smith 1148abcba341SShri Abhyankar /* Create inactive set submatrix */ 114962298a1eSBarry Smith ierr = MatGetSubMatrix(snes->jacobian,IS_inact,IS_inact,MAT_INITIAL_MATRIX,&jac_inact_inact);CHKERRQ(ierr); 1150a6b72b01SJungho Lee 1151b3a44c85SBarry Smith ierr = MatFindNonzeroRows(jac_inact_inact,&keptrows);CHKERRQ(ierr); 11529ce20c35SJungho Lee if (0 && keptrows) { 11539ce20c35SJungho Lee // if (keptrows) { 115462298a1eSBarry Smith PetscInt cnt,*nrows,k; 115562298a1eSBarry Smith const PetscInt *krows,*inact; 115627d4218bSShri Abhyankar PetscInt rstart=jac_inact_inact->rmap->rstart; 115762298a1eSBarry Smith 11586bf464f9SBarry Smith ierr = MatDestroy(&jac_inact_inact);CHKERRQ(ierr); 11596bf464f9SBarry Smith ierr = ISDestroy(&IS_act);CHKERRQ(ierr); 116062298a1eSBarry Smith 116162298a1eSBarry Smith ierr = ISGetLocalSize(keptrows,&cnt);CHKERRQ(ierr); 116262298a1eSBarry Smith ierr = ISGetIndices(keptrows,&krows);CHKERRQ(ierr); 116362298a1eSBarry Smith ierr = ISGetIndices(IS_inact,&inact);CHKERRQ(ierr); 116462298a1eSBarry Smith ierr = PetscMalloc(cnt*sizeof(PetscInt),&nrows);CHKERRQ(ierr); 116562298a1eSBarry Smith for (k=0; k<cnt; k++) { 116627d4218bSShri Abhyankar nrows[k] = inact[krows[k]-rstart]; 116762298a1eSBarry Smith } 116862298a1eSBarry Smith ierr = ISRestoreIndices(keptrows,&krows);CHKERRQ(ierr); 116962298a1eSBarry Smith ierr = ISRestoreIndices(IS_inact,&inact);CHKERRQ(ierr); 11706bf464f9SBarry Smith ierr = ISDestroy(&keptrows);CHKERRQ(ierr); 11716bf464f9SBarry Smith ierr = ISDestroy(&IS_inact);CHKERRQ(ierr); 117262298a1eSBarry Smith 117327d4218bSShri Abhyankar ierr = ISCreateGeneral(PETSC_COMM_WORLD,cnt,nrows,PETSC_OWN_POINTER,&IS_inact);CHKERRQ(ierr); 117427d4218bSShri Abhyankar ierr = ISComplement(IS_inact,F->map->rstart,F->map->rend,&IS_act);CHKERRQ(ierr); 117562298a1eSBarry Smith ierr = MatGetSubMatrix(snes->jacobian,IS_inact,IS_inact,MAT_INITIAL_MATRIX,&jac_inact_inact);CHKERRQ(ierr); 117662298a1eSBarry Smith } 11779ce20c35SJungho Lee ierr = DMSetVI(snes->dm,IS_inact);CHKERRQ(ierr); 11789ce20c35SJungho Lee /* remove later */ 11799ce20c35SJungho Lee 11809ce20c35SJungho Lee /* 11819ce20c35SJungho Lee ierr = VecView(vi->xu,PETSC_VIEWER_BINARY_(PETSC_COMM_WORLD));CHKERRQ(ierr); 11829ce20c35SJungho Lee ierr = VecView(vi->xl,PETSC_VIEWER_BINARY_(PETSC_COMM_WORLD));CHKERRQ(ierr); 11839ce20c35SJungho Lee ierr = VecView(X,PETSC_VIEWER_BINARY_(PETSC_COMM_WORLD));CHKERRQ(ierr); 11849ce20c35SJungho Lee ierr = VecView(F,PETSC_VIEWER_BINARY_(PETSC_COMM_WORLD));CHKERRQ(ierr); 11859ce20c35SJungho Lee ierr = ISView(IS_inact,PETSC_VIEWER_BINARY_(PETSC_COMM_WORLD));CHKERRQ(ierr); 11869ce20c35SJungho Lee */ 118762298a1eSBarry Smith 1188d950fb63SShri Abhyankar /* Get sizes of active and inactive sets */ 1189d950fb63SShri Abhyankar ierr = ISGetLocalSize(IS_act,&nis_act);CHKERRQ(ierr); 1190d950fb63SShri Abhyankar ierr = ISGetLocalSize(IS_inact,&nis_inact);CHKERRQ(ierr); 1191d950fb63SShri Abhyankar 1192d950fb63SShri Abhyankar /* Create active and inactive set vectors */ 1193fe835674SShri Abhyankar ierr = SNESVICreateSubVectors(snes,nis_inact,&F_inact);CHKERRQ(ierr); 1194fe835674SShri Abhyankar ierr = SNESVICreateSubVectors(snes,nis_act,&Y_act);CHKERRQ(ierr); 1195fe835674SShri Abhyankar ierr = SNESVICreateSubVectors(snes,nis_inact,&Y_inact);CHKERRQ(ierr); 1196d950fb63SShri Abhyankar 1197d950fb63SShri Abhyankar /* Create scatter contexts */ 1198d950fb63SShri Abhyankar ierr = VecScatterCreate(Y,IS_act,Y_act,PETSC_NULL,&scat_act);CHKERRQ(ierr); 1199d950fb63SShri Abhyankar ierr = VecScatterCreate(Y,IS_inact,Y_inact,PETSC_NULL,&scat_inact);CHKERRQ(ierr); 1200d950fb63SShri Abhyankar 1201d950fb63SShri Abhyankar /* Do a vec scatter to active and inactive set vectors */ 1202fe835674SShri Abhyankar ierr = VecScatterBegin(scat_inact,F,F_inact,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1203fe835674SShri Abhyankar ierr = VecScatterEnd(scat_inact,F,F_inact,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1204d950fb63SShri Abhyankar 1205d950fb63SShri Abhyankar ierr = VecScatterBegin(scat_act,Y,Y_act,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1206d950fb63SShri Abhyankar ierr = VecScatterEnd(scat_act,Y,Y_act,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1207d950fb63SShri Abhyankar 1208d950fb63SShri Abhyankar ierr = VecScatterBegin(scat_inact,Y,Y_inact,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1209d950fb63SShri Abhyankar ierr = VecScatterEnd(scat_inact,Y,Y_inact,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1210d950fb63SShri Abhyankar 1211d950fb63SShri Abhyankar /* Active set direction = 0 */ 1212d950fb63SShri Abhyankar ierr = VecSet(Y_act,0);CHKERRQ(ierr); 1213d950fb63SShri Abhyankar if (snes->jacobian != snes->jacobian_pre) { 1214d950fb63SShri Abhyankar ierr = MatGetSubMatrix(snes->jacobian_pre,IS_inact,IS_inact,MAT_INITIAL_MATRIX,&prejac_inact_inact);CHKERRQ(ierr); 1215d950fb63SShri Abhyankar } else prejac_inact_inact = jac_inact_inact; 1216d950fb63SShri Abhyankar 1217abcba341SShri Abhyankar ierr = ISEqual(vi->IS_inact_prev,IS_inact,&isequal);CHKERRQ(ierr); 1218abcba341SShri Abhyankar if (!isequal) { 1219732bb160SShri Abhyankar ierr = SNESVIResetPCandKSP(snes,jac_inact_inact,prejac_inact_inact);CHKERRQ(ierr); 1220c58c0d17SBarry Smith flg = DIFFERENT_NONZERO_PATTERN; 1221d950fb63SShri Abhyankar } 1222d950fb63SShri Abhyankar 122313e0d083SBarry Smith /* ierr = ISView(IS_inact,0);CHKERRQ(ierr); */ 122413e0d083SBarry Smith /* ierr = ISView(IS_act,0);CHKERRQ(ierr);*/ 122513e0d083SBarry Smith /* ierr = MatView(snes->jacobian_pre,0); */ 122613e0d083SBarry Smith 1227f15307b4SJungho Lee 12289ce20c35SJungho Lee 1229d950fb63SShri Abhyankar ierr = KSPSetOperators(snes->ksp,jac_inact_inact,prejac_inact_inact,flg);CHKERRQ(ierr); 123013e0d083SBarry Smith ierr = KSPSetUp(snes->ksp);CHKERRQ(ierr); 123113e0d083SBarry Smith { 123213e0d083SBarry Smith PC pc; 123313e0d083SBarry Smith PetscBool flg; 123413e0d083SBarry Smith ierr = KSPGetPC(snes->ksp,&pc);CHKERRQ(ierr); 123513e0d083SBarry Smith ierr = PetscTypeCompare((PetscObject)pc,PCFIELDSPLIT,&flg);CHKERRQ(ierr); 123613e0d083SBarry Smith if (flg) { 123713e0d083SBarry Smith KSP *subksps; 123813e0d083SBarry Smith ierr = PCFieldSplitGetSubKSP(pc,PETSC_NULL,&subksps);CHKERRQ(ierr); 123913e0d083SBarry Smith ierr = KSPGetPC(subksps[0],&pc);CHKERRQ(ierr); 124013e0d083SBarry Smith ierr = PetscFree(subksps);CHKERRQ(ierr); 124113e0d083SBarry Smith ierr = PetscTypeCompare((PetscObject)pc,PCBJACOBI,&flg);CHKERRQ(ierr); 124213e0d083SBarry Smith if (flg) { 124313e0d083SBarry Smith PetscInt n,N = 101*101,j,cnts[3] = {0,0,0}; 124413e0d083SBarry Smith const PetscInt *ii; 124513e0d083SBarry Smith 124613e0d083SBarry Smith ierr = ISGetSize(IS_inact,&n);CHKERRQ(ierr); 124713e0d083SBarry Smith ierr = ISGetIndices(IS_inact,&ii);CHKERRQ(ierr); 124813e0d083SBarry Smith for (j=0; j<n; j++) { 124913e0d083SBarry Smith if (ii[j] < N) cnts[0]++; 125013e0d083SBarry Smith else if (ii[j] < 2*N) cnts[1]++; 125113e0d083SBarry Smith else if (ii[j] < 3*N) cnts[2]++; 125213e0d083SBarry Smith } 125313e0d083SBarry Smith ierr = ISRestoreIndices(IS_inact,&ii);CHKERRQ(ierr); 125413e0d083SBarry Smith 125513e0d083SBarry Smith ierr = PCBJacobiSetTotalBlocks(pc,3,cnts);CHKERRQ(ierr); 125613e0d083SBarry Smith } 125713e0d083SBarry Smith } 125813e0d083SBarry Smith } 125913e0d083SBarry Smith 1260fe835674SShri Abhyankar ierr = SNES_KSPSolve(snes,snes->ksp,F_inact,Y_inact);CHKERRQ(ierr); 1261d950fb63SShri Abhyankar ierr = KSPGetConvergedReason(snes->ksp,&kspreason);CHKERRQ(ierr); 1262d950fb63SShri Abhyankar if (kspreason < 0) { 1263d950fb63SShri Abhyankar if (++snes->numLinearSolveFailures >= snes->maxLinearSolveFailures) { 1264d950fb63SShri 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); 1265d950fb63SShri Abhyankar snes->reason = SNES_DIVERGED_LINEAR_SOLVE; 1266d950fb63SShri Abhyankar break; 1267d950fb63SShri Abhyankar } 1268d950fb63SShri Abhyankar } 1269d950fb63SShri Abhyankar 1270d950fb63SShri Abhyankar ierr = VecScatterBegin(scat_act,Y_act,Y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1271d950fb63SShri Abhyankar ierr = VecScatterEnd(scat_act,Y_act,Y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1272d950fb63SShri Abhyankar ierr = VecScatterBegin(scat_inact,Y_inact,Y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1273d950fb63SShri Abhyankar ierr = VecScatterEnd(scat_inact,Y_inact,Y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1274d950fb63SShri Abhyankar 12756bf464f9SBarry Smith ierr = VecDestroy(&F_inact);CHKERRQ(ierr); 12766bf464f9SBarry Smith ierr = VecDestroy(&Y_act);CHKERRQ(ierr); 12776bf464f9SBarry Smith ierr = VecDestroy(&Y_inact);CHKERRQ(ierr); 12786bf464f9SBarry Smith ierr = VecScatterDestroy(&scat_act);CHKERRQ(ierr); 12796bf464f9SBarry Smith ierr = VecScatterDestroy(&scat_inact);CHKERRQ(ierr); 12806bf464f9SBarry Smith ierr = ISDestroy(&IS_act);CHKERRQ(ierr); 1281abcba341SShri Abhyankar if (!isequal) { 12826bf464f9SBarry Smith ierr = ISDestroy(&vi->IS_inact_prev);CHKERRQ(ierr); 1283abcba341SShri Abhyankar ierr = ISDuplicate(IS_inact,&vi->IS_inact_prev);CHKERRQ(ierr); 1284abcba341SShri Abhyankar } 12856bf464f9SBarry Smith ierr = ISDestroy(&IS_inact);CHKERRQ(ierr); 12866bf464f9SBarry Smith ierr = MatDestroy(&jac_inact_inact);CHKERRQ(ierr); 1287d950fb63SShri Abhyankar if (snes->jacobian != snes->jacobian_pre) { 12886bf464f9SBarry Smith ierr = MatDestroy(&prejac_inact_inact);CHKERRQ(ierr); 1289d950fb63SShri Abhyankar } 1290d950fb63SShri Abhyankar ierr = KSPGetIterationNumber(snes->ksp,&lits);CHKERRQ(ierr); 1291d950fb63SShri Abhyankar snes->linear_its += lits; 1292d950fb63SShri Abhyankar ierr = PetscInfo2(snes,"iter=%D, linear solve iterations=%D\n",snes->iter,lits);CHKERRQ(ierr); 1293d950fb63SShri Abhyankar /* 1294d950fb63SShri Abhyankar if (vi->precheckstep) { 1295d950fb63SShri Abhyankar PetscBool changed_y = PETSC_FALSE; 1296d950fb63SShri Abhyankar ierr = (*vi->precheckstep)(snes,X,Y,vi->precheck,&changed_y);CHKERRQ(ierr); 1297d950fb63SShri Abhyankar } 1298d950fb63SShri Abhyankar 1299d950fb63SShri Abhyankar if (PetscLogPrintInfo){ 1300d950fb63SShri Abhyankar ierr = SNESVICheckResidual_Private(snes,snes->jacobian,F,Y,G,W);CHKERRQ(ierr); 1301d950fb63SShri Abhyankar } 1302d950fb63SShri Abhyankar */ 1303d950fb63SShri Abhyankar /* Compute a (scaled) negative update in the line search routine: 1304d950fb63SShri Abhyankar Y <- X - lambda*Y 1305d950fb63SShri Abhyankar and evaluate G = function(Y) (depends on the line search). 1306d950fb63SShri Abhyankar */ 1307d950fb63SShri Abhyankar ierr = VecCopy(Y,snes->vec_sol_update);CHKERRQ(ierr); 1308fe835674SShri Abhyankar ynorm = 1; gnorm = fnorm; 1309fe835674SShri Abhyankar ierr = (*vi->LineSearch)(snes,vi->lsP,X,F,G,Y,W,fnorm,xnorm,&ynorm,&gnorm,&lssucceed);CHKERRQ(ierr); 1310fe835674SShri Abhyankar ierr = PetscInfo4(snes,"fnorm=%18.16e, gnorm=%18.16e, ynorm=%18.16e, lssucceed=%d\n",fnorm,gnorm,ynorm,(int)lssucceed);CHKERRQ(ierr); 13112b4ed282SShri Abhyankar if (snes->reason == SNES_DIVERGED_FUNCTION_COUNT) break; 13122b4ed282SShri Abhyankar if (snes->domainerror) { 13132b4ed282SShri Abhyankar snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN; 13144c661befSBarry Smith ierr = DMDestroyVI(snes->dm);CHKERRQ(ierr); 13152b4ed282SShri Abhyankar PetscFunctionReturn(0); 13162b4ed282SShri Abhyankar } 13172b4ed282SShri Abhyankar if (!lssucceed) { 13182b4ed282SShri Abhyankar if (++snes->numFailures >= snes->maxFailures) { 13192b4ed282SShri Abhyankar PetscBool ismin; 13202b4ed282SShri Abhyankar snes->reason = SNES_DIVERGED_LINE_SEARCH; 13212b4ed282SShri Abhyankar ierr = SNESVICheckLocalMin_Private(snes,snes->jacobian,G,W,gnorm,&ismin);CHKERRQ(ierr); 13222b4ed282SShri Abhyankar if (ismin) snes->reason = SNES_DIVERGED_LOCAL_MIN; 13232b4ed282SShri Abhyankar break; 13242b4ed282SShri Abhyankar } 13252b4ed282SShri Abhyankar } 13262b4ed282SShri Abhyankar /* Update function and solution vectors */ 1327fe835674SShri Abhyankar fnorm = gnorm; 1328fe835674SShri Abhyankar ierr = VecCopy(G,F);CHKERRQ(ierr); 13292b4ed282SShri Abhyankar ierr = VecCopy(W,X);CHKERRQ(ierr); 13302b4ed282SShri Abhyankar /* Monitor convergence */ 13312b4ed282SShri Abhyankar ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 13322b4ed282SShri Abhyankar snes->iter = i+1; 1333fe835674SShri Abhyankar snes->norm = fnorm; 13342b4ed282SShri Abhyankar ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 13352b4ed282SShri Abhyankar SNESLogConvHistory(snes,snes->norm,lits); 13367a03ce2fSLisandro Dalcin ierr = SNESMonitor(snes,snes->iter,snes->norm);CHKERRQ(ierr); 13372b4ed282SShri Abhyankar /* Test for convergence, xnorm = || X || */ 13382b4ed282SShri Abhyankar if (snes->ops->converged != SNESSkipConverged) { ierr = VecNorm(X,NORM_2,&xnorm);CHKERRQ(ierr); } 1339fe835674SShri Abhyankar ierr = (*snes->ops->converged)(snes,snes->iter,xnorm,ynorm,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); 13402b4ed282SShri Abhyankar if (snes->reason) break; 13412b4ed282SShri Abhyankar } 13424c661befSBarry Smith ierr = DMDestroyVI(snes->dm);CHKERRQ(ierr); 13432b4ed282SShri Abhyankar if (i == maxits) { 13442b4ed282SShri Abhyankar ierr = PetscInfo1(snes,"Maximum number of iterations has been reached: %D\n",maxits);CHKERRQ(ierr); 13452b4ed282SShri Abhyankar if(!snes->reason) snes->reason = SNES_DIVERGED_MAX_IT; 13462b4ed282SShri Abhyankar } 13472b4ed282SShri Abhyankar PetscFunctionReturn(0); 13482b4ed282SShri Abhyankar } 13492b4ed282SShri Abhyankar 13502f63a38cSShri Abhyankar #undef __FUNCT__ 1351720c9a41SShri Abhyankar #define __FUNCT__ "SNESVISetRedundancyCheck" 1352cb5fe31bSShri Abhyankar PetscErrorCode SNESVISetRedundancyCheck(SNES snes,PetscErrorCode (*func)(SNES,IS,IS*,void*),void *ctx) 13532f63a38cSShri Abhyankar { 13542f63a38cSShri Abhyankar SNES_VI *vi = (SNES_VI*)snes->data; 13552f63a38cSShri Abhyankar 13562f63a38cSShri Abhyankar PetscFunctionBegin; 13572f63a38cSShri Abhyankar PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 13582f63a38cSShri Abhyankar vi->checkredundancy = func; 1359cb5fe31bSShri Abhyankar vi->ctxP = ctx; 13602f63a38cSShri Abhyankar PetscFunctionReturn(0); 13612f63a38cSShri Abhyankar } 13622f63a38cSShri Abhyankar 1363ff596062SShri Abhyankar #if defined(PETSC_HAVE_MATLAB_ENGINE) 1364ff596062SShri Abhyankar #include <engine.h> 1365ff596062SShri Abhyankar #include <mex.h> 1366cb5fe31bSShri Abhyankar typedef struct {char *funcname; mxArray *ctx;} SNESMatlabContext; 1367ff596062SShri Abhyankar 1368ff596062SShri Abhyankar #undef __FUNCT__ 1369ff596062SShri Abhyankar #define __FUNCT__ "SNESVIRedundancyCheck_Matlab" 1370ff596062SShri Abhyankar PetscErrorCode SNESVIRedundancyCheck_Matlab(SNES snes,IS is_act,IS* is_redact,void* ctx) 1371ff596062SShri Abhyankar { 1372ff596062SShri Abhyankar PetscErrorCode ierr; 1373cb5fe31bSShri Abhyankar SNESMatlabContext *sctx = (SNESMatlabContext*)ctx; 1374cb5fe31bSShri Abhyankar int nlhs = 1, nrhs = 5; 1375cb5fe31bSShri Abhyankar mxArray *plhs[1], *prhs[5]; 1376cb5fe31bSShri Abhyankar long long int l1 = 0, l2 = 0, ls = 0; 1377fcb1c9afSShri Abhyankar PetscInt *indices=PETSC_NULL; 1378ff596062SShri Abhyankar 1379ff596062SShri Abhyankar PetscFunctionBegin; 1380ff596062SShri Abhyankar PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 1381ff596062SShri Abhyankar PetscValidHeaderSpecific(is_act,IS_CLASSID,2); 1382ff596062SShri Abhyankar PetscValidPointer(is_redact,3); 1383ff596062SShri Abhyankar PetscCheckSameComm(snes,1,is_act,2); 1384ff596062SShri Abhyankar 138509db5ad8SShri Abhyankar /* Create IS for reduced active set of size 0, its size and indices will 138609db5ad8SShri Abhyankar bet set by the Matlab function */ 1387fcb1c9afSShri Abhyankar ierr = ISCreateGeneral(((PetscObject)snes)->comm,0,indices,PETSC_OWN_POINTER,is_redact);CHKERRQ(ierr); 1388cb5fe31bSShri Abhyankar /* call Matlab function in ctx */ 1389ff596062SShri Abhyankar ierr = PetscMemcpy(&ls,&snes,sizeof(snes));CHKERRQ(ierr); 1390ff596062SShri Abhyankar ierr = PetscMemcpy(&l1,&is_act,sizeof(is_act));CHKERRQ(ierr); 1391cb5fe31bSShri Abhyankar ierr = PetscMemcpy(&l2,is_redact,sizeof(is_act));CHKERRQ(ierr); 1392ff596062SShri Abhyankar prhs[0] = mxCreateDoubleScalar((double)ls); 1393ff596062SShri Abhyankar prhs[1] = mxCreateDoubleScalar((double)l1); 1394cb5fe31bSShri Abhyankar prhs[2] = mxCreateDoubleScalar((double)l2); 1395cb5fe31bSShri Abhyankar prhs[3] = mxCreateString(sctx->funcname); 1396cb5fe31bSShri Abhyankar prhs[4] = sctx->ctx; 1397ff596062SShri Abhyankar ierr = mexCallMATLAB(nlhs,plhs,nrhs,prhs,"PetscSNESVIRedundancyCheckInternal");CHKERRQ(ierr); 1398ff596062SShri Abhyankar ierr = mxGetScalar(plhs[0]);CHKERRQ(ierr); 1399ff596062SShri Abhyankar mxDestroyArray(prhs[0]); 1400ff596062SShri Abhyankar mxDestroyArray(prhs[1]); 1401ff596062SShri Abhyankar mxDestroyArray(prhs[2]); 1402ff596062SShri Abhyankar mxDestroyArray(prhs[3]); 1403ff596062SShri Abhyankar mxDestroyArray(plhs[0]); 1404ff596062SShri Abhyankar PetscFunctionReturn(0); 1405ff596062SShri Abhyankar } 1406ff596062SShri Abhyankar 1407ff596062SShri Abhyankar #undef __FUNCT__ 1408ff596062SShri Abhyankar #define __FUNCT__ "SNESVISetRedundancyCheckMatlab" 1409ff596062SShri Abhyankar PetscErrorCode SNESVISetRedundancyCheckMatlab(SNES snes,const char* func,mxArray* ctx) 1410ff596062SShri Abhyankar { 1411ff596062SShri Abhyankar PetscErrorCode ierr; 1412cb5fe31bSShri Abhyankar SNESMatlabContext *sctx; 1413ff596062SShri Abhyankar 1414ff596062SShri Abhyankar PetscFunctionBegin; 1415ff596062SShri Abhyankar /* currently sctx is memory bleed */ 1416cb5fe31bSShri Abhyankar ierr = PetscMalloc(sizeof(SNESMatlabContext),&sctx);CHKERRQ(ierr); 1417ff596062SShri Abhyankar ierr = PetscStrallocpy(func,&sctx->funcname);CHKERRQ(ierr); 1418ff596062SShri Abhyankar sctx->ctx = mxDuplicateArray(ctx); 1419cb5fe31bSShri Abhyankar ierr = SNESVISetRedundancyCheck(snes,SNESVIRedundancyCheck_Matlab,sctx);CHKERRQ(ierr); 1420ff596062SShri Abhyankar PetscFunctionReturn(0); 1421ff596062SShri Abhyankar } 1422ff596062SShri Abhyankar 1423ff596062SShri Abhyankar #endif 1424ff596062SShri Abhyankar 1425ff596062SShri Abhyankar 14262f63a38cSShri Abhyankar /* Variational Inequality solver using augmented space method. It does the opposite of the 14272f63a38cSShri Abhyankar reduced space method i.e. it identifies the active set variables and instead of discarding 1428720c9a41SShri Abhyankar them it augments the original system by introducing additional equality 142956a221efSShri Abhyankar constraint equations for active set variables. The user can optionally provide an IS for 143056a221efSShri Abhyankar a subset of 'redundant' active set variables which will treated as free variables. 14312f63a38cSShri Abhyankar Specific implementation for Allen-Cahn problem 14322f63a38cSShri Abhyankar */ 14332f63a38cSShri Abhyankar #undef __FUNCT__ 1434b350b9c9SBarry Smith #define __FUNCT__ "SNESSolveVI_RSAUG" 1435b350b9c9SBarry Smith PetscErrorCode SNESSolveVI_RSAUG(SNES snes) 14362f63a38cSShri Abhyankar { 14372f63a38cSShri Abhyankar SNES_VI *vi = (SNES_VI*)snes->data; 14382f63a38cSShri Abhyankar PetscErrorCode ierr; 14392f63a38cSShri Abhyankar PetscInt maxits,i,lits; 14402f63a38cSShri Abhyankar PetscBool lssucceed; 14412f63a38cSShri Abhyankar MatStructure flg = DIFFERENT_NONZERO_PATTERN; 14422f63a38cSShri Abhyankar PetscReal fnorm,gnorm,xnorm=0,ynorm; 14432f63a38cSShri Abhyankar Vec Y,X,F,G,W; 14442f63a38cSShri Abhyankar KSPConvergedReason kspreason; 14452f63a38cSShri Abhyankar 14462f63a38cSShri Abhyankar PetscFunctionBegin; 14472f63a38cSShri Abhyankar snes->numFailures = 0; 14482f63a38cSShri Abhyankar snes->numLinearSolveFailures = 0; 14492f63a38cSShri Abhyankar snes->reason = SNES_CONVERGED_ITERATING; 14502f63a38cSShri Abhyankar 14512f63a38cSShri Abhyankar maxits = snes->max_its; /* maximum number of iterations */ 14522f63a38cSShri Abhyankar X = snes->vec_sol; /* solution vector */ 14532f63a38cSShri Abhyankar F = snes->vec_func; /* residual vector */ 14542f63a38cSShri Abhyankar Y = snes->work[0]; /* work vectors */ 14552f63a38cSShri Abhyankar G = snes->work[1]; 14562f63a38cSShri Abhyankar W = snes->work[2]; 14572f63a38cSShri Abhyankar 14582f63a38cSShri Abhyankar ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 14592f63a38cSShri Abhyankar snes->iter = 0; 14602f63a38cSShri Abhyankar snes->norm = 0.0; 14612f63a38cSShri Abhyankar ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 14622f63a38cSShri Abhyankar 14632f63a38cSShri Abhyankar ierr = SNESVIProjectOntoBounds(snes,X);CHKERRQ(ierr); 14642f63a38cSShri Abhyankar ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr); 14652f63a38cSShri Abhyankar if (snes->domainerror) { 14662f63a38cSShri Abhyankar snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN; 14672f63a38cSShri Abhyankar PetscFunctionReturn(0); 14682f63a38cSShri Abhyankar } 14692f63a38cSShri Abhyankar ierr = SNESVIComputeInactiveSetFnorm(snes,F,X,&fnorm);CHKERRQ(ierr); 14702f63a38cSShri Abhyankar ierr = VecNormBegin(X,NORM_2,&xnorm);CHKERRQ(ierr); /* xnorm <- ||x|| */ 14712f63a38cSShri Abhyankar ierr = VecNormEnd(X,NORM_2,&xnorm);CHKERRQ(ierr); 147262cbcd01SMatthew G Knepley if (PetscIsInfOrNanReal(fnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number"); 14732f63a38cSShri Abhyankar 14742f63a38cSShri Abhyankar ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 14752f63a38cSShri Abhyankar snes->norm = fnorm; 14762f63a38cSShri Abhyankar ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 14772f63a38cSShri Abhyankar SNESLogConvHistory(snes,fnorm,0); 14787a03ce2fSLisandro Dalcin ierr = SNESMonitor(snes,0,fnorm);CHKERRQ(ierr); 14792f63a38cSShri Abhyankar 14802f63a38cSShri Abhyankar /* set parameter for default relative tolerance convergence test */ 14812f63a38cSShri Abhyankar snes->ttol = fnorm*snes->rtol; 14822f63a38cSShri Abhyankar /* test convergence */ 14832f63a38cSShri Abhyankar ierr = (*snes->ops->converged)(snes,0,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); 14842f63a38cSShri Abhyankar if (snes->reason) PetscFunctionReturn(0); 14852f63a38cSShri Abhyankar 14862f63a38cSShri Abhyankar for (i=0; i<maxits; i++) { 14872f63a38cSShri Abhyankar IS IS_act,IS_inact; /* _act -> active set _inact -> inactive set */ 1488cb5fe31bSShri Abhyankar IS IS_redact; /* redundant active set */ 148956a221efSShri Abhyankar Mat J_aug,Jpre_aug; 149056a221efSShri Abhyankar Vec F_aug,Y_aug; 149156a221efSShri Abhyankar PetscInt nis_redact,nis_act; 149256a221efSShri Abhyankar const PetscInt *idx_redact,*idx_act; 149356a221efSShri Abhyankar PetscInt k; 149463ee972cSSatish Balay PetscInt *idx_actkept=PETSC_NULL,nkept=0; /* list of kept active set */ 149556a221efSShri Abhyankar PetscScalar *f,*f2; 14962f63a38cSShri Abhyankar PetscBool isequal; 149756a221efSShri Abhyankar PetscInt i1=0,j1=0; 14982f63a38cSShri Abhyankar 14992f63a38cSShri Abhyankar /* Call general purpose update function */ 15002f63a38cSShri Abhyankar if (snes->ops->update) { 15012f63a38cSShri Abhyankar ierr = (*snes->ops->update)(snes, snes->iter);CHKERRQ(ierr); 15022f63a38cSShri Abhyankar } 15032f63a38cSShri Abhyankar ierr = SNESComputeJacobian(snes,X,&snes->jacobian,&snes->jacobian_pre,&flg);CHKERRQ(ierr); 15042f63a38cSShri Abhyankar 15052f63a38cSShri Abhyankar /* Create active and inactive index sets */ 15062f63a38cSShri Abhyankar ierr = SNESVICreateIndexSets_RS(snes,X,F,&IS_act,&IS_inact);CHKERRQ(ierr); 15072f63a38cSShri Abhyankar 150856a221efSShri Abhyankar /* Get local active set size */ 15092f63a38cSShri Abhyankar ierr = ISGetLocalSize(IS_act,&nis_act);CHKERRQ(ierr); 151056a221efSShri Abhyankar if (nis_act) { 1511e63076c7SBarry Smith ierr = ISGetIndices(IS_act,&idx_act);CHKERRQ(ierr); 1512e63076c7SBarry Smith IS_redact = PETSC_NULL; 151356a221efSShri Abhyankar if(vi->checkredundancy) { 1514cb5fe31bSShri Abhyankar (*vi->checkredundancy)(snes,IS_act,&IS_redact,vi->ctxP); 151556a221efSShri Abhyankar } 15162f63a38cSShri Abhyankar 151756a221efSShri Abhyankar if(!IS_redact) { 151856a221efSShri Abhyankar /* User called checkredundancy function but didn't create IS_redact because 151956a221efSShri Abhyankar there were no redundant active set variables */ 152056a221efSShri Abhyankar /* Copy over all active set indices to the list */ 152156a221efSShri Abhyankar ierr = PetscMalloc(nis_act*sizeof(PetscInt),&idx_actkept);CHKERRQ(ierr); 152256a221efSShri Abhyankar for(k=0;k < nis_act;k++) idx_actkept[k] = idx_act[k]; 152356a221efSShri Abhyankar nkept = nis_act; 152456a221efSShri Abhyankar } else { 152556a221efSShri Abhyankar ierr = ISGetLocalSize(IS_redact,&nis_redact);CHKERRQ(ierr); 152656a221efSShri Abhyankar ierr = PetscMalloc((nis_act-nis_redact)*sizeof(PetscInt),&idx_actkept);CHKERRQ(ierr); 15272f63a38cSShri Abhyankar 152856a221efSShri Abhyankar /* Create reduced active set list */ 152956a221efSShri Abhyankar ierr = ISGetIndices(IS_act,&idx_act);CHKERRQ(ierr); 153056a221efSShri Abhyankar ierr = ISGetIndices(IS_redact,&idx_redact);CHKERRQ(ierr); 1531cb5fe31bSShri Abhyankar j1 = 0;nkept = 0; 153256a221efSShri Abhyankar for(k=0;k<nis_act;k++) { 153356a221efSShri Abhyankar if(j1 < nis_redact && idx_act[k] == idx_redact[j1]) j1++; 153456a221efSShri Abhyankar else idx_actkept[nkept++] = idx_act[k]; 153556a221efSShri Abhyankar } 153656a221efSShri Abhyankar ierr = ISRestoreIndices(IS_act,&idx_act);CHKERRQ(ierr); 153756a221efSShri Abhyankar ierr = ISRestoreIndices(IS_redact,&idx_redact);CHKERRQ(ierr); 1538cb5fe31bSShri Abhyankar 1539cb5fe31bSShri Abhyankar ierr = ISDestroy(&IS_redact);CHKERRQ(ierr); 154056a221efSShri Abhyankar } 15412f63a38cSShri Abhyankar 154256a221efSShri Abhyankar /* Create augmented F and Y */ 154356a221efSShri Abhyankar ierr = VecCreate(((PetscObject)snes)->comm,&F_aug);CHKERRQ(ierr); 154456a221efSShri Abhyankar ierr = VecSetSizes(F_aug,F->map->n+nkept,PETSC_DECIDE);CHKERRQ(ierr); 154556a221efSShri Abhyankar ierr = VecSetFromOptions(F_aug);CHKERRQ(ierr); 154656a221efSShri Abhyankar ierr = VecDuplicate(F_aug,&Y_aug);CHKERRQ(ierr); 15472f63a38cSShri Abhyankar 154856a221efSShri Abhyankar /* Copy over F to F_aug in the first n locations */ 154956a221efSShri Abhyankar ierr = VecGetArray(F,&f);CHKERRQ(ierr); 155056a221efSShri Abhyankar ierr = VecGetArray(F_aug,&f2);CHKERRQ(ierr); 155156a221efSShri Abhyankar ierr = PetscMemcpy(f2,f,F->map->n*sizeof(PetscScalar));CHKERRQ(ierr); 155256a221efSShri Abhyankar ierr = VecRestoreArray(F,&f);CHKERRQ(ierr); 155356a221efSShri Abhyankar ierr = VecRestoreArray(F_aug,&f2);CHKERRQ(ierr); 15542f63a38cSShri Abhyankar 155556a221efSShri Abhyankar /* Create the augmented jacobian matrix */ 155656a221efSShri Abhyankar ierr = MatCreate(((PetscObject)snes)->comm,&J_aug);CHKERRQ(ierr); 155756a221efSShri Abhyankar ierr = MatSetSizes(J_aug,X->map->n+nkept,X->map->n+nkept,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr); 155856a221efSShri Abhyankar ierr = MatSetFromOptions(J_aug);CHKERRQ(ierr); 15592f63a38cSShri Abhyankar 156056a221efSShri Abhyankar 15619521db3cSSatish Balay { /* local vars */ 1562493a4f3dSShri Abhyankar /* Preallocate augmented matrix and set values in it...Doing only sequential case first*/ 156356a221efSShri Abhyankar PetscInt ncols; 156456a221efSShri Abhyankar const PetscInt *cols; 156556a221efSShri Abhyankar const PetscScalar *vals; 15662969f145SShri Abhyankar PetscScalar value[2]; 15672969f145SShri Abhyankar PetscInt row,col[2]; 1568493a4f3dSShri Abhyankar PetscInt *d_nnz; 15692969f145SShri Abhyankar value[0] = 1.0; value[1] = 0.0; 1570493a4f3dSShri Abhyankar ierr = PetscMalloc((X->map->n+nkept)*sizeof(PetscInt),&d_nnz);CHKERRQ(ierr); 1571493a4f3dSShri Abhyankar ierr = PetscMemzero(d_nnz,(X->map->n+nkept)*sizeof(PetscInt));CHKERRQ(ierr); 1572493a4f3dSShri Abhyankar for(row=0;row<snes->jacobian->rmap->n;row++) { 1573493a4f3dSShri Abhyankar ierr = MatGetRow(snes->jacobian,row,&ncols,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr); 1574493a4f3dSShri Abhyankar d_nnz[row] += ncols; 1575493a4f3dSShri Abhyankar ierr = MatRestoreRow(snes->jacobian,row,&ncols,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr); 1576493a4f3dSShri Abhyankar } 1577493a4f3dSShri Abhyankar 1578493a4f3dSShri Abhyankar for(k=0;k<nkept;k++) { 1579493a4f3dSShri Abhyankar d_nnz[idx_actkept[k]] += 1; 15802969f145SShri Abhyankar d_nnz[snes->jacobian->rmap->n+k] += 2; 1581493a4f3dSShri Abhyankar } 1582493a4f3dSShri Abhyankar ierr = MatSeqAIJSetPreallocation(J_aug,PETSC_NULL,d_nnz);CHKERRQ(ierr); 1583493a4f3dSShri Abhyankar 1584493a4f3dSShri Abhyankar ierr = PetscFree(d_nnz);CHKERRQ(ierr); 158556a221efSShri Abhyankar 158656a221efSShri Abhyankar /* Set the original jacobian matrix in J_aug */ 158756a221efSShri Abhyankar for(row=0;row<snes->jacobian->rmap->n;row++) { 158856a221efSShri Abhyankar ierr = MatGetRow(snes->jacobian,row,&ncols,&cols,&vals);CHKERRQ(ierr); 158956a221efSShri Abhyankar ierr = MatSetValues(J_aug,1,&row,ncols,cols,vals,INSERT_VALUES);CHKERRQ(ierr); 159056a221efSShri Abhyankar ierr = MatRestoreRow(snes->jacobian,row,&ncols,&cols,&vals);CHKERRQ(ierr); 159156a221efSShri Abhyankar } 159256a221efSShri Abhyankar /* Add the augmented part */ 159356a221efSShri Abhyankar for(k=0;k<nkept;k++) { 15942969f145SShri Abhyankar row = snes->jacobian->rmap->n+k; 15952969f145SShri Abhyankar col[0] = idx_actkept[k]; col[1] = snes->jacobian->rmap->n+k; 15962969f145SShri Abhyankar ierr = MatSetValues(J_aug,1,&row,1,col,value,INSERT_VALUES);CHKERRQ(ierr); 15972969f145SShri Abhyankar ierr = MatSetValues(J_aug,1,&col[0],1,&row,&value[0],INSERT_VALUES);CHKERRQ(ierr); 159856a221efSShri Abhyankar } 159956a221efSShri Abhyankar ierr = MatAssemblyBegin(J_aug,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 160056a221efSShri Abhyankar ierr = MatAssemblyEnd(J_aug,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 160156a221efSShri Abhyankar /* Only considering prejac = jac for now */ 160256a221efSShri Abhyankar Jpre_aug = J_aug; 16039521db3cSSatish Balay } /* local vars*/ 1604e63076c7SBarry Smith ierr = ISRestoreIndices(IS_act,&idx_act);CHKERRQ(ierr); 1605e63076c7SBarry Smith ierr = ISDestroy(&IS_act);CHKERRQ(ierr); 160656a221efSShri Abhyankar } else { 160756a221efSShri Abhyankar F_aug = F; J_aug = snes->jacobian; Y_aug = Y; Jpre_aug = snes->jacobian_pre; 160856a221efSShri Abhyankar } 16092f63a38cSShri Abhyankar 16102f63a38cSShri Abhyankar ierr = ISEqual(vi->IS_inact_prev,IS_inact,&isequal);CHKERRQ(ierr); 16112f63a38cSShri Abhyankar if (!isequal) { 161256a221efSShri Abhyankar ierr = SNESVIResetPCandKSP(snes,J_aug,Jpre_aug);CHKERRQ(ierr); 16132f63a38cSShri Abhyankar } 161456a221efSShri Abhyankar ierr = KSPSetOperators(snes->ksp,J_aug,Jpre_aug,flg);CHKERRQ(ierr); 16152f63a38cSShri Abhyankar ierr = KSPSetUp(snes->ksp);CHKERRQ(ierr); 161656a221efSShri Abhyankar /* { 16172f63a38cSShri Abhyankar PC pc; 16182f63a38cSShri Abhyankar PetscBool flg; 16192f63a38cSShri Abhyankar ierr = KSPGetPC(snes->ksp,&pc);CHKERRQ(ierr); 16202f63a38cSShri Abhyankar ierr = PetscTypeCompare((PetscObject)pc,PCFIELDSPLIT,&flg);CHKERRQ(ierr); 16212f63a38cSShri Abhyankar if (flg) { 16222f63a38cSShri Abhyankar KSP *subksps; 16232f63a38cSShri Abhyankar ierr = PCFieldSplitGetSubKSP(pc,PETSC_NULL,&subksps);CHKERRQ(ierr); 16242f63a38cSShri Abhyankar ierr = KSPGetPC(subksps[0],&pc);CHKERRQ(ierr); 16252f63a38cSShri Abhyankar ierr = PetscFree(subksps);CHKERRQ(ierr); 16262f63a38cSShri Abhyankar ierr = PetscTypeCompare((PetscObject)pc,PCBJACOBI,&flg);CHKERRQ(ierr); 16272f63a38cSShri Abhyankar if (flg) { 16282f63a38cSShri Abhyankar PetscInt n,N = 101*101,j,cnts[3] = {0,0,0}; 16292f63a38cSShri Abhyankar const PetscInt *ii; 16302f63a38cSShri Abhyankar 16312f63a38cSShri Abhyankar ierr = ISGetSize(IS_inact,&n);CHKERRQ(ierr); 16322f63a38cSShri Abhyankar ierr = ISGetIndices(IS_inact,&ii);CHKERRQ(ierr); 16332f63a38cSShri Abhyankar for (j=0; j<n; j++) { 16342f63a38cSShri Abhyankar if (ii[j] < N) cnts[0]++; 16352f63a38cSShri Abhyankar else if (ii[j] < 2*N) cnts[1]++; 16362f63a38cSShri Abhyankar else if (ii[j] < 3*N) cnts[2]++; 16372f63a38cSShri Abhyankar } 16382f63a38cSShri Abhyankar ierr = ISRestoreIndices(IS_inact,&ii);CHKERRQ(ierr); 16392f63a38cSShri Abhyankar 16402f63a38cSShri Abhyankar ierr = PCBJacobiSetTotalBlocks(pc,3,cnts);CHKERRQ(ierr); 16412f63a38cSShri Abhyankar } 16422f63a38cSShri Abhyankar } 16432f63a38cSShri Abhyankar } 164456a221efSShri Abhyankar */ 164556a221efSShri Abhyankar ierr = SNES_KSPSolve(snes,snes->ksp,F_aug,Y_aug);CHKERRQ(ierr); 16462f63a38cSShri Abhyankar ierr = KSPGetConvergedReason(snes->ksp,&kspreason);CHKERRQ(ierr); 16472f63a38cSShri Abhyankar if (kspreason < 0) { 16482f63a38cSShri Abhyankar if (++snes->numLinearSolveFailures >= snes->maxLinearSolveFailures) { 16492f63a38cSShri 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); 16502f63a38cSShri Abhyankar snes->reason = SNES_DIVERGED_LINEAR_SOLVE; 16512f63a38cSShri Abhyankar break; 16522f63a38cSShri Abhyankar } 16532f63a38cSShri Abhyankar } 16542f63a38cSShri Abhyankar 165556a221efSShri Abhyankar if(nis_act) { 165656a221efSShri Abhyankar PetscScalar *y1,*y2; 165756a221efSShri Abhyankar ierr = VecGetArray(Y,&y1);CHKERRQ(ierr); 165856a221efSShri Abhyankar ierr = VecGetArray(Y_aug,&y2);CHKERRQ(ierr); 165956a221efSShri Abhyankar /* Copy over inactive Y_aug to Y */ 166056a221efSShri Abhyankar j1 = 0; 166156a221efSShri Abhyankar for(i1=Y->map->rstart;i1 < Y->map->rend;i1++) { 166256a221efSShri Abhyankar if(j1 < nkept && idx_actkept[j1] == i1) j1++; 166356a221efSShri Abhyankar else y1[i1-Y->map->rstart] = y2[i1-Y->map->rstart]; 166456a221efSShri Abhyankar } 166556a221efSShri Abhyankar ierr = VecRestoreArray(Y,&y1);CHKERRQ(ierr); 166656a221efSShri Abhyankar ierr = VecRestoreArray(Y_aug,&y2);CHKERRQ(ierr); 16672f63a38cSShri Abhyankar 16686bf464f9SBarry Smith ierr = VecDestroy(&F_aug);CHKERRQ(ierr); 16696bf464f9SBarry Smith ierr = VecDestroy(&Y_aug);CHKERRQ(ierr); 16706bf464f9SBarry Smith ierr = MatDestroy(&J_aug);CHKERRQ(ierr); 167156a221efSShri Abhyankar ierr = PetscFree(idx_actkept);CHKERRQ(ierr); 167256a221efSShri Abhyankar } 167356a221efSShri Abhyankar 16742f63a38cSShri Abhyankar if (!isequal) { 16756bf464f9SBarry Smith ierr = ISDestroy(&vi->IS_inact_prev);CHKERRQ(ierr); 16762f63a38cSShri Abhyankar ierr = ISDuplicate(IS_inact,&vi->IS_inact_prev);CHKERRQ(ierr); 16772f63a38cSShri Abhyankar } 16786bf464f9SBarry Smith ierr = ISDestroy(&IS_inact);CHKERRQ(ierr); 167956a221efSShri Abhyankar 16802f63a38cSShri Abhyankar ierr = KSPGetIterationNumber(snes->ksp,&lits);CHKERRQ(ierr); 16812f63a38cSShri Abhyankar snes->linear_its += lits; 16822f63a38cSShri Abhyankar ierr = PetscInfo2(snes,"iter=%D, linear solve iterations=%D\n",snes->iter,lits);CHKERRQ(ierr); 16832f63a38cSShri Abhyankar /* 16842f63a38cSShri Abhyankar if (vi->precheckstep) { 16852f63a38cSShri Abhyankar PetscBool changed_y = PETSC_FALSE; 16862f63a38cSShri Abhyankar ierr = (*vi->precheckstep)(snes,X,Y,vi->precheck,&changed_y);CHKERRQ(ierr); 16872f63a38cSShri Abhyankar } 16882f63a38cSShri Abhyankar 16892f63a38cSShri Abhyankar if (PetscLogPrintInfo){ 16902f63a38cSShri Abhyankar ierr = SNESVICheckResidual_Private(snes,snes->jacobian,F,Y,G,W);CHKERRQ(ierr); 16912f63a38cSShri Abhyankar } 16922f63a38cSShri Abhyankar */ 16932f63a38cSShri Abhyankar /* Compute a (scaled) negative update in the line search routine: 16942f63a38cSShri Abhyankar Y <- X - lambda*Y 16952f63a38cSShri Abhyankar and evaluate G = function(Y) (depends on the line search). 16962f63a38cSShri Abhyankar */ 16972f63a38cSShri Abhyankar ierr = VecCopy(Y,snes->vec_sol_update);CHKERRQ(ierr); 16982f63a38cSShri Abhyankar ynorm = 1; gnorm = fnorm; 16992f63a38cSShri Abhyankar ierr = (*vi->LineSearch)(snes,vi->lsP,X,F,G,Y,W,fnorm,xnorm,&ynorm,&gnorm,&lssucceed);CHKERRQ(ierr); 17002f63a38cSShri Abhyankar ierr = PetscInfo4(snes,"fnorm=%18.16e, gnorm=%18.16e, ynorm=%18.16e, lssucceed=%d\n",fnorm,gnorm,ynorm,(int)lssucceed);CHKERRQ(ierr); 17012f63a38cSShri Abhyankar if (snes->reason == SNES_DIVERGED_FUNCTION_COUNT) break; 17022f63a38cSShri Abhyankar if (snes->domainerror) { 17032f63a38cSShri Abhyankar snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN; 17042f63a38cSShri Abhyankar PetscFunctionReturn(0); 17052f63a38cSShri Abhyankar } 17062f63a38cSShri Abhyankar if (!lssucceed) { 17072f63a38cSShri Abhyankar if (++snes->numFailures >= snes->maxFailures) { 17082f63a38cSShri Abhyankar PetscBool ismin; 17092f63a38cSShri Abhyankar snes->reason = SNES_DIVERGED_LINE_SEARCH; 17102f63a38cSShri Abhyankar ierr = SNESVICheckLocalMin_Private(snes,snes->jacobian,G,W,gnorm,&ismin);CHKERRQ(ierr); 17112f63a38cSShri Abhyankar if (ismin) snes->reason = SNES_DIVERGED_LOCAL_MIN; 17122f63a38cSShri Abhyankar break; 17132f63a38cSShri Abhyankar } 17142f63a38cSShri Abhyankar } 17152f63a38cSShri Abhyankar /* Update function and solution vectors */ 17162f63a38cSShri Abhyankar fnorm = gnorm; 17172f63a38cSShri Abhyankar ierr = VecCopy(G,F);CHKERRQ(ierr); 17182f63a38cSShri Abhyankar ierr = VecCopy(W,X);CHKERRQ(ierr); 17192f63a38cSShri Abhyankar /* Monitor convergence */ 17202f63a38cSShri Abhyankar ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 17212f63a38cSShri Abhyankar snes->iter = i+1; 17222f63a38cSShri Abhyankar snes->norm = fnorm; 17232f63a38cSShri Abhyankar ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 17242f63a38cSShri Abhyankar SNESLogConvHistory(snes,snes->norm,lits); 17257a03ce2fSLisandro Dalcin ierr = SNESMonitor(snes,snes->iter,snes->norm);CHKERRQ(ierr); 17262f63a38cSShri Abhyankar /* Test for convergence, xnorm = || X || */ 17272f63a38cSShri Abhyankar if (snes->ops->converged != SNESSkipConverged) { ierr = VecNorm(X,NORM_2,&xnorm);CHKERRQ(ierr); } 17282f63a38cSShri Abhyankar ierr = (*snes->ops->converged)(snes,snes->iter,xnorm,ynorm,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); 17292f63a38cSShri Abhyankar if (snes->reason) break; 17302f63a38cSShri Abhyankar } 17312f63a38cSShri Abhyankar if (i == maxits) { 17322f63a38cSShri Abhyankar ierr = PetscInfo1(snes,"Maximum number of iterations has been reached: %D\n",maxits);CHKERRQ(ierr); 17332f63a38cSShri Abhyankar if(!snes->reason) snes->reason = SNES_DIVERGED_MAX_IT; 17342f63a38cSShri Abhyankar } 17352f63a38cSShri Abhyankar PetscFunctionReturn(0); 17362f63a38cSShri Abhyankar } 17372f63a38cSShri Abhyankar 17382b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */ 17392b4ed282SShri Abhyankar /* 17402b4ed282SShri Abhyankar SNESSetUp_VI - Sets up the internal data structures for the later use 17412b4ed282SShri Abhyankar of the SNESVI nonlinear solver. 17422b4ed282SShri Abhyankar 17432b4ed282SShri Abhyankar Input Parameter: 17442b4ed282SShri Abhyankar . snes - the SNES context 17452b4ed282SShri Abhyankar . x - the solution vector 17462b4ed282SShri Abhyankar 17472b4ed282SShri Abhyankar Application Interface Routine: SNESSetUp() 17482b4ed282SShri Abhyankar 17492b4ed282SShri Abhyankar Notes: 17502b4ed282SShri Abhyankar For basic use of the SNES solvers, the user need not explicitly call 17512b4ed282SShri Abhyankar SNESSetUp(), since these actions will automatically occur during 17522b4ed282SShri Abhyankar the call to SNESSolve(). 17532b4ed282SShri Abhyankar */ 17542b4ed282SShri Abhyankar #undef __FUNCT__ 17552b4ed282SShri Abhyankar #define __FUNCT__ "SNESSetUp_VI" 17562b4ed282SShri Abhyankar PetscErrorCode SNESSetUp_VI(SNES snes) 17572b4ed282SShri Abhyankar { 17582b4ed282SShri Abhyankar PetscErrorCode ierr; 17592b4ed282SShri Abhyankar SNES_VI *vi = (SNES_VI*) snes->data; 17602b4ed282SShri Abhyankar PetscInt i_start[3],i_end[3]; 17612b4ed282SShri Abhyankar 17622b4ed282SShri Abhyankar PetscFunctionBegin; 176358c9b817SLisandro Dalcin 176458c9b817SLisandro Dalcin ierr = SNESDefaultGetWork(snes,3);CHKERRQ(ierr); 17652b4ed282SShri Abhyankar 17662176524cSBarry Smith if (vi->computevariablebounds) { 176777cdaf69SJed Brown if (!vi->xl) {ierr = VecDuplicate(snes->vec_sol,&vi->xl);CHKERRQ(ierr);} 176877cdaf69SJed Brown if (!vi->xu) {ierr = VecDuplicate(snes->vec_sol,&vi->xu);CHKERRQ(ierr);} 176977cdaf69SJed Brown ierr = (*vi->computevariablebounds)(snes,vi->xl,vi->xu);CHKERRQ(ierr); 17702176524cSBarry Smith } else if (!vi->xl && !vi->xu) { 17712176524cSBarry Smith /* If the lower and upper bound on variables are not set, set it to -Inf and Inf */ 17722b4ed282SShri Abhyankar ierr = VecDuplicate(snes->vec_sol, &vi->xl);CHKERRQ(ierr); 177301f0b76bSBarry Smith ierr = VecSet(vi->xl,SNES_VI_NINF);CHKERRQ(ierr); 17742b4ed282SShri Abhyankar ierr = VecDuplicate(snes->vec_sol, &vi->xu);CHKERRQ(ierr); 177501f0b76bSBarry Smith ierr = VecSet(vi->xu,SNES_VI_INF);CHKERRQ(ierr); 17762b4ed282SShri Abhyankar } else { 17772b4ed282SShri Abhyankar /* Check if lower bound, upper bound and solution vector distribution across the processors is identical */ 17782b4ed282SShri Abhyankar ierr = VecGetOwnershipRange(snes->vec_sol,i_start,i_end);CHKERRQ(ierr); 17792b4ed282SShri Abhyankar ierr = VecGetOwnershipRange(vi->xl,i_start+1,i_end+1);CHKERRQ(ierr); 17802b4ed282SShri Abhyankar ierr = VecGetOwnershipRange(vi->xu,i_start+2,i_end+2);CHKERRQ(ierr); 17812b4ed282SShri 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])) 17822b4ed282SShri 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."); 17832b4ed282SShri Abhyankar } 17842f63a38cSShri Abhyankar if (snes->ops->solve != SNESSolveVI_SS) { 1785abcba341SShri Abhyankar /* Set up previous active index set for the first snes solve 1786abcba341SShri Abhyankar vi->IS_inact_prev = 0,1,2,....N */ 1787abcba341SShri Abhyankar PetscInt *indices; 1788abcba341SShri Abhyankar PetscInt i,n,rstart,rend; 1789abcba341SShri Abhyankar 1790abcba341SShri Abhyankar ierr = VecGetOwnershipRange(snes->vec_sol,&rstart,&rend);CHKERRQ(ierr); 1791abcba341SShri Abhyankar ierr = VecGetLocalSize(snes->vec_sol,&n);CHKERRQ(ierr); 1792abcba341SShri Abhyankar ierr = PetscMalloc(n*sizeof(PetscInt),&indices);CHKERRQ(ierr); 1793abcba341SShri Abhyankar for(i=0;i < n; i++) indices[i] = rstart + i; 1794abcba341SShri Abhyankar ierr = ISCreateGeneral(((PetscObject)snes)->comm,n,indices,PETSC_OWN_POINTER,&vi->IS_inact_prev); 1795abcba341SShri Abhyankar } 17962b4ed282SShri Abhyankar 17972f63a38cSShri Abhyankar if (snes->ops->solve == SNESSolveVI_SS) { 1798fe835674SShri Abhyankar ierr = VecDuplicate(snes->vec_sol, &vi->dpsi);CHKERRQ(ierr); 1799fe835674SShri Abhyankar ierr = VecDuplicate(snes->vec_sol, &vi->phi);CHKERRQ(ierr); 1800fe835674SShri Abhyankar ierr = VecDuplicate(snes->vec_sol, &vi->Da);CHKERRQ(ierr); 1801fe835674SShri Abhyankar ierr = VecDuplicate(snes->vec_sol, &vi->Db);CHKERRQ(ierr); 1802fe835674SShri Abhyankar ierr = VecDuplicate(snes->vec_sol, &vi->z);CHKERRQ(ierr); 1803fe835674SShri Abhyankar ierr = VecDuplicate(snes->vec_sol, &vi->t);CHKERRQ(ierr); 1804fe835674SShri Abhyankar } 18052b4ed282SShri Abhyankar PetscFunctionReturn(0); 18062b4ed282SShri Abhyankar } 18072b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */ 18082176524cSBarry Smith #undef __FUNCT__ 18092176524cSBarry Smith #define __FUNCT__ "SNESReset_VI" 18102176524cSBarry Smith PetscErrorCode SNESReset_VI(SNES snes) 18112176524cSBarry Smith { 18122176524cSBarry Smith SNES_VI *vi = (SNES_VI*) snes->data; 18132176524cSBarry Smith PetscErrorCode ierr; 18142176524cSBarry Smith 18152176524cSBarry Smith PetscFunctionBegin; 18162176524cSBarry Smith ierr = VecDestroy(&vi->xl);CHKERRQ(ierr); 18172176524cSBarry Smith ierr = VecDestroy(&vi->xu);CHKERRQ(ierr); 1818d655a5daSBarry Smith if (snes->ops->solve != SNESSolveVI_SS) { 1819d655a5daSBarry Smith ierr = ISDestroy(&vi->IS_inact_prev);CHKERRQ(ierr); 1820d655a5daSBarry Smith } 18212176524cSBarry Smith PetscFunctionReturn(0); 18222176524cSBarry Smith } 18232176524cSBarry Smith 18242b4ed282SShri Abhyankar /* 18252b4ed282SShri Abhyankar SNESDestroy_VI - Destroys the private SNES_VI context that was created 18262b4ed282SShri Abhyankar with SNESCreate_VI(). 18272b4ed282SShri Abhyankar 18282b4ed282SShri Abhyankar Input Parameter: 18292b4ed282SShri Abhyankar . snes - the SNES context 18302b4ed282SShri Abhyankar 18312b4ed282SShri Abhyankar Application Interface Routine: SNESDestroy() 18322b4ed282SShri Abhyankar */ 18332b4ed282SShri Abhyankar #undef __FUNCT__ 18342b4ed282SShri Abhyankar #define __FUNCT__ "SNESDestroy_VI" 18352b4ed282SShri Abhyankar PetscErrorCode SNESDestroy_VI(SNES snes) 18362b4ed282SShri Abhyankar { 18372b4ed282SShri Abhyankar SNES_VI *vi = (SNES_VI*) snes->data; 18382b4ed282SShri Abhyankar PetscErrorCode ierr; 18392b4ed282SShri Abhyankar 18402b4ed282SShri Abhyankar PetscFunctionBegin; 18412b4ed282SShri Abhyankar 18422f63a38cSShri Abhyankar if (snes->ops->solve == SNESSolveVI_SS) { 18432b4ed282SShri Abhyankar /* clear vectors */ 18446bf464f9SBarry Smith ierr = VecDestroy(&vi->dpsi);CHKERRQ(ierr); 18456bf464f9SBarry Smith ierr = VecDestroy(&vi->phi);CHKERRQ(ierr); 18466bf464f9SBarry Smith ierr = VecDestroy(&vi->Da);CHKERRQ(ierr); 18476bf464f9SBarry Smith ierr = VecDestroy(&vi->Db);CHKERRQ(ierr); 18486bf464f9SBarry Smith ierr = VecDestroy(&vi->z);CHKERRQ(ierr); 18496bf464f9SBarry Smith ierr = VecDestroy(&vi->t);CHKERRQ(ierr); 18507fe79bc4SShri Abhyankar } 18517fe79bc4SShri Abhyankar 1852649052a6SBarry Smith ierr = PetscViewerDestroy(&vi->lsmonitor);CHKERRQ(ierr); 18532b4ed282SShri Abhyankar ierr = PetscFree(snes->data);CHKERRQ(ierr); 18542b4ed282SShri Abhyankar 18552b4ed282SShri Abhyankar /* clear composed functions */ 18562b4ed282SShri Abhyankar ierr = PetscObjectComposeFunctionDynamic((PetscObject)snes,"SNESLineSearchSet_C","",PETSC_NULL);CHKERRQ(ierr); 1857c92abb8aSShri Abhyankar ierr = PetscObjectComposeFunctionDynamic((PetscObject)snes,"SNESLineSearchSetMonitor_C","",PETSC_NULL);CHKERRQ(ierr); 18582b4ed282SShri Abhyankar PetscFunctionReturn(0); 18592b4ed282SShri Abhyankar } 18607fe79bc4SShri Abhyankar 18612b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */ 18622b4ed282SShri Abhyankar #undef __FUNCT__ 18632b4ed282SShri Abhyankar #define __FUNCT__ "SNESLineSearchNo_VI" 18642b4ed282SShri Abhyankar 18652b4ed282SShri Abhyankar /* 18667fe79bc4SShri Abhyankar This routine does not actually do a line search but it takes a full newton 18677fe79bc4SShri Abhyankar step while ensuring that the new iterates remain within the constraints. 18682b4ed282SShri Abhyankar 18692b4ed282SShri Abhyankar */ 1870ace3abfcSBarry Smith PetscErrorCode SNESLineSearchNo_VI(SNES snes,void *lsctx,Vec x,Vec f,Vec g,Vec y,Vec w,PetscReal fnorm,PetscReal xnorm,PetscReal *ynorm,PetscReal *gnorm,PetscBool *flag) 18712b4ed282SShri Abhyankar { 18722b4ed282SShri Abhyankar PetscErrorCode ierr; 18732b4ed282SShri Abhyankar SNES_VI *vi = (SNES_VI*)snes->data; 1874ace3abfcSBarry Smith PetscBool changed_w = PETSC_FALSE,changed_y = PETSC_FALSE; 18752b4ed282SShri Abhyankar 18762b4ed282SShri Abhyankar PetscFunctionBegin; 18772b4ed282SShri Abhyankar *flag = PETSC_TRUE; 18782b4ed282SShri Abhyankar ierr = PetscLogEventBegin(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); 18792b4ed282SShri Abhyankar ierr = VecNorm(y,NORM_2,ynorm);CHKERRQ(ierr); /* ynorm = || y || */ 18802b4ed282SShri Abhyankar ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr); /* w <- x - y */ 1881c1a5e521SShri Abhyankar ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr); 1882c1a5e521SShri Abhyankar if (vi->postcheckstep) { 1883c1a5e521SShri Abhyankar ierr = (*vi->postcheckstep)(snes,x,y,w,vi->postcheck,&changed_y,&changed_w);CHKERRQ(ierr); 1884c1a5e521SShri Abhyankar } 1885c1a5e521SShri Abhyankar if (changed_y) { 1886c1a5e521SShri Abhyankar ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr); /* w <- x - y */ 18877fe79bc4SShri Abhyankar ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr); 1888c1a5e521SShri Abhyankar } 1889c1a5e521SShri Abhyankar ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr); 1890c1a5e521SShri Abhyankar ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr); 1891c1a5e521SShri Abhyankar if (!snes->domainerror) { 18922f63a38cSShri Abhyankar if (snes->ops->solve != SNESSolveVI_SS) { 18937fe79bc4SShri Abhyankar ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr); 18947fe79bc4SShri Abhyankar } else { 1895c1a5e521SShri Abhyankar ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr); /* gnorm = || g || */ 18967fe79bc4SShri Abhyankar } 189762cbcd01SMatthew G Knepley if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number"); 1898c1a5e521SShri Abhyankar } 1899c1a5e521SShri Abhyankar if (vi->lsmonitor) { 1900649052a6SBarry Smith ierr = PetscViewerASCIIAddTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 1901649052a6SBarry Smith ierr = PetscViewerASCIIPrintf(vi->lsmonitor," Line search: Using full step: fnorm %G gnorm %G\n",fnorm,*gnorm);CHKERRQ(ierr); 1902649052a6SBarry Smith ierr = PetscViewerASCIISubtractTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 1903c1a5e521SShri Abhyankar } 1904c1a5e521SShri Abhyankar ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); 1905c1a5e521SShri Abhyankar PetscFunctionReturn(0); 1906c1a5e521SShri Abhyankar } 1907c1a5e521SShri Abhyankar 1908c1a5e521SShri Abhyankar /* -------------------------------------------------------------------------- */ 1909c1a5e521SShri Abhyankar #undef __FUNCT__ 19102b4ed282SShri Abhyankar #define __FUNCT__ "SNESLineSearchNoNorms_VI" 19112b4ed282SShri Abhyankar 19122b4ed282SShri Abhyankar /* 19132b4ed282SShri Abhyankar This routine is a copy of SNESLineSearchNoNorms in snes/impls/ls/ls.c 19142b4ed282SShri Abhyankar */ 1915ace3abfcSBarry Smith PetscErrorCode SNESLineSearchNoNorms_VI(SNES snes,void *lsctx,Vec x,Vec f,Vec g,Vec y,Vec w,PetscReal fnorm,PetscReal xnorm,PetscReal *ynorm,PetscReal *gnorm,PetscBool *flag) 19162b4ed282SShri Abhyankar { 19172b4ed282SShri Abhyankar PetscErrorCode ierr; 19182b4ed282SShri Abhyankar SNES_VI *vi = (SNES_VI*)snes->data; 1919ace3abfcSBarry Smith PetscBool changed_w = PETSC_FALSE,changed_y = PETSC_FALSE; 19202b4ed282SShri Abhyankar 19212b4ed282SShri Abhyankar PetscFunctionBegin; 19222b4ed282SShri Abhyankar *flag = PETSC_TRUE; 19232b4ed282SShri Abhyankar ierr = PetscLogEventBegin(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); 19242b4ed282SShri Abhyankar ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr); /* w <- x - y */ 19257fe79bc4SShri Abhyankar ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr); 19262b4ed282SShri Abhyankar if (vi->postcheckstep) { 19272b4ed282SShri Abhyankar ierr = (*vi->postcheckstep)(snes,x,y,w,vi->postcheck,&changed_y,&changed_w);CHKERRQ(ierr); 19282b4ed282SShri Abhyankar } 19292b4ed282SShri Abhyankar if (changed_y) { 19302b4ed282SShri Abhyankar ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr); /* w <- x - y */ 19317fe79bc4SShri Abhyankar ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr); 19322b4ed282SShri Abhyankar } 19332b4ed282SShri Abhyankar 19342b4ed282SShri Abhyankar /* don't evaluate function the last time through */ 19352b4ed282SShri Abhyankar if (snes->iter < snes->max_its-1) { 19362b4ed282SShri Abhyankar ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr); 19372b4ed282SShri Abhyankar } 19382b4ed282SShri Abhyankar ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); 19392b4ed282SShri Abhyankar PetscFunctionReturn(0); 19402b4ed282SShri Abhyankar } 19417fe79bc4SShri Abhyankar 19422b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */ 19432b4ed282SShri Abhyankar #undef __FUNCT__ 19442b4ed282SShri Abhyankar #define __FUNCT__ "SNESLineSearchCubic_VI" 19452b4ed282SShri Abhyankar /* 19467fe79bc4SShri Abhyankar This routine implements a cubic line search while doing a projection on the variable bounds 19472b4ed282SShri Abhyankar */ 1948ace3abfcSBarry Smith PetscErrorCode SNESLineSearchCubic_VI(SNES snes,void *lsctx,Vec x,Vec f,Vec g,Vec y,Vec w,PetscReal fnorm,PetscReal xnorm,PetscReal *ynorm,PetscReal *gnorm,PetscBool *flag) 19492b4ed282SShri Abhyankar { 1950fe835674SShri Abhyankar PetscReal initslope,lambdaprev,gnormprev,a,b,d,t1,t2,rellength; 1951fe835674SShri Abhyankar PetscReal minlambda,lambda,lambdatemp; 1952fe835674SShri Abhyankar #if defined(PETSC_USE_COMPLEX) 1953fe835674SShri Abhyankar PetscScalar cinitslope; 1954fe835674SShri Abhyankar #endif 1955fe835674SShri Abhyankar PetscErrorCode ierr; 1956fe835674SShri Abhyankar PetscInt count; 1957fe835674SShri Abhyankar SNES_VI *vi = (SNES_VI*)snes->data; 1958fe835674SShri Abhyankar PetscBool changed_w = PETSC_FALSE,changed_y = PETSC_FALSE; 1959fe835674SShri Abhyankar MPI_Comm comm; 1960fe835674SShri Abhyankar 1961fe835674SShri Abhyankar PetscFunctionBegin; 1962fe835674SShri Abhyankar ierr = PetscObjectGetComm((PetscObject)snes,&comm);CHKERRQ(ierr); 1963fe835674SShri Abhyankar ierr = PetscLogEventBegin(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); 1964fe835674SShri Abhyankar *flag = PETSC_TRUE; 1965fe835674SShri Abhyankar 1966fe835674SShri Abhyankar ierr = VecNorm(y,NORM_2,ynorm);CHKERRQ(ierr); 1967fe835674SShri Abhyankar if (*ynorm == 0.0) { 1968fe835674SShri Abhyankar if (vi->lsmonitor) { 1969649052a6SBarry Smith ierr = PetscViewerASCIIAddTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 1970649052a6SBarry Smith ierr = PetscViewerASCIIPrintf(vi->lsmonitor," Line search: Initial direction and size is 0\n");CHKERRQ(ierr); 1971649052a6SBarry Smith ierr = PetscViewerASCIISubtractTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 1972fe835674SShri Abhyankar } 1973fe835674SShri Abhyankar *gnorm = fnorm; 1974fe835674SShri Abhyankar ierr = VecCopy(x,w);CHKERRQ(ierr); 1975fe835674SShri Abhyankar ierr = VecCopy(f,g);CHKERRQ(ierr); 1976fe835674SShri Abhyankar *flag = PETSC_FALSE; 1977fe835674SShri Abhyankar goto theend1; 1978fe835674SShri Abhyankar } 1979fe835674SShri Abhyankar if (*ynorm > vi->maxstep) { /* Step too big, so scale back */ 1980fe835674SShri Abhyankar if (vi->lsmonitor) { 1981649052a6SBarry Smith ierr = PetscViewerASCIIAddTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 1982649052a6SBarry Smith ierr = PetscViewerASCIIPrintf(vi->lsmonitor," Line search: Scaling step by %G old ynorm %G\n",vi->maxstep/(*ynorm),*ynorm);CHKERRQ(ierr); 1983649052a6SBarry Smith ierr = PetscViewerASCIISubtractTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 1984fe835674SShri Abhyankar } 1985fe835674SShri Abhyankar ierr = VecScale(y,vi->maxstep/(*ynorm));CHKERRQ(ierr); 1986fe835674SShri Abhyankar *ynorm = vi->maxstep; 1987fe835674SShri Abhyankar } 1988fe835674SShri Abhyankar ierr = VecMaxPointwiseDivide(y,x,&rellength);CHKERRQ(ierr); 1989fe835674SShri Abhyankar minlambda = vi->minlambda/rellength; 1990fe835674SShri Abhyankar ierr = MatMult(snes->jacobian,y,w);CHKERRQ(ierr); 1991fe835674SShri Abhyankar #if defined(PETSC_USE_COMPLEX) 1992fe835674SShri Abhyankar ierr = VecDot(f,w,&cinitslope);CHKERRQ(ierr); 1993fe835674SShri Abhyankar initslope = PetscRealPart(cinitslope); 1994fe835674SShri Abhyankar #else 1995fe835674SShri Abhyankar ierr = VecDot(f,w,&initslope);CHKERRQ(ierr); 1996fe835674SShri Abhyankar #endif 1997fe835674SShri Abhyankar if (initslope > 0.0) initslope = -initslope; 1998fe835674SShri Abhyankar if (initslope == 0.0) initslope = -1.0; 1999fe835674SShri Abhyankar 2000fe835674SShri Abhyankar ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr); 2001fe835674SShri Abhyankar ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr); 2002fe835674SShri Abhyankar if (snes->nfuncs >= snes->max_funcs) { 2003fe835674SShri Abhyankar ierr = PetscInfo(snes,"Exceeded maximum function evaluations, while checking full step length!\n");CHKERRQ(ierr); 2004fe835674SShri Abhyankar *flag = PETSC_FALSE; 2005fe835674SShri Abhyankar snes->reason = SNES_DIVERGED_FUNCTION_COUNT; 2006fe835674SShri Abhyankar goto theend1; 2007fe835674SShri Abhyankar } 2008fe835674SShri Abhyankar ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr); 20092f63a38cSShri Abhyankar if (snes->ops->solve != SNESSolveVI_SS) { 2010fe835674SShri Abhyankar ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr); 20117fe79bc4SShri Abhyankar } else { 20127fe79bc4SShri Abhyankar ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr); 20137fe79bc4SShri Abhyankar } 2014fe835674SShri Abhyankar if (snes->domainerror) { 2015fe835674SShri Abhyankar ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); 2016fe835674SShri Abhyankar PetscFunctionReturn(0); 2017fe835674SShri Abhyankar } 201862cbcd01SMatthew G Knepley if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number"); 2019ed70e96aSJungho Lee ierr = PetscInfo4(snes,"Initial fnorm %G gnorm %G alpha %G initslope %G\n",fnorm,*gnorm,vi->alpha,initslope);CHKERRQ(ierr); 2020f2b03b96SBarry Smith if ((*gnorm)*(*gnorm) <= (1.0 - vi->alpha)*fnorm*fnorm ) { /* Sufficient reduction */ 2021fe835674SShri Abhyankar if (vi->lsmonitor) { 2022649052a6SBarry Smith ierr = PetscViewerASCIIAddTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 2023649052a6SBarry Smith ierr = PetscViewerASCIIPrintf(vi->lsmonitor," Line search: Using full step: fnorm %G gnorm %G\n",fnorm,*gnorm);CHKERRQ(ierr); 2024649052a6SBarry Smith ierr = PetscViewerASCIISubtractTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 2025fe835674SShri Abhyankar } 2026fe835674SShri Abhyankar goto theend1; 2027fe835674SShri Abhyankar } 2028fe835674SShri Abhyankar 2029fe835674SShri Abhyankar /* Fit points with quadratic */ 2030fe835674SShri Abhyankar lambda = 1.0; 2031fe835674SShri Abhyankar lambdatemp = -initslope/((*gnorm)*(*gnorm) - fnorm*fnorm - 2.0*initslope); 2032fe835674SShri Abhyankar lambdaprev = lambda; 2033fe835674SShri Abhyankar gnormprev = *gnorm; 2034fe835674SShri Abhyankar if (lambdatemp > .5*lambda) lambdatemp = .5*lambda; 2035fe835674SShri Abhyankar if (lambdatemp <= .1*lambda) lambda = .1*lambda; 2036fe835674SShri Abhyankar else lambda = lambdatemp; 2037fe835674SShri Abhyankar 2038fe835674SShri Abhyankar ierr = VecWAXPY(w,-lambda,y,x);CHKERRQ(ierr); 2039fe835674SShri Abhyankar ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr); 2040fe835674SShri Abhyankar if (snes->nfuncs >= snes->max_funcs) { 2041fe835674SShri Abhyankar ierr = PetscInfo1(snes,"Exceeded maximum function evaluations, while attempting quadratic backtracking! %D \n",snes->nfuncs);CHKERRQ(ierr); 2042fe835674SShri Abhyankar *flag = PETSC_FALSE; 2043fe835674SShri Abhyankar snes->reason = SNES_DIVERGED_FUNCTION_COUNT; 2044fe835674SShri Abhyankar goto theend1; 2045fe835674SShri Abhyankar } 2046fe835674SShri Abhyankar ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr); 20472f63a38cSShri Abhyankar if (snes->ops->solve != SNESSolveVI_SS) { 2048fe835674SShri Abhyankar ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr); 20497fe79bc4SShri Abhyankar } else { 20507fe79bc4SShri Abhyankar ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr); 20517fe79bc4SShri Abhyankar } 2052fe835674SShri Abhyankar if (snes->domainerror) { 2053fe835674SShri Abhyankar ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); 2054fe835674SShri Abhyankar PetscFunctionReturn(0); 2055fe835674SShri Abhyankar } 205662cbcd01SMatthew G Knepley if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number"); 2057fe835674SShri Abhyankar if (vi->lsmonitor) { 2058649052a6SBarry Smith ierr = PetscViewerASCIIAddTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 2059649052a6SBarry Smith ierr = PetscViewerASCIIPrintf(vi->lsmonitor," Line search: gnorm after quadratic fit %G\n",*gnorm);CHKERRQ(ierr); 2060649052a6SBarry Smith ierr = PetscViewerASCIISubtractTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 2061fe835674SShri Abhyankar } 2062f2b03b96SBarry Smith if ((*gnorm)*(*gnorm) < (1.0 - vi->alpha)*fnorm*fnorm ) { /* sufficient reduction */ 2063fe835674SShri Abhyankar if (vi->lsmonitor) { 2064649052a6SBarry Smith ierr = PetscViewerASCIIAddTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 2065649052a6SBarry Smith ierr = PetscViewerASCIIPrintf(vi->lsmonitor," Line search: Quadratically determined step, lambda=%18.16e\n",lambda);CHKERRQ(ierr); 2066649052a6SBarry Smith ierr = PetscViewerASCIISubtractTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 2067fe835674SShri Abhyankar } 2068fe835674SShri Abhyankar goto theend1; 2069fe835674SShri Abhyankar } 2070fe835674SShri Abhyankar 2071fe835674SShri Abhyankar /* Fit points with cubic */ 2072fe835674SShri Abhyankar count = 1; 2073fe835674SShri Abhyankar while (PETSC_TRUE) { 2074fe835674SShri Abhyankar if (lambda <= minlambda) { 2075fe835674SShri Abhyankar if (vi->lsmonitor) { 2076649052a6SBarry Smith ierr = PetscViewerASCIIAddTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 2077649052a6SBarry Smith ierr = PetscViewerASCIIPrintf(vi->lsmonitor," Line search: unable to find good step length! After %D tries \n",count);CHKERRQ(ierr); 2078649052a6SBarry Smith ierr = PetscViewerASCIIPrintf(vi->lsmonitor," Line search: fnorm=%18.16e, gnorm=%18.16e, ynorm=%18.16e, minlambda=%18.16e, lambda=%18.16e, initial slope=%18.16e\n",fnorm,*gnorm,*ynorm,minlambda,lambda,initslope);CHKERRQ(ierr); 2079649052a6SBarry Smith ierr = PetscViewerASCIISubtractTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 2080fe835674SShri Abhyankar } 2081fe835674SShri Abhyankar *flag = PETSC_FALSE; 2082fe835674SShri Abhyankar break; 2083fe835674SShri Abhyankar } 2084fe835674SShri Abhyankar t1 = .5*((*gnorm)*(*gnorm) - fnorm*fnorm) - lambda*initslope; 2085fe835674SShri Abhyankar t2 = .5*(gnormprev*gnormprev - fnorm*fnorm) - lambdaprev*initslope; 2086fe835674SShri Abhyankar a = (t1/(lambda*lambda) - t2/(lambdaprev*lambdaprev))/(lambda-lambdaprev); 2087fe835674SShri Abhyankar b = (-lambdaprev*t1/(lambda*lambda) + lambda*t2/(lambdaprev*lambdaprev))/(lambda-lambdaprev); 2088fe835674SShri Abhyankar d = b*b - 3*a*initslope; 2089fe835674SShri Abhyankar if (d < 0.0) d = 0.0; 2090fe835674SShri Abhyankar if (a == 0.0) { 2091fe835674SShri Abhyankar lambdatemp = -initslope/(2.0*b); 2092fe835674SShri Abhyankar } else { 2093fe835674SShri Abhyankar lambdatemp = (-b + sqrt(d))/(3.0*a); 2094fe835674SShri Abhyankar } 2095fe835674SShri Abhyankar lambdaprev = lambda; 2096fe835674SShri Abhyankar gnormprev = *gnorm; 2097fe835674SShri Abhyankar if (lambdatemp > .5*lambda) lambdatemp = .5*lambda; 2098fe835674SShri Abhyankar if (lambdatemp <= .1*lambda) lambda = .1*lambda; 2099fe835674SShri Abhyankar else lambda = lambdatemp; 2100fe835674SShri Abhyankar ierr = VecWAXPY(w,-lambda,y,x);CHKERRQ(ierr); 2101fe835674SShri Abhyankar ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr); 2102fe835674SShri Abhyankar if (snes->nfuncs >= snes->max_funcs) { 2103fe835674SShri Abhyankar ierr = PetscInfo1(snes,"Exceeded maximum function evaluations, while looking for good step length! %D \n",count);CHKERRQ(ierr); 2104fe835674SShri Abhyankar ierr = PetscInfo5(snes,"fnorm=%18.16e, gnorm=%18.16e, ynorm=%18.16e, lambda=%18.16e, initial slope=%18.16e\n",fnorm,*gnorm,*ynorm,lambda,initslope);CHKERRQ(ierr); 2105fe835674SShri Abhyankar *flag = PETSC_FALSE; 2106fe835674SShri Abhyankar snes->reason = SNES_DIVERGED_FUNCTION_COUNT; 2107fe835674SShri Abhyankar break; 2108fe835674SShri Abhyankar } 2109fe835674SShri Abhyankar ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr); 21102f63a38cSShri Abhyankar if (snes->ops->solve != SNESSolveVI_SS) { 2111fe835674SShri Abhyankar ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr); 21127fe79bc4SShri Abhyankar } else { 21137fe79bc4SShri Abhyankar ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr); 21147fe79bc4SShri Abhyankar } 2115fe835674SShri Abhyankar if (snes->domainerror) { 2116fe835674SShri Abhyankar ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); 2117fe835674SShri Abhyankar PetscFunctionReturn(0); 2118fe835674SShri Abhyankar } 211962cbcd01SMatthew G Knepley if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number"); 2120f2b03b96SBarry Smith if ((*gnorm)*(*gnorm) < (1.0 - vi->alpha)*fnorm*fnorm) { /* is reduction enough? */ 2121fe835674SShri Abhyankar if (vi->lsmonitor) { 2122fe835674SShri Abhyankar ierr = PetscPrintf(comm," Line search: Cubically determined step, current gnorm %G lambda=%18.16e\n",*gnorm,lambda);CHKERRQ(ierr); 2123fe835674SShri Abhyankar } 2124fe835674SShri Abhyankar break; 2125fe835674SShri Abhyankar } else { 2126fe835674SShri Abhyankar if (vi->lsmonitor) { 2127fe835674SShri Abhyankar ierr = PetscPrintf(comm," Line search: Cubic step no good, shrinking lambda, current gnorm %G lambda=%18.16e\n",*gnorm,lambda);CHKERRQ(ierr); 2128fe835674SShri Abhyankar } 2129fe835674SShri Abhyankar } 2130fe835674SShri Abhyankar count++; 2131fe835674SShri Abhyankar } 2132fe835674SShri Abhyankar theend1: 2133fe835674SShri Abhyankar /* Optional user-defined check for line search step validity */ 2134fe835674SShri Abhyankar if (vi->postcheckstep && *flag) { 2135fe835674SShri Abhyankar ierr = (*vi->postcheckstep)(snes,x,y,w,vi->postcheck,&changed_y,&changed_w);CHKERRQ(ierr); 2136fe835674SShri Abhyankar if (changed_y) { 2137fe835674SShri Abhyankar ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr); 2138fe835674SShri Abhyankar ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr); 2139fe835674SShri Abhyankar } 2140fe835674SShri Abhyankar if (changed_y || changed_w) { /* recompute the function if the step has changed */ 2141fe835674SShri Abhyankar ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr); 21422f63a38cSShri Abhyankar if (snes->ops->solve != SNESSolveVI_SS) { 2143fe835674SShri Abhyankar ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr); 21447fe79bc4SShri Abhyankar } else { 21457fe79bc4SShri Abhyankar ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr); 21467fe79bc4SShri Abhyankar } 2147fe835674SShri Abhyankar if (snes->domainerror) { 2148fe835674SShri Abhyankar ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); 2149fe835674SShri Abhyankar PetscFunctionReturn(0); 2150fe835674SShri Abhyankar } 215162cbcd01SMatthew G Knepley if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number"); 2152fe835674SShri Abhyankar ierr = VecNormBegin(y,NORM_2,ynorm);CHKERRQ(ierr); 2153fe835674SShri Abhyankar ierr = VecNormEnd(y,NORM_2,ynorm);CHKERRQ(ierr); 2154fe835674SShri Abhyankar } 2155fe835674SShri Abhyankar } 2156fe835674SShri Abhyankar ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); 2157fe835674SShri Abhyankar PetscFunctionReturn(0); 2158fe835674SShri Abhyankar } 2159fe835674SShri Abhyankar 21602b4ed282SShri Abhyankar #undef __FUNCT__ 21612b4ed282SShri Abhyankar #define __FUNCT__ "SNESLineSearchQuadratic_VI" 21622b4ed282SShri Abhyankar /* 21637fe79bc4SShri Abhyankar This routine does a quadratic line search while keeping the iterates within the variable bounds 21642b4ed282SShri Abhyankar */ 2165ace3abfcSBarry Smith PetscErrorCode SNESLineSearchQuadratic_VI(SNES snes,void *lsctx,Vec x,Vec f,Vec g,Vec y,Vec w,PetscReal fnorm,PetscReal xnorm,PetscReal *ynorm,PetscReal *gnorm,PetscBool *flag) 21662b4ed282SShri Abhyankar { 21672b4ed282SShri Abhyankar /* 21682b4ed282SShri Abhyankar Note that for line search purposes we work with with the related 21692b4ed282SShri Abhyankar minimization problem: 21702b4ed282SShri Abhyankar min z(x): R^n -> R, 21712b4ed282SShri Abhyankar where z(x) = .5 * fnorm*fnorm,and fnorm = || f ||_2. 21722b4ed282SShri Abhyankar */ 21732b4ed282SShri Abhyankar PetscReal initslope,minlambda,lambda,lambdatemp,rellength; 21742b4ed282SShri Abhyankar #if defined(PETSC_USE_COMPLEX) 21752b4ed282SShri Abhyankar PetscScalar cinitslope; 21762b4ed282SShri Abhyankar #endif 21772b4ed282SShri Abhyankar PetscErrorCode ierr; 21782b4ed282SShri Abhyankar PetscInt count; 21792b4ed282SShri Abhyankar SNES_VI *vi = (SNES_VI*)snes->data; 2180ace3abfcSBarry Smith PetscBool changed_w = PETSC_FALSE,changed_y = PETSC_FALSE; 21812b4ed282SShri Abhyankar 21822b4ed282SShri Abhyankar PetscFunctionBegin; 21832b4ed282SShri Abhyankar ierr = PetscLogEventBegin(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); 21842b4ed282SShri Abhyankar *flag = PETSC_TRUE; 21852b4ed282SShri Abhyankar 21862b4ed282SShri Abhyankar ierr = VecNorm(y,NORM_2,ynorm);CHKERRQ(ierr); 21872b4ed282SShri Abhyankar if (*ynorm == 0.0) { 2188c92abb8aSShri Abhyankar if (vi->lsmonitor) { 2189649052a6SBarry Smith ierr = PetscViewerASCIIAddTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 2190649052a6SBarry Smith ierr = PetscViewerASCIIPrintf(vi->lsmonitor,"Line search: Direction and size is 0\n");CHKERRQ(ierr); 2191649052a6SBarry Smith ierr = PetscViewerASCIISubtractTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 21922b4ed282SShri Abhyankar } 21932b4ed282SShri Abhyankar *gnorm = fnorm; 21942b4ed282SShri Abhyankar ierr = VecCopy(x,w);CHKERRQ(ierr); 21952b4ed282SShri Abhyankar ierr = VecCopy(f,g);CHKERRQ(ierr); 21962b4ed282SShri Abhyankar *flag = PETSC_FALSE; 21972b4ed282SShri Abhyankar goto theend2; 21982b4ed282SShri Abhyankar } 21992b4ed282SShri Abhyankar if (*ynorm > vi->maxstep) { /* Step too big, so scale back */ 22002b4ed282SShri Abhyankar ierr = VecScale(y,vi->maxstep/(*ynorm));CHKERRQ(ierr); 22012b4ed282SShri Abhyankar *ynorm = vi->maxstep; 22022b4ed282SShri Abhyankar } 22032b4ed282SShri Abhyankar ierr = VecMaxPointwiseDivide(y,x,&rellength);CHKERRQ(ierr); 22042b4ed282SShri Abhyankar minlambda = vi->minlambda/rellength; 22057fe79bc4SShri Abhyankar ierr = MatMult(snes->jacobian,y,w);CHKERRQ(ierr); 22062b4ed282SShri Abhyankar #if defined(PETSC_USE_COMPLEX) 22077fe79bc4SShri Abhyankar ierr = VecDot(f,w,&cinitslope);CHKERRQ(ierr); 22082b4ed282SShri Abhyankar initslope = PetscRealPart(cinitslope); 22092b4ed282SShri Abhyankar #else 22107fe79bc4SShri Abhyankar ierr = VecDot(f,w,&initslope);CHKERRQ(ierr); 22112b4ed282SShri Abhyankar #endif 22122b4ed282SShri Abhyankar if (initslope > 0.0) initslope = -initslope; 22132b4ed282SShri Abhyankar if (initslope == 0.0) initslope = -1.0; 22142b4ed282SShri Abhyankar ierr = PetscInfo1(snes,"Initslope %G \n",initslope);CHKERRQ(ierr); 22152b4ed282SShri Abhyankar 22162b4ed282SShri Abhyankar ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr); 22177fe79bc4SShri Abhyankar ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr); 22182b4ed282SShri Abhyankar if (snes->nfuncs >= snes->max_funcs) { 22192b4ed282SShri Abhyankar ierr = PetscInfo(snes,"Exceeded maximum function evaluations, while checking full step length!\n");CHKERRQ(ierr); 22202b4ed282SShri Abhyankar *flag = PETSC_FALSE; 22212b4ed282SShri Abhyankar snes->reason = SNES_DIVERGED_FUNCTION_COUNT; 22222b4ed282SShri Abhyankar goto theend2; 22232b4ed282SShri Abhyankar } 22242b4ed282SShri Abhyankar ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr); 22252f63a38cSShri Abhyankar if (snes->ops->solve != SNESSolveVI_SS) { 22267fe79bc4SShri Abhyankar ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr); 22277fe79bc4SShri Abhyankar } else { 22287fe79bc4SShri Abhyankar ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr); 22297fe79bc4SShri Abhyankar } 22302b4ed282SShri Abhyankar if (snes->domainerror) { 22312b4ed282SShri Abhyankar ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); 22322b4ed282SShri Abhyankar PetscFunctionReturn(0); 22332b4ed282SShri Abhyankar } 223462cbcd01SMatthew G Knepley if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number"); 2235f2b03b96SBarry Smith if ((*gnorm)*(*gnorm) <= (1.0 - vi->alpha)*fnorm*fnorm) { /* Sufficient reduction */ 2236c92abb8aSShri Abhyankar if (vi->lsmonitor) { 2237649052a6SBarry Smith ierr = PetscViewerASCIIAddTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 2238649052a6SBarry Smith ierr = PetscViewerASCIIPrintf(vi->lsmonitor," Line search: Using full step: fnorm %G gnorm %G\n",fnorm,*gnorm);CHKERRQ(ierr); 2239649052a6SBarry Smith ierr = PetscViewerASCIISubtractTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 22402b4ed282SShri Abhyankar } 22412b4ed282SShri Abhyankar goto theend2; 22422b4ed282SShri Abhyankar } 22432b4ed282SShri Abhyankar 22442b4ed282SShri Abhyankar /* Fit points with quadratic */ 22452b4ed282SShri Abhyankar lambda = 1.0; 22462b4ed282SShri Abhyankar count = 1; 22472b4ed282SShri Abhyankar while (PETSC_TRUE) { 22482b4ed282SShri Abhyankar if (lambda <= minlambda) { /* bad luck; use full step */ 2249c92abb8aSShri Abhyankar if (vi->lsmonitor) { 2250649052a6SBarry Smith ierr = PetscViewerASCIIAddTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 2251649052a6SBarry Smith ierr = PetscViewerASCIIPrintf(vi->lsmonitor,"Line search: Unable to find good step length! %D \n",count);CHKERRQ(ierr); 2252649052a6SBarry Smith ierr = PetscViewerASCIIPrintf(vi->lsmonitor,"Line search: fnorm=%G, gnorm=%G, ynorm=%G, lambda=%G, initial slope=%G\n",fnorm,*gnorm,*ynorm,lambda,initslope);CHKERRQ(ierr); 2253649052a6SBarry Smith ierr = PetscViewerASCIISubtractTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 22542b4ed282SShri Abhyankar } 22552b4ed282SShri Abhyankar ierr = VecCopy(x,w);CHKERRQ(ierr); 22562b4ed282SShri Abhyankar *flag = PETSC_FALSE; 22572b4ed282SShri Abhyankar break; 22582b4ed282SShri Abhyankar } 22592b4ed282SShri Abhyankar lambdatemp = -initslope/((*gnorm)*(*gnorm) - fnorm*fnorm - 2.0*initslope); 22602b4ed282SShri Abhyankar if (lambdatemp > .5*lambda) lambdatemp = .5*lambda; 22612b4ed282SShri Abhyankar if (lambdatemp <= .1*lambda) lambda = .1*lambda; 22622b4ed282SShri Abhyankar else lambda = lambdatemp; 22632b4ed282SShri Abhyankar 22642b4ed282SShri Abhyankar ierr = VecWAXPY(w,-lambda,y,x);CHKERRQ(ierr); 22657fe79bc4SShri Abhyankar ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr); 22662b4ed282SShri Abhyankar if (snes->nfuncs >= snes->max_funcs) { 22672b4ed282SShri Abhyankar ierr = PetscInfo1(snes,"Exceeded maximum function evaluations, while looking for good step length! %D \n",count);CHKERRQ(ierr); 22682b4ed282SShri Abhyankar ierr = PetscInfo5(snes,"fnorm=%18.16e, gnorm=%18.16e, ynorm=%18.16e, lambda=%18.16e, initial slope=%18.16e\n",fnorm,*gnorm,*ynorm,lambda,initslope);CHKERRQ(ierr); 22692b4ed282SShri Abhyankar *flag = PETSC_FALSE; 22702b4ed282SShri Abhyankar snes->reason = SNES_DIVERGED_FUNCTION_COUNT; 22712b4ed282SShri Abhyankar break; 22722b4ed282SShri Abhyankar } 22732b4ed282SShri Abhyankar ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr); 22742b4ed282SShri Abhyankar if (snes->domainerror) { 22752b4ed282SShri Abhyankar ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); 22762b4ed282SShri Abhyankar PetscFunctionReturn(0); 22772b4ed282SShri Abhyankar } 22782f63a38cSShri Abhyankar if (snes->ops->solve != SNESSolveVI_SS) { 22797fe79bc4SShri Abhyankar ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr); 22807fe79bc4SShri Abhyankar } else { 22812b4ed282SShri Abhyankar ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr); 22827fe79bc4SShri Abhyankar } 228362cbcd01SMatthew G Knepley if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number"); 2284f2b03b96SBarry Smith if ((*gnorm)*(*gnorm) < (1.0 - vi->alpha)*fnorm*fnorm) { /* sufficient reduction */ 2285c92abb8aSShri Abhyankar if (vi->lsmonitor) { 2286649052a6SBarry Smith ierr = PetscViewerASCIIAddTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 2287649052a6SBarry Smith ierr = PetscViewerASCIIPrintf(vi->lsmonitor," Line Search: Quadratically determined step, lambda=%G\n",lambda);CHKERRQ(ierr); 2288649052a6SBarry Smith ierr = PetscViewerASCIISubtractTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 22892b4ed282SShri Abhyankar } 22902b4ed282SShri Abhyankar break; 22912b4ed282SShri Abhyankar } 22922b4ed282SShri Abhyankar count++; 22932b4ed282SShri Abhyankar } 22942b4ed282SShri Abhyankar theend2: 22952b4ed282SShri Abhyankar /* Optional user-defined check for line search step validity */ 22962b4ed282SShri Abhyankar if (vi->postcheckstep) { 22972b4ed282SShri Abhyankar ierr = (*vi->postcheckstep)(snes,x,y,w,vi->postcheck,&changed_y,&changed_w);CHKERRQ(ierr); 22982b4ed282SShri Abhyankar if (changed_y) { 22992b4ed282SShri Abhyankar ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr); 23007fe79bc4SShri Abhyankar ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr); 23012b4ed282SShri Abhyankar } 23022b4ed282SShri Abhyankar if (changed_y || changed_w) { /* recompute the function if the step has changed */ 23032b4ed282SShri Abhyankar ierr = SNESComputeFunction(snes,w,g); 23042b4ed282SShri Abhyankar if (snes->domainerror) { 23052b4ed282SShri Abhyankar ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); 23062b4ed282SShri Abhyankar PetscFunctionReturn(0); 23072b4ed282SShri Abhyankar } 23082f63a38cSShri Abhyankar if (snes->ops->solve != SNESSolveVI_SS) { 23097fe79bc4SShri Abhyankar ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr); 23107fe79bc4SShri Abhyankar } else { 23117fe79bc4SShri Abhyankar ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr); 23127fe79bc4SShri Abhyankar } 23137fe79bc4SShri Abhyankar 23142b4ed282SShri Abhyankar ierr = VecNormBegin(y,NORM_2,ynorm);CHKERRQ(ierr); 23152b4ed282SShri Abhyankar ierr = VecNormEnd(y,NORM_2,ynorm);CHKERRQ(ierr); 231662cbcd01SMatthew G Knepley if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number"); 23172b4ed282SShri Abhyankar } 23182b4ed282SShri Abhyankar } 23192b4ed282SShri Abhyankar ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); 23202b4ed282SShri Abhyankar PetscFunctionReturn(0); 23212b4ed282SShri Abhyankar } 23222b4ed282SShri Abhyankar 2323ace3abfcSBarry Smith typedef PetscErrorCode (*FCN2)(SNES,void*,Vec,Vec,Vec,Vec,Vec,PetscReal,PetscReal,PetscReal*,PetscReal*,PetscBool*); /* force argument to next function to not be extern C*/ 23242b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */ 23252b4ed282SShri Abhyankar EXTERN_C_BEGIN 23262b4ed282SShri Abhyankar #undef __FUNCT__ 23272b4ed282SShri Abhyankar #define __FUNCT__ "SNESLineSearchSet_VI" 23287087cfbeSBarry Smith PetscErrorCode SNESLineSearchSet_VI(SNES snes,FCN2 func,void *lsctx) 23292b4ed282SShri Abhyankar { 23302b4ed282SShri Abhyankar PetscFunctionBegin; 23312b4ed282SShri Abhyankar ((SNES_VI *)(snes->data))->LineSearch = func; 23322b4ed282SShri Abhyankar ((SNES_VI *)(snes->data))->lsP = lsctx; 23332b4ed282SShri Abhyankar PetscFunctionReturn(0); 23342b4ed282SShri Abhyankar } 23352b4ed282SShri Abhyankar EXTERN_C_END 23362b4ed282SShri Abhyankar 23372b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */ 23382b4ed282SShri Abhyankar EXTERN_C_BEGIN 23392b4ed282SShri Abhyankar #undef __FUNCT__ 23402b4ed282SShri Abhyankar #define __FUNCT__ "SNESLineSearchSetMonitor_VI" 23417087cfbeSBarry Smith PetscErrorCode SNESLineSearchSetMonitor_VI(SNES snes,PetscBool flg) 23422b4ed282SShri Abhyankar { 23432b4ed282SShri Abhyankar SNES_VI *vi = (SNES_VI*)snes->data; 23442b4ed282SShri Abhyankar PetscErrorCode ierr; 23452b4ed282SShri Abhyankar 23462b4ed282SShri Abhyankar PetscFunctionBegin; 2347c92abb8aSShri Abhyankar if (flg && !vi->lsmonitor) { 2348649052a6SBarry Smith ierr = PetscViewerASCIIOpen(((PetscObject)snes)->comm,"stdout",&vi->lsmonitor);CHKERRQ(ierr); 2349c92abb8aSShri Abhyankar } else if (!flg && vi->lsmonitor) { 2350649052a6SBarry Smith ierr = PetscViewerDestroy(&vi->lsmonitor);CHKERRQ(ierr); 23512b4ed282SShri Abhyankar } 23522b4ed282SShri Abhyankar PetscFunctionReturn(0); 23532b4ed282SShri Abhyankar } 23542b4ed282SShri Abhyankar EXTERN_C_END 23552b4ed282SShri Abhyankar 23562b4ed282SShri Abhyankar /* 23572b4ed282SShri Abhyankar SNESView_VI - Prints info from the SNESVI data structure. 23582b4ed282SShri Abhyankar 23592b4ed282SShri Abhyankar Input Parameters: 23602b4ed282SShri Abhyankar . SNES - the SNES context 23612b4ed282SShri Abhyankar . viewer - visualization context 23622b4ed282SShri Abhyankar 23632b4ed282SShri Abhyankar Application Interface Routine: SNESView() 23642b4ed282SShri Abhyankar */ 23652b4ed282SShri Abhyankar #undef __FUNCT__ 23662b4ed282SShri Abhyankar #define __FUNCT__ "SNESView_VI" 23672b4ed282SShri Abhyankar static PetscErrorCode SNESView_VI(SNES snes,PetscViewer viewer) 23682b4ed282SShri Abhyankar { 23692b4ed282SShri Abhyankar SNES_VI *vi = (SNES_VI *)snes->data; 237078c4b9d3SShri Abhyankar const char *cstr,*tstr; 23712b4ed282SShri Abhyankar PetscErrorCode ierr; 2372ace3abfcSBarry Smith PetscBool iascii; 23732b4ed282SShri Abhyankar 23742b4ed282SShri Abhyankar PetscFunctionBegin; 23752b4ed282SShri Abhyankar ierr = PetscTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); 23762b4ed282SShri Abhyankar if (iascii) { 23772b4ed282SShri Abhyankar if (vi->LineSearch == SNESLineSearchNo_VI) cstr = "SNESLineSearchNo"; 23782b4ed282SShri Abhyankar else if (vi->LineSearch == SNESLineSearchQuadratic_VI) cstr = "SNESLineSearchQuadratic"; 23792b4ed282SShri Abhyankar else if (vi->LineSearch == SNESLineSearchCubic_VI) cstr = "SNESLineSearchCubic"; 23802b4ed282SShri Abhyankar else cstr = "unknown"; 238178c4b9d3SShri Abhyankar if (snes->ops->solve == SNESSolveVI_SS) tstr = "Semismooth"; 23820a7c7af0SShri Abhyankar else if (snes->ops->solve == SNESSolveVI_RS) tstr = "Reduced Space"; 2383b350b9c9SBarry Smith else if (snes->ops->solve == SNESSolveVI_RSAUG) tstr = "Reduced space with augmented variables"; 238478c4b9d3SShri Abhyankar else tstr = "unknown"; 238578c4b9d3SShri Abhyankar ierr = PetscViewerASCIIPrintf(viewer," VI algorithm: %s\n",tstr);CHKERRQ(ierr); 23862b4ed282SShri Abhyankar ierr = PetscViewerASCIIPrintf(viewer," line search variant: %s\n",cstr);CHKERRQ(ierr); 23872b4ed282SShri Abhyankar ierr = PetscViewerASCIIPrintf(viewer," alpha=%G, maxstep=%G, minlambda=%G\n",vi->alpha,vi->maxstep,vi->minlambda);CHKERRQ(ierr); 23882b4ed282SShri Abhyankar } 23892b4ed282SShri Abhyankar PetscFunctionReturn(0); 23902b4ed282SShri Abhyankar } 23912b4ed282SShri Abhyankar 23925559b345SBarry Smith #undef __FUNCT__ 23935559b345SBarry Smith #define __FUNCT__ "SNESVISetVariableBounds" 23945559b345SBarry Smith /*@ 23952b4ed282SShri Abhyankar SNESVISetVariableBounds - Sets the lower and upper bounds for the solution vector. xl <= x <= xu. 23962b4ed282SShri Abhyankar 23972b4ed282SShri Abhyankar Input Parameters: 23982b4ed282SShri Abhyankar . snes - the SNES context. 23992b4ed282SShri Abhyankar . xl - lower bound. 24002b4ed282SShri Abhyankar . xu - upper bound. 24012b4ed282SShri Abhyankar 24022b4ed282SShri Abhyankar Notes: 24032b4ed282SShri Abhyankar If this routine is not called then the lower and upper bounds are set to 240401f0b76bSBarry Smith SNES_VI_INF and SNES_VI_NINF respectively during SNESSetUp(). 240584c105d7SBarry Smith 24065559b345SBarry Smith @*/ 240769c03620SShri Abhyankar PetscErrorCode SNESVISetVariableBounds(SNES snes, Vec xl, Vec xu) 24082b4ed282SShri Abhyankar { 2409d923200aSJungho Lee SNES_VI *vi; 2410d923200aSJungho Lee PetscErrorCode ierr; 2411*6fd67740SBarry Smith const PetscScalar *xxl,*xxu; 2412*6fd67740SBarry Smith PetscInt i,n, cnt = 0; 24132b4ed282SShri Abhyankar 24142b4ed282SShri Abhyankar PetscFunctionBegin; 24152b4ed282SShri Abhyankar PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 24162b4ed282SShri Abhyankar PetscValidHeaderSpecific(xl,VEC_CLASSID,2); 24172b4ed282SShri Abhyankar PetscValidHeaderSpecific(xu,VEC_CLASSID,3); 24182b4ed282SShri Abhyankar if (!snes->vec_func) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Must call SNESSetFunction() first"); 24192b4ed282SShri 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); 24202b4ed282SShri 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); 2421d923200aSJungho Lee ierr = SNESSetType(snes,SNESVI);CHKERRQ(ierr); 2422d923200aSJungho Lee vi = (SNES_VI*)snes->data; 24232176524cSBarry Smith ierr = PetscObjectReference((PetscObject)xl);CHKERRQ(ierr); 24242176524cSBarry Smith ierr = PetscObjectReference((PetscObject)xu);CHKERRQ(ierr); 24252176524cSBarry Smith ierr = VecDestroy(&vi->xl);CHKERRQ(ierr); 24262176524cSBarry Smith ierr = VecDestroy(&vi->xu);CHKERRQ(ierr); 24272b4ed282SShri Abhyankar vi->xl = xl; 24282b4ed282SShri Abhyankar vi->xu = xu; 2429*6fd67740SBarry Smith ierr = VecGetLocalSize(xl,&n);CHKERRQ(ierr); 2430*6fd67740SBarry Smith ierr = VecGetArrayRead(xl,&xxl);CHKERRQ(ierr); 2431*6fd67740SBarry Smith ierr = VecGetArrayRead(xu,&xxu);CHKERRQ(ierr); 2432*6fd67740SBarry Smith for (i=0; i<n; i++) { 2433*6fd67740SBarry Smith cnt += ((xxl[i] != SNES_VI_NINF) || (xxu[i] != SNES_VI_INF)); 2434*6fd67740SBarry Smith } 2435*6fd67740SBarry Smith ierr = MPI_Allreduce(&cnt,&vi->ntruebounds,1,MPIU_INT,MPI_SUM,((PetscObject)snes)->comm);CHKERRQ(ierr); 2436*6fd67740SBarry Smith ierr = VecRestoreArrayRead(xl,&xxl);CHKERRQ(ierr); 2437*6fd67740SBarry Smith ierr = VecRestoreArrayRead(xu,&xxu);CHKERRQ(ierr); 24382b4ed282SShri Abhyankar PetscFunctionReturn(0); 24392b4ed282SShri Abhyankar } 2440693ddf92SShri Abhyankar 24412b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */ 24422b4ed282SShri Abhyankar /* 24432b4ed282SShri Abhyankar SNESSetFromOptions_VI - Sets various parameters for the SNESVI method. 24442b4ed282SShri Abhyankar 24452b4ed282SShri Abhyankar Input Parameter: 24462b4ed282SShri Abhyankar . snes - the SNES context 24472b4ed282SShri Abhyankar 24482b4ed282SShri Abhyankar Application Interface Routine: SNESSetFromOptions() 24492b4ed282SShri Abhyankar */ 24502b4ed282SShri Abhyankar #undef __FUNCT__ 24512b4ed282SShri Abhyankar #define __FUNCT__ "SNESSetFromOptions_VI" 24522b4ed282SShri Abhyankar static PetscErrorCode SNESSetFromOptions_VI(SNES snes) 24532b4ed282SShri Abhyankar { 24542b4ed282SShri Abhyankar SNES_VI *vi = (SNES_VI *)snes->data; 24557fe79bc4SShri Abhyankar const char *lses[] = {"basic","basicnonorms","quadratic","cubic"}; 2456b350b9c9SBarry Smith const char *vies[] = {"ss","rs","rsaug"}; 24572b4ed282SShri Abhyankar PetscErrorCode ierr; 24582b4ed282SShri Abhyankar PetscInt indx; 245969c03620SShri Abhyankar PetscBool flg,set,flg2; 24602b4ed282SShri Abhyankar 24612b4ed282SShri Abhyankar PetscFunctionBegin; 24622b4ed282SShri Abhyankar ierr = PetscOptionsHead("SNES semismooth method options");CHKERRQ(ierr); 24639308c137SBarry Smith ierr = PetscOptionsBool("-snes_vi_monitor","Monitor all non-active variables","None",PETSC_FALSE,&flg,0);CHKERRQ(ierr); 24649308c137SBarry Smith if (flg) { 24659308c137SBarry Smith ierr = SNESMonitorSet(snes,SNESMonitorVI,0,0);CHKERRQ(ierr); 24669308c137SBarry Smith } 2467be6adb11SBarry Smith ierr = PetscOptionsReal("-snes_ls_alpha","Function norm must decrease by","None",vi->alpha,&vi->alpha,0);CHKERRQ(ierr); 2468be6adb11SBarry Smith ierr = PetscOptionsReal("-snes_ls_maxstep","Step must be less than","None",vi->maxstep,&vi->maxstep,0);CHKERRQ(ierr); 2469be6adb11SBarry Smith ierr = PetscOptionsReal("-snes_ls_minlambda","Minimum lambda allowed","None",vi->minlambda,&vi->minlambda,0);CHKERRQ(ierr); 24702b4ed282SShri Abhyankar ierr = PetscOptionsReal("-snes_vi_const_tol","constraint tolerance","None",vi->const_tol,&vi->const_tol,0);CHKERRQ(ierr); 2471be6adb11SBarry Smith ierr = PetscOptionsBool("-snes_ls_monitor","Print progress of line searches","SNESLineSearchSetMonitor",vi->lsmonitor ? PETSC_TRUE : PETSC_FALSE,&flg,&set);CHKERRQ(ierr); 24722b4ed282SShri Abhyankar if (set) {ierr = SNESLineSearchSetMonitor(snes,flg);CHKERRQ(ierr);} 24732f63a38cSShri Abhyankar ierr = PetscOptionsEList("-snes_vi_type","Semismooth algorithm used","",vies,3,"ss",&indx,&flg2);CHKERRQ(ierr); 247469c03620SShri Abhyankar if (flg2) { 247569c03620SShri Abhyankar switch (indx) { 247669c03620SShri Abhyankar case 0: 247769c03620SShri Abhyankar snes->ops->solve = SNESSolveVI_SS; 247869c03620SShri Abhyankar break; 247969c03620SShri Abhyankar case 1: 2480d950fb63SShri Abhyankar snes->ops->solve = SNESSolveVI_RS; 2481d950fb63SShri Abhyankar break; 24822f63a38cSShri Abhyankar case 2: 2483b350b9c9SBarry Smith snes->ops->solve = SNESSolveVI_RSAUG; 248469c03620SShri Abhyankar } 248569c03620SShri Abhyankar } 2486f2b03b96SBarry Smith ierr = PetscOptionsEList("-snes_ls","Line search used","SNESLineSearchSet",lses,4,"cubic",&indx,&flg);CHKERRQ(ierr); 24872b4ed282SShri Abhyankar if (flg) { 24882b4ed282SShri Abhyankar switch (indx) { 24892b4ed282SShri Abhyankar case 0: 24902b4ed282SShri Abhyankar ierr = SNESLineSearchSet(snes,SNESLineSearchNo_VI,PETSC_NULL);CHKERRQ(ierr); 24912b4ed282SShri Abhyankar break; 24922b4ed282SShri Abhyankar case 1: 24932b4ed282SShri Abhyankar ierr = SNESLineSearchSet(snes,SNESLineSearchNoNorms_VI,PETSC_NULL);CHKERRQ(ierr); 24942b4ed282SShri Abhyankar break; 24952b4ed282SShri Abhyankar case 2: 24962b4ed282SShri Abhyankar ierr = SNESLineSearchSet(snes,SNESLineSearchQuadratic_VI,PETSC_NULL);CHKERRQ(ierr); 24972b4ed282SShri Abhyankar break; 24982b4ed282SShri Abhyankar case 3: 24992b4ed282SShri Abhyankar ierr = SNESLineSearchSet(snes,SNESLineSearchCubic_VI,PETSC_NULL);CHKERRQ(ierr); 25002b4ed282SShri Abhyankar break; 25012b4ed282SShri Abhyankar } 2502fe835674SShri Abhyankar } 25032b4ed282SShri Abhyankar ierr = PetscOptionsTail();CHKERRQ(ierr); 25042b4ed282SShri Abhyankar PetscFunctionReturn(0); 25052b4ed282SShri Abhyankar } 25062b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */ 25072b4ed282SShri Abhyankar /*MC 25088b4c83edSBarry Smith SNESVI - Various solvers for variational inequalities based on Newton's method 25092b4ed282SShri Abhyankar 25102b4ed282SShri Abhyankar Options Database: 25118b4c83edSBarry 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 25128b4c83edSBarry Smith additional variables that enforce the constraints 25138b4c83edSBarry Smith - -snes_vi_monitor - prints the number of active constraints at each iteration. 25142b4ed282SShri Abhyankar 25152b4ed282SShri Abhyankar 25162b4ed282SShri Abhyankar Level: beginner 25172b4ed282SShri Abhyankar 25182b4ed282SShri Abhyankar .seealso: SNESCreate(), SNES, SNESSetType(), SNESTR, SNESLineSearchSet(), 25192b4ed282SShri Abhyankar SNESLineSearchSetPostCheck(), SNESLineSearchNo(), SNESLineSearchCubic(), SNESLineSearchQuadratic(), 25202b4ed282SShri Abhyankar SNESLineSearchSet(), SNESLineSearchNoNorms(), SNESLineSearchSetPreCheck(), SNESLineSearchSetParams(), SNESLineSearchGetParams() 25212b4ed282SShri Abhyankar 25222b4ed282SShri Abhyankar M*/ 25232b4ed282SShri Abhyankar EXTERN_C_BEGIN 25242b4ed282SShri Abhyankar #undef __FUNCT__ 25252b4ed282SShri Abhyankar #define __FUNCT__ "SNESCreate_VI" 25267087cfbeSBarry Smith PetscErrorCode SNESCreate_VI(SNES snes) 25272b4ed282SShri Abhyankar { 25282b4ed282SShri Abhyankar PetscErrorCode ierr; 25292b4ed282SShri Abhyankar SNES_VI *vi; 25302b4ed282SShri Abhyankar 25312b4ed282SShri Abhyankar PetscFunctionBegin; 25322176524cSBarry Smith snes->ops->reset = SNESReset_VI; 25332b4ed282SShri Abhyankar snes->ops->setup = SNESSetUp_VI; 2534edafb9efSBarry Smith snes->ops->solve = SNESSolveVI_RS; 25352b4ed282SShri Abhyankar snes->ops->destroy = SNESDestroy_VI; 25362b4ed282SShri Abhyankar snes->ops->setfromoptions = SNESSetFromOptions_VI; 25372b4ed282SShri Abhyankar snes->ops->view = SNESView_VI; 25382b4ed282SShri Abhyankar snes->ops->converged = SNESDefaultConverged_VI; 25392b4ed282SShri Abhyankar 25402b4ed282SShri Abhyankar ierr = PetscNewLog(snes,SNES_VI,&vi);CHKERRQ(ierr); 25412b4ed282SShri Abhyankar snes->data = (void*)vi; 25422b4ed282SShri Abhyankar vi->alpha = 1.e-4; 25432b4ed282SShri Abhyankar vi->maxstep = 1.e8; 25442b4ed282SShri Abhyankar vi->minlambda = 1.e-12; 2545f2b03b96SBarry Smith vi->LineSearch = SNESLineSearchCubic_VI; 25462b4ed282SShri Abhyankar vi->lsP = PETSC_NULL; 25472b4ed282SShri Abhyankar vi->postcheckstep = PETSC_NULL; 25482b4ed282SShri Abhyankar vi->postcheck = PETSC_NULL; 25492b4ed282SShri Abhyankar vi->precheckstep = PETSC_NULL; 25502b4ed282SShri Abhyankar vi->precheck = PETSC_NULL; 25512b4ed282SShri Abhyankar vi->const_tol = 2.2204460492503131e-16; 25522f63a38cSShri Abhyankar vi->checkredundancy = PETSC_NULL; 25532b4ed282SShri Abhyankar 25542b4ed282SShri Abhyankar ierr = PetscObjectComposeFunctionDynamic((PetscObject)snes,"SNESLineSearchSetMonitor_C","SNESLineSearchSetMonitor_VI",SNESLineSearchSetMonitor_VI);CHKERRQ(ierr); 25552b4ed282SShri Abhyankar ierr = PetscObjectComposeFunctionDynamic((PetscObject)snes,"SNESLineSearchSet_C","SNESLineSearchSet_VI",SNESLineSearchSet_VI);CHKERRQ(ierr); 25562b4ed282SShri Abhyankar 25572b4ed282SShri Abhyankar PetscFunctionReturn(0); 25582b4ed282SShri Abhyankar } 25592b4ed282SShri Abhyankar EXTERN_C_END 2560ed70e96aSJungho Lee 2561ed70e96aSJungho Lee #undef __FUNCT__ 2562ed70e96aSJungho Lee #define __FUNCT__ "SNESVIGetInactiveSet" 2563ed70e96aSJungho Lee /* 2564ed70e96aSJungho Lee SNESVIGetInactiveSet - Gets the global indices for the inactive set variables (these correspond to the degrees of freedom the linear 2565ed70e96aSJungho Lee system is solved on) 2566ed70e96aSJungho Lee 2567ed70e96aSJungho Lee Input parameter 2568ed70e96aSJungho Lee . snes - the SNES context 2569ed70e96aSJungho Lee 2570ed70e96aSJungho Lee Output parameter 2571ed70e96aSJungho Lee . ISact - active set index set 2572ed70e96aSJungho Lee 2573ed70e96aSJungho Lee */ 2574ed70e96aSJungho Lee PetscErrorCode SNESVIGetInactiveSet(SNES snes,IS* inact) 2575ed70e96aSJungho Lee { 2576ed70e96aSJungho Lee SNES_VI *vi = (SNES_VI*)snes->data; 2577ed70e96aSJungho Lee PetscFunctionBegin; 2578ed70e96aSJungho Lee *inact = vi->IS_inact_prev; 2579ed70e96aSJungho Lee PetscFunctionReturn(0); 2580ed70e96aSJungho Lee } 2581