xref: /petsc/src/mat/interface/matnull.c (revision 5eb3c5974edb7aaac8ec7c7605a5b07b44bb05b9)
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;
4752e6d16bSBarry Smith   ierr = PetscHeaderCreate(sp,_p_MatNullSpace,int,MAT_NULLSPACE_COOKIE,0,"MatNullSpace",comm,MatNullSpaceDestroy,0);CHKERRQ(ierr);
4852e6d16bSBarry Smith   ierr = PetscLogObjectMemory(sp,sizeof(struct _p_MatNullSpace));CHKERRQ(ierr);
49f7765cecSBarry Smith 
50b4fd4287SBarry Smith   sp->has_cnst = has_cnst;
51b4fd4287SBarry Smith   sp->n        = n;
525cfeda75SBarry Smith   sp->vec      = PETSC_NULL;
53f7a9e4ceSBarry Smith   if (n) {
54f7a9e4ceSBarry Smith     ierr = PetscMalloc(n*sizeof(Vec),&sp->vecs);CHKERRQ(ierr);
55f7a9e4ceSBarry Smith     for (i=0; i<n; i++) sp->vecs[i] = vecs[i];
56f7a9e4ceSBarry Smith   } else {
57f7a9e4ceSBarry Smith     sp->vecs = 0;
58f7a9e4ceSBarry Smith   }
59b4fd4287SBarry Smith 
60f7a9e4ceSBarry Smith   for (i=0; i<n; i++) {
61f7a9e4ceSBarry Smith     ierr = PetscObjectReference((PetscObject)sp->vecs[i]);CHKERRQ(ierr);
62f7a9e4ceSBarry Smith   }
63b4fd4287SBarry Smith   *SP          = sp;
643a40ed3dSBarry Smith   PetscFunctionReturn(0);
65f7765cecSBarry Smith }
66f7765cecSBarry Smith 
674a2ae208SSatish Balay #undef __FUNCT__
684a2ae208SSatish Balay #define __FUNCT__ "MatNullSpaceDestroy"
69f7765cecSBarry Smith /*@
705cfeda75SBarry Smith    MatNullSpaceDestroy - Destroys a data structure used to project vectors
71b4fd4287SBarry Smith    out of null spaces.
72b4fd4287SBarry Smith 
735cfeda75SBarry Smith    Collective on MatNullSpace
744e472627SLois Curfman McInnes 
75b4fd4287SBarry Smith    Input Parameter:
76b9756687SLois Curfman McInnes .  sp - the null space context to be destroyed
77b9756687SLois Curfman McInnes 
78b9756687SLois Curfman McInnes    Level: advanced
79b4fd4287SBarry Smith 
8083c3bef8SLois Curfman McInnes .keywords: PC, null space, destroy
8141a59933SSatish Balay 
825cfeda75SBarry Smith .seealso: MatNullSpaceCreate(), MatNullSpaceRemove()
83b4fd4287SBarry Smith @*/
84be1d678aSKris Buschelman PetscErrorCode PETSCMAT_DLLEXPORT MatNullSpaceDestroy(MatNullSpace sp)
85b4fd4287SBarry Smith {
86dfbe8321SBarry Smith   PetscErrorCode ierr;
8785614651SBarry Smith 
885cfeda75SBarry Smith   PetscFunctionBegin;
8985614651SBarry Smith   if (--sp->refct > 0) PetscFunctionReturn(0);
9085614651SBarry Smith 
915cfeda75SBarry Smith   if (sp->vec) {ierr = VecDestroy(sp->vec);CHKERRQ(ierr);}
92f7a9e4ceSBarry Smith   if (sp->vecs) {
93f7a9e4ceSBarry Smith     ierr = VecDestroyVecs(sp->vecs,sp->n);CHKERRQ(ierr);
94f7a9e4ceSBarry Smith   }
95d38fa0fbSBarry Smith   ierr = PetscHeaderDestroy(sp);CHKERRQ(ierr);
963a40ed3dSBarry Smith   PetscFunctionReturn(0);
97b4fd4287SBarry Smith }
98b4fd4287SBarry Smith 
994a2ae208SSatish Balay #undef __FUNCT__
1004a2ae208SSatish Balay #define __FUNCT__ "MatNullSpaceRemove"
101b4fd4287SBarry Smith /*@
1025cfeda75SBarry Smith    MatNullSpaceRemove - Removes all the components of a null space from a vector.
103f7765cecSBarry Smith 
1045cfeda75SBarry Smith    Collective on MatNullSpace
105f7765cecSBarry Smith 
1064e472627SLois Curfman McInnes    Input Parameters:
1074e472627SLois Curfman McInnes +  sp - the null space context
1084e7234bfSBarry Smith .  vec - the vector from which the null space is to be removed
1095fcf39f4SBarry Smith -  out - if this is requested (not PETSC_NULL) then this is a vector with the null space removed otherwise
1104e7234bfSBarry Smith          the removal is done in-place (in vec)
1114e7234bfSBarry Smith 
1124e7234bfSBarry Smith 
1134e472627SLois Curfman McInnes 
114b9756687SLois Curfman McInnes    Level: advanced
115b9756687SLois Curfman McInnes 
11683c3bef8SLois Curfman McInnes .keywords: PC, null space, remove
11741a59933SSatish Balay 
1185cfeda75SBarry Smith .seealso: MatNullSpaceCreate(), MatNullSpaceDestroy()
119f7765cecSBarry Smith @*/
120be1d678aSKris Buschelman PetscErrorCode PETSCMAT_DLLEXPORT MatNullSpaceRemove(MatNullSpace sp,Vec vec,Vec *out)
121f7765cecSBarry Smith {
12287828ca2SBarry Smith   PetscScalar    sum;
1236849ba73SBarry Smith   PetscErrorCode ierr;
124c1ac3661SBarry Smith   PetscInt       j,n = sp->n,N;
1255cfeda75SBarry Smith   Vec            l = vec;
126f7765cecSBarry Smith 
1273a40ed3dSBarry Smith   PetscFunctionBegin;
1285cfeda75SBarry Smith   if (out) {
1295cfeda75SBarry Smith     if (!sp->vec) {
1305cfeda75SBarry Smith       ierr = VecDuplicate(vec,&sp->vec);CHKERRQ(ierr);
1315cfeda75SBarry Smith     }
1325cfeda75SBarry Smith     *out = sp->vec;
1335cfeda75SBarry Smith     ierr = VecCopy(vec,*out);CHKERRQ(ierr);
1345cfeda75SBarry Smith     l    = *out;
1355cfeda75SBarry Smith   }
1365cfeda75SBarry Smith 
137b4fd4287SBarry Smith   if (sp->has_cnst) {
1385cfeda75SBarry Smith     ierr = VecSum(l,&sum);CHKERRQ(ierr);
1395cfeda75SBarry Smith     ierr = VecGetSize(l,&N);CHKERRQ(ierr);
14018a7d68fSSatish Balay     sum  = sum/(-1.0*N);
1412dcb1b2aSMatthew Knepley     ierr = VecShift(l,sum);CHKERRQ(ierr);
142f7765cecSBarry Smith   }
143b4fd4287SBarry Smith 
144b4fd4287SBarry Smith   for (j=0; j<n; j++) {
1455cfeda75SBarry Smith     ierr = VecDot(l,sp->vecs[j],&sum);CHKERRQ(ierr);
146*5eb3c597SBarry Smith     ierr = VecAXPY(l,-sum,sp->vecs[j]);CHKERRQ(ierr);
147f7765cecSBarry Smith   }
148b4fd4287SBarry Smith 
1493a40ed3dSBarry Smith   PetscFunctionReturn(0);
150f7765cecSBarry Smith }
151a2e34c3dSBarry Smith 
1524a2ae208SSatish Balay #undef __FUNCT__
1534a2ae208SSatish Balay #define __FUNCT__ "MatNullSpaceTest"
154a2e34c3dSBarry Smith /*@
155a2e34c3dSBarry Smith    MatNullSpaceTest  - Tests if the claimed null space is really a
156a2e34c3dSBarry Smith      null space of a matrix
157a2e34c3dSBarry Smith 
158a2e34c3dSBarry Smith    Collective on MatNullSpace
159a2e34c3dSBarry Smith 
160a2e34c3dSBarry Smith    Input Parameters:
161a2e34c3dSBarry Smith +  sp - the null space context
162a2e34c3dSBarry Smith -  mat - the matrix
163a2e34c3dSBarry Smith 
164a2e34c3dSBarry Smith    Level: advanced
165a2e34c3dSBarry Smith 
166a2e34c3dSBarry Smith .keywords: PC, null space, remove
167a2e34c3dSBarry Smith 
168a2e34c3dSBarry Smith .seealso: MatNullSpaceCreate(), MatNullSpaceDestroy()
169a2e34c3dSBarry Smith @*/
170be1d678aSKris Buschelman PetscErrorCode PETSCMAT_DLLEXPORT MatNullSpaceTest(MatNullSpace sp,Mat mat)
171a2e34c3dSBarry Smith {
17287828ca2SBarry Smith   PetscScalar    sum;
1738bb6bcc5SSatish Balay   PetscReal      nrm;
174c1ac3661SBarry Smith   PetscInt       j,n = sp->n,N,m;
1756849ba73SBarry Smith   PetscErrorCode ierr;
176a2e34c3dSBarry Smith   Vec            l,r;
177a2e34c3dSBarry Smith   MPI_Comm       comm = sp->comm;
178a2e34c3dSBarry Smith   PetscTruth     flg1,flg2;
179a2e34c3dSBarry Smith 
180a2e34c3dSBarry Smith   PetscFunctionBegin;
181b0a32e0cSBarry Smith   ierr = PetscOptionsHasName(PETSC_NULL,"-mat_null_space_test_view",&flg1);CHKERRQ(ierr);
182b0a32e0cSBarry Smith   ierr = PetscOptionsHasName(PETSC_NULL,"-mat_null_space_test_view_draw",&flg2);CHKERRQ(ierr);
183a2e34c3dSBarry Smith 
184a2e34c3dSBarry Smith   if (!sp->vec) {
185a2e34c3dSBarry Smith     if (n) {
186a2e34c3dSBarry Smith       ierr = VecDuplicate(sp->vecs[0],&sp->vec);CHKERRQ(ierr);
187a2e34c3dSBarry Smith     } else {
188a2e34c3dSBarry Smith       ierr = MatGetLocalSize(mat,&m,PETSC_NULL);CHKERRQ(ierr);
189a2e34c3dSBarry Smith       ierr = VecCreateMPI(sp->comm,m,PETSC_DETERMINE,&sp->vec);CHKERRQ(ierr);
190a2e34c3dSBarry Smith     }
191a2e34c3dSBarry Smith   }
192a2e34c3dSBarry Smith   l    = sp->vec;
193a2e34c3dSBarry Smith 
194a2e34c3dSBarry Smith   if (sp->has_cnst) {
195a2e34c3dSBarry Smith     ierr = VecDuplicate(l,&r);CHKERRQ(ierr);
196a2e34c3dSBarry Smith     ierr = VecGetSize(l,&N);CHKERRQ(ierr);
197a2e34c3dSBarry Smith     sum  = 1.0/N;
1982dcb1b2aSMatthew Knepley     ierr = VecSet(l,sum);CHKERRQ(ierr);
199a2e34c3dSBarry Smith     ierr = MatMult(mat,l,r);CHKERRQ(ierr);
2008bb6bcc5SSatish Balay     ierr = VecNorm(r,NORM_2,&nrm);CHKERRQ(ierr);
2018bb6bcc5SSatish Balay     if (nrm < 1.e-7) {ierr = PetscPrintf(comm,"Constants are likely null vector");CHKERRQ(ierr);}
202a2e34c3dSBarry Smith     else {ierr = PetscPrintf(comm,"Constants are unlikely null vector ");CHKERRQ(ierr);}
2038bb6bcc5SSatish Balay     ierr = PetscPrintf(comm,"|| A * 1 || = %g\n",nrm);CHKERRQ(ierr);
204b0a32e0cSBarry Smith     if (nrm > 1.e-7 && flg1) {ierr = VecView(r,PETSC_VIEWER_STDOUT_(comm));CHKERRQ(ierr);}
205b0a32e0cSBarry Smith     if (nrm > 1.e-7 && flg2) {ierr = VecView(r,PETSC_VIEWER_DRAW_(comm));CHKERRQ(ierr);}
206a2e34c3dSBarry Smith     ierr = VecDestroy(r);CHKERRQ(ierr);
207a2e34c3dSBarry Smith   }
208a2e34c3dSBarry Smith 
209a2e34c3dSBarry Smith   for (j=0; j<n; j++) {
210a2e34c3dSBarry Smith     ierr = (*mat->ops->mult)(mat,sp->vecs[j],l);CHKERRQ(ierr);
2118bb6bcc5SSatish Balay     ierr = VecNorm(l,NORM_2,&nrm);CHKERRQ(ierr);
21277431f27SBarry Smith     if (nrm < 1.e-7) {ierr = PetscPrintf(comm,"Null vector %D is likely null vector",j);CHKERRQ(ierr);}
21377431f27SBarry Smith     else {ierr = PetscPrintf(comm,"Null vector %D unlikely null vector ",j);CHKERRQ(ierr);}
21477431f27SBarry Smith     ierr = PetscPrintf(comm,"|| A * v[%D] || = %g\n",j,nrm);CHKERRQ(ierr);
215b0a32e0cSBarry Smith     if (nrm > 1.e-7 && flg1) {ierr = VecView(l,PETSC_VIEWER_STDOUT_(comm));CHKERRQ(ierr);}
216b0a32e0cSBarry Smith     if (nrm > 1.e-7 && flg2) {ierr = VecView(l,PETSC_VIEWER_DRAW_(comm));CHKERRQ(ierr);}
217a2e34c3dSBarry Smith   }
218a2e34c3dSBarry Smith 
219a2e34c3dSBarry Smith   PetscFunctionReturn(0);
220a2e34c3dSBarry Smith }
221a2e34c3dSBarry Smith 
222