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__ 8d0af7cd3SBarry Smith #define __FUNCT__ "SNESVIGetInActiveSetIS" 9d0af7cd3SBarry Smith /* 10d0af7cd3SBarry Smith SNESVIGetInActiveSetIS - Gets the global indices for the bogus inactive set variables 11d0af7cd3SBarry Smith 12d0af7cd3SBarry Smith Input parameter 13d0af7cd3SBarry Smith . snes - the SNES context 14d0af7cd3SBarry Smith . X - the snes solution vector 15d0af7cd3SBarry Smith 16d0af7cd3SBarry Smith Output parameter 17d0af7cd3SBarry Smith . ISact - active set index set 18d0af7cd3SBarry Smith 19d0af7cd3SBarry Smith */ 20d0af7cd3SBarry Smith PetscErrorCode SNESVIGetInActiveSetIS(Vec upper,Vec lower,Vec X,Vec F,IS* inact) 21d0af7cd3SBarry Smith { 22d0af7cd3SBarry Smith PetscErrorCode ierr; 23d0af7cd3SBarry Smith const PetscScalar *x,*xl,*xu,*f; 24d0af7cd3SBarry Smith PetscInt *idx_act,i,nlocal,nloc_isact=0,ilow,ihigh,i1=0; 25d0af7cd3SBarry Smith 26d0af7cd3SBarry Smith PetscFunctionBegin; 27d0af7cd3SBarry Smith ierr = VecGetLocalSize(X,&nlocal);CHKERRQ(ierr); 28d0af7cd3SBarry Smith ierr = VecGetOwnershipRange(X,&ilow,&ihigh);CHKERRQ(ierr); 29d0af7cd3SBarry Smith ierr = VecGetArrayRead(X,&x);CHKERRQ(ierr); 30d0af7cd3SBarry Smith ierr = VecGetArrayRead(lower,&xl);CHKERRQ(ierr); 31d0af7cd3SBarry Smith ierr = VecGetArrayRead(upper,&xu);CHKERRQ(ierr); 32d0af7cd3SBarry Smith ierr = VecGetArrayRead(F,&f);CHKERRQ(ierr); 33d0af7cd3SBarry Smith /* Compute inactive set size */ 34d0af7cd3SBarry Smith for (i=0; i < nlocal;i++) { 35d0af7cd3SBarry 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++; 36d0af7cd3SBarry Smith } 37d0af7cd3SBarry Smith 38d0af7cd3SBarry Smith ierr = PetscMalloc(nloc_isact*sizeof(PetscInt),&idx_act);CHKERRQ(ierr); 39d0af7cd3SBarry Smith 40d0af7cd3SBarry Smith /* Set inactive set indices */ 41d0af7cd3SBarry Smith for(i=0; i < nlocal; i++) { 42d0af7cd3SBarry 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; 43d0af7cd3SBarry Smith } 44d0af7cd3SBarry Smith 45d0af7cd3SBarry Smith /* Create inactive set IS */ 46d0af7cd3SBarry Smith ierr = ISCreateGeneral(((PetscObject)upper)->comm,nloc_isact,idx_act,PETSC_OWN_POINTER,inact);CHKERRQ(ierr); 47d0af7cd3SBarry Smith 48d0af7cd3SBarry Smith ierr = VecRestoreArrayRead(X,&x);CHKERRQ(ierr); 49d0af7cd3SBarry Smith ierr = VecRestoreArrayRead(lower,&xl);CHKERRQ(ierr); 50d0af7cd3SBarry Smith ierr = VecRestoreArrayRead(upper,&xu);CHKERRQ(ierr); 51d0af7cd3SBarry Smith ierr = VecRestoreArrayRead(F,&f);CHKERRQ(ierr); 52d0af7cd3SBarry Smith PetscFunctionReturn(0); 53d0af7cd3SBarry Smith } 54d0af7cd3SBarry Smith 553c0c59f3SBarry Smith /* 563c0c59f3SBarry 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 573c0c59f3SBarry Smith defined by the reduced space method. 583c0c59f3SBarry Smith 593c0c59f3SBarry Smith Simple calls the regular DM interpolation and restricts it to operation on the variables not associated with active constraints. 603c0c59f3SBarry Smith 613c0c59f3SBarry Smith */ 623c0c59f3SBarry Smith typedef struct { 633c0c59f3SBarry Smith PetscInt n; /* size of vectors in the reduced DM space */ 643c0c59f3SBarry Smith IS inactive; 653c0c59f3SBarry Smith Vec upper,lower,values,F; /* upper and lower bounds of all variables on this level, the values and the function values */ 663c0c59f3SBarry Smith PetscErrorCode (*getinterpolation)(DM,DM,Mat*,Vec*); /* DM's original routines */ 673c0c59f3SBarry Smith PetscErrorCode (*coarsen)(DM, MPI_Comm, DM*); 683c0c59f3SBarry Smith PetscErrorCode (*createglobalvector)(DM,Vec*); 694c661befSBarry Smith DM dm; /* when destroying this object we need to reset the above function into the base DM */ 703c0c59f3SBarry Smith } DM_SNESVI; 713c0c59f3SBarry Smith 72d0af7cd3SBarry Smith #undef __FUNCT__ 734dcab191SBarry Smith #define __FUNCT__ "DMCreateGlobalVector_SNESVI" 744dcab191SBarry Smith /* 754dcab191SBarry Smith DMCreateGlobalVector_SNESVI - Creates global vector of the size of the reduced space 764dcab191SBarry Smith 774dcab191SBarry Smith */ 784dcab191SBarry Smith PetscErrorCode DMCreateGlobalVector_SNESVI(DM dm,Vec *vec) 794dcab191SBarry Smith { 804dcab191SBarry Smith PetscErrorCode ierr; 814dcab191SBarry Smith PetscContainer isnes; 823c0c59f3SBarry Smith DM_SNESVI *dmsnesvi; 834dcab191SBarry Smith 844dcab191SBarry Smith PetscFunctionBegin; 854dcab191SBarry Smith ierr = PetscObjectQuery((PetscObject)dm,"VI",(PetscObject *)&isnes);CHKERRQ(ierr); 864dcab191SBarry Smith if (!isnes) SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_PLIB,"Composed SNES is missing"); 874dcab191SBarry Smith ierr = PetscContainerGetPointer(isnes,(void**)&dmsnesvi);CHKERRQ(ierr); 884dcab191SBarry Smith ierr = VecCreateMPI(((PetscObject)dm)->comm,dmsnesvi->n,PETSC_DETERMINE,vec);CHKERRQ(ierr); 894dcab191SBarry Smith PetscFunctionReturn(0); 904dcab191SBarry Smith } 914dcab191SBarry Smith 924dcab191SBarry Smith #undef __FUNCT__ 93d0af7cd3SBarry Smith #define __FUNCT__ "DMGetInterpolation_SNESVI" 94d0af7cd3SBarry Smith /* 95d0af7cd3SBarry Smith DMGetInterpolation_SNESVI - Modifieds the interpolation obtained from the DM by removing all rows and columns associated with active constraints. 96d0af7cd3SBarry Smith 97d0af7cd3SBarry Smith */ 98d0af7cd3SBarry Smith PetscErrorCode DMGetInterpolation_SNESVI(DM dm1,DM dm2,Mat *mat,Vec *vec) 99d0af7cd3SBarry Smith { 100d0af7cd3SBarry Smith PetscErrorCode ierr; 101d0af7cd3SBarry Smith PetscContainer isnes; 1023c0c59f3SBarry Smith DM_SNESVI *dmsnesvi1,*dmsnesvi2; 103d0af7cd3SBarry Smith Mat interp; 104d0af7cd3SBarry Smith 105d0af7cd3SBarry Smith PetscFunctionBegin; 106d0af7cd3SBarry Smith ierr = PetscObjectQuery((PetscObject)dm1,"VI",(PetscObject *)&isnes);CHKERRQ(ierr); 1074c661befSBarry Smith if (!isnes) SETERRQ(((PetscObject)dm1)->comm,PETSC_ERR_PLIB,"Composed VI data structure is missing"); 108d0af7cd3SBarry Smith ierr = PetscContainerGetPointer(isnes,(void**)&dmsnesvi1);CHKERRQ(ierr); 109d0af7cd3SBarry Smith ierr = PetscObjectQuery((PetscObject)dm2,"VI",(PetscObject *)&isnes);CHKERRQ(ierr); 1104c661befSBarry Smith if (!isnes) SETERRQ(((PetscObject)dm2)->comm,PETSC_ERR_PLIB,"Composed VI data structure is missing"); 111d0af7cd3SBarry Smith ierr = PetscContainerGetPointer(isnes,(void**)&dmsnesvi2);CHKERRQ(ierr); 112d0af7cd3SBarry Smith 113d0af7cd3SBarry Smith ierr = (*dmsnesvi1->getinterpolation)(dm1,dm2,&interp,PETSC_NULL);CHKERRQ(ierr); 1144dcab191SBarry Smith ierr = MatGetSubMatrix(interp,dmsnesvi2->inactive,dmsnesvi1->inactive,MAT_INITIAL_MATRIX,mat);CHKERRQ(ierr); 115d0af7cd3SBarry Smith ierr = MatDestroy(&interp);CHKERRQ(ierr); 116d0af7cd3SBarry Smith PetscFunctionReturn(0); 117d0af7cd3SBarry Smith } 118d0af7cd3SBarry Smith 119d0af7cd3SBarry Smith extern PetscErrorCode DMSetVI(DM,Vec,Vec,Vec,Vec,IS); 120d0af7cd3SBarry Smith 121d0af7cd3SBarry Smith #undef __FUNCT__ 122d0af7cd3SBarry Smith #define __FUNCT__ "DMCoarsen_SNESVI" 123d0af7cd3SBarry Smith /* 124d0af7cd3SBarry Smith DMCoarsen_SNESVI - Computes the regular coarsened DM then computes additional information about its inactive set 125d0af7cd3SBarry Smith 126d0af7cd3SBarry Smith */ 127d0af7cd3SBarry Smith PetscErrorCode DMCoarsen_SNESVI(DM dm1,MPI_Comm comm,DM *dm2) 128d0af7cd3SBarry Smith { 129d0af7cd3SBarry Smith PetscErrorCode ierr; 130d0af7cd3SBarry Smith PetscContainer isnes; 1313c0c59f3SBarry Smith DM_SNESVI *dmsnesvi1; 132d0af7cd3SBarry Smith Vec upper,lower,values,F; 133d0af7cd3SBarry Smith IS inactive; 134d0af7cd3SBarry Smith VecScatter inject; 135d0af7cd3SBarry Smith 136d0af7cd3SBarry Smith PetscFunctionBegin; 137d0af7cd3SBarry Smith ierr = PetscObjectQuery((PetscObject)dm1,"VI",(PetscObject *)&isnes);CHKERRQ(ierr); 1384c661befSBarry Smith if (!isnes) SETERRQ(((PetscObject)dm1)->comm,PETSC_ERR_PLIB,"Composed VI data structure is missing"); 139d0af7cd3SBarry Smith ierr = PetscContainerGetPointer(isnes,(void**)&dmsnesvi1);CHKERRQ(ierr); 140d0af7cd3SBarry Smith 141298cc208SBarry Smith /* get the original coarsen */ 142d0af7cd3SBarry Smith ierr = (*dmsnesvi1->coarsen)(dm1,comm,dm2);CHKERRQ(ierr); 143298cc208SBarry Smith 1443c0c59f3SBarry Smith /* not sure why this extra reference is needed, but without the dm2 disappears too early */ 1453c0c59f3SBarry Smith ierr = PetscObjectReference((PetscObject)*dm2);CHKERRQ(ierr); 1463c0c59f3SBarry Smith 147298cc208SBarry Smith /* need to set back global vectors in order to use the original injection */ 148298cc208SBarry Smith ierr = DMClearGlobalVectors(dm1);CHKERRQ(ierr); 149298cc208SBarry Smith dm1->ops->createglobalvector = dmsnesvi1->createglobalvector; 150d0af7cd3SBarry Smith ierr = DMGetInjection(*dm2,dm1,&inject);CHKERRQ(ierr); 151d0af7cd3SBarry Smith ierr = DMCreateGlobalVector(*dm2,&upper);CHKERRQ(ierr); 152d0af7cd3SBarry Smith ierr = VecScatterBegin(inject,dmsnesvi1->upper,upper,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 153d0af7cd3SBarry Smith ierr = VecScatterEnd(inject,dmsnesvi1->upper,upper,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 154d0af7cd3SBarry Smith ierr = DMCreateGlobalVector(*dm2,&lower);CHKERRQ(ierr); 155d0af7cd3SBarry Smith ierr = VecScatterBegin(inject,dmsnesvi1->lower,lower,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 156d0af7cd3SBarry Smith ierr = VecScatterEnd(inject,dmsnesvi1->lower,lower,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 157d0af7cd3SBarry Smith ierr = DMCreateGlobalVector(*dm2,&values);CHKERRQ(ierr); 158d0af7cd3SBarry Smith ierr = VecScatterBegin(inject,dmsnesvi1->values,values,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 159d0af7cd3SBarry Smith ierr = VecScatterEnd(inject,dmsnesvi1->values,values,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 160d0af7cd3SBarry Smith ierr = DMCreateGlobalVector(*dm2,&F);CHKERRQ(ierr); 161d0af7cd3SBarry Smith ierr = VecScatterBegin(inject,dmsnesvi1->F,F,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 162d0af7cd3SBarry Smith ierr = VecScatterEnd(inject,dmsnesvi1->F,F,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 163d0af7cd3SBarry Smith ierr = VecScatterDestroy(&inject);CHKERRQ(ierr); 164298cc208SBarry Smith ierr = DMClearGlobalVectors(dm1);CHKERRQ(ierr); 165298cc208SBarry Smith dm1->ops->createglobalvector = DMCreateGlobalVector_SNESVI; 166d0af7cd3SBarry Smith ierr = SNESVIGetInActiveSetIS(upper,lower,values,F,&inactive);CHKERRQ(ierr); 167d0af7cd3SBarry Smith ierr = DMSetVI(*dm2,upper,lower,values,F,inactive);CHKERRQ(ierr); 1683c0c59f3SBarry Smith ierr = VecDestroy(&upper);CHKERRQ(ierr); 1693c0c59f3SBarry Smith ierr = VecDestroy(&lower);CHKERRQ(ierr); 1703c0c59f3SBarry Smith ierr = VecDestroy(&values);CHKERRQ(ierr); 1713c0c59f3SBarry Smith ierr = VecDestroy(&F);CHKERRQ(ierr); 1723c0c59f3SBarry Smith ierr = ISDestroy(&inactive);CHKERRQ(ierr); 173d0af7cd3SBarry Smith PetscFunctionReturn(0); 174d0af7cd3SBarry Smith } 175d0af7cd3SBarry Smith 176d0af7cd3SBarry Smith #undef __FUNCT__ 1773c0c59f3SBarry Smith #define __FUNCT__ "DMDestroy_SNESVI" 1783c0c59f3SBarry Smith PetscErrorCode DMDestroy_SNESVI(DM_SNESVI *dmsnesvi) 179d0af7cd3SBarry Smith { 180d0af7cd3SBarry Smith PetscErrorCode ierr; 181d0af7cd3SBarry Smith 182d0af7cd3SBarry Smith PetscFunctionBegin; 1834c661befSBarry Smith /* reset the base methods in the DM object that were changed when the DM_SNESVI was reset */ 1844c661befSBarry Smith dmsnesvi->dm->ops->getinterpolation = dmsnesvi->getinterpolation; 1854c661befSBarry Smith dmsnesvi->dm->ops->coarsen = dmsnesvi->coarsen; 1864c661befSBarry Smith dmsnesvi->dm->ops->createglobalvector = dmsnesvi->createglobalvector; 1874c661befSBarry Smith 188d0af7cd3SBarry Smith ierr = VecDestroy(&dmsnesvi->upper);CHKERRQ(ierr); 189d0af7cd3SBarry Smith ierr = VecDestroy(&dmsnesvi->lower);CHKERRQ(ierr); 190d0af7cd3SBarry Smith ierr = VecDestroy(&dmsnesvi->values);CHKERRQ(ierr); 191d0af7cd3SBarry Smith ierr = VecDestroy(&dmsnesvi->F);CHKERRQ(ierr); 192d0af7cd3SBarry Smith ierr = ISDestroy(&dmsnesvi->inactive);CHKERRQ(ierr); 193d0af7cd3SBarry Smith ierr = PetscFree(dmsnesvi);CHKERRQ(ierr); 194d0af7cd3SBarry Smith PetscFunctionReturn(0); 195d0af7cd3SBarry Smith } 196d0af7cd3SBarry Smith 197d0af7cd3SBarry Smith #undef __FUNCT__ 198d0af7cd3SBarry Smith #define __FUNCT__ "DMSetVI" 199d0af7cd3SBarry Smith /* 200d0af7cd3SBarry Smith DMSetVI - Marks a DM as associated with a VI problem. This causes the interpolation/restriction operators to 201d0af7cd3SBarry Smith be restricted to only those variables NOT associated with active constraints. 202d0af7cd3SBarry Smith 203d0af7cd3SBarry Smith */ 204d0af7cd3SBarry Smith PetscErrorCode DMSetVI(DM dm,Vec upper,Vec lower,Vec values,Vec F,IS inactive) 205d0af7cd3SBarry Smith { 206d0af7cd3SBarry Smith PetscErrorCode ierr; 207d0af7cd3SBarry Smith PetscContainer isnes; 2083c0c59f3SBarry Smith DM_SNESVI *dmsnesvi; 209d0af7cd3SBarry Smith 210d0af7cd3SBarry Smith PetscFunctionBegin; 2114dcab191SBarry Smith if (!dm) PetscFunctionReturn(0); 212d0af7cd3SBarry Smith ierr = PetscObjectReference((PetscObject)upper);CHKERRQ(ierr); 213d0af7cd3SBarry Smith ierr = PetscObjectReference((PetscObject)lower);CHKERRQ(ierr); 214d0af7cd3SBarry Smith ierr = PetscObjectReference((PetscObject)values);CHKERRQ(ierr); 215d0af7cd3SBarry Smith ierr = PetscObjectReference((PetscObject)F);CHKERRQ(ierr); 216d0af7cd3SBarry Smith ierr = PetscObjectReference((PetscObject)inactive);CHKERRQ(ierr); 217d0af7cd3SBarry Smith 218d0af7cd3SBarry Smith ierr = PetscObjectQuery((PetscObject)dm,"VI",(PetscObject *)&isnes);CHKERRQ(ierr); 219d0af7cd3SBarry Smith if (!isnes) { 220d0af7cd3SBarry Smith ierr = PetscContainerCreate(((PetscObject)dm)->comm,&isnes);CHKERRQ(ierr); 2213c0c59f3SBarry Smith ierr = PetscContainerSetUserDestroy(isnes,(PetscErrorCode (*)(void*))DMDestroy_SNESVI);CHKERRQ(ierr); 2223c0c59f3SBarry Smith ierr = PetscNew(DM_SNESVI,&dmsnesvi);CHKERRQ(ierr); 223d0af7cd3SBarry Smith ierr = PetscContainerSetPointer(isnes,(void*)dmsnesvi);CHKERRQ(ierr); 224d0af7cd3SBarry Smith ierr = PetscObjectCompose((PetscObject)dm,"VI",(PetscObject)isnes);CHKERRQ(ierr); 2253c0c59f3SBarry Smith ierr = PetscContainerDestroy(&isnes);CHKERRQ(ierr); 226d0af7cd3SBarry Smith dmsnesvi->getinterpolation = dm->ops->getinterpolation; 227d0af7cd3SBarry Smith dm->ops->getinterpolation = DMGetInterpolation_SNESVI; 228d0af7cd3SBarry Smith dmsnesvi->coarsen = dm->ops->coarsen; 229d0af7cd3SBarry Smith dm->ops->coarsen = DMCoarsen_SNESVI; 230298cc208SBarry Smith dmsnesvi->createglobalvector = dm->ops->createglobalvector; 2314dcab191SBarry Smith dm->ops->createglobalvector = DMCreateGlobalVector_SNESVI; 2326ba4bc90SBarry Smith /* since these vectors may reference the DM, need to remove circle referencing */ 2336ba4bc90SBarry Smith ierr = PetscObjectRemoveReference((PetscObject)upper,"DM");CHKERRQ(ierr); 2346ba4bc90SBarry Smith ierr = PetscObjectRemoveReference((PetscObject)lower,"DM");CHKERRQ(ierr); 2356ba4bc90SBarry Smith ierr = PetscObjectRemoveReference((PetscObject)values,"DM");CHKERRQ(ierr); 2366ba4bc90SBarry Smith ierr = PetscObjectRemoveReference((PetscObject)F,"DM");CHKERRQ(ierr); 237d0af7cd3SBarry Smith } else { 238d0af7cd3SBarry Smith ierr = PetscContainerGetPointer(isnes,(void**)&dmsnesvi);CHKERRQ(ierr); 239d0af7cd3SBarry Smith ierr = VecDestroy(&dmsnesvi->upper);CHKERRQ(ierr); 240d0af7cd3SBarry Smith ierr = VecDestroy(&dmsnesvi->lower);CHKERRQ(ierr); 241d0af7cd3SBarry Smith ierr = VecDestroy(&dmsnesvi->values);CHKERRQ(ierr); 242d0af7cd3SBarry Smith ierr = VecDestroy(&dmsnesvi->F);CHKERRQ(ierr); 243d0af7cd3SBarry Smith ierr = ISDestroy(&dmsnesvi->inactive);CHKERRQ(ierr); 244d0af7cd3SBarry Smith } 2454dcab191SBarry Smith ierr = DMClearGlobalVectors(dm);CHKERRQ(ierr); 2464dcab191SBarry Smith ierr = ISGetLocalSize(inactive,&dmsnesvi->n);CHKERRQ(ierr); 247d0af7cd3SBarry Smith dmsnesvi->upper = upper; 248d0af7cd3SBarry Smith dmsnesvi->lower = lower; 249d0af7cd3SBarry Smith dmsnesvi->values = values; 250d0af7cd3SBarry Smith dmsnesvi->F = F; 251d0af7cd3SBarry Smith dmsnesvi->inactive = inactive; 252*1a223a97SBarry Smith dmsnesvi->dm = dm; 253d0af7cd3SBarry Smith PetscFunctionReturn(0); 254d0af7cd3SBarry Smith } 255d0af7cd3SBarry Smith 2564c661befSBarry Smith #undef __FUNCT__ 2574c661befSBarry Smith #define __FUNCT__ "DMDestroyVI" 2584c661befSBarry Smith /* 2594c661befSBarry Smith DMDestroyVI - Frees the DM_SNESVI object contained in the DM 2604c661befSBarry Smith - also resets the function pointers in the DM for getinterpolation() etc to use the original DM 2614c661befSBarry Smith */ 2624c661befSBarry Smith PetscErrorCode DMDestroyVI(DM dm) 2634c661befSBarry Smith { 2644c661befSBarry Smith PetscErrorCode ierr; 2654c661befSBarry Smith 2664c661befSBarry Smith PetscFunctionBegin; 2674c661befSBarry Smith if (!dm) PetscFunctionReturn(0); 2684c661befSBarry Smith ierr = PetscObjectCompose((PetscObject)dm,"VI",(PetscObject)PETSC_NULL);CHKERRQ(ierr); 2694c661befSBarry Smith PetscFunctionReturn(0); 2704c661befSBarry Smith } 2714c661befSBarry Smith 2723c0c59f3SBarry Smith /* --------------------------------------------------------------------------------------------------------*/ 2732b4ed282SShri Abhyankar 2749308c137SBarry Smith #undef __FUNCT__ 2759308c137SBarry Smith #define __FUNCT__ "SNESMonitorVI" 2767087cfbeSBarry Smith PetscErrorCode SNESMonitorVI(SNES snes,PetscInt its,PetscReal fgnorm,void *dummy) 2779308c137SBarry Smith { 2789308c137SBarry Smith PetscErrorCode ierr; 2799308c137SBarry Smith SNES_VI *vi = (SNES_VI*)snes->data; 2809308c137SBarry Smith PetscViewerASCIIMonitor viewer = (PetscViewerASCIIMonitor) dummy; 2819308c137SBarry Smith const PetscScalar *x,*xl,*xu,*f; 28209573ac7SBarry Smith PetscInt i,n,act = 0; 2839308c137SBarry Smith PetscReal rnorm,fnorm; 2849308c137SBarry Smith 2859308c137SBarry Smith PetscFunctionBegin; 2869308c137SBarry Smith if (!dummy) { 2879308c137SBarry Smith ierr = PetscViewerASCIIMonitorCreate(((PetscObject)snes)->comm,"stdout",0,&viewer);CHKERRQ(ierr); 2889308c137SBarry Smith } 2899308c137SBarry Smith ierr = VecGetLocalSize(snes->vec_sol,&n);CHKERRQ(ierr); 2909308c137SBarry Smith ierr = VecGetArrayRead(vi->xl,&xl);CHKERRQ(ierr); 2919308c137SBarry Smith ierr = VecGetArrayRead(vi->xu,&xu);CHKERRQ(ierr); 2929308c137SBarry Smith ierr = VecGetArrayRead(snes->vec_sol,&x);CHKERRQ(ierr); 2933f731af5SBarry Smith ierr = VecGetArrayRead(snes->vec_func,&f);CHKERRQ(ierr); 2949308c137SBarry Smith 2959308c137SBarry Smith rnorm = 0.0; 2969308c137SBarry Smith for (i=0; i<n; i++) { 29710f5ae6bSBarry 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]); 29809573ac7SBarry Smith else act++; 2999308c137SBarry Smith } 3003f731af5SBarry Smith ierr = VecRestoreArrayRead(snes->vec_func,&f);CHKERRQ(ierr); 3019308c137SBarry Smith ierr = VecRestoreArrayRead(vi->xl,&xl);CHKERRQ(ierr); 3029308c137SBarry Smith ierr = VecRestoreArrayRead(vi->xu,&xu);CHKERRQ(ierr); 3039308c137SBarry Smith ierr = VecRestoreArrayRead(snes->vec_sol,&x);CHKERRQ(ierr); 304d9822059SBarry Smith ierr = MPI_Allreduce(&rnorm,&fnorm,1,MPIU_REAL,MPIU_SUM,((PetscObject)snes)->comm);CHKERRQ(ierr); 3059308c137SBarry Smith fnorm = sqrt(fnorm); 30609573ac7SBarry Smith ierr = PetscViewerASCIIMonitorPrintf(viewer,"%3D SNES VI Function norm %14.12e Active constraints %D\n",its,fnorm,act);CHKERRQ(ierr); 3079308c137SBarry Smith if (!dummy) { 3086bf464f9SBarry Smith ierr = PetscViewerASCIIMonitorDestroy(&viewer);CHKERRQ(ierr); 3099308c137SBarry Smith } 3109308c137SBarry Smith PetscFunctionReturn(0); 3119308c137SBarry Smith } 3129308c137SBarry Smith 3132b4ed282SShri Abhyankar /* 3142b4ed282SShri Abhyankar Checks if J^T F = 0 which implies we've found a local minimum of the norm of the function, 3152b4ed282SShri 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 3162b4ed282SShri Abhyankar 0 = (J^T F)^T W = F^T J W iff W not in the null space of J. Thanks for Jorge More 3172b4ed282SShri Abhyankar for this trick. One assumes that the probability that W is in the null space of J is very, very small. 3182b4ed282SShri Abhyankar */ 3192b4ed282SShri Abhyankar #undef __FUNCT__ 3202b4ed282SShri Abhyankar #define __FUNCT__ "SNESVICheckLocalMin_Private" 321ace3abfcSBarry Smith PetscErrorCode SNESVICheckLocalMin_Private(SNES snes,Mat A,Vec F,Vec W,PetscReal fnorm,PetscBool *ismin) 3222b4ed282SShri Abhyankar { 3232b4ed282SShri Abhyankar PetscReal a1; 3242b4ed282SShri Abhyankar PetscErrorCode ierr; 325ace3abfcSBarry Smith PetscBool hastranspose; 3262b4ed282SShri Abhyankar 3272b4ed282SShri Abhyankar PetscFunctionBegin; 3282b4ed282SShri Abhyankar *ismin = PETSC_FALSE; 3292b4ed282SShri Abhyankar ierr = MatHasOperation(A,MATOP_MULT_TRANSPOSE,&hastranspose);CHKERRQ(ierr); 3302b4ed282SShri Abhyankar if (hastranspose) { 3312b4ed282SShri Abhyankar /* Compute || J^T F|| */ 3322b4ed282SShri Abhyankar ierr = MatMultTranspose(A,F,W);CHKERRQ(ierr); 3332b4ed282SShri Abhyankar ierr = VecNorm(W,NORM_2,&a1);CHKERRQ(ierr); 3342b4ed282SShri Abhyankar ierr = PetscInfo1(snes,"|| J^T F|| %G near zero implies found a local minimum\n",a1/fnorm);CHKERRQ(ierr); 3352b4ed282SShri Abhyankar if (a1/fnorm < 1.e-4) *ismin = PETSC_TRUE; 3362b4ed282SShri Abhyankar } else { 3372b4ed282SShri Abhyankar Vec work; 3382b4ed282SShri Abhyankar PetscScalar result; 3392b4ed282SShri Abhyankar PetscReal wnorm; 3402b4ed282SShri Abhyankar 3412b4ed282SShri Abhyankar ierr = VecSetRandom(W,PETSC_NULL);CHKERRQ(ierr); 3422b4ed282SShri Abhyankar ierr = VecNorm(W,NORM_2,&wnorm);CHKERRQ(ierr); 3432b4ed282SShri Abhyankar ierr = VecDuplicate(W,&work);CHKERRQ(ierr); 3442b4ed282SShri Abhyankar ierr = MatMult(A,W,work);CHKERRQ(ierr); 3452b4ed282SShri Abhyankar ierr = VecDot(F,work,&result);CHKERRQ(ierr); 3466bf464f9SBarry Smith ierr = VecDestroy(&work);CHKERRQ(ierr); 3472b4ed282SShri Abhyankar a1 = PetscAbsScalar(result)/(fnorm*wnorm); 3482b4ed282SShri Abhyankar ierr = PetscInfo1(snes,"(F^T J random)/(|| F ||*||random|| %G near zero implies found a local minimum\n",a1);CHKERRQ(ierr); 3492b4ed282SShri Abhyankar if (a1 < 1.e-4) *ismin = PETSC_TRUE; 3502b4ed282SShri Abhyankar } 3512b4ed282SShri Abhyankar PetscFunctionReturn(0); 3522b4ed282SShri Abhyankar } 3532b4ed282SShri Abhyankar 3542b4ed282SShri Abhyankar /* 3552b4ed282SShri Abhyankar Checks if J^T(F - J*X) = 0 3562b4ed282SShri Abhyankar */ 3572b4ed282SShri Abhyankar #undef __FUNCT__ 3582b4ed282SShri Abhyankar #define __FUNCT__ "SNESVICheckResidual_Private" 3592b4ed282SShri Abhyankar PetscErrorCode SNESVICheckResidual_Private(SNES snes,Mat A,Vec F,Vec X,Vec W1,Vec W2) 3602b4ed282SShri Abhyankar { 3612b4ed282SShri Abhyankar PetscReal a1,a2; 3622b4ed282SShri Abhyankar PetscErrorCode ierr; 363ace3abfcSBarry Smith PetscBool hastranspose; 3642b4ed282SShri Abhyankar 3652b4ed282SShri Abhyankar PetscFunctionBegin; 3662b4ed282SShri Abhyankar ierr = MatHasOperation(A,MATOP_MULT_TRANSPOSE,&hastranspose);CHKERRQ(ierr); 3672b4ed282SShri Abhyankar if (hastranspose) { 3682b4ed282SShri Abhyankar ierr = MatMult(A,X,W1);CHKERRQ(ierr); 3692b4ed282SShri Abhyankar ierr = VecAXPY(W1,-1.0,F);CHKERRQ(ierr); 3702b4ed282SShri Abhyankar 3712b4ed282SShri Abhyankar /* Compute || J^T W|| */ 3722b4ed282SShri Abhyankar ierr = MatMultTranspose(A,W1,W2);CHKERRQ(ierr); 3732b4ed282SShri Abhyankar ierr = VecNorm(W1,NORM_2,&a1);CHKERRQ(ierr); 3742b4ed282SShri Abhyankar ierr = VecNorm(W2,NORM_2,&a2);CHKERRQ(ierr); 3752b4ed282SShri Abhyankar if (a1 != 0.0) { 3762b4ed282SShri Abhyankar ierr = PetscInfo1(snes,"||J^T(F-Ax)||/||F-AX|| %G near zero implies inconsistent rhs\n",a2/a1);CHKERRQ(ierr); 3772b4ed282SShri Abhyankar } 3782b4ed282SShri Abhyankar } 3792b4ed282SShri Abhyankar PetscFunctionReturn(0); 3802b4ed282SShri Abhyankar } 3812b4ed282SShri Abhyankar 3822b4ed282SShri Abhyankar /* 3832b4ed282SShri Abhyankar SNESDefaultConverged_VI - Checks the convergence of the semismooth newton algorithm. 3842b4ed282SShri Abhyankar 3852b4ed282SShri Abhyankar Notes: 3862b4ed282SShri Abhyankar The convergence criterion currently implemented is 3872b4ed282SShri Abhyankar merit < abstol 3882b4ed282SShri Abhyankar merit < rtol*merit_initial 3892b4ed282SShri Abhyankar */ 3902b4ed282SShri Abhyankar #undef __FUNCT__ 3912b4ed282SShri Abhyankar #define __FUNCT__ "SNESDefaultConverged_VI" 3927fe79bc4SShri Abhyankar PetscErrorCode SNESDefaultConverged_VI(SNES snes,PetscInt it,PetscReal xnorm,PetscReal gradnorm,PetscReal fnorm,SNESConvergedReason *reason,void *dummy) 3932b4ed282SShri Abhyankar { 3942b4ed282SShri Abhyankar PetscErrorCode ierr; 3952b4ed282SShri Abhyankar 3962b4ed282SShri Abhyankar PetscFunctionBegin; 3972b4ed282SShri Abhyankar PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 3982b4ed282SShri Abhyankar PetscValidPointer(reason,6); 3992b4ed282SShri Abhyankar 4002b4ed282SShri Abhyankar *reason = SNES_CONVERGED_ITERATING; 4012b4ed282SShri Abhyankar 4022b4ed282SShri Abhyankar if (!it) { 4032b4ed282SShri Abhyankar /* set parameter for default relative tolerance convergence test */ 4047fe79bc4SShri Abhyankar snes->ttol = fnorm*snes->rtol; 4052b4ed282SShri Abhyankar } 4067fe79bc4SShri Abhyankar if (fnorm != fnorm) { 4072b4ed282SShri Abhyankar ierr = PetscInfo(snes,"Failed to converged, function norm is NaN\n");CHKERRQ(ierr); 4082b4ed282SShri Abhyankar *reason = SNES_DIVERGED_FNORM_NAN; 4097fe79bc4SShri Abhyankar } else if (fnorm < snes->abstol) { 4107fe79bc4SShri Abhyankar ierr = PetscInfo2(snes,"Converged due to function norm %G < %G\n",fnorm,snes->abstol);CHKERRQ(ierr); 4112b4ed282SShri Abhyankar *reason = SNES_CONVERGED_FNORM_ABS; 4122b4ed282SShri Abhyankar } else if (snes->nfuncs >= snes->max_funcs) { 4132b4ed282SShri Abhyankar ierr = PetscInfo2(snes,"Exceeded maximum number of function evaluations: %D > %D\n",snes->nfuncs,snes->max_funcs);CHKERRQ(ierr); 4142b4ed282SShri Abhyankar *reason = SNES_DIVERGED_FUNCTION_COUNT; 4152b4ed282SShri Abhyankar } 4162b4ed282SShri Abhyankar 4172b4ed282SShri Abhyankar if (it && !*reason) { 4187fe79bc4SShri Abhyankar if (fnorm < snes->ttol) { 4197fe79bc4SShri Abhyankar ierr = PetscInfo2(snes,"Converged due to function norm %G < %G (relative tolerance)\n",fnorm,snes->ttol);CHKERRQ(ierr); 4202b4ed282SShri Abhyankar *reason = SNES_CONVERGED_FNORM_RELATIVE; 4212b4ed282SShri Abhyankar } 4222b4ed282SShri Abhyankar } 4232b4ed282SShri Abhyankar PetscFunctionReturn(0); 4242b4ed282SShri Abhyankar } 4252b4ed282SShri Abhyankar 4262b4ed282SShri Abhyankar /* 4272b4ed282SShri Abhyankar SNESVIComputeMeritFunction - Evaluates the merit function for the mixed complementarity problem. 4282b4ed282SShri Abhyankar 4292b4ed282SShri Abhyankar Input Parameter: 4302b4ed282SShri Abhyankar . phi - the semismooth function 4312b4ed282SShri Abhyankar 4322b4ed282SShri Abhyankar Output Parameter: 4332b4ed282SShri Abhyankar . merit - the merit function 4342b4ed282SShri Abhyankar . phinorm - ||phi|| 4352b4ed282SShri Abhyankar 4362b4ed282SShri Abhyankar Notes: 4372b4ed282SShri Abhyankar The merit function for the mixed complementarity problem is defined as 4382b4ed282SShri Abhyankar merit = 0.5*phi^T*phi 4392b4ed282SShri Abhyankar */ 4402b4ed282SShri Abhyankar #undef __FUNCT__ 4412b4ed282SShri Abhyankar #define __FUNCT__ "SNESVIComputeMeritFunction" 4422b4ed282SShri Abhyankar static PetscErrorCode SNESVIComputeMeritFunction(Vec phi, PetscReal* merit,PetscReal* phinorm) 4432b4ed282SShri Abhyankar { 4442b4ed282SShri Abhyankar PetscErrorCode ierr; 4452b4ed282SShri Abhyankar 4462b4ed282SShri Abhyankar PetscFunctionBegin; 4475f48b12bSBarry Smith ierr = VecNormBegin(phi,NORM_2,phinorm);CHKERRQ(ierr); 4485f48b12bSBarry Smith ierr = VecNormEnd(phi,NORM_2,phinorm);CHKERRQ(ierr); 4492b4ed282SShri Abhyankar 4502b4ed282SShri Abhyankar *merit = 0.5*(*phinorm)*(*phinorm); 4512b4ed282SShri Abhyankar PetscFunctionReturn(0); 4522b4ed282SShri Abhyankar } 4532b4ed282SShri Abhyankar 4547f6f51e9SSatish Balay PETSC_STATIC_INLINE PetscScalar Phi(PetscScalar a,PetscScalar b) 4554c21c6cdSBarry Smith { 4564c21c6cdSBarry Smith return a + b - sqrt(a*a + b*b); 4574c21c6cdSBarry Smith } 4584c21c6cdSBarry Smith 4597f6f51e9SSatish Balay PETSC_STATIC_INLINE PetscScalar DPhi(PetscScalar a,PetscScalar b) 4604c21c6cdSBarry Smith { 4615559b345SBarry Smith if ((PetscAbsScalar(a) >= 1.e-6) || (PetscAbsScalar(b) >= 1.e-6)) return 1.0 - a/ sqrt(a*a + b*b); 4625559b345SBarry Smith else return .5; 4634c21c6cdSBarry Smith } 4644c21c6cdSBarry Smith 4652b4ed282SShri Abhyankar /* 4661f79c099SShri Abhyankar SNESVIComputeFunction - Reformulates a system of nonlinear equations in mixed complementarity form to a system of nonlinear equations in semismooth form. 4672b4ed282SShri Abhyankar 4682b4ed282SShri Abhyankar Input Parameters: 4692b4ed282SShri Abhyankar . snes - the SNES context 4702b4ed282SShri Abhyankar . x - current iterate 4712b4ed282SShri Abhyankar . functx - user defined function context 4722b4ed282SShri Abhyankar 4732b4ed282SShri Abhyankar Output Parameters: 4742b4ed282SShri Abhyankar . phi - Semismooth function 4752b4ed282SShri Abhyankar 4762b4ed282SShri Abhyankar */ 4772b4ed282SShri Abhyankar #undef __FUNCT__ 4781f79c099SShri Abhyankar #define __FUNCT__ "SNESVIComputeFunction" 4791f79c099SShri Abhyankar static PetscErrorCode SNESVIComputeFunction(SNES snes,Vec X,Vec phi,void* functx) 4802b4ed282SShri Abhyankar { 4812b4ed282SShri Abhyankar PetscErrorCode ierr; 4822b4ed282SShri Abhyankar SNES_VI *vi = (SNES_VI*)snes->data; 4832b4ed282SShri Abhyankar Vec Xl = vi->xl,Xu = vi->xu,F = snes->vec_func; 4844c21c6cdSBarry Smith PetscScalar *phi_arr,*x_arr,*f_arr,*l,*u; 4852b4ed282SShri Abhyankar PetscInt i,nlocal; 4862b4ed282SShri Abhyankar 4872b4ed282SShri Abhyankar PetscFunctionBegin; 4882b4ed282SShri Abhyankar ierr = (*vi->computeuserfunction)(snes,X,F,functx);CHKERRQ(ierr); 4892b4ed282SShri Abhyankar ierr = VecGetLocalSize(X,&nlocal);CHKERRQ(ierr); 4902b4ed282SShri Abhyankar ierr = VecGetArray(X,&x_arr);CHKERRQ(ierr); 4912b4ed282SShri Abhyankar ierr = VecGetArray(F,&f_arr);CHKERRQ(ierr); 4922b4ed282SShri Abhyankar ierr = VecGetArray(Xl,&l);CHKERRQ(ierr); 4932b4ed282SShri Abhyankar ierr = VecGetArray(Xu,&u);CHKERRQ(ierr); 4942b4ed282SShri Abhyankar ierr = VecGetArray(phi,&phi_arr);CHKERRQ(ierr); 4952b4ed282SShri Abhyankar 4962b4ed282SShri Abhyankar for (i=0;i < nlocal;i++) { 49710f5ae6bSBarry Smith if ((PetscRealPart(l[i]) <= SNES_VI_NINF) && (PetscRealPart(u[i]) >= SNES_VI_INF)) { /* no constraints on variable */ 4984c21c6cdSBarry Smith phi_arr[i] = f_arr[i]; 49910f5ae6bSBarry Smith } else if (PetscRealPart(l[i]) <= SNES_VI_NINF) { /* upper bound on variable only */ 5004c21c6cdSBarry Smith phi_arr[i] = -Phi(u[i] - x_arr[i],-f_arr[i]); 50110f5ae6bSBarry Smith } else if (PetscRealPart(u[i]) >= SNES_VI_INF) { /* lower bound on variable only */ 5024c21c6cdSBarry Smith phi_arr[i] = Phi(x_arr[i] - l[i],f_arr[i]); 5035559b345SBarry Smith } else if (l[i] == u[i]) { 5042b4ed282SShri Abhyankar phi_arr[i] = l[i] - x_arr[i]; 5055559b345SBarry Smith } else { /* both bounds on variable */ 5064c21c6cdSBarry Smith phi_arr[i] = Phi(x_arr[i] - l[i],-Phi(u[i] - x_arr[i],-f_arr[i])); 5072b4ed282SShri Abhyankar } 5082b4ed282SShri Abhyankar } 5092b4ed282SShri Abhyankar 5102b4ed282SShri Abhyankar ierr = VecRestoreArray(X,&x_arr);CHKERRQ(ierr); 5112b4ed282SShri Abhyankar ierr = VecRestoreArray(F,&f_arr);CHKERRQ(ierr); 5122b4ed282SShri Abhyankar ierr = VecRestoreArray(Xl,&l);CHKERRQ(ierr); 5132b4ed282SShri Abhyankar ierr = VecRestoreArray(Xu,&u);CHKERRQ(ierr); 5142b4ed282SShri Abhyankar ierr = VecRestoreArray(phi,&phi_arr);CHKERRQ(ierr); 5152b4ed282SShri Abhyankar PetscFunctionReturn(0); 5162b4ed282SShri Abhyankar } 5172b4ed282SShri Abhyankar 5182b4ed282SShri Abhyankar /* 519a79edbefSShri Abhyankar SNESVIComputeBsubdifferentialVectors - Computes the diagonal shift (Da) and row scaling (Db) vectors needed for the 520a79edbefSShri Abhyankar the semismooth jacobian. 5212b4ed282SShri Abhyankar */ 5222b4ed282SShri Abhyankar #undef __FUNCT__ 523a79edbefSShri Abhyankar #define __FUNCT__ "SNESVIComputeBsubdifferentialVectors" 524a79edbefSShri Abhyankar PetscErrorCode SNESVIComputeBsubdifferentialVectors(SNES snes,Vec X,Vec F,Mat jac,Vec Da,Vec Db) 5252b4ed282SShri Abhyankar { 5262b4ed282SShri Abhyankar PetscErrorCode ierr; 5272b4ed282SShri Abhyankar SNES_VI *vi = (SNES_VI*)snes->data; 5284c21c6cdSBarry Smith PetscScalar *l,*u,*x,*f,*da,*db,da1,da2,db1,db2; 5292b4ed282SShri Abhyankar PetscInt i,nlocal; 5302b4ed282SShri Abhyankar 5312b4ed282SShri Abhyankar PetscFunctionBegin; 5322b4ed282SShri Abhyankar 5332b4ed282SShri Abhyankar ierr = VecGetArray(X,&x);CHKERRQ(ierr); 5342b4ed282SShri Abhyankar ierr = VecGetArray(F,&f);CHKERRQ(ierr); 5352b4ed282SShri Abhyankar ierr = VecGetArray(vi->xl,&l);CHKERRQ(ierr); 5362b4ed282SShri Abhyankar ierr = VecGetArray(vi->xu,&u);CHKERRQ(ierr); 537a79edbefSShri Abhyankar ierr = VecGetArray(Da,&da);CHKERRQ(ierr); 538a79edbefSShri Abhyankar ierr = VecGetArray(Db,&db);CHKERRQ(ierr); 5392b4ed282SShri Abhyankar ierr = VecGetLocalSize(X,&nlocal);CHKERRQ(ierr); 5404c21c6cdSBarry Smith 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 da[i] = 0; 5442b4ed282SShri Abhyankar db[i] = 1; 54510f5ae6bSBarry Smith } else if (PetscRealPart(l[i]) <= SNES_VI_NINF) { /* upper bound on variable only */ 5464c21c6cdSBarry Smith da[i] = DPhi(u[i] - x[i], -f[i]); 5474c21c6cdSBarry Smith db[i] = DPhi(-f[i],u[i] - x[i]); 54810f5ae6bSBarry Smith } else if (PetscRealPart(u[i]) >= SNES_VI_INF) { /* lower bound on variable only */ 5495559b345SBarry Smith da[i] = DPhi(x[i] - l[i], f[i]); 5505559b345SBarry Smith db[i] = DPhi(f[i],x[i] - l[i]); 5515559b345SBarry Smith } else if (l[i] == u[i]) { /* fixed variable */ 5524c21c6cdSBarry Smith da[i] = 1; 5532b4ed282SShri Abhyankar db[i] = 0; 5545559b345SBarry Smith } else { /* upper and lower bounds on variable */ 5554c21c6cdSBarry Smith da1 = DPhi(x[i] - l[i], -Phi(u[i] - x[i], -f[i])); 5564c21c6cdSBarry Smith db1 = DPhi(-Phi(u[i] - x[i], -f[i]),x[i] - l[i]); 5574c21c6cdSBarry Smith da2 = DPhi(u[i] - x[i], -f[i]); 5584c21c6cdSBarry Smith db2 = DPhi(-f[i],u[i] - x[i]); 5594c21c6cdSBarry Smith da[i] = da1 + db1*da2; 5604c21c6cdSBarry Smith db[i] = db1*db2; 5612b4ed282SShri Abhyankar } 5622b4ed282SShri Abhyankar } 5635559b345SBarry Smith 5642b4ed282SShri Abhyankar ierr = VecRestoreArray(X,&x);CHKERRQ(ierr); 5652b4ed282SShri Abhyankar ierr = VecRestoreArray(F,&f);CHKERRQ(ierr); 5662b4ed282SShri Abhyankar ierr = VecRestoreArray(vi->xl,&l);CHKERRQ(ierr); 5672b4ed282SShri Abhyankar ierr = VecRestoreArray(vi->xu,&u);CHKERRQ(ierr); 568a79edbefSShri Abhyankar ierr = VecRestoreArray(Da,&da);CHKERRQ(ierr); 569a79edbefSShri Abhyankar ierr = VecRestoreArray(Db,&db);CHKERRQ(ierr); 570a79edbefSShri Abhyankar PetscFunctionReturn(0); 571a79edbefSShri Abhyankar } 572a79edbefSShri Abhyankar 573a79edbefSShri Abhyankar /* 574a79edbefSShri 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. 575a79edbefSShri Abhyankar 576a79edbefSShri Abhyankar Input Parameters: 577a79edbefSShri Abhyankar . Da - Diagonal shift vector for the semismooth jacobian. 578a79edbefSShri Abhyankar . Db - Row scaling vector for the semismooth jacobian. 579a79edbefSShri Abhyankar 580a79edbefSShri Abhyankar Output Parameters: 581a79edbefSShri Abhyankar . jac - semismooth jacobian 582a79edbefSShri Abhyankar . jac_pre - optional preconditioning matrix 583a79edbefSShri Abhyankar 584a79edbefSShri Abhyankar Notes: 585a79edbefSShri Abhyankar The semismooth jacobian matrix is given by 586a79edbefSShri Abhyankar jac = Da + Db*jacfun 587a79edbefSShri Abhyankar where Db is the row scaling matrix stored as a vector, 588a79edbefSShri Abhyankar Da is the diagonal perturbation matrix stored as a vector 589a79edbefSShri Abhyankar and jacfun is the jacobian of the original nonlinear function. 590a79edbefSShri Abhyankar */ 591a79edbefSShri Abhyankar #undef __FUNCT__ 592a79edbefSShri Abhyankar #define __FUNCT__ "SNESVIComputeJacobian" 593a79edbefSShri Abhyankar PetscErrorCode SNESVIComputeJacobian(Mat jac, Mat jac_pre,Vec Da, Vec Db) 594a79edbefSShri Abhyankar { 595a79edbefSShri Abhyankar PetscErrorCode ierr; 596a79edbefSShri Abhyankar 5972b4ed282SShri Abhyankar /* Do row scaling and add diagonal perturbation */ 598a79edbefSShri Abhyankar ierr = MatDiagonalScale(jac,Db,PETSC_NULL);CHKERRQ(ierr); 599a79edbefSShri Abhyankar ierr = MatDiagonalSet(jac,Da,ADD_VALUES);CHKERRQ(ierr); 600a79edbefSShri Abhyankar if (jac != jac_pre) { /* If jac and jac_pre are different */ 601a79edbefSShri Abhyankar ierr = MatDiagonalScale(jac_pre,Db,PETSC_NULL); 602a79edbefSShri Abhyankar ierr = MatDiagonalSet(jac_pre,Da,ADD_VALUES);CHKERRQ(ierr); 6032b4ed282SShri Abhyankar } 6042b4ed282SShri Abhyankar PetscFunctionReturn(0); 6052b4ed282SShri Abhyankar } 6062b4ed282SShri Abhyankar 6072b4ed282SShri Abhyankar /* 608ee657d29SShri Abhyankar SNESVIComputeMeritFunctionGradient - Computes the gradient of the merit function psi. 609ee657d29SShri Abhyankar 610ee657d29SShri Abhyankar Input Parameters: 611ee657d29SShri Abhyankar phi - semismooth function. 612ee657d29SShri Abhyankar H - semismooth jacobian 613ee657d29SShri Abhyankar 614ee657d29SShri Abhyankar Output Parameters: 615ee657d29SShri Abhyankar dpsi - merit function gradient 616ee657d29SShri Abhyankar 617ee657d29SShri Abhyankar Notes: 618ee657d29SShri Abhyankar The merit function gradient is computed as follows 619ee657d29SShri Abhyankar dpsi = H^T*phi 620ee657d29SShri Abhyankar */ 621ee657d29SShri Abhyankar #undef __FUNCT__ 622ee657d29SShri Abhyankar #define __FUNCT__ "SNESVIComputeMeritFunctionGradient" 623ee657d29SShri Abhyankar PetscErrorCode SNESVIComputeMeritFunctionGradient(Mat H, Vec phi, Vec dpsi) 624ee657d29SShri Abhyankar { 625ee657d29SShri Abhyankar PetscErrorCode ierr; 626ee657d29SShri Abhyankar 627ee657d29SShri Abhyankar PetscFunctionBegin; 6285f48b12bSBarry Smith ierr = MatMultTranspose(H,phi,dpsi);CHKERRQ(ierr); 629ee657d29SShri Abhyankar PetscFunctionReturn(0); 630ee657d29SShri Abhyankar } 631ee657d29SShri Abhyankar 632c1a5e521SShri Abhyankar /* -------------------------------------------------------------------------- */ 633c1a5e521SShri Abhyankar /* 634c1a5e521SShri Abhyankar SNESVIProjectOntoBounds - Projects X onto the feasible region so that Xl[i] <= X[i] <= Xu[i] for i = 1...n. 635c1a5e521SShri Abhyankar 636c1a5e521SShri Abhyankar Input Parameters: 637c1a5e521SShri Abhyankar . SNES - nonlinear solver context 638c1a5e521SShri Abhyankar 639c1a5e521SShri Abhyankar Output Parameters: 640c1a5e521SShri Abhyankar . X - Bound projected X 641c1a5e521SShri Abhyankar 642c1a5e521SShri Abhyankar */ 643c1a5e521SShri Abhyankar 644c1a5e521SShri Abhyankar #undef __FUNCT__ 645c1a5e521SShri Abhyankar #define __FUNCT__ "SNESVIProjectOntoBounds" 646c1a5e521SShri Abhyankar PetscErrorCode SNESVIProjectOntoBounds(SNES snes,Vec X) 647c1a5e521SShri Abhyankar { 648c1a5e521SShri Abhyankar PetscErrorCode ierr; 649c1a5e521SShri Abhyankar SNES_VI *vi = (SNES_VI*)snes->data; 650c1a5e521SShri Abhyankar const PetscScalar *xl,*xu; 651c1a5e521SShri Abhyankar PetscScalar *x; 652c1a5e521SShri Abhyankar PetscInt i,n; 653c1a5e521SShri Abhyankar 654c1a5e521SShri Abhyankar PetscFunctionBegin; 655c1a5e521SShri Abhyankar ierr = VecGetLocalSize(X,&n);CHKERRQ(ierr); 656c1a5e521SShri Abhyankar ierr = VecGetArray(X,&x);CHKERRQ(ierr); 657c1a5e521SShri Abhyankar ierr = VecGetArrayRead(vi->xl,&xl);CHKERRQ(ierr); 658c1a5e521SShri Abhyankar ierr = VecGetArrayRead(vi->xu,&xu);CHKERRQ(ierr); 659c1a5e521SShri Abhyankar 660c1a5e521SShri Abhyankar for(i = 0;i<n;i++) { 66110f5ae6bSBarry Smith if (PetscRealPart(x[i]) < PetscRealPart(xl[i])) x[i] = xl[i]; 66210f5ae6bSBarry Smith else if (PetscRealPart(x[i]) > PetscRealPart(xu[i])) x[i] = xu[i]; 663c1a5e521SShri Abhyankar } 664c1a5e521SShri Abhyankar ierr = VecRestoreArray(X,&x);CHKERRQ(ierr); 665c1a5e521SShri Abhyankar ierr = VecRestoreArrayRead(vi->xl,&xl);CHKERRQ(ierr); 666c1a5e521SShri Abhyankar ierr = VecRestoreArrayRead(vi->xu,&xu);CHKERRQ(ierr); 667c1a5e521SShri Abhyankar PetscFunctionReturn(0); 668c1a5e521SShri Abhyankar } 669c1a5e521SShri Abhyankar 6702b4ed282SShri Abhyankar /* -------------------------------------------------------------------- 6712b4ed282SShri Abhyankar 6722b4ed282SShri Abhyankar This file implements a semismooth truncated Newton method with a line search, 6732b4ed282SShri Abhyankar for solving a system of nonlinear equations in complementarity form, using the KSP, Vec, 6742b4ed282SShri Abhyankar and Mat interfaces for linear solvers, vectors, and matrices, 6752b4ed282SShri Abhyankar respectively. 6762b4ed282SShri Abhyankar 6772b4ed282SShri Abhyankar The following basic routines are required for each nonlinear solver: 6782b4ed282SShri Abhyankar SNESCreate_XXX() - Creates a nonlinear solver context 6792b4ed282SShri Abhyankar SNESSetFromOptions_XXX() - Sets runtime options 6802b4ed282SShri Abhyankar SNESSolve_XXX() - Solves the nonlinear system 6812b4ed282SShri Abhyankar SNESDestroy_XXX() - Destroys the nonlinear solver context 6822b4ed282SShri Abhyankar The suffix "_XXX" denotes a particular implementation, in this case 6832b4ed282SShri Abhyankar we use _VI (e.g., SNESCreate_VI, SNESSolve_VI) for solving 6842b4ed282SShri Abhyankar systems of nonlinear equations with a line search (LS) method. 6852b4ed282SShri Abhyankar These routines are actually called via the common user interface 6862b4ed282SShri Abhyankar routines SNESCreate(), SNESSetFromOptions(), SNESSolve(), and 6872b4ed282SShri Abhyankar SNESDestroy(), so the application code interface remains identical 6882b4ed282SShri Abhyankar for all nonlinear solvers. 6892b4ed282SShri Abhyankar 6902b4ed282SShri Abhyankar Another key routine is: 6912b4ed282SShri Abhyankar SNESSetUp_XXX() - Prepares for the use of a nonlinear solver 6922b4ed282SShri Abhyankar by setting data structures and options. The interface routine SNESSetUp() 6932b4ed282SShri Abhyankar is not usually called directly by the user, but instead is called by 6942b4ed282SShri Abhyankar SNESSolve() if necessary. 6952b4ed282SShri Abhyankar 6962b4ed282SShri Abhyankar Additional basic routines are: 6972b4ed282SShri Abhyankar SNESView_XXX() - Prints details of runtime options that 6982b4ed282SShri Abhyankar have actually been used. 6992b4ed282SShri Abhyankar These are called by application codes via the interface routines 7002b4ed282SShri Abhyankar SNESView(). 7012b4ed282SShri Abhyankar 7022b4ed282SShri Abhyankar The various types of solvers (preconditioners, Krylov subspace methods, 7032b4ed282SShri Abhyankar nonlinear solvers, timesteppers) are all organized similarly, so the 7042b4ed282SShri Abhyankar above description applies to these categories also. 7052b4ed282SShri Abhyankar 7062b4ed282SShri Abhyankar -------------------------------------------------------------------- */ 7072b4ed282SShri Abhyankar /* 70869c03620SShri Abhyankar SNESSolveVI_SS - Solves the complementarity problem with a semismooth Newton 7092b4ed282SShri Abhyankar method using a line search. 7102b4ed282SShri Abhyankar 7112b4ed282SShri Abhyankar Input Parameters: 7122b4ed282SShri Abhyankar . snes - the SNES context 7132b4ed282SShri Abhyankar 7142b4ed282SShri Abhyankar Output Parameter: 7152b4ed282SShri Abhyankar . outits - number of iterations until termination 7162b4ed282SShri Abhyankar 7172b4ed282SShri Abhyankar Application Interface Routine: SNESSolve() 7182b4ed282SShri Abhyankar 7192b4ed282SShri Abhyankar Notes: 7202b4ed282SShri Abhyankar This implements essentially a semismooth Newton method with a 72151defd01SShri Abhyankar line search. The default line search does not do any line seach 72251defd01SShri Abhyankar but rather takes a full newton step. 7232b4ed282SShri Abhyankar */ 7242b4ed282SShri Abhyankar #undef __FUNCT__ 72569c03620SShri Abhyankar #define __FUNCT__ "SNESSolveVI_SS" 72669c03620SShri Abhyankar PetscErrorCode SNESSolveVI_SS(SNES snes) 7272b4ed282SShri Abhyankar { 7282b4ed282SShri Abhyankar SNES_VI *vi = (SNES_VI*)snes->data; 7292b4ed282SShri Abhyankar PetscErrorCode ierr; 7302b4ed282SShri Abhyankar PetscInt maxits,i,lits; 7313b336b49SShri Abhyankar PetscBool lssucceed; 7322b4ed282SShri Abhyankar MatStructure flg = DIFFERENT_NONZERO_PATTERN; 7332b4ed282SShri Abhyankar PetscReal gnorm,xnorm=0,ynorm; 7342b4ed282SShri Abhyankar Vec Y,X,F,G,W; 7352b4ed282SShri Abhyankar KSPConvergedReason kspreason; 7362b4ed282SShri Abhyankar 7372b4ed282SShri Abhyankar PetscFunctionBegin; 7389ce7406fSBarry Smith vi->computeuserfunction = snes->ops->computefunction; 7399ce7406fSBarry Smith snes->ops->computefunction = SNESVIComputeFunction; 7409ce7406fSBarry Smith 7412b4ed282SShri Abhyankar snes->numFailures = 0; 7422b4ed282SShri Abhyankar snes->numLinearSolveFailures = 0; 7432b4ed282SShri Abhyankar snes->reason = SNES_CONVERGED_ITERATING; 7442b4ed282SShri Abhyankar 7452b4ed282SShri Abhyankar maxits = snes->max_its; /* maximum number of iterations */ 7462b4ed282SShri Abhyankar X = snes->vec_sol; /* solution vector */ 7472b4ed282SShri Abhyankar F = snes->vec_func; /* residual vector */ 7482b4ed282SShri Abhyankar Y = snes->work[0]; /* work vectors */ 7492b4ed282SShri Abhyankar G = snes->work[1]; 7502b4ed282SShri Abhyankar W = snes->work[2]; 7512b4ed282SShri Abhyankar 7522b4ed282SShri Abhyankar ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 7532b4ed282SShri Abhyankar snes->iter = 0; 7542b4ed282SShri Abhyankar snes->norm = 0.0; 7552b4ed282SShri Abhyankar ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 7562b4ed282SShri Abhyankar 7577fe79bc4SShri Abhyankar ierr = SNESVIProjectOntoBounds(snes,X);CHKERRQ(ierr); 7582b4ed282SShri Abhyankar ierr = SNESComputeFunction(snes,X,vi->phi);CHKERRQ(ierr); 7592b4ed282SShri Abhyankar if (snes->domainerror) { 7602b4ed282SShri Abhyankar snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN; 7619ce7406fSBarry Smith snes->ops->computefunction = vi->computeuserfunction; 7622b4ed282SShri Abhyankar PetscFunctionReturn(0); 7632b4ed282SShri Abhyankar } 7642b4ed282SShri Abhyankar /* Compute Merit function */ 7652b4ed282SShri Abhyankar ierr = SNESVIComputeMeritFunction(vi->phi,&vi->merit,&vi->phinorm);CHKERRQ(ierr); 7662b4ed282SShri Abhyankar 7672b4ed282SShri Abhyankar ierr = VecNormBegin(X,NORM_2,&xnorm);CHKERRQ(ierr); /* xnorm <- ||x|| */ 7682b4ed282SShri Abhyankar ierr = VecNormEnd(X,NORM_2,&xnorm);CHKERRQ(ierr); 76962cbcd01SMatthew G Knepley if (PetscIsInfOrNanReal(vi->merit)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number"); 7702b4ed282SShri Abhyankar 7712b4ed282SShri Abhyankar ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 7722b4ed282SShri Abhyankar snes->norm = vi->phinorm; 7732b4ed282SShri Abhyankar ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 7742b4ed282SShri Abhyankar SNESLogConvHistory(snes,vi->phinorm,0); 7757a03ce2fSLisandro Dalcin ierr = SNESMonitor(snes,0,vi->phinorm);CHKERRQ(ierr); 7762b4ed282SShri Abhyankar 7772b4ed282SShri Abhyankar /* set parameter for default relative tolerance convergence test */ 7782b4ed282SShri Abhyankar snes->ttol = vi->phinorm*snes->rtol; 7792b4ed282SShri Abhyankar /* test convergence */ 7802b4ed282SShri Abhyankar ierr = (*snes->ops->converged)(snes,0,0.0,0.0,vi->phinorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); 7819ce7406fSBarry Smith if (snes->reason) { 7829ce7406fSBarry Smith snes->ops->computefunction = vi->computeuserfunction; 7839ce7406fSBarry Smith PetscFunctionReturn(0); 7849ce7406fSBarry Smith } 7852b4ed282SShri Abhyankar 7862b4ed282SShri Abhyankar for (i=0; i<maxits; i++) { 7872b4ed282SShri Abhyankar 7882b4ed282SShri Abhyankar /* Call general purpose update function */ 7892b4ed282SShri Abhyankar if (snes->ops->update) { 7902b4ed282SShri Abhyankar ierr = (*snes->ops->update)(snes, snes->iter);CHKERRQ(ierr); 7912b4ed282SShri Abhyankar } 7922b4ed282SShri Abhyankar 7932b4ed282SShri Abhyankar /* Solve J Y = Phi, where J is the semismooth jacobian */ 794a79edbefSShri Abhyankar /* Get the nonlinear function jacobian */ 7952b4ed282SShri Abhyankar ierr = SNESComputeJacobian(snes,X,&snes->jacobian,&snes->jacobian_pre,&flg);CHKERRQ(ierr); 796a79edbefSShri Abhyankar /* Get the diagonal shift and row scaling vectors */ 797a79edbefSShri Abhyankar ierr = SNESVIComputeBsubdifferentialVectors(snes,X,F,snes->jacobian,vi->Da,vi->Db);CHKERRQ(ierr); 798a79edbefSShri Abhyankar /* Compute the semismooth jacobian */ 799a79edbefSShri Abhyankar ierr = SNESVIComputeJacobian(snes->jacobian,snes->jacobian_pre,vi->Da,vi->Db);CHKERRQ(ierr); 800ee657d29SShri Abhyankar /* Compute the merit function gradient */ 801ee657d29SShri Abhyankar ierr = SNESVIComputeMeritFunctionGradient(snes->jacobian,vi->phi,vi->dpsi);CHKERRQ(ierr); 8022b4ed282SShri Abhyankar ierr = KSPSetOperators(snes->ksp,snes->jacobian,snes->jacobian_pre,flg);CHKERRQ(ierr); 8032b4ed282SShri Abhyankar ierr = SNES_KSPSolve(snes,snes->ksp,vi->phi,Y);CHKERRQ(ierr); 8042b4ed282SShri Abhyankar ierr = KSPGetConvergedReason(snes->ksp,&kspreason);CHKERRQ(ierr); 8053b336b49SShri Abhyankar 8063b336b49SShri Abhyankar if (kspreason < 0) { 8072b4ed282SShri Abhyankar if (++snes->numLinearSolveFailures >= snes->maxLinearSolveFailures) { 8082b4ed282SShri 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); 8092b4ed282SShri Abhyankar snes->reason = SNES_DIVERGED_LINEAR_SOLVE; 8102b4ed282SShri Abhyankar break; 8112b4ed282SShri Abhyankar } 8122b4ed282SShri Abhyankar } 8132b4ed282SShri Abhyankar ierr = KSPGetIterationNumber(snes->ksp,&lits);CHKERRQ(ierr); 8142b4ed282SShri Abhyankar snes->linear_its += lits; 8152b4ed282SShri Abhyankar ierr = PetscInfo2(snes,"iter=%D, linear solve iterations=%D\n",snes->iter,lits);CHKERRQ(ierr); 8162b4ed282SShri Abhyankar /* 8172b4ed282SShri Abhyankar if (vi->precheckstep) { 818ace3abfcSBarry Smith PetscBool changed_y = PETSC_FALSE; 8192b4ed282SShri Abhyankar ierr = (*vi->precheckstep)(snes,X,Y,vi->precheck,&changed_y);CHKERRQ(ierr); 8202b4ed282SShri Abhyankar } 8212b4ed282SShri Abhyankar 8222b4ed282SShri Abhyankar if (PetscLogPrintInfo){ 8232b4ed282SShri Abhyankar ierr = SNESVICheckResidual_Private(snes,snes->jacobian,F,Y,G,W);CHKERRQ(ierr); 8242b4ed282SShri Abhyankar } 8252b4ed282SShri Abhyankar */ 8262b4ed282SShri Abhyankar /* Compute a (scaled) negative update in the line search routine: 8272b4ed282SShri Abhyankar Y <- X - lambda*Y 8282b4ed282SShri Abhyankar and evaluate G = function(Y) (depends on the line search). 8292b4ed282SShri Abhyankar */ 8302b4ed282SShri Abhyankar ierr = VecCopy(Y,snes->vec_sol_update);CHKERRQ(ierr); 8312b4ed282SShri Abhyankar ynorm = 1; gnorm = vi->phinorm; 8322b4ed282SShri Abhyankar ierr = (*vi->LineSearch)(snes,vi->lsP,X,vi->phi,G,Y,W,vi->phinorm,xnorm,&ynorm,&gnorm,&lssucceed);CHKERRQ(ierr); 8332b4ed282SShri Abhyankar ierr = PetscInfo4(snes,"fnorm=%18.16e, gnorm=%18.16e, ynorm=%18.16e, lssucceed=%d\n",vi->phinorm,gnorm,ynorm,(int)lssucceed);CHKERRQ(ierr); 8342b4ed282SShri Abhyankar if (snes->reason == SNES_DIVERGED_FUNCTION_COUNT) break; 8352b4ed282SShri Abhyankar if (snes->domainerror) { 8362b4ed282SShri Abhyankar snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN; 8379ce7406fSBarry Smith snes->ops->computefunction = vi->computeuserfunction; 8382b4ed282SShri Abhyankar PetscFunctionReturn(0); 8392b4ed282SShri Abhyankar } 8402b4ed282SShri Abhyankar if (!lssucceed) { 8412b4ed282SShri Abhyankar if (++snes->numFailures >= snes->maxFailures) { 842ace3abfcSBarry Smith PetscBool ismin; 8432b4ed282SShri Abhyankar snes->reason = SNES_DIVERGED_LINE_SEARCH; 8442b4ed282SShri Abhyankar ierr = SNESVICheckLocalMin_Private(snes,snes->jacobian,G,W,gnorm,&ismin);CHKERRQ(ierr); 8452b4ed282SShri Abhyankar if (ismin) snes->reason = SNES_DIVERGED_LOCAL_MIN; 8462b4ed282SShri Abhyankar break; 8472b4ed282SShri Abhyankar } 8482b4ed282SShri Abhyankar } 8492b4ed282SShri Abhyankar /* Update function and solution vectors */ 8502b4ed282SShri Abhyankar vi->phinorm = gnorm; 8512b4ed282SShri Abhyankar vi->merit = 0.5*vi->phinorm*vi->phinorm; 8522b4ed282SShri Abhyankar ierr = VecCopy(G,vi->phi);CHKERRQ(ierr); 8532b4ed282SShri Abhyankar ierr = VecCopy(W,X);CHKERRQ(ierr); 8542b4ed282SShri Abhyankar /* Monitor convergence */ 8552b4ed282SShri Abhyankar ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 8562b4ed282SShri Abhyankar snes->iter = i+1; 8572b4ed282SShri Abhyankar snes->norm = vi->phinorm; 8582b4ed282SShri Abhyankar ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 8592b4ed282SShri Abhyankar SNESLogConvHistory(snes,snes->norm,lits); 8607a03ce2fSLisandro Dalcin ierr = SNESMonitor(snes,snes->iter,snes->norm);CHKERRQ(ierr); 8612b4ed282SShri Abhyankar /* Test for convergence, xnorm = || X || */ 8622b4ed282SShri Abhyankar if (snes->ops->converged != SNESSkipConverged) { ierr = VecNorm(X,NORM_2,&xnorm);CHKERRQ(ierr); } 8632b4ed282SShri Abhyankar ierr = (*snes->ops->converged)(snes,snes->iter,xnorm,ynorm,vi->phinorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); 8642b4ed282SShri Abhyankar if (snes->reason) break; 8652b4ed282SShri Abhyankar } 8662b4ed282SShri Abhyankar if (i == maxits) { 8672b4ed282SShri Abhyankar ierr = PetscInfo1(snes,"Maximum number of iterations has been reached: %D\n",maxits);CHKERRQ(ierr); 8682b4ed282SShri Abhyankar if(!snes->reason) snes->reason = SNES_DIVERGED_MAX_IT; 8692b4ed282SShri Abhyankar } 8709ce7406fSBarry Smith snes->ops->computefunction = vi->computeuserfunction; 8712b4ed282SShri Abhyankar PetscFunctionReturn(0); 8722b4ed282SShri Abhyankar } 87369c03620SShri Abhyankar 87469c03620SShri Abhyankar #undef __FUNCT__ 875693ddf92SShri Abhyankar #define __FUNCT__ "SNESVIGetActiveSetIS" 876693ddf92SShri Abhyankar /* 877693ddf92SShri Abhyankar SNESVIGetActiveSetIndices - Gets the global indices for the active set variables 878693ddf92SShri Abhyankar 879693ddf92SShri Abhyankar Input parameter 880693ddf92SShri Abhyankar . snes - the SNES context 881693ddf92SShri Abhyankar . X - the snes solution vector 882693ddf92SShri Abhyankar . F - the nonlinear function vector 883693ddf92SShri Abhyankar 884693ddf92SShri Abhyankar Output parameter 885693ddf92SShri Abhyankar . ISact - active set index set 886693ddf92SShri Abhyankar */ 887693ddf92SShri Abhyankar PetscErrorCode SNESVIGetActiveSetIS(SNES snes,Vec X,Vec F,IS* ISact) 888d950fb63SShri Abhyankar { 889d950fb63SShri Abhyankar PetscErrorCode ierr; 890693ddf92SShri Abhyankar SNES_VI *vi = (SNES_VI*)snes->data; 891693ddf92SShri Abhyankar Vec Xl=vi->xl,Xu=vi->xu; 892693ddf92SShri Abhyankar const PetscScalar *x,*f,*xl,*xu; 893693ddf92SShri Abhyankar PetscInt *idx_act,i,nlocal,nloc_isact=0,ilow,ihigh,i1=0; 894d950fb63SShri Abhyankar 895d950fb63SShri Abhyankar PetscFunctionBegin; 896d950fb63SShri Abhyankar ierr = VecGetLocalSize(X,&nlocal);CHKERRQ(ierr); 897d950fb63SShri Abhyankar ierr = VecGetOwnershipRange(X,&ilow,&ihigh);CHKERRQ(ierr); 898fe835674SShri Abhyankar ierr = VecGetArrayRead(X,&x);CHKERRQ(ierr); 899fe835674SShri Abhyankar ierr = VecGetArrayRead(Xl,&xl);CHKERRQ(ierr); 900fe835674SShri Abhyankar ierr = VecGetArrayRead(Xu,&xu);CHKERRQ(ierr); 901fe835674SShri Abhyankar ierr = VecGetArrayRead(F,&f);CHKERRQ(ierr); 902693ddf92SShri Abhyankar /* Compute active set size */ 903d950fb63SShri Abhyankar for (i=0; i < nlocal;i++) { 90410f5ae6bSBarry 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++; 905d950fb63SShri Abhyankar } 906693ddf92SShri Abhyankar 907d950fb63SShri Abhyankar ierr = PetscMalloc(nloc_isact*sizeof(PetscInt),&idx_act);CHKERRQ(ierr); 908d950fb63SShri Abhyankar 909693ddf92SShri Abhyankar /* Set active set indices */ 910d950fb63SShri Abhyankar for(i=0; i < nlocal; i++) { 91110f5ae6bSBarry 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; 912d950fb63SShri Abhyankar } 913d950fb63SShri Abhyankar 914693ddf92SShri Abhyankar /* Create active set IS */ 91562298a1eSBarry Smith ierr = ISCreateGeneral(((PetscObject)snes)->comm,nloc_isact,idx_act,PETSC_OWN_POINTER,ISact);CHKERRQ(ierr); 916d950fb63SShri Abhyankar 917fe835674SShri Abhyankar ierr = VecRestoreArrayRead(X,&x);CHKERRQ(ierr); 918fe835674SShri Abhyankar ierr = VecRestoreArrayRead(Xl,&xl);CHKERRQ(ierr); 919fe835674SShri Abhyankar ierr = VecRestoreArrayRead(Xu,&xu);CHKERRQ(ierr); 920fe835674SShri Abhyankar ierr = VecRestoreArrayRead(F,&f);CHKERRQ(ierr); 921d950fb63SShri Abhyankar PetscFunctionReturn(0); 922d950fb63SShri Abhyankar } 923d950fb63SShri Abhyankar 924693ddf92SShri Abhyankar #undef __FUNCT__ 925693ddf92SShri Abhyankar #define __FUNCT__ "SNESVICreateIndexSets_RS" 926693ddf92SShri Abhyankar PetscErrorCode SNESVICreateIndexSets_RS(SNES snes,Vec X,Vec F,IS* ISact,IS* ISinact) 927693ddf92SShri Abhyankar { 928693ddf92SShri Abhyankar PetscErrorCode ierr; 929693ddf92SShri Abhyankar 930693ddf92SShri Abhyankar PetscFunctionBegin; 931693ddf92SShri Abhyankar ierr = SNESVIGetActiveSetIS(snes,X,F,ISact);CHKERRQ(ierr); 932693ddf92SShri Abhyankar ierr = ISComplement(*ISact,X->map->rstart,X->map->rend,ISinact);CHKERRQ(ierr); 933693ddf92SShri Abhyankar PetscFunctionReturn(0); 934693ddf92SShri Abhyankar } 935693ddf92SShri Abhyankar 936dbd914b8SShri Abhyankar /* Create active and inactive set vectors. The local size of this vector is set and petsc computes the global size */ 937dbd914b8SShri Abhyankar #undef __FUNCT__ 938fe835674SShri Abhyankar #define __FUNCT__ "SNESVICreateSubVectors" 939fe835674SShri Abhyankar PetscErrorCode SNESVICreateSubVectors(SNES snes,PetscInt n,Vec* newv) 940dbd914b8SShri Abhyankar { 941dbd914b8SShri Abhyankar PetscErrorCode ierr; 942dbd914b8SShri Abhyankar Vec v; 943dbd914b8SShri Abhyankar 944dbd914b8SShri Abhyankar PetscFunctionBegin; 945dbd914b8SShri Abhyankar ierr = VecCreate(((PetscObject)snes)->comm,&v);CHKERRQ(ierr); 946dbd914b8SShri Abhyankar ierr = VecSetSizes(v,n,PETSC_DECIDE);CHKERRQ(ierr); 947dbd914b8SShri Abhyankar ierr = VecSetFromOptions(v);CHKERRQ(ierr); 948dbd914b8SShri Abhyankar *newv = v; 949dbd914b8SShri Abhyankar 950dbd914b8SShri Abhyankar PetscFunctionReturn(0); 951dbd914b8SShri Abhyankar } 952dbd914b8SShri Abhyankar 953732bb160SShri Abhyankar /* Resets the snes PC and KSP when the active set sizes change */ 954732bb160SShri Abhyankar #undef __FUNCT__ 955732bb160SShri Abhyankar #define __FUNCT__ "SNESVIResetPCandKSP" 956732bb160SShri Abhyankar PetscErrorCode SNESVIResetPCandKSP(SNES snes,Mat Amat,Mat Pmat) 957732bb160SShri Abhyankar { 958732bb160SShri Abhyankar PetscErrorCode ierr; 959d0af7cd3SBarry Smith KSP snesksp; 960dbd914b8SShri Abhyankar 961732bb160SShri Abhyankar PetscFunctionBegin; 962732bb160SShri Abhyankar ierr = SNESGetKSP(snes,&snesksp);CHKERRQ(ierr); 963d0af7cd3SBarry Smith ierr = KSPReset(snesksp);CHKERRQ(ierr); 964c2efdce3SBarry Smith 965c2efdce3SBarry Smith /* 966d0af7cd3SBarry Smith KSP kspnew; 967d0af7cd3SBarry Smith PC pcnew; 968d0af7cd3SBarry Smith const MatSolverPackage stype; 969d0af7cd3SBarry Smith 970c2efdce3SBarry Smith 971732bb160SShri Abhyankar ierr = KSPCreate(((PetscObject)snes)->comm,&kspnew);CHKERRQ(ierr); 972732bb160SShri Abhyankar kspnew->pc_side = snesksp->pc_side; 973732bb160SShri Abhyankar kspnew->rtol = snesksp->rtol; 974732bb160SShri Abhyankar kspnew->abstol = snesksp->abstol; 975732bb160SShri Abhyankar kspnew->max_it = snesksp->max_it; 976732bb160SShri Abhyankar ierr = KSPSetType(kspnew,((PetscObject)snesksp)->type_name);CHKERRQ(ierr); 977732bb160SShri Abhyankar ierr = KSPGetPC(kspnew,&pcnew);CHKERRQ(ierr); 978732bb160SShri Abhyankar ierr = PCSetType(kspnew->pc,((PetscObject)snesksp->pc)->type_name);CHKERRQ(ierr); 979732bb160SShri Abhyankar ierr = PCSetOperators(kspnew->pc,Amat,Pmat,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr); 980732bb160SShri Abhyankar ierr = PCFactorGetMatSolverPackage(snesksp->pc,&stype);CHKERRQ(ierr); 981732bb160SShri Abhyankar ierr = PCFactorSetMatSolverPackage(kspnew->pc,stype);CHKERRQ(ierr); 9826bf464f9SBarry Smith ierr = KSPDestroy(&snesksp);CHKERRQ(ierr); 983732bb160SShri Abhyankar snes->ksp = kspnew; 984732bb160SShri Abhyankar ierr = PetscLogObjectParent(snes,kspnew);CHKERRQ(ierr); 985d0af7cd3SBarry Smith ierr = KSPSetFromOptions(kspnew);CHKERRQ(ierr);*/ 986732bb160SShri Abhyankar PetscFunctionReturn(0); 987732bb160SShri Abhyankar } 98869c03620SShri Abhyankar 98969c03620SShri Abhyankar 990fe835674SShri Abhyankar #undef __FUNCT__ 991fe835674SShri Abhyankar #define __FUNCT__ "SNESVIComputeInactiveSetFnorm" 99210f5ae6bSBarry Smith PetscErrorCode SNESVIComputeInactiveSetFnorm(SNES snes,Vec F,Vec X,PetscReal *fnorm) 993fe835674SShri Abhyankar { 994fe835674SShri Abhyankar PetscErrorCode ierr; 995fe835674SShri Abhyankar SNES_VI *vi = (SNES_VI*)snes->data; 996fe835674SShri Abhyankar const PetscScalar *x,*xl,*xu,*f; 997fe835674SShri Abhyankar PetscInt i,n; 998fe835674SShri Abhyankar PetscReal rnorm; 999fe835674SShri Abhyankar 1000fe835674SShri Abhyankar PetscFunctionBegin; 1001fe835674SShri Abhyankar ierr = VecGetLocalSize(X,&n);CHKERRQ(ierr); 1002fe835674SShri Abhyankar ierr = VecGetArrayRead(vi->xl,&xl);CHKERRQ(ierr); 1003fe835674SShri Abhyankar ierr = VecGetArrayRead(vi->xu,&xu);CHKERRQ(ierr); 1004fe835674SShri Abhyankar ierr = VecGetArrayRead(X,&x);CHKERRQ(ierr); 1005fe835674SShri Abhyankar ierr = VecGetArrayRead(F,&f);CHKERRQ(ierr); 1006fe835674SShri Abhyankar rnorm = 0.0; 1007fe835674SShri Abhyankar for (i=0; i<n; i++) { 100810f5ae6bSBarry 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]); 1009fe835674SShri Abhyankar } 1010fe835674SShri Abhyankar ierr = VecRestoreArrayRead(F,&f);CHKERRQ(ierr); 1011fe835674SShri Abhyankar ierr = VecRestoreArrayRead(vi->xl,&xl);CHKERRQ(ierr); 1012fe835674SShri Abhyankar ierr = VecRestoreArrayRead(vi->xu,&xu);CHKERRQ(ierr); 1013fe835674SShri Abhyankar ierr = VecRestoreArrayRead(X,&x);CHKERRQ(ierr); 1014d9822059SBarry Smith ierr = MPI_Allreduce(&rnorm,fnorm,1,MPIU_REAL,MPIU_SUM,((PetscObject)snes)->comm);CHKERRQ(ierr); 1015fe835674SShri Abhyankar *fnorm = sqrt(*fnorm); 1016fe835674SShri Abhyankar PetscFunctionReturn(0); 1017fe835674SShri Abhyankar } 1018fe835674SShri Abhyankar 1019fe835674SShri Abhyankar /* Variational Inequality solver using reduce space method. No semismooth algorithm is 1020c2efdce3SBarry Smith implemented in this algorithm. It basically identifies the active constraints and does 1021c2efdce3SBarry Smith a linear solve on the other variables (those not associated with the active constraints). */ 1022d950fb63SShri Abhyankar #undef __FUNCT__ 1023d950fb63SShri Abhyankar #define __FUNCT__ "SNESSolveVI_RS" 1024d950fb63SShri Abhyankar PetscErrorCode SNESSolveVI_RS(SNES snes) 1025d950fb63SShri Abhyankar { 1026d950fb63SShri Abhyankar SNES_VI *vi = (SNES_VI*)snes->data; 1027d950fb63SShri Abhyankar PetscErrorCode ierr; 1028abcba341SShri Abhyankar PetscInt maxits,i,lits; 1029d950fb63SShri Abhyankar PetscBool lssucceed; 1030d950fb63SShri Abhyankar MatStructure flg = DIFFERENT_NONZERO_PATTERN; 1031fe835674SShri Abhyankar PetscReal fnorm,gnorm,xnorm=0,ynorm; 1032d950fb63SShri Abhyankar Vec Y,X,F,G,W; 1033d950fb63SShri Abhyankar KSPConvergedReason kspreason; 1034d950fb63SShri Abhyankar 1035d950fb63SShri Abhyankar PetscFunctionBegin; 1036d950fb63SShri Abhyankar snes->numFailures = 0; 1037d950fb63SShri Abhyankar snes->numLinearSolveFailures = 0; 1038d950fb63SShri Abhyankar snes->reason = SNES_CONVERGED_ITERATING; 1039d950fb63SShri Abhyankar 1040d950fb63SShri Abhyankar maxits = snes->max_its; /* maximum number of iterations */ 1041d950fb63SShri Abhyankar X = snes->vec_sol; /* solution vector */ 1042d950fb63SShri Abhyankar F = snes->vec_func; /* residual vector */ 1043d950fb63SShri Abhyankar Y = snes->work[0]; /* work vectors */ 1044d950fb63SShri Abhyankar G = snes->work[1]; 1045d950fb63SShri Abhyankar W = snes->work[2]; 1046d950fb63SShri Abhyankar 1047d950fb63SShri Abhyankar ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 1048d950fb63SShri Abhyankar snes->iter = 0; 1049d950fb63SShri Abhyankar snes->norm = 0.0; 1050d950fb63SShri Abhyankar ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 1051d950fb63SShri Abhyankar 10527fe79bc4SShri Abhyankar ierr = SNESVIProjectOntoBounds(snes,X);CHKERRQ(ierr); 1053fe835674SShri Abhyankar ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr); 1054d950fb63SShri Abhyankar if (snes->domainerror) { 1055d950fb63SShri Abhyankar snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN; 1056d950fb63SShri Abhyankar PetscFunctionReturn(0); 1057d950fb63SShri Abhyankar } 1058fe835674SShri Abhyankar ierr = SNESVIComputeInactiveSetFnorm(snes,F,X,&fnorm);CHKERRQ(ierr); 1059d950fb63SShri Abhyankar ierr = VecNormBegin(X,NORM_2,&xnorm);CHKERRQ(ierr); /* xnorm <- ||x|| */ 1060d950fb63SShri Abhyankar ierr = VecNormEnd(X,NORM_2,&xnorm);CHKERRQ(ierr); 106162cbcd01SMatthew G Knepley if (PetscIsInfOrNanReal(fnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number"); 1062d950fb63SShri Abhyankar 1063d950fb63SShri Abhyankar ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 1064fe835674SShri Abhyankar snes->norm = fnorm; 1065d950fb63SShri Abhyankar ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 1066fe835674SShri Abhyankar SNESLogConvHistory(snes,fnorm,0); 10677a03ce2fSLisandro Dalcin ierr = SNESMonitor(snes,0,fnorm);CHKERRQ(ierr); 1068d950fb63SShri Abhyankar 1069d950fb63SShri Abhyankar /* set parameter for default relative tolerance convergence test */ 1070fe835674SShri Abhyankar snes->ttol = fnorm*snes->rtol; 1071d950fb63SShri Abhyankar /* test convergence */ 1072fe835674SShri Abhyankar ierr = (*snes->ops->converged)(snes,0,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); 1073d950fb63SShri Abhyankar if (snes->reason) PetscFunctionReturn(0); 1074d950fb63SShri Abhyankar 1075d950fb63SShri Abhyankar for (i=0; i<maxits; i++) { 1076d950fb63SShri Abhyankar 1077d950fb63SShri Abhyankar IS IS_act,IS_inact; /* _act -> active set _inact -> inactive set */ 1078d950fb63SShri Abhyankar VecScatter scat_act,scat_inact; 1079abcba341SShri Abhyankar PetscInt nis_act,nis_inact; 1080fe835674SShri Abhyankar Vec Y_act,Y_inact,F_inact; 1081d950fb63SShri Abhyankar Mat jac_inact_inact,prejac_inact_inact; 108262298a1eSBarry Smith IS keptrows; 1083abcba341SShri Abhyankar PetscBool isequal; 1084d950fb63SShri Abhyankar 1085d950fb63SShri Abhyankar /* Call general purpose update function */ 1086d950fb63SShri Abhyankar if (snes->ops->update) { 1087d950fb63SShri Abhyankar ierr = (*snes->ops->update)(snes, snes->iter);CHKERRQ(ierr); 1088d950fb63SShri Abhyankar } 1089d950fb63SShri Abhyankar ierr = SNESComputeJacobian(snes,X,&snes->jacobian,&snes->jacobian_pre,&flg);CHKERRQ(ierr); 109062298a1eSBarry Smith 1091d950fb63SShri Abhyankar /* Create active and inactive index sets */ 1092693ddf92SShri Abhyankar ierr = SNESVICreateIndexSets_RS(snes,X,F,&IS_act,&IS_inact);CHKERRQ(ierr); 1093d950fb63SShri Abhyankar 10944dcab191SBarry Smith 1095abcba341SShri Abhyankar /* Create inactive set submatrix */ 109662298a1eSBarry Smith ierr = MatGetSubMatrix(snes->jacobian,IS_inact,IS_inact,MAT_INITIAL_MATRIX,&jac_inact_inact);CHKERRQ(ierr); 1097b3a44c85SBarry Smith ierr = MatFindNonzeroRows(jac_inact_inact,&keptrows);CHKERRQ(ierr); 109862298a1eSBarry Smith if (keptrows) { 109962298a1eSBarry Smith PetscInt cnt,*nrows,k; 110062298a1eSBarry Smith const PetscInt *krows,*inact; 110127d4218bSShri Abhyankar PetscInt rstart=jac_inact_inact->rmap->rstart; 110262298a1eSBarry Smith 11036bf464f9SBarry Smith ierr = MatDestroy(&jac_inact_inact);CHKERRQ(ierr); 11046bf464f9SBarry Smith ierr = ISDestroy(&IS_act);CHKERRQ(ierr); 110562298a1eSBarry Smith 110662298a1eSBarry Smith ierr = ISGetLocalSize(keptrows,&cnt);CHKERRQ(ierr); 110762298a1eSBarry Smith ierr = ISGetIndices(keptrows,&krows);CHKERRQ(ierr); 110862298a1eSBarry Smith ierr = ISGetIndices(IS_inact,&inact);CHKERRQ(ierr); 110962298a1eSBarry Smith ierr = PetscMalloc(cnt*sizeof(PetscInt),&nrows);CHKERRQ(ierr); 111062298a1eSBarry Smith for (k=0; k<cnt; k++) { 111127d4218bSShri Abhyankar nrows[k] = inact[krows[k]-rstart]; 111262298a1eSBarry Smith } 111362298a1eSBarry Smith ierr = ISRestoreIndices(keptrows,&krows);CHKERRQ(ierr); 111462298a1eSBarry Smith ierr = ISRestoreIndices(IS_inact,&inact);CHKERRQ(ierr); 11156bf464f9SBarry Smith ierr = ISDestroy(&keptrows);CHKERRQ(ierr); 11166bf464f9SBarry Smith ierr = ISDestroy(&IS_inact);CHKERRQ(ierr); 111762298a1eSBarry Smith 111827d4218bSShri Abhyankar ierr = ISCreateGeneral(PETSC_COMM_WORLD,cnt,nrows,PETSC_OWN_POINTER,&IS_inact);CHKERRQ(ierr); 111927d4218bSShri Abhyankar ierr = ISComplement(IS_inact,F->map->rstart,F->map->rend,&IS_act);CHKERRQ(ierr); 112062298a1eSBarry Smith ierr = MatGetSubMatrix(snes->jacobian,IS_inact,IS_inact,MAT_INITIAL_MATRIX,&jac_inact_inact);CHKERRQ(ierr); 112162298a1eSBarry Smith } 11229e516c8fSBarry Smith ierr = DMSetVI(snes->dm,vi->xu,vi->xl,X,F,IS_inact);CHKERRQ(ierr); 112362298a1eSBarry Smith 1124d950fb63SShri Abhyankar /* Get sizes of active and inactive sets */ 1125d950fb63SShri Abhyankar ierr = ISGetLocalSize(IS_act,&nis_act);CHKERRQ(ierr); 1126d950fb63SShri Abhyankar ierr = ISGetLocalSize(IS_inact,&nis_inact);CHKERRQ(ierr); 1127d950fb63SShri Abhyankar 1128d950fb63SShri Abhyankar /* Create active and inactive set vectors */ 1129fe835674SShri Abhyankar ierr = SNESVICreateSubVectors(snes,nis_inact,&F_inact);CHKERRQ(ierr); 1130fe835674SShri Abhyankar ierr = SNESVICreateSubVectors(snes,nis_act,&Y_act);CHKERRQ(ierr); 1131fe835674SShri Abhyankar ierr = SNESVICreateSubVectors(snes,nis_inact,&Y_inact);CHKERRQ(ierr); 1132d950fb63SShri Abhyankar 1133d950fb63SShri Abhyankar /* Create scatter contexts */ 1134d950fb63SShri Abhyankar ierr = VecScatterCreate(Y,IS_act,Y_act,PETSC_NULL,&scat_act);CHKERRQ(ierr); 1135d950fb63SShri Abhyankar ierr = VecScatterCreate(Y,IS_inact,Y_inact,PETSC_NULL,&scat_inact);CHKERRQ(ierr); 1136d950fb63SShri Abhyankar 1137d950fb63SShri Abhyankar /* Do a vec scatter to active and inactive set vectors */ 1138fe835674SShri Abhyankar ierr = VecScatterBegin(scat_inact,F,F_inact,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1139fe835674SShri Abhyankar ierr = VecScatterEnd(scat_inact,F,F_inact,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1140d950fb63SShri Abhyankar 1141d950fb63SShri Abhyankar ierr = VecScatterBegin(scat_act,Y,Y_act,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1142d950fb63SShri Abhyankar ierr = VecScatterEnd(scat_act,Y,Y_act,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1143d950fb63SShri Abhyankar 1144d950fb63SShri Abhyankar ierr = VecScatterBegin(scat_inact,Y,Y_inact,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1145d950fb63SShri Abhyankar ierr = VecScatterEnd(scat_inact,Y,Y_inact,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1146d950fb63SShri Abhyankar 1147d950fb63SShri Abhyankar /* Active set direction = 0 */ 1148d950fb63SShri Abhyankar ierr = VecSet(Y_act,0);CHKERRQ(ierr); 1149d950fb63SShri Abhyankar if (snes->jacobian != snes->jacobian_pre) { 1150d950fb63SShri Abhyankar ierr = MatGetSubMatrix(snes->jacobian_pre,IS_inact,IS_inact,MAT_INITIAL_MATRIX,&prejac_inact_inact);CHKERRQ(ierr); 1151d950fb63SShri Abhyankar } else prejac_inact_inact = jac_inact_inact; 1152d950fb63SShri Abhyankar 1153abcba341SShri Abhyankar ierr = ISEqual(vi->IS_inact_prev,IS_inact,&isequal);CHKERRQ(ierr); 1154abcba341SShri Abhyankar if (!isequal) { 1155732bb160SShri Abhyankar ierr = SNESVIResetPCandKSP(snes,jac_inact_inact,prejac_inact_inact);CHKERRQ(ierr); 1156d950fb63SShri Abhyankar } 1157d950fb63SShri Abhyankar 115813e0d083SBarry Smith /* ierr = ISView(IS_inact,0);CHKERRQ(ierr); */ 115913e0d083SBarry Smith /* ierr = ISView(IS_act,0);CHKERRQ(ierr);*/ 116013e0d083SBarry Smith /* ierr = MatView(snes->jacobian_pre,0); */ 116113e0d083SBarry Smith 1162d950fb63SShri Abhyankar ierr = KSPSetOperators(snes->ksp,jac_inact_inact,prejac_inact_inact,flg);CHKERRQ(ierr); 116313e0d083SBarry Smith ierr = KSPSetUp(snes->ksp);CHKERRQ(ierr); 116413e0d083SBarry Smith { 116513e0d083SBarry Smith PC pc; 116613e0d083SBarry Smith PetscBool flg; 116713e0d083SBarry Smith ierr = KSPGetPC(snes->ksp,&pc);CHKERRQ(ierr); 116813e0d083SBarry Smith ierr = PetscTypeCompare((PetscObject)pc,PCFIELDSPLIT,&flg);CHKERRQ(ierr); 116913e0d083SBarry Smith if (flg) { 117013e0d083SBarry Smith KSP *subksps; 117113e0d083SBarry Smith ierr = PCFieldSplitGetSubKSP(pc,PETSC_NULL,&subksps);CHKERRQ(ierr); 117213e0d083SBarry Smith ierr = KSPGetPC(subksps[0],&pc);CHKERRQ(ierr); 117313e0d083SBarry Smith ierr = PetscFree(subksps);CHKERRQ(ierr); 117413e0d083SBarry Smith ierr = PetscTypeCompare((PetscObject)pc,PCBJACOBI,&flg);CHKERRQ(ierr); 117513e0d083SBarry Smith if (flg) { 117613e0d083SBarry Smith PetscInt n,N = 101*101,j,cnts[3] = {0,0,0}; 117713e0d083SBarry Smith const PetscInt *ii; 117813e0d083SBarry Smith 117913e0d083SBarry Smith ierr = ISGetSize(IS_inact,&n);CHKERRQ(ierr); 118013e0d083SBarry Smith ierr = ISGetIndices(IS_inact,&ii);CHKERRQ(ierr); 118113e0d083SBarry Smith for (j=0; j<n; j++) { 118213e0d083SBarry Smith if (ii[j] < N) cnts[0]++; 118313e0d083SBarry Smith else if (ii[j] < 2*N) cnts[1]++; 118413e0d083SBarry Smith else if (ii[j] < 3*N) cnts[2]++; 118513e0d083SBarry Smith } 118613e0d083SBarry Smith ierr = ISRestoreIndices(IS_inact,&ii);CHKERRQ(ierr); 118713e0d083SBarry Smith 118813e0d083SBarry Smith ierr = PCBJacobiSetTotalBlocks(pc,3,cnts);CHKERRQ(ierr); 118913e0d083SBarry Smith } 119013e0d083SBarry Smith } 119113e0d083SBarry Smith } 119213e0d083SBarry Smith 1193fe835674SShri Abhyankar ierr = SNES_KSPSolve(snes,snes->ksp,F_inact,Y_inact);CHKERRQ(ierr); 1194d950fb63SShri Abhyankar ierr = KSPGetConvergedReason(snes->ksp,&kspreason);CHKERRQ(ierr); 1195d950fb63SShri Abhyankar if (kspreason < 0) { 1196d950fb63SShri Abhyankar if (++snes->numLinearSolveFailures >= snes->maxLinearSolveFailures) { 1197d950fb63SShri 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); 1198d950fb63SShri Abhyankar snes->reason = SNES_DIVERGED_LINEAR_SOLVE; 1199d950fb63SShri Abhyankar break; 1200d950fb63SShri Abhyankar } 1201d950fb63SShri Abhyankar } 1202d950fb63SShri Abhyankar 1203d950fb63SShri Abhyankar ierr = VecScatterBegin(scat_act,Y_act,Y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1204d950fb63SShri Abhyankar ierr = VecScatterEnd(scat_act,Y_act,Y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1205d950fb63SShri Abhyankar ierr = VecScatterBegin(scat_inact,Y_inact,Y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1206d950fb63SShri Abhyankar ierr = VecScatterEnd(scat_inact,Y_inact,Y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1207d950fb63SShri Abhyankar 12086bf464f9SBarry Smith ierr = VecDestroy(&F_inact);CHKERRQ(ierr); 12096bf464f9SBarry Smith ierr = VecDestroy(&Y_act);CHKERRQ(ierr); 12106bf464f9SBarry Smith ierr = VecDestroy(&Y_inact);CHKERRQ(ierr); 12116bf464f9SBarry Smith ierr = VecScatterDestroy(&scat_act);CHKERRQ(ierr); 12126bf464f9SBarry Smith ierr = VecScatterDestroy(&scat_inact);CHKERRQ(ierr); 12136bf464f9SBarry Smith ierr = ISDestroy(&IS_act);CHKERRQ(ierr); 1214abcba341SShri Abhyankar if (!isequal) { 12156bf464f9SBarry Smith ierr = ISDestroy(&vi->IS_inact_prev);CHKERRQ(ierr); 1216abcba341SShri Abhyankar ierr = ISDuplicate(IS_inact,&vi->IS_inact_prev);CHKERRQ(ierr); 1217abcba341SShri Abhyankar } 12186bf464f9SBarry Smith ierr = ISDestroy(&IS_inact);CHKERRQ(ierr); 12196bf464f9SBarry Smith ierr = MatDestroy(&jac_inact_inact);CHKERRQ(ierr); 1220d950fb63SShri Abhyankar if (snes->jacobian != snes->jacobian_pre) { 12216bf464f9SBarry Smith ierr = MatDestroy(&prejac_inact_inact);CHKERRQ(ierr); 1222d950fb63SShri Abhyankar } 1223d950fb63SShri Abhyankar ierr = KSPGetIterationNumber(snes->ksp,&lits);CHKERRQ(ierr); 1224d950fb63SShri Abhyankar snes->linear_its += lits; 1225d950fb63SShri Abhyankar ierr = PetscInfo2(snes,"iter=%D, linear solve iterations=%D\n",snes->iter,lits);CHKERRQ(ierr); 1226d950fb63SShri Abhyankar /* 1227d950fb63SShri Abhyankar if (vi->precheckstep) { 1228d950fb63SShri Abhyankar PetscBool changed_y = PETSC_FALSE; 1229d950fb63SShri Abhyankar ierr = (*vi->precheckstep)(snes,X,Y,vi->precheck,&changed_y);CHKERRQ(ierr); 1230d950fb63SShri Abhyankar } 1231d950fb63SShri Abhyankar 1232d950fb63SShri Abhyankar if (PetscLogPrintInfo){ 1233d950fb63SShri Abhyankar ierr = SNESVICheckResidual_Private(snes,snes->jacobian,F,Y,G,W);CHKERRQ(ierr); 1234d950fb63SShri Abhyankar } 1235d950fb63SShri Abhyankar */ 1236d950fb63SShri Abhyankar /* Compute a (scaled) negative update in the line search routine: 1237d950fb63SShri Abhyankar Y <- X - lambda*Y 1238d950fb63SShri Abhyankar and evaluate G = function(Y) (depends on the line search). 1239d950fb63SShri Abhyankar */ 1240d950fb63SShri Abhyankar ierr = VecCopy(Y,snes->vec_sol_update);CHKERRQ(ierr); 1241fe835674SShri Abhyankar ynorm = 1; gnorm = fnorm; 1242fe835674SShri Abhyankar ierr = (*vi->LineSearch)(snes,vi->lsP,X,F,G,Y,W,fnorm,xnorm,&ynorm,&gnorm,&lssucceed);CHKERRQ(ierr); 1243fe835674SShri Abhyankar ierr = PetscInfo4(snes,"fnorm=%18.16e, gnorm=%18.16e, ynorm=%18.16e, lssucceed=%d\n",fnorm,gnorm,ynorm,(int)lssucceed);CHKERRQ(ierr); 12442b4ed282SShri Abhyankar if (snes->reason == SNES_DIVERGED_FUNCTION_COUNT) break; 12452b4ed282SShri Abhyankar if (snes->domainerror) { 12462b4ed282SShri Abhyankar snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN; 12474c661befSBarry Smith ierr = DMDestroyVI(snes->dm);CHKERRQ(ierr); 12482b4ed282SShri Abhyankar PetscFunctionReturn(0); 12492b4ed282SShri Abhyankar } 12502b4ed282SShri Abhyankar if (!lssucceed) { 12512b4ed282SShri Abhyankar if (++snes->numFailures >= snes->maxFailures) { 12522b4ed282SShri Abhyankar PetscBool ismin; 12532b4ed282SShri Abhyankar snes->reason = SNES_DIVERGED_LINE_SEARCH; 12542b4ed282SShri Abhyankar ierr = SNESVICheckLocalMin_Private(snes,snes->jacobian,G,W,gnorm,&ismin);CHKERRQ(ierr); 12552b4ed282SShri Abhyankar if (ismin) snes->reason = SNES_DIVERGED_LOCAL_MIN; 12562b4ed282SShri Abhyankar break; 12572b4ed282SShri Abhyankar } 12582b4ed282SShri Abhyankar } 12592b4ed282SShri Abhyankar /* Update function and solution vectors */ 1260fe835674SShri Abhyankar fnorm = gnorm; 1261fe835674SShri Abhyankar ierr = VecCopy(G,F);CHKERRQ(ierr); 12622b4ed282SShri Abhyankar ierr = VecCopy(W,X);CHKERRQ(ierr); 12632b4ed282SShri Abhyankar /* Monitor convergence */ 12642b4ed282SShri Abhyankar ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 12652b4ed282SShri Abhyankar snes->iter = i+1; 1266fe835674SShri Abhyankar snes->norm = fnorm; 12672b4ed282SShri Abhyankar ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 12682b4ed282SShri Abhyankar SNESLogConvHistory(snes,snes->norm,lits); 12697a03ce2fSLisandro Dalcin ierr = SNESMonitor(snes,snes->iter,snes->norm);CHKERRQ(ierr); 12702b4ed282SShri Abhyankar /* Test for convergence, xnorm = || X || */ 12712b4ed282SShri Abhyankar if (snes->ops->converged != SNESSkipConverged) { ierr = VecNorm(X,NORM_2,&xnorm);CHKERRQ(ierr); } 1272fe835674SShri Abhyankar ierr = (*snes->ops->converged)(snes,snes->iter,xnorm,ynorm,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); 12732b4ed282SShri Abhyankar if (snes->reason) break; 12742b4ed282SShri Abhyankar } 12754c661befSBarry Smith ierr = DMDestroyVI(snes->dm);CHKERRQ(ierr); 12762b4ed282SShri Abhyankar if (i == maxits) { 12772b4ed282SShri Abhyankar ierr = PetscInfo1(snes,"Maximum number of iterations has been reached: %D\n",maxits);CHKERRQ(ierr); 12782b4ed282SShri Abhyankar if(!snes->reason) snes->reason = SNES_DIVERGED_MAX_IT; 12792b4ed282SShri Abhyankar } 12802b4ed282SShri Abhyankar PetscFunctionReturn(0); 12812b4ed282SShri Abhyankar } 12822b4ed282SShri Abhyankar 12832f63a38cSShri Abhyankar #undef __FUNCT__ 1284720c9a41SShri Abhyankar #define __FUNCT__ "SNESVISetRedundancyCheck" 1285cb5fe31bSShri Abhyankar PetscErrorCode SNESVISetRedundancyCheck(SNES snes,PetscErrorCode (*func)(SNES,IS,IS*,void*),void *ctx) 12862f63a38cSShri Abhyankar { 12872f63a38cSShri Abhyankar SNES_VI *vi = (SNES_VI*)snes->data; 12882f63a38cSShri Abhyankar 12892f63a38cSShri Abhyankar PetscFunctionBegin; 12902f63a38cSShri Abhyankar PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 12912f63a38cSShri Abhyankar vi->checkredundancy = func; 1292cb5fe31bSShri Abhyankar vi->ctxP = ctx; 12932f63a38cSShri Abhyankar PetscFunctionReturn(0); 12942f63a38cSShri Abhyankar } 12952f63a38cSShri Abhyankar 1296ff596062SShri Abhyankar #if defined(PETSC_HAVE_MATLAB_ENGINE) 1297ff596062SShri Abhyankar #include <engine.h> 1298ff596062SShri Abhyankar #include <mex.h> 1299cb5fe31bSShri Abhyankar typedef struct {char *funcname; mxArray *ctx;} SNESMatlabContext; 1300ff596062SShri Abhyankar 1301ff596062SShri Abhyankar #undef __FUNCT__ 1302ff596062SShri Abhyankar #define __FUNCT__ "SNESVIRedundancyCheck_Matlab" 1303ff596062SShri Abhyankar PetscErrorCode SNESVIRedundancyCheck_Matlab(SNES snes,IS is_act,IS* is_redact,void* ctx) 1304ff596062SShri Abhyankar { 1305ff596062SShri Abhyankar PetscErrorCode ierr; 1306cb5fe31bSShri Abhyankar SNESMatlabContext *sctx = (SNESMatlabContext*)ctx; 1307cb5fe31bSShri Abhyankar int nlhs = 1, nrhs = 5; 1308cb5fe31bSShri Abhyankar mxArray *plhs[1], *prhs[5]; 1309cb5fe31bSShri Abhyankar long long int l1 = 0, l2 = 0, ls = 0; 1310fcb1c9afSShri Abhyankar PetscInt *indices=PETSC_NULL; 1311ff596062SShri Abhyankar 1312ff596062SShri Abhyankar PetscFunctionBegin; 1313ff596062SShri Abhyankar PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 1314ff596062SShri Abhyankar PetscValidHeaderSpecific(is_act,IS_CLASSID,2); 1315ff596062SShri Abhyankar PetscValidPointer(is_redact,3); 1316ff596062SShri Abhyankar PetscCheckSameComm(snes,1,is_act,2); 1317ff596062SShri Abhyankar 131809db5ad8SShri Abhyankar /* Create IS for reduced active set of size 0, its size and indices will 131909db5ad8SShri Abhyankar bet set by the Matlab function */ 1320fcb1c9afSShri Abhyankar ierr = ISCreateGeneral(((PetscObject)snes)->comm,0,indices,PETSC_OWN_POINTER,is_redact);CHKERRQ(ierr); 1321cb5fe31bSShri Abhyankar /* call Matlab function in ctx */ 1322ff596062SShri Abhyankar ierr = PetscMemcpy(&ls,&snes,sizeof(snes));CHKERRQ(ierr); 1323ff596062SShri Abhyankar ierr = PetscMemcpy(&l1,&is_act,sizeof(is_act));CHKERRQ(ierr); 1324cb5fe31bSShri Abhyankar ierr = PetscMemcpy(&l2,is_redact,sizeof(is_act));CHKERRQ(ierr); 1325ff596062SShri Abhyankar prhs[0] = mxCreateDoubleScalar((double)ls); 1326ff596062SShri Abhyankar prhs[1] = mxCreateDoubleScalar((double)l1); 1327cb5fe31bSShri Abhyankar prhs[2] = mxCreateDoubleScalar((double)l2); 1328cb5fe31bSShri Abhyankar prhs[3] = mxCreateString(sctx->funcname); 1329cb5fe31bSShri Abhyankar prhs[4] = sctx->ctx; 1330ff596062SShri Abhyankar ierr = mexCallMATLAB(nlhs,plhs,nrhs,prhs,"PetscSNESVIRedundancyCheckInternal");CHKERRQ(ierr); 1331ff596062SShri Abhyankar ierr = mxGetScalar(plhs[0]);CHKERRQ(ierr); 1332ff596062SShri Abhyankar mxDestroyArray(prhs[0]); 1333ff596062SShri Abhyankar mxDestroyArray(prhs[1]); 1334ff596062SShri Abhyankar mxDestroyArray(prhs[2]); 1335ff596062SShri Abhyankar mxDestroyArray(prhs[3]); 1336ff596062SShri Abhyankar mxDestroyArray(plhs[0]); 1337ff596062SShri Abhyankar PetscFunctionReturn(0); 1338ff596062SShri Abhyankar } 1339ff596062SShri Abhyankar 1340ff596062SShri Abhyankar #undef __FUNCT__ 1341ff596062SShri Abhyankar #define __FUNCT__ "SNESVISetRedundancyCheckMatlab" 1342ff596062SShri Abhyankar PetscErrorCode SNESVISetRedundancyCheckMatlab(SNES snes,const char* func,mxArray* ctx) 1343ff596062SShri Abhyankar { 1344ff596062SShri Abhyankar PetscErrorCode ierr; 1345cb5fe31bSShri Abhyankar SNESMatlabContext *sctx; 1346ff596062SShri Abhyankar 1347ff596062SShri Abhyankar PetscFunctionBegin; 1348ff596062SShri Abhyankar /* currently sctx is memory bleed */ 1349cb5fe31bSShri Abhyankar ierr = PetscMalloc(sizeof(SNESMatlabContext),&sctx);CHKERRQ(ierr); 1350ff596062SShri Abhyankar ierr = PetscStrallocpy(func,&sctx->funcname);CHKERRQ(ierr); 1351ff596062SShri Abhyankar sctx->ctx = mxDuplicateArray(ctx); 1352cb5fe31bSShri Abhyankar ierr = SNESVISetRedundancyCheck(snes,SNESVIRedundancyCheck_Matlab,sctx);CHKERRQ(ierr); 1353ff596062SShri Abhyankar PetscFunctionReturn(0); 1354ff596062SShri Abhyankar } 1355ff596062SShri Abhyankar 1356ff596062SShri Abhyankar #endif 1357ff596062SShri Abhyankar 1358ff596062SShri Abhyankar 13592f63a38cSShri Abhyankar /* Variational Inequality solver using augmented space method. It does the opposite of the 13602f63a38cSShri Abhyankar reduced space method i.e. it identifies the active set variables and instead of discarding 1361720c9a41SShri Abhyankar them it augments the original system by introducing additional equality 136256a221efSShri Abhyankar constraint equations for active set variables. The user can optionally provide an IS for 136356a221efSShri Abhyankar a subset of 'redundant' active set variables which will treated as free variables. 13642f63a38cSShri Abhyankar Specific implementation for Allen-Cahn problem 13652f63a38cSShri Abhyankar */ 13662f63a38cSShri Abhyankar #undef __FUNCT__ 1367b350b9c9SBarry Smith #define __FUNCT__ "SNESSolveVI_RSAUG" 1368b350b9c9SBarry Smith PetscErrorCode SNESSolveVI_RSAUG(SNES snes) 13692f63a38cSShri Abhyankar { 13702f63a38cSShri Abhyankar SNES_VI *vi = (SNES_VI*)snes->data; 13712f63a38cSShri Abhyankar PetscErrorCode ierr; 13722f63a38cSShri Abhyankar PetscInt maxits,i,lits; 13732f63a38cSShri Abhyankar PetscBool lssucceed; 13742f63a38cSShri Abhyankar MatStructure flg = DIFFERENT_NONZERO_PATTERN; 13752f63a38cSShri Abhyankar PetscReal fnorm,gnorm,xnorm=0,ynorm; 13762f63a38cSShri Abhyankar Vec Y,X,F,G,W; 13772f63a38cSShri Abhyankar KSPConvergedReason kspreason; 13782f63a38cSShri Abhyankar 13792f63a38cSShri Abhyankar PetscFunctionBegin; 13802f63a38cSShri Abhyankar snes->numFailures = 0; 13812f63a38cSShri Abhyankar snes->numLinearSolveFailures = 0; 13822f63a38cSShri Abhyankar snes->reason = SNES_CONVERGED_ITERATING; 13832f63a38cSShri Abhyankar 13842f63a38cSShri Abhyankar maxits = snes->max_its; /* maximum number of iterations */ 13852f63a38cSShri Abhyankar X = snes->vec_sol; /* solution vector */ 13862f63a38cSShri Abhyankar F = snes->vec_func; /* residual vector */ 13872f63a38cSShri Abhyankar Y = snes->work[0]; /* work vectors */ 13882f63a38cSShri Abhyankar G = snes->work[1]; 13892f63a38cSShri Abhyankar W = snes->work[2]; 13902f63a38cSShri Abhyankar 13912f63a38cSShri Abhyankar ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 13922f63a38cSShri Abhyankar snes->iter = 0; 13932f63a38cSShri Abhyankar snes->norm = 0.0; 13942f63a38cSShri Abhyankar ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 13952f63a38cSShri Abhyankar 13962f63a38cSShri Abhyankar ierr = SNESVIProjectOntoBounds(snes,X);CHKERRQ(ierr); 13972f63a38cSShri Abhyankar ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr); 13982f63a38cSShri Abhyankar if (snes->domainerror) { 13992f63a38cSShri Abhyankar snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN; 14002f63a38cSShri Abhyankar PetscFunctionReturn(0); 14012f63a38cSShri Abhyankar } 14022f63a38cSShri Abhyankar ierr = SNESVIComputeInactiveSetFnorm(snes,F,X,&fnorm);CHKERRQ(ierr); 14032f63a38cSShri Abhyankar ierr = VecNormBegin(X,NORM_2,&xnorm);CHKERRQ(ierr); /* xnorm <- ||x|| */ 14042f63a38cSShri Abhyankar ierr = VecNormEnd(X,NORM_2,&xnorm);CHKERRQ(ierr); 140562cbcd01SMatthew G Knepley if (PetscIsInfOrNanReal(fnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number"); 14062f63a38cSShri Abhyankar 14072f63a38cSShri Abhyankar ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 14082f63a38cSShri Abhyankar snes->norm = fnorm; 14092f63a38cSShri Abhyankar ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 14102f63a38cSShri Abhyankar SNESLogConvHistory(snes,fnorm,0); 14117a03ce2fSLisandro Dalcin ierr = SNESMonitor(snes,0,fnorm);CHKERRQ(ierr); 14122f63a38cSShri Abhyankar 14132f63a38cSShri Abhyankar /* set parameter for default relative tolerance convergence test */ 14142f63a38cSShri Abhyankar snes->ttol = fnorm*snes->rtol; 14152f63a38cSShri Abhyankar /* test convergence */ 14162f63a38cSShri Abhyankar ierr = (*snes->ops->converged)(snes,0,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); 14172f63a38cSShri Abhyankar if (snes->reason) PetscFunctionReturn(0); 14182f63a38cSShri Abhyankar 14192f63a38cSShri Abhyankar for (i=0; i<maxits; i++) { 14202f63a38cSShri Abhyankar IS IS_act,IS_inact; /* _act -> active set _inact -> inactive set */ 1421cb5fe31bSShri Abhyankar IS IS_redact; /* redundant active set */ 142256a221efSShri Abhyankar Mat J_aug,Jpre_aug; 142356a221efSShri Abhyankar Vec F_aug,Y_aug; 142456a221efSShri Abhyankar PetscInt nis_redact,nis_act; 142556a221efSShri Abhyankar const PetscInt *idx_redact,*idx_act; 142656a221efSShri Abhyankar PetscInt k; 142763ee972cSSatish Balay PetscInt *idx_actkept=PETSC_NULL,nkept=0; /* list of kept active set */ 142856a221efSShri Abhyankar PetscScalar *f,*f2; 14292f63a38cSShri Abhyankar PetscBool isequal; 143056a221efSShri Abhyankar PetscInt i1=0,j1=0; 14312f63a38cSShri Abhyankar 14322f63a38cSShri Abhyankar /* Call general purpose update function */ 14332f63a38cSShri Abhyankar if (snes->ops->update) { 14342f63a38cSShri Abhyankar ierr = (*snes->ops->update)(snes, snes->iter);CHKERRQ(ierr); 14352f63a38cSShri Abhyankar } 14362f63a38cSShri Abhyankar ierr = SNESComputeJacobian(snes,X,&snes->jacobian,&snes->jacobian_pre,&flg);CHKERRQ(ierr); 14372f63a38cSShri Abhyankar 14382f63a38cSShri Abhyankar /* Create active and inactive index sets */ 14392f63a38cSShri Abhyankar ierr = SNESVICreateIndexSets_RS(snes,X,F,&IS_act,&IS_inact);CHKERRQ(ierr); 14402f63a38cSShri Abhyankar 144156a221efSShri Abhyankar /* Get local active set size */ 14422f63a38cSShri Abhyankar ierr = ISGetLocalSize(IS_act,&nis_act);CHKERRQ(ierr); 144356a221efSShri Abhyankar if (nis_act) { 1444e63076c7SBarry Smith ierr = ISGetIndices(IS_act,&idx_act);CHKERRQ(ierr); 1445e63076c7SBarry Smith IS_redact = PETSC_NULL; 144656a221efSShri Abhyankar if(vi->checkredundancy) { 1447cb5fe31bSShri Abhyankar (*vi->checkredundancy)(snes,IS_act,&IS_redact,vi->ctxP); 144856a221efSShri Abhyankar } 14492f63a38cSShri Abhyankar 145056a221efSShri Abhyankar if(!IS_redact) { 145156a221efSShri Abhyankar /* User called checkredundancy function but didn't create IS_redact because 145256a221efSShri Abhyankar there were no redundant active set variables */ 145356a221efSShri Abhyankar /* Copy over all active set indices to the list */ 145456a221efSShri Abhyankar ierr = PetscMalloc(nis_act*sizeof(PetscInt),&idx_actkept);CHKERRQ(ierr); 145556a221efSShri Abhyankar for(k=0;k < nis_act;k++) idx_actkept[k] = idx_act[k]; 145656a221efSShri Abhyankar nkept = nis_act; 145756a221efSShri Abhyankar } else { 145856a221efSShri Abhyankar ierr = ISGetLocalSize(IS_redact,&nis_redact);CHKERRQ(ierr); 145956a221efSShri Abhyankar ierr = PetscMalloc((nis_act-nis_redact)*sizeof(PetscInt),&idx_actkept);CHKERRQ(ierr); 14602f63a38cSShri Abhyankar 146156a221efSShri Abhyankar /* Create reduced active set list */ 146256a221efSShri Abhyankar ierr = ISGetIndices(IS_act,&idx_act);CHKERRQ(ierr); 146356a221efSShri Abhyankar ierr = ISGetIndices(IS_redact,&idx_redact);CHKERRQ(ierr); 1464cb5fe31bSShri Abhyankar j1 = 0;nkept = 0; 146556a221efSShri Abhyankar for(k=0;k<nis_act;k++) { 146656a221efSShri Abhyankar if(j1 < nis_redact && idx_act[k] == idx_redact[j1]) j1++; 146756a221efSShri Abhyankar else idx_actkept[nkept++] = idx_act[k]; 146856a221efSShri Abhyankar } 146956a221efSShri Abhyankar ierr = ISRestoreIndices(IS_act,&idx_act);CHKERRQ(ierr); 147056a221efSShri Abhyankar ierr = ISRestoreIndices(IS_redact,&idx_redact);CHKERRQ(ierr); 1471cb5fe31bSShri Abhyankar 1472cb5fe31bSShri Abhyankar ierr = ISDestroy(&IS_redact);CHKERRQ(ierr); 147356a221efSShri Abhyankar } 14742f63a38cSShri Abhyankar 147556a221efSShri Abhyankar /* Create augmented F and Y */ 147656a221efSShri Abhyankar ierr = VecCreate(((PetscObject)snes)->comm,&F_aug);CHKERRQ(ierr); 147756a221efSShri Abhyankar ierr = VecSetSizes(F_aug,F->map->n+nkept,PETSC_DECIDE);CHKERRQ(ierr); 147856a221efSShri Abhyankar ierr = VecSetFromOptions(F_aug);CHKERRQ(ierr); 147956a221efSShri Abhyankar ierr = VecDuplicate(F_aug,&Y_aug);CHKERRQ(ierr); 14802f63a38cSShri Abhyankar 148156a221efSShri Abhyankar /* Copy over F to F_aug in the first n locations */ 148256a221efSShri Abhyankar ierr = VecGetArray(F,&f);CHKERRQ(ierr); 148356a221efSShri Abhyankar ierr = VecGetArray(F_aug,&f2);CHKERRQ(ierr); 148456a221efSShri Abhyankar ierr = PetscMemcpy(f2,f,F->map->n*sizeof(PetscScalar));CHKERRQ(ierr); 148556a221efSShri Abhyankar ierr = VecRestoreArray(F,&f);CHKERRQ(ierr); 148656a221efSShri Abhyankar ierr = VecRestoreArray(F_aug,&f2);CHKERRQ(ierr); 14872f63a38cSShri Abhyankar 148856a221efSShri Abhyankar /* Create the augmented jacobian matrix */ 148956a221efSShri Abhyankar ierr = MatCreate(((PetscObject)snes)->comm,&J_aug);CHKERRQ(ierr); 149056a221efSShri Abhyankar ierr = MatSetSizes(J_aug,X->map->n+nkept,X->map->n+nkept,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr); 149156a221efSShri Abhyankar ierr = MatSetFromOptions(J_aug);CHKERRQ(ierr); 14922f63a38cSShri Abhyankar 149356a221efSShri Abhyankar 14949521db3cSSatish Balay { /* local vars */ 1495493a4f3dSShri Abhyankar /* Preallocate augmented matrix and set values in it...Doing only sequential case first*/ 149656a221efSShri Abhyankar PetscInt ncols; 149756a221efSShri Abhyankar const PetscInt *cols; 149856a221efSShri Abhyankar const PetscScalar *vals; 14992969f145SShri Abhyankar PetscScalar value[2]; 15002969f145SShri Abhyankar PetscInt row,col[2]; 1501493a4f3dSShri Abhyankar PetscInt *d_nnz; 15022969f145SShri Abhyankar value[0] = 1.0; value[1] = 0.0; 1503493a4f3dSShri Abhyankar ierr = PetscMalloc((X->map->n+nkept)*sizeof(PetscInt),&d_nnz);CHKERRQ(ierr); 1504493a4f3dSShri Abhyankar ierr = PetscMemzero(d_nnz,(X->map->n+nkept)*sizeof(PetscInt));CHKERRQ(ierr); 1505493a4f3dSShri Abhyankar for(row=0;row<snes->jacobian->rmap->n;row++) { 1506493a4f3dSShri Abhyankar ierr = MatGetRow(snes->jacobian,row,&ncols,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr); 1507493a4f3dSShri Abhyankar d_nnz[row] += ncols; 1508493a4f3dSShri Abhyankar ierr = MatRestoreRow(snes->jacobian,row,&ncols,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr); 1509493a4f3dSShri Abhyankar } 1510493a4f3dSShri Abhyankar 1511493a4f3dSShri Abhyankar for(k=0;k<nkept;k++) { 1512493a4f3dSShri Abhyankar d_nnz[idx_actkept[k]] += 1; 15132969f145SShri Abhyankar d_nnz[snes->jacobian->rmap->n+k] += 2; 1514493a4f3dSShri Abhyankar } 1515493a4f3dSShri Abhyankar ierr = MatSeqAIJSetPreallocation(J_aug,PETSC_NULL,d_nnz);CHKERRQ(ierr); 1516493a4f3dSShri Abhyankar 1517493a4f3dSShri Abhyankar ierr = PetscFree(d_nnz);CHKERRQ(ierr); 151856a221efSShri Abhyankar 151956a221efSShri Abhyankar /* Set the original jacobian matrix in J_aug */ 152056a221efSShri Abhyankar for(row=0;row<snes->jacobian->rmap->n;row++) { 152156a221efSShri Abhyankar ierr = MatGetRow(snes->jacobian,row,&ncols,&cols,&vals);CHKERRQ(ierr); 152256a221efSShri Abhyankar ierr = MatSetValues(J_aug,1,&row,ncols,cols,vals,INSERT_VALUES);CHKERRQ(ierr); 152356a221efSShri Abhyankar ierr = MatRestoreRow(snes->jacobian,row,&ncols,&cols,&vals);CHKERRQ(ierr); 152456a221efSShri Abhyankar } 152556a221efSShri Abhyankar /* Add the augmented part */ 152656a221efSShri Abhyankar for(k=0;k<nkept;k++) { 15272969f145SShri Abhyankar row = snes->jacobian->rmap->n+k; 15282969f145SShri Abhyankar col[0] = idx_actkept[k]; col[1] = snes->jacobian->rmap->n+k; 15292969f145SShri Abhyankar ierr = MatSetValues(J_aug,1,&row,1,col,value,INSERT_VALUES);CHKERRQ(ierr); 15302969f145SShri Abhyankar ierr = MatSetValues(J_aug,1,&col[0],1,&row,&value[0],INSERT_VALUES);CHKERRQ(ierr); 153156a221efSShri Abhyankar } 153256a221efSShri Abhyankar ierr = MatAssemblyBegin(J_aug,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 153356a221efSShri Abhyankar ierr = MatAssemblyEnd(J_aug,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 153456a221efSShri Abhyankar /* Only considering prejac = jac for now */ 153556a221efSShri Abhyankar Jpre_aug = J_aug; 15369521db3cSSatish Balay } /* local vars*/ 1537e63076c7SBarry Smith ierr = ISRestoreIndices(IS_act,&idx_act);CHKERRQ(ierr); 1538e63076c7SBarry Smith ierr = ISDestroy(&IS_act);CHKERRQ(ierr); 153956a221efSShri Abhyankar } else { 154056a221efSShri Abhyankar F_aug = F; J_aug = snes->jacobian; Y_aug = Y; Jpre_aug = snes->jacobian_pre; 154156a221efSShri Abhyankar } 15422f63a38cSShri Abhyankar 15432f63a38cSShri Abhyankar ierr = ISEqual(vi->IS_inact_prev,IS_inact,&isequal);CHKERRQ(ierr); 15442f63a38cSShri Abhyankar if (!isequal) { 154556a221efSShri Abhyankar ierr = SNESVIResetPCandKSP(snes,J_aug,Jpre_aug);CHKERRQ(ierr); 15462f63a38cSShri Abhyankar } 154756a221efSShri Abhyankar ierr = KSPSetOperators(snes->ksp,J_aug,Jpre_aug,flg);CHKERRQ(ierr); 15482f63a38cSShri Abhyankar ierr = KSPSetUp(snes->ksp);CHKERRQ(ierr); 154956a221efSShri Abhyankar /* { 15502f63a38cSShri Abhyankar PC pc; 15512f63a38cSShri Abhyankar PetscBool flg; 15522f63a38cSShri Abhyankar ierr = KSPGetPC(snes->ksp,&pc);CHKERRQ(ierr); 15532f63a38cSShri Abhyankar ierr = PetscTypeCompare((PetscObject)pc,PCFIELDSPLIT,&flg);CHKERRQ(ierr); 15542f63a38cSShri Abhyankar if (flg) { 15552f63a38cSShri Abhyankar KSP *subksps; 15562f63a38cSShri Abhyankar ierr = PCFieldSplitGetSubKSP(pc,PETSC_NULL,&subksps);CHKERRQ(ierr); 15572f63a38cSShri Abhyankar ierr = KSPGetPC(subksps[0],&pc);CHKERRQ(ierr); 15582f63a38cSShri Abhyankar ierr = PetscFree(subksps);CHKERRQ(ierr); 15592f63a38cSShri Abhyankar ierr = PetscTypeCompare((PetscObject)pc,PCBJACOBI,&flg);CHKERRQ(ierr); 15602f63a38cSShri Abhyankar if (flg) { 15612f63a38cSShri Abhyankar PetscInt n,N = 101*101,j,cnts[3] = {0,0,0}; 15622f63a38cSShri Abhyankar const PetscInt *ii; 15632f63a38cSShri Abhyankar 15642f63a38cSShri Abhyankar ierr = ISGetSize(IS_inact,&n);CHKERRQ(ierr); 15652f63a38cSShri Abhyankar ierr = ISGetIndices(IS_inact,&ii);CHKERRQ(ierr); 15662f63a38cSShri Abhyankar for (j=0; j<n; j++) { 15672f63a38cSShri Abhyankar if (ii[j] < N) cnts[0]++; 15682f63a38cSShri Abhyankar else if (ii[j] < 2*N) cnts[1]++; 15692f63a38cSShri Abhyankar else if (ii[j] < 3*N) cnts[2]++; 15702f63a38cSShri Abhyankar } 15712f63a38cSShri Abhyankar ierr = ISRestoreIndices(IS_inact,&ii);CHKERRQ(ierr); 15722f63a38cSShri Abhyankar 15732f63a38cSShri Abhyankar ierr = PCBJacobiSetTotalBlocks(pc,3,cnts);CHKERRQ(ierr); 15742f63a38cSShri Abhyankar } 15752f63a38cSShri Abhyankar } 15762f63a38cSShri Abhyankar } 157756a221efSShri Abhyankar */ 157856a221efSShri Abhyankar ierr = SNES_KSPSolve(snes,snes->ksp,F_aug,Y_aug);CHKERRQ(ierr); 15792f63a38cSShri Abhyankar ierr = KSPGetConvergedReason(snes->ksp,&kspreason);CHKERRQ(ierr); 15802f63a38cSShri Abhyankar if (kspreason < 0) { 15812f63a38cSShri Abhyankar if (++snes->numLinearSolveFailures >= snes->maxLinearSolveFailures) { 15822f63a38cSShri 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); 15832f63a38cSShri Abhyankar snes->reason = SNES_DIVERGED_LINEAR_SOLVE; 15842f63a38cSShri Abhyankar break; 15852f63a38cSShri Abhyankar } 15862f63a38cSShri Abhyankar } 15872f63a38cSShri Abhyankar 158856a221efSShri Abhyankar if(nis_act) { 158956a221efSShri Abhyankar PetscScalar *y1,*y2; 159056a221efSShri Abhyankar ierr = VecGetArray(Y,&y1);CHKERRQ(ierr); 159156a221efSShri Abhyankar ierr = VecGetArray(Y_aug,&y2);CHKERRQ(ierr); 159256a221efSShri Abhyankar /* Copy over inactive Y_aug to Y */ 159356a221efSShri Abhyankar j1 = 0; 159456a221efSShri Abhyankar for(i1=Y->map->rstart;i1 < Y->map->rend;i1++) { 159556a221efSShri Abhyankar if(j1 < nkept && idx_actkept[j1] == i1) j1++; 159656a221efSShri Abhyankar else y1[i1-Y->map->rstart] = y2[i1-Y->map->rstart]; 159756a221efSShri Abhyankar } 159856a221efSShri Abhyankar ierr = VecRestoreArray(Y,&y1);CHKERRQ(ierr); 159956a221efSShri Abhyankar ierr = VecRestoreArray(Y_aug,&y2);CHKERRQ(ierr); 16002f63a38cSShri Abhyankar 16016bf464f9SBarry Smith ierr = VecDestroy(&F_aug);CHKERRQ(ierr); 16026bf464f9SBarry Smith ierr = VecDestroy(&Y_aug);CHKERRQ(ierr); 16036bf464f9SBarry Smith ierr = MatDestroy(&J_aug);CHKERRQ(ierr); 160456a221efSShri Abhyankar ierr = PetscFree(idx_actkept);CHKERRQ(ierr); 160556a221efSShri Abhyankar } 160656a221efSShri Abhyankar 16072f63a38cSShri Abhyankar if (!isequal) { 16086bf464f9SBarry Smith ierr = ISDestroy(&vi->IS_inact_prev);CHKERRQ(ierr); 16092f63a38cSShri Abhyankar ierr = ISDuplicate(IS_inact,&vi->IS_inact_prev);CHKERRQ(ierr); 16102f63a38cSShri Abhyankar } 16116bf464f9SBarry Smith ierr = ISDestroy(&IS_inact);CHKERRQ(ierr); 161256a221efSShri Abhyankar 16132f63a38cSShri Abhyankar ierr = KSPGetIterationNumber(snes->ksp,&lits);CHKERRQ(ierr); 16142f63a38cSShri Abhyankar snes->linear_its += lits; 16152f63a38cSShri Abhyankar ierr = PetscInfo2(snes,"iter=%D, linear solve iterations=%D\n",snes->iter,lits);CHKERRQ(ierr); 16162f63a38cSShri Abhyankar /* 16172f63a38cSShri Abhyankar if (vi->precheckstep) { 16182f63a38cSShri Abhyankar PetscBool changed_y = PETSC_FALSE; 16192f63a38cSShri Abhyankar ierr = (*vi->precheckstep)(snes,X,Y,vi->precheck,&changed_y);CHKERRQ(ierr); 16202f63a38cSShri Abhyankar } 16212f63a38cSShri Abhyankar 16222f63a38cSShri Abhyankar if (PetscLogPrintInfo){ 16232f63a38cSShri Abhyankar ierr = SNESVICheckResidual_Private(snes,snes->jacobian,F,Y,G,W);CHKERRQ(ierr); 16242f63a38cSShri Abhyankar } 16252f63a38cSShri Abhyankar */ 16262f63a38cSShri Abhyankar /* Compute a (scaled) negative update in the line search routine: 16272f63a38cSShri Abhyankar Y <- X - lambda*Y 16282f63a38cSShri Abhyankar and evaluate G = function(Y) (depends on the line search). 16292f63a38cSShri Abhyankar */ 16302f63a38cSShri Abhyankar ierr = VecCopy(Y,snes->vec_sol_update);CHKERRQ(ierr); 16312f63a38cSShri Abhyankar ynorm = 1; gnorm = fnorm; 16322f63a38cSShri Abhyankar ierr = (*vi->LineSearch)(snes,vi->lsP,X,F,G,Y,W,fnorm,xnorm,&ynorm,&gnorm,&lssucceed);CHKERRQ(ierr); 16332f63a38cSShri Abhyankar ierr = PetscInfo4(snes,"fnorm=%18.16e, gnorm=%18.16e, ynorm=%18.16e, lssucceed=%d\n",fnorm,gnorm,ynorm,(int)lssucceed);CHKERRQ(ierr); 16342f63a38cSShri Abhyankar if (snes->reason == SNES_DIVERGED_FUNCTION_COUNT) break; 16352f63a38cSShri Abhyankar if (snes->domainerror) { 16362f63a38cSShri Abhyankar snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN; 16372f63a38cSShri Abhyankar PetscFunctionReturn(0); 16382f63a38cSShri Abhyankar } 16392f63a38cSShri Abhyankar if (!lssucceed) { 16402f63a38cSShri Abhyankar if (++snes->numFailures >= snes->maxFailures) { 16412f63a38cSShri Abhyankar PetscBool ismin; 16422f63a38cSShri Abhyankar snes->reason = SNES_DIVERGED_LINE_SEARCH; 16432f63a38cSShri Abhyankar ierr = SNESVICheckLocalMin_Private(snes,snes->jacobian,G,W,gnorm,&ismin);CHKERRQ(ierr); 16442f63a38cSShri Abhyankar if (ismin) snes->reason = SNES_DIVERGED_LOCAL_MIN; 16452f63a38cSShri Abhyankar break; 16462f63a38cSShri Abhyankar } 16472f63a38cSShri Abhyankar } 16482f63a38cSShri Abhyankar /* Update function and solution vectors */ 16492f63a38cSShri Abhyankar fnorm = gnorm; 16502f63a38cSShri Abhyankar ierr = VecCopy(G,F);CHKERRQ(ierr); 16512f63a38cSShri Abhyankar ierr = VecCopy(W,X);CHKERRQ(ierr); 16522f63a38cSShri Abhyankar /* Monitor convergence */ 16532f63a38cSShri Abhyankar ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 16542f63a38cSShri Abhyankar snes->iter = i+1; 16552f63a38cSShri Abhyankar snes->norm = fnorm; 16562f63a38cSShri Abhyankar ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 16572f63a38cSShri Abhyankar SNESLogConvHistory(snes,snes->norm,lits); 16587a03ce2fSLisandro Dalcin ierr = SNESMonitor(snes,snes->iter,snes->norm);CHKERRQ(ierr); 16592f63a38cSShri Abhyankar /* Test for convergence, xnorm = || X || */ 16602f63a38cSShri Abhyankar if (snes->ops->converged != SNESSkipConverged) { ierr = VecNorm(X,NORM_2,&xnorm);CHKERRQ(ierr); } 16612f63a38cSShri Abhyankar ierr = (*snes->ops->converged)(snes,snes->iter,xnorm,ynorm,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); 16622f63a38cSShri Abhyankar if (snes->reason) break; 16632f63a38cSShri Abhyankar } 16642f63a38cSShri Abhyankar if (i == maxits) { 16652f63a38cSShri Abhyankar ierr = PetscInfo1(snes,"Maximum number of iterations has been reached: %D\n",maxits);CHKERRQ(ierr); 16662f63a38cSShri Abhyankar if(!snes->reason) snes->reason = SNES_DIVERGED_MAX_IT; 16672f63a38cSShri Abhyankar } 16682f63a38cSShri Abhyankar PetscFunctionReturn(0); 16692f63a38cSShri Abhyankar } 16702f63a38cSShri Abhyankar 16712b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */ 16722b4ed282SShri Abhyankar /* 16732b4ed282SShri Abhyankar SNESSetUp_VI - Sets up the internal data structures for the later use 16742b4ed282SShri Abhyankar of the SNESVI nonlinear solver. 16752b4ed282SShri Abhyankar 16762b4ed282SShri Abhyankar Input Parameter: 16772b4ed282SShri Abhyankar . snes - the SNES context 16782b4ed282SShri Abhyankar . x - the solution vector 16792b4ed282SShri Abhyankar 16802b4ed282SShri Abhyankar Application Interface Routine: SNESSetUp() 16812b4ed282SShri Abhyankar 16822b4ed282SShri Abhyankar Notes: 16832b4ed282SShri Abhyankar For basic use of the SNES solvers, the user need not explicitly call 16842b4ed282SShri Abhyankar SNESSetUp(), since these actions will automatically occur during 16852b4ed282SShri Abhyankar the call to SNESSolve(). 16862b4ed282SShri Abhyankar */ 16872b4ed282SShri Abhyankar #undef __FUNCT__ 16882b4ed282SShri Abhyankar #define __FUNCT__ "SNESSetUp_VI" 16892b4ed282SShri Abhyankar PetscErrorCode SNESSetUp_VI(SNES snes) 16902b4ed282SShri Abhyankar { 16912b4ed282SShri Abhyankar PetscErrorCode ierr; 16922b4ed282SShri Abhyankar SNES_VI *vi = (SNES_VI*) snes->data; 16932b4ed282SShri Abhyankar PetscInt i_start[3],i_end[3]; 16942b4ed282SShri Abhyankar 16952b4ed282SShri Abhyankar PetscFunctionBegin; 169658c9b817SLisandro Dalcin 169758c9b817SLisandro Dalcin ierr = SNESDefaultGetWork(snes,3);CHKERRQ(ierr); 16982b4ed282SShri Abhyankar 16992b4ed282SShri Abhyankar /* If the lower and upper bound on variables are not set, set it to 17002b4ed282SShri Abhyankar -Inf and Inf */ 17012b4ed282SShri Abhyankar if (!vi->xl && !vi->xu) { 17022b4ed282SShri Abhyankar vi->usersetxbounds = PETSC_FALSE; 17032b4ed282SShri Abhyankar ierr = VecDuplicate(snes->vec_sol, &vi->xl); CHKERRQ(ierr); 170401f0b76bSBarry Smith ierr = VecSet(vi->xl,SNES_VI_NINF);CHKERRQ(ierr); 17052b4ed282SShri Abhyankar ierr = VecDuplicate(snes->vec_sol, &vi->xu); CHKERRQ(ierr); 170601f0b76bSBarry Smith ierr = VecSet(vi->xu,SNES_VI_INF);CHKERRQ(ierr); 17072b4ed282SShri Abhyankar } else { 17082b4ed282SShri Abhyankar /* Check if lower bound, upper bound and solution vector distribution across the processors is identical */ 17092b4ed282SShri Abhyankar ierr = VecGetOwnershipRange(snes->vec_sol,i_start,i_end);CHKERRQ(ierr); 17102b4ed282SShri Abhyankar ierr = VecGetOwnershipRange(vi->xl,i_start+1,i_end+1);CHKERRQ(ierr); 17112b4ed282SShri Abhyankar ierr = VecGetOwnershipRange(vi->xu,i_start+2,i_end+2);CHKERRQ(ierr); 17122b4ed282SShri 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])) 17132b4ed282SShri 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."); 17142b4ed282SShri Abhyankar } 17152f63a38cSShri Abhyankar if (snes->ops->solve != SNESSolveVI_SS) { 1716abcba341SShri Abhyankar /* Set up previous active index set for the first snes solve 1717abcba341SShri Abhyankar vi->IS_inact_prev = 0,1,2,....N */ 1718abcba341SShri Abhyankar PetscInt *indices; 1719abcba341SShri Abhyankar PetscInt i,n,rstart,rend; 1720abcba341SShri Abhyankar 1721abcba341SShri Abhyankar ierr = VecGetOwnershipRange(snes->vec_sol,&rstart,&rend);CHKERRQ(ierr); 1722abcba341SShri Abhyankar ierr = VecGetLocalSize(snes->vec_sol,&n);CHKERRQ(ierr); 1723abcba341SShri Abhyankar ierr = PetscMalloc(n*sizeof(PetscInt),&indices);CHKERRQ(ierr); 1724abcba341SShri Abhyankar for(i=0;i < n; i++) indices[i] = rstart + i; 1725abcba341SShri Abhyankar ierr = ISCreateGeneral(((PetscObject)snes)->comm,n,indices,PETSC_OWN_POINTER,&vi->IS_inact_prev); 1726abcba341SShri Abhyankar } 17272b4ed282SShri Abhyankar 17282f63a38cSShri Abhyankar if (snes->ops->solve == SNESSolveVI_SS) { 1729fe835674SShri Abhyankar ierr = VecDuplicate(snes->vec_sol, &vi->dpsi);CHKERRQ(ierr); 1730fe835674SShri Abhyankar ierr = VecDuplicate(snes->vec_sol, &vi->phi); CHKERRQ(ierr); 1731fe835674SShri Abhyankar ierr = VecDuplicate(snes->vec_sol, &vi->Da); CHKERRQ(ierr); 1732fe835674SShri Abhyankar ierr = VecDuplicate(snes->vec_sol, &vi->Db); CHKERRQ(ierr); 1733fe835674SShri Abhyankar ierr = VecDuplicate(snes->vec_sol, &vi->z);CHKERRQ(ierr); 1734fe835674SShri Abhyankar ierr = VecDuplicate(snes->vec_sol, &vi->t); CHKERRQ(ierr); 1735fe835674SShri Abhyankar } 17362b4ed282SShri Abhyankar PetscFunctionReturn(0); 17372b4ed282SShri Abhyankar } 17382b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */ 17392b4ed282SShri Abhyankar /* 17402b4ed282SShri Abhyankar SNESDestroy_VI - Destroys the private SNES_VI context that was created 17412b4ed282SShri Abhyankar with SNESCreate_VI(). 17422b4ed282SShri Abhyankar 17432b4ed282SShri Abhyankar Input Parameter: 17442b4ed282SShri Abhyankar . snes - the SNES context 17452b4ed282SShri Abhyankar 17462b4ed282SShri Abhyankar Application Interface Routine: SNESDestroy() 17472b4ed282SShri Abhyankar */ 17482b4ed282SShri Abhyankar #undef __FUNCT__ 17492b4ed282SShri Abhyankar #define __FUNCT__ "SNESDestroy_VI" 17502b4ed282SShri Abhyankar PetscErrorCode SNESDestroy_VI(SNES snes) 17512b4ed282SShri Abhyankar { 17522b4ed282SShri Abhyankar SNES_VI *vi = (SNES_VI*) snes->data; 17532b4ed282SShri Abhyankar PetscErrorCode ierr; 17542b4ed282SShri Abhyankar 17552b4ed282SShri Abhyankar PetscFunctionBegin; 17562f63a38cSShri Abhyankar if (snes->ops->solve != SNESSolveVI_SS) { 17576bf464f9SBarry Smith ierr = ISDestroy(&vi->IS_inact_prev); 1758abcba341SShri Abhyankar } 17592b4ed282SShri Abhyankar 17602f63a38cSShri Abhyankar if (snes->ops->solve == SNESSolveVI_SS) { 17612b4ed282SShri Abhyankar /* clear vectors */ 17626bf464f9SBarry Smith ierr = VecDestroy(&vi->dpsi);CHKERRQ(ierr); 17636bf464f9SBarry Smith ierr = VecDestroy(&vi->phi); CHKERRQ(ierr); 17646bf464f9SBarry Smith ierr = VecDestroy(&vi->Da); CHKERRQ(ierr); 17656bf464f9SBarry Smith ierr = VecDestroy(&vi->Db); CHKERRQ(ierr); 17666bf464f9SBarry Smith ierr = VecDestroy(&vi->z); CHKERRQ(ierr); 17676bf464f9SBarry Smith ierr = VecDestroy(&vi->t); CHKERRQ(ierr); 17687fe79bc4SShri Abhyankar } 17697fe79bc4SShri Abhyankar 17702b4ed282SShri Abhyankar if (!vi->usersetxbounds) { 17716bf464f9SBarry Smith ierr = VecDestroy(&vi->xl); CHKERRQ(ierr); 17726bf464f9SBarry Smith ierr = VecDestroy(&vi->xu); CHKERRQ(ierr); 17732b4ed282SShri Abhyankar } 17747fe79bc4SShri Abhyankar 17756bf464f9SBarry Smith ierr = PetscViewerASCIIMonitorDestroy(&vi->lsmonitor);CHKERRQ(ierr); 17762b4ed282SShri Abhyankar ierr = PetscFree(snes->data);CHKERRQ(ierr); 17772b4ed282SShri Abhyankar 17782b4ed282SShri Abhyankar /* clear composed functions */ 17792b4ed282SShri Abhyankar ierr = PetscObjectComposeFunctionDynamic((PetscObject)snes,"SNESLineSearchSet_C","",PETSC_NULL);CHKERRQ(ierr); 1780c92abb8aSShri Abhyankar ierr = PetscObjectComposeFunctionDynamic((PetscObject)snes,"SNESLineSearchSetMonitor_C","",PETSC_NULL);CHKERRQ(ierr); 17812b4ed282SShri Abhyankar PetscFunctionReturn(0); 17822b4ed282SShri Abhyankar } 17837fe79bc4SShri Abhyankar 17842b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */ 17852b4ed282SShri Abhyankar #undef __FUNCT__ 17862b4ed282SShri Abhyankar #define __FUNCT__ "SNESLineSearchNo_VI" 17872b4ed282SShri Abhyankar 17882b4ed282SShri Abhyankar /* 17897fe79bc4SShri Abhyankar This routine does not actually do a line search but it takes a full newton 17907fe79bc4SShri Abhyankar step while ensuring that the new iterates remain within the constraints. 17912b4ed282SShri Abhyankar 17922b4ed282SShri Abhyankar */ 1793ace3abfcSBarry 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) 17942b4ed282SShri Abhyankar { 17952b4ed282SShri Abhyankar PetscErrorCode ierr; 17962b4ed282SShri Abhyankar SNES_VI *vi = (SNES_VI*)snes->data; 1797ace3abfcSBarry Smith PetscBool changed_w = PETSC_FALSE,changed_y = PETSC_FALSE; 17982b4ed282SShri Abhyankar 17992b4ed282SShri Abhyankar PetscFunctionBegin; 18002b4ed282SShri Abhyankar *flag = PETSC_TRUE; 18012b4ed282SShri Abhyankar ierr = PetscLogEventBegin(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); 18022b4ed282SShri Abhyankar ierr = VecNorm(y,NORM_2,ynorm);CHKERRQ(ierr); /* ynorm = || y || */ 18032b4ed282SShri Abhyankar ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr); /* w <- x - y */ 1804c1a5e521SShri Abhyankar ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr); 1805c1a5e521SShri Abhyankar if (vi->postcheckstep) { 1806c1a5e521SShri Abhyankar ierr = (*vi->postcheckstep)(snes,x,y,w,vi->postcheck,&changed_y,&changed_w);CHKERRQ(ierr); 1807c1a5e521SShri Abhyankar } 1808c1a5e521SShri Abhyankar if (changed_y) { 1809c1a5e521SShri Abhyankar ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr); /* w <- x - y */ 18107fe79bc4SShri Abhyankar ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr); 1811c1a5e521SShri Abhyankar } 1812c1a5e521SShri Abhyankar ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr); 1813c1a5e521SShri Abhyankar ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr); 1814c1a5e521SShri Abhyankar if (!snes->domainerror) { 18152f63a38cSShri Abhyankar if (snes->ops->solve != SNESSolveVI_SS) { 18167fe79bc4SShri Abhyankar ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr); 18177fe79bc4SShri Abhyankar } else { 1818c1a5e521SShri Abhyankar ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr); /* gnorm = || g || */ 18197fe79bc4SShri Abhyankar } 182062cbcd01SMatthew G Knepley if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number"); 1821c1a5e521SShri Abhyankar } 1822c1a5e521SShri Abhyankar if (vi->lsmonitor) { 1823c1a5e521SShri Abhyankar ierr = PetscViewerASCIIMonitorPrintf(vi->lsmonitor," Line search: Using full step: fnorm %G gnorm %G\n",fnorm,*gnorm);CHKERRQ(ierr); 1824c1a5e521SShri Abhyankar } 1825c1a5e521SShri Abhyankar ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); 1826c1a5e521SShri Abhyankar PetscFunctionReturn(0); 1827c1a5e521SShri Abhyankar } 1828c1a5e521SShri Abhyankar 1829c1a5e521SShri Abhyankar /* -------------------------------------------------------------------------- */ 1830c1a5e521SShri Abhyankar #undef __FUNCT__ 18312b4ed282SShri Abhyankar #define __FUNCT__ "SNESLineSearchNoNorms_VI" 18322b4ed282SShri Abhyankar 18332b4ed282SShri Abhyankar /* 18342b4ed282SShri Abhyankar This routine is a copy of SNESLineSearchNoNorms in snes/impls/ls/ls.c 18352b4ed282SShri Abhyankar */ 1836ace3abfcSBarry 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) 18372b4ed282SShri Abhyankar { 18382b4ed282SShri Abhyankar PetscErrorCode ierr; 18392b4ed282SShri Abhyankar SNES_VI *vi = (SNES_VI*)snes->data; 1840ace3abfcSBarry Smith PetscBool changed_w = PETSC_FALSE,changed_y = PETSC_FALSE; 18412b4ed282SShri Abhyankar 18422b4ed282SShri Abhyankar PetscFunctionBegin; 18432b4ed282SShri Abhyankar *flag = PETSC_TRUE; 18442b4ed282SShri Abhyankar ierr = PetscLogEventBegin(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); 18452b4ed282SShri Abhyankar ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr); /* w <- x - y */ 18467fe79bc4SShri Abhyankar ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr); 18472b4ed282SShri Abhyankar if (vi->postcheckstep) { 18482b4ed282SShri Abhyankar ierr = (*vi->postcheckstep)(snes,x,y,w,vi->postcheck,&changed_y,&changed_w);CHKERRQ(ierr); 18492b4ed282SShri Abhyankar } 18502b4ed282SShri Abhyankar if (changed_y) { 18512b4ed282SShri Abhyankar ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr); /* w <- x - y */ 18527fe79bc4SShri Abhyankar ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr); 18532b4ed282SShri Abhyankar } 18542b4ed282SShri Abhyankar 18552b4ed282SShri Abhyankar /* don't evaluate function the last time through */ 18562b4ed282SShri Abhyankar if (snes->iter < snes->max_its-1) { 18572b4ed282SShri Abhyankar ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr); 18582b4ed282SShri Abhyankar } 18592b4ed282SShri Abhyankar ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); 18602b4ed282SShri Abhyankar PetscFunctionReturn(0); 18612b4ed282SShri Abhyankar } 18627fe79bc4SShri Abhyankar 18632b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */ 18642b4ed282SShri Abhyankar #undef __FUNCT__ 18652b4ed282SShri Abhyankar #define __FUNCT__ "SNESLineSearchCubic_VI" 18662b4ed282SShri Abhyankar /* 18677fe79bc4SShri Abhyankar This routine implements a cubic line search while doing a projection on the variable bounds 18682b4ed282SShri Abhyankar */ 1869ace3abfcSBarry 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) 18702b4ed282SShri Abhyankar { 1871fe835674SShri Abhyankar PetscReal initslope,lambdaprev,gnormprev,a,b,d,t1,t2,rellength; 1872fe835674SShri Abhyankar PetscReal minlambda,lambda,lambdatemp; 1873fe835674SShri Abhyankar #if defined(PETSC_USE_COMPLEX) 1874fe835674SShri Abhyankar PetscScalar cinitslope; 1875fe835674SShri Abhyankar #endif 1876fe835674SShri Abhyankar PetscErrorCode ierr; 1877fe835674SShri Abhyankar PetscInt count; 1878fe835674SShri Abhyankar SNES_VI *vi = (SNES_VI*)snes->data; 1879fe835674SShri Abhyankar PetscBool changed_w = PETSC_FALSE,changed_y = PETSC_FALSE; 1880fe835674SShri Abhyankar MPI_Comm comm; 1881fe835674SShri Abhyankar 1882fe835674SShri Abhyankar PetscFunctionBegin; 1883fe835674SShri Abhyankar ierr = PetscObjectGetComm((PetscObject)snes,&comm);CHKERRQ(ierr); 1884fe835674SShri Abhyankar ierr = PetscLogEventBegin(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); 1885fe835674SShri Abhyankar *flag = PETSC_TRUE; 1886fe835674SShri Abhyankar 1887fe835674SShri Abhyankar ierr = VecNorm(y,NORM_2,ynorm);CHKERRQ(ierr); 1888fe835674SShri Abhyankar if (*ynorm == 0.0) { 1889fe835674SShri Abhyankar if (vi->lsmonitor) { 1890fe835674SShri Abhyankar ierr = PetscViewerASCIIMonitorPrintf(vi->lsmonitor," Line search: Initial direction and size is 0\n");CHKERRQ(ierr); 1891fe835674SShri Abhyankar } 1892fe835674SShri Abhyankar *gnorm = fnorm; 1893fe835674SShri Abhyankar ierr = VecCopy(x,w);CHKERRQ(ierr); 1894fe835674SShri Abhyankar ierr = VecCopy(f,g);CHKERRQ(ierr); 1895fe835674SShri Abhyankar *flag = PETSC_FALSE; 1896fe835674SShri Abhyankar goto theend1; 1897fe835674SShri Abhyankar } 1898fe835674SShri Abhyankar if (*ynorm > vi->maxstep) { /* Step too big, so scale back */ 1899fe835674SShri Abhyankar if (vi->lsmonitor) { 1900fe835674SShri Abhyankar ierr = PetscViewerASCIIMonitorPrintf(vi->lsmonitor," Line search: Scaling step by %G old ynorm %G\n",vi->maxstep/(*ynorm),*ynorm);CHKERRQ(ierr); 1901fe835674SShri Abhyankar } 1902fe835674SShri Abhyankar ierr = VecScale(y,vi->maxstep/(*ynorm));CHKERRQ(ierr); 1903fe835674SShri Abhyankar *ynorm = vi->maxstep; 1904fe835674SShri Abhyankar } 1905fe835674SShri Abhyankar ierr = VecMaxPointwiseDivide(y,x,&rellength);CHKERRQ(ierr); 1906fe835674SShri Abhyankar minlambda = vi->minlambda/rellength; 1907fe835674SShri Abhyankar ierr = MatMult(snes->jacobian,y,w);CHKERRQ(ierr); 1908fe835674SShri Abhyankar #if defined(PETSC_USE_COMPLEX) 1909fe835674SShri Abhyankar ierr = VecDot(f,w,&cinitslope);CHKERRQ(ierr); 1910fe835674SShri Abhyankar initslope = PetscRealPart(cinitslope); 1911fe835674SShri Abhyankar #else 1912fe835674SShri Abhyankar ierr = VecDot(f,w,&initslope);CHKERRQ(ierr); 1913fe835674SShri Abhyankar #endif 1914fe835674SShri Abhyankar if (initslope > 0.0) initslope = -initslope; 1915fe835674SShri Abhyankar if (initslope == 0.0) initslope = -1.0; 1916fe835674SShri Abhyankar 1917fe835674SShri Abhyankar ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr); 1918fe835674SShri Abhyankar ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr); 1919fe835674SShri Abhyankar if (snes->nfuncs >= snes->max_funcs) { 1920fe835674SShri Abhyankar ierr = PetscInfo(snes,"Exceeded maximum function evaluations, while checking full step length!\n");CHKERRQ(ierr); 1921fe835674SShri Abhyankar *flag = PETSC_FALSE; 1922fe835674SShri Abhyankar snes->reason = SNES_DIVERGED_FUNCTION_COUNT; 1923fe835674SShri Abhyankar goto theend1; 1924fe835674SShri Abhyankar } 1925fe835674SShri Abhyankar ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr); 19262f63a38cSShri Abhyankar if (snes->ops->solve != SNESSolveVI_SS) { 1927fe835674SShri Abhyankar ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr); 19287fe79bc4SShri Abhyankar } else { 19297fe79bc4SShri Abhyankar ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr); 19307fe79bc4SShri Abhyankar } 1931fe835674SShri Abhyankar if (snes->domainerror) { 1932fe835674SShri Abhyankar ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); 1933fe835674SShri Abhyankar PetscFunctionReturn(0); 1934fe835674SShri Abhyankar } 193562cbcd01SMatthew G Knepley if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number"); 1936fe835674SShri Abhyankar ierr = PetscInfo2(snes,"Initial fnorm %G gnorm %G\n",fnorm,*gnorm);CHKERRQ(ierr); 1937fe835674SShri Abhyankar if (.5*(*gnorm)*(*gnorm) <= .5*fnorm*fnorm + vi->alpha*initslope) { /* Sufficient reduction */ 1938fe835674SShri Abhyankar if (vi->lsmonitor) { 1939fe835674SShri Abhyankar ierr = PetscViewerASCIIMonitorPrintf(vi->lsmonitor," Line search: Using full step: fnorm %G gnorm %G\n",fnorm,*gnorm);CHKERRQ(ierr); 1940fe835674SShri Abhyankar } 1941fe835674SShri Abhyankar goto theend1; 1942fe835674SShri Abhyankar } 1943fe835674SShri Abhyankar 1944fe835674SShri Abhyankar /* Fit points with quadratic */ 1945fe835674SShri Abhyankar lambda = 1.0; 1946fe835674SShri Abhyankar lambdatemp = -initslope/((*gnorm)*(*gnorm) - fnorm*fnorm - 2.0*initslope); 1947fe835674SShri Abhyankar lambdaprev = lambda; 1948fe835674SShri Abhyankar gnormprev = *gnorm; 1949fe835674SShri Abhyankar if (lambdatemp > .5*lambda) lambdatemp = .5*lambda; 1950fe835674SShri Abhyankar if (lambdatemp <= .1*lambda) lambda = .1*lambda; 1951fe835674SShri Abhyankar else lambda = lambdatemp; 1952fe835674SShri Abhyankar 1953fe835674SShri Abhyankar ierr = VecWAXPY(w,-lambda,y,x);CHKERRQ(ierr); 1954fe835674SShri Abhyankar ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr); 1955fe835674SShri Abhyankar if (snes->nfuncs >= snes->max_funcs) { 1956fe835674SShri Abhyankar ierr = PetscInfo1(snes,"Exceeded maximum function evaluations, while attempting quadratic backtracking! %D \n",snes->nfuncs);CHKERRQ(ierr); 1957fe835674SShri Abhyankar *flag = PETSC_FALSE; 1958fe835674SShri Abhyankar snes->reason = SNES_DIVERGED_FUNCTION_COUNT; 1959fe835674SShri Abhyankar goto theend1; 1960fe835674SShri Abhyankar } 1961fe835674SShri Abhyankar ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr); 19622f63a38cSShri Abhyankar if (snes->ops->solve != SNESSolveVI_SS) { 1963fe835674SShri Abhyankar ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr); 19647fe79bc4SShri Abhyankar } else { 19657fe79bc4SShri Abhyankar ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr); 19667fe79bc4SShri Abhyankar } 1967fe835674SShri Abhyankar if (snes->domainerror) { 1968fe835674SShri Abhyankar ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); 1969fe835674SShri Abhyankar PetscFunctionReturn(0); 1970fe835674SShri Abhyankar } 197162cbcd01SMatthew G Knepley if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number"); 1972fe835674SShri Abhyankar if (vi->lsmonitor) { 1973fe835674SShri Abhyankar ierr = PetscViewerASCIIMonitorPrintf(vi->lsmonitor," Line search: gnorm after quadratic fit %G\n",*gnorm);CHKERRQ(ierr); 1974fe835674SShri Abhyankar } 1975fe835674SShri Abhyankar if (.5*(*gnorm)*(*gnorm) < .5*fnorm*fnorm + lambda*vi->alpha*initslope) { /* sufficient reduction */ 1976fe835674SShri Abhyankar if (vi->lsmonitor) { 1977fe835674SShri Abhyankar ierr = PetscViewerASCIIMonitorPrintf(vi->lsmonitor," Line search: Quadratically determined step, lambda=%18.16e\n",lambda);CHKERRQ(ierr); 1978fe835674SShri Abhyankar } 1979fe835674SShri Abhyankar goto theend1; 1980fe835674SShri Abhyankar } 1981fe835674SShri Abhyankar 1982fe835674SShri Abhyankar /* Fit points with cubic */ 1983fe835674SShri Abhyankar count = 1; 1984fe835674SShri Abhyankar while (PETSC_TRUE) { 1985fe835674SShri Abhyankar if (lambda <= minlambda) { 1986fe835674SShri Abhyankar if (vi->lsmonitor) { 1987fe835674SShri Abhyankar ierr = PetscViewerASCIIMonitorPrintf(vi->lsmonitor," Line search: unable to find good step length! After %D tries \n",count);CHKERRQ(ierr); 1988fe835674SShri Abhyankar ierr = PetscViewerASCIIMonitorPrintf(vi->lsmonitor," Line search: fnorm=%18.16e, gnorm=%18.16e, ynorm=%18.16e, minlambda=%18.16e, lambda=%18.16e, initial slope=%18.16e\n",fnorm,*gnorm,*ynorm,minlambda,lambda,initslope);CHKERRQ(ierr); 1989fe835674SShri Abhyankar } 1990fe835674SShri Abhyankar *flag = PETSC_FALSE; 1991fe835674SShri Abhyankar break; 1992fe835674SShri Abhyankar } 1993fe835674SShri Abhyankar t1 = .5*((*gnorm)*(*gnorm) - fnorm*fnorm) - lambda*initslope; 1994fe835674SShri Abhyankar t2 = .5*(gnormprev*gnormprev - fnorm*fnorm) - lambdaprev*initslope; 1995fe835674SShri Abhyankar a = (t1/(lambda*lambda) - t2/(lambdaprev*lambdaprev))/(lambda-lambdaprev); 1996fe835674SShri Abhyankar b = (-lambdaprev*t1/(lambda*lambda) + lambda*t2/(lambdaprev*lambdaprev))/(lambda-lambdaprev); 1997fe835674SShri Abhyankar d = b*b - 3*a*initslope; 1998fe835674SShri Abhyankar if (d < 0.0) d = 0.0; 1999fe835674SShri Abhyankar if (a == 0.0) { 2000fe835674SShri Abhyankar lambdatemp = -initslope/(2.0*b); 2001fe835674SShri Abhyankar } else { 2002fe835674SShri Abhyankar lambdatemp = (-b + sqrt(d))/(3.0*a); 2003fe835674SShri Abhyankar } 2004fe835674SShri Abhyankar lambdaprev = lambda; 2005fe835674SShri Abhyankar gnormprev = *gnorm; 2006fe835674SShri Abhyankar if (lambdatemp > .5*lambda) lambdatemp = .5*lambda; 2007fe835674SShri Abhyankar if (lambdatemp <= .1*lambda) lambda = .1*lambda; 2008fe835674SShri Abhyankar else lambda = lambdatemp; 2009fe835674SShri Abhyankar ierr = VecWAXPY(w,-lambda,y,x);CHKERRQ(ierr); 2010fe835674SShri Abhyankar ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr); 2011fe835674SShri Abhyankar if (snes->nfuncs >= snes->max_funcs) { 2012fe835674SShri Abhyankar ierr = PetscInfo1(snes,"Exceeded maximum function evaluations, while looking for good step length! %D \n",count);CHKERRQ(ierr); 2013fe835674SShri 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); 2014fe835674SShri Abhyankar *flag = PETSC_FALSE; 2015fe835674SShri Abhyankar snes->reason = SNES_DIVERGED_FUNCTION_COUNT; 2016fe835674SShri Abhyankar break; 2017fe835674SShri Abhyankar } 2018fe835674SShri Abhyankar ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr); 20192f63a38cSShri Abhyankar if (snes->ops->solve != SNESSolveVI_SS) { 2020fe835674SShri Abhyankar ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr); 20217fe79bc4SShri Abhyankar } else { 20227fe79bc4SShri Abhyankar ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr); 20237fe79bc4SShri Abhyankar } 2024fe835674SShri Abhyankar if (snes->domainerror) { 2025fe835674SShri Abhyankar ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); 2026fe835674SShri Abhyankar PetscFunctionReturn(0); 2027fe835674SShri Abhyankar } 202862cbcd01SMatthew G Knepley if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number"); 2029fe835674SShri Abhyankar if (.5*(*gnorm)*(*gnorm) < .5*fnorm*fnorm + lambda*vi->alpha*initslope) { /* is reduction enough? */ 2030fe835674SShri Abhyankar if (vi->lsmonitor) { 2031fe835674SShri Abhyankar ierr = PetscPrintf(comm," Line search: Cubically determined step, current gnorm %G lambda=%18.16e\n",*gnorm,lambda);CHKERRQ(ierr); 2032fe835674SShri Abhyankar } 2033fe835674SShri Abhyankar break; 2034fe835674SShri Abhyankar } else { 2035fe835674SShri Abhyankar if (vi->lsmonitor) { 2036fe835674SShri Abhyankar ierr = PetscPrintf(comm," Line search: Cubic step no good, shrinking lambda, current gnorm %G lambda=%18.16e\n",*gnorm,lambda);CHKERRQ(ierr); 2037fe835674SShri Abhyankar } 2038fe835674SShri Abhyankar } 2039fe835674SShri Abhyankar count++; 2040fe835674SShri Abhyankar } 2041fe835674SShri Abhyankar theend1: 2042fe835674SShri Abhyankar /* Optional user-defined check for line search step validity */ 2043fe835674SShri Abhyankar if (vi->postcheckstep && *flag) { 2044fe835674SShri Abhyankar ierr = (*vi->postcheckstep)(snes,x,y,w,vi->postcheck,&changed_y,&changed_w);CHKERRQ(ierr); 2045fe835674SShri Abhyankar if (changed_y) { 2046fe835674SShri Abhyankar ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr); 2047fe835674SShri Abhyankar ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr); 2048fe835674SShri Abhyankar } 2049fe835674SShri Abhyankar if (changed_y || changed_w) { /* recompute the function if the step has changed */ 2050fe835674SShri Abhyankar ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr); 20512f63a38cSShri Abhyankar if (snes->ops->solve != SNESSolveVI_SS) { 2052fe835674SShri Abhyankar ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr); 20537fe79bc4SShri Abhyankar } else { 20547fe79bc4SShri Abhyankar ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr); 20557fe79bc4SShri Abhyankar } 2056fe835674SShri Abhyankar if (snes->domainerror) { 2057fe835674SShri Abhyankar ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); 2058fe835674SShri Abhyankar PetscFunctionReturn(0); 2059fe835674SShri Abhyankar } 206062cbcd01SMatthew G Knepley if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number"); 2061fe835674SShri Abhyankar ierr = VecNormBegin(y,NORM_2,ynorm);CHKERRQ(ierr); 2062fe835674SShri Abhyankar ierr = VecNormEnd(y,NORM_2,ynorm);CHKERRQ(ierr); 2063fe835674SShri Abhyankar } 2064fe835674SShri Abhyankar } 2065fe835674SShri Abhyankar ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); 2066fe835674SShri Abhyankar PetscFunctionReturn(0); 2067fe835674SShri Abhyankar } 2068fe835674SShri Abhyankar 20692b4ed282SShri Abhyankar #undef __FUNCT__ 20702b4ed282SShri Abhyankar #define __FUNCT__ "SNESLineSearchQuadratic_VI" 20712b4ed282SShri Abhyankar /* 20727fe79bc4SShri Abhyankar This routine does a quadratic line search while keeping the iterates within the variable bounds 20732b4ed282SShri Abhyankar */ 2074ace3abfcSBarry 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) 20752b4ed282SShri Abhyankar { 20762b4ed282SShri Abhyankar /* 20772b4ed282SShri Abhyankar Note that for line search purposes we work with with the related 20782b4ed282SShri Abhyankar minimization problem: 20792b4ed282SShri Abhyankar min z(x): R^n -> R, 20802b4ed282SShri Abhyankar where z(x) = .5 * fnorm*fnorm,and fnorm = || f ||_2. 20812b4ed282SShri Abhyankar */ 20822b4ed282SShri Abhyankar PetscReal initslope,minlambda,lambda,lambdatemp,rellength; 20832b4ed282SShri Abhyankar #if defined(PETSC_USE_COMPLEX) 20842b4ed282SShri Abhyankar PetscScalar cinitslope; 20852b4ed282SShri Abhyankar #endif 20862b4ed282SShri Abhyankar PetscErrorCode ierr; 20872b4ed282SShri Abhyankar PetscInt count; 20882b4ed282SShri Abhyankar SNES_VI *vi = (SNES_VI*)snes->data; 2089ace3abfcSBarry Smith PetscBool changed_w = PETSC_FALSE,changed_y = PETSC_FALSE; 20902b4ed282SShri Abhyankar 20912b4ed282SShri Abhyankar PetscFunctionBegin; 20922b4ed282SShri Abhyankar ierr = PetscLogEventBegin(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); 20932b4ed282SShri Abhyankar *flag = PETSC_TRUE; 20942b4ed282SShri Abhyankar 20952b4ed282SShri Abhyankar ierr = VecNorm(y,NORM_2,ynorm);CHKERRQ(ierr); 20962b4ed282SShri Abhyankar if (*ynorm == 0.0) { 2097c92abb8aSShri Abhyankar if (vi->lsmonitor) { 2098c92abb8aSShri Abhyankar ierr = PetscViewerASCIIMonitorPrintf(vi->lsmonitor,"Line search: Direction and size is 0\n");CHKERRQ(ierr); 20992b4ed282SShri Abhyankar } 21002b4ed282SShri Abhyankar *gnorm = fnorm; 21012b4ed282SShri Abhyankar ierr = VecCopy(x,w);CHKERRQ(ierr); 21022b4ed282SShri Abhyankar ierr = VecCopy(f,g);CHKERRQ(ierr); 21032b4ed282SShri Abhyankar *flag = PETSC_FALSE; 21042b4ed282SShri Abhyankar goto theend2; 21052b4ed282SShri Abhyankar } 21062b4ed282SShri Abhyankar if (*ynorm > vi->maxstep) { /* Step too big, so scale back */ 21072b4ed282SShri Abhyankar ierr = VecScale(y,vi->maxstep/(*ynorm));CHKERRQ(ierr); 21082b4ed282SShri Abhyankar *ynorm = vi->maxstep; 21092b4ed282SShri Abhyankar } 21102b4ed282SShri Abhyankar ierr = VecMaxPointwiseDivide(y,x,&rellength);CHKERRQ(ierr); 21112b4ed282SShri Abhyankar minlambda = vi->minlambda/rellength; 21127fe79bc4SShri Abhyankar ierr = MatMult(snes->jacobian,y,w);CHKERRQ(ierr); 21132b4ed282SShri Abhyankar #if defined(PETSC_USE_COMPLEX) 21147fe79bc4SShri Abhyankar ierr = VecDot(f,w,&cinitslope);CHKERRQ(ierr); 21152b4ed282SShri Abhyankar initslope = PetscRealPart(cinitslope); 21162b4ed282SShri Abhyankar #else 21177fe79bc4SShri Abhyankar ierr = VecDot(f,w,&initslope);CHKERRQ(ierr); 21182b4ed282SShri Abhyankar #endif 21192b4ed282SShri Abhyankar if (initslope > 0.0) initslope = -initslope; 21202b4ed282SShri Abhyankar if (initslope == 0.0) initslope = -1.0; 21212b4ed282SShri Abhyankar ierr = PetscInfo1(snes,"Initslope %G \n",initslope);CHKERRQ(ierr); 21222b4ed282SShri Abhyankar 21232b4ed282SShri Abhyankar ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr); 21247fe79bc4SShri Abhyankar ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr); 21252b4ed282SShri Abhyankar if (snes->nfuncs >= snes->max_funcs) { 21262b4ed282SShri Abhyankar ierr = PetscInfo(snes,"Exceeded maximum function evaluations, while checking full step length!\n");CHKERRQ(ierr); 21272b4ed282SShri Abhyankar *flag = PETSC_FALSE; 21282b4ed282SShri Abhyankar snes->reason = SNES_DIVERGED_FUNCTION_COUNT; 21292b4ed282SShri Abhyankar goto theend2; 21302b4ed282SShri Abhyankar } 21312b4ed282SShri Abhyankar ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr); 21322f63a38cSShri Abhyankar if (snes->ops->solve != SNESSolveVI_SS) { 21337fe79bc4SShri Abhyankar ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr); 21347fe79bc4SShri Abhyankar } else { 21357fe79bc4SShri Abhyankar ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr); 21367fe79bc4SShri Abhyankar } 21372b4ed282SShri Abhyankar if (snes->domainerror) { 21382b4ed282SShri Abhyankar ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); 21392b4ed282SShri Abhyankar PetscFunctionReturn(0); 21402b4ed282SShri Abhyankar } 214162cbcd01SMatthew G Knepley if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number"); 21422b4ed282SShri Abhyankar if (.5*(*gnorm)*(*gnorm) <= .5*fnorm*fnorm + vi->alpha*initslope) { /* Sufficient reduction */ 2143c92abb8aSShri Abhyankar if (vi->lsmonitor) { 2144c92abb8aSShri Abhyankar ierr = PetscViewerASCIIMonitorPrintf(vi->lsmonitor," Line search: Using full step: fnorm %G gnorm %G\n",fnorm,*gnorm);CHKERRQ(ierr); 21452b4ed282SShri Abhyankar } 21462b4ed282SShri Abhyankar goto theend2; 21472b4ed282SShri Abhyankar } 21482b4ed282SShri Abhyankar 21492b4ed282SShri Abhyankar /* Fit points with quadratic */ 21502b4ed282SShri Abhyankar lambda = 1.0; 21512b4ed282SShri Abhyankar count = 1; 21522b4ed282SShri Abhyankar while (PETSC_TRUE) { 21532b4ed282SShri Abhyankar if (lambda <= minlambda) { /* bad luck; use full step */ 2154c92abb8aSShri Abhyankar if (vi->lsmonitor) { 2155c92abb8aSShri Abhyankar ierr = PetscViewerASCIIMonitorPrintf(vi->lsmonitor,"Line search: Unable to find good step length! %D \n",count);CHKERRQ(ierr); 2156c92abb8aSShri Abhyankar ierr = PetscViewerASCIIMonitorPrintf(vi->lsmonitor,"Line search: fnorm=%G, gnorm=%G, ynorm=%G, lambda=%G, initial slope=%G\n",fnorm,*gnorm,*ynorm,lambda,initslope);CHKERRQ(ierr); 21572b4ed282SShri Abhyankar } 21582b4ed282SShri Abhyankar ierr = VecCopy(x,w);CHKERRQ(ierr); 21592b4ed282SShri Abhyankar *flag = PETSC_FALSE; 21602b4ed282SShri Abhyankar break; 21612b4ed282SShri Abhyankar } 21622b4ed282SShri Abhyankar lambdatemp = -initslope/((*gnorm)*(*gnorm) - fnorm*fnorm - 2.0*initslope); 21632b4ed282SShri Abhyankar if (lambdatemp > .5*lambda) lambdatemp = .5*lambda; 21642b4ed282SShri Abhyankar if (lambdatemp <= .1*lambda) lambda = .1*lambda; 21652b4ed282SShri Abhyankar else lambda = lambdatemp; 21662b4ed282SShri Abhyankar 21672b4ed282SShri Abhyankar ierr = VecWAXPY(w,-lambda,y,x);CHKERRQ(ierr); 21687fe79bc4SShri Abhyankar ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr); 21692b4ed282SShri Abhyankar if (snes->nfuncs >= snes->max_funcs) { 21702b4ed282SShri Abhyankar ierr = PetscInfo1(snes,"Exceeded maximum function evaluations, while looking for good step length! %D \n",count);CHKERRQ(ierr); 21712b4ed282SShri 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); 21722b4ed282SShri Abhyankar *flag = PETSC_FALSE; 21732b4ed282SShri Abhyankar snes->reason = SNES_DIVERGED_FUNCTION_COUNT; 21742b4ed282SShri Abhyankar break; 21752b4ed282SShri Abhyankar } 21762b4ed282SShri Abhyankar ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr); 21772b4ed282SShri Abhyankar if (snes->domainerror) { 21782b4ed282SShri Abhyankar ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); 21792b4ed282SShri Abhyankar PetscFunctionReturn(0); 21802b4ed282SShri Abhyankar } 21812f63a38cSShri Abhyankar if (snes->ops->solve != SNESSolveVI_SS) { 21827fe79bc4SShri Abhyankar ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr); 21837fe79bc4SShri Abhyankar } else { 21842b4ed282SShri Abhyankar ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr); 21857fe79bc4SShri Abhyankar } 218662cbcd01SMatthew G Knepley if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number"); 21872b4ed282SShri Abhyankar if (.5*(*gnorm)*(*gnorm) < .5*fnorm*fnorm + lambda*vi->alpha*initslope) { /* sufficient reduction */ 2188c92abb8aSShri Abhyankar if (vi->lsmonitor) { 2189c92abb8aSShri Abhyankar ierr = PetscViewerASCIIMonitorPrintf(vi->lsmonitor," Line Search: Quadratically determined step, lambda=%G\n",lambda);CHKERRQ(ierr); 21902b4ed282SShri Abhyankar } 21912b4ed282SShri Abhyankar break; 21922b4ed282SShri Abhyankar } 21932b4ed282SShri Abhyankar count++; 21942b4ed282SShri Abhyankar } 21952b4ed282SShri Abhyankar theend2: 21962b4ed282SShri Abhyankar /* Optional user-defined check for line search step validity */ 21972b4ed282SShri Abhyankar if (vi->postcheckstep) { 21982b4ed282SShri Abhyankar ierr = (*vi->postcheckstep)(snes,x,y,w,vi->postcheck,&changed_y,&changed_w);CHKERRQ(ierr); 21992b4ed282SShri Abhyankar if (changed_y) { 22002b4ed282SShri Abhyankar ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr); 22017fe79bc4SShri Abhyankar ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr); 22022b4ed282SShri Abhyankar } 22032b4ed282SShri Abhyankar if (changed_y || changed_w) { /* recompute the function if the step has changed */ 22042b4ed282SShri Abhyankar ierr = SNESComputeFunction(snes,w,g); 22052b4ed282SShri Abhyankar if (snes->domainerror) { 22062b4ed282SShri Abhyankar ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); 22072b4ed282SShri Abhyankar PetscFunctionReturn(0); 22082b4ed282SShri Abhyankar } 22092f63a38cSShri Abhyankar if (snes->ops->solve != SNESSolveVI_SS) { 22107fe79bc4SShri Abhyankar ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr); 22117fe79bc4SShri Abhyankar } else { 22127fe79bc4SShri Abhyankar ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr); 22137fe79bc4SShri Abhyankar } 22147fe79bc4SShri Abhyankar 22152b4ed282SShri Abhyankar ierr = VecNormBegin(y,NORM_2,ynorm);CHKERRQ(ierr); 22162b4ed282SShri Abhyankar ierr = VecNormEnd(y,NORM_2,ynorm);CHKERRQ(ierr); 221762cbcd01SMatthew G Knepley if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number"); 22182b4ed282SShri Abhyankar } 22192b4ed282SShri Abhyankar } 22202b4ed282SShri Abhyankar ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); 22212b4ed282SShri Abhyankar PetscFunctionReturn(0); 22222b4ed282SShri Abhyankar } 22232b4ed282SShri Abhyankar 2224ace3abfcSBarry 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*/ 22252b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */ 22262b4ed282SShri Abhyankar EXTERN_C_BEGIN 22272b4ed282SShri Abhyankar #undef __FUNCT__ 22282b4ed282SShri Abhyankar #define __FUNCT__ "SNESLineSearchSet_VI" 22297087cfbeSBarry Smith PetscErrorCode SNESLineSearchSet_VI(SNES snes,FCN2 func,void *lsctx) 22302b4ed282SShri Abhyankar { 22312b4ed282SShri Abhyankar PetscFunctionBegin; 22322b4ed282SShri Abhyankar ((SNES_VI *)(snes->data))->LineSearch = func; 22332b4ed282SShri Abhyankar ((SNES_VI *)(snes->data))->lsP = lsctx; 22342b4ed282SShri Abhyankar PetscFunctionReturn(0); 22352b4ed282SShri Abhyankar } 22362b4ed282SShri Abhyankar EXTERN_C_END 22372b4ed282SShri Abhyankar 22382b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */ 22392b4ed282SShri Abhyankar EXTERN_C_BEGIN 22402b4ed282SShri Abhyankar #undef __FUNCT__ 22412b4ed282SShri Abhyankar #define __FUNCT__ "SNESLineSearchSetMonitor_VI" 22427087cfbeSBarry Smith PetscErrorCode SNESLineSearchSetMonitor_VI(SNES snes,PetscBool flg) 22432b4ed282SShri Abhyankar { 22442b4ed282SShri Abhyankar SNES_VI *vi = (SNES_VI*)snes->data; 22452b4ed282SShri Abhyankar PetscErrorCode ierr; 22462b4ed282SShri Abhyankar 22472b4ed282SShri Abhyankar PetscFunctionBegin; 2248c92abb8aSShri Abhyankar if (flg && !vi->lsmonitor) { 2249c92abb8aSShri Abhyankar ierr = PetscViewerASCIIMonitorCreate(((PetscObject)snes)->comm,"stdout",((PetscObject)snes)->tablevel,&vi->lsmonitor);CHKERRQ(ierr); 2250c92abb8aSShri Abhyankar } else if (!flg && vi->lsmonitor) { 22516bf464f9SBarry Smith ierr = PetscViewerASCIIMonitorDestroy(&vi->lsmonitor);CHKERRQ(ierr); 22522b4ed282SShri Abhyankar } 22532b4ed282SShri Abhyankar PetscFunctionReturn(0); 22542b4ed282SShri Abhyankar } 22552b4ed282SShri Abhyankar EXTERN_C_END 22562b4ed282SShri Abhyankar 22572b4ed282SShri Abhyankar /* 22582b4ed282SShri Abhyankar SNESView_VI - Prints info from the SNESVI data structure. 22592b4ed282SShri Abhyankar 22602b4ed282SShri Abhyankar Input Parameters: 22612b4ed282SShri Abhyankar . SNES - the SNES context 22622b4ed282SShri Abhyankar . viewer - visualization context 22632b4ed282SShri Abhyankar 22642b4ed282SShri Abhyankar Application Interface Routine: SNESView() 22652b4ed282SShri Abhyankar */ 22662b4ed282SShri Abhyankar #undef __FUNCT__ 22672b4ed282SShri Abhyankar #define __FUNCT__ "SNESView_VI" 22682b4ed282SShri Abhyankar static PetscErrorCode SNESView_VI(SNES snes,PetscViewer viewer) 22692b4ed282SShri Abhyankar { 22702b4ed282SShri Abhyankar SNES_VI *vi = (SNES_VI *)snes->data; 227178c4b9d3SShri Abhyankar const char *cstr,*tstr; 22722b4ed282SShri Abhyankar PetscErrorCode ierr; 2273ace3abfcSBarry Smith PetscBool iascii; 22742b4ed282SShri Abhyankar 22752b4ed282SShri Abhyankar PetscFunctionBegin; 22762b4ed282SShri Abhyankar ierr = PetscTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); 22772b4ed282SShri Abhyankar if (iascii) { 22782b4ed282SShri Abhyankar if (vi->LineSearch == SNESLineSearchNo_VI) cstr = "SNESLineSearchNo"; 22792b4ed282SShri Abhyankar else if (vi->LineSearch == SNESLineSearchQuadratic_VI) cstr = "SNESLineSearchQuadratic"; 22802b4ed282SShri Abhyankar else if (vi->LineSearch == SNESLineSearchCubic_VI) cstr = "SNESLineSearchCubic"; 22812b4ed282SShri Abhyankar else cstr = "unknown"; 228278c4b9d3SShri Abhyankar if (snes->ops->solve == SNESSolveVI_SS) tstr = "Semismooth"; 22830a7c7af0SShri Abhyankar else if (snes->ops->solve == SNESSolveVI_RS) tstr = "Reduced Space"; 2284b350b9c9SBarry Smith else if (snes->ops->solve == SNESSolveVI_RSAUG) tstr = "Reduced space with augmented variables"; 228578c4b9d3SShri Abhyankar else tstr = "unknown"; 228678c4b9d3SShri Abhyankar ierr = PetscViewerASCIIPrintf(viewer," VI algorithm: %s\n",tstr);CHKERRQ(ierr); 22872b4ed282SShri Abhyankar ierr = PetscViewerASCIIPrintf(viewer," line search variant: %s\n",cstr);CHKERRQ(ierr); 22882b4ed282SShri Abhyankar ierr = PetscViewerASCIIPrintf(viewer," alpha=%G, maxstep=%G, minlambda=%G\n",vi->alpha,vi->maxstep,vi->minlambda);CHKERRQ(ierr); 22892b4ed282SShri Abhyankar } else { 22902b4ed282SShri Abhyankar SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Viewer type %s not supported for SNES EQ VI",((PetscObject)viewer)->type_name); 22912b4ed282SShri Abhyankar } 22922b4ed282SShri Abhyankar PetscFunctionReturn(0); 22932b4ed282SShri Abhyankar } 22942b4ed282SShri Abhyankar 22955559b345SBarry Smith #undef __FUNCT__ 22965559b345SBarry Smith #define __FUNCT__ "SNESVISetVariableBounds" 22975559b345SBarry Smith /*@ 22982b4ed282SShri Abhyankar SNESVISetVariableBounds - Sets the lower and upper bounds for the solution vector. xl <= x <= xu. 22992b4ed282SShri Abhyankar 23002b4ed282SShri Abhyankar Input Parameters: 23012b4ed282SShri Abhyankar . snes - the SNES context. 23022b4ed282SShri Abhyankar . xl - lower bound. 23032b4ed282SShri Abhyankar . xu - upper bound. 23042b4ed282SShri Abhyankar 23052b4ed282SShri Abhyankar Notes: 23062b4ed282SShri Abhyankar If this routine is not called then the lower and upper bounds are set to 230701f0b76bSBarry Smith SNES_VI_INF and SNES_VI_NINF respectively during SNESSetUp(). 230884c105d7SBarry Smith 23095559b345SBarry Smith @*/ 231069c03620SShri Abhyankar PetscErrorCode SNESVISetVariableBounds(SNES snes, Vec xl, Vec xu) 23112b4ed282SShri Abhyankar { 2312d923200aSJungho Lee SNES_VI *vi; 2313d923200aSJungho Lee PetscErrorCode ierr; 23142b4ed282SShri Abhyankar 23152b4ed282SShri Abhyankar PetscFunctionBegin; 23162b4ed282SShri Abhyankar PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 23172b4ed282SShri Abhyankar PetscValidHeaderSpecific(xl,VEC_CLASSID,2); 23182b4ed282SShri Abhyankar PetscValidHeaderSpecific(xu,VEC_CLASSID,3); 23192b4ed282SShri Abhyankar if (!snes->vec_func) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Must call SNESSetFunction() first"); 23202b4ed282SShri 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); 23212b4ed282SShri 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); 2322d923200aSJungho Lee ierr = SNESSetType(snes,SNESVI);CHKERRQ(ierr); 2323d923200aSJungho Lee vi = (SNES_VI*)snes->data; 23242b4ed282SShri Abhyankar vi->usersetxbounds = PETSC_TRUE; 23252b4ed282SShri Abhyankar vi->xl = xl; 23262b4ed282SShri Abhyankar vi->xu = xu; 23272b4ed282SShri Abhyankar PetscFunctionReturn(0); 23282b4ed282SShri Abhyankar } 2329693ddf92SShri Abhyankar 23302b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */ 23312b4ed282SShri Abhyankar /* 23322b4ed282SShri Abhyankar SNESSetFromOptions_VI - Sets various parameters for the SNESVI method. 23332b4ed282SShri Abhyankar 23342b4ed282SShri Abhyankar Input Parameter: 23352b4ed282SShri Abhyankar . snes - the SNES context 23362b4ed282SShri Abhyankar 23372b4ed282SShri Abhyankar Application Interface Routine: SNESSetFromOptions() 23382b4ed282SShri Abhyankar */ 23392b4ed282SShri Abhyankar #undef __FUNCT__ 23402b4ed282SShri Abhyankar #define __FUNCT__ "SNESSetFromOptions_VI" 23412b4ed282SShri Abhyankar static PetscErrorCode SNESSetFromOptions_VI(SNES snes) 23422b4ed282SShri Abhyankar { 23432b4ed282SShri Abhyankar SNES_VI *vi = (SNES_VI *)snes->data; 23447fe79bc4SShri Abhyankar const char *lses[] = {"basic","basicnonorms","quadratic","cubic"}; 2345b350b9c9SBarry Smith const char *vies[] = {"ss","rs","rsaug"}; 23462b4ed282SShri Abhyankar PetscErrorCode ierr; 23472b4ed282SShri Abhyankar PetscInt indx; 234869c03620SShri Abhyankar PetscBool flg,set,flg2; 23492b4ed282SShri Abhyankar 23502b4ed282SShri Abhyankar PetscFunctionBegin; 23512b4ed282SShri Abhyankar ierr = PetscOptionsHead("SNES semismooth method options");CHKERRQ(ierr); 23529308c137SBarry Smith ierr = PetscOptionsBool("-snes_vi_monitor","Monitor all non-active variables","None",PETSC_FALSE,&flg,0);CHKERRQ(ierr); 23539308c137SBarry Smith if (flg) { 23549308c137SBarry Smith ierr = SNESMonitorSet(snes,SNESMonitorVI,0,0);CHKERRQ(ierr); 23559308c137SBarry Smith } 2356be6adb11SBarry Smith ierr = PetscOptionsReal("-snes_ls_alpha","Function norm must decrease by","None",vi->alpha,&vi->alpha,0);CHKERRQ(ierr); 2357be6adb11SBarry Smith ierr = PetscOptionsReal("-snes_ls_maxstep","Step must be less than","None",vi->maxstep,&vi->maxstep,0);CHKERRQ(ierr); 2358be6adb11SBarry Smith ierr = PetscOptionsReal("-snes_ls_minlambda","Minimum lambda allowed","None",vi->minlambda,&vi->minlambda,0);CHKERRQ(ierr); 23592b4ed282SShri Abhyankar ierr = PetscOptionsReal("-snes_vi_const_tol","constraint tolerance","None",vi->const_tol,&vi->const_tol,0);CHKERRQ(ierr); 2360be6adb11SBarry Smith ierr = PetscOptionsBool("-snes_ls_monitor","Print progress of line searches","SNESLineSearchSetMonitor",vi->lsmonitor ? PETSC_TRUE : PETSC_FALSE,&flg,&set);CHKERRQ(ierr); 23612b4ed282SShri Abhyankar if (set) {ierr = SNESLineSearchSetMonitor(snes,flg);CHKERRQ(ierr);} 23622f63a38cSShri Abhyankar ierr = PetscOptionsEList("-snes_vi_type","Semismooth algorithm used","",vies,3,"ss",&indx,&flg2);CHKERRQ(ierr); 236369c03620SShri Abhyankar if (flg2) { 236469c03620SShri Abhyankar switch (indx) { 236569c03620SShri Abhyankar case 0: 236669c03620SShri Abhyankar snes->ops->solve = SNESSolveVI_SS; 236769c03620SShri Abhyankar break; 236869c03620SShri Abhyankar case 1: 2369d950fb63SShri Abhyankar snes->ops->solve = SNESSolveVI_RS; 2370d950fb63SShri Abhyankar break; 23712f63a38cSShri Abhyankar case 2: 2372b350b9c9SBarry Smith snes->ops->solve = SNESSolveVI_RSAUG; 237369c03620SShri Abhyankar } 237469c03620SShri Abhyankar } 2375be6adb11SBarry Smith ierr = PetscOptionsEList("-snes_ls","Line search used","SNESLineSearchSet",lses,4,"basic",&indx,&flg);CHKERRQ(ierr); 23762b4ed282SShri Abhyankar if (flg) { 23772b4ed282SShri Abhyankar switch (indx) { 23782b4ed282SShri Abhyankar case 0: 23792b4ed282SShri Abhyankar ierr = SNESLineSearchSet(snes,SNESLineSearchNo_VI,PETSC_NULL);CHKERRQ(ierr); 23802b4ed282SShri Abhyankar break; 23812b4ed282SShri Abhyankar case 1: 23822b4ed282SShri Abhyankar ierr = SNESLineSearchSet(snes,SNESLineSearchNoNorms_VI,PETSC_NULL);CHKERRQ(ierr); 23832b4ed282SShri Abhyankar break; 23842b4ed282SShri Abhyankar case 2: 23852b4ed282SShri Abhyankar ierr = SNESLineSearchSet(snes,SNESLineSearchQuadratic_VI,PETSC_NULL);CHKERRQ(ierr); 23862b4ed282SShri Abhyankar break; 23872b4ed282SShri Abhyankar case 3: 23882b4ed282SShri Abhyankar ierr = SNESLineSearchSet(snes,SNESLineSearchCubic_VI,PETSC_NULL);CHKERRQ(ierr); 23892b4ed282SShri Abhyankar break; 23902b4ed282SShri Abhyankar } 2391fe835674SShri Abhyankar } 23922b4ed282SShri Abhyankar ierr = PetscOptionsTail();CHKERRQ(ierr); 23932b4ed282SShri Abhyankar PetscFunctionReturn(0); 23942b4ed282SShri Abhyankar } 23952b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */ 23962b4ed282SShri Abhyankar /*MC 23978b4c83edSBarry Smith SNESVI - Various solvers for variational inequalities based on Newton's method 23982b4ed282SShri Abhyankar 23992b4ed282SShri Abhyankar Options Database: 24008b4c83edSBarry 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 24018b4c83edSBarry Smith additional variables that enforce the constraints 24028b4c83edSBarry Smith - -snes_vi_monitor - prints the number of active constraints at each iteration. 24032b4ed282SShri Abhyankar 24042b4ed282SShri Abhyankar 24052b4ed282SShri Abhyankar Level: beginner 24062b4ed282SShri Abhyankar 24072b4ed282SShri Abhyankar .seealso: SNESCreate(), SNES, SNESSetType(), SNESTR, SNESLineSearchSet(), 24082b4ed282SShri Abhyankar SNESLineSearchSetPostCheck(), SNESLineSearchNo(), SNESLineSearchCubic(), SNESLineSearchQuadratic(), 24092b4ed282SShri Abhyankar SNESLineSearchSet(), SNESLineSearchNoNorms(), SNESLineSearchSetPreCheck(), SNESLineSearchSetParams(), SNESLineSearchGetParams() 24102b4ed282SShri Abhyankar 24112b4ed282SShri Abhyankar M*/ 24122b4ed282SShri Abhyankar EXTERN_C_BEGIN 24132b4ed282SShri Abhyankar #undef __FUNCT__ 24142b4ed282SShri Abhyankar #define __FUNCT__ "SNESCreate_VI" 24157087cfbeSBarry Smith PetscErrorCode SNESCreate_VI(SNES snes) 24162b4ed282SShri Abhyankar { 24172b4ed282SShri Abhyankar PetscErrorCode ierr; 24182b4ed282SShri Abhyankar SNES_VI *vi; 24192b4ed282SShri Abhyankar 24202b4ed282SShri Abhyankar PetscFunctionBegin; 24212b4ed282SShri Abhyankar snes->ops->setup = SNESSetUp_VI; 2422edafb9efSBarry Smith snes->ops->solve = SNESSolveVI_RS; 24232b4ed282SShri Abhyankar snes->ops->destroy = SNESDestroy_VI; 24242b4ed282SShri Abhyankar snes->ops->setfromoptions = SNESSetFromOptions_VI; 24252b4ed282SShri Abhyankar snes->ops->view = SNESView_VI; 242637596af1SLisandro Dalcin snes->ops->reset = 0; /* XXX Implement!!! */ 24272b4ed282SShri Abhyankar snes->ops->converged = SNESDefaultConverged_VI; 24282b4ed282SShri Abhyankar 24292b4ed282SShri Abhyankar ierr = PetscNewLog(snes,SNES_VI,&vi);CHKERRQ(ierr); 24302b4ed282SShri Abhyankar snes->data = (void*)vi; 24312b4ed282SShri Abhyankar vi->alpha = 1.e-4; 24322b4ed282SShri Abhyankar vi->maxstep = 1.e8; 24332b4ed282SShri Abhyankar vi->minlambda = 1.e-12; 24347fe79bc4SShri Abhyankar vi->LineSearch = SNESLineSearchNo_VI; 24352b4ed282SShri Abhyankar vi->lsP = PETSC_NULL; 24362b4ed282SShri Abhyankar vi->postcheckstep = PETSC_NULL; 24372b4ed282SShri Abhyankar vi->postcheck = PETSC_NULL; 24382b4ed282SShri Abhyankar vi->precheckstep = PETSC_NULL; 24392b4ed282SShri Abhyankar vi->precheck = PETSC_NULL; 24402b4ed282SShri Abhyankar vi->const_tol = 2.2204460492503131e-16; 24412f63a38cSShri Abhyankar vi->checkredundancy = PETSC_NULL; 24422b4ed282SShri Abhyankar 24432b4ed282SShri Abhyankar ierr = PetscObjectComposeFunctionDynamic((PetscObject)snes,"SNESLineSearchSetMonitor_C","SNESLineSearchSetMonitor_VI",SNESLineSearchSetMonitor_VI);CHKERRQ(ierr); 24442b4ed282SShri Abhyankar ierr = PetscObjectComposeFunctionDynamic((PetscObject)snes,"SNESLineSearchSet_C","SNESLineSearchSet_VI",SNESLineSearchSet_VI);CHKERRQ(ierr); 24452b4ed282SShri Abhyankar 24462b4ed282SShri Abhyankar PetscFunctionReturn(0); 24472b4ed282SShri Abhyankar } 24482b4ed282SShri Abhyankar EXTERN_C_END 2449