xref: /petsc/src/mat/interface/matnull.c (revision 52e6d16ba989af9362d0fcebb12e73dd7c9666ed)
1f7765cecSBarry Smith /*
2b4fd4287SBarry Smith     Routines to project vectors out of null spaces.
3f7765cecSBarry Smith */
4f7765cecSBarry Smith 
55cfeda75SBarry Smith #include "src/mat/matimpl.h"      /*I "petscmat.h" I*/
6e090d566SSatish Balay #include "petscsys.h"
7f7765cecSBarry Smith 
86849ba73SBarry Smith PetscCookie MAT_NULLSPACE_COOKIE = 0;
98ba1e511SMatthew Knepley 
104a2ae208SSatish Balay #undef __FUNCT__
114a2ae208SSatish Balay #define __FUNCT__ "MatNullSpaceCreate"
12112a2221SBarry Smith /*@C
135cfeda75SBarry Smith    MatNullSpaceCreate - Creates a data structure used to project vectors
14b4fd4287SBarry Smith    out of null spaces.
15f7765cecSBarry Smith 
164e472627SLois Curfman McInnes    Collective on MPI_Comm
174e472627SLois Curfman McInnes 
18f7765cecSBarry Smith    Input Parameters:
1983c3bef8SLois Curfman McInnes +  comm - the MPI communicator associated with the object
2083c3bef8SLois Curfman McInnes .  has_cnst - PETSC_TRUE if the null space contains the constant vector; otherwise PETSC_FALSE
21b4fd4287SBarry Smith .  n - number of vectors (excluding constant vector) in null space
2283c3bef8SLois Curfman McInnes -  vecs - the vectors that span the null space (excluding the constant vector);
23f7a9e4ceSBarry Smith           these vectors must be orthonormal. These vectors are NOT copied, so do not change them
24f7a9e4ceSBarry Smith           after this call. You should free the array that you pass in.
25f7765cecSBarry Smith 
26f7765cecSBarry Smith    Output Parameter:
27b4fd4287SBarry Smith .  SP - the null space context
28f7765cecSBarry Smith 
2983c3bef8SLois Curfman McInnes    Level: advanced
3083c3bef8SLois Curfman McInnes 
316e1639daSBarry Smith   Users manual sections:
326e1639daSBarry Smith .   sec_singular
336e1639daSBarry Smith 
3483c3bef8SLois Curfman McInnes .keywords: PC, null space, create
3541a59933SSatish Balay 
36d8fd42c4SBarry Smith .seealso: MatNullSpaceDestroy(), MatNullSpaceRemove(), KSPSetNullSpace(), MatNullSpace
37f7765cecSBarry Smith @*/
38c1ac3661SBarry Smith PetscErrorCode MatNullSpaceCreate(MPI_Comm comm,PetscTruth has_cnst,PetscInt n,const Vec vecs[],MatNullSpace *SP)
39f7765cecSBarry Smith {
405cfeda75SBarry Smith   MatNullSpace   sp;
41dfbe8321SBarry Smith   PetscErrorCode ierr;
42c1ac3661SBarry Smith   PetscInt       i;
43f7765cecSBarry Smith 
443a40ed3dSBarry Smith   PetscFunctionBegin;
45*52e6d16bSBarry Smith   ierr = PetscHeaderCreate(sp,_p_MatNullSpace,int,MAT_NULLSPACE_COOKIE,0,"MatNullSpace",comm,MatNullSpaceDestroy,0);CHKERRQ(ierr);
46*52e6d16bSBarry Smith   ierr = PetscLogObjectMemory(sp,sizeof(struct _p_MatNullSpace));CHKERRQ(ierr);
47f7765cecSBarry Smith 
48b4fd4287SBarry Smith   sp->has_cnst = has_cnst;
49b4fd4287SBarry Smith   sp->n        = n;
505cfeda75SBarry Smith   sp->vec      = PETSC_NULL;
51f7a9e4ceSBarry Smith   if (n) {
52f7a9e4ceSBarry Smith     ierr = PetscMalloc(n*sizeof(Vec),&sp->vecs);CHKERRQ(ierr);
53f7a9e4ceSBarry Smith     for (i=0; i<n; i++) sp->vecs[i] = vecs[i];
54f7a9e4ceSBarry Smith   } else {
55f7a9e4ceSBarry Smith     sp->vecs = 0;
56f7a9e4ceSBarry Smith   }
57b4fd4287SBarry Smith 
58f7a9e4ceSBarry Smith   for (i=0; i<n; i++) {
59f7a9e4ceSBarry Smith     ierr = PetscObjectReference((PetscObject)sp->vecs[i]);CHKERRQ(ierr);
60f7a9e4ceSBarry Smith   }
61b4fd4287SBarry Smith   *SP          = sp;
623a40ed3dSBarry Smith   PetscFunctionReturn(0);
63f7765cecSBarry Smith }
64f7765cecSBarry Smith 
654a2ae208SSatish Balay #undef __FUNCT__
664a2ae208SSatish Balay #define __FUNCT__ "MatNullSpaceDestroy"
67f7765cecSBarry Smith /*@
685cfeda75SBarry Smith    MatNullSpaceDestroy - Destroys a data structure used to project vectors
69b4fd4287SBarry Smith    out of null spaces.
70b4fd4287SBarry Smith 
715cfeda75SBarry Smith    Collective on MatNullSpace
724e472627SLois Curfman McInnes 
73b4fd4287SBarry Smith    Input Parameter:
74b9756687SLois Curfman McInnes .  sp - the null space context to be destroyed
75b9756687SLois Curfman McInnes 
76b9756687SLois Curfman McInnes    Level: advanced
77b4fd4287SBarry Smith 
7883c3bef8SLois Curfman McInnes .keywords: PC, null space, destroy
7941a59933SSatish Balay 
805cfeda75SBarry Smith .seealso: MatNullSpaceCreate(), MatNullSpaceRemove()
81b4fd4287SBarry Smith @*/
82dfbe8321SBarry Smith PetscErrorCode MatNullSpaceDestroy(MatNullSpace sp)
83b4fd4287SBarry Smith {
84dfbe8321SBarry Smith   PetscErrorCode ierr;
8585614651SBarry Smith 
865cfeda75SBarry Smith   PetscFunctionBegin;
8785614651SBarry Smith   if (--sp->refct > 0) PetscFunctionReturn(0);
8885614651SBarry Smith 
895cfeda75SBarry Smith   if (sp->vec) {ierr = VecDestroy(sp->vec);CHKERRQ(ierr);}
90f7a9e4ceSBarry Smith   if (sp->vecs) {
91f7a9e4ceSBarry Smith     ierr = VecDestroyVecs(sp->vecs,sp->n);CHKERRQ(ierr);
92f7a9e4ceSBarry Smith   }
93d38fa0fbSBarry Smith   ierr = PetscHeaderDestroy(sp);CHKERRQ(ierr);
943a40ed3dSBarry Smith   PetscFunctionReturn(0);
95b4fd4287SBarry Smith }
96b4fd4287SBarry Smith 
974a2ae208SSatish Balay #undef __FUNCT__
984a2ae208SSatish Balay #define __FUNCT__ "MatNullSpaceRemove"
99b4fd4287SBarry Smith /*@
1005cfeda75SBarry Smith    MatNullSpaceRemove - Removes all the components of a null space from a vector.
101f7765cecSBarry Smith 
1025cfeda75SBarry Smith    Collective on MatNullSpace
103f7765cecSBarry Smith 
1044e472627SLois Curfman McInnes    Input Parameters:
1054e472627SLois Curfman McInnes +  sp - the null space context
1064e7234bfSBarry Smith .  vec - the vector from which the null space is to be removed
1075fcf39f4SBarry Smith -  out - if this is requested (not PETSC_NULL) then this is a vector with the null space removed otherwise
1084e7234bfSBarry Smith          the removal is done in-place (in vec)
1094e7234bfSBarry Smith 
1104e7234bfSBarry Smith 
1114e472627SLois Curfman McInnes 
112b9756687SLois Curfman McInnes    Level: advanced
113b9756687SLois Curfman McInnes 
11483c3bef8SLois Curfman McInnes .keywords: PC, null space, remove
11541a59933SSatish Balay 
1165cfeda75SBarry Smith .seealso: MatNullSpaceCreate(), MatNullSpaceDestroy()
117f7765cecSBarry Smith @*/
118dfbe8321SBarry Smith PetscErrorCode MatNullSpaceRemove(MatNullSpace sp,Vec vec,Vec *out)
119f7765cecSBarry Smith {
12087828ca2SBarry Smith   PetscScalar    sum;
1216849ba73SBarry Smith   PetscErrorCode ierr;
122c1ac3661SBarry Smith   PetscInt       j,n = sp->n,N;
1235cfeda75SBarry Smith   Vec            l = vec;
124f7765cecSBarry Smith 
1253a40ed3dSBarry Smith   PetscFunctionBegin;
1265cfeda75SBarry Smith   if (out) {
1275cfeda75SBarry Smith     if (!sp->vec) {
1285cfeda75SBarry Smith       ierr = VecDuplicate(vec,&sp->vec);CHKERRQ(ierr);
1295cfeda75SBarry Smith     }
1305cfeda75SBarry Smith     *out = sp->vec;
1315cfeda75SBarry Smith     ierr = VecCopy(vec,*out);CHKERRQ(ierr);
1325cfeda75SBarry Smith     l    = *out;
1335cfeda75SBarry Smith   }
1345cfeda75SBarry Smith 
135b4fd4287SBarry Smith   if (sp->has_cnst) {
1365cfeda75SBarry Smith     ierr = VecSum(l,&sum);CHKERRQ(ierr);
1375cfeda75SBarry Smith     ierr = VecGetSize(l,&N);CHKERRQ(ierr);
13818a7d68fSSatish Balay     sum  = sum/(-1.0*N);
1395cfeda75SBarry Smith     ierr = VecShift(&sum,l);CHKERRQ(ierr);
140f7765cecSBarry Smith   }
141b4fd4287SBarry Smith 
142b4fd4287SBarry Smith   for (j=0; j<n; j++) {
1435cfeda75SBarry Smith     ierr = VecDot(l,sp->vecs[j],&sum);CHKERRQ(ierr);
144b4fd4287SBarry Smith     sum  = -sum;
1455cfeda75SBarry Smith     ierr = VecAXPY(&sum,sp->vecs[j],l);CHKERRQ(ierr);
146f7765cecSBarry Smith   }
147b4fd4287SBarry Smith 
1483a40ed3dSBarry Smith   PetscFunctionReturn(0);
149f7765cecSBarry Smith }
150a2e34c3dSBarry Smith 
1514a2ae208SSatish Balay #undef __FUNCT__
1524a2ae208SSatish Balay #define __FUNCT__ "MatNullSpaceTest"
153a2e34c3dSBarry Smith /*@
154a2e34c3dSBarry Smith    MatNullSpaceTest  - Tests if the claimed null space is really a
155a2e34c3dSBarry Smith      null space of a matrix
156a2e34c3dSBarry Smith 
157a2e34c3dSBarry Smith    Collective on MatNullSpace
158a2e34c3dSBarry Smith 
159a2e34c3dSBarry Smith    Input Parameters:
160a2e34c3dSBarry Smith +  sp - the null space context
161a2e34c3dSBarry Smith -  mat - the matrix
162a2e34c3dSBarry Smith 
163a2e34c3dSBarry Smith    Level: advanced
164a2e34c3dSBarry Smith 
165a2e34c3dSBarry Smith .keywords: PC, null space, remove
166a2e34c3dSBarry Smith 
167a2e34c3dSBarry Smith .seealso: MatNullSpaceCreate(), MatNullSpaceDestroy()
168a2e34c3dSBarry Smith @*/
169dfbe8321SBarry Smith PetscErrorCode MatNullSpaceTest(MatNullSpace sp,Mat mat)
170a2e34c3dSBarry Smith {
17187828ca2SBarry Smith   PetscScalar    sum;
1728bb6bcc5SSatish Balay   PetscReal      nrm;
173c1ac3661SBarry Smith   PetscInt       j,n = sp->n,N,m;
1746849ba73SBarry Smith   PetscErrorCode ierr;
175a2e34c3dSBarry Smith   Vec            l,r;
176a2e34c3dSBarry Smith   MPI_Comm       comm = sp->comm;
177a2e34c3dSBarry Smith   PetscTruth     flg1,flg2;
178a2e34c3dSBarry Smith 
179a2e34c3dSBarry Smith   PetscFunctionBegin;
180b0a32e0cSBarry Smith   ierr = PetscOptionsHasName(PETSC_NULL,"-mat_null_space_test_view",&flg1);CHKERRQ(ierr);
181b0a32e0cSBarry Smith   ierr = PetscOptionsHasName(PETSC_NULL,"-mat_null_space_test_view_draw",&flg2);CHKERRQ(ierr);
182a2e34c3dSBarry Smith 
183a2e34c3dSBarry Smith   if (!sp->vec) {
184a2e34c3dSBarry Smith     if (n) {
185a2e34c3dSBarry Smith       ierr = VecDuplicate(sp->vecs[0],&sp->vec);CHKERRQ(ierr);
186a2e34c3dSBarry Smith     } else {
187a2e34c3dSBarry Smith       ierr = MatGetLocalSize(mat,&m,PETSC_NULL);CHKERRQ(ierr);
188a2e34c3dSBarry Smith       ierr = VecCreateMPI(sp->comm,m,PETSC_DETERMINE,&sp->vec);CHKERRQ(ierr);
189a2e34c3dSBarry Smith     }
190a2e34c3dSBarry Smith   }
191a2e34c3dSBarry Smith   l    = sp->vec;
192a2e34c3dSBarry Smith 
193a2e34c3dSBarry Smith   if (sp->has_cnst) {
194a2e34c3dSBarry Smith     ierr = VecDuplicate(l,&r);CHKERRQ(ierr);
195a2e34c3dSBarry Smith     ierr = VecGetSize(l,&N);CHKERRQ(ierr);
196a2e34c3dSBarry Smith     sum  = 1.0/N;
197a2e34c3dSBarry Smith     ierr = VecSet(&sum,l);CHKERRQ(ierr);
198a2e34c3dSBarry Smith     ierr = MatMult(mat,l,r);CHKERRQ(ierr);
1998bb6bcc5SSatish Balay     ierr = VecNorm(r,NORM_2,&nrm);CHKERRQ(ierr);
2008bb6bcc5SSatish Balay     if (nrm < 1.e-7) {ierr = PetscPrintf(comm,"Constants are likely null vector");CHKERRQ(ierr);}
201a2e34c3dSBarry Smith     else {ierr = PetscPrintf(comm,"Constants are unlikely null vector ");CHKERRQ(ierr);}
2028bb6bcc5SSatish Balay     ierr = PetscPrintf(comm,"|| A * 1 || = %g\n",nrm);CHKERRQ(ierr);
203b0a32e0cSBarry Smith     if (nrm > 1.e-7 && flg1) {ierr = VecView(r,PETSC_VIEWER_STDOUT_(comm));CHKERRQ(ierr);}
204b0a32e0cSBarry Smith     if (nrm > 1.e-7 && flg2) {ierr = VecView(r,PETSC_VIEWER_DRAW_(comm));CHKERRQ(ierr);}
205a2e34c3dSBarry Smith     ierr = VecDestroy(r);CHKERRQ(ierr);
206a2e34c3dSBarry Smith   }
207a2e34c3dSBarry Smith 
208a2e34c3dSBarry Smith   for (j=0; j<n; j++) {
209a2e34c3dSBarry Smith     ierr = (*mat->ops->mult)(mat,sp->vecs[j],l);CHKERRQ(ierr);
2108bb6bcc5SSatish Balay     ierr = VecNorm(l,NORM_2,&nrm);CHKERRQ(ierr);
21177431f27SBarry Smith     if (nrm < 1.e-7) {ierr = PetscPrintf(comm,"Null vector %D is likely null vector",j);CHKERRQ(ierr);}
21277431f27SBarry Smith     else {ierr = PetscPrintf(comm,"Null vector %D unlikely null vector ",j);CHKERRQ(ierr);}
21377431f27SBarry Smith     ierr = PetscPrintf(comm,"|| A * v[%D] || = %g\n",j,nrm);CHKERRQ(ierr);
214b0a32e0cSBarry Smith     if (nrm > 1.e-7 && flg1) {ierr = VecView(l,PETSC_VIEWER_STDOUT_(comm));CHKERRQ(ierr);}
215b0a32e0cSBarry Smith     if (nrm > 1.e-7 && flg2) {ierr = VecView(l,PETSC_VIEWER_DRAW_(comm));CHKERRQ(ierr);}
216a2e34c3dSBarry Smith   }
217a2e34c3dSBarry Smith 
218a2e34c3dSBarry Smith   PetscFunctionReturn(0);
219a2e34c3dSBarry Smith }
220a2e34c3dSBarry Smith 
221