1be1d678aSKris Buschelman #define PETSCMAT_DLL 2be1d678aSKris Buschelman 3f7765cecSBarry Smith /* 4b4fd4287SBarry Smith Routines to project vectors out of null spaces. 5f7765cecSBarry Smith */ 6f7765cecSBarry Smith 75cfeda75SBarry Smith #include "src/mat/matimpl.h" /*I "petscmat.h" I*/ 8e090d566SSatish Balay #include "petscsys.h" 9f7765cecSBarry Smith 10be1d678aSKris Buschelman PetscCookie PETSCMAT_DLLEXPORT MAT_NULLSPACE_COOKIE = 0; 118ba1e511SMatthew Knepley 124a2ae208SSatish Balay #undef __FUNCT__ 13*72875594SBarry Smith #define __FUNCT__ "MatNullSpaceSetFunction" 14*72875594SBarry Smith /*@C 15*72875594SBarry Smith MatNullSpaceSetFunction - set a function that removes a null space from a vector 16*72875594SBarry Smith out of null spaces. 17*72875594SBarry Smith 18*72875594SBarry Smith Collective on MatNullSpace 19*72875594SBarry Smith 20*72875594SBarry Smith Input Parameters: 21*72875594SBarry Smith + sp - the null space object 22*72875594SBarry Smith - remove - the function that removes the null space 23*72875594SBarry Smith 24*72875594SBarry Smith .keywords: PC, null space, create 25*72875594SBarry Smith 26*72875594SBarry Smith .seealso: MatNullSpaceDestroy(), MatNullSpaceRemove(), KSPSetNullSpace(), MatNullSpace, MatNullSpaceCreate() 27*72875594SBarry Smith @*/ 28*72875594SBarry Smith PetscErrorCode PETSCMAT_DLLEXPORT MatNullSpaceSetFunction(MatNullSpace sp, PetscErrorCode (*remove)(Vec)) 29*72875594SBarry Smith { 30*72875594SBarry Smith PetscFunctionBegin; 31*72875594SBarry Smith sp->remove = remove; 32*72875594SBarry Smith PetscFunctionReturn(0); 33*72875594SBarry Smith } 34*72875594SBarry Smith 35*72875594SBarry Smith #undef __FUNCT__ 364a2ae208SSatish Balay #define __FUNCT__ "MatNullSpaceCreate" 37112a2221SBarry Smith /*@C 385cfeda75SBarry Smith MatNullSpaceCreate - Creates a data structure used to project vectors 39b4fd4287SBarry Smith out of null spaces. 40f7765cecSBarry Smith 414e472627SLois Curfman McInnes Collective on MPI_Comm 424e472627SLois Curfman McInnes 43f7765cecSBarry Smith Input Parameters: 4483c3bef8SLois Curfman McInnes + comm - the MPI communicator associated with the object 4583c3bef8SLois Curfman McInnes . has_cnst - PETSC_TRUE if the null space contains the constant vector; otherwise PETSC_FALSE 46b4fd4287SBarry Smith . n - number of vectors (excluding constant vector) in null space 4783c3bef8SLois Curfman McInnes - vecs - the vectors that span the null space (excluding the constant vector); 48f7a9e4ceSBarry Smith these vectors must be orthonormal. These vectors are NOT copied, so do not change them 49f7a9e4ceSBarry Smith after this call. You should free the array that you pass in. 50f7765cecSBarry Smith 51f7765cecSBarry Smith Output Parameter: 52b4fd4287SBarry Smith . SP - the null space context 53f7765cecSBarry Smith 5483c3bef8SLois Curfman McInnes Level: advanced 5583c3bef8SLois Curfman McInnes 566e1639daSBarry Smith Users manual sections: 576e1639daSBarry Smith . sec_singular 586e1639daSBarry Smith 5983c3bef8SLois Curfman McInnes .keywords: PC, null space, create 6041a59933SSatish Balay 61*72875594SBarry Smith .seealso: MatNullSpaceDestroy(), MatNullSpaceRemove(), KSPSetNullSpace(), MatNullSpace, MatNullSpaceSetFunction() 62f7765cecSBarry Smith @*/ 63be1d678aSKris Buschelman PetscErrorCode PETSCMAT_DLLEXPORT MatNullSpaceCreate(MPI_Comm comm,PetscTruth has_cnst,PetscInt n,const Vec vecs[],MatNullSpace *SP) 64f7765cecSBarry Smith { 655cfeda75SBarry Smith MatNullSpace sp; 66dfbe8321SBarry Smith PetscErrorCode ierr; 67c1ac3661SBarry Smith PetscInt i; 68f7765cecSBarry Smith 693a40ed3dSBarry Smith PetscFunctionBegin; 7052e6d16bSBarry Smith ierr = PetscHeaderCreate(sp,_p_MatNullSpace,int,MAT_NULLSPACE_COOKIE,0,"MatNullSpace",comm,MatNullSpaceDestroy,0);CHKERRQ(ierr); 7152e6d16bSBarry Smith ierr = PetscLogObjectMemory(sp,sizeof(struct _p_MatNullSpace));CHKERRQ(ierr); 72f7765cecSBarry Smith 73b4fd4287SBarry Smith sp->has_cnst = has_cnst; 74b4fd4287SBarry Smith sp->n = n; 755cfeda75SBarry Smith sp->vec = PETSC_NULL; 76f7a9e4ceSBarry Smith if (n) { 77f7a9e4ceSBarry Smith ierr = PetscMalloc(n*sizeof(Vec),&sp->vecs);CHKERRQ(ierr); 78f7a9e4ceSBarry Smith for (i=0; i<n; i++) sp->vecs[i] = vecs[i]; 79f7a9e4ceSBarry Smith } else { 80f7a9e4ceSBarry Smith sp->vecs = 0; 81f7a9e4ceSBarry Smith } 82b4fd4287SBarry Smith 83f7a9e4ceSBarry Smith for (i=0; i<n; i++) { 84f7a9e4ceSBarry Smith ierr = PetscObjectReference((PetscObject)sp->vecs[i]);CHKERRQ(ierr); 85f7a9e4ceSBarry Smith } 86b4fd4287SBarry Smith *SP = sp; 873a40ed3dSBarry Smith PetscFunctionReturn(0); 88f7765cecSBarry Smith } 89f7765cecSBarry Smith 904a2ae208SSatish Balay #undef __FUNCT__ 914a2ae208SSatish Balay #define __FUNCT__ "MatNullSpaceDestroy" 92f7765cecSBarry Smith /*@ 935cfeda75SBarry Smith MatNullSpaceDestroy - Destroys a data structure used to project vectors 94b4fd4287SBarry Smith out of null spaces. 95b4fd4287SBarry Smith 965cfeda75SBarry Smith Collective on MatNullSpace 974e472627SLois Curfman McInnes 98b4fd4287SBarry Smith Input Parameter: 99b9756687SLois Curfman McInnes . sp - the null space context to be destroyed 100b9756687SLois Curfman McInnes 101b9756687SLois Curfman McInnes Level: advanced 102b4fd4287SBarry Smith 10383c3bef8SLois Curfman McInnes .keywords: PC, null space, destroy 10441a59933SSatish Balay 105*72875594SBarry Smith .seealso: MatNullSpaceCreate(), MatNullSpaceRemove(), MatNullSpaceSetFunction() 106b4fd4287SBarry Smith @*/ 107be1d678aSKris Buschelman PetscErrorCode PETSCMAT_DLLEXPORT MatNullSpaceDestroy(MatNullSpace sp) 108b4fd4287SBarry Smith { 109dfbe8321SBarry Smith PetscErrorCode ierr; 11085614651SBarry Smith 1115cfeda75SBarry Smith PetscFunctionBegin; 11285614651SBarry Smith if (--sp->refct > 0) PetscFunctionReturn(0); 11385614651SBarry Smith 1145cfeda75SBarry Smith if (sp->vec) {ierr = VecDestroy(sp->vec);CHKERRQ(ierr);} 115f7a9e4ceSBarry Smith if (sp->vecs) { 116f7a9e4ceSBarry Smith ierr = VecDestroyVecs(sp->vecs,sp->n);CHKERRQ(ierr); 117f7a9e4ceSBarry Smith } 118d38fa0fbSBarry Smith ierr = PetscHeaderDestroy(sp);CHKERRQ(ierr); 1193a40ed3dSBarry Smith PetscFunctionReturn(0); 120b4fd4287SBarry Smith } 121b4fd4287SBarry Smith 1224a2ae208SSatish Balay #undef __FUNCT__ 1234a2ae208SSatish Balay #define __FUNCT__ "MatNullSpaceRemove" 124b4fd4287SBarry Smith /*@ 1255cfeda75SBarry Smith MatNullSpaceRemove - Removes all the components of a null space from a vector. 126f7765cecSBarry Smith 1275cfeda75SBarry Smith Collective on MatNullSpace 128f7765cecSBarry Smith 1294e472627SLois Curfman McInnes Input Parameters: 1304e472627SLois Curfman McInnes + sp - the null space context 1314e7234bfSBarry Smith . vec - the vector from which the null space is to be removed 1325fcf39f4SBarry Smith - out - if this is requested (not PETSC_NULL) then this is a vector with the null space removed otherwise 1334e7234bfSBarry Smith the removal is done in-place (in vec) 1344e7234bfSBarry Smith 1354e7234bfSBarry Smith 1364e472627SLois Curfman McInnes 137b9756687SLois Curfman McInnes Level: advanced 138b9756687SLois Curfman McInnes 13983c3bef8SLois Curfman McInnes .keywords: PC, null space, remove 14041a59933SSatish Balay 141*72875594SBarry Smith .seealso: MatNullSpaceCreate(), MatNullSpaceDestroy(), MatNullSpaceSetFunction() 142f7765cecSBarry Smith @*/ 143be1d678aSKris Buschelman PetscErrorCode PETSCMAT_DLLEXPORT MatNullSpaceRemove(MatNullSpace sp,Vec vec,Vec *out) 144f7765cecSBarry Smith { 14587828ca2SBarry Smith PetscScalar sum; 1466849ba73SBarry Smith PetscErrorCode ierr; 147c1ac3661SBarry Smith PetscInt j,n = sp->n,N; 1485cfeda75SBarry Smith Vec l = vec; 149f7765cecSBarry Smith 1503a40ed3dSBarry Smith PetscFunctionBegin; 1515cfeda75SBarry Smith if (out) { 1525cfeda75SBarry Smith if (!sp->vec) { 1535cfeda75SBarry Smith ierr = VecDuplicate(vec,&sp->vec);CHKERRQ(ierr); 1545cfeda75SBarry Smith } 1555cfeda75SBarry Smith *out = sp->vec; 1565cfeda75SBarry Smith ierr = VecCopy(vec,*out);CHKERRQ(ierr); 1575cfeda75SBarry Smith l = *out; 1585cfeda75SBarry Smith } 1595cfeda75SBarry Smith 160b4fd4287SBarry Smith if (sp->has_cnst) { 1615cfeda75SBarry Smith ierr = VecSum(l,&sum);CHKERRQ(ierr); 1625cfeda75SBarry Smith ierr = VecGetSize(l,&N);CHKERRQ(ierr); 16318a7d68fSSatish Balay sum = sum/(-1.0*N); 1642dcb1b2aSMatthew Knepley ierr = VecShift(l,sum);CHKERRQ(ierr); 165f7765cecSBarry Smith } 166b4fd4287SBarry Smith 167b4fd4287SBarry Smith for (j=0; j<n; j++) { 1685cfeda75SBarry Smith ierr = VecDot(l,sp->vecs[j],&sum);CHKERRQ(ierr); 169b4fd4287SBarry Smith sum = -sum; 1702dcb1b2aSMatthew Knepley ierr = VecAXPY(l,sum,sp->vecs[j]);CHKERRQ(ierr); 171f7765cecSBarry Smith } 172b4fd4287SBarry Smith 173*72875594SBarry Smith if (sp->remove){ 174*72875594SBarry Smith ierr = (*sp->remove)(l); 175*72875594SBarry Smith } 1763a40ed3dSBarry Smith PetscFunctionReturn(0); 177f7765cecSBarry Smith } 178a2e34c3dSBarry Smith 1794a2ae208SSatish Balay #undef __FUNCT__ 1804a2ae208SSatish Balay #define __FUNCT__ "MatNullSpaceTest" 181a2e34c3dSBarry Smith /*@ 182a2e34c3dSBarry Smith MatNullSpaceTest - Tests if the claimed null space is really a 183a2e34c3dSBarry Smith null space of a matrix 184a2e34c3dSBarry Smith 185a2e34c3dSBarry Smith Collective on MatNullSpace 186a2e34c3dSBarry Smith 187a2e34c3dSBarry Smith Input Parameters: 188a2e34c3dSBarry Smith + sp - the null space context 189a2e34c3dSBarry Smith - mat - the matrix 190a2e34c3dSBarry Smith 191a2e34c3dSBarry Smith Level: advanced 192a2e34c3dSBarry Smith 193a2e34c3dSBarry Smith .keywords: PC, null space, remove 194a2e34c3dSBarry Smith 195*72875594SBarry Smith .seealso: MatNullSpaceCreate(), MatNullSpaceDestroy(), MatNullSpaceSetFunction() 196a2e34c3dSBarry Smith @*/ 197be1d678aSKris Buschelman PetscErrorCode PETSCMAT_DLLEXPORT MatNullSpaceTest(MatNullSpace sp,Mat mat) 198a2e34c3dSBarry Smith { 19987828ca2SBarry Smith PetscScalar sum; 2008bb6bcc5SSatish Balay PetscReal nrm; 201c1ac3661SBarry Smith PetscInt j,n = sp->n,N,m; 2026849ba73SBarry Smith PetscErrorCode ierr; 203a2e34c3dSBarry Smith Vec l,r; 204a2e34c3dSBarry Smith MPI_Comm comm = sp->comm; 205a2e34c3dSBarry Smith PetscTruth flg1,flg2; 206a2e34c3dSBarry Smith 207a2e34c3dSBarry Smith PetscFunctionBegin; 208b0a32e0cSBarry Smith ierr = PetscOptionsHasName(PETSC_NULL,"-mat_null_space_test_view",&flg1);CHKERRQ(ierr); 209b0a32e0cSBarry Smith ierr = PetscOptionsHasName(PETSC_NULL,"-mat_null_space_test_view_draw",&flg2);CHKERRQ(ierr); 210a2e34c3dSBarry Smith 211a2e34c3dSBarry Smith if (!sp->vec) { 212a2e34c3dSBarry Smith if (n) { 213a2e34c3dSBarry Smith ierr = VecDuplicate(sp->vecs[0],&sp->vec);CHKERRQ(ierr); 214a2e34c3dSBarry Smith } else { 215a2e34c3dSBarry Smith ierr = MatGetLocalSize(mat,&m,PETSC_NULL);CHKERRQ(ierr); 216a2e34c3dSBarry Smith ierr = VecCreateMPI(sp->comm,m,PETSC_DETERMINE,&sp->vec);CHKERRQ(ierr); 217a2e34c3dSBarry Smith } 218a2e34c3dSBarry Smith } 219a2e34c3dSBarry Smith l = sp->vec; 220a2e34c3dSBarry Smith 221a2e34c3dSBarry Smith if (sp->has_cnst) { 222a2e34c3dSBarry Smith ierr = VecDuplicate(l,&r);CHKERRQ(ierr); 223a2e34c3dSBarry Smith ierr = VecGetSize(l,&N);CHKERRQ(ierr); 224a2e34c3dSBarry Smith sum = 1.0/N; 2252dcb1b2aSMatthew Knepley ierr = VecSet(l,sum);CHKERRQ(ierr); 226a2e34c3dSBarry Smith ierr = MatMult(mat,l,r);CHKERRQ(ierr); 2278bb6bcc5SSatish Balay ierr = VecNorm(r,NORM_2,&nrm);CHKERRQ(ierr); 2288bb6bcc5SSatish Balay if (nrm < 1.e-7) {ierr = PetscPrintf(comm,"Constants are likely null vector");CHKERRQ(ierr);} 229a2e34c3dSBarry Smith else {ierr = PetscPrintf(comm,"Constants are unlikely null vector ");CHKERRQ(ierr);} 2308bb6bcc5SSatish Balay ierr = PetscPrintf(comm,"|| A * 1 || = %g\n",nrm);CHKERRQ(ierr); 231b0a32e0cSBarry Smith if (nrm > 1.e-7 && flg1) {ierr = VecView(r,PETSC_VIEWER_STDOUT_(comm));CHKERRQ(ierr);} 232b0a32e0cSBarry Smith if (nrm > 1.e-7 && flg2) {ierr = VecView(r,PETSC_VIEWER_DRAW_(comm));CHKERRQ(ierr);} 233a2e34c3dSBarry Smith ierr = VecDestroy(r);CHKERRQ(ierr); 234a2e34c3dSBarry Smith } 235a2e34c3dSBarry Smith 236a2e34c3dSBarry Smith for (j=0; j<n; j++) { 237a2e34c3dSBarry Smith ierr = (*mat->ops->mult)(mat,sp->vecs[j],l);CHKERRQ(ierr); 2388bb6bcc5SSatish Balay ierr = VecNorm(l,NORM_2,&nrm);CHKERRQ(ierr); 23977431f27SBarry Smith if (nrm < 1.e-7) {ierr = PetscPrintf(comm,"Null vector %D is likely null vector",j);CHKERRQ(ierr);} 24077431f27SBarry Smith else {ierr = PetscPrintf(comm,"Null vector %D unlikely null vector ",j);CHKERRQ(ierr);} 24177431f27SBarry Smith ierr = PetscPrintf(comm,"|| A * v[%D] || = %g\n",j,nrm);CHKERRQ(ierr); 242b0a32e0cSBarry Smith if (nrm > 1.e-7 && flg1) {ierr = VecView(l,PETSC_VIEWER_STDOUT_(comm));CHKERRQ(ierr);} 243b0a32e0cSBarry Smith if (nrm > 1.e-7 && flg2) {ierr = VecView(l,PETSC_VIEWER_DRAW_(comm));CHKERRQ(ierr);} 244a2e34c3dSBarry Smith } 245a2e34c3dSBarry Smith 246*72875594SBarry Smith if (sp->remove){ 247*72875594SBarry Smith SETERRQ(PETSC_ERR_SUP,"Cannot test a null space provided as a function with MatNullSpaceSetFunction()"); 248*72875594SBarry Smith } 249*72875594SBarry Smith 250a2e34c3dSBarry Smith PetscFunctionReturn(0); 251a2e34c3dSBarry Smith } 252a2e34c3dSBarry Smith 253