xref: /petsc/src/mat/interface/matnull.c (revision 3cfa868005f9094c013e5a0923a816520f5fe8a6)
1be1d678aSKris Buschelman #define PETSCMAT_DLL
2be1d678aSKris Buschelman 
3f7765cecSBarry Smith /*
4b4fd4287SBarry Smith     Routines to project vectors out of null spaces.
5f7765cecSBarry Smith */
6f7765cecSBarry Smith 
7b9147fbbSdalcinl #include "include/private/matimpl.h"      /*I "petscmat.h" I*/
8e090d566SSatish Balay #include "petscsys.h"
9f7765cecSBarry Smith 
10be1d678aSKris Buschelman PetscCookie PETSCMAT_DLLEXPORT MAT_NULLSPACE_COOKIE = 0;
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;
34*3cfa8680SLisandro 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
54f7a9e4ceSBarry Smith           after this call. You should free the array that you pass in.
55f7765cecSBarry Smith 
56f7765cecSBarry Smith    Output Parameter:
57b4fd4287SBarry Smith .  SP - the null space context
58f7765cecSBarry Smith 
5983c3bef8SLois Curfman McInnes    Level: advanced
6083c3bef8SLois Curfman McInnes 
616e1639daSBarry Smith   Users manual sections:
626e1639daSBarry Smith .   sec_singular
636e1639daSBarry Smith 
6483c3bef8SLois Curfman McInnes .keywords: PC, null space, create
6541a59933SSatish Balay 
6672875594SBarry Smith .seealso: MatNullSpaceDestroy(), MatNullSpaceRemove(), KSPSetNullSpace(), MatNullSpace, MatNullSpaceSetFunction()
67f7765cecSBarry Smith @*/
68be1d678aSKris Buschelman PetscErrorCode PETSCMAT_DLLEXPORT MatNullSpaceCreate(MPI_Comm comm,PetscTruth has_cnst,PetscInt n,const Vec vecs[],MatNullSpace *SP)
69f7765cecSBarry Smith {
705cfeda75SBarry Smith   MatNullSpace   sp;
71dfbe8321SBarry Smith   PetscErrorCode ierr;
72c1ac3661SBarry Smith   PetscInt       i;
73f7765cecSBarry Smith 
743a40ed3dSBarry Smith   PetscFunctionBegin;
75574b3360SMatthew Knepley   if (n) PetscValidPointer(vecs,4);
76574b3360SMatthew Knepley   for (i=0; i<n; i++) PetscValidHeaderSpecific(vecs[i],VEC_COOKIE,4);
77574b3360SMatthew Knepley   PetscValidPointer(SP,5);
78574b3360SMatthew Knepley 
79574b3360SMatthew Knepley   *SP = PETSC_NULL;
80574b3360SMatthew Knepley #ifndef PETSC_USE_DYNAMIC_LIBRARIES
81574b3360SMatthew Knepley   ierr = MatInitializePackage(PETSC_NULL);CHKERRQ(ierr);
82574b3360SMatthew Knepley #endif
83574b3360SMatthew Knepley 
8452e6d16bSBarry Smith   ierr = PetscHeaderCreate(sp,_p_MatNullSpace,int,MAT_NULLSPACE_COOKIE,0,"MatNullSpace",comm,MatNullSpaceDestroy,0);CHKERRQ(ierr);
8552e6d16bSBarry Smith   ierr = PetscLogObjectMemory(sp,sizeof(struct _p_MatNullSpace));CHKERRQ(ierr);
86f7765cecSBarry Smith 
87b4fd4287SBarry Smith   sp->has_cnst = has_cnst;
88b4fd4287SBarry Smith   sp->n        = n;
895cfeda75SBarry Smith   sp->vec      = PETSC_NULL;
90f7a9e4ceSBarry Smith   if (n) {
91f7a9e4ceSBarry Smith     ierr = PetscMalloc(n*sizeof(Vec),&sp->vecs);CHKERRQ(ierr);
92f7a9e4ceSBarry Smith     for (i=0; i<n; i++) sp->vecs[i] = vecs[i];
93f7a9e4ceSBarry Smith   } else {
94f7a9e4ceSBarry Smith     sp->vecs = 0;
95f7a9e4ceSBarry Smith   }
96b4fd4287SBarry Smith 
97f7a9e4ceSBarry Smith   for (i=0; i<n; i++) {
98f7a9e4ceSBarry Smith     ierr = PetscObjectReference((PetscObject)sp->vecs[i]);CHKERRQ(ierr);
99f7a9e4ceSBarry Smith   }
100b4fd4287SBarry Smith   *SP          = sp;
1013a40ed3dSBarry Smith   PetscFunctionReturn(0);
102f7765cecSBarry Smith }
103f7765cecSBarry Smith 
1044a2ae208SSatish Balay #undef __FUNCT__
1054a2ae208SSatish Balay #define __FUNCT__ "MatNullSpaceDestroy"
106f7765cecSBarry Smith /*@
1075cfeda75SBarry Smith    MatNullSpaceDestroy - Destroys a data structure used to project vectors
108b4fd4287SBarry Smith    out of null spaces.
109b4fd4287SBarry Smith 
1105cfeda75SBarry Smith    Collective on MatNullSpace
1114e472627SLois Curfman McInnes 
112b4fd4287SBarry Smith    Input Parameter:
113b9756687SLois Curfman McInnes .  sp - the null space context to be destroyed
114b9756687SLois Curfman McInnes 
115b9756687SLois Curfman McInnes    Level: advanced
116b4fd4287SBarry Smith 
11783c3bef8SLois Curfman McInnes .keywords: PC, null space, destroy
11841a59933SSatish Balay 
11972875594SBarry Smith .seealso: MatNullSpaceCreate(), MatNullSpaceRemove(), MatNullSpaceSetFunction()
120b4fd4287SBarry Smith @*/
121be1d678aSKris Buschelman PetscErrorCode PETSCMAT_DLLEXPORT MatNullSpaceDestroy(MatNullSpace sp)
122b4fd4287SBarry Smith {
123dfbe8321SBarry Smith   PetscErrorCode ierr;
12485614651SBarry Smith 
1255cfeda75SBarry Smith   PetscFunctionBegin;
126*3cfa8680SLisandro Dalcin   PetscValidHeaderSpecific(sp,MAT_NULLSPACE_COOKIE,1);
12785614651SBarry Smith   if (--sp->refct > 0) PetscFunctionReturn(0);
12885614651SBarry Smith 
1295cfeda75SBarry Smith   if (sp->vec) {ierr = VecDestroy(sp->vec);CHKERRQ(ierr);}
130f7a9e4ceSBarry Smith   if (sp->vecs) {
131f7a9e4ceSBarry Smith     ierr = VecDestroyVecs(sp->vecs,sp->n);CHKERRQ(ierr);
132f7a9e4ceSBarry Smith   }
133d38fa0fbSBarry Smith   ierr = PetscHeaderDestroy(sp);CHKERRQ(ierr);
1343a40ed3dSBarry Smith   PetscFunctionReturn(0);
135b4fd4287SBarry Smith }
136b4fd4287SBarry Smith 
1374a2ae208SSatish Balay #undef __FUNCT__
1384a2ae208SSatish Balay #define __FUNCT__ "MatNullSpaceRemove"
139b4fd4287SBarry Smith /*@
1405cfeda75SBarry Smith    MatNullSpaceRemove - Removes all the components of a null space from a vector.
141f7765cecSBarry Smith 
1425cfeda75SBarry Smith    Collective on MatNullSpace
143f7765cecSBarry Smith 
1444e472627SLois Curfman McInnes    Input Parameters:
1454e472627SLois Curfman McInnes +  sp - the null space context
1464e7234bfSBarry Smith .  vec - the vector from which the null space is to be removed
1475fcf39f4SBarry Smith -  out - if this is requested (not PETSC_NULL) then this is a vector with the null space removed otherwise
1484e7234bfSBarry Smith          the removal is done in-place (in vec)
1494e7234bfSBarry Smith 
150db090513SMatthew Knepley    Note: The user is not responsible for the vector returned and should not destroy it.
1514e472627SLois Curfman McInnes 
152b9756687SLois Curfman McInnes    Level: advanced
153b9756687SLois Curfman McInnes 
15483c3bef8SLois Curfman McInnes .keywords: PC, null space, remove
15541a59933SSatish Balay 
15672875594SBarry Smith .seealso: MatNullSpaceCreate(), MatNullSpaceDestroy(), MatNullSpaceSetFunction()
157f7765cecSBarry Smith @*/
158be1d678aSKris Buschelman PetscErrorCode PETSCMAT_DLLEXPORT MatNullSpaceRemove(MatNullSpace sp,Vec vec,Vec *out)
159f7765cecSBarry Smith {
16087828ca2SBarry Smith   PetscScalar    sum;
1616849ba73SBarry Smith   PetscErrorCode ierr;
162c1ac3661SBarry Smith   PetscInt       j,n = sp->n,N;
1635cfeda75SBarry Smith   Vec            l = vec;
164f7765cecSBarry Smith 
1653a40ed3dSBarry Smith   PetscFunctionBegin;
1663cd8ff7eSMatthew Knepley   PetscValidHeaderSpecific(sp,MAT_NULLSPACE_COOKIE,1);
1673cd8ff7eSMatthew Knepley   PetscValidHeaderSpecific(vec,VEC_COOKIE,2);
1683cd8ff7eSMatthew Knepley 
1695cfeda75SBarry Smith   if (out) {
1703cd8ff7eSMatthew Knepley     PetscValidPointer(out,3);
1715cfeda75SBarry Smith     if (!sp->vec) {
1725cfeda75SBarry Smith       ierr = VecDuplicate(vec,&sp->vec);CHKERRQ(ierr);
1735cfeda75SBarry Smith     }
1745cfeda75SBarry Smith     *out = sp->vec;
1755cfeda75SBarry Smith     ierr = VecCopy(vec,*out);CHKERRQ(ierr);
1765cfeda75SBarry Smith     l    = *out;
1775cfeda75SBarry Smith   }
1785cfeda75SBarry Smith 
179b4fd4287SBarry Smith   if (sp->has_cnst) {
1805cfeda75SBarry Smith     ierr = VecSum(l,&sum);CHKERRQ(ierr);
1815cfeda75SBarry Smith     ierr = VecGetSize(l,&N);CHKERRQ(ierr);
18218a7d68fSSatish Balay     sum  = sum/(-1.0*N);
1832dcb1b2aSMatthew Knepley     ierr = VecShift(l,sum);CHKERRQ(ierr);
184f7765cecSBarry Smith   }
185b4fd4287SBarry Smith 
186b4fd4287SBarry Smith   for (j=0; j<n; j++) {
1875cfeda75SBarry Smith     ierr = VecDot(l,sp->vecs[j],&sum);CHKERRQ(ierr);
1885eb3c597SBarry Smith     ierr = VecAXPY(l,-sum,sp->vecs[j]);CHKERRQ(ierr);
189f7765cecSBarry Smith   }
190b4fd4287SBarry Smith 
19172875594SBarry Smith   if (sp->remove){
192ce0145b1SBarry Smith     ierr = (*sp->remove)(l,sp->rmctx);
19372875594SBarry Smith   }
1943a40ed3dSBarry Smith   PetscFunctionReturn(0);
195f7765cecSBarry Smith }
196a2e34c3dSBarry Smith 
1974a2ae208SSatish Balay #undef __FUNCT__
1984a2ae208SSatish Balay #define __FUNCT__ "MatNullSpaceTest"
199a2e34c3dSBarry Smith /*@
200a2e34c3dSBarry Smith    MatNullSpaceTest  - Tests if the claimed null space is really a
201a2e34c3dSBarry Smith      null space of a matrix
202a2e34c3dSBarry Smith 
203a2e34c3dSBarry Smith    Collective on MatNullSpace
204a2e34c3dSBarry Smith 
205a2e34c3dSBarry Smith    Input Parameters:
206a2e34c3dSBarry Smith +  sp - the null space context
207a2e34c3dSBarry Smith -  mat - the matrix
208a2e34c3dSBarry Smith 
209a2e34c3dSBarry Smith    Level: advanced
210a2e34c3dSBarry Smith 
211a2e34c3dSBarry Smith .keywords: PC, null space, remove
212a2e34c3dSBarry Smith 
21372875594SBarry Smith .seealso: MatNullSpaceCreate(), MatNullSpaceDestroy(), MatNullSpaceSetFunction()
214a2e34c3dSBarry Smith @*/
215be1d678aSKris Buschelman PetscErrorCode PETSCMAT_DLLEXPORT MatNullSpaceTest(MatNullSpace sp,Mat mat)
216a2e34c3dSBarry Smith {
21787828ca2SBarry Smith   PetscScalar    sum;
2188bb6bcc5SSatish Balay   PetscReal      nrm;
219*3cfa8680SLisandro Dalcin   PetscInt       j,n,N,m;
2206849ba73SBarry Smith   PetscErrorCode ierr;
221a2e34c3dSBarry Smith   Vec            l,r;
222a2e34c3dSBarry Smith   PetscTruth     flg1,flg2;
2233050cee2SBarry Smith   PetscViewer    viewer;
224a2e34c3dSBarry Smith 
225a2e34c3dSBarry Smith   PetscFunctionBegin;
226*3cfa8680SLisandro Dalcin   PetscValidHeaderSpecific(sp,MAT_NULLSPACE_COOKIE,1);
227*3cfa8680SLisandro Dalcin   PetscValidHeaderSpecific(mat,MAT_COOKIE,2);
228*3cfa8680SLisandro Dalcin   n = sp->n;
229b0a32e0cSBarry Smith   ierr = PetscOptionsHasName(PETSC_NULL,"-mat_null_space_test_view",&flg1);CHKERRQ(ierr);
230b0a32e0cSBarry Smith   ierr = PetscOptionsHasName(PETSC_NULL,"-mat_null_space_test_view_draw",&flg2);CHKERRQ(ierr);
231a2e34c3dSBarry Smith 
232a2e34c3dSBarry Smith   if (!sp->vec) {
233a2e34c3dSBarry Smith     if (n) {
234a2e34c3dSBarry Smith       ierr = VecDuplicate(sp->vecs[0],&sp->vec);CHKERRQ(ierr);
235a2e34c3dSBarry Smith     } else {
236a2e34c3dSBarry Smith       ierr = MatGetLocalSize(mat,&m,PETSC_NULL);CHKERRQ(ierr);
237a2e34c3dSBarry Smith       ierr = VecCreateMPI(sp->comm,m,PETSC_DETERMINE,&sp->vec);CHKERRQ(ierr);
238a2e34c3dSBarry Smith     }
239a2e34c3dSBarry Smith   }
240a2e34c3dSBarry Smith   l    = sp->vec;
241a2e34c3dSBarry Smith 
242*3cfa8680SLisandro Dalcin   ierr = PetscViewerASCIIGetStdout(sp->comm,&viewer);CHKERRQ(ierr);
243a2e34c3dSBarry Smith   if (sp->has_cnst) {
244a2e34c3dSBarry Smith     ierr = VecDuplicate(l,&r);CHKERRQ(ierr);
245a2e34c3dSBarry Smith     ierr = VecGetSize(l,&N);CHKERRQ(ierr);
246a2e34c3dSBarry Smith     sum  = 1.0/N;
2472dcb1b2aSMatthew Knepley     ierr = VecSet(l,sum);CHKERRQ(ierr);
248a2e34c3dSBarry Smith     ierr = MatMult(mat,l,r);CHKERRQ(ierr);
2498bb6bcc5SSatish Balay     ierr = VecNorm(r,NORM_2,&nrm);CHKERRQ(ierr);
250*3cfa8680SLisandro Dalcin     if (nrm < 1.e-7) {ierr = PetscPrintf(sp->comm,"Constants are likely null vector");CHKERRQ(ierr);}
251*3cfa8680SLisandro Dalcin     else {ierr = PetscPrintf(sp->comm,"Constants are unlikely null vector ");CHKERRQ(ierr);}
252*3cfa8680SLisandro Dalcin     ierr = PetscPrintf(sp->comm,"|| A * 1 || = %G\n",nrm);CHKERRQ(ierr);
2533050cee2SBarry Smith     if (nrm > 1.e-7 && flg1) {ierr = VecView(r,viewer);CHKERRQ(ierr);}
2543050cee2SBarry Smith     if (nrm > 1.e-7 && flg2) {ierr = VecView(r,viewer);CHKERRQ(ierr);}
255a2e34c3dSBarry Smith     ierr = VecDestroy(r);CHKERRQ(ierr);
256a2e34c3dSBarry Smith   }
257a2e34c3dSBarry Smith 
258a2e34c3dSBarry Smith   for (j=0; j<n; j++) {
259a2e34c3dSBarry Smith     ierr = (*mat->ops->mult)(mat,sp->vecs[j],l);CHKERRQ(ierr);
2608bb6bcc5SSatish Balay     ierr = VecNorm(l,NORM_2,&nrm);CHKERRQ(ierr);
261*3cfa8680SLisandro Dalcin     if (nrm < 1.e-7) {ierr = PetscPrintf(sp->comm,"Null vector %D is likely null vector",j);CHKERRQ(ierr);}
262*3cfa8680SLisandro Dalcin     else {ierr = PetscPrintf(sp->comm,"Null vector %D unlikely null vector ",j);CHKERRQ(ierr);}
263*3cfa8680SLisandro Dalcin     ierr = PetscPrintf(sp->comm,"|| A * v[%D] || = %G\n",j,nrm);CHKERRQ(ierr);
2643050cee2SBarry Smith     if (nrm > 1.e-7 && flg1) {ierr = VecView(l,viewer);CHKERRQ(ierr);}
2653050cee2SBarry Smith     if (nrm > 1.e-7 && flg2) {ierr = VecView(l,viewer);CHKERRQ(ierr);}
266a2e34c3dSBarry Smith   }
267a2e34c3dSBarry Smith 
26872875594SBarry Smith   if (sp->remove){
26972875594SBarry Smith     SETERRQ(PETSC_ERR_SUP,"Cannot test a null space provided as a function with MatNullSpaceSetFunction()");
27072875594SBarry Smith   }
27172875594SBarry Smith 
272a2e34c3dSBarry Smith   PetscFunctionReturn(0);
273a2e34c3dSBarry Smith }
274a2e34c3dSBarry Smith 
275