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