xref: /petsc/src/mat/interface/matnull.c (revision 3cd8ff7ef82d7069cbad5366da736ff3054dd19f)
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;
47574b3360SMatthew Knepley   if (n) PetscValidPointer(vecs,4);
48574b3360SMatthew Knepley   for (i=0; i<n; i++) PetscValidHeaderSpecific(vecs[i],VEC_COOKIE,4);
49574b3360SMatthew Knepley   PetscValidPointer(SP,5);
50574b3360SMatthew Knepley 
51574b3360SMatthew Knepley   *SP = PETSC_NULL;
52574b3360SMatthew Knepley #ifndef PETSC_USE_DYNAMIC_LIBRARIES
53574b3360SMatthew Knepley   ierr = MatInitializePackage(PETSC_NULL);CHKERRQ(ierr);
54574b3360SMatthew Knepley #endif
55574b3360SMatthew 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 
121*3cd8ff7eSMatthew Knepley    Note: The vector returned is managed by the MatNullSpace, so the user should not destroy it.
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;
137*3cd8ff7eSMatthew Knepley   PetscValidHeaderSpecific(sp,MAT_NULLSPACE_COOKIE,1);
138*3cd8ff7eSMatthew Knepley   PetscValidHeaderSpecific(vec,VEC_COOKIE,2);
139*3cd8ff7eSMatthew Knepley 
1405cfeda75SBarry Smith   if (out) {
141*3cd8ff7eSMatthew Knepley     PetscValidPointer(out,3);
1425cfeda75SBarry Smith     if (!sp->vec) {
1435cfeda75SBarry Smith       ierr = VecDuplicate(vec,&sp->vec);CHKERRQ(ierr);
1445cfeda75SBarry Smith     }
1455cfeda75SBarry Smith     *out = sp->vec;
1465cfeda75SBarry Smith     ierr = VecCopy(vec,*out);CHKERRQ(ierr);
1475cfeda75SBarry Smith     l    = *out;
1485cfeda75SBarry Smith   }
1495cfeda75SBarry Smith 
150b4fd4287SBarry Smith   if (sp->has_cnst) {
1515cfeda75SBarry Smith     ierr = VecSum(l,&sum);CHKERRQ(ierr);
1525cfeda75SBarry Smith     ierr = VecGetSize(l,&N);CHKERRQ(ierr);
15318a7d68fSSatish Balay     sum  = sum/(-1.0*N);
1542dcb1b2aSMatthew Knepley     ierr = VecShift(l,sum);CHKERRQ(ierr);
155f7765cecSBarry Smith   }
156b4fd4287SBarry Smith 
157b4fd4287SBarry Smith   for (j=0; j<n; j++) {
1585cfeda75SBarry Smith     ierr = VecDot(l,sp->vecs[j],&sum);CHKERRQ(ierr);
159b4fd4287SBarry Smith     sum  = -sum;
1602dcb1b2aSMatthew Knepley     ierr = VecAXPY(l,sum,sp->vecs[j]);CHKERRQ(ierr);
161f7765cecSBarry Smith   }
162b4fd4287SBarry Smith 
1633a40ed3dSBarry Smith   PetscFunctionReturn(0);
164f7765cecSBarry Smith }
165a2e34c3dSBarry Smith 
1664a2ae208SSatish Balay #undef __FUNCT__
1674a2ae208SSatish Balay #define __FUNCT__ "MatNullSpaceTest"
168a2e34c3dSBarry Smith /*@
169a2e34c3dSBarry Smith    MatNullSpaceTest  - Tests if the claimed null space is really a
170a2e34c3dSBarry Smith      null space of a matrix
171a2e34c3dSBarry Smith 
172a2e34c3dSBarry Smith    Collective on MatNullSpace
173a2e34c3dSBarry Smith 
174a2e34c3dSBarry Smith    Input Parameters:
175a2e34c3dSBarry Smith +  sp - the null space context
176a2e34c3dSBarry Smith -  mat - the matrix
177a2e34c3dSBarry Smith 
178a2e34c3dSBarry Smith    Level: advanced
179a2e34c3dSBarry Smith 
180a2e34c3dSBarry Smith .keywords: PC, null space, remove
181a2e34c3dSBarry Smith 
182a2e34c3dSBarry Smith .seealso: MatNullSpaceCreate(), MatNullSpaceDestroy()
183a2e34c3dSBarry Smith @*/
184be1d678aSKris Buschelman PetscErrorCode PETSCMAT_DLLEXPORT MatNullSpaceTest(MatNullSpace sp,Mat mat)
185a2e34c3dSBarry Smith {
18687828ca2SBarry Smith   PetscScalar    sum;
1878bb6bcc5SSatish Balay   PetscReal      nrm;
188c1ac3661SBarry Smith   PetscInt       j,n = sp->n,N,m;
1896849ba73SBarry Smith   PetscErrorCode ierr;
190a2e34c3dSBarry Smith   Vec            l,r;
191a2e34c3dSBarry Smith   MPI_Comm       comm = sp->comm;
192a2e34c3dSBarry Smith   PetscTruth     flg1,flg2;
193a2e34c3dSBarry Smith 
194a2e34c3dSBarry Smith   PetscFunctionBegin;
195b0a32e0cSBarry Smith   ierr = PetscOptionsHasName(PETSC_NULL,"-mat_null_space_test_view",&flg1);CHKERRQ(ierr);
196b0a32e0cSBarry Smith   ierr = PetscOptionsHasName(PETSC_NULL,"-mat_null_space_test_view_draw",&flg2);CHKERRQ(ierr);
197a2e34c3dSBarry Smith 
198a2e34c3dSBarry Smith   if (!sp->vec) {
199a2e34c3dSBarry Smith     if (n) {
200a2e34c3dSBarry Smith       ierr = VecDuplicate(sp->vecs[0],&sp->vec);CHKERRQ(ierr);
201a2e34c3dSBarry Smith     } else {
202a2e34c3dSBarry Smith       ierr = MatGetLocalSize(mat,&m,PETSC_NULL);CHKERRQ(ierr);
203a2e34c3dSBarry Smith       ierr = VecCreateMPI(sp->comm,m,PETSC_DETERMINE,&sp->vec);CHKERRQ(ierr);
204a2e34c3dSBarry Smith     }
205a2e34c3dSBarry Smith   }
206a2e34c3dSBarry Smith   l    = sp->vec;
207a2e34c3dSBarry Smith 
208a2e34c3dSBarry Smith   if (sp->has_cnst) {
209a2e34c3dSBarry Smith     ierr = VecDuplicate(l,&r);CHKERRQ(ierr);
210a2e34c3dSBarry Smith     ierr = VecGetSize(l,&N);CHKERRQ(ierr);
211a2e34c3dSBarry Smith     sum  = 1.0/N;
2122dcb1b2aSMatthew Knepley     ierr = VecSet(l,sum);CHKERRQ(ierr);
213a2e34c3dSBarry Smith     ierr = MatMult(mat,l,r);CHKERRQ(ierr);
2148bb6bcc5SSatish Balay     ierr = VecNorm(r,NORM_2,&nrm);CHKERRQ(ierr);
2158bb6bcc5SSatish Balay     if (nrm < 1.e-7) {ierr = PetscPrintf(comm,"Constants are likely null vector");CHKERRQ(ierr);}
216a2e34c3dSBarry Smith     else {ierr = PetscPrintf(comm,"Constants are unlikely null vector ");CHKERRQ(ierr);}
2178bb6bcc5SSatish Balay     ierr = PetscPrintf(comm,"|| A * 1 || = %g\n",nrm);CHKERRQ(ierr);
218b0a32e0cSBarry Smith     if (nrm > 1.e-7 && flg1) {ierr = VecView(r,PETSC_VIEWER_STDOUT_(comm));CHKERRQ(ierr);}
219b0a32e0cSBarry Smith     if (nrm > 1.e-7 && flg2) {ierr = VecView(r,PETSC_VIEWER_DRAW_(comm));CHKERRQ(ierr);}
220a2e34c3dSBarry Smith     ierr = VecDestroy(r);CHKERRQ(ierr);
221a2e34c3dSBarry Smith   }
222a2e34c3dSBarry Smith 
223a2e34c3dSBarry Smith   for (j=0; j<n; j++) {
224a2e34c3dSBarry Smith     ierr = (*mat->ops->mult)(mat,sp->vecs[j],l);CHKERRQ(ierr);
2258bb6bcc5SSatish Balay     ierr = VecNorm(l,NORM_2,&nrm);CHKERRQ(ierr);
22677431f27SBarry Smith     if (nrm < 1.e-7) {ierr = PetscPrintf(comm,"Null vector %D is likely null vector",j);CHKERRQ(ierr);}
22777431f27SBarry Smith     else {ierr = PetscPrintf(comm,"Null vector %D unlikely null vector ",j);CHKERRQ(ierr);}
22877431f27SBarry Smith     ierr = PetscPrintf(comm,"|| A * v[%D] || = %g\n",j,nrm);CHKERRQ(ierr);
229b0a32e0cSBarry Smith     if (nrm > 1.e-7 && flg1) {ierr = VecView(l,PETSC_VIEWER_STDOUT_(comm));CHKERRQ(ierr);}
230b0a32e0cSBarry Smith     if (nrm > 1.e-7 && flg2) {ierr = VecView(l,PETSC_VIEWER_DRAW_(comm));CHKERRQ(ierr);}
231a2e34c3dSBarry Smith   }
232a2e34c3dSBarry Smith 
233a2e34c3dSBarry Smith   PetscFunctionReturn(0);
234a2e34c3dSBarry Smith }
235a2e34c3dSBarry Smith 
236