xref: /petsc/src/mat/interface/matnull.c (revision 2f613bf53f46f9356e00a2ca2bd69453be72fc31)
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