Actual source code: matnull.c
1: #define PETSCMAT_DLL
3: /*
4: Routines to project vectors out of null spaces.
5: */
7: #include src/mat/matimpl.h
8: #include petscsys.h
10: PetscCookie PETSCMAT_DLLEXPORT MAT_NULLSPACE_COOKIE = 0;
14: /*@C
15: MatNullSpaceCreate - Creates a data structure used to project vectors
16: out of null spaces.
18: Collective on MPI_Comm
20: Input Parameters:
21: + comm - the MPI communicator associated with the object
22: . has_cnst - PETSC_TRUE if the null space contains the constant vector; otherwise PETSC_FALSE
23: . n - number of vectors (excluding constant vector) in null space
24: - vecs - the vectors that span the null space (excluding the constant vector);
25: these vectors must be orthonormal. These vectors are NOT copied, so do not change them
26: after this call. You should free the array that you pass in.
28: Output Parameter:
29: . SP - the null space context
31: Level: advanced
33: Users manual sections:
34: . Section 4.15 Solving Singular Systems
36: .keywords: PC, null space, create
38: .seealso: MatNullSpaceDestroy(), MatNullSpaceRemove(), KSPSetNullSpace(), MatNullSpace
39: @*/
40: PetscErrorCode PETSCMAT_DLLEXPORT MatNullSpaceCreate(MPI_Comm comm,PetscTruth has_cnst,PetscInt n,const Vec vecs[],MatNullSpace *SP)
41: {
42: MatNullSpace sp;
44: PetscInt i;
47: PetscHeaderCreate(sp,_p_MatNullSpace,int,MAT_NULLSPACE_COOKIE,0,"MatNullSpace",comm,MatNullSpaceDestroy,0);
48: PetscLogObjectMemory(sp,sizeof(struct _p_MatNullSpace));
50: sp->has_cnst = has_cnst;
51: sp->n = n;
52: sp->vec = PETSC_NULL;
53: if (n) {
54: PetscMalloc(n*sizeof(Vec),&sp->vecs);
55: for (i=0; i<n; i++) sp->vecs[i] = vecs[i];
56: } else {
57: sp->vecs = 0;
58: }
60: for (i=0; i<n; i++) {
61: PetscObjectReference((PetscObject)sp->vecs[i]);
62: }
63: *SP = sp;
64: return(0);
65: }
69: /*@
70: MatNullSpaceDestroy - Destroys a data structure used to project vectors
71: out of null spaces.
73: Collective on MatNullSpace
75: Input Parameter:
76: . sp - the null space context to be destroyed
78: Level: advanced
80: .keywords: PC, null space, destroy
82: .seealso: MatNullSpaceCreate(), MatNullSpaceRemove()
83: @*/
84: PetscErrorCode PETSCMAT_DLLEXPORT MatNullSpaceDestroy(MatNullSpace sp)
85: {
89: if (--sp->refct > 0) return(0);
91: if (sp->vec) {VecDestroy(sp->vec);}
92: if (sp->vecs) {
93: VecDestroyVecs(sp->vecs,sp->n);
94: }
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: PetscErrorCode PETSCMAT_DLLEXPORT MatNullSpaceRemove(MatNullSpace sp,Vec vec,Vec *out)
121: {
122: PetscScalar sum;
124: PetscInt j,n = sp->n,N;
125: Vec l = vec;
128: if (out) {
129: if (!sp->vec) {
130: VecDuplicate(vec,&sp->vec);
131: }
132: *out = sp->vec;
133: VecCopy(vec,*out);
134: l = *out;
135: }
137: if (sp->has_cnst) {
138: VecSum(l,&sum);
139: VecGetSize(l,&N);
140: sum = sum/(-1.0*N);
141: VecShift(l,sum);
142: }
144: for (j=0; j<n; j++) {
145: VecDot(l,sp->vecs[j],&sum);
146: sum = -sum;
147: VecAXPY(l,sum,sp->vecs[j]);
148: }
149:
150: return(0);
151: }
155: /*@
156: MatNullSpaceTest - Tests if the claimed null space is really a
157: null space of a matrix
159: Collective on MatNullSpace
161: Input Parameters:
162: + sp - the null space context
163: - mat - the matrix
165: Level: advanced
167: .keywords: PC, null space, remove
169: .seealso: MatNullSpaceCreate(), MatNullSpaceDestroy()
170: @*/
171: PetscErrorCode PETSCMAT_DLLEXPORT MatNullSpaceTest(MatNullSpace sp,Mat mat)
172: {
173: PetscScalar sum;
174: PetscReal nrm;
175: PetscInt j,n = sp->n,N,m;
177: Vec l,r;
178: MPI_Comm comm = sp->comm;
179: PetscTruth flg1,flg2;
182: PetscOptionsHasName(PETSC_NULL,"-mat_null_space_test_view",&flg1);
183: PetscOptionsHasName(PETSC_NULL,"-mat_null_space_test_view_draw",&flg2);
185: if (!sp->vec) {
186: if (n) {
187: VecDuplicate(sp->vecs[0],&sp->vec);
188: } else {
189: MatGetLocalSize(mat,&m,PETSC_NULL);
190: VecCreateMPI(sp->comm,m,PETSC_DETERMINE,&sp->vec);
191: }
192: }
193: l = sp->vec;
195: if (sp->has_cnst) {
196: VecDuplicate(l,&r);
197: VecGetSize(l,&N);
198: sum = 1.0/N;
199: VecSet(l,sum);
200: MatMult(mat,l,r);
201: VecNorm(r,NORM_2,&nrm);
202: if (nrm < 1.e-7) {PetscPrintf(comm,"Constants are likely null vector");}
203: else {PetscPrintf(comm,"Constants are unlikely null vector ");}
204: PetscPrintf(comm,"|| A * 1 || = %g\n",nrm);
205: if (nrm > 1.e-7 && flg1) {VecView(r,PETSC_VIEWER_STDOUT_(comm));}
206: if (nrm > 1.e-7 && flg2) {VecView(r,PETSC_VIEWER_DRAW_(comm));}
207: VecDestroy(r);
208: }
210: for (j=0; j<n; j++) {
211: (*mat->ops->mult)(mat,sp->vecs[j],l);
212: VecNorm(l,NORM_2,&nrm);
213: if (nrm < 1.e-7) {PetscPrintf(comm,"Null vector %D is likely null vector",j);}
214: else {PetscPrintf(comm,"Null vector %D unlikely null vector ",j);}
215: PetscPrintf(comm,"|| A * v[%D] || = %g\n",j,nrm);
216: if (nrm > 1.e-7 && flg1) {VecView(l,PETSC_VIEWER_STDOUT_(comm));}
217: if (nrm > 1.e-7 && flg2) {VecView(l,PETSC_VIEWER_DRAW_(comm));}
218: }
219:
220: return(0);
221: }