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