xref: /petsc/src/mat/interface/matnull.c (revision 574b3360adf4daf2d5a24a71a0b7e89556dea9b4)
1 #define PETSCMAT_DLL
2 
3 /*
4     Routines to project vectors out of null spaces.
5 */
6 
7 #include "src/mat/matimpl.h"      /*I "petscmat.h" I*/
8 #include "petscsys.h"
9 
10 PetscCookie PETSCMAT_DLLEXPORT MAT_NULLSPACE_COOKIE = 0;
11 
12 #undef __FUNCT__
13 #define __FUNCT__ "MatNullSpaceCreate"
14 /*@
15    MatNullSpaceCreate - Creates a data structure used to project vectors
16    out of null spaces.
17 
18    Collective on MPI_Comm
19 
20    Input Parameters:
21 +  comm - the MPI communicator associated with the object
22 .  has_cnst - PETSC_TRUE if the null space contains the constant vector; otherwise PETSC_FALSE
23 .  n - number of vectors (excluding constant vector) in null space
24 -  vecs - the vectors that span the null space (excluding the constant vector);
25           these vectors must be orthonormal. These vectors are NOT copied, so do not change them
26           after this call. You should free the array that you pass in.
27 
28    Output Parameter:
29 .  SP - the null space context
30 
31    Level: advanced
32 
33   Users manual sections:
34 .   sec_singular
35 
36 .keywords: PC, null space, create
37 
38 .seealso: MatNullSpaceDestroy(), MatNullSpaceRemove(), KSPSetNullSpace(), MatNullSpace
39 @*/
40 PetscErrorCode PETSCMAT_DLLEXPORT MatNullSpaceCreate(MPI_Comm comm,PetscTruth has_cnst,PetscInt n,const Vec vecs[],MatNullSpace *SP)
41 {
42   MatNullSpace   sp;
43   PetscErrorCode ierr;
44   PetscInt       i;
45 
46   PetscFunctionBegin;
47   if (n) PetscValidPointer(vecs,4);
48   for (i=0; i<n; i++) PetscValidHeaderSpecific(vecs[i],VEC_COOKIE,4);
49   PetscValidPointer(SP,5);
50 
51   *SP = PETSC_NULL;
52 #ifndef PETSC_USE_DYNAMIC_LIBRARIES
53   ierr = MatInitializePackage(PETSC_NULL);CHKERRQ(ierr);
54 #endif
55 
56   ierr = PetscHeaderCreate(sp,_p_MatNullSpace,int,MAT_NULLSPACE_COOKIE,0,"MatNullSpace",comm,MatNullSpaceDestroy,0);CHKERRQ(ierr);
57   ierr = PetscLogObjectMemory(sp,sizeof(struct _p_MatNullSpace));CHKERRQ(ierr);
58 
59   sp->has_cnst = has_cnst;
60   sp->n        = n;
61   sp->vec      = PETSC_NULL;
62   if (n) {
63     ierr = PetscMalloc(n*sizeof(Vec),&sp->vecs);CHKERRQ(ierr);
64     for (i=0; i<n; i++) sp->vecs[i] = vecs[i];
65   } else {
66     sp->vecs = 0;
67   }
68 
69   for (i=0; i<n; i++) {
70     ierr = PetscObjectReference((PetscObject)sp->vecs[i]);CHKERRQ(ierr);
71   }
72   *SP          = sp;
73   PetscFunctionReturn(0);
74 }
75 
76 #undef __FUNCT__
77 #define __FUNCT__ "MatNullSpaceDestroy"
78 /*@
79    MatNullSpaceDestroy - Destroys a data structure used to project vectors
80    out of null spaces.
81 
82    Collective on MatNullSpace
83 
84    Input Parameter:
85 .  sp - the null space context to be destroyed
86 
87    Level: advanced
88 
89 .keywords: PC, null space, destroy
90 
91 .seealso: MatNullSpaceCreate(), MatNullSpaceRemove()
92 @*/
93 PetscErrorCode PETSCMAT_DLLEXPORT MatNullSpaceDestroy(MatNullSpace sp)
94 {
95   PetscErrorCode ierr;
96 
97   PetscFunctionBegin;
98   if (--sp->refct > 0) PetscFunctionReturn(0);
99 
100   if (sp->vec) {ierr = VecDestroy(sp->vec);CHKERRQ(ierr);}
101   if (sp->vecs) {
102     ierr = VecDestroyVecs(sp->vecs,sp->n);CHKERRQ(ierr);
103   }
104   ierr = PetscHeaderDestroy(sp);CHKERRQ(ierr);
105   PetscFunctionReturn(0);
106 }
107 
108 #undef __FUNCT__
109 #define __FUNCT__ "MatNullSpaceRemove"
110 /*@
111    MatNullSpaceRemove - Removes all the components of a null space from a vector.
112 
113    Collective on MatNullSpace
114 
115    Input Parameters:
116 +  sp - the null space context
117 .  vec - the vector from which the null space is to be removed
118 -  out - if this is requested (not PETSC_NULL) then this is a vector with the null space removed otherwise
119          the removal is done in-place (in vec)
120 
121 
122 
123    Level: advanced
124 
125 .keywords: PC, null space, remove
126 
127 .seealso: MatNullSpaceCreate(), MatNullSpaceDestroy()
128 @*/
129 PetscErrorCode PETSCMAT_DLLEXPORT MatNullSpaceRemove(MatNullSpace sp,Vec vec,Vec *out)
130 {
131   PetscScalar    sum;
132   PetscErrorCode ierr;
133   PetscInt       j,n = sp->n,N;
134   Vec            l = vec;
135 
136   PetscFunctionBegin;
137   if (out) {
138     if (!sp->vec) {
139       ierr = VecDuplicate(vec,&sp->vec);CHKERRQ(ierr);
140     }
141     *out = sp->vec;
142     ierr = VecCopy(vec,*out);CHKERRQ(ierr);
143     l    = *out;
144   }
145 
146   if (sp->has_cnst) {
147     ierr = VecSum(l,&sum);CHKERRQ(ierr);
148     ierr = VecGetSize(l,&N);CHKERRQ(ierr);
149     sum  = sum/(-1.0*N);
150     ierr = VecShift(l,sum);CHKERRQ(ierr);
151   }
152 
153   for (j=0; j<n; j++) {
154     ierr = VecDot(l,sp->vecs[j],&sum);CHKERRQ(ierr);
155     sum  = -sum;
156     ierr = VecAXPY(l,sum,sp->vecs[j]);CHKERRQ(ierr);
157   }
158 
159   PetscFunctionReturn(0);
160 }
161 
162 #undef __FUNCT__
163 #define __FUNCT__ "MatNullSpaceTest"
164 /*@
165    MatNullSpaceTest  - Tests if the claimed null space is really a
166      null space of a matrix
167 
168    Collective on MatNullSpace
169 
170    Input Parameters:
171 +  sp - the null space context
172 -  mat - the matrix
173 
174    Level: advanced
175 
176 .keywords: PC, null space, remove
177 
178 .seealso: MatNullSpaceCreate(), MatNullSpaceDestroy()
179 @*/
180 PetscErrorCode PETSCMAT_DLLEXPORT MatNullSpaceTest(MatNullSpace sp,Mat mat)
181 {
182   PetscScalar    sum;
183   PetscReal      nrm;
184   PetscInt       j,n = sp->n,N,m;
185   PetscErrorCode ierr;
186   Vec            l,r;
187   MPI_Comm       comm = sp->comm;
188   PetscTruth     flg1,flg2;
189 
190   PetscFunctionBegin;
191   ierr = PetscOptionsHasName(PETSC_NULL,"-mat_null_space_test_view",&flg1);CHKERRQ(ierr);
192   ierr = PetscOptionsHasName(PETSC_NULL,"-mat_null_space_test_view_draw",&flg2);CHKERRQ(ierr);
193 
194   if (!sp->vec) {
195     if (n) {
196       ierr = VecDuplicate(sp->vecs[0],&sp->vec);CHKERRQ(ierr);
197     } else {
198       ierr = MatGetLocalSize(mat,&m,PETSC_NULL);CHKERRQ(ierr);
199       ierr = VecCreateMPI(sp->comm,m,PETSC_DETERMINE,&sp->vec);CHKERRQ(ierr);
200     }
201   }
202   l    = sp->vec;
203 
204   if (sp->has_cnst) {
205     ierr = VecDuplicate(l,&r);CHKERRQ(ierr);
206     ierr = VecGetSize(l,&N);CHKERRQ(ierr);
207     sum  = 1.0/N;
208     ierr = VecSet(l,sum);CHKERRQ(ierr);
209     ierr = MatMult(mat,l,r);CHKERRQ(ierr);
210     ierr = VecNorm(r,NORM_2,&nrm);CHKERRQ(ierr);
211     if (nrm < 1.e-7) {ierr = PetscPrintf(comm,"Constants are likely null vector");CHKERRQ(ierr);}
212     else {ierr = PetscPrintf(comm,"Constants are unlikely null vector ");CHKERRQ(ierr);}
213     ierr = PetscPrintf(comm,"|| A * 1 || = %g\n",nrm);CHKERRQ(ierr);
214     if (nrm > 1.e-7 && flg1) {ierr = VecView(r,PETSC_VIEWER_STDOUT_(comm));CHKERRQ(ierr);}
215     if (nrm > 1.e-7 && flg2) {ierr = VecView(r,PETSC_VIEWER_DRAW_(comm));CHKERRQ(ierr);}
216     ierr = VecDestroy(r);CHKERRQ(ierr);
217   }
218 
219   for (j=0; j<n; j++) {
220     ierr = (*mat->ops->mult)(mat,sp->vecs[j],l);CHKERRQ(ierr);
221     ierr = VecNorm(l,NORM_2,&nrm);CHKERRQ(ierr);
222     if (nrm < 1.e-7) {ierr = PetscPrintf(comm,"Null vector %D is likely null vector",j);CHKERRQ(ierr);}
223     else {ierr = PetscPrintf(comm,"Null vector %D unlikely null vector ",j);CHKERRQ(ierr);}
224     ierr = PetscPrintf(comm,"|| A * v[%D] || = %g\n",j,nrm);CHKERRQ(ierr);
225     if (nrm > 1.e-7 && flg1) {ierr = VecView(l,PETSC_VIEWER_STDOUT_(comm));CHKERRQ(ierr);}
226     if (nrm > 1.e-7 && flg2) {ierr = VecView(l,PETSC_VIEWER_DRAW_(comm));CHKERRQ(ierr);}
227   }
228 
229   PetscFunctionReturn(0);
230 }
231 
232