1be1d678aSKris Buschelman #define PETSCMAT_DLL 2be1d678aSKris Buschelman 3f7765cecSBarry Smith /* 4b4fd4287SBarry Smith Routines to project vectors out of null spaces. 5f7765cecSBarry Smith */ 6f7765cecSBarry Smith 7b9147fbbSdalcinl #include "include/private/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__ 1372875594SBarry Smith #define __FUNCT__ "MatNullSpaceSetFunction" 1472875594SBarry Smith /*@C 1572875594SBarry Smith MatNullSpaceSetFunction - set a function that removes a null space from a vector 1672875594SBarry Smith out of null spaces. 1772875594SBarry Smith 1872875594SBarry Smith Collective on MatNullSpace 1972875594SBarry Smith 2072875594SBarry Smith Input Parameters: 2172875594SBarry Smith + sp - the null space object 229dbe9a8aSBarry Smith . rem - the function that removes the null space 239dbe9a8aSBarry Smith - ctx - context for the remove function 2472875594SBarry Smith 25658c74aaSSatish Balay Level: advanced 2672875594SBarry Smith 27658c74aaSSatish Balay .keywords: PC, null space, create 28b47fd4b1SSatish Balay 2972875594SBarry Smith .seealso: MatNullSpaceDestroy(), MatNullSpaceRemove(), KSPSetNullSpace(), MatNullSpace, MatNullSpaceCreate() 3072875594SBarry Smith @*/ 319dbe9a8aSBarry Smith PetscErrorCode PETSCMAT_DLLEXPORT MatNullSpaceSetFunction(MatNullSpace sp, PetscErrorCode (*rem)(Vec,void*),void *ctx) 3272875594SBarry Smith { 3372875594SBarry Smith PetscFunctionBegin; 349dbe9a8aSBarry Smith sp->remove = rem; 359dbe9a8aSBarry Smith sp->rmctx = ctx; 3672875594SBarry Smith PetscFunctionReturn(0); 3772875594SBarry Smith } 3872875594SBarry Smith 3972875594SBarry Smith #undef __FUNCT__ 404a2ae208SSatish Balay #define __FUNCT__ "MatNullSpaceCreate" 41f39d8e23SSatish Balay /*@ 425cfeda75SBarry Smith MatNullSpaceCreate - Creates a data structure used to project vectors 43b4fd4287SBarry Smith out of null spaces. 44f7765cecSBarry Smith 454e472627SLois Curfman McInnes Collective on MPI_Comm 464e472627SLois Curfman McInnes 47f7765cecSBarry Smith Input Parameters: 4883c3bef8SLois Curfman McInnes + comm - the MPI communicator associated with the object 4983c3bef8SLois Curfman McInnes . has_cnst - PETSC_TRUE if the null space contains the constant vector; otherwise PETSC_FALSE 50b4fd4287SBarry Smith . n - number of vectors (excluding constant vector) in null space 5183c3bef8SLois Curfman McInnes - vecs - the vectors that span the null space (excluding the constant vector); 52f7a9e4ceSBarry Smith these vectors must be orthonormal. These vectors are NOT copied, so do not change them 53f7a9e4ceSBarry Smith after this call. You should free the array that you pass in. 54f7765cecSBarry Smith 55f7765cecSBarry Smith Output Parameter: 56b4fd4287SBarry Smith . SP - the null space context 57f7765cecSBarry Smith 5883c3bef8SLois Curfman McInnes Level: advanced 5983c3bef8SLois Curfman McInnes 606e1639daSBarry Smith Users manual sections: 616e1639daSBarry Smith . sec_singular 626e1639daSBarry Smith 6383c3bef8SLois Curfman McInnes .keywords: PC, null space, create 6441a59933SSatish Balay 6572875594SBarry Smith .seealso: MatNullSpaceDestroy(), MatNullSpaceRemove(), KSPSetNullSpace(), MatNullSpace, MatNullSpaceSetFunction() 66f7765cecSBarry Smith @*/ 67be1d678aSKris Buschelman PetscErrorCode PETSCMAT_DLLEXPORT MatNullSpaceCreate(MPI_Comm comm,PetscTruth has_cnst,PetscInt n,const Vec vecs[],MatNullSpace *SP) 68f7765cecSBarry Smith { 695cfeda75SBarry Smith MatNullSpace sp; 70dfbe8321SBarry Smith PetscErrorCode ierr; 71c1ac3661SBarry Smith PetscInt i; 72f7765cecSBarry Smith 733a40ed3dSBarry Smith PetscFunctionBegin; 74574b3360SMatthew Knepley if (n) PetscValidPointer(vecs,4); 75574b3360SMatthew Knepley for (i=0; i<n; i++) PetscValidHeaderSpecific(vecs[i],VEC_COOKIE,4); 76574b3360SMatthew Knepley PetscValidPointer(SP,5); 77574b3360SMatthew Knepley 78574b3360SMatthew Knepley *SP = PETSC_NULL; 79574b3360SMatthew Knepley #ifndef PETSC_USE_DYNAMIC_LIBRARIES 80574b3360SMatthew Knepley ierr = MatInitializePackage(PETSC_NULL);CHKERRQ(ierr); 81574b3360SMatthew Knepley #endif 82574b3360SMatthew Knepley 8352e6d16bSBarry Smith ierr = PetscHeaderCreate(sp,_p_MatNullSpace,int,MAT_NULLSPACE_COOKIE,0,"MatNullSpace",comm,MatNullSpaceDestroy,0);CHKERRQ(ierr); 8452e6d16bSBarry Smith ierr = PetscLogObjectMemory(sp,sizeof(struct _p_MatNullSpace));CHKERRQ(ierr); 85f7765cecSBarry Smith 86b4fd4287SBarry Smith sp->has_cnst = has_cnst; 87b4fd4287SBarry Smith sp->n = n; 885cfeda75SBarry Smith sp->vec = PETSC_NULL; 89f7a9e4ceSBarry Smith if (n) { 90f7a9e4ceSBarry Smith ierr = PetscMalloc(n*sizeof(Vec),&sp->vecs);CHKERRQ(ierr); 91f7a9e4ceSBarry Smith for (i=0; i<n; i++) sp->vecs[i] = vecs[i]; 92f7a9e4ceSBarry Smith } else { 93f7a9e4ceSBarry Smith sp->vecs = 0; 94f7a9e4ceSBarry Smith } 95b4fd4287SBarry Smith 96f7a9e4ceSBarry Smith for (i=0; i<n; i++) { 97f7a9e4ceSBarry Smith ierr = PetscObjectReference((PetscObject)sp->vecs[i]);CHKERRQ(ierr); 98f7a9e4ceSBarry Smith } 99b4fd4287SBarry Smith *SP = sp; 1003a40ed3dSBarry Smith PetscFunctionReturn(0); 101f7765cecSBarry Smith } 102f7765cecSBarry Smith 1034a2ae208SSatish Balay #undef __FUNCT__ 1044a2ae208SSatish Balay #define __FUNCT__ "MatNullSpaceDestroy" 105f7765cecSBarry Smith /*@ 1065cfeda75SBarry Smith MatNullSpaceDestroy - Destroys a data structure used to project vectors 107b4fd4287SBarry Smith out of null spaces. 108b4fd4287SBarry Smith 1095cfeda75SBarry Smith Collective on MatNullSpace 1104e472627SLois Curfman McInnes 111b4fd4287SBarry Smith Input Parameter: 112b9756687SLois Curfman McInnes . sp - the null space context to be destroyed 113b9756687SLois Curfman McInnes 114b9756687SLois Curfman McInnes Level: advanced 115b4fd4287SBarry Smith 11683c3bef8SLois Curfman McInnes .keywords: PC, null space, destroy 11741a59933SSatish Balay 11872875594SBarry Smith .seealso: MatNullSpaceCreate(), MatNullSpaceRemove(), MatNullSpaceSetFunction() 119b4fd4287SBarry Smith @*/ 120be1d678aSKris Buschelman PetscErrorCode PETSCMAT_DLLEXPORT MatNullSpaceDestroy(MatNullSpace sp) 121b4fd4287SBarry Smith { 122dfbe8321SBarry Smith PetscErrorCode ierr; 12385614651SBarry Smith 1245cfeda75SBarry Smith PetscFunctionBegin; 12585614651SBarry Smith if (--sp->refct > 0) PetscFunctionReturn(0); 12685614651SBarry Smith 1275cfeda75SBarry Smith if (sp->vec) {ierr = VecDestroy(sp->vec);CHKERRQ(ierr);} 128f7a9e4ceSBarry Smith if (sp->vecs) { 129f7a9e4ceSBarry Smith ierr = VecDestroyVecs(sp->vecs,sp->n);CHKERRQ(ierr); 130f7a9e4ceSBarry Smith } 131d38fa0fbSBarry Smith ierr = PetscHeaderDestroy(sp);CHKERRQ(ierr); 1323a40ed3dSBarry Smith PetscFunctionReturn(0); 133b4fd4287SBarry Smith } 134b4fd4287SBarry Smith 1354a2ae208SSatish Balay #undef __FUNCT__ 1364a2ae208SSatish Balay #define __FUNCT__ "MatNullSpaceRemove" 137b4fd4287SBarry Smith /*@ 1385cfeda75SBarry Smith MatNullSpaceRemove - Removes all the components of a null space from a vector. 139f7765cecSBarry Smith 1405cfeda75SBarry Smith Collective on MatNullSpace 141f7765cecSBarry Smith 1424e472627SLois Curfman McInnes Input Parameters: 1434e472627SLois Curfman McInnes + sp - the null space context 1444e7234bfSBarry Smith . vec - the vector from which the null space is to be removed 1455fcf39f4SBarry Smith - out - if this is requested (not PETSC_NULL) then this is a vector with the null space removed otherwise 1464e7234bfSBarry Smith the removal is done in-place (in vec) 1474e7234bfSBarry Smith 148db090513SMatthew Knepley Note: The user is not responsible for the vector returned and should not destroy it. 1494e472627SLois Curfman McInnes 150b9756687SLois Curfman McInnes Level: advanced 151b9756687SLois Curfman McInnes 15283c3bef8SLois Curfman McInnes .keywords: PC, null space, remove 15341a59933SSatish Balay 15472875594SBarry Smith .seealso: MatNullSpaceCreate(), MatNullSpaceDestroy(), MatNullSpaceSetFunction() 155f7765cecSBarry Smith @*/ 156be1d678aSKris Buschelman PetscErrorCode PETSCMAT_DLLEXPORT MatNullSpaceRemove(MatNullSpace sp,Vec vec,Vec *out) 157f7765cecSBarry Smith { 15887828ca2SBarry Smith PetscScalar sum; 1596849ba73SBarry Smith PetscErrorCode ierr; 160c1ac3661SBarry Smith PetscInt j,n = sp->n,N; 1615cfeda75SBarry Smith Vec l = vec; 162f7765cecSBarry Smith 1633a40ed3dSBarry Smith PetscFunctionBegin; 1643cd8ff7eSMatthew Knepley PetscValidHeaderSpecific(sp,MAT_NULLSPACE_COOKIE,1); 1653cd8ff7eSMatthew Knepley PetscValidHeaderSpecific(vec,VEC_COOKIE,2); 1663cd8ff7eSMatthew Knepley 1675cfeda75SBarry Smith if (out) { 1683cd8ff7eSMatthew Knepley PetscValidPointer(out,3); 1695cfeda75SBarry Smith if (!sp->vec) { 1705cfeda75SBarry Smith ierr = VecDuplicate(vec,&sp->vec);CHKERRQ(ierr); 1715cfeda75SBarry Smith } 1725cfeda75SBarry Smith *out = sp->vec; 1735cfeda75SBarry Smith ierr = VecCopy(vec,*out);CHKERRQ(ierr); 1745cfeda75SBarry Smith l = *out; 1755cfeda75SBarry Smith } 1765cfeda75SBarry Smith 177b4fd4287SBarry Smith if (sp->has_cnst) { 1785cfeda75SBarry Smith ierr = VecSum(l,&sum);CHKERRQ(ierr); 1795cfeda75SBarry Smith ierr = VecGetSize(l,&N);CHKERRQ(ierr); 18018a7d68fSSatish Balay sum = sum/(-1.0*N); 1812dcb1b2aSMatthew Knepley ierr = VecShift(l,sum);CHKERRQ(ierr); 182f7765cecSBarry Smith } 183b4fd4287SBarry Smith 184b4fd4287SBarry Smith for (j=0; j<n; j++) { 1855cfeda75SBarry Smith ierr = VecDot(l,sp->vecs[j],&sum);CHKERRQ(ierr); 1865eb3c597SBarry Smith ierr = VecAXPY(l,-sum,sp->vecs[j]);CHKERRQ(ierr); 187f7765cecSBarry Smith } 188b4fd4287SBarry Smith 18972875594SBarry Smith if (sp->remove){ 190ce0145b1SBarry Smith ierr = (*sp->remove)(l,sp->rmctx); 19172875594SBarry Smith } 1923a40ed3dSBarry Smith PetscFunctionReturn(0); 193f7765cecSBarry Smith } 194a2e34c3dSBarry Smith 1954a2ae208SSatish Balay #undef __FUNCT__ 1964a2ae208SSatish Balay #define __FUNCT__ "MatNullSpaceTest" 197a2e34c3dSBarry Smith /*@ 198a2e34c3dSBarry Smith MatNullSpaceTest - Tests if the claimed null space is really a 199a2e34c3dSBarry Smith null space of a matrix 200a2e34c3dSBarry Smith 201a2e34c3dSBarry Smith Collective on MatNullSpace 202a2e34c3dSBarry Smith 203a2e34c3dSBarry Smith Input Parameters: 204a2e34c3dSBarry Smith + sp - the null space context 205a2e34c3dSBarry Smith - mat - the matrix 206a2e34c3dSBarry Smith 207a2e34c3dSBarry Smith Level: advanced 208a2e34c3dSBarry Smith 209a2e34c3dSBarry Smith .keywords: PC, null space, remove 210a2e34c3dSBarry Smith 21172875594SBarry Smith .seealso: MatNullSpaceCreate(), MatNullSpaceDestroy(), MatNullSpaceSetFunction() 212a2e34c3dSBarry Smith @*/ 213be1d678aSKris Buschelman PetscErrorCode PETSCMAT_DLLEXPORT MatNullSpaceTest(MatNullSpace sp,Mat mat) 214a2e34c3dSBarry Smith { 21587828ca2SBarry Smith PetscScalar sum; 2168bb6bcc5SSatish Balay PetscReal nrm; 217c1ac3661SBarry Smith PetscInt j,n = sp->n,N,m; 2186849ba73SBarry Smith PetscErrorCode ierr; 219a2e34c3dSBarry Smith Vec l,r; 220a2e34c3dSBarry Smith MPI_Comm comm = sp->comm; 221a2e34c3dSBarry Smith PetscTruth flg1,flg2; 222*3050cee2SBarry Smith PetscViewer viewer; 223a2e34c3dSBarry Smith 224a2e34c3dSBarry Smith PetscFunctionBegin; 225b0a32e0cSBarry Smith ierr = PetscOptionsHasName(PETSC_NULL,"-mat_null_space_test_view",&flg1);CHKERRQ(ierr); 226b0a32e0cSBarry Smith ierr = PetscOptionsHasName(PETSC_NULL,"-mat_null_space_test_view_draw",&flg2);CHKERRQ(ierr); 227a2e34c3dSBarry Smith 228a2e34c3dSBarry Smith if (!sp->vec) { 229a2e34c3dSBarry Smith if (n) { 230a2e34c3dSBarry Smith ierr = VecDuplicate(sp->vecs[0],&sp->vec);CHKERRQ(ierr); 231a2e34c3dSBarry Smith } else { 232a2e34c3dSBarry Smith ierr = MatGetLocalSize(mat,&m,PETSC_NULL);CHKERRQ(ierr); 233a2e34c3dSBarry Smith ierr = VecCreateMPI(sp->comm,m,PETSC_DETERMINE,&sp->vec);CHKERRQ(ierr); 234a2e34c3dSBarry Smith } 235a2e34c3dSBarry Smith } 236a2e34c3dSBarry Smith l = sp->vec; 237a2e34c3dSBarry Smith 238*3050cee2SBarry Smith ierr = PetscViewerASCIIGetStdout(comm,&viewer);CHKERRQ(ierr); 239a2e34c3dSBarry Smith if (sp->has_cnst) { 240a2e34c3dSBarry Smith ierr = VecDuplicate(l,&r);CHKERRQ(ierr); 241a2e34c3dSBarry Smith ierr = VecGetSize(l,&N);CHKERRQ(ierr); 242a2e34c3dSBarry Smith sum = 1.0/N; 2432dcb1b2aSMatthew Knepley ierr = VecSet(l,sum);CHKERRQ(ierr); 244a2e34c3dSBarry Smith ierr = MatMult(mat,l,r);CHKERRQ(ierr); 2458bb6bcc5SSatish Balay ierr = VecNorm(r,NORM_2,&nrm);CHKERRQ(ierr); 2468bb6bcc5SSatish Balay if (nrm < 1.e-7) {ierr = PetscPrintf(comm,"Constants are likely null vector");CHKERRQ(ierr);} 247a2e34c3dSBarry Smith else {ierr = PetscPrintf(comm,"Constants are unlikely null vector ");CHKERRQ(ierr);} 248a83599f4SBarry Smith ierr = PetscPrintf(comm,"|| A * 1 || = %G\n",nrm);CHKERRQ(ierr); 249*3050cee2SBarry Smith if (nrm > 1.e-7 && flg1) {ierr = VecView(r,viewer);CHKERRQ(ierr);} 250*3050cee2SBarry Smith if (nrm > 1.e-7 && flg2) {ierr = VecView(r,viewer);CHKERRQ(ierr);} 251a2e34c3dSBarry Smith ierr = VecDestroy(r);CHKERRQ(ierr); 252a2e34c3dSBarry Smith } 253a2e34c3dSBarry Smith 254a2e34c3dSBarry Smith for (j=0; j<n; j++) { 255a2e34c3dSBarry Smith ierr = (*mat->ops->mult)(mat,sp->vecs[j],l);CHKERRQ(ierr); 2568bb6bcc5SSatish Balay ierr = VecNorm(l,NORM_2,&nrm);CHKERRQ(ierr); 25777431f27SBarry Smith if (nrm < 1.e-7) {ierr = PetscPrintf(comm,"Null vector %D is likely null vector",j);CHKERRQ(ierr);} 25877431f27SBarry Smith else {ierr = PetscPrintf(comm,"Null vector %D unlikely null vector ",j);CHKERRQ(ierr);} 259a83599f4SBarry Smith ierr = PetscPrintf(comm,"|| A * v[%D] || = %G\n",j,nrm);CHKERRQ(ierr); 260*3050cee2SBarry Smith if (nrm > 1.e-7 && flg1) {ierr = VecView(l,viewer);CHKERRQ(ierr);} 261*3050cee2SBarry Smith if (nrm > 1.e-7 && flg2) {ierr = VecView(l,viewer);CHKERRQ(ierr);} 262a2e34c3dSBarry Smith } 263a2e34c3dSBarry Smith 26472875594SBarry Smith if (sp->remove){ 26572875594SBarry Smith SETERRQ(PETSC_ERR_SUP,"Cannot test a null space provided as a function with MatNullSpaceSetFunction()"); 26672875594SBarry Smith } 26772875594SBarry Smith 268a2e34c3dSBarry Smith PetscFunctionReturn(0); 269a2e34c3dSBarry Smith } 270a2e34c3dSBarry Smith 271