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
8: #include petscsys.h
10: PetscCookie MAT_NULLSPACE_COOKIE;
14: /*@C
15: MatNullSpaceSetFunction - set a function that removes a null space from a vector
16: out of null spaces.
18: Collective on MatNullSpace
20: Input Parameters:
21: + sp - the null space object
22: . rem - the function that removes the null space
23: - ctx - context for the remove function
25: Level: advanced
27: .keywords: PC, null space, create
29: .seealso: MatNullSpaceDestroy(), MatNullSpaceRemove(), KSPSetNullSpace(), MatNullSpace, MatNullSpaceCreate()
30: @*/
31: PetscErrorCode MatNullSpaceSetFunction(MatNullSpace sp, PetscErrorCode (*rem)(Vec,void*),void *ctx)
32: {
35: sp->remove = rem;
36: sp->rmctx = ctx;
37: return(0);
38: }
42: /*@
43: MatNullSpaceCreate - Creates a data structure used to project vectors
44: out of null spaces.
46: Collective on MPI_Comm
48: Input Parameters:
49: + comm - the MPI communicator associated with the object
50: . has_cnst - PETSC_TRUE if the null space contains the constant vector; otherwise PETSC_FALSE
51: . n - number of vectors (excluding constant vector) in null space
52: - vecs - the vectors that span the null space (excluding the constant vector);
53: these vectors must be orthonormal. These vectors are NOT copied, so do not change them
54: after this call. You should free the array that you pass in.
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)(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,m;
235: Vec l,r;
236: PetscTruth flg1,flg2,consistent = PETSC_TRUE;
237: PetscViewer viewer;
242: n = sp->n;
243: PetscOptionsHasName(PETSC_NULL,"-mat_null_space_test_view",&flg1);
244: PetscOptionsHasName(PETSC_NULL,"-mat_null_space_test_view_draw",&flg2);
246: if (!sp->vec) {
247: if (n) {
248: VecDuplicate(sp->vecs[0],&sp->vec);
249: } else {
250: MatGetLocalSize(mat,&m,PETSC_NULL);
251: VecCreateMPI(((PetscObject)sp)->comm,m,PETSC_DETERMINE,&sp->vec);
252: }
253: }
254: l = sp->vec;
256: PetscViewerASCIIGetStdout(((PetscObject)sp)->comm,&viewer);
257: if (sp->has_cnst) {
258: VecDuplicate(l,&r);
259: VecGetSize(l,&N);
260: sum = 1.0/N;
261: VecSet(l,sum);
262: MatMult(mat,l,r);
263: VecNorm(r,NORM_2,&nrm);
264: if (nrm < 1.e-7) {
265: PetscPrintf(((PetscObject)sp)->comm,"Constants are likely null vector");
266: } else {
267: PetscPrintf(((PetscObject)sp)->comm,"Constants are unlikely null vector ");
268: consistent = PETSC_FALSE;
269: }
270: PetscPrintf(((PetscObject)sp)->comm,"|| A * 1 || = %G\n",nrm);
271: if (nrm > 1.e-7 && flg1) {VecView(r,viewer);}
272: if (nrm > 1.e-7 && flg2) {VecView(r,viewer);}
273: VecDestroy(r);
274: }
276: for (j=0; j<n; j++) {
277: (*mat->ops->mult)(mat,sp->vecs[j],l);
278: VecNorm(l,NORM_2,&nrm);
279: if (nrm < 1.e-7) {
280: PetscPrintf(((PetscObject)sp)->comm,"Null vector %D is likely null vector",j);
281: } else {
282: PetscPrintf(((PetscObject)sp)->comm,"Null vector %D unlikely null vector ",j);
283: consistent = PETSC_FALSE;
284: }
285: PetscPrintf(((PetscObject)sp)->comm,"|| A * v[%D] || = %G\n",j,nrm);
286: if (nrm > 1.e-7 && flg1) {VecView(l,viewer);}
287: if (nrm > 1.e-7 && flg2) {VecView(l,viewer);}
288: }
290: if (sp->remove){
291: SETERRQ(PETSC_ERR_SUP,"Cannot test a null space provided as a function with MatNullSpaceSetFunction()");
292: }
293: *isNull = consistent;
294: return(0);
295: }