Actual source code: matnull.c
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: */
6: #include src/mat/matimpl.h
7: #include petscsys.h
9: int MAT_NULLSPACE_COOKIE = 0;
13: /*@C
14: MatNullSpaceCreate - Creates a data structure used to project vectors
15: out of null spaces.
17: Collective on MPI_Comm
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.
27: Output Parameter:
28: . SP - the null space context
30: Level: advanced
32: Users manual sections:
33: . Section 4.15 Solving Singular Systems
35: .keywords: PC, null space, create
37: .seealso: MatNullSpaceDestroy(), MatNullSpaceRemove(), PCNullSpaceAttach(), MatNullSpace
38: @*/
39: int MatNullSpaceCreate(MPI_Comm comm,int has_cnst,int n,const Vec vecs[],MatNullSpace *SP)
40: {
41: MatNullSpace sp;
42: int ierr,i;
45: PetscHeaderCreate(sp,_p_MatNullSpace,int,MAT_NULLSPACE_COOKIE,0,"MatNullSpace",comm,MatNullSpaceDestroy,0);
46: PetscLogObjectCreate(sp);
47: PetscLogObjectMemory(sp,sizeof(struct _p_MatNullSpace));
49: sp->has_cnst = has_cnst;
50: sp->n = n;
51: sp->vec = PETSC_NULL;
52: if (n) {
53: PetscMalloc(n*sizeof(Vec),&sp->vecs);
54: for (i=0; i<n; i++) sp->vecs[i] = vecs[i];
55: } else {
56: sp->vecs = 0;
57: }
59: for (i=0; i<n; i++) {
60: PetscObjectReference((PetscObject)sp->vecs[i]);
61: }
62: *SP = sp;
63: return(0);
64: }
68: /*@
69: MatNullSpaceDestroy - Destroys a data structure used to project vectors
70: out of null spaces.
72: Collective on MatNullSpace
74: Input Parameter:
75: . sp - the null space context to be destroyed
77: Level: advanced
79: .keywords: PC, null space, destroy
81: .seealso: MatNullSpaceCreate(), MatNullSpaceRemove()
82: @*/
83: int MatNullSpaceDestroy(MatNullSpace sp)
84: {
88: if (--sp->refct > 0) return(0);
90: if (sp->vec) {VecDestroy(sp->vec);}
91: if (sp->vecs) {
92: VecDestroyVecs(sp->vecs,sp->n);
93: }
94: PetscLogObjectDestroy(sp);
95: PetscHeaderDestroy(sp);
96: return(0);
97: }
101: /*@
102: MatNullSpaceRemove - Removes all the components of a null space from a vector.
104: Collective on MatNullSpace
106: Input Parameters:
107: + sp - the null space context
108: . vec - the vector from which the null space is to be removed
109: - out - if this is requested (not PETSC_NULL) then this is a vector with the null space removed otherwise
110: the removal is done in-place (in vec)
114: Level: advanced
116: .keywords: PC, null space, remove
118: .seealso: MatNullSpaceCreate(), MatNullSpaceDestroy()
119: @*/
120: int MatNullSpaceRemove(MatNullSpace sp,Vec vec,Vec *out)
121: {
122: PetscScalar sum;
123: int j,n = sp->n,N,ierr;
124: Vec l = vec;
127: if (out) {
128: if (!sp->vec) {
129: VecDuplicate(vec,&sp->vec);
130: }
131: *out = sp->vec;
132: VecCopy(vec,*out);
133: l = *out;
134: }
136: if (sp->has_cnst) {
137: VecSum(l,&sum);
138: VecGetSize(l,&N);
139: sum = sum/(-1.0*N);
140: VecShift(&sum,l);
141: }
143: for (j=0; j<n; j++) {
144: VecDot(l,sp->vecs[j],&sum);
145: sum = -sum;
146: VecAXPY(&sum,sp->vecs[j],l);
147: }
148:
149: return(0);
150: }
154: /*@
155: MatNullSpaceTest - Tests if the claimed null space is really a
156: null space of a matrix
158: Collective on MatNullSpace
160: Input Parameters:
161: + sp - the null space context
162: - mat - the matrix
164: Level: advanced
166: .keywords: PC, null space, remove
168: .seealso: MatNullSpaceCreate(), MatNullSpaceDestroy()
169: @*/
170: int MatNullSpaceTest(MatNullSpace sp,Mat mat)
171: {
172: PetscScalar sum;
173: PetscReal nrm;
174: int j,n = sp->n,N,ierr,m;
175: Vec l,r;
176: MPI_Comm comm = sp->comm;
177: PetscTruth flg1,flg2;
180: PetscOptionsHasName(PETSC_NULL,"-mat_null_space_test_view",&flg1);
181: PetscOptionsHasName(PETSC_NULL,"-mat_null_space_test_view_draw",&flg2);
183: if (!sp->vec) {
184: if (n) {
185: VecDuplicate(sp->vecs[0],&sp->vec);
186: } else {
187: MatGetLocalSize(mat,&m,PETSC_NULL);
188: VecCreateMPI(sp->comm,m,PETSC_DETERMINE,&sp->vec);
189: }
190: }
191: l = sp->vec;
193: if (sp->has_cnst) {
194: VecDuplicate(l,&r);
195: VecGetSize(l,&N);
196: sum = 1.0/N;
197: VecSet(&sum,l);
198: MatMult(mat,l,r);
199: VecNorm(r,NORM_2,&nrm);
200: if (nrm < 1.e-7) {PetscPrintf(comm,"Constants are likely null vector");}
201: else {PetscPrintf(comm,"Constants are unlikely null vector ");}
202: PetscPrintf(comm,"|| A * 1 || = %g\n",nrm);
203: if (nrm > 1.e-7 && flg1) {VecView(r,PETSC_VIEWER_STDOUT_(comm));}
204: if (nrm > 1.e-7 && flg2) {VecView(r,PETSC_VIEWER_DRAW_(comm));}
205: VecDestroy(r);
206: }
208: for (j=0; j<n; j++) {
209: (*mat->ops->mult)(mat,sp->vecs[j],l);
210: VecNorm(l,NORM_2,&nrm);
211: if (nrm < 1.e-7) {PetscPrintf(comm,"Null vector %d is likely null vector",j);}
212: else {PetscPrintf(comm,"Null vector %d unlikely null vector ",j);}
213: PetscPrintf(comm,"|| A * v[%d] || = %g\n",j,nrm);
214: if (nrm > 1.e-7 && flg1) {VecView(l,PETSC_VIEWER_STDOUT_(comm));}
215: if (nrm > 1.e-7 && flg2) {VecView(l,PETSC_VIEWER_DRAW_(comm));}
216: }
217:
218: return(0);
219: }