12b4ed282SShri Abhyankar 2c6db04a5SJed Brown #include <../src/snes/impls/vi/viimpl.h> /*I "petscsnes.h" I*/ 3c6db04a5SJed Brown #include <../include/private/kspimpl.h> 4c6db04a5SJed Brown #include <../include/private/matimpl.h> 5d0af7cd3SBarry Smith #include <../include/private/dmimpl.h> 6d0af7cd3SBarry Smith 7d0af7cd3SBarry Smith #undef __FUNCT__ 82176524cSBarry Smith #define __FUNCT__ "SNESVISetComputeVariableBounds" 92176524cSBarry Smith /*@C 102176524cSBarry Smith SNESVISetComputeVariableBounds - Sets a function that is called to compute the variable bounds 112176524cSBarry Smith 122176524cSBarry Smith Input parameter 132176524cSBarry Smith + snes - the SNES context 142176524cSBarry Smith - compute - computes the bounds 152176524cSBarry Smith 162176524cSBarry Smith 17aab9d709SJed Brown @*/ 1877cdaf69SJed Brown PetscErrorCode SNESVISetComputeVariableBounds(SNES snes, PetscErrorCode (*compute)(SNES,Vec,Vec)) 192176524cSBarry Smith { 202176524cSBarry Smith PetscErrorCode ierr; 212176524cSBarry Smith SNES_VI *vi; 222176524cSBarry Smith 232176524cSBarry Smith PetscFunctionBegin; 242176524cSBarry Smith ierr = SNESSetType(snes,SNESVI);CHKERRQ(ierr); 252176524cSBarry Smith vi = (SNES_VI*)snes->data; 262176524cSBarry Smith vi->computevariablebounds = compute; 272176524cSBarry Smith PetscFunctionReturn(0); 282176524cSBarry Smith } 292176524cSBarry Smith 302176524cSBarry Smith 312176524cSBarry Smith #undef __FUNCT__ 32d0af7cd3SBarry Smith #define __FUNCT__ "SNESVIGetInActiveSetIS" 33d0af7cd3SBarry Smith /* 34d0af7cd3SBarry Smith SNESVIGetInActiveSetIS - Gets the global indices for the bogus inactive set variables 35d0af7cd3SBarry Smith 36d0af7cd3SBarry Smith Input parameter 37d0af7cd3SBarry Smith . snes - the SNES context 38d0af7cd3SBarry Smith . X - the snes solution vector 39d0af7cd3SBarry Smith 40d0af7cd3SBarry Smith Output parameter 41d0af7cd3SBarry Smith . ISact - active set index set 42d0af7cd3SBarry Smith 43d0af7cd3SBarry Smith */ 44d0af7cd3SBarry Smith PetscErrorCode SNESVIGetInActiveSetIS(Vec upper,Vec lower,Vec X,Vec F,IS* inact) 45d0af7cd3SBarry Smith { 46d0af7cd3SBarry Smith PetscErrorCode ierr; 47d0af7cd3SBarry Smith const PetscScalar *x,*xl,*xu,*f; 48d0af7cd3SBarry Smith PetscInt *idx_act,i,nlocal,nloc_isact=0,ilow,ihigh,i1=0; 49d0af7cd3SBarry Smith 50d0af7cd3SBarry Smith PetscFunctionBegin; 51d0af7cd3SBarry Smith ierr = VecGetLocalSize(X,&nlocal);CHKERRQ(ierr); 52d0af7cd3SBarry Smith ierr = VecGetOwnershipRange(X,&ilow,&ihigh);CHKERRQ(ierr); 53d0af7cd3SBarry Smith ierr = VecGetArrayRead(X,&x);CHKERRQ(ierr); 54d0af7cd3SBarry Smith ierr = VecGetArrayRead(lower,&xl);CHKERRQ(ierr); 55d0af7cd3SBarry Smith ierr = VecGetArrayRead(upper,&xu);CHKERRQ(ierr); 56d0af7cd3SBarry Smith ierr = VecGetArrayRead(F,&f);CHKERRQ(ierr); 57d0af7cd3SBarry Smith /* Compute inactive set size */ 58d0af7cd3SBarry Smith for (i=0; i < nlocal;i++) { 59d0af7cd3SBarry Smith if (((PetscRealPart(x[i]) > PetscRealPart(xl[i]) + 1.e-8 || (PetscRealPart(f[i]) < 0.0)) && ((PetscRealPart(x[i]) < PetscRealPart(xu[i]) - 1.e-8) || PetscRealPart(f[i]) > 0.0))) nloc_isact++; 60d0af7cd3SBarry Smith } 61d0af7cd3SBarry Smith 62d0af7cd3SBarry Smith ierr = PetscMalloc(nloc_isact*sizeof(PetscInt),&idx_act);CHKERRQ(ierr); 63d0af7cd3SBarry Smith 64d0af7cd3SBarry Smith /* Set inactive set indices */ 65d0af7cd3SBarry Smith for(i=0; i < nlocal; i++) { 66d0af7cd3SBarry Smith if (((PetscRealPart(x[i]) > PetscRealPart(xl[i]) + 1.e-8 || (PetscRealPart(f[i]) < 0.0)) && ((PetscRealPart(x[i]) < PetscRealPart(xu[i]) - 1.e-8) || PetscRealPart(f[i]) > 0.0))) idx_act[i1++] = ilow+i; 67d0af7cd3SBarry Smith } 68d0af7cd3SBarry Smith 69d0af7cd3SBarry Smith /* Create inactive set IS */ 70d0af7cd3SBarry Smith ierr = ISCreateGeneral(((PetscObject)upper)->comm,nloc_isact,idx_act,PETSC_OWN_POINTER,inact);CHKERRQ(ierr); 71d0af7cd3SBarry Smith 72d0af7cd3SBarry Smith ierr = VecRestoreArrayRead(X,&x);CHKERRQ(ierr); 73d0af7cd3SBarry Smith ierr = VecRestoreArrayRead(lower,&xl);CHKERRQ(ierr); 74d0af7cd3SBarry Smith ierr = VecRestoreArrayRead(upper,&xu);CHKERRQ(ierr); 75d0af7cd3SBarry Smith ierr = VecRestoreArrayRead(F,&f);CHKERRQ(ierr); 76d0af7cd3SBarry Smith PetscFunctionReturn(0); 77d0af7cd3SBarry Smith } 78d0af7cd3SBarry Smith 793c0c59f3SBarry Smith /* 803c0c59f3SBarry Smith Provides a wrapper to a DM to allow it to be used to generated the interpolation/restriction from the DM for the smaller matrices and vectors 813c0c59f3SBarry Smith defined by the reduced space method. 823c0c59f3SBarry Smith 833c0c59f3SBarry Smith Simple calls the regular DM interpolation and restricts it to operation on the variables not associated with active constraints. 843c0c59f3SBarry Smith 853c0c59f3SBarry Smith */ 863c0c59f3SBarry Smith typedef struct { 873c0c59f3SBarry Smith PetscInt n; /* size of vectors in the reduced DM space */ 883c0c59f3SBarry Smith IS inactive; 893c0c59f3SBarry Smith Vec upper,lower,values,F; /* upper and lower bounds of all variables on this level, the values and the function values */ 903c0c59f3SBarry Smith PetscErrorCode (*getinterpolation)(DM,DM,Mat*,Vec*); /* DM's original routines */ 913c0c59f3SBarry Smith PetscErrorCode (*coarsen)(DM, MPI_Comm, DM*); 923c0c59f3SBarry Smith PetscErrorCode (*createglobalvector)(DM,Vec*); 934c661befSBarry Smith DM dm; /* when destroying this object we need to reset the above function into the base DM */ 943c0c59f3SBarry Smith } DM_SNESVI; 953c0c59f3SBarry Smith 96d0af7cd3SBarry Smith #undef __FUNCT__ 974dcab191SBarry Smith #define __FUNCT__ "DMCreateGlobalVector_SNESVI" 984dcab191SBarry Smith /* 994dcab191SBarry Smith DMCreateGlobalVector_SNESVI - Creates global vector of the size of the reduced space 1004dcab191SBarry Smith 1014dcab191SBarry Smith */ 1024dcab191SBarry Smith PetscErrorCode DMCreateGlobalVector_SNESVI(DM dm,Vec *vec) 1034dcab191SBarry Smith { 1044dcab191SBarry Smith PetscErrorCode ierr; 1054dcab191SBarry Smith PetscContainer isnes; 1063c0c59f3SBarry Smith DM_SNESVI *dmsnesvi; 1074dcab191SBarry Smith 1084dcab191SBarry Smith PetscFunctionBegin; 1094dcab191SBarry Smith ierr = PetscObjectQuery((PetscObject)dm,"VI",(PetscObject *)&isnes);CHKERRQ(ierr); 1104dcab191SBarry Smith if (!isnes) SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_PLIB,"Composed SNES is missing"); 1114dcab191SBarry Smith ierr = PetscContainerGetPointer(isnes,(void**)&dmsnesvi);CHKERRQ(ierr); 1124dcab191SBarry Smith ierr = VecCreateMPI(((PetscObject)dm)->comm,dmsnesvi->n,PETSC_DETERMINE,vec);CHKERRQ(ierr); 1134dcab191SBarry Smith PetscFunctionReturn(0); 1144dcab191SBarry Smith } 1154dcab191SBarry Smith 1164dcab191SBarry Smith #undef __FUNCT__ 117d0af7cd3SBarry Smith #define __FUNCT__ "DMGetInterpolation_SNESVI" 118d0af7cd3SBarry Smith /* 119d0af7cd3SBarry Smith DMGetInterpolation_SNESVI - Modifieds the interpolation obtained from the DM by removing all rows and columns associated with active constraints. 120d0af7cd3SBarry Smith 121d0af7cd3SBarry Smith */ 122d0af7cd3SBarry Smith PetscErrorCode DMGetInterpolation_SNESVI(DM dm1,DM dm2,Mat *mat,Vec *vec) 123d0af7cd3SBarry Smith { 124d0af7cd3SBarry Smith PetscErrorCode ierr; 125d0af7cd3SBarry Smith PetscContainer isnes; 1263c0c59f3SBarry Smith DM_SNESVI *dmsnesvi1,*dmsnesvi2; 127d0af7cd3SBarry Smith Mat interp; 128d0af7cd3SBarry Smith 129d0af7cd3SBarry Smith PetscFunctionBegin; 130d0af7cd3SBarry Smith ierr = PetscObjectQuery((PetscObject)dm1,"VI",(PetscObject *)&isnes);CHKERRQ(ierr); 1314c661befSBarry Smith if (!isnes) SETERRQ(((PetscObject)dm1)->comm,PETSC_ERR_PLIB,"Composed VI data structure is missing"); 132d0af7cd3SBarry Smith ierr = PetscContainerGetPointer(isnes,(void**)&dmsnesvi1);CHKERRQ(ierr); 133d0af7cd3SBarry Smith ierr = PetscObjectQuery((PetscObject)dm2,"VI",(PetscObject *)&isnes);CHKERRQ(ierr); 1344c661befSBarry Smith if (!isnes) SETERRQ(((PetscObject)dm2)->comm,PETSC_ERR_PLIB,"Composed VI data structure is missing"); 135d0af7cd3SBarry Smith ierr = PetscContainerGetPointer(isnes,(void**)&dmsnesvi2);CHKERRQ(ierr); 136d0af7cd3SBarry Smith 137d0af7cd3SBarry Smith ierr = (*dmsnesvi1->getinterpolation)(dm1,dm2,&interp,PETSC_NULL);CHKERRQ(ierr); 1384dcab191SBarry Smith ierr = MatGetSubMatrix(interp,dmsnesvi2->inactive,dmsnesvi1->inactive,MAT_INITIAL_MATRIX,mat);CHKERRQ(ierr); 139d0af7cd3SBarry Smith ierr = MatDestroy(&interp);CHKERRQ(ierr); 14000ac8be1SBarry Smith *vec = 0; 141d0af7cd3SBarry Smith PetscFunctionReturn(0); 142d0af7cd3SBarry Smith } 143d0af7cd3SBarry Smith 144d0af7cd3SBarry Smith extern PetscErrorCode DMSetVI(DM,Vec,Vec,Vec,Vec,IS); 145d0af7cd3SBarry Smith 146d0af7cd3SBarry Smith #undef __FUNCT__ 147d0af7cd3SBarry Smith #define __FUNCT__ "DMCoarsen_SNESVI" 148d0af7cd3SBarry Smith /* 149d0af7cd3SBarry Smith DMCoarsen_SNESVI - Computes the regular coarsened DM then computes additional information about its inactive set 150d0af7cd3SBarry Smith 151d0af7cd3SBarry Smith */ 152d0af7cd3SBarry Smith PetscErrorCode DMCoarsen_SNESVI(DM dm1,MPI_Comm comm,DM *dm2) 153d0af7cd3SBarry Smith { 154d0af7cd3SBarry Smith PetscErrorCode ierr; 155d0af7cd3SBarry Smith PetscContainer isnes; 1563c0c59f3SBarry Smith DM_SNESVI *dmsnesvi1; 157d0af7cd3SBarry Smith Vec upper,lower,values,F; 158d0af7cd3SBarry Smith IS inactive; 159d0af7cd3SBarry Smith VecScatter inject; 160d0af7cd3SBarry Smith 161d0af7cd3SBarry Smith PetscFunctionBegin; 162d0af7cd3SBarry Smith ierr = PetscObjectQuery((PetscObject)dm1,"VI",(PetscObject *)&isnes);CHKERRQ(ierr); 1634c661befSBarry Smith if (!isnes) SETERRQ(((PetscObject)dm1)->comm,PETSC_ERR_PLIB,"Composed VI data structure is missing"); 164d0af7cd3SBarry Smith ierr = PetscContainerGetPointer(isnes,(void**)&dmsnesvi1);CHKERRQ(ierr); 165d0af7cd3SBarry Smith 166298cc208SBarry Smith /* get the original coarsen */ 167d0af7cd3SBarry Smith ierr = (*dmsnesvi1->coarsen)(dm1,comm,dm2);CHKERRQ(ierr); 168298cc208SBarry Smith 1693c0c59f3SBarry Smith /* not sure why this extra reference is needed, but without the dm2 disappears too early */ 1703c0c59f3SBarry Smith ierr = PetscObjectReference((PetscObject)*dm2);CHKERRQ(ierr); 1713c0c59f3SBarry Smith 172298cc208SBarry Smith /* need to set back global vectors in order to use the original injection */ 173298cc208SBarry Smith ierr = DMClearGlobalVectors(dm1);CHKERRQ(ierr); 174298cc208SBarry Smith dm1->ops->createglobalvector = dmsnesvi1->createglobalvector; 175d0af7cd3SBarry Smith ierr = DMGetInjection(*dm2,dm1,&inject);CHKERRQ(ierr); 176d0af7cd3SBarry Smith ierr = DMCreateGlobalVector(*dm2,&upper);CHKERRQ(ierr); 177d0af7cd3SBarry Smith ierr = VecScatterBegin(inject,dmsnesvi1->upper,upper,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 178d0af7cd3SBarry Smith ierr = VecScatterEnd(inject,dmsnesvi1->upper,upper,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 179d0af7cd3SBarry Smith ierr = DMCreateGlobalVector(*dm2,&lower);CHKERRQ(ierr); 180d0af7cd3SBarry Smith ierr = VecScatterBegin(inject,dmsnesvi1->lower,lower,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 181d0af7cd3SBarry Smith ierr = VecScatterEnd(inject,dmsnesvi1->lower,lower,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 182d0af7cd3SBarry Smith ierr = DMCreateGlobalVector(*dm2,&values);CHKERRQ(ierr); 183d0af7cd3SBarry Smith ierr = VecScatterBegin(inject,dmsnesvi1->values,values,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 184d0af7cd3SBarry Smith ierr = VecScatterEnd(inject,dmsnesvi1->values,values,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 185d0af7cd3SBarry Smith ierr = DMCreateGlobalVector(*dm2,&F);CHKERRQ(ierr); 186d0af7cd3SBarry Smith ierr = VecScatterBegin(inject,dmsnesvi1->F,F,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 187d0af7cd3SBarry Smith ierr = VecScatterEnd(inject,dmsnesvi1->F,F,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 188d0af7cd3SBarry Smith ierr = VecScatterDestroy(&inject);CHKERRQ(ierr); 189298cc208SBarry Smith ierr = DMClearGlobalVectors(dm1);CHKERRQ(ierr); 190298cc208SBarry Smith dm1->ops->createglobalvector = DMCreateGlobalVector_SNESVI; 191d0af7cd3SBarry Smith ierr = SNESVIGetInActiveSetIS(upper,lower,values,F,&inactive);CHKERRQ(ierr); 192d0af7cd3SBarry Smith ierr = DMSetVI(*dm2,upper,lower,values,F,inactive);CHKERRQ(ierr); 1933c0c59f3SBarry Smith ierr = VecDestroy(&upper);CHKERRQ(ierr); 1943c0c59f3SBarry Smith ierr = VecDestroy(&lower);CHKERRQ(ierr); 1953c0c59f3SBarry Smith ierr = VecDestroy(&values);CHKERRQ(ierr); 1963c0c59f3SBarry Smith ierr = VecDestroy(&F);CHKERRQ(ierr); 1973c0c59f3SBarry Smith ierr = ISDestroy(&inactive);CHKERRQ(ierr); 198d0af7cd3SBarry Smith PetscFunctionReturn(0); 199d0af7cd3SBarry Smith } 200d0af7cd3SBarry Smith 201d0af7cd3SBarry Smith #undef __FUNCT__ 2023c0c59f3SBarry Smith #define __FUNCT__ "DMDestroy_SNESVI" 2033c0c59f3SBarry Smith PetscErrorCode DMDestroy_SNESVI(DM_SNESVI *dmsnesvi) 204d0af7cd3SBarry Smith { 205d0af7cd3SBarry Smith PetscErrorCode ierr; 206d0af7cd3SBarry Smith 207d0af7cd3SBarry Smith PetscFunctionBegin; 2084c661befSBarry Smith /* reset the base methods in the DM object that were changed when the DM_SNESVI was reset */ 2094c661befSBarry Smith dmsnesvi->dm->ops->getinterpolation = dmsnesvi->getinterpolation; 2104c661befSBarry Smith dmsnesvi->dm->ops->coarsen = dmsnesvi->coarsen; 2114c661befSBarry Smith dmsnesvi->dm->ops->createglobalvector = dmsnesvi->createglobalvector; 21200ac8be1SBarry Smith /* need to clear out this vectors because some of them may not have a reference to the DM 21300ac8be1SBarry Smith but they are counted as having references to the DM in DMDestroy() */ 21400ac8be1SBarry Smith ierr = DMClearGlobalVectors(dmsnesvi->dm);CHKERRQ(ierr); 2154c661befSBarry Smith 216d0af7cd3SBarry Smith ierr = VecDestroy(&dmsnesvi->upper);CHKERRQ(ierr); 217d0af7cd3SBarry Smith ierr = VecDestroy(&dmsnesvi->lower);CHKERRQ(ierr); 218d0af7cd3SBarry Smith ierr = VecDestroy(&dmsnesvi->values);CHKERRQ(ierr); 219d0af7cd3SBarry Smith ierr = VecDestroy(&dmsnesvi->F);CHKERRQ(ierr); 220d0af7cd3SBarry Smith ierr = ISDestroy(&dmsnesvi->inactive);CHKERRQ(ierr); 221d0af7cd3SBarry Smith ierr = PetscFree(dmsnesvi);CHKERRQ(ierr); 222d0af7cd3SBarry Smith PetscFunctionReturn(0); 223d0af7cd3SBarry Smith } 224d0af7cd3SBarry Smith 225d0af7cd3SBarry Smith #undef __FUNCT__ 226d0af7cd3SBarry Smith #define __FUNCT__ "DMSetVI" 227d0af7cd3SBarry Smith /* 228d0af7cd3SBarry Smith DMSetVI - Marks a DM as associated with a VI problem. This causes the interpolation/restriction operators to 229d0af7cd3SBarry Smith be restricted to only those variables NOT associated with active constraints. 230d0af7cd3SBarry Smith 231d0af7cd3SBarry Smith */ 232d0af7cd3SBarry Smith PetscErrorCode DMSetVI(DM dm,Vec upper,Vec lower,Vec values,Vec F,IS inactive) 233d0af7cd3SBarry Smith { 234d0af7cd3SBarry Smith PetscErrorCode ierr; 235d0af7cd3SBarry Smith PetscContainer isnes; 2363c0c59f3SBarry Smith DM_SNESVI *dmsnesvi; 237d0af7cd3SBarry Smith 238d0af7cd3SBarry Smith PetscFunctionBegin; 2394dcab191SBarry Smith if (!dm) PetscFunctionReturn(0); 2401c0a9e84SBarry Smith 241d0af7cd3SBarry Smith ierr = PetscObjectReference((PetscObject)upper);CHKERRQ(ierr); 242d0af7cd3SBarry Smith ierr = PetscObjectReference((PetscObject)lower);CHKERRQ(ierr); 243d0af7cd3SBarry Smith ierr = PetscObjectReference((PetscObject)values);CHKERRQ(ierr); 244d0af7cd3SBarry Smith ierr = PetscObjectReference((PetscObject)F);CHKERRQ(ierr); 245d0af7cd3SBarry Smith ierr = PetscObjectReference((PetscObject)inactive);CHKERRQ(ierr); 246d0af7cd3SBarry Smith 247d0af7cd3SBarry Smith ierr = PetscObjectQuery((PetscObject)dm,"VI",(PetscObject *)&isnes);CHKERRQ(ierr); 248d0af7cd3SBarry Smith if (!isnes) { 249d0af7cd3SBarry Smith ierr = PetscContainerCreate(((PetscObject)dm)->comm,&isnes);CHKERRQ(ierr); 2503c0c59f3SBarry Smith ierr = PetscContainerSetUserDestroy(isnes,(PetscErrorCode (*)(void*))DMDestroy_SNESVI);CHKERRQ(ierr); 2513c0c59f3SBarry Smith ierr = PetscNew(DM_SNESVI,&dmsnesvi);CHKERRQ(ierr); 252d0af7cd3SBarry Smith ierr = PetscContainerSetPointer(isnes,(void*)dmsnesvi);CHKERRQ(ierr); 253d0af7cd3SBarry Smith ierr = PetscObjectCompose((PetscObject)dm,"VI",(PetscObject)isnes);CHKERRQ(ierr); 2543c0c59f3SBarry Smith ierr = PetscContainerDestroy(&isnes);CHKERRQ(ierr); 255d0af7cd3SBarry Smith dmsnesvi->getinterpolation = dm->ops->getinterpolation; 256d0af7cd3SBarry Smith dm->ops->getinterpolation = DMGetInterpolation_SNESVI; 257d0af7cd3SBarry Smith dmsnesvi->coarsen = dm->ops->coarsen; 258d0af7cd3SBarry Smith dm->ops->coarsen = DMCoarsen_SNESVI; 259298cc208SBarry Smith dmsnesvi->createglobalvector = dm->ops->createglobalvector; 2604dcab191SBarry Smith dm->ops->createglobalvector = DMCreateGlobalVector_SNESVI; 2616ba4bc90SBarry Smith /* since these vectors may reference the DM, need to remove circle referencing */ 2626ba4bc90SBarry Smith ierr = PetscObjectRemoveReference((PetscObject)upper,"DM");CHKERRQ(ierr); 2636ba4bc90SBarry Smith ierr = PetscObjectRemoveReference((PetscObject)lower,"DM");CHKERRQ(ierr); 2646ba4bc90SBarry Smith ierr = PetscObjectRemoveReference((PetscObject)values,"DM");CHKERRQ(ierr); 2656ba4bc90SBarry Smith ierr = PetscObjectRemoveReference((PetscObject)F,"DM");CHKERRQ(ierr); 266d0af7cd3SBarry Smith } else { 267d0af7cd3SBarry Smith ierr = PetscContainerGetPointer(isnes,(void**)&dmsnesvi);CHKERRQ(ierr); 268d0af7cd3SBarry Smith ierr = VecDestroy(&dmsnesvi->upper);CHKERRQ(ierr); 269d0af7cd3SBarry Smith ierr = VecDestroy(&dmsnesvi->lower);CHKERRQ(ierr); 270d0af7cd3SBarry Smith ierr = VecDestroy(&dmsnesvi->values);CHKERRQ(ierr); 271d0af7cd3SBarry Smith ierr = VecDestroy(&dmsnesvi->F);CHKERRQ(ierr); 272d0af7cd3SBarry Smith ierr = ISDestroy(&dmsnesvi->inactive);CHKERRQ(ierr); 273d0af7cd3SBarry Smith } 2744dcab191SBarry Smith ierr = DMClearGlobalVectors(dm);CHKERRQ(ierr); 2754dcab191SBarry Smith ierr = ISGetLocalSize(inactive,&dmsnesvi->n);CHKERRQ(ierr); 276d0af7cd3SBarry Smith dmsnesvi->upper = upper; 277d0af7cd3SBarry Smith dmsnesvi->lower = lower; 278d0af7cd3SBarry Smith dmsnesvi->values = values; 279d0af7cd3SBarry Smith dmsnesvi->F = F; 280d0af7cd3SBarry Smith dmsnesvi->inactive = inactive; 2811a223a97SBarry Smith dmsnesvi->dm = dm; 282d0af7cd3SBarry Smith PetscFunctionReturn(0); 283d0af7cd3SBarry Smith } 284d0af7cd3SBarry Smith 2854c661befSBarry Smith #undef __FUNCT__ 2864c661befSBarry Smith #define __FUNCT__ "DMDestroyVI" 2874c661befSBarry Smith /* 2884c661befSBarry Smith DMDestroyVI - Frees the DM_SNESVI object contained in the DM 2894c661befSBarry Smith - also resets the function pointers in the DM for getinterpolation() etc to use the original DM 2904c661befSBarry Smith */ 2914c661befSBarry Smith PetscErrorCode DMDestroyVI(DM dm) 2924c661befSBarry Smith { 2934c661befSBarry Smith PetscErrorCode ierr; 2944c661befSBarry Smith 2954c661befSBarry Smith PetscFunctionBegin; 2964c661befSBarry Smith if (!dm) PetscFunctionReturn(0); 2974c661befSBarry Smith ierr = PetscObjectCompose((PetscObject)dm,"VI",(PetscObject)PETSC_NULL);CHKERRQ(ierr); 2984c661befSBarry Smith PetscFunctionReturn(0); 2994c661befSBarry Smith } 3004c661befSBarry Smith 3013c0c59f3SBarry Smith /* --------------------------------------------------------------------------------------------------------*/ 3022b4ed282SShri Abhyankar 3039308c137SBarry Smith #undef __FUNCT__ 3049308c137SBarry Smith #define __FUNCT__ "SNESMonitorVI" 3057087cfbeSBarry Smith PetscErrorCode SNESMonitorVI(SNES snes,PetscInt its,PetscReal fgnorm,void *dummy) 3069308c137SBarry Smith { 3079308c137SBarry Smith PetscErrorCode ierr; 3089308c137SBarry Smith SNES_VI *vi = (SNES_VI*)snes->data; 309649052a6SBarry Smith PetscViewer viewer = dummy ? (PetscViewer) dummy : PETSC_VIEWER_STDOUT_(((PetscObject)snes)->comm); 3109308c137SBarry Smith const PetscScalar *x,*xl,*xu,*f; 31109573ac7SBarry Smith PetscInt i,n,act = 0; 3129308c137SBarry Smith PetscReal rnorm,fnorm; 3139308c137SBarry Smith 3149308c137SBarry Smith PetscFunctionBegin; 3159308c137SBarry Smith ierr = VecGetLocalSize(snes->vec_sol,&n);CHKERRQ(ierr); 3169308c137SBarry Smith ierr = VecGetArrayRead(vi->xl,&xl);CHKERRQ(ierr); 3179308c137SBarry Smith ierr = VecGetArrayRead(vi->xu,&xu);CHKERRQ(ierr); 3189308c137SBarry Smith ierr = VecGetArrayRead(snes->vec_sol,&x);CHKERRQ(ierr); 3193f731af5SBarry Smith ierr = VecGetArrayRead(snes->vec_func,&f);CHKERRQ(ierr); 3209308c137SBarry Smith 3219308c137SBarry Smith rnorm = 0.0; 3229308c137SBarry Smith for (i=0; i<n; i++) { 32310f5ae6bSBarry 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]); 32409573ac7SBarry Smith else act++; 3259308c137SBarry Smith } 3263f731af5SBarry Smith ierr = VecRestoreArrayRead(snes->vec_func,&f);CHKERRQ(ierr); 3279308c137SBarry Smith ierr = VecRestoreArrayRead(vi->xl,&xl);CHKERRQ(ierr); 3289308c137SBarry Smith ierr = VecRestoreArrayRead(vi->xu,&xu);CHKERRQ(ierr); 3299308c137SBarry Smith ierr = VecRestoreArrayRead(snes->vec_sol,&x);CHKERRQ(ierr); 330d9822059SBarry Smith ierr = MPI_Allreduce(&rnorm,&fnorm,1,MPIU_REAL,MPIU_SUM,((PetscObject)snes)->comm);CHKERRQ(ierr); 3319308c137SBarry Smith fnorm = sqrt(fnorm); 332649052a6SBarry Smith ierr = PetscViewerASCIIAddTab(viewer,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 333649052a6SBarry Smith ierr = PetscViewerASCIIPrintf(viewer,"%3D SNES VI Function norm %14.12e Active constraints %D\n",its,fnorm,act);CHKERRQ(ierr); 334649052a6SBarry Smith ierr = PetscViewerASCIISubtractTab(viewer,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 3359308c137SBarry Smith PetscFunctionReturn(0); 3369308c137SBarry Smith } 3379308c137SBarry Smith 3382b4ed282SShri Abhyankar /* 3392b4ed282SShri Abhyankar Checks if J^T F = 0 which implies we've found a local minimum of the norm of the function, 3402b4ed282SShri 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 3412b4ed282SShri Abhyankar 0 = (J^T F)^T W = F^T J W iff W not in the null space of J. Thanks for Jorge More 3422b4ed282SShri Abhyankar for this trick. One assumes that the probability that W is in the null space of J is very, very small. 3432b4ed282SShri Abhyankar */ 3442b4ed282SShri Abhyankar #undef __FUNCT__ 3452b4ed282SShri Abhyankar #define __FUNCT__ "SNESVICheckLocalMin_Private" 346ace3abfcSBarry Smith PetscErrorCode SNESVICheckLocalMin_Private(SNES snes,Mat A,Vec F,Vec W,PetscReal fnorm,PetscBool *ismin) 3472b4ed282SShri Abhyankar { 3482b4ed282SShri Abhyankar PetscReal a1; 3492b4ed282SShri Abhyankar PetscErrorCode ierr; 350ace3abfcSBarry Smith PetscBool hastranspose; 3512b4ed282SShri Abhyankar 3522b4ed282SShri Abhyankar PetscFunctionBegin; 3532b4ed282SShri Abhyankar *ismin = PETSC_FALSE; 3542b4ed282SShri Abhyankar ierr = MatHasOperation(A,MATOP_MULT_TRANSPOSE,&hastranspose);CHKERRQ(ierr); 3552b4ed282SShri Abhyankar if (hastranspose) { 3562b4ed282SShri Abhyankar /* Compute || J^T F|| */ 3572b4ed282SShri Abhyankar ierr = MatMultTranspose(A,F,W);CHKERRQ(ierr); 3582b4ed282SShri Abhyankar ierr = VecNorm(W,NORM_2,&a1);CHKERRQ(ierr); 3592b4ed282SShri Abhyankar ierr = PetscInfo1(snes,"|| J^T F|| %G near zero implies found a local minimum\n",a1/fnorm);CHKERRQ(ierr); 3602b4ed282SShri Abhyankar if (a1/fnorm < 1.e-4) *ismin = PETSC_TRUE; 3612b4ed282SShri Abhyankar } else { 3622b4ed282SShri Abhyankar Vec work; 3632b4ed282SShri Abhyankar PetscScalar result; 3642b4ed282SShri Abhyankar PetscReal wnorm; 3652b4ed282SShri Abhyankar 3662b4ed282SShri Abhyankar ierr = VecSetRandom(W,PETSC_NULL);CHKERRQ(ierr); 3672b4ed282SShri Abhyankar ierr = VecNorm(W,NORM_2,&wnorm);CHKERRQ(ierr); 3682b4ed282SShri Abhyankar ierr = VecDuplicate(W,&work);CHKERRQ(ierr); 3692b4ed282SShri Abhyankar ierr = MatMult(A,W,work);CHKERRQ(ierr); 3702b4ed282SShri Abhyankar ierr = VecDot(F,work,&result);CHKERRQ(ierr); 3716bf464f9SBarry Smith ierr = VecDestroy(&work);CHKERRQ(ierr); 3722b4ed282SShri Abhyankar a1 = PetscAbsScalar(result)/(fnorm*wnorm); 3732b4ed282SShri Abhyankar ierr = PetscInfo1(snes,"(F^T J random)/(|| F ||*||random|| %G near zero implies found a local minimum\n",a1);CHKERRQ(ierr); 3742b4ed282SShri Abhyankar if (a1 < 1.e-4) *ismin = PETSC_TRUE; 3752b4ed282SShri Abhyankar } 3762b4ed282SShri Abhyankar PetscFunctionReturn(0); 3772b4ed282SShri Abhyankar } 3782b4ed282SShri Abhyankar 3792b4ed282SShri Abhyankar /* 3802b4ed282SShri Abhyankar Checks if J^T(F - J*X) = 0 3812b4ed282SShri Abhyankar */ 3822b4ed282SShri Abhyankar #undef __FUNCT__ 3832b4ed282SShri Abhyankar #define __FUNCT__ "SNESVICheckResidual_Private" 3842b4ed282SShri Abhyankar PetscErrorCode SNESVICheckResidual_Private(SNES snes,Mat A,Vec F,Vec X,Vec W1,Vec W2) 3852b4ed282SShri Abhyankar { 3862b4ed282SShri Abhyankar PetscReal a1,a2; 3872b4ed282SShri Abhyankar PetscErrorCode ierr; 388ace3abfcSBarry Smith PetscBool hastranspose; 3892b4ed282SShri Abhyankar 3902b4ed282SShri Abhyankar PetscFunctionBegin; 3912b4ed282SShri Abhyankar ierr = MatHasOperation(A,MATOP_MULT_TRANSPOSE,&hastranspose);CHKERRQ(ierr); 3922b4ed282SShri Abhyankar if (hastranspose) { 3932b4ed282SShri Abhyankar ierr = MatMult(A,X,W1);CHKERRQ(ierr); 3942b4ed282SShri Abhyankar ierr = VecAXPY(W1,-1.0,F);CHKERRQ(ierr); 3952b4ed282SShri Abhyankar 3962b4ed282SShri Abhyankar /* Compute || J^T W|| */ 3972b4ed282SShri Abhyankar ierr = MatMultTranspose(A,W1,W2);CHKERRQ(ierr); 3982b4ed282SShri Abhyankar ierr = VecNorm(W1,NORM_2,&a1);CHKERRQ(ierr); 3992b4ed282SShri Abhyankar ierr = VecNorm(W2,NORM_2,&a2);CHKERRQ(ierr); 4002b4ed282SShri Abhyankar if (a1 != 0.0) { 4012b4ed282SShri Abhyankar ierr = PetscInfo1(snes,"||J^T(F-Ax)||/||F-AX|| %G near zero implies inconsistent rhs\n",a2/a1);CHKERRQ(ierr); 4022b4ed282SShri Abhyankar } 4032b4ed282SShri Abhyankar } 4042b4ed282SShri Abhyankar PetscFunctionReturn(0); 4052b4ed282SShri Abhyankar } 4062b4ed282SShri Abhyankar 4072b4ed282SShri Abhyankar /* 4082b4ed282SShri Abhyankar SNESDefaultConverged_VI - Checks the convergence of the semismooth newton algorithm. 4092b4ed282SShri Abhyankar 4102b4ed282SShri Abhyankar Notes: 4112b4ed282SShri Abhyankar The convergence criterion currently implemented is 4122b4ed282SShri Abhyankar merit < abstol 4132b4ed282SShri Abhyankar merit < rtol*merit_initial 4142b4ed282SShri Abhyankar */ 4152b4ed282SShri Abhyankar #undef __FUNCT__ 4162b4ed282SShri Abhyankar #define __FUNCT__ "SNESDefaultConverged_VI" 4177fe79bc4SShri Abhyankar PetscErrorCode SNESDefaultConverged_VI(SNES snes,PetscInt it,PetscReal xnorm,PetscReal gradnorm,PetscReal fnorm,SNESConvergedReason *reason,void *dummy) 4182b4ed282SShri Abhyankar { 4192b4ed282SShri Abhyankar PetscErrorCode ierr; 4202b4ed282SShri Abhyankar 4212b4ed282SShri Abhyankar PetscFunctionBegin; 4222b4ed282SShri Abhyankar PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 4232b4ed282SShri Abhyankar PetscValidPointer(reason,6); 4242b4ed282SShri Abhyankar 4252b4ed282SShri Abhyankar *reason = SNES_CONVERGED_ITERATING; 4262b4ed282SShri Abhyankar 4272b4ed282SShri Abhyankar if (!it) { 4282b4ed282SShri Abhyankar /* set parameter for default relative tolerance convergence test */ 4297fe79bc4SShri Abhyankar snes->ttol = fnorm*snes->rtol; 4302b4ed282SShri Abhyankar } 4317fe79bc4SShri Abhyankar if (fnorm != fnorm) { 4322b4ed282SShri Abhyankar ierr = PetscInfo(snes,"Failed to converged, function norm is NaN\n");CHKERRQ(ierr); 4332b4ed282SShri Abhyankar *reason = SNES_DIVERGED_FNORM_NAN; 4347fe79bc4SShri Abhyankar } else if (fnorm < snes->abstol) { 4357fe79bc4SShri Abhyankar ierr = PetscInfo2(snes,"Converged due to function norm %G < %G\n",fnorm,snes->abstol);CHKERRQ(ierr); 4362b4ed282SShri Abhyankar *reason = SNES_CONVERGED_FNORM_ABS; 4372b4ed282SShri Abhyankar } else if (snes->nfuncs >= snes->max_funcs) { 4382b4ed282SShri Abhyankar ierr = PetscInfo2(snes,"Exceeded maximum number of function evaluations: %D > %D\n",snes->nfuncs,snes->max_funcs);CHKERRQ(ierr); 4392b4ed282SShri Abhyankar *reason = SNES_DIVERGED_FUNCTION_COUNT; 4402b4ed282SShri Abhyankar } 4412b4ed282SShri Abhyankar 4422b4ed282SShri Abhyankar if (it && !*reason) { 4437fe79bc4SShri Abhyankar if (fnorm < snes->ttol) { 4447fe79bc4SShri Abhyankar ierr = PetscInfo2(snes,"Converged due to function norm %G < %G (relative tolerance)\n",fnorm,snes->ttol);CHKERRQ(ierr); 4452b4ed282SShri Abhyankar *reason = SNES_CONVERGED_FNORM_RELATIVE; 4462b4ed282SShri Abhyankar } 4472b4ed282SShri Abhyankar } 4482b4ed282SShri Abhyankar PetscFunctionReturn(0); 4492b4ed282SShri Abhyankar } 4502b4ed282SShri Abhyankar 4512b4ed282SShri Abhyankar /* 4522b4ed282SShri Abhyankar SNESVIComputeMeritFunction - Evaluates the merit function for the mixed complementarity problem. 4532b4ed282SShri Abhyankar 4542b4ed282SShri Abhyankar Input Parameter: 4552b4ed282SShri Abhyankar . phi - the semismooth function 4562b4ed282SShri Abhyankar 4572b4ed282SShri Abhyankar Output Parameter: 4582b4ed282SShri Abhyankar . merit - the merit function 4592b4ed282SShri Abhyankar . phinorm - ||phi|| 4602b4ed282SShri Abhyankar 4612b4ed282SShri Abhyankar Notes: 4622b4ed282SShri Abhyankar The merit function for the mixed complementarity problem is defined as 4632b4ed282SShri Abhyankar merit = 0.5*phi^T*phi 4642b4ed282SShri Abhyankar */ 4652b4ed282SShri Abhyankar #undef __FUNCT__ 4662b4ed282SShri Abhyankar #define __FUNCT__ "SNESVIComputeMeritFunction" 4672b4ed282SShri Abhyankar static PetscErrorCode SNESVIComputeMeritFunction(Vec phi, PetscReal* merit,PetscReal* phinorm) 4682b4ed282SShri Abhyankar { 4692b4ed282SShri Abhyankar PetscErrorCode ierr; 4702b4ed282SShri Abhyankar 4712b4ed282SShri Abhyankar PetscFunctionBegin; 4725f48b12bSBarry Smith ierr = VecNormBegin(phi,NORM_2,phinorm);CHKERRQ(ierr); 4735f48b12bSBarry Smith ierr = VecNormEnd(phi,NORM_2,phinorm);CHKERRQ(ierr); 4742b4ed282SShri Abhyankar 4752b4ed282SShri Abhyankar *merit = 0.5*(*phinorm)*(*phinorm); 4762b4ed282SShri Abhyankar PetscFunctionReturn(0); 4772b4ed282SShri Abhyankar } 4782b4ed282SShri Abhyankar 4797f6f51e9SSatish Balay PETSC_STATIC_INLINE PetscScalar Phi(PetscScalar a,PetscScalar b) 4804c21c6cdSBarry Smith { 4814c21c6cdSBarry Smith return a + b - sqrt(a*a + b*b); 4824c21c6cdSBarry Smith } 4834c21c6cdSBarry Smith 4847f6f51e9SSatish Balay PETSC_STATIC_INLINE PetscScalar DPhi(PetscScalar a,PetscScalar b) 4854c21c6cdSBarry Smith { 4865559b345SBarry Smith if ((PetscAbsScalar(a) >= 1.e-6) || (PetscAbsScalar(b) >= 1.e-6)) return 1.0 - a/ sqrt(a*a + b*b); 4875559b345SBarry Smith else return .5; 4884c21c6cdSBarry Smith } 4894c21c6cdSBarry Smith 4902b4ed282SShri Abhyankar /* 4911f79c099SShri Abhyankar SNESVIComputeFunction - Reformulates a system of nonlinear equations in mixed complementarity form to a system of nonlinear equations in semismooth form. 4922b4ed282SShri Abhyankar 4932b4ed282SShri Abhyankar Input Parameters: 4942b4ed282SShri Abhyankar . snes - the SNES context 4952b4ed282SShri Abhyankar . x - current iterate 4962b4ed282SShri Abhyankar . functx - user defined function context 4972b4ed282SShri Abhyankar 4982b4ed282SShri Abhyankar Output Parameters: 4992b4ed282SShri Abhyankar . phi - Semismooth function 5002b4ed282SShri Abhyankar 5012b4ed282SShri Abhyankar */ 5022b4ed282SShri Abhyankar #undef __FUNCT__ 5031f79c099SShri Abhyankar #define __FUNCT__ "SNESVIComputeFunction" 5041f79c099SShri Abhyankar static PetscErrorCode SNESVIComputeFunction(SNES snes,Vec X,Vec phi,void* functx) 5052b4ed282SShri Abhyankar { 5062b4ed282SShri Abhyankar PetscErrorCode ierr; 5072b4ed282SShri Abhyankar SNES_VI *vi = (SNES_VI*)snes->data; 5082b4ed282SShri Abhyankar Vec Xl = vi->xl,Xu = vi->xu,F = snes->vec_func; 5094c21c6cdSBarry Smith PetscScalar *phi_arr,*x_arr,*f_arr,*l,*u; 5102b4ed282SShri Abhyankar PetscInt i,nlocal; 5112b4ed282SShri Abhyankar 5122b4ed282SShri Abhyankar PetscFunctionBegin; 5132b4ed282SShri Abhyankar ierr = (*vi->computeuserfunction)(snes,X,F,functx);CHKERRQ(ierr); 5142b4ed282SShri Abhyankar ierr = VecGetLocalSize(X,&nlocal);CHKERRQ(ierr); 5152b4ed282SShri Abhyankar ierr = VecGetArray(X,&x_arr);CHKERRQ(ierr); 5162b4ed282SShri Abhyankar ierr = VecGetArray(F,&f_arr);CHKERRQ(ierr); 5172b4ed282SShri Abhyankar ierr = VecGetArray(Xl,&l);CHKERRQ(ierr); 5182b4ed282SShri Abhyankar ierr = VecGetArray(Xu,&u);CHKERRQ(ierr); 5192b4ed282SShri Abhyankar ierr = VecGetArray(phi,&phi_arr);CHKERRQ(ierr); 5202b4ed282SShri Abhyankar 5212b4ed282SShri Abhyankar for (i=0;i < nlocal;i++) { 52210f5ae6bSBarry Smith if ((PetscRealPart(l[i]) <= SNES_VI_NINF) && (PetscRealPart(u[i]) >= SNES_VI_INF)) { /* no constraints on variable */ 5234c21c6cdSBarry Smith phi_arr[i] = f_arr[i]; 52410f5ae6bSBarry Smith } else if (PetscRealPart(l[i]) <= SNES_VI_NINF) { /* upper bound on variable only */ 5254c21c6cdSBarry Smith phi_arr[i] = -Phi(u[i] - x_arr[i],-f_arr[i]); 52610f5ae6bSBarry Smith } else if (PetscRealPart(u[i]) >= SNES_VI_INF) { /* lower bound on variable only */ 5274c21c6cdSBarry Smith phi_arr[i] = Phi(x_arr[i] - l[i],f_arr[i]); 5285559b345SBarry Smith } else if (l[i] == u[i]) { 5292b4ed282SShri Abhyankar phi_arr[i] = l[i] - x_arr[i]; 5305559b345SBarry Smith } else { /* both bounds on variable */ 5314c21c6cdSBarry Smith phi_arr[i] = Phi(x_arr[i] - l[i],-Phi(u[i] - x_arr[i],-f_arr[i])); 5322b4ed282SShri Abhyankar } 5332b4ed282SShri Abhyankar } 5342b4ed282SShri Abhyankar 5352b4ed282SShri Abhyankar ierr = VecRestoreArray(X,&x_arr);CHKERRQ(ierr); 5362b4ed282SShri Abhyankar ierr = VecRestoreArray(F,&f_arr);CHKERRQ(ierr); 5372b4ed282SShri Abhyankar ierr = VecRestoreArray(Xl,&l);CHKERRQ(ierr); 5382b4ed282SShri Abhyankar ierr = VecRestoreArray(Xu,&u);CHKERRQ(ierr); 5392b4ed282SShri Abhyankar ierr = VecRestoreArray(phi,&phi_arr);CHKERRQ(ierr); 5402b4ed282SShri Abhyankar PetscFunctionReturn(0); 5412b4ed282SShri Abhyankar } 5422b4ed282SShri Abhyankar 5432b4ed282SShri Abhyankar /* 544a79edbefSShri Abhyankar SNESVIComputeBsubdifferentialVectors - Computes the diagonal shift (Da) and row scaling (Db) vectors needed for the 545a79edbefSShri Abhyankar the semismooth jacobian. 5462b4ed282SShri Abhyankar */ 5472b4ed282SShri Abhyankar #undef __FUNCT__ 548a79edbefSShri Abhyankar #define __FUNCT__ "SNESVIComputeBsubdifferentialVectors" 549a79edbefSShri Abhyankar PetscErrorCode SNESVIComputeBsubdifferentialVectors(SNES snes,Vec X,Vec F,Mat jac,Vec Da,Vec Db) 5502b4ed282SShri Abhyankar { 5512b4ed282SShri Abhyankar PetscErrorCode ierr; 5522b4ed282SShri Abhyankar SNES_VI *vi = (SNES_VI*)snes->data; 5534c21c6cdSBarry Smith PetscScalar *l,*u,*x,*f,*da,*db,da1,da2,db1,db2; 5542b4ed282SShri Abhyankar PetscInt i,nlocal; 5552b4ed282SShri Abhyankar 5562b4ed282SShri Abhyankar PetscFunctionBegin; 5572b4ed282SShri Abhyankar 5582b4ed282SShri Abhyankar ierr = VecGetArray(X,&x);CHKERRQ(ierr); 5592b4ed282SShri Abhyankar ierr = VecGetArray(F,&f);CHKERRQ(ierr); 5602b4ed282SShri Abhyankar ierr = VecGetArray(vi->xl,&l);CHKERRQ(ierr); 5612b4ed282SShri Abhyankar ierr = VecGetArray(vi->xu,&u);CHKERRQ(ierr); 562a79edbefSShri Abhyankar ierr = VecGetArray(Da,&da);CHKERRQ(ierr); 563a79edbefSShri Abhyankar ierr = VecGetArray(Db,&db);CHKERRQ(ierr); 5642b4ed282SShri Abhyankar ierr = VecGetLocalSize(X,&nlocal);CHKERRQ(ierr); 5654c21c6cdSBarry Smith 5662b4ed282SShri Abhyankar for (i=0;i< nlocal;i++) { 56710f5ae6bSBarry Smith if ((PetscRealPart(l[i]) <= SNES_VI_NINF) && (PetscRealPart(u[i]) >= SNES_VI_INF)) {/* no constraints on variable */ 5684c21c6cdSBarry Smith da[i] = 0; 5692b4ed282SShri Abhyankar db[i] = 1; 57010f5ae6bSBarry Smith } else if (PetscRealPart(l[i]) <= SNES_VI_NINF) { /* upper bound on variable only */ 5714c21c6cdSBarry Smith da[i] = DPhi(u[i] - x[i], -f[i]); 5724c21c6cdSBarry Smith db[i] = DPhi(-f[i],u[i] - x[i]); 57310f5ae6bSBarry Smith } else if (PetscRealPart(u[i]) >= SNES_VI_INF) { /* lower bound on variable only */ 5745559b345SBarry Smith da[i] = DPhi(x[i] - l[i], f[i]); 5755559b345SBarry Smith db[i] = DPhi(f[i],x[i] - l[i]); 5765559b345SBarry Smith } else if (l[i] == u[i]) { /* fixed variable */ 5774c21c6cdSBarry Smith da[i] = 1; 5782b4ed282SShri Abhyankar db[i] = 0; 5795559b345SBarry Smith } else { /* upper and lower bounds on variable */ 5804c21c6cdSBarry Smith da1 = DPhi(x[i] - l[i], -Phi(u[i] - x[i], -f[i])); 5814c21c6cdSBarry Smith db1 = DPhi(-Phi(u[i] - x[i], -f[i]),x[i] - l[i]); 5824c21c6cdSBarry Smith da2 = DPhi(u[i] - x[i], -f[i]); 5834c21c6cdSBarry Smith db2 = DPhi(-f[i],u[i] - x[i]); 5844c21c6cdSBarry Smith da[i] = da1 + db1*da2; 5854c21c6cdSBarry Smith db[i] = db1*db2; 5862b4ed282SShri Abhyankar } 5872b4ed282SShri Abhyankar } 5885559b345SBarry Smith 5892b4ed282SShri Abhyankar ierr = VecRestoreArray(X,&x);CHKERRQ(ierr); 5902b4ed282SShri Abhyankar ierr = VecRestoreArray(F,&f);CHKERRQ(ierr); 5912b4ed282SShri Abhyankar ierr = VecRestoreArray(vi->xl,&l);CHKERRQ(ierr); 5922b4ed282SShri Abhyankar ierr = VecRestoreArray(vi->xu,&u);CHKERRQ(ierr); 593a79edbefSShri Abhyankar ierr = VecRestoreArray(Da,&da);CHKERRQ(ierr); 594a79edbefSShri Abhyankar ierr = VecRestoreArray(Db,&db);CHKERRQ(ierr); 595a79edbefSShri Abhyankar PetscFunctionReturn(0); 596a79edbefSShri Abhyankar } 597a79edbefSShri Abhyankar 598a79edbefSShri Abhyankar /* 599a79edbefSShri 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. 600a79edbefSShri Abhyankar 601a79edbefSShri Abhyankar Input Parameters: 602a79edbefSShri Abhyankar . Da - Diagonal shift vector for the semismooth jacobian. 603a79edbefSShri Abhyankar . Db - Row scaling vector for the semismooth jacobian. 604a79edbefSShri Abhyankar 605a79edbefSShri Abhyankar Output Parameters: 606a79edbefSShri Abhyankar . jac - semismooth jacobian 607a79edbefSShri Abhyankar . jac_pre - optional preconditioning matrix 608a79edbefSShri Abhyankar 609a79edbefSShri Abhyankar Notes: 610a79edbefSShri Abhyankar The semismooth jacobian matrix is given by 611a79edbefSShri Abhyankar jac = Da + Db*jacfun 612a79edbefSShri Abhyankar where Db is the row scaling matrix stored as a vector, 613a79edbefSShri Abhyankar Da is the diagonal perturbation matrix stored as a vector 614a79edbefSShri Abhyankar and jacfun is the jacobian of the original nonlinear function. 615a79edbefSShri Abhyankar */ 616a79edbefSShri Abhyankar #undef __FUNCT__ 617a79edbefSShri Abhyankar #define __FUNCT__ "SNESVIComputeJacobian" 618a79edbefSShri Abhyankar PetscErrorCode SNESVIComputeJacobian(Mat jac, Mat jac_pre,Vec Da, Vec Db) 619a79edbefSShri Abhyankar { 620a79edbefSShri Abhyankar PetscErrorCode ierr; 621a79edbefSShri Abhyankar 6222b4ed282SShri Abhyankar /* Do row scaling and add diagonal perturbation */ 623a79edbefSShri Abhyankar ierr = MatDiagonalScale(jac,Db,PETSC_NULL);CHKERRQ(ierr); 624a79edbefSShri Abhyankar ierr = MatDiagonalSet(jac,Da,ADD_VALUES);CHKERRQ(ierr); 625a79edbefSShri Abhyankar if (jac != jac_pre) { /* If jac and jac_pre are different */ 626a79edbefSShri Abhyankar ierr = MatDiagonalScale(jac_pre,Db,PETSC_NULL); 627a79edbefSShri Abhyankar ierr = MatDiagonalSet(jac_pre,Da,ADD_VALUES);CHKERRQ(ierr); 6282b4ed282SShri Abhyankar } 6292b4ed282SShri Abhyankar PetscFunctionReturn(0); 6302b4ed282SShri Abhyankar } 6312b4ed282SShri Abhyankar 6322b4ed282SShri Abhyankar /* 633ee657d29SShri Abhyankar SNESVIComputeMeritFunctionGradient - Computes the gradient of the merit function psi. 634ee657d29SShri Abhyankar 635ee657d29SShri Abhyankar Input Parameters: 636ee657d29SShri Abhyankar phi - semismooth function. 637ee657d29SShri Abhyankar H - semismooth jacobian 638ee657d29SShri Abhyankar 639ee657d29SShri Abhyankar Output Parameters: 640ee657d29SShri Abhyankar dpsi - merit function gradient 641ee657d29SShri Abhyankar 642ee657d29SShri Abhyankar Notes: 643ee657d29SShri Abhyankar The merit function gradient is computed as follows 644ee657d29SShri Abhyankar dpsi = H^T*phi 645ee657d29SShri Abhyankar */ 646ee657d29SShri Abhyankar #undef __FUNCT__ 647ee657d29SShri Abhyankar #define __FUNCT__ "SNESVIComputeMeritFunctionGradient" 648ee657d29SShri Abhyankar PetscErrorCode SNESVIComputeMeritFunctionGradient(Mat H, Vec phi, Vec dpsi) 649ee657d29SShri Abhyankar { 650ee657d29SShri Abhyankar PetscErrorCode ierr; 651ee657d29SShri Abhyankar 652ee657d29SShri Abhyankar PetscFunctionBegin; 6535f48b12bSBarry Smith ierr = MatMultTranspose(H,phi,dpsi);CHKERRQ(ierr); 654ee657d29SShri Abhyankar PetscFunctionReturn(0); 655ee657d29SShri Abhyankar } 656ee657d29SShri Abhyankar 657c1a5e521SShri Abhyankar /* -------------------------------------------------------------------------- */ 658c1a5e521SShri Abhyankar /* 659c1a5e521SShri Abhyankar SNESVIProjectOntoBounds - Projects X onto the feasible region so that Xl[i] <= X[i] <= Xu[i] for i = 1...n. 660c1a5e521SShri Abhyankar 661c1a5e521SShri Abhyankar Input Parameters: 662c1a5e521SShri Abhyankar . SNES - nonlinear solver context 663c1a5e521SShri Abhyankar 664c1a5e521SShri Abhyankar Output Parameters: 665c1a5e521SShri Abhyankar . X - Bound projected X 666c1a5e521SShri Abhyankar 667c1a5e521SShri Abhyankar */ 668c1a5e521SShri Abhyankar 669c1a5e521SShri Abhyankar #undef __FUNCT__ 670c1a5e521SShri Abhyankar #define __FUNCT__ "SNESVIProjectOntoBounds" 671c1a5e521SShri Abhyankar PetscErrorCode SNESVIProjectOntoBounds(SNES snes,Vec X) 672c1a5e521SShri Abhyankar { 673c1a5e521SShri Abhyankar PetscErrorCode ierr; 674c1a5e521SShri Abhyankar SNES_VI *vi = (SNES_VI*)snes->data; 675c1a5e521SShri Abhyankar const PetscScalar *xl,*xu; 676c1a5e521SShri Abhyankar PetscScalar *x; 677c1a5e521SShri Abhyankar PetscInt i,n; 678c1a5e521SShri Abhyankar 679c1a5e521SShri Abhyankar PetscFunctionBegin; 680c1a5e521SShri Abhyankar ierr = VecGetLocalSize(X,&n);CHKERRQ(ierr); 681c1a5e521SShri Abhyankar ierr = VecGetArray(X,&x);CHKERRQ(ierr); 682c1a5e521SShri Abhyankar ierr = VecGetArrayRead(vi->xl,&xl);CHKERRQ(ierr); 683c1a5e521SShri Abhyankar ierr = VecGetArrayRead(vi->xu,&xu);CHKERRQ(ierr); 684c1a5e521SShri Abhyankar 685c1a5e521SShri Abhyankar for(i = 0;i<n;i++) { 68610f5ae6bSBarry Smith if (PetscRealPart(x[i]) < PetscRealPart(xl[i])) x[i] = xl[i]; 68710f5ae6bSBarry Smith else if (PetscRealPart(x[i]) > PetscRealPart(xu[i])) x[i] = xu[i]; 688c1a5e521SShri Abhyankar } 689c1a5e521SShri Abhyankar ierr = VecRestoreArray(X,&x);CHKERRQ(ierr); 690c1a5e521SShri Abhyankar ierr = VecRestoreArrayRead(vi->xl,&xl);CHKERRQ(ierr); 691c1a5e521SShri Abhyankar ierr = VecRestoreArrayRead(vi->xu,&xu);CHKERRQ(ierr); 692c1a5e521SShri Abhyankar PetscFunctionReturn(0); 693c1a5e521SShri Abhyankar } 694c1a5e521SShri Abhyankar 6952b4ed282SShri Abhyankar /* -------------------------------------------------------------------- 6962b4ed282SShri Abhyankar 6972b4ed282SShri Abhyankar This file implements a semismooth truncated Newton method with a line search, 6982b4ed282SShri Abhyankar for solving a system of nonlinear equations in complementarity form, using the KSP, Vec, 6992b4ed282SShri Abhyankar and Mat interfaces for linear solvers, vectors, and matrices, 7002b4ed282SShri Abhyankar respectively. 7012b4ed282SShri Abhyankar 7022b4ed282SShri Abhyankar The following basic routines are required for each nonlinear solver: 7032b4ed282SShri Abhyankar SNESCreate_XXX() - Creates a nonlinear solver context 7042b4ed282SShri Abhyankar SNESSetFromOptions_XXX() - Sets runtime options 7052b4ed282SShri Abhyankar SNESSolve_XXX() - Solves the nonlinear system 7062b4ed282SShri Abhyankar SNESDestroy_XXX() - Destroys the nonlinear solver context 7072b4ed282SShri Abhyankar The suffix "_XXX" denotes a particular implementation, in this case 7082b4ed282SShri Abhyankar we use _VI (e.g., SNESCreate_VI, SNESSolve_VI) for solving 7092b4ed282SShri Abhyankar systems of nonlinear equations with a line search (LS) method. 7102b4ed282SShri Abhyankar These routines are actually called via the common user interface 7112b4ed282SShri Abhyankar routines SNESCreate(), SNESSetFromOptions(), SNESSolve(), and 7122b4ed282SShri Abhyankar SNESDestroy(), so the application code interface remains identical 7132b4ed282SShri Abhyankar for all nonlinear solvers. 7142b4ed282SShri Abhyankar 7152b4ed282SShri Abhyankar Another key routine is: 7162b4ed282SShri Abhyankar SNESSetUp_XXX() - Prepares for the use of a nonlinear solver 7172b4ed282SShri Abhyankar by setting data structures and options. The interface routine SNESSetUp() 7182b4ed282SShri Abhyankar is not usually called directly by the user, but instead is called by 7192b4ed282SShri Abhyankar SNESSolve() if necessary. 7202b4ed282SShri Abhyankar 7212b4ed282SShri Abhyankar Additional basic routines are: 7222b4ed282SShri Abhyankar SNESView_XXX() - Prints details of runtime options that 7232b4ed282SShri Abhyankar have actually been used. 7242b4ed282SShri Abhyankar These are called by application codes via the interface routines 7252b4ed282SShri Abhyankar SNESView(). 7262b4ed282SShri Abhyankar 7272b4ed282SShri Abhyankar The various types of solvers (preconditioners, Krylov subspace methods, 7282b4ed282SShri Abhyankar nonlinear solvers, timesteppers) are all organized similarly, so the 7292b4ed282SShri Abhyankar above description applies to these categories also. 7302b4ed282SShri Abhyankar 7312b4ed282SShri Abhyankar -------------------------------------------------------------------- */ 7322b4ed282SShri Abhyankar /* 73369c03620SShri Abhyankar SNESSolveVI_SS - Solves the complementarity problem with a semismooth Newton 7342b4ed282SShri Abhyankar method using a line search. 7352b4ed282SShri Abhyankar 7362b4ed282SShri Abhyankar Input Parameters: 7372b4ed282SShri Abhyankar . snes - the SNES context 7382b4ed282SShri Abhyankar 7392b4ed282SShri Abhyankar Output Parameter: 7402b4ed282SShri Abhyankar . outits - number of iterations until termination 7412b4ed282SShri Abhyankar 7422b4ed282SShri Abhyankar Application Interface Routine: SNESSolve() 7432b4ed282SShri Abhyankar 7442b4ed282SShri Abhyankar Notes: 7452b4ed282SShri Abhyankar This implements essentially a semismooth Newton method with a 74651defd01SShri Abhyankar line search. The default line search does not do any line seach 74751defd01SShri Abhyankar but rather takes a full newton step. 7482b4ed282SShri Abhyankar */ 7492b4ed282SShri Abhyankar #undef __FUNCT__ 75069c03620SShri Abhyankar #define __FUNCT__ "SNESSolveVI_SS" 75169c03620SShri Abhyankar PetscErrorCode SNESSolveVI_SS(SNES snes) 7522b4ed282SShri Abhyankar { 7532b4ed282SShri Abhyankar SNES_VI *vi = (SNES_VI*)snes->data; 7542b4ed282SShri Abhyankar PetscErrorCode ierr; 7552b4ed282SShri Abhyankar PetscInt maxits,i,lits; 7563b336b49SShri Abhyankar PetscBool lssucceed; 7572b4ed282SShri Abhyankar MatStructure flg = DIFFERENT_NONZERO_PATTERN; 7582b4ed282SShri Abhyankar PetscReal gnorm,xnorm=0,ynorm; 7592b4ed282SShri Abhyankar Vec Y,X,F,G,W; 7602b4ed282SShri Abhyankar KSPConvergedReason kspreason; 7612b4ed282SShri Abhyankar 7622b4ed282SShri Abhyankar PetscFunctionBegin; 7639ce7406fSBarry Smith vi->computeuserfunction = snes->ops->computefunction; 7649ce7406fSBarry Smith snes->ops->computefunction = SNESVIComputeFunction; 7659ce7406fSBarry Smith 7662b4ed282SShri Abhyankar snes->numFailures = 0; 7672b4ed282SShri Abhyankar snes->numLinearSolveFailures = 0; 7682b4ed282SShri Abhyankar snes->reason = SNES_CONVERGED_ITERATING; 7692b4ed282SShri Abhyankar 7702b4ed282SShri Abhyankar maxits = snes->max_its; /* maximum number of iterations */ 7712b4ed282SShri Abhyankar X = snes->vec_sol; /* solution vector */ 7722b4ed282SShri Abhyankar F = snes->vec_func; /* residual vector */ 7732b4ed282SShri Abhyankar Y = snes->work[0]; /* work vectors */ 7742b4ed282SShri Abhyankar G = snes->work[1]; 7752b4ed282SShri Abhyankar W = snes->work[2]; 7762b4ed282SShri Abhyankar 7772b4ed282SShri Abhyankar ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 7782b4ed282SShri Abhyankar snes->iter = 0; 7792b4ed282SShri Abhyankar snes->norm = 0.0; 7802b4ed282SShri Abhyankar ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 7812b4ed282SShri Abhyankar 7827fe79bc4SShri Abhyankar ierr = SNESVIProjectOntoBounds(snes,X);CHKERRQ(ierr); 7832b4ed282SShri Abhyankar ierr = SNESComputeFunction(snes,X,vi->phi);CHKERRQ(ierr); 7842b4ed282SShri Abhyankar if (snes->domainerror) { 7852b4ed282SShri Abhyankar snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN; 7869ce7406fSBarry Smith snes->ops->computefunction = vi->computeuserfunction; 7872b4ed282SShri Abhyankar PetscFunctionReturn(0); 7882b4ed282SShri Abhyankar } 7892b4ed282SShri Abhyankar /* Compute Merit function */ 7902b4ed282SShri Abhyankar ierr = SNESVIComputeMeritFunction(vi->phi,&vi->merit,&vi->phinorm);CHKERRQ(ierr); 7912b4ed282SShri Abhyankar 7922b4ed282SShri Abhyankar ierr = VecNormBegin(X,NORM_2,&xnorm);CHKERRQ(ierr); /* xnorm <- ||x|| */ 7932b4ed282SShri Abhyankar ierr = VecNormEnd(X,NORM_2,&xnorm);CHKERRQ(ierr); 79462cbcd01SMatthew G Knepley if (PetscIsInfOrNanReal(vi->merit)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number"); 7952b4ed282SShri Abhyankar 7962b4ed282SShri Abhyankar ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 7972b4ed282SShri Abhyankar snes->norm = vi->phinorm; 7982b4ed282SShri Abhyankar ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 7992b4ed282SShri Abhyankar SNESLogConvHistory(snes,vi->phinorm,0); 8007a03ce2fSLisandro Dalcin ierr = SNESMonitor(snes,0,vi->phinorm);CHKERRQ(ierr); 8012b4ed282SShri Abhyankar 8022b4ed282SShri Abhyankar /* set parameter for default relative tolerance convergence test */ 8032b4ed282SShri Abhyankar snes->ttol = vi->phinorm*snes->rtol; 8042b4ed282SShri Abhyankar /* test convergence */ 8052b4ed282SShri Abhyankar ierr = (*snes->ops->converged)(snes,0,0.0,0.0,vi->phinorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); 8069ce7406fSBarry Smith if (snes->reason) { 8079ce7406fSBarry Smith snes->ops->computefunction = vi->computeuserfunction; 8089ce7406fSBarry Smith PetscFunctionReturn(0); 8099ce7406fSBarry Smith } 8102b4ed282SShri Abhyankar 8112b4ed282SShri Abhyankar for (i=0; i<maxits; i++) { 8122b4ed282SShri Abhyankar 8132b4ed282SShri Abhyankar /* Call general purpose update function */ 8142b4ed282SShri Abhyankar if (snes->ops->update) { 8152b4ed282SShri Abhyankar ierr = (*snes->ops->update)(snes, snes->iter);CHKERRQ(ierr); 8162b4ed282SShri Abhyankar } 8172b4ed282SShri Abhyankar 8182b4ed282SShri Abhyankar /* Solve J Y = Phi, where J is the semismooth jacobian */ 819a79edbefSShri Abhyankar /* Get the nonlinear function jacobian */ 8202b4ed282SShri Abhyankar ierr = SNESComputeJacobian(snes,X,&snes->jacobian,&snes->jacobian_pre,&flg);CHKERRQ(ierr); 821a79edbefSShri Abhyankar /* Get the diagonal shift and row scaling vectors */ 822a79edbefSShri Abhyankar ierr = SNESVIComputeBsubdifferentialVectors(snes,X,F,snes->jacobian,vi->Da,vi->Db);CHKERRQ(ierr); 823a79edbefSShri Abhyankar /* Compute the semismooth jacobian */ 824a79edbefSShri Abhyankar ierr = SNESVIComputeJacobian(snes->jacobian,snes->jacobian_pre,vi->Da,vi->Db);CHKERRQ(ierr); 825ee657d29SShri Abhyankar /* Compute the merit function gradient */ 826ee657d29SShri Abhyankar ierr = SNESVIComputeMeritFunctionGradient(snes->jacobian,vi->phi,vi->dpsi);CHKERRQ(ierr); 8272b4ed282SShri Abhyankar ierr = KSPSetOperators(snes->ksp,snes->jacobian,snes->jacobian_pre,flg);CHKERRQ(ierr); 8282b4ed282SShri Abhyankar ierr = SNES_KSPSolve(snes,snes->ksp,vi->phi,Y);CHKERRQ(ierr); 8292b4ed282SShri Abhyankar ierr = KSPGetConvergedReason(snes->ksp,&kspreason);CHKERRQ(ierr); 8303b336b49SShri Abhyankar 8313b336b49SShri Abhyankar if (kspreason < 0) { 8322b4ed282SShri Abhyankar if (++snes->numLinearSolveFailures >= snes->maxLinearSolveFailures) { 8332b4ed282SShri 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); 8342b4ed282SShri Abhyankar snes->reason = SNES_DIVERGED_LINEAR_SOLVE; 8352b4ed282SShri Abhyankar break; 8362b4ed282SShri Abhyankar } 8372b4ed282SShri Abhyankar } 8382b4ed282SShri Abhyankar ierr = KSPGetIterationNumber(snes->ksp,&lits);CHKERRQ(ierr); 8392b4ed282SShri Abhyankar snes->linear_its += lits; 8402b4ed282SShri Abhyankar ierr = PetscInfo2(snes,"iter=%D, linear solve iterations=%D\n",snes->iter,lits);CHKERRQ(ierr); 8412b4ed282SShri Abhyankar /* 8422b4ed282SShri Abhyankar if (vi->precheckstep) { 843ace3abfcSBarry Smith PetscBool changed_y = PETSC_FALSE; 8442b4ed282SShri Abhyankar ierr = (*vi->precheckstep)(snes,X,Y,vi->precheck,&changed_y);CHKERRQ(ierr); 8452b4ed282SShri Abhyankar } 8462b4ed282SShri Abhyankar 8472b4ed282SShri Abhyankar if (PetscLogPrintInfo){ 8482b4ed282SShri Abhyankar ierr = SNESVICheckResidual_Private(snes,snes->jacobian,F,Y,G,W);CHKERRQ(ierr); 8492b4ed282SShri Abhyankar } 8502b4ed282SShri Abhyankar */ 8512b4ed282SShri Abhyankar /* Compute a (scaled) negative update in the line search routine: 8522b4ed282SShri Abhyankar Y <- X - lambda*Y 8532b4ed282SShri Abhyankar and evaluate G = function(Y) (depends on the line search). 8542b4ed282SShri Abhyankar */ 8552b4ed282SShri Abhyankar ierr = VecCopy(Y,snes->vec_sol_update);CHKERRQ(ierr); 8562b4ed282SShri Abhyankar ynorm = 1; gnorm = vi->phinorm; 8572b4ed282SShri Abhyankar ierr = (*vi->LineSearch)(snes,vi->lsP,X,vi->phi,G,Y,W,vi->phinorm,xnorm,&ynorm,&gnorm,&lssucceed);CHKERRQ(ierr); 8582b4ed282SShri Abhyankar ierr = PetscInfo4(snes,"fnorm=%18.16e, gnorm=%18.16e, ynorm=%18.16e, lssucceed=%d\n",vi->phinorm,gnorm,ynorm,(int)lssucceed);CHKERRQ(ierr); 8592b4ed282SShri Abhyankar if (snes->reason == SNES_DIVERGED_FUNCTION_COUNT) break; 8602b4ed282SShri Abhyankar if (snes->domainerror) { 8612b4ed282SShri Abhyankar snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN; 8629ce7406fSBarry Smith snes->ops->computefunction = vi->computeuserfunction; 8632b4ed282SShri Abhyankar PetscFunctionReturn(0); 8642b4ed282SShri Abhyankar } 8652b4ed282SShri Abhyankar if (!lssucceed) { 8662b4ed282SShri Abhyankar if (++snes->numFailures >= snes->maxFailures) { 867ace3abfcSBarry Smith PetscBool ismin; 8682b4ed282SShri Abhyankar snes->reason = SNES_DIVERGED_LINE_SEARCH; 8692b4ed282SShri Abhyankar ierr = SNESVICheckLocalMin_Private(snes,snes->jacobian,G,W,gnorm,&ismin);CHKERRQ(ierr); 8702b4ed282SShri Abhyankar if (ismin) snes->reason = SNES_DIVERGED_LOCAL_MIN; 8712b4ed282SShri Abhyankar break; 8722b4ed282SShri Abhyankar } 8732b4ed282SShri Abhyankar } 8742b4ed282SShri Abhyankar /* Update function and solution vectors */ 8752b4ed282SShri Abhyankar vi->phinorm = gnorm; 8762b4ed282SShri Abhyankar vi->merit = 0.5*vi->phinorm*vi->phinorm; 8772b4ed282SShri Abhyankar ierr = VecCopy(G,vi->phi);CHKERRQ(ierr); 8782b4ed282SShri Abhyankar ierr = VecCopy(W,X);CHKERRQ(ierr); 8792b4ed282SShri Abhyankar /* Monitor convergence */ 8802b4ed282SShri Abhyankar ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 8812b4ed282SShri Abhyankar snes->iter = i+1; 8822b4ed282SShri Abhyankar snes->norm = vi->phinorm; 8832b4ed282SShri Abhyankar ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 8842b4ed282SShri Abhyankar SNESLogConvHistory(snes,snes->norm,lits); 8857a03ce2fSLisandro Dalcin ierr = SNESMonitor(snes,snes->iter,snes->norm);CHKERRQ(ierr); 8862b4ed282SShri Abhyankar /* Test for convergence, xnorm = || X || */ 8872b4ed282SShri Abhyankar if (snes->ops->converged != SNESSkipConverged) { ierr = VecNorm(X,NORM_2,&xnorm);CHKERRQ(ierr); } 8882b4ed282SShri Abhyankar ierr = (*snes->ops->converged)(snes,snes->iter,xnorm,ynorm,vi->phinorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); 8892b4ed282SShri Abhyankar if (snes->reason) break; 8902b4ed282SShri Abhyankar } 8912b4ed282SShri Abhyankar if (i == maxits) { 8922b4ed282SShri Abhyankar ierr = PetscInfo1(snes,"Maximum number of iterations has been reached: %D\n",maxits);CHKERRQ(ierr); 8932b4ed282SShri Abhyankar if(!snes->reason) snes->reason = SNES_DIVERGED_MAX_IT; 8942b4ed282SShri Abhyankar } 8959ce7406fSBarry Smith snes->ops->computefunction = vi->computeuserfunction; 8962b4ed282SShri Abhyankar PetscFunctionReturn(0); 8972b4ed282SShri Abhyankar } 89869c03620SShri Abhyankar 89969c03620SShri Abhyankar #undef __FUNCT__ 900693ddf92SShri Abhyankar #define __FUNCT__ "SNESVIGetActiveSetIS" 901693ddf92SShri Abhyankar /* 902693ddf92SShri Abhyankar SNESVIGetActiveSetIndices - Gets the global indices for the active set variables 903693ddf92SShri Abhyankar 904693ddf92SShri Abhyankar Input parameter 905693ddf92SShri Abhyankar . snes - the SNES context 906693ddf92SShri Abhyankar . X - the snes solution vector 907693ddf92SShri Abhyankar . F - the nonlinear function vector 908693ddf92SShri Abhyankar 909693ddf92SShri Abhyankar Output parameter 910693ddf92SShri Abhyankar . ISact - active set index set 911693ddf92SShri Abhyankar */ 912693ddf92SShri Abhyankar PetscErrorCode SNESVIGetActiveSetIS(SNES snes,Vec X,Vec F,IS* ISact) 913d950fb63SShri Abhyankar { 914d950fb63SShri Abhyankar PetscErrorCode ierr; 915693ddf92SShri Abhyankar SNES_VI *vi = (SNES_VI*)snes->data; 916693ddf92SShri Abhyankar Vec Xl=vi->xl,Xu=vi->xu; 917693ddf92SShri Abhyankar const PetscScalar *x,*f,*xl,*xu; 918693ddf92SShri Abhyankar PetscInt *idx_act,i,nlocal,nloc_isact=0,ilow,ihigh,i1=0; 919d950fb63SShri Abhyankar 920d950fb63SShri Abhyankar PetscFunctionBegin; 921d950fb63SShri Abhyankar ierr = VecGetLocalSize(X,&nlocal);CHKERRQ(ierr); 922d950fb63SShri Abhyankar ierr = VecGetOwnershipRange(X,&ilow,&ihigh);CHKERRQ(ierr); 923fe835674SShri Abhyankar ierr = VecGetArrayRead(X,&x);CHKERRQ(ierr); 924fe835674SShri Abhyankar ierr = VecGetArrayRead(Xl,&xl);CHKERRQ(ierr); 925fe835674SShri Abhyankar ierr = VecGetArrayRead(Xu,&xu);CHKERRQ(ierr); 926fe835674SShri Abhyankar ierr = VecGetArrayRead(F,&f);CHKERRQ(ierr); 927693ddf92SShri Abhyankar /* Compute active set size */ 928d950fb63SShri Abhyankar for (i=0; i < nlocal;i++) { 92910f5ae6bSBarry 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++; 930d950fb63SShri Abhyankar } 931693ddf92SShri Abhyankar 932d950fb63SShri Abhyankar ierr = PetscMalloc(nloc_isact*sizeof(PetscInt),&idx_act);CHKERRQ(ierr); 933d950fb63SShri Abhyankar 934693ddf92SShri Abhyankar /* Set active set indices */ 935d950fb63SShri Abhyankar for(i=0; i < nlocal; i++) { 93610f5ae6bSBarry Smith if (!((PetscRealPart(x[i]) > PetscRealPart(xl[i]) + 1.e-8 || (PetscRealPart(f[i]) < 0.0)) && ((PetscRealPart(x[i]) < PetscRealPart(xu[i]) - 1.e-8) || PetscRealPart(f[i]) > 0.0))) idx_act[i1++] = ilow+i; 937d950fb63SShri Abhyankar } 938d950fb63SShri Abhyankar 939693ddf92SShri Abhyankar /* Create active set IS */ 94062298a1eSBarry Smith ierr = ISCreateGeneral(((PetscObject)snes)->comm,nloc_isact,idx_act,PETSC_OWN_POINTER,ISact);CHKERRQ(ierr); 941d950fb63SShri Abhyankar 942fe835674SShri Abhyankar ierr = VecRestoreArrayRead(X,&x);CHKERRQ(ierr); 943fe835674SShri Abhyankar ierr = VecRestoreArrayRead(Xl,&xl);CHKERRQ(ierr); 944fe835674SShri Abhyankar ierr = VecRestoreArrayRead(Xu,&xu);CHKERRQ(ierr); 945fe835674SShri Abhyankar ierr = VecRestoreArrayRead(F,&f);CHKERRQ(ierr); 946d950fb63SShri Abhyankar PetscFunctionReturn(0); 947d950fb63SShri Abhyankar } 948d950fb63SShri Abhyankar 949693ddf92SShri Abhyankar #undef __FUNCT__ 950693ddf92SShri Abhyankar #define __FUNCT__ "SNESVICreateIndexSets_RS" 951693ddf92SShri Abhyankar PetscErrorCode SNESVICreateIndexSets_RS(SNES snes,Vec X,Vec F,IS* ISact,IS* ISinact) 952693ddf92SShri Abhyankar { 953693ddf92SShri Abhyankar PetscErrorCode ierr; 954693ddf92SShri Abhyankar 955693ddf92SShri Abhyankar PetscFunctionBegin; 956693ddf92SShri Abhyankar ierr = SNESVIGetActiveSetIS(snes,X,F,ISact);CHKERRQ(ierr); 957693ddf92SShri Abhyankar ierr = ISComplement(*ISact,X->map->rstart,X->map->rend,ISinact);CHKERRQ(ierr); 958693ddf92SShri Abhyankar PetscFunctionReturn(0); 959693ddf92SShri Abhyankar } 960693ddf92SShri Abhyankar 961dbd914b8SShri Abhyankar /* Create active and inactive set vectors. The local size of this vector is set and petsc computes the global size */ 962dbd914b8SShri Abhyankar #undef __FUNCT__ 963fe835674SShri Abhyankar #define __FUNCT__ "SNESVICreateSubVectors" 964fe835674SShri Abhyankar PetscErrorCode SNESVICreateSubVectors(SNES snes,PetscInt n,Vec* newv) 965dbd914b8SShri Abhyankar { 966dbd914b8SShri Abhyankar PetscErrorCode ierr; 967dbd914b8SShri Abhyankar Vec v; 968dbd914b8SShri Abhyankar 969dbd914b8SShri Abhyankar PetscFunctionBegin; 970dbd914b8SShri Abhyankar ierr = VecCreate(((PetscObject)snes)->comm,&v);CHKERRQ(ierr); 971dbd914b8SShri Abhyankar ierr = VecSetSizes(v,n,PETSC_DECIDE);CHKERRQ(ierr); 972dbd914b8SShri Abhyankar ierr = VecSetFromOptions(v);CHKERRQ(ierr); 973dbd914b8SShri Abhyankar *newv = v; 974dbd914b8SShri Abhyankar 975dbd914b8SShri Abhyankar PetscFunctionReturn(0); 976dbd914b8SShri Abhyankar } 977dbd914b8SShri Abhyankar 978732bb160SShri Abhyankar /* Resets the snes PC and KSP when the active set sizes change */ 979732bb160SShri Abhyankar #undef __FUNCT__ 980732bb160SShri Abhyankar #define __FUNCT__ "SNESVIResetPCandKSP" 981732bb160SShri Abhyankar PetscErrorCode SNESVIResetPCandKSP(SNES snes,Mat Amat,Mat Pmat) 982732bb160SShri Abhyankar { 983732bb160SShri Abhyankar PetscErrorCode ierr; 984d0af7cd3SBarry Smith KSP snesksp; 985dbd914b8SShri Abhyankar 986732bb160SShri Abhyankar PetscFunctionBegin; 987732bb160SShri Abhyankar ierr = SNESGetKSP(snes,&snesksp);CHKERRQ(ierr); 988d0af7cd3SBarry Smith ierr = KSPReset(snesksp);CHKERRQ(ierr); 989c2efdce3SBarry Smith 990c2efdce3SBarry Smith /* 991d0af7cd3SBarry Smith KSP kspnew; 992d0af7cd3SBarry Smith PC pcnew; 993d0af7cd3SBarry Smith const MatSolverPackage stype; 994d0af7cd3SBarry Smith 995c2efdce3SBarry Smith 996732bb160SShri Abhyankar ierr = KSPCreate(((PetscObject)snes)->comm,&kspnew);CHKERRQ(ierr); 997732bb160SShri Abhyankar kspnew->pc_side = snesksp->pc_side; 998732bb160SShri Abhyankar kspnew->rtol = snesksp->rtol; 999732bb160SShri Abhyankar kspnew->abstol = snesksp->abstol; 1000732bb160SShri Abhyankar kspnew->max_it = snesksp->max_it; 1001732bb160SShri Abhyankar ierr = KSPSetType(kspnew,((PetscObject)snesksp)->type_name);CHKERRQ(ierr); 1002732bb160SShri Abhyankar ierr = KSPGetPC(kspnew,&pcnew);CHKERRQ(ierr); 1003732bb160SShri Abhyankar ierr = PCSetType(kspnew->pc,((PetscObject)snesksp->pc)->type_name);CHKERRQ(ierr); 1004732bb160SShri Abhyankar ierr = PCSetOperators(kspnew->pc,Amat,Pmat,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr); 1005732bb160SShri Abhyankar ierr = PCFactorGetMatSolverPackage(snesksp->pc,&stype);CHKERRQ(ierr); 1006732bb160SShri Abhyankar ierr = PCFactorSetMatSolverPackage(kspnew->pc,stype);CHKERRQ(ierr); 10076bf464f9SBarry Smith ierr = KSPDestroy(&snesksp);CHKERRQ(ierr); 1008732bb160SShri Abhyankar snes->ksp = kspnew; 1009732bb160SShri Abhyankar ierr = PetscLogObjectParent(snes,kspnew);CHKERRQ(ierr); 1010d0af7cd3SBarry Smith ierr = KSPSetFromOptions(kspnew);CHKERRQ(ierr);*/ 1011732bb160SShri Abhyankar PetscFunctionReturn(0); 1012732bb160SShri Abhyankar } 101369c03620SShri Abhyankar 101469c03620SShri Abhyankar 1015fe835674SShri Abhyankar #undef __FUNCT__ 1016fe835674SShri Abhyankar #define __FUNCT__ "SNESVIComputeInactiveSetFnorm" 101710f5ae6bSBarry Smith PetscErrorCode SNESVIComputeInactiveSetFnorm(SNES snes,Vec F,Vec X,PetscReal *fnorm) 1018fe835674SShri Abhyankar { 1019fe835674SShri Abhyankar PetscErrorCode ierr; 1020fe835674SShri Abhyankar SNES_VI *vi = (SNES_VI*)snes->data; 1021fe835674SShri Abhyankar const PetscScalar *x,*xl,*xu,*f; 1022fe835674SShri Abhyankar PetscInt i,n; 1023fe835674SShri Abhyankar PetscReal rnorm; 1024fe835674SShri Abhyankar 1025fe835674SShri Abhyankar PetscFunctionBegin; 1026fe835674SShri Abhyankar ierr = VecGetLocalSize(X,&n);CHKERRQ(ierr); 1027fe835674SShri Abhyankar ierr = VecGetArrayRead(vi->xl,&xl);CHKERRQ(ierr); 1028fe835674SShri Abhyankar ierr = VecGetArrayRead(vi->xu,&xu);CHKERRQ(ierr); 1029fe835674SShri Abhyankar ierr = VecGetArrayRead(X,&x);CHKERRQ(ierr); 1030fe835674SShri Abhyankar ierr = VecGetArrayRead(F,&f);CHKERRQ(ierr); 1031fe835674SShri Abhyankar rnorm = 0.0; 1032fe835674SShri Abhyankar for (i=0; i<n; i++) { 103310f5ae6bSBarry 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]); 1034fe835674SShri Abhyankar } 1035fe835674SShri Abhyankar ierr = VecRestoreArrayRead(F,&f);CHKERRQ(ierr); 1036fe835674SShri Abhyankar ierr = VecRestoreArrayRead(vi->xl,&xl);CHKERRQ(ierr); 1037fe835674SShri Abhyankar ierr = VecRestoreArrayRead(vi->xu,&xu);CHKERRQ(ierr); 1038fe835674SShri Abhyankar ierr = VecRestoreArrayRead(X,&x);CHKERRQ(ierr); 1039d9822059SBarry Smith ierr = MPI_Allreduce(&rnorm,fnorm,1,MPIU_REAL,MPIU_SUM,((PetscObject)snes)->comm);CHKERRQ(ierr); 1040fe835674SShri Abhyankar *fnorm = sqrt(*fnorm); 1041fe835674SShri Abhyankar PetscFunctionReturn(0); 1042fe835674SShri Abhyankar } 1043fe835674SShri Abhyankar 1044fe835674SShri Abhyankar /* Variational Inequality solver using reduce space method. No semismooth algorithm is 1045c2efdce3SBarry Smith implemented in this algorithm. It basically identifies the active constraints and does 1046c2efdce3SBarry Smith a linear solve on the other variables (those not associated with the active constraints). */ 1047d950fb63SShri Abhyankar #undef __FUNCT__ 1048d950fb63SShri Abhyankar #define __FUNCT__ "SNESSolveVI_RS" 1049d950fb63SShri Abhyankar PetscErrorCode SNESSolveVI_RS(SNES snes) 1050d950fb63SShri Abhyankar { 1051d950fb63SShri Abhyankar SNES_VI *vi = (SNES_VI*)snes->data; 1052d950fb63SShri Abhyankar PetscErrorCode ierr; 1053abcba341SShri Abhyankar PetscInt maxits,i,lits; 1054d950fb63SShri Abhyankar PetscBool lssucceed; 1055d950fb63SShri Abhyankar MatStructure flg = DIFFERENT_NONZERO_PATTERN; 1056fe835674SShri Abhyankar PetscReal fnorm,gnorm,xnorm=0,ynorm; 1057d950fb63SShri Abhyankar Vec Y,X,F,G,W; 1058d950fb63SShri Abhyankar KSPConvergedReason kspreason; 1059d950fb63SShri Abhyankar 1060d950fb63SShri Abhyankar PetscFunctionBegin; 1061d950fb63SShri Abhyankar snes->numFailures = 0; 1062d950fb63SShri Abhyankar snes->numLinearSolveFailures = 0; 1063d950fb63SShri Abhyankar snes->reason = SNES_CONVERGED_ITERATING; 1064d950fb63SShri Abhyankar 1065d950fb63SShri Abhyankar maxits = snes->max_its; /* maximum number of iterations */ 1066d950fb63SShri Abhyankar X = snes->vec_sol; /* solution vector */ 1067d950fb63SShri Abhyankar F = snes->vec_func; /* residual vector */ 1068d950fb63SShri Abhyankar Y = snes->work[0]; /* work vectors */ 1069d950fb63SShri Abhyankar G = snes->work[1]; 1070d950fb63SShri Abhyankar W = snes->work[2]; 1071d950fb63SShri Abhyankar 1072d950fb63SShri Abhyankar ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 1073d950fb63SShri Abhyankar snes->iter = 0; 1074d950fb63SShri Abhyankar snes->norm = 0.0; 1075d950fb63SShri Abhyankar ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 1076d950fb63SShri Abhyankar 10777fe79bc4SShri Abhyankar ierr = SNESVIProjectOntoBounds(snes,X);CHKERRQ(ierr); 1078fe835674SShri Abhyankar ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr); 1079d950fb63SShri Abhyankar if (snes->domainerror) { 1080d950fb63SShri Abhyankar snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN; 1081d950fb63SShri Abhyankar PetscFunctionReturn(0); 1082d950fb63SShri Abhyankar } 1083fe835674SShri Abhyankar ierr = SNESVIComputeInactiveSetFnorm(snes,F,X,&fnorm);CHKERRQ(ierr); 1084d950fb63SShri Abhyankar ierr = VecNormBegin(X,NORM_2,&xnorm);CHKERRQ(ierr); /* xnorm <- ||x|| */ 1085d950fb63SShri Abhyankar ierr = VecNormEnd(X,NORM_2,&xnorm);CHKERRQ(ierr); 108662cbcd01SMatthew G Knepley if (PetscIsInfOrNanReal(fnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number"); 1087d950fb63SShri Abhyankar 1088d950fb63SShri Abhyankar ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 1089fe835674SShri Abhyankar snes->norm = fnorm; 1090d950fb63SShri Abhyankar ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 1091fe835674SShri Abhyankar SNESLogConvHistory(snes,fnorm,0); 10927a03ce2fSLisandro Dalcin ierr = SNESMonitor(snes,0,fnorm);CHKERRQ(ierr); 1093d950fb63SShri Abhyankar 1094d950fb63SShri Abhyankar /* set parameter for default relative tolerance convergence test */ 1095fe835674SShri Abhyankar snes->ttol = fnorm*snes->rtol; 1096d950fb63SShri Abhyankar /* test convergence */ 1097fe835674SShri Abhyankar ierr = (*snes->ops->converged)(snes,0,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); 1098d950fb63SShri Abhyankar if (snes->reason) PetscFunctionReturn(0); 1099d950fb63SShri Abhyankar 1100d950fb63SShri Abhyankar for (i=0; i<maxits; i++) { 1101d950fb63SShri Abhyankar 1102d950fb63SShri Abhyankar IS IS_act,IS_inact; /* _act -> active set _inact -> inactive set */ 1103*a6b72b01SJungho Lee IS IS_redact; /* redundant active set */ 1104d950fb63SShri Abhyankar VecScatter scat_act,scat_inact; 1105abcba341SShri Abhyankar PetscInt nis_act,nis_inact; 1106fe835674SShri Abhyankar Vec Y_act,Y_inact,F_inact; 1107d950fb63SShri Abhyankar Mat jac_inact_inact,prejac_inact_inact; 110862298a1eSBarry Smith IS keptrows; 1109abcba341SShri Abhyankar PetscBool isequal; 1110d950fb63SShri Abhyankar 1111d950fb63SShri Abhyankar /* Call general purpose update function */ 1112d950fb63SShri Abhyankar if (snes->ops->update) { 1113d950fb63SShri Abhyankar ierr = (*snes->ops->update)(snes, snes->iter);CHKERRQ(ierr); 1114d950fb63SShri Abhyankar } 1115d950fb63SShri Abhyankar ierr = SNESComputeJacobian(snes,X,&snes->jacobian,&snes->jacobian_pre,&flg);CHKERRQ(ierr); 111662298a1eSBarry Smith 1117d950fb63SShri Abhyankar /* Create active and inactive index sets */ 1118*a6b72b01SJungho Lee 1119*a6b72b01SJungho Lee /*original 1120693ddf92SShri Abhyankar ierr = SNESVICreateIndexSets_RS(snes,X,F,&IS_act,&IS_inact);CHKERRQ(ierr); 1121*a6b72b01SJungho Lee */ 1122*a6b72b01SJungho Lee ierr = SNESVIGetActiveSetIS(snes,X,F,&IS_act);CHKERRQ(ierr); 1123*a6b72b01SJungho Lee 1124*a6b72b01SJungho Lee if (vi->checkredundancy) { 1125*a6b72b01SJungho Lee (*vi->checkredundancy)(snes,IS_act,&IS_redact,vi->ctxP);CHKERRQ(ierr); 1126*a6b72b01SJungho Lee ierr = ISComplement(IS_redact,X->map->rstart,X->map->rend,&IS_inact);CHKERRQ(ierr); 1127*a6b72b01SJungho Lee ierr = ISDestroy(&IS_redact);CHKERRQ(ierr); 1128*a6b72b01SJungho Lee } else { 1129*a6b72b01SJungho Lee ierr = ISComplement(IS_act,X->map->rstart,X->map->rend,&IS_inact);CHKERRQ(ierr); 1130*a6b72b01SJungho Lee } 1131d950fb63SShri Abhyankar 11324dcab191SBarry Smith 1133abcba341SShri Abhyankar /* Create inactive set submatrix */ 113462298a1eSBarry Smith ierr = MatGetSubMatrix(snes->jacobian,IS_inact,IS_inact,MAT_INITIAL_MATRIX,&jac_inact_inact);CHKERRQ(ierr); 1135*a6b72b01SJungho Lee 1136b3a44c85SBarry Smith ierr = MatFindNonzeroRows(jac_inact_inact,&keptrows);CHKERRQ(ierr); 113762298a1eSBarry Smith if (keptrows) { 113862298a1eSBarry Smith PetscInt cnt,*nrows,k; 113962298a1eSBarry Smith const PetscInt *krows,*inact; 114027d4218bSShri Abhyankar PetscInt rstart=jac_inact_inact->rmap->rstart; 114162298a1eSBarry Smith 11426bf464f9SBarry Smith ierr = MatDestroy(&jac_inact_inact);CHKERRQ(ierr); 11436bf464f9SBarry Smith ierr = ISDestroy(&IS_act);CHKERRQ(ierr); 114462298a1eSBarry Smith 114562298a1eSBarry Smith ierr = ISGetLocalSize(keptrows,&cnt);CHKERRQ(ierr); 114662298a1eSBarry Smith ierr = ISGetIndices(keptrows,&krows);CHKERRQ(ierr); 114762298a1eSBarry Smith ierr = ISGetIndices(IS_inact,&inact);CHKERRQ(ierr); 114862298a1eSBarry Smith ierr = PetscMalloc(cnt*sizeof(PetscInt),&nrows);CHKERRQ(ierr); 114962298a1eSBarry Smith for (k=0; k<cnt; k++) { 115027d4218bSShri Abhyankar nrows[k] = inact[krows[k]-rstart]; 115162298a1eSBarry Smith } 115262298a1eSBarry Smith ierr = ISRestoreIndices(keptrows,&krows);CHKERRQ(ierr); 115362298a1eSBarry Smith ierr = ISRestoreIndices(IS_inact,&inact);CHKERRQ(ierr); 11546bf464f9SBarry Smith ierr = ISDestroy(&keptrows);CHKERRQ(ierr); 11556bf464f9SBarry Smith ierr = ISDestroy(&IS_inact);CHKERRQ(ierr); 115662298a1eSBarry Smith 115727d4218bSShri Abhyankar ierr = ISCreateGeneral(PETSC_COMM_WORLD,cnt,nrows,PETSC_OWN_POINTER,&IS_inact);CHKERRQ(ierr); 115827d4218bSShri Abhyankar ierr = ISComplement(IS_inact,F->map->rstart,F->map->rend,&IS_act);CHKERRQ(ierr); 115962298a1eSBarry Smith ierr = MatGetSubMatrix(snes->jacobian,IS_inact,IS_inact,MAT_INITIAL_MATRIX,&jac_inact_inact);CHKERRQ(ierr); 116062298a1eSBarry Smith } 11619e516c8fSBarry Smith ierr = DMSetVI(snes->dm,vi->xu,vi->xl,X,F,IS_inact);CHKERRQ(ierr); 116262298a1eSBarry Smith 1163d950fb63SShri Abhyankar /* Get sizes of active and inactive sets */ 1164d950fb63SShri Abhyankar ierr = ISGetLocalSize(IS_act,&nis_act);CHKERRQ(ierr); 1165d950fb63SShri Abhyankar ierr = ISGetLocalSize(IS_inact,&nis_inact);CHKERRQ(ierr); 1166d950fb63SShri Abhyankar 1167d950fb63SShri Abhyankar /* Create active and inactive set vectors */ 1168fe835674SShri Abhyankar ierr = SNESVICreateSubVectors(snes,nis_inact,&F_inact);CHKERRQ(ierr); 1169fe835674SShri Abhyankar ierr = SNESVICreateSubVectors(snes,nis_act,&Y_act);CHKERRQ(ierr); 1170fe835674SShri Abhyankar ierr = SNESVICreateSubVectors(snes,nis_inact,&Y_inact);CHKERRQ(ierr); 1171d950fb63SShri Abhyankar 1172d950fb63SShri Abhyankar /* Create scatter contexts */ 1173d950fb63SShri Abhyankar ierr = VecScatterCreate(Y,IS_act,Y_act,PETSC_NULL,&scat_act);CHKERRQ(ierr); 1174d950fb63SShri Abhyankar ierr = VecScatterCreate(Y,IS_inact,Y_inact,PETSC_NULL,&scat_inact);CHKERRQ(ierr); 1175d950fb63SShri Abhyankar 1176d950fb63SShri Abhyankar /* Do a vec scatter to active and inactive set vectors */ 1177fe835674SShri Abhyankar ierr = VecScatterBegin(scat_inact,F,F_inact,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1178fe835674SShri Abhyankar ierr = VecScatterEnd(scat_inact,F,F_inact,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1179d950fb63SShri Abhyankar 1180d950fb63SShri Abhyankar ierr = VecScatterBegin(scat_act,Y,Y_act,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1181d950fb63SShri Abhyankar ierr = VecScatterEnd(scat_act,Y,Y_act,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1182d950fb63SShri Abhyankar 1183d950fb63SShri Abhyankar ierr = VecScatterBegin(scat_inact,Y,Y_inact,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1184d950fb63SShri Abhyankar ierr = VecScatterEnd(scat_inact,Y,Y_inact,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1185d950fb63SShri Abhyankar 1186d950fb63SShri Abhyankar /* Active set direction = 0 */ 1187d950fb63SShri Abhyankar ierr = VecSet(Y_act,0);CHKERRQ(ierr); 1188d950fb63SShri Abhyankar if (snes->jacobian != snes->jacobian_pre) { 1189d950fb63SShri Abhyankar ierr = MatGetSubMatrix(snes->jacobian_pre,IS_inact,IS_inact,MAT_INITIAL_MATRIX,&prejac_inact_inact);CHKERRQ(ierr); 1190d950fb63SShri Abhyankar } else prejac_inact_inact = jac_inact_inact; 1191d950fb63SShri Abhyankar 1192abcba341SShri Abhyankar ierr = ISEqual(vi->IS_inact_prev,IS_inact,&isequal);CHKERRQ(ierr); 1193abcba341SShri Abhyankar if (!isequal) { 1194732bb160SShri Abhyankar ierr = SNESVIResetPCandKSP(snes,jac_inact_inact,prejac_inact_inact);CHKERRQ(ierr); 1195c58c0d17SBarry Smith flg = DIFFERENT_NONZERO_PATTERN; 1196d950fb63SShri Abhyankar } 1197d950fb63SShri Abhyankar 119813e0d083SBarry Smith /* ierr = ISView(IS_inact,0);CHKERRQ(ierr); */ 119913e0d083SBarry Smith /* ierr = ISView(IS_act,0);CHKERRQ(ierr);*/ 120013e0d083SBarry Smith /* ierr = MatView(snes->jacobian_pre,0); */ 120113e0d083SBarry Smith 1202d950fb63SShri Abhyankar ierr = KSPSetOperators(snes->ksp,jac_inact_inact,prejac_inact_inact,flg);CHKERRQ(ierr); 120313e0d083SBarry Smith ierr = KSPSetUp(snes->ksp);CHKERRQ(ierr); 120413e0d083SBarry Smith { 120513e0d083SBarry Smith PC pc; 120613e0d083SBarry Smith PetscBool flg; 120713e0d083SBarry Smith ierr = KSPGetPC(snes->ksp,&pc);CHKERRQ(ierr); 120813e0d083SBarry Smith ierr = PetscTypeCompare((PetscObject)pc,PCFIELDSPLIT,&flg);CHKERRQ(ierr); 120913e0d083SBarry Smith if (flg) { 121013e0d083SBarry Smith KSP *subksps; 121113e0d083SBarry Smith ierr = PCFieldSplitGetSubKSP(pc,PETSC_NULL,&subksps);CHKERRQ(ierr); 121213e0d083SBarry Smith ierr = KSPGetPC(subksps[0],&pc);CHKERRQ(ierr); 121313e0d083SBarry Smith ierr = PetscFree(subksps);CHKERRQ(ierr); 121413e0d083SBarry Smith ierr = PetscTypeCompare((PetscObject)pc,PCBJACOBI,&flg);CHKERRQ(ierr); 121513e0d083SBarry Smith if (flg) { 121613e0d083SBarry Smith PetscInt n,N = 101*101,j,cnts[3] = {0,0,0}; 121713e0d083SBarry Smith const PetscInt *ii; 121813e0d083SBarry Smith 121913e0d083SBarry Smith ierr = ISGetSize(IS_inact,&n);CHKERRQ(ierr); 122013e0d083SBarry Smith ierr = ISGetIndices(IS_inact,&ii);CHKERRQ(ierr); 122113e0d083SBarry Smith for (j=0; j<n; j++) { 122213e0d083SBarry Smith if (ii[j] < N) cnts[0]++; 122313e0d083SBarry Smith else if (ii[j] < 2*N) cnts[1]++; 122413e0d083SBarry Smith else if (ii[j] < 3*N) cnts[2]++; 122513e0d083SBarry Smith } 122613e0d083SBarry Smith ierr = ISRestoreIndices(IS_inact,&ii);CHKERRQ(ierr); 122713e0d083SBarry Smith 122813e0d083SBarry Smith ierr = PCBJacobiSetTotalBlocks(pc,3,cnts);CHKERRQ(ierr); 122913e0d083SBarry Smith } 123013e0d083SBarry Smith } 123113e0d083SBarry Smith } 123213e0d083SBarry Smith 1233fe835674SShri Abhyankar ierr = SNES_KSPSolve(snes,snes->ksp,F_inact,Y_inact);CHKERRQ(ierr); 1234d950fb63SShri Abhyankar ierr = KSPGetConvergedReason(snes->ksp,&kspreason);CHKERRQ(ierr); 1235d950fb63SShri Abhyankar if (kspreason < 0) { 1236d950fb63SShri Abhyankar if (++snes->numLinearSolveFailures >= snes->maxLinearSolveFailures) { 1237d950fb63SShri 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); 1238d950fb63SShri Abhyankar snes->reason = SNES_DIVERGED_LINEAR_SOLVE; 1239d950fb63SShri Abhyankar break; 1240d950fb63SShri Abhyankar } 1241d950fb63SShri Abhyankar } 1242d950fb63SShri Abhyankar 1243d950fb63SShri Abhyankar ierr = VecScatterBegin(scat_act,Y_act,Y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1244d950fb63SShri Abhyankar ierr = VecScatterEnd(scat_act,Y_act,Y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1245d950fb63SShri Abhyankar ierr = VecScatterBegin(scat_inact,Y_inact,Y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1246d950fb63SShri Abhyankar ierr = VecScatterEnd(scat_inact,Y_inact,Y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1247d950fb63SShri Abhyankar 12486bf464f9SBarry Smith ierr = VecDestroy(&F_inact);CHKERRQ(ierr); 12496bf464f9SBarry Smith ierr = VecDestroy(&Y_act);CHKERRQ(ierr); 12506bf464f9SBarry Smith ierr = VecDestroy(&Y_inact);CHKERRQ(ierr); 12516bf464f9SBarry Smith ierr = VecScatterDestroy(&scat_act);CHKERRQ(ierr); 12526bf464f9SBarry Smith ierr = VecScatterDestroy(&scat_inact);CHKERRQ(ierr); 12536bf464f9SBarry Smith ierr = ISDestroy(&IS_act);CHKERRQ(ierr); 1254abcba341SShri Abhyankar if (!isequal) { 12556bf464f9SBarry Smith ierr = ISDestroy(&vi->IS_inact_prev);CHKERRQ(ierr); 1256abcba341SShri Abhyankar ierr = ISDuplicate(IS_inact,&vi->IS_inact_prev);CHKERRQ(ierr); 1257abcba341SShri Abhyankar } 12586bf464f9SBarry Smith ierr = ISDestroy(&IS_inact);CHKERRQ(ierr); 12596bf464f9SBarry Smith ierr = MatDestroy(&jac_inact_inact);CHKERRQ(ierr); 1260d950fb63SShri Abhyankar if (snes->jacobian != snes->jacobian_pre) { 12616bf464f9SBarry Smith ierr = MatDestroy(&prejac_inact_inact);CHKERRQ(ierr); 1262d950fb63SShri Abhyankar } 1263d950fb63SShri Abhyankar ierr = KSPGetIterationNumber(snes->ksp,&lits);CHKERRQ(ierr); 1264d950fb63SShri Abhyankar snes->linear_its += lits; 1265d950fb63SShri Abhyankar ierr = PetscInfo2(snes,"iter=%D, linear solve iterations=%D\n",snes->iter,lits);CHKERRQ(ierr); 1266d950fb63SShri Abhyankar /* 1267d950fb63SShri Abhyankar if (vi->precheckstep) { 1268d950fb63SShri Abhyankar PetscBool changed_y = PETSC_FALSE; 1269d950fb63SShri Abhyankar ierr = (*vi->precheckstep)(snes,X,Y,vi->precheck,&changed_y);CHKERRQ(ierr); 1270d950fb63SShri Abhyankar } 1271d950fb63SShri Abhyankar 1272d950fb63SShri Abhyankar if (PetscLogPrintInfo){ 1273d950fb63SShri Abhyankar ierr = SNESVICheckResidual_Private(snes,snes->jacobian,F,Y,G,W);CHKERRQ(ierr); 1274d950fb63SShri Abhyankar } 1275d950fb63SShri Abhyankar */ 1276d950fb63SShri Abhyankar /* Compute a (scaled) negative update in the line search routine: 1277d950fb63SShri Abhyankar Y <- X - lambda*Y 1278d950fb63SShri Abhyankar and evaluate G = function(Y) (depends on the line search). 1279d950fb63SShri Abhyankar */ 1280d950fb63SShri Abhyankar ierr = VecCopy(Y,snes->vec_sol_update);CHKERRQ(ierr); 1281fe835674SShri Abhyankar ynorm = 1; gnorm = fnorm; 1282fe835674SShri Abhyankar ierr = (*vi->LineSearch)(snes,vi->lsP,X,F,G,Y,W,fnorm,xnorm,&ynorm,&gnorm,&lssucceed);CHKERRQ(ierr); 1283fe835674SShri Abhyankar ierr = PetscInfo4(snes,"fnorm=%18.16e, gnorm=%18.16e, ynorm=%18.16e, lssucceed=%d\n",fnorm,gnorm,ynorm,(int)lssucceed);CHKERRQ(ierr); 12842b4ed282SShri Abhyankar if (snes->reason == SNES_DIVERGED_FUNCTION_COUNT) break; 12852b4ed282SShri Abhyankar if (snes->domainerror) { 12862b4ed282SShri Abhyankar snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN; 12874c661befSBarry Smith ierr = DMDestroyVI(snes->dm);CHKERRQ(ierr); 12882b4ed282SShri Abhyankar PetscFunctionReturn(0); 12892b4ed282SShri Abhyankar } 12902b4ed282SShri Abhyankar if (!lssucceed) { 12912b4ed282SShri Abhyankar if (++snes->numFailures >= snes->maxFailures) { 12922b4ed282SShri Abhyankar PetscBool ismin; 12932b4ed282SShri Abhyankar snes->reason = SNES_DIVERGED_LINE_SEARCH; 12942b4ed282SShri Abhyankar ierr = SNESVICheckLocalMin_Private(snes,snes->jacobian,G,W,gnorm,&ismin);CHKERRQ(ierr); 12952b4ed282SShri Abhyankar if (ismin) snes->reason = SNES_DIVERGED_LOCAL_MIN; 12962b4ed282SShri Abhyankar break; 12972b4ed282SShri Abhyankar } 12982b4ed282SShri Abhyankar } 12992b4ed282SShri Abhyankar /* Update function and solution vectors */ 1300fe835674SShri Abhyankar fnorm = gnorm; 1301fe835674SShri Abhyankar ierr = VecCopy(G,F);CHKERRQ(ierr); 13022b4ed282SShri Abhyankar ierr = VecCopy(W,X);CHKERRQ(ierr); 13032b4ed282SShri Abhyankar /* Monitor convergence */ 13042b4ed282SShri Abhyankar ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 13052b4ed282SShri Abhyankar snes->iter = i+1; 1306fe835674SShri Abhyankar snes->norm = fnorm; 13072b4ed282SShri Abhyankar ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 13082b4ed282SShri Abhyankar SNESLogConvHistory(snes,snes->norm,lits); 13097a03ce2fSLisandro Dalcin ierr = SNESMonitor(snes,snes->iter,snes->norm);CHKERRQ(ierr); 13102b4ed282SShri Abhyankar /* Test for convergence, xnorm = || X || */ 13112b4ed282SShri Abhyankar if (snes->ops->converged != SNESSkipConverged) { ierr = VecNorm(X,NORM_2,&xnorm);CHKERRQ(ierr); } 1312fe835674SShri Abhyankar ierr = (*snes->ops->converged)(snes,snes->iter,xnorm,ynorm,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); 13132b4ed282SShri Abhyankar if (snes->reason) break; 13142b4ed282SShri Abhyankar } 13154c661befSBarry Smith ierr = DMDestroyVI(snes->dm);CHKERRQ(ierr); 13162b4ed282SShri Abhyankar if (i == maxits) { 13172b4ed282SShri Abhyankar ierr = PetscInfo1(snes,"Maximum number of iterations has been reached: %D\n",maxits);CHKERRQ(ierr); 13182b4ed282SShri Abhyankar if(!snes->reason) snes->reason = SNES_DIVERGED_MAX_IT; 13192b4ed282SShri Abhyankar } 13202b4ed282SShri Abhyankar PetscFunctionReturn(0); 13212b4ed282SShri Abhyankar } 13222b4ed282SShri Abhyankar 13232f63a38cSShri Abhyankar #undef __FUNCT__ 1324720c9a41SShri Abhyankar #define __FUNCT__ "SNESVISetRedundancyCheck" 1325cb5fe31bSShri Abhyankar PetscErrorCode SNESVISetRedundancyCheck(SNES snes,PetscErrorCode (*func)(SNES,IS,IS*,void*),void *ctx) 13262f63a38cSShri Abhyankar { 13272f63a38cSShri Abhyankar SNES_VI *vi = (SNES_VI*)snes->data; 13282f63a38cSShri Abhyankar 13292f63a38cSShri Abhyankar PetscFunctionBegin; 13302f63a38cSShri Abhyankar PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 13312f63a38cSShri Abhyankar vi->checkredundancy = func; 1332cb5fe31bSShri Abhyankar vi->ctxP = ctx; 13332f63a38cSShri Abhyankar PetscFunctionReturn(0); 13342f63a38cSShri Abhyankar } 13352f63a38cSShri Abhyankar 1336ff596062SShri Abhyankar #if defined(PETSC_HAVE_MATLAB_ENGINE) 1337ff596062SShri Abhyankar #include <engine.h> 1338ff596062SShri Abhyankar #include <mex.h> 1339cb5fe31bSShri Abhyankar typedef struct {char *funcname; mxArray *ctx;} SNESMatlabContext; 1340ff596062SShri Abhyankar 1341ff596062SShri Abhyankar #undef __FUNCT__ 1342ff596062SShri Abhyankar #define __FUNCT__ "SNESVIRedundancyCheck_Matlab" 1343ff596062SShri Abhyankar PetscErrorCode SNESVIRedundancyCheck_Matlab(SNES snes,IS is_act,IS* is_redact,void* ctx) 1344ff596062SShri Abhyankar { 1345ff596062SShri Abhyankar PetscErrorCode ierr; 1346cb5fe31bSShri Abhyankar SNESMatlabContext *sctx = (SNESMatlabContext*)ctx; 1347cb5fe31bSShri Abhyankar int nlhs = 1, nrhs = 5; 1348cb5fe31bSShri Abhyankar mxArray *plhs[1], *prhs[5]; 1349cb5fe31bSShri Abhyankar long long int l1 = 0, l2 = 0, ls = 0; 1350fcb1c9afSShri Abhyankar PetscInt *indices=PETSC_NULL; 1351ff596062SShri Abhyankar 1352ff596062SShri Abhyankar PetscFunctionBegin; 1353ff596062SShri Abhyankar PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 1354ff596062SShri Abhyankar PetscValidHeaderSpecific(is_act,IS_CLASSID,2); 1355ff596062SShri Abhyankar PetscValidPointer(is_redact,3); 1356ff596062SShri Abhyankar PetscCheckSameComm(snes,1,is_act,2); 1357ff596062SShri Abhyankar 135809db5ad8SShri Abhyankar /* Create IS for reduced active set of size 0, its size and indices will 135909db5ad8SShri Abhyankar bet set by the Matlab function */ 1360fcb1c9afSShri Abhyankar ierr = ISCreateGeneral(((PetscObject)snes)->comm,0,indices,PETSC_OWN_POINTER,is_redact);CHKERRQ(ierr); 1361cb5fe31bSShri Abhyankar /* call Matlab function in ctx */ 1362ff596062SShri Abhyankar ierr = PetscMemcpy(&ls,&snes,sizeof(snes));CHKERRQ(ierr); 1363ff596062SShri Abhyankar ierr = PetscMemcpy(&l1,&is_act,sizeof(is_act));CHKERRQ(ierr); 1364cb5fe31bSShri Abhyankar ierr = PetscMemcpy(&l2,is_redact,sizeof(is_act));CHKERRQ(ierr); 1365ff596062SShri Abhyankar prhs[0] = mxCreateDoubleScalar((double)ls); 1366ff596062SShri Abhyankar prhs[1] = mxCreateDoubleScalar((double)l1); 1367cb5fe31bSShri Abhyankar prhs[2] = mxCreateDoubleScalar((double)l2); 1368cb5fe31bSShri Abhyankar prhs[3] = mxCreateString(sctx->funcname); 1369cb5fe31bSShri Abhyankar prhs[4] = sctx->ctx; 1370ff596062SShri Abhyankar ierr = mexCallMATLAB(nlhs,plhs,nrhs,prhs,"PetscSNESVIRedundancyCheckInternal");CHKERRQ(ierr); 1371ff596062SShri Abhyankar ierr = mxGetScalar(plhs[0]);CHKERRQ(ierr); 1372ff596062SShri Abhyankar mxDestroyArray(prhs[0]); 1373ff596062SShri Abhyankar mxDestroyArray(prhs[1]); 1374ff596062SShri Abhyankar mxDestroyArray(prhs[2]); 1375ff596062SShri Abhyankar mxDestroyArray(prhs[3]); 1376ff596062SShri Abhyankar mxDestroyArray(plhs[0]); 1377ff596062SShri Abhyankar PetscFunctionReturn(0); 1378ff596062SShri Abhyankar } 1379ff596062SShri Abhyankar 1380ff596062SShri Abhyankar #undef __FUNCT__ 1381ff596062SShri Abhyankar #define __FUNCT__ "SNESVISetRedundancyCheckMatlab" 1382ff596062SShri Abhyankar PetscErrorCode SNESVISetRedundancyCheckMatlab(SNES snes,const char* func,mxArray* ctx) 1383ff596062SShri Abhyankar { 1384ff596062SShri Abhyankar PetscErrorCode ierr; 1385cb5fe31bSShri Abhyankar SNESMatlabContext *sctx; 1386ff596062SShri Abhyankar 1387ff596062SShri Abhyankar PetscFunctionBegin; 1388ff596062SShri Abhyankar /* currently sctx is memory bleed */ 1389cb5fe31bSShri Abhyankar ierr = PetscMalloc(sizeof(SNESMatlabContext),&sctx);CHKERRQ(ierr); 1390ff596062SShri Abhyankar ierr = PetscStrallocpy(func,&sctx->funcname);CHKERRQ(ierr); 1391ff596062SShri Abhyankar sctx->ctx = mxDuplicateArray(ctx); 1392cb5fe31bSShri Abhyankar ierr = SNESVISetRedundancyCheck(snes,SNESVIRedundancyCheck_Matlab,sctx);CHKERRQ(ierr); 1393ff596062SShri Abhyankar PetscFunctionReturn(0); 1394ff596062SShri Abhyankar } 1395ff596062SShri Abhyankar 1396ff596062SShri Abhyankar #endif 1397ff596062SShri Abhyankar 1398ff596062SShri Abhyankar 13992f63a38cSShri Abhyankar /* Variational Inequality solver using augmented space method. It does the opposite of the 14002f63a38cSShri Abhyankar reduced space method i.e. it identifies the active set variables and instead of discarding 1401720c9a41SShri Abhyankar them it augments the original system by introducing additional equality 140256a221efSShri Abhyankar constraint equations for active set variables. The user can optionally provide an IS for 140356a221efSShri Abhyankar a subset of 'redundant' active set variables which will treated as free variables. 14042f63a38cSShri Abhyankar Specific implementation for Allen-Cahn problem 14052f63a38cSShri Abhyankar */ 14062f63a38cSShri Abhyankar #undef __FUNCT__ 1407b350b9c9SBarry Smith #define __FUNCT__ "SNESSolveVI_RSAUG" 1408b350b9c9SBarry Smith PetscErrorCode SNESSolveVI_RSAUG(SNES snes) 14092f63a38cSShri Abhyankar { 14102f63a38cSShri Abhyankar SNES_VI *vi = (SNES_VI*)snes->data; 14112f63a38cSShri Abhyankar PetscErrorCode ierr; 14122f63a38cSShri Abhyankar PetscInt maxits,i,lits; 14132f63a38cSShri Abhyankar PetscBool lssucceed; 14142f63a38cSShri Abhyankar MatStructure flg = DIFFERENT_NONZERO_PATTERN; 14152f63a38cSShri Abhyankar PetscReal fnorm,gnorm,xnorm=0,ynorm; 14162f63a38cSShri Abhyankar Vec Y,X,F,G,W; 14172f63a38cSShri Abhyankar KSPConvergedReason kspreason; 14182f63a38cSShri Abhyankar 14192f63a38cSShri Abhyankar PetscFunctionBegin; 14202f63a38cSShri Abhyankar snes->numFailures = 0; 14212f63a38cSShri Abhyankar snes->numLinearSolveFailures = 0; 14222f63a38cSShri Abhyankar snes->reason = SNES_CONVERGED_ITERATING; 14232f63a38cSShri Abhyankar 14242f63a38cSShri Abhyankar maxits = snes->max_its; /* maximum number of iterations */ 14252f63a38cSShri Abhyankar X = snes->vec_sol; /* solution vector */ 14262f63a38cSShri Abhyankar F = snes->vec_func; /* residual vector */ 14272f63a38cSShri Abhyankar Y = snes->work[0]; /* work vectors */ 14282f63a38cSShri Abhyankar G = snes->work[1]; 14292f63a38cSShri Abhyankar W = snes->work[2]; 14302f63a38cSShri Abhyankar 14312f63a38cSShri Abhyankar ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 14322f63a38cSShri Abhyankar snes->iter = 0; 14332f63a38cSShri Abhyankar snes->norm = 0.0; 14342f63a38cSShri Abhyankar ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 14352f63a38cSShri Abhyankar 14362f63a38cSShri Abhyankar ierr = SNESVIProjectOntoBounds(snes,X);CHKERRQ(ierr); 14372f63a38cSShri Abhyankar ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr); 14382f63a38cSShri Abhyankar if (snes->domainerror) { 14392f63a38cSShri Abhyankar snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN; 14402f63a38cSShri Abhyankar PetscFunctionReturn(0); 14412f63a38cSShri Abhyankar } 14422f63a38cSShri Abhyankar ierr = SNESVIComputeInactiveSetFnorm(snes,F,X,&fnorm);CHKERRQ(ierr); 14432f63a38cSShri Abhyankar ierr = VecNormBegin(X,NORM_2,&xnorm);CHKERRQ(ierr); /* xnorm <- ||x|| */ 14442f63a38cSShri Abhyankar ierr = VecNormEnd(X,NORM_2,&xnorm);CHKERRQ(ierr); 144562cbcd01SMatthew G Knepley if (PetscIsInfOrNanReal(fnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number"); 14462f63a38cSShri Abhyankar 14472f63a38cSShri Abhyankar ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 14482f63a38cSShri Abhyankar snes->norm = fnorm; 14492f63a38cSShri Abhyankar ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 14502f63a38cSShri Abhyankar SNESLogConvHistory(snes,fnorm,0); 14517a03ce2fSLisandro Dalcin ierr = SNESMonitor(snes,0,fnorm);CHKERRQ(ierr); 14522f63a38cSShri Abhyankar 14532f63a38cSShri Abhyankar /* set parameter for default relative tolerance convergence test */ 14542f63a38cSShri Abhyankar snes->ttol = fnorm*snes->rtol; 14552f63a38cSShri Abhyankar /* test convergence */ 14562f63a38cSShri Abhyankar ierr = (*snes->ops->converged)(snes,0,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); 14572f63a38cSShri Abhyankar if (snes->reason) PetscFunctionReturn(0); 14582f63a38cSShri Abhyankar 14592f63a38cSShri Abhyankar for (i=0; i<maxits; i++) { 14602f63a38cSShri Abhyankar IS IS_act,IS_inact; /* _act -> active set _inact -> inactive set */ 1461cb5fe31bSShri Abhyankar IS IS_redact; /* redundant active set */ 146256a221efSShri Abhyankar Mat J_aug,Jpre_aug; 146356a221efSShri Abhyankar Vec F_aug,Y_aug; 146456a221efSShri Abhyankar PetscInt nis_redact,nis_act; 146556a221efSShri Abhyankar const PetscInt *idx_redact,*idx_act; 146656a221efSShri Abhyankar PetscInt k; 146763ee972cSSatish Balay PetscInt *idx_actkept=PETSC_NULL,nkept=0; /* list of kept active set */ 146856a221efSShri Abhyankar PetscScalar *f,*f2; 14692f63a38cSShri Abhyankar PetscBool isequal; 147056a221efSShri Abhyankar PetscInt i1=0,j1=0; 14712f63a38cSShri Abhyankar 14722f63a38cSShri Abhyankar /* Call general purpose update function */ 14732f63a38cSShri Abhyankar if (snes->ops->update) { 14742f63a38cSShri Abhyankar ierr = (*snes->ops->update)(snes, snes->iter);CHKERRQ(ierr); 14752f63a38cSShri Abhyankar } 14762f63a38cSShri Abhyankar ierr = SNESComputeJacobian(snes,X,&snes->jacobian,&snes->jacobian_pre,&flg);CHKERRQ(ierr); 14772f63a38cSShri Abhyankar 14782f63a38cSShri Abhyankar /* Create active and inactive index sets */ 14792f63a38cSShri Abhyankar ierr = SNESVICreateIndexSets_RS(snes,X,F,&IS_act,&IS_inact);CHKERRQ(ierr); 14802f63a38cSShri Abhyankar 148156a221efSShri Abhyankar /* Get local active set size */ 14822f63a38cSShri Abhyankar ierr = ISGetLocalSize(IS_act,&nis_act);CHKERRQ(ierr); 148356a221efSShri Abhyankar if (nis_act) { 1484e63076c7SBarry Smith ierr = ISGetIndices(IS_act,&idx_act);CHKERRQ(ierr); 1485e63076c7SBarry Smith IS_redact = PETSC_NULL; 148656a221efSShri Abhyankar if(vi->checkredundancy) { 1487cb5fe31bSShri Abhyankar (*vi->checkredundancy)(snes,IS_act,&IS_redact,vi->ctxP); 148856a221efSShri Abhyankar } 14892f63a38cSShri Abhyankar 149056a221efSShri Abhyankar if(!IS_redact) { 149156a221efSShri Abhyankar /* User called checkredundancy function but didn't create IS_redact because 149256a221efSShri Abhyankar there were no redundant active set variables */ 149356a221efSShri Abhyankar /* Copy over all active set indices to the list */ 149456a221efSShri Abhyankar ierr = PetscMalloc(nis_act*sizeof(PetscInt),&idx_actkept);CHKERRQ(ierr); 149556a221efSShri Abhyankar for(k=0;k < nis_act;k++) idx_actkept[k] = idx_act[k]; 149656a221efSShri Abhyankar nkept = nis_act; 149756a221efSShri Abhyankar } else { 149856a221efSShri Abhyankar ierr = ISGetLocalSize(IS_redact,&nis_redact);CHKERRQ(ierr); 149956a221efSShri Abhyankar ierr = PetscMalloc((nis_act-nis_redact)*sizeof(PetscInt),&idx_actkept);CHKERRQ(ierr); 15002f63a38cSShri Abhyankar 150156a221efSShri Abhyankar /* Create reduced active set list */ 150256a221efSShri Abhyankar ierr = ISGetIndices(IS_act,&idx_act);CHKERRQ(ierr); 150356a221efSShri Abhyankar ierr = ISGetIndices(IS_redact,&idx_redact);CHKERRQ(ierr); 1504cb5fe31bSShri Abhyankar j1 = 0;nkept = 0; 150556a221efSShri Abhyankar for(k=0;k<nis_act;k++) { 150656a221efSShri Abhyankar if(j1 < nis_redact && idx_act[k] == idx_redact[j1]) j1++; 150756a221efSShri Abhyankar else idx_actkept[nkept++] = idx_act[k]; 150856a221efSShri Abhyankar } 150956a221efSShri Abhyankar ierr = ISRestoreIndices(IS_act,&idx_act);CHKERRQ(ierr); 151056a221efSShri Abhyankar ierr = ISRestoreIndices(IS_redact,&idx_redact);CHKERRQ(ierr); 1511cb5fe31bSShri Abhyankar 1512cb5fe31bSShri Abhyankar ierr = ISDestroy(&IS_redact);CHKERRQ(ierr); 151356a221efSShri Abhyankar } 15142f63a38cSShri Abhyankar 151556a221efSShri Abhyankar /* Create augmented F and Y */ 151656a221efSShri Abhyankar ierr = VecCreate(((PetscObject)snes)->comm,&F_aug);CHKERRQ(ierr); 151756a221efSShri Abhyankar ierr = VecSetSizes(F_aug,F->map->n+nkept,PETSC_DECIDE);CHKERRQ(ierr); 151856a221efSShri Abhyankar ierr = VecSetFromOptions(F_aug);CHKERRQ(ierr); 151956a221efSShri Abhyankar ierr = VecDuplicate(F_aug,&Y_aug);CHKERRQ(ierr); 15202f63a38cSShri Abhyankar 152156a221efSShri Abhyankar /* Copy over F to F_aug in the first n locations */ 152256a221efSShri Abhyankar ierr = VecGetArray(F,&f);CHKERRQ(ierr); 152356a221efSShri Abhyankar ierr = VecGetArray(F_aug,&f2);CHKERRQ(ierr); 152456a221efSShri Abhyankar ierr = PetscMemcpy(f2,f,F->map->n*sizeof(PetscScalar));CHKERRQ(ierr); 152556a221efSShri Abhyankar ierr = VecRestoreArray(F,&f);CHKERRQ(ierr); 152656a221efSShri Abhyankar ierr = VecRestoreArray(F_aug,&f2);CHKERRQ(ierr); 15272f63a38cSShri Abhyankar 152856a221efSShri Abhyankar /* Create the augmented jacobian matrix */ 152956a221efSShri Abhyankar ierr = MatCreate(((PetscObject)snes)->comm,&J_aug);CHKERRQ(ierr); 153056a221efSShri Abhyankar ierr = MatSetSizes(J_aug,X->map->n+nkept,X->map->n+nkept,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr); 153156a221efSShri Abhyankar ierr = MatSetFromOptions(J_aug);CHKERRQ(ierr); 15322f63a38cSShri Abhyankar 153356a221efSShri Abhyankar 15349521db3cSSatish Balay { /* local vars */ 1535493a4f3dSShri Abhyankar /* Preallocate augmented matrix and set values in it...Doing only sequential case first*/ 153656a221efSShri Abhyankar PetscInt ncols; 153756a221efSShri Abhyankar const PetscInt *cols; 153856a221efSShri Abhyankar const PetscScalar *vals; 15392969f145SShri Abhyankar PetscScalar value[2]; 15402969f145SShri Abhyankar PetscInt row,col[2]; 1541493a4f3dSShri Abhyankar PetscInt *d_nnz; 15422969f145SShri Abhyankar value[0] = 1.0; value[1] = 0.0; 1543493a4f3dSShri Abhyankar ierr = PetscMalloc((X->map->n+nkept)*sizeof(PetscInt),&d_nnz);CHKERRQ(ierr); 1544493a4f3dSShri Abhyankar ierr = PetscMemzero(d_nnz,(X->map->n+nkept)*sizeof(PetscInt));CHKERRQ(ierr); 1545493a4f3dSShri Abhyankar for(row=0;row<snes->jacobian->rmap->n;row++) { 1546493a4f3dSShri Abhyankar ierr = MatGetRow(snes->jacobian,row,&ncols,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr); 1547493a4f3dSShri Abhyankar d_nnz[row] += ncols; 1548493a4f3dSShri Abhyankar ierr = MatRestoreRow(snes->jacobian,row,&ncols,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr); 1549493a4f3dSShri Abhyankar } 1550493a4f3dSShri Abhyankar 1551493a4f3dSShri Abhyankar for(k=0;k<nkept;k++) { 1552493a4f3dSShri Abhyankar d_nnz[idx_actkept[k]] += 1; 15532969f145SShri Abhyankar d_nnz[snes->jacobian->rmap->n+k] += 2; 1554493a4f3dSShri Abhyankar } 1555493a4f3dSShri Abhyankar ierr = MatSeqAIJSetPreallocation(J_aug,PETSC_NULL,d_nnz);CHKERRQ(ierr); 1556493a4f3dSShri Abhyankar 1557493a4f3dSShri Abhyankar ierr = PetscFree(d_nnz);CHKERRQ(ierr); 155856a221efSShri Abhyankar 155956a221efSShri Abhyankar /* Set the original jacobian matrix in J_aug */ 156056a221efSShri Abhyankar for(row=0;row<snes->jacobian->rmap->n;row++) { 156156a221efSShri Abhyankar ierr = MatGetRow(snes->jacobian,row,&ncols,&cols,&vals);CHKERRQ(ierr); 156256a221efSShri Abhyankar ierr = MatSetValues(J_aug,1,&row,ncols,cols,vals,INSERT_VALUES);CHKERRQ(ierr); 156356a221efSShri Abhyankar ierr = MatRestoreRow(snes->jacobian,row,&ncols,&cols,&vals);CHKERRQ(ierr); 156456a221efSShri Abhyankar } 156556a221efSShri Abhyankar /* Add the augmented part */ 156656a221efSShri Abhyankar for(k=0;k<nkept;k++) { 15672969f145SShri Abhyankar row = snes->jacobian->rmap->n+k; 15682969f145SShri Abhyankar col[0] = idx_actkept[k]; col[1] = snes->jacobian->rmap->n+k; 15692969f145SShri Abhyankar ierr = MatSetValues(J_aug,1,&row,1,col,value,INSERT_VALUES);CHKERRQ(ierr); 15702969f145SShri Abhyankar ierr = MatSetValues(J_aug,1,&col[0],1,&row,&value[0],INSERT_VALUES);CHKERRQ(ierr); 157156a221efSShri Abhyankar } 157256a221efSShri Abhyankar ierr = MatAssemblyBegin(J_aug,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 157356a221efSShri Abhyankar ierr = MatAssemblyEnd(J_aug,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 157456a221efSShri Abhyankar /* Only considering prejac = jac for now */ 157556a221efSShri Abhyankar Jpre_aug = J_aug; 15769521db3cSSatish Balay } /* local vars*/ 1577e63076c7SBarry Smith ierr = ISRestoreIndices(IS_act,&idx_act);CHKERRQ(ierr); 1578e63076c7SBarry Smith ierr = ISDestroy(&IS_act);CHKERRQ(ierr); 157956a221efSShri Abhyankar } else { 158056a221efSShri Abhyankar F_aug = F; J_aug = snes->jacobian; Y_aug = Y; Jpre_aug = snes->jacobian_pre; 158156a221efSShri Abhyankar } 15822f63a38cSShri Abhyankar 15832f63a38cSShri Abhyankar ierr = ISEqual(vi->IS_inact_prev,IS_inact,&isequal);CHKERRQ(ierr); 15842f63a38cSShri Abhyankar if (!isequal) { 158556a221efSShri Abhyankar ierr = SNESVIResetPCandKSP(snes,J_aug,Jpre_aug);CHKERRQ(ierr); 15862f63a38cSShri Abhyankar } 158756a221efSShri Abhyankar ierr = KSPSetOperators(snes->ksp,J_aug,Jpre_aug,flg);CHKERRQ(ierr); 15882f63a38cSShri Abhyankar ierr = KSPSetUp(snes->ksp);CHKERRQ(ierr); 158956a221efSShri Abhyankar /* { 15902f63a38cSShri Abhyankar PC pc; 15912f63a38cSShri Abhyankar PetscBool flg; 15922f63a38cSShri Abhyankar ierr = KSPGetPC(snes->ksp,&pc);CHKERRQ(ierr); 15932f63a38cSShri Abhyankar ierr = PetscTypeCompare((PetscObject)pc,PCFIELDSPLIT,&flg);CHKERRQ(ierr); 15942f63a38cSShri Abhyankar if (flg) { 15952f63a38cSShri Abhyankar KSP *subksps; 15962f63a38cSShri Abhyankar ierr = PCFieldSplitGetSubKSP(pc,PETSC_NULL,&subksps);CHKERRQ(ierr); 15972f63a38cSShri Abhyankar ierr = KSPGetPC(subksps[0],&pc);CHKERRQ(ierr); 15982f63a38cSShri Abhyankar ierr = PetscFree(subksps);CHKERRQ(ierr); 15992f63a38cSShri Abhyankar ierr = PetscTypeCompare((PetscObject)pc,PCBJACOBI,&flg);CHKERRQ(ierr); 16002f63a38cSShri Abhyankar if (flg) { 16012f63a38cSShri Abhyankar PetscInt n,N = 101*101,j,cnts[3] = {0,0,0}; 16022f63a38cSShri Abhyankar const PetscInt *ii; 16032f63a38cSShri Abhyankar 16042f63a38cSShri Abhyankar ierr = ISGetSize(IS_inact,&n);CHKERRQ(ierr); 16052f63a38cSShri Abhyankar ierr = ISGetIndices(IS_inact,&ii);CHKERRQ(ierr); 16062f63a38cSShri Abhyankar for (j=0; j<n; j++) { 16072f63a38cSShri Abhyankar if (ii[j] < N) cnts[0]++; 16082f63a38cSShri Abhyankar else if (ii[j] < 2*N) cnts[1]++; 16092f63a38cSShri Abhyankar else if (ii[j] < 3*N) cnts[2]++; 16102f63a38cSShri Abhyankar } 16112f63a38cSShri Abhyankar ierr = ISRestoreIndices(IS_inact,&ii);CHKERRQ(ierr); 16122f63a38cSShri Abhyankar 16132f63a38cSShri Abhyankar ierr = PCBJacobiSetTotalBlocks(pc,3,cnts);CHKERRQ(ierr); 16142f63a38cSShri Abhyankar } 16152f63a38cSShri Abhyankar } 16162f63a38cSShri Abhyankar } 161756a221efSShri Abhyankar */ 161856a221efSShri Abhyankar ierr = SNES_KSPSolve(snes,snes->ksp,F_aug,Y_aug);CHKERRQ(ierr); 16192f63a38cSShri Abhyankar ierr = KSPGetConvergedReason(snes->ksp,&kspreason);CHKERRQ(ierr); 16202f63a38cSShri Abhyankar if (kspreason < 0) { 16212f63a38cSShri Abhyankar if (++snes->numLinearSolveFailures >= snes->maxLinearSolveFailures) { 16222f63a38cSShri 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); 16232f63a38cSShri Abhyankar snes->reason = SNES_DIVERGED_LINEAR_SOLVE; 16242f63a38cSShri Abhyankar break; 16252f63a38cSShri Abhyankar } 16262f63a38cSShri Abhyankar } 16272f63a38cSShri Abhyankar 162856a221efSShri Abhyankar if(nis_act) { 162956a221efSShri Abhyankar PetscScalar *y1,*y2; 163056a221efSShri Abhyankar ierr = VecGetArray(Y,&y1);CHKERRQ(ierr); 163156a221efSShri Abhyankar ierr = VecGetArray(Y_aug,&y2);CHKERRQ(ierr); 163256a221efSShri Abhyankar /* Copy over inactive Y_aug to Y */ 163356a221efSShri Abhyankar j1 = 0; 163456a221efSShri Abhyankar for(i1=Y->map->rstart;i1 < Y->map->rend;i1++) { 163556a221efSShri Abhyankar if(j1 < nkept && idx_actkept[j1] == i1) j1++; 163656a221efSShri Abhyankar else y1[i1-Y->map->rstart] = y2[i1-Y->map->rstart]; 163756a221efSShri Abhyankar } 163856a221efSShri Abhyankar ierr = VecRestoreArray(Y,&y1);CHKERRQ(ierr); 163956a221efSShri Abhyankar ierr = VecRestoreArray(Y_aug,&y2);CHKERRQ(ierr); 16402f63a38cSShri Abhyankar 16416bf464f9SBarry Smith ierr = VecDestroy(&F_aug);CHKERRQ(ierr); 16426bf464f9SBarry Smith ierr = VecDestroy(&Y_aug);CHKERRQ(ierr); 16436bf464f9SBarry Smith ierr = MatDestroy(&J_aug);CHKERRQ(ierr); 164456a221efSShri Abhyankar ierr = PetscFree(idx_actkept);CHKERRQ(ierr); 164556a221efSShri Abhyankar } 164656a221efSShri Abhyankar 16472f63a38cSShri Abhyankar if (!isequal) { 16486bf464f9SBarry Smith ierr = ISDestroy(&vi->IS_inact_prev);CHKERRQ(ierr); 16492f63a38cSShri Abhyankar ierr = ISDuplicate(IS_inact,&vi->IS_inact_prev);CHKERRQ(ierr); 16502f63a38cSShri Abhyankar } 16516bf464f9SBarry Smith ierr = ISDestroy(&IS_inact);CHKERRQ(ierr); 165256a221efSShri Abhyankar 16532f63a38cSShri Abhyankar ierr = KSPGetIterationNumber(snes->ksp,&lits);CHKERRQ(ierr); 16542f63a38cSShri Abhyankar snes->linear_its += lits; 16552f63a38cSShri Abhyankar ierr = PetscInfo2(snes,"iter=%D, linear solve iterations=%D\n",snes->iter,lits);CHKERRQ(ierr); 16562f63a38cSShri Abhyankar /* 16572f63a38cSShri Abhyankar if (vi->precheckstep) { 16582f63a38cSShri Abhyankar PetscBool changed_y = PETSC_FALSE; 16592f63a38cSShri Abhyankar ierr = (*vi->precheckstep)(snes,X,Y,vi->precheck,&changed_y);CHKERRQ(ierr); 16602f63a38cSShri Abhyankar } 16612f63a38cSShri Abhyankar 16622f63a38cSShri Abhyankar if (PetscLogPrintInfo){ 16632f63a38cSShri Abhyankar ierr = SNESVICheckResidual_Private(snes,snes->jacobian,F,Y,G,W);CHKERRQ(ierr); 16642f63a38cSShri Abhyankar } 16652f63a38cSShri Abhyankar */ 16662f63a38cSShri Abhyankar /* Compute a (scaled) negative update in the line search routine: 16672f63a38cSShri Abhyankar Y <- X - lambda*Y 16682f63a38cSShri Abhyankar and evaluate G = function(Y) (depends on the line search). 16692f63a38cSShri Abhyankar */ 16702f63a38cSShri Abhyankar ierr = VecCopy(Y,snes->vec_sol_update);CHKERRQ(ierr); 16712f63a38cSShri Abhyankar ynorm = 1; gnorm = fnorm; 16722f63a38cSShri Abhyankar ierr = (*vi->LineSearch)(snes,vi->lsP,X,F,G,Y,W,fnorm,xnorm,&ynorm,&gnorm,&lssucceed);CHKERRQ(ierr); 16732f63a38cSShri Abhyankar ierr = PetscInfo4(snes,"fnorm=%18.16e, gnorm=%18.16e, ynorm=%18.16e, lssucceed=%d\n",fnorm,gnorm,ynorm,(int)lssucceed);CHKERRQ(ierr); 16742f63a38cSShri Abhyankar if (snes->reason == SNES_DIVERGED_FUNCTION_COUNT) break; 16752f63a38cSShri Abhyankar if (snes->domainerror) { 16762f63a38cSShri Abhyankar snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN; 16772f63a38cSShri Abhyankar PetscFunctionReturn(0); 16782f63a38cSShri Abhyankar } 16792f63a38cSShri Abhyankar if (!lssucceed) { 16802f63a38cSShri Abhyankar if (++snes->numFailures >= snes->maxFailures) { 16812f63a38cSShri Abhyankar PetscBool ismin; 16822f63a38cSShri Abhyankar snes->reason = SNES_DIVERGED_LINE_SEARCH; 16832f63a38cSShri Abhyankar ierr = SNESVICheckLocalMin_Private(snes,snes->jacobian,G,W,gnorm,&ismin);CHKERRQ(ierr); 16842f63a38cSShri Abhyankar if (ismin) snes->reason = SNES_DIVERGED_LOCAL_MIN; 16852f63a38cSShri Abhyankar break; 16862f63a38cSShri Abhyankar } 16872f63a38cSShri Abhyankar } 16882f63a38cSShri Abhyankar /* Update function and solution vectors */ 16892f63a38cSShri Abhyankar fnorm = gnorm; 16902f63a38cSShri Abhyankar ierr = VecCopy(G,F);CHKERRQ(ierr); 16912f63a38cSShri Abhyankar ierr = VecCopy(W,X);CHKERRQ(ierr); 16922f63a38cSShri Abhyankar /* Monitor convergence */ 16932f63a38cSShri Abhyankar ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 16942f63a38cSShri Abhyankar snes->iter = i+1; 16952f63a38cSShri Abhyankar snes->norm = fnorm; 16962f63a38cSShri Abhyankar ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 16972f63a38cSShri Abhyankar SNESLogConvHistory(snes,snes->norm,lits); 16987a03ce2fSLisandro Dalcin ierr = SNESMonitor(snes,snes->iter,snes->norm);CHKERRQ(ierr); 16992f63a38cSShri Abhyankar /* Test for convergence, xnorm = || X || */ 17002f63a38cSShri Abhyankar if (snes->ops->converged != SNESSkipConverged) { ierr = VecNorm(X,NORM_2,&xnorm);CHKERRQ(ierr); } 17012f63a38cSShri Abhyankar ierr = (*snes->ops->converged)(snes,snes->iter,xnorm,ynorm,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); 17022f63a38cSShri Abhyankar if (snes->reason) break; 17032f63a38cSShri Abhyankar } 17042f63a38cSShri Abhyankar if (i == maxits) { 17052f63a38cSShri Abhyankar ierr = PetscInfo1(snes,"Maximum number of iterations has been reached: %D\n",maxits);CHKERRQ(ierr); 17062f63a38cSShri Abhyankar if(!snes->reason) snes->reason = SNES_DIVERGED_MAX_IT; 17072f63a38cSShri Abhyankar } 17082f63a38cSShri Abhyankar PetscFunctionReturn(0); 17092f63a38cSShri Abhyankar } 17102f63a38cSShri Abhyankar 17112b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */ 17122b4ed282SShri Abhyankar /* 17132b4ed282SShri Abhyankar SNESSetUp_VI - Sets up the internal data structures for the later use 17142b4ed282SShri Abhyankar of the SNESVI nonlinear solver. 17152b4ed282SShri Abhyankar 17162b4ed282SShri Abhyankar Input Parameter: 17172b4ed282SShri Abhyankar . snes - the SNES context 17182b4ed282SShri Abhyankar . x - the solution vector 17192b4ed282SShri Abhyankar 17202b4ed282SShri Abhyankar Application Interface Routine: SNESSetUp() 17212b4ed282SShri Abhyankar 17222b4ed282SShri Abhyankar Notes: 17232b4ed282SShri Abhyankar For basic use of the SNES solvers, the user need not explicitly call 17242b4ed282SShri Abhyankar SNESSetUp(), since these actions will automatically occur during 17252b4ed282SShri Abhyankar the call to SNESSolve(). 17262b4ed282SShri Abhyankar */ 17272b4ed282SShri Abhyankar #undef __FUNCT__ 17282b4ed282SShri Abhyankar #define __FUNCT__ "SNESSetUp_VI" 17292b4ed282SShri Abhyankar PetscErrorCode SNESSetUp_VI(SNES snes) 17302b4ed282SShri Abhyankar { 17312b4ed282SShri Abhyankar PetscErrorCode ierr; 17322b4ed282SShri Abhyankar SNES_VI *vi = (SNES_VI*) snes->data; 17332b4ed282SShri Abhyankar PetscInt i_start[3],i_end[3]; 17342b4ed282SShri Abhyankar 17352b4ed282SShri Abhyankar PetscFunctionBegin; 173658c9b817SLisandro Dalcin 173758c9b817SLisandro Dalcin ierr = SNESDefaultGetWork(snes,3);CHKERRQ(ierr); 17382b4ed282SShri Abhyankar 17392176524cSBarry Smith if (vi->computevariablebounds) { 174077cdaf69SJed Brown if (!vi->xl) {ierr = VecDuplicate(snes->vec_sol,&vi->xl);CHKERRQ(ierr);} 174177cdaf69SJed Brown if (!vi->xu) {ierr = VecDuplicate(snes->vec_sol,&vi->xu);CHKERRQ(ierr);} 174277cdaf69SJed Brown ierr = (*vi->computevariablebounds)(snes,vi->xl,vi->xu);CHKERRQ(ierr); 17432176524cSBarry Smith } else if (!vi->xl && !vi->xu) { 17442176524cSBarry Smith /* If the lower and upper bound on variables are not set, set it to -Inf and Inf */ 17452b4ed282SShri Abhyankar ierr = VecDuplicate(snes->vec_sol, &vi->xl);CHKERRQ(ierr); 174601f0b76bSBarry Smith ierr = VecSet(vi->xl,SNES_VI_NINF);CHKERRQ(ierr); 17472b4ed282SShri Abhyankar ierr = VecDuplicate(snes->vec_sol, &vi->xu);CHKERRQ(ierr); 174801f0b76bSBarry Smith ierr = VecSet(vi->xu,SNES_VI_INF);CHKERRQ(ierr); 17492b4ed282SShri Abhyankar } else { 17502b4ed282SShri Abhyankar /* Check if lower bound, upper bound and solution vector distribution across the processors is identical */ 17512b4ed282SShri Abhyankar ierr = VecGetOwnershipRange(snes->vec_sol,i_start,i_end);CHKERRQ(ierr); 17522b4ed282SShri Abhyankar ierr = VecGetOwnershipRange(vi->xl,i_start+1,i_end+1);CHKERRQ(ierr); 17532b4ed282SShri Abhyankar ierr = VecGetOwnershipRange(vi->xu,i_start+2,i_end+2);CHKERRQ(ierr); 17542b4ed282SShri 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])) 17552b4ed282SShri 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."); 17562b4ed282SShri Abhyankar } 17572f63a38cSShri Abhyankar if (snes->ops->solve != SNESSolveVI_SS) { 1758abcba341SShri Abhyankar /* Set up previous active index set for the first snes solve 1759abcba341SShri Abhyankar vi->IS_inact_prev = 0,1,2,....N */ 1760abcba341SShri Abhyankar PetscInt *indices; 1761abcba341SShri Abhyankar PetscInt i,n,rstart,rend; 1762abcba341SShri Abhyankar 1763abcba341SShri Abhyankar ierr = VecGetOwnershipRange(snes->vec_sol,&rstart,&rend);CHKERRQ(ierr); 1764abcba341SShri Abhyankar ierr = VecGetLocalSize(snes->vec_sol,&n);CHKERRQ(ierr); 1765abcba341SShri Abhyankar ierr = PetscMalloc(n*sizeof(PetscInt),&indices);CHKERRQ(ierr); 1766abcba341SShri Abhyankar for(i=0;i < n; i++) indices[i] = rstart + i; 1767abcba341SShri Abhyankar ierr = ISCreateGeneral(((PetscObject)snes)->comm,n,indices,PETSC_OWN_POINTER,&vi->IS_inact_prev); 1768abcba341SShri Abhyankar } 17692b4ed282SShri Abhyankar 17702f63a38cSShri Abhyankar if (snes->ops->solve == SNESSolveVI_SS) { 1771fe835674SShri Abhyankar ierr = VecDuplicate(snes->vec_sol, &vi->dpsi);CHKERRQ(ierr); 1772fe835674SShri Abhyankar ierr = VecDuplicate(snes->vec_sol, &vi->phi);CHKERRQ(ierr); 1773fe835674SShri Abhyankar ierr = VecDuplicate(snes->vec_sol, &vi->Da);CHKERRQ(ierr); 1774fe835674SShri Abhyankar ierr = VecDuplicate(snes->vec_sol, &vi->Db);CHKERRQ(ierr); 1775fe835674SShri Abhyankar ierr = VecDuplicate(snes->vec_sol, &vi->z);CHKERRQ(ierr); 1776fe835674SShri Abhyankar ierr = VecDuplicate(snes->vec_sol, &vi->t);CHKERRQ(ierr); 1777fe835674SShri Abhyankar } 17782b4ed282SShri Abhyankar PetscFunctionReturn(0); 17792b4ed282SShri Abhyankar } 17802b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */ 17812176524cSBarry Smith #undef __FUNCT__ 17822176524cSBarry Smith #define __FUNCT__ "SNESReset_VI" 17832176524cSBarry Smith PetscErrorCode SNESReset_VI(SNES snes) 17842176524cSBarry Smith { 17852176524cSBarry Smith SNES_VI *vi = (SNES_VI*) snes->data; 17862176524cSBarry Smith PetscErrorCode ierr; 17872176524cSBarry Smith 17882176524cSBarry Smith PetscFunctionBegin; 17892176524cSBarry Smith ierr = VecDestroy(&vi->xl);CHKERRQ(ierr); 17902176524cSBarry Smith ierr = VecDestroy(&vi->xu);CHKERRQ(ierr); 1791d655a5daSBarry Smith if (snes->ops->solve != SNESSolveVI_SS) { 1792d655a5daSBarry Smith ierr = ISDestroy(&vi->IS_inact_prev);CHKERRQ(ierr); 1793d655a5daSBarry Smith } 17942176524cSBarry Smith PetscFunctionReturn(0); 17952176524cSBarry Smith } 17962176524cSBarry Smith 17972b4ed282SShri Abhyankar /* 17982b4ed282SShri Abhyankar SNESDestroy_VI - Destroys the private SNES_VI context that was created 17992b4ed282SShri Abhyankar with SNESCreate_VI(). 18002b4ed282SShri Abhyankar 18012b4ed282SShri Abhyankar Input Parameter: 18022b4ed282SShri Abhyankar . snes - the SNES context 18032b4ed282SShri Abhyankar 18042b4ed282SShri Abhyankar Application Interface Routine: SNESDestroy() 18052b4ed282SShri Abhyankar */ 18062b4ed282SShri Abhyankar #undef __FUNCT__ 18072b4ed282SShri Abhyankar #define __FUNCT__ "SNESDestroy_VI" 18082b4ed282SShri Abhyankar PetscErrorCode SNESDestroy_VI(SNES snes) 18092b4ed282SShri Abhyankar { 18102b4ed282SShri Abhyankar SNES_VI *vi = (SNES_VI*) snes->data; 18112b4ed282SShri Abhyankar PetscErrorCode ierr; 18122b4ed282SShri Abhyankar 18132b4ed282SShri Abhyankar PetscFunctionBegin; 18142b4ed282SShri Abhyankar 18152f63a38cSShri Abhyankar if (snes->ops->solve == SNESSolveVI_SS) { 18162b4ed282SShri Abhyankar /* clear vectors */ 18176bf464f9SBarry Smith ierr = VecDestroy(&vi->dpsi);CHKERRQ(ierr); 18186bf464f9SBarry Smith ierr = VecDestroy(&vi->phi);CHKERRQ(ierr); 18196bf464f9SBarry Smith ierr = VecDestroy(&vi->Da);CHKERRQ(ierr); 18206bf464f9SBarry Smith ierr = VecDestroy(&vi->Db);CHKERRQ(ierr); 18216bf464f9SBarry Smith ierr = VecDestroy(&vi->z);CHKERRQ(ierr); 18226bf464f9SBarry Smith ierr = VecDestroy(&vi->t);CHKERRQ(ierr); 18237fe79bc4SShri Abhyankar } 18247fe79bc4SShri Abhyankar 1825649052a6SBarry Smith ierr = PetscViewerDestroy(&vi->lsmonitor);CHKERRQ(ierr); 18262b4ed282SShri Abhyankar ierr = PetscFree(snes->data);CHKERRQ(ierr); 18272b4ed282SShri Abhyankar 18282b4ed282SShri Abhyankar /* clear composed functions */ 18292b4ed282SShri Abhyankar ierr = PetscObjectComposeFunctionDynamic((PetscObject)snes,"SNESLineSearchSet_C","",PETSC_NULL);CHKERRQ(ierr); 1830c92abb8aSShri Abhyankar ierr = PetscObjectComposeFunctionDynamic((PetscObject)snes,"SNESLineSearchSetMonitor_C","",PETSC_NULL);CHKERRQ(ierr); 18312b4ed282SShri Abhyankar PetscFunctionReturn(0); 18322b4ed282SShri Abhyankar } 18337fe79bc4SShri Abhyankar 18342b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */ 18352b4ed282SShri Abhyankar #undef __FUNCT__ 18362b4ed282SShri Abhyankar #define __FUNCT__ "SNESLineSearchNo_VI" 18372b4ed282SShri Abhyankar 18382b4ed282SShri Abhyankar /* 18397fe79bc4SShri Abhyankar This routine does not actually do a line search but it takes a full newton 18407fe79bc4SShri Abhyankar step while ensuring that the new iterates remain within the constraints. 18412b4ed282SShri Abhyankar 18422b4ed282SShri Abhyankar */ 1843ace3abfcSBarry 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) 18442b4ed282SShri Abhyankar { 18452b4ed282SShri Abhyankar PetscErrorCode ierr; 18462b4ed282SShri Abhyankar SNES_VI *vi = (SNES_VI*)snes->data; 1847ace3abfcSBarry Smith PetscBool changed_w = PETSC_FALSE,changed_y = PETSC_FALSE; 18482b4ed282SShri Abhyankar 18492b4ed282SShri Abhyankar PetscFunctionBegin; 18502b4ed282SShri Abhyankar *flag = PETSC_TRUE; 18512b4ed282SShri Abhyankar ierr = PetscLogEventBegin(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); 18522b4ed282SShri Abhyankar ierr = VecNorm(y,NORM_2,ynorm);CHKERRQ(ierr); /* ynorm = || y || */ 18532b4ed282SShri Abhyankar ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr); /* w <- x - y */ 1854c1a5e521SShri Abhyankar ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr); 1855c1a5e521SShri Abhyankar if (vi->postcheckstep) { 1856c1a5e521SShri Abhyankar ierr = (*vi->postcheckstep)(snes,x,y,w,vi->postcheck,&changed_y,&changed_w);CHKERRQ(ierr); 1857c1a5e521SShri Abhyankar } 1858c1a5e521SShri Abhyankar if (changed_y) { 1859c1a5e521SShri Abhyankar ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr); /* w <- x - y */ 18607fe79bc4SShri Abhyankar ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr); 1861c1a5e521SShri Abhyankar } 1862c1a5e521SShri Abhyankar ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr); 1863c1a5e521SShri Abhyankar ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr); 1864c1a5e521SShri Abhyankar if (!snes->domainerror) { 18652f63a38cSShri Abhyankar if (snes->ops->solve != SNESSolveVI_SS) { 18667fe79bc4SShri Abhyankar ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr); 18677fe79bc4SShri Abhyankar } else { 1868c1a5e521SShri Abhyankar ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr); /* gnorm = || g || */ 18697fe79bc4SShri Abhyankar } 187062cbcd01SMatthew G Knepley if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number"); 1871c1a5e521SShri Abhyankar } 1872c1a5e521SShri Abhyankar if (vi->lsmonitor) { 1873649052a6SBarry Smith ierr = PetscViewerASCIIAddTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 1874649052a6SBarry Smith ierr = PetscViewerASCIIPrintf(vi->lsmonitor," Line search: Using full step: fnorm %G gnorm %G\n",fnorm,*gnorm);CHKERRQ(ierr); 1875649052a6SBarry Smith ierr = PetscViewerASCIISubtractTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 1876c1a5e521SShri Abhyankar } 1877c1a5e521SShri Abhyankar ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); 1878c1a5e521SShri Abhyankar PetscFunctionReturn(0); 1879c1a5e521SShri Abhyankar } 1880c1a5e521SShri Abhyankar 1881c1a5e521SShri Abhyankar /* -------------------------------------------------------------------------- */ 1882c1a5e521SShri Abhyankar #undef __FUNCT__ 18832b4ed282SShri Abhyankar #define __FUNCT__ "SNESLineSearchNoNorms_VI" 18842b4ed282SShri Abhyankar 18852b4ed282SShri Abhyankar /* 18862b4ed282SShri Abhyankar This routine is a copy of SNESLineSearchNoNorms in snes/impls/ls/ls.c 18872b4ed282SShri Abhyankar */ 1888ace3abfcSBarry 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) 18892b4ed282SShri Abhyankar { 18902b4ed282SShri Abhyankar PetscErrorCode ierr; 18912b4ed282SShri Abhyankar SNES_VI *vi = (SNES_VI*)snes->data; 1892ace3abfcSBarry Smith PetscBool changed_w = PETSC_FALSE,changed_y = PETSC_FALSE; 18932b4ed282SShri Abhyankar 18942b4ed282SShri Abhyankar PetscFunctionBegin; 18952b4ed282SShri Abhyankar *flag = PETSC_TRUE; 18962b4ed282SShri Abhyankar ierr = PetscLogEventBegin(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); 18972b4ed282SShri Abhyankar ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr); /* w <- x - y */ 18987fe79bc4SShri Abhyankar ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr); 18992b4ed282SShri Abhyankar if (vi->postcheckstep) { 19002b4ed282SShri Abhyankar ierr = (*vi->postcheckstep)(snes,x,y,w,vi->postcheck,&changed_y,&changed_w);CHKERRQ(ierr); 19012b4ed282SShri Abhyankar } 19022b4ed282SShri Abhyankar if (changed_y) { 19032b4ed282SShri Abhyankar ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr); /* w <- x - y */ 19047fe79bc4SShri Abhyankar ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr); 19052b4ed282SShri Abhyankar } 19062b4ed282SShri Abhyankar 19072b4ed282SShri Abhyankar /* don't evaluate function the last time through */ 19082b4ed282SShri Abhyankar if (snes->iter < snes->max_its-1) { 19092b4ed282SShri Abhyankar ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr); 19102b4ed282SShri Abhyankar } 19112b4ed282SShri Abhyankar ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); 19122b4ed282SShri Abhyankar PetscFunctionReturn(0); 19132b4ed282SShri Abhyankar } 19147fe79bc4SShri Abhyankar 19152b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */ 19162b4ed282SShri Abhyankar #undef __FUNCT__ 19172b4ed282SShri Abhyankar #define __FUNCT__ "SNESLineSearchCubic_VI" 19182b4ed282SShri Abhyankar /* 19197fe79bc4SShri Abhyankar This routine implements a cubic line search while doing a projection on the variable bounds 19202b4ed282SShri Abhyankar */ 1921ace3abfcSBarry 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) 19222b4ed282SShri Abhyankar { 1923fe835674SShri Abhyankar PetscReal initslope,lambdaprev,gnormprev,a,b,d,t1,t2,rellength; 1924fe835674SShri Abhyankar PetscReal minlambda,lambda,lambdatemp; 1925fe835674SShri Abhyankar #if defined(PETSC_USE_COMPLEX) 1926fe835674SShri Abhyankar PetscScalar cinitslope; 1927fe835674SShri Abhyankar #endif 1928fe835674SShri Abhyankar PetscErrorCode ierr; 1929fe835674SShri Abhyankar PetscInt count; 1930fe835674SShri Abhyankar SNES_VI *vi = (SNES_VI*)snes->data; 1931fe835674SShri Abhyankar PetscBool changed_w = PETSC_FALSE,changed_y = PETSC_FALSE; 1932fe835674SShri Abhyankar MPI_Comm comm; 1933fe835674SShri Abhyankar 1934fe835674SShri Abhyankar PetscFunctionBegin; 1935fe835674SShri Abhyankar ierr = PetscObjectGetComm((PetscObject)snes,&comm);CHKERRQ(ierr); 1936fe835674SShri Abhyankar ierr = PetscLogEventBegin(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); 1937fe835674SShri Abhyankar *flag = PETSC_TRUE; 1938fe835674SShri Abhyankar 1939fe835674SShri Abhyankar ierr = VecNorm(y,NORM_2,ynorm);CHKERRQ(ierr); 1940fe835674SShri Abhyankar if (*ynorm == 0.0) { 1941fe835674SShri Abhyankar if (vi->lsmonitor) { 1942649052a6SBarry Smith ierr = PetscViewerASCIIAddTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 1943649052a6SBarry Smith ierr = PetscViewerASCIIPrintf(vi->lsmonitor," Line search: Initial direction and size is 0\n");CHKERRQ(ierr); 1944649052a6SBarry Smith ierr = PetscViewerASCIISubtractTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 1945fe835674SShri Abhyankar } 1946fe835674SShri Abhyankar *gnorm = fnorm; 1947fe835674SShri Abhyankar ierr = VecCopy(x,w);CHKERRQ(ierr); 1948fe835674SShri Abhyankar ierr = VecCopy(f,g);CHKERRQ(ierr); 1949fe835674SShri Abhyankar *flag = PETSC_FALSE; 1950fe835674SShri Abhyankar goto theend1; 1951fe835674SShri Abhyankar } 1952fe835674SShri Abhyankar if (*ynorm > vi->maxstep) { /* Step too big, so scale back */ 1953fe835674SShri Abhyankar if (vi->lsmonitor) { 1954649052a6SBarry Smith ierr = PetscViewerASCIIAddTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 1955649052a6SBarry Smith ierr = PetscViewerASCIIPrintf(vi->lsmonitor," Line search: Scaling step by %G old ynorm %G\n",vi->maxstep/(*ynorm),*ynorm);CHKERRQ(ierr); 1956649052a6SBarry Smith ierr = PetscViewerASCIISubtractTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 1957fe835674SShri Abhyankar } 1958fe835674SShri Abhyankar ierr = VecScale(y,vi->maxstep/(*ynorm));CHKERRQ(ierr); 1959fe835674SShri Abhyankar *ynorm = vi->maxstep; 1960fe835674SShri Abhyankar } 1961fe835674SShri Abhyankar ierr = VecMaxPointwiseDivide(y,x,&rellength);CHKERRQ(ierr); 1962fe835674SShri Abhyankar minlambda = vi->minlambda/rellength; 1963fe835674SShri Abhyankar ierr = MatMult(snes->jacobian,y,w);CHKERRQ(ierr); 1964fe835674SShri Abhyankar #if defined(PETSC_USE_COMPLEX) 1965fe835674SShri Abhyankar ierr = VecDot(f,w,&cinitslope);CHKERRQ(ierr); 1966fe835674SShri Abhyankar initslope = PetscRealPart(cinitslope); 1967fe835674SShri Abhyankar #else 1968fe835674SShri Abhyankar ierr = VecDot(f,w,&initslope);CHKERRQ(ierr); 1969fe835674SShri Abhyankar #endif 1970fe835674SShri Abhyankar if (initslope > 0.0) initslope = -initslope; 1971fe835674SShri Abhyankar if (initslope == 0.0) initslope = -1.0; 1972fe835674SShri Abhyankar 1973fe835674SShri Abhyankar ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr); 1974fe835674SShri Abhyankar ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr); 1975fe835674SShri Abhyankar if (snes->nfuncs >= snes->max_funcs) { 1976fe835674SShri Abhyankar ierr = PetscInfo(snes,"Exceeded maximum function evaluations, while checking full step length!\n");CHKERRQ(ierr); 1977fe835674SShri Abhyankar *flag = PETSC_FALSE; 1978fe835674SShri Abhyankar snes->reason = SNES_DIVERGED_FUNCTION_COUNT; 1979fe835674SShri Abhyankar goto theend1; 1980fe835674SShri Abhyankar } 1981fe835674SShri Abhyankar ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr); 19822f63a38cSShri Abhyankar if (snes->ops->solve != SNESSolveVI_SS) { 1983fe835674SShri Abhyankar ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr); 19847fe79bc4SShri Abhyankar } else { 19857fe79bc4SShri Abhyankar ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr); 19867fe79bc4SShri Abhyankar } 1987fe835674SShri Abhyankar if (snes->domainerror) { 1988fe835674SShri Abhyankar ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); 1989fe835674SShri Abhyankar PetscFunctionReturn(0); 1990fe835674SShri Abhyankar } 199162cbcd01SMatthew G Knepley if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number"); 1992fe835674SShri Abhyankar ierr = PetscInfo2(snes,"Initial fnorm %G gnorm %G\n",fnorm,*gnorm);CHKERRQ(ierr); 1993fe835674SShri Abhyankar if (.5*(*gnorm)*(*gnorm) <= .5*fnorm*fnorm + vi->alpha*initslope) { /* Sufficient reduction */ 1994fe835674SShri Abhyankar if (vi->lsmonitor) { 1995649052a6SBarry Smith ierr = PetscViewerASCIIAddTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 1996649052a6SBarry Smith ierr = PetscViewerASCIIPrintf(vi->lsmonitor," Line search: Using full step: fnorm %G gnorm %G\n",fnorm,*gnorm);CHKERRQ(ierr); 1997649052a6SBarry Smith ierr = PetscViewerASCIISubtractTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 1998fe835674SShri Abhyankar } 1999fe835674SShri Abhyankar goto theend1; 2000fe835674SShri Abhyankar } 2001fe835674SShri Abhyankar 2002fe835674SShri Abhyankar /* Fit points with quadratic */ 2003fe835674SShri Abhyankar lambda = 1.0; 2004fe835674SShri Abhyankar lambdatemp = -initslope/((*gnorm)*(*gnorm) - fnorm*fnorm - 2.0*initslope); 2005fe835674SShri Abhyankar lambdaprev = lambda; 2006fe835674SShri Abhyankar gnormprev = *gnorm; 2007fe835674SShri Abhyankar if (lambdatemp > .5*lambda) lambdatemp = .5*lambda; 2008fe835674SShri Abhyankar if (lambdatemp <= .1*lambda) lambda = .1*lambda; 2009fe835674SShri Abhyankar else lambda = lambdatemp; 2010fe835674SShri Abhyankar 2011fe835674SShri Abhyankar ierr = VecWAXPY(w,-lambda,y,x);CHKERRQ(ierr); 2012fe835674SShri Abhyankar ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr); 2013fe835674SShri Abhyankar if (snes->nfuncs >= snes->max_funcs) { 2014fe835674SShri Abhyankar ierr = PetscInfo1(snes,"Exceeded maximum function evaluations, while attempting quadratic backtracking! %D \n",snes->nfuncs);CHKERRQ(ierr); 2015fe835674SShri Abhyankar *flag = PETSC_FALSE; 2016fe835674SShri Abhyankar snes->reason = SNES_DIVERGED_FUNCTION_COUNT; 2017fe835674SShri Abhyankar goto theend1; 2018fe835674SShri Abhyankar } 2019fe835674SShri Abhyankar ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr); 20202f63a38cSShri Abhyankar if (snes->ops->solve != SNESSolveVI_SS) { 2021fe835674SShri Abhyankar ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr); 20227fe79bc4SShri Abhyankar } else { 20237fe79bc4SShri Abhyankar ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr); 20247fe79bc4SShri Abhyankar } 2025fe835674SShri Abhyankar if (snes->domainerror) { 2026fe835674SShri Abhyankar ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); 2027fe835674SShri Abhyankar PetscFunctionReturn(0); 2028fe835674SShri Abhyankar } 202962cbcd01SMatthew G Knepley if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number"); 2030fe835674SShri Abhyankar if (vi->lsmonitor) { 2031649052a6SBarry Smith ierr = PetscViewerASCIIAddTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 2032649052a6SBarry Smith ierr = PetscViewerASCIIPrintf(vi->lsmonitor," Line search: gnorm after quadratic fit %G\n",*gnorm);CHKERRQ(ierr); 2033649052a6SBarry Smith ierr = PetscViewerASCIISubtractTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 2034fe835674SShri Abhyankar } 2035fe835674SShri Abhyankar if (.5*(*gnorm)*(*gnorm) < .5*fnorm*fnorm + lambda*vi->alpha*initslope) { /* sufficient reduction */ 2036fe835674SShri Abhyankar if (vi->lsmonitor) { 2037649052a6SBarry Smith ierr = PetscViewerASCIIAddTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 2038649052a6SBarry Smith ierr = PetscViewerASCIIPrintf(vi->lsmonitor," Line search: Quadratically determined step, lambda=%18.16e\n",lambda);CHKERRQ(ierr); 2039649052a6SBarry Smith ierr = PetscViewerASCIISubtractTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 2040fe835674SShri Abhyankar } 2041fe835674SShri Abhyankar goto theend1; 2042fe835674SShri Abhyankar } 2043fe835674SShri Abhyankar 2044fe835674SShri Abhyankar /* Fit points with cubic */ 2045fe835674SShri Abhyankar count = 1; 2046fe835674SShri Abhyankar while (PETSC_TRUE) { 2047fe835674SShri Abhyankar if (lambda <= minlambda) { 2048fe835674SShri Abhyankar if (vi->lsmonitor) { 2049649052a6SBarry Smith ierr = PetscViewerASCIIAddTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 2050649052a6SBarry Smith ierr = PetscViewerASCIIPrintf(vi->lsmonitor," Line search: unable to find good step length! After %D tries \n",count);CHKERRQ(ierr); 2051649052a6SBarry Smith ierr = PetscViewerASCIIPrintf(vi->lsmonitor," Line search: fnorm=%18.16e, gnorm=%18.16e, ynorm=%18.16e, minlambda=%18.16e, lambda=%18.16e, initial slope=%18.16e\n",fnorm,*gnorm,*ynorm,minlambda,lambda,initslope);CHKERRQ(ierr); 2052649052a6SBarry Smith ierr = PetscViewerASCIISubtractTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 2053fe835674SShri Abhyankar } 2054fe835674SShri Abhyankar *flag = PETSC_FALSE; 2055fe835674SShri Abhyankar break; 2056fe835674SShri Abhyankar } 2057fe835674SShri Abhyankar t1 = .5*((*gnorm)*(*gnorm) - fnorm*fnorm) - lambda*initslope; 2058fe835674SShri Abhyankar t2 = .5*(gnormprev*gnormprev - fnorm*fnorm) - lambdaprev*initslope; 2059fe835674SShri Abhyankar a = (t1/(lambda*lambda) - t2/(lambdaprev*lambdaprev))/(lambda-lambdaprev); 2060fe835674SShri Abhyankar b = (-lambdaprev*t1/(lambda*lambda) + lambda*t2/(lambdaprev*lambdaprev))/(lambda-lambdaprev); 2061fe835674SShri Abhyankar d = b*b - 3*a*initslope; 2062fe835674SShri Abhyankar if (d < 0.0) d = 0.0; 2063fe835674SShri Abhyankar if (a == 0.0) { 2064fe835674SShri Abhyankar lambdatemp = -initslope/(2.0*b); 2065fe835674SShri Abhyankar } else { 2066fe835674SShri Abhyankar lambdatemp = (-b + sqrt(d))/(3.0*a); 2067fe835674SShri Abhyankar } 2068fe835674SShri Abhyankar lambdaprev = lambda; 2069fe835674SShri Abhyankar gnormprev = *gnorm; 2070fe835674SShri Abhyankar if (lambdatemp > .5*lambda) lambdatemp = .5*lambda; 2071fe835674SShri Abhyankar if (lambdatemp <= .1*lambda) lambda = .1*lambda; 2072fe835674SShri Abhyankar else lambda = lambdatemp; 2073fe835674SShri Abhyankar ierr = VecWAXPY(w,-lambda,y,x);CHKERRQ(ierr); 2074fe835674SShri Abhyankar ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr); 2075fe835674SShri Abhyankar if (snes->nfuncs >= snes->max_funcs) { 2076fe835674SShri Abhyankar ierr = PetscInfo1(snes,"Exceeded maximum function evaluations, while looking for good step length! %D \n",count);CHKERRQ(ierr); 2077fe835674SShri 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); 2078fe835674SShri Abhyankar *flag = PETSC_FALSE; 2079fe835674SShri Abhyankar snes->reason = SNES_DIVERGED_FUNCTION_COUNT; 2080fe835674SShri Abhyankar break; 2081fe835674SShri Abhyankar } 2082fe835674SShri Abhyankar ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr); 20832f63a38cSShri Abhyankar if (snes->ops->solve != SNESSolveVI_SS) { 2084fe835674SShri Abhyankar ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr); 20857fe79bc4SShri Abhyankar } else { 20867fe79bc4SShri Abhyankar ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr); 20877fe79bc4SShri Abhyankar } 2088fe835674SShri Abhyankar if (snes->domainerror) { 2089fe835674SShri Abhyankar ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); 2090fe835674SShri Abhyankar PetscFunctionReturn(0); 2091fe835674SShri Abhyankar } 209262cbcd01SMatthew G Knepley if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number"); 2093fe835674SShri Abhyankar if (.5*(*gnorm)*(*gnorm) < .5*fnorm*fnorm + lambda*vi->alpha*initslope) { /* is reduction enough? */ 2094fe835674SShri Abhyankar if (vi->lsmonitor) { 2095fe835674SShri Abhyankar ierr = PetscPrintf(comm," Line search: Cubically determined step, current gnorm %G lambda=%18.16e\n",*gnorm,lambda);CHKERRQ(ierr); 2096fe835674SShri Abhyankar } 2097fe835674SShri Abhyankar break; 2098fe835674SShri Abhyankar } else { 2099fe835674SShri Abhyankar if (vi->lsmonitor) { 2100fe835674SShri Abhyankar ierr = PetscPrintf(comm," Line search: Cubic step no good, shrinking lambda, current gnorm %G lambda=%18.16e\n",*gnorm,lambda);CHKERRQ(ierr); 2101fe835674SShri Abhyankar } 2102fe835674SShri Abhyankar } 2103fe835674SShri Abhyankar count++; 2104fe835674SShri Abhyankar } 2105fe835674SShri Abhyankar theend1: 2106fe835674SShri Abhyankar /* Optional user-defined check for line search step validity */ 2107fe835674SShri Abhyankar if (vi->postcheckstep && *flag) { 2108fe835674SShri Abhyankar ierr = (*vi->postcheckstep)(snes,x,y,w,vi->postcheck,&changed_y,&changed_w);CHKERRQ(ierr); 2109fe835674SShri Abhyankar if (changed_y) { 2110fe835674SShri Abhyankar ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr); 2111fe835674SShri Abhyankar ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr); 2112fe835674SShri Abhyankar } 2113fe835674SShri Abhyankar if (changed_y || changed_w) { /* recompute the function if the step has changed */ 2114fe835674SShri Abhyankar ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr); 21152f63a38cSShri Abhyankar if (snes->ops->solve != SNESSolveVI_SS) { 2116fe835674SShri Abhyankar ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr); 21177fe79bc4SShri Abhyankar } else { 21187fe79bc4SShri Abhyankar ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr); 21197fe79bc4SShri Abhyankar } 2120fe835674SShri Abhyankar if (snes->domainerror) { 2121fe835674SShri Abhyankar ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); 2122fe835674SShri Abhyankar PetscFunctionReturn(0); 2123fe835674SShri Abhyankar } 212462cbcd01SMatthew G Knepley if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number"); 2125fe835674SShri Abhyankar ierr = VecNormBegin(y,NORM_2,ynorm);CHKERRQ(ierr); 2126fe835674SShri Abhyankar ierr = VecNormEnd(y,NORM_2,ynorm);CHKERRQ(ierr); 2127fe835674SShri Abhyankar } 2128fe835674SShri Abhyankar } 2129fe835674SShri Abhyankar ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); 2130fe835674SShri Abhyankar PetscFunctionReturn(0); 2131fe835674SShri Abhyankar } 2132fe835674SShri Abhyankar 21332b4ed282SShri Abhyankar #undef __FUNCT__ 21342b4ed282SShri Abhyankar #define __FUNCT__ "SNESLineSearchQuadratic_VI" 21352b4ed282SShri Abhyankar /* 21367fe79bc4SShri Abhyankar This routine does a quadratic line search while keeping the iterates within the variable bounds 21372b4ed282SShri Abhyankar */ 2138ace3abfcSBarry 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) 21392b4ed282SShri Abhyankar { 21402b4ed282SShri Abhyankar /* 21412b4ed282SShri Abhyankar Note that for line search purposes we work with with the related 21422b4ed282SShri Abhyankar minimization problem: 21432b4ed282SShri Abhyankar min z(x): R^n -> R, 21442b4ed282SShri Abhyankar where z(x) = .5 * fnorm*fnorm,and fnorm = || f ||_2. 21452b4ed282SShri Abhyankar */ 21462b4ed282SShri Abhyankar PetscReal initslope,minlambda,lambda,lambdatemp,rellength; 21472b4ed282SShri Abhyankar #if defined(PETSC_USE_COMPLEX) 21482b4ed282SShri Abhyankar PetscScalar cinitslope; 21492b4ed282SShri Abhyankar #endif 21502b4ed282SShri Abhyankar PetscErrorCode ierr; 21512b4ed282SShri Abhyankar PetscInt count; 21522b4ed282SShri Abhyankar SNES_VI *vi = (SNES_VI*)snes->data; 2153ace3abfcSBarry Smith PetscBool changed_w = PETSC_FALSE,changed_y = PETSC_FALSE; 21542b4ed282SShri Abhyankar 21552b4ed282SShri Abhyankar PetscFunctionBegin; 21562b4ed282SShri Abhyankar ierr = PetscLogEventBegin(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); 21572b4ed282SShri Abhyankar *flag = PETSC_TRUE; 21582b4ed282SShri Abhyankar 21592b4ed282SShri Abhyankar ierr = VecNorm(y,NORM_2,ynorm);CHKERRQ(ierr); 21602b4ed282SShri Abhyankar if (*ynorm == 0.0) { 2161c92abb8aSShri Abhyankar if (vi->lsmonitor) { 2162649052a6SBarry Smith ierr = PetscViewerASCIIAddTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 2163649052a6SBarry Smith ierr = PetscViewerASCIIPrintf(vi->lsmonitor,"Line search: Direction and size is 0\n");CHKERRQ(ierr); 2164649052a6SBarry Smith ierr = PetscViewerASCIISubtractTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 21652b4ed282SShri Abhyankar } 21662b4ed282SShri Abhyankar *gnorm = fnorm; 21672b4ed282SShri Abhyankar ierr = VecCopy(x,w);CHKERRQ(ierr); 21682b4ed282SShri Abhyankar ierr = VecCopy(f,g);CHKERRQ(ierr); 21692b4ed282SShri Abhyankar *flag = PETSC_FALSE; 21702b4ed282SShri Abhyankar goto theend2; 21712b4ed282SShri Abhyankar } 21722b4ed282SShri Abhyankar if (*ynorm > vi->maxstep) { /* Step too big, so scale back */ 21732b4ed282SShri Abhyankar ierr = VecScale(y,vi->maxstep/(*ynorm));CHKERRQ(ierr); 21742b4ed282SShri Abhyankar *ynorm = vi->maxstep; 21752b4ed282SShri Abhyankar } 21762b4ed282SShri Abhyankar ierr = VecMaxPointwiseDivide(y,x,&rellength);CHKERRQ(ierr); 21772b4ed282SShri Abhyankar minlambda = vi->minlambda/rellength; 21787fe79bc4SShri Abhyankar ierr = MatMult(snes->jacobian,y,w);CHKERRQ(ierr); 21792b4ed282SShri Abhyankar #if defined(PETSC_USE_COMPLEX) 21807fe79bc4SShri Abhyankar ierr = VecDot(f,w,&cinitslope);CHKERRQ(ierr); 21812b4ed282SShri Abhyankar initslope = PetscRealPart(cinitslope); 21822b4ed282SShri Abhyankar #else 21837fe79bc4SShri Abhyankar ierr = VecDot(f,w,&initslope);CHKERRQ(ierr); 21842b4ed282SShri Abhyankar #endif 21852b4ed282SShri Abhyankar if (initslope > 0.0) initslope = -initslope; 21862b4ed282SShri Abhyankar if (initslope == 0.0) initslope = -1.0; 21872b4ed282SShri Abhyankar ierr = PetscInfo1(snes,"Initslope %G \n",initslope);CHKERRQ(ierr); 21882b4ed282SShri Abhyankar 21892b4ed282SShri Abhyankar ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr); 21907fe79bc4SShri Abhyankar ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr); 21912b4ed282SShri Abhyankar if (snes->nfuncs >= snes->max_funcs) { 21922b4ed282SShri Abhyankar ierr = PetscInfo(snes,"Exceeded maximum function evaluations, while checking full step length!\n");CHKERRQ(ierr); 21932b4ed282SShri Abhyankar *flag = PETSC_FALSE; 21942b4ed282SShri Abhyankar snes->reason = SNES_DIVERGED_FUNCTION_COUNT; 21952b4ed282SShri Abhyankar goto theend2; 21962b4ed282SShri Abhyankar } 21972b4ed282SShri Abhyankar ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr); 21982f63a38cSShri Abhyankar if (snes->ops->solve != SNESSolveVI_SS) { 21997fe79bc4SShri Abhyankar ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr); 22007fe79bc4SShri Abhyankar } else { 22017fe79bc4SShri Abhyankar ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr); 22027fe79bc4SShri Abhyankar } 22032b4ed282SShri Abhyankar if (snes->domainerror) { 22042b4ed282SShri Abhyankar ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); 22052b4ed282SShri Abhyankar PetscFunctionReturn(0); 22062b4ed282SShri Abhyankar } 220762cbcd01SMatthew G Knepley if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number"); 22082b4ed282SShri Abhyankar if (.5*(*gnorm)*(*gnorm) <= .5*fnorm*fnorm + vi->alpha*initslope) { /* Sufficient reduction */ 2209c92abb8aSShri Abhyankar if (vi->lsmonitor) { 2210649052a6SBarry Smith ierr = PetscViewerASCIIAddTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 2211649052a6SBarry Smith ierr = PetscViewerASCIIPrintf(vi->lsmonitor," Line search: Using full step: fnorm %G gnorm %G\n",fnorm,*gnorm);CHKERRQ(ierr); 2212649052a6SBarry Smith ierr = PetscViewerASCIISubtractTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 22132b4ed282SShri Abhyankar } 22142b4ed282SShri Abhyankar goto theend2; 22152b4ed282SShri Abhyankar } 22162b4ed282SShri Abhyankar 22172b4ed282SShri Abhyankar /* Fit points with quadratic */ 22182b4ed282SShri Abhyankar lambda = 1.0; 22192b4ed282SShri Abhyankar count = 1; 22202b4ed282SShri Abhyankar while (PETSC_TRUE) { 22212b4ed282SShri Abhyankar if (lambda <= minlambda) { /* bad luck; use full step */ 2222c92abb8aSShri Abhyankar if (vi->lsmonitor) { 2223649052a6SBarry Smith ierr = PetscViewerASCIIAddTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 2224649052a6SBarry Smith ierr = PetscViewerASCIIPrintf(vi->lsmonitor,"Line search: Unable to find good step length! %D \n",count);CHKERRQ(ierr); 2225649052a6SBarry Smith ierr = PetscViewerASCIIPrintf(vi->lsmonitor,"Line search: fnorm=%G, gnorm=%G, ynorm=%G, lambda=%G, initial slope=%G\n",fnorm,*gnorm,*ynorm,lambda,initslope);CHKERRQ(ierr); 2226649052a6SBarry Smith ierr = PetscViewerASCIISubtractTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 22272b4ed282SShri Abhyankar } 22282b4ed282SShri Abhyankar ierr = VecCopy(x,w);CHKERRQ(ierr); 22292b4ed282SShri Abhyankar *flag = PETSC_FALSE; 22302b4ed282SShri Abhyankar break; 22312b4ed282SShri Abhyankar } 22322b4ed282SShri Abhyankar lambdatemp = -initslope/((*gnorm)*(*gnorm) - fnorm*fnorm - 2.0*initslope); 22332b4ed282SShri Abhyankar if (lambdatemp > .5*lambda) lambdatemp = .5*lambda; 22342b4ed282SShri Abhyankar if (lambdatemp <= .1*lambda) lambda = .1*lambda; 22352b4ed282SShri Abhyankar else lambda = lambdatemp; 22362b4ed282SShri Abhyankar 22372b4ed282SShri Abhyankar ierr = VecWAXPY(w,-lambda,y,x);CHKERRQ(ierr); 22387fe79bc4SShri Abhyankar ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr); 22392b4ed282SShri Abhyankar if (snes->nfuncs >= snes->max_funcs) { 22402b4ed282SShri Abhyankar ierr = PetscInfo1(snes,"Exceeded maximum function evaluations, while looking for good step length! %D \n",count);CHKERRQ(ierr); 22412b4ed282SShri 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); 22422b4ed282SShri Abhyankar *flag = PETSC_FALSE; 22432b4ed282SShri Abhyankar snes->reason = SNES_DIVERGED_FUNCTION_COUNT; 22442b4ed282SShri Abhyankar break; 22452b4ed282SShri Abhyankar } 22462b4ed282SShri Abhyankar ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr); 22472b4ed282SShri Abhyankar if (snes->domainerror) { 22482b4ed282SShri Abhyankar ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); 22492b4ed282SShri Abhyankar PetscFunctionReturn(0); 22502b4ed282SShri Abhyankar } 22512f63a38cSShri Abhyankar if (snes->ops->solve != SNESSolveVI_SS) { 22527fe79bc4SShri Abhyankar ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr); 22537fe79bc4SShri Abhyankar } else { 22542b4ed282SShri Abhyankar ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr); 22557fe79bc4SShri Abhyankar } 225662cbcd01SMatthew G Knepley if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number"); 22572b4ed282SShri Abhyankar if (.5*(*gnorm)*(*gnorm) < .5*fnorm*fnorm + lambda*vi->alpha*initslope) { /* sufficient reduction */ 2258c92abb8aSShri Abhyankar if (vi->lsmonitor) { 2259649052a6SBarry Smith ierr = PetscViewerASCIIAddTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 2260649052a6SBarry Smith ierr = PetscViewerASCIIPrintf(vi->lsmonitor," Line Search: Quadratically determined step, lambda=%G\n",lambda);CHKERRQ(ierr); 2261649052a6SBarry Smith ierr = PetscViewerASCIISubtractTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 22622b4ed282SShri Abhyankar } 22632b4ed282SShri Abhyankar break; 22642b4ed282SShri Abhyankar } 22652b4ed282SShri Abhyankar count++; 22662b4ed282SShri Abhyankar } 22672b4ed282SShri Abhyankar theend2: 22682b4ed282SShri Abhyankar /* Optional user-defined check for line search step validity */ 22692b4ed282SShri Abhyankar if (vi->postcheckstep) { 22702b4ed282SShri Abhyankar ierr = (*vi->postcheckstep)(snes,x,y,w,vi->postcheck,&changed_y,&changed_w);CHKERRQ(ierr); 22712b4ed282SShri Abhyankar if (changed_y) { 22722b4ed282SShri Abhyankar ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr); 22737fe79bc4SShri Abhyankar ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr); 22742b4ed282SShri Abhyankar } 22752b4ed282SShri Abhyankar if (changed_y || changed_w) { /* recompute the function if the step has changed */ 22762b4ed282SShri Abhyankar ierr = SNESComputeFunction(snes,w,g); 22772b4ed282SShri Abhyankar if (snes->domainerror) { 22782b4ed282SShri Abhyankar ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); 22792b4ed282SShri Abhyankar PetscFunctionReturn(0); 22802b4ed282SShri Abhyankar } 22812f63a38cSShri Abhyankar if (snes->ops->solve != SNESSolveVI_SS) { 22827fe79bc4SShri Abhyankar ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr); 22837fe79bc4SShri Abhyankar } else { 22847fe79bc4SShri Abhyankar ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr); 22857fe79bc4SShri Abhyankar } 22867fe79bc4SShri Abhyankar 22872b4ed282SShri Abhyankar ierr = VecNormBegin(y,NORM_2,ynorm);CHKERRQ(ierr); 22882b4ed282SShri Abhyankar ierr = VecNormEnd(y,NORM_2,ynorm);CHKERRQ(ierr); 228962cbcd01SMatthew G Knepley if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number"); 22902b4ed282SShri Abhyankar } 22912b4ed282SShri Abhyankar } 22922b4ed282SShri Abhyankar ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); 22932b4ed282SShri Abhyankar PetscFunctionReturn(0); 22942b4ed282SShri Abhyankar } 22952b4ed282SShri Abhyankar 2296ace3abfcSBarry 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*/ 22972b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */ 22982b4ed282SShri Abhyankar EXTERN_C_BEGIN 22992b4ed282SShri Abhyankar #undef __FUNCT__ 23002b4ed282SShri Abhyankar #define __FUNCT__ "SNESLineSearchSet_VI" 23017087cfbeSBarry Smith PetscErrorCode SNESLineSearchSet_VI(SNES snes,FCN2 func,void *lsctx) 23022b4ed282SShri Abhyankar { 23032b4ed282SShri Abhyankar PetscFunctionBegin; 23042b4ed282SShri Abhyankar ((SNES_VI *)(snes->data))->LineSearch = func; 23052b4ed282SShri Abhyankar ((SNES_VI *)(snes->data))->lsP = lsctx; 23062b4ed282SShri Abhyankar PetscFunctionReturn(0); 23072b4ed282SShri Abhyankar } 23082b4ed282SShri Abhyankar EXTERN_C_END 23092b4ed282SShri Abhyankar 23102b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */ 23112b4ed282SShri Abhyankar EXTERN_C_BEGIN 23122b4ed282SShri Abhyankar #undef __FUNCT__ 23132b4ed282SShri Abhyankar #define __FUNCT__ "SNESLineSearchSetMonitor_VI" 23147087cfbeSBarry Smith PetscErrorCode SNESLineSearchSetMonitor_VI(SNES snes,PetscBool flg) 23152b4ed282SShri Abhyankar { 23162b4ed282SShri Abhyankar SNES_VI *vi = (SNES_VI*)snes->data; 23172b4ed282SShri Abhyankar PetscErrorCode ierr; 23182b4ed282SShri Abhyankar 23192b4ed282SShri Abhyankar PetscFunctionBegin; 2320c92abb8aSShri Abhyankar if (flg && !vi->lsmonitor) { 2321649052a6SBarry Smith ierr = PetscViewerASCIIOpen(((PetscObject)snes)->comm,"stdout",&vi->lsmonitor);CHKERRQ(ierr); 2322c92abb8aSShri Abhyankar } else if (!flg && vi->lsmonitor) { 2323649052a6SBarry Smith ierr = PetscViewerDestroy(&vi->lsmonitor);CHKERRQ(ierr); 23242b4ed282SShri Abhyankar } 23252b4ed282SShri Abhyankar PetscFunctionReturn(0); 23262b4ed282SShri Abhyankar } 23272b4ed282SShri Abhyankar EXTERN_C_END 23282b4ed282SShri Abhyankar 23292b4ed282SShri Abhyankar /* 23302b4ed282SShri Abhyankar SNESView_VI - Prints info from the SNESVI data structure. 23312b4ed282SShri Abhyankar 23322b4ed282SShri Abhyankar Input Parameters: 23332b4ed282SShri Abhyankar . SNES - the SNES context 23342b4ed282SShri Abhyankar . viewer - visualization context 23352b4ed282SShri Abhyankar 23362b4ed282SShri Abhyankar Application Interface Routine: SNESView() 23372b4ed282SShri Abhyankar */ 23382b4ed282SShri Abhyankar #undef __FUNCT__ 23392b4ed282SShri Abhyankar #define __FUNCT__ "SNESView_VI" 23402b4ed282SShri Abhyankar static PetscErrorCode SNESView_VI(SNES snes,PetscViewer viewer) 23412b4ed282SShri Abhyankar { 23422b4ed282SShri Abhyankar SNES_VI *vi = (SNES_VI *)snes->data; 234378c4b9d3SShri Abhyankar const char *cstr,*tstr; 23442b4ed282SShri Abhyankar PetscErrorCode ierr; 2345ace3abfcSBarry Smith PetscBool iascii; 23462b4ed282SShri Abhyankar 23472b4ed282SShri Abhyankar PetscFunctionBegin; 23482b4ed282SShri Abhyankar ierr = PetscTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); 23492b4ed282SShri Abhyankar if (iascii) { 23502b4ed282SShri Abhyankar if (vi->LineSearch == SNESLineSearchNo_VI) cstr = "SNESLineSearchNo"; 23512b4ed282SShri Abhyankar else if (vi->LineSearch == SNESLineSearchQuadratic_VI) cstr = "SNESLineSearchQuadratic"; 23522b4ed282SShri Abhyankar else if (vi->LineSearch == SNESLineSearchCubic_VI) cstr = "SNESLineSearchCubic"; 23532b4ed282SShri Abhyankar else cstr = "unknown"; 235478c4b9d3SShri Abhyankar if (snes->ops->solve == SNESSolveVI_SS) tstr = "Semismooth"; 23550a7c7af0SShri Abhyankar else if (snes->ops->solve == SNESSolveVI_RS) tstr = "Reduced Space"; 2356b350b9c9SBarry Smith else if (snes->ops->solve == SNESSolveVI_RSAUG) tstr = "Reduced space with augmented variables"; 235778c4b9d3SShri Abhyankar else tstr = "unknown"; 235878c4b9d3SShri Abhyankar ierr = PetscViewerASCIIPrintf(viewer," VI algorithm: %s\n",tstr);CHKERRQ(ierr); 23592b4ed282SShri Abhyankar ierr = PetscViewerASCIIPrintf(viewer," line search variant: %s\n",cstr);CHKERRQ(ierr); 23602b4ed282SShri Abhyankar ierr = PetscViewerASCIIPrintf(viewer," alpha=%G, maxstep=%G, minlambda=%G\n",vi->alpha,vi->maxstep,vi->minlambda);CHKERRQ(ierr); 23612b4ed282SShri Abhyankar } else { 23622b4ed282SShri Abhyankar SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Viewer type %s not supported for SNES EQ VI",((PetscObject)viewer)->type_name); 23632b4ed282SShri Abhyankar } 23642b4ed282SShri Abhyankar PetscFunctionReturn(0); 23652b4ed282SShri Abhyankar } 23662b4ed282SShri Abhyankar 23675559b345SBarry Smith #undef __FUNCT__ 23685559b345SBarry Smith #define __FUNCT__ "SNESVISetVariableBounds" 23695559b345SBarry Smith /*@ 23702b4ed282SShri Abhyankar SNESVISetVariableBounds - Sets the lower and upper bounds for the solution vector. xl <= x <= xu. 23712b4ed282SShri Abhyankar 23722b4ed282SShri Abhyankar Input Parameters: 23732b4ed282SShri Abhyankar . snes - the SNES context. 23742b4ed282SShri Abhyankar . xl - lower bound. 23752b4ed282SShri Abhyankar . xu - upper bound. 23762b4ed282SShri Abhyankar 23772b4ed282SShri Abhyankar Notes: 23782b4ed282SShri Abhyankar If this routine is not called then the lower and upper bounds are set to 237901f0b76bSBarry Smith SNES_VI_INF and SNES_VI_NINF respectively during SNESSetUp(). 238084c105d7SBarry Smith 23815559b345SBarry Smith @*/ 238269c03620SShri Abhyankar PetscErrorCode SNESVISetVariableBounds(SNES snes, Vec xl, Vec xu) 23832b4ed282SShri Abhyankar { 2384d923200aSJungho Lee SNES_VI *vi; 2385d923200aSJungho Lee PetscErrorCode ierr; 23862b4ed282SShri Abhyankar 23872b4ed282SShri Abhyankar PetscFunctionBegin; 23882b4ed282SShri Abhyankar PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 23892b4ed282SShri Abhyankar PetscValidHeaderSpecific(xl,VEC_CLASSID,2); 23902b4ed282SShri Abhyankar PetscValidHeaderSpecific(xu,VEC_CLASSID,3); 23912b4ed282SShri Abhyankar if (!snes->vec_func) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Must call SNESSetFunction() first"); 23922b4ed282SShri 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); 23932b4ed282SShri 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); 2394d923200aSJungho Lee ierr = SNESSetType(snes,SNESVI);CHKERRQ(ierr); 2395d923200aSJungho Lee vi = (SNES_VI*)snes->data; 23962176524cSBarry Smith ierr = PetscObjectReference((PetscObject)xl);CHKERRQ(ierr); 23972176524cSBarry Smith ierr = PetscObjectReference((PetscObject)xu);CHKERRQ(ierr); 23982176524cSBarry Smith ierr = VecDestroy(&vi->xl);CHKERRQ(ierr); 23992176524cSBarry Smith ierr = VecDestroy(&vi->xu);CHKERRQ(ierr); 24002b4ed282SShri Abhyankar vi->xl = xl; 24012b4ed282SShri Abhyankar vi->xu = xu; 24022b4ed282SShri Abhyankar PetscFunctionReturn(0); 24032b4ed282SShri Abhyankar } 2404693ddf92SShri Abhyankar 24052b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */ 24062b4ed282SShri Abhyankar /* 24072b4ed282SShri Abhyankar SNESSetFromOptions_VI - Sets various parameters for the SNESVI method. 24082b4ed282SShri Abhyankar 24092b4ed282SShri Abhyankar Input Parameter: 24102b4ed282SShri Abhyankar . snes - the SNES context 24112b4ed282SShri Abhyankar 24122b4ed282SShri Abhyankar Application Interface Routine: SNESSetFromOptions() 24132b4ed282SShri Abhyankar */ 24142b4ed282SShri Abhyankar #undef __FUNCT__ 24152b4ed282SShri Abhyankar #define __FUNCT__ "SNESSetFromOptions_VI" 24162b4ed282SShri Abhyankar static PetscErrorCode SNESSetFromOptions_VI(SNES snes) 24172b4ed282SShri Abhyankar { 24182b4ed282SShri Abhyankar SNES_VI *vi = (SNES_VI *)snes->data; 24197fe79bc4SShri Abhyankar const char *lses[] = {"basic","basicnonorms","quadratic","cubic"}; 2420b350b9c9SBarry Smith const char *vies[] = {"ss","rs","rsaug"}; 24212b4ed282SShri Abhyankar PetscErrorCode ierr; 24222b4ed282SShri Abhyankar PetscInt indx; 242369c03620SShri Abhyankar PetscBool flg,set,flg2; 24242b4ed282SShri Abhyankar 24252b4ed282SShri Abhyankar PetscFunctionBegin; 24262b4ed282SShri Abhyankar ierr = PetscOptionsHead("SNES semismooth method options");CHKERRQ(ierr); 24279308c137SBarry Smith ierr = PetscOptionsBool("-snes_vi_monitor","Monitor all non-active variables","None",PETSC_FALSE,&flg,0);CHKERRQ(ierr); 24289308c137SBarry Smith if (flg) { 24299308c137SBarry Smith ierr = SNESMonitorSet(snes,SNESMonitorVI,0,0);CHKERRQ(ierr); 24309308c137SBarry Smith } 2431be6adb11SBarry Smith ierr = PetscOptionsReal("-snes_ls_alpha","Function norm must decrease by","None",vi->alpha,&vi->alpha,0);CHKERRQ(ierr); 2432be6adb11SBarry Smith ierr = PetscOptionsReal("-snes_ls_maxstep","Step must be less than","None",vi->maxstep,&vi->maxstep,0);CHKERRQ(ierr); 2433be6adb11SBarry Smith ierr = PetscOptionsReal("-snes_ls_minlambda","Minimum lambda allowed","None",vi->minlambda,&vi->minlambda,0);CHKERRQ(ierr); 24342b4ed282SShri Abhyankar ierr = PetscOptionsReal("-snes_vi_const_tol","constraint tolerance","None",vi->const_tol,&vi->const_tol,0);CHKERRQ(ierr); 2435be6adb11SBarry Smith ierr = PetscOptionsBool("-snes_ls_monitor","Print progress of line searches","SNESLineSearchSetMonitor",vi->lsmonitor ? PETSC_TRUE : PETSC_FALSE,&flg,&set);CHKERRQ(ierr); 24362b4ed282SShri Abhyankar if (set) {ierr = SNESLineSearchSetMonitor(snes,flg);CHKERRQ(ierr);} 24372f63a38cSShri Abhyankar ierr = PetscOptionsEList("-snes_vi_type","Semismooth algorithm used","",vies,3,"ss",&indx,&flg2);CHKERRQ(ierr); 243869c03620SShri Abhyankar if (flg2) { 243969c03620SShri Abhyankar switch (indx) { 244069c03620SShri Abhyankar case 0: 244169c03620SShri Abhyankar snes->ops->solve = SNESSolveVI_SS; 244269c03620SShri Abhyankar break; 244369c03620SShri Abhyankar case 1: 2444d950fb63SShri Abhyankar snes->ops->solve = SNESSolveVI_RS; 2445d950fb63SShri Abhyankar break; 24462f63a38cSShri Abhyankar case 2: 2447b350b9c9SBarry Smith snes->ops->solve = SNESSolveVI_RSAUG; 244869c03620SShri Abhyankar } 244969c03620SShri Abhyankar } 2450be6adb11SBarry Smith ierr = PetscOptionsEList("-snes_ls","Line search used","SNESLineSearchSet",lses,4,"basic",&indx,&flg);CHKERRQ(ierr); 24512b4ed282SShri Abhyankar if (flg) { 24522b4ed282SShri Abhyankar switch (indx) { 24532b4ed282SShri Abhyankar case 0: 24542b4ed282SShri Abhyankar ierr = SNESLineSearchSet(snes,SNESLineSearchNo_VI,PETSC_NULL);CHKERRQ(ierr); 24552b4ed282SShri Abhyankar break; 24562b4ed282SShri Abhyankar case 1: 24572b4ed282SShri Abhyankar ierr = SNESLineSearchSet(snes,SNESLineSearchNoNorms_VI,PETSC_NULL);CHKERRQ(ierr); 24582b4ed282SShri Abhyankar break; 24592b4ed282SShri Abhyankar case 2: 24602b4ed282SShri Abhyankar ierr = SNESLineSearchSet(snes,SNESLineSearchQuadratic_VI,PETSC_NULL);CHKERRQ(ierr); 24612b4ed282SShri Abhyankar break; 24622b4ed282SShri Abhyankar case 3: 24632b4ed282SShri Abhyankar ierr = SNESLineSearchSet(snes,SNESLineSearchCubic_VI,PETSC_NULL);CHKERRQ(ierr); 24642b4ed282SShri Abhyankar break; 24652b4ed282SShri Abhyankar } 2466fe835674SShri Abhyankar } 24672b4ed282SShri Abhyankar ierr = PetscOptionsTail();CHKERRQ(ierr); 24682b4ed282SShri Abhyankar PetscFunctionReturn(0); 24692b4ed282SShri Abhyankar } 24702b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */ 24712b4ed282SShri Abhyankar /*MC 24728b4c83edSBarry Smith SNESVI - Various solvers for variational inequalities based on Newton's method 24732b4ed282SShri Abhyankar 24742b4ed282SShri Abhyankar Options Database: 24758b4c83edSBarry 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 24768b4c83edSBarry Smith additional variables that enforce the constraints 24778b4c83edSBarry Smith - -snes_vi_monitor - prints the number of active constraints at each iteration. 24782b4ed282SShri Abhyankar 24792b4ed282SShri Abhyankar 24802b4ed282SShri Abhyankar Level: beginner 24812b4ed282SShri Abhyankar 24822b4ed282SShri Abhyankar .seealso: SNESCreate(), SNES, SNESSetType(), SNESTR, SNESLineSearchSet(), 24832b4ed282SShri Abhyankar SNESLineSearchSetPostCheck(), SNESLineSearchNo(), SNESLineSearchCubic(), SNESLineSearchQuadratic(), 24842b4ed282SShri Abhyankar SNESLineSearchSet(), SNESLineSearchNoNorms(), SNESLineSearchSetPreCheck(), SNESLineSearchSetParams(), SNESLineSearchGetParams() 24852b4ed282SShri Abhyankar 24862b4ed282SShri Abhyankar M*/ 24872b4ed282SShri Abhyankar EXTERN_C_BEGIN 24882b4ed282SShri Abhyankar #undef __FUNCT__ 24892b4ed282SShri Abhyankar #define __FUNCT__ "SNESCreate_VI" 24907087cfbeSBarry Smith PetscErrorCode SNESCreate_VI(SNES snes) 24912b4ed282SShri Abhyankar { 24922b4ed282SShri Abhyankar PetscErrorCode ierr; 24932b4ed282SShri Abhyankar SNES_VI *vi; 24942b4ed282SShri Abhyankar 24952b4ed282SShri Abhyankar PetscFunctionBegin; 24962176524cSBarry Smith snes->ops->reset = SNESReset_VI; 24972b4ed282SShri Abhyankar snes->ops->setup = SNESSetUp_VI; 2498edafb9efSBarry Smith snes->ops->solve = SNESSolveVI_RS; 24992b4ed282SShri Abhyankar snes->ops->destroy = SNESDestroy_VI; 25002b4ed282SShri Abhyankar snes->ops->setfromoptions = SNESSetFromOptions_VI; 25012b4ed282SShri Abhyankar snes->ops->view = SNESView_VI; 25022b4ed282SShri Abhyankar snes->ops->converged = SNESDefaultConverged_VI; 25032b4ed282SShri Abhyankar 25042b4ed282SShri Abhyankar ierr = PetscNewLog(snes,SNES_VI,&vi);CHKERRQ(ierr); 25052b4ed282SShri Abhyankar snes->data = (void*)vi; 25062b4ed282SShri Abhyankar vi->alpha = 1.e-4; 25072b4ed282SShri Abhyankar vi->maxstep = 1.e8; 25082b4ed282SShri Abhyankar vi->minlambda = 1.e-12; 25097fe79bc4SShri Abhyankar vi->LineSearch = SNESLineSearchNo_VI; 25102b4ed282SShri Abhyankar vi->lsP = PETSC_NULL; 25112b4ed282SShri Abhyankar vi->postcheckstep = PETSC_NULL; 25122b4ed282SShri Abhyankar vi->postcheck = PETSC_NULL; 25132b4ed282SShri Abhyankar vi->precheckstep = PETSC_NULL; 25142b4ed282SShri Abhyankar vi->precheck = PETSC_NULL; 25152b4ed282SShri Abhyankar vi->const_tol = 2.2204460492503131e-16; 25162f63a38cSShri Abhyankar vi->checkredundancy = PETSC_NULL; 25172b4ed282SShri Abhyankar 25182b4ed282SShri Abhyankar ierr = PetscObjectComposeFunctionDynamic((PetscObject)snes,"SNESLineSearchSetMonitor_C","SNESLineSearchSetMonitor_VI",SNESLineSearchSetMonitor_VI);CHKERRQ(ierr); 25192b4ed282SShri Abhyankar ierr = PetscObjectComposeFunctionDynamic((PetscObject)snes,"SNESLineSearchSet_C","SNESLineSearchSet_VI",SNESLineSearchSet_VI);CHKERRQ(ierr); 25202b4ed282SShri Abhyankar 25212b4ed282SShri Abhyankar PetscFunctionReturn(0); 25222b4ed282SShri Abhyankar } 25232b4ed282SShri Abhyankar EXTERN_C_END 2524