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;
11: #undef __FUNCT__
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,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: }
66: #undef __FUNCT__
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: }
99: #undef __FUNCT__
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
110: Level: advanced
112: .keywords: PC, null space, remove
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;
123: if (out) {
124: if (!sp->vec) {
125: VecDuplicate(vec,&sp->vec);
126: }
127: *out = sp->vec;
128: VecCopy(vec,*out);
129: l = *out;
130: }
132: if (sp->has_cnst) {
133: VecSum(l,&sum);
134: VecGetSize(l,&N);
135: sum = sum/(-1.0*N);
136: VecShift(&sum,l);
137: }
139: for (j=0; j<n; j++) {
140: VecDot(l,sp->vecs[j],&sum);
141: sum = -sum;
142: VecAXPY(&sum,sp->vecs[j],l);
143: }
144:
145: return(0);
146: }
148: #undef __FUNCT__
150: /*@
151: MatNullSpaceTest - Tests if the claimed null space is really a
152: null space of a matrix
154: Collective on MatNullSpace
156: Input Parameters:
157: + sp - the null space context
158: - mat - the matrix
160: Level: advanced
162: .keywords: PC, null space, remove
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;
176: PetscOptionsHasName(PETSC_NULL,"-mat_null_space_test_view",&flg1);
177: PetscOptionsHasName(PETSC_NULL,"-mat_null_space_test_view_draw",&flg2);
179: if (!sp->vec) {
180: if (n) {
181: VecDuplicate(sp->vecs[0],&sp->vec);
182: } else {
183: MatGetLocalSize(mat,&m,PETSC_NULL);
184: VecCreateMPI(sp->comm,m,PETSC_DETERMINE,&sp->vec);
185: }
186: }
187: l = sp->vec;
189: if (sp->has_cnst) {
190: VecDuplicate(l,&r);
191: VecGetSize(l,&N);
192: sum = 1.0/N;
193: VecSet(&sum,l);
194: MatMult(mat,l,r);
195: VecNorm(r,NORM_2,&nrm);
196: if (nrm < 1.e-7) {PetscPrintf(comm,"Constants are likely null vector");}
197: else {PetscPrintf(comm,"Constants are unlikely null vector ");}
198: PetscPrintf(comm,"|| A * 1 || = %gn",nrm);
199: if (nrm > 1.e-7 && flg1) {VecView(r,PETSC_VIEWER_STDOUT_(comm));}
200: if (nrm > 1.e-7 && flg2) {VecView(r,PETSC_VIEWER_DRAW_(comm));}
201: VecDestroy(r);
202: }
204: for (j=0; j<n; j++) {
205: (*mat->ops->mult)(mat,sp->vecs[j],l);
206: VecNorm(l,NORM_2,&nrm);
207: if (nrm < 1.e-7) {PetscPrintf(comm,"Null vector %d is likely null vector",j);}
208: else {PetscPrintf(comm,"Null vector %d unlikely null vector ",j);}
209: PetscPrintf(comm,"|| A * v[%d] || = %gn",j,nrm);
210: if (nrm > 1.e-7 && flg1) {VecView(l,PETSC_VIEWER_STDOUT_(comm));}
211: if (nrm > 1.e-7 && flg2) {VecView(l,PETSC_VIEWER_DRAW_(comm));}
212: }
213:
214: return(0);
215: }