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