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