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__ 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 22*9dbe9a8aSBarry Smith . rem - the function that removes the null space 23*9dbe9a8aSBarry Smith - ctx - context for the remove function 2472875594SBarry Smith 2572875594SBarry Smith .keywords: PC, null space, create 2672875594SBarry Smith 2772875594SBarry Smith .seealso: MatNullSpaceDestroy(), MatNullSpaceRemove(), KSPSetNullSpace(), MatNullSpace, MatNullSpaceCreate() 2872875594SBarry Smith @*/ 29*9dbe9a8aSBarry Smith PetscErrorCode PETSCMAT_DLLEXPORT MatNullSpaceSetFunction(MatNullSpace sp, PetscErrorCode (*rem)(Vec,void*),void *ctx) 3072875594SBarry Smith { 3172875594SBarry Smith PetscFunctionBegin; 32*9dbe9a8aSBarry Smith sp->remove = rem; 33*9dbe9a8aSBarry Smith sp->rmctx = ctx; 3472875594SBarry Smith PetscFunctionReturn(0); 3572875594SBarry Smith } 3672875594SBarry Smith 3772875594SBarry Smith #undef __FUNCT__ 384a2ae208SSatish Balay #define __FUNCT__ "MatNullSpaceCreate" 39f39d8e23SSatish Balay /*@ 405cfeda75SBarry Smith MatNullSpaceCreate - Creates a data structure used to project vectors 41b4fd4287SBarry Smith out of null spaces. 42f7765cecSBarry Smith 434e472627SLois Curfman McInnes Collective on MPI_Comm 444e472627SLois Curfman McInnes 45f7765cecSBarry Smith Input Parameters: 4683c3bef8SLois Curfman McInnes + comm - the MPI communicator associated with the object 4783c3bef8SLois Curfman McInnes . has_cnst - PETSC_TRUE if the null space contains the constant vector; otherwise PETSC_FALSE 48b4fd4287SBarry Smith . n - number of vectors (excluding constant vector) in null space 4983c3bef8SLois Curfman McInnes - vecs - the vectors that span the null space (excluding the constant vector); 50f7a9e4ceSBarry Smith these vectors must be orthonormal. These vectors are NOT copied, so do not change them 51f7a9e4ceSBarry Smith after this call. You should free the array that you pass in. 52f7765cecSBarry Smith 53f7765cecSBarry Smith Output Parameter: 54b4fd4287SBarry Smith . SP - the null space context 55f7765cecSBarry Smith 5683c3bef8SLois Curfman McInnes Level: advanced 5783c3bef8SLois Curfman McInnes 586e1639daSBarry Smith Users manual sections: 596e1639daSBarry Smith . sec_singular 606e1639daSBarry Smith 6183c3bef8SLois Curfman McInnes .keywords: PC, null space, create 6241a59933SSatish Balay 6372875594SBarry Smith .seealso: MatNullSpaceDestroy(), MatNullSpaceRemove(), KSPSetNullSpace(), MatNullSpace, MatNullSpaceSetFunction() 64f7765cecSBarry Smith @*/ 65be1d678aSKris Buschelman PetscErrorCode PETSCMAT_DLLEXPORT MatNullSpaceCreate(MPI_Comm comm,PetscTruth has_cnst,PetscInt n,const Vec vecs[],MatNullSpace *SP) 66f7765cecSBarry Smith { 675cfeda75SBarry Smith MatNullSpace sp; 68dfbe8321SBarry Smith PetscErrorCode ierr; 69c1ac3661SBarry Smith PetscInt i; 70f7765cecSBarry Smith 713a40ed3dSBarry Smith PetscFunctionBegin; 72574b3360SMatthew Knepley if (n) PetscValidPointer(vecs,4); 73574b3360SMatthew Knepley for (i=0; i<n; i++) PetscValidHeaderSpecific(vecs[i],VEC_COOKIE,4); 74574b3360SMatthew Knepley PetscValidPointer(SP,5); 75574b3360SMatthew Knepley 76574b3360SMatthew Knepley *SP = PETSC_NULL; 77574b3360SMatthew Knepley #ifndef PETSC_USE_DYNAMIC_LIBRARIES 78574b3360SMatthew Knepley ierr = MatInitializePackage(PETSC_NULL);CHKERRQ(ierr); 79574b3360SMatthew Knepley #endif 80574b3360SMatthew Knepley 8152e6d16bSBarry Smith ierr = PetscHeaderCreate(sp,_p_MatNullSpace,int,MAT_NULLSPACE_COOKIE,0,"MatNullSpace",comm,MatNullSpaceDestroy,0);CHKERRQ(ierr); 8252e6d16bSBarry Smith ierr = PetscLogObjectMemory(sp,sizeof(struct _p_MatNullSpace));CHKERRQ(ierr); 83f7765cecSBarry Smith 84b4fd4287SBarry Smith sp->has_cnst = has_cnst; 85b4fd4287SBarry Smith sp->n = n; 865cfeda75SBarry Smith sp->vec = PETSC_NULL; 87f7a9e4ceSBarry Smith if (n) { 88f7a9e4ceSBarry Smith ierr = PetscMalloc(n*sizeof(Vec),&sp->vecs);CHKERRQ(ierr); 89f7a9e4ceSBarry Smith for (i=0; i<n; i++) sp->vecs[i] = vecs[i]; 90f7a9e4ceSBarry Smith } else { 91f7a9e4ceSBarry Smith sp->vecs = 0; 92f7a9e4ceSBarry Smith } 93b4fd4287SBarry Smith 94f7a9e4ceSBarry Smith for (i=0; i<n; i++) { 95f7a9e4ceSBarry Smith ierr = PetscObjectReference((PetscObject)sp->vecs[i]);CHKERRQ(ierr); 96f7a9e4ceSBarry Smith } 97b4fd4287SBarry Smith *SP = sp; 983a40ed3dSBarry Smith PetscFunctionReturn(0); 99f7765cecSBarry Smith } 100f7765cecSBarry Smith 1014a2ae208SSatish Balay #undef __FUNCT__ 1024a2ae208SSatish Balay #define __FUNCT__ "MatNullSpaceDestroy" 103f7765cecSBarry Smith /*@ 1045cfeda75SBarry Smith MatNullSpaceDestroy - Destroys a data structure used to project vectors 105b4fd4287SBarry Smith out of null spaces. 106b4fd4287SBarry Smith 1075cfeda75SBarry Smith Collective on MatNullSpace 1084e472627SLois Curfman McInnes 109b4fd4287SBarry Smith Input Parameter: 110b9756687SLois Curfman McInnes . sp - the null space context to be destroyed 111b9756687SLois Curfman McInnes 112b9756687SLois Curfman McInnes Level: advanced 113b4fd4287SBarry Smith 11483c3bef8SLois Curfman McInnes .keywords: PC, null space, destroy 11541a59933SSatish Balay 11672875594SBarry Smith .seealso: MatNullSpaceCreate(), MatNullSpaceRemove(), MatNullSpaceSetFunction() 117b4fd4287SBarry Smith @*/ 118be1d678aSKris Buschelman PetscErrorCode PETSCMAT_DLLEXPORT MatNullSpaceDestroy(MatNullSpace sp) 119b4fd4287SBarry Smith { 120dfbe8321SBarry Smith PetscErrorCode ierr; 12185614651SBarry Smith 1225cfeda75SBarry Smith PetscFunctionBegin; 12385614651SBarry Smith if (--sp->refct > 0) PetscFunctionReturn(0); 12485614651SBarry Smith 1255cfeda75SBarry Smith if (sp->vec) {ierr = VecDestroy(sp->vec);CHKERRQ(ierr);} 126f7a9e4ceSBarry Smith if (sp->vecs) { 127f7a9e4ceSBarry Smith ierr = VecDestroyVecs(sp->vecs,sp->n);CHKERRQ(ierr); 128f7a9e4ceSBarry Smith } 129d38fa0fbSBarry Smith ierr = PetscHeaderDestroy(sp);CHKERRQ(ierr); 1303a40ed3dSBarry Smith PetscFunctionReturn(0); 131b4fd4287SBarry Smith } 132b4fd4287SBarry Smith 1334a2ae208SSatish Balay #undef __FUNCT__ 1344a2ae208SSatish Balay #define __FUNCT__ "MatNullSpaceRemove" 135b4fd4287SBarry Smith /*@ 1365cfeda75SBarry Smith MatNullSpaceRemove - Removes all the components of a null space from a vector. 137f7765cecSBarry Smith 1385cfeda75SBarry Smith Collective on MatNullSpace 139f7765cecSBarry Smith 1404e472627SLois Curfman McInnes Input Parameters: 1414e472627SLois Curfman McInnes + sp - the null space context 1424e7234bfSBarry Smith . vec - the vector from which the null space is to be removed 1435fcf39f4SBarry Smith - out - if this is requested (not PETSC_NULL) then this is a vector with the null space removed otherwise 1444e7234bfSBarry Smith the removal is done in-place (in vec) 1454e7234bfSBarry Smith 146db090513SMatthew Knepley Note: The user is not responsible for the vector returned and should not destroy it. 1474e472627SLois Curfman McInnes 148b9756687SLois Curfman McInnes Level: advanced 149b9756687SLois Curfman McInnes 15083c3bef8SLois Curfman McInnes .keywords: PC, null space, remove 15141a59933SSatish Balay 15272875594SBarry Smith .seealso: MatNullSpaceCreate(), MatNullSpaceDestroy(), MatNullSpaceSetFunction() 153f7765cecSBarry Smith @*/ 154be1d678aSKris Buschelman PetscErrorCode PETSCMAT_DLLEXPORT MatNullSpaceRemove(MatNullSpace sp,Vec vec,Vec *out) 155f7765cecSBarry Smith { 15687828ca2SBarry Smith PetscScalar sum; 1576849ba73SBarry Smith PetscErrorCode ierr; 158c1ac3661SBarry Smith PetscInt j,n = sp->n,N; 1595cfeda75SBarry Smith Vec l = vec; 160f7765cecSBarry Smith 1613a40ed3dSBarry Smith PetscFunctionBegin; 1623cd8ff7eSMatthew Knepley PetscValidHeaderSpecific(sp,MAT_NULLSPACE_COOKIE,1); 1633cd8ff7eSMatthew Knepley PetscValidHeaderSpecific(vec,VEC_COOKIE,2); 1643cd8ff7eSMatthew Knepley 1655cfeda75SBarry Smith if (out) { 1663cd8ff7eSMatthew Knepley PetscValidPointer(out,3); 1675cfeda75SBarry Smith if (!sp->vec) { 1685cfeda75SBarry Smith ierr = VecDuplicate(vec,&sp->vec);CHKERRQ(ierr); 1695cfeda75SBarry Smith } 1705cfeda75SBarry Smith *out = sp->vec; 1715cfeda75SBarry Smith ierr = VecCopy(vec,*out);CHKERRQ(ierr); 1725cfeda75SBarry Smith l = *out; 1735cfeda75SBarry Smith } 1745cfeda75SBarry Smith 175b4fd4287SBarry Smith if (sp->has_cnst) { 1765cfeda75SBarry Smith ierr = VecSum(l,&sum);CHKERRQ(ierr); 1775cfeda75SBarry Smith ierr = VecGetSize(l,&N);CHKERRQ(ierr); 17818a7d68fSSatish Balay sum = sum/(-1.0*N); 1792dcb1b2aSMatthew Knepley ierr = VecShift(l,sum);CHKERRQ(ierr); 180f7765cecSBarry Smith } 181b4fd4287SBarry Smith 182b4fd4287SBarry Smith for (j=0; j<n; j++) { 1835cfeda75SBarry Smith ierr = VecDot(l,sp->vecs[j],&sum);CHKERRQ(ierr); 1845eb3c597SBarry Smith ierr = VecAXPY(l,-sum,sp->vecs[j]);CHKERRQ(ierr); 185f7765cecSBarry Smith } 186b4fd4287SBarry Smith 18772875594SBarry Smith if (sp->remove){ 188ce0145b1SBarry Smith ierr = (*sp->remove)(l,sp->rmctx); 18972875594SBarry Smith } 1903a40ed3dSBarry Smith PetscFunctionReturn(0); 191f7765cecSBarry Smith } 192a2e34c3dSBarry Smith 1934a2ae208SSatish Balay #undef __FUNCT__ 1944a2ae208SSatish Balay #define __FUNCT__ "MatNullSpaceTest" 195a2e34c3dSBarry Smith /*@ 196a2e34c3dSBarry Smith MatNullSpaceTest - Tests if the claimed null space is really a 197a2e34c3dSBarry Smith null space of a matrix 198a2e34c3dSBarry Smith 199a2e34c3dSBarry Smith Collective on MatNullSpace 200a2e34c3dSBarry Smith 201a2e34c3dSBarry Smith Input Parameters: 202a2e34c3dSBarry Smith + sp - the null space context 203a2e34c3dSBarry Smith - mat - the matrix 204a2e34c3dSBarry Smith 205a2e34c3dSBarry Smith Level: advanced 206a2e34c3dSBarry Smith 207a2e34c3dSBarry Smith .keywords: PC, null space, remove 208a2e34c3dSBarry Smith 20972875594SBarry Smith .seealso: MatNullSpaceCreate(), MatNullSpaceDestroy(), MatNullSpaceSetFunction() 210a2e34c3dSBarry Smith @*/ 211be1d678aSKris Buschelman PetscErrorCode PETSCMAT_DLLEXPORT MatNullSpaceTest(MatNullSpace sp,Mat mat) 212a2e34c3dSBarry Smith { 21387828ca2SBarry Smith PetscScalar sum; 2148bb6bcc5SSatish Balay PetscReal nrm; 215c1ac3661SBarry Smith PetscInt j,n = sp->n,N,m; 2166849ba73SBarry Smith PetscErrorCode ierr; 217a2e34c3dSBarry Smith Vec l,r; 218a2e34c3dSBarry Smith MPI_Comm comm = sp->comm; 219a2e34c3dSBarry Smith PetscTruth flg1,flg2; 220a2e34c3dSBarry Smith 221a2e34c3dSBarry Smith PetscFunctionBegin; 222b0a32e0cSBarry Smith ierr = PetscOptionsHasName(PETSC_NULL,"-mat_null_space_test_view",&flg1);CHKERRQ(ierr); 223b0a32e0cSBarry Smith ierr = PetscOptionsHasName(PETSC_NULL,"-mat_null_space_test_view_draw",&flg2);CHKERRQ(ierr); 224a2e34c3dSBarry Smith 225a2e34c3dSBarry Smith if (!sp->vec) { 226a2e34c3dSBarry Smith if (n) { 227a2e34c3dSBarry Smith ierr = VecDuplicate(sp->vecs[0],&sp->vec);CHKERRQ(ierr); 228a2e34c3dSBarry Smith } else { 229a2e34c3dSBarry Smith ierr = MatGetLocalSize(mat,&m,PETSC_NULL);CHKERRQ(ierr); 230a2e34c3dSBarry Smith ierr = VecCreateMPI(sp->comm,m,PETSC_DETERMINE,&sp->vec);CHKERRQ(ierr); 231a2e34c3dSBarry Smith } 232a2e34c3dSBarry Smith } 233a2e34c3dSBarry Smith l = sp->vec; 234a2e34c3dSBarry Smith 235a2e34c3dSBarry Smith if (sp->has_cnst) { 236a2e34c3dSBarry Smith ierr = VecDuplicate(l,&r);CHKERRQ(ierr); 237a2e34c3dSBarry Smith ierr = VecGetSize(l,&N);CHKERRQ(ierr); 238a2e34c3dSBarry Smith sum = 1.0/N; 2392dcb1b2aSMatthew Knepley ierr = VecSet(l,sum);CHKERRQ(ierr); 240a2e34c3dSBarry Smith ierr = MatMult(mat,l,r);CHKERRQ(ierr); 2418bb6bcc5SSatish Balay ierr = VecNorm(r,NORM_2,&nrm);CHKERRQ(ierr); 2428bb6bcc5SSatish Balay if (nrm < 1.e-7) {ierr = PetscPrintf(comm,"Constants are likely null vector");CHKERRQ(ierr);} 243a2e34c3dSBarry Smith else {ierr = PetscPrintf(comm,"Constants are unlikely null vector ");CHKERRQ(ierr);} 2448bb6bcc5SSatish Balay ierr = PetscPrintf(comm,"|| A * 1 || = %g\n",nrm);CHKERRQ(ierr); 245b0a32e0cSBarry Smith if (nrm > 1.e-7 && flg1) {ierr = VecView(r,PETSC_VIEWER_STDOUT_(comm));CHKERRQ(ierr);} 246b0a32e0cSBarry Smith if (nrm > 1.e-7 && flg2) {ierr = VecView(r,PETSC_VIEWER_DRAW_(comm));CHKERRQ(ierr);} 247a2e34c3dSBarry Smith ierr = VecDestroy(r);CHKERRQ(ierr); 248a2e34c3dSBarry Smith } 249a2e34c3dSBarry Smith 250a2e34c3dSBarry Smith for (j=0; j<n; j++) { 251a2e34c3dSBarry Smith ierr = (*mat->ops->mult)(mat,sp->vecs[j],l);CHKERRQ(ierr); 2528bb6bcc5SSatish Balay ierr = VecNorm(l,NORM_2,&nrm);CHKERRQ(ierr); 25377431f27SBarry Smith if (nrm < 1.e-7) {ierr = PetscPrintf(comm,"Null vector %D is likely null vector",j);CHKERRQ(ierr);} 25477431f27SBarry Smith else {ierr = PetscPrintf(comm,"Null vector %D unlikely null vector ",j);CHKERRQ(ierr);} 25577431f27SBarry Smith ierr = PetscPrintf(comm,"|| A * v[%D] || = %g\n",j,nrm);CHKERRQ(ierr); 256b0a32e0cSBarry Smith if (nrm > 1.e-7 && flg1) {ierr = VecView(l,PETSC_VIEWER_STDOUT_(comm));CHKERRQ(ierr);} 257b0a32e0cSBarry Smith if (nrm > 1.e-7 && flg2) {ierr = VecView(l,PETSC_VIEWER_DRAW_(comm));CHKERRQ(ierr);} 258a2e34c3dSBarry Smith } 259a2e34c3dSBarry Smith 26072875594SBarry Smith if (sp->remove){ 26172875594SBarry Smith SETERRQ(PETSC_ERR_SUP,"Cannot test a null space provided as a function with MatNullSpaceSetFunction()"); 26272875594SBarry Smith } 26372875594SBarry Smith 264a2e34c3dSBarry Smith PetscFunctionReturn(0); 265a2e34c3dSBarry Smith } 266a2e34c3dSBarry Smith 267