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 */ 5 6 #include "src/mat/matimpl.h" /*I "petscmat.h" I*/ 7 #include "petscsys.h" 8 9 int MAT_NULLSPACE_COOKIE; 10 11 #undef __FUNCT__ 12 #define __FUNCT__ "MatNullSpaceCreate" 13 /*@C 14 MatNullSpaceCreate - Creates a data structure used to project vectors 15 out of null spaces. 16 17 Collective on MPI_Comm 18 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. 26 27 Output Parameter: 28 . SP - the null space context 29 30 Level: advanced 31 32 Users manual sections: 33 . sec_singular 34 35 .keywords: PC, null space, create 36 37 .seealso: MatNullSpaceDestroy(), MatNullSpaceRemove(), PCNullSpaceAttach(), MatNullSpace 38 @*/ 39 int MatNullSpaceCreate(MPI_Comm comm,int has_cnst,int n,Vec *vecs,MatNullSpace *SP) 40 { 41 MatNullSpace sp; 42 int ierr,i; 43 44 PetscFunctionBegin; 45 PetscHeaderCreate(sp,_p_MatNullSpace,int,MAT_NULLSPACE_COOKIE,0,"MatNullSpace",comm,MatNullSpaceDestroy,0); 46 PetscLogObjectCreate(sp); 47 PetscLogObjectMemory(sp,sizeof(struct _p_MatNullSpace)); 48 49 sp->has_cnst = has_cnst; 50 sp->n = n; 51 sp->vec = PETSC_NULL; 52 if (n) { 53 ierr = PetscMalloc(n*sizeof(Vec),&sp->vecs);CHKERRQ(ierr); 54 for (i=0; i<n; i++) sp->vecs[i] = vecs[i]; 55 } else { 56 sp->vecs = 0; 57 } 58 59 for (i=0; i<n; i++) { 60 ierr = PetscObjectReference((PetscObject)sp->vecs[i]);CHKERRQ(ierr); 61 } 62 *SP = sp; 63 PetscFunctionReturn(0); 64 } 65 66 #undef __FUNCT__ 67 #define __FUNCT__ "MatNullSpaceDestroy" 68 /*@ 69 MatNullSpaceDestroy - Destroys a data structure used to project vectors 70 out of null spaces. 71 72 Collective on MatNullSpace 73 74 Input Parameter: 75 . sp - the null space context to be destroyed 76 77 Level: advanced 78 79 .keywords: PC, null space, destroy 80 81 .seealso: MatNullSpaceCreate(), MatNullSpaceRemove() 82 @*/ 83 int MatNullSpaceDestroy(MatNullSpace sp) 84 { 85 int ierr; 86 87 PetscFunctionBegin; 88 if (--sp->refct > 0) PetscFunctionReturn(0); 89 90 if (sp->vec) {ierr = VecDestroy(sp->vec);CHKERRQ(ierr);} 91 if (sp->vecs) { 92 ierr = VecDestroyVecs(sp->vecs,sp->n);CHKERRQ(ierr); 93 } 94 PetscLogObjectDestroy(sp); 95 PetscHeaderDestroy(sp); 96 PetscFunctionReturn(0); 97 } 98 99 #undef __FUNCT__ 100 #define __FUNCT__ "MatNullSpaceRemove" 101 /*@ 102 MatNullSpaceRemove - Removes all the components of a null space from a vector. 103 104 Collective on MatNullSpace 105 106 Input Parameters: 107 + sp - the null space context 108 - vec - the vector from which the null space is to be removed 109 110 Level: advanced 111 112 .keywords: PC, null space, remove 113 114 .seealso: MatNullSpaceCreate(), MatNullSpaceDestroy() 115 @*/ 116 int MatNullSpaceRemove(MatNullSpace sp,Vec vec,Vec *out) 117 { 118 PetscScalar sum; 119 int j,n = sp->n,N,ierr; 120 Vec l = vec; 121 122 PetscFunctionBegin; 123 if (out) { 124 if (!sp->vec) { 125 ierr = VecDuplicate(vec,&sp->vec);CHKERRQ(ierr); 126 } 127 *out = sp->vec; 128 ierr = VecCopy(vec,*out);CHKERRQ(ierr); 129 l = *out; 130 } 131 132 if (sp->has_cnst) { 133 ierr = VecSum(l,&sum);CHKERRQ(ierr); 134 ierr = VecGetSize(l,&N);CHKERRQ(ierr); 135 sum = sum/(-1.0*N); 136 ierr = VecShift(&sum,l);CHKERRQ(ierr); 137 } 138 139 for (j=0; j<n; j++) { 140 ierr = VecDot(l,sp->vecs[j],&sum);CHKERRQ(ierr); 141 sum = -sum; 142 ierr = VecAXPY(&sum,sp->vecs[j],l);CHKERRQ(ierr); 143 } 144 145 PetscFunctionReturn(0); 146 } 147 148 #undef __FUNCT__ 149 #define __FUNCT__ "MatNullSpaceTest" 150 /*@ 151 MatNullSpaceTest - Tests if the claimed null space is really a 152 null space of a matrix 153 154 Collective on MatNullSpace 155 156 Input Parameters: 157 + sp - the null space context 158 - mat - the matrix 159 160 Level: advanced 161 162 .keywords: PC, null space, remove 163 164 .seealso: MatNullSpaceCreate(), MatNullSpaceDestroy() 165 @*/ 166 int MatNullSpaceTest(MatNullSpace sp,Mat mat) 167 { 168 PetscScalar sum; 169 PetscReal nrm; 170 int j,n = sp->n,N,ierr,m; 171 Vec l,r; 172 MPI_Comm comm = sp->comm; 173 PetscTruth flg1,flg2; 174 175 PetscFunctionBegin; 176 ierr = PetscOptionsHasName(PETSC_NULL,"-mat_null_space_test_view",&flg1);CHKERRQ(ierr); 177 ierr = PetscOptionsHasName(PETSC_NULL,"-mat_null_space_test_view_draw",&flg2);CHKERRQ(ierr); 178 179 if (!sp->vec) { 180 if (n) { 181 ierr = VecDuplicate(sp->vecs[0],&sp->vec);CHKERRQ(ierr); 182 } else { 183 ierr = MatGetLocalSize(mat,&m,PETSC_NULL);CHKERRQ(ierr); 184 ierr = VecCreateMPI(sp->comm,m,PETSC_DETERMINE,&sp->vec);CHKERRQ(ierr); 185 } 186 } 187 l = sp->vec; 188 189 if (sp->has_cnst) { 190 ierr = VecDuplicate(l,&r);CHKERRQ(ierr); 191 ierr = VecGetSize(l,&N);CHKERRQ(ierr); 192 sum = 1.0/N; 193 ierr = VecSet(&sum,l);CHKERRQ(ierr); 194 ierr = MatMult(mat,l,r);CHKERRQ(ierr); 195 ierr = VecNorm(r,NORM_2,&nrm);CHKERRQ(ierr); 196 if (nrm < 1.e-7) {ierr = PetscPrintf(comm,"Constants are likely null vector");CHKERRQ(ierr);} 197 else {ierr = PetscPrintf(comm,"Constants are unlikely null vector ");CHKERRQ(ierr);} 198 ierr = PetscPrintf(comm,"|| A * 1 || = %g\n",nrm);CHKERRQ(ierr); 199 if (nrm > 1.e-7 && flg1) {ierr = VecView(r,PETSC_VIEWER_STDOUT_(comm));CHKERRQ(ierr);} 200 if (nrm > 1.e-7 && flg2) {ierr = VecView(r,PETSC_VIEWER_DRAW_(comm));CHKERRQ(ierr);} 201 ierr = VecDestroy(r);CHKERRQ(ierr); 202 } 203 204 for (j=0; j<n; j++) { 205 ierr = (*mat->ops->mult)(mat,sp->vecs[j],l);CHKERRQ(ierr); 206 ierr = VecNorm(l,NORM_2,&nrm);CHKERRQ(ierr); 207 if (nrm < 1.e-7) {ierr = PetscPrintf(comm,"Null vector %d is likely null vector",j);CHKERRQ(ierr);} 208 else {ierr = PetscPrintf(comm,"Null vector %d unlikely null vector ",j);CHKERRQ(ierr);} 209 ierr = PetscPrintf(comm,"|| A * v[%d] || = %g\n",j,nrm);CHKERRQ(ierr); 210 if (nrm > 1.e-7 && flg1) {ierr = VecView(l,PETSC_VIEWER_STDOUT_(comm));CHKERRQ(ierr);} 211 if (nrm > 1.e-7 && flg2) {ierr = VecView(l,PETSC_VIEWER_DRAW_(comm));CHKERRQ(ierr);} 212 } 213 214 PetscFunctionReturn(0); 215 } 216 217