1be1d678aSKris Buschelman 2f7765cecSBarry Smith /* 3b4fd4287SBarry Smith Routines to project vectors out of null spaces. 4f7765cecSBarry Smith */ 5f7765cecSBarry Smith 6af0996ceSBarry Smith #include <petsc/private/matimpl.h> /*I "petscmat.h" I*/ 7f7765cecSBarry Smith 87087cfbeSBarry Smith PetscClassId MAT_NULLSPACE_CLASSID; 98ba1e511SMatthew Knepley 1072875594SBarry Smith /*@C 1172875594SBarry Smith MatNullSpaceSetFunction - set a function that removes a null space from a vector 1272875594SBarry Smith out of null spaces. 1372875594SBarry Smith 143f9fe445SBarry Smith Logically Collective on MatNullSpace 1572875594SBarry Smith 1672875594SBarry Smith Input Parameters: 1772875594SBarry Smith + sp - the null space object 189dbe9a8aSBarry Smith . rem - the function that removes the null space 199dbe9a8aSBarry Smith - ctx - context for the remove function 2072875594SBarry Smith 21658c74aaSSatish Balay Level: advanced 2272875594SBarry Smith 235fa7ec2dSBarry Smith .seealso: MatNullSpaceDestroy(), MatNullSpaceRemove(), MatSetNullSpace(), MatNullSpace, MatNullSpaceCreate() 2472875594SBarry Smith @*/ 257087cfbeSBarry Smith PetscErrorCode MatNullSpaceSetFunction(MatNullSpace sp, PetscErrorCode (*rem)(MatNullSpace,Vec,void*),void *ctx) 2672875594SBarry Smith { 2772875594SBarry Smith PetscFunctionBegin; 280700a824SBarry Smith PetscValidHeaderSpecific(sp,MAT_NULLSPACE_CLASSID,1); 299dbe9a8aSBarry Smith sp->remove = rem; 309dbe9a8aSBarry Smith sp->rmctx = ctx; 3172875594SBarry Smith PetscFunctionReturn(0); 3272875594SBarry Smith } 3372875594SBarry Smith 34009ec7a5SJed Brown /*@C 35009ec7a5SJed Brown MatNullSpaceGetVecs - get vectors defining the null space 36009ec7a5SJed Brown 37009ec7a5SJed Brown Not Collective 38009ec7a5SJed Brown 394165533cSJose E. Roman Input Parameter: 40009ec7a5SJed Brown . sp - null space object 41009ec7a5SJed Brown 424165533cSJose E. Roman Output Parameters: 43009ec7a5SJed Brown + has_cnst - PETSC_TRUE if the null space contains the constant vector, otherwise PETSC_FALSE 44009ec7a5SJed Brown . n - number of vectors (excluding constant vector) in null space 45009ec7a5SJed Brown - vecs - orthonormal vectors that span the null space (excluding the constant vector) 46009ec7a5SJed Brown 47009ec7a5SJed Brown Level: developer 48009ec7a5SJed Brown 492a7a6963SBarry Smith Notes: 502a7a6963SBarry Smith These vectors and the array are owned by the MatNullSpace and should not be destroyed or freeded by the caller 512a7a6963SBarry Smith 52009ec7a5SJed Brown .seealso: MatNullSpaceCreate(), MatGetNullSpace(), MatGetNearNullSpace() 53009ec7a5SJed Brown @*/ 54009ec7a5SJed Brown PetscErrorCode MatNullSpaceGetVecs(MatNullSpace sp,PetscBool *has_const,PetscInt *n,const Vec **vecs) 55009ec7a5SJed Brown { 56009ec7a5SJed Brown 57009ec7a5SJed Brown PetscFunctionBegin; 58009ec7a5SJed Brown PetscValidHeaderSpecific(sp,MAT_NULLSPACE_CLASSID,1); 59009ec7a5SJed Brown if (has_const) *has_const = sp->has_cnst; 60009ec7a5SJed Brown if (n) *n = sp->n; 61009ec7a5SJed Brown if (vecs) *vecs = sp->vecs; 62009ec7a5SJed Brown PetscFunctionReturn(0); 63009ec7a5SJed Brown } 64009ec7a5SJed Brown 65009ec7a5SJed Brown /*@ 66009ec7a5SJed Brown MatNullSpaceCreateRigidBody - create rigid body modes from coordinates 67009ec7a5SJed Brown 68009ec7a5SJed Brown Collective on Vec 69009ec7a5SJed Brown 704165533cSJose E. Roman Input Parameter: 71009ec7a5SJed Brown . coords - block of coordinates of each node, must have block size set 72009ec7a5SJed Brown 734165533cSJose E. Roman Output Parameter: 74009ec7a5SJed Brown . sp - the null space 75009ec7a5SJed Brown 76009ec7a5SJed Brown Level: advanced 77009ec7a5SJed Brown 7895452b02SPatrick Sanan Notes: 7969858f1bSStefano Zampini If you are solving an elasticity problem you should likely use this, in conjunction with MatSetNearNullspace(), to provide information that 8040220148SBarry Smith the PCGAMG preconditioner can use to construct a much more efficient preconditioner. 8140220148SBarry Smith 8240220148SBarry Smith If you are solving an elasticity problem with pure Neumann boundary conditions you can use this in conjunction with MatSetNullspace() to 8340220148SBarry Smith provide this information to the linear solver so it can handle the null space appropriately in the linear solution. 8440220148SBarry Smith 8540220148SBarry Smith .seealso: MatNullSpaceCreate(), MatSetNearNullspace(), MatSetNullspace() 86009ec7a5SJed Brown @*/ 87009ec7a5SJed Brown PetscErrorCode MatNullSpaceCreateRigidBody(Vec coords,MatNullSpace *sp) 88009ec7a5SJed Brown { 89009ec7a5SJed Brown PetscErrorCode ierr; 90009ec7a5SJed Brown const PetscScalar *x; 91bee94d3eSJed Brown PetscScalar *v[6],dots[5]; 92009ec7a5SJed Brown Vec vec[6]; 93009ec7a5SJed Brown PetscInt n,N,dim,nmodes,i,j; 94eb7a2786SBarry Smith PetscReal sN; 95009ec7a5SJed Brown 96009ec7a5SJed Brown PetscFunctionBegin; 97009ec7a5SJed Brown ierr = VecGetBlockSize(coords,&dim);CHKERRQ(ierr); 98009ec7a5SJed Brown ierr = VecGetLocalSize(coords,&n);CHKERRQ(ierr); 99009ec7a5SJed Brown ierr = VecGetSize(coords,&N);CHKERRQ(ierr); 100009ec7a5SJed Brown n /= dim; 101009ec7a5SJed Brown N /= dim; 102eb7a2786SBarry Smith sN = 1./PetscSqrtReal((PetscReal)N); 103009ec7a5SJed Brown switch (dim) { 104009ec7a5SJed Brown case 1: 105ce94432eSBarry Smith ierr = MatNullSpaceCreate(PetscObjectComm((PetscObject)coords),PETSC_TRUE,0,NULL,sp);CHKERRQ(ierr); 106009ec7a5SJed Brown break; 107009ec7a5SJed Brown case 2: 108009ec7a5SJed Brown case 3: 109009ec7a5SJed Brown nmodes = (dim == 2) ? 3 : 6; 110ce94432eSBarry Smith ierr = VecCreate(PetscObjectComm((PetscObject)coords),&vec[0]);CHKERRQ(ierr); 111009ec7a5SJed Brown ierr = VecSetSizes(vec[0],dim*n,dim*N);CHKERRQ(ierr); 112009ec7a5SJed Brown ierr = VecSetBlockSize(vec[0],dim);CHKERRQ(ierr); 113009ec7a5SJed Brown ierr = VecSetUp(vec[0]);CHKERRQ(ierr); 114009ec7a5SJed Brown for (i=1; i<nmodes; i++) {ierr = VecDuplicate(vec[0],&vec[i]);CHKERRQ(ierr);} 115009ec7a5SJed Brown for (i=0; i<nmodes; i++) {ierr = VecGetArray(vec[i],&v[i]);CHKERRQ(ierr);} 116009ec7a5SJed Brown ierr = VecGetArrayRead(coords,&x);CHKERRQ(ierr); 117009ec7a5SJed Brown for (i=0; i<n; i++) { 118009ec7a5SJed Brown if (dim == 2) { 119eb7a2786SBarry Smith v[0][i*2+0] = sN; 120009ec7a5SJed Brown v[0][i*2+1] = 0.; 121009ec7a5SJed Brown v[1][i*2+0] = 0.; 122eb7a2786SBarry Smith v[1][i*2+1] = sN; 123009ec7a5SJed Brown /* Rotations */ 124009ec7a5SJed Brown v[2][i*2+0] = -x[i*2+1]; 125009ec7a5SJed Brown v[2][i*2+1] = x[i*2+0]; 126009ec7a5SJed Brown } else { 127eb7a2786SBarry Smith v[0][i*3+0] = sN; 128009ec7a5SJed Brown v[0][i*3+1] = 0.; 129009ec7a5SJed Brown v[0][i*3+2] = 0.; 130009ec7a5SJed Brown v[1][i*3+0] = 0.; 131eb7a2786SBarry Smith v[1][i*3+1] = sN; 132009ec7a5SJed Brown v[1][i*3+2] = 0.; 133009ec7a5SJed Brown v[2][i*3+0] = 0.; 134009ec7a5SJed Brown v[2][i*3+1] = 0.; 135eb7a2786SBarry Smith v[2][i*3+2] = sN; 136009ec7a5SJed Brown 137009ec7a5SJed Brown v[3][i*3+0] = x[i*3+1]; 138009ec7a5SJed Brown v[3][i*3+1] = -x[i*3+0]; 139009ec7a5SJed Brown v[3][i*3+2] = 0.; 140009ec7a5SJed Brown v[4][i*3+0] = 0.; 141009ec7a5SJed Brown v[4][i*3+1] = -x[i*3+2]; 142009ec7a5SJed Brown v[4][i*3+2] = x[i*3+1]; 143009ec7a5SJed Brown v[5][i*3+0] = x[i*3+2]; 144009ec7a5SJed Brown v[5][i*3+1] = 0.; 145009ec7a5SJed Brown v[5][i*3+2] = -x[i*3+0]; 146009ec7a5SJed Brown } 147009ec7a5SJed Brown } 148009ec7a5SJed Brown for (i=0; i<nmodes; i++) {ierr = VecRestoreArray(vec[i],&v[i]);CHKERRQ(ierr);} 149009ec7a5SJed Brown ierr = VecRestoreArrayRead(coords,&x);CHKERRQ(ierr); 150009ec7a5SJed Brown for (i=dim; i<nmodes; i++) { 151bee94d3eSJed Brown /* Orthonormalize vec[i] against vec[0:i-1] */ 152009ec7a5SJed Brown ierr = VecMDot(vec[i],i,vec,dots);CHKERRQ(ierr); 153009ec7a5SJed Brown for (j=0; j<i; j++) dots[j] *= -1.; 154009ec7a5SJed Brown ierr = VecMAXPY(vec[i],i,dots,vec);CHKERRQ(ierr); 1550298fd71SBarry Smith ierr = VecNormalize(vec[i],NULL);CHKERRQ(ierr); 156009ec7a5SJed Brown } 157ce94432eSBarry Smith ierr = MatNullSpaceCreate(PetscObjectComm((PetscObject)coords),PETSC_FALSE,nmodes,vec,sp);CHKERRQ(ierr); 158009ec7a5SJed Brown for (i=0; i<nmodes; i++) {ierr = VecDestroy(&vec[i]);CHKERRQ(ierr);} 159009ec7a5SJed Brown } 160009ec7a5SJed Brown PetscFunctionReturn(0); 161009ec7a5SJed Brown } 162009ec7a5SJed Brown 163b717e993SJed Brown /*@C 164b717e993SJed Brown MatNullSpaceView - Visualizes a null space object. 165b717e993SJed Brown 166b717e993SJed Brown Collective on MatNullSpace 167b717e993SJed Brown 168b717e993SJed Brown Input Parameters: 169b717e993SJed Brown + matnull - the null space 170b717e993SJed Brown - viewer - visualization context 171b717e993SJed Brown 172b717e993SJed Brown Level: advanced 173b717e993SJed Brown 174b717e993SJed Brown Fortran Note: 175b717e993SJed Brown This routine is not supported in Fortran. 176b717e993SJed Brown 177b717e993SJed Brown .seealso: MatNullSpaceCreate(), PetscViewerASCIIOpen() 178b717e993SJed Brown @*/ 179b717e993SJed Brown PetscErrorCode MatNullSpaceView(MatNullSpace sp,PetscViewer viewer) 180f7357b39SLisandro Dalcin { 181f7357b39SLisandro Dalcin PetscErrorCode ierr; 182f7357b39SLisandro Dalcin PetscBool iascii; 183f7357b39SLisandro Dalcin 184f7357b39SLisandro Dalcin PetscFunctionBegin; 185f7357b39SLisandro Dalcin PetscValidHeaderSpecific(sp,MAT_NULLSPACE_CLASSID,1); 186f55353a2SBarry Smith if (!viewer) { 187f55353a2SBarry Smith ierr = PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)sp),&viewer);CHKERRQ(ierr); 188f55353a2SBarry Smith } 189f7357b39SLisandro Dalcin PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2); 190f7357b39SLisandro Dalcin PetscCheckSameComm(sp,1,viewer,2); 191f7357b39SLisandro Dalcin 192251f4c67SDmitry Karpeev ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); 193f7357b39SLisandro Dalcin if (iascii) { 19402cf292fSJed Brown PetscViewerFormat format; 19502cf292fSJed Brown PetscInt i; 19602cf292fSJed Brown ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr); 197dae58748SBarry Smith ierr = PetscObjectPrintClassNamePrefixType((PetscObject)sp,viewer);CHKERRQ(ierr); 19802cf292fSJed Brown ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 19902cf292fSJed Brown ierr = PetscViewerASCIIPrintf(viewer,"Contains %D vector%s%s\n",sp->n,sp->n==1 ? "" : "s",sp->has_cnst ? " and the constant" : "");CHKERRQ(ierr); 20002cf292fSJed Brown if (sp->remove) {ierr = PetscViewerASCIIPrintf(viewer,"Has user-provided removal function\n");CHKERRQ(ierr);} 20102cf292fSJed Brown if (!(format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL)) { 20202cf292fSJed Brown for (i=0; i<sp->n; i++) { 20302cf292fSJed Brown ierr = VecView(sp->vecs[i],viewer);CHKERRQ(ierr); 20402cf292fSJed Brown } 20502cf292fSJed Brown } 20602cf292fSJed Brown ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 207f7357b39SLisandro Dalcin } 208f7357b39SLisandro Dalcin PetscFunctionReturn(0); 209f7357b39SLisandro Dalcin } 210f7357b39SLisandro Dalcin 211c3c607ccSBarry Smith /*@C 2125cfeda75SBarry Smith MatNullSpaceCreate - Creates a data structure used to project vectors 213b4fd4287SBarry Smith out of null spaces. 214f7765cecSBarry Smith 215d083f849SBarry Smith Collective 2164e472627SLois Curfman McInnes 217f7765cecSBarry Smith Input Parameters: 21883c3bef8SLois Curfman McInnes + comm - the MPI communicator associated with the object 21983c3bef8SLois Curfman McInnes . has_cnst - PETSC_TRUE if the null space contains the constant vector; otherwise PETSC_FALSE 220b4fd4287SBarry Smith . n - number of vectors (excluding constant vector) in null space 22183c3bef8SLois Curfman McInnes - vecs - the vectors that span the null space (excluding the constant vector); 222f7a9e4ceSBarry Smith these vectors must be orthonormal. These vectors are NOT copied, so do not change them 22373141a14SBarry Smith after this call. You should free the array that you pass in and destroy the vectors (this will reduce the reference count 22473141a14SBarry Smith for them by one). 225f7765cecSBarry Smith 226f7765cecSBarry Smith Output Parameter: 227b4fd4287SBarry Smith . SP - the null space context 228f7765cecSBarry Smith 22983c3bef8SLois Curfman McInnes Level: advanced 23083c3bef8SLois Curfman McInnes 23195452b02SPatrick Sanan Notes: 23295452b02SPatrick Sanan See MatNullSpaceSetFunction() as an alternative way of providing the null space information instead of setting vecs. 23380bf1014SBarry Smith 23480bf1014SBarry 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 23580bf1014SBarry Smith need to pass in a function that eliminates the constant function into MatNullSpaceSetFunction(). 23680bf1014SBarry Smith 2376e1639daSBarry Smith Users manual sections: 2386e1639daSBarry Smith . sec_singular 2396e1639daSBarry Smith 2405fa7ec2dSBarry Smith .seealso: MatNullSpaceDestroy(), MatNullSpaceRemove(), MatSetNullSpace(), MatNullSpace, MatNullSpaceSetFunction() 241f7765cecSBarry Smith @*/ 2427087cfbeSBarry Smith PetscErrorCode MatNullSpaceCreate(MPI_Comm comm,PetscBool has_cnst,PetscInt n,const Vec vecs[],MatNullSpace *SP) 243f7765cecSBarry Smith { 2445cfeda75SBarry Smith MatNullSpace sp; 245dfbe8321SBarry Smith PetscErrorCode ierr; 246c1ac3661SBarry Smith PetscInt i; 247f7765cecSBarry Smith 2483a40ed3dSBarry Smith PetscFunctionBegin; 249e32f2f54SBarry Smith if (n < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Number of vectors (given %D) cannot be negative",n); 250574b3360SMatthew Knepley if (n) PetscValidPointer(vecs,4); 2510700a824SBarry Smith for (i=0; i<n; i++) PetscValidHeaderSpecific(vecs[i],VEC_CLASSID,4); 252574b3360SMatthew Knepley PetscValidPointer(SP,5); 2539d2471e0SBarry Smith if (n) { 2549d2471e0SBarry Smith for (i=0; i<n; i++) { 2559d2471e0SBarry Smith /* prevent the user from changes values in the vector */ 2568860a134SJunchao Zhang ierr = VecLockReadPush(vecs[i]);CHKERRQ(ierr); 2579d2471e0SBarry Smith } 2589d2471e0SBarry Smith } 259cf9c20a2SJed Brown if (PetscUnlikelyDebug(n)) { 26096ded551SBarry Smith PetscScalar *dots; 26196ded551SBarry Smith for (i=0; i<n; i++) { 26296ded551SBarry Smith PetscReal norm; 26396ded551SBarry Smith ierr = VecNorm(vecs[i],NORM_2,&norm);CHKERRQ(ierr); 264c068d9bbSLisandro Dalcin if (PetscAbsReal(norm - 1) > PETSC_SQRT_MACHINE_EPSILON) SETERRQ2(PetscObjectComm((PetscObject)vecs[i]),PETSC_ERR_ARG_WRONG,"Vector %D must have 2-norm of 1.0, it is %g",i,(double)norm); 26596ded551SBarry Smith } 26696ded551SBarry Smith if (has_cnst) { 26796ded551SBarry Smith for (i=0; i<n; i++) { 26896ded551SBarry Smith PetscScalar sum; 26996ded551SBarry Smith ierr = VecSum(vecs[i],&sum);CHKERRQ(ierr); 2701cb85adbSBarry Smith if (PetscAbsScalar(sum) > PETSC_SQRT_MACHINE_EPSILON) SETERRQ2(PetscObjectComm((PetscObject)vecs[i]),PETSC_ERR_ARG_WRONG,"Vector %D must be orthogonal to constant vector, inner product is %g",i,(double)PetscAbsScalar(sum)); 27196ded551SBarry Smith } 27296ded551SBarry Smith } 27396ded551SBarry Smith ierr = PetscMalloc1(n-1,&dots);CHKERRQ(ierr); 27496ded551SBarry Smith for (i=0; i<n-1; i++) { 27596ded551SBarry Smith PetscInt j; 27696ded551SBarry Smith ierr = VecMDot(vecs[i],n-i-1,vecs+i+1,dots);CHKERRQ(ierr); 27796ded551SBarry Smith for (j=0;j<n-i-1;j++) { 2781cb85adbSBarry Smith if (PetscAbsScalar(dots[j]) > PETSC_SQRT_MACHINE_EPSILON) SETERRQ3(PetscObjectComm((PetscObject)vecs[i]),PETSC_ERR_ARG_WRONG,"Vector %D must be orthogonal to vector %D, inner product is %g",i,i+j+1,(double)PetscAbsScalar(dots[j])); 27996ded551SBarry Smith } 28096ded551SBarry Smith } 281*2f613bf5SBarry Smith ierr = PetscFree(dots);CHKERRQ(ierr); 28296ded551SBarry Smith } 283574b3360SMatthew Knepley 2840298fd71SBarry Smith *SP = NULL; 285607a6623SBarry Smith ierr = MatInitializePackage();CHKERRQ(ierr); 286574b3360SMatthew Knepley 28773107ff1SLisandro Dalcin ierr = PetscHeaderCreate(sp,MAT_NULLSPACE_CLASSID,"MatNullSpace","Null space","Mat",comm,MatNullSpaceDestroy,MatNullSpaceView);CHKERRQ(ierr); 288f7765cecSBarry Smith 289b4fd4287SBarry Smith sp->has_cnst = has_cnst; 290b4fd4287SBarry Smith sp->n = n; 291f4259b30SLisandro Dalcin sp->vecs = NULL; 292f4259b30SLisandro Dalcin sp->alpha = NULL; 293f4259b30SLisandro Dalcin sp->remove = NULL; 294f4259b30SLisandro Dalcin sp->rmctx = NULL; 2957850f3fbSLisandro Dalcin 296f7a9e4ceSBarry Smith if (n) { 297785e854fSJed Brown ierr = PetscMalloc1(n,&sp->vecs);CHKERRQ(ierr); 298785e854fSJed Brown ierr = PetscMalloc1(n,&sp->alpha);CHKERRQ(ierr); 2993bb1ff40SBarry Smith ierr = PetscLogObjectMemory((PetscObject)sp,n*(sizeof(Vec)+sizeof(PetscScalar)));CHKERRQ(ierr); 3007850f3fbSLisandro Dalcin for (i=0; i<n; i++) { 3017850f3fbSLisandro Dalcin ierr = PetscObjectReference((PetscObject)vecs[i]);CHKERRQ(ierr); 3027850f3fbSLisandro Dalcin sp->vecs[i] = vecs[i]; 3037850f3fbSLisandro Dalcin } 304f7a9e4ceSBarry Smith } 305b4fd4287SBarry Smith 306b4fd4287SBarry Smith *SP = sp; 3073a40ed3dSBarry Smith PetscFunctionReturn(0); 308f7765cecSBarry Smith } 309f7765cecSBarry Smith 310f7765cecSBarry Smith /*@ 3115cfeda75SBarry Smith MatNullSpaceDestroy - Destroys a data structure used to project vectors 312b4fd4287SBarry Smith out of null spaces. 313b4fd4287SBarry Smith 3145cfeda75SBarry Smith Collective on MatNullSpace 3154e472627SLois Curfman McInnes 316b4fd4287SBarry Smith Input Parameter: 317b9756687SLois Curfman McInnes . sp - the null space context to be destroyed 318b9756687SLois Curfman McInnes 319b9756687SLois Curfman McInnes Level: advanced 320b4fd4287SBarry Smith 32172875594SBarry Smith .seealso: MatNullSpaceCreate(), MatNullSpaceRemove(), MatNullSpaceSetFunction() 322b4fd4287SBarry Smith @*/ 323d34fcf5fSBarry Smith PetscErrorCode MatNullSpaceDestroy(MatNullSpace *sp) 324b4fd4287SBarry Smith { 325dfbe8321SBarry Smith PetscErrorCode ierr; 3269d2471e0SBarry Smith PetscInt i; 32785614651SBarry Smith 3285cfeda75SBarry Smith PetscFunctionBegin; 3296bf464f9SBarry Smith if (!*sp) PetscFunctionReturn(0); 330d34fcf5fSBarry Smith PetscValidHeaderSpecific((*sp),MAT_NULLSPACE_CLASSID,1); 331f4259b30SLisandro Dalcin if (--((PetscObject)(*sp))->refct > 0) {*sp = NULL; PetscFunctionReturn(0);} 33285614651SBarry Smith 3339d2471e0SBarry Smith for (i=0; i < (*sp)->n; i++) { 3348860a134SJunchao Zhang ierr = VecLockReadPop((*sp)->vecs[i]);CHKERRQ(ierr); 3359d2471e0SBarry Smith } 3369d2471e0SBarry Smith 3376bf464f9SBarry Smith ierr = VecDestroyVecs((*sp)->n,&(*sp)->vecs);CHKERRQ(ierr); 338d34fcf5fSBarry Smith ierr = PetscFree((*sp)->alpha);CHKERRQ(ierr); 3396bf464f9SBarry Smith ierr = PetscHeaderDestroy(sp);CHKERRQ(ierr); 3403a40ed3dSBarry Smith PetscFunctionReturn(0); 341b4fd4287SBarry Smith } 342b4fd4287SBarry Smith 343812c3f48SMatthew Knepley /*@C 3445cfeda75SBarry Smith MatNullSpaceRemove - Removes all the components of a null space from a vector. 345f7765cecSBarry Smith 3465cfeda75SBarry Smith Collective on MatNullSpace 347f7765cecSBarry Smith 3484e472627SLois Curfman McInnes Input Parameters: 349260663b8SBarry Smith + sp - the null space context (if this is NULL then no null space is removed) 350359a2de3SMatthew G. Knepley - vec - the vector from which the null space is to be removed 3514e472627SLois Curfman McInnes 352b9756687SLois Curfman McInnes Level: advanced 353b9756687SLois Curfman McInnes 35472875594SBarry Smith .seealso: MatNullSpaceCreate(), MatNullSpaceDestroy(), MatNullSpaceSetFunction() 355f7765cecSBarry Smith @*/ 356d0195637SJed Brown PetscErrorCode MatNullSpaceRemove(MatNullSpace sp,Vec vec) 357f7765cecSBarry Smith { 35887828ca2SBarry Smith PetscScalar sum; 3597850f3fbSLisandro Dalcin PetscInt i,N; 3606849ba73SBarry Smith PetscErrorCode ierr; 361f7765cecSBarry Smith 3623a40ed3dSBarry Smith PetscFunctionBegin; 363260663b8SBarry Smith if (!sp) PetscFunctionReturn(0); 3640700a824SBarry Smith PetscValidHeaderSpecific(sp,MAT_NULLSPACE_CLASSID,1); 3650700a824SBarry Smith PetscValidHeaderSpecific(vec,VEC_CLASSID,2); 3663cd8ff7eSMatthew Knepley 367b4fd4287SBarry Smith if (sp->has_cnst) { 3687850f3fbSLisandro Dalcin ierr = VecGetSize(vec,&N);CHKERRQ(ierr); 3697850f3fbSLisandro Dalcin if (N > 0) { 3707850f3fbSLisandro Dalcin ierr = VecSum(vec,&sum);CHKERRQ(ierr); 371d4a378daSJed Brown sum = sum/((PetscScalar)(-1.0*N)); 3727850f3fbSLisandro Dalcin ierr = VecShift(vec,sum);CHKERRQ(ierr); 3737850f3fbSLisandro Dalcin } 374f7765cecSBarry Smith } 375b4fd4287SBarry Smith 3767850f3fbSLisandro Dalcin if (sp->n) { 3777850f3fbSLisandro Dalcin ierr = VecMDot(vec,sp->n,sp->vecs,sp->alpha);CHKERRQ(ierr); 3787850f3fbSLisandro Dalcin for (i=0; i<sp->n; i++) sp->alpha[i] = -sp->alpha[i]; 3797850f3fbSLisandro Dalcin ierr = VecMAXPY(vec,sp->n,sp->alpha,sp->vecs);CHKERRQ(ierr); 380f7765cecSBarry Smith } 381b4fd4287SBarry Smith 38272875594SBarry Smith if (sp->remove) { 3830c3c4d68SMatthew Knepley ierr = (*sp->remove)(sp,vec,sp->rmctx);CHKERRQ(ierr); 38472875594SBarry Smith } 3853a40ed3dSBarry Smith PetscFunctionReturn(0); 386f7765cecSBarry Smith } 387a2e34c3dSBarry Smith 388a2e34c3dSBarry Smith /*@ 389a2e34c3dSBarry Smith MatNullSpaceTest - Tests if the claimed null space is really a 390a2e34c3dSBarry Smith null space of a matrix 391a2e34c3dSBarry Smith 392a2e34c3dSBarry Smith Collective on MatNullSpace 393a2e34c3dSBarry Smith 394a2e34c3dSBarry Smith Input Parameters: 395a2e34c3dSBarry Smith + sp - the null space context 396a2e34c3dSBarry Smith - mat - the matrix 397a2e34c3dSBarry Smith 39895902228SMatthew Knepley Output Parameters: 39995902228SMatthew Knepley . isNull - PETSC_TRUE if the nullspace is valid for this matrix 40095902228SMatthew Knepley 401a2e34c3dSBarry Smith Level: advanced 402a2e34c3dSBarry Smith 40372875594SBarry Smith .seealso: MatNullSpaceCreate(), MatNullSpaceDestroy(), MatNullSpaceSetFunction() 404a2e34c3dSBarry Smith @*/ 4057087cfbeSBarry Smith PetscErrorCode MatNullSpaceTest(MatNullSpace sp,Mat mat,PetscBool *isNull) 406a2e34c3dSBarry Smith { 40787828ca2SBarry Smith PetscScalar sum; 408a872bbdcSToby Isaac PetscReal nrm,tol = 10. * PETSC_SQRT_MACHINE_EPSILON; 4090b12b109SJed Brown PetscInt j,n,N; 4106849ba73SBarry Smith PetscErrorCode ierr; 411a2e34c3dSBarry Smith Vec l,r; 412ace3abfcSBarry Smith PetscBool flg1 = PETSC_FALSE,flg2 = PETSC_FALSE,consistent = PETSC_TRUE; 4133050cee2SBarry Smith PetscViewer viewer; 414a2e34c3dSBarry Smith 415a2e34c3dSBarry Smith PetscFunctionBegin; 4160700a824SBarry Smith PetscValidHeaderSpecific(sp,MAT_NULLSPACE_CLASSID,1); 4170700a824SBarry Smith PetscValidHeaderSpecific(mat,MAT_CLASSID,2); 4183cfa8680SLisandro Dalcin n = sp->n; 419fb04ea6fSLawrence Mitchell ierr = PetscOptionsGetBool(((PetscObject)sp)->options,((PetscObject)mat)->prefix,"-mat_null_space_test_view",&flg1,NULL);CHKERRQ(ierr); 420fb04ea6fSLawrence Mitchell ierr = PetscOptionsGetBool(((PetscObject)sp)->options,((PetscObject)mat)->prefix,"-mat_null_space_test_view_draw",&flg2,NULL);CHKERRQ(ierr); 421a2e34c3dSBarry Smith 422a2e34c3dSBarry Smith if (n) { 423401b765aSJed Brown ierr = VecDuplicate(sp->vecs[0],&l);CHKERRQ(ierr); 424a2e34c3dSBarry Smith } else { 4252a7a6963SBarry Smith ierr = MatCreateVecs(mat,&l,NULL);CHKERRQ(ierr); 426a2e34c3dSBarry Smith } 427a2e34c3dSBarry Smith 428ce94432eSBarry Smith ierr = PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)sp),&viewer);CHKERRQ(ierr); 429a2e34c3dSBarry Smith if (sp->has_cnst) { 430a2e34c3dSBarry Smith ierr = VecDuplicate(l,&r);CHKERRQ(ierr); 431a2e34c3dSBarry Smith ierr = VecGetSize(l,&N);CHKERRQ(ierr); 432a2e34c3dSBarry Smith sum = 1.0/N; 4332dcb1b2aSMatthew Knepley ierr = VecSet(l,sum);CHKERRQ(ierr); 434a2e34c3dSBarry Smith ierr = MatMult(mat,l,r);CHKERRQ(ierr); 4358bb6bcc5SSatish Balay ierr = VecNorm(r,NORM_2,&nrm);CHKERRQ(ierr); 436a872bbdcSToby Isaac if (nrm >= tol) consistent = PETSC_FALSE; 437874288d9SMatthew G Knepley if (flg1) { 43818404f68SMatthew G Knepley if (consistent) { 439ce94432eSBarry Smith ierr = PetscPrintf(PetscObjectComm((PetscObject)sp),"Constants are likely null vector");CHKERRQ(ierr); 44095902228SMatthew Knepley } else { 441ce94432eSBarry Smith ierr = PetscPrintf(PetscObjectComm((PetscObject)sp),"Constants are unlikely null vector ");CHKERRQ(ierr); 44295902228SMatthew Knepley } 44357622a8eSBarry Smith ierr = PetscPrintf(PetscObjectComm((PetscObject)sp),"|| A * 1/N || = %g\n",(double)nrm);CHKERRQ(ierr); 444874288d9SMatthew G Knepley } 44518404f68SMatthew G Knepley if (!consistent && flg1) {ierr = VecView(r,viewer);CHKERRQ(ierr);} 44618404f68SMatthew G Knepley if (!consistent && flg2) {ierr = VecView(r,viewer);CHKERRQ(ierr);} 4476bf464f9SBarry Smith ierr = VecDestroy(&r);CHKERRQ(ierr); 448a2e34c3dSBarry Smith } 449a2e34c3dSBarry Smith 450a2e34c3dSBarry Smith for (j=0; j<n; j++) { 451a2e34c3dSBarry Smith ierr = (*mat->ops->mult)(mat,sp->vecs[j],l);CHKERRQ(ierr); 4528bb6bcc5SSatish Balay ierr = VecNorm(l,NORM_2,&nrm);CHKERRQ(ierr); 453a872bbdcSToby Isaac if (nrm >= tol) consistent = PETSC_FALSE; 454874288d9SMatthew G Knepley if (flg1) { 45518404f68SMatthew G Knepley if (consistent) { 456ce94432eSBarry Smith ierr = PetscPrintf(PetscObjectComm((PetscObject)sp),"Null vector %D is likely null vector",j);CHKERRQ(ierr); 45795902228SMatthew Knepley } else { 458ce94432eSBarry Smith ierr = PetscPrintf(PetscObjectComm((PetscObject)sp),"Null vector %D unlikely null vector ",j);CHKERRQ(ierr); 45995902228SMatthew Knepley consistent = PETSC_FALSE; 46095902228SMatthew Knepley } 46157622a8eSBarry Smith ierr = PetscPrintf(PetscObjectComm((PetscObject)sp),"|| A * v[%D] || = %g\n",j,(double)nrm);CHKERRQ(ierr); 462874288d9SMatthew G Knepley } 46318404f68SMatthew G Knepley if (!consistent && flg1) {ierr = VecView(l,viewer);CHKERRQ(ierr);} 46418404f68SMatthew G Knepley if (!consistent && flg2) {ierr = VecView(l,viewer);CHKERRQ(ierr);} 465a2e34c3dSBarry Smith } 466a2e34c3dSBarry Smith 467ce94432eSBarry Smith if (sp->remove) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot test a null space provided as a function with MatNullSpaceSetFunction()"); 468401b765aSJed Brown ierr = VecDestroy(&l);CHKERRQ(ierr); 46931980aa1SBarry Smith if (isNull) *isNull = consistent; 470a2e34c3dSBarry Smith PetscFunctionReturn(0); 471a2e34c3dSBarry Smith } 472