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*); 693c0c59f3SBarry Smith } DM_SNESVI; 703c0c59f3SBarry Smith 71d0af7cd3SBarry Smith #undef __FUNCT__ 724dcab191SBarry Smith #define __FUNCT__ "DMCreateGlobalVector_SNESVI" 734dcab191SBarry Smith /* 744dcab191SBarry Smith DMCreateGlobalVector_SNESVI - Creates global vector of the size of the reduced space 754dcab191SBarry Smith 764dcab191SBarry Smith */ 774dcab191SBarry Smith PetscErrorCode DMCreateGlobalVector_SNESVI(DM dm,Vec *vec) 784dcab191SBarry Smith { 794dcab191SBarry Smith PetscErrorCode ierr; 804dcab191SBarry Smith PetscContainer isnes; 813c0c59f3SBarry Smith DM_SNESVI *dmsnesvi; 824dcab191SBarry Smith 834dcab191SBarry Smith PetscFunctionBegin; 844dcab191SBarry Smith ierr = PetscObjectQuery((PetscObject)dm,"VI",(PetscObject *)&isnes);CHKERRQ(ierr); 854dcab191SBarry Smith if (!isnes) SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_PLIB,"Composed SNES is missing"); 864dcab191SBarry Smith ierr = PetscContainerGetPointer(isnes,(void**)&dmsnesvi);CHKERRQ(ierr); 874dcab191SBarry Smith ierr = VecCreateMPI(((PetscObject)dm)->comm,dmsnesvi->n,PETSC_DETERMINE,vec);CHKERRQ(ierr); 884dcab191SBarry Smith PetscFunctionReturn(0); 894dcab191SBarry Smith } 904dcab191SBarry Smith 914dcab191SBarry Smith #undef __FUNCT__ 92d0af7cd3SBarry Smith #define __FUNCT__ "DMGetInterpolation_SNESVI" 93d0af7cd3SBarry Smith /* 94d0af7cd3SBarry Smith DMGetInterpolation_SNESVI - Modifieds the interpolation obtained from the DM by removing all rows and columns associated with active constraints. 95d0af7cd3SBarry Smith 96d0af7cd3SBarry Smith */ 97d0af7cd3SBarry Smith PetscErrorCode DMGetInterpolation_SNESVI(DM dm1,DM dm2,Mat *mat,Vec *vec) 98d0af7cd3SBarry Smith { 99d0af7cd3SBarry Smith PetscErrorCode ierr; 100d0af7cd3SBarry Smith PetscContainer isnes; 1013c0c59f3SBarry Smith DM_SNESVI *dmsnesvi1,*dmsnesvi2; 102d0af7cd3SBarry Smith Mat interp; 103d0af7cd3SBarry Smith 104d0af7cd3SBarry Smith PetscFunctionBegin; 105d0af7cd3SBarry Smith ierr = PetscObjectQuery((PetscObject)dm1,"VI",(PetscObject *)&isnes);CHKERRQ(ierr); 1064dcab191SBarry Smith if (!isnes) SETERRQ(((PetscObject)dm1)->comm,PETSC_ERR_PLIB,"Composed SNES is missing"); 107d0af7cd3SBarry Smith ierr = PetscContainerGetPointer(isnes,(void**)&dmsnesvi1);CHKERRQ(ierr); 108d0af7cd3SBarry Smith ierr = PetscObjectQuery((PetscObject)dm2,"VI",(PetscObject *)&isnes);CHKERRQ(ierr); 1094dcab191SBarry Smith if (!isnes) SETERRQ(((PetscObject)dm2)->comm,PETSC_ERR_PLIB,"Composed SNES is missing"); 110d0af7cd3SBarry Smith ierr = PetscContainerGetPointer(isnes,(void**)&dmsnesvi2);CHKERRQ(ierr); 111d0af7cd3SBarry Smith 112d0af7cd3SBarry Smith ierr = (*dmsnesvi1->getinterpolation)(dm1,dm2,&interp,PETSC_NULL);CHKERRQ(ierr); 1134dcab191SBarry Smith ierr = MatGetSubMatrix(interp,dmsnesvi2->inactive,dmsnesvi1->inactive,MAT_INITIAL_MATRIX,mat);CHKERRQ(ierr); 114d0af7cd3SBarry Smith ierr = MatDestroy(&interp);CHKERRQ(ierr); 115d0af7cd3SBarry Smith PetscFunctionReturn(0); 116d0af7cd3SBarry Smith } 117d0af7cd3SBarry Smith 118d0af7cd3SBarry Smith extern PetscErrorCode DMSetVI(DM,Vec,Vec,Vec,Vec,IS); 119d0af7cd3SBarry Smith 120d0af7cd3SBarry Smith #undef __FUNCT__ 121d0af7cd3SBarry Smith #define __FUNCT__ "DMCoarsen_SNESVI" 122d0af7cd3SBarry Smith /* 123d0af7cd3SBarry Smith DMCoarsen_SNESVI - Computes the regular coarsened DM then computes additional information about its inactive set 124d0af7cd3SBarry Smith 125d0af7cd3SBarry Smith */ 126d0af7cd3SBarry Smith PetscErrorCode DMCoarsen_SNESVI(DM dm1,MPI_Comm comm,DM *dm2) 127d0af7cd3SBarry Smith { 128d0af7cd3SBarry Smith PetscErrorCode ierr; 129d0af7cd3SBarry Smith PetscContainer isnes; 1303c0c59f3SBarry Smith DM_SNESVI *dmsnesvi1; 131d0af7cd3SBarry Smith Vec upper,lower,values,F; 132d0af7cd3SBarry Smith IS inactive; 133d0af7cd3SBarry Smith VecScatter inject; 134d0af7cd3SBarry Smith 135d0af7cd3SBarry Smith PetscFunctionBegin; 136d0af7cd3SBarry Smith ierr = PetscObjectQuery((PetscObject)dm1,"VI",(PetscObject *)&isnes);CHKERRQ(ierr); 1374dcab191SBarry Smith if (!isnes) SETERRQ(((PetscObject)dm1)->comm,PETSC_ERR_PLIB,"Composed SNES is missing"); 138d0af7cd3SBarry Smith ierr = PetscContainerGetPointer(isnes,(void**)&dmsnesvi1);CHKERRQ(ierr); 139d0af7cd3SBarry Smith 140298cc208SBarry Smith /* get the original coarsen */ 141d0af7cd3SBarry Smith ierr = (*dmsnesvi1->coarsen)(dm1,comm,dm2);CHKERRQ(ierr); 142298cc208SBarry Smith 1433c0c59f3SBarry Smith /* not sure why this extra reference is needed, but without the dm2 disappears too early */ 1443c0c59f3SBarry Smith ierr = PetscObjectReference((PetscObject)*dm2);CHKERRQ(ierr); 1453c0c59f3SBarry Smith 146298cc208SBarry Smith /* need to set back global vectors in order to use the original injection */ 147298cc208SBarry Smith ierr = DMClearGlobalVectors(dm1);CHKERRQ(ierr); 148298cc208SBarry Smith dm1->ops->createglobalvector = dmsnesvi1->createglobalvector; 149d0af7cd3SBarry Smith ierr = DMGetInjection(*dm2,dm1,&inject);CHKERRQ(ierr); 150d0af7cd3SBarry Smith ierr = DMCreateGlobalVector(*dm2,&upper);CHKERRQ(ierr); 151d0af7cd3SBarry Smith ierr = VecScatterBegin(inject,dmsnesvi1->upper,upper,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 152d0af7cd3SBarry Smith ierr = VecScatterEnd(inject,dmsnesvi1->upper,upper,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 153d0af7cd3SBarry Smith ierr = DMCreateGlobalVector(*dm2,&lower);CHKERRQ(ierr); 154d0af7cd3SBarry Smith ierr = VecScatterBegin(inject,dmsnesvi1->lower,lower,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 155d0af7cd3SBarry Smith ierr = VecScatterEnd(inject,dmsnesvi1->lower,lower,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 156d0af7cd3SBarry Smith ierr = DMCreateGlobalVector(*dm2,&values);CHKERRQ(ierr); 157d0af7cd3SBarry Smith ierr = VecScatterBegin(inject,dmsnesvi1->values,values,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 158d0af7cd3SBarry Smith ierr = VecScatterEnd(inject,dmsnesvi1->values,values,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 159d0af7cd3SBarry Smith ierr = DMCreateGlobalVector(*dm2,&F);CHKERRQ(ierr); 160d0af7cd3SBarry Smith ierr = VecScatterBegin(inject,dmsnesvi1->F,F,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 161d0af7cd3SBarry Smith ierr = VecScatterEnd(inject,dmsnesvi1->F,F,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 162d0af7cd3SBarry Smith ierr = VecScatterDestroy(&inject);CHKERRQ(ierr); 163298cc208SBarry Smith ierr = DMClearGlobalVectors(dm1);CHKERRQ(ierr); 164298cc208SBarry Smith dm1->ops->createglobalvector = DMCreateGlobalVector_SNESVI; 165d0af7cd3SBarry Smith ierr = SNESVIGetInActiveSetIS(upper,lower,values,F,&inactive);CHKERRQ(ierr); 166d0af7cd3SBarry Smith ierr = DMSetVI(*dm2,upper,lower,values,F,inactive);CHKERRQ(ierr); 1673c0c59f3SBarry Smith ierr = VecDestroy(&upper);CHKERRQ(ierr); 1683c0c59f3SBarry Smith ierr = VecDestroy(&lower);CHKERRQ(ierr); 1693c0c59f3SBarry Smith ierr = VecDestroy(&values);CHKERRQ(ierr); 1703c0c59f3SBarry Smith ierr = VecDestroy(&F);CHKERRQ(ierr); 1713c0c59f3SBarry Smith ierr = ISDestroy(&inactive);CHKERRQ(ierr); 172d0af7cd3SBarry Smith PetscFunctionReturn(0); 173d0af7cd3SBarry Smith } 174d0af7cd3SBarry Smith 175d0af7cd3SBarry Smith #undef __FUNCT__ 1763c0c59f3SBarry Smith #define __FUNCT__ "DMDestroy_SNESVI" 1773c0c59f3SBarry Smith PetscErrorCode DMDestroy_SNESVI(DM_SNESVI *dmsnesvi) 178d0af7cd3SBarry Smith { 179d0af7cd3SBarry Smith PetscErrorCode ierr; 180d0af7cd3SBarry Smith 181d0af7cd3SBarry Smith PetscFunctionBegin; 182d0af7cd3SBarry Smith ierr = VecDestroy(&dmsnesvi->upper);CHKERRQ(ierr); 183d0af7cd3SBarry Smith ierr = VecDestroy(&dmsnesvi->lower);CHKERRQ(ierr); 184d0af7cd3SBarry Smith ierr = VecDestroy(&dmsnesvi->values);CHKERRQ(ierr); 185d0af7cd3SBarry Smith ierr = VecDestroy(&dmsnesvi->F);CHKERRQ(ierr); 186d0af7cd3SBarry Smith ierr = ISDestroy(&dmsnesvi->inactive);CHKERRQ(ierr); 187d0af7cd3SBarry Smith ierr = PetscFree(dmsnesvi);CHKERRQ(ierr); 188d0af7cd3SBarry Smith PetscFunctionReturn(0); 189d0af7cd3SBarry Smith } 190d0af7cd3SBarry Smith 191d0af7cd3SBarry Smith #undef __FUNCT__ 192d0af7cd3SBarry Smith #define __FUNCT__ "DMSetVI" 193d0af7cd3SBarry Smith /* 194d0af7cd3SBarry Smith DMSetVI - Marks a DM as associated with a VI problem. This causes the interpolation/restriction operators to 195d0af7cd3SBarry Smith be restricted to only those variables NOT associated with active constraints. 196d0af7cd3SBarry Smith 197d0af7cd3SBarry Smith */ 198d0af7cd3SBarry Smith PetscErrorCode DMSetVI(DM dm,Vec upper,Vec lower,Vec values,Vec F,IS inactive) 199d0af7cd3SBarry Smith { 200d0af7cd3SBarry Smith PetscErrorCode ierr; 201d0af7cd3SBarry Smith PetscContainer isnes; 2023c0c59f3SBarry Smith DM_SNESVI *dmsnesvi; 203d0af7cd3SBarry Smith 204d0af7cd3SBarry Smith PetscFunctionBegin; 2054dcab191SBarry Smith if (!dm) PetscFunctionReturn(0); 206d0af7cd3SBarry Smith ierr = PetscObjectReference((PetscObject)upper);CHKERRQ(ierr); 207d0af7cd3SBarry Smith ierr = PetscObjectReference((PetscObject)lower);CHKERRQ(ierr); 208d0af7cd3SBarry Smith ierr = PetscObjectReference((PetscObject)values);CHKERRQ(ierr); 209d0af7cd3SBarry Smith ierr = PetscObjectReference((PetscObject)F);CHKERRQ(ierr); 210d0af7cd3SBarry Smith ierr = PetscObjectReference((PetscObject)inactive);CHKERRQ(ierr); 211d0af7cd3SBarry Smith 212d0af7cd3SBarry Smith ierr = PetscObjectQuery((PetscObject)dm,"VI",(PetscObject *)&isnes);CHKERRQ(ierr); 213d0af7cd3SBarry Smith if (!isnes) { 214d0af7cd3SBarry Smith ierr = PetscContainerCreate(((PetscObject)dm)->comm,&isnes);CHKERRQ(ierr); 2153c0c59f3SBarry Smith ierr = PetscContainerSetUserDestroy(isnes,(PetscErrorCode (*)(void*))DMDestroy_SNESVI);CHKERRQ(ierr); 2163c0c59f3SBarry Smith ierr = PetscNew(DM_SNESVI,&dmsnesvi);CHKERRQ(ierr); 217d0af7cd3SBarry Smith ierr = PetscContainerSetPointer(isnes,(void*)dmsnesvi);CHKERRQ(ierr); 218d0af7cd3SBarry Smith ierr = PetscObjectCompose((PetscObject)dm,"VI",(PetscObject)isnes);CHKERRQ(ierr); 2193c0c59f3SBarry Smith ierr = PetscContainerDestroy(&isnes);CHKERRQ(ierr); 220d0af7cd3SBarry Smith dmsnesvi->getinterpolation = dm->ops->getinterpolation; 221d0af7cd3SBarry Smith dm->ops->getinterpolation = DMGetInterpolation_SNESVI; 222d0af7cd3SBarry Smith dmsnesvi->coarsen = dm->ops->coarsen; 223d0af7cd3SBarry Smith dm->ops->coarsen = DMCoarsen_SNESVI; 224298cc208SBarry Smith dmsnesvi->createglobalvector = dm->ops->createglobalvector; 2254dcab191SBarry Smith dm->ops->createglobalvector = DMCreateGlobalVector_SNESVI; 226*6ba4bc90SBarry Smith /* since these vectors may reference the DM, need to remove circle referencing */ 227*6ba4bc90SBarry Smith ierr = PetscObjectRemoveReference((PetscObject)upper,"DM");CHKERRQ(ierr); 228*6ba4bc90SBarry Smith ierr = PetscObjectRemoveReference((PetscObject)lower,"DM");CHKERRQ(ierr); 229*6ba4bc90SBarry Smith ierr = PetscObjectRemoveReference((PetscObject)values,"DM");CHKERRQ(ierr); 230*6ba4bc90SBarry Smith ierr = PetscObjectRemoveReference((PetscObject)F,"DM");CHKERRQ(ierr); 231d0af7cd3SBarry Smith } else { 232d0af7cd3SBarry Smith ierr = PetscContainerGetPointer(isnes,(void**)&dmsnesvi);CHKERRQ(ierr); 233d0af7cd3SBarry Smith ierr = VecDestroy(&dmsnesvi->upper);CHKERRQ(ierr); 234d0af7cd3SBarry Smith ierr = VecDestroy(&dmsnesvi->lower);CHKERRQ(ierr); 235d0af7cd3SBarry Smith ierr = VecDestroy(&dmsnesvi->values);CHKERRQ(ierr); 236d0af7cd3SBarry Smith ierr = VecDestroy(&dmsnesvi->F);CHKERRQ(ierr); 237d0af7cd3SBarry Smith ierr = ISDestroy(&dmsnesvi->inactive);CHKERRQ(ierr); 238d0af7cd3SBarry Smith } 2394dcab191SBarry Smith ierr = DMClearGlobalVectors(dm);CHKERRQ(ierr); 2404dcab191SBarry Smith ierr = ISGetLocalSize(inactive,&dmsnesvi->n);CHKERRQ(ierr); 241d0af7cd3SBarry Smith dmsnesvi->upper = upper; 242d0af7cd3SBarry Smith dmsnesvi->lower = lower; 243d0af7cd3SBarry Smith dmsnesvi->values = values; 244d0af7cd3SBarry Smith dmsnesvi->F = F; 245d0af7cd3SBarry Smith dmsnesvi->inactive = inactive; 246d0af7cd3SBarry Smith PetscFunctionReturn(0); 247d0af7cd3SBarry Smith } 248d0af7cd3SBarry Smith 2493c0c59f3SBarry Smith /* --------------------------------------------------------------------------------------------------------*/ 2502b4ed282SShri Abhyankar 2519308c137SBarry Smith #undef __FUNCT__ 2529308c137SBarry Smith #define __FUNCT__ "SNESMonitorVI" 2537087cfbeSBarry Smith PetscErrorCode SNESMonitorVI(SNES snes,PetscInt its,PetscReal fgnorm,void *dummy) 2549308c137SBarry Smith { 2559308c137SBarry Smith PetscErrorCode ierr; 2569308c137SBarry Smith SNES_VI *vi = (SNES_VI*)snes->data; 2579308c137SBarry Smith PetscViewerASCIIMonitor viewer = (PetscViewerASCIIMonitor) dummy; 2589308c137SBarry Smith const PetscScalar *x,*xl,*xu,*f; 25909573ac7SBarry Smith PetscInt i,n,act = 0; 2609308c137SBarry Smith PetscReal rnorm,fnorm; 2619308c137SBarry Smith 2629308c137SBarry Smith PetscFunctionBegin; 2639308c137SBarry Smith if (!dummy) { 2649308c137SBarry Smith ierr = PetscViewerASCIIMonitorCreate(((PetscObject)snes)->comm,"stdout",0,&viewer);CHKERRQ(ierr); 2659308c137SBarry Smith } 2669308c137SBarry Smith ierr = VecGetLocalSize(snes->vec_sol,&n);CHKERRQ(ierr); 2679308c137SBarry Smith ierr = VecGetArrayRead(vi->xl,&xl);CHKERRQ(ierr); 2689308c137SBarry Smith ierr = VecGetArrayRead(vi->xu,&xu);CHKERRQ(ierr); 2699308c137SBarry Smith ierr = VecGetArrayRead(snes->vec_sol,&x);CHKERRQ(ierr); 2703f731af5SBarry Smith ierr = VecGetArrayRead(snes->vec_func,&f);CHKERRQ(ierr); 2719308c137SBarry Smith 2729308c137SBarry Smith rnorm = 0.0; 2739308c137SBarry Smith for (i=0; i<n; i++) { 27410f5ae6bSBarry 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]); 27509573ac7SBarry Smith else act++; 2769308c137SBarry Smith } 2773f731af5SBarry Smith ierr = VecRestoreArrayRead(snes->vec_func,&f);CHKERRQ(ierr); 2789308c137SBarry Smith ierr = VecRestoreArrayRead(vi->xl,&xl);CHKERRQ(ierr); 2799308c137SBarry Smith ierr = VecRestoreArrayRead(vi->xu,&xu);CHKERRQ(ierr); 2809308c137SBarry Smith ierr = VecRestoreArrayRead(snes->vec_sol,&x);CHKERRQ(ierr); 281d9822059SBarry Smith ierr = MPI_Allreduce(&rnorm,&fnorm,1,MPIU_REAL,MPIU_SUM,((PetscObject)snes)->comm);CHKERRQ(ierr); 2829308c137SBarry Smith fnorm = sqrt(fnorm); 28309573ac7SBarry Smith ierr = PetscViewerASCIIMonitorPrintf(viewer,"%3D SNES VI Function norm %14.12e Active constraints %D\n",its,fnorm,act);CHKERRQ(ierr); 2849308c137SBarry Smith if (!dummy) { 2856bf464f9SBarry Smith ierr = PetscViewerASCIIMonitorDestroy(&viewer);CHKERRQ(ierr); 2869308c137SBarry Smith } 2879308c137SBarry Smith PetscFunctionReturn(0); 2889308c137SBarry Smith } 2899308c137SBarry Smith 2902b4ed282SShri Abhyankar /* 2912b4ed282SShri Abhyankar Checks if J^T F = 0 which implies we've found a local minimum of the norm of the function, 2922b4ed282SShri 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 2932b4ed282SShri Abhyankar 0 = (J^T F)^T W = F^T J W iff W not in the null space of J. Thanks for Jorge More 2942b4ed282SShri Abhyankar for this trick. One assumes that the probability that W is in the null space of J is very, very small. 2952b4ed282SShri Abhyankar */ 2962b4ed282SShri Abhyankar #undef __FUNCT__ 2972b4ed282SShri Abhyankar #define __FUNCT__ "SNESVICheckLocalMin_Private" 298ace3abfcSBarry Smith PetscErrorCode SNESVICheckLocalMin_Private(SNES snes,Mat A,Vec F,Vec W,PetscReal fnorm,PetscBool *ismin) 2992b4ed282SShri Abhyankar { 3002b4ed282SShri Abhyankar PetscReal a1; 3012b4ed282SShri Abhyankar PetscErrorCode ierr; 302ace3abfcSBarry Smith PetscBool hastranspose; 3032b4ed282SShri Abhyankar 3042b4ed282SShri Abhyankar PetscFunctionBegin; 3052b4ed282SShri Abhyankar *ismin = PETSC_FALSE; 3062b4ed282SShri Abhyankar ierr = MatHasOperation(A,MATOP_MULT_TRANSPOSE,&hastranspose);CHKERRQ(ierr); 3072b4ed282SShri Abhyankar if (hastranspose) { 3082b4ed282SShri Abhyankar /* Compute || J^T F|| */ 3092b4ed282SShri Abhyankar ierr = MatMultTranspose(A,F,W);CHKERRQ(ierr); 3102b4ed282SShri Abhyankar ierr = VecNorm(W,NORM_2,&a1);CHKERRQ(ierr); 3112b4ed282SShri Abhyankar ierr = PetscInfo1(snes,"|| J^T F|| %G near zero implies found a local minimum\n",a1/fnorm);CHKERRQ(ierr); 3122b4ed282SShri Abhyankar if (a1/fnorm < 1.e-4) *ismin = PETSC_TRUE; 3132b4ed282SShri Abhyankar } else { 3142b4ed282SShri Abhyankar Vec work; 3152b4ed282SShri Abhyankar PetscScalar result; 3162b4ed282SShri Abhyankar PetscReal wnorm; 3172b4ed282SShri Abhyankar 3182b4ed282SShri Abhyankar ierr = VecSetRandom(W,PETSC_NULL);CHKERRQ(ierr); 3192b4ed282SShri Abhyankar ierr = VecNorm(W,NORM_2,&wnorm);CHKERRQ(ierr); 3202b4ed282SShri Abhyankar ierr = VecDuplicate(W,&work);CHKERRQ(ierr); 3212b4ed282SShri Abhyankar ierr = MatMult(A,W,work);CHKERRQ(ierr); 3222b4ed282SShri Abhyankar ierr = VecDot(F,work,&result);CHKERRQ(ierr); 3236bf464f9SBarry Smith ierr = VecDestroy(&work);CHKERRQ(ierr); 3242b4ed282SShri Abhyankar a1 = PetscAbsScalar(result)/(fnorm*wnorm); 3252b4ed282SShri Abhyankar ierr = PetscInfo1(snes,"(F^T J random)/(|| F ||*||random|| %G near zero implies found a local minimum\n",a1);CHKERRQ(ierr); 3262b4ed282SShri Abhyankar if (a1 < 1.e-4) *ismin = PETSC_TRUE; 3272b4ed282SShri Abhyankar } 3282b4ed282SShri Abhyankar PetscFunctionReturn(0); 3292b4ed282SShri Abhyankar } 3302b4ed282SShri Abhyankar 3312b4ed282SShri Abhyankar /* 3322b4ed282SShri Abhyankar Checks if J^T(F - J*X) = 0 3332b4ed282SShri Abhyankar */ 3342b4ed282SShri Abhyankar #undef __FUNCT__ 3352b4ed282SShri Abhyankar #define __FUNCT__ "SNESVICheckResidual_Private" 3362b4ed282SShri Abhyankar PetscErrorCode SNESVICheckResidual_Private(SNES snes,Mat A,Vec F,Vec X,Vec W1,Vec W2) 3372b4ed282SShri Abhyankar { 3382b4ed282SShri Abhyankar PetscReal a1,a2; 3392b4ed282SShri Abhyankar PetscErrorCode ierr; 340ace3abfcSBarry Smith PetscBool hastranspose; 3412b4ed282SShri Abhyankar 3422b4ed282SShri Abhyankar PetscFunctionBegin; 3432b4ed282SShri Abhyankar ierr = MatHasOperation(A,MATOP_MULT_TRANSPOSE,&hastranspose);CHKERRQ(ierr); 3442b4ed282SShri Abhyankar if (hastranspose) { 3452b4ed282SShri Abhyankar ierr = MatMult(A,X,W1);CHKERRQ(ierr); 3462b4ed282SShri Abhyankar ierr = VecAXPY(W1,-1.0,F);CHKERRQ(ierr); 3472b4ed282SShri Abhyankar 3482b4ed282SShri Abhyankar /* Compute || J^T W|| */ 3492b4ed282SShri Abhyankar ierr = MatMultTranspose(A,W1,W2);CHKERRQ(ierr); 3502b4ed282SShri Abhyankar ierr = VecNorm(W1,NORM_2,&a1);CHKERRQ(ierr); 3512b4ed282SShri Abhyankar ierr = VecNorm(W2,NORM_2,&a2);CHKERRQ(ierr); 3522b4ed282SShri Abhyankar if (a1 != 0.0) { 3532b4ed282SShri Abhyankar ierr = PetscInfo1(snes,"||J^T(F-Ax)||/||F-AX|| %G near zero implies inconsistent rhs\n",a2/a1);CHKERRQ(ierr); 3542b4ed282SShri Abhyankar } 3552b4ed282SShri Abhyankar } 3562b4ed282SShri Abhyankar PetscFunctionReturn(0); 3572b4ed282SShri Abhyankar } 3582b4ed282SShri Abhyankar 3592b4ed282SShri Abhyankar /* 3602b4ed282SShri Abhyankar SNESDefaultConverged_VI - Checks the convergence of the semismooth newton algorithm. 3612b4ed282SShri Abhyankar 3622b4ed282SShri Abhyankar Notes: 3632b4ed282SShri Abhyankar The convergence criterion currently implemented is 3642b4ed282SShri Abhyankar merit < abstol 3652b4ed282SShri Abhyankar merit < rtol*merit_initial 3662b4ed282SShri Abhyankar */ 3672b4ed282SShri Abhyankar #undef __FUNCT__ 3682b4ed282SShri Abhyankar #define __FUNCT__ "SNESDefaultConverged_VI" 3697fe79bc4SShri Abhyankar PetscErrorCode SNESDefaultConverged_VI(SNES snes,PetscInt it,PetscReal xnorm,PetscReal gradnorm,PetscReal fnorm,SNESConvergedReason *reason,void *dummy) 3702b4ed282SShri Abhyankar { 3712b4ed282SShri Abhyankar PetscErrorCode ierr; 3722b4ed282SShri Abhyankar 3732b4ed282SShri Abhyankar PetscFunctionBegin; 3742b4ed282SShri Abhyankar PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 3752b4ed282SShri Abhyankar PetscValidPointer(reason,6); 3762b4ed282SShri Abhyankar 3772b4ed282SShri Abhyankar *reason = SNES_CONVERGED_ITERATING; 3782b4ed282SShri Abhyankar 3792b4ed282SShri Abhyankar if (!it) { 3802b4ed282SShri Abhyankar /* set parameter for default relative tolerance convergence test */ 3817fe79bc4SShri Abhyankar snes->ttol = fnorm*snes->rtol; 3822b4ed282SShri Abhyankar } 3837fe79bc4SShri Abhyankar if (fnorm != fnorm) { 3842b4ed282SShri Abhyankar ierr = PetscInfo(snes,"Failed to converged, function norm is NaN\n");CHKERRQ(ierr); 3852b4ed282SShri Abhyankar *reason = SNES_DIVERGED_FNORM_NAN; 3867fe79bc4SShri Abhyankar } else if (fnorm < snes->abstol) { 3877fe79bc4SShri Abhyankar ierr = PetscInfo2(snes,"Converged due to function norm %G < %G\n",fnorm,snes->abstol);CHKERRQ(ierr); 3882b4ed282SShri Abhyankar *reason = SNES_CONVERGED_FNORM_ABS; 3892b4ed282SShri Abhyankar } else if (snes->nfuncs >= snes->max_funcs) { 3902b4ed282SShri Abhyankar ierr = PetscInfo2(snes,"Exceeded maximum number of function evaluations: %D > %D\n",snes->nfuncs,snes->max_funcs);CHKERRQ(ierr); 3912b4ed282SShri Abhyankar *reason = SNES_DIVERGED_FUNCTION_COUNT; 3922b4ed282SShri Abhyankar } 3932b4ed282SShri Abhyankar 3942b4ed282SShri Abhyankar if (it && !*reason) { 3957fe79bc4SShri Abhyankar if (fnorm < snes->ttol) { 3967fe79bc4SShri Abhyankar ierr = PetscInfo2(snes,"Converged due to function norm %G < %G (relative tolerance)\n",fnorm,snes->ttol);CHKERRQ(ierr); 3972b4ed282SShri Abhyankar *reason = SNES_CONVERGED_FNORM_RELATIVE; 3982b4ed282SShri Abhyankar } 3992b4ed282SShri Abhyankar } 4002b4ed282SShri Abhyankar PetscFunctionReturn(0); 4012b4ed282SShri Abhyankar } 4022b4ed282SShri Abhyankar 4032b4ed282SShri Abhyankar /* 4042b4ed282SShri Abhyankar SNESVIComputeMeritFunction - Evaluates the merit function for the mixed complementarity problem. 4052b4ed282SShri Abhyankar 4062b4ed282SShri Abhyankar Input Parameter: 4072b4ed282SShri Abhyankar . phi - the semismooth function 4082b4ed282SShri Abhyankar 4092b4ed282SShri Abhyankar Output Parameter: 4102b4ed282SShri Abhyankar . merit - the merit function 4112b4ed282SShri Abhyankar . phinorm - ||phi|| 4122b4ed282SShri Abhyankar 4132b4ed282SShri Abhyankar Notes: 4142b4ed282SShri Abhyankar The merit function for the mixed complementarity problem is defined as 4152b4ed282SShri Abhyankar merit = 0.5*phi^T*phi 4162b4ed282SShri Abhyankar */ 4172b4ed282SShri Abhyankar #undef __FUNCT__ 4182b4ed282SShri Abhyankar #define __FUNCT__ "SNESVIComputeMeritFunction" 4192b4ed282SShri Abhyankar static PetscErrorCode SNESVIComputeMeritFunction(Vec phi, PetscReal* merit,PetscReal* phinorm) 4202b4ed282SShri Abhyankar { 4212b4ed282SShri Abhyankar PetscErrorCode ierr; 4222b4ed282SShri Abhyankar 4232b4ed282SShri Abhyankar PetscFunctionBegin; 4245f48b12bSBarry Smith ierr = VecNormBegin(phi,NORM_2,phinorm);CHKERRQ(ierr); 4255f48b12bSBarry Smith ierr = VecNormEnd(phi,NORM_2,phinorm);CHKERRQ(ierr); 4262b4ed282SShri Abhyankar 4272b4ed282SShri Abhyankar *merit = 0.5*(*phinorm)*(*phinorm); 4282b4ed282SShri Abhyankar PetscFunctionReturn(0); 4292b4ed282SShri Abhyankar } 4302b4ed282SShri Abhyankar 4317f6f51e9SSatish Balay PETSC_STATIC_INLINE PetscScalar Phi(PetscScalar a,PetscScalar b) 4324c21c6cdSBarry Smith { 4334c21c6cdSBarry Smith return a + b - sqrt(a*a + b*b); 4344c21c6cdSBarry Smith } 4354c21c6cdSBarry Smith 4367f6f51e9SSatish Balay PETSC_STATIC_INLINE PetscScalar DPhi(PetscScalar a,PetscScalar b) 4374c21c6cdSBarry Smith { 4385559b345SBarry Smith if ((PetscAbsScalar(a) >= 1.e-6) || (PetscAbsScalar(b) >= 1.e-6)) return 1.0 - a/ sqrt(a*a + b*b); 4395559b345SBarry Smith else return .5; 4404c21c6cdSBarry Smith } 4414c21c6cdSBarry Smith 4422b4ed282SShri Abhyankar /* 4431f79c099SShri Abhyankar SNESVIComputeFunction - Reformulates a system of nonlinear equations in mixed complementarity form to a system of nonlinear equations in semismooth form. 4442b4ed282SShri Abhyankar 4452b4ed282SShri Abhyankar Input Parameters: 4462b4ed282SShri Abhyankar . snes - the SNES context 4472b4ed282SShri Abhyankar . x - current iterate 4482b4ed282SShri Abhyankar . functx - user defined function context 4492b4ed282SShri Abhyankar 4502b4ed282SShri Abhyankar Output Parameters: 4512b4ed282SShri Abhyankar . phi - Semismooth function 4522b4ed282SShri Abhyankar 4532b4ed282SShri Abhyankar */ 4542b4ed282SShri Abhyankar #undef __FUNCT__ 4551f79c099SShri Abhyankar #define __FUNCT__ "SNESVIComputeFunction" 4561f79c099SShri Abhyankar static PetscErrorCode SNESVIComputeFunction(SNES snes,Vec X,Vec phi,void* functx) 4572b4ed282SShri Abhyankar { 4582b4ed282SShri Abhyankar PetscErrorCode ierr; 4592b4ed282SShri Abhyankar SNES_VI *vi = (SNES_VI*)snes->data; 4602b4ed282SShri Abhyankar Vec Xl = vi->xl,Xu = vi->xu,F = snes->vec_func; 4614c21c6cdSBarry Smith PetscScalar *phi_arr,*x_arr,*f_arr,*l,*u; 4622b4ed282SShri Abhyankar PetscInt i,nlocal; 4632b4ed282SShri Abhyankar 4642b4ed282SShri Abhyankar PetscFunctionBegin; 4652b4ed282SShri Abhyankar ierr = (*vi->computeuserfunction)(snes,X,F,functx);CHKERRQ(ierr); 4662b4ed282SShri Abhyankar ierr = VecGetLocalSize(X,&nlocal);CHKERRQ(ierr); 4672b4ed282SShri Abhyankar ierr = VecGetArray(X,&x_arr);CHKERRQ(ierr); 4682b4ed282SShri Abhyankar ierr = VecGetArray(F,&f_arr);CHKERRQ(ierr); 4692b4ed282SShri Abhyankar ierr = VecGetArray(Xl,&l);CHKERRQ(ierr); 4702b4ed282SShri Abhyankar ierr = VecGetArray(Xu,&u);CHKERRQ(ierr); 4712b4ed282SShri Abhyankar ierr = VecGetArray(phi,&phi_arr);CHKERRQ(ierr); 4722b4ed282SShri Abhyankar 4732b4ed282SShri Abhyankar for (i=0;i < nlocal;i++) { 47410f5ae6bSBarry Smith if ((PetscRealPart(l[i]) <= SNES_VI_NINF) && (PetscRealPart(u[i]) >= SNES_VI_INF)) { /* no constraints on variable */ 4754c21c6cdSBarry Smith phi_arr[i] = f_arr[i]; 47610f5ae6bSBarry Smith } else if (PetscRealPart(l[i]) <= SNES_VI_NINF) { /* upper bound on variable only */ 4774c21c6cdSBarry Smith phi_arr[i] = -Phi(u[i] - x_arr[i],-f_arr[i]); 47810f5ae6bSBarry Smith } else if (PetscRealPart(u[i]) >= SNES_VI_INF) { /* lower bound on variable only */ 4794c21c6cdSBarry Smith phi_arr[i] = Phi(x_arr[i] - l[i],f_arr[i]); 4805559b345SBarry Smith } else if (l[i] == u[i]) { 4812b4ed282SShri Abhyankar phi_arr[i] = l[i] - x_arr[i]; 4825559b345SBarry Smith } else { /* both bounds on variable */ 4834c21c6cdSBarry Smith phi_arr[i] = Phi(x_arr[i] - l[i],-Phi(u[i] - x_arr[i],-f_arr[i])); 4842b4ed282SShri Abhyankar } 4852b4ed282SShri Abhyankar } 4862b4ed282SShri Abhyankar 4872b4ed282SShri Abhyankar ierr = VecRestoreArray(X,&x_arr);CHKERRQ(ierr); 4882b4ed282SShri Abhyankar ierr = VecRestoreArray(F,&f_arr);CHKERRQ(ierr); 4892b4ed282SShri Abhyankar ierr = VecRestoreArray(Xl,&l);CHKERRQ(ierr); 4902b4ed282SShri Abhyankar ierr = VecRestoreArray(Xu,&u);CHKERRQ(ierr); 4912b4ed282SShri Abhyankar ierr = VecRestoreArray(phi,&phi_arr);CHKERRQ(ierr); 4922b4ed282SShri Abhyankar PetscFunctionReturn(0); 4932b4ed282SShri Abhyankar } 4942b4ed282SShri Abhyankar 4952b4ed282SShri Abhyankar /* 496a79edbefSShri Abhyankar SNESVIComputeBsubdifferentialVectors - Computes the diagonal shift (Da) and row scaling (Db) vectors needed for the 497a79edbefSShri Abhyankar the semismooth jacobian. 4982b4ed282SShri Abhyankar */ 4992b4ed282SShri Abhyankar #undef __FUNCT__ 500a79edbefSShri Abhyankar #define __FUNCT__ "SNESVIComputeBsubdifferentialVectors" 501a79edbefSShri Abhyankar PetscErrorCode SNESVIComputeBsubdifferentialVectors(SNES snes,Vec X,Vec F,Mat jac,Vec Da,Vec Db) 5022b4ed282SShri Abhyankar { 5032b4ed282SShri Abhyankar PetscErrorCode ierr; 5042b4ed282SShri Abhyankar SNES_VI *vi = (SNES_VI*)snes->data; 5054c21c6cdSBarry Smith PetscScalar *l,*u,*x,*f,*da,*db,da1,da2,db1,db2; 5062b4ed282SShri Abhyankar PetscInt i,nlocal; 5072b4ed282SShri Abhyankar 5082b4ed282SShri Abhyankar PetscFunctionBegin; 5092b4ed282SShri Abhyankar 5102b4ed282SShri Abhyankar ierr = VecGetArray(X,&x);CHKERRQ(ierr); 5112b4ed282SShri Abhyankar ierr = VecGetArray(F,&f);CHKERRQ(ierr); 5122b4ed282SShri Abhyankar ierr = VecGetArray(vi->xl,&l);CHKERRQ(ierr); 5132b4ed282SShri Abhyankar ierr = VecGetArray(vi->xu,&u);CHKERRQ(ierr); 514a79edbefSShri Abhyankar ierr = VecGetArray(Da,&da);CHKERRQ(ierr); 515a79edbefSShri Abhyankar ierr = VecGetArray(Db,&db);CHKERRQ(ierr); 5162b4ed282SShri Abhyankar ierr = VecGetLocalSize(X,&nlocal);CHKERRQ(ierr); 5174c21c6cdSBarry Smith 5182b4ed282SShri Abhyankar for (i=0;i< nlocal;i++) { 51910f5ae6bSBarry Smith if ((PetscRealPart(l[i]) <= SNES_VI_NINF) && (PetscRealPart(u[i]) >= SNES_VI_INF)) {/* no constraints on variable */ 5204c21c6cdSBarry Smith da[i] = 0; 5212b4ed282SShri Abhyankar db[i] = 1; 52210f5ae6bSBarry Smith } else if (PetscRealPart(l[i]) <= SNES_VI_NINF) { /* upper bound on variable only */ 5234c21c6cdSBarry Smith da[i] = DPhi(u[i] - x[i], -f[i]); 5244c21c6cdSBarry Smith db[i] = DPhi(-f[i],u[i] - x[i]); 52510f5ae6bSBarry Smith } else if (PetscRealPart(u[i]) >= SNES_VI_INF) { /* lower bound on variable only */ 5265559b345SBarry Smith da[i] = DPhi(x[i] - l[i], f[i]); 5275559b345SBarry Smith db[i] = DPhi(f[i],x[i] - l[i]); 5285559b345SBarry Smith } else if (l[i] == u[i]) { /* fixed variable */ 5294c21c6cdSBarry Smith da[i] = 1; 5302b4ed282SShri Abhyankar db[i] = 0; 5315559b345SBarry Smith } else { /* upper and lower bounds on variable */ 5324c21c6cdSBarry Smith da1 = DPhi(x[i] - l[i], -Phi(u[i] - x[i], -f[i])); 5334c21c6cdSBarry Smith db1 = DPhi(-Phi(u[i] - x[i], -f[i]),x[i] - l[i]); 5344c21c6cdSBarry Smith da2 = DPhi(u[i] - x[i], -f[i]); 5354c21c6cdSBarry Smith db2 = DPhi(-f[i],u[i] - x[i]); 5364c21c6cdSBarry Smith da[i] = da1 + db1*da2; 5374c21c6cdSBarry Smith db[i] = db1*db2; 5382b4ed282SShri Abhyankar } 5392b4ed282SShri Abhyankar } 5405559b345SBarry Smith 5412b4ed282SShri Abhyankar ierr = VecRestoreArray(X,&x);CHKERRQ(ierr); 5422b4ed282SShri Abhyankar ierr = VecRestoreArray(F,&f);CHKERRQ(ierr); 5432b4ed282SShri Abhyankar ierr = VecRestoreArray(vi->xl,&l);CHKERRQ(ierr); 5442b4ed282SShri Abhyankar ierr = VecRestoreArray(vi->xu,&u);CHKERRQ(ierr); 545a79edbefSShri Abhyankar ierr = VecRestoreArray(Da,&da);CHKERRQ(ierr); 546a79edbefSShri Abhyankar ierr = VecRestoreArray(Db,&db);CHKERRQ(ierr); 547a79edbefSShri Abhyankar PetscFunctionReturn(0); 548a79edbefSShri Abhyankar } 549a79edbefSShri Abhyankar 550a79edbefSShri Abhyankar /* 551a79edbefSShri 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. 552a79edbefSShri Abhyankar 553a79edbefSShri Abhyankar Input Parameters: 554a79edbefSShri Abhyankar . Da - Diagonal shift vector for the semismooth jacobian. 555a79edbefSShri Abhyankar . Db - Row scaling vector for the semismooth jacobian. 556a79edbefSShri Abhyankar 557a79edbefSShri Abhyankar Output Parameters: 558a79edbefSShri Abhyankar . jac - semismooth jacobian 559a79edbefSShri Abhyankar . jac_pre - optional preconditioning matrix 560a79edbefSShri Abhyankar 561a79edbefSShri Abhyankar Notes: 562a79edbefSShri Abhyankar The semismooth jacobian matrix is given by 563a79edbefSShri Abhyankar jac = Da + Db*jacfun 564a79edbefSShri Abhyankar where Db is the row scaling matrix stored as a vector, 565a79edbefSShri Abhyankar Da is the diagonal perturbation matrix stored as a vector 566a79edbefSShri Abhyankar and jacfun is the jacobian of the original nonlinear function. 567a79edbefSShri Abhyankar */ 568a79edbefSShri Abhyankar #undef __FUNCT__ 569a79edbefSShri Abhyankar #define __FUNCT__ "SNESVIComputeJacobian" 570a79edbefSShri Abhyankar PetscErrorCode SNESVIComputeJacobian(Mat jac, Mat jac_pre,Vec Da, Vec Db) 571a79edbefSShri Abhyankar { 572a79edbefSShri Abhyankar PetscErrorCode ierr; 573a79edbefSShri Abhyankar 5742b4ed282SShri Abhyankar /* Do row scaling and add diagonal perturbation */ 575a79edbefSShri Abhyankar ierr = MatDiagonalScale(jac,Db,PETSC_NULL);CHKERRQ(ierr); 576a79edbefSShri Abhyankar ierr = MatDiagonalSet(jac,Da,ADD_VALUES);CHKERRQ(ierr); 577a79edbefSShri Abhyankar if (jac != jac_pre) { /* If jac and jac_pre are different */ 578a79edbefSShri Abhyankar ierr = MatDiagonalScale(jac_pre,Db,PETSC_NULL); 579a79edbefSShri Abhyankar ierr = MatDiagonalSet(jac_pre,Da,ADD_VALUES);CHKERRQ(ierr); 5802b4ed282SShri Abhyankar } 5812b4ed282SShri Abhyankar PetscFunctionReturn(0); 5822b4ed282SShri Abhyankar } 5832b4ed282SShri Abhyankar 5842b4ed282SShri Abhyankar /* 585ee657d29SShri Abhyankar SNESVIComputeMeritFunctionGradient - Computes the gradient of the merit function psi. 586ee657d29SShri Abhyankar 587ee657d29SShri Abhyankar Input Parameters: 588ee657d29SShri Abhyankar phi - semismooth function. 589ee657d29SShri Abhyankar H - semismooth jacobian 590ee657d29SShri Abhyankar 591ee657d29SShri Abhyankar Output Parameters: 592ee657d29SShri Abhyankar dpsi - merit function gradient 593ee657d29SShri Abhyankar 594ee657d29SShri Abhyankar Notes: 595ee657d29SShri Abhyankar The merit function gradient is computed as follows 596ee657d29SShri Abhyankar dpsi = H^T*phi 597ee657d29SShri Abhyankar */ 598ee657d29SShri Abhyankar #undef __FUNCT__ 599ee657d29SShri Abhyankar #define __FUNCT__ "SNESVIComputeMeritFunctionGradient" 600ee657d29SShri Abhyankar PetscErrorCode SNESVIComputeMeritFunctionGradient(Mat H, Vec phi, Vec dpsi) 601ee657d29SShri Abhyankar { 602ee657d29SShri Abhyankar PetscErrorCode ierr; 603ee657d29SShri Abhyankar 604ee657d29SShri Abhyankar PetscFunctionBegin; 6055f48b12bSBarry Smith ierr = MatMultTranspose(H,phi,dpsi);CHKERRQ(ierr); 606ee657d29SShri Abhyankar PetscFunctionReturn(0); 607ee657d29SShri Abhyankar } 608ee657d29SShri Abhyankar 609c1a5e521SShri Abhyankar /* -------------------------------------------------------------------------- */ 610c1a5e521SShri Abhyankar /* 611c1a5e521SShri Abhyankar SNESVIProjectOntoBounds - Projects X onto the feasible region so that Xl[i] <= X[i] <= Xu[i] for i = 1...n. 612c1a5e521SShri Abhyankar 613c1a5e521SShri Abhyankar Input Parameters: 614c1a5e521SShri Abhyankar . SNES - nonlinear solver context 615c1a5e521SShri Abhyankar 616c1a5e521SShri Abhyankar Output Parameters: 617c1a5e521SShri Abhyankar . X - Bound projected X 618c1a5e521SShri Abhyankar 619c1a5e521SShri Abhyankar */ 620c1a5e521SShri Abhyankar 621c1a5e521SShri Abhyankar #undef __FUNCT__ 622c1a5e521SShri Abhyankar #define __FUNCT__ "SNESVIProjectOntoBounds" 623c1a5e521SShri Abhyankar PetscErrorCode SNESVIProjectOntoBounds(SNES snes,Vec X) 624c1a5e521SShri Abhyankar { 625c1a5e521SShri Abhyankar PetscErrorCode ierr; 626c1a5e521SShri Abhyankar SNES_VI *vi = (SNES_VI*)snes->data; 627c1a5e521SShri Abhyankar const PetscScalar *xl,*xu; 628c1a5e521SShri Abhyankar PetscScalar *x; 629c1a5e521SShri Abhyankar PetscInt i,n; 630c1a5e521SShri Abhyankar 631c1a5e521SShri Abhyankar PetscFunctionBegin; 632c1a5e521SShri Abhyankar ierr = VecGetLocalSize(X,&n);CHKERRQ(ierr); 633c1a5e521SShri Abhyankar ierr = VecGetArray(X,&x);CHKERRQ(ierr); 634c1a5e521SShri Abhyankar ierr = VecGetArrayRead(vi->xl,&xl);CHKERRQ(ierr); 635c1a5e521SShri Abhyankar ierr = VecGetArrayRead(vi->xu,&xu);CHKERRQ(ierr); 636c1a5e521SShri Abhyankar 637c1a5e521SShri Abhyankar for(i = 0;i<n;i++) { 63810f5ae6bSBarry Smith if (PetscRealPart(x[i]) < PetscRealPart(xl[i])) x[i] = xl[i]; 63910f5ae6bSBarry Smith else if (PetscRealPart(x[i]) > PetscRealPart(xu[i])) x[i] = xu[i]; 640c1a5e521SShri Abhyankar } 641c1a5e521SShri Abhyankar ierr = VecRestoreArray(X,&x);CHKERRQ(ierr); 642c1a5e521SShri Abhyankar ierr = VecRestoreArrayRead(vi->xl,&xl);CHKERRQ(ierr); 643c1a5e521SShri Abhyankar ierr = VecRestoreArrayRead(vi->xu,&xu);CHKERRQ(ierr); 644c1a5e521SShri Abhyankar PetscFunctionReturn(0); 645c1a5e521SShri Abhyankar } 646c1a5e521SShri Abhyankar 6472b4ed282SShri Abhyankar /* -------------------------------------------------------------------- 6482b4ed282SShri Abhyankar 6492b4ed282SShri Abhyankar This file implements a semismooth truncated Newton method with a line search, 6502b4ed282SShri Abhyankar for solving a system of nonlinear equations in complementarity form, using the KSP, Vec, 6512b4ed282SShri Abhyankar and Mat interfaces for linear solvers, vectors, and matrices, 6522b4ed282SShri Abhyankar respectively. 6532b4ed282SShri Abhyankar 6542b4ed282SShri Abhyankar The following basic routines are required for each nonlinear solver: 6552b4ed282SShri Abhyankar SNESCreate_XXX() - Creates a nonlinear solver context 6562b4ed282SShri Abhyankar SNESSetFromOptions_XXX() - Sets runtime options 6572b4ed282SShri Abhyankar SNESSolve_XXX() - Solves the nonlinear system 6582b4ed282SShri Abhyankar SNESDestroy_XXX() - Destroys the nonlinear solver context 6592b4ed282SShri Abhyankar The suffix "_XXX" denotes a particular implementation, in this case 6602b4ed282SShri Abhyankar we use _VI (e.g., SNESCreate_VI, SNESSolve_VI) for solving 6612b4ed282SShri Abhyankar systems of nonlinear equations with a line search (LS) method. 6622b4ed282SShri Abhyankar These routines are actually called via the common user interface 6632b4ed282SShri Abhyankar routines SNESCreate(), SNESSetFromOptions(), SNESSolve(), and 6642b4ed282SShri Abhyankar SNESDestroy(), so the application code interface remains identical 6652b4ed282SShri Abhyankar for all nonlinear solvers. 6662b4ed282SShri Abhyankar 6672b4ed282SShri Abhyankar Another key routine is: 6682b4ed282SShri Abhyankar SNESSetUp_XXX() - Prepares for the use of a nonlinear solver 6692b4ed282SShri Abhyankar by setting data structures and options. The interface routine SNESSetUp() 6702b4ed282SShri Abhyankar is not usually called directly by the user, but instead is called by 6712b4ed282SShri Abhyankar SNESSolve() if necessary. 6722b4ed282SShri Abhyankar 6732b4ed282SShri Abhyankar Additional basic routines are: 6742b4ed282SShri Abhyankar SNESView_XXX() - Prints details of runtime options that 6752b4ed282SShri Abhyankar have actually been used. 6762b4ed282SShri Abhyankar These are called by application codes via the interface routines 6772b4ed282SShri Abhyankar SNESView(). 6782b4ed282SShri Abhyankar 6792b4ed282SShri Abhyankar The various types of solvers (preconditioners, Krylov subspace methods, 6802b4ed282SShri Abhyankar nonlinear solvers, timesteppers) are all organized similarly, so the 6812b4ed282SShri Abhyankar above description applies to these categories also. 6822b4ed282SShri Abhyankar 6832b4ed282SShri Abhyankar -------------------------------------------------------------------- */ 6842b4ed282SShri Abhyankar /* 68569c03620SShri Abhyankar SNESSolveVI_SS - Solves the complementarity problem with a semismooth Newton 6862b4ed282SShri Abhyankar method using a line search. 6872b4ed282SShri Abhyankar 6882b4ed282SShri Abhyankar Input Parameters: 6892b4ed282SShri Abhyankar . snes - the SNES context 6902b4ed282SShri Abhyankar 6912b4ed282SShri Abhyankar Output Parameter: 6922b4ed282SShri Abhyankar . outits - number of iterations until termination 6932b4ed282SShri Abhyankar 6942b4ed282SShri Abhyankar Application Interface Routine: SNESSolve() 6952b4ed282SShri Abhyankar 6962b4ed282SShri Abhyankar Notes: 6972b4ed282SShri Abhyankar This implements essentially a semismooth Newton method with a 69851defd01SShri Abhyankar line search. The default line search does not do any line seach 69951defd01SShri Abhyankar but rather takes a full newton step. 7002b4ed282SShri Abhyankar */ 7012b4ed282SShri Abhyankar #undef __FUNCT__ 70269c03620SShri Abhyankar #define __FUNCT__ "SNESSolveVI_SS" 70369c03620SShri Abhyankar PetscErrorCode SNESSolveVI_SS(SNES snes) 7042b4ed282SShri Abhyankar { 7052b4ed282SShri Abhyankar SNES_VI *vi = (SNES_VI*)snes->data; 7062b4ed282SShri Abhyankar PetscErrorCode ierr; 7072b4ed282SShri Abhyankar PetscInt maxits,i,lits; 7083b336b49SShri Abhyankar PetscBool lssucceed; 7092b4ed282SShri Abhyankar MatStructure flg = DIFFERENT_NONZERO_PATTERN; 7102b4ed282SShri Abhyankar PetscReal gnorm,xnorm=0,ynorm; 7112b4ed282SShri Abhyankar Vec Y,X,F,G,W; 7122b4ed282SShri Abhyankar KSPConvergedReason kspreason; 7132b4ed282SShri Abhyankar 7142b4ed282SShri Abhyankar PetscFunctionBegin; 7159ce7406fSBarry Smith vi->computeuserfunction = snes->ops->computefunction; 7169ce7406fSBarry Smith snes->ops->computefunction = SNESVIComputeFunction; 7179ce7406fSBarry Smith 7182b4ed282SShri Abhyankar snes->numFailures = 0; 7192b4ed282SShri Abhyankar snes->numLinearSolveFailures = 0; 7202b4ed282SShri Abhyankar snes->reason = SNES_CONVERGED_ITERATING; 7212b4ed282SShri Abhyankar 7222b4ed282SShri Abhyankar maxits = snes->max_its; /* maximum number of iterations */ 7232b4ed282SShri Abhyankar X = snes->vec_sol; /* solution vector */ 7242b4ed282SShri Abhyankar F = snes->vec_func; /* residual vector */ 7252b4ed282SShri Abhyankar Y = snes->work[0]; /* work vectors */ 7262b4ed282SShri Abhyankar G = snes->work[1]; 7272b4ed282SShri Abhyankar W = snes->work[2]; 7282b4ed282SShri Abhyankar 7292b4ed282SShri Abhyankar ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 7302b4ed282SShri Abhyankar snes->iter = 0; 7312b4ed282SShri Abhyankar snes->norm = 0.0; 7322b4ed282SShri Abhyankar ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 7332b4ed282SShri Abhyankar 7347fe79bc4SShri Abhyankar ierr = SNESVIProjectOntoBounds(snes,X);CHKERRQ(ierr); 7352b4ed282SShri Abhyankar ierr = SNESComputeFunction(snes,X,vi->phi);CHKERRQ(ierr); 7362b4ed282SShri Abhyankar if (snes->domainerror) { 7372b4ed282SShri Abhyankar snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN; 7389ce7406fSBarry Smith snes->ops->computefunction = vi->computeuserfunction; 7392b4ed282SShri Abhyankar PetscFunctionReturn(0); 7402b4ed282SShri Abhyankar } 7412b4ed282SShri Abhyankar /* Compute Merit function */ 7422b4ed282SShri Abhyankar ierr = SNESVIComputeMeritFunction(vi->phi,&vi->merit,&vi->phinorm);CHKERRQ(ierr); 7432b4ed282SShri Abhyankar 7442b4ed282SShri Abhyankar ierr = VecNormBegin(X,NORM_2,&xnorm);CHKERRQ(ierr); /* xnorm <- ||x|| */ 7452b4ed282SShri Abhyankar ierr = VecNormEnd(X,NORM_2,&xnorm);CHKERRQ(ierr); 74662cbcd01SMatthew G Knepley if (PetscIsInfOrNanReal(vi->merit)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number"); 7472b4ed282SShri Abhyankar 7482b4ed282SShri Abhyankar ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 7492b4ed282SShri Abhyankar snes->norm = vi->phinorm; 7502b4ed282SShri Abhyankar ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 7512b4ed282SShri Abhyankar SNESLogConvHistory(snes,vi->phinorm,0); 7527a03ce2fSLisandro Dalcin ierr = SNESMonitor(snes,0,vi->phinorm);CHKERRQ(ierr); 7532b4ed282SShri Abhyankar 7542b4ed282SShri Abhyankar /* set parameter for default relative tolerance convergence test */ 7552b4ed282SShri Abhyankar snes->ttol = vi->phinorm*snes->rtol; 7562b4ed282SShri Abhyankar /* test convergence */ 7572b4ed282SShri Abhyankar ierr = (*snes->ops->converged)(snes,0,0.0,0.0,vi->phinorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); 7589ce7406fSBarry Smith if (snes->reason) { 7599ce7406fSBarry Smith snes->ops->computefunction = vi->computeuserfunction; 7609ce7406fSBarry Smith PetscFunctionReturn(0); 7619ce7406fSBarry Smith } 7622b4ed282SShri Abhyankar 7632b4ed282SShri Abhyankar for (i=0; i<maxits; i++) { 7642b4ed282SShri Abhyankar 7652b4ed282SShri Abhyankar /* Call general purpose update function */ 7662b4ed282SShri Abhyankar if (snes->ops->update) { 7672b4ed282SShri Abhyankar ierr = (*snes->ops->update)(snes, snes->iter);CHKERRQ(ierr); 7682b4ed282SShri Abhyankar } 7692b4ed282SShri Abhyankar 7702b4ed282SShri Abhyankar /* Solve J Y = Phi, where J is the semismooth jacobian */ 771a79edbefSShri Abhyankar /* Get the nonlinear function jacobian */ 7722b4ed282SShri Abhyankar ierr = SNESComputeJacobian(snes,X,&snes->jacobian,&snes->jacobian_pre,&flg);CHKERRQ(ierr); 773a79edbefSShri Abhyankar /* Get the diagonal shift and row scaling vectors */ 774a79edbefSShri Abhyankar ierr = SNESVIComputeBsubdifferentialVectors(snes,X,F,snes->jacobian,vi->Da,vi->Db);CHKERRQ(ierr); 775a79edbefSShri Abhyankar /* Compute the semismooth jacobian */ 776a79edbefSShri Abhyankar ierr = SNESVIComputeJacobian(snes->jacobian,snes->jacobian_pre,vi->Da,vi->Db);CHKERRQ(ierr); 777ee657d29SShri Abhyankar /* Compute the merit function gradient */ 778ee657d29SShri Abhyankar ierr = SNESVIComputeMeritFunctionGradient(snes->jacobian,vi->phi,vi->dpsi);CHKERRQ(ierr); 7792b4ed282SShri Abhyankar ierr = KSPSetOperators(snes->ksp,snes->jacobian,snes->jacobian_pre,flg);CHKERRQ(ierr); 7802b4ed282SShri Abhyankar ierr = SNES_KSPSolve(snes,snes->ksp,vi->phi,Y);CHKERRQ(ierr); 7812b4ed282SShri Abhyankar ierr = KSPGetConvergedReason(snes->ksp,&kspreason);CHKERRQ(ierr); 7823b336b49SShri Abhyankar 7833b336b49SShri Abhyankar if (kspreason < 0) { 7842b4ed282SShri Abhyankar if (++snes->numLinearSolveFailures >= snes->maxLinearSolveFailures) { 7852b4ed282SShri 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); 7862b4ed282SShri Abhyankar snes->reason = SNES_DIVERGED_LINEAR_SOLVE; 7872b4ed282SShri Abhyankar break; 7882b4ed282SShri Abhyankar } 7892b4ed282SShri Abhyankar } 7902b4ed282SShri Abhyankar ierr = KSPGetIterationNumber(snes->ksp,&lits);CHKERRQ(ierr); 7912b4ed282SShri Abhyankar snes->linear_its += lits; 7922b4ed282SShri Abhyankar ierr = PetscInfo2(snes,"iter=%D, linear solve iterations=%D\n",snes->iter,lits);CHKERRQ(ierr); 7932b4ed282SShri Abhyankar /* 7942b4ed282SShri Abhyankar if (vi->precheckstep) { 795ace3abfcSBarry Smith PetscBool changed_y = PETSC_FALSE; 7962b4ed282SShri Abhyankar ierr = (*vi->precheckstep)(snes,X,Y,vi->precheck,&changed_y);CHKERRQ(ierr); 7972b4ed282SShri Abhyankar } 7982b4ed282SShri Abhyankar 7992b4ed282SShri Abhyankar if (PetscLogPrintInfo){ 8002b4ed282SShri Abhyankar ierr = SNESVICheckResidual_Private(snes,snes->jacobian,F,Y,G,W);CHKERRQ(ierr); 8012b4ed282SShri Abhyankar } 8022b4ed282SShri Abhyankar */ 8032b4ed282SShri Abhyankar /* Compute a (scaled) negative update in the line search routine: 8042b4ed282SShri Abhyankar Y <- X - lambda*Y 8052b4ed282SShri Abhyankar and evaluate G = function(Y) (depends on the line search). 8062b4ed282SShri Abhyankar */ 8072b4ed282SShri Abhyankar ierr = VecCopy(Y,snes->vec_sol_update);CHKERRQ(ierr); 8082b4ed282SShri Abhyankar ynorm = 1; gnorm = vi->phinorm; 8092b4ed282SShri Abhyankar ierr = (*vi->LineSearch)(snes,vi->lsP,X,vi->phi,G,Y,W,vi->phinorm,xnorm,&ynorm,&gnorm,&lssucceed);CHKERRQ(ierr); 8102b4ed282SShri Abhyankar ierr = PetscInfo4(snes,"fnorm=%18.16e, gnorm=%18.16e, ynorm=%18.16e, lssucceed=%d\n",vi->phinorm,gnorm,ynorm,(int)lssucceed);CHKERRQ(ierr); 8112b4ed282SShri Abhyankar if (snes->reason == SNES_DIVERGED_FUNCTION_COUNT) break; 8122b4ed282SShri Abhyankar if (snes->domainerror) { 8132b4ed282SShri Abhyankar snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN; 8149ce7406fSBarry Smith snes->ops->computefunction = vi->computeuserfunction; 8152b4ed282SShri Abhyankar PetscFunctionReturn(0); 8162b4ed282SShri Abhyankar } 8172b4ed282SShri Abhyankar if (!lssucceed) { 8182b4ed282SShri Abhyankar if (++snes->numFailures >= snes->maxFailures) { 819ace3abfcSBarry Smith PetscBool ismin; 8202b4ed282SShri Abhyankar snes->reason = SNES_DIVERGED_LINE_SEARCH; 8212b4ed282SShri Abhyankar ierr = SNESVICheckLocalMin_Private(snes,snes->jacobian,G,W,gnorm,&ismin);CHKERRQ(ierr); 8222b4ed282SShri Abhyankar if (ismin) snes->reason = SNES_DIVERGED_LOCAL_MIN; 8232b4ed282SShri Abhyankar break; 8242b4ed282SShri Abhyankar } 8252b4ed282SShri Abhyankar } 8262b4ed282SShri Abhyankar /* Update function and solution vectors */ 8272b4ed282SShri Abhyankar vi->phinorm = gnorm; 8282b4ed282SShri Abhyankar vi->merit = 0.5*vi->phinorm*vi->phinorm; 8292b4ed282SShri Abhyankar ierr = VecCopy(G,vi->phi);CHKERRQ(ierr); 8302b4ed282SShri Abhyankar ierr = VecCopy(W,X);CHKERRQ(ierr); 8312b4ed282SShri Abhyankar /* Monitor convergence */ 8322b4ed282SShri Abhyankar ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 8332b4ed282SShri Abhyankar snes->iter = i+1; 8342b4ed282SShri Abhyankar snes->norm = vi->phinorm; 8352b4ed282SShri Abhyankar ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 8362b4ed282SShri Abhyankar SNESLogConvHistory(snes,snes->norm,lits); 8377a03ce2fSLisandro Dalcin ierr = SNESMonitor(snes,snes->iter,snes->norm);CHKERRQ(ierr); 8382b4ed282SShri Abhyankar /* Test for convergence, xnorm = || X || */ 8392b4ed282SShri Abhyankar if (snes->ops->converged != SNESSkipConverged) { ierr = VecNorm(X,NORM_2,&xnorm);CHKERRQ(ierr); } 8402b4ed282SShri Abhyankar ierr = (*snes->ops->converged)(snes,snes->iter,xnorm,ynorm,vi->phinorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); 8412b4ed282SShri Abhyankar if (snes->reason) break; 8422b4ed282SShri Abhyankar } 8432b4ed282SShri Abhyankar if (i == maxits) { 8442b4ed282SShri Abhyankar ierr = PetscInfo1(snes,"Maximum number of iterations has been reached: %D\n",maxits);CHKERRQ(ierr); 8452b4ed282SShri Abhyankar if(!snes->reason) snes->reason = SNES_DIVERGED_MAX_IT; 8462b4ed282SShri Abhyankar } 8479ce7406fSBarry Smith snes->ops->computefunction = vi->computeuserfunction; 8482b4ed282SShri Abhyankar PetscFunctionReturn(0); 8492b4ed282SShri Abhyankar } 85069c03620SShri Abhyankar 85169c03620SShri Abhyankar #undef __FUNCT__ 852693ddf92SShri Abhyankar #define __FUNCT__ "SNESVIGetActiveSetIS" 853693ddf92SShri Abhyankar /* 854693ddf92SShri Abhyankar SNESVIGetActiveSetIndices - Gets the global indices for the active set variables 855693ddf92SShri Abhyankar 856693ddf92SShri Abhyankar Input parameter 857693ddf92SShri Abhyankar . snes - the SNES context 858693ddf92SShri Abhyankar . X - the snes solution vector 859693ddf92SShri Abhyankar . F - the nonlinear function vector 860693ddf92SShri Abhyankar 861693ddf92SShri Abhyankar Output parameter 862693ddf92SShri Abhyankar . ISact - active set index set 863693ddf92SShri Abhyankar */ 864693ddf92SShri Abhyankar PetscErrorCode SNESVIGetActiveSetIS(SNES snes,Vec X,Vec F,IS* ISact) 865d950fb63SShri Abhyankar { 866d950fb63SShri Abhyankar PetscErrorCode ierr; 867693ddf92SShri Abhyankar SNES_VI *vi = (SNES_VI*)snes->data; 868693ddf92SShri Abhyankar Vec Xl=vi->xl,Xu=vi->xu; 869693ddf92SShri Abhyankar const PetscScalar *x,*f,*xl,*xu; 870693ddf92SShri Abhyankar PetscInt *idx_act,i,nlocal,nloc_isact=0,ilow,ihigh,i1=0; 871d950fb63SShri Abhyankar 872d950fb63SShri Abhyankar PetscFunctionBegin; 873d950fb63SShri Abhyankar ierr = VecGetLocalSize(X,&nlocal);CHKERRQ(ierr); 874d950fb63SShri Abhyankar ierr = VecGetOwnershipRange(X,&ilow,&ihigh);CHKERRQ(ierr); 875fe835674SShri Abhyankar ierr = VecGetArrayRead(X,&x);CHKERRQ(ierr); 876fe835674SShri Abhyankar ierr = VecGetArrayRead(Xl,&xl);CHKERRQ(ierr); 877fe835674SShri Abhyankar ierr = VecGetArrayRead(Xu,&xu);CHKERRQ(ierr); 878fe835674SShri Abhyankar ierr = VecGetArrayRead(F,&f);CHKERRQ(ierr); 879693ddf92SShri Abhyankar /* Compute active set size */ 880d950fb63SShri Abhyankar for (i=0; i < nlocal;i++) { 88110f5ae6bSBarry 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++; 882d950fb63SShri Abhyankar } 883693ddf92SShri Abhyankar 884d950fb63SShri Abhyankar ierr = PetscMalloc(nloc_isact*sizeof(PetscInt),&idx_act);CHKERRQ(ierr); 885d950fb63SShri Abhyankar 886693ddf92SShri Abhyankar /* Set active set indices */ 887d950fb63SShri Abhyankar for(i=0; i < nlocal; i++) { 88810f5ae6bSBarry 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; 889d950fb63SShri Abhyankar } 890d950fb63SShri Abhyankar 891693ddf92SShri Abhyankar /* Create active set IS */ 89262298a1eSBarry Smith ierr = ISCreateGeneral(((PetscObject)snes)->comm,nloc_isact,idx_act,PETSC_OWN_POINTER,ISact);CHKERRQ(ierr); 893d950fb63SShri Abhyankar 894fe835674SShri Abhyankar ierr = VecRestoreArrayRead(X,&x);CHKERRQ(ierr); 895fe835674SShri Abhyankar ierr = VecRestoreArrayRead(Xl,&xl);CHKERRQ(ierr); 896fe835674SShri Abhyankar ierr = VecRestoreArrayRead(Xu,&xu);CHKERRQ(ierr); 897fe835674SShri Abhyankar ierr = VecRestoreArrayRead(F,&f);CHKERRQ(ierr); 898d950fb63SShri Abhyankar PetscFunctionReturn(0); 899d950fb63SShri Abhyankar } 900d950fb63SShri Abhyankar 901693ddf92SShri Abhyankar #undef __FUNCT__ 902693ddf92SShri Abhyankar #define __FUNCT__ "SNESVICreateIndexSets_RS" 903693ddf92SShri Abhyankar PetscErrorCode SNESVICreateIndexSets_RS(SNES snes,Vec X,Vec F,IS* ISact,IS* ISinact) 904693ddf92SShri Abhyankar { 905693ddf92SShri Abhyankar PetscErrorCode ierr; 906693ddf92SShri Abhyankar 907693ddf92SShri Abhyankar PetscFunctionBegin; 908693ddf92SShri Abhyankar ierr = SNESVIGetActiveSetIS(snes,X,F,ISact);CHKERRQ(ierr); 909693ddf92SShri Abhyankar ierr = ISComplement(*ISact,X->map->rstart,X->map->rend,ISinact);CHKERRQ(ierr); 910693ddf92SShri Abhyankar PetscFunctionReturn(0); 911693ddf92SShri Abhyankar } 912693ddf92SShri Abhyankar 913dbd914b8SShri Abhyankar /* Create active and inactive set vectors. The local size of this vector is set and petsc computes the global size */ 914dbd914b8SShri Abhyankar #undef __FUNCT__ 915fe835674SShri Abhyankar #define __FUNCT__ "SNESVICreateSubVectors" 916fe835674SShri Abhyankar PetscErrorCode SNESVICreateSubVectors(SNES snes,PetscInt n,Vec* newv) 917dbd914b8SShri Abhyankar { 918dbd914b8SShri Abhyankar PetscErrorCode ierr; 919dbd914b8SShri Abhyankar Vec v; 920dbd914b8SShri Abhyankar 921dbd914b8SShri Abhyankar PetscFunctionBegin; 922dbd914b8SShri Abhyankar ierr = VecCreate(((PetscObject)snes)->comm,&v);CHKERRQ(ierr); 923dbd914b8SShri Abhyankar ierr = VecSetSizes(v,n,PETSC_DECIDE);CHKERRQ(ierr); 924dbd914b8SShri Abhyankar ierr = VecSetFromOptions(v);CHKERRQ(ierr); 925dbd914b8SShri Abhyankar *newv = v; 926dbd914b8SShri Abhyankar 927dbd914b8SShri Abhyankar PetscFunctionReturn(0); 928dbd914b8SShri Abhyankar } 929dbd914b8SShri Abhyankar 930732bb160SShri Abhyankar /* Resets the snes PC and KSP when the active set sizes change */ 931732bb160SShri Abhyankar #undef __FUNCT__ 932732bb160SShri Abhyankar #define __FUNCT__ "SNESVIResetPCandKSP" 933732bb160SShri Abhyankar PetscErrorCode SNESVIResetPCandKSP(SNES snes,Mat Amat,Mat Pmat) 934732bb160SShri Abhyankar { 935732bb160SShri Abhyankar PetscErrorCode ierr; 936d0af7cd3SBarry Smith KSP snesksp; 937dbd914b8SShri Abhyankar 938732bb160SShri Abhyankar PetscFunctionBegin; 939732bb160SShri Abhyankar ierr = SNESGetKSP(snes,&snesksp);CHKERRQ(ierr); 940d0af7cd3SBarry Smith ierr = KSPReset(snesksp);CHKERRQ(ierr); 941c2efdce3SBarry Smith 942c2efdce3SBarry Smith /* 943d0af7cd3SBarry Smith KSP kspnew; 944d0af7cd3SBarry Smith PC pcnew; 945d0af7cd3SBarry Smith const MatSolverPackage stype; 946d0af7cd3SBarry Smith 947c2efdce3SBarry Smith 948732bb160SShri Abhyankar ierr = KSPCreate(((PetscObject)snes)->comm,&kspnew);CHKERRQ(ierr); 949732bb160SShri Abhyankar kspnew->pc_side = snesksp->pc_side; 950732bb160SShri Abhyankar kspnew->rtol = snesksp->rtol; 951732bb160SShri Abhyankar kspnew->abstol = snesksp->abstol; 952732bb160SShri Abhyankar kspnew->max_it = snesksp->max_it; 953732bb160SShri Abhyankar ierr = KSPSetType(kspnew,((PetscObject)snesksp)->type_name);CHKERRQ(ierr); 954732bb160SShri Abhyankar ierr = KSPGetPC(kspnew,&pcnew);CHKERRQ(ierr); 955732bb160SShri Abhyankar ierr = PCSetType(kspnew->pc,((PetscObject)snesksp->pc)->type_name);CHKERRQ(ierr); 956732bb160SShri Abhyankar ierr = PCSetOperators(kspnew->pc,Amat,Pmat,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr); 957732bb160SShri Abhyankar ierr = PCFactorGetMatSolverPackage(snesksp->pc,&stype);CHKERRQ(ierr); 958732bb160SShri Abhyankar ierr = PCFactorSetMatSolverPackage(kspnew->pc,stype);CHKERRQ(ierr); 9596bf464f9SBarry Smith ierr = KSPDestroy(&snesksp);CHKERRQ(ierr); 960732bb160SShri Abhyankar snes->ksp = kspnew; 961732bb160SShri Abhyankar ierr = PetscLogObjectParent(snes,kspnew);CHKERRQ(ierr); 962d0af7cd3SBarry Smith ierr = KSPSetFromOptions(kspnew);CHKERRQ(ierr);*/ 963732bb160SShri Abhyankar PetscFunctionReturn(0); 964732bb160SShri Abhyankar } 96569c03620SShri Abhyankar 96669c03620SShri Abhyankar 967fe835674SShri Abhyankar #undef __FUNCT__ 968fe835674SShri Abhyankar #define __FUNCT__ "SNESVIComputeInactiveSetFnorm" 96910f5ae6bSBarry Smith PetscErrorCode SNESVIComputeInactiveSetFnorm(SNES snes,Vec F,Vec X,PetscReal *fnorm) 970fe835674SShri Abhyankar { 971fe835674SShri Abhyankar PetscErrorCode ierr; 972fe835674SShri Abhyankar SNES_VI *vi = (SNES_VI*)snes->data; 973fe835674SShri Abhyankar const PetscScalar *x,*xl,*xu,*f; 974fe835674SShri Abhyankar PetscInt i,n; 975fe835674SShri Abhyankar PetscReal rnorm; 976fe835674SShri Abhyankar 977fe835674SShri Abhyankar PetscFunctionBegin; 978fe835674SShri Abhyankar ierr = VecGetLocalSize(X,&n);CHKERRQ(ierr); 979fe835674SShri Abhyankar ierr = VecGetArrayRead(vi->xl,&xl);CHKERRQ(ierr); 980fe835674SShri Abhyankar ierr = VecGetArrayRead(vi->xu,&xu);CHKERRQ(ierr); 981fe835674SShri Abhyankar ierr = VecGetArrayRead(X,&x);CHKERRQ(ierr); 982fe835674SShri Abhyankar ierr = VecGetArrayRead(F,&f);CHKERRQ(ierr); 983fe835674SShri Abhyankar rnorm = 0.0; 984fe835674SShri Abhyankar for (i=0; i<n; i++) { 98510f5ae6bSBarry 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]); 986fe835674SShri Abhyankar } 987fe835674SShri Abhyankar ierr = VecRestoreArrayRead(F,&f);CHKERRQ(ierr); 988fe835674SShri Abhyankar ierr = VecRestoreArrayRead(vi->xl,&xl);CHKERRQ(ierr); 989fe835674SShri Abhyankar ierr = VecRestoreArrayRead(vi->xu,&xu);CHKERRQ(ierr); 990fe835674SShri Abhyankar ierr = VecRestoreArrayRead(X,&x);CHKERRQ(ierr); 991d9822059SBarry Smith ierr = MPI_Allreduce(&rnorm,fnorm,1,MPIU_REAL,MPIU_SUM,((PetscObject)snes)->comm);CHKERRQ(ierr); 992fe835674SShri Abhyankar *fnorm = sqrt(*fnorm); 993fe835674SShri Abhyankar PetscFunctionReturn(0); 994fe835674SShri Abhyankar } 995fe835674SShri Abhyankar 996fe835674SShri Abhyankar /* Variational Inequality solver using reduce space method. No semismooth algorithm is 997c2efdce3SBarry Smith implemented in this algorithm. It basically identifies the active constraints and does 998c2efdce3SBarry Smith a linear solve on the other variables (those not associated with the active constraints). */ 999d950fb63SShri Abhyankar #undef __FUNCT__ 1000d950fb63SShri Abhyankar #define __FUNCT__ "SNESSolveVI_RS" 1001d950fb63SShri Abhyankar PetscErrorCode SNESSolveVI_RS(SNES snes) 1002d950fb63SShri Abhyankar { 1003d950fb63SShri Abhyankar SNES_VI *vi = (SNES_VI*)snes->data; 1004d950fb63SShri Abhyankar PetscErrorCode ierr; 1005abcba341SShri Abhyankar PetscInt maxits,i,lits; 1006d950fb63SShri Abhyankar PetscBool lssucceed; 1007d950fb63SShri Abhyankar MatStructure flg = DIFFERENT_NONZERO_PATTERN; 1008fe835674SShri Abhyankar PetscReal fnorm,gnorm,xnorm=0,ynorm; 1009d950fb63SShri Abhyankar Vec Y,X,F,G,W; 1010d950fb63SShri Abhyankar KSPConvergedReason kspreason; 1011d950fb63SShri Abhyankar 1012d950fb63SShri Abhyankar PetscFunctionBegin; 1013d950fb63SShri Abhyankar snes->numFailures = 0; 1014d950fb63SShri Abhyankar snes->numLinearSolveFailures = 0; 1015d950fb63SShri Abhyankar snes->reason = SNES_CONVERGED_ITERATING; 1016d950fb63SShri Abhyankar 1017d950fb63SShri Abhyankar maxits = snes->max_its; /* maximum number of iterations */ 1018d950fb63SShri Abhyankar X = snes->vec_sol; /* solution vector */ 1019d950fb63SShri Abhyankar F = snes->vec_func; /* residual vector */ 1020d950fb63SShri Abhyankar Y = snes->work[0]; /* work vectors */ 1021d950fb63SShri Abhyankar G = snes->work[1]; 1022d950fb63SShri Abhyankar W = snes->work[2]; 1023d950fb63SShri Abhyankar 1024d950fb63SShri Abhyankar ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 1025d950fb63SShri Abhyankar snes->iter = 0; 1026d950fb63SShri Abhyankar snes->norm = 0.0; 1027d950fb63SShri Abhyankar ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 1028d950fb63SShri Abhyankar 10297fe79bc4SShri Abhyankar ierr = SNESVIProjectOntoBounds(snes,X);CHKERRQ(ierr); 1030fe835674SShri Abhyankar ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr); 1031d950fb63SShri Abhyankar if (snes->domainerror) { 1032d950fb63SShri Abhyankar snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN; 1033d950fb63SShri Abhyankar PetscFunctionReturn(0); 1034d950fb63SShri Abhyankar } 1035fe835674SShri Abhyankar ierr = SNESVIComputeInactiveSetFnorm(snes,F,X,&fnorm);CHKERRQ(ierr); 1036d950fb63SShri Abhyankar ierr = VecNormBegin(X,NORM_2,&xnorm);CHKERRQ(ierr); /* xnorm <- ||x|| */ 1037d950fb63SShri Abhyankar ierr = VecNormEnd(X,NORM_2,&xnorm);CHKERRQ(ierr); 103862cbcd01SMatthew G Knepley if (PetscIsInfOrNanReal(fnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number"); 1039d950fb63SShri Abhyankar 1040d950fb63SShri Abhyankar ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 1041fe835674SShri Abhyankar snes->norm = fnorm; 1042d950fb63SShri Abhyankar ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 1043fe835674SShri Abhyankar SNESLogConvHistory(snes,fnorm,0); 10447a03ce2fSLisandro Dalcin ierr = SNESMonitor(snes,0,fnorm);CHKERRQ(ierr); 1045d950fb63SShri Abhyankar 1046d950fb63SShri Abhyankar /* set parameter for default relative tolerance convergence test */ 1047fe835674SShri Abhyankar snes->ttol = fnorm*snes->rtol; 1048d950fb63SShri Abhyankar /* test convergence */ 1049fe835674SShri Abhyankar ierr = (*snes->ops->converged)(snes,0,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); 1050d950fb63SShri Abhyankar if (snes->reason) PetscFunctionReturn(0); 1051d950fb63SShri Abhyankar 1052d950fb63SShri Abhyankar for (i=0; i<maxits; i++) { 1053d950fb63SShri Abhyankar 1054d950fb63SShri Abhyankar IS IS_act,IS_inact; /* _act -> active set _inact -> inactive set */ 1055d950fb63SShri Abhyankar VecScatter scat_act,scat_inact; 1056abcba341SShri Abhyankar PetscInt nis_act,nis_inact; 1057fe835674SShri Abhyankar Vec Y_act,Y_inact,F_inact; 1058d950fb63SShri Abhyankar Mat jac_inact_inact,prejac_inact_inact; 105962298a1eSBarry Smith IS keptrows; 1060abcba341SShri Abhyankar PetscBool isequal; 1061d950fb63SShri Abhyankar 1062d950fb63SShri Abhyankar /* Call general purpose update function */ 1063d950fb63SShri Abhyankar if (snes->ops->update) { 1064d950fb63SShri Abhyankar ierr = (*snes->ops->update)(snes, snes->iter);CHKERRQ(ierr); 1065d950fb63SShri Abhyankar } 1066d950fb63SShri Abhyankar ierr = SNESComputeJacobian(snes,X,&snes->jacobian,&snes->jacobian_pre,&flg);CHKERRQ(ierr); 106762298a1eSBarry Smith 1068d950fb63SShri Abhyankar /* Create active and inactive index sets */ 1069693ddf92SShri Abhyankar ierr = SNESVICreateIndexSets_RS(snes,X,F,&IS_act,&IS_inact);CHKERRQ(ierr); 1070d950fb63SShri Abhyankar 10714dcab191SBarry Smith 1072abcba341SShri Abhyankar /* Create inactive set submatrix */ 107362298a1eSBarry Smith ierr = MatGetSubMatrix(snes->jacobian,IS_inact,IS_inact,MAT_INITIAL_MATRIX,&jac_inact_inact);CHKERRQ(ierr); 1074b3a44c85SBarry Smith ierr = MatFindNonzeroRows(jac_inact_inact,&keptrows);CHKERRQ(ierr); 107562298a1eSBarry Smith if (keptrows) { 107662298a1eSBarry Smith PetscInt cnt,*nrows,k; 107762298a1eSBarry Smith const PetscInt *krows,*inact; 107827d4218bSShri Abhyankar PetscInt rstart=jac_inact_inact->rmap->rstart; 107962298a1eSBarry Smith 10806bf464f9SBarry Smith ierr = MatDestroy(&jac_inact_inact);CHKERRQ(ierr); 10816bf464f9SBarry Smith ierr = ISDestroy(&IS_act);CHKERRQ(ierr); 108262298a1eSBarry Smith 108362298a1eSBarry Smith ierr = ISGetLocalSize(keptrows,&cnt);CHKERRQ(ierr); 108462298a1eSBarry Smith ierr = ISGetIndices(keptrows,&krows);CHKERRQ(ierr); 108562298a1eSBarry Smith ierr = ISGetIndices(IS_inact,&inact);CHKERRQ(ierr); 108662298a1eSBarry Smith ierr = PetscMalloc(cnt*sizeof(PetscInt),&nrows);CHKERRQ(ierr); 108762298a1eSBarry Smith for (k=0; k<cnt; k++) { 108827d4218bSShri Abhyankar nrows[k] = inact[krows[k]-rstart]; 108962298a1eSBarry Smith } 109062298a1eSBarry Smith ierr = ISRestoreIndices(keptrows,&krows);CHKERRQ(ierr); 109162298a1eSBarry Smith ierr = ISRestoreIndices(IS_inact,&inact);CHKERRQ(ierr); 10926bf464f9SBarry Smith ierr = ISDestroy(&keptrows);CHKERRQ(ierr); 10936bf464f9SBarry Smith ierr = ISDestroy(&IS_inact);CHKERRQ(ierr); 109462298a1eSBarry Smith 109527d4218bSShri Abhyankar ierr = ISCreateGeneral(PETSC_COMM_WORLD,cnt,nrows,PETSC_OWN_POINTER,&IS_inact);CHKERRQ(ierr); 109627d4218bSShri Abhyankar ierr = ISComplement(IS_inact,F->map->rstart,F->map->rend,&IS_act);CHKERRQ(ierr); 109762298a1eSBarry Smith ierr = MatGetSubMatrix(snes->jacobian,IS_inact,IS_inact,MAT_INITIAL_MATRIX,&jac_inact_inact);CHKERRQ(ierr); 109862298a1eSBarry Smith } 10999e516c8fSBarry Smith ierr = DMSetVI(snes->dm,vi->xu,vi->xl,X,F,IS_inact);CHKERRQ(ierr); 110062298a1eSBarry Smith 1101d950fb63SShri Abhyankar /* Get sizes of active and inactive sets */ 1102d950fb63SShri Abhyankar ierr = ISGetLocalSize(IS_act,&nis_act);CHKERRQ(ierr); 1103d950fb63SShri Abhyankar ierr = ISGetLocalSize(IS_inact,&nis_inact);CHKERRQ(ierr); 1104d950fb63SShri Abhyankar 1105d950fb63SShri Abhyankar /* Create active and inactive set vectors */ 1106fe835674SShri Abhyankar ierr = SNESVICreateSubVectors(snes,nis_inact,&F_inact);CHKERRQ(ierr); 1107fe835674SShri Abhyankar ierr = SNESVICreateSubVectors(snes,nis_act,&Y_act);CHKERRQ(ierr); 1108fe835674SShri Abhyankar ierr = SNESVICreateSubVectors(snes,nis_inact,&Y_inact);CHKERRQ(ierr); 1109d950fb63SShri Abhyankar 1110d950fb63SShri Abhyankar /* Create scatter contexts */ 1111d950fb63SShri Abhyankar ierr = VecScatterCreate(Y,IS_act,Y_act,PETSC_NULL,&scat_act);CHKERRQ(ierr); 1112d950fb63SShri Abhyankar ierr = VecScatterCreate(Y,IS_inact,Y_inact,PETSC_NULL,&scat_inact);CHKERRQ(ierr); 1113d950fb63SShri Abhyankar 1114d950fb63SShri Abhyankar /* Do a vec scatter to active and inactive set vectors */ 1115fe835674SShri Abhyankar ierr = VecScatterBegin(scat_inact,F,F_inact,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1116fe835674SShri Abhyankar ierr = VecScatterEnd(scat_inact,F,F_inact,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1117d950fb63SShri Abhyankar 1118d950fb63SShri Abhyankar ierr = VecScatterBegin(scat_act,Y,Y_act,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1119d950fb63SShri Abhyankar ierr = VecScatterEnd(scat_act,Y,Y_act,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1120d950fb63SShri Abhyankar 1121d950fb63SShri Abhyankar ierr = VecScatterBegin(scat_inact,Y,Y_inact,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1122d950fb63SShri Abhyankar ierr = VecScatterEnd(scat_inact,Y,Y_inact,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1123d950fb63SShri Abhyankar 1124d950fb63SShri Abhyankar /* Active set direction = 0 */ 1125d950fb63SShri Abhyankar ierr = VecSet(Y_act,0);CHKERRQ(ierr); 1126d950fb63SShri Abhyankar if (snes->jacobian != snes->jacobian_pre) { 1127d950fb63SShri Abhyankar ierr = MatGetSubMatrix(snes->jacobian_pre,IS_inact,IS_inact,MAT_INITIAL_MATRIX,&prejac_inact_inact);CHKERRQ(ierr); 1128d950fb63SShri Abhyankar } else prejac_inact_inact = jac_inact_inact; 1129d950fb63SShri Abhyankar 1130abcba341SShri Abhyankar ierr = ISEqual(vi->IS_inact_prev,IS_inact,&isequal);CHKERRQ(ierr); 1131abcba341SShri Abhyankar if (!isequal) { 1132732bb160SShri Abhyankar ierr = SNESVIResetPCandKSP(snes,jac_inact_inact,prejac_inact_inact);CHKERRQ(ierr); 1133d950fb63SShri Abhyankar } 1134d950fb63SShri Abhyankar 113513e0d083SBarry Smith /* ierr = ISView(IS_inact,0);CHKERRQ(ierr); */ 113613e0d083SBarry Smith /* ierr = ISView(IS_act,0);CHKERRQ(ierr);*/ 113713e0d083SBarry Smith /* ierr = MatView(snes->jacobian_pre,0); */ 113813e0d083SBarry Smith 1139d950fb63SShri Abhyankar ierr = KSPSetOperators(snes->ksp,jac_inact_inact,prejac_inact_inact,flg);CHKERRQ(ierr); 114013e0d083SBarry Smith ierr = KSPSetUp(snes->ksp);CHKERRQ(ierr); 114113e0d083SBarry Smith { 114213e0d083SBarry Smith PC pc; 114313e0d083SBarry Smith PetscBool flg; 114413e0d083SBarry Smith ierr = KSPGetPC(snes->ksp,&pc);CHKERRQ(ierr); 114513e0d083SBarry Smith ierr = PetscTypeCompare((PetscObject)pc,PCFIELDSPLIT,&flg);CHKERRQ(ierr); 114613e0d083SBarry Smith if (flg) { 114713e0d083SBarry Smith KSP *subksps; 114813e0d083SBarry Smith ierr = PCFieldSplitGetSubKSP(pc,PETSC_NULL,&subksps);CHKERRQ(ierr); 114913e0d083SBarry Smith ierr = KSPGetPC(subksps[0],&pc);CHKERRQ(ierr); 115013e0d083SBarry Smith ierr = PetscFree(subksps);CHKERRQ(ierr); 115113e0d083SBarry Smith ierr = PetscTypeCompare((PetscObject)pc,PCBJACOBI,&flg);CHKERRQ(ierr); 115213e0d083SBarry Smith if (flg) { 115313e0d083SBarry Smith PetscInt n,N = 101*101,j,cnts[3] = {0,0,0}; 115413e0d083SBarry Smith const PetscInt *ii; 115513e0d083SBarry Smith 115613e0d083SBarry Smith ierr = ISGetSize(IS_inact,&n);CHKERRQ(ierr); 115713e0d083SBarry Smith ierr = ISGetIndices(IS_inact,&ii);CHKERRQ(ierr); 115813e0d083SBarry Smith for (j=0; j<n; j++) { 115913e0d083SBarry Smith if (ii[j] < N) cnts[0]++; 116013e0d083SBarry Smith else if (ii[j] < 2*N) cnts[1]++; 116113e0d083SBarry Smith else if (ii[j] < 3*N) cnts[2]++; 116213e0d083SBarry Smith } 116313e0d083SBarry Smith ierr = ISRestoreIndices(IS_inact,&ii);CHKERRQ(ierr); 116413e0d083SBarry Smith 116513e0d083SBarry Smith ierr = PCBJacobiSetTotalBlocks(pc,3,cnts);CHKERRQ(ierr); 116613e0d083SBarry Smith } 116713e0d083SBarry Smith } 116813e0d083SBarry Smith } 116913e0d083SBarry Smith 1170fe835674SShri Abhyankar ierr = SNES_KSPSolve(snes,snes->ksp,F_inact,Y_inact);CHKERRQ(ierr); 1171d950fb63SShri Abhyankar ierr = KSPGetConvergedReason(snes->ksp,&kspreason);CHKERRQ(ierr); 1172d950fb63SShri Abhyankar if (kspreason < 0) { 1173d950fb63SShri Abhyankar if (++snes->numLinearSolveFailures >= snes->maxLinearSolveFailures) { 1174d950fb63SShri 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); 1175d950fb63SShri Abhyankar snes->reason = SNES_DIVERGED_LINEAR_SOLVE; 1176d950fb63SShri Abhyankar break; 1177d950fb63SShri Abhyankar } 1178d950fb63SShri Abhyankar } 1179d950fb63SShri Abhyankar 1180d950fb63SShri Abhyankar ierr = VecScatterBegin(scat_act,Y_act,Y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1181d950fb63SShri Abhyankar ierr = VecScatterEnd(scat_act,Y_act,Y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1182d950fb63SShri Abhyankar ierr = VecScatterBegin(scat_inact,Y_inact,Y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1183d950fb63SShri Abhyankar ierr = VecScatterEnd(scat_inact,Y_inact,Y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1184d950fb63SShri Abhyankar 11856bf464f9SBarry Smith ierr = VecDestroy(&F_inact);CHKERRQ(ierr); 11866bf464f9SBarry Smith ierr = VecDestroy(&Y_act);CHKERRQ(ierr); 11876bf464f9SBarry Smith ierr = VecDestroy(&Y_inact);CHKERRQ(ierr); 11886bf464f9SBarry Smith ierr = VecScatterDestroy(&scat_act);CHKERRQ(ierr); 11896bf464f9SBarry Smith ierr = VecScatterDestroy(&scat_inact);CHKERRQ(ierr); 11906bf464f9SBarry Smith ierr = ISDestroy(&IS_act);CHKERRQ(ierr); 1191abcba341SShri Abhyankar if (!isequal) { 11926bf464f9SBarry Smith ierr = ISDestroy(&vi->IS_inact_prev);CHKERRQ(ierr); 1193abcba341SShri Abhyankar ierr = ISDuplicate(IS_inact,&vi->IS_inact_prev);CHKERRQ(ierr); 1194abcba341SShri Abhyankar } 11956bf464f9SBarry Smith ierr = ISDestroy(&IS_inact);CHKERRQ(ierr); 11966bf464f9SBarry Smith ierr = MatDestroy(&jac_inact_inact);CHKERRQ(ierr); 1197d950fb63SShri Abhyankar if (snes->jacobian != snes->jacobian_pre) { 11986bf464f9SBarry Smith ierr = MatDestroy(&prejac_inact_inact);CHKERRQ(ierr); 1199d950fb63SShri Abhyankar } 1200d950fb63SShri Abhyankar ierr = KSPGetIterationNumber(snes->ksp,&lits);CHKERRQ(ierr); 1201d950fb63SShri Abhyankar snes->linear_its += lits; 1202d950fb63SShri Abhyankar ierr = PetscInfo2(snes,"iter=%D, linear solve iterations=%D\n",snes->iter,lits);CHKERRQ(ierr); 1203d950fb63SShri Abhyankar /* 1204d950fb63SShri Abhyankar if (vi->precheckstep) { 1205d950fb63SShri Abhyankar PetscBool changed_y = PETSC_FALSE; 1206d950fb63SShri Abhyankar ierr = (*vi->precheckstep)(snes,X,Y,vi->precheck,&changed_y);CHKERRQ(ierr); 1207d950fb63SShri Abhyankar } 1208d950fb63SShri Abhyankar 1209d950fb63SShri Abhyankar if (PetscLogPrintInfo){ 1210d950fb63SShri Abhyankar ierr = SNESVICheckResidual_Private(snes,snes->jacobian,F,Y,G,W);CHKERRQ(ierr); 1211d950fb63SShri Abhyankar } 1212d950fb63SShri Abhyankar */ 1213d950fb63SShri Abhyankar /* Compute a (scaled) negative update in the line search routine: 1214d950fb63SShri Abhyankar Y <- X - lambda*Y 1215d950fb63SShri Abhyankar and evaluate G = function(Y) (depends on the line search). 1216d950fb63SShri Abhyankar */ 1217d950fb63SShri Abhyankar ierr = VecCopy(Y,snes->vec_sol_update);CHKERRQ(ierr); 1218fe835674SShri Abhyankar ynorm = 1; gnorm = fnorm; 1219fe835674SShri Abhyankar ierr = (*vi->LineSearch)(snes,vi->lsP,X,F,G,Y,W,fnorm,xnorm,&ynorm,&gnorm,&lssucceed);CHKERRQ(ierr); 1220fe835674SShri Abhyankar ierr = PetscInfo4(snes,"fnorm=%18.16e, gnorm=%18.16e, ynorm=%18.16e, lssucceed=%d\n",fnorm,gnorm,ynorm,(int)lssucceed);CHKERRQ(ierr); 12212b4ed282SShri Abhyankar if (snes->reason == SNES_DIVERGED_FUNCTION_COUNT) break; 12222b4ed282SShri Abhyankar if (snes->domainerror) { 12232b4ed282SShri Abhyankar snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN; 12242b4ed282SShri Abhyankar PetscFunctionReturn(0); 12252b4ed282SShri Abhyankar } 12262b4ed282SShri Abhyankar if (!lssucceed) { 12272b4ed282SShri Abhyankar if (++snes->numFailures >= snes->maxFailures) { 12282b4ed282SShri Abhyankar PetscBool ismin; 12292b4ed282SShri Abhyankar snes->reason = SNES_DIVERGED_LINE_SEARCH; 12302b4ed282SShri Abhyankar ierr = SNESVICheckLocalMin_Private(snes,snes->jacobian,G,W,gnorm,&ismin);CHKERRQ(ierr); 12312b4ed282SShri Abhyankar if (ismin) snes->reason = SNES_DIVERGED_LOCAL_MIN; 12322b4ed282SShri Abhyankar break; 12332b4ed282SShri Abhyankar } 12342b4ed282SShri Abhyankar } 12352b4ed282SShri Abhyankar /* Update function and solution vectors */ 1236fe835674SShri Abhyankar fnorm = gnorm; 1237fe835674SShri Abhyankar ierr = VecCopy(G,F);CHKERRQ(ierr); 12382b4ed282SShri Abhyankar ierr = VecCopy(W,X);CHKERRQ(ierr); 12392b4ed282SShri Abhyankar /* Monitor convergence */ 12402b4ed282SShri Abhyankar ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 12412b4ed282SShri Abhyankar snes->iter = i+1; 1242fe835674SShri Abhyankar snes->norm = fnorm; 12432b4ed282SShri Abhyankar ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 12442b4ed282SShri Abhyankar SNESLogConvHistory(snes,snes->norm,lits); 12457a03ce2fSLisandro Dalcin ierr = SNESMonitor(snes,snes->iter,snes->norm);CHKERRQ(ierr); 12462b4ed282SShri Abhyankar /* Test for convergence, xnorm = || X || */ 12472b4ed282SShri Abhyankar if (snes->ops->converged != SNESSkipConverged) { ierr = VecNorm(X,NORM_2,&xnorm);CHKERRQ(ierr); } 1248fe835674SShri Abhyankar ierr = (*snes->ops->converged)(snes,snes->iter,xnorm,ynorm,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); 12492b4ed282SShri Abhyankar if (snes->reason) break; 12502b4ed282SShri Abhyankar } 12512b4ed282SShri Abhyankar if (i == maxits) { 12522b4ed282SShri Abhyankar ierr = PetscInfo1(snes,"Maximum number of iterations has been reached: %D\n",maxits);CHKERRQ(ierr); 12532b4ed282SShri Abhyankar if(!snes->reason) snes->reason = SNES_DIVERGED_MAX_IT; 12542b4ed282SShri Abhyankar } 12552b4ed282SShri Abhyankar PetscFunctionReturn(0); 12562b4ed282SShri Abhyankar } 12572b4ed282SShri Abhyankar 12582f63a38cSShri Abhyankar #undef __FUNCT__ 1259720c9a41SShri Abhyankar #define __FUNCT__ "SNESVISetRedundancyCheck" 1260cb5fe31bSShri Abhyankar PetscErrorCode SNESVISetRedundancyCheck(SNES snes,PetscErrorCode (*func)(SNES,IS,IS*,void*),void *ctx) 12612f63a38cSShri Abhyankar { 12622f63a38cSShri Abhyankar SNES_VI *vi = (SNES_VI*)snes->data; 12632f63a38cSShri Abhyankar 12642f63a38cSShri Abhyankar PetscFunctionBegin; 12652f63a38cSShri Abhyankar PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 12662f63a38cSShri Abhyankar vi->checkredundancy = func; 1267cb5fe31bSShri Abhyankar vi->ctxP = ctx; 12682f63a38cSShri Abhyankar PetscFunctionReturn(0); 12692f63a38cSShri Abhyankar } 12702f63a38cSShri Abhyankar 1271ff596062SShri Abhyankar #if defined(PETSC_HAVE_MATLAB_ENGINE) 1272ff596062SShri Abhyankar #include <engine.h> 1273ff596062SShri Abhyankar #include <mex.h> 1274cb5fe31bSShri Abhyankar typedef struct {char *funcname; mxArray *ctx;} SNESMatlabContext; 1275ff596062SShri Abhyankar 1276ff596062SShri Abhyankar #undef __FUNCT__ 1277ff596062SShri Abhyankar #define __FUNCT__ "SNESVIRedundancyCheck_Matlab" 1278ff596062SShri Abhyankar PetscErrorCode SNESVIRedundancyCheck_Matlab(SNES snes,IS is_act,IS* is_redact,void* ctx) 1279ff596062SShri Abhyankar { 1280ff596062SShri Abhyankar PetscErrorCode ierr; 1281cb5fe31bSShri Abhyankar SNESMatlabContext *sctx = (SNESMatlabContext*)ctx; 1282cb5fe31bSShri Abhyankar int nlhs = 1, nrhs = 5; 1283cb5fe31bSShri Abhyankar mxArray *plhs[1], *prhs[5]; 1284cb5fe31bSShri Abhyankar long long int l1 = 0, l2 = 0, ls = 0; 1285fcb1c9afSShri Abhyankar PetscInt *indices=PETSC_NULL; 1286ff596062SShri Abhyankar 1287ff596062SShri Abhyankar PetscFunctionBegin; 1288ff596062SShri Abhyankar PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 1289ff596062SShri Abhyankar PetscValidHeaderSpecific(is_act,IS_CLASSID,2); 1290ff596062SShri Abhyankar PetscValidPointer(is_redact,3); 1291ff596062SShri Abhyankar PetscCheckSameComm(snes,1,is_act,2); 1292ff596062SShri Abhyankar 129309db5ad8SShri Abhyankar /* Create IS for reduced active set of size 0, its size and indices will 129409db5ad8SShri Abhyankar bet set by the Matlab function */ 1295fcb1c9afSShri Abhyankar ierr = ISCreateGeneral(((PetscObject)snes)->comm,0,indices,PETSC_OWN_POINTER,is_redact);CHKERRQ(ierr); 1296cb5fe31bSShri Abhyankar /* call Matlab function in ctx */ 1297ff596062SShri Abhyankar ierr = PetscMemcpy(&ls,&snes,sizeof(snes));CHKERRQ(ierr); 1298ff596062SShri Abhyankar ierr = PetscMemcpy(&l1,&is_act,sizeof(is_act));CHKERRQ(ierr); 1299cb5fe31bSShri Abhyankar ierr = PetscMemcpy(&l2,is_redact,sizeof(is_act));CHKERRQ(ierr); 1300ff596062SShri Abhyankar prhs[0] = mxCreateDoubleScalar((double)ls); 1301ff596062SShri Abhyankar prhs[1] = mxCreateDoubleScalar((double)l1); 1302cb5fe31bSShri Abhyankar prhs[2] = mxCreateDoubleScalar((double)l2); 1303cb5fe31bSShri Abhyankar prhs[3] = mxCreateString(sctx->funcname); 1304cb5fe31bSShri Abhyankar prhs[4] = sctx->ctx; 1305ff596062SShri Abhyankar ierr = mexCallMATLAB(nlhs,plhs,nrhs,prhs,"PetscSNESVIRedundancyCheckInternal");CHKERRQ(ierr); 1306ff596062SShri Abhyankar ierr = mxGetScalar(plhs[0]);CHKERRQ(ierr); 1307ff596062SShri Abhyankar mxDestroyArray(prhs[0]); 1308ff596062SShri Abhyankar mxDestroyArray(prhs[1]); 1309ff596062SShri Abhyankar mxDestroyArray(prhs[2]); 1310ff596062SShri Abhyankar mxDestroyArray(prhs[3]); 1311ff596062SShri Abhyankar mxDestroyArray(plhs[0]); 1312ff596062SShri Abhyankar PetscFunctionReturn(0); 1313ff596062SShri Abhyankar } 1314ff596062SShri Abhyankar 1315ff596062SShri Abhyankar #undef __FUNCT__ 1316ff596062SShri Abhyankar #define __FUNCT__ "SNESVISetRedundancyCheckMatlab" 1317ff596062SShri Abhyankar PetscErrorCode SNESVISetRedundancyCheckMatlab(SNES snes,const char* func,mxArray* ctx) 1318ff596062SShri Abhyankar { 1319ff596062SShri Abhyankar PetscErrorCode ierr; 1320cb5fe31bSShri Abhyankar SNESMatlabContext *sctx; 1321ff596062SShri Abhyankar 1322ff596062SShri Abhyankar PetscFunctionBegin; 1323ff596062SShri Abhyankar /* currently sctx is memory bleed */ 1324cb5fe31bSShri Abhyankar ierr = PetscMalloc(sizeof(SNESMatlabContext),&sctx);CHKERRQ(ierr); 1325ff596062SShri Abhyankar ierr = PetscStrallocpy(func,&sctx->funcname);CHKERRQ(ierr); 1326ff596062SShri Abhyankar sctx->ctx = mxDuplicateArray(ctx); 1327cb5fe31bSShri Abhyankar ierr = SNESVISetRedundancyCheck(snes,SNESVIRedundancyCheck_Matlab,sctx);CHKERRQ(ierr); 1328ff596062SShri Abhyankar PetscFunctionReturn(0); 1329ff596062SShri Abhyankar } 1330ff596062SShri Abhyankar 1331ff596062SShri Abhyankar #endif 1332ff596062SShri Abhyankar 1333ff596062SShri Abhyankar 13342f63a38cSShri Abhyankar /* Variational Inequality solver using augmented space method. It does the opposite of the 13352f63a38cSShri Abhyankar reduced space method i.e. it identifies the active set variables and instead of discarding 1336720c9a41SShri Abhyankar them it augments the original system by introducing additional equality 133756a221efSShri Abhyankar constraint equations for active set variables. The user can optionally provide an IS for 133856a221efSShri Abhyankar a subset of 'redundant' active set variables which will treated as free variables. 13392f63a38cSShri Abhyankar Specific implementation for Allen-Cahn problem 13402f63a38cSShri Abhyankar */ 13412f63a38cSShri Abhyankar #undef __FUNCT__ 1342b350b9c9SBarry Smith #define __FUNCT__ "SNESSolveVI_RSAUG" 1343b350b9c9SBarry Smith PetscErrorCode SNESSolveVI_RSAUG(SNES snes) 13442f63a38cSShri Abhyankar { 13452f63a38cSShri Abhyankar SNES_VI *vi = (SNES_VI*)snes->data; 13462f63a38cSShri Abhyankar PetscErrorCode ierr; 13472f63a38cSShri Abhyankar PetscInt maxits,i,lits; 13482f63a38cSShri Abhyankar PetscBool lssucceed; 13492f63a38cSShri Abhyankar MatStructure flg = DIFFERENT_NONZERO_PATTERN; 13502f63a38cSShri Abhyankar PetscReal fnorm,gnorm,xnorm=0,ynorm; 13512f63a38cSShri Abhyankar Vec Y,X,F,G,W; 13522f63a38cSShri Abhyankar KSPConvergedReason kspreason; 13532f63a38cSShri Abhyankar 13542f63a38cSShri Abhyankar PetscFunctionBegin; 13552f63a38cSShri Abhyankar snes->numFailures = 0; 13562f63a38cSShri Abhyankar snes->numLinearSolveFailures = 0; 13572f63a38cSShri Abhyankar snes->reason = SNES_CONVERGED_ITERATING; 13582f63a38cSShri Abhyankar 13592f63a38cSShri Abhyankar maxits = snes->max_its; /* maximum number of iterations */ 13602f63a38cSShri Abhyankar X = snes->vec_sol; /* solution vector */ 13612f63a38cSShri Abhyankar F = snes->vec_func; /* residual vector */ 13622f63a38cSShri Abhyankar Y = snes->work[0]; /* work vectors */ 13632f63a38cSShri Abhyankar G = snes->work[1]; 13642f63a38cSShri Abhyankar W = snes->work[2]; 13652f63a38cSShri Abhyankar 13662f63a38cSShri Abhyankar ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 13672f63a38cSShri Abhyankar snes->iter = 0; 13682f63a38cSShri Abhyankar snes->norm = 0.0; 13692f63a38cSShri Abhyankar ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 13702f63a38cSShri Abhyankar 13712f63a38cSShri Abhyankar ierr = SNESVIProjectOntoBounds(snes,X);CHKERRQ(ierr); 13722f63a38cSShri Abhyankar ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr); 13732f63a38cSShri Abhyankar if (snes->domainerror) { 13742f63a38cSShri Abhyankar snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN; 13752f63a38cSShri Abhyankar PetscFunctionReturn(0); 13762f63a38cSShri Abhyankar } 13772f63a38cSShri Abhyankar ierr = SNESVIComputeInactiveSetFnorm(snes,F,X,&fnorm);CHKERRQ(ierr); 13782f63a38cSShri Abhyankar ierr = VecNormBegin(X,NORM_2,&xnorm);CHKERRQ(ierr); /* xnorm <- ||x|| */ 13792f63a38cSShri Abhyankar ierr = VecNormEnd(X,NORM_2,&xnorm);CHKERRQ(ierr); 138062cbcd01SMatthew G Knepley if (PetscIsInfOrNanReal(fnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number"); 13812f63a38cSShri Abhyankar 13822f63a38cSShri Abhyankar ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 13832f63a38cSShri Abhyankar snes->norm = fnorm; 13842f63a38cSShri Abhyankar ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 13852f63a38cSShri Abhyankar SNESLogConvHistory(snes,fnorm,0); 13867a03ce2fSLisandro Dalcin ierr = SNESMonitor(snes,0,fnorm);CHKERRQ(ierr); 13872f63a38cSShri Abhyankar 13882f63a38cSShri Abhyankar /* set parameter for default relative tolerance convergence test */ 13892f63a38cSShri Abhyankar snes->ttol = fnorm*snes->rtol; 13902f63a38cSShri Abhyankar /* test convergence */ 13912f63a38cSShri Abhyankar ierr = (*snes->ops->converged)(snes,0,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); 13922f63a38cSShri Abhyankar if (snes->reason) PetscFunctionReturn(0); 13932f63a38cSShri Abhyankar 13942f63a38cSShri Abhyankar for (i=0; i<maxits; i++) { 13952f63a38cSShri Abhyankar IS IS_act,IS_inact; /* _act -> active set _inact -> inactive set */ 1396cb5fe31bSShri Abhyankar IS IS_redact; /* redundant active set */ 139756a221efSShri Abhyankar Mat J_aug,Jpre_aug; 139856a221efSShri Abhyankar Vec F_aug,Y_aug; 139956a221efSShri Abhyankar PetscInt nis_redact,nis_act; 140056a221efSShri Abhyankar const PetscInt *idx_redact,*idx_act; 140156a221efSShri Abhyankar PetscInt k; 140263ee972cSSatish Balay PetscInt *idx_actkept=PETSC_NULL,nkept=0; /* list of kept active set */ 140356a221efSShri Abhyankar PetscScalar *f,*f2; 14042f63a38cSShri Abhyankar PetscBool isequal; 140556a221efSShri Abhyankar PetscInt i1=0,j1=0; 14062f63a38cSShri Abhyankar 14072f63a38cSShri Abhyankar /* Call general purpose update function */ 14082f63a38cSShri Abhyankar if (snes->ops->update) { 14092f63a38cSShri Abhyankar ierr = (*snes->ops->update)(snes, snes->iter);CHKERRQ(ierr); 14102f63a38cSShri Abhyankar } 14112f63a38cSShri Abhyankar ierr = SNESComputeJacobian(snes,X,&snes->jacobian,&snes->jacobian_pre,&flg);CHKERRQ(ierr); 14122f63a38cSShri Abhyankar 14132f63a38cSShri Abhyankar /* Create active and inactive index sets */ 14142f63a38cSShri Abhyankar ierr = SNESVICreateIndexSets_RS(snes,X,F,&IS_act,&IS_inact);CHKERRQ(ierr); 14152f63a38cSShri Abhyankar 141656a221efSShri Abhyankar /* Get local active set size */ 14172f63a38cSShri Abhyankar ierr = ISGetLocalSize(IS_act,&nis_act);CHKERRQ(ierr); 141856a221efSShri Abhyankar if (nis_act) { 1419e63076c7SBarry Smith ierr = ISGetIndices(IS_act,&idx_act);CHKERRQ(ierr); 1420e63076c7SBarry Smith IS_redact = PETSC_NULL; 142156a221efSShri Abhyankar if(vi->checkredundancy) { 1422cb5fe31bSShri Abhyankar (*vi->checkredundancy)(snes,IS_act,&IS_redact,vi->ctxP); 142356a221efSShri Abhyankar } 14242f63a38cSShri Abhyankar 142556a221efSShri Abhyankar if(!IS_redact) { 142656a221efSShri Abhyankar /* User called checkredundancy function but didn't create IS_redact because 142756a221efSShri Abhyankar there were no redundant active set variables */ 142856a221efSShri Abhyankar /* Copy over all active set indices to the list */ 142956a221efSShri Abhyankar ierr = PetscMalloc(nis_act*sizeof(PetscInt),&idx_actkept);CHKERRQ(ierr); 143056a221efSShri Abhyankar for(k=0;k < nis_act;k++) idx_actkept[k] = idx_act[k]; 143156a221efSShri Abhyankar nkept = nis_act; 143256a221efSShri Abhyankar } else { 143356a221efSShri Abhyankar ierr = ISGetLocalSize(IS_redact,&nis_redact);CHKERRQ(ierr); 143456a221efSShri Abhyankar ierr = PetscMalloc((nis_act-nis_redact)*sizeof(PetscInt),&idx_actkept);CHKERRQ(ierr); 14352f63a38cSShri Abhyankar 143656a221efSShri Abhyankar /* Create reduced active set list */ 143756a221efSShri Abhyankar ierr = ISGetIndices(IS_act,&idx_act);CHKERRQ(ierr); 143856a221efSShri Abhyankar ierr = ISGetIndices(IS_redact,&idx_redact);CHKERRQ(ierr); 1439cb5fe31bSShri Abhyankar j1 = 0;nkept = 0; 144056a221efSShri Abhyankar for(k=0;k<nis_act;k++) { 144156a221efSShri Abhyankar if(j1 < nis_redact && idx_act[k] == idx_redact[j1]) j1++; 144256a221efSShri Abhyankar else idx_actkept[nkept++] = idx_act[k]; 144356a221efSShri Abhyankar } 144456a221efSShri Abhyankar ierr = ISRestoreIndices(IS_act,&idx_act);CHKERRQ(ierr); 144556a221efSShri Abhyankar ierr = ISRestoreIndices(IS_redact,&idx_redact);CHKERRQ(ierr); 1446cb5fe31bSShri Abhyankar 1447cb5fe31bSShri Abhyankar ierr = ISDestroy(&IS_redact);CHKERRQ(ierr); 144856a221efSShri Abhyankar } 14492f63a38cSShri Abhyankar 145056a221efSShri Abhyankar /* Create augmented F and Y */ 145156a221efSShri Abhyankar ierr = VecCreate(((PetscObject)snes)->comm,&F_aug);CHKERRQ(ierr); 145256a221efSShri Abhyankar ierr = VecSetSizes(F_aug,F->map->n+nkept,PETSC_DECIDE);CHKERRQ(ierr); 145356a221efSShri Abhyankar ierr = VecSetFromOptions(F_aug);CHKERRQ(ierr); 145456a221efSShri Abhyankar ierr = VecDuplicate(F_aug,&Y_aug);CHKERRQ(ierr); 14552f63a38cSShri Abhyankar 145656a221efSShri Abhyankar /* Copy over F to F_aug in the first n locations */ 145756a221efSShri Abhyankar ierr = VecGetArray(F,&f);CHKERRQ(ierr); 145856a221efSShri Abhyankar ierr = VecGetArray(F_aug,&f2);CHKERRQ(ierr); 145956a221efSShri Abhyankar ierr = PetscMemcpy(f2,f,F->map->n*sizeof(PetscScalar));CHKERRQ(ierr); 146056a221efSShri Abhyankar ierr = VecRestoreArray(F,&f);CHKERRQ(ierr); 146156a221efSShri Abhyankar ierr = VecRestoreArray(F_aug,&f2);CHKERRQ(ierr); 14622f63a38cSShri Abhyankar 146356a221efSShri Abhyankar /* Create the augmented jacobian matrix */ 146456a221efSShri Abhyankar ierr = MatCreate(((PetscObject)snes)->comm,&J_aug);CHKERRQ(ierr); 146556a221efSShri Abhyankar ierr = MatSetSizes(J_aug,X->map->n+nkept,X->map->n+nkept,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr); 146656a221efSShri Abhyankar ierr = MatSetFromOptions(J_aug);CHKERRQ(ierr); 14672f63a38cSShri Abhyankar 146856a221efSShri Abhyankar 14699521db3cSSatish Balay { /* local vars */ 1470493a4f3dSShri Abhyankar /* Preallocate augmented matrix and set values in it...Doing only sequential case first*/ 147156a221efSShri Abhyankar PetscInt ncols; 147256a221efSShri Abhyankar const PetscInt *cols; 147356a221efSShri Abhyankar const PetscScalar *vals; 14742969f145SShri Abhyankar PetscScalar value[2]; 14752969f145SShri Abhyankar PetscInt row,col[2]; 1476493a4f3dSShri Abhyankar PetscInt *d_nnz; 14772969f145SShri Abhyankar value[0] = 1.0; value[1] = 0.0; 1478493a4f3dSShri Abhyankar ierr = PetscMalloc((X->map->n+nkept)*sizeof(PetscInt),&d_nnz);CHKERRQ(ierr); 1479493a4f3dSShri Abhyankar ierr = PetscMemzero(d_nnz,(X->map->n+nkept)*sizeof(PetscInt));CHKERRQ(ierr); 1480493a4f3dSShri Abhyankar for(row=0;row<snes->jacobian->rmap->n;row++) { 1481493a4f3dSShri Abhyankar ierr = MatGetRow(snes->jacobian,row,&ncols,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr); 1482493a4f3dSShri Abhyankar d_nnz[row] += ncols; 1483493a4f3dSShri Abhyankar ierr = MatRestoreRow(snes->jacobian,row,&ncols,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr); 1484493a4f3dSShri Abhyankar } 1485493a4f3dSShri Abhyankar 1486493a4f3dSShri Abhyankar for(k=0;k<nkept;k++) { 1487493a4f3dSShri Abhyankar d_nnz[idx_actkept[k]] += 1; 14882969f145SShri Abhyankar d_nnz[snes->jacobian->rmap->n+k] += 2; 1489493a4f3dSShri Abhyankar } 1490493a4f3dSShri Abhyankar ierr = MatSeqAIJSetPreallocation(J_aug,PETSC_NULL,d_nnz);CHKERRQ(ierr); 1491493a4f3dSShri Abhyankar 1492493a4f3dSShri Abhyankar ierr = PetscFree(d_nnz);CHKERRQ(ierr); 149356a221efSShri Abhyankar 149456a221efSShri Abhyankar /* Set the original jacobian matrix in J_aug */ 149556a221efSShri Abhyankar for(row=0;row<snes->jacobian->rmap->n;row++) { 149656a221efSShri Abhyankar ierr = MatGetRow(snes->jacobian,row,&ncols,&cols,&vals);CHKERRQ(ierr); 149756a221efSShri Abhyankar ierr = MatSetValues(J_aug,1,&row,ncols,cols,vals,INSERT_VALUES);CHKERRQ(ierr); 149856a221efSShri Abhyankar ierr = MatRestoreRow(snes->jacobian,row,&ncols,&cols,&vals);CHKERRQ(ierr); 149956a221efSShri Abhyankar } 150056a221efSShri Abhyankar /* Add the augmented part */ 150156a221efSShri Abhyankar for(k=0;k<nkept;k++) { 15022969f145SShri Abhyankar row = snes->jacobian->rmap->n+k; 15032969f145SShri Abhyankar col[0] = idx_actkept[k]; col[1] = snes->jacobian->rmap->n+k; 15042969f145SShri Abhyankar ierr = MatSetValues(J_aug,1,&row,1,col,value,INSERT_VALUES);CHKERRQ(ierr); 15052969f145SShri Abhyankar ierr = MatSetValues(J_aug,1,&col[0],1,&row,&value[0],INSERT_VALUES);CHKERRQ(ierr); 150656a221efSShri Abhyankar } 150756a221efSShri Abhyankar ierr = MatAssemblyBegin(J_aug,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 150856a221efSShri Abhyankar ierr = MatAssemblyEnd(J_aug,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 150956a221efSShri Abhyankar /* Only considering prejac = jac for now */ 151056a221efSShri Abhyankar Jpre_aug = J_aug; 15119521db3cSSatish Balay } /* local vars*/ 1512e63076c7SBarry Smith ierr = ISRestoreIndices(IS_act,&idx_act);CHKERRQ(ierr); 1513e63076c7SBarry Smith ierr = ISDestroy(&IS_act);CHKERRQ(ierr); 151456a221efSShri Abhyankar } else { 151556a221efSShri Abhyankar F_aug = F; J_aug = snes->jacobian; Y_aug = Y; Jpre_aug = snes->jacobian_pre; 151656a221efSShri Abhyankar } 15172f63a38cSShri Abhyankar 15182f63a38cSShri Abhyankar ierr = ISEqual(vi->IS_inact_prev,IS_inact,&isequal);CHKERRQ(ierr); 15192f63a38cSShri Abhyankar if (!isequal) { 152056a221efSShri Abhyankar ierr = SNESVIResetPCandKSP(snes,J_aug,Jpre_aug);CHKERRQ(ierr); 15212f63a38cSShri Abhyankar } 152256a221efSShri Abhyankar ierr = KSPSetOperators(snes->ksp,J_aug,Jpre_aug,flg);CHKERRQ(ierr); 15232f63a38cSShri Abhyankar ierr = KSPSetUp(snes->ksp);CHKERRQ(ierr); 152456a221efSShri Abhyankar /* { 15252f63a38cSShri Abhyankar PC pc; 15262f63a38cSShri Abhyankar PetscBool flg; 15272f63a38cSShri Abhyankar ierr = KSPGetPC(snes->ksp,&pc);CHKERRQ(ierr); 15282f63a38cSShri Abhyankar ierr = PetscTypeCompare((PetscObject)pc,PCFIELDSPLIT,&flg);CHKERRQ(ierr); 15292f63a38cSShri Abhyankar if (flg) { 15302f63a38cSShri Abhyankar KSP *subksps; 15312f63a38cSShri Abhyankar ierr = PCFieldSplitGetSubKSP(pc,PETSC_NULL,&subksps);CHKERRQ(ierr); 15322f63a38cSShri Abhyankar ierr = KSPGetPC(subksps[0],&pc);CHKERRQ(ierr); 15332f63a38cSShri Abhyankar ierr = PetscFree(subksps);CHKERRQ(ierr); 15342f63a38cSShri Abhyankar ierr = PetscTypeCompare((PetscObject)pc,PCBJACOBI,&flg);CHKERRQ(ierr); 15352f63a38cSShri Abhyankar if (flg) { 15362f63a38cSShri Abhyankar PetscInt n,N = 101*101,j,cnts[3] = {0,0,0}; 15372f63a38cSShri Abhyankar const PetscInt *ii; 15382f63a38cSShri Abhyankar 15392f63a38cSShri Abhyankar ierr = ISGetSize(IS_inact,&n);CHKERRQ(ierr); 15402f63a38cSShri Abhyankar ierr = ISGetIndices(IS_inact,&ii);CHKERRQ(ierr); 15412f63a38cSShri Abhyankar for (j=0; j<n; j++) { 15422f63a38cSShri Abhyankar if (ii[j] < N) cnts[0]++; 15432f63a38cSShri Abhyankar else if (ii[j] < 2*N) cnts[1]++; 15442f63a38cSShri Abhyankar else if (ii[j] < 3*N) cnts[2]++; 15452f63a38cSShri Abhyankar } 15462f63a38cSShri Abhyankar ierr = ISRestoreIndices(IS_inact,&ii);CHKERRQ(ierr); 15472f63a38cSShri Abhyankar 15482f63a38cSShri Abhyankar ierr = PCBJacobiSetTotalBlocks(pc,3,cnts);CHKERRQ(ierr); 15492f63a38cSShri Abhyankar } 15502f63a38cSShri Abhyankar } 15512f63a38cSShri Abhyankar } 155256a221efSShri Abhyankar */ 155356a221efSShri Abhyankar ierr = SNES_KSPSolve(snes,snes->ksp,F_aug,Y_aug);CHKERRQ(ierr); 15542f63a38cSShri Abhyankar ierr = KSPGetConvergedReason(snes->ksp,&kspreason);CHKERRQ(ierr); 15552f63a38cSShri Abhyankar if (kspreason < 0) { 15562f63a38cSShri Abhyankar if (++snes->numLinearSolveFailures >= snes->maxLinearSolveFailures) { 15572f63a38cSShri 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); 15582f63a38cSShri Abhyankar snes->reason = SNES_DIVERGED_LINEAR_SOLVE; 15592f63a38cSShri Abhyankar break; 15602f63a38cSShri Abhyankar } 15612f63a38cSShri Abhyankar } 15622f63a38cSShri Abhyankar 156356a221efSShri Abhyankar if(nis_act) { 156456a221efSShri Abhyankar PetscScalar *y1,*y2; 156556a221efSShri Abhyankar ierr = VecGetArray(Y,&y1);CHKERRQ(ierr); 156656a221efSShri Abhyankar ierr = VecGetArray(Y_aug,&y2);CHKERRQ(ierr); 156756a221efSShri Abhyankar /* Copy over inactive Y_aug to Y */ 156856a221efSShri Abhyankar j1 = 0; 156956a221efSShri Abhyankar for(i1=Y->map->rstart;i1 < Y->map->rend;i1++) { 157056a221efSShri Abhyankar if(j1 < nkept && idx_actkept[j1] == i1) j1++; 157156a221efSShri Abhyankar else y1[i1-Y->map->rstart] = y2[i1-Y->map->rstart]; 157256a221efSShri Abhyankar } 157356a221efSShri Abhyankar ierr = VecRestoreArray(Y,&y1);CHKERRQ(ierr); 157456a221efSShri Abhyankar ierr = VecRestoreArray(Y_aug,&y2);CHKERRQ(ierr); 15752f63a38cSShri Abhyankar 15766bf464f9SBarry Smith ierr = VecDestroy(&F_aug);CHKERRQ(ierr); 15776bf464f9SBarry Smith ierr = VecDestroy(&Y_aug);CHKERRQ(ierr); 15786bf464f9SBarry Smith ierr = MatDestroy(&J_aug);CHKERRQ(ierr); 157956a221efSShri Abhyankar ierr = PetscFree(idx_actkept);CHKERRQ(ierr); 158056a221efSShri Abhyankar } 158156a221efSShri Abhyankar 15822f63a38cSShri Abhyankar if (!isequal) { 15836bf464f9SBarry Smith ierr = ISDestroy(&vi->IS_inact_prev);CHKERRQ(ierr); 15842f63a38cSShri Abhyankar ierr = ISDuplicate(IS_inact,&vi->IS_inact_prev);CHKERRQ(ierr); 15852f63a38cSShri Abhyankar } 15866bf464f9SBarry Smith ierr = ISDestroy(&IS_inact);CHKERRQ(ierr); 158756a221efSShri Abhyankar 15882f63a38cSShri Abhyankar ierr = KSPGetIterationNumber(snes->ksp,&lits);CHKERRQ(ierr); 15892f63a38cSShri Abhyankar snes->linear_its += lits; 15902f63a38cSShri Abhyankar ierr = PetscInfo2(snes,"iter=%D, linear solve iterations=%D\n",snes->iter,lits);CHKERRQ(ierr); 15912f63a38cSShri Abhyankar /* 15922f63a38cSShri Abhyankar if (vi->precheckstep) { 15932f63a38cSShri Abhyankar PetscBool changed_y = PETSC_FALSE; 15942f63a38cSShri Abhyankar ierr = (*vi->precheckstep)(snes,X,Y,vi->precheck,&changed_y);CHKERRQ(ierr); 15952f63a38cSShri Abhyankar } 15962f63a38cSShri Abhyankar 15972f63a38cSShri Abhyankar if (PetscLogPrintInfo){ 15982f63a38cSShri Abhyankar ierr = SNESVICheckResidual_Private(snes,snes->jacobian,F,Y,G,W);CHKERRQ(ierr); 15992f63a38cSShri Abhyankar } 16002f63a38cSShri Abhyankar */ 16012f63a38cSShri Abhyankar /* Compute a (scaled) negative update in the line search routine: 16022f63a38cSShri Abhyankar Y <- X - lambda*Y 16032f63a38cSShri Abhyankar and evaluate G = function(Y) (depends on the line search). 16042f63a38cSShri Abhyankar */ 16052f63a38cSShri Abhyankar ierr = VecCopy(Y,snes->vec_sol_update);CHKERRQ(ierr); 16062f63a38cSShri Abhyankar ynorm = 1; gnorm = fnorm; 16072f63a38cSShri Abhyankar ierr = (*vi->LineSearch)(snes,vi->lsP,X,F,G,Y,W,fnorm,xnorm,&ynorm,&gnorm,&lssucceed);CHKERRQ(ierr); 16082f63a38cSShri Abhyankar ierr = PetscInfo4(snes,"fnorm=%18.16e, gnorm=%18.16e, ynorm=%18.16e, lssucceed=%d\n",fnorm,gnorm,ynorm,(int)lssucceed);CHKERRQ(ierr); 16092f63a38cSShri Abhyankar if (snes->reason == SNES_DIVERGED_FUNCTION_COUNT) break; 16102f63a38cSShri Abhyankar if (snes->domainerror) { 16112f63a38cSShri Abhyankar snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN; 16122f63a38cSShri Abhyankar PetscFunctionReturn(0); 16132f63a38cSShri Abhyankar } 16142f63a38cSShri Abhyankar if (!lssucceed) { 16152f63a38cSShri Abhyankar if (++snes->numFailures >= snes->maxFailures) { 16162f63a38cSShri Abhyankar PetscBool ismin; 16172f63a38cSShri Abhyankar snes->reason = SNES_DIVERGED_LINE_SEARCH; 16182f63a38cSShri Abhyankar ierr = SNESVICheckLocalMin_Private(snes,snes->jacobian,G,W,gnorm,&ismin);CHKERRQ(ierr); 16192f63a38cSShri Abhyankar if (ismin) snes->reason = SNES_DIVERGED_LOCAL_MIN; 16202f63a38cSShri Abhyankar break; 16212f63a38cSShri Abhyankar } 16222f63a38cSShri Abhyankar } 16232f63a38cSShri Abhyankar /* Update function and solution vectors */ 16242f63a38cSShri Abhyankar fnorm = gnorm; 16252f63a38cSShri Abhyankar ierr = VecCopy(G,F);CHKERRQ(ierr); 16262f63a38cSShri Abhyankar ierr = VecCopy(W,X);CHKERRQ(ierr); 16272f63a38cSShri Abhyankar /* Monitor convergence */ 16282f63a38cSShri Abhyankar ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 16292f63a38cSShri Abhyankar snes->iter = i+1; 16302f63a38cSShri Abhyankar snes->norm = fnorm; 16312f63a38cSShri Abhyankar ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 16322f63a38cSShri Abhyankar SNESLogConvHistory(snes,snes->norm,lits); 16337a03ce2fSLisandro Dalcin ierr = SNESMonitor(snes,snes->iter,snes->norm);CHKERRQ(ierr); 16342f63a38cSShri Abhyankar /* Test for convergence, xnorm = || X || */ 16352f63a38cSShri Abhyankar if (snes->ops->converged != SNESSkipConverged) { ierr = VecNorm(X,NORM_2,&xnorm);CHKERRQ(ierr); } 16362f63a38cSShri Abhyankar ierr = (*snes->ops->converged)(snes,snes->iter,xnorm,ynorm,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); 16372f63a38cSShri Abhyankar if (snes->reason) break; 16382f63a38cSShri Abhyankar } 16392f63a38cSShri Abhyankar if (i == maxits) { 16402f63a38cSShri Abhyankar ierr = PetscInfo1(snes,"Maximum number of iterations has been reached: %D\n",maxits);CHKERRQ(ierr); 16412f63a38cSShri Abhyankar if(!snes->reason) snes->reason = SNES_DIVERGED_MAX_IT; 16422f63a38cSShri Abhyankar } 16432f63a38cSShri Abhyankar PetscFunctionReturn(0); 16442f63a38cSShri Abhyankar } 16452f63a38cSShri Abhyankar 16462b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */ 16472b4ed282SShri Abhyankar /* 16482b4ed282SShri Abhyankar SNESSetUp_VI - Sets up the internal data structures for the later use 16492b4ed282SShri Abhyankar of the SNESVI nonlinear solver. 16502b4ed282SShri Abhyankar 16512b4ed282SShri Abhyankar Input Parameter: 16522b4ed282SShri Abhyankar . snes - the SNES context 16532b4ed282SShri Abhyankar . x - the solution vector 16542b4ed282SShri Abhyankar 16552b4ed282SShri Abhyankar Application Interface Routine: SNESSetUp() 16562b4ed282SShri Abhyankar 16572b4ed282SShri Abhyankar Notes: 16582b4ed282SShri Abhyankar For basic use of the SNES solvers, the user need not explicitly call 16592b4ed282SShri Abhyankar SNESSetUp(), since these actions will automatically occur during 16602b4ed282SShri Abhyankar the call to SNESSolve(). 16612b4ed282SShri Abhyankar */ 16622b4ed282SShri Abhyankar #undef __FUNCT__ 16632b4ed282SShri Abhyankar #define __FUNCT__ "SNESSetUp_VI" 16642b4ed282SShri Abhyankar PetscErrorCode SNESSetUp_VI(SNES snes) 16652b4ed282SShri Abhyankar { 16662b4ed282SShri Abhyankar PetscErrorCode ierr; 16672b4ed282SShri Abhyankar SNES_VI *vi = (SNES_VI*) snes->data; 16682b4ed282SShri Abhyankar PetscInt i_start[3],i_end[3]; 16692b4ed282SShri Abhyankar 16702b4ed282SShri Abhyankar PetscFunctionBegin; 167158c9b817SLisandro Dalcin 167258c9b817SLisandro Dalcin ierr = SNESDefaultGetWork(snes,3);CHKERRQ(ierr); 16732b4ed282SShri Abhyankar 16742b4ed282SShri Abhyankar /* If the lower and upper bound on variables are not set, set it to 16752b4ed282SShri Abhyankar -Inf and Inf */ 16762b4ed282SShri Abhyankar if (!vi->xl && !vi->xu) { 16772b4ed282SShri Abhyankar vi->usersetxbounds = PETSC_FALSE; 16782b4ed282SShri Abhyankar ierr = VecDuplicate(snes->vec_sol, &vi->xl); CHKERRQ(ierr); 167901f0b76bSBarry Smith ierr = VecSet(vi->xl,SNES_VI_NINF);CHKERRQ(ierr); 16802b4ed282SShri Abhyankar ierr = VecDuplicate(snes->vec_sol, &vi->xu); CHKERRQ(ierr); 168101f0b76bSBarry Smith ierr = VecSet(vi->xu,SNES_VI_INF);CHKERRQ(ierr); 16822b4ed282SShri Abhyankar } else { 16832b4ed282SShri Abhyankar /* Check if lower bound, upper bound and solution vector distribution across the processors is identical */ 16842b4ed282SShri Abhyankar ierr = VecGetOwnershipRange(snes->vec_sol,i_start,i_end);CHKERRQ(ierr); 16852b4ed282SShri Abhyankar ierr = VecGetOwnershipRange(vi->xl,i_start+1,i_end+1);CHKERRQ(ierr); 16862b4ed282SShri Abhyankar ierr = VecGetOwnershipRange(vi->xu,i_start+2,i_end+2);CHKERRQ(ierr); 16872b4ed282SShri 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])) 16882b4ed282SShri 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."); 16892b4ed282SShri Abhyankar } 16902f63a38cSShri Abhyankar if (snes->ops->solve != SNESSolveVI_SS) { 1691abcba341SShri Abhyankar /* Set up previous active index set for the first snes solve 1692abcba341SShri Abhyankar vi->IS_inact_prev = 0,1,2,....N */ 1693abcba341SShri Abhyankar PetscInt *indices; 1694abcba341SShri Abhyankar PetscInt i,n,rstart,rend; 1695abcba341SShri Abhyankar 1696abcba341SShri Abhyankar ierr = VecGetOwnershipRange(snes->vec_sol,&rstart,&rend);CHKERRQ(ierr); 1697abcba341SShri Abhyankar ierr = VecGetLocalSize(snes->vec_sol,&n);CHKERRQ(ierr); 1698abcba341SShri Abhyankar ierr = PetscMalloc(n*sizeof(PetscInt),&indices);CHKERRQ(ierr); 1699abcba341SShri Abhyankar for(i=0;i < n; i++) indices[i] = rstart + i; 1700abcba341SShri Abhyankar ierr = ISCreateGeneral(((PetscObject)snes)->comm,n,indices,PETSC_OWN_POINTER,&vi->IS_inact_prev); 1701abcba341SShri Abhyankar } 17022b4ed282SShri Abhyankar 17032f63a38cSShri Abhyankar if (snes->ops->solve == SNESSolveVI_SS) { 1704fe835674SShri Abhyankar ierr = VecDuplicate(snes->vec_sol, &vi->dpsi);CHKERRQ(ierr); 1705fe835674SShri Abhyankar ierr = VecDuplicate(snes->vec_sol, &vi->phi); CHKERRQ(ierr); 1706fe835674SShri Abhyankar ierr = VecDuplicate(snes->vec_sol, &vi->Da); CHKERRQ(ierr); 1707fe835674SShri Abhyankar ierr = VecDuplicate(snes->vec_sol, &vi->Db); CHKERRQ(ierr); 1708fe835674SShri Abhyankar ierr = VecDuplicate(snes->vec_sol, &vi->z);CHKERRQ(ierr); 1709fe835674SShri Abhyankar ierr = VecDuplicate(snes->vec_sol, &vi->t); CHKERRQ(ierr); 1710fe835674SShri Abhyankar } 17112b4ed282SShri Abhyankar PetscFunctionReturn(0); 17122b4ed282SShri Abhyankar } 17132b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */ 17142b4ed282SShri Abhyankar /* 17152b4ed282SShri Abhyankar SNESDestroy_VI - Destroys the private SNES_VI context that was created 17162b4ed282SShri Abhyankar with SNESCreate_VI(). 17172b4ed282SShri Abhyankar 17182b4ed282SShri Abhyankar Input Parameter: 17192b4ed282SShri Abhyankar . snes - the SNES context 17202b4ed282SShri Abhyankar 17212b4ed282SShri Abhyankar Application Interface Routine: SNESDestroy() 17222b4ed282SShri Abhyankar */ 17232b4ed282SShri Abhyankar #undef __FUNCT__ 17242b4ed282SShri Abhyankar #define __FUNCT__ "SNESDestroy_VI" 17252b4ed282SShri Abhyankar PetscErrorCode SNESDestroy_VI(SNES snes) 17262b4ed282SShri Abhyankar { 17272b4ed282SShri Abhyankar SNES_VI *vi = (SNES_VI*) snes->data; 17282b4ed282SShri Abhyankar PetscErrorCode ierr; 17292b4ed282SShri Abhyankar 17302b4ed282SShri Abhyankar PetscFunctionBegin; 17312f63a38cSShri Abhyankar if (snes->ops->solve != SNESSolveVI_SS) { 17326bf464f9SBarry Smith ierr = ISDestroy(&vi->IS_inact_prev); 1733abcba341SShri Abhyankar } 17342b4ed282SShri Abhyankar 17352f63a38cSShri Abhyankar if (snes->ops->solve == SNESSolveVI_SS) { 17362b4ed282SShri Abhyankar /* clear vectors */ 17376bf464f9SBarry Smith ierr = VecDestroy(&vi->dpsi);CHKERRQ(ierr); 17386bf464f9SBarry Smith ierr = VecDestroy(&vi->phi); CHKERRQ(ierr); 17396bf464f9SBarry Smith ierr = VecDestroy(&vi->Da); CHKERRQ(ierr); 17406bf464f9SBarry Smith ierr = VecDestroy(&vi->Db); CHKERRQ(ierr); 17416bf464f9SBarry Smith ierr = VecDestroy(&vi->z); CHKERRQ(ierr); 17426bf464f9SBarry Smith ierr = VecDestroy(&vi->t); CHKERRQ(ierr); 17437fe79bc4SShri Abhyankar } 17447fe79bc4SShri Abhyankar 17452b4ed282SShri Abhyankar if (!vi->usersetxbounds) { 17466bf464f9SBarry Smith ierr = VecDestroy(&vi->xl); CHKERRQ(ierr); 17476bf464f9SBarry Smith ierr = VecDestroy(&vi->xu); CHKERRQ(ierr); 17482b4ed282SShri Abhyankar } 17497fe79bc4SShri Abhyankar 17506bf464f9SBarry Smith ierr = PetscViewerASCIIMonitorDestroy(&vi->lsmonitor);CHKERRQ(ierr); 17512b4ed282SShri Abhyankar ierr = PetscFree(snes->data);CHKERRQ(ierr); 17522b4ed282SShri Abhyankar 17532b4ed282SShri Abhyankar /* clear composed functions */ 17542b4ed282SShri Abhyankar ierr = PetscObjectComposeFunctionDynamic((PetscObject)snes,"SNESLineSearchSet_C","",PETSC_NULL);CHKERRQ(ierr); 1755c92abb8aSShri Abhyankar ierr = PetscObjectComposeFunctionDynamic((PetscObject)snes,"SNESLineSearchSetMonitor_C","",PETSC_NULL);CHKERRQ(ierr); 17562b4ed282SShri Abhyankar PetscFunctionReturn(0); 17572b4ed282SShri Abhyankar } 17587fe79bc4SShri Abhyankar 17592b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */ 17602b4ed282SShri Abhyankar #undef __FUNCT__ 17612b4ed282SShri Abhyankar #define __FUNCT__ "SNESLineSearchNo_VI" 17622b4ed282SShri Abhyankar 17632b4ed282SShri Abhyankar /* 17647fe79bc4SShri Abhyankar This routine does not actually do a line search but it takes a full newton 17657fe79bc4SShri Abhyankar step while ensuring that the new iterates remain within the constraints. 17662b4ed282SShri Abhyankar 17672b4ed282SShri Abhyankar */ 1768ace3abfcSBarry 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) 17692b4ed282SShri Abhyankar { 17702b4ed282SShri Abhyankar PetscErrorCode ierr; 17712b4ed282SShri Abhyankar SNES_VI *vi = (SNES_VI*)snes->data; 1772ace3abfcSBarry Smith PetscBool changed_w = PETSC_FALSE,changed_y = PETSC_FALSE; 17732b4ed282SShri Abhyankar 17742b4ed282SShri Abhyankar PetscFunctionBegin; 17752b4ed282SShri Abhyankar *flag = PETSC_TRUE; 17762b4ed282SShri Abhyankar ierr = PetscLogEventBegin(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); 17772b4ed282SShri Abhyankar ierr = VecNorm(y,NORM_2,ynorm);CHKERRQ(ierr); /* ynorm = || y || */ 17782b4ed282SShri Abhyankar ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr); /* w <- x - y */ 1779c1a5e521SShri Abhyankar ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr); 1780c1a5e521SShri Abhyankar if (vi->postcheckstep) { 1781c1a5e521SShri Abhyankar ierr = (*vi->postcheckstep)(snes,x,y,w,vi->postcheck,&changed_y,&changed_w);CHKERRQ(ierr); 1782c1a5e521SShri Abhyankar } 1783c1a5e521SShri Abhyankar if (changed_y) { 1784c1a5e521SShri Abhyankar ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr); /* w <- x - y */ 17857fe79bc4SShri Abhyankar ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr); 1786c1a5e521SShri Abhyankar } 1787c1a5e521SShri Abhyankar ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr); 1788c1a5e521SShri Abhyankar ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr); 1789c1a5e521SShri Abhyankar if (!snes->domainerror) { 17902f63a38cSShri Abhyankar if (snes->ops->solve != SNESSolveVI_SS) { 17917fe79bc4SShri Abhyankar ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr); 17927fe79bc4SShri Abhyankar } else { 1793c1a5e521SShri Abhyankar ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr); /* gnorm = || g || */ 17947fe79bc4SShri Abhyankar } 179562cbcd01SMatthew G Knepley if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number"); 1796c1a5e521SShri Abhyankar } 1797c1a5e521SShri Abhyankar if (vi->lsmonitor) { 1798c1a5e521SShri Abhyankar ierr = PetscViewerASCIIMonitorPrintf(vi->lsmonitor," Line search: Using full step: fnorm %G gnorm %G\n",fnorm,*gnorm);CHKERRQ(ierr); 1799c1a5e521SShri Abhyankar } 1800c1a5e521SShri Abhyankar ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); 1801c1a5e521SShri Abhyankar PetscFunctionReturn(0); 1802c1a5e521SShri Abhyankar } 1803c1a5e521SShri Abhyankar 1804c1a5e521SShri Abhyankar /* -------------------------------------------------------------------------- */ 1805c1a5e521SShri Abhyankar #undef __FUNCT__ 18062b4ed282SShri Abhyankar #define __FUNCT__ "SNESLineSearchNoNorms_VI" 18072b4ed282SShri Abhyankar 18082b4ed282SShri Abhyankar /* 18092b4ed282SShri Abhyankar This routine is a copy of SNESLineSearchNoNorms in snes/impls/ls/ls.c 18102b4ed282SShri Abhyankar */ 1811ace3abfcSBarry 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) 18122b4ed282SShri Abhyankar { 18132b4ed282SShri Abhyankar PetscErrorCode ierr; 18142b4ed282SShri Abhyankar SNES_VI *vi = (SNES_VI*)snes->data; 1815ace3abfcSBarry Smith PetscBool changed_w = PETSC_FALSE,changed_y = PETSC_FALSE; 18162b4ed282SShri Abhyankar 18172b4ed282SShri Abhyankar PetscFunctionBegin; 18182b4ed282SShri Abhyankar *flag = PETSC_TRUE; 18192b4ed282SShri Abhyankar ierr = PetscLogEventBegin(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); 18202b4ed282SShri Abhyankar ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr); /* w <- x - y */ 18217fe79bc4SShri Abhyankar ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr); 18222b4ed282SShri Abhyankar if (vi->postcheckstep) { 18232b4ed282SShri Abhyankar ierr = (*vi->postcheckstep)(snes,x,y,w,vi->postcheck,&changed_y,&changed_w);CHKERRQ(ierr); 18242b4ed282SShri Abhyankar } 18252b4ed282SShri Abhyankar if (changed_y) { 18262b4ed282SShri Abhyankar ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr); /* w <- x - y */ 18277fe79bc4SShri Abhyankar ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr); 18282b4ed282SShri Abhyankar } 18292b4ed282SShri Abhyankar 18302b4ed282SShri Abhyankar /* don't evaluate function the last time through */ 18312b4ed282SShri Abhyankar if (snes->iter < snes->max_its-1) { 18322b4ed282SShri Abhyankar ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr); 18332b4ed282SShri Abhyankar } 18342b4ed282SShri Abhyankar ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); 18352b4ed282SShri Abhyankar PetscFunctionReturn(0); 18362b4ed282SShri Abhyankar } 18377fe79bc4SShri Abhyankar 18382b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */ 18392b4ed282SShri Abhyankar #undef __FUNCT__ 18402b4ed282SShri Abhyankar #define __FUNCT__ "SNESLineSearchCubic_VI" 18412b4ed282SShri Abhyankar /* 18427fe79bc4SShri Abhyankar This routine implements a cubic line search while doing a projection on the variable bounds 18432b4ed282SShri Abhyankar */ 1844ace3abfcSBarry 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) 18452b4ed282SShri Abhyankar { 1846fe835674SShri Abhyankar PetscReal initslope,lambdaprev,gnormprev,a,b,d,t1,t2,rellength; 1847fe835674SShri Abhyankar PetscReal minlambda,lambda,lambdatemp; 1848fe835674SShri Abhyankar #if defined(PETSC_USE_COMPLEX) 1849fe835674SShri Abhyankar PetscScalar cinitslope; 1850fe835674SShri Abhyankar #endif 1851fe835674SShri Abhyankar PetscErrorCode ierr; 1852fe835674SShri Abhyankar PetscInt count; 1853fe835674SShri Abhyankar SNES_VI *vi = (SNES_VI*)snes->data; 1854fe835674SShri Abhyankar PetscBool changed_w = PETSC_FALSE,changed_y = PETSC_FALSE; 1855fe835674SShri Abhyankar MPI_Comm comm; 1856fe835674SShri Abhyankar 1857fe835674SShri Abhyankar PetscFunctionBegin; 1858fe835674SShri Abhyankar ierr = PetscObjectGetComm((PetscObject)snes,&comm);CHKERRQ(ierr); 1859fe835674SShri Abhyankar ierr = PetscLogEventBegin(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); 1860fe835674SShri Abhyankar *flag = PETSC_TRUE; 1861fe835674SShri Abhyankar 1862fe835674SShri Abhyankar ierr = VecNorm(y,NORM_2,ynorm);CHKERRQ(ierr); 1863fe835674SShri Abhyankar if (*ynorm == 0.0) { 1864fe835674SShri Abhyankar if (vi->lsmonitor) { 1865fe835674SShri Abhyankar ierr = PetscViewerASCIIMonitorPrintf(vi->lsmonitor," Line search: Initial direction and size is 0\n");CHKERRQ(ierr); 1866fe835674SShri Abhyankar } 1867fe835674SShri Abhyankar *gnorm = fnorm; 1868fe835674SShri Abhyankar ierr = VecCopy(x,w);CHKERRQ(ierr); 1869fe835674SShri Abhyankar ierr = VecCopy(f,g);CHKERRQ(ierr); 1870fe835674SShri Abhyankar *flag = PETSC_FALSE; 1871fe835674SShri Abhyankar goto theend1; 1872fe835674SShri Abhyankar } 1873fe835674SShri Abhyankar if (*ynorm > vi->maxstep) { /* Step too big, so scale back */ 1874fe835674SShri Abhyankar if (vi->lsmonitor) { 1875fe835674SShri Abhyankar ierr = PetscViewerASCIIMonitorPrintf(vi->lsmonitor," Line search: Scaling step by %G old ynorm %G\n",vi->maxstep/(*ynorm),*ynorm);CHKERRQ(ierr); 1876fe835674SShri Abhyankar } 1877fe835674SShri Abhyankar ierr = VecScale(y,vi->maxstep/(*ynorm));CHKERRQ(ierr); 1878fe835674SShri Abhyankar *ynorm = vi->maxstep; 1879fe835674SShri Abhyankar } 1880fe835674SShri Abhyankar ierr = VecMaxPointwiseDivide(y,x,&rellength);CHKERRQ(ierr); 1881fe835674SShri Abhyankar minlambda = vi->minlambda/rellength; 1882fe835674SShri Abhyankar ierr = MatMult(snes->jacobian,y,w);CHKERRQ(ierr); 1883fe835674SShri Abhyankar #if defined(PETSC_USE_COMPLEX) 1884fe835674SShri Abhyankar ierr = VecDot(f,w,&cinitslope);CHKERRQ(ierr); 1885fe835674SShri Abhyankar initslope = PetscRealPart(cinitslope); 1886fe835674SShri Abhyankar #else 1887fe835674SShri Abhyankar ierr = VecDot(f,w,&initslope);CHKERRQ(ierr); 1888fe835674SShri Abhyankar #endif 1889fe835674SShri Abhyankar if (initslope > 0.0) initslope = -initslope; 1890fe835674SShri Abhyankar if (initslope == 0.0) initslope = -1.0; 1891fe835674SShri Abhyankar 1892fe835674SShri Abhyankar ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr); 1893fe835674SShri Abhyankar ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr); 1894fe835674SShri Abhyankar if (snes->nfuncs >= snes->max_funcs) { 1895fe835674SShri Abhyankar ierr = PetscInfo(snes,"Exceeded maximum function evaluations, while checking full step length!\n");CHKERRQ(ierr); 1896fe835674SShri Abhyankar *flag = PETSC_FALSE; 1897fe835674SShri Abhyankar snes->reason = SNES_DIVERGED_FUNCTION_COUNT; 1898fe835674SShri Abhyankar goto theend1; 1899fe835674SShri Abhyankar } 1900fe835674SShri Abhyankar ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr); 19012f63a38cSShri Abhyankar if (snes->ops->solve != SNESSolveVI_SS) { 1902fe835674SShri Abhyankar ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr); 19037fe79bc4SShri Abhyankar } else { 19047fe79bc4SShri Abhyankar ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr); 19057fe79bc4SShri Abhyankar } 1906fe835674SShri Abhyankar if (snes->domainerror) { 1907fe835674SShri Abhyankar ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); 1908fe835674SShri Abhyankar PetscFunctionReturn(0); 1909fe835674SShri Abhyankar } 191062cbcd01SMatthew G Knepley if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number"); 1911fe835674SShri Abhyankar ierr = PetscInfo2(snes,"Initial fnorm %G gnorm %G\n",fnorm,*gnorm);CHKERRQ(ierr); 1912fe835674SShri Abhyankar if (.5*(*gnorm)*(*gnorm) <= .5*fnorm*fnorm + vi->alpha*initslope) { /* Sufficient reduction */ 1913fe835674SShri Abhyankar if (vi->lsmonitor) { 1914fe835674SShri Abhyankar ierr = PetscViewerASCIIMonitorPrintf(vi->lsmonitor," Line search: Using full step: fnorm %G gnorm %G\n",fnorm,*gnorm);CHKERRQ(ierr); 1915fe835674SShri Abhyankar } 1916fe835674SShri Abhyankar goto theend1; 1917fe835674SShri Abhyankar } 1918fe835674SShri Abhyankar 1919fe835674SShri Abhyankar /* Fit points with quadratic */ 1920fe835674SShri Abhyankar lambda = 1.0; 1921fe835674SShri Abhyankar lambdatemp = -initslope/((*gnorm)*(*gnorm) - fnorm*fnorm - 2.0*initslope); 1922fe835674SShri Abhyankar lambdaprev = lambda; 1923fe835674SShri Abhyankar gnormprev = *gnorm; 1924fe835674SShri Abhyankar if (lambdatemp > .5*lambda) lambdatemp = .5*lambda; 1925fe835674SShri Abhyankar if (lambdatemp <= .1*lambda) lambda = .1*lambda; 1926fe835674SShri Abhyankar else lambda = lambdatemp; 1927fe835674SShri Abhyankar 1928fe835674SShri Abhyankar ierr = VecWAXPY(w,-lambda,y,x);CHKERRQ(ierr); 1929fe835674SShri Abhyankar ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr); 1930fe835674SShri Abhyankar if (snes->nfuncs >= snes->max_funcs) { 1931fe835674SShri Abhyankar ierr = PetscInfo1(snes,"Exceeded maximum function evaluations, while attempting quadratic backtracking! %D \n",snes->nfuncs);CHKERRQ(ierr); 1932fe835674SShri Abhyankar *flag = PETSC_FALSE; 1933fe835674SShri Abhyankar snes->reason = SNES_DIVERGED_FUNCTION_COUNT; 1934fe835674SShri Abhyankar goto theend1; 1935fe835674SShri Abhyankar } 1936fe835674SShri Abhyankar ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr); 19372f63a38cSShri Abhyankar if (snes->ops->solve != SNESSolveVI_SS) { 1938fe835674SShri Abhyankar ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr); 19397fe79bc4SShri Abhyankar } else { 19407fe79bc4SShri Abhyankar ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr); 19417fe79bc4SShri Abhyankar } 1942fe835674SShri Abhyankar if (snes->domainerror) { 1943fe835674SShri Abhyankar ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); 1944fe835674SShri Abhyankar PetscFunctionReturn(0); 1945fe835674SShri Abhyankar } 194662cbcd01SMatthew G Knepley if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number"); 1947fe835674SShri Abhyankar if (vi->lsmonitor) { 1948fe835674SShri Abhyankar ierr = PetscViewerASCIIMonitorPrintf(vi->lsmonitor," Line search: gnorm after quadratic fit %G\n",*gnorm);CHKERRQ(ierr); 1949fe835674SShri Abhyankar } 1950fe835674SShri Abhyankar if (.5*(*gnorm)*(*gnorm) < .5*fnorm*fnorm + lambda*vi->alpha*initslope) { /* sufficient reduction */ 1951fe835674SShri Abhyankar if (vi->lsmonitor) { 1952fe835674SShri Abhyankar ierr = PetscViewerASCIIMonitorPrintf(vi->lsmonitor," Line search: Quadratically determined step, lambda=%18.16e\n",lambda);CHKERRQ(ierr); 1953fe835674SShri Abhyankar } 1954fe835674SShri Abhyankar goto theend1; 1955fe835674SShri Abhyankar } 1956fe835674SShri Abhyankar 1957fe835674SShri Abhyankar /* Fit points with cubic */ 1958fe835674SShri Abhyankar count = 1; 1959fe835674SShri Abhyankar while (PETSC_TRUE) { 1960fe835674SShri Abhyankar if (lambda <= minlambda) { 1961fe835674SShri Abhyankar if (vi->lsmonitor) { 1962fe835674SShri Abhyankar ierr = PetscViewerASCIIMonitorPrintf(vi->lsmonitor," Line search: unable to find good step length! After %D tries \n",count);CHKERRQ(ierr); 1963fe835674SShri 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); 1964fe835674SShri Abhyankar } 1965fe835674SShri Abhyankar *flag = PETSC_FALSE; 1966fe835674SShri Abhyankar break; 1967fe835674SShri Abhyankar } 1968fe835674SShri Abhyankar t1 = .5*((*gnorm)*(*gnorm) - fnorm*fnorm) - lambda*initslope; 1969fe835674SShri Abhyankar t2 = .5*(gnormprev*gnormprev - fnorm*fnorm) - lambdaprev*initslope; 1970fe835674SShri Abhyankar a = (t1/(lambda*lambda) - t2/(lambdaprev*lambdaprev))/(lambda-lambdaprev); 1971fe835674SShri Abhyankar b = (-lambdaprev*t1/(lambda*lambda) + lambda*t2/(lambdaprev*lambdaprev))/(lambda-lambdaprev); 1972fe835674SShri Abhyankar d = b*b - 3*a*initslope; 1973fe835674SShri Abhyankar if (d < 0.0) d = 0.0; 1974fe835674SShri Abhyankar if (a == 0.0) { 1975fe835674SShri Abhyankar lambdatemp = -initslope/(2.0*b); 1976fe835674SShri Abhyankar } else { 1977fe835674SShri Abhyankar lambdatemp = (-b + sqrt(d))/(3.0*a); 1978fe835674SShri Abhyankar } 1979fe835674SShri Abhyankar lambdaprev = lambda; 1980fe835674SShri Abhyankar gnormprev = *gnorm; 1981fe835674SShri Abhyankar if (lambdatemp > .5*lambda) lambdatemp = .5*lambda; 1982fe835674SShri Abhyankar if (lambdatemp <= .1*lambda) lambda = .1*lambda; 1983fe835674SShri Abhyankar else lambda = lambdatemp; 1984fe835674SShri Abhyankar ierr = VecWAXPY(w,-lambda,y,x);CHKERRQ(ierr); 1985fe835674SShri Abhyankar ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr); 1986fe835674SShri Abhyankar if (snes->nfuncs >= snes->max_funcs) { 1987fe835674SShri Abhyankar ierr = PetscInfo1(snes,"Exceeded maximum function evaluations, while looking for good step length! %D \n",count);CHKERRQ(ierr); 1988fe835674SShri 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); 1989fe835674SShri Abhyankar *flag = PETSC_FALSE; 1990fe835674SShri Abhyankar snes->reason = SNES_DIVERGED_FUNCTION_COUNT; 1991fe835674SShri Abhyankar break; 1992fe835674SShri Abhyankar } 1993fe835674SShri Abhyankar ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr); 19942f63a38cSShri Abhyankar if (snes->ops->solve != SNESSolveVI_SS) { 1995fe835674SShri Abhyankar ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr); 19967fe79bc4SShri Abhyankar } else { 19977fe79bc4SShri Abhyankar ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr); 19987fe79bc4SShri Abhyankar } 1999fe835674SShri Abhyankar if (snes->domainerror) { 2000fe835674SShri Abhyankar ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); 2001fe835674SShri Abhyankar PetscFunctionReturn(0); 2002fe835674SShri Abhyankar } 200362cbcd01SMatthew G Knepley if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number"); 2004fe835674SShri Abhyankar if (.5*(*gnorm)*(*gnorm) < .5*fnorm*fnorm + lambda*vi->alpha*initslope) { /* is reduction enough? */ 2005fe835674SShri Abhyankar if (vi->lsmonitor) { 2006fe835674SShri Abhyankar ierr = PetscPrintf(comm," Line search: Cubically determined step, current gnorm %G lambda=%18.16e\n",*gnorm,lambda);CHKERRQ(ierr); 2007fe835674SShri Abhyankar } 2008fe835674SShri Abhyankar break; 2009fe835674SShri Abhyankar } else { 2010fe835674SShri Abhyankar if (vi->lsmonitor) { 2011fe835674SShri Abhyankar ierr = PetscPrintf(comm," Line search: Cubic step no good, shrinking lambda, current gnorm %G lambda=%18.16e\n",*gnorm,lambda);CHKERRQ(ierr); 2012fe835674SShri Abhyankar } 2013fe835674SShri Abhyankar } 2014fe835674SShri Abhyankar count++; 2015fe835674SShri Abhyankar } 2016fe835674SShri Abhyankar theend1: 2017fe835674SShri Abhyankar /* Optional user-defined check for line search step validity */ 2018fe835674SShri Abhyankar if (vi->postcheckstep && *flag) { 2019fe835674SShri Abhyankar ierr = (*vi->postcheckstep)(snes,x,y,w,vi->postcheck,&changed_y,&changed_w);CHKERRQ(ierr); 2020fe835674SShri Abhyankar if (changed_y) { 2021fe835674SShri Abhyankar ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr); 2022fe835674SShri Abhyankar ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr); 2023fe835674SShri Abhyankar } 2024fe835674SShri Abhyankar if (changed_y || changed_w) { /* recompute the function if the step has changed */ 2025fe835674SShri Abhyankar ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr); 20262f63a38cSShri Abhyankar if (snes->ops->solve != SNESSolveVI_SS) { 2027fe835674SShri Abhyankar ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr); 20287fe79bc4SShri Abhyankar } else { 20297fe79bc4SShri Abhyankar ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr); 20307fe79bc4SShri Abhyankar } 2031fe835674SShri Abhyankar if (snes->domainerror) { 2032fe835674SShri Abhyankar ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); 2033fe835674SShri Abhyankar PetscFunctionReturn(0); 2034fe835674SShri Abhyankar } 203562cbcd01SMatthew G Knepley if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number"); 2036fe835674SShri Abhyankar ierr = VecNormBegin(y,NORM_2,ynorm);CHKERRQ(ierr); 2037fe835674SShri Abhyankar ierr = VecNormEnd(y,NORM_2,ynorm);CHKERRQ(ierr); 2038fe835674SShri Abhyankar } 2039fe835674SShri Abhyankar } 2040fe835674SShri Abhyankar ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); 2041fe835674SShri Abhyankar PetscFunctionReturn(0); 2042fe835674SShri Abhyankar } 2043fe835674SShri Abhyankar 20442b4ed282SShri Abhyankar #undef __FUNCT__ 20452b4ed282SShri Abhyankar #define __FUNCT__ "SNESLineSearchQuadratic_VI" 20462b4ed282SShri Abhyankar /* 20477fe79bc4SShri Abhyankar This routine does a quadratic line search while keeping the iterates within the variable bounds 20482b4ed282SShri Abhyankar */ 2049ace3abfcSBarry 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) 20502b4ed282SShri Abhyankar { 20512b4ed282SShri Abhyankar /* 20522b4ed282SShri Abhyankar Note that for line search purposes we work with with the related 20532b4ed282SShri Abhyankar minimization problem: 20542b4ed282SShri Abhyankar min z(x): R^n -> R, 20552b4ed282SShri Abhyankar where z(x) = .5 * fnorm*fnorm,and fnorm = || f ||_2. 20562b4ed282SShri Abhyankar */ 20572b4ed282SShri Abhyankar PetscReal initslope,minlambda,lambda,lambdatemp,rellength; 20582b4ed282SShri Abhyankar #if defined(PETSC_USE_COMPLEX) 20592b4ed282SShri Abhyankar PetscScalar cinitslope; 20602b4ed282SShri Abhyankar #endif 20612b4ed282SShri Abhyankar PetscErrorCode ierr; 20622b4ed282SShri Abhyankar PetscInt count; 20632b4ed282SShri Abhyankar SNES_VI *vi = (SNES_VI*)snes->data; 2064ace3abfcSBarry Smith PetscBool changed_w = PETSC_FALSE,changed_y = PETSC_FALSE; 20652b4ed282SShri Abhyankar 20662b4ed282SShri Abhyankar PetscFunctionBegin; 20672b4ed282SShri Abhyankar ierr = PetscLogEventBegin(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); 20682b4ed282SShri Abhyankar *flag = PETSC_TRUE; 20692b4ed282SShri Abhyankar 20702b4ed282SShri Abhyankar ierr = VecNorm(y,NORM_2,ynorm);CHKERRQ(ierr); 20712b4ed282SShri Abhyankar if (*ynorm == 0.0) { 2072c92abb8aSShri Abhyankar if (vi->lsmonitor) { 2073c92abb8aSShri Abhyankar ierr = PetscViewerASCIIMonitorPrintf(vi->lsmonitor,"Line search: Direction and size is 0\n");CHKERRQ(ierr); 20742b4ed282SShri Abhyankar } 20752b4ed282SShri Abhyankar *gnorm = fnorm; 20762b4ed282SShri Abhyankar ierr = VecCopy(x,w);CHKERRQ(ierr); 20772b4ed282SShri Abhyankar ierr = VecCopy(f,g);CHKERRQ(ierr); 20782b4ed282SShri Abhyankar *flag = PETSC_FALSE; 20792b4ed282SShri Abhyankar goto theend2; 20802b4ed282SShri Abhyankar } 20812b4ed282SShri Abhyankar if (*ynorm > vi->maxstep) { /* Step too big, so scale back */ 20822b4ed282SShri Abhyankar ierr = VecScale(y,vi->maxstep/(*ynorm));CHKERRQ(ierr); 20832b4ed282SShri Abhyankar *ynorm = vi->maxstep; 20842b4ed282SShri Abhyankar } 20852b4ed282SShri Abhyankar ierr = VecMaxPointwiseDivide(y,x,&rellength);CHKERRQ(ierr); 20862b4ed282SShri Abhyankar minlambda = vi->minlambda/rellength; 20877fe79bc4SShri Abhyankar ierr = MatMult(snes->jacobian,y,w);CHKERRQ(ierr); 20882b4ed282SShri Abhyankar #if defined(PETSC_USE_COMPLEX) 20897fe79bc4SShri Abhyankar ierr = VecDot(f,w,&cinitslope);CHKERRQ(ierr); 20902b4ed282SShri Abhyankar initslope = PetscRealPart(cinitslope); 20912b4ed282SShri Abhyankar #else 20927fe79bc4SShri Abhyankar ierr = VecDot(f,w,&initslope);CHKERRQ(ierr); 20932b4ed282SShri Abhyankar #endif 20942b4ed282SShri Abhyankar if (initslope > 0.0) initslope = -initslope; 20952b4ed282SShri Abhyankar if (initslope == 0.0) initslope = -1.0; 20962b4ed282SShri Abhyankar ierr = PetscInfo1(snes,"Initslope %G \n",initslope);CHKERRQ(ierr); 20972b4ed282SShri Abhyankar 20982b4ed282SShri Abhyankar ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr); 20997fe79bc4SShri Abhyankar ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr); 21002b4ed282SShri Abhyankar if (snes->nfuncs >= snes->max_funcs) { 21012b4ed282SShri Abhyankar ierr = PetscInfo(snes,"Exceeded maximum function evaluations, while checking full step length!\n");CHKERRQ(ierr); 21022b4ed282SShri Abhyankar *flag = PETSC_FALSE; 21032b4ed282SShri Abhyankar snes->reason = SNES_DIVERGED_FUNCTION_COUNT; 21042b4ed282SShri Abhyankar goto theend2; 21052b4ed282SShri Abhyankar } 21062b4ed282SShri Abhyankar ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr); 21072f63a38cSShri Abhyankar if (snes->ops->solve != SNESSolveVI_SS) { 21087fe79bc4SShri Abhyankar ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr); 21097fe79bc4SShri Abhyankar } else { 21107fe79bc4SShri Abhyankar ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr); 21117fe79bc4SShri Abhyankar } 21122b4ed282SShri Abhyankar if (snes->domainerror) { 21132b4ed282SShri Abhyankar ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); 21142b4ed282SShri Abhyankar PetscFunctionReturn(0); 21152b4ed282SShri Abhyankar } 211662cbcd01SMatthew G Knepley if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number"); 21172b4ed282SShri Abhyankar if (.5*(*gnorm)*(*gnorm) <= .5*fnorm*fnorm + vi->alpha*initslope) { /* Sufficient reduction */ 2118c92abb8aSShri Abhyankar if (vi->lsmonitor) { 2119c92abb8aSShri Abhyankar ierr = PetscViewerASCIIMonitorPrintf(vi->lsmonitor," Line search: Using full step: fnorm %G gnorm %G\n",fnorm,*gnorm);CHKERRQ(ierr); 21202b4ed282SShri Abhyankar } 21212b4ed282SShri Abhyankar goto theend2; 21222b4ed282SShri Abhyankar } 21232b4ed282SShri Abhyankar 21242b4ed282SShri Abhyankar /* Fit points with quadratic */ 21252b4ed282SShri Abhyankar lambda = 1.0; 21262b4ed282SShri Abhyankar count = 1; 21272b4ed282SShri Abhyankar while (PETSC_TRUE) { 21282b4ed282SShri Abhyankar if (lambda <= minlambda) { /* bad luck; use full step */ 2129c92abb8aSShri Abhyankar if (vi->lsmonitor) { 2130c92abb8aSShri Abhyankar ierr = PetscViewerASCIIMonitorPrintf(vi->lsmonitor,"Line search: Unable to find good step length! %D \n",count);CHKERRQ(ierr); 2131c92abb8aSShri 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); 21322b4ed282SShri Abhyankar } 21332b4ed282SShri Abhyankar ierr = VecCopy(x,w);CHKERRQ(ierr); 21342b4ed282SShri Abhyankar *flag = PETSC_FALSE; 21352b4ed282SShri Abhyankar break; 21362b4ed282SShri Abhyankar } 21372b4ed282SShri Abhyankar lambdatemp = -initslope/((*gnorm)*(*gnorm) - fnorm*fnorm - 2.0*initslope); 21382b4ed282SShri Abhyankar if (lambdatemp > .5*lambda) lambdatemp = .5*lambda; 21392b4ed282SShri Abhyankar if (lambdatemp <= .1*lambda) lambda = .1*lambda; 21402b4ed282SShri Abhyankar else lambda = lambdatemp; 21412b4ed282SShri Abhyankar 21422b4ed282SShri Abhyankar ierr = VecWAXPY(w,-lambda,y,x);CHKERRQ(ierr); 21437fe79bc4SShri Abhyankar ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr); 21442b4ed282SShri Abhyankar if (snes->nfuncs >= snes->max_funcs) { 21452b4ed282SShri Abhyankar ierr = PetscInfo1(snes,"Exceeded maximum function evaluations, while looking for good step length! %D \n",count);CHKERRQ(ierr); 21462b4ed282SShri 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); 21472b4ed282SShri Abhyankar *flag = PETSC_FALSE; 21482b4ed282SShri Abhyankar snes->reason = SNES_DIVERGED_FUNCTION_COUNT; 21492b4ed282SShri Abhyankar break; 21502b4ed282SShri Abhyankar } 21512b4ed282SShri Abhyankar ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr); 21522b4ed282SShri Abhyankar if (snes->domainerror) { 21532b4ed282SShri Abhyankar ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); 21542b4ed282SShri Abhyankar PetscFunctionReturn(0); 21552b4ed282SShri Abhyankar } 21562f63a38cSShri Abhyankar if (snes->ops->solve != SNESSolveVI_SS) { 21577fe79bc4SShri Abhyankar ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr); 21587fe79bc4SShri Abhyankar } else { 21592b4ed282SShri Abhyankar ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr); 21607fe79bc4SShri Abhyankar } 216162cbcd01SMatthew G Knepley if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number"); 21622b4ed282SShri Abhyankar if (.5*(*gnorm)*(*gnorm) < .5*fnorm*fnorm + lambda*vi->alpha*initslope) { /* sufficient reduction */ 2163c92abb8aSShri Abhyankar if (vi->lsmonitor) { 2164c92abb8aSShri Abhyankar ierr = PetscViewerASCIIMonitorPrintf(vi->lsmonitor," Line Search: Quadratically determined step, lambda=%G\n",lambda);CHKERRQ(ierr); 21652b4ed282SShri Abhyankar } 21662b4ed282SShri Abhyankar break; 21672b4ed282SShri Abhyankar } 21682b4ed282SShri Abhyankar count++; 21692b4ed282SShri Abhyankar } 21702b4ed282SShri Abhyankar theend2: 21712b4ed282SShri Abhyankar /* Optional user-defined check for line search step validity */ 21722b4ed282SShri Abhyankar if (vi->postcheckstep) { 21732b4ed282SShri Abhyankar ierr = (*vi->postcheckstep)(snes,x,y,w,vi->postcheck,&changed_y,&changed_w);CHKERRQ(ierr); 21742b4ed282SShri Abhyankar if (changed_y) { 21752b4ed282SShri Abhyankar ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr); 21767fe79bc4SShri Abhyankar ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr); 21772b4ed282SShri Abhyankar } 21782b4ed282SShri Abhyankar if (changed_y || changed_w) { /* recompute the function if the step has changed */ 21792b4ed282SShri Abhyankar ierr = SNESComputeFunction(snes,w,g); 21802b4ed282SShri Abhyankar if (snes->domainerror) { 21812b4ed282SShri Abhyankar ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); 21822b4ed282SShri Abhyankar PetscFunctionReturn(0); 21832b4ed282SShri Abhyankar } 21842f63a38cSShri Abhyankar if (snes->ops->solve != SNESSolveVI_SS) { 21857fe79bc4SShri Abhyankar ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr); 21867fe79bc4SShri Abhyankar } else { 21877fe79bc4SShri Abhyankar ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr); 21887fe79bc4SShri Abhyankar } 21897fe79bc4SShri Abhyankar 21902b4ed282SShri Abhyankar ierr = VecNormBegin(y,NORM_2,ynorm);CHKERRQ(ierr); 21912b4ed282SShri Abhyankar ierr = VecNormEnd(y,NORM_2,ynorm);CHKERRQ(ierr); 219262cbcd01SMatthew G Knepley if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number"); 21932b4ed282SShri Abhyankar } 21942b4ed282SShri Abhyankar } 21952b4ed282SShri Abhyankar ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); 21962b4ed282SShri Abhyankar PetscFunctionReturn(0); 21972b4ed282SShri Abhyankar } 21982b4ed282SShri Abhyankar 2199ace3abfcSBarry 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*/ 22002b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */ 22012b4ed282SShri Abhyankar EXTERN_C_BEGIN 22022b4ed282SShri Abhyankar #undef __FUNCT__ 22032b4ed282SShri Abhyankar #define __FUNCT__ "SNESLineSearchSet_VI" 22047087cfbeSBarry Smith PetscErrorCode SNESLineSearchSet_VI(SNES snes,FCN2 func,void *lsctx) 22052b4ed282SShri Abhyankar { 22062b4ed282SShri Abhyankar PetscFunctionBegin; 22072b4ed282SShri Abhyankar ((SNES_VI *)(snes->data))->LineSearch = func; 22082b4ed282SShri Abhyankar ((SNES_VI *)(snes->data))->lsP = lsctx; 22092b4ed282SShri Abhyankar PetscFunctionReturn(0); 22102b4ed282SShri Abhyankar } 22112b4ed282SShri Abhyankar EXTERN_C_END 22122b4ed282SShri Abhyankar 22132b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */ 22142b4ed282SShri Abhyankar EXTERN_C_BEGIN 22152b4ed282SShri Abhyankar #undef __FUNCT__ 22162b4ed282SShri Abhyankar #define __FUNCT__ "SNESLineSearchSetMonitor_VI" 22177087cfbeSBarry Smith PetscErrorCode SNESLineSearchSetMonitor_VI(SNES snes,PetscBool flg) 22182b4ed282SShri Abhyankar { 22192b4ed282SShri Abhyankar SNES_VI *vi = (SNES_VI*)snes->data; 22202b4ed282SShri Abhyankar PetscErrorCode ierr; 22212b4ed282SShri Abhyankar 22222b4ed282SShri Abhyankar PetscFunctionBegin; 2223c92abb8aSShri Abhyankar if (flg && !vi->lsmonitor) { 2224c92abb8aSShri Abhyankar ierr = PetscViewerASCIIMonitorCreate(((PetscObject)snes)->comm,"stdout",((PetscObject)snes)->tablevel,&vi->lsmonitor);CHKERRQ(ierr); 2225c92abb8aSShri Abhyankar } else if (!flg && vi->lsmonitor) { 22266bf464f9SBarry Smith ierr = PetscViewerASCIIMonitorDestroy(&vi->lsmonitor);CHKERRQ(ierr); 22272b4ed282SShri Abhyankar } 22282b4ed282SShri Abhyankar PetscFunctionReturn(0); 22292b4ed282SShri Abhyankar } 22302b4ed282SShri Abhyankar EXTERN_C_END 22312b4ed282SShri Abhyankar 22322b4ed282SShri Abhyankar /* 22332b4ed282SShri Abhyankar SNESView_VI - Prints info from the SNESVI data structure. 22342b4ed282SShri Abhyankar 22352b4ed282SShri Abhyankar Input Parameters: 22362b4ed282SShri Abhyankar . SNES - the SNES context 22372b4ed282SShri Abhyankar . viewer - visualization context 22382b4ed282SShri Abhyankar 22392b4ed282SShri Abhyankar Application Interface Routine: SNESView() 22402b4ed282SShri Abhyankar */ 22412b4ed282SShri Abhyankar #undef __FUNCT__ 22422b4ed282SShri Abhyankar #define __FUNCT__ "SNESView_VI" 22432b4ed282SShri Abhyankar static PetscErrorCode SNESView_VI(SNES snes,PetscViewer viewer) 22442b4ed282SShri Abhyankar { 22452b4ed282SShri Abhyankar SNES_VI *vi = (SNES_VI *)snes->data; 224678c4b9d3SShri Abhyankar const char *cstr,*tstr; 22472b4ed282SShri Abhyankar PetscErrorCode ierr; 2248ace3abfcSBarry Smith PetscBool iascii; 22492b4ed282SShri Abhyankar 22502b4ed282SShri Abhyankar PetscFunctionBegin; 22512b4ed282SShri Abhyankar ierr = PetscTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); 22522b4ed282SShri Abhyankar if (iascii) { 22532b4ed282SShri Abhyankar if (vi->LineSearch == SNESLineSearchNo_VI) cstr = "SNESLineSearchNo"; 22542b4ed282SShri Abhyankar else if (vi->LineSearch == SNESLineSearchQuadratic_VI) cstr = "SNESLineSearchQuadratic"; 22552b4ed282SShri Abhyankar else if (vi->LineSearch == SNESLineSearchCubic_VI) cstr = "SNESLineSearchCubic"; 22562b4ed282SShri Abhyankar else cstr = "unknown"; 225778c4b9d3SShri Abhyankar if (snes->ops->solve == SNESSolveVI_SS) tstr = "Semismooth"; 22580a7c7af0SShri Abhyankar else if (snes->ops->solve == SNESSolveVI_RS) tstr = "Reduced Space"; 2259b350b9c9SBarry Smith else if (snes->ops->solve == SNESSolveVI_RSAUG) tstr = "Reduced space with augmented variables"; 226078c4b9d3SShri Abhyankar else tstr = "unknown"; 226178c4b9d3SShri Abhyankar ierr = PetscViewerASCIIPrintf(viewer," VI algorithm: %s\n",tstr);CHKERRQ(ierr); 22622b4ed282SShri Abhyankar ierr = PetscViewerASCIIPrintf(viewer," line search variant: %s\n",cstr);CHKERRQ(ierr); 22632b4ed282SShri Abhyankar ierr = PetscViewerASCIIPrintf(viewer," alpha=%G, maxstep=%G, minlambda=%G\n",vi->alpha,vi->maxstep,vi->minlambda);CHKERRQ(ierr); 22642b4ed282SShri Abhyankar } else { 22652b4ed282SShri Abhyankar SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Viewer type %s not supported for SNES EQ VI",((PetscObject)viewer)->type_name); 22662b4ed282SShri Abhyankar } 22672b4ed282SShri Abhyankar PetscFunctionReturn(0); 22682b4ed282SShri Abhyankar } 22692b4ed282SShri Abhyankar 22705559b345SBarry Smith #undef __FUNCT__ 22715559b345SBarry Smith #define __FUNCT__ "SNESVISetVariableBounds" 22725559b345SBarry Smith /*@ 22732b4ed282SShri Abhyankar SNESVISetVariableBounds - Sets the lower and upper bounds for the solution vector. xl <= x <= xu. 22742b4ed282SShri Abhyankar 22752b4ed282SShri Abhyankar Input Parameters: 22762b4ed282SShri Abhyankar . snes - the SNES context. 22772b4ed282SShri Abhyankar . xl - lower bound. 22782b4ed282SShri Abhyankar . xu - upper bound. 22792b4ed282SShri Abhyankar 22802b4ed282SShri Abhyankar Notes: 22812b4ed282SShri Abhyankar If this routine is not called then the lower and upper bounds are set to 228201f0b76bSBarry Smith SNES_VI_INF and SNES_VI_NINF respectively during SNESSetUp(). 228384c105d7SBarry Smith 22845559b345SBarry Smith @*/ 228569c03620SShri Abhyankar PetscErrorCode SNESVISetVariableBounds(SNES snes, Vec xl, Vec xu) 22862b4ed282SShri Abhyankar { 2287d923200aSJungho Lee SNES_VI *vi; 2288d923200aSJungho Lee PetscErrorCode ierr; 22892b4ed282SShri Abhyankar 22902b4ed282SShri Abhyankar PetscFunctionBegin; 22912b4ed282SShri Abhyankar PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 22922b4ed282SShri Abhyankar PetscValidHeaderSpecific(xl,VEC_CLASSID,2); 22932b4ed282SShri Abhyankar PetscValidHeaderSpecific(xu,VEC_CLASSID,3); 22942b4ed282SShri Abhyankar if (!snes->vec_func) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Must call SNESSetFunction() first"); 22952b4ed282SShri 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); 22962b4ed282SShri 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); 2297d923200aSJungho Lee ierr = SNESSetType(snes,SNESVI);CHKERRQ(ierr); 2298d923200aSJungho Lee vi = (SNES_VI*)snes->data; 22992b4ed282SShri Abhyankar vi->usersetxbounds = PETSC_TRUE; 23002b4ed282SShri Abhyankar vi->xl = xl; 23012b4ed282SShri Abhyankar vi->xu = xu; 23022b4ed282SShri Abhyankar PetscFunctionReturn(0); 23032b4ed282SShri Abhyankar } 2304693ddf92SShri Abhyankar 23052b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */ 23062b4ed282SShri Abhyankar /* 23072b4ed282SShri Abhyankar SNESSetFromOptions_VI - Sets various parameters for the SNESVI method. 23082b4ed282SShri Abhyankar 23092b4ed282SShri Abhyankar Input Parameter: 23102b4ed282SShri Abhyankar . snes - the SNES context 23112b4ed282SShri Abhyankar 23122b4ed282SShri Abhyankar Application Interface Routine: SNESSetFromOptions() 23132b4ed282SShri Abhyankar */ 23142b4ed282SShri Abhyankar #undef __FUNCT__ 23152b4ed282SShri Abhyankar #define __FUNCT__ "SNESSetFromOptions_VI" 23162b4ed282SShri Abhyankar static PetscErrorCode SNESSetFromOptions_VI(SNES snes) 23172b4ed282SShri Abhyankar { 23182b4ed282SShri Abhyankar SNES_VI *vi = (SNES_VI *)snes->data; 23197fe79bc4SShri Abhyankar const char *lses[] = {"basic","basicnonorms","quadratic","cubic"}; 2320b350b9c9SBarry Smith const char *vies[] = {"ss","rs","rsaug"}; 23212b4ed282SShri Abhyankar PetscErrorCode ierr; 23222b4ed282SShri Abhyankar PetscInt indx; 232369c03620SShri Abhyankar PetscBool flg,set,flg2; 23242b4ed282SShri Abhyankar 23252b4ed282SShri Abhyankar PetscFunctionBegin; 23262b4ed282SShri Abhyankar ierr = PetscOptionsHead("SNES semismooth method options");CHKERRQ(ierr); 23279308c137SBarry Smith ierr = PetscOptionsBool("-snes_vi_monitor","Monitor all non-active variables","None",PETSC_FALSE,&flg,0);CHKERRQ(ierr); 23289308c137SBarry Smith if (flg) { 23299308c137SBarry Smith ierr = SNESMonitorSet(snes,SNESMonitorVI,0,0);CHKERRQ(ierr); 23309308c137SBarry Smith } 2331be6adb11SBarry Smith ierr = PetscOptionsReal("-snes_ls_alpha","Function norm must decrease by","None",vi->alpha,&vi->alpha,0);CHKERRQ(ierr); 2332be6adb11SBarry Smith ierr = PetscOptionsReal("-snes_ls_maxstep","Step must be less than","None",vi->maxstep,&vi->maxstep,0);CHKERRQ(ierr); 2333be6adb11SBarry Smith ierr = PetscOptionsReal("-snes_ls_minlambda","Minimum lambda allowed","None",vi->minlambda,&vi->minlambda,0);CHKERRQ(ierr); 23342b4ed282SShri Abhyankar ierr = PetscOptionsReal("-snes_vi_const_tol","constraint tolerance","None",vi->const_tol,&vi->const_tol,0);CHKERRQ(ierr); 2335be6adb11SBarry Smith ierr = PetscOptionsBool("-snes_ls_monitor","Print progress of line searches","SNESLineSearchSetMonitor",vi->lsmonitor ? PETSC_TRUE : PETSC_FALSE,&flg,&set);CHKERRQ(ierr); 23362b4ed282SShri Abhyankar if (set) {ierr = SNESLineSearchSetMonitor(snes,flg);CHKERRQ(ierr);} 23372f63a38cSShri Abhyankar ierr = PetscOptionsEList("-snes_vi_type","Semismooth algorithm used","",vies,3,"ss",&indx,&flg2);CHKERRQ(ierr); 233869c03620SShri Abhyankar if (flg2) { 233969c03620SShri Abhyankar switch (indx) { 234069c03620SShri Abhyankar case 0: 234169c03620SShri Abhyankar snes->ops->solve = SNESSolveVI_SS; 234269c03620SShri Abhyankar break; 234369c03620SShri Abhyankar case 1: 2344d950fb63SShri Abhyankar snes->ops->solve = SNESSolveVI_RS; 2345d950fb63SShri Abhyankar break; 23462f63a38cSShri Abhyankar case 2: 2347b350b9c9SBarry Smith snes->ops->solve = SNESSolveVI_RSAUG; 234869c03620SShri Abhyankar } 234969c03620SShri Abhyankar } 2350be6adb11SBarry Smith ierr = PetscOptionsEList("-snes_ls","Line search used","SNESLineSearchSet",lses,4,"basic",&indx,&flg);CHKERRQ(ierr); 23512b4ed282SShri Abhyankar if (flg) { 23522b4ed282SShri Abhyankar switch (indx) { 23532b4ed282SShri Abhyankar case 0: 23542b4ed282SShri Abhyankar ierr = SNESLineSearchSet(snes,SNESLineSearchNo_VI,PETSC_NULL);CHKERRQ(ierr); 23552b4ed282SShri Abhyankar break; 23562b4ed282SShri Abhyankar case 1: 23572b4ed282SShri Abhyankar ierr = SNESLineSearchSet(snes,SNESLineSearchNoNorms_VI,PETSC_NULL);CHKERRQ(ierr); 23582b4ed282SShri Abhyankar break; 23592b4ed282SShri Abhyankar case 2: 23602b4ed282SShri Abhyankar ierr = SNESLineSearchSet(snes,SNESLineSearchQuadratic_VI,PETSC_NULL);CHKERRQ(ierr); 23612b4ed282SShri Abhyankar break; 23622b4ed282SShri Abhyankar case 3: 23632b4ed282SShri Abhyankar ierr = SNESLineSearchSet(snes,SNESLineSearchCubic_VI,PETSC_NULL);CHKERRQ(ierr); 23642b4ed282SShri Abhyankar break; 23652b4ed282SShri Abhyankar } 2366fe835674SShri Abhyankar } 23672b4ed282SShri Abhyankar ierr = PetscOptionsTail();CHKERRQ(ierr); 23682b4ed282SShri Abhyankar PetscFunctionReturn(0); 23692b4ed282SShri Abhyankar } 23702b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */ 23712b4ed282SShri Abhyankar /*MC 23728b4c83edSBarry Smith SNESVI - Various solvers for variational inequalities based on Newton's method 23732b4ed282SShri Abhyankar 23742b4ed282SShri Abhyankar Options Database: 23758b4c83edSBarry 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 23768b4c83edSBarry Smith additional variables that enforce the constraints 23778b4c83edSBarry Smith - -snes_vi_monitor - prints the number of active constraints at each iteration. 23782b4ed282SShri Abhyankar 23792b4ed282SShri Abhyankar 23802b4ed282SShri Abhyankar Level: beginner 23812b4ed282SShri Abhyankar 23822b4ed282SShri Abhyankar .seealso: SNESCreate(), SNES, SNESSetType(), SNESTR, SNESLineSearchSet(), 23832b4ed282SShri Abhyankar SNESLineSearchSetPostCheck(), SNESLineSearchNo(), SNESLineSearchCubic(), SNESLineSearchQuadratic(), 23842b4ed282SShri Abhyankar SNESLineSearchSet(), SNESLineSearchNoNorms(), SNESLineSearchSetPreCheck(), SNESLineSearchSetParams(), SNESLineSearchGetParams() 23852b4ed282SShri Abhyankar 23862b4ed282SShri Abhyankar M*/ 23872b4ed282SShri Abhyankar EXTERN_C_BEGIN 23882b4ed282SShri Abhyankar #undef __FUNCT__ 23892b4ed282SShri Abhyankar #define __FUNCT__ "SNESCreate_VI" 23907087cfbeSBarry Smith PetscErrorCode SNESCreate_VI(SNES snes) 23912b4ed282SShri Abhyankar { 23922b4ed282SShri Abhyankar PetscErrorCode ierr; 23932b4ed282SShri Abhyankar SNES_VI *vi; 23942b4ed282SShri Abhyankar 23952b4ed282SShri Abhyankar PetscFunctionBegin; 23962b4ed282SShri Abhyankar snes->ops->setup = SNESSetUp_VI; 2397edafb9efSBarry Smith snes->ops->solve = SNESSolveVI_RS; 23982b4ed282SShri Abhyankar snes->ops->destroy = SNESDestroy_VI; 23992b4ed282SShri Abhyankar snes->ops->setfromoptions = SNESSetFromOptions_VI; 24002b4ed282SShri Abhyankar snes->ops->view = SNESView_VI; 240137596af1SLisandro Dalcin snes->ops->reset = 0; /* XXX Implement!!! */ 24022b4ed282SShri Abhyankar snes->ops->converged = SNESDefaultConverged_VI; 24032b4ed282SShri Abhyankar 24042b4ed282SShri Abhyankar ierr = PetscNewLog(snes,SNES_VI,&vi);CHKERRQ(ierr); 24052b4ed282SShri Abhyankar snes->data = (void*)vi; 24062b4ed282SShri Abhyankar vi->alpha = 1.e-4; 24072b4ed282SShri Abhyankar vi->maxstep = 1.e8; 24082b4ed282SShri Abhyankar vi->minlambda = 1.e-12; 24097fe79bc4SShri Abhyankar vi->LineSearch = SNESLineSearchNo_VI; 24102b4ed282SShri Abhyankar vi->lsP = PETSC_NULL; 24112b4ed282SShri Abhyankar vi->postcheckstep = PETSC_NULL; 24122b4ed282SShri Abhyankar vi->postcheck = PETSC_NULL; 24132b4ed282SShri Abhyankar vi->precheckstep = PETSC_NULL; 24142b4ed282SShri Abhyankar vi->precheck = PETSC_NULL; 24152b4ed282SShri Abhyankar vi->const_tol = 2.2204460492503131e-16; 24162f63a38cSShri Abhyankar vi->checkredundancy = PETSC_NULL; 24172b4ed282SShri Abhyankar 24182b4ed282SShri Abhyankar ierr = PetscObjectComposeFunctionDynamic((PetscObject)snes,"SNESLineSearchSetMonitor_C","SNESLineSearchSetMonitor_VI",SNESLineSearchSetMonitor_VI);CHKERRQ(ierr); 24192b4ed282SShri Abhyankar ierr = PetscObjectComposeFunctionDynamic((PetscObject)snes,"SNESLineSearchSet_C","SNESLineSearchSet_VI",SNESLineSearchSet_VI);CHKERRQ(ierr); 24202b4ed282SShri Abhyankar 24212b4ed282SShri Abhyankar PetscFunctionReturn(0); 24222b4ed282SShri Abhyankar } 24232b4ed282SShri Abhyankar EXTERN_C_END 2424