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 static PetscErrorCode MatNullSpaceDestroy_WRAP(MatNullSpace sp) { return MatNullSpaceDestroy(&sp); } 59f7357b39SLisandro Dalcin 60f7357b39SLisandro Dalcin #undef __FUNCT__ 614a2ae208SSatish Balay #define __FUNCT__ "MatNullSpaceCreate" 62f39d8e23SSatish Balay /*@ 635cfeda75SBarry Smith MatNullSpaceCreate - Creates a data structure used to project vectors 64b4fd4287SBarry Smith out of null spaces. 65f7765cecSBarry Smith 664e472627SLois Curfman McInnes Collective on MPI_Comm 674e472627SLois Curfman McInnes 68f7765cecSBarry Smith Input Parameters: 6983c3bef8SLois Curfman McInnes + comm - the MPI communicator associated with the object 7083c3bef8SLois Curfman McInnes . has_cnst - PETSC_TRUE if the null space contains the constant vector; otherwise PETSC_FALSE 71b4fd4287SBarry Smith . n - number of vectors (excluding constant vector) in null space 7283c3bef8SLois Curfman McInnes - vecs - the vectors that span the null space (excluding the constant vector); 73f7a9e4ceSBarry Smith these vectors must be orthonormal. These vectors are NOT copied, so do not change them 7473141a14SBarry Smith after this call. You should free the array that you pass in and destroy the vectors (this will reduce the reference count 7573141a14SBarry Smith for them by one). 76f7765cecSBarry Smith 77f7765cecSBarry Smith Output Parameter: 78b4fd4287SBarry Smith . SP - the null space context 79f7765cecSBarry Smith 8083c3bef8SLois Curfman McInnes Level: advanced 8183c3bef8SLois Curfman McInnes 8280bf1014SBarry Smith Notes: See MatNullSpaceSetFunction() as an alternative way of providing the null space information instead of setting vecs. 8380bf1014SBarry Smith 8480bf1014SBarry 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 8580bf1014SBarry Smith need to pass in a function that eliminates the constant function into MatNullSpaceSetFunction(). 8680bf1014SBarry Smith 876e1639daSBarry Smith Users manual sections: 886e1639daSBarry Smith . sec_singular 896e1639daSBarry Smith 9083c3bef8SLois Curfman McInnes .keywords: PC, null space, create 9141a59933SSatish Balay 9272875594SBarry Smith .seealso: MatNullSpaceDestroy(), MatNullSpaceRemove(), KSPSetNullSpace(), MatNullSpace, MatNullSpaceSetFunction() 93f7765cecSBarry Smith @*/ 947087cfbeSBarry Smith PetscErrorCode MatNullSpaceCreate(MPI_Comm comm,PetscBool has_cnst,PetscInt n,const Vec vecs[],MatNullSpace *SP) 95f7765cecSBarry Smith { 965cfeda75SBarry Smith MatNullSpace sp; 97dfbe8321SBarry Smith PetscErrorCode ierr; 98c1ac3661SBarry Smith PetscInt i; 99f7765cecSBarry Smith 1003a40ed3dSBarry Smith PetscFunctionBegin; 101e32f2f54SBarry Smith if (n < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Number of vectors (given %D) cannot be negative",n); 102574b3360SMatthew Knepley if (n) PetscValidPointer(vecs,4); 1030700a824SBarry Smith for (i=0; i<n; i++) PetscValidHeaderSpecific(vecs[i],VEC_CLASSID,4); 104574b3360SMatthew Knepley PetscValidPointer(SP,5); 105574b3360SMatthew Knepley 106574b3360SMatthew Knepley *SP = PETSC_NULL; 107574b3360SMatthew Knepley #ifndef PETSC_USE_DYNAMIC_LIBRARIES 108574b3360SMatthew Knepley ierr = MatInitializePackage(PETSC_NULL);CHKERRQ(ierr); 109574b3360SMatthew Knepley #endif 110574b3360SMatthew Knepley 111d34fcf5fSBarry Smith /* cannot use MatNullSpaceDestroy() as generic destroy function because it takes pointer to the object */ 112f7357b39SLisandro Dalcin ierr = PetscHeaderCreate(sp,_p_MatNullSpace,int,MAT_NULLSPACE_CLASSID,0,"MatNullSpace",comm,MatNullSpaceDestroy_WRAP,MatNullSpaceView);CHKERRQ(ierr); 113f7765cecSBarry Smith 114b4fd4287SBarry Smith sp->has_cnst = has_cnst; 115b4fd4287SBarry Smith sp->n = n; 1167850f3fbSLisandro Dalcin sp->vecs = 0; 1177850f3fbSLisandro Dalcin sp->alpha = 0; 1187850f3fbSLisandro Dalcin sp->vec = 0; 1197850f3fbSLisandro Dalcin sp->remove = 0; 1207850f3fbSLisandro Dalcin sp->rmctx = 0; 1217850f3fbSLisandro Dalcin 122f7a9e4ceSBarry Smith if (n) { 123f7a9e4ceSBarry Smith ierr = PetscMalloc(n*sizeof(Vec),&sp->vecs);CHKERRQ(ierr); 1247850f3fbSLisandro Dalcin ierr = PetscMalloc(n*sizeof(PetscScalar),&sp->alpha);CHKERRQ(ierr); 1257850f3fbSLisandro Dalcin ierr = PetscLogObjectMemory(sp,n*(sizeof(Vec)+sizeof(PetscScalar)));CHKERRQ(ierr); 1267850f3fbSLisandro Dalcin for (i=0; i<n; i++) { 1277850f3fbSLisandro Dalcin ierr = PetscObjectReference((PetscObject)vecs[i]);CHKERRQ(ierr); 1287850f3fbSLisandro Dalcin sp->vecs[i] = vecs[i]; 1297850f3fbSLisandro Dalcin } 130f7a9e4ceSBarry Smith } 131b4fd4287SBarry Smith 132b4fd4287SBarry Smith *SP = sp; 1333a40ed3dSBarry Smith PetscFunctionReturn(0); 134f7765cecSBarry Smith } 135f7765cecSBarry Smith 1364a2ae208SSatish Balay #undef __FUNCT__ 1374a2ae208SSatish Balay #define __FUNCT__ "MatNullSpaceDestroy" 138f7765cecSBarry Smith /*@ 1395cfeda75SBarry Smith MatNullSpaceDestroy - Destroys a data structure used to project vectors 140b4fd4287SBarry Smith out of null spaces. 141b4fd4287SBarry Smith 1425cfeda75SBarry Smith Collective on MatNullSpace 1434e472627SLois Curfman McInnes 144b4fd4287SBarry Smith Input Parameter: 145b9756687SLois Curfman McInnes . sp - the null space context to be destroyed 146b9756687SLois Curfman McInnes 147b9756687SLois Curfman McInnes Level: advanced 148b4fd4287SBarry Smith 14983c3bef8SLois Curfman McInnes .keywords: PC, null space, destroy 15041a59933SSatish Balay 15172875594SBarry Smith .seealso: MatNullSpaceCreate(), MatNullSpaceRemove(), MatNullSpaceSetFunction() 152b4fd4287SBarry Smith @*/ 153d34fcf5fSBarry Smith PetscErrorCode MatNullSpaceDestroy(MatNullSpace *sp) 154b4fd4287SBarry Smith { 155dfbe8321SBarry Smith PetscErrorCode ierr; 15685614651SBarry Smith 1575cfeda75SBarry Smith PetscFunctionBegin; 158*6bf464f9SBarry Smith if (!*sp) PetscFunctionReturn(0); 159d34fcf5fSBarry Smith PetscValidHeaderSpecific((*sp),MAT_NULLSPACE_CLASSID,1); 160d34fcf5fSBarry Smith if (--((PetscObject)(*sp))->refct > 0) {*sp = 0; PetscFunctionReturn(0);} 16185614651SBarry Smith 162*6bf464f9SBarry Smith ierr = VecDestroy(&(*sp)->vec);CHKERRQ(ierr); 163*6bf464f9SBarry Smith ierr = VecDestroyVecs((*sp)->n,&(*sp)->vecs);CHKERRQ(ierr); 164d34fcf5fSBarry Smith ierr = PetscFree((*sp)->alpha);CHKERRQ(ierr); 165*6bf464f9SBarry Smith ierr = PetscHeaderDestroy(sp);CHKERRQ(ierr); 1663a40ed3dSBarry Smith PetscFunctionReturn(0); 167b4fd4287SBarry Smith } 168b4fd4287SBarry Smith 1694a2ae208SSatish Balay #undef __FUNCT__ 1704a2ae208SSatish Balay #define __FUNCT__ "MatNullSpaceRemove" 171812c3f48SMatthew Knepley /*@C 1725cfeda75SBarry Smith MatNullSpaceRemove - Removes all the components of a null space from a vector. 173f7765cecSBarry Smith 1745cfeda75SBarry Smith Collective on MatNullSpace 175f7765cecSBarry Smith 1764e472627SLois Curfman McInnes Input Parameters: 1774e472627SLois Curfman McInnes + sp - the null space context 1784e7234bfSBarry Smith . vec - the vector from which the null space is to be removed 1795fcf39f4SBarry Smith - out - if this is requested (not PETSC_NULL) then this is a vector with the null space removed otherwise 1804e7234bfSBarry Smith the removal is done in-place (in vec) 1814e7234bfSBarry Smith 182db090513SMatthew Knepley Note: The user is not responsible for the vector returned and should not destroy it. 1834e472627SLois Curfman McInnes 184b9756687SLois Curfman McInnes Level: advanced 185b9756687SLois Curfman McInnes 18683c3bef8SLois Curfman McInnes .keywords: PC, null space, remove 18741a59933SSatish Balay 18872875594SBarry Smith .seealso: MatNullSpaceCreate(), MatNullSpaceDestroy(), MatNullSpaceSetFunction() 189f7765cecSBarry Smith @*/ 1907087cfbeSBarry Smith PetscErrorCode MatNullSpaceRemove(MatNullSpace sp,Vec vec,Vec *out) 191f7765cecSBarry Smith { 19287828ca2SBarry Smith PetscScalar sum; 1937850f3fbSLisandro Dalcin PetscInt i,N; 1946849ba73SBarry Smith PetscErrorCode ierr; 195f7765cecSBarry Smith 1963a40ed3dSBarry Smith PetscFunctionBegin; 1970700a824SBarry Smith PetscValidHeaderSpecific(sp,MAT_NULLSPACE_CLASSID,1); 1980700a824SBarry Smith PetscValidHeaderSpecific(vec,VEC_CLASSID,2); 1993cd8ff7eSMatthew Knepley 2005cfeda75SBarry Smith if (out) { 2013cd8ff7eSMatthew Knepley PetscValidPointer(out,3); 2025cfeda75SBarry Smith if (!sp->vec) { 2035cfeda75SBarry Smith ierr = VecDuplicate(vec,&sp->vec);CHKERRQ(ierr); 2047850f3fbSLisandro Dalcin ierr = PetscLogObjectParent(sp,sp->vec);CHKERRQ(ierr); 2055cfeda75SBarry Smith } 2067850f3fbSLisandro Dalcin ierr = VecCopy(vec,sp->vec);CHKERRQ(ierr); 2077850f3fbSLisandro Dalcin vec = *out = sp->vec; 2085cfeda75SBarry Smith } 2095cfeda75SBarry Smith 210b4fd4287SBarry Smith if (sp->has_cnst) { 2117850f3fbSLisandro Dalcin ierr = VecGetSize(vec,&N);CHKERRQ(ierr); 2127850f3fbSLisandro Dalcin if (N > 0) { 2137850f3fbSLisandro Dalcin ierr = VecSum(vec,&sum);CHKERRQ(ierr); 21418a7d68fSSatish Balay sum = sum/(-1.0*N); 2157850f3fbSLisandro Dalcin ierr = VecShift(vec,sum);CHKERRQ(ierr); 2167850f3fbSLisandro Dalcin } 217f7765cecSBarry Smith } 218b4fd4287SBarry Smith 2197850f3fbSLisandro Dalcin if (sp->n) { 2207850f3fbSLisandro Dalcin ierr = VecMDot(vec,sp->n,sp->vecs,sp->alpha);CHKERRQ(ierr); 2217850f3fbSLisandro Dalcin for (i=0; i<sp->n; i++) sp->alpha[i] = -sp->alpha[i]; 2227850f3fbSLisandro Dalcin ierr = VecMAXPY(vec,sp->n,sp->alpha,sp->vecs);CHKERRQ(ierr); 223f7765cecSBarry Smith } 224b4fd4287SBarry Smith 22572875594SBarry Smith if (sp->remove){ 2260c3c4d68SMatthew Knepley ierr = (*sp->remove)(sp,vec,sp->rmctx);CHKERRQ(ierr); 22772875594SBarry Smith } 2283a40ed3dSBarry Smith PetscFunctionReturn(0); 229f7765cecSBarry Smith } 230a2e34c3dSBarry Smith 2314a2ae208SSatish Balay #undef __FUNCT__ 2324a2ae208SSatish Balay #define __FUNCT__ "MatNullSpaceTest" 233a2e34c3dSBarry Smith /*@ 234a2e34c3dSBarry Smith MatNullSpaceTest - Tests if the claimed null space is really a 235a2e34c3dSBarry Smith null space of a matrix 236a2e34c3dSBarry Smith 237a2e34c3dSBarry Smith Collective on MatNullSpace 238a2e34c3dSBarry Smith 239a2e34c3dSBarry Smith Input Parameters: 240a2e34c3dSBarry Smith + sp - the null space context 241a2e34c3dSBarry Smith - mat - the matrix 242a2e34c3dSBarry Smith 24395902228SMatthew Knepley Output Parameters: 24495902228SMatthew Knepley . isNull - PETSC_TRUE if the nullspace is valid for this matrix 24595902228SMatthew Knepley 246a2e34c3dSBarry Smith Level: advanced 247a2e34c3dSBarry Smith 248a2e34c3dSBarry Smith .keywords: PC, null space, remove 249a2e34c3dSBarry Smith 25072875594SBarry Smith .seealso: MatNullSpaceCreate(), MatNullSpaceDestroy(), MatNullSpaceSetFunction() 251a2e34c3dSBarry Smith @*/ 2527087cfbeSBarry Smith PetscErrorCode MatNullSpaceTest(MatNullSpace sp,Mat mat,PetscBool *isNull) 253a2e34c3dSBarry Smith { 25487828ca2SBarry Smith PetscScalar sum; 2558bb6bcc5SSatish Balay PetscReal nrm; 2560b12b109SJed Brown PetscInt j,n,N; 2576849ba73SBarry Smith PetscErrorCode ierr; 258a2e34c3dSBarry Smith Vec l,r; 259ace3abfcSBarry Smith PetscBool flg1 = PETSC_FALSE,flg2 = PETSC_FALSE,consistent = PETSC_TRUE; 2603050cee2SBarry Smith PetscViewer viewer; 261a2e34c3dSBarry Smith 262a2e34c3dSBarry Smith PetscFunctionBegin; 2630700a824SBarry Smith PetscValidHeaderSpecific(sp,MAT_NULLSPACE_CLASSID,1); 2640700a824SBarry Smith PetscValidHeaderSpecific(mat,MAT_CLASSID,2); 2653cfa8680SLisandro Dalcin n = sp->n; 266acfcf0e5SJed Brown ierr = PetscOptionsGetBool(PETSC_NULL,"-mat_null_space_test_view",&flg1,PETSC_NULL);CHKERRQ(ierr); 267acfcf0e5SJed Brown ierr = PetscOptionsGetBool(PETSC_NULL,"-mat_null_space_test_view_draw",&flg2,PETSC_NULL);CHKERRQ(ierr); 268a2e34c3dSBarry Smith 269a2e34c3dSBarry Smith if (!sp->vec) { 270a2e34c3dSBarry Smith if (n) { 271a2e34c3dSBarry Smith ierr = VecDuplicate(sp->vecs[0],&sp->vec);CHKERRQ(ierr); 272a2e34c3dSBarry Smith } else { 2730b12b109SJed Brown ierr = MatGetVecs(mat,&sp->vec,PETSC_NULL);CHKERRQ(ierr); 274a2e34c3dSBarry Smith } 275a2e34c3dSBarry Smith } 276a2e34c3dSBarry Smith l = sp->vec; 277a2e34c3dSBarry Smith 2787adad957SLisandro Dalcin ierr = PetscViewerASCIIGetStdout(((PetscObject)sp)->comm,&viewer);CHKERRQ(ierr); 279a2e34c3dSBarry Smith if (sp->has_cnst) { 280a2e34c3dSBarry Smith ierr = VecDuplicate(l,&r);CHKERRQ(ierr); 281a2e34c3dSBarry Smith ierr = VecGetSize(l,&N);CHKERRQ(ierr); 282a2e34c3dSBarry Smith sum = 1.0/N; 2832dcb1b2aSMatthew Knepley ierr = VecSet(l,sum);CHKERRQ(ierr); 284a2e34c3dSBarry Smith ierr = MatMult(mat,l,r);CHKERRQ(ierr); 2858bb6bcc5SSatish Balay ierr = VecNorm(r,NORM_2,&nrm);CHKERRQ(ierr); 28695902228SMatthew Knepley if (nrm < 1.e-7) { 28795902228SMatthew Knepley ierr = PetscPrintf(((PetscObject)sp)->comm,"Constants are likely null vector");CHKERRQ(ierr); 28895902228SMatthew Knepley } else { 28995902228SMatthew Knepley ierr = PetscPrintf(((PetscObject)sp)->comm,"Constants are unlikely null vector ");CHKERRQ(ierr); 29095902228SMatthew Knepley consistent = PETSC_FALSE; 29195902228SMatthew Knepley } 29231980aa1SBarry Smith ierr = PetscPrintf(((PetscObject)sp)->comm,"|| A * 1/N || = %G\n",nrm);CHKERRQ(ierr); 2933050cee2SBarry Smith if (nrm > 1.e-7 && flg1) {ierr = VecView(r,viewer);CHKERRQ(ierr);} 2943050cee2SBarry Smith if (nrm > 1.e-7 && flg2) {ierr = VecView(r,viewer);CHKERRQ(ierr);} 295*6bf464f9SBarry Smith ierr = VecDestroy(&r);CHKERRQ(ierr); 296a2e34c3dSBarry Smith } 297a2e34c3dSBarry Smith 298a2e34c3dSBarry Smith for (j=0; j<n; j++) { 299a2e34c3dSBarry Smith ierr = (*mat->ops->mult)(mat,sp->vecs[j],l);CHKERRQ(ierr); 3008bb6bcc5SSatish Balay ierr = VecNorm(l,NORM_2,&nrm);CHKERRQ(ierr); 30195902228SMatthew Knepley if (nrm < 1.e-7) { 30295902228SMatthew Knepley ierr = PetscPrintf(((PetscObject)sp)->comm,"Null vector %D is likely null vector",j);CHKERRQ(ierr); 30395902228SMatthew Knepley } else { 30495902228SMatthew Knepley ierr = PetscPrintf(((PetscObject)sp)->comm,"Null vector %D unlikely null vector ",j);CHKERRQ(ierr); 30595902228SMatthew Knepley consistent = PETSC_FALSE; 30695902228SMatthew Knepley } 3077adad957SLisandro Dalcin ierr = PetscPrintf(((PetscObject)sp)->comm,"|| A * v[%D] || = %G\n",j,nrm);CHKERRQ(ierr); 3083050cee2SBarry Smith if (nrm > 1.e-7 && flg1) {ierr = VecView(l,viewer);CHKERRQ(ierr);} 3093050cee2SBarry Smith if (nrm > 1.e-7 && flg2) {ierr = VecView(l,viewer);CHKERRQ(ierr);} 310a2e34c3dSBarry Smith } 311a2e34c3dSBarry Smith 312ac53348aSBarry Smith if (sp->remove) SETERRQ(((PetscObject)mat)->comm,PETSC_ERR_SUP,"Cannot test a null space provided as a function with MatNullSpaceSetFunction()"); 31331980aa1SBarry Smith if (isNull) *isNull = consistent; 314a2e34c3dSBarry Smith PetscFunctionReturn(0); 315a2e34c3dSBarry Smith } 316a2e34c3dSBarry Smith 317