1 #define PETSCMAT_DLL 2 3 /* 4 Routines to project vectors out of null spaces. 5 */ 6 7 #include "src/mat/matimpl.h" /*I "petscmat.h" I*/ 8 #include "petscsys.h" 9 10 PetscCookie PETSCMAT_DLLEXPORT MAT_NULLSPACE_COOKIE = 0; 11 12 #undef __FUNCT__ 13 #define __FUNCT__ "MatNullSpaceSetFunction" 14 /*@C 15 MatNullSpaceSetFunction - set a function that removes a null space from a vector 16 out of null spaces. 17 18 Collective on MatNullSpace 19 20 Input Parameters: 21 + sp - the null space object 22 - remove - the function that removes the null space 23 24 .keywords: PC, null space, create 25 26 .seealso: MatNullSpaceDestroy(), MatNullSpaceRemove(), KSPSetNullSpace(), MatNullSpace, MatNullSpaceCreate() 27 @*/ 28 PetscErrorCode PETSCMAT_DLLEXPORT MatNullSpaceSetFunction(MatNullSpace sp, PetscErrorCode (*remove)(Vec)) 29 { 30 PetscFunctionBegin; 31 sp->remove = remove; 32 PetscFunctionReturn(0); 33 } 34 35 #undef __FUNCT__ 36 #define __FUNCT__ "MatNullSpaceCreate" 37 /*@ 38 MatNullSpaceCreate - Creates a data structure used to project vectors 39 out of null spaces. 40 41 Collective on MPI_Comm 42 43 Input Parameters: 44 + comm - the MPI communicator associated with the object 45 . has_cnst - PETSC_TRUE if the null space contains the constant vector; otherwise PETSC_FALSE 46 . n - number of vectors (excluding constant vector) in null space 47 - vecs - the vectors that span the null space (excluding the constant vector); 48 these vectors must be orthonormal. These vectors are NOT copied, so do not change them 49 after this call. You should free the array that you pass in. 50 51 Output Parameter: 52 . SP - the null space context 53 54 Level: advanced 55 56 Users manual sections: 57 . sec_singular 58 59 .keywords: PC, null space, create 60 61 .seealso: MatNullSpaceDestroy(), MatNullSpaceRemove(), KSPSetNullSpace(), MatNullSpace, MatNullSpaceSetFunction() 62 @*/ 63 PetscErrorCode PETSCMAT_DLLEXPORT MatNullSpaceCreate(MPI_Comm comm,PetscTruth has_cnst,PetscInt n,const Vec vecs[],MatNullSpace *SP) 64 { 65 MatNullSpace sp; 66 PetscErrorCode ierr; 67 PetscInt i; 68 69 PetscFunctionBegin; 70 if (n) PetscValidPointer(vecs,4); 71 for (i=0; i<n; i++) PetscValidHeaderSpecific(vecs[i],VEC_COOKIE,4); 72 PetscValidPointer(SP,5); 73 74 *SP = PETSC_NULL; 75 #ifndef PETSC_USE_DYNAMIC_LIBRARIES 76 ierr = MatInitializePackage(PETSC_NULL);CHKERRQ(ierr); 77 #endif 78 79 ierr = PetscHeaderCreate(sp,_p_MatNullSpace,int,MAT_NULLSPACE_COOKIE,0,"MatNullSpace",comm,MatNullSpaceDestroy,0);CHKERRQ(ierr); 80 ierr = PetscLogObjectMemory(sp,sizeof(struct _p_MatNullSpace));CHKERRQ(ierr); 81 82 sp->has_cnst = has_cnst; 83 sp->n = n; 84 sp->vec = PETSC_NULL; 85 if (n) { 86 ierr = PetscMalloc(n*sizeof(Vec),&sp->vecs);CHKERRQ(ierr); 87 for (i=0; i<n; i++) sp->vecs[i] = vecs[i]; 88 } else { 89 sp->vecs = 0; 90 } 91 92 for (i=0; i<n; i++) { 93 ierr = PetscObjectReference((PetscObject)sp->vecs[i]);CHKERRQ(ierr); 94 } 95 *SP = sp; 96 PetscFunctionReturn(0); 97 } 98 99 #undef __FUNCT__ 100 #define __FUNCT__ "MatNullSpaceDestroy" 101 /*@ 102 MatNullSpaceDestroy - Destroys a data structure used to project vectors 103 out of null spaces. 104 105 Collective on MatNullSpace 106 107 Input Parameter: 108 . sp - the null space context to be destroyed 109 110 Level: advanced 111 112 .keywords: PC, null space, destroy 113 114 .seealso: MatNullSpaceCreate(), MatNullSpaceRemove(), MatNullSpaceSetFunction() 115 @*/ 116 PetscErrorCode PETSCMAT_DLLEXPORT MatNullSpaceDestroy(MatNullSpace sp) 117 { 118 PetscErrorCode ierr; 119 120 PetscFunctionBegin; 121 if (--sp->refct > 0) PetscFunctionReturn(0); 122 123 if (sp->vec) {ierr = VecDestroy(sp->vec);CHKERRQ(ierr);} 124 if (sp->vecs) { 125 ierr = VecDestroyVecs(sp->vecs,sp->n);CHKERRQ(ierr); 126 } 127 ierr = PetscHeaderDestroy(sp);CHKERRQ(ierr); 128 PetscFunctionReturn(0); 129 } 130 131 #undef __FUNCT__ 132 #define __FUNCT__ "MatNullSpaceRemove" 133 /*@ 134 MatNullSpaceRemove - Removes all the components of a null space from a vector. 135 136 Collective on MatNullSpace 137 138 Input Parameters: 139 + sp - the null space context 140 . vec - the vector from which the null space is to be removed 141 - out - if this is requested (not PETSC_NULL) then this is a vector with the null space removed otherwise 142 the removal is done in-place (in vec) 143 144 Note: The user is not responsible for the vector returned and should not destroy it. 145 146 Level: advanced 147 148 .keywords: PC, null space, remove 149 150 .seealso: MatNullSpaceCreate(), MatNullSpaceDestroy(), MatNullSpaceSetFunction() 151 @*/ 152 PetscErrorCode PETSCMAT_DLLEXPORT MatNullSpaceRemove(MatNullSpace sp,Vec vec,Vec *out) 153 { 154 PetscScalar sum; 155 PetscErrorCode ierr; 156 PetscInt j,n = sp->n,N; 157 Vec l = vec; 158 159 PetscFunctionBegin; 160 PetscValidHeaderSpecific(sp,MAT_NULLSPACE_COOKIE,1); 161 PetscValidHeaderSpecific(vec,VEC_COOKIE,2); 162 163 if (out) { 164 PetscValidPointer(out,3); 165 if (!sp->vec) { 166 ierr = VecDuplicate(vec,&sp->vec);CHKERRQ(ierr); 167 } 168 *out = sp->vec; 169 ierr = VecCopy(vec,*out);CHKERRQ(ierr); 170 l = *out; 171 } 172 173 if (sp->has_cnst) { 174 ierr = VecSum(l,&sum);CHKERRQ(ierr); 175 ierr = VecGetSize(l,&N);CHKERRQ(ierr); 176 sum = sum/(-1.0*N); 177 ierr = VecShift(l,sum);CHKERRQ(ierr); 178 } 179 180 for (j=0; j<n; j++) { 181 ierr = VecDot(l,sp->vecs[j],&sum);CHKERRQ(ierr); 182 ierr = VecAXPY(l,-sum,sp->vecs[j]);CHKERRQ(ierr); 183 } 184 185 if (sp->remove){ 186 ierr = (*sp->remove)(l); 187 } 188 PetscFunctionReturn(0); 189 } 190 191 #undef __FUNCT__ 192 #define __FUNCT__ "MatNullSpaceTest" 193 /*@ 194 MatNullSpaceTest - Tests if the claimed null space is really a 195 null space of a matrix 196 197 Collective on MatNullSpace 198 199 Input Parameters: 200 + sp - the null space context 201 - mat - the matrix 202 203 Level: advanced 204 205 .keywords: PC, null space, remove 206 207 .seealso: MatNullSpaceCreate(), MatNullSpaceDestroy(), MatNullSpaceSetFunction() 208 @*/ 209 PetscErrorCode PETSCMAT_DLLEXPORT MatNullSpaceTest(MatNullSpace sp,Mat mat) 210 { 211 PetscScalar sum; 212 PetscReal nrm; 213 PetscInt j,n = sp->n,N,m; 214 PetscErrorCode ierr; 215 Vec l,r; 216 MPI_Comm comm = sp->comm; 217 PetscTruth flg1,flg2; 218 219 PetscFunctionBegin; 220 ierr = PetscOptionsHasName(PETSC_NULL,"-mat_null_space_test_view",&flg1);CHKERRQ(ierr); 221 ierr = PetscOptionsHasName(PETSC_NULL,"-mat_null_space_test_view_draw",&flg2);CHKERRQ(ierr); 222 223 if (!sp->vec) { 224 if (n) { 225 ierr = VecDuplicate(sp->vecs[0],&sp->vec);CHKERRQ(ierr); 226 } else { 227 ierr = MatGetLocalSize(mat,&m,PETSC_NULL);CHKERRQ(ierr); 228 ierr = VecCreateMPI(sp->comm,m,PETSC_DETERMINE,&sp->vec);CHKERRQ(ierr); 229 } 230 } 231 l = sp->vec; 232 233 if (sp->has_cnst) { 234 ierr = VecDuplicate(l,&r);CHKERRQ(ierr); 235 ierr = VecGetSize(l,&N);CHKERRQ(ierr); 236 sum = 1.0/N; 237 ierr = VecSet(l,sum);CHKERRQ(ierr); 238 ierr = MatMult(mat,l,r);CHKERRQ(ierr); 239 ierr = VecNorm(r,NORM_2,&nrm);CHKERRQ(ierr); 240 if (nrm < 1.e-7) {ierr = PetscPrintf(comm,"Constants are likely null vector");CHKERRQ(ierr);} 241 else {ierr = PetscPrintf(comm,"Constants are unlikely null vector ");CHKERRQ(ierr);} 242 ierr = PetscPrintf(comm,"|| A * 1 || = %g\n",nrm);CHKERRQ(ierr); 243 if (nrm > 1.e-7 && flg1) {ierr = VecView(r,PETSC_VIEWER_STDOUT_(comm));CHKERRQ(ierr);} 244 if (nrm > 1.e-7 && flg2) {ierr = VecView(r,PETSC_VIEWER_DRAW_(comm));CHKERRQ(ierr);} 245 ierr = VecDestroy(r);CHKERRQ(ierr); 246 } 247 248 for (j=0; j<n; j++) { 249 ierr = (*mat->ops->mult)(mat,sp->vecs[j],l);CHKERRQ(ierr); 250 ierr = VecNorm(l,NORM_2,&nrm);CHKERRQ(ierr); 251 if (nrm < 1.e-7) {ierr = PetscPrintf(comm,"Null vector %D is likely null vector",j);CHKERRQ(ierr);} 252 else {ierr = PetscPrintf(comm,"Null vector %D unlikely null vector ",j);CHKERRQ(ierr);} 253 ierr = PetscPrintf(comm,"|| A * v[%D] || = %g\n",j,nrm);CHKERRQ(ierr); 254 if (nrm > 1.e-7 && flg1) {ierr = VecView(l,PETSC_VIEWER_STDOUT_(comm));CHKERRQ(ierr);} 255 if (nrm > 1.e-7 && flg2) {ierr = VecView(l,PETSC_VIEWER_DRAW_(comm));CHKERRQ(ierr);} 256 } 257 258 if (sp->remove){ 259 SETERRQ(PETSC_ERR_SUP,"Cannot test a null space provided as a function with MatNullSpaceSetFunction()"); 260 } 261 262 PetscFunctionReturn(0); 263 } 264 265