xref: /petsc/src/mat/interface/matnull.c (revision f39d8e23b40eadf790a9090b651a5e6aab3feb96)
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"
14*f39d8e23SSatish 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);
146b4fd4287SBarry Smith     sum  = -sum;
1472dcb1b2aSMatthew Knepley     ierr = VecAXPY(l,sum,sp->vecs[j]);CHKERRQ(ierr);
148f7765cecSBarry Smith   }
149b4fd4287SBarry Smith 
1503a40ed3dSBarry Smith   PetscFunctionReturn(0);
151f7765cecSBarry Smith }
152a2e34c3dSBarry Smith 
1534a2ae208SSatish Balay #undef __FUNCT__
1544a2ae208SSatish Balay #define __FUNCT__ "MatNullSpaceTest"
155a2e34c3dSBarry Smith /*@
156a2e34c3dSBarry Smith    MatNullSpaceTest  - Tests if the claimed null space is really a
157a2e34c3dSBarry Smith      null space of a matrix
158a2e34c3dSBarry Smith 
159a2e34c3dSBarry Smith    Collective on MatNullSpace
160a2e34c3dSBarry Smith 
161a2e34c3dSBarry Smith    Input Parameters:
162a2e34c3dSBarry Smith +  sp - the null space context
163a2e34c3dSBarry Smith -  mat - the matrix
164a2e34c3dSBarry Smith 
165a2e34c3dSBarry Smith    Level: advanced
166a2e34c3dSBarry Smith 
167a2e34c3dSBarry Smith .keywords: PC, null space, remove
168a2e34c3dSBarry Smith 
169a2e34c3dSBarry Smith .seealso: MatNullSpaceCreate(), MatNullSpaceDestroy()
170a2e34c3dSBarry Smith @*/
171be1d678aSKris Buschelman PetscErrorCode PETSCMAT_DLLEXPORT MatNullSpaceTest(MatNullSpace sp,Mat mat)
172a2e34c3dSBarry Smith {
17387828ca2SBarry Smith   PetscScalar    sum;
1748bb6bcc5SSatish Balay   PetscReal      nrm;
175c1ac3661SBarry Smith   PetscInt       j,n = sp->n,N,m;
1766849ba73SBarry Smith   PetscErrorCode ierr;
177a2e34c3dSBarry Smith   Vec            l,r;
178a2e34c3dSBarry Smith   MPI_Comm       comm = sp->comm;
179a2e34c3dSBarry Smith   PetscTruth     flg1,flg2;
180a2e34c3dSBarry Smith 
181a2e34c3dSBarry Smith   PetscFunctionBegin;
182b0a32e0cSBarry Smith   ierr = PetscOptionsHasName(PETSC_NULL,"-mat_null_space_test_view",&flg1);CHKERRQ(ierr);
183b0a32e0cSBarry Smith   ierr = PetscOptionsHasName(PETSC_NULL,"-mat_null_space_test_view_draw",&flg2);CHKERRQ(ierr);
184a2e34c3dSBarry Smith 
185a2e34c3dSBarry Smith   if (!sp->vec) {
186a2e34c3dSBarry Smith     if (n) {
187a2e34c3dSBarry Smith       ierr = VecDuplicate(sp->vecs[0],&sp->vec);CHKERRQ(ierr);
188a2e34c3dSBarry Smith     } else {
189a2e34c3dSBarry Smith       ierr = MatGetLocalSize(mat,&m,PETSC_NULL);CHKERRQ(ierr);
190a2e34c3dSBarry Smith       ierr = VecCreateMPI(sp->comm,m,PETSC_DETERMINE,&sp->vec);CHKERRQ(ierr);
191a2e34c3dSBarry Smith     }
192a2e34c3dSBarry Smith   }
193a2e34c3dSBarry Smith   l    = sp->vec;
194a2e34c3dSBarry Smith 
195a2e34c3dSBarry Smith   if (sp->has_cnst) {
196a2e34c3dSBarry Smith     ierr = VecDuplicate(l,&r);CHKERRQ(ierr);
197a2e34c3dSBarry Smith     ierr = VecGetSize(l,&N);CHKERRQ(ierr);
198a2e34c3dSBarry Smith     sum  = 1.0/N;
1992dcb1b2aSMatthew Knepley     ierr = VecSet(l,sum);CHKERRQ(ierr);
200a2e34c3dSBarry Smith     ierr = MatMult(mat,l,r);CHKERRQ(ierr);
2018bb6bcc5SSatish Balay     ierr = VecNorm(r,NORM_2,&nrm);CHKERRQ(ierr);
2028bb6bcc5SSatish Balay     if (nrm < 1.e-7) {ierr = PetscPrintf(comm,"Constants are likely null vector");CHKERRQ(ierr);}
203a2e34c3dSBarry Smith     else {ierr = PetscPrintf(comm,"Constants are unlikely null vector ");CHKERRQ(ierr);}
2048bb6bcc5SSatish Balay     ierr = PetscPrintf(comm,"|| A * 1 || = %g\n",nrm);CHKERRQ(ierr);
205b0a32e0cSBarry Smith     if (nrm > 1.e-7 && flg1) {ierr = VecView(r,PETSC_VIEWER_STDOUT_(comm));CHKERRQ(ierr);}
206b0a32e0cSBarry Smith     if (nrm > 1.e-7 && flg2) {ierr = VecView(r,PETSC_VIEWER_DRAW_(comm));CHKERRQ(ierr);}
207a2e34c3dSBarry Smith     ierr = VecDestroy(r);CHKERRQ(ierr);
208a2e34c3dSBarry Smith   }
209a2e34c3dSBarry Smith 
210a2e34c3dSBarry Smith   for (j=0; j<n; j++) {
211a2e34c3dSBarry Smith     ierr = (*mat->ops->mult)(mat,sp->vecs[j],l);CHKERRQ(ierr);
2128bb6bcc5SSatish Balay     ierr = VecNorm(l,NORM_2,&nrm);CHKERRQ(ierr);
21377431f27SBarry Smith     if (nrm < 1.e-7) {ierr = PetscPrintf(comm,"Null vector %D is likely null vector",j);CHKERRQ(ierr);}
21477431f27SBarry Smith     else {ierr = PetscPrintf(comm,"Null vector %D unlikely null vector ",j);CHKERRQ(ierr);}
21577431f27SBarry Smith     ierr = PetscPrintf(comm,"|| A * v[%D] || = %g\n",j,nrm);CHKERRQ(ierr);
216b0a32e0cSBarry Smith     if (nrm > 1.e-7 && flg1) {ierr = VecView(l,PETSC_VIEWER_STDOUT_(comm));CHKERRQ(ierr);}
217b0a32e0cSBarry Smith     if (nrm > 1.e-7 && flg2) {ierr = VecView(l,PETSC_VIEWER_DRAW_(comm));CHKERRQ(ierr);}
218a2e34c3dSBarry Smith   }
219a2e34c3dSBarry Smith 
220a2e34c3dSBarry Smith   PetscFunctionReturn(0);
221a2e34c3dSBarry Smith }
222a2e34c3dSBarry Smith 
223