Actual source code: matnull.c
1: #define PETSCMAT_DLL
3: /*
4: Routines to project vectors out of null spaces.
5: */
7: #include private/matimpl.h
9: PetscCookie MAT_NULLSPACE_COOKIE;
13: /*@C
14: MatNullSpaceSetFunction - set a function that removes a null space from a vector
15: out of null spaces.
17: Collective on MatNullSpace
19: Input Parameters:
20: + sp - the null space object
21: . rem - the function that removes the null space
22: - ctx - context for the remove function
24: Level: advanced
26: .keywords: PC, null space, create
28: .seealso: MatNullSpaceDestroy(), MatNullSpaceRemove(), KSPSetNullSpace(), MatNullSpace, MatNullSpaceCreate()
29: @*/
30: PetscErrorCode MatNullSpaceSetFunction(MatNullSpace sp, PetscErrorCode (*rem)(MatNullSpace,Vec,void*),void *ctx)
31: {
34: sp->remove = rem;
35: sp->rmctx = ctx;
36: return(0);
37: }
41: /*@
42: MatNullSpaceCreate - Creates a data structure used to project vectors
43: out of null spaces.
45: Collective on MPI_Comm
47: Input Parameters:
48: + comm - the MPI communicator associated with the object
49: . has_cnst - PETSC_TRUE if the null space contains the constant vector; otherwise PETSC_FALSE
50: . n - number of vectors (excluding constant vector) in null space
51: - vecs - the vectors that span the null space (excluding the constant vector);
52: these vectors must be orthonormal. These vectors are NOT copied, so do not change them
53: after this call. You should free the array that you pass in and destroy the vectors (this will reduce the reference count
54: for them by one).
56: Output Parameter:
57: . SP - the null space context
59: Level: advanced
61: Notes: See MatNullSpaceSetFunction() as an alternative way of providing the null space information instead of setting vecs.
63: If has_cnst is PETSC_TRUE you do not need to pass a constant vector in as a fourth argument to this routine, nor do you
64: need to pass in a function that eliminates the constant function into MatNullSpaceSetFunction().
66: Users manual sections:
67: . Section 4.15 Solving Singular Systems
69: .keywords: PC, null space, create
71: .seealso: MatNullSpaceDestroy(), MatNullSpaceRemove(), KSPSetNullSpace(), MatNullSpace, MatNullSpaceSetFunction()
72: @*/
73: PetscErrorCode MatNullSpaceCreate(MPI_Comm comm,PetscTruth has_cnst,PetscInt n,const Vec vecs[],MatNullSpace *SP)
74: {
75: MatNullSpace sp;
77: PetscInt i;
80: if (n < 0) SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"Number of vectors (given %D) cannot be negative",n);
84:
85: *SP = PETSC_NULL;
86: #ifndef PETSC_USE_DYNAMIC_LIBRARIES
87: MatInitializePackage(PETSC_NULL);
88: #endif
90: PetscHeaderCreate(sp,_p_MatNullSpace,int,MAT_NULLSPACE_COOKIE,0,"MatNullSpace",comm,MatNullSpaceDestroy,0);
92: sp->has_cnst = has_cnst;
93: sp->n = n;
94: sp->vecs = 0;
95: sp->alpha = 0;
96: sp->vec = 0;
97: sp->remove = 0;
98: sp->rmctx = 0;
100: if (n) {
101: PetscMalloc(n*sizeof(Vec),&sp->vecs);
102: PetscMalloc(n*sizeof(PetscScalar),&sp->alpha);
103: PetscLogObjectMemory(sp,n*(sizeof(Vec)+sizeof(PetscScalar)));
104: for (i=0; i<n; i++) {
105: PetscObjectReference((PetscObject)vecs[i]);
106: sp->vecs[i] = vecs[i];
107: }
108: }
110: *SP = sp;
111: return(0);
112: }
116: /*@
117: MatNullSpaceDestroy - Destroys a data structure used to project vectors
118: out of null spaces.
120: Collective on MatNullSpace
122: Input Parameter:
123: . sp - the null space context to be destroyed
125: Level: advanced
127: .keywords: PC, null space, destroy
129: .seealso: MatNullSpaceCreate(), MatNullSpaceRemove(), MatNullSpaceSetFunction()
130: @*/
131: PetscErrorCode MatNullSpaceDestroy(MatNullSpace sp)
132: {
137: if (--((PetscObject)sp)->refct > 0) return(0);
139: if (sp->vec) { VecDestroy(sp->vec); }
140: if (sp->vecs) { VecDestroyVecs(sp->vecs,sp->n); }
141: PetscFree(sp->alpha);
142: PetscHeaderDestroy(sp);
143: return(0);
144: }
148: /*@C
149: MatNullSpaceRemove - Removes all the components of a null space from a vector.
151: Collective on MatNullSpace
153: Input Parameters:
154: + sp - the null space context
155: . vec - the vector from which the null space is to be removed
156: - out - if this is requested (not PETSC_NULL) then this is a vector with the null space removed otherwise
157: the removal is done in-place (in vec)
159: Note: The user is not responsible for the vector returned and should not destroy it.
161: Level: advanced
163: .keywords: PC, null space, remove
165: .seealso: MatNullSpaceCreate(), MatNullSpaceDestroy(), MatNullSpaceSetFunction()
166: @*/
167: PetscErrorCode MatNullSpaceRemove(MatNullSpace sp,Vec vec,Vec *out)
168: {
169: PetscScalar sum;
170: PetscInt i,N;
177: if (out) {
179: if (!sp->vec) {
180: VecDuplicate(vec,&sp->vec);
181: PetscLogObjectParent(sp,sp->vec);
182: }
183: VecCopy(vec,sp->vec);
184: vec = *out = sp->vec;
185: }
186:
187: if (sp->has_cnst) {
188: VecGetSize(vec,&N);
189: if (N > 0) {
190: VecSum(vec,&sum);
191: sum = sum/(-1.0*N);
192: VecShift(vec,sum);
193: }
194: }
195:
196: if (sp->n) {
197: VecMDot(vec,sp->n,sp->vecs,sp->alpha);
198: for (i=0; i<sp->n; i++) sp->alpha[i] = -sp->alpha[i];
199: VecMAXPY(vec,sp->n,sp->alpha,sp->vecs);
200: }
202: if (sp->remove){
203: (*sp->remove)(sp,vec,sp->rmctx);
204: }
205: return(0);
206: }
210: /*@
211: MatNullSpaceTest - Tests if the claimed null space is really a
212: null space of a matrix
214: Collective on MatNullSpace
216: Input Parameters:
217: + sp - the null space context
218: - mat - the matrix
220: Output Parameters:
221: . isNull - PETSC_TRUE if the nullspace is valid for this matrix
223: Level: advanced
225: .keywords: PC, null space, remove
227: .seealso: MatNullSpaceCreate(), MatNullSpaceDestroy(), MatNullSpaceSetFunction()
228: @*/
229: PetscErrorCode MatNullSpaceTest(MatNullSpace sp,Mat mat,PetscTruth *isNull)
230: {
231: PetscScalar sum;
232: PetscReal nrm;
233: PetscInt j,n,N;
235: Vec l,r;
236: PetscTruth flg1 = PETSC_FALSE,flg2 = PETSC_FALSE,consistent = PETSC_TRUE;
237: PetscViewer viewer;
242: n = sp->n;
243: PetscOptionsGetTruth(PETSC_NULL,"-mat_null_space_test_view",&flg1,PETSC_NULL);
244: PetscOptionsGetTruth(PETSC_NULL,"-mat_null_space_test_view_draw",&flg2,PETSC_NULL);
246: if (!sp->vec) {
247: if (n) {
248: VecDuplicate(sp->vecs[0],&sp->vec);
249: } else {
250: MatGetVecs(mat,&sp->vec,PETSC_NULL);
251: }
252: }
253: l = sp->vec;
255: PetscViewerASCIIGetStdout(((PetscObject)sp)->comm,&viewer);
256: if (sp->has_cnst) {
257: VecDuplicate(l,&r);
258: VecGetSize(l,&N);
259: sum = 1.0/N;
260: VecSet(l,sum);
261: MatMult(mat,l,r);
262: VecNorm(r,NORM_2,&nrm);
263: if (nrm < 1.e-7) {
264: PetscPrintf(((PetscObject)sp)->comm,"Constants are likely null vector");
265: } else {
266: PetscPrintf(((PetscObject)sp)->comm,"Constants are unlikely null vector ");
267: consistent = PETSC_FALSE;
268: }
269: PetscPrintf(((PetscObject)sp)->comm,"|| A * 1 || = %G\n",nrm);
270: if (nrm > 1.e-7 && flg1) {VecView(r,viewer);}
271: if (nrm > 1.e-7 && flg2) {VecView(r,viewer);}
272: VecDestroy(r);
273: }
275: for (j=0; j<n; j++) {
276: (*mat->ops->mult)(mat,sp->vecs[j],l);
277: VecNorm(l,NORM_2,&nrm);
278: if (nrm < 1.e-7) {
279: PetscPrintf(((PetscObject)sp)->comm,"Null vector %D is likely null vector",j);
280: } else {
281: PetscPrintf(((PetscObject)sp)->comm,"Null vector %D unlikely null vector ",j);
282: consistent = PETSC_FALSE;
283: }
284: PetscPrintf(((PetscObject)sp)->comm,"|| A * v[%D] || = %G\n",j,nrm);
285: if (nrm > 1.e-7 && flg1) {VecView(l,viewer);}
286: if (nrm > 1.e-7 && flg2) {VecView(l,viewer);}
287: }
289: if (sp->remove){
290: SETERRQ(PETSC_ERR_SUP,"Cannot test a null space provided as a function with MatNullSpaceSetFunction()");
291: }
292: *isNull = consistent;
293: return(0);
294: }