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; 3136fd67740SBarry Smith PetscInt i,n,act[2] = {0,0},fact[2],N; 3146a9e2d46SJungho Lee /* remove later */ 3156a9e2d46SJungho Lee /* Number of components that actually hit the bounds (c.f. active variables) */ 3166a9e2d46SJungho Lee PetscInt act_bound[2] = {0,0},fact_bound[2]; 3179308c137SBarry Smith PetscReal rnorm,fnorm; 3189308c137SBarry Smith 3199308c137SBarry Smith PetscFunctionBegin; 3209308c137SBarry Smith ierr = VecGetLocalSize(snes->vec_sol,&n);CHKERRQ(ierr); 3216fd67740SBarry Smith ierr = VecGetSize(snes->vec_sol,&N);CHKERRQ(ierr); 3229308c137SBarry Smith ierr = VecGetArrayRead(vi->xl,&xl);CHKERRQ(ierr); 3239308c137SBarry Smith ierr = VecGetArrayRead(vi->xu,&xu);CHKERRQ(ierr); 3249308c137SBarry Smith ierr = VecGetArrayRead(snes->vec_sol,&x);CHKERRQ(ierr); 3253f731af5SBarry Smith ierr = VecGetArrayRead(snes->vec_func,&f);CHKERRQ(ierr); 3269308c137SBarry Smith 3279308c137SBarry Smith rnorm = 0.0; 3289308c137SBarry Smith for (i=0; i<n; i++) { 32910f5ae6bSBarry Smith if (((PetscRealPart(x[i]) > PetscRealPart(xl[i]) + 1.e-8 || (PetscRealPart(f[i]) < 0.0)) && ((PetscRealPart(x[i]) < PetscRealPart(xu[i]) - 1.e-8) || PetscRealPart(f[i]) > 0.0))) rnorm += PetscRealPart(PetscConj(f[i])*f[i]); 330e400df7aSBarry Smith else if (PetscRealPart(x[i]) <= PetscRealPart(xl[i]) + 1.e-8 && PetscRealPart(f[i]) >= 0.0) act[0]++; 331e400df7aSBarry Smith else if (PetscRealPart(x[i]) >= PetscRealPart(xu[i]) - 1.e-8 && PetscRealPart(f[i]) <= 0.0) act[1]++; 332e400df7aSBarry Smith else SETERRQ(((PetscObject)snes)->comm,PETSC_ERR_PLIB,"Can never get here"); 3339308c137SBarry Smith } 3346a9e2d46SJungho Lee 3356a9e2d46SJungho Lee /* Remove later, number of components that actually hit the bounds */ 3366a9e2d46SJungho Lee for (i=0; i<n; i++) { 3376a9e2d46SJungho Lee if (PetscRealPart(x[i]) <= PetscRealPart(xl[i]) + 1.e-8) act_bound[0]++; 3386a9e2d46SJungho Lee else if (PetscRealPart(x[i]) >= PetscRealPart(xu[i]) - 1.e-8) act_bound[1]++; 3396a9e2d46SJungho Lee } 3403f731af5SBarry Smith ierr = VecRestoreArrayRead(snes->vec_func,&f);CHKERRQ(ierr); 3419308c137SBarry Smith ierr = VecRestoreArrayRead(vi->xl,&xl);CHKERRQ(ierr); 3429308c137SBarry Smith ierr = VecRestoreArrayRead(vi->xu,&xu);CHKERRQ(ierr); 3439308c137SBarry Smith ierr = VecRestoreArrayRead(snes->vec_sol,&x);CHKERRQ(ierr); 344d9822059SBarry Smith ierr = MPI_Allreduce(&rnorm,&fnorm,1,MPIU_REAL,MPIU_SUM,((PetscObject)snes)->comm);CHKERRQ(ierr); 34521a4c9b1SBarry Smith ierr = MPI_Allreduce(act,fact,2,MPIU_INT,MPIU_SUM,((PetscObject)snes)->comm);CHKERRQ(ierr); 3466a9e2d46SJungho Lee /* remove later */ 3476a9e2d46SJungho Lee ierr = MPI_Allreduce(act_bound,fact_bound,2,MPIU_INT,MPIU_SUM,((PetscObject)snes)->comm);CHKERRQ(ierr); 348f137e44dSBarry Smith fnorm = PetscSqrtReal(fnorm); 3496fd67740SBarry Smith 350649052a6SBarry Smith ierr = PetscViewerASCIIAddTab(viewer,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 351f137e44dSBarry 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,(double)fnorm,fact[0],fact[1],((double)(fact[0]+fact[1]))/((double)N),((double)(fact[0]+fact[1]))/((double)vi->ntruebounds));CHKERRQ(ierr); 352f137e44dSBarry Smith ierr = PetscViewerASCIIPrintf(viewer," lower constraints satisfied %D upper constraints satisfied %D\n",its,fact_bound[0],fact_bound[1]);CHKERRQ(ierr); 3536a9e2d46SJungho Lee 354649052a6SBarry Smith ierr = PetscViewerASCIISubtractTab(viewer,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 3559308c137SBarry Smith PetscFunctionReturn(0); 3569308c137SBarry Smith } 3579308c137SBarry Smith 3582b4ed282SShri Abhyankar /* 3592b4ed282SShri Abhyankar Checks if J^T F = 0 which implies we've found a local minimum of the norm of the function, 3602b4ed282SShri 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 3612b4ed282SShri Abhyankar 0 = (J^T F)^T W = F^T J W iff W not in the null space of J. Thanks for Jorge More 3622b4ed282SShri Abhyankar for this trick. One assumes that the probability that W is in the null space of J is very, very small. 3632b4ed282SShri Abhyankar */ 3642b4ed282SShri Abhyankar #undef __FUNCT__ 3652b4ed282SShri Abhyankar #define __FUNCT__ "SNESVICheckLocalMin_Private" 366ace3abfcSBarry Smith PetscErrorCode SNESVICheckLocalMin_Private(SNES snes,Mat A,Vec F,Vec W,PetscReal fnorm,PetscBool *ismin) 3672b4ed282SShri Abhyankar { 3682b4ed282SShri Abhyankar PetscReal a1; 3692b4ed282SShri Abhyankar PetscErrorCode ierr; 370ace3abfcSBarry Smith PetscBool hastranspose; 3712b4ed282SShri Abhyankar 3722b4ed282SShri Abhyankar PetscFunctionBegin; 3732b4ed282SShri Abhyankar *ismin = PETSC_FALSE; 3742b4ed282SShri Abhyankar ierr = MatHasOperation(A,MATOP_MULT_TRANSPOSE,&hastranspose);CHKERRQ(ierr); 3752b4ed282SShri Abhyankar if (hastranspose) { 3762b4ed282SShri Abhyankar /* Compute || J^T F|| */ 3772b4ed282SShri Abhyankar ierr = MatMultTranspose(A,F,W);CHKERRQ(ierr); 3782b4ed282SShri Abhyankar ierr = VecNorm(W,NORM_2,&a1);CHKERRQ(ierr); 3792b4ed282SShri Abhyankar ierr = PetscInfo1(snes,"|| J^T F|| %G near zero implies found a local minimum\n",a1/fnorm);CHKERRQ(ierr); 3802b4ed282SShri Abhyankar if (a1/fnorm < 1.e-4) *ismin = PETSC_TRUE; 3812b4ed282SShri Abhyankar } else { 3822b4ed282SShri Abhyankar Vec work; 3832b4ed282SShri Abhyankar PetscScalar result; 3842b4ed282SShri Abhyankar PetscReal wnorm; 3852b4ed282SShri Abhyankar 3862b4ed282SShri Abhyankar ierr = VecSetRandom(W,PETSC_NULL);CHKERRQ(ierr); 3872b4ed282SShri Abhyankar ierr = VecNorm(W,NORM_2,&wnorm);CHKERRQ(ierr); 3882b4ed282SShri Abhyankar ierr = VecDuplicate(W,&work);CHKERRQ(ierr); 3892b4ed282SShri Abhyankar ierr = MatMult(A,W,work);CHKERRQ(ierr); 3902b4ed282SShri Abhyankar ierr = VecDot(F,work,&result);CHKERRQ(ierr); 3916bf464f9SBarry Smith ierr = VecDestroy(&work);CHKERRQ(ierr); 3922b4ed282SShri Abhyankar a1 = PetscAbsScalar(result)/(fnorm*wnorm); 3932b4ed282SShri Abhyankar ierr = PetscInfo1(snes,"(F^T J random)/(|| F ||*||random|| %G near zero implies found a local minimum\n",a1);CHKERRQ(ierr); 3942b4ed282SShri Abhyankar if (a1 < 1.e-4) *ismin = PETSC_TRUE; 3952b4ed282SShri Abhyankar } 3962b4ed282SShri Abhyankar PetscFunctionReturn(0); 3972b4ed282SShri Abhyankar } 3982b4ed282SShri Abhyankar 3992b4ed282SShri Abhyankar /* 4002b4ed282SShri Abhyankar Checks if J^T(F - J*X) = 0 4012b4ed282SShri Abhyankar */ 4022b4ed282SShri Abhyankar #undef __FUNCT__ 4032b4ed282SShri Abhyankar #define __FUNCT__ "SNESVICheckResidual_Private" 4042b4ed282SShri Abhyankar PetscErrorCode SNESVICheckResidual_Private(SNES snes,Mat A,Vec F,Vec X,Vec W1,Vec W2) 4052b4ed282SShri Abhyankar { 4062b4ed282SShri Abhyankar PetscReal a1,a2; 4072b4ed282SShri Abhyankar PetscErrorCode ierr; 408ace3abfcSBarry Smith PetscBool hastranspose; 4092b4ed282SShri Abhyankar 4102b4ed282SShri Abhyankar PetscFunctionBegin; 4112b4ed282SShri Abhyankar ierr = MatHasOperation(A,MATOP_MULT_TRANSPOSE,&hastranspose);CHKERRQ(ierr); 4122b4ed282SShri Abhyankar if (hastranspose) { 4132b4ed282SShri Abhyankar ierr = MatMult(A,X,W1);CHKERRQ(ierr); 4142b4ed282SShri Abhyankar ierr = VecAXPY(W1,-1.0,F);CHKERRQ(ierr); 4152b4ed282SShri Abhyankar 4162b4ed282SShri Abhyankar /* Compute || J^T W|| */ 4172b4ed282SShri Abhyankar ierr = MatMultTranspose(A,W1,W2);CHKERRQ(ierr); 4182b4ed282SShri Abhyankar ierr = VecNorm(W1,NORM_2,&a1);CHKERRQ(ierr); 4192b4ed282SShri Abhyankar ierr = VecNorm(W2,NORM_2,&a2);CHKERRQ(ierr); 4202b4ed282SShri Abhyankar if (a1 != 0.0) { 4212b4ed282SShri Abhyankar ierr = PetscInfo1(snes,"||J^T(F-Ax)||/||F-AX|| %G near zero implies inconsistent rhs\n",a2/a1);CHKERRQ(ierr); 4222b4ed282SShri Abhyankar } 4232b4ed282SShri Abhyankar } 4242b4ed282SShri Abhyankar PetscFunctionReturn(0); 4252b4ed282SShri Abhyankar } 4262b4ed282SShri Abhyankar 4272b4ed282SShri Abhyankar /* 4282b4ed282SShri Abhyankar SNESDefaultConverged_VI - Checks the convergence of the semismooth newton algorithm. 4292b4ed282SShri Abhyankar 4302b4ed282SShri Abhyankar Notes: 4312b4ed282SShri Abhyankar The convergence criterion currently implemented is 4322b4ed282SShri Abhyankar merit < abstol 4332b4ed282SShri Abhyankar merit < rtol*merit_initial 4342b4ed282SShri Abhyankar */ 4352b4ed282SShri Abhyankar #undef __FUNCT__ 4362b4ed282SShri Abhyankar #define __FUNCT__ "SNESDefaultConverged_VI" 4377fe79bc4SShri Abhyankar PetscErrorCode SNESDefaultConverged_VI(SNES snes,PetscInt it,PetscReal xnorm,PetscReal gradnorm,PetscReal fnorm,SNESConvergedReason *reason,void *dummy) 4382b4ed282SShri Abhyankar { 4392b4ed282SShri Abhyankar PetscErrorCode ierr; 4402b4ed282SShri Abhyankar 4412b4ed282SShri Abhyankar PetscFunctionBegin; 4422b4ed282SShri Abhyankar PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 4432b4ed282SShri Abhyankar PetscValidPointer(reason,6); 4442b4ed282SShri Abhyankar 4452b4ed282SShri Abhyankar *reason = SNES_CONVERGED_ITERATING; 4462b4ed282SShri Abhyankar 4472b4ed282SShri Abhyankar if (!it) { 4482b4ed282SShri Abhyankar /* set parameter for default relative tolerance convergence test */ 4497fe79bc4SShri Abhyankar snes->ttol = fnorm*snes->rtol; 4502b4ed282SShri Abhyankar } 4517fe79bc4SShri Abhyankar if (fnorm != fnorm) { 4522b4ed282SShri Abhyankar ierr = PetscInfo(snes,"Failed to converged, function norm is NaN\n");CHKERRQ(ierr); 4532b4ed282SShri Abhyankar *reason = SNES_DIVERGED_FNORM_NAN; 4547fe79bc4SShri Abhyankar } else if (fnorm < snes->abstol) { 4557fe79bc4SShri Abhyankar ierr = PetscInfo2(snes,"Converged due to function norm %G < %G\n",fnorm,snes->abstol);CHKERRQ(ierr); 4562b4ed282SShri Abhyankar *reason = SNES_CONVERGED_FNORM_ABS; 4572b4ed282SShri Abhyankar } else if (snes->nfuncs >= snes->max_funcs) { 4582b4ed282SShri Abhyankar ierr = PetscInfo2(snes,"Exceeded maximum number of function evaluations: %D > %D\n",snes->nfuncs,snes->max_funcs);CHKERRQ(ierr); 4592b4ed282SShri Abhyankar *reason = SNES_DIVERGED_FUNCTION_COUNT; 4602b4ed282SShri Abhyankar } 4612b4ed282SShri Abhyankar 4622b4ed282SShri Abhyankar if (it && !*reason) { 4637fe79bc4SShri Abhyankar if (fnorm < snes->ttol) { 4647fe79bc4SShri Abhyankar ierr = PetscInfo2(snes,"Converged due to function norm %G < %G (relative tolerance)\n",fnorm,snes->ttol);CHKERRQ(ierr); 4652b4ed282SShri Abhyankar *reason = SNES_CONVERGED_FNORM_RELATIVE; 4662b4ed282SShri Abhyankar } 4672b4ed282SShri Abhyankar } 4682b4ed282SShri Abhyankar PetscFunctionReturn(0); 4692b4ed282SShri Abhyankar } 4702b4ed282SShri Abhyankar 4712b4ed282SShri Abhyankar /* 4722b4ed282SShri Abhyankar SNESVIComputeMeritFunction - Evaluates the merit function for the mixed complementarity problem. 4732b4ed282SShri Abhyankar 4742b4ed282SShri Abhyankar Input Parameter: 4752b4ed282SShri Abhyankar . phi - the semismooth function 4762b4ed282SShri Abhyankar 4772b4ed282SShri Abhyankar Output Parameter: 4782b4ed282SShri Abhyankar . merit - the merit function 4792b4ed282SShri Abhyankar . phinorm - ||phi|| 4802b4ed282SShri Abhyankar 4812b4ed282SShri Abhyankar Notes: 4822b4ed282SShri Abhyankar The merit function for the mixed complementarity problem is defined as 4832b4ed282SShri Abhyankar merit = 0.5*phi^T*phi 4842b4ed282SShri Abhyankar */ 4852b4ed282SShri Abhyankar #undef __FUNCT__ 4862b4ed282SShri Abhyankar #define __FUNCT__ "SNESVIComputeMeritFunction" 4872b4ed282SShri Abhyankar static PetscErrorCode SNESVIComputeMeritFunction(Vec phi, PetscReal* merit,PetscReal* phinorm) 4882b4ed282SShri Abhyankar { 4892b4ed282SShri Abhyankar PetscErrorCode ierr; 4902b4ed282SShri Abhyankar 4912b4ed282SShri Abhyankar PetscFunctionBegin; 4925f48b12bSBarry Smith ierr = VecNormBegin(phi,NORM_2,phinorm);CHKERRQ(ierr); 4935f48b12bSBarry Smith ierr = VecNormEnd(phi,NORM_2,phinorm);CHKERRQ(ierr); 4942b4ed282SShri Abhyankar 4952b4ed282SShri Abhyankar *merit = 0.5*(*phinorm)*(*phinorm); 4962b4ed282SShri Abhyankar PetscFunctionReturn(0); 4972b4ed282SShri Abhyankar } 4982b4ed282SShri Abhyankar 4997f6f51e9SSatish Balay PETSC_STATIC_INLINE PetscScalar Phi(PetscScalar a,PetscScalar b) 5004c21c6cdSBarry Smith { 5014c21c6cdSBarry Smith return a + b - sqrt(a*a + b*b); 5024c21c6cdSBarry Smith } 5034c21c6cdSBarry Smith 5047f6f51e9SSatish Balay PETSC_STATIC_INLINE PetscScalar DPhi(PetscScalar a,PetscScalar b) 5054c21c6cdSBarry Smith { 5065559b345SBarry Smith if ((PetscAbsScalar(a) >= 1.e-6) || (PetscAbsScalar(b) >= 1.e-6)) return 1.0 - a/ sqrt(a*a + b*b); 5075559b345SBarry Smith else return .5; 5084c21c6cdSBarry Smith } 5094c21c6cdSBarry Smith 5102b4ed282SShri Abhyankar /* 5111f79c099SShri Abhyankar SNESVIComputeFunction - Reformulates a system of nonlinear equations in mixed complementarity form to a system of nonlinear equations in semismooth form. 5122b4ed282SShri Abhyankar 5132b4ed282SShri Abhyankar Input Parameters: 5142b4ed282SShri Abhyankar . snes - the SNES context 5152b4ed282SShri Abhyankar . x - current iterate 5162b4ed282SShri Abhyankar . functx - user defined function context 5172b4ed282SShri Abhyankar 5182b4ed282SShri Abhyankar Output Parameters: 5192b4ed282SShri Abhyankar . phi - Semismooth function 5202b4ed282SShri Abhyankar 5212b4ed282SShri Abhyankar */ 5222b4ed282SShri Abhyankar #undef __FUNCT__ 5231f79c099SShri Abhyankar #define __FUNCT__ "SNESVIComputeFunction" 5241f79c099SShri Abhyankar static PetscErrorCode SNESVIComputeFunction(SNES snes,Vec X,Vec phi,void* functx) 5252b4ed282SShri Abhyankar { 5262b4ed282SShri Abhyankar PetscErrorCode ierr; 5272b4ed282SShri Abhyankar SNES_VI *vi = (SNES_VI*)snes->data; 5282b4ed282SShri Abhyankar Vec Xl = vi->xl,Xu = vi->xu,F = snes->vec_func; 5294c21c6cdSBarry Smith PetscScalar *phi_arr,*x_arr,*f_arr,*l,*u; 5302b4ed282SShri Abhyankar PetscInt i,nlocal; 5312b4ed282SShri Abhyankar 5322b4ed282SShri Abhyankar PetscFunctionBegin; 5332b4ed282SShri Abhyankar ierr = (*vi->computeuserfunction)(snes,X,F,functx);CHKERRQ(ierr); 5342b4ed282SShri Abhyankar ierr = VecGetLocalSize(X,&nlocal);CHKERRQ(ierr); 5352b4ed282SShri Abhyankar ierr = VecGetArray(X,&x_arr);CHKERRQ(ierr); 5362b4ed282SShri Abhyankar ierr = VecGetArray(F,&f_arr);CHKERRQ(ierr); 5372b4ed282SShri Abhyankar ierr = VecGetArray(Xl,&l);CHKERRQ(ierr); 5382b4ed282SShri Abhyankar ierr = VecGetArray(Xu,&u);CHKERRQ(ierr); 5392b4ed282SShri Abhyankar ierr = VecGetArray(phi,&phi_arr);CHKERRQ(ierr); 5402b4ed282SShri Abhyankar 5412b4ed282SShri Abhyankar for (i=0;i < nlocal;i++) { 54210f5ae6bSBarry Smith if ((PetscRealPart(l[i]) <= SNES_VI_NINF) && (PetscRealPart(u[i]) >= SNES_VI_INF)) { /* no constraints on variable */ 5434c21c6cdSBarry Smith phi_arr[i] = f_arr[i]; 54410f5ae6bSBarry Smith } else if (PetscRealPart(l[i]) <= SNES_VI_NINF) { /* upper bound on variable only */ 5454c21c6cdSBarry Smith phi_arr[i] = -Phi(u[i] - x_arr[i],-f_arr[i]); 54610f5ae6bSBarry Smith } else if (PetscRealPart(u[i]) >= SNES_VI_INF) { /* lower bound on variable only */ 5474c21c6cdSBarry Smith phi_arr[i] = Phi(x_arr[i] - l[i],f_arr[i]); 5485559b345SBarry Smith } else if (l[i] == u[i]) { 5492b4ed282SShri Abhyankar phi_arr[i] = l[i] - x_arr[i]; 5505559b345SBarry Smith } else { /* both bounds on variable */ 5514c21c6cdSBarry Smith phi_arr[i] = Phi(x_arr[i] - l[i],-Phi(u[i] - x_arr[i],-f_arr[i])); 5522b4ed282SShri Abhyankar } 5532b4ed282SShri Abhyankar } 5542b4ed282SShri Abhyankar 5552b4ed282SShri Abhyankar ierr = VecRestoreArray(X,&x_arr);CHKERRQ(ierr); 5562b4ed282SShri Abhyankar ierr = VecRestoreArray(F,&f_arr);CHKERRQ(ierr); 5572b4ed282SShri Abhyankar ierr = VecRestoreArray(Xl,&l);CHKERRQ(ierr); 5582b4ed282SShri Abhyankar ierr = VecRestoreArray(Xu,&u);CHKERRQ(ierr); 5592b4ed282SShri Abhyankar ierr = VecRestoreArray(phi,&phi_arr);CHKERRQ(ierr); 5602b4ed282SShri Abhyankar PetscFunctionReturn(0); 5612b4ed282SShri Abhyankar } 5622b4ed282SShri Abhyankar 5632b4ed282SShri Abhyankar /* 564a79edbefSShri Abhyankar SNESVIComputeBsubdifferentialVectors - Computes the diagonal shift (Da) and row scaling (Db) vectors needed for the 565a79edbefSShri Abhyankar the semismooth jacobian. 5662b4ed282SShri Abhyankar */ 5672b4ed282SShri Abhyankar #undef __FUNCT__ 568a79edbefSShri Abhyankar #define __FUNCT__ "SNESVIComputeBsubdifferentialVectors" 569a79edbefSShri Abhyankar PetscErrorCode SNESVIComputeBsubdifferentialVectors(SNES snes,Vec X,Vec F,Mat jac,Vec Da,Vec Db) 5702b4ed282SShri Abhyankar { 5712b4ed282SShri Abhyankar PetscErrorCode ierr; 5722b4ed282SShri Abhyankar SNES_VI *vi = (SNES_VI*)snes->data; 5734c21c6cdSBarry Smith PetscScalar *l,*u,*x,*f,*da,*db,da1,da2,db1,db2; 5742b4ed282SShri Abhyankar PetscInt i,nlocal; 5752b4ed282SShri Abhyankar 5762b4ed282SShri Abhyankar PetscFunctionBegin; 5772b4ed282SShri Abhyankar 5782b4ed282SShri Abhyankar ierr = VecGetArray(X,&x);CHKERRQ(ierr); 5792b4ed282SShri Abhyankar ierr = VecGetArray(F,&f);CHKERRQ(ierr); 5802b4ed282SShri Abhyankar ierr = VecGetArray(vi->xl,&l);CHKERRQ(ierr); 5812b4ed282SShri Abhyankar ierr = VecGetArray(vi->xu,&u);CHKERRQ(ierr); 582a79edbefSShri Abhyankar ierr = VecGetArray(Da,&da);CHKERRQ(ierr); 583a79edbefSShri Abhyankar ierr = VecGetArray(Db,&db);CHKERRQ(ierr); 5842b4ed282SShri Abhyankar ierr = VecGetLocalSize(X,&nlocal);CHKERRQ(ierr); 5854c21c6cdSBarry Smith 5862b4ed282SShri Abhyankar for (i=0;i< nlocal;i++) { 58710f5ae6bSBarry Smith if ((PetscRealPart(l[i]) <= SNES_VI_NINF) && (PetscRealPart(u[i]) >= SNES_VI_INF)) {/* no constraints on variable */ 5884c21c6cdSBarry Smith da[i] = 0; 5892b4ed282SShri Abhyankar db[i] = 1; 59010f5ae6bSBarry Smith } else if (PetscRealPart(l[i]) <= SNES_VI_NINF) { /* upper bound on variable only */ 5914c21c6cdSBarry Smith da[i] = DPhi(u[i] - x[i], -f[i]); 5924c21c6cdSBarry Smith db[i] = DPhi(-f[i],u[i] - x[i]); 59310f5ae6bSBarry Smith } else if (PetscRealPart(u[i]) >= SNES_VI_INF) { /* lower bound on variable only */ 5945559b345SBarry Smith da[i] = DPhi(x[i] - l[i], f[i]); 5955559b345SBarry Smith db[i] = DPhi(f[i],x[i] - l[i]); 5965559b345SBarry Smith } else if (l[i] == u[i]) { /* fixed variable */ 5974c21c6cdSBarry Smith da[i] = 1; 5982b4ed282SShri Abhyankar db[i] = 0; 5995559b345SBarry Smith } else { /* upper and lower bounds on variable */ 6004c21c6cdSBarry Smith da1 = DPhi(x[i] - l[i], -Phi(u[i] - x[i], -f[i])); 6014c21c6cdSBarry Smith db1 = DPhi(-Phi(u[i] - x[i], -f[i]),x[i] - l[i]); 6024c21c6cdSBarry Smith da2 = DPhi(u[i] - x[i], -f[i]); 6034c21c6cdSBarry Smith db2 = DPhi(-f[i],u[i] - x[i]); 6044c21c6cdSBarry Smith da[i] = da1 + db1*da2; 6054c21c6cdSBarry Smith db[i] = db1*db2; 6062b4ed282SShri Abhyankar } 6072b4ed282SShri Abhyankar } 6085559b345SBarry Smith 6092b4ed282SShri Abhyankar ierr = VecRestoreArray(X,&x);CHKERRQ(ierr); 6102b4ed282SShri Abhyankar ierr = VecRestoreArray(F,&f);CHKERRQ(ierr); 6112b4ed282SShri Abhyankar ierr = VecRestoreArray(vi->xl,&l);CHKERRQ(ierr); 6122b4ed282SShri Abhyankar ierr = VecRestoreArray(vi->xu,&u);CHKERRQ(ierr); 613a79edbefSShri Abhyankar ierr = VecRestoreArray(Da,&da);CHKERRQ(ierr); 614a79edbefSShri Abhyankar ierr = VecRestoreArray(Db,&db);CHKERRQ(ierr); 615a79edbefSShri Abhyankar PetscFunctionReturn(0); 616a79edbefSShri Abhyankar } 617a79edbefSShri Abhyankar 618a79edbefSShri Abhyankar /* 619a79edbefSShri 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. 620a79edbefSShri Abhyankar 621a79edbefSShri Abhyankar Input Parameters: 622a79edbefSShri Abhyankar . Da - Diagonal shift vector for the semismooth jacobian. 623a79edbefSShri Abhyankar . Db - Row scaling vector for the semismooth jacobian. 624a79edbefSShri Abhyankar 625a79edbefSShri Abhyankar Output Parameters: 626a79edbefSShri Abhyankar . jac - semismooth jacobian 627a79edbefSShri Abhyankar . jac_pre - optional preconditioning matrix 628a79edbefSShri Abhyankar 629a79edbefSShri Abhyankar Notes: 630a79edbefSShri Abhyankar The semismooth jacobian matrix is given by 631a79edbefSShri Abhyankar jac = Da + Db*jacfun 632a79edbefSShri Abhyankar where Db is the row scaling matrix stored as a vector, 633a79edbefSShri Abhyankar Da is the diagonal perturbation matrix stored as a vector 634a79edbefSShri Abhyankar and jacfun is the jacobian of the original nonlinear function. 635a79edbefSShri Abhyankar */ 636a79edbefSShri Abhyankar #undef __FUNCT__ 637a79edbefSShri Abhyankar #define __FUNCT__ "SNESVIComputeJacobian" 638a79edbefSShri Abhyankar PetscErrorCode SNESVIComputeJacobian(Mat jac, Mat jac_pre,Vec Da, Vec Db) 639a79edbefSShri Abhyankar { 640a79edbefSShri Abhyankar PetscErrorCode ierr; 641a79edbefSShri Abhyankar 6422b4ed282SShri Abhyankar /* Do row scaling and add diagonal perturbation */ 643a79edbefSShri Abhyankar ierr = MatDiagonalScale(jac,Db,PETSC_NULL);CHKERRQ(ierr); 644a79edbefSShri Abhyankar ierr = MatDiagonalSet(jac,Da,ADD_VALUES);CHKERRQ(ierr); 645a79edbefSShri Abhyankar if (jac != jac_pre) { /* If jac and jac_pre are different */ 646a79edbefSShri Abhyankar ierr = MatDiagonalScale(jac_pre,Db,PETSC_NULL); 647a79edbefSShri Abhyankar ierr = MatDiagonalSet(jac_pre,Da,ADD_VALUES);CHKERRQ(ierr); 6482b4ed282SShri Abhyankar } 6492b4ed282SShri Abhyankar PetscFunctionReturn(0); 6502b4ed282SShri Abhyankar } 6512b4ed282SShri Abhyankar 6522b4ed282SShri Abhyankar /* 653ee657d29SShri Abhyankar SNESVIComputeMeritFunctionGradient - Computes the gradient of the merit function psi. 654ee657d29SShri Abhyankar 655ee657d29SShri Abhyankar Input Parameters: 656ee657d29SShri Abhyankar phi - semismooth function. 657ee657d29SShri Abhyankar H - semismooth jacobian 658ee657d29SShri Abhyankar 659ee657d29SShri Abhyankar Output Parameters: 660ee657d29SShri Abhyankar dpsi - merit function gradient 661ee657d29SShri Abhyankar 662ee657d29SShri Abhyankar Notes: 663ee657d29SShri Abhyankar The merit function gradient is computed as follows 664ee657d29SShri Abhyankar dpsi = H^T*phi 665ee657d29SShri Abhyankar */ 666ee657d29SShri Abhyankar #undef __FUNCT__ 667ee657d29SShri Abhyankar #define __FUNCT__ "SNESVIComputeMeritFunctionGradient" 668ee657d29SShri Abhyankar PetscErrorCode SNESVIComputeMeritFunctionGradient(Mat H, Vec phi, Vec dpsi) 669ee657d29SShri Abhyankar { 670ee657d29SShri Abhyankar PetscErrorCode ierr; 671ee657d29SShri Abhyankar 672ee657d29SShri Abhyankar PetscFunctionBegin; 6735f48b12bSBarry Smith ierr = MatMultTranspose(H,phi,dpsi);CHKERRQ(ierr); 674ee657d29SShri Abhyankar PetscFunctionReturn(0); 675ee657d29SShri Abhyankar } 676ee657d29SShri Abhyankar 677c1a5e521SShri Abhyankar /* -------------------------------------------------------------------------- */ 678c1a5e521SShri Abhyankar /* 679c1a5e521SShri Abhyankar SNESVIProjectOntoBounds - Projects X onto the feasible region so that Xl[i] <= X[i] <= Xu[i] for i = 1...n. 680c1a5e521SShri Abhyankar 681c1a5e521SShri Abhyankar Input Parameters: 682c1a5e521SShri Abhyankar . SNES - nonlinear solver context 683c1a5e521SShri Abhyankar 684c1a5e521SShri Abhyankar Output Parameters: 685c1a5e521SShri Abhyankar . X - Bound projected X 686c1a5e521SShri Abhyankar 687c1a5e521SShri Abhyankar */ 688c1a5e521SShri Abhyankar 689c1a5e521SShri Abhyankar #undef __FUNCT__ 690c1a5e521SShri Abhyankar #define __FUNCT__ "SNESVIProjectOntoBounds" 691c1a5e521SShri Abhyankar PetscErrorCode SNESVIProjectOntoBounds(SNES snes,Vec X) 692c1a5e521SShri Abhyankar { 693c1a5e521SShri Abhyankar PetscErrorCode ierr; 694c1a5e521SShri Abhyankar SNES_VI *vi = (SNES_VI*)snes->data; 695c1a5e521SShri Abhyankar const PetscScalar *xl,*xu; 696c1a5e521SShri Abhyankar PetscScalar *x; 697c1a5e521SShri Abhyankar PetscInt i,n; 698c1a5e521SShri Abhyankar 699c1a5e521SShri Abhyankar PetscFunctionBegin; 700c1a5e521SShri Abhyankar ierr = VecGetLocalSize(X,&n);CHKERRQ(ierr); 701c1a5e521SShri Abhyankar ierr = VecGetArray(X,&x);CHKERRQ(ierr); 702c1a5e521SShri Abhyankar ierr = VecGetArrayRead(vi->xl,&xl);CHKERRQ(ierr); 703c1a5e521SShri Abhyankar ierr = VecGetArrayRead(vi->xu,&xu);CHKERRQ(ierr); 704c1a5e521SShri Abhyankar 705c1a5e521SShri Abhyankar for(i = 0;i<n;i++) { 70610f5ae6bSBarry Smith if (PetscRealPart(x[i]) < PetscRealPart(xl[i])) x[i] = xl[i]; 70710f5ae6bSBarry Smith else if (PetscRealPart(x[i]) > PetscRealPart(xu[i])) x[i] = xu[i]; 708c1a5e521SShri Abhyankar } 709c1a5e521SShri Abhyankar ierr = VecRestoreArray(X,&x);CHKERRQ(ierr); 710c1a5e521SShri Abhyankar ierr = VecRestoreArrayRead(vi->xl,&xl);CHKERRQ(ierr); 711c1a5e521SShri Abhyankar ierr = VecRestoreArrayRead(vi->xu,&xu);CHKERRQ(ierr); 712c1a5e521SShri Abhyankar PetscFunctionReturn(0); 713c1a5e521SShri Abhyankar } 714c1a5e521SShri Abhyankar 7152b4ed282SShri Abhyankar /* -------------------------------------------------------------------- 7162b4ed282SShri Abhyankar 7172b4ed282SShri Abhyankar This file implements a semismooth truncated Newton method with a line search, 7182b4ed282SShri Abhyankar for solving a system of nonlinear equations in complementarity form, using the KSP, Vec, 7192b4ed282SShri Abhyankar and Mat interfaces for linear solvers, vectors, and matrices, 7202b4ed282SShri Abhyankar respectively. 7212b4ed282SShri Abhyankar 7222b4ed282SShri Abhyankar The following basic routines are required for each nonlinear solver: 7232b4ed282SShri Abhyankar SNESCreate_XXX() - Creates a nonlinear solver context 7242b4ed282SShri Abhyankar SNESSetFromOptions_XXX() - Sets runtime options 7252b4ed282SShri Abhyankar SNESSolve_XXX() - Solves the nonlinear system 7262b4ed282SShri Abhyankar SNESDestroy_XXX() - Destroys the nonlinear solver context 7272b4ed282SShri Abhyankar The suffix "_XXX" denotes a particular implementation, in this case 7282b4ed282SShri Abhyankar we use _VI (e.g., SNESCreate_VI, SNESSolve_VI) for solving 7292b4ed282SShri Abhyankar systems of nonlinear equations with a line search (LS) method. 7302b4ed282SShri Abhyankar These routines are actually called via the common user interface 7312b4ed282SShri Abhyankar routines SNESCreate(), SNESSetFromOptions(), SNESSolve(), and 7322b4ed282SShri Abhyankar SNESDestroy(), so the application code interface remains identical 7332b4ed282SShri Abhyankar for all nonlinear solvers. 7342b4ed282SShri Abhyankar 7352b4ed282SShri Abhyankar Another key routine is: 7362b4ed282SShri Abhyankar SNESSetUp_XXX() - Prepares for the use of a nonlinear solver 7372b4ed282SShri Abhyankar by setting data structures and options. The interface routine SNESSetUp() 7382b4ed282SShri Abhyankar is not usually called directly by the user, but instead is called by 7392b4ed282SShri Abhyankar SNESSolve() if necessary. 7402b4ed282SShri Abhyankar 7412b4ed282SShri Abhyankar Additional basic routines are: 7422b4ed282SShri Abhyankar SNESView_XXX() - Prints details of runtime options that 7432b4ed282SShri Abhyankar have actually been used. 7442b4ed282SShri Abhyankar These are called by application codes via the interface routines 7452b4ed282SShri Abhyankar SNESView(). 7462b4ed282SShri Abhyankar 7472b4ed282SShri Abhyankar The various types of solvers (preconditioners, Krylov subspace methods, 7482b4ed282SShri Abhyankar nonlinear solvers, timesteppers) are all organized similarly, so the 7492b4ed282SShri Abhyankar above description applies to these categories also. 7502b4ed282SShri Abhyankar 7512b4ed282SShri Abhyankar -------------------------------------------------------------------- */ 7522b4ed282SShri Abhyankar /* 75369c03620SShri Abhyankar SNESSolveVI_SS - Solves the complementarity problem with a semismooth Newton 7542b4ed282SShri Abhyankar method using a line search. 7552b4ed282SShri Abhyankar 7562b4ed282SShri Abhyankar Input Parameters: 7572b4ed282SShri Abhyankar . snes - the SNES context 7582b4ed282SShri Abhyankar 7592b4ed282SShri Abhyankar Output Parameter: 7602b4ed282SShri Abhyankar . outits - number of iterations until termination 7612b4ed282SShri Abhyankar 7622b4ed282SShri Abhyankar Application Interface Routine: SNESSolve() 7632b4ed282SShri Abhyankar 7642b4ed282SShri Abhyankar Notes: 7652b4ed282SShri Abhyankar This implements essentially a semismooth Newton method with a 76651defd01SShri Abhyankar line search. The default line search does not do any line seach 76751defd01SShri Abhyankar but rather takes a full newton step. 7682b4ed282SShri Abhyankar */ 7692b4ed282SShri Abhyankar #undef __FUNCT__ 77069c03620SShri Abhyankar #define __FUNCT__ "SNESSolveVI_SS" 77169c03620SShri Abhyankar PetscErrorCode SNESSolveVI_SS(SNES snes) 7722b4ed282SShri Abhyankar { 7732b4ed282SShri Abhyankar SNES_VI *vi = (SNES_VI*)snes->data; 7742b4ed282SShri Abhyankar PetscErrorCode ierr; 7752b4ed282SShri Abhyankar PetscInt maxits,i,lits; 7763b336b49SShri Abhyankar PetscBool lssucceed; 7772b4ed282SShri Abhyankar MatStructure flg = DIFFERENT_NONZERO_PATTERN; 7782b4ed282SShri Abhyankar PetscReal gnorm,xnorm=0,ynorm; 7792b4ed282SShri Abhyankar Vec Y,X,F,G,W; 7802b4ed282SShri Abhyankar KSPConvergedReason kspreason; 7812b4ed282SShri Abhyankar 7822b4ed282SShri Abhyankar PetscFunctionBegin; 7839ce7406fSBarry Smith vi->computeuserfunction = snes->ops->computefunction; 7849ce7406fSBarry Smith snes->ops->computefunction = SNESVIComputeFunction; 7859ce7406fSBarry Smith 7862b4ed282SShri Abhyankar snes->numFailures = 0; 7872b4ed282SShri Abhyankar snes->numLinearSolveFailures = 0; 7882b4ed282SShri Abhyankar snes->reason = SNES_CONVERGED_ITERATING; 7892b4ed282SShri Abhyankar 7902b4ed282SShri Abhyankar maxits = snes->max_its; /* maximum number of iterations */ 7912b4ed282SShri Abhyankar X = snes->vec_sol; /* solution vector */ 7922b4ed282SShri Abhyankar F = snes->vec_func; /* residual vector */ 7932b4ed282SShri Abhyankar Y = snes->work[0]; /* work vectors */ 7942b4ed282SShri Abhyankar G = snes->work[1]; 7952b4ed282SShri Abhyankar W = snes->work[2]; 7962b4ed282SShri Abhyankar 7972b4ed282SShri Abhyankar ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 7982b4ed282SShri Abhyankar snes->iter = 0; 7992b4ed282SShri Abhyankar snes->norm = 0.0; 8002b4ed282SShri Abhyankar ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 8012b4ed282SShri Abhyankar 8027fe79bc4SShri Abhyankar ierr = SNESVIProjectOntoBounds(snes,X);CHKERRQ(ierr); 8032b4ed282SShri Abhyankar ierr = SNESComputeFunction(snes,X,vi->phi);CHKERRQ(ierr); 8042b4ed282SShri Abhyankar if (snes->domainerror) { 8052b4ed282SShri Abhyankar snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN; 8069ce7406fSBarry Smith snes->ops->computefunction = vi->computeuserfunction; 8072b4ed282SShri Abhyankar PetscFunctionReturn(0); 8082b4ed282SShri Abhyankar } 8092b4ed282SShri Abhyankar /* Compute Merit function */ 8102b4ed282SShri Abhyankar ierr = SNESVIComputeMeritFunction(vi->phi,&vi->merit,&vi->phinorm);CHKERRQ(ierr); 8112b4ed282SShri Abhyankar 8122b4ed282SShri Abhyankar ierr = VecNormBegin(X,NORM_2,&xnorm);CHKERRQ(ierr); /* xnorm <- ||x|| */ 8132b4ed282SShri Abhyankar ierr = VecNormEnd(X,NORM_2,&xnorm);CHKERRQ(ierr); 81462cbcd01SMatthew G Knepley if (PetscIsInfOrNanReal(vi->merit)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number"); 8152b4ed282SShri Abhyankar 8162b4ed282SShri Abhyankar ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 8172b4ed282SShri Abhyankar snes->norm = vi->phinorm; 8182b4ed282SShri Abhyankar ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 8192b4ed282SShri Abhyankar SNESLogConvHistory(snes,vi->phinorm,0); 8207a03ce2fSLisandro Dalcin ierr = SNESMonitor(snes,0,vi->phinorm);CHKERRQ(ierr); 8212b4ed282SShri Abhyankar 8222b4ed282SShri Abhyankar /* set parameter for default relative tolerance convergence test */ 8232b4ed282SShri Abhyankar snes->ttol = vi->phinorm*snes->rtol; 8242b4ed282SShri Abhyankar /* test convergence */ 8252b4ed282SShri Abhyankar ierr = (*snes->ops->converged)(snes,0,0.0,0.0,vi->phinorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); 8269ce7406fSBarry Smith if (snes->reason) { 8279ce7406fSBarry Smith snes->ops->computefunction = vi->computeuserfunction; 8289ce7406fSBarry Smith PetscFunctionReturn(0); 8299ce7406fSBarry Smith } 8302b4ed282SShri Abhyankar 8312b4ed282SShri Abhyankar for (i=0; i<maxits; i++) { 8322b4ed282SShri Abhyankar 8332b4ed282SShri Abhyankar /* Call general purpose update function */ 8342b4ed282SShri Abhyankar if (snes->ops->update) { 8352b4ed282SShri Abhyankar ierr = (*snes->ops->update)(snes, snes->iter);CHKERRQ(ierr); 8362b4ed282SShri Abhyankar } 8372b4ed282SShri Abhyankar 8382b4ed282SShri Abhyankar /* Solve J Y = Phi, where J is the semismooth jacobian */ 839a79edbefSShri Abhyankar /* Get the nonlinear function jacobian */ 8402b4ed282SShri Abhyankar ierr = SNESComputeJacobian(snes,X,&snes->jacobian,&snes->jacobian_pre,&flg);CHKERRQ(ierr); 841a79edbefSShri Abhyankar /* Get the diagonal shift and row scaling vectors */ 842a79edbefSShri Abhyankar ierr = SNESVIComputeBsubdifferentialVectors(snes,X,F,snes->jacobian,vi->Da,vi->Db);CHKERRQ(ierr); 843a79edbefSShri Abhyankar /* Compute the semismooth jacobian */ 844a79edbefSShri Abhyankar ierr = SNESVIComputeJacobian(snes->jacobian,snes->jacobian_pre,vi->Da,vi->Db);CHKERRQ(ierr); 845ee657d29SShri Abhyankar /* Compute the merit function gradient */ 846ee657d29SShri Abhyankar ierr = SNESVIComputeMeritFunctionGradient(snes->jacobian,vi->phi,vi->dpsi);CHKERRQ(ierr); 8472b4ed282SShri Abhyankar ierr = KSPSetOperators(snes->ksp,snes->jacobian,snes->jacobian_pre,flg);CHKERRQ(ierr); 8482b4ed282SShri Abhyankar ierr = SNES_KSPSolve(snes,snes->ksp,vi->phi,Y);CHKERRQ(ierr); 8492b4ed282SShri Abhyankar ierr = KSPGetConvergedReason(snes->ksp,&kspreason);CHKERRQ(ierr); 8503b336b49SShri Abhyankar 8513b336b49SShri Abhyankar if (kspreason < 0) { 8522b4ed282SShri Abhyankar if (++snes->numLinearSolveFailures >= snes->maxLinearSolveFailures) { 8532b4ed282SShri 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); 8542b4ed282SShri Abhyankar snes->reason = SNES_DIVERGED_LINEAR_SOLVE; 8552b4ed282SShri Abhyankar break; 8562b4ed282SShri Abhyankar } 8572b4ed282SShri Abhyankar } 8582b4ed282SShri Abhyankar ierr = KSPGetIterationNumber(snes->ksp,&lits);CHKERRQ(ierr); 8592b4ed282SShri Abhyankar snes->linear_its += lits; 8602b4ed282SShri Abhyankar ierr = PetscInfo2(snes,"iter=%D, linear solve iterations=%D\n",snes->iter,lits);CHKERRQ(ierr); 8612b4ed282SShri Abhyankar /* 8622b4ed282SShri Abhyankar if (vi->precheckstep) { 863ace3abfcSBarry Smith PetscBool changed_y = PETSC_FALSE; 8642b4ed282SShri Abhyankar ierr = (*vi->precheckstep)(snes,X,Y,vi->precheck,&changed_y);CHKERRQ(ierr); 8652b4ed282SShri Abhyankar } 8662b4ed282SShri Abhyankar 8672b4ed282SShri Abhyankar if (PetscLogPrintInfo){ 8682b4ed282SShri Abhyankar ierr = SNESVICheckResidual_Private(snes,snes->jacobian,F,Y,G,W);CHKERRQ(ierr); 8692b4ed282SShri Abhyankar } 8702b4ed282SShri Abhyankar */ 8712b4ed282SShri Abhyankar /* Compute a (scaled) negative update in the line search routine: 8722b4ed282SShri Abhyankar Y <- X - lambda*Y 8732b4ed282SShri Abhyankar and evaluate G = function(Y) (depends on the line search). 8742b4ed282SShri Abhyankar */ 8752b4ed282SShri Abhyankar ierr = VecCopy(Y,snes->vec_sol_update);CHKERRQ(ierr); 8762b4ed282SShri Abhyankar ynorm = 1; gnorm = vi->phinorm; 8772b4ed282SShri Abhyankar ierr = (*vi->LineSearch)(snes,vi->lsP,X,vi->phi,G,Y,W,vi->phinorm,xnorm,&ynorm,&gnorm,&lssucceed);CHKERRQ(ierr); 8782b4ed282SShri Abhyankar ierr = PetscInfo4(snes,"fnorm=%18.16e, gnorm=%18.16e, ynorm=%18.16e, lssucceed=%d\n",vi->phinorm,gnorm,ynorm,(int)lssucceed);CHKERRQ(ierr); 8792b4ed282SShri Abhyankar if (snes->reason == SNES_DIVERGED_FUNCTION_COUNT) break; 8802b4ed282SShri Abhyankar if (snes->domainerror) { 8812b4ed282SShri Abhyankar snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN; 8829ce7406fSBarry Smith snes->ops->computefunction = vi->computeuserfunction; 8832b4ed282SShri Abhyankar PetscFunctionReturn(0); 8842b4ed282SShri Abhyankar } 8852b4ed282SShri Abhyankar if (!lssucceed) { 8862b4ed282SShri Abhyankar if (++snes->numFailures >= snes->maxFailures) { 887ace3abfcSBarry Smith PetscBool ismin; 8882b4ed282SShri Abhyankar snes->reason = SNES_DIVERGED_LINE_SEARCH; 8892b4ed282SShri Abhyankar ierr = SNESVICheckLocalMin_Private(snes,snes->jacobian,G,W,gnorm,&ismin);CHKERRQ(ierr); 8902b4ed282SShri Abhyankar if (ismin) snes->reason = SNES_DIVERGED_LOCAL_MIN; 8912b4ed282SShri Abhyankar break; 8922b4ed282SShri Abhyankar } 8932b4ed282SShri Abhyankar } 8942b4ed282SShri Abhyankar /* Update function and solution vectors */ 8952b4ed282SShri Abhyankar vi->phinorm = gnorm; 8962b4ed282SShri Abhyankar vi->merit = 0.5*vi->phinorm*vi->phinorm; 8972b4ed282SShri Abhyankar ierr = VecCopy(G,vi->phi);CHKERRQ(ierr); 8982b4ed282SShri Abhyankar ierr = VecCopy(W,X);CHKERRQ(ierr); 8992b4ed282SShri Abhyankar /* Monitor convergence */ 9002b4ed282SShri Abhyankar ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 9012b4ed282SShri Abhyankar snes->iter = i+1; 9022b4ed282SShri Abhyankar snes->norm = vi->phinorm; 9032b4ed282SShri Abhyankar ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 9042b4ed282SShri Abhyankar SNESLogConvHistory(snes,snes->norm,lits); 9057a03ce2fSLisandro Dalcin ierr = SNESMonitor(snes,snes->iter,snes->norm);CHKERRQ(ierr); 9062b4ed282SShri Abhyankar /* Test for convergence, xnorm = || X || */ 9072b4ed282SShri Abhyankar if (snes->ops->converged != SNESSkipConverged) { ierr = VecNorm(X,NORM_2,&xnorm);CHKERRQ(ierr); } 9082b4ed282SShri Abhyankar ierr = (*snes->ops->converged)(snes,snes->iter,xnorm,ynorm,vi->phinorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); 9092b4ed282SShri Abhyankar if (snes->reason) break; 9102b4ed282SShri Abhyankar } 9112b4ed282SShri Abhyankar if (i == maxits) { 9122b4ed282SShri Abhyankar ierr = PetscInfo1(snes,"Maximum number of iterations has been reached: %D\n",maxits);CHKERRQ(ierr); 9132b4ed282SShri Abhyankar if(!snes->reason) snes->reason = SNES_DIVERGED_MAX_IT; 9142b4ed282SShri Abhyankar } 9159ce7406fSBarry Smith snes->ops->computefunction = vi->computeuserfunction; 9162b4ed282SShri Abhyankar PetscFunctionReturn(0); 9172b4ed282SShri Abhyankar } 91869c03620SShri Abhyankar 91969c03620SShri Abhyankar #undef __FUNCT__ 920693ddf92SShri Abhyankar #define __FUNCT__ "SNESVIGetActiveSetIS" 921693ddf92SShri Abhyankar /* 922693ddf92SShri Abhyankar SNESVIGetActiveSetIndices - Gets the global indices for the active set variables 923693ddf92SShri Abhyankar 924693ddf92SShri Abhyankar Input parameter 925693ddf92SShri Abhyankar . snes - the SNES context 926693ddf92SShri Abhyankar . X - the snes solution vector 927693ddf92SShri Abhyankar . F - the nonlinear function vector 928693ddf92SShri Abhyankar 929693ddf92SShri Abhyankar Output parameter 930693ddf92SShri Abhyankar . ISact - active set index set 931693ddf92SShri Abhyankar */ 932693ddf92SShri Abhyankar PetscErrorCode SNESVIGetActiveSetIS(SNES snes,Vec X,Vec F,IS* ISact) 933d950fb63SShri Abhyankar { 934d950fb63SShri Abhyankar PetscErrorCode ierr; 935693ddf92SShri Abhyankar SNES_VI *vi = (SNES_VI*)snes->data; 936693ddf92SShri Abhyankar Vec Xl=vi->xl,Xu=vi->xu; 937693ddf92SShri Abhyankar const PetscScalar *x,*f,*xl,*xu; 938693ddf92SShri Abhyankar PetscInt *idx_act,i,nlocal,nloc_isact=0,ilow,ihigh,i1=0; 939d950fb63SShri Abhyankar 940d950fb63SShri Abhyankar PetscFunctionBegin; 941d950fb63SShri Abhyankar ierr = VecGetLocalSize(X,&nlocal);CHKERRQ(ierr); 942d950fb63SShri Abhyankar ierr = VecGetOwnershipRange(X,&ilow,&ihigh);CHKERRQ(ierr); 943fe835674SShri Abhyankar ierr = VecGetArrayRead(X,&x);CHKERRQ(ierr); 944fe835674SShri Abhyankar ierr = VecGetArrayRead(Xl,&xl);CHKERRQ(ierr); 945fe835674SShri Abhyankar ierr = VecGetArrayRead(Xu,&xu);CHKERRQ(ierr); 946fe835674SShri Abhyankar ierr = VecGetArrayRead(F,&f);CHKERRQ(ierr); 947693ddf92SShri Abhyankar /* Compute active set size */ 948d950fb63SShri Abhyankar for (i=0; i < nlocal;i++) { 949*e6337399SBarry Smith if (!vi->ignorefunctionsign) { 95010f5ae6bSBarry 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++; 951*e6337399SBarry Smith } else { 952*e6337399SBarry Smith if (!(PetscRealPart(x[i]) > PetscRealPart(xl[i]) + 1.e-8 && PetscRealPart(x[i]) < PetscRealPart(xu[i]) - 1.e-8)) nloc_isact++; 953*e6337399SBarry Smith } 954d950fb63SShri Abhyankar } 955693ddf92SShri Abhyankar 956d950fb63SShri Abhyankar ierr = PetscMalloc(nloc_isact*sizeof(PetscInt),&idx_act);CHKERRQ(ierr); 957d950fb63SShri Abhyankar 958693ddf92SShri Abhyankar /* Set active set indices */ 959d950fb63SShri Abhyankar for(i=0; i < nlocal; i++) { 960*e6337399SBarry Smith if (!vi->ignorefunctionsign) { 96110f5ae6bSBarry 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; 962*e6337399SBarry Smith } else { 963*e6337399SBarry Smith if (!(PetscRealPart(x[i]) > PetscRealPart(xl[i]) + 1.e-8 && PetscRealPart(x[i]) < PetscRealPart(xu[i]) - 1.e-8)) idx_act[i1++] = ilow+i; 964*e6337399SBarry Smith } 965d950fb63SShri Abhyankar } 966d950fb63SShri Abhyankar 967693ddf92SShri Abhyankar /* Create active set IS */ 96862298a1eSBarry Smith ierr = ISCreateGeneral(((PetscObject)snes)->comm,nloc_isact,idx_act,PETSC_OWN_POINTER,ISact);CHKERRQ(ierr); 969d950fb63SShri Abhyankar 970fe835674SShri Abhyankar ierr = VecRestoreArrayRead(X,&x);CHKERRQ(ierr); 971fe835674SShri Abhyankar ierr = VecRestoreArrayRead(Xl,&xl);CHKERRQ(ierr); 972fe835674SShri Abhyankar ierr = VecRestoreArrayRead(Xu,&xu);CHKERRQ(ierr); 973fe835674SShri Abhyankar ierr = VecRestoreArrayRead(F,&f);CHKERRQ(ierr); 974d950fb63SShri Abhyankar PetscFunctionReturn(0); 975d950fb63SShri Abhyankar } 976d950fb63SShri Abhyankar 977693ddf92SShri Abhyankar #undef __FUNCT__ 978693ddf92SShri Abhyankar #define __FUNCT__ "SNESVICreateIndexSets_RS" 979693ddf92SShri Abhyankar PetscErrorCode SNESVICreateIndexSets_RS(SNES snes,Vec X,Vec F,IS* ISact,IS* ISinact) 980693ddf92SShri Abhyankar { 981693ddf92SShri Abhyankar PetscErrorCode ierr; 982693ddf92SShri Abhyankar 983693ddf92SShri Abhyankar PetscFunctionBegin; 984693ddf92SShri Abhyankar ierr = SNESVIGetActiveSetIS(snes,X,F,ISact);CHKERRQ(ierr); 985693ddf92SShri Abhyankar ierr = ISComplement(*ISact,X->map->rstart,X->map->rend,ISinact);CHKERRQ(ierr); 986693ddf92SShri Abhyankar PetscFunctionReturn(0); 987693ddf92SShri Abhyankar } 988693ddf92SShri Abhyankar 989dbd914b8SShri Abhyankar /* Create active and inactive set vectors. The local size of this vector is set and petsc computes the global size */ 990dbd914b8SShri Abhyankar #undef __FUNCT__ 991fe835674SShri Abhyankar #define __FUNCT__ "SNESVICreateSubVectors" 992fe835674SShri Abhyankar PetscErrorCode SNESVICreateSubVectors(SNES snes,PetscInt n,Vec* newv) 993dbd914b8SShri Abhyankar { 994dbd914b8SShri Abhyankar PetscErrorCode ierr; 995dbd914b8SShri Abhyankar Vec v; 996dbd914b8SShri Abhyankar 997dbd914b8SShri Abhyankar PetscFunctionBegin; 998dbd914b8SShri Abhyankar ierr = VecCreate(((PetscObject)snes)->comm,&v);CHKERRQ(ierr); 999dbd914b8SShri Abhyankar ierr = VecSetSizes(v,n,PETSC_DECIDE);CHKERRQ(ierr); 1000dbd914b8SShri Abhyankar ierr = VecSetFromOptions(v);CHKERRQ(ierr); 1001dbd914b8SShri Abhyankar *newv = v; 1002dbd914b8SShri Abhyankar 1003dbd914b8SShri Abhyankar PetscFunctionReturn(0); 1004dbd914b8SShri Abhyankar } 1005dbd914b8SShri Abhyankar 1006732bb160SShri Abhyankar /* Resets the snes PC and KSP when the active set sizes change */ 1007732bb160SShri Abhyankar #undef __FUNCT__ 1008732bb160SShri Abhyankar #define __FUNCT__ "SNESVIResetPCandKSP" 1009732bb160SShri Abhyankar PetscErrorCode SNESVIResetPCandKSP(SNES snes,Mat Amat,Mat Pmat) 1010732bb160SShri Abhyankar { 1011732bb160SShri Abhyankar PetscErrorCode ierr; 1012d0af7cd3SBarry Smith KSP snesksp; 1013dbd914b8SShri Abhyankar 1014732bb160SShri Abhyankar PetscFunctionBegin; 1015732bb160SShri Abhyankar ierr = SNESGetKSP(snes,&snesksp);CHKERRQ(ierr); 1016d0af7cd3SBarry Smith ierr = KSPReset(snesksp);CHKERRQ(ierr); 1017c2efdce3SBarry Smith 1018c2efdce3SBarry Smith /* 1019d0af7cd3SBarry Smith KSP kspnew; 1020d0af7cd3SBarry Smith PC pcnew; 1021d0af7cd3SBarry Smith const MatSolverPackage stype; 1022d0af7cd3SBarry Smith 1023c2efdce3SBarry Smith 1024732bb160SShri Abhyankar ierr = KSPCreate(((PetscObject)snes)->comm,&kspnew);CHKERRQ(ierr); 1025732bb160SShri Abhyankar kspnew->pc_side = snesksp->pc_side; 1026732bb160SShri Abhyankar kspnew->rtol = snesksp->rtol; 1027732bb160SShri Abhyankar kspnew->abstol = snesksp->abstol; 1028732bb160SShri Abhyankar kspnew->max_it = snesksp->max_it; 1029732bb160SShri Abhyankar ierr = KSPSetType(kspnew,((PetscObject)snesksp)->type_name);CHKERRQ(ierr); 1030732bb160SShri Abhyankar ierr = KSPGetPC(kspnew,&pcnew);CHKERRQ(ierr); 1031732bb160SShri Abhyankar ierr = PCSetType(kspnew->pc,((PetscObject)snesksp->pc)->type_name);CHKERRQ(ierr); 1032732bb160SShri Abhyankar ierr = PCSetOperators(kspnew->pc,Amat,Pmat,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr); 1033732bb160SShri Abhyankar ierr = PCFactorGetMatSolverPackage(snesksp->pc,&stype);CHKERRQ(ierr); 1034732bb160SShri Abhyankar ierr = PCFactorSetMatSolverPackage(kspnew->pc,stype);CHKERRQ(ierr); 10356bf464f9SBarry Smith ierr = KSPDestroy(&snesksp);CHKERRQ(ierr); 1036732bb160SShri Abhyankar snes->ksp = kspnew; 1037732bb160SShri Abhyankar ierr = PetscLogObjectParent(snes,kspnew);CHKERRQ(ierr); 1038d0af7cd3SBarry Smith ierr = KSPSetFromOptions(kspnew);CHKERRQ(ierr);*/ 1039732bb160SShri Abhyankar PetscFunctionReturn(0); 1040732bb160SShri Abhyankar } 104169c03620SShri Abhyankar 104269c03620SShri Abhyankar 1043fe835674SShri Abhyankar #undef __FUNCT__ 1044fe835674SShri Abhyankar #define __FUNCT__ "SNESVIComputeInactiveSetFnorm" 104510f5ae6bSBarry Smith PetscErrorCode SNESVIComputeInactiveSetFnorm(SNES snes,Vec F,Vec X,PetscReal *fnorm) 1046fe835674SShri Abhyankar { 1047fe835674SShri Abhyankar PetscErrorCode ierr; 1048fe835674SShri Abhyankar SNES_VI *vi = (SNES_VI*)snes->data; 1049fe835674SShri Abhyankar const PetscScalar *x,*xl,*xu,*f; 1050fe835674SShri Abhyankar PetscInt i,n; 1051fe835674SShri Abhyankar PetscReal rnorm; 1052fe835674SShri Abhyankar 1053fe835674SShri Abhyankar PetscFunctionBegin; 1054fe835674SShri Abhyankar ierr = VecGetLocalSize(X,&n);CHKERRQ(ierr); 1055fe835674SShri Abhyankar ierr = VecGetArrayRead(vi->xl,&xl);CHKERRQ(ierr); 1056fe835674SShri Abhyankar ierr = VecGetArrayRead(vi->xu,&xu);CHKERRQ(ierr); 1057fe835674SShri Abhyankar ierr = VecGetArrayRead(X,&x);CHKERRQ(ierr); 1058fe835674SShri Abhyankar ierr = VecGetArrayRead(F,&f);CHKERRQ(ierr); 1059fe835674SShri Abhyankar rnorm = 0.0; 1060fe835674SShri Abhyankar for (i=0; i<n; i++) { 106110f5ae6bSBarry 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]); 1062fe835674SShri Abhyankar } 1063fe835674SShri Abhyankar ierr = VecRestoreArrayRead(F,&f);CHKERRQ(ierr); 1064fe835674SShri Abhyankar ierr = VecRestoreArrayRead(vi->xl,&xl);CHKERRQ(ierr); 1065fe835674SShri Abhyankar ierr = VecRestoreArrayRead(vi->xu,&xu);CHKERRQ(ierr); 1066fe835674SShri Abhyankar ierr = VecRestoreArrayRead(X,&x);CHKERRQ(ierr); 1067d9822059SBarry Smith ierr = MPI_Allreduce(&rnorm,fnorm,1,MPIU_REAL,MPIU_SUM,((PetscObject)snes)->comm);CHKERRQ(ierr); 1068fe835674SShri Abhyankar *fnorm = sqrt(*fnorm); 1069fe835674SShri Abhyankar PetscFunctionReturn(0); 1070fe835674SShri Abhyankar } 1071fe835674SShri Abhyankar 1072fe835674SShri Abhyankar /* Variational Inequality solver using reduce space method. No semismooth algorithm is 1073c2efdce3SBarry Smith implemented in this algorithm. It basically identifies the active constraints and does 1074c2efdce3SBarry Smith a linear solve on the other variables (those not associated with the active constraints). */ 1075d950fb63SShri Abhyankar #undef __FUNCT__ 1076d950fb63SShri Abhyankar #define __FUNCT__ "SNESSolveVI_RS" 1077d950fb63SShri Abhyankar PetscErrorCode SNESSolveVI_RS(SNES snes) 1078d950fb63SShri Abhyankar { 1079d950fb63SShri Abhyankar SNES_VI *vi = (SNES_VI*)snes->data; 1080d950fb63SShri Abhyankar PetscErrorCode ierr; 1081abcba341SShri Abhyankar PetscInt maxits,i,lits; 1082d950fb63SShri Abhyankar PetscBool lssucceed; 1083d950fb63SShri Abhyankar MatStructure flg = DIFFERENT_NONZERO_PATTERN; 1084fe835674SShri Abhyankar PetscReal fnorm,gnorm,xnorm=0,ynorm; 1085d950fb63SShri Abhyankar Vec Y,X,F,G,W; 1086d950fb63SShri Abhyankar KSPConvergedReason kspreason; 1087d950fb63SShri Abhyankar 1088d950fb63SShri Abhyankar PetscFunctionBegin; 1089d950fb63SShri Abhyankar snes->numFailures = 0; 1090d950fb63SShri Abhyankar snes->numLinearSolveFailures = 0; 1091d950fb63SShri Abhyankar snes->reason = SNES_CONVERGED_ITERATING; 1092d950fb63SShri Abhyankar 1093d950fb63SShri Abhyankar maxits = snes->max_its; /* maximum number of iterations */ 1094d950fb63SShri Abhyankar X = snes->vec_sol; /* solution vector */ 1095d950fb63SShri Abhyankar F = snes->vec_func; /* residual vector */ 1096d950fb63SShri Abhyankar Y = snes->work[0]; /* work vectors */ 1097d950fb63SShri Abhyankar G = snes->work[1]; 1098d950fb63SShri Abhyankar W = snes->work[2]; 1099d950fb63SShri Abhyankar 1100d950fb63SShri Abhyankar ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 1101d950fb63SShri Abhyankar snes->iter = 0; 1102d950fb63SShri Abhyankar snes->norm = 0.0; 1103d950fb63SShri Abhyankar ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 1104d950fb63SShri Abhyankar 11057fe79bc4SShri Abhyankar ierr = SNESVIProjectOntoBounds(snes,X);CHKERRQ(ierr); 1106fe835674SShri Abhyankar ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr); 1107d950fb63SShri Abhyankar if (snes->domainerror) { 1108d950fb63SShri Abhyankar snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN; 1109d950fb63SShri Abhyankar PetscFunctionReturn(0); 1110d950fb63SShri Abhyankar } 1111fe835674SShri Abhyankar ierr = SNESVIComputeInactiveSetFnorm(snes,F,X,&fnorm);CHKERRQ(ierr); 1112d950fb63SShri Abhyankar ierr = VecNormBegin(X,NORM_2,&xnorm);CHKERRQ(ierr); /* xnorm <- ||x|| */ 1113d950fb63SShri Abhyankar ierr = VecNormEnd(X,NORM_2,&xnorm);CHKERRQ(ierr); 111462cbcd01SMatthew G Knepley if (PetscIsInfOrNanReal(fnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number"); 1115d950fb63SShri Abhyankar 1116d950fb63SShri Abhyankar ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 1117fe835674SShri Abhyankar snes->norm = fnorm; 1118d950fb63SShri Abhyankar ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 1119fe835674SShri Abhyankar SNESLogConvHistory(snes,fnorm,0); 11207a03ce2fSLisandro Dalcin ierr = SNESMonitor(snes,0,fnorm);CHKERRQ(ierr); 1121d950fb63SShri Abhyankar 1122d950fb63SShri Abhyankar /* set parameter for default relative tolerance convergence test */ 1123fe835674SShri Abhyankar snes->ttol = fnorm*snes->rtol; 1124d950fb63SShri Abhyankar /* test convergence */ 1125fe835674SShri Abhyankar ierr = (*snes->ops->converged)(snes,0,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); 1126d950fb63SShri Abhyankar if (snes->reason) PetscFunctionReturn(0); 1127d950fb63SShri Abhyankar 11289ce20c35SJungho Lee 1129d950fb63SShri Abhyankar for (i=0; i<maxits; i++) { 1130d950fb63SShri Abhyankar 1131d950fb63SShri Abhyankar IS IS_act,IS_inact; /* _act -> active set _inact -> inactive set */ 1132a6b72b01SJungho Lee IS IS_redact; /* redundant active set */ 1133d950fb63SShri Abhyankar VecScatter scat_act,scat_inact; 1134abcba341SShri Abhyankar PetscInt nis_act,nis_inact; 1135fe835674SShri Abhyankar Vec Y_act,Y_inact,F_inact; 1136d950fb63SShri Abhyankar Mat jac_inact_inact,prejac_inact_inact; 113762298a1eSBarry Smith IS keptrows; 1138abcba341SShri Abhyankar PetscBool isequal; 1139d950fb63SShri Abhyankar 1140d950fb63SShri Abhyankar /* Call general purpose update function */ 1141d950fb63SShri Abhyankar if (snes->ops->update) { 1142d950fb63SShri Abhyankar ierr = (*snes->ops->update)(snes, snes->iter);CHKERRQ(ierr); 1143d950fb63SShri Abhyankar } 1144d950fb63SShri Abhyankar ierr = SNESComputeJacobian(snes,X,&snes->jacobian,&snes->jacobian_pre,&flg);CHKERRQ(ierr); 114562298a1eSBarry Smith 11469ce20c35SJungho Lee 1147d950fb63SShri Abhyankar /* Create active and inactive index sets */ 1148a6b72b01SJungho Lee 1149a6b72b01SJungho Lee /*original 1150693ddf92SShri Abhyankar ierr = SNESVICreateIndexSets_RS(snes,X,F,&IS_act,&IS_inact);CHKERRQ(ierr); 1151a6b72b01SJungho Lee */ 1152a6b72b01SJungho Lee ierr = SNESVIGetActiveSetIS(snes,X,F,&IS_act);CHKERRQ(ierr); 1153a6b72b01SJungho Lee 1154a6b72b01SJungho Lee if (vi->checkredundancy) { 1155a6b72b01SJungho Lee (*vi->checkredundancy)(snes,IS_act,&IS_redact,vi->ctxP);CHKERRQ(ierr); 1156ed70e96aSJungho Lee if (IS_redact){ 1157ed70e96aSJungho Lee ierr = ISSort(IS_redact);CHKERRQ(ierr); 1158a6b72b01SJungho Lee ierr = ISComplement(IS_redact,X->map->rstart,X->map->rend,&IS_inact);CHKERRQ(ierr); 1159a6b72b01SJungho Lee ierr = ISDestroy(&IS_redact);CHKERRQ(ierr); 1160ed70e96aSJungho Lee } 1161ed70e96aSJungho Lee else { 1162ed70e96aSJungho Lee ierr = ISComplement(IS_act,X->map->rstart,X->map->rend,&IS_inact);CHKERRQ(ierr); 1163ed70e96aSJungho Lee } 1164a6b72b01SJungho Lee } else { 1165a6b72b01SJungho Lee ierr = ISComplement(IS_act,X->map->rstart,X->map->rend,&IS_inact);CHKERRQ(ierr); 1166a6b72b01SJungho Lee } 1167d950fb63SShri Abhyankar 11684dcab191SBarry Smith 1169abcba341SShri Abhyankar /* Create inactive set submatrix */ 117062298a1eSBarry Smith ierr = MatGetSubMatrix(snes->jacobian,IS_inact,IS_inact,MAT_INITIAL_MATRIX,&jac_inact_inact);CHKERRQ(ierr); 1171a6b72b01SJungho Lee 1172b3a44c85SBarry Smith ierr = MatFindNonzeroRows(jac_inact_inact,&keptrows);CHKERRQ(ierr); 11739ce20c35SJungho Lee if (0 && keptrows) { 11749ce20c35SJungho Lee // if (keptrows) { 117562298a1eSBarry Smith PetscInt cnt,*nrows,k; 117662298a1eSBarry Smith const PetscInt *krows,*inact; 117727d4218bSShri Abhyankar PetscInt rstart=jac_inact_inact->rmap->rstart; 117862298a1eSBarry Smith 11796bf464f9SBarry Smith ierr = MatDestroy(&jac_inact_inact);CHKERRQ(ierr); 11806bf464f9SBarry Smith ierr = ISDestroy(&IS_act);CHKERRQ(ierr); 118162298a1eSBarry Smith 118262298a1eSBarry Smith ierr = ISGetLocalSize(keptrows,&cnt);CHKERRQ(ierr); 118362298a1eSBarry Smith ierr = ISGetIndices(keptrows,&krows);CHKERRQ(ierr); 118462298a1eSBarry Smith ierr = ISGetIndices(IS_inact,&inact);CHKERRQ(ierr); 118562298a1eSBarry Smith ierr = PetscMalloc(cnt*sizeof(PetscInt),&nrows);CHKERRQ(ierr); 118662298a1eSBarry Smith for (k=0; k<cnt; k++) { 118727d4218bSShri Abhyankar nrows[k] = inact[krows[k]-rstart]; 118862298a1eSBarry Smith } 118962298a1eSBarry Smith ierr = ISRestoreIndices(keptrows,&krows);CHKERRQ(ierr); 119062298a1eSBarry Smith ierr = ISRestoreIndices(IS_inact,&inact);CHKERRQ(ierr); 11916bf464f9SBarry Smith ierr = ISDestroy(&keptrows);CHKERRQ(ierr); 11926bf464f9SBarry Smith ierr = ISDestroy(&IS_inact);CHKERRQ(ierr); 119362298a1eSBarry Smith 119427d4218bSShri Abhyankar ierr = ISCreateGeneral(PETSC_COMM_WORLD,cnt,nrows,PETSC_OWN_POINTER,&IS_inact);CHKERRQ(ierr); 119527d4218bSShri Abhyankar ierr = ISComplement(IS_inact,F->map->rstart,F->map->rend,&IS_act);CHKERRQ(ierr); 119662298a1eSBarry Smith ierr = MatGetSubMatrix(snes->jacobian,IS_inact,IS_inact,MAT_INITIAL_MATRIX,&jac_inact_inact);CHKERRQ(ierr); 119762298a1eSBarry Smith } 11989ce20c35SJungho Lee ierr = DMSetVI(snes->dm,IS_inact);CHKERRQ(ierr); 11999ce20c35SJungho Lee /* remove later */ 12009ce20c35SJungho Lee 12019ce20c35SJungho Lee /* 12029ce20c35SJungho Lee ierr = VecView(vi->xu,PETSC_VIEWER_BINARY_(PETSC_COMM_WORLD));CHKERRQ(ierr); 12039ce20c35SJungho Lee ierr = VecView(vi->xl,PETSC_VIEWER_BINARY_(PETSC_COMM_WORLD));CHKERRQ(ierr); 12049ce20c35SJungho Lee ierr = VecView(X,PETSC_VIEWER_BINARY_(PETSC_COMM_WORLD));CHKERRQ(ierr); 12059ce20c35SJungho Lee ierr = VecView(F,PETSC_VIEWER_BINARY_(PETSC_COMM_WORLD));CHKERRQ(ierr); 12069ce20c35SJungho Lee ierr = ISView(IS_inact,PETSC_VIEWER_BINARY_(PETSC_COMM_WORLD));CHKERRQ(ierr); 12079ce20c35SJungho Lee */ 120862298a1eSBarry Smith 1209d950fb63SShri Abhyankar /* Get sizes of active and inactive sets */ 1210d950fb63SShri Abhyankar ierr = ISGetLocalSize(IS_act,&nis_act);CHKERRQ(ierr); 1211d950fb63SShri Abhyankar ierr = ISGetLocalSize(IS_inact,&nis_inact);CHKERRQ(ierr); 1212d950fb63SShri Abhyankar 1213d950fb63SShri Abhyankar /* Create active and inactive set vectors */ 1214fe835674SShri Abhyankar ierr = SNESVICreateSubVectors(snes,nis_inact,&F_inact);CHKERRQ(ierr); 1215fe835674SShri Abhyankar ierr = SNESVICreateSubVectors(snes,nis_act,&Y_act);CHKERRQ(ierr); 1216fe835674SShri Abhyankar ierr = SNESVICreateSubVectors(snes,nis_inact,&Y_inact);CHKERRQ(ierr); 1217d950fb63SShri Abhyankar 1218d950fb63SShri Abhyankar /* Create scatter contexts */ 1219d950fb63SShri Abhyankar ierr = VecScatterCreate(Y,IS_act,Y_act,PETSC_NULL,&scat_act);CHKERRQ(ierr); 1220d950fb63SShri Abhyankar ierr = VecScatterCreate(Y,IS_inact,Y_inact,PETSC_NULL,&scat_inact);CHKERRQ(ierr); 1221d950fb63SShri Abhyankar 1222d950fb63SShri Abhyankar /* Do a vec scatter to active and inactive set vectors */ 1223fe835674SShri Abhyankar ierr = VecScatterBegin(scat_inact,F,F_inact,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1224fe835674SShri Abhyankar ierr = VecScatterEnd(scat_inact,F,F_inact,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1225d950fb63SShri Abhyankar 1226d950fb63SShri Abhyankar ierr = VecScatterBegin(scat_act,Y,Y_act,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1227d950fb63SShri Abhyankar ierr = VecScatterEnd(scat_act,Y,Y_act,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1228d950fb63SShri Abhyankar 1229d950fb63SShri Abhyankar ierr = VecScatterBegin(scat_inact,Y,Y_inact,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1230d950fb63SShri Abhyankar ierr = VecScatterEnd(scat_inact,Y,Y_inact,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1231d950fb63SShri Abhyankar 1232d950fb63SShri Abhyankar /* Active set direction = 0 */ 1233d950fb63SShri Abhyankar ierr = VecSet(Y_act,0);CHKERRQ(ierr); 1234d950fb63SShri Abhyankar if (snes->jacobian != snes->jacobian_pre) { 1235d950fb63SShri Abhyankar ierr = MatGetSubMatrix(snes->jacobian_pre,IS_inact,IS_inact,MAT_INITIAL_MATRIX,&prejac_inact_inact);CHKERRQ(ierr); 1236d950fb63SShri Abhyankar } else prejac_inact_inact = jac_inact_inact; 1237d950fb63SShri Abhyankar 1238abcba341SShri Abhyankar ierr = ISEqual(vi->IS_inact_prev,IS_inact,&isequal);CHKERRQ(ierr); 1239abcba341SShri Abhyankar if (!isequal) { 1240732bb160SShri Abhyankar ierr = SNESVIResetPCandKSP(snes,jac_inact_inact,prejac_inact_inact);CHKERRQ(ierr); 1241c58c0d17SBarry Smith flg = DIFFERENT_NONZERO_PATTERN; 1242d950fb63SShri Abhyankar } 1243d950fb63SShri Abhyankar 124413e0d083SBarry Smith /* ierr = ISView(IS_inact,0);CHKERRQ(ierr); */ 124513e0d083SBarry Smith /* ierr = ISView(IS_act,0);CHKERRQ(ierr);*/ 124613e0d083SBarry Smith /* ierr = MatView(snes->jacobian_pre,0); */ 124713e0d083SBarry Smith 1248f15307b4SJungho Lee 12499ce20c35SJungho Lee 1250d950fb63SShri Abhyankar ierr = KSPSetOperators(snes->ksp,jac_inact_inact,prejac_inact_inact,flg);CHKERRQ(ierr); 125113e0d083SBarry Smith ierr = KSPSetUp(snes->ksp);CHKERRQ(ierr); 125213e0d083SBarry Smith { 125313e0d083SBarry Smith PC pc; 125413e0d083SBarry Smith PetscBool flg; 125513e0d083SBarry Smith ierr = KSPGetPC(snes->ksp,&pc);CHKERRQ(ierr); 125613e0d083SBarry Smith ierr = PetscTypeCompare((PetscObject)pc,PCFIELDSPLIT,&flg);CHKERRQ(ierr); 125713e0d083SBarry Smith if (flg) { 125813e0d083SBarry Smith KSP *subksps; 125913e0d083SBarry Smith ierr = PCFieldSplitGetSubKSP(pc,PETSC_NULL,&subksps);CHKERRQ(ierr); 126013e0d083SBarry Smith ierr = KSPGetPC(subksps[0],&pc);CHKERRQ(ierr); 126113e0d083SBarry Smith ierr = PetscFree(subksps);CHKERRQ(ierr); 126213e0d083SBarry Smith ierr = PetscTypeCompare((PetscObject)pc,PCBJACOBI,&flg);CHKERRQ(ierr); 126313e0d083SBarry Smith if (flg) { 126413e0d083SBarry Smith PetscInt n,N = 101*101,j,cnts[3] = {0,0,0}; 126513e0d083SBarry Smith const PetscInt *ii; 126613e0d083SBarry Smith 126713e0d083SBarry Smith ierr = ISGetSize(IS_inact,&n);CHKERRQ(ierr); 126813e0d083SBarry Smith ierr = ISGetIndices(IS_inact,&ii);CHKERRQ(ierr); 126913e0d083SBarry Smith for (j=0; j<n; j++) { 127013e0d083SBarry Smith if (ii[j] < N) cnts[0]++; 127113e0d083SBarry Smith else if (ii[j] < 2*N) cnts[1]++; 127213e0d083SBarry Smith else if (ii[j] < 3*N) cnts[2]++; 127313e0d083SBarry Smith } 127413e0d083SBarry Smith ierr = ISRestoreIndices(IS_inact,&ii);CHKERRQ(ierr); 127513e0d083SBarry Smith 127613e0d083SBarry Smith ierr = PCBJacobiSetTotalBlocks(pc,3,cnts);CHKERRQ(ierr); 127713e0d083SBarry Smith } 127813e0d083SBarry Smith } 127913e0d083SBarry Smith } 128013e0d083SBarry Smith 1281fe835674SShri Abhyankar ierr = SNES_KSPSolve(snes,snes->ksp,F_inact,Y_inact);CHKERRQ(ierr); 1282d950fb63SShri Abhyankar ierr = KSPGetConvergedReason(snes->ksp,&kspreason);CHKERRQ(ierr); 1283d950fb63SShri Abhyankar if (kspreason < 0) { 1284d950fb63SShri Abhyankar if (++snes->numLinearSolveFailures >= snes->maxLinearSolveFailures) { 1285d950fb63SShri 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); 1286d950fb63SShri Abhyankar snes->reason = SNES_DIVERGED_LINEAR_SOLVE; 1287d950fb63SShri Abhyankar break; 1288d950fb63SShri Abhyankar } 1289d950fb63SShri Abhyankar } 1290d950fb63SShri Abhyankar 1291d950fb63SShri Abhyankar ierr = VecScatterBegin(scat_act,Y_act,Y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1292d950fb63SShri Abhyankar ierr = VecScatterEnd(scat_act,Y_act,Y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1293d950fb63SShri Abhyankar ierr = VecScatterBegin(scat_inact,Y_inact,Y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1294d950fb63SShri Abhyankar ierr = VecScatterEnd(scat_inact,Y_inact,Y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1295d950fb63SShri Abhyankar 12966bf464f9SBarry Smith ierr = VecDestroy(&F_inact);CHKERRQ(ierr); 12976bf464f9SBarry Smith ierr = VecDestroy(&Y_act);CHKERRQ(ierr); 12986bf464f9SBarry Smith ierr = VecDestroy(&Y_inact);CHKERRQ(ierr); 12996bf464f9SBarry Smith ierr = VecScatterDestroy(&scat_act);CHKERRQ(ierr); 13006bf464f9SBarry Smith ierr = VecScatterDestroy(&scat_inact);CHKERRQ(ierr); 13016bf464f9SBarry Smith ierr = ISDestroy(&IS_act);CHKERRQ(ierr); 1302abcba341SShri Abhyankar if (!isequal) { 13036bf464f9SBarry Smith ierr = ISDestroy(&vi->IS_inact_prev);CHKERRQ(ierr); 1304abcba341SShri Abhyankar ierr = ISDuplicate(IS_inact,&vi->IS_inact_prev);CHKERRQ(ierr); 1305abcba341SShri Abhyankar } 13066bf464f9SBarry Smith ierr = ISDestroy(&IS_inact);CHKERRQ(ierr); 13076bf464f9SBarry Smith ierr = MatDestroy(&jac_inact_inact);CHKERRQ(ierr); 1308d950fb63SShri Abhyankar if (snes->jacobian != snes->jacobian_pre) { 13096bf464f9SBarry Smith ierr = MatDestroy(&prejac_inact_inact);CHKERRQ(ierr); 1310d950fb63SShri Abhyankar } 1311d950fb63SShri Abhyankar ierr = KSPGetIterationNumber(snes->ksp,&lits);CHKERRQ(ierr); 1312d950fb63SShri Abhyankar snes->linear_its += lits; 1313d950fb63SShri Abhyankar ierr = PetscInfo2(snes,"iter=%D, linear solve iterations=%D\n",snes->iter,lits);CHKERRQ(ierr); 1314d950fb63SShri Abhyankar /* 1315d950fb63SShri Abhyankar if (vi->precheckstep) { 1316d950fb63SShri Abhyankar PetscBool changed_y = PETSC_FALSE; 1317d950fb63SShri Abhyankar ierr = (*vi->precheckstep)(snes,X,Y,vi->precheck,&changed_y);CHKERRQ(ierr); 1318d950fb63SShri Abhyankar } 1319d950fb63SShri Abhyankar 1320d950fb63SShri Abhyankar if (PetscLogPrintInfo){ 1321d950fb63SShri Abhyankar ierr = SNESVICheckResidual_Private(snes,snes->jacobian,F,Y,G,W);CHKERRQ(ierr); 1322d950fb63SShri Abhyankar } 1323d950fb63SShri Abhyankar */ 1324d950fb63SShri Abhyankar /* Compute a (scaled) negative update in the line search routine: 1325d950fb63SShri Abhyankar Y <- X - lambda*Y 1326d950fb63SShri Abhyankar and evaluate G = function(Y) (depends on the line search). 1327d950fb63SShri Abhyankar */ 1328d950fb63SShri Abhyankar ierr = VecCopy(Y,snes->vec_sol_update);CHKERRQ(ierr); 1329fe835674SShri Abhyankar ynorm = 1; gnorm = fnorm; 1330fe835674SShri Abhyankar ierr = (*vi->LineSearch)(snes,vi->lsP,X,F,G,Y,W,fnorm,xnorm,&ynorm,&gnorm,&lssucceed);CHKERRQ(ierr); 1331fe835674SShri Abhyankar ierr = PetscInfo4(snes,"fnorm=%18.16e, gnorm=%18.16e, ynorm=%18.16e, lssucceed=%d\n",fnorm,gnorm,ynorm,(int)lssucceed);CHKERRQ(ierr); 13322b4ed282SShri Abhyankar if (snes->reason == SNES_DIVERGED_FUNCTION_COUNT) break; 13332b4ed282SShri Abhyankar if (snes->domainerror) { 13342b4ed282SShri Abhyankar snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN; 13354c661befSBarry Smith ierr = DMDestroyVI(snes->dm);CHKERRQ(ierr); 13362b4ed282SShri Abhyankar PetscFunctionReturn(0); 13372b4ed282SShri Abhyankar } 13382b4ed282SShri Abhyankar if (!lssucceed) { 13392b4ed282SShri Abhyankar if (++snes->numFailures >= snes->maxFailures) { 13402b4ed282SShri Abhyankar PetscBool ismin; 13412b4ed282SShri Abhyankar snes->reason = SNES_DIVERGED_LINE_SEARCH; 13422b4ed282SShri Abhyankar ierr = SNESVICheckLocalMin_Private(snes,snes->jacobian,G,W,gnorm,&ismin);CHKERRQ(ierr); 13432b4ed282SShri Abhyankar if (ismin) snes->reason = SNES_DIVERGED_LOCAL_MIN; 13442b4ed282SShri Abhyankar break; 13452b4ed282SShri Abhyankar } 13462b4ed282SShri Abhyankar } 13472b4ed282SShri Abhyankar /* Update function and solution vectors */ 1348fe835674SShri Abhyankar fnorm = gnorm; 1349fe835674SShri Abhyankar ierr = VecCopy(G,F);CHKERRQ(ierr); 13502b4ed282SShri Abhyankar ierr = VecCopy(W,X);CHKERRQ(ierr); 13512b4ed282SShri Abhyankar /* Monitor convergence */ 13522b4ed282SShri Abhyankar ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 13532b4ed282SShri Abhyankar snes->iter = i+1; 1354fe835674SShri Abhyankar snes->norm = fnorm; 13552b4ed282SShri Abhyankar ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 13562b4ed282SShri Abhyankar SNESLogConvHistory(snes,snes->norm,lits); 13577a03ce2fSLisandro Dalcin ierr = SNESMonitor(snes,snes->iter,snes->norm);CHKERRQ(ierr); 13582b4ed282SShri Abhyankar /* Test for convergence, xnorm = || X || */ 13592b4ed282SShri Abhyankar if (snes->ops->converged != SNESSkipConverged) { ierr = VecNorm(X,NORM_2,&xnorm);CHKERRQ(ierr); } 1360fe835674SShri Abhyankar ierr = (*snes->ops->converged)(snes,snes->iter,xnorm,ynorm,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); 13612b4ed282SShri Abhyankar if (snes->reason) break; 13622b4ed282SShri Abhyankar } 13634c661befSBarry Smith ierr = DMDestroyVI(snes->dm);CHKERRQ(ierr); 13642b4ed282SShri Abhyankar if (i == maxits) { 13652b4ed282SShri Abhyankar ierr = PetscInfo1(snes,"Maximum number of iterations has been reached: %D\n",maxits);CHKERRQ(ierr); 13662b4ed282SShri Abhyankar if(!snes->reason) snes->reason = SNES_DIVERGED_MAX_IT; 13672b4ed282SShri Abhyankar } 13682b4ed282SShri Abhyankar PetscFunctionReturn(0); 13692b4ed282SShri Abhyankar } 13702b4ed282SShri Abhyankar 13712f63a38cSShri Abhyankar #undef __FUNCT__ 1372720c9a41SShri Abhyankar #define __FUNCT__ "SNESVISetRedundancyCheck" 1373cb5fe31bSShri Abhyankar PetscErrorCode SNESVISetRedundancyCheck(SNES snes,PetscErrorCode (*func)(SNES,IS,IS*,void*),void *ctx) 13742f63a38cSShri Abhyankar { 13752f63a38cSShri Abhyankar SNES_VI *vi = (SNES_VI*)snes->data; 13762f63a38cSShri Abhyankar 13772f63a38cSShri Abhyankar PetscFunctionBegin; 13782f63a38cSShri Abhyankar PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 13792f63a38cSShri Abhyankar vi->checkredundancy = func; 1380cb5fe31bSShri Abhyankar vi->ctxP = ctx; 13812f63a38cSShri Abhyankar PetscFunctionReturn(0); 13822f63a38cSShri Abhyankar } 13832f63a38cSShri Abhyankar 1384ff596062SShri Abhyankar #if defined(PETSC_HAVE_MATLAB_ENGINE) 1385ff596062SShri Abhyankar #include <engine.h> 1386ff596062SShri Abhyankar #include <mex.h> 1387cb5fe31bSShri Abhyankar typedef struct {char *funcname; mxArray *ctx;} SNESMatlabContext; 1388ff596062SShri Abhyankar 1389ff596062SShri Abhyankar #undef __FUNCT__ 1390ff596062SShri Abhyankar #define __FUNCT__ "SNESVIRedundancyCheck_Matlab" 1391ff596062SShri Abhyankar PetscErrorCode SNESVIRedundancyCheck_Matlab(SNES snes,IS is_act,IS* is_redact,void* ctx) 1392ff596062SShri Abhyankar { 1393ff596062SShri Abhyankar PetscErrorCode ierr; 1394cb5fe31bSShri Abhyankar SNESMatlabContext *sctx = (SNESMatlabContext*)ctx; 1395cb5fe31bSShri Abhyankar int nlhs = 1, nrhs = 5; 1396cb5fe31bSShri Abhyankar mxArray *plhs[1], *prhs[5]; 1397cb5fe31bSShri Abhyankar long long int l1 = 0, l2 = 0, ls = 0; 1398fcb1c9afSShri Abhyankar PetscInt *indices=PETSC_NULL; 1399ff596062SShri Abhyankar 1400ff596062SShri Abhyankar PetscFunctionBegin; 1401ff596062SShri Abhyankar PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 1402ff596062SShri Abhyankar PetscValidHeaderSpecific(is_act,IS_CLASSID,2); 1403ff596062SShri Abhyankar PetscValidPointer(is_redact,3); 1404ff596062SShri Abhyankar PetscCheckSameComm(snes,1,is_act,2); 1405ff596062SShri Abhyankar 140609db5ad8SShri Abhyankar /* Create IS for reduced active set of size 0, its size and indices will 140709db5ad8SShri Abhyankar bet set by the Matlab function */ 1408fcb1c9afSShri Abhyankar ierr = ISCreateGeneral(((PetscObject)snes)->comm,0,indices,PETSC_OWN_POINTER,is_redact);CHKERRQ(ierr); 1409cb5fe31bSShri Abhyankar /* call Matlab function in ctx */ 1410ff596062SShri Abhyankar ierr = PetscMemcpy(&ls,&snes,sizeof(snes));CHKERRQ(ierr); 1411ff596062SShri Abhyankar ierr = PetscMemcpy(&l1,&is_act,sizeof(is_act));CHKERRQ(ierr); 1412cb5fe31bSShri Abhyankar ierr = PetscMemcpy(&l2,is_redact,sizeof(is_act));CHKERRQ(ierr); 1413ff596062SShri Abhyankar prhs[0] = mxCreateDoubleScalar((double)ls); 1414ff596062SShri Abhyankar prhs[1] = mxCreateDoubleScalar((double)l1); 1415cb5fe31bSShri Abhyankar prhs[2] = mxCreateDoubleScalar((double)l2); 1416cb5fe31bSShri Abhyankar prhs[3] = mxCreateString(sctx->funcname); 1417cb5fe31bSShri Abhyankar prhs[4] = sctx->ctx; 1418ff596062SShri Abhyankar ierr = mexCallMATLAB(nlhs,plhs,nrhs,prhs,"PetscSNESVIRedundancyCheckInternal");CHKERRQ(ierr); 1419ff596062SShri Abhyankar ierr = mxGetScalar(plhs[0]);CHKERRQ(ierr); 1420ff596062SShri Abhyankar mxDestroyArray(prhs[0]); 1421ff596062SShri Abhyankar mxDestroyArray(prhs[1]); 1422ff596062SShri Abhyankar mxDestroyArray(prhs[2]); 1423ff596062SShri Abhyankar mxDestroyArray(prhs[3]); 1424ff596062SShri Abhyankar mxDestroyArray(plhs[0]); 1425ff596062SShri Abhyankar PetscFunctionReturn(0); 1426ff596062SShri Abhyankar } 1427ff596062SShri Abhyankar 1428ff596062SShri Abhyankar #undef __FUNCT__ 1429ff596062SShri Abhyankar #define __FUNCT__ "SNESVISetRedundancyCheckMatlab" 1430ff596062SShri Abhyankar PetscErrorCode SNESVISetRedundancyCheckMatlab(SNES snes,const char* func,mxArray* ctx) 1431ff596062SShri Abhyankar { 1432ff596062SShri Abhyankar PetscErrorCode ierr; 1433cb5fe31bSShri Abhyankar SNESMatlabContext *sctx; 1434ff596062SShri Abhyankar 1435ff596062SShri Abhyankar PetscFunctionBegin; 1436ff596062SShri Abhyankar /* currently sctx is memory bleed */ 1437cb5fe31bSShri Abhyankar ierr = PetscMalloc(sizeof(SNESMatlabContext),&sctx);CHKERRQ(ierr); 1438ff596062SShri Abhyankar ierr = PetscStrallocpy(func,&sctx->funcname);CHKERRQ(ierr); 1439ff596062SShri Abhyankar sctx->ctx = mxDuplicateArray(ctx); 1440cb5fe31bSShri Abhyankar ierr = SNESVISetRedundancyCheck(snes,SNESVIRedundancyCheck_Matlab,sctx);CHKERRQ(ierr); 1441ff596062SShri Abhyankar PetscFunctionReturn(0); 1442ff596062SShri Abhyankar } 1443ff596062SShri Abhyankar 1444ff596062SShri Abhyankar #endif 1445ff596062SShri Abhyankar 1446ff596062SShri Abhyankar 14472f63a38cSShri Abhyankar /* Variational Inequality solver using augmented space method. It does the opposite of the 14482f63a38cSShri Abhyankar reduced space method i.e. it identifies the active set variables and instead of discarding 1449720c9a41SShri Abhyankar them it augments the original system by introducing additional equality 145056a221efSShri Abhyankar constraint equations for active set variables. The user can optionally provide an IS for 145156a221efSShri Abhyankar a subset of 'redundant' active set variables which will treated as free variables. 14522f63a38cSShri Abhyankar Specific implementation for Allen-Cahn problem 14532f63a38cSShri Abhyankar */ 14542f63a38cSShri Abhyankar #undef __FUNCT__ 1455b350b9c9SBarry Smith #define __FUNCT__ "SNESSolveVI_RSAUG" 1456b350b9c9SBarry Smith PetscErrorCode SNESSolveVI_RSAUG(SNES snes) 14572f63a38cSShri Abhyankar { 14582f63a38cSShri Abhyankar SNES_VI *vi = (SNES_VI*)snes->data; 14592f63a38cSShri Abhyankar PetscErrorCode ierr; 14602f63a38cSShri Abhyankar PetscInt maxits,i,lits; 14612f63a38cSShri Abhyankar PetscBool lssucceed; 14622f63a38cSShri Abhyankar MatStructure flg = DIFFERENT_NONZERO_PATTERN; 14632f63a38cSShri Abhyankar PetscReal fnorm,gnorm,xnorm=0,ynorm; 14642f63a38cSShri Abhyankar Vec Y,X,F,G,W; 14652f63a38cSShri Abhyankar KSPConvergedReason kspreason; 14662f63a38cSShri Abhyankar 14672f63a38cSShri Abhyankar PetscFunctionBegin; 14682f63a38cSShri Abhyankar snes->numFailures = 0; 14692f63a38cSShri Abhyankar snes->numLinearSolveFailures = 0; 14702f63a38cSShri Abhyankar snes->reason = SNES_CONVERGED_ITERATING; 14712f63a38cSShri Abhyankar 14722f63a38cSShri Abhyankar maxits = snes->max_its; /* maximum number of iterations */ 14732f63a38cSShri Abhyankar X = snes->vec_sol; /* solution vector */ 14742f63a38cSShri Abhyankar F = snes->vec_func; /* residual vector */ 14752f63a38cSShri Abhyankar Y = snes->work[0]; /* work vectors */ 14762f63a38cSShri Abhyankar G = snes->work[1]; 14772f63a38cSShri Abhyankar W = snes->work[2]; 14782f63a38cSShri Abhyankar 14792f63a38cSShri Abhyankar ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 14802f63a38cSShri Abhyankar snes->iter = 0; 14812f63a38cSShri Abhyankar snes->norm = 0.0; 14822f63a38cSShri Abhyankar ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 14832f63a38cSShri Abhyankar 14842f63a38cSShri Abhyankar ierr = SNESVIProjectOntoBounds(snes,X);CHKERRQ(ierr); 14852f63a38cSShri Abhyankar ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr); 14862f63a38cSShri Abhyankar if (snes->domainerror) { 14872f63a38cSShri Abhyankar snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN; 14882f63a38cSShri Abhyankar PetscFunctionReturn(0); 14892f63a38cSShri Abhyankar } 14902f63a38cSShri Abhyankar ierr = SNESVIComputeInactiveSetFnorm(snes,F,X,&fnorm);CHKERRQ(ierr); 14912f63a38cSShri Abhyankar ierr = VecNormBegin(X,NORM_2,&xnorm);CHKERRQ(ierr); /* xnorm <- ||x|| */ 14922f63a38cSShri Abhyankar ierr = VecNormEnd(X,NORM_2,&xnorm);CHKERRQ(ierr); 149362cbcd01SMatthew G Knepley if (PetscIsInfOrNanReal(fnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number"); 14942f63a38cSShri Abhyankar 14952f63a38cSShri Abhyankar ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 14962f63a38cSShri Abhyankar snes->norm = fnorm; 14972f63a38cSShri Abhyankar ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 14982f63a38cSShri Abhyankar SNESLogConvHistory(snes,fnorm,0); 14997a03ce2fSLisandro Dalcin ierr = SNESMonitor(snes,0,fnorm);CHKERRQ(ierr); 15002f63a38cSShri Abhyankar 15012f63a38cSShri Abhyankar /* set parameter for default relative tolerance convergence test */ 15022f63a38cSShri Abhyankar snes->ttol = fnorm*snes->rtol; 15032f63a38cSShri Abhyankar /* test convergence */ 15042f63a38cSShri Abhyankar ierr = (*snes->ops->converged)(snes,0,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); 15052f63a38cSShri Abhyankar if (snes->reason) PetscFunctionReturn(0); 15062f63a38cSShri Abhyankar 15072f63a38cSShri Abhyankar for (i=0; i<maxits; i++) { 15082f63a38cSShri Abhyankar IS IS_act,IS_inact; /* _act -> active set _inact -> inactive set */ 1509cb5fe31bSShri Abhyankar IS IS_redact; /* redundant active set */ 151056a221efSShri Abhyankar Mat J_aug,Jpre_aug; 151156a221efSShri Abhyankar Vec F_aug,Y_aug; 151256a221efSShri Abhyankar PetscInt nis_redact,nis_act; 151356a221efSShri Abhyankar const PetscInt *idx_redact,*idx_act; 151456a221efSShri Abhyankar PetscInt k; 151563ee972cSSatish Balay PetscInt *idx_actkept=PETSC_NULL,nkept=0; /* list of kept active set */ 151656a221efSShri Abhyankar PetscScalar *f,*f2; 15172f63a38cSShri Abhyankar PetscBool isequal; 151856a221efSShri Abhyankar PetscInt i1=0,j1=0; 15192f63a38cSShri Abhyankar 15202f63a38cSShri Abhyankar /* Call general purpose update function */ 15212f63a38cSShri Abhyankar if (snes->ops->update) { 15222f63a38cSShri Abhyankar ierr = (*snes->ops->update)(snes, snes->iter);CHKERRQ(ierr); 15232f63a38cSShri Abhyankar } 15242f63a38cSShri Abhyankar ierr = SNESComputeJacobian(snes,X,&snes->jacobian,&snes->jacobian_pre,&flg);CHKERRQ(ierr); 15252f63a38cSShri Abhyankar 15262f63a38cSShri Abhyankar /* Create active and inactive index sets */ 15272f63a38cSShri Abhyankar ierr = SNESVICreateIndexSets_RS(snes,X,F,&IS_act,&IS_inact);CHKERRQ(ierr); 15282f63a38cSShri Abhyankar 152956a221efSShri Abhyankar /* Get local active set size */ 15302f63a38cSShri Abhyankar ierr = ISGetLocalSize(IS_act,&nis_act);CHKERRQ(ierr); 153156a221efSShri Abhyankar if (nis_act) { 1532e63076c7SBarry Smith ierr = ISGetIndices(IS_act,&idx_act);CHKERRQ(ierr); 1533e63076c7SBarry Smith IS_redact = PETSC_NULL; 153456a221efSShri Abhyankar if(vi->checkredundancy) { 1535cb5fe31bSShri Abhyankar (*vi->checkredundancy)(snes,IS_act,&IS_redact,vi->ctxP); 153656a221efSShri Abhyankar } 15372f63a38cSShri Abhyankar 153856a221efSShri Abhyankar if(!IS_redact) { 153956a221efSShri Abhyankar /* User called checkredundancy function but didn't create IS_redact because 154056a221efSShri Abhyankar there were no redundant active set variables */ 154156a221efSShri Abhyankar /* Copy over all active set indices to the list */ 154256a221efSShri Abhyankar ierr = PetscMalloc(nis_act*sizeof(PetscInt),&idx_actkept);CHKERRQ(ierr); 154356a221efSShri Abhyankar for(k=0;k < nis_act;k++) idx_actkept[k] = idx_act[k]; 154456a221efSShri Abhyankar nkept = nis_act; 154556a221efSShri Abhyankar } else { 154656a221efSShri Abhyankar ierr = ISGetLocalSize(IS_redact,&nis_redact);CHKERRQ(ierr); 154756a221efSShri Abhyankar ierr = PetscMalloc((nis_act-nis_redact)*sizeof(PetscInt),&idx_actkept);CHKERRQ(ierr); 15482f63a38cSShri Abhyankar 154956a221efSShri Abhyankar /* Create reduced active set list */ 155056a221efSShri Abhyankar ierr = ISGetIndices(IS_act,&idx_act);CHKERRQ(ierr); 155156a221efSShri Abhyankar ierr = ISGetIndices(IS_redact,&idx_redact);CHKERRQ(ierr); 1552cb5fe31bSShri Abhyankar j1 = 0;nkept = 0; 155356a221efSShri Abhyankar for(k=0;k<nis_act;k++) { 155456a221efSShri Abhyankar if(j1 < nis_redact && idx_act[k] == idx_redact[j1]) j1++; 155556a221efSShri Abhyankar else idx_actkept[nkept++] = idx_act[k]; 155656a221efSShri Abhyankar } 155756a221efSShri Abhyankar ierr = ISRestoreIndices(IS_act,&idx_act);CHKERRQ(ierr); 155856a221efSShri Abhyankar ierr = ISRestoreIndices(IS_redact,&idx_redact);CHKERRQ(ierr); 1559cb5fe31bSShri Abhyankar 1560cb5fe31bSShri Abhyankar ierr = ISDestroy(&IS_redact);CHKERRQ(ierr); 156156a221efSShri Abhyankar } 15622f63a38cSShri Abhyankar 156356a221efSShri Abhyankar /* Create augmented F and Y */ 156456a221efSShri Abhyankar ierr = VecCreate(((PetscObject)snes)->comm,&F_aug);CHKERRQ(ierr); 156556a221efSShri Abhyankar ierr = VecSetSizes(F_aug,F->map->n+nkept,PETSC_DECIDE);CHKERRQ(ierr); 156656a221efSShri Abhyankar ierr = VecSetFromOptions(F_aug);CHKERRQ(ierr); 156756a221efSShri Abhyankar ierr = VecDuplicate(F_aug,&Y_aug);CHKERRQ(ierr); 15682f63a38cSShri Abhyankar 156956a221efSShri Abhyankar /* Copy over F to F_aug in the first n locations */ 157056a221efSShri Abhyankar ierr = VecGetArray(F,&f);CHKERRQ(ierr); 157156a221efSShri Abhyankar ierr = VecGetArray(F_aug,&f2);CHKERRQ(ierr); 157256a221efSShri Abhyankar ierr = PetscMemcpy(f2,f,F->map->n*sizeof(PetscScalar));CHKERRQ(ierr); 157356a221efSShri Abhyankar ierr = VecRestoreArray(F,&f);CHKERRQ(ierr); 157456a221efSShri Abhyankar ierr = VecRestoreArray(F_aug,&f2);CHKERRQ(ierr); 15752f63a38cSShri Abhyankar 157656a221efSShri Abhyankar /* Create the augmented jacobian matrix */ 157756a221efSShri Abhyankar ierr = MatCreate(((PetscObject)snes)->comm,&J_aug);CHKERRQ(ierr); 157856a221efSShri Abhyankar ierr = MatSetSizes(J_aug,X->map->n+nkept,X->map->n+nkept,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr); 157956a221efSShri Abhyankar ierr = MatSetFromOptions(J_aug);CHKERRQ(ierr); 15802f63a38cSShri Abhyankar 158156a221efSShri Abhyankar 15829521db3cSSatish Balay { /* local vars */ 1583493a4f3dSShri Abhyankar /* Preallocate augmented matrix and set values in it...Doing only sequential case first*/ 158456a221efSShri Abhyankar PetscInt ncols; 158556a221efSShri Abhyankar const PetscInt *cols; 158656a221efSShri Abhyankar const PetscScalar *vals; 15872969f145SShri Abhyankar PetscScalar value[2]; 15882969f145SShri Abhyankar PetscInt row,col[2]; 1589493a4f3dSShri Abhyankar PetscInt *d_nnz; 15902969f145SShri Abhyankar value[0] = 1.0; value[1] = 0.0; 1591493a4f3dSShri Abhyankar ierr = PetscMalloc((X->map->n+nkept)*sizeof(PetscInt),&d_nnz);CHKERRQ(ierr); 1592493a4f3dSShri Abhyankar ierr = PetscMemzero(d_nnz,(X->map->n+nkept)*sizeof(PetscInt));CHKERRQ(ierr); 1593493a4f3dSShri Abhyankar for(row=0;row<snes->jacobian->rmap->n;row++) { 1594493a4f3dSShri Abhyankar ierr = MatGetRow(snes->jacobian,row,&ncols,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr); 1595493a4f3dSShri Abhyankar d_nnz[row] += ncols; 1596493a4f3dSShri Abhyankar ierr = MatRestoreRow(snes->jacobian,row,&ncols,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr); 1597493a4f3dSShri Abhyankar } 1598493a4f3dSShri Abhyankar 1599493a4f3dSShri Abhyankar for(k=0;k<nkept;k++) { 1600493a4f3dSShri Abhyankar d_nnz[idx_actkept[k]] += 1; 16012969f145SShri Abhyankar d_nnz[snes->jacobian->rmap->n+k] += 2; 1602493a4f3dSShri Abhyankar } 1603493a4f3dSShri Abhyankar ierr = MatSeqAIJSetPreallocation(J_aug,PETSC_NULL,d_nnz);CHKERRQ(ierr); 1604493a4f3dSShri Abhyankar 1605493a4f3dSShri Abhyankar ierr = PetscFree(d_nnz);CHKERRQ(ierr); 160656a221efSShri Abhyankar 160756a221efSShri Abhyankar /* Set the original jacobian matrix in J_aug */ 160856a221efSShri Abhyankar for(row=0;row<snes->jacobian->rmap->n;row++) { 160956a221efSShri Abhyankar ierr = MatGetRow(snes->jacobian,row,&ncols,&cols,&vals);CHKERRQ(ierr); 161056a221efSShri Abhyankar ierr = MatSetValues(J_aug,1,&row,ncols,cols,vals,INSERT_VALUES);CHKERRQ(ierr); 161156a221efSShri Abhyankar ierr = MatRestoreRow(snes->jacobian,row,&ncols,&cols,&vals);CHKERRQ(ierr); 161256a221efSShri Abhyankar } 161356a221efSShri Abhyankar /* Add the augmented part */ 161456a221efSShri Abhyankar for(k=0;k<nkept;k++) { 16152969f145SShri Abhyankar row = snes->jacobian->rmap->n+k; 16162969f145SShri Abhyankar col[0] = idx_actkept[k]; col[1] = snes->jacobian->rmap->n+k; 16172969f145SShri Abhyankar ierr = MatSetValues(J_aug,1,&row,1,col,value,INSERT_VALUES);CHKERRQ(ierr); 16182969f145SShri Abhyankar ierr = MatSetValues(J_aug,1,&col[0],1,&row,&value[0],INSERT_VALUES);CHKERRQ(ierr); 161956a221efSShri Abhyankar } 162056a221efSShri Abhyankar ierr = MatAssemblyBegin(J_aug,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 162156a221efSShri Abhyankar ierr = MatAssemblyEnd(J_aug,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 162256a221efSShri Abhyankar /* Only considering prejac = jac for now */ 162356a221efSShri Abhyankar Jpre_aug = J_aug; 16249521db3cSSatish Balay } /* local vars*/ 1625e63076c7SBarry Smith ierr = ISRestoreIndices(IS_act,&idx_act);CHKERRQ(ierr); 1626e63076c7SBarry Smith ierr = ISDestroy(&IS_act);CHKERRQ(ierr); 162756a221efSShri Abhyankar } else { 162856a221efSShri Abhyankar F_aug = F; J_aug = snes->jacobian; Y_aug = Y; Jpre_aug = snes->jacobian_pre; 162956a221efSShri Abhyankar } 16302f63a38cSShri Abhyankar 16312f63a38cSShri Abhyankar ierr = ISEqual(vi->IS_inact_prev,IS_inact,&isequal);CHKERRQ(ierr); 16322f63a38cSShri Abhyankar if (!isequal) { 163356a221efSShri Abhyankar ierr = SNESVIResetPCandKSP(snes,J_aug,Jpre_aug);CHKERRQ(ierr); 16342f63a38cSShri Abhyankar } 163556a221efSShri Abhyankar ierr = KSPSetOperators(snes->ksp,J_aug,Jpre_aug,flg);CHKERRQ(ierr); 16362f63a38cSShri Abhyankar ierr = KSPSetUp(snes->ksp);CHKERRQ(ierr); 163756a221efSShri Abhyankar /* { 16382f63a38cSShri Abhyankar PC pc; 16392f63a38cSShri Abhyankar PetscBool flg; 16402f63a38cSShri Abhyankar ierr = KSPGetPC(snes->ksp,&pc);CHKERRQ(ierr); 16412f63a38cSShri Abhyankar ierr = PetscTypeCompare((PetscObject)pc,PCFIELDSPLIT,&flg);CHKERRQ(ierr); 16422f63a38cSShri Abhyankar if (flg) { 16432f63a38cSShri Abhyankar KSP *subksps; 16442f63a38cSShri Abhyankar ierr = PCFieldSplitGetSubKSP(pc,PETSC_NULL,&subksps);CHKERRQ(ierr); 16452f63a38cSShri Abhyankar ierr = KSPGetPC(subksps[0],&pc);CHKERRQ(ierr); 16462f63a38cSShri Abhyankar ierr = PetscFree(subksps);CHKERRQ(ierr); 16472f63a38cSShri Abhyankar ierr = PetscTypeCompare((PetscObject)pc,PCBJACOBI,&flg);CHKERRQ(ierr); 16482f63a38cSShri Abhyankar if (flg) { 16492f63a38cSShri Abhyankar PetscInt n,N = 101*101,j,cnts[3] = {0,0,0}; 16502f63a38cSShri Abhyankar const PetscInt *ii; 16512f63a38cSShri Abhyankar 16522f63a38cSShri Abhyankar ierr = ISGetSize(IS_inact,&n);CHKERRQ(ierr); 16532f63a38cSShri Abhyankar ierr = ISGetIndices(IS_inact,&ii);CHKERRQ(ierr); 16542f63a38cSShri Abhyankar for (j=0; j<n; j++) { 16552f63a38cSShri Abhyankar if (ii[j] < N) cnts[0]++; 16562f63a38cSShri Abhyankar else if (ii[j] < 2*N) cnts[1]++; 16572f63a38cSShri Abhyankar else if (ii[j] < 3*N) cnts[2]++; 16582f63a38cSShri Abhyankar } 16592f63a38cSShri Abhyankar ierr = ISRestoreIndices(IS_inact,&ii);CHKERRQ(ierr); 16602f63a38cSShri Abhyankar 16612f63a38cSShri Abhyankar ierr = PCBJacobiSetTotalBlocks(pc,3,cnts);CHKERRQ(ierr); 16622f63a38cSShri Abhyankar } 16632f63a38cSShri Abhyankar } 16642f63a38cSShri Abhyankar } 166556a221efSShri Abhyankar */ 166656a221efSShri Abhyankar ierr = SNES_KSPSolve(snes,snes->ksp,F_aug,Y_aug);CHKERRQ(ierr); 16672f63a38cSShri Abhyankar ierr = KSPGetConvergedReason(snes->ksp,&kspreason);CHKERRQ(ierr); 16682f63a38cSShri Abhyankar if (kspreason < 0) { 16692f63a38cSShri Abhyankar if (++snes->numLinearSolveFailures >= snes->maxLinearSolveFailures) { 16702f63a38cSShri 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); 16712f63a38cSShri Abhyankar snes->reason = SNES_DIVERGED_LINEAR_SOLVE; 16722f63a38cSShri Abhyankar break; 16732f63a38cSShri Abhyankar } 16742f63a38cSShri Abhyankar } 16752f63a38cSShri Abhyankar 167656a221efSShri Abhyankar if(nis_act) { 167756a221efSShri Abhyankar PetscScalar *y1,*y2; 167856a221efSShri Abhyankar ierr = VecGetArray(Y,&y1);CHKERRQ(ierr); 167956a221efSShri Abhyankar ierr = VecGetArray(Y_aug,&y2);CHKERRQ(ierr); 168056a221efSShri Abhyankar /* Copy over inactive Y_aug to Y */ 168156a221efSShri Abhyankar j1 = 0; 168256a221efSShri Abhyankar for(i1=Y->map->rstart;i1 < Y->map->rend;i1++) { 168356a221efSShri Abhyankar if(j1 < nkept && idx_actkept[j1] == i1) j1++; 168456a221efSShri Abhyankar else y1[i1-Y->map->rstart] = y2[i1-Y->map->rstart]; 168556a221efSShri Abhyankar } 168656a221efSShri Abhyankar ierr = VecRestoreArray(Y,&y1);CHKERRQ(ierr); 168756a221efSShri Abhyankar ierr = VecRestoreArray(Y_aug,&y2);CHKERRQ(ierr); 16882f63a38cSShri Abhyankar 16896bf464f9SBarry Smith ierr = VecDestroy(&F_aug);CHKERRQ(ierr); 16906bf464f9SBarry Smith ierr = VecDestroy(&Y_aug);CHKERRQ(ierr); 16916bf464f9SBarry Smith ierr = MatDestroy(&J_aug);CHKERRQ(ierr); 169256a221efSShri Abhyankar ierr = PetscFree(idx_actkept);CHKERRQ(ierr); 169356a221efSShri Abhyankar } 169456a221efSShri Abhyankar 16952f63a38cSShri Abhyankar if (!isequal) { 16966bf464f9SBarry Smith ierr = ISDestroy(&vi->IS_inact_prev);CHKERRQ(ierr); 16972f63a38cSShri Abhyankar ierr = ISDuplicate(IS_inact,&vi->IS_inact_prev);CHKERRQ(ierr); 16982f63a38cSShri Abhyankar } 16996bf464f9SBarry Smith ierr = ISDestroy(&IS_inact);CHKERRQ(ierr); 170056a221efSShri Abhyankar 17012f63a38cSShri Abhyankar ierr = KSPGetIterationNumber(snes->ksp,&lits);CHKERRQ(ierr); 17022f63a38cSShri Abhyankar snes->linear_its += lits; 17032f63a38cSShri Abhyankar ierr = PetscInfo2(snes,"iter=%D, linear solve iterations=%D\n",snes->iter,lits);CHKERRQ(ierr); 17042f63a38cSShri Abhyankar /* 17052f63a38cSShri Abhyankar if (vi->precheckstep) { 17062f63a38cSShri Abhyankar PetscBool changed_y = PETSC_FALSE; 17072f63a38cSShri Abhyankar ierr = (*vi->precheckstep)(snes,X,Y,vi->precheck,&changed_y);CHKERRQ(ierr); 17082f63a38cSShri Abhyankar } 17092f63a38cSShri Abhyankar 17102f63a38cSShri Abhyankar if (PetscLogPrintInfo){ 17112f63a38cSShri Abhyankar ierr = SNESVICheckResidual_Private(snes,snes->jacobian,F,Y,G,W);CHKERRQ(ierr); 17122f63a38cSShri Abhyankar } 17132f63a38cSShri Abhyankar */ 17142f63a38cSShri Abhyankar /* Compute a (scaled) negative update in the line search routine: 17152f63a38cSShri Abhyankar Y <- X - lambda*Y 17162f63a38cSShri Abhyankar and evaluate G = function(Y) (depends on the line search). 17172f63a38cSShri Abhyankar */ 17182f63a38cSShri Abhyankar ierr = VecCopy(Y,snes->vec_sol_update);CHKERRQ(ierr); 17192f63a38cSShri Abhyankar ynorm = 1; gnorm = fnorm; 17202f63a38cSShri Abhyankar ierr = (*vi->LineSearch)(snes,vi->lsP,X,F,G,Y,W,fnorm,xnorm,&ynorm,&gnorm,&lssucceed);CHKERRQ(ierr); 17212f63a38cSShri Abhyankar ierr = PetscInfo4(snes,"fnorm=%18.16e, gnorm=%18.16e, ynorm=%18.16e, lssucceed=%d\n",fnorm,gnorm,ynorm,(int)lssucceed);CHKERRQ(ierr); 17222f63a38cSShri Abhyankar if (snes->reason == SNES_DIVERGED_FUNCTION_COUNT) break; 17232f63a38cSShri Abhyankar if (snes->domainerror) { 17242f63a38cSShri Abhyankar snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN; 17252f63a38cSShri Abhyankar PetscFunctionReturn(0); 17262f63a38cSShri Abhyankar } 17272f63a38cSShri Abhyankar if (!lssucceed) { 17282f63a38cSShri Abhyankar if (++snes->numFailures >= snes->maxFailures) { 17292f63a38cSShri Abhyankar PetscBool ismin; 17302f63a38cSShri Abhyankar snes->reason = SNES_DIVERGED_LINE_SEARCH; 17312f63a38cSShri Abhyankar ierr = SNESVICheckLocalMin_Private(snes,snes->jacobian,G,W,gnorm,&ismin);CHKERRQ(ierr); 17322f63a38cSShri Abhyankar if (ismin) snes->reason = SNES_DIVERGED_LOCAL_MIN; 17332f63a38cSShri Abhyankar break; 17342f63a38cSShri Abhyankar } 17352f63a38cSShri Abhyankar } 17362f63a38cSShri Abhyankar /* Update function and solution vectors */ 17372f63a38cSShri Abhyankar fnorm = gnorm; 17382f63a38cSShri Abhyankar ierr = VecCopy(G,F);CHKERRQ(ierr); 17392f63a38cSShri Abhyankar ierr = VecCopy(W,X);CHKERRQ(ierr); 17402f63a38cSShri Abhyankar /* Monitor convergence */ 17412f63a38cSShri Abhyankar ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 17422f63a38cSShri Abhyankar snes->iter = i+1; 17432f63a38cSShri Abhyankar snes->norm = fnorm; 17442f63a38cSShri Abhyankar ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 17452f63a38cSShri Abhyankar SNESLogConvHistory(snes,snes->norm,lits); 17467a03ce2fSLisandro Dalcin ierr = SNESMonitor(snes,snes->iter,snes->norm);CHKERRQ(ierr); 17472f63a38cSShri Abhyankar /* Test for convergence, xnorm = || X || */ 17482f63a38cSShri Abhyankar if (snes->ops->converged != SNESSkipConverged) { ierr = VecNorm(X,NORM_2,&xnorm);CHKERRQ(ierr); } 17492f63a38cSShri Abhyankar ierr = (*snes->ops->converged)(snes,snes->iter,xnorm,ynorm,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); 17502f63a38cSShri Abhyankar if (snes->reason) break; 17512f63a38cSShri Abhyankar } 17522f63a38cSShri Abhyankar if (i == maxits) { 17532f63a38cSShri Abhyankar ierr = PetscInfo1(snes,"Maximum number of iterations has been reached: %D\n",maxits);CHKERRQ(ierr); 17542f63a38cSShri Abhyankar if(!snes->reason) snes->reason = SNES_DIVERGED_MAX_IT; 17552f63a38cSShri Abhyankar } 17562f63a38cSShri Abhyankar PetscFunctionReturn(0); 17572f63a38cSShri Abhyankar } 17582f63a38cSShri Abhyankar 17592b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */ 17602b4ed282SShri Abhyankar /* 17612b4ed282SShri Abhyankar SNESSetUp_VI - Sets up the internal data structures for the later use 17622b4ed282SShri Abhyankar of the SNESVI nonlinear solver. 17632b4ed282SShri Abhyankar 17642b4ed282SShri Abhyankar Input Parameter: 17652b4ed282SShri Abhyankar . snes - the SNES context 17662b4ed282SShri Abhyankar . x - the solution vector 17672b4ed282SShri Abhyankar 17682b4ed282SShri Abhyankar Application Interface Routine: SNESSetUp() 17692b4ed282SShri Abhyankar 17702b4ed282SShri Abhyankar Notes: 17712b4ed282SShri Abhyankar For basic use of the SNES solvers, the user need not explicitly call 17722b4ed282SShri Abhyankar SNESSetUp(), since these actions will automatically occur during 17732b4ed282SShri Abhyankar the call to SNESSolve(). 17742b4ed282SShri Abhyankar */ 17752b4ed282SShri Abhyankar #undef __FUNCT__ 17762b4ed282SShri Abhyankar #define __FUNCT__ "SNESSetUp_VI" 17772b4ed282SShri Abhyankar PetscErrorCode SNESSetUp_VI(SNES snes) 17782b4ed282SShri Abhyankar { 17792b4ed282SShri Abhyankar PetscErrorCode ierr; 17802b4ed282SShri Abhyankar SNES_VI *vi = (SNES_VI*) snes->data; 17812b4ed282SShri Abhyankar PetscInt i_start[3],i_end[3]; 17822b4ed282SShri Abhyankar 17832b4ed282SShri Abhyankar PetscFunctionBegin; 178458c9b817SLisandro Dalcin 178558c9b817SLisandro Dalcin ierr = SNESDefaultGetWork(snes,3);CHKERRQ(ierr); 17862b4ed282SShri Abhyankar 17872176524cSBarry Smith if (vi->computevariablebounds) { 178877cdaf69SJed Brown if (!vi->xl) {ierr = VecDuplicate(snes->vec_sol,&vi->xl);CHKERRQ(ierr);} 178977cdaf69SJed Brown if (!vi->xu) {ierr = VecDuplicate(snes->vec_sol,&vi->xu);CHKERRQ(ierr);} 179077cdaf69SJed Brown ierr = (*vi->computevariablebounds)(snes,vi->xl,vi->xu);CHKERRQ(ierr); 17912176524cSBarry Smith } else if (!vi->xl && !vi->xu) { 17922176524cSBarry Smith /* If the lower and upper bound on variables are not set, set it to -Inf and Inf */ 17932b4ed282SShri Abhyankar ierr = VecDuplicate(snes->vec_sol, &vi->xl);CHKERRQ(ierr); 179401f0b76bSBarry Smith ierr = VecSet(vi->xl,SNES_VI_NINF);CHKERRQ(ierr); 17952b4ed282SShri Abhyankar ierr = VecDuplicate(snes->vec_sol, &vi->xu);CHKERRQ(ierr); 179601f0b76bSBarry Smith ierr = VecSet(vi->xu,SNES_VI_INF);CHKERRQ(ierr); 17972b4ed282SShri Abhyankar } else { 17982b4ed282SShri Abhyankar /* Check if lower bound, upper bound and solution vector distribution across the processors is identical */ 17992b4ed282SShri Abhyankar ierr = VecGetOwnershipRange(snes->vec_sol,i_start,i_end);CHKERRQ(ierr); 18002b4ed282SShri Abhyankar ierr = VecGetOwnershipRange(vi->xl,i_start+1,i_end+1);CHKERRQ(ierr); 18012b4ed282SShri Abhyankar ierr = VecGetOwnershipRange(vi->xu,i_start+2,i_end+2);CHKERRQ(ierr); 18022b4ed282SShri 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])) 18032b4ed282SShri 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."); 18042b4ed282SShri Abhyankar } 18052f63a38cSShri Abhyankar if (snes->ops->solve != SNESSolveVI_SS) { 1806abcba341SShri Abhyankar /* Set up previous active index set for the first snes solve 1807abcba341SShri Abhyankar vi->IS_inact_prev = 0,1,2,....N */ 1808abcba341SShri Abhyankar PetscInt *indices; 1809abcba341SShri Abhyankar PetscInt i,n,rstart,rend; 1810abcba341SShri Abhyankar 1811abcba341SShri Abhyankar ierr = VecGetOwnershipRange(snes->vec_sol,&rstart,&rend);CHKERRQ(ierr); 1812abcba341SShri Abhyankar ierr = VecGetLocalSize(snes->vec_sol,&n);CHKERRQ(ierr); 1813abcba341SShri Abhyankar ierr = PetscMalloc(n*sizeof(PetscInt),&indices);CHKERRQ(ierr); 1814abcba341SShri Abhyankar for(i=0;i < n; i++) indices[i] = rstart + i; 1815abcba341SShri Abhyankar ierr = ISCreateGeneral(((PetscObject)snes)->comm,n,indices,PETSC_OWN_POINTER,&vi->IS_inact_prev); 1816abcba341SShri Abhyankar } 18172b4ed282SShri Abhyankar 18182f63a38cSShri Abhyankar if (snes->ops->solve == SNESSolveVI_SS) { 1819fe835674SShri Abhyankar ierr = VecDuplicate(snes->vec_sol, &vi->dpsi);CHKERRQ(ierr); 1820fe835674SShri Abhyankar ierr = VecDuplicate(snes->vec_sol, &vi->phi);CHKERRQ(ierr); 1821fe835674SShri Abhyankar ierr = VecDuplicate(snes->vec_sol, &vi->Da);CHKERRQ(ierr); 1822fe835674SShri Abhyankar ierr = VecDuplicate(snes->vec_sol, &vi->Db);CHKERRQ(ierr); 1823fe835674SShri Abhyankar ierr = VecDuplicate(snes->vec_sol, &vi->z);CHKERRQ(ierr); 1824fe835674SShri Abhyankar ierr = VecDuplicate(snes->vec_sol, &vi->t);CHKERRQ(ierr); 1825fe835674SShri Abhyankar } 18262b4ed282SShri Abhyankar PetscFunctionReturn(0); 18272b4ed282SShri Abhyankar } 18282b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */ 18292176524cSBarry Smith #undef __FUNCT__ 18302176524cSBarry Smith #define __FUNCT__ "SNESReset_VI" 18312176524cSBarry Smith PetscErrorCode SNESReset_VI(SNES snes) 18322176524cSBarry Smith { 18332176524cSBarry Smith SNES_VI *vi = (SNES_VI*) snes->data; 18342176524cSBarry Smith PetscErrorCode ierr; 18352176524cSBarry Smith 18362176524cSBarry Smith PetscFunctionBegin; 18372176524cSBarry Smith ierr = VecDestroy(&vi->xl);CHKERRQ(ierr); 18382176524cSBarry Smith ierr = VecDestroy(&vi->xu);CHKERRQ(ierr); 1839d655a5daSBarry Smith if (snes->ops->solve != SNESSolveVI_SS) { 1840d655a5daSBarry Smith ierr = ISDestroy(&vi->IS_inact_prev);CHKERRQ(ierr); 1841d655a5daSBarry Smith } 18422176524cSBarry Smith PetscFunctionReturn(0); 18432176524cSBarry Smith } 18442176524cSBarry Smith 18452b4ed282SShri Abhyankar /* 18462b4ed282SShri Abhyankar SNESDestroy_VI - Destroys the private SNES_VI context that was created 18472b4ed282SShri Abhyankar with SNESCreate_VI(). 18482b4ed282SShri Abhyankar 18492b4ed282SShri Abhyankar Input Parameter: 18502b4ed282SShri Abhyankar . snes - the SNES context 18512b4ed282SShri Abhyankar 18522b4ed282SShri Abhyankar Application Interface Routine: SNESDestroy() 18532b4ed282SShri Abhyankar */ 18542b4ed282SShri Abhyankar #undef __FUNCT__ 18552b4ed282SShri Abhyankar #define __FUNCT__ "SNESDestroy_VI" 18562b4ed282SShri Abhyankar PetscErrorCode SNESDestroy_VI(SNES snes) 18572b4ed282SShri Abhyankar { 18582b4ed282SShri Abhyankar SNES_VI *vi = (SNES_VI*) snes->data; 18592b4ed282SShri Abhyankar PetscErrorCode ierr; 18602b4ed282SShri Abhyankar 18612b4ed282SShri Abhyankar PetscFunctionBegin; 18622b4ed282SShri Abhyankar 18632f63a38cSShri Abhyankar if (snes->ops->solve == SNESSolveVI_SS) { 18642b4ed282SShri Abhyankar /* clear vectors */ 18656bf464f9SBarry Smith ierr = VecDestroy(&vi->dpsi);CHKERRQ(ierr); 18666bf464f9SBarry Smith ierr = VecDestroy(&vi->phi);CHKERRQ(ierr); 18676bf464f9SBarry Smith ierr = VecDestroy(&vi->Da);CHKERRQ(ierr); 18686bf464f9SBarry Smith ierr = VecDestroy(&vi->Db);CHKERRQ(ierr); 18696bf464f9SBarry Smith ierr = VecDestroy(&vi->z);CHKERRQ(ierr); 18706bf464f9SBarry Smith ierr = VecDestroy(&vi->t);CHKERRQ(ierr); 18717fe79bc4SShri Abhyankar } 18727fe79bc4SShri Abhyankar 1873649052a6SBarry Smith ierr = PetscViewerDestroy(&vi->lsmonitor);CHKERRQ(ierr); 18742b4ed282SShri Abhyankar ierr = PetscFree(snes->data);CHKERRQ(ierr); 18752b4ed282SShri Abhyankar 18762b4ed282SShri Abhyankar /* clear composed functions */ 18772b4ed282SShri Abhyankar ierr = PetscObjectComposeFunctionDynamic((PetscObject)snes,"SNESLineSearchSet_C","",PETSC_NULL);CHKERRQ(ierr); 1878c92abb8aSShri Abhyankar ierr = PetscObjectComposeFunctionDynamic((PetscObject)snes,"SNESLineSearchSetMonitor_C","",PETSC_NULL);CHKERRQ(ierr); 18792b4ed282SShri Abhyankar PetscFunctionReturn(0); 18802b4ed282SShri Abhyankar } 18817fe79bc4SShri Abhyankar 18822b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */ 18832b4ed282SShri Abhyankar #undef __FUNCT__ 18842b4ed282SShri Abhyankar #define __FUNCT__ "SNESLineSearchNo_VI" 18852b4ed282SShri Abhyankar 18862b4ed282SShri Abhyankar /* 18877fe79bc4SShri Abhyankar This routine does not actually do a line search but it takes a full newton 18887fe79bc4SShri Abhyankar step while ensuring that the new iterates remain within the constraints. 18892b4ed282SShri Abhyankar 18902b4ed282SShri Abhyankar */ 1891ace3abfcSBarry 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) 18922b4ed282SShri Abhyankar { 18932b4ed282SShri Abhyankar PetscErrorCode ierr; 18942b4ed282SShri Abhyankar SNES_VI *vi = (SNES_VI*)snes->data; 1895ace3abfcSBarry Smith PetscBool changed_w = PETSC_FALSE,changed_y = PETSC_FALSE; 18962b4ed282SShri Abhyankar 18972b4ed282SShri Abhyankar PetscFunctionBegin; 18982b4ed282SShri Abhyankar *flag = PETSC_TRUE; 18992b4ed282SShri Abhyankar ierr = PetscLogEventBegin(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); 19002b4ed282SShri Abhyankar ierr = VecNorm(y,NORM_2,ynorm);CHKERRQ(ierr); /* ynorm = || y || */ 19012b4ed282SShri Abhyankar ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr); /* w <- x - y */ 1902c1a5e521SShri Abhyankar ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr); 1903c1a5e521SShri Abhyankar if (vi->postcheckstep) { 1904c1a5e521SShri Abhyankar ierr = (*vi->postcheckstep)(snes,x,y,w,vi->postcheck,&changed_y,&changed_w);CHKERRQ(ierr); 1905c1a5e521SShri Abhyankar } 1906c1a5e521SShri Abhyankar if (changed_y) { 1907c1a5e521SShri Abhyankar ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr); /* w <- x - y */ 19087fe79bc4SShri Abhyankar ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr); 1909c1a5e521SShri Abhyankar } 1910c1a5e521SShri Abhyankar ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr); 1911c1a5e521SShri Abhyankar ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr); 1912c1a5e521SShri Abhyankar if (!snes->domainerror) { 19132f63a38cSShri Abhyankar if (snes->ops->solve != SNESSolveVI_SS) { 19147fe79bc4SShri Abhyankar ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr); 19157fe79bc4SShri Abhyankar } else { 1916c1a5e521SShri Abhyankar ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr); /* gnorm = || g || */ 19177fe79bc4SShri Abhyankar } 191862cbcd01SMatthew G Knepley if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number"); 1919c1a5e521SShri Abhyankar } 1920c1a5e521SShri Abhyankar if (vi->lsmonitor) { 1921649052a6SBarry Smith ierr = PetscViewerASCIIAddTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 1922*e6337399SBarry Smith ierr = PetscViewerASCIIPrintf(vi->lsmonitor," Line search: Using full step: fnorm %g gnorm %g\n",(double)fnorm,(double)*gnorm);CHKERRQ(ierr); 1923649052a6SBarry Smith ierr = PetscViewerASCIISubtractTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 1924c1a5e521SShri Abhyankar } 1925c1a5e521SShri Abhyankar ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); 1926c1a5e521SShri Abhyankar PetscFunctionReturn(0); 1927c1a5e521SShri Abhyankar } 1928c1a5e521SShri Abhyankar 1929c1a5e521SShri Abhyankar /* -------------------------------------------------------------------------- */ 1930c1a5e521SShri Abhyankar #undef __FUNCT__ 19312b4ed282SShri Abhyankar #define __FUNCT__ "SNESLineSearchNoNorms_VI" 19322b4ed282SShri Abhyankar 19332b4ed282SShri Abhyankar /* 19342b4ed282SShri Abhyankar This routine is a copy of SNESLineSearchNoNorms in snes/impls/ls/ls.c 19352b4ed282SShri Abhyankar */ 1936ace3abfcSBarry 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) 19372b4ed282SShri Abhyankar { 19382b4ed282SShri Abhyankar PetscErrorCode ierr; 19392b4ed282SShri Abhyankar SNES_VI *vi = (SNES_VI*)snes->data; 1940ace3abfcSBarry Smith PetscBool changed_w = PETSC_FALSE,changed_y = PETSC_FALSE; 19412b4ed282SShri Abhyankar 19422b4ed282SShri Abhyankar PetscFunctionBegin; 19432b4ed282SShri Abhyankar *flag = PETSC_TRUE; 19442b4ed282SShri Abhyankar ierr = PetscLogEventBegin(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); 19452b4ed282SShri Abhyankar ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr); /* w <- x - y */ 19467fe79bc4SShri Abhyankar ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr); 19472b4ed282SShri Abhyankar if (vi->postcheckstep) { 19482b4ed282SShri Abhyankar ierr = (*vi->postcheckstep)(snes,x,y,w,vi->postcheck,&changed_y,&changed_w);CHKERRQ(ierr); 19492b4ed282SShri Abhyankar } 19502b4ed282SShri Abhyankar if (changed_y) { 19512b4ed282SShri Abhyankar ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr); /* w <- x - y */ 19527fe79bc4SShri Abhyankar ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr); 19532b4ed282SShri Abhyankar } 19542b4ed282SShri Abhyankar 19552b4ed282SShri Abhyankar /* don't evaluate function the last time through */ 19562b4ed282SShri Abhyankar if (snes->iter < snes->max_its-1) { 19572b4ed282SShri Abhyankar ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr); 19582b4ed282SShri Abhyankar } 19592b4ed282SShri Abhyankar ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); 19602b4ed282SShri Abhyankar PetscFunctionReturn(0); 19612b4ed282SShri Abhyankar } 19627fe79bc4SShri Abhyankar 19632b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */ 19642b4ed282SShri Abhyankar #undef __FUNCT__ 19652b4ed282SShri Abhyankar #define __FUNCT__ "SNESLineSearchCubic_VI" 19662b4ed282SShri Abhyankar /* 19677fe79bc4SShri Abhyankar This routine implements a cubic line search while doing a projection on the variable bounds 19682b4ed282SShri Abhyankar */ 1969ace3abfcSBarry 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) 19702b4ed282SShri Abhyankar { 1971fe835674SShri Abhyankar PetscReal initslope,lambdaprev,gnormprev,a,b,d,t1,t2,rellength; 1972fe835674SShri Abhyankar PetscReal minlambda,lambda,lambdatemp; 1973fe835674SShri Abhyankar #if defined(PETSC_USE_COMPLEX) 1974fe835674SShri Abhyankar PetscScalar cinitslope; 1975fe835674SShri Abhyankar #endif 1976fe835674SShri Abhyankar PetscErrorCode ierr; 1977fe835674SShri Abhyankar PetscInt count; 1978fe835674SShri Abhyankar SNES_VI *vi = (SNES_VI*)snes->data; 1979fe835674SShri Abhyankar PetscBool changed_w = PETSC_FALSE,changed_y = PETSC_FALSE; 1980fe835674SShri Abhyankar MPI_Comm comm; 1981fe835674SShri Abhyankar 1982fe835674SShri Abhyankar PetscFunctionBegin; 1983fe835674SShri Abhyankar ierr = PetscObjectGetComm((PetscObject)snes,&comm);CHKERRQ(ierr); 1984fe835674SShri Abhyankar ierr = PetscLogEventBegin(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); 1985fe835674SShri Abhyankar *flag = PETSC_TRUE; 1986fe835674SShri Abhyankar 1987fe835674SShri Abhyankar ierr = VecNorm(y,NORM_2,ynorm);CHKERRQ(ierr); 1988fe835674SShri Abhyankar if (*ynorm == 0.0) { 1989fe835674SShri Abhyankar if (vi->lsmonitor) { 1990649052a6SBarry Smith ierr = PetscViewerASCIIAddTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 1991649052a6SBarry Smith ierr = PetscViewerASCIIPrintf(vi->lsmonitor," Line search: Initial direction and size is 0\n");CHKERRQ(ierr); 1992649052a6SBarry Smith ierr = PetscViewerASCIISubtractTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 1993fe835674SShri Abhyankar } 1994fe835674SShri Abhyankar *gnorm = fnorm; 1995fe835674SShri Abhyankar ierr = VecCopy(x,w);CHKERRQ(ierr); 1996fe835674SShri Abhyankar ierr = VecCopy(f,g);CHKERRQ(ierr); 1997fe835674SShri Abhyankar *flag = PETSC_FALSE; 1998fe835674SShri Abhyankar goto theend1; 1999fe835674SShri Abhyankar } 2000fe835674SShri Abhyankar if (*ynorm > vi->maxstep) { /* Step too big, so scale back */ 2001fe835674SShri Abhyankar if (vi->lsmonitor) { 2002649052a6SBarry Smith ierr = PetscViewerASCIIAddTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 2003*e6337399SBarry Smith ierr = PetscViewerASCIIPrintf(vi->lsmonitor," Line search: Scaling step by %g old ynorm %g\n",(double)vi->maxstep/(*ynorm),(double)*ynorm);CHKERRQ(ierr); 2004649052a6SBarry Smith ierr = PetscViewerASCIISubtractTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 2005fe835674SShri Abhyankar } 2006fe835674SShri Abhyankar ierr = VecScale(y,vi->maxstep/(*ynorm));CHKERRQ(ierr); 2007fe835674SShri Abhyankar *ynorm = vi->maxstep; 2008fe835674SShri Abhyankar } 2009fe835674SShri Abhyankar ierr = VecMaxPointwiseDivide(y,x,&rellength);CHKERRQ(ierr); 2010fe835674SShri Abhyankar minlambda = vi->minlambda/rellength; 2011fe835674SShri Abhyankar ierr = MatMult(snes->jacobian,y,w);CHKERRQ(ierr); 2012fe835674SShri Abhyankar #if defined(PETSC_USE_COMPLEX) 2013fe835674SShri Abhyankar ierr = VecDot(f,w,&cinitslope);CHKERRQ(ierr); 2014fe835674SShri Abhyankar initslope = PetscRealPart(cinitslope); 2015fe835674SShri Abhyankar #else 2016fe835674SShri Abhyankar ierr = VecDot(f,w,&initslope);CHKERRQ(ierr); 2017fe835674SShri Abhyankar #endif 2018fe835674SShri Abhyankar if (initslope > 0.0) initslope = -initslope; 2019fe835674SShri Abhyankar if (initslope == 0.0) initslope = -1.0; 2020fe835674SShri Abhyankar 2021fe835674SShri Abhyankar ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr); 2022fe835674SShri Abhyankar ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr); 2023fe835674SShri Abhyankar if (snes->nfuncs >= snes->max_funcs) { 2024fe835674SShri Abhyankar ierr = PetscInfo(snes,"Exceeded maximum function evaluations, while checking full step length!\n");CHKERRQ(ierr); 2025fe835674SShri Abhyankar *flag = PETSC_FALSE; 2026fe835674SShri Abhyankar snes->reason = SNES_DIVERGED_FUNCTION_COUNT; 2027fe835674SShri Abhyankar goto theend1; 2028fe835674SShri Abhyankar } 2029fe835674SShri Abhyankar ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr); 20302f63a38cSShri Abhyankar if (snes->ops->solve != SNESSolveVI_SS) { 2031fe835674SShri Abhyankar ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr); 20327fe79bc4SShri Abhyankar } else { 20337fe79bc4SShri Abhyankar ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr); 20347fe79bc4SShri Abhyankar } 2035fe835674SShri Abhyankar if (snes->domainerror) { 2036fe835674SShri Abhyankar ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); 2037fe835674SShri Abhyankar PetscFunctionReturn(0); 2038fe835674SShri Abhyankar } 203962cbcd01SMatthew G Knepley if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number"); 2040*e6337399SBarry Smith ierr = PetscInfo4(snes,"Initial fnorm %g gnorm %g alpha %g initslope %g\n",(double)fnorm,(double)*gnorm,(double)vi->alpha,(double)initslope);CHKERRQ(ierr); 2041f2b03b96SBarry Smith if ((*gnorm)*(*gnorm) <= (1.0 - vi->alpha)*fnorm*fnorm ) { /* Sufficient reduction */ 2042fe835674SShri Abhyankar if (vi->lsmonitor) { 2043649052a6SBarry Smith ierr = PetscViewerASCIIAddTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 2044*e6337399SBarry Smith ierr = PetscViewerASCIIPrintf(vi->lsmonitor," Line search: Using full step: fnorm %g gnorm %g\n",(double)fnorm,(double)*gnorm);CHKERRQ(ierr); 2045649052a6SBarry Smith ierr = PetscViewerASCIISubtractTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 2046fe835674SShri Abhyankar } 2047fe835674SShri Abhyankar goto theend1; 2048fe835674SShri Abhyankar } 2049fe835674SShri Abhyankar 2050fe835674SShri Abhyankar /* Fit points with quadratic */ 2051fe835674SShri Abhyankar lambda = 1.0; 2052fe835674SShri Abhyankar lambdatemp = -initslope/((*gnorm)*(*gnorm) - fnorm*fnorm - 2.0*initslope); 2053fe835674SShri Abhyankar lambdaprev = lambda; 2054fe835674SShri Abhyankar gnormprev = *gnorm; 2055fe835674SShri Abhyankar if (lambdatemp > .5*lambda) lambdatemp = .5*lambda; 2056fe835674SShri Abhyankar if (lambdatemp <= .1*lambda) lambda = .1*lambda; 2057fe835674SShri Abhyankar else lambda = lambdatemp; 2058fe835674SShri Abhyankar 2059fe835674SShri Abhyankar ierr = VecWAXPY(w,-lambda,y,x);CHKERRQ(ierr); 2060fe835674SShri Abhyankar ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr); 2061fe835674SShri Abhyankar if (snes->nfuncs >= snes->max_funcs) { 2062fe835674SShri Abhyankar ierr = PetscInfo1(snes,"Exceeded maximum function evaluations, while attempting quadratic backtracking! %D \n",snes->nfuncs);CHKERRQ(ierr); 2063fe835674SShri Abhyankar *flag = PETSC_FALSE; 2064fe835674SShri Abhyankar snes->reason = SNES_DIVERGED_FUNCTION_COUNT; 2065fe835674SShri Abhyankar goto theend1; 2066fe835674SShri Abhyankar } 2067fe835674SShri Abhyankar ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr); 20682f63a38cSShri Abhyankar if (snes->ops->solve != SNESSolveVI_SS) { 2069fe835674SShri Abhyankar ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr); 20707fe79bc4SShri Abhyankar } else { 20717fe79bc4SShri Abhyankar ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr); 20727fe79bc4SShri Abhyankar } 2073fe835674SShri Abhyankar if (snes->domainerror) { 2074fe835674SShri Abhyankar ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); 2075fe835674SShri Abhyankar PetscFunctionReturn(0); 2076fe835674SShri Abhyankar } 207762cbcd01SMatthew G Knepley if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number"); 2078fe835674SShri Abhyankar if (vi->lsmonitor) { 2079649052a6SBarry Smith ierr = PetscViewerASCIIAddTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 2080*e6337399SBarry Smith ierr = PetscViewerASCIIPrintf(vi->lsmonitor," Line search: gnorm after quadratic fit %g\n",(double)*gnorm);CHKERRQ(ierr); 2081649052a6SBarry Smith ierr = PetscViewerASCIISubtractTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 2082fe835674SShri Abhyankar } 2083f2b03b96SBarry Smith if ((*gnorm)*(*gnorm) < (1.0 - vi->alpha)*fnorm*fnorm ) { /* sufficient reduction */ 2084fe835674SShri Abhyankar if (vi->lsmonitor) { 2085649052a6SBarry Smith ierr = PetscViewerASCIIAddTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 2086649052a6SBarry Smith ierr = PetscViewerASCIIPrintf(vi->lsmonitor," Line search: Quadratically determined step, lambda=%18.16e\n",lambda);CHKERRQ(ierr); 2087649052a6SBarry Smith ierr = PetscViewerASCIISubtractTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 2088fe835674SShri Abhyankar } 2089fe835674SShri Abhyankar goto theend1; 2090fe835674SShri Abhyankar } 2091fe835674SShri Abhyankar 2092fe835674SShri Abhyankar /* Fit points with cubic */ 2093fe835674SShri Abhyankar count = 1; 2094fe835674SShri Abhyankar while (PETSC_TRUE) { 2095fe835674SShri Abhyankar if (lambda <= minlambda) { 2096fe835674SShri Abhyankar if (vi->lsmonitor) { 2097649052a6SBarry Smith ierr = PetscViewerASCIIAddTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 2098649052a6SBarry Smith ierr = PetscViewerASCIIPrintf(vi->lsmonitor," Line search: unable to find good step length! After %D tries \n",count);CHKERRQ(ierr); 2099649052a6SBarry 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); 2100649052a6SBarry Smith ierr = PetscViewerASCIISubtractTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 2101fe835674SShri Abhyankar } 2102fe835674SShri Abhyankar *flag = PETSC_FALSE; 2103fe835674SShri Abhyankar break; 2104fe835674SShri Abhyankar } 2105fe835674SShri Abhyankar t1 = .5*((*gnorm)*(*gnorm) - fnorm*fnorm) - lambda*initslope; 2106fe835674SShri Abhyankar t2 = .5*(gnormprev*gnormprev - fnorm*fnorm) - lambdaprev*initslope; 2107fe835674SShri Abhyankar a = (t1/(lambda*lambda) - t2/(lambdaprev*lambdaprev))/(lambda-lambdaprev); 2108fe835674SShri Abhyankar b = (-lambdaprev*t1/(lambda*lambda) + lambda*t2/(lambdaprev*lambdaprev))/(lambda-lambdaprev); 2109fe835674SShri Abhyankar d = b*b - 3*a*initslope; 2110fe835674SShri Abhyankar if (d < 0.0) d = 0.0; 2111fe835674SShri Abhyankar if (a == 0.0) { 2112fe835674SShri Abhyankar lambdatemp = -initslope/(2.0*b); 2113fe835674SShri Abhyankar } else { 2114fe835674SShri Abhyankar lambdatemp = (-b + sqrt(d))/(3.0*a); 2115fe835674SShri Abhyankar } 2116fe835674SShri Abhyankar lambdaprev = lambda; 2117fe835674SShri Abhyankar gnormprev = *gnorm; 2118fe835674SShri Abhyankar if (lambdatemp > .5*lambda) lambdatemp = .5*lambda; 2119fe835674SShri Abhyankar if (lambdatemp <= .1*lambda) lambda = .1*lambda; 2120fe835674SShri Abhyankar else lambda = lambdatemp; 2121fe835674SShri Abhyankar ierr = VecWAXPY(w,-lambda,y,x);CHKERRQ(ierr); 2122fe835674SShri Abhyankar ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr); 2123fe835674SShri Abhyankar if (snes->nfuncs >= snes->max_funcs) { 2124fe835674SShri Abhyankar ierr = PetscInfo1(snes,"Exceeded maximum function evaluations, while looking for good step length! %D \n",count);CHKERRQ(ierr); 2125fe835674SShri 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); 2126fe835674SShri Abhyankar *flag = PETSC_FALSE; 2127fe835674SShri Abhyankar snes->reason = SNES_DIVERGED_FUNCTION_COUNT; 2128fe835674SShri Abhyankar break; 2129fe835674SShri Abhyankar } 2130fe835674SShri Abhyankar ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr); 21312f63a38cSShri Abhyankar if (snes->ops->solve != SNESSolveVI_SS) { 2132fe835674SShri Abhyankar ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr); 21337fe79bc4SShri Abhyankar } else { 21347fe79bc4SShri Abhyankar ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr); 21357fe79bc4SShri Abhyankar } 2136fe835674SShri Abhyankar if (snes->domainerror) { 2137fe835674SShri Abhyankar ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); 2138fe835674SShri Abhyankar PetscFunctionReturn(0); 2139fe835674SShri Abhyankar } 214062cbcd01SMatthew G Knepley if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number"); 2141f2b03b96SBarry Smith if ((*gnorm)*(*gnorm) < (1.0 - vi->alpha)*fnorm*fnorm) { /* is reduction enough? */ 2142fe835674SShri Abhyankar if (vi->lsmonitor) { 2143*e6337399SBarry Smith ierr = PetscPrintf(comm," Line search: Cubically determined step, current gnorm %g lambda=%18.16e\n",(double)*gnorm,(double)lambda);CHKERRQ(ierr); 2144fe835674SShri Abhyankar } 2145fe835674SShri Abhyankar break; 2146fe835674SShri Abhyankar } else { 2147fe835674SShri Abhyankar if (vi->lsmonitor) { 2148*e6337399SBarry Smith ierr = PetscPrintf(comm," Line search: Cubic step no good, shrinking lambda, current gnorm %g lambda=%18.16e\n",(double)*gnorm,(double)lambda);CHKERRQ(ierr); 2149fe835674SShri Abhyankar } 2150fe835674SShri Abhyankar } 2151fe835674SShri Abhyankar count++; 2152fe835674SShri Abhyankar } 2153fe835674SShri Abhyankar theend1: 2154fe835674SShri Abhyankar /* Optional user-defined check for line search step validity */ 2155fe835674SShri Abhyankar if (vi->postcheckstep && *flag) { 2156fe835674SShri Abhyankar ierr = (*vi->postcheckstep)(snes,x,y,w,vi->postcheck,&changed_y,&changed_w);CHKERRQ(ierr); 2157fe835674SShri Abhyankar if (changed_y) { 2158fe835674SShri Abhyankar ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr); 2159fe835674SShri Abhyankar ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr); 2160fe835674SShri Abhyankar } 2161fe835674SShri Abhyankar if (changed_y || changed_w) { /* recompute the function if the step has changed */ 2162fe835674SShri Abhyankar ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr); 21632f63a38cSShri Abhyankar if (snes->ops->solve != SNESSolveVI_SS) { 2164fe835674SShri Abhyankar ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr); 21657fe79bc4SShri Abhyankar } else { 21667fe79bc4SShri Abhyankar ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr); 21677fe79bc4SShri Abhyankar } 2168fe835674SShri Abhyankar if (snes->domainerror) { 2169fe835674SShri Abhyankar ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); 2170fe835674SShri Abhyankar PetscFunctionReturn(0); 2171fe835674SShri Abhyankar } 217262cbcd01SMatthew G Knepley if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number"); 2173fe835674SShri Abhyankar ierr = VecNormBegin(y,NORM_2,ynorm);CHKERRQ(ierr); 2174fe835674SShri Abhyankar ierr = VecNormEnd(y,NORM_2,ynorm);CHKERRQ(ierr); 2175fe835674SShri Abhyankar } 2176fe835674SShri Abhyankar } 2177fe835674SShri Abhyankar ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); 2178fe835674SShri Abhyankar PetscFunctionReturn(0); 2179fe835674SShri Abhyankar } 2180fe835674SShri Abhyankar 21812b4ed282SShri Abhyankar #undef __FUNCT__ 21822b4ed282SShri Abhyankar #define __FUNCT__ "SNESLineSearchQuadratic_VI" 21832b4ed282SShri Abhyankar /* 21847fe79bc4SShri Abhyankar This routine does a quadratic line search while keeping the iterates within the variable bounds 21852b4ed282SShri Abhyankar */ 2186ace3abfcSBarry 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) 21872b4ed282SShri Abhyankar { 21882b4ed282SShri Abhyankar /* 21892b4ed282SShri Abhyankar Note that for line search purposes we work with with the related 21902b4ed282SShri Abhyankar minimization problem: 21912b4ed282SShri Abhyankar min z(x): R^n -> R, 21922b4ed282SShri Abhyankar where z(x) = .5 * fnorm*fnorm,and fnorm = || f ||_2. 21932b4ed282SShri Abhyankar */ 21942b4ed282SShri Abhyankar PetscReal initslope,minlambda,lambda,lambdatemp,rellength; 21952b4ed282SShri Abhyankar #if defined(PETSC_USE_COMPLEX) 21962b4ed282SShri Abhyankar PetscScalar cinitslope; 21972b4ed282SShri Abhyankar #endif 21982b4ed282SShri Abhyankar PetscErrorCode ierr; 21992b4ed282SShri Abhyankar PetscInt count; 22002b4ed282SShri Abhyankar SNES_VI *vi = (SNES_VI*)snes->data; 2201ace3abfcSBarry Smith PetscBool changed_w = PETSC_FALSE,changed_y = PETSC_FALSE; 22022b4ed282SShri Abhyankar 22032b4ed282SShri Abhyankar PetscFunctionBegin; 22042b4ed282SShri Abhyankar ierr = PetscLogEventBegin(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); 22052b4ed282SShri Abhyankar *flag = PETSC_TRUE; 22062b4ed282SShri Abhyankar 22072b4ed282SShri Abhyankar ierr = VecNorm(y,NORM_2,ynorm);CHKERRQ(ierr); 22082b4ed282SShri Abhyankar if (*ynorm == 0.0) { 2209c92abb8aSShri Abhyankar if (vi->lsmonitor) { 2210649052a6SBarry Smith ierr = PetscViewerASCIIAddTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 2211649052a6SBarry Smith ierr = PetscViewerASCIIPrintf(vi->lsmonitor,"Line search: Direction and size is 0\n");CHKERRQ(ierr); 2212649052a6SBarry Smith ierr = PetscViewerASCIISubtractTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 22132b4ed282SShri Abhyankar } 22142b4ed282SShri Abhyankar *gnorm = fnorm; 22152b4ed282SShri Abhyankar ierr = VecCopy(x,w);CHKERRQ(ierr); 22162b4ed282SShri Abhyankar ierr = VecCopy(f,g);CHKERRQ(ierr); 22172b4ed282SShri Abhyankar *flag = PETSC_FALSE; 22182b4ed282SShri Abhyankar goto theend2; 22192b4ed282SShri Abhyankar } 22202b4ed282SShri Abhyankar if (*ynorm > vi->maxstep) { /* Step too big, so scale back */ 22212b4ed282SShri Abhyankar ierr = VecScale(y,vi->maxstep/(*ynorm));CHKERRQ(ierr); 22222b4ed282SShri Abhyankar *ynorm = vi->maxstep; 22232b4ed282SShri Abhyankar } 22242b4ed282SShri Abhyankar ierr = VecMaxPointwiseDivide(y,x,&rellength);CHKERRQ(ierr); 22252b4ed282SShri Abhyankar minlambda = vi->minlambda/rellength; 22267fe79bc4SShri Abhyankar ierr = MatMult(snes->jacobian,y,w);CHKERRQ(ierr); 22272b4ed282SShri Abhyankar #if defined(PETSC_USE_COMPLEX) 22287fe79bc4SShri Abhyankar ierr = VecDot(f,w,&cinitslope);CHKERRQ(ierr); 22292b4ed282SShri Abhyankar initslope = PetscRealPart(cinitslope); 22302b4ed282SShri Abhyankar #else 22317fe79bc4SShri Abhyankar ierr = VecDot(f,w,&initslope);CHKERRQ(ierr); 22322b4ed282SShri Abhyankar #endif 22332b4ed282SShri Abhyankar if (initslope > 0.0) initslope = -initslope; 22342b4ed282SShri Abhyankar if (initslope == 0.0) initslope = -1.0; 22352b4ed282SShri Abhyankar ierr = PetscInfo1(snes,"Initslope %G \n",initslope);CHKERRQ(ierr); 22362b4ed282SShri Abhyankar 22372b4ed282SShri Abhyankar ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr); 22387fe79bc4SShri Abhyankar ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr); 22392b4ed282SShri Abhyankar if (snes->nfuncs >= snes->max_funcs) { 22402b4ed282SShri Abhyankar ierr = PetscInfo(snes,"Exceeded maximum function evaluations, while checking full step length!\n");CHKERRQ(ierr); 22412b4ed282SShri Abhyankar *flag = PETSC_FALSE; 22422b4ed282SShri Abhyankar snes->reason = SNES_DIVERGED_FUNCTION_COUNT; 22432b4ed282SShri Abhyankar goto theend2; 22442b4ed282SShri Abhyankar } 22452b4ed282SShri Abhyankar ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr); 22462f63a38cSShri Abhyankar if (snes->ops->solve != SNESSolveVI_SS) { 22477fe79bc4SShri Abhyankar ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr); 22487fe79bc4SShri Abhyankar } else { 22497fe79bc4SShri Abhyankar ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr); 22507fe79bc4SShri Abhyankar } 22512b4ed282SShri Abhyankar if (snes->domainerror) { 22522b4ed282SShri Abhyankar ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); 22532b4ed282SShri Abhyankar PetscFunctionReturn(0); 22542b4ed282SShri Abhyankar } 225562cbcd01SMatthew G Knepley if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number"); 2256f2b03b96SBarry Smith if ((*gnorm)*(*gnorm) <= (1.0 - vi->alpha)*fnorm*fnorm) { /* Sufficient reduction */ 2257c92abb8aSShri Abhyankar if (vi->lsmonitor) { 2258649052a6SBarry Smith ierr = PetscViewerASCIIAddTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 2259649052a6SBarry Smith ierr = PetscViewerASCIIPrintf(vi->lsmonitor," Line search: Using full step: fnorm %G gnorm %G\n",fnorm,*gnorm);CHKERRQ(ierr); 2260649052a6SBarry Smith ierr = PetscViewerASCIISubtractTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 22612b4ed282SShri Abhyankar } 22622b4ed282SShri Abhyankar goto theend2; 22632b4ed282SShri Abhyankar } 22642b4ed282SShri Abhyankar 22652b4ed282SShri Abhyankar /* Fit points with quadratic */ 22662b4ed282SShri Abhyankar lambda = 1.0; 22672b4ed282SShri Abhyankar count = 1; 22682b4ed282SShri Abhyankar while (PETSC_TRUE) { 22692b4ed282SShri Abhyankar if (lambda <= minlambda) { /* bad luck; use full step */ 2270c92abb8aSShri Abhyankar if (vi->lsmonitor) { 2271649052a6SBarry Smith ierr = PetscViewerASCIIAddTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 2272649052a6SBarry Smith ierr = PetscViewerASCIIPrintf(vi->lsmonitor,"Line search: Unable to find good step length! %D \n",count);CHKERRQ(ierr); 2273649052a6SBarry 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); 2274649052a6SBarry Smith ierr = PetscViewerASCIISubtractTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 22752b4ed282SShri Abhyankar } 22762b4ed282SShri Abhyankar ierr = VecCopy(x,w);CHKERRQ(ierr); 22772b4ed282SShri Abhyankar *flag = PETSC_FALSE; 22782b4ed282SShri Abhyankar break; 22792b4ed282SShri Abhyankar } 22802b4ed282SShri Abhyankar lambdatemp = -initslope/((*gnorm)*(*gnorm) - fnorm*fnorm - 2.0*initslope); 22812b4ed282SShri Abhyankar if (lambdatemp > .5*lambda) lambdatemp = .5*lambda; 22822b4ed282SShri Abhyankar if (lambdatemp <= .1*lambda) lambda = .1*lambda; 22832b4ed282SShri Abhyankar else lambda = lambdatemp; 22842b4ed282SShri Abhyankar 22852b4ed282SShri Abhyankar ierr = VecWAXPY(w,-lambda,y,x);CHKERRQ(ierr); 22867fe79bc4SShri Abhyankar ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr); 22872b4ed282SShri Abhyankar if (snes->nfuncs >= snes->max_funcs) { 22882b4ed282SShri Abhyankar ierr = PetscInfo1(snes,"Exceeded maximum function evaluations, while looking for good step length! %D \n",count);CHKERRQ(ierr); 22892b4ed282SShri 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); 22902b4ed282SShri Abhyankar *flag = PETSC_FALSE; 22912b4ed282SShri Abhyankar snes->reason = SNES_DIVERGED_FUNCTION_COUNT; 22922b4ed282SShri Abhyankar break; 22932b4ed282SShri Abhyankar } 22942b4ed282SShri Abhyankar ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr); 22952b4ed282SShri Abhyankar if (snes->domainerror) { 22962b4ed282SShri Abhyankar ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); 22972b4ed282SShri Abhyankar PetscFunctionReturn(0); 22982b4ed282SShri Abhyankar } 22992f63a38cSShri Abhyankar if (snes->ops->solve != SNESSolveVI_SS) { 23007fe79bc4SShri Abhyankar ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr); 23017fe79bc4SShri Abhyankar } else { 23022b4ed282SShri Abhyankar ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr); 23037fe79bc4SShri Abhyankar } 230462cbcd01SMatthew G Knepley if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number"); 2305f2b03b96SBarry Smith if ((*gnorm)*(*gnorm) < (1.0 - vi->alpha)*fnorm*fnorm) { /* sufficient reduction */ 2306c92abb8aSShri Abhyankar if (vi->lsmonitor) { 2307649052a6SBarry Smith ierr = PetscViewerASCIIAddTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 2308649052a6SBarry Smith ierr = PetscViewerASCIIPrintf(vi->lsmonitor," Line Search: Quadratically determined step, lambda=%G\n",lambda);CHKERRQ(ierr); 2309649052a6SBarry Smith ierr = PetscViewerASCIISubtractTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 23102b4ed282SShri Abhyankar } 23112b4ed282SShri Abhyankar break; 23122b4ed282SShri Abhyankar } 23132b4ed282SShri Abhyankar count++; 23142b4ed282SShri Abhyankar } 23152b4ed282SShri Abhyankar theend2: 23162b4ed282SShri Abhyankar /* Optional user-defined check for line search step validity */ 23172b4ed282SShri Abhyankar if (vi->postcheckstep) { 23182b4ed282SShri Abhyankar ierr = (*vi->postcheckstep)(snes,x,y,w,vi->postcheck,&changed_y,&changed_w);CHKERRQ(ierr); 23192b4ed282SShri Abhyankar if (changed_y) { 23202b4ed282SShri Abhyankar ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr); 23217fe79bc4SShri Abhyankar ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr); 23222b4ed282SShri Abhyankar } 23232b4ed282SShri Abhyankar if (changed_y || changed_w) { /* recompute the function if the step has changed */ 23242b4ed282SShri Abhyankar ierr = SNESComputeFunction(snes,w,g); 23252b4ed282SShri Abhyankar if (snes->domainerror) { 23262b4ed282SShri Abhyankar ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); 23272b4ed282SShri Abhyankar PetscFunctionReturn(0); 23282b4ed282SShri Abhyankar } 23292f63a38cSShri Abhyankar if (snes->ops->solve != SNESSolveVI_SS) { 23307fe79bc4SShri Abhyankar ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr); 23317fe79bc4SShri Abhyankar } else { 23327fe79bc4SShri Abhyankar ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr); 23337fe79bc4SShri Abhyankar } 23347fe79bc4SShri Abhyankar 23352b4ed282SShri Abhyankar ierr = VecNormBegin(y,NORM_2,ynorm);CHKERRQ(ierr); 23362b4ed282SShri Abhyankar ierr = VecNormEnd(y,NORM_2,ynorm);CHKERRQ(ierr); 233762cbcd01SMatthew G Knepley if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number"); 23382b4ed282SShri Abhyankar } 23392b4ed282SShri Abhyankar } 23402b4ed282SShri Abhyankar ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); 23412b4ed282SShri Abhyankar PetscFunctionReturn(0); 23422b4ed282SShri Abhyankar } 23432b4ed282SShri Abhyankar 2344ace3abfcSBarry 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*/ 23452b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */ 23462b4ed282SShri Abhyankar EXTERN_C_BEGIN 23472b4ed282SShri Abhyankar #undef __FUNCT__ 23482b4ed282SShri Abhyankar #define __FUNCT__ "SNESLineSearchSet_VI" 23497087cfbeSBarry Smith PetscErrorCode SNESLineSearchSet_VI(SNES snes,FCN2 func,void *lsctx) 23502b4ed282SShri Abhyankar { 23512b4ed282SShri Abhyankar PetscFunctionBegin; 23522b4ed282SShri Abhyankar ((SNES_VI *)(snes->data))->LineSearch = func; 23532b4ed282SShri Abhyankar ((SNES_VI *)(snes->data))->lsP = lsctx; 23542b4ed282SShri Abhyankar PetscFunctionReturn(0); 23552b4ed282SShri Abhyankar } 23562b4ed282SShri Abhyankar EXTERN_C_END 23572b4ed282SShri Abhyankar 23582b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */ 23592b4ed282SShri Abhyankar EXTERN_C_BEGIN 23602b4ed282SShri Abhyankar #undef __FUNCT__ 23612b4ed282SShri Abhyankar #define __FUNCT__ "SNESLineSearchSetMonitor_VI" 23627087cfbeSBarry Smith PetscErrorCode SNESLineSearchSetMonitor_VI(SNES snes,PetscBool flg) 23632b4ed282SShri Abhyankar { 23642b4ed282SShri Abhyankar SNES_VI *vi = (SNES_VI*)snes->data; 23652b4ed282SShri Abhyankar PetscErrorCode ierr; 23662b4ed282SShri Abhyankar 23672b4ed282SShri Abhyankar PetscFunctionBegin; 2368c92abb8aSShri Abhyankar if (flg && !vi->lsmonitor) { 2369649052a6SBarry Smith ierr = PetscViewerASCIIOpen(((PetscObject)snes)->comm,"stdout",&vi->lsmonitor);CHKERRQ(ierr); 2370c92abb8aSShri Abhyankar } else if (!flg && vi->lsmonitor) { 2371649052a6SBarry Smith ierr = PetscViewerDestroy(&vi->lsmonitor);CHKERRQ(ierr); 23722b4ed282SShri Abhyankar } 23732b4ed282SShri Abhyankar PetscFunctionReturn(0); 23742b4ed282SShri Abhyankar } 23752b4ed282SShri Abhyankar EXTERN_C_END 23762b4ed282SShri Abhyankar 23772b4ed282SShri Abhyankar /* 23782b4ed282SShri Abhyankar SNESView_VI - Prints info from the SNESVI data structure. 23792b4ed282SShri Abhyankar 23802b4ed282SShri Abhyankar Input Parameters: 23812b4ed282SShri Abhyankar . SNES - the SNES context 23822b4ed282SShri Abhyankar . viewer - visualization context 23832b4ed282SShri Abhyankar 23842b4ed282SShri Abhyankar Application Interface Routine: SNESView() 23852b4ed282SShri Abhyankar */ 23862b4ed282SShri Abhyankar #undef __FUNCT__ 23872b4ed282SShri Abhyankar #define __FUNCT__ "SNESView_VI" 23882b4ed282SShri Abhyankar static PetscErrorCode SNESView_VI(SNES snes,PetscViewer viewer) 23892b4ed282SShri Abhyankar { 23902b4ed282SShri Abhyankar SNES_VI *vi = (SNES_VI *)snes->data; 239178c4b9d3SShri Abhyankar const char *cstr,*tstr; 23922b4ed282SShri Abhyankar PetscErrorCode ierr; 2393ace3abfcSBarry Smith PetscBool iascii; 23942b4ed282SShri Abhyankar 23952b4ed282SShri Abhyankar PetscFunctionBegin; 23962b4ed282SShri Abhyankar ierr = PetscTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); 23972b4ed282SShri Abhyankar if (iascii) { 23982b4ed282SShri Abhyankar if (vi->LineSearch == SNESLineSearchNo_VI) cstr = "SNESLineSearchNo"; 23992b4ed282SShri Abhyankar else if (vi->LineSearch == SNESLineSearchQuadratic_VI) cstr = "SNESLineSearchQuadratic"; 24002b4ed282SShri Abhyankar else if (vi->LineSearch == SNESLineSearchCubic_VI) cstr = "SNESLineSearchCubic"; 24012b4ed282SShri Abhyankar else cstr = "unknown"; 240278c4b9d3SShri Abhyankar if (snes->ops->solve == SNESSolveVI_SS) tstr = "Semismooth"; 24030a7c7af0SShri Abhyankar else if (snes->ops->solve == SNESSolveVI_RS) tstr = "Reduced Space"; 2404b350b9c9SBarry Smith else if (snes->ops->solve == SNESSolveVI_RSAUG) tstr = "Reduced space with augmented variables"; 240578c4b9d3SShri Abhyankar else tstr = "unknown"; 240678c4b9d3SShri Abhyankar ierr = PetscViewerASCIIPrintf(viewer," VI algorithm: %s\n",tstr);CHKERRQ(ierr); 24072b4ed282SShri Abhyankar ierr = PetscViewerASCIIPrintf(viewer," line search variant: %s\n",cstr);CHKERRQ(ierr); 24082b4ed282SShri Abhyankar ierr = PetscViewerASCIIPrintf(viewer," alpha=%G, maxstep=%G, minlambda=%G\n",vi->alpha,vi->maxstep,vi->minlambda);CHKERRQ(ierr); 24092b4ed282SShri Abhyankar } 24102b4ed282SShri Abhyankar PetscFunctionReturn(0); 24112b4ed282SShri Abhyankar } 24122b4ed282SShri Abhyankar 24135559b345SBarry Smith #undef __FUNCT__ 24145559b345SBarry Smith #define __FUNCT__ "SNESVISetVariableBounds" 24155559b345SBarry Smith /*@ 24162b4ed282SShri Abhyankar SNESVISetVariableBounds - Sets the lower and upper bounds for the solution vector. xl <= x <= xu. 24172b4ed282SShri Abhyankar 24182b4ed282SShri Abhyankar Input Parameters: 24192b4ed282SShri Abhyankar . snes - the SNES context. 24202b4ed282SShri Abhyankar . xl - lower bound. 24212b4ed282SShri Abhyankar . xu - upper bound. 24222b4ed282SShri Abhyankar 24232b4ed282SShri Abhyankar Notes: 24242b4ed282SShri Abhyankar If this routine is not called then the lower and upper bounds are set to 242501f0b76bSBarry Smith SNES_VI_INF and SNES_VI_NINF respectively during SNESSetUp(). 242684c105d7SBarry Smith 24275559b345SBarry Smith @*/ 242869c03620SShri Abhyankar PetscErrorCode SNESVISetVariableBounds(SNES snes, Vec xl, Vec xu) 24292b4ed282SShri Abhyankar { 2430d923200aSJungho Lee SNES_VI *vi; 2431d923200aSJungho Lee PetscErrorCode ierr; 24326fd67740SBarry Smith const PetscScalar *xxl,*xxu; 24336fd67740SBarry Smith PetscInt i,n, cnt = 0; 24342b4ed282SShri Abhyankar 24352b4ed282SShri Abhyankar PetscFunctionBegin; 24362b4ed282SShri Abhyankar PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 24372b4ed282SShri Abhyankar PetscValidHeaderSpecific(xl,VEC_CLASSID,2); 24382b4ed282SShri Abhyankar PetscValidHeaderSpecific(xu,VEC_CLASSID,3); 24392b4ed282SShri Abhyankar if (!snes->vec_func) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Must call SNESSetFunction() first"); 24402b4ed282SShri 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); 24412b4ed282SShri 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); 2442d923200aSJungho Lee ierr = SNESSetType(snes,SNESVI);CHKERRQ(ierr); 2443d923200aSJungho Lee vi = (SNES_VI*)snes->data; 24442176524cSBarry Smith ierr = PetscObjectReference((PetscObject)xl);CHKERRQ(ierr); 24452176524cSBarry Smith ierr = PetscObjectReference((PetscObject)xu);CHKERRQ(ierr); 24462176524cSBarry Smith ierr = VecDestroy(&vi->xl);CHKERRQ(ierr); 24472176524cSBarry Smith ierr = VecDestroy(&vi->xu);CHKERRQ(ierr); 24482b4ed282SShri Abhyankar vi->xl = xl; 24492b4ed282SShri Abhyankar vi->xu = xu; 24506fd67740SBarry Smith ierr = VecGetLocalSize(xl,&n);CHKERRQ(ierr); 24516fd67740SBarry Smith ierr = VecGetArrayRead(xl,&xxl);CHKERRQ(ierr); 24526fd67740SBarry Smith ierr = VecGetArrayRead(xu,&xxu);CHKERRQ(ierr); 24536fd67740SBarry Smith for (i=0; i<n; i++) { 24546fd67740SBarry Smith cnt += ((xxl[i] != SNES_VI_NINF) || (xxu[i] != SNES_VI_INF)); 24556fd67740SBarry Smith } 24566fd67740SBarry Smith ierr = MPI_Allreduce(&cnt,&vi->ntruebounds,1,MPIU_INT,MPI_SUM,((PetscObject)snes)->comm);CHKERRQ(ierr); 24576fd67740SBarry Smith ierr = VecRestoreArrayRead(xl,&xxl);CHKERRQ(ierr); 24586fd67740SBarry Smith ierr = VecRestoreArrayRead(xu,&xxu);CHKERRQ(ierr); 24592b4ed282SShri Abhyankar PetscFunctionReturn(0); 24602b4ed282SShri Abhyankar } 2461693ddf92SShri Abhyankar 24622b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */ 24632b4ed282SShri Abhyankar /* 24642b4ed282SShri Abhyankar SNESSetFromOptions_VI - Sets various parameters for the SNESVI method. 24652b4ed282SShri Abhyankar 24662b4ed282SShri Abhyankar Input Parameter: 24672b4ed282SShri Abhyankar . snes - the SNES context 24682b4ed282SShri Abhyankar 24692b4ed282SShri Abhyankar Application Interface Routine: SNESSetFromOptions() 24702b4ed282SShri Abhyankar */ 24712b4ed282SShri Abhyankar #undef __FUNCT__ 24722b4ed282SShri Abhyankar #define __FUNCT__ "SNESSetFromOptions_VI" 24732b4ed282SShri Abhyankar static PetscErrorCode SNESSetFromOptions_VI(SNES snes) 24742b4ed282SShri Abhyankar { 24752b4ed282SShri Abhyankar SNES_VI *vi = (SNES_VI *)snes->data; 24767fe79bc4SShri Abhyankar const char *lses[] = {"basic","basicnonorms","quadratic","cubic"}; 2477b350b9c9SBarry Smith const char *vies[] = {"ss","rs","rsaug"}; 24782b4ed282SShri Abhyankar PetscErrorCode ierr; 24792b4ed282SShri Abhyankar PetscInt indx; 248069c03620SShri Abhyankar PetscBool flg,set,flg2; 24812b4ed282SShri Abhyankar 24822b4ed282SShri Abhyankar PetscFunctionBegin; 24832b4ed282SShri Abhyankar ierr = PetscOptionsHead("SNES semismooth method options");CHKERRQ(ierr); 24849308c137SBarry Smith ierr = PetscOptionsBool("-snes_vi_monitor","Monitor all non-active variables","None",PETSC_FALSE,&flg,0);CHKERRQ(ierr); 24859308c137SBarry Smith if (flg) { 24869308c137SBarry Smith ierr = SNESMonitorSet(snes,SNESMonitorVI,0,0);CHKERRQ(ierr); 24879308c137SBarry Smith } 2488be6adb11SBarry Smith ierr = PetscOptionsReal("-snes_ls_alpha","Function norm must decrease by","None",vi->alpha,&vi->alpha,0);CHKERRQ(ierr); 2489be6adb11SBarry Smith ierr = PetscOptionsReal("-snes_ls_maxstep","Step must be less than","None",vi->maxstep,&vi->maxstep,0);CHKERRQ(ierr); 2490be6adb11SBarry Smith ierr = PetscOptionsReal("-snes_ls_minlambda","Minimum lambda allowed","None",vi->minlambda,&vi->minlambda,0);CHKERRQ(ierr); 24912b4ed282SShri Abhyankar ierr = PetscOptionsReal("-snes_vi_const_tol","constraint tolerance","None",vi->const_tol,&vi->const_tol,0);CHKERRQ(ierr); 2492be6adb11SBarry Smith ierr = PetscOptionsBool("-snes_ls_monitor","Print progress of line searches","SNESLineSearchSetMonitor",vi->lsmonitor ? PETSC_TRUE : PETSC_FALSE,&flg,&set);CHKERRQ(ierr); 24932b4ed282SShri Abhyankar if (set) {ierr = SNESLineSearchSetMonitor(snes,flg);CHKERRQ(ierr);} 24942f63a38cSShri Abhyankar ierr = PetscOptionsEList("-snes_vi_type","Semismooth algorithm used","",vies,3,"ss",&indx,&flg2);CHKERRQ(ierr); 249569c03620SShri Abhyankar if (flg2) { 249669c03620SShri Abhyankar switch (indx) { 249769c03620SShri Abhyankar case 0: 249869c03620SShri Abhyankar snes->ops->solve = SNESSolveVI_SS; 249969c03620SShri Abhyankar break; 250069c03620SShri Abhyankar case 1: 2501d950fb63SShri Abhyankar snes->ops->solve = SNESSolveVI_RS; 2502d950fb63SShri Abhyankar break; 25032f63a38cSShri Abhyankar case 2: 2504b350b9c9SBarry Smith snes->ops->solve = SNESSolveVI_RSAUG; 250569c03620SShri Abhyankar } 250669c03620SShri Abhyankar } 2507f2b03b96SBarry Smith ierr = PetscOptionsEList("-snes_ls","Line search used","SNESLineSearchSet",lses,4,"cubic",&indx,&flg);CHKERRQ(ierr); 25082b4ed282SShri Abhyankar if (flg) { 25092b4ed282SShri Abhyankar switch (indx) { 25102b4ed282SShri Abhyankar case 0: 25112b4ed282SShri Abhyankar ierr = SNESLineSearchSet(snes,SNESLineSearchNo_VI,PETSC_NULL);CHKERRQ(ierr); 25122b4ed282SShri Abhyankar break; 25132b4ed282SShri Abhyankar case 1: 25142b4ed282SShri Abhyankar ierr = SNESLineSearchSet(snes,SNESLineSearchNoNorms_VI,PETSC_NULL);CHKERRQ(ierr); 25152b4ed282SShri Abhyankar break; 25162b4ed282SShri Abhyankar case 2: 25172b4ed282SShri Abhyankar ierr = SNESLineSearchSet(snes,SNESLineSearchQuadratic_VI,PETSC_NULL);CHKERRQ(ierr); 25182b4ed282SShri Abhyankar break; 25192b4ed282SShri Abhyankar case 3: 25202b4ed282SShri Abhyankar ierr = SNESLineSearchSet(snes,SNESLineSearchCubic_VI,PETSC_NULL);CHKERRQ(ierr); 25212b4ed282SShri Abhyankar break; 25222b4ed282SShri Abhyankar } 2523fe835674SShri Abhyankar } 2524*e6337399SBarry Smith ierr = PetscOptionsBool("-snes_vi_ignore_function_sign","Ignore the sign of function for active constraints","None",vi->ignorefunctionsign,&vi->ignorefunctionsign,PETSC_NULL);CHKERRQ(ierr); 25252b4ed282SShri Abhyankar ierr = PetscOptionsTail();CHKERRQ(ierr); 25262b4ed282SShri Abhyankar PetscFunctionReturn(0); 25272b4ed282SShri Abhyankar } 25282b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */ 25292b4ed282SShri Abhyankar /*MC 25308b4c83edSBarry Smith SNESVI - Various solvers for variational inequalities based on Newton's method 25312b4ed282SShri Abhyankar 25322b4ed282SShri Abhyankar Options Database: 25338b4c83edSBarry 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 25348b4c83edSBarry Smith additional variables that enforce the constraints 25358b4c83edSBarry Smith - -snes_vi_monitor - prints the number of active constraints at each iteration. 25362b4ed282SShri Abhyankar 25372b4ed282SShri Abhyankar 25382b4ed282SShri Abhyankar Level: beginner 25392b4ed282SShri Abhyankar 25402b4ed282SShri Abhyankar .seealso: SNESCreate(), SNES, SNESSetType(), SNESTR, SNESLineSearchSet(), 25412b4ed282SShri Abhyankar SNESLineSearchSetPostCheck(), SNESLineSearchNo(), SNESLineSearchCubic(), SNESLineSearchQuadratic(), 25422b4ed282SShri Abhyankar SNESLineSearchSet(), SNESLineSearchNoNorms(), SNESLineSearchSetPreCheck(), SNESLineSearchSetParams(), SNESLineSearchGetParams() 25432b4ed282SShri Abhyankar 25442b4ed282SShri Abhyankar M*/ 25452b4ed282SShri Abhyankar EXTERN_C_BEGIN 25462b4ed282SShri Abhyankar #undef __FUNCT__ 25472b4ed282SShri Abhyankar #define __FUNCT__ "SNESCreate_VI" 25487087cfbeSBarry Smith PetscErrorCode SNESCreate_VI(SNES snes) 25492b4ed282SShri Abhyankar { 25502b4ed282SShri Abhyankar PetscErrorCode ierr; 25512b4ed282SShri Abhyankar SNES_VI *vi; 25522b4ed282SShri Abhyankar 25532b4ed282SShri Abhyankar PetscFunctionBegin; 25542176524cSBarry Smith snes->ops->reset = SNESReset_VI; 25552b4ed282SShri Abhyankar snes->ops->setup = SNESSetUp_VI; 2556edafb9efSBarry Smith snes->ops->solve = SNESSolveVI_RS; 25572b4ed282SShri Abhyankar snes->ops->destroy = SNESDestroy_VI; 25582b4ed282SShri Abhyankar snes->ops->setfromoptions = SNESSetFromOptions_VI; 25592b4ed282SShri Abhyankar snes->ops->view = SNESView_VI; 25602b4ed282SShri Abhyankar snes->ops->converged = SNESDefaultConverged_VI; 25612b4ed282SShri Abhyankar 25622b4ed282SShri Abhyankar ierr = PetscNewLog(snes,SNES_VI,&vi);CHKERRQ(ierr); 25632b4ed282SShri Abhyankar snes->data = (void*)vi; 25642b4ed282SShri Abhyankar vi->alpha = 1.e-4; 25652b4ed282SShri Abhyankar vi->maxstep = 1.e8; 25662b4ed282SShri Abhyankar vi->minlambda = 1.e-12; 2567f2b03b96SBarry Smith vi->LineSearch = SNESLineSearchCubic_VI; 25682b4ed282SShri Abhyankar vi->lsP = PETSC_NULL; 25692b4ed282SShri Abhyankar vi->postcheckstep = PETSC_NULL; 25702b4ed282SShri Abhyankar vi->postcheck = PETSC_NULL; 25712b4ed282SShri Abhyankar vi->precheckstep = PETSC_NULL; 25722b4ed282SShri Abhyankar vi->precheck = PETSC_NULL; 25732b4ed282SShri Abhyankar vi->const_tol = 2.2204460492503131e-16; 25742f63a38cSShri Abhyankar vi->checkredundancy = PETSC_NULL; 25752b4ed282SShri Abhyankar 25762b4ed282SShri Abhyankar ierr = PetscObjectComposeFunctionDynamic((PetscObject)snes,"SNESLineSearchSetMonitor_C","SNESLineSearchSetMonitor_VI",SNESLineSearchSetMonitor_VI);CHKERRQ(ierr); 25772b4ed282SShri Abhyankar ierr = PetscObjectComposeFunctionDynamic((PetscObject)snes,"SNESLineSearchSet_C","SNESLineSearchSet_VI",SNESLineSearchSet_VI);CHKERRQ(ierr); 25782b4ed282SShri Abhyankar 25792b4ed282SShri Abhyankar PetscFunctionReturn(0); 25802b4ed282SShri Abhyankar } 25812b4ed282SShri Abhyankar EXTERN_C_END 2582ed70e96aSJungho Lee 2583ed70e96aSJungho Lee #undef __FUNCT__ 2584ed70e96aSJungho Lee #define __FUNCT__ "SNESVIGetInactiveSet" 2585ed70e96aSJungho Lee /* 2586ed70e96aSJungho Lee SNESVIGetInactiveSet - Gets the global indices for the inactive set variables (these correspond to the degrees of freedom the linear 2587ed70e96aSJungho Lee system is solved on) 2588ed70e96aSJungho Lee 2589ed70e96aSJungho Lee Input parameter 2590ed70e96aSJungho Lee . snes - the SNES context 2591ed70e96aSJungho Lee 2592ed70e96aSJungho Lee Output parameter 2593ed70e96aSJungho Lee . ISact - active set index set 2594ed70e96aSJungho Lee 2595ed70e96aSJungho Lee */ 2596ed70e96aSJungho Lee PetscErrorCode SNESVIGetInactiveSet(SNES snes,IS* inact) 2597ed70e96aSJungho Lee { 2598ed70e96aSJungho Lee SNES_VI *vi = (SNES_VI*)snes->data; 2599ed70e96aSJungho Lee PetscFunctionBegin; 2600ed70e96aSJungho Lee *inact = vi->IS_inact_prev; 2601ed70e96aSJungho Lee PetscFunctionReturn(0); 2602ed70e96aSJungho Lee } 2603