Actual source code: matnull.c

  1: #define PETSCMAT_DLL

  3: /*
  4:     Routines to project vectors out of null spaces.
  5: */

 7:  #include include/private/matimpl.h
 8:  #include petscsys.h

 10: PetscCookie  MAT_NULLSPACE_COOKIE = 0;

 14: /*@C
 15:    MatNullSpaceSetFunction - set a function that removes a null space from a vector
 16:    out of null spaces.

 18:    Collective on MatNullSpace

 20:    Input Parameters:
 21: +  sp - the null space object
 22: .  rem - the function that removes the null space
 23: -  ctx - context for the remove function

 25:    Level: advanced

 27: .keywords: PC, null space, create

 29: .seealso: MatNullSpaceDestroy(), MatNullSpaceRemove(), KSPSetNullSpace(), MatNullSpace, MatNullSpaceCreate()
 30: @*/
 31: PetscErrorCode  MatNullSpaceSetFunction(MatNullSpace sp, PetscErrorCode (*rem)(Vec,void*),void *ctx)
 32: {
 35:   sp->remove = rem;
 36:   sp->rmctx  = ctx;
 37:   return(0);
 38: }

 42: /*@
 43:    MatNullSpaceCreate - Creates a data structure used to project vectors 
 44:    out of null spaces.

 46:    Collective on MPI_Comm

 48:    Input Parameters:
 49: +  comm - the MPI communicator associated with the object
 50: .  has_cnst - PETSC_TRUE if the null space contains the constant vector; otherwise PETSC_FALSE
 51: .  n - number of vectors (excluding constant vector) in null space
 52: -  vecs - the vectors that span the null space (excluding the constant vector);
 53:           these vectors must be orthonormal. These vectors are NOT copied, so do not change them
 54:           after this call. You should free the array that you pass in.

 56:    Output Parameter:
 57: .  SP - the null space context

 59:    Level: advanced

 61:   Users manual sections:
 62: .   Section 4.15 Solving Singular Systems

 64: .keywords: PC, null space, create

 66: .seealso: MatNullSpaceDestroy(), MatNullSpaceRemove(), KSPSetNullSpace(), MatNullSpace, MatNullSpaceSetFunction()
 67: @*/
 68: PetscErrorCode  MatNullSpaceCreate(MPI_Comm comm,PetscTruth has_cnst,PetscInt n,const Vec vecs[],MatNullSpace *SP)
 69: {
 70:   MatNullSpace   sp;
 72:   PetscInt       i;

 75:   if (n < 0) SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"Number of vectors (given %D) cannot be negative",n);
 79: 
 80:   *SP = PETSC_NULL;
 81: #ifndef PETSC_USE_DYNAMIC_LIBRARIES 
 82:   MatInitializePackage(PETSC_NULL);
 83: #endif 

 85:   PetscHeaderCreate(sp,_p_MatNullSpace,int,MAT_NULLSPACE_COOKIE,0,"MatNullSpace",comm,MatNullSpaceDestroy,0);

 87:   sp->has_cnst = has_cnst;
 88:   sp->n        = n;
 89:   sp->vecs     = 0;
 90:   sp->alpha    = 0;
 91:   sp->vec      = 0;
 92:   sp->remove   = 0;
 93:   sp->rmctx    = 0;

 95:   if (n) {
 96:     PetscMalloc(n*sizeof(Vec),&sp->vecs);
 97:     PetscMalloc(n*sizeof(PetscScalar),&sp->alpha);
 98:     PetscLogObjectMemory(sp,n*(sizeof(Vec)+sizeof(PetscScalar)));
 99:     for (i=0; i<n; i++) {
100:       PetscObjectReference((PetscObject)vecs[i]);
101:       sp->vecs[i] = vecs[i];
102:     }
103:   }

105:   *SP          = sp;
106:   return(0);
107: }

111: /*@
112:    MatNullSpaceDestroy - Destroys a data structure used to project vectors 
113:    out of null spaces.

115:    Collective on MatNullSpace

117:    Input Parameter:
118: .  sp - the null space context to be destroyed

120:    Level: advanced

122: .keywords: PC, null space, destroy

124: .seealso: MatNullSpaceCreate(), MatNullSpaceRemove(), MatNullSpaceSetFunction()
125: @*/
126: PetscErrorCode  MatNullSpaceDestroy(MatNullSpace sp)
127: {

132:   if (--((PetscObject)sp)->refct > 0) return(0);

134:   if (sp->vec)  { VecDestroy(sp->vec); }
135:   if (sp->vecs) { VecDestroyVecs(sp->vecs,sp->n); }
136:   PetscFree(sp->alpha);
137:   PetscHeaderDestroy(sp);
138:   return(0);
139: }

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

146:    Collective on MatNullSpace

148:    Input Parameters:
149: +  sp - the null space context
150: .  vec - the vector from which the null space is to be removed 
151: -  out - if this is requested (not PETSC_NULL) then this is a vector with the null space removed otherwise
152:          the removal is done in-place (in vec)

