1be1d678aSKris Buschelman 2f7765cecSBarry Smith /* 3b4fd4287SBarry Smith Routines to project vectors out of null spaces. 4f7765cecSBarry Smith */ 5f7765cecSBarry Smith 6c6db04a5SJed Brown #include <private/matimpl.h> /*I "petscmat.h" I*/ 7f7765cecSBarry Smith 87087cfbeSBarry Smith PetscClassId MAT_NULLSPACE_CLASSID; 98ba1e511SMatthew Knepley 104a2ae208SSatish Balay #undef __FUNCT__ 1172875594SBarry Smith #define __FUNCT__ "MatNullSpaceSetFunction" 1272875594SBarry Smith /*@C 1372875594SBarry Smith MatNullSpaceSetFunction - set a function that removes a null space from a vector 1472875594SBarry Smith out of null spaces. 1572875594SBarry Smith 163f9fe445SBarry Smith Logically Collective on MatNullSpace 1772875594SBarry Smith 1872875594SBarry Smith Input Parameters: 1972875594SBarry Smith + sp - the null space object 209dbe9a8aSBarry Smith . rem - the function that removes the null space 219dbe9a8aSBarry Smith - ctx - context for the remove function 2272875594SBarry Smith 23658c74aaSSatish Balay Level: advanced 2472875594SBarry Smith 25658c74aaSSatish Balay .keywords: PC, null space, create 26b47fd4b1SSatish Balay 2772875594SBarry Smith .seealso: MatNullSpaceDestroy(), MatNullSpaceRemove(), KSPSetNullSpace(), MatNullSpace, MatNullSpaceCreate() 2872875594SBarry Smith @*/ 297087cfbeSBarry Smith PetscErrorCode MatNullSpaceSetFunction(MatNullSpace sp, PetscErrorCode (*rem)(MatNullSpace,Vec,void*),void *ctx) 3072875594SBarry Smith { 3172875594SBarry Smith PetscFunctionBegin; 320700a824SBarry Smith PetscValidHeaderSpecific(sp,MAT_NULLSPACE_CLASSID,1); 339dbe9a8aSBarry Smith sp->remove = rem; 349dbe9a8aSBarry Smith sp->rmctx = ctx; 3572875594SBarry Smith PetscFunctionReturn(0); 3672875594SBarry Smith } 3772875594SBarry Smith 3872875594SBarry Smith #undef __FUNCT__ 39f7357b39SLisandro Dalcin #define __FUNCT__ "MatNullSpaceView" 40f7357b39SLisandro Dalcin static PetscErrorCode MatNullSpaceView(MatNullSpace sp, PetscViewer viewer) 41f7357b39SLisandro Dalcin { 42f7357b39SLisandro Dalcin PetscErrorCode ierr; 43f7357b39SLisandro Dalcin PetscBool iascii; 44f7357b39SLisandro Dalcin 45f7357b39SLisandro Dalcin PetscFunctionBegin; 46f7357b39SLisandro Dalcin PetscValidHeaderSpecific(sp,MAT_NULLSPACE_CLASSID,1); 47f7357b39SLisandro Dalcin if (!viewer) viewer = PETSC_VIEWER_STDOUT_(((PetscObject)sp)->comm); 48f7357b39SLisandro Dalcin PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2); 49f7357b39SLisandro Dalcin PetscCheckSameComm(sp,1,viewer,2); 50f7357b39SLisandro Dalcin 51f7357b39SLisandro Dalcin ierr = PetscTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); 52f7357b39SLisandro Dalcin if (iascii) { 53f7357b39SLisandro Dalcin ierr = PetscObjectPrintClassNamePrefixType((PetscObject)sp,viewer,"MatNullSpace Object");CHKERRQ(ierr); 54f7357b39SLisandro Dalcin } 55f7357b39SLisandro Dalcin PetscFunctionReturn(0); 56f7357b39SLisandro Dalcin } 57f7357b39SLisandro Dalcin 58f7357b39SLisandro Dalcin #undef __FUNCT__ 594a2ae208SSatish Balay #define __FUNCT__ "MatNullSpaceCreate" 60f39d8e23SSatish Balay /*@ 615cfeda75SBarry Smith MatNullSpaceCreate - Creates a data structure used to project vectors 62b4fd4287SBarry Smith out of null spaces. 63f7765cecSBarry Smith 644e472627SLois Curfman McInnes Collective on MPI_Comm 654e472627SLois Curfman McInnes 66f7765cecSBarry Smith Input Parameters: 6783c3bef8SLois Curfman McInnes + comm - the MPI communicator associated with the object 6883c3bef8SLois Curfman McInnes . has_cnst - PETSC_TRUE if the null space contains the constant vector; otherwise PETSC_FALSE 69b4fd4287SBarry Smith . n - number of vectors (excluding constant vector) in null space 7083c3bef8SLois Curfman McInnes - vecs - the vectors that span the null space (excluding the constant vector); 71f7a9e4ceSBarry Smith these vectors must be orthonormal. These vectors are NOT copied, so do not change them 7273141a14SBarry Smith after this call. You should free the array that you pass in and destroy the vectors (this will reduce the reference count 7373141a14SBarry Smith for them by one). 74f7765cecSBarry Smith 75f7765cecSBarry Smith Output Parameter: 76b4fd4287SBarry Smith . SP - the null space context 77f7765cecSBarry Smith 7883c3bef8SLois Curfman McInnes Level: advanced 7983c3bef8SLois Curfman McInnes 8080bf1014SBarry Smith Notes: See MatNullSpaceSetFunction() as an alternative way of providing the null space information instead of setting vecs. 8180bf1014SBarry Smith 8280bf1014SBarry Smith If has_cnst is PETSC_TRUE you do not need to pass a constant vector in as a fourth argument to this routine, nor do you 8380bf1014SBarry Smith need to pass in a function that eliminates the constant function into MatNullSpaceSetFunction(). 8480bf1014SBarry Smith 856e1639daSBarry Smith Users manual sections: 866e1639daSBarry Smith . sec_singular 876e1639daSBarry Smith 8883c3bef8SLois Curfman McInnes .keywords: PC, null space, create 8941a59933SSatish Balay 9072875594SBarry Smith .seealso: MatNullSpaceDestroy(), MatNullSpaceRemove(), KSPSetNullSpace(), MatNullSpace, MatNullSpaceSetFunction() 91f7765cecSBarry Smith @*/ 927087cfbeSBarry Smith PetscErrorCode MatNullSpaceCreate(MPI_Comm comm,PetscBool has_cnst,PetscInt n,const Vec vecs[],MatNullSpace *SP) 93f7765cecSBarry Smith { 945cfeda75SBarry Smith MatNullSpace sp; 95dfbe8321SBarry Smith PetscErrorCode ierr; 96c1ac3661SBarry Smith PetscInt i; 97f7765cecSBarry Smith 983a40ed3dSBarry Smith PetscFunctionBegin; 99e32f2f54SBarry Smith if (n < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Number of vectors (given %D) cannot be negative",n); 100574b3360SMatthew Knepley if (n) PetscValidPointer(vecs,4); 1010700a824SBarry Smith for (i=0; i<n; i++) PetscValidHeaderSpecific(vecs[i],VEC_CLASSID,4); 102574b3360SMatthew Knepley PetscValidPointer(SP,5); 103574b3360SMatthew Knepley 104574b3360SMatthew Knepley *SP = PETSC_NULL; 105574b3360SMatthew Knepley #ifndef PETSC_USE_DYNAMIC_LIBRARIES 106574b3360SMatthew Knepley ierr = MatInitializePackage(PETSC_NULL);CHKERRQ(ierr); 107574b3360SMatthew Knepley #endif 108574b3360SMatthew Knepley 109*5b9de0c1SLisandro Dalcin ierr = PetscHeaderCreate(sp,_p_MatNullSpace,int,MAT_NULLSPACE_CLASSID,0,"MatNullSpace",comm,MatNullSpaceDestroy,MatNullSpaceView);CHKERRQ(ierr); 110f7765cecSBarry Smith 111b4fd4287SBarry Smith sp->has_cnst = has_cnst; 112b4fd4287SBarry Smith sp->n = n; 1137850f3fbSLisandro Dalcin sp->vecs = 0; 1147850f3fbSLisandro Dalcin sp->alpha = 0; 1157850f3fbSLisandro Dalcin sp->vec = 0; 1167850f3fbSLisandro Dalcin sp->remove = 0; 1177850f3fbSLisandro Dalcin sp->rmctx = 0; 1187850f3fbSLisandro Dalcin 119f7a9e4ceSBarry Smith if (n) { 120f7a9e4ceSBarry Smith ierr = PetscMalloc(n*sizeof(Vec),&sp->vecs);CHKERRQ(ierr); 1217850f3fbSLisandro Dalcin ierr = PetscMalloc(n*sizeof(PetscScalar),&sp->alpha);CHKERRQ(ierr); 1227850f3fbSLisandro Dalcin ierr = PetscLogObjectMemory(sp,n*(sizeof(Vec)+sizeof(PetscScalar)));CHKERRQ(ierr); 1237850f3fbSLisandro Dalcin for (i=0; i<n; i++) { 1247850f3fbSLisandro Dalcin ierr = PetscObjectReference((PetscObject)vecs[i]);CHKERRQ(ierr); 1257850f3fbSLisandro Dalcin sp->vecs[i] = vecs[i]; 1267850f3fbSLisandro Dalcin } 127f7a9e4ceSBarry Smith } 128b4fd4287SBarry Smith 129b4fd4287SBarry Smith *SP = sp; 1303a40ed3dSBarry Smith PetscFunctionReturn(0); 131f7765cecSBarry Smith } 132f7765cecSBarry Smith 1334a2ae208SSatish Balay #undef __FUNCT__ 1344a2ae208SSatish Balay #define __FUNCT__ "MatNullSpaceDestroy" 135f7765cecSBarry Smith /*@ 1365cfeda75SBarry Smith MatNullSpaceDestroy - Destroys a data structure used to project vectors 137b4fd4287SBarry Smith out of null spaces. 138b4fd4287SBarry Smith 1395cfeda75SBarry Smith Collective on MatNullSpace 1404e472627SLois Curfman McInnes 141b4fd4287SBarry Smith Input Parameter: 142b9756687SLois Curfman McInnes . sp - the null space context to be destroyed 143b9756687SLois Curfman McInnes 144b9756687SLois Curfman McInnes Level: advanced 145b4fd4287SBarry Smith 14683c3bef8SLois Curfman McInnes .keywords: PC, null space, destroy 14741a59933SSatish Balay 14872875594SBarry Smith .seealso: MatNullSpaceCreate(), MatNullSpaceRemove(), MatNullSpaceSetFunction() 149b4fd4287SBarry Smith @*/ 150d34fcf5fSBarry Smith PetscErrorCode MatNullSpaceDestroy(MatNullSpace *sp) 151b4fd4287SBarry Smith { 152dfbe8321SBarry Smith PetscErrorCode ierr; 15385614651SBarry Smith 1545cfeda75SBarry Smith PetscFunctionBegin; 1556bf464f9SBarry Smith if (!*sp) PetscFunctionReturn(0); 156d34fcf5fSBarry Smith PetscValidHeaderSpecific((*sp),MAT_NULLSPACE_CLASSID,1); 157d34fcf5fSBarry Smith if (--((PetscObject)(*sp))->refct > 0) {*sp = 0; PetscFunctionReturn(0);} 15885614651SBarry Smith 1596bf464f9SBarry Smith ierr = VecDestroy(&(*sp)->vec);CHKERRQ(ierr); 1606bf464f9SBarry Smith ierr = VecDestroyVecs((*sp)->n,&(*sp)->vecs);CHKERRQ(ierr); 161d34fcf5fSBarry Smith ierr = PetscFree((*sp)->alpha);CHKERRQ(ierr); 1626bf464f9SBarry Smith ierr = PetscHeaderDestroy(sp);CHKERRQ(ierr); 1633a40ed3dSBarry Smith PetscFunctionReturn(0); 164b4fd4287SBarry Smith } 165b4fd4287SBarry Smith 1664a2ae208SSatish Balay #undef __FUNCT__ 1674a2ae208SSatish Balay #define __FUNCT__ "MatNullSpaceRemove" 168812c3f48SMatthew Knepley /*@C 1695cfeda75SBarry Smith MatNullSpaceRemove - Removes all the components of a null space from a vector. 170f7765cecSBarry Smith 1715cfeda75SBarry Smith Collective on MatNullSpace 172f7765cecSBarry Smith 1734e472627SLois Curfman McInnes Input Parameters: 1744e472627SLois Curfman McInnes + sp - the null space context 1754e7234bfSBarry Smith . vec - the vector from which the null space is to be removed 1765fcf39f4SBarry Smith - out - if this is requested (not PETSC_NULL) then this is a vector with the null space removed otherwise 1774e7234bfSBarry Smith the removal is done in-place (in vec) 1784e7234bfSBarry Smith 179db090513SMatthew Knepley Note: The user is not responsible for the vector returned and should not destroy it. 1804e472627SLois Curfman McInnes 181b9756687SLois Curfman McInnes Level: advanced 182b9756687SLois Curfman McInnes 18383c3bef8SLois Curfman McInnes .keywords: PC, null space, remove 18441a59933SSatish Balay 18572875594SBarry Smith .seealso: MatNullSpaceCreate(), MatNullSpaceDestroy(), MatNullSpaceSetFunction() 186f7765cecSBarry Smith @*/ 1877087cfbeSBarry Smith PetscErrorCode MatNullSpaceRemove(MatNullSpace sp,Vec vec,Vec *out) 188f7765cecSBarry Smith { 18987828ca2SBarry Smith PetscScalar sum; 1907850f3fbSLisandro Dalcin PetscInt i,N; 1916849ba73SBarry Smith PetscErrorCode ierr; 192f7765cecSBarry Smith 1933a40ed3dSBarry Smith PetscFunctionBegin; 1940700a824SBarry Smith PetscValidHeaderSpecific(sp,MAT_NULLSPACE_CLASSID,1); 1950700a824SBarry Smith PetscValidHeaderSpecific(vec,VEC_CLASSID,2); 1963cd8ff7eSMatthew Knepley 1975cfeda75SBarry Smith if (out) { 1983cd8ff7eSMatthew Knepley PetscValidPointer(out,3); 1995cfeda75SBarry Smith if (!sp->vec) { 2005cfeda75SBarry Smith ierr = VecDuplicate(vec,&sp->vec);CHKERRQ(ierr); 2017850f3fbSLisandro Dalcin ierr = PetscLogObjectParent(sp,sp->vec);CHKERRQ(ierr); 2025cfeda75SBarry Smith } 2037850f3fbSLisandro Dalcin ierr = VecCopy(vec,sp->vec);CHKERRQ(ierr); 2047850f3fbSLisandro Dalcin vec = *out = sp->vec; 2055cfeda75SBarry Smith } 2065cfeda75SBarry Smith 207b4fd4287SBarry Smith if (sp->has_cnst) { 2087850f3fbSLisandro Dalcin ierr = VecGetSize(vec,&N);CHKERRQ(ierr); 2097850f3fbSLisandro Dalcin if (N > 0) { 2107850f3fbSLisandro Dalcin ierr = VecSum(vec,&sum);CHKERRQ(ierr); 21118a7d68fSSatish Balay sum = sum/(-1.0*N); 2127850f3fbSLisandro Dalcin ierr = VecShift(vec,sum);CHKERRQ(ierr); 2137850f3fbSLisandro Dalcin } 214f7765cecSBarry Smith } 215b4fd4287SBarry Smith 2167850f3fbSLisandro Dalcin if (sp->n) { 2177850f3fbSLisandro Dalcin ierr = VecMDot(vec,sp->n,sp->vecs,sp->alpha);CHKERRQ(ierr); 2187850f3fbSLisandro Dalcin for (i=0; i<sp->n; i++) sp->alpha[i] = -sp->alpha[i]; 2197850f3fbSLisandro Dalcin ierr = VecMAXPY(vec,sp->n,sp->alpha,sp->vecs);CHKERRQ(ierr); 220f7765cecSBarry Smith } 221b4fd4287SBarry Smith 22272875594SBarry Smith if (sp->remove){ 2230c3c4d68SMatthew Knepley ierr = (*sp->remove)(sp,vec,sp->rmctx);CHKERRQ(ierr); 22472875594SBarry Smith } 2253a40ed3dSBarry Smith PetscFunctionReturn(0); 226f7765cecSBarry Smith } 227a2e34c3dSBarry Smith 2284a2ae208SSatish Balay #undef __FUNCT__ 2294a2ae208SSatish Balay #define __FUNCT__ "MatNullSpaceTest" 230a2e34c3dSBarry Smith /*@ 231a2e34c3dSBarry Smith MatNullSpaceTest - Tests if the claimed null space is really a 232a2e34c3dSBarry Smith null space of a matrix 233a2e34c3dSBarry Smith 234a2e34c3dSBarry Smith Collective on MatNullSpace 235a2e34c3dSBarry Smith 236a2e34c3dSBarry Smith Input Parameters: 237a2e34c3dSBarry Smith + sp - the null space context 238a2e34c3dSBarry Smith - mat - the matrix 239a2e34c3dSBarry Smith 24095902228SMatthew Knepley Output Parameters: 24195902228SMatthew Knepley . isNull - PETSC_TRUE if the nullspace is valid for this matrix 24295902228SMatthew Knepley 243a2e34c3dSBarry Smith Level: advanced 244a2e34c3dSBarry Smith 245a2e34c3dSBarry Smith .keywords: PC, null space, remove 246a2e34c3dSBarry Smith 24772875594SBarry Smith .seealso: MatNullSpaceCreate(), MatNullSpaceDestroy(), MatNullSpaceSetFunction() 248a2e34c3dSBarry Smith @*/ 2497087cfbeSBarry Smith PetscErrorCode MatNullSpaceTest(MatNullSpace sp,Mat mat,PetscBool *isNull) 250a2e34c3dSBarry Smith { 25187828ca2SBarry Smith PetscScalar sum; 2528bb6bcc5SSatish Balay PetscReal nrm; 2530b12b109SJed Brown PetscInt j,n,N; 2546849ba73SBarry Smith PetscErrorCode ierr; 255a2e34c3dSBarry Smith Vec l,r; 256ace3abfcSBarry Smith PetscBool flg1 = PETSC_FALSE,flg2 = PETSC_FALSE,consistent = PETSC_TRUE; 2573050cee2SBarry Smith PetscViewer viewer; 258a2e34c3dSBarry Smith 259a2e34c3dSBarry Smith PetscFunctionBegin; 2600700a824SBarry Smith PetscValidHeaderSpecific(sp,MAT_NULLSPACE_CLASSID,1); 2610700a824SBarry Smith PetscValidHeaderSpecific(mat,MAT_CLASSID,2); 2623cfa8680SLisandro Dalcin n = sp->n; 263acfcf0e5SJed Brown ierr = PetscOptionsGetBool(PETSC_NULL,"-mat_null_space_test_view",&flg1,PETSC_NULL);CHKERRQ(ierr); 264acfcf0e5SJed Brown ierr = PetscOptionsGetBool(PETSC_NULL,"-mat_null_space_test_view_draw",&flg2,PETSC_NULL);CHKERRQ(ierr); 265a2e34c3dSBarry Smith 266a2e34c3dSBarry Smith if (!sp->vec) { 267a2e34c3dSBarry Smith if (n) { 268a2e34c3dSBarry Smith ierr = VecDuplicate(sp->vecs[0],&sp->vec);CHKERRQ(ierr); 269a2e34c3dSBarry Smith } else { 2700b12b109SJed Brown ierr = MatGetVecs(mat,&sp->vec,PETSC_NULL);CHKERRQ(ierr); 271a2e34c3dSBarry Smith } 272a2e34c3dSBarry Smith } 273a2e34c3dSBarry Smith l = sp->vec; 274a2e34c3dSBarry Smith 2757adad957SLisandro Dalcin ierr = PetscViewerASCIIGetStdout(((PetscObject)sp)->comm,&viewer);CHKERRQ(ierr); 276a2e34c3dSBarry Smith if (sp->has_cnst) { 277a2e34c3dSBarry Smith ierr = VecDuplicate(l,&r);CHKERRQ(ierr); 278a2e34c3dSBarry Smith ierr = VecGetSize(l,&N);CHKERRQ(ierr); 279a2e34c3dSBarry Smith sum = 1.0/N; 2802dcb1b2aSMatthew Knepley ierr = VecSet(l,sum);CHKERRQ(ierr); 281a2e34c3dSBarry Smith ierr = MatMult(mat,l,r);CHKERRQ(ierr); 2828bb6bcc5SSatish Balay ierr = VecNorm(r,NORM_2,&nrm);CHKERRQ(ierr); 28395902228SMatthew Knepley if (nrm < 1.e-7) { 28495902228SMatthew Knepley ierr = PetscPrintf(((PetscObject)sp)->comm,"Constants are likely null vector");CHKERRQ(ierr); 28595902228SMatthew Knepley } else { 28695902228SMatthew Knepley ierr = PetscPrintf(((PetscObject)sp)->comm,"Constants are unlikely null vector ");CHKERRQ(ierr); 28795902228SMatthew Knepley consistent = PETSC_FALSE; 28895902228SMatthew Knepley } 28931980aa1SBarry Smith ierr = PetscPrintf(((PetscObject)sp)->comm,"|| A * 1/N || = %G\n",nrm);CHKERRQ(ierr); 2903050cee2SBarry Smith if (nrm > 1.e-7 && flg1) {ierr = VecView(r,viewer);CHKERRQ(ierr);} 2913050cee2SBarry Smith if (nrm > 1.e-7 && flg2) {ierr = VecView(r,viewer);CHKERRQ(ierr);} 2926bf464f9SBarry Smith ierr = VecDestroy(&r);CHKERRQ(ierr); 293a2e34c3dSBarry Smith } 294a2e34c3dSBarry Smith 295a2e34c3dSBarry Smith for (j=0; j<n; j++) { 296a2e34c3dSBarry Smith ierr = (*mat->ops->mult)(mat,sp->vecs[j],l);CHKERRQ(ierr); 2978bb6bcc5SSatish Balay ierr = VecNorm(l,NORM_2,&nrm);CHKERRQ(ierr); 29895902228SMatthew Knepley if (nrm < 1.e-7) { 29995902228SMatthew Knepley ierr = PetscPrintf(((PetscObject)sp)->comm,"Null vector %D is likely null vector",j);CHKERRQ(ierr); 30095902228SMatthew Knepley } else { 30195902228SMatthew Knepley ierr = PetscPrintf(((PetscObject)sp)->comm,"Null vector %D unlikely null vector ",j);CHKERRQ(ierr); 30295902228SMatthew Knepley consistent = PETSC_FALSE; 30395902228SMatthew Knepley } 3047adad957SLisandro Dalcin ierr = PetscPrintf(((PetscObject)sp)->comm,"|| A * v[%D] || = %G\n",j,nrm);CHKERRQ(ierr); 3053050cee2SBarry Smith if (nrm > 1.e-7 && flg1) {ierr = VecView(l,viewer);CHKERRQ(ierr);} 3063050cee2SBarry Smith if (nrm > 1.e-7 && flg2) {ierr = VecView(l,viewer);CHKERRQ(ierr);} 307a2e34c3dSBarry Smith } 308a2e34c3dSBarry Smith 309ac53348aSBarry Smith if (sp->remove) SETERRQ(((PetscObject)mat)->comm,PETSC_ERR_SUP,"Cannot test a null space provided as a function with MatNullSpaceSetFunction()"); 31031980aa1SBarry Smith if (isNull) *isNull = consistent; 311a2e34c3dSBarry Smith PetscFunctionReturn(0); 312a2e34c3dSBarry Smith } 313a2e34c3dSBarry Smith 314