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