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