154:    Note: The user is not responsible for the vector returned and should not destroy it.

156:    Level: advanced

158: .keywords: PC, null space, remove

160: .seealso: MatNullSpaceCreate(), MatNullSpaceDestroy(), MatNullSpaceSetFunction()
161: @*/
162: PetscErrorCode  MatNullSpaceRemove(MatNullSpace sp,Vec vec,Vec *out)
163: {
164:   PetscScalar    sum;
165:   PetscInt       i,N;


172:   if (out) {
174:     if (!sp->vec) {
175:       VecDuplicate(vec,&sp->vec);
176:       PetscLogObjectParent(sp,sp->vec);
177:     }
178:     VecCopy(vec,sp->vec);
179:     vec = *out = sp->vec;
180:   }
181: 
182:   if (sp->has_cnst) {
183:     VecGetSize(vec,&N);
184:     if (N > 0) {
185:       VecSum(vec,&sum);
186:       sum  = sum/(-1.0*N);
187:       VecShift(vec,sum);
188:     }
189:   }
190: 
191:   if (sp->n) {
192:     VecMDot(vec,sp->n,sp->vecs,sp->alpha);
193:     for (i=0; i<sp->n; i++) sp->alpha[i] = -sp->alpha[i];
194:     VecMAXPY(vec,sp->n,sp->alpha,sp->vecs);
195:   }

197:   if (sp->remove){
198:     (*sp->remove)(vec,sp->rmctx);
199:   }
200:   return(0);
201: }

205: /*@
206:    MatNullSpaceTest  - Tests if the claimed null space is really a
207:      null space of a matrix

209:    Collective on MatNullSpace

211:    Input Parameters:
212: +  sp - the null space context
213: -  mat - the matrix

215:    Level: advanced

217: .keywords: PC, null space, remove

219: .seealso: MatNullSpaceCreate(), MatNullSpaceDestroy(), MatNullSpaceSetFunction()
220: @*/
221: PetscErrorCode  MatNullSpaceTest(MatNullSpace sp,Mat mat)
222: {
223:   PetscScalar    sum;
224:   PetscReal      nrm;
225:   PetscInt       j,n,N,m;
227:   Vec            l,r;
228:   PetscTruth     flg1,flg2;
229:   PetscViewer    viewer;

234:   n = sp->n;
235:   PetscOptionsHasName(PETSC_NULL,"-mat_null_space_test_view",&flg1);
236:   PetscOptionsHasName(PETSC_NULL,"-mat_null_space_test_view_draw",&flg2);

238:   if (!sp->vec) {
239:     if (n) {
240:       VecDuplicate(sp->vecs[0],&sp->vec);
241:     } else {
242:       MatGetLocalSize(mat,&m,PETSC_NULL);
243:       VecCreateMPI(((PetscObject)sp)->comm,m,PETSC_DETERMINE,&sp->vec);
244:     }
245:   }
246:   l    = sp->vec;

248:   PetscViewerASCIIGetStdout(((PetscObject)sp)->comm,&viewer);
249:   if (sp->has_cnst) {
250:     VecDuplicate(l,&r);
251:     VecGetSize(l,&N);
252:     sum  = 1.0/N;
253:     VecSet(l,sum);
254:     MatMult(mat,l,r);
255:     VecNorm(r,NORM_2,&nrm);
256:     if (nrm < 1.e-7) {PetscPrintf(((PetscObject)sp)->comm,"Constants are likely null vector");}
257:     else {PetscPrintf(((PetscObject)sp)->comm,"Constants are unlikely null vector ");}
258:     PetscPrintf(((PetscObject)sp)->comm,"|| A * 1 || = %G\n",nrm);
259:     if (nrm > 1.e-7 && flg1) {VecView(r,viewer);}
260:     if (nrm > 1.e-7 && flg2) {VecView(r,viewer);}
261:     VecDestroy(r);
262:   }

264:   for (j=0; j<n; j++) {
265:     (*mat->ops->mult)(mat,sp->vecs[j],l);
266:     VecNorm(l,NORM_2,&nrm);
267:     if (nrm < 1.e-7) {PetscPrintf(((PetscObject)sp)->comm,"Null vector %D is likely null vector",j);}
268:     else {PetscPrintf(((PetscObject)sp)->comm,"Null vector %D unlikely null vector ",j);}
269:     PetscPrintf(((PetscObject)sp)->comm,"|| A * v[%D] || = %G\n",j,nrm);
270:     if (nrm > 1.e-7 && flg1) {VecView(l,viewer);}
271:     if (nrm > 1.e-7 && flg2) {VecView(l,viewer);}
272:   }

274:   if (sp->remove){
275:     SETERRQ(PETSC_ERR_SUP,"Cannot test a null space provided as a function with MatNullSpaceSetFunction()");
276:   }
277: 
278:   return(0);
279: }