xref: /petsc/src/mat/interface/matnull.c (revision 574b3360adf4daf2d5a24a71a0b7e89556dea9b4)
1be1d678aSKris Buschelman #define PETSCMAT_DLL
2be1d678aSKris Buschelman 
3f7765cecSBarry Smith /*
4b4fd4287SBarry Smith     Routines to project vectors out of null spaces.
5f7765cecSBarry Smith */
6f7765cecSBarry Smith 
75cfeda75SBarry Smith #include "src/mat/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__
134a2ae208SSatish Balay #define __FUNCT__ "MatNullSpaceCreate"
14f39d8e23SSatish Balay /*@
155cfeda75SBarry Smith    MatNullSpaceCreate - Creates a data structure used to project vectors
16b4fd4287SBarry Smith    out of null spaces.
17f7765cecSBarry Smith 
184e472627SLois Curfman McInnes    Collective on MPI_Comm
194e472627SLois Curfman McInnes 
20f7765cecSBarry Smith    Input Parameters:
2183c3bef8SLois Curfman McInnes +  comm - the MPI communicator associated with the object
2283c3bef8SLois Curfman McInnes .  has_cnst - PETSC_TRUE if the null space contains the constant vector; otherwise PETSC_FALSE
23b4fd4287SBarry Smith .  n - number of vectors (excluding constant vector) in null space
2483c3bef8SLois Curfman McInnes -  vecs - the vectors that span the null space (excluding the constant vector);
25f7a9e4ceSBarry Smith           these vectors must be orthonormal. These vectors are NOT copied, so do not change them
26f7a9e4ceSBarry Smith           after this call. You should free the array that you pass in.
27f7765cecSBarry Smith 
28f7765cecSBarry Smith    Output Parameter:
29b4fd4287SBarry Smith .  SP - the null space context
30f7765cecSBarry Smith 
3183c3bef8SLois Curfman McInnes    Level: advanced
3283c3bef8SLois Curfman McInnes 
336e1639daSBarry Smith   Users manual sections:
346e1639daSBarry Smith .   sec_singular
356e1639daSBarry Smith 
3683c3bef8SLois Curfman McInnes .keywords: PC, null space, create
3741a59933SSatish Balay 
38d8fd42c4SBarry Smith .seealso: MatNullSpaceDestroy(), MatNullSpaceRemove(), KSPSetNullSpace(), MatNullSpace
39f7765cecSBarry Smith @*/
40be1d678aSKris Buschelman PetscErrorCode PETSCMAT_DLLEXPORT MatNullSpaceCreate(MPI_Comm comm,PetscTruth has_cnst,PetscInt n,const Vec vecs[],MatNullSpace *SP)
41f7765cecSBarry Smith {
425cfeda75SBarry Smith   MatNullSpace   sp;
43dfbe8321SBarry Smith   PetscErrorCode ierr;
44c1ac3661SBarry Smith   PetscInt       i;
45f7765cecSBarry Smith 
463a40ed3dSBarry Smith   PetscFunctionBegin;
47*574b3360SMatthew Knepley   if (n) PetscValidPointer(vecs,4);
48*574b3360SMatthew Knepley   for (i=0; i<n; i++) PetscValidHeaderSpecific(vecs[i],VEC_COOKIE,4);
49*574b3360SMatthew Knepley   PetscValidPointer(SP,5);
50*574b3360SMatthew Knepley 
51*574b3360SMatthew Knepley   *SP = PETSC_NULL;
52*574b3360SMatthew Knepley #ifndef PETSC_USE_DYNAMIC_LIBRARIES
53*574b3360SMatthew Knepley   ierr = MatInitializePackage(PETSC_NULL);CHKERRQ(ierr);
54*574b3360SMatthew Knepley #endif
55*574b3360SMatthew Knepley 
5652e6d16bSBarry Smith   ierr = PetscHeaderCreate(sp,_p_MatNullSpace,int,MAT_NULLSPACE_COOKIE,0,"MatNullSpace",comm,MatNullSpaceDestroy,0);CHKERRQ(ierr);
5752e6d16bSBarry Smith   ierr = PetscLogObjectMemory(sp,sizeof(struct _p_MatNullSpace));CHKERRQ(ierr);
58f7765cecSBarry Smith 
59b4fd4287SBarry Smith   sp->has_cnst = has_cnst;
60b4fd4287SBarry Smith   sp->n        = n;
615cfeda75SBarry Smith   sp->vec      = PETSC_NULL;
62f7a9e4ceSBarry Smith   if (n) {
63f7a9e4ceSBarry Smith     ierr = PetscMalloc(n*sizeof(Vec),&sp->vecs);CHKERRQ(ierr);
64f7a9e4ceSBarry Smith     for (i=0; i<n; i++) sp->vecs[i] = vecs[i];
65f7a9e4ceSBarry Smith   } else {
66f7a9e4ceSBarry Smith     sp->vecs = 0;
67f7a9e4ceSBarry Smith   }
68b4fd4287SBarry Smith 
69f7a9e4ceSBarry Smith   for (i=0; i<n; i++) {
70f7a9e4ceSBarry Smith     ierr = PetscObjectReference((PetscObject)sp->vecs[i]);CHKERRQ(ierr);
71f7a9e4ceSBarry Smith   }
72b4fd4287SBarry Smith   *SP          = sp;
733a40ed3dSBarry Smith   PetscFunctionReturn(0);
74f7765cecSBarry Smith }
75f7765cecSBarry Smith 
764a2ae208SSatish Balay #undef __FUNCT__
774a2ae208SSatish Balay #define __FUNCT__ "MatNullSpaceDestroy"
78f7765cecSBarry Smith /*@
795cfeda75SBarry Smith    MatNullSpaceDestroy - Destroys a data structure used to project vectors
80b4fd4287SBarry Smith    out of null spaces.
81b4fd4287SBarry Smith 
825cfeda75SBarry Smith    Collective on MatNullSpace
834e472627SLois Curfman McInnes 
84b4fd4287SBarry Smith    Input Parameter:
85b9756687SLois Curfman McInnes .  sp - the null space context to be destroyed
86b9756687SLois Curfman McInnes 
87b9756687SLois Curfman McInnes    Level: advanced
88b4fd4287SBarry Smith 
8983c3bef8SLois Curfman McInnes .keywords: PC, null space, destroy
9041a59933SSatish Balay 
915cfeda75SBarry Smith .seealso: MatNullSpaceCreate(), MatNullSpaceRemove()
92b4fd4287SBarry Smith @*/
93be1d678aSKris Buschelman PetscErrorCode PETSCMAT_DLLEXPORT MatNullSpaceDestroy(MatNullSpace sp)
94b4fd4287SBarry Smith {
95dfbe8321SBarry Smith   PetscErrorCode ierr;
9685614651SBarry Smith 
975cfeda75SBarry Smith   PetscFunctionBegin;
9885614651SBarry Smith   if (--sp->refct > 0) PetscFunctionReturn(0);
9985614651SBarry Smith 
1005cfeda75SBarry Smith   if (sp->vec) {ierr = VecDestroy(sp->vec);CHKERRQ(ierr);}
101f7a9e4ceSBarry Smith   if (sp->vecs) {
102f7a9e4ceSBarry Smith     ierr = VecDestroyVecs(sp->vecs,sp->n);CHKERRQ(ierr);
103f7a9e4ceSBarry Smith   }
104d38fa0fbSBarry Smith   ierr = PetscHeaderDestroy(sp);CHKERRQ(ierr);
1053a40ed3dSBarry Smith   PetscFunctionReturn(0);
106b4fd4287SBarry Smith }
107b4fd4287SBarry Smith 
1084a2ae208SSatish Balay #undef __FUNCT__
1094a2ae208SSatish Balay #define __FUNCT__ "MatNullSpaceRemove"
110b4fd4287SBarry Smith /*@
1115cfeda75SBarry Smith    MatNullSpaceRemove - Removes all the components of a null space from a vector.
112f7765cecSBarry Smith 
1135cfeda75SBarry Smith    Collective on MatNullSpace
114f7765cecSBarry Smith 
1154e472627SLois Curfman McInnes    Input Parameters:
1164e472627SLois Curfman McInnes +  sp - the null space context
1174e7234bfSBarry Smith .  vec - the vector from which the null space is to be removed
1185fcf39f4SBarry Smith -  out - if this is requested (not PETSC_NULL) then this is a vector with the null space removed otherwise
1194e7234bfSBarry Smith          the removal is done in-place (in vec)
1204e7234bfSBarry Smith 
1214e7234bfSBarry Smith 
1224e472627SLois Curfman McInnes 
123b9756687SLois Curfman McInnes    Level: advanced
124b9756687SLois Curfman McInnes 
12583c3bef8SLois Curfman McInnes .keywords: PC, null space, remove
12641a59933SSatish Balay 
1275cfeda75SBarry Smith .seealso: MatNullSpaceCreate(), MatNullSpaceDestroy()
128f7765cecSBarry Smith @*/
129be1d678aSKris Buschelman PetscErrorCode PETSCMAT_DLLEXPORT MatNullSpaceRemove(MatNullSpace sp,Vec vec,Vec *out)
130f7765cecSBarry Smith {
13187828ca2SBarry Smith   PetscScalar    sum;
1326849ba73SBarry Smith   PetscErrorCode ierr;
133c1ac3661SBarry Smith   PetscInt       j,n = sp->n,N;
1345cfeda75SBarry Smith   Vec            l = vec;
135f7765cecSBarry Smith 
1363a40ed3dSBarry Smith   PetscFunctionBegin;
1375cfeda75SBarry Smith   if (out) {
1385cfeda75SBarry Smith     if (!sp->vec) {
1395cfeda75SBarry Smith       ierr = VecDuplicate(vec,&sp->vec);CHKERRQ(ierr);
1405cfeda75SBarry Smith     }
1415cfeda75SBarry Smith     *out = sp->vec;
1425cfeda75SBarry Smith     ierr = VecCopy(vec,*out);CHKERRQ(ierr);
1435cfeda75SBarry Smith     l    = *out;
1445cfeda75SBarry Smith   }
1455cfeda75SBarry Smith 
146b4fd4287SBarry Smith   if (sp->has_cnst) {
1475cfeda75SBarry Smith     ierr = VecSum(l,&sum);CHKERRQ(ierr);
1485cfeda75SBarry Smith     ierr = VecGetSize(l,&N);CHKERRQ(ierr);
14918a7d68fSSatish Balay     sum  = sum/(-1.0*N);
1502dcb1b2aSMatthew Knepley     ierr = VecShift(l,sum);CHKERRQ(ierr);
151f7765cecSBarry Smith   }
152b4fd4287SBarry Smith 
153b4fd4287SBarry Smith   for (j=0; j<n; j++) {
1545cfeda75SBarry Smith     ierr = VecDot(l,sp->vecs[j],&sum);CHKERRQ(ierr);
155b4fd4287SBarry Smith     sum  = -sum;
1562dcb1b2aSMatthew Knepley     ierr = VecAXPY(l,sum,sp->vecs[j]);CHKERRQ(ierr);
157f7765cecSBarry Smith   }
158b4fd4287SBarry Smith 
1593a40ed3dSBarry Smith   PetscFunctionReturn(0);
160f7765cecSBarry Smith }
161a2e34c3dSBarry Smith 
1624a2ae208SSatish Balay #undef __FUNCT__
1634a2ae208SSatish Balay #define __FUNCT__ "MatNullSpaceTest"
164a2e34c3dSBarry Smith /*@
165a2e34c3dSBarry Smith    MatNullSpaceTest  - Tests if the claimed null space is really a
166a2e34c3dSBarry Smith      null space of a matrix
167a2e34c3dSBarry Smith 
168a2e34c3dSBarry Smith    Collective on MatNullSpace
169a2e34c3dSBarry Smith 
170a2e34c3dSBarry Smith    Input Parameters:
171a2e34c3dSBarry Smith +  sp - the null space context
172a2e34c3dSBarry Smith -  mat - the matrix
173a2e34c3dSBarry Smith 
174a2e34c3dSBarry Smith    Level: advanced
175a2e34c3dSBarry Smith 
176a2e34c3dSBarry Smith .keywords: PC, null space, remove
177a2e34c3dSBarry Smith 
178a2e34c3dSBarry Smith .seealso: MatNullSpaceCreate(), MatNullSpaceDestroy()
179a2e34c3dSBarry Smith @*/
180be1d678aSKris Buschelman PetscErrorCode PETSCMAT_DLLEXPORT MatNullSpaceTest(MatNullSpace sp,Mat mat)
181a2e34c3dSBarry Smith {
18287828ca2SBarry Smith   PetscScalar    sum;
1838bb6bcc5SSatish Balay   PetscReal      nrm;
184c1ac3661SBarry Smith   PetscInt       j,n = sp->n,N,m;
1856849ba73SBarry Smith   PetscErrorCode ierr;
186a2e34c3dSBarry Smith   Vec            l,r;
187a2e34c3dSBarry Smith   MPI_Comm       comm = sp->comm;
188a2e34c3dSBarry Smith   PetscTruth     flg1,flg2;
189a2e34c3dSBarry Smith 
190a2e34c3dSBarry Smith   PetscFunctionBegin;
191b0a32e0cSBarry Smith   ierr = PetscOptionsHasName(PETSC_NULL,"-mat_null_space_test_view",&flg1);CHKERRQ(ierr);
192b0a32e0cSBarry Smith   ierr = PetscOptionsHasName(PETSC_NULL,"-mat_null_space_test_view_draw",&flg2);CHKERRQ(ierr);
193a2e34c3dSBarry Smith 
194a2e34c3dSBarry Smith   if (!sp->vec) {
195a2e34c3dSBarry Smith     if (n) {
196a2e34c3dSBarry Smith       ierr = VecDuplicate(sp->vecs[0],&sp->vec);CHKERRQ(ierr);
197a2e34c3dSBarry Smith     } else {
198a2e34c3dSBarry Smith       ierr = MatGetLocalSize(mat,&m,PETSC_NULL);CHKERRQ(ierr);
199a2e34c3dSBarry Smith       ierr = VecCreateMPI(sp->comm,m,PETSC_DETERMINE,&sp->vec);CHKERRQ(ierr);
200a2e34c3dSBarry Smith     }
201a2e34c3dSBarry Smith   }
202a2e34c3dSBarry Smith   l    = sp->vec;
203a2e34c3dSBarry Smith 
204a2e34c3dSBarry Smith   if (sp->has_cnst) {
205a2e34c3dSBarry Smith     ierr = VecDuplicate(l,&r);CHKERRQ(ierr);
206a2e34c3dSBarry Smith     ierr = VecGetSize(l,&N);CHKERRQ(ierr);
207a2e34c3dSBarry Smith     sum  = 1.0/N;
2082dcb1b2aSMatthew Knepley     ierr = VecSet(l,sum);CHKERRQ(ierr);
209a2e34c3dSBarry Smith     ierr = MatMult(mat,l,r);CHKERRQ(ierr);
2108bb6bcc5SSatish Balay     ierr = VecNorm(r,NORM_2,&nrm);CHKERRQ(ierr);
2118bb6bcc5SSatish Balay     if (nrm < 1.e-7) {ierr = PetscPrintf(comm,"Constants are likely null vector");CHKERRQ(ierr);}
212a2e34c3dSBarry Smith     else {ierr = PetscPrintf(comm,"Constants are unlikely null vector ");CHKERRQ(ierr);}
2138bb6bcc5SSatish Balay     ierr = PetscPrintf(comm,"|| A * 1 || = %g\n",nrm);CHKERRQ(ierr);
214b0a32e0cSBarry Smith     if (nrm > 1.e-7 && flg1) {ierr = VecView(r,PETSC_VIEWER_STDOUT_(comm));CHKERRQ(ierr);}
215b0a32e0cSBarry Smith     if (nrm > 1.e-7 && flg2) {ierr = VecView(r,PETSC_VIEWER_DRAW_(comm));CHKERRQ(ierr);}
216a2e34c3dSBarry Smith     ierr = VecDestroy(r);CHKERRQ(ierr);
217a2e34c3dSBarry Smith   }
218a2e34c3dSBarry Smith 
219a2e34c3dSBarry Smith   for (j=0; j<n; j++) {
220a2e34c3dSBarry Smith     ierr = (*mat->ops->mult)(mat,sp->vecs[j],l);CHKERRQ(ierr);
2218bb6bcc5SSatish Balay     ierr = VecNorm(l,NORM_2,&nrm);CHKERRQ(ierr);
22277431f27SBarry Smith     if (nrm < 1.e-7) {ierr = PetscPrintf(comm,"Null vector %D is likely null vector",j);CHKERRQ(ierr);}
22377431f27SBarry Smith     else {ierr = PetscPrintf(comm,"Null vector %D unlikely null vector ",j);CHKERRQ(ierr);}
22477431f27SBarry Smith     ierr = PetscPrintf(comm,"|| A * v[%D] || = %g\n",j,nrm);CHKERRQ(ierr);
225b0a32e0cSBarry Smith     if (nrm > 1.e-7 && flg1) {ierr = VecView(l,PETSC_VIEWER_STDOUT_(comm));CHKERRQ(ierr);}
226b0a32e0cSBarry Smith     if (nrm > 1.e-7 && flg2) {ierr = VecView(l,PETSC_VIEWER_DRAW_(comm));CHKERRQ(ierr);}
227a2e34c3dSBarry Smith   }
228a2e34c3dSBarry Smith 
229a2e34c3dSBarry Smith   PetscFunctionReturn(0);
230a2e34c3dSBarry Smith }
231a2e34c3dSBarry Smith 
232