xref: /petsc/src/mat/interface/matnull.c (revision 6849ba73f22fecb8f92ef896a42e4e8bd4cd6965)
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 
8*6849ba73SBarry 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 @*/
38dfbe8321SBarry Smith PetscErrorCode MatNullSpaceCreate(MPI_Comm comm,int has_cnst,int n,const Vec vecs[],MatNullSpace *SP)
39f7765cecSBarry Smith {
405cfeda75SBarry Smith   MatNullSpace sp;
41dfbe8321SBarry Smith   PetscErrorCode ierr;
42dfbe8321SBarry Smith   int          i;
43f7765cecSBarry Smith 
443a40ed3dSBarry Smith   PetscFunctionBegin;
458ba1e511SMatthew Knepley   PetscHeaderCreate(sp,_p_MatNullSpace,int,MAT_NULLSPACE_COOKIE,0,"MatNullSpace",comm,MatNullSpaceDestroy,0);
46b0a32e0cSBarry Smith   PetscLogObjectCreate(sp);
47b0a32e0cSBarry Smith   PetscLogObjectMemory(sp,sizeof(struct _p_MatNullSpace));
48f7765cecSBarry Smith 
49b4fd4287SBarry Smith   sp->has_cnst = has_cnst;
50b4fd4287SBarry Smith   sp->n        = n;
515cfeda75SBarry Smith   sp->vec      = PETSC_NULL;
52f7a9e4ceSBarry Smith   if (n) {
53f7a9e4ceSBarry Smith     ierr = PetscMalloc(n*sizeof(Vec),&sp->vecs);CHKERRQ(ierr);
54f7a9e4ceSBarry Smith     for (i=0; i<n; i++) sp->vecs[i] = vecs[i];
55f7a9e4ceSBarry Smith   } else {
56f7a9e4ceSBarry Smith     sp->vecs = 0;
57f7a9e4ceSBarry Smith   }
58b4fd4287SBarry Smith 
59f7a9e4ceSBarry Smith   for (i=0; i<n; i++) {
60f7a9e4ceSBarry Smith     ierr = PetscObjectReference((PetscObject)sp->vecs[i]);CHKERRQ(ierr);
61f7a9e4ceSBarry Smith   }
62b4fd4287SBarry Smith   *SP          = sp;
633a40ed3dSBarry Smith   PetscFunctionReturn(0);
64f7765cecSBarry Smith }
65f7765cecSBarry Smith 
664a2ae208SSatish Balay #undef __FUNCT__
674a2ae208SSatish Balay #define __FUNCT__ "MatNullSpaceDestroy"
68f7765cecSBarry Smith /*@
695cfeda75SBarry Smith    MatNullSpaceDestroy - Destroys a data structure used to project vectors
70b4fd4287SBarry Smith    out of null spaces.
71b4fd4287SBarry Smith 
725cfeda75SBarry Smith    Collective on MatNullSpace
734e472627SLois Curfman McInnes 
74b4fd4287SBarry Smith    Input Parameter:
75b9756687SLois Curfman McInnes .  sp - the null space context to be destroyed
76b9756687SLois Curfman McInnes 
77b9756687SLois Curfman McInnes    Level: advanced
78b4fd4287SBarry Smith 
7983c3bef8SLois Curfman McInnes .keywords: PC, null space, destroy
8041a59933SSatish Balay 
815cfeda75SBarry Smith .seealso: MatNullSpaceCreate(), MatNullSpaceRemove()
82b4fd4287SBarry Smith @*/
83dfbe8321SBarry Smith PetscErrorCode MatNullSpaceDestroy(MatNullSpace sp)
84b4fd4287SBarry Smith {
85dfbe8321SBarry Smith   PetscErrorCode ierr;
8685614651SBarry Smith 
875cfeda75SBarry Smith   PetscFunctionBegin;
8885614651SBarry Smith   if (--sp->refct > 0) PetscFunctionReturn(0);
8985614651SBarry Smith 
905cfeda75SBarry Smith   if (sp->vec) {ierr = VecDestroy(sp->vec);CHKERRQ(ierr);}
91f7a9e4ceSBarry Smith   if (sp->vecs) {
92f7a9e4ceSBarry Smith     ierr = VecDestroyVecs(sp->vecs,sp->n);CHKERRQ(ierr);
93f7a9e4ceSBarry Smith   }
94b0a32e0cSBarry Smith   PetscLogObjectDestroy(sp);
95b4fd4287SBarry Smith   PetscHeaderDestroy(sp);
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 @*/
120dfbe8321SBarry Smith PetscErrorCode MatNullSpaceRemove(MatNullSpace sp,Vec vec,Vec *out)
121f7765cecSBarry Smith {
12287828ca2SBarry Smith   PetscScalar sum;
123*6849ba73SBarry Smith   PetscErrorCode ierr;
124*6849ba73SBarry Smith   int         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);
1415cfeda75SBarry Smith     ierr = VecShift(&sum,l);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;
1475cfeda75SBarry Smith     ierr = VecAXPY(&sum,sp->vecs[j],l);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 @*/
171dfbe8321SBarry Smith PetscErrorCode MatNullSpaceTest(MatNullSpace sp,Mat mat)
172a2e34c3dSBarry Smith {
17387828ca2SBarry Smith   PetscScalar  sum;
1748bb6bcc5SSatish Balay   PetscReal    nrm;
175*6849ba73SBarry Smith   int          j,n = sp->n,N,m;
176*6849ba73SBarry 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;
199a2e34c3dSBarry Smith     ierr = VecSet(&sum,l);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);
2138bb6bcc5SSatish Balay     if (nrm < 1.e-7) {ierr = PetscPrintf(comm,"Null vector %d is likely null vector",j);CHKERRQ(ierr);}
214a2e34c3dSBarry Smith     else {ierr = PetscPrintf(comm,"Null vector %d unlikely null vector ",j);CHKERRQ(ierr);}
2158bb6bcc5SSatish Balay     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