xref: /petsc/src/mat/interface/matnull.c (revision 3050cee28ff83b093d983d7c5197e87b438ca09b)
1be1d678aSKris Buschelman #define PETSCMAT_DLL
2be1d678aSKris Buschelman 
3f7765cecSBarry Smith /*
4b4fd4287SBarry Smith     Routines to project vectors out of null spaces.
5f7765cecSBarry Smith */
6f7765cecSBarry Smith 
7b9147fbbSdalcinl #include "include/private/matimpl.h"      /*I "petscmat.h" I*/
8e090d566SSatish Balay #include "petscsys.h"
9f7765cecSBarry Smith 
10be1d678aSKris Buschelman PetscCookie PETSCMAT_DLLEXPORT MAT_NULLSPACE_COOKIE = 0;
118ba1e511SMatthew Knepley 
124a2ae208SSatish Balay #undef __FUNCT__
1372875594SBarry Smith #define __FUNCT__ "MatNullSpaceSetFunction"
1472875594SBarry Smith /*@C
1572875594SBarry Smith    MatNullSpaceSetFunction - set a function that removes a null space from a vector
1672875594SBarry Smith    out of null spaces.
1772875594SBarry Smith 
1872875594SBarry Smith    Collective on MatNullSpace
1972875594SBarry Smith 
2072875594SBarry Smith    Input Parameters:
2172875594SBarry Smith +  sp - the null space object
229dbe9a8aSBarry Smith .  rem - the function that removes the null space
239dbe9a8aSBarry Smith -  ctx - context for the remove function
2472875594SBarry Smith 
25658c74aaSSatish Balay    Level: advanced
2672875594SBarry Smith 
27658c74aaSSatish Balay .keywords: PC, null space, create
28b47fd4b1SSatish Balay 
2972875594SBarry Smith .seealso: MatNullSpaceDestroy(), MatNullSpaceRemove(), KSPSetNullSpace(), MatNullSpace, MatNullSpaceCreate()
3072875594SBarry Smith @*/
319dbe9a8aSBarry Smith PetscErrorCode PETSCMAT_DLLEXPORT MatNullSpaceSetFunction(MatNullSpace sp, PetscErrorCode (*rem)(Vec,void*),void *ctx)
3272875594SBarry Smith {
3372875594SBarry Smith   PetscFunctionBegin;
349dbe9a8aSBarry Smith   sp->remove = rem;
359dbe9a8aSBarry Smith   sp->rmctx  = ctx;
3672875594SBarry Smith   PetscFunctionReturn(0);
3772875594SBarry Smith }
3872875594SBarry Smith 
3972875594SBarry Smith #undef __FUNCT__
404a2ae208SSatish Balay #define __FUNCT__ "MatNullSpaceCreate"
41f39d8e23SSatish Balay /*@
425cfeda75SBarry Smith    MatNullSpaceCreate - Creates a data structure used to project vectors
43b4fd4287SBarry Smith    out of null spaces.
44f7765cecSBarry Smith 
454e472627SLois Curfman McInnes    Collective on MPI_Comm
464e472627SLois Curfman McInnes 
47f7765cecSBarry Smith    Input Parameters:
4883c3bef8SLois Curfman McInnes +  comm - the MPI communicator associated with the object
4983c3bef8SLois Curfman McInnes .  has_cnst - PETSC_TRUE if the null space contains the constant vector; otherwise PETSC_FALSE
50b4fd4287SBarry Smith .  n - number of vectors (excluding constant vector) in null space
5183c3bef8SLois Curfman McInnes -  vecs - the vectors that span the null space (excluding the constant vector);
52f7a9e4ceSBarry Smith           these vectors must be orthonormal. These vectors are NOT copied, so do not change them
53f7a9e4ceSBarry Smith           after this call. You should free the array that you pass in.
54f7765cecSBarry Smith 
55f7765cecSBarry Smith    Output Parameter:
56b4fd4287SBarry Smith .  SP - the null space context
57f7765cecSBarry Smith 
5883c3bef8SLois Curfman McInnes    Level: advanced
5983c3bef8SLois Curfman McInnes 
606e1639daSBarry Smith   Users manual sections:
616e1639daSBarry Smith .   sec_singular
626e1639daSBarry Smith 
6383c3bef8SLois Curfman McInnes .keywords: PC, null space, create
6441a59933SSatish Balay 
6572875594SBarry Smith .seealso: MatNullSpaceDestroy(), MatNullSpaceRemove(), KSPSetNullSpace(), MatNullSpace, MatNullSpaceSetFunction()
66f7765cecSBarry Smith @*/
67be1d678aSKris Buschelman PetscErrorCode PETSCMAT_DLLEXPORT MatNullSpaceCreate(MPI_Comm comm,PetscTruth has_cnst,PetscInt n,const Vec vecs[],MatNullSpace *SP)
68f7765cecSBarry Smith {
695cfeda75SBarry Smith   MatNullSpace   sp;
70dfbe8321SBarry Smith   PetscErrorCode ierr;
71c1ac3661SBarry Smith   PetscInt       i;
72f7765cecSBarry Smith 
733a40ed3dSBarry Smith   PetscFunctionBegin;
74574b3360SMatthew Knepley   if (n) PetscValidPointer(vecs,4);
75574b3360SMatthew Knepley   for (i=0; i<n; i++) PetscValidHeaderSpecific(vecs[i],VEC_COOKIE,4);
76574b3360SMatthew Knepley   PetscValidPointer(SP,5);
77574b3360SMatthew Knepley 
78574b3360SMatthew Knepley   *SP = PETSC_NULL;
79574b3360SMatthew Knepley #ifndef PETSC_USE_DYNAMIC_LIBRARIES
80574b3360SMatthew Knepley   ierr = MatInitializePackage(PETSC_NULL);CHKERRQ(ierr);
81574b3360SMatthew Knepley #endif
82574b3360SMatthew Knepley 
8352e6d16bSBarry Smith   ierr = PetscHeaderCreate(sp,_p_MatNullSpace,int,MAT_NULLSPACE_COOKIE,0,"MatNullSpace",comm,MatNullSpaceDestroy,0);CHKERRQ(ierr);
8452e6d16bSBarry Smith   ierr = PetscLogObjectMemory(sp,sizeof(struct _p_MatNullSpace));CHKERRQ(ierr);
85f7765cecSBarry Smith 
86b4fd4287SBarry Smith   sp->has_cnst = has_cnst;
87b4fd4287SBarry Smith   sp->n        = n;
885cfeda75SBarry Smith   sp->vec      = PETSC_NULL;
89f7a9e4ceSBarry Smith   if (n) {
90f7a9e4ceSBarry Smith     ierr = PetscMalloc(n*sizeof(Vec),&sp->vecs);CHKERRQ(ierr);
91f7a9e4ceSBarry Smith     for (i=0; i<n; i++) sp->vecs[i] = vecs[i];
92f7a9e4ceSBarry Smith   } else {
93f7a9e4ceSBarry Smith     sp->vecs = 0;
94f7a9e4ceSBarry Smith   }
95b4fd4287SBarry Smith 
96f7a9e4ceSBarry Smith   for (i=0; i<n; i++) {
97f7a9e4ceSBarry Smith     ierr = PetscObjectReference((PetscObject)sp->vecs[i]);CHKERRQ(ierr);
98f7a9e4ceSBarry Smith   }
99b4fd4287SBarry Smith   *SP          = sp;
1003a40ed3dSBarry Smith   PetscFunctionReturn(0);
101f7765cecSBarry Smith }
102f7765cecSBarry Smith 
1034a2ae208SSatish Balay #undef __FUNCT__
1044a2ae208SSatish Balay #define __FUNCT__ "MatNullSpaceDestroy"
105f7765cecSBarry Smith /*@
1065cfeda75SBarry Smith    MatNullSpaceDestroy - Destroys a data structure used to project vectors
107b4fd4287SBarry Smith    out of null spaces.
108b4fd4287SBarry Smith 
1095cfeda75SBarry Smith    Collective on MatNullSpace
1104e472627SLois Curfman McInnes 
111b4fd4287SBarry Smith    Input Parameter:
112b9756687SLois Curfman McInnes .  sp - the null space context to be destroyed
113b9756687SLois Curfman McInnes 
114b9756687SLois Curfman McInnes    Level: advanced
115b4fd4287SBarry Smith 
11683c3bef8SLois Curfman McInnes .keywords: PC, null space, destroy
11741a59933SSatish Balay 
11872875594SBarry Smith .seealso: MatNullSpaceCreate(), MatNullSpaceRemove(), MatNullSpaceSetFunction()
119b4fd4287SBarry Smith @*/
120be1d678aSKris Buschelman PetscErrorCode PETSCMAT_DLLEXPORT MatNullSpaceDestroy(MatNullSpace sp)
121b4fd4287SBarry Smith {
122dfbe8321SBarry Smith   PetscErrorCode ierr;
12385614651SBarry Smith 
1245cfeda75SBarry Smith   PetscFunctionBegin;
12585614651SBarry Smith   if (--sp->refct > 0) PetscFunctionReturn(0);
12685614651SBarry Smith 
1275cfeda75SBarry Smith   if (sp->vec) {ierr = VecDestroy(sp->vec);CHKERRQ(ierr);}
128f7a9e4ceSBarry Smith   if (sp->vecs) {
129f7a9e4ceSBarry Smith     ierr = VecDestroyVecs(sp->vecs,sp->n);CHKERRQ(ierr);
130f7a9e4ceSBarry Smith   }
131d38fa0fbSBarry Smith   ierr = PetscHeaderDestroy(sp);CHKERRQ(ierr);
1323a40ed3dSBarry Smith   PetscFunctionReturn(0);
133b4fd4287SBarry Smith }
134b4fd4287SBarry Smith 
1354a2ae208SSatish Balay #undef __FUNCT__
1364a2ae208SSatish Balay #define __FUNCT__ "MatNullSpaceRemove"
137b4fd4287SBarry Smith /*@
1385cfeda75SBarry Smith    MatNullSpaceRemove - Removes all the components of a null space from a vector.
139f7765cecSBarry Smith 
1405cfeda75SBarry Smith    Collective on MatNullSpace
141f7765cecSBarry Smith 
1424e472627SLois Curfman McInnes    Input Parameters:
1434e472627SLois Curfman McInnes +  sp - the null space context
1444e7234bfSBarry Smith .  vec - the vector from which the null space is to be removed
1455fcf39f4SBarry Smith -  out - if this is requested (not PETSC_NULL) then this is a vector with the null space removed otherwise
1464e7234bfSBarry Smith          the removal is done in-place (in vec)
1474e7234bfSBarry Smith 
148db090513SMatthew Knepley    Note: The user is not responsible for the vector returned and should not destroy it.
1494e472627SLois Curfman McInnes 
150b9756687SLois Curfman McInnes    Level: advanced
151b9756687SLois Curfman McInnes 
15283c3bef8SLois Curfman McInnes .keywords: PC, null space, remove
15341a59933SSatish Balay 
15472875594SBarry Smith .seealso: MatNullSpaceCreate(), MatNullSpaceDestroy(), MatNullSpaceSetFunction()
155f7765cecSBarry Smith @*/
156be1d678aSKris Buschelman PetscErrorCode PETSCMAT_DLLEXPORT MatNullSpaceRemove(MatNullSpace sp,Vec vec,Vec *out)
157f7765cecSBarry Smith {
15887828ca2SBarry Smith   PetscScalar    sum;
1596849ba73SBarry Smith   PetscErrorCode ierr;
160c1ac3661SBarry Smith   PetscInt       j,n = sp->n,N;
1615cfeda75SBarry Smith   Vec            l = vec;
162f7765cecSBarry Smith 
1633a40ed3dSBarry Smith   PetscFunctionBegin;
1643cd8ff7eSMatthew Knepley   PetscValidHeaderSpecific(sp,MAT_NULLSPACE_COOKIE,1);
1653cd8ff7eSMatthew Knepley   PetscValidHeaderSpecific(vec,VEC_COOKIE,2);
1663cd8ff7eSMatthew Knepley 
1675cfeda75SBarry Smith   if (out) {
1683cd8ff7eSMatthew Knepley     PetscValidPointer(out,3);
1695cfeda75SBarry Smith     if (!sp->vec) {
1705cfeda75SBarry Smith       ierr = VecDuplicate(vec,&sp->vec);CHKERRQ(ierr);
1715cfeda75SBarry Smith     }
1725cfeda75SBarry Smith     *out = sp->vec;
1735cfeda75SBarry Smith     ierr = VecCopy(vec,*out);CHKERRQ(ierr);
1745cfeda75SBarry Smith     l    = *out;
1755cfeda75SBarry Smith   }
1765cfeda75SBarry Smith 
177b4fd4287SBarry Smith   if (sp->has_cnst) {
1785cfeda75SBarry Smith     ierr = VecSum(l,&sum);CHKERRQ(ierr);
1795cfeda75SBarry Smith     ierr = VecGetSize(l,&N);CHKERRQ(ierr);
18018a7d68fSSatish Balay     sum  = sum/(-1.0*N);
1812dcb1b2aSMatthew Knepley     ierr = VecShift(l,sum);CHKERRQ(ierr);
182f7765cecSBarry Smith   }
183b4fd4287SBarry Smith 
184b4fd4287SBarry Smith   for (j=0; j<n; j++) {
1855cfeda75SBarry Smith     ierr = VecDot(l,sp->vecs[j],&sum);CHKERRQ(ierr);
1865eb3c597SBarry Smith     ierr = VecAXPY(l,-sum,sp->vecs[j]);CHKERRQ(ierr);
187f7765cecSBarry Smith   }
188b4fd4287SBarry Smith 
18972875594SBarry Smith   if (sp->remove){
190ce0145b1SBarry Smith     ierr = (*sp->remove)(l,sp->rmctx);
19172875594SBarry Smith   }
1923a40ed3dSBarry Smith   PetscFunctionReturn(0);
193f7765cecSBarry Smith }
194a2e34c3dSBarry Smith 
1954a2ae208SSatish Balay #undef __FUNCT__
1964a2ae208SSatish Balay #define __FUNCT__ "MatNullSpaceTest"
197a2e34c3dSBarry Smith /*@
198a2e34c3dSBarry Smith    MatNullSpaceTest  - Tests if the claimed null space is really a
199a2e34c3dSBarry Smith      null space of a matrix
200a2e34c3dSBarry Smith 
201a2e34c3dSBarry Smith    Collective on MatNullSpace
202a2e34c3dSBarry Smith 
203a2e34c3dSBarry Smith    Input Parameters:
204a2e34c3dSBarry Smith +  sp - the null space context
205a2e34c3dSBarry Smith -  mat - the matrix
206a2e34c3dSBarry Smith 
207a2e34c3dSBarry Smith    Level: advanced
208a2e34c3dSBarry Smith 
209a2e34c3dSBarry Smith .keywords: PC, null space, remove
210a2e34c3dSBarry Smith 
21172875594SBarry Smith .seealso: MatNullSpaceCreate(), MatNullSpaceDestroy(), MatNullSpaceSetFunction()
212a2e34c3dSBarry Smith @*/
213be1d678aSKris Buschelman PetscErrorCode PETSCMAT_DLLEXPORT MatNullSpaceTest(MatNullSpace sp,Mat mat)
214a2e34c3dSBarry Smith {
21587828ca2SBarry Smith   PetscScalar    sum;
2168bb6bcc5SSatish Balay   PetscReal      nrm;
217c1ac3661SBarry Smith   PetscInt       j,n = sp->n,N,m;
2186849ba73SBarry Smith   PetscErrorCode ierr;
219a2e34c3dSBarry Smith   Vec            l,r;
220a2e34c3dSBarry Smith   MPI_Comm       comm = sp->comm;
221a2e34c3dSBarry Smith   PetscTruth     flg1,flg2;
222*3050cee2SBarry Smith   PetscViewer    viewer;
223a2e34c3dSBarry Smith 
224a2e34c3dSBarry Smith   PetscFunctionBegin;
225b0a32e0cSBarry Smith   ierr = PetscOptionsHasName(PETSC_NULL,"-mat_null_space_test_view",&flg1);CHKERRQ(ierr);
226b0a32e0cSBarry Smith   ierr = PetscOptionsHasName(PETSC_NULL,"-mat_null_space_test_view_draw",&flg2);CHKERRQ(ierr);
227a2e34c3dSBarry Smith 
228a2e34c3dSBarry Smith   if (!sp->vec) {
229a2e34c3dSBarry Smith     if (n) {
230a2e34c3dSBarry Smith       ierr = VecDuplicate(sp->vecs[0],&sp->vec);CHKERRQ(ierr);
231a2e34c3dSBarry Smith     } else {
232a2e34c3dSBarry Smith       ierr = MatGetLocalSize(mat,&m,PETSC_NULL);CHKERRQ(ierr);
233a2e34c3dSBarry Smith       ierr = VecCreateMPI(sp->comm,m,PETSC_DETERMINE,&sp->vec);CHKERRQ(ierr);
234a2e34c3dSBarry Smith     }
235a2e34c3dSBarry Smith   }
236a2e34c3dSBarry Smith   l    = sp->vec;
237a2e34c3dSBarry Smith 
238*3050cee2SBarry Smith   ierr = PetscViewerASCIIGetStdout(comm,&viewer);CHKERRQ(ierr);
239a2e34c3dSBarry Smith   if (sp->has_cnst) {
240a2e34c3dSBarry Smith     ierr = VecDuplicate(l,&r);CHKERRQ(ierr);
241a2e34c3dSBarry Smith     ierr = VecGetSize(l,&N);CHKERRQ(ierr);
242a2e34c3dSBarry Smith     sum  = 1.0/N;
2432dcb1b2aSMatthew Knepley     ierr = VecSet(l,sum);CHKERRQ(ierr);
244a2e34c3dSBarry Smith     ierr = MatMult(mat,l,r);CHKERRQ(ierr);
2458bb6bcc5SSatish Balay     ierr = VecNorm(r,NORM_2,&nrm);CHKERRQ(ierr);
2468bb6bcc5SSatish Balay     if (nrm < 1.e-7) {ierr = PetscPrintf(comm,"Constants are likely null vector");CHKERRQ(ierr);}
247a2e34c3dSBarry Smith     else {ierr = PetscPrintf(comm,"Constants are unlikely null vector ");CHKERRQ(ierr);}
248a83599f4SBarry Smith     ierr = PetscPrintf(comm,"|| A * 1 || = %G\n",nrm);CHKERRQ(ierr);
249*3050cee2SBarry Smith     if (nrm > 1.e-7 && flg1) {ierr = VecView(r,viewer);CHKERRQ(ierr);}
250*3050cee2SBarry Smith     if (nrm > 1.e-7 && flg2) {ierr = VecView(r,viewer);CHKERRQ(ierr);}
251a2e34c3dSBarry Smith     ierr = VecDestroy(r);CHKERRQ(ierr);
252a2e34c3dSBarry Smith   }
253a2e34c3dSBarry Smith 
254a2e34c3dSBarry Smith   for (j=0; j<n; j++) {
255a2e34c3dSBarry Smith     ierr = (*mat->ops->mult)(mat,sp->vecs[j],l);CHKERRQ(ierr);
2568bb6bcc5SSatish Balay     ierr = VecNorm(l,NORM_2,&nrm);CHKERRQ(ierr);
25777431f27SBarry Smith     if (nrm < 1.e-7) {ierr = PetscPrintf(comm,"Null vector %D is likely null vector",j);CHKERRQ(ierr);}
25877431f27SBarry Smith     else {ierr = PetscPrintf(comm,"Null vector %D unlikely null vector ",j);CHKERRQ(ierr);}
259a83599f4SBarry Smith     ierr = PetscPrintf(comm,"|| A * v[%D] || = %G\n",j,nrm);CHKERRQ(ierr);
260*3050cee2SBarry Smith     if (nrm > 1.e-7 && flg1) {ierr = VecView(l,viewer);CHKERRQ(ierr);}
261*3050cee2SBarry Smith     if (nrm > 1.e-7 && flg2) {ierr = VecView(l,viewer);CHKERRQ(ierr);}
262a2e34c3dSBarry Smith   }
263a2e34c3dSBarry Smith 
26472875594SBarry Smith   if (sp->remove){
26572875594SBarry Smith     SETERRQ(PETSC_ERR_SUP,"Cannot test a null space provided as a function with MatNullSpaceSetFunction()");
26672875594SBarry Smith   }
26772875594SBarry Smith 
268a2e34c3dSBarry Smith   PetscFunctionReturn(0);
269a2e34c3dSBarry Smith }
270a2e34c3dSBarry Smith 
271