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: /*@C
 12:    MatNullSpaceCreate - Creates a data structure used to project vectors 
 13:    out of null spaces.

 15:    Collective on MPI_Comm

 17:    Input Parameters:
 18: +  comm - the MPI communicator associated with the object
 19: .  has_cnst - PETSC_TRUE if the null space contains the constant vector; otherwise PETSC_FALSE
 20: .  n - number of vectors (excluding constant vector) in null space
 21: -  vecs - the vectors that span the null space (excluding the constant vector);
 22:           these vectors must be orthonormal

 24:    Output Parameter:
 25: .  SP - the null space context

 27:    Level: advanced

 29:   Users manual sections:
 30: .   Section 4.15 Solving Singular Systems

 32: .keywords: PC, null space, create

 34: .seealso: MatNullSpaceDestroy(), MatNullSpaceRemove(), PCNullSpaceAttach(), MatNullSpace
 35: @*/
 36: int MatNullSpaceCreate(MPI_Comm comm,int has_cnst,int n,Vec *vecs,MatNullSpace *SP)
 37: {
 38:   MatNullSpace sp;

 41:   PetscHeaderCreate(sp,_p_MatNullSpace,int,MAT_NULLSPACE_COOKIE,0,"MatNullSpace",comm,MatNullSpaceDestroy,0);
 42:   PetscLogObjectCreate(sp);
 43:   PetscLogObjectMemory(sp,sizeof(struct _p_MatNullSpace));

 45:   sp->has_cnst = has_cnst;
 46:   sp->n        = n;
 47:   sp->vecs     = vecs;
 48:   sp->vec      = PETSC_NULL;

 50:   *SP          = sp;
 51:   return(0);
 52: }

 54: /*@
 55:    MatNullSpaceDestroy - Destroys a data structure used to project vectors 
 56:    out of null spaces.

 58:    Collective on MatNullSpace

 60:    Input Parameter:
 61: .  sp - the null space context to be destroyed

 63:    Level: advanced

 65: .keywords: PC, null space, destroy

 67: .seealso: MatNullSpaceCreate(), MatNullSpaceRemove()
 68: @*/
 69: int MatNullSpaceDestroy(MatNullSpace sp)
 70: {

 74:   if (--sp->refct > 0) return(0);

 76:   if (sp->vec) {VecDestroy(sp->vec);}

 78:   PetscLogObjectDestroy(sp);
 79:   PetscHeaderDestroy(sp);
 80:   return(0);
 81: }

 83: /*@
 84:    MatNullSpaceRemove - Removes all the components of a null space from a vector.

 86:    Collective on MatNullSpace

 88:    Input Parameters:
 89: +  sp - the null space context
 90: -  vec - the vector from which the null space is to be removed 

 92:    Level: advanced

 94: .keywords: PC, null space, remove

 96: .seealso: MatNullSpaceCreate(), MatNullSpaceDestroy()
 97: @*/
 98: int MatNullSpaceRemove(MatNullSpace sp,Vec vec,Vec *out)
 99: {
100:   PetscScalar sum;
101:   int         j,n = sp->n,N,ierr;
102:   Vec         l = vec;

105:   if (out) {
106:     if (!sp->vec) {
107:       VecDuplicate(vec,&sp->vec);
108:     }
109:     *out = sp->vec;
110:     VecCopy(vec,*out);
111:     l    = *out;
112:   }

114:   if (sp->has_cnst) {
115:     VecSum(l,&sum);
116:     VecGetSize(l,&N);
117:     sum  = sum/(-1.0*N);
118:     VecShift(&sum,l);
119:   }

121:   for (j=0; j<n; j++) {
122:     VecDot(l,sp->vecs[j],&sum);
123:     sum  = -sum;
124:     VecAXPY(&sum,sp->vecs[j],l);
125:   }
126: 
127:   return(0);
128: }

130: /*@
131:    MatNullSpaceTest  - Tests if the claimed null space is really a
132:      null space of a matrix

134:    Collective on MatNullSpace

136:    Input Parameters:
137: +  sp - the null space context
138: -  mat - the matrix

140:    Level: advanced

142: .keywords: PC, null space, remove

144: .seealso: MatNullSpaceCreate(), MatNullSpaceDestroy()
145: @*/
146: int MatNullSpaceTest(MatNullSpace sp,Mat mat)
147: {
148:   PetscScalar  sum;
149:   PetscReal    nrm;
150:   int          j,n = sp->n,N,ierr,m;
151:   Vec          l,r;
152:   MPI_Comm     comm = sp->comm;
153:   PetscTruth   flg1,flg2;

156:   PetscOptionsHasName(PETSC_NULL,"-mat_null_space_test_view",&flg1);
157:   PetscOptionsHasName(PETSC_NULL,"-mat_null_space_test_view_draw",&flg2);

159:   if (!sp->vec) {
160:     if (n) {
161:       VecDuplicate(sp->vecs[0],&sp->vec);
162:     } else {
163:       MatGetLocalSize(mat,&m,PETSC_NULL);
164:       VecCreateMPI(sp->comm,m,PETSC_DETERMINE,&sp->vec);
165:     }
166:   }
167:   l    = sp->vec;

169:   if (sp->has_cnst) {
170:     VecDuplicate(l,&r);
171:     VecGetSize(l,&N);
172:     sum  = 1.0/N;
173:     VecSet(&sum,l);
174:     MatMult(mat,l,r);
175:     VecNorm(r,NORM_2,&nrm);
176:     if (nrm < 1.e-7) {PetscPrintf(comm,"Constants are likely null vector");}
177:     else {PetscPrintf(comm,"Constants are unlikely null vector ");}
178:     PetscPrintf(comm,"|| A * 1 || = %gn",nrm);
179:     if (nrm > 1.e-7 && flg1) {VecView(r,PETSC_VIEWER_STDOUT_(comm));}
180:     if (nrm > 1.e-7 && flg2) {VecView(r,PETSC_VIEWER_DRAW_(comm));}
181:     VecDestroy(r);
182:   }

184:   for (j=0; j<n; j++) {
185:     (*mat->ops->mult)(mat,sp->vecs[j],l);
186:     VecNorm(l,NORM_2,&nrm);
187:     if (nrm < 1.e-7) {PetscPrintf(comm,"Null vector %d is likely null vector",j);}
188:     else {PetscPrintf(comm,"Null vector %d unlikely null vector ",j);}
189:     PetscPrintf(comm,"|| A * v[%d] || = %gn",j,nrm);
190:     if (nrm > 1.e-7 && flg1) {VecView(l,PETSC_VIEWER_STDOUT_(comm));}
191:     if (nrm > 1.e-7 && flg2) {VecView(l,PETSC_VIEWER_DRAW_(comm));}
192:   }
193: 
194:   return(0);
195: }