1be1d678aSKris Buschelman #define PETSCMAT_DLL 2be1d678aSKris Buschelman 3f7765cecSBarry Smith /* 4b4fd4287SBarry Smith Routines to project vectors out of null spaces. 5f7765cecSBarry Smith */ 6f7765cecSBarry Smith 77c4f633dSBarry Smith #include "private/matimpl.h" /*I "petscmat.h" I*/ 8e090d566SSatish Balay #include "petscsys.h" 9f7765cecSBarry Smith 10166c7f25SBarry Smith PetscCookie PETSCMAT_DLLEXPORT MAT_NULLSPACE_COOKIE; 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; 343cfa8680SLisandro Dalcin PetscValidHeaderSpecific(sp,MAT_NULLSPACE_COOKIE,1); 359dbe9a8aSBarry Smith sp->remove = rem; 369dbe9a8aSBarry Smith sp->rmctx = ctx; 3772875594SBarry Smith PetscFunctionReturn(0); 3872875594SBarry Smith } 3972875594SBarry Smith 4072875594SBarry Smith #undef __FUNCT__ 414a2ae208SSatish Balay #define __FUNCT__ "MatNullSpaceCreate" 42f39d8e23SSatish Balay /*@ 435cfeda75SBarry Smith MatNullSpaceCreate - Creates a data structure used to project vectors 44b4fd4287SBarry Smith out of null spaces. 45f7765cecSBarry Smith 464e472627SLois Curfman McInnes Collective on MPI_Comm 474e472627SLois Curfman McInnes 48f7765cecSBarry Smith Input Parameters: 4983c3bef8SLois Curfman McInnes + comm - the MPI communicator associated with the object 5083c3bef8SLois Curfman McInnes . has_cnst - PETSC_TRUE if the null space contains the constant vector; otherwise PETSC_FALSE 51b4fd4287SBarry Smith . n - number of vectors (excluding constant vector) in null space 5283c3bef8SLois Curfman McInnes - vecs - the vectors that span the null space (excluding the constant vector); 53f7a9e4ceSBarry Smith these vectors must be orthonormal. These vectors are NOT copied, so do not change them 54*73141a14SBarry Smith after this call. You should free the array that you pass in and destroy the vectors (this will reduce the reference count 55*73141a14SBarry Smith for them by one). 56f7765cecSBarry Smith 57f7765cecSBarry Smith Output Parameter: 58b4fd4287SBarry Smith . SP - the null space context 59f7765cecSBarry Smith 6083c3bef8SLois Curfman McInnes Level: advanced 6183c3bef8SLois Curfman McInnes 6280bf1014SBarry Smith Notes: See MatNullSpaceSetFunction() as an alternative way of providing the null space information instead of setting vecs. 6380bf1014SBarry Smith 6480bf1014SBarry 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 6580bf1014SBarry Smith need to pass in a function that eliminates the constant function into MatNullSpaceSetFunction(). 6680bf1014SBarry Smith 676e1639daSBarry Smith Users manual sections: 686e1639daSBarry Smith . sec_singular 696e1639daSBarry Smith 7083c3bef8SLois Curfman McInnes .keywords: PC, null space, create 7141a59933SSatish Balay 7272875594SBarry Smith .seealso: MatNullSpaceDestroy(), MatNullSpaceRemove(), KSPSetNullSpace(), MatNullSpace, MatNullSpaceSetFunction() 73f7765cecSBarry Smith @*/ 74be1d678aSKris Buschelman PetscErrorCode PETSCMAT_DLLEXPORT MatNullSpaceCreate(MPI_Comm comm,PetscTruth has_cnst,PetscInt n,const Vec vecs[],MatNullSpace *SP) 75f7765cecSBarry Smith { 765cfeda75SBarry Smith MatNullSpace sp; 77dfbe8321SBarry Smith PetscErrorCode ierr; 78c1ac3661SBarry Smith PetscInt i; 79f7765cecSBarry Smith 803a40ed3dSBarry Smith PetscFunctionBegin; 817850f3fbSLisandro Dalcin if (n < 0) SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"Number of vectors (given %D) cannot be negative",n); 82574b3360SMatthew Knepley if (n) PetscValidPointer(vecs,4); 83574b3360SMatthew Knepley for (i=0; i<n; i++) PetscValidHeaderSpecific(vecs[i],VEC_COOKIE,4); 84574b3360SMatthew Knepley PetscValidPointer(SP,5); 85574b3360SMatthew Knepley 86574b3360SMatthew Knepley *SP = PETSC_NULL; 87574b3360SMatthew Knepley #ifndef PETSC_USE_DYNAMIC_LIBRARIES 88574b3360SMatthew Knepley ierr = MatInitializePackage(PETSC_NULL);CHKERRQ(ierr); 89574b3360SMatthew Knepley #endif 90574b3360SMatthew Knepley 9152e6d16bSBarry Smith ierr = PetscHeaderCreate(sp,_p_MatNullSpace,int,MAT_NULLSPACE_COOKIE,0,"MatNullSpace",comm,MatNullSpaceDestroy,0);CHKERRQ(ierr); 92f7765cecSBarry Smith 93b4fd4287SBarry Smith sp->has_cnst = has_cnst; 94b4fd4287SBarry Smith sp->n = n; 957850f3fbSLisandro Dalcin sp->vecs = 0; 967850f3fbSLisandro Dalcin sp->alpha = 0; 977850f3fbSLisandro Dalcin sp->vec = 0; 987850f3fbSLisandro Dalcin sp->remove = 0; 997850f3fbSLisandro Dalcin sp->rmctx = 0; 1007850f3fbSLisandro Dalcin 101f7a9e4ceSBarry Smith if (n) { 102f7a9e4ceSBarry Smith ierr = PetscMalloc(n*sizeof(Vec),&sp->vecs);CHKERRQ(ierr); 1037850f3fbSLisandro Dalcin ierr = PetscMalloc(n*sizeof(PetscScalar),&sp->alpha);CHKERRQ(ierr); 1047850f3fbSLisandro Dalcin ierr = PetscLogObjectMemory(sp,n*(sizeof(Vec)+sizeof(PetscScalar)));CHKERRQ(ierr); 1057850f3fbSLisandro Dalcin for (i=0; i<n; i++) { 1067850f3fbSLisandro Dalcin ierr = PetscObjectReference((PetscObject)vecs[i]);CHKERRQ(ierr); 1077850f3fbSLisandro Dalcin sp->vecs[i] = vecs[i]; 1087850f3fbSLisandro Dalcin } 109f7a9e4ceSBarry Smith } 110b4fd4287SBarry Smith 111b4fd4287SBarry Smith *SP = sp; 1123a40ed3dSBarry Smith PetscFunctionReturn(0); 113f7765cecSBarry Smith } 114f7765cecSBarry Smith 1154a2ae208SSatish Balay #undef __FUNCT__ 1164a2ae208SSatish Balay #define __FUNCT__ "MatNullSpaceDestroy" 117f7765cecSBarry Smith /*@ 1185cfeda75SBarry Smith MatNullSpaceDestroy - Destroys a data structure used to project vectors 119b4fd4287SBarry Smith out of null spaces. 120b4fd4287SBarry Smith 1215cfeda75SBarry Smith Collective on MatNullSpace 1224e472627SLois Curfman McInnes 123b4fd4287SBarry Smith Input Parameter: 124b9756687SLois Curfman McInnes . sp - the null space context to be destroyed 125b9756687SLois Curfman McInnes 126b9756687SLois Curfman McInnes Level: advanced 127b4fd4287SBarry Smith 12883c3bef8SLois Curfman McInnes .keywords: PC, null space, destroy 12941a59933SSatish Balay 13072875594SBarry Smith .seealso: MatNullSpaceCreate(), MatNullSpaceRemove(), MatNullSpaceSetFunction() 131b4fd4287SBarry Smith @*/ 132be1d678aSKris Buschelman PetscErrorCode PETSCMAT_DLLEXPORT MatNullSpaceDestroy(MatNullSpace sp) 133b4fd4287SBarry Smith { 134dfbe8321SBarry Smith PetscErrorCode ierr; 13585614651SBarry Smith 1365cfeda75SBarry Smith PetscFunctionBegin; 1373cfa8680SLisandro Dalcin PetscValidHeaderSpecific(sp,MAT_NULLSPACE_COOKIE,1); 1387adad957SLisandro Dalcin if (--((PetscObject)sp)->refct > 0) PetscFunctionReturn(0); 13985614651SBarry Smith 1405cfeda75SBarry Smith if (sp->vec) { ierr = VecDestroy(sp->vec);CHKERRQ(ierr); } 1417850f3fbSLisandro Dalcin if (sp->vecs) { ierr = VecDestroyVecs(sp->vecs,sp->n);CHKERRQ(ierr); } 1427850f3fbSLisandro Dalcin ierr = PetscFree(sp->alpha);CHKERRQ(ierr); 143d38fa0fbSBarry Smith ierr = PetscHeaderDestroy(sp);CHKERRQ(ierr); 1443a40ed3dSBarry Smith PetscFunctionReturn(0); 145b4fd4287SBarry Smith } 146b4fd4287SBarry Smith 1474a2ae208SSatish Balay #undef __FUNCT__ 1484a2ae208SSatish Balay #define __FUNCT__ "MatNullSpaceRemove" 149812c3f48SMatthew Knepley /*@C 1505cfeda75SBarry Smith MatNullSpaceRemove - Removes all the components of a null space from a vector. 151f7765cecSBarry Smith 1525cfeda75SBarry Smith Collective on MatNullSpace 153f7765cecSBarry Smith 1544e472627SLois Curfman McInnes Input Parameters: 1554e472627SLois Curfman McInnes + sp - the null space context 1564e7234bfSBarry Smith . vec - the vector from which the null space is to be removed 1575fcf39f4SBarry Smith - out - if this is requested (not PETSC_NULL) then this is a vector with the null space removed otherwise 1584e7234bfSBarry Smith the removal is done in-place (in vec) 1594e7234bfSBarry Smith 160db090513SMatthew Knepley Note: The user is not responsible for the vector returned and should not destroy it. 1614e472627SLois Curfman McInnes 162b9756687SLois Curfman McInnes Level: advanced 163b9756687SLois Curfman McInnes 16483c3bef8SLois Curfman McInnes .keywords: PC, null space, remove 16541a59933SSatish Balay 16672875594SBarry Smith .seealso: MatNullSpaceCreate(), MatNullSpaceDestroy(), MatNullSpaceSetFunction() 167f7765cecSBarry Smith @*/ 168be1d678aSKris Buschelman PetscErrorCode PETSCMAT_DLLEXPORT MatNullSpaceRemove(MatNullSpace sp,Vec vec,Vec *out) 169f7765cecSBarry Smith { 17087828ca2SBarry Smith PetscScalar sum; 1717850f3fbSLisandro Dalcin PetscInt i,N; 1726849ba73SBarry Smith PetscErrorCode ierr; 173f7765cecSBarry Smith 1743a40ed3dSBarry Smith PetscFunctionBegin; 1753cd8ff7eSMatthew Knepley PetscValidHeaderSpecific(sp,MAT_NULLSPACE_COOKIE,1); 1763cd8ff7eSMatthew Knepley PetscValidHeaderSpecific(vec,VEC_COOKIE,2); 1773cd8ff7eSMatthew Knepley 1785cfeda75SBarry Smith if (out) { 1793cd8ff7eSMatthew Knepley PetscValidPointer(out,3); 1805cfeda75SBarry Smith if (!sp->vec) { 1815cfeda75SBarry Smith ierr = VecDuplicate(vec,&sp->vec);CHKERRQ(ierr); 1827850f3fbSLisandro Dalcin ierr = PetscLogObjectParent(sp,sp->vec);CHKERRQ(ierr); 1835cfeda75SBarry Smith } 1847850f3fbSLisandro Dalcin ierr = VecCopy(vec,sp->vec);CHKERRQ(ierr); 1857850f3fbSLisandro Dalcin vec = *out = sp->vec; 1865cfeda75SBarry Smith } 1875cfeda75SBarry Smith 188b4fd4287SBarry Smith if (sp->has_cnst) { 1897850f3fbSLisandro Dalcin ierr = VecGetSize(vec,&N);CHKERRQ(ierr); 1907850f3fbSLisandro Dalcin if (N > 0) { 1917850f3fbSLisandro Dalcin ierr = VecSum(vec,&sum);CHKERRQ(ierr); 19218a7d68fSSatish Balay sum = sum/(-1.0*N); 1937850f3fbSLisandro Dalcin ierr = VecShift(vec,sum);CHKERRQ(ierr); 1947850f3fbSLisandro Dalcin } 195f7765cecSBarry Smith } 196b4fd4287SBarry Smith 1977850f3fbSLisandro Dalcin if (sp->n) { 1987850f3fbSLisandro Dalcin ierr = VecMDot(vec,sp->n,sp->vecs,sp->alpha);CHKERRQ(ierr); 1997850f3fbSLisandro Dalcin for (i=0; i<sp->n; i++) sp->alpha[i] = -sp->alpha[i]; 2007850f3fbSLisandro Dalcin ierr = VecMAXPY(vec,sp->n,sp->alpha,sp->vecs);CHKERRQ(ierr); 201f7765cecSBarry Smith } 202b4fd4287SBarry Smith 20372875594SBarry Smith if (sp->remove){ 2047850f3fbSLisandro Dalcin ierr = (*sp->remove)(vec,sp->rmctx); 20572875594SBarry Smith } 2063a40ed3dSBarry Smith PetscFunctionReturn(0); 207f7765cecSBarry Smith } 208a2e34c3dSBarry Smith 2094a2ae208SSatish Balay #undef __FUNCT__ 2104a2ae208SSatish Balay #define __FUNCT__ "MatNullSpaceTest" 211a2e34c3dSBarry Smith /*@ 212a2e34c3dSBarry Smith MatNullSpaceTest - Tests if the claimed null space is really a 213a2e34c3dSBarry Smith null space of a matrix 214a2e34c3dSBarry Smith 215a2e34c3dSBarry Smith Collective on MatNullSpace 216a2e34c3dSBarry Smith 217a2e34c3dSBarry Smith Input Parameters: 218a2e34c3dSBarry Smith + sp - the null space context 219a2e34c3dSBarry Smith - mat - the matrix 220a2e34c3dSBarry Smith 22195902228SMatthew Knepley Output Parameters: 22295902228SMatthew Knepley . isNull - PETSC_TRUE if the nullspace is valid for this matrix 22395902228SMatthew Knepley 224a2e34c3dSBarry Smith Level: advanced 225a2e34c3dSBarry Smith 226a2e34c3dSBarry Smith .keywords: PC, null space, remove 227a2e34c3dSBarry Smith 22872875594SBarry Smith .seealso: MatNullSpaceCreate(), MatNullSpaceDestroy(), MatNullSpaceSetFunction() 229a2e34c3dSBarry Smith @*/ 23095902228SMatthew Knepley PetscErrorCode PETSCMAT_DLLEXPORT MatNullSpaceTest(MatNullSpace sp,Mat mat,PetscTruth *isNull) 231a2e34c3dSBarry Smith { 23287828ca2SBarry Smith PetscScalar sum; 2338bb6bcc5SSatish Balay PetscReal nrm; 2340b12b109SJed Brown PetscInt j,n,N; 2356849ba73SBarry Smith PetscErrorCode ierr; 236a2e34c3dSBarry Smith Vec l,r; 23790d69ab7SBarry Smith PetscTruth flg1 = PETSC_FALSE,flg2 = PETSC_FALSE,consistent = PETSC_TRUE; 2383050cee2SBarry Smith PetscViewer viewer; 239a2e34c3dSBarry Smith 240a2e34c3dSBarry Smith PetscFunctionBegin; 2413cfa8680SLisandro Dalcin PetscValidHeaderSpecific(sp,MAT_NULLSPACE_COOKIE,1); 2423cfa8680SLisandro Dalcin PetscValidHeaderSpecific(mat,MAT_COOKIE,2); 2433cfa8680SLisandro Dalcin n = sp->n; 24490d69ab7SBarry Smith ierr = PetscOptionsGetTruth(PETSC_NULL,"-mat_null_space_test_view",&flg1,PETSC_NULL);CHKERRQ(ierr); 24590d69ab7SBarry Smith ierr = PetscOptionsGetTruth(PETSC_NULL,"-mat_null_space_test_view_draw",&flg2,PETSC_NULL);CHKERRQ(ierr); 246a2e34c3dSBarry Smith 247a2e34c3dSBarry Smith if (!sp->vec) { 248a2e34c3dSBarry Smith if (n) { 249a2e34c3dSBarry Smith ierr = VecDuplicate(sp->vecs[0],&sp->vec);CHKERRQ(ierr); 250a2e34c3dSBarry Smith } else { 2510b12b109SJed Brown ierr = MatGetVecs(mat,&sp->vec,PETSC_NULL);CHKERRQ(ierr); 252a2e34c3dSBarry Smith } 253a2e34c3dSBarry Smith } 254a2e34c3dSBarry Smith l = sp->vec; 255a2e34c3dSBarry Smith 2567adad957SLisandro Dalcin ierr = PetscViewerASCIIGetStdout(((PetscObject)sp)->comm,&viewer);CHKERRQ(ierr); 257a2e34c3dSBarry Smith if (sp->has_cnst) { 258a2e34c3dSBarry Smith ierr = VecDuplicate(l,&r);CHKERRQ(ierr); 259a2e34c3dSBarry Smith ierr = VecGetSize(l,&N);CHKERRQ(ierr); 260a2e34c3dSBarry Smith sum = 1.0/N; 2612dcb1b2aSMatthew Knepley ierr = VecSet(l,sum);CHKERRQ(ierr); 262a2e34c3dSBarry Smith ierr = MatMult(mat,l,r);CHKERRQ(ierr); 2638bb6bcc5SSatish Balay ierr = VecNorm(r,NORM_2,&nrm);CHKERRQ(ierr); 26495902228SMatthew Knepley if (nrm < 1.e-7) { 26595902228SMatthew Knepley ierr = PetscPrintf(((PetscObject)sp)->comm,"Constants are likely null vector");CHKERRQ(ierr); 26695902228SMatthew Knepley } else { 26795902228SMatthew Knepley ierr = PetscPrintf(((PetscObject)sp)->comm,"Constants are unlikely null vector ");CHKERRQ(ierr); 26895902228SMatthew Knepley consistent = PETSC_FALSE; 26995902228SMatthew Knepley } 2707adad957SLisandro Dalcin ierr = PetscPrintf(((PetscObject)sp)->comm,"|| A * 1 || = %G\n",nrm);CHKERRQ(ierr); 2713050cee2SBarry Smith if (nrm > 1.e-7 && flg1) {ierr = VecView(r,viewer);CHKERRQ(ierr);} 2723050cee2SBarry Smith if (nrm > 1.e-7 && flg2) {ierr = VecView(r,viewer);CHKERRQ(ierr);} 273a2e34c3dSBarry Smith ierr = VecDestroy(r);CHKERRQ(ierr); 274a2e34c3dSBarry Smith } 275a2e34c3dSBarry Smith 276a2e34c3dSBarry Smith for (j=0; j<n; j++) { 277a2e34c3dSBarry Smith ierr = (*mat->ops->mult)(mat,sp->vecs[j],l);CHKERRQ(ierr); 2788bb6bcc5SSatish Balay ierr = VecNorm(l,NORM_2,&nrm);CHKERRQ(ierr); 27995902228SMatthew Knepley if (nrm < 1.e-7) { 28095902228SMatthew Knepley ierr = PetscPrintf(((PetscObject)sp)->comm,"Null vector %D is likely null vector",j);CHKERRQ(ierr); 28195902228SMatthew Knepley } else { 28295902228SMatthew Knepley ierr = PetscPrintf(((PetscObject)sp)->comm,"Null vector %D unlikely null vector ",j);CHKERRQ(ierr); 28395902228SMatthew Knepley consistent = PETSC_FALSE; 28495902228SMatthew Knepley } 2857adad957SLisandro Dalcin ierr = PetscPrintf(((PetscObject)sp)->comm,"|| A * v[%D] || = %G\n",j,nrm);CHKERRQ(ierr); 2863050cee2SBarry Smith if (nrm > 1.e-7 && flg1) {ierr = VecView(l,viewer);CHKERRQ(ierr);} 2873050cee2SBarry Smith if (nrm > 1.e-7 && flg2) {ierr = VecView(l,viewer);CHKERRQ(ierr);} 288a2e34c3dSBarry Smith } 289a2e34c3dSBarry Smith 29072875594SBarry Smith if (sp->remove){ 29172875594SBarry Smith SETERRQ(PETSC_ERR_SUP,"Cannot test a null space provided as a function with MatNullSpaceSetFunction()"); 29272875594SBarry Smith } 29395902228SMatthew Knepley *isNull = consistent; 294a2e34c3dSBarry Smith PetscFunctionReturn(0); 295a2e34c3dSBarry Smith } 296a2e34c3dSBarry Smith 297