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: }