xref: /petsc/src/mat/interface/matnull.c (revision 9dbe9a8af344963313994f68cc3773a4cdb856f3)
1be1d678aSKris Buschelman #define PETSCMAT_DLL
2be1d678aSKris Buschelman 
3f7765cecSBarry Smith /*
4b4fd4287SBarry Smith     Routines to project vectors out of null spaces.
5f7765cecSBarry Smith */
6f7765cecSBarry Smith 
75cfeda75SBarry Smith #include "src/mat/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
22*9dbe9a8aSBarry Smith .  rem - the function that removes the null space
23*9dbe9a8aSBarry Smith -  ctx - context for the remove function
2472875594SBarry Smith 
2572875594SBarry Smith .keywords: PC, null space, create
2672875594SBarry Smith 
2772875594SBarry Smith .seealso: MatNullSpaceDestroy(), MatNullSpaceRemove(), KSPSetNullSpace(), MatNullSpace, MatNullSpaceCreate()
2872875594SBarry Smith @*/
29*9dbe9a8aSBarry Smith PetscErrorCode PETSCMAT_DLLEXPORT MatNullSpaceSetFunction(MatNullSpace sp, PetscErrorCode (*rem)(Vec,void*),void *ctx)
3072875594SBarry Smith {
3172875594SBarry Smith   PetscFunctionBegin;
32*9dbe9a8aSBarry Smith   sp->remove = rem;
33*9dbe9a8aSBarry Smith   sp->rmctx  = ctx;
3472875594SBarry Smith   PetscFunctionReturn(0);
3572875594SBarry Smith }
3672875594SBarry Smith 
3772875594SBarry Smith #undef __FUNCT__
384a2ae208SSatish Balay #define __FUNCT__ "MatNullSpaceCreate"
39f39d8e23SSatish Balay /*@
405cfeda75SBarry Smith    MatNullSpaceCreate - Creates a data structure used to project vectors
41b4fd4287SBarry Smith    out of null spaces.
42f7765cecSBarry Smith 
434e472627SLois Curfman McInnes    Collective on MPI_Comm
444e472627SLois Curfman McInnes 
45f7765cecSBarry Smith    Input Parameters:
4683c3bef8SLois Curfman McInnes +  comm - the MPI communicator associated with the object
4783c3bef8SLois Curfman McInnes .  has_cnst - PETSC_TRUE if the null space contains the constant vector; otherwise PETSC_FALSE
48b4fd4287SBarry Smith .  n - number of vectors (excluding constant vector) in null space
4983c3bef8SLois Curfman McInnes -  vecs - the vectors that span the null space (excluding the constant vector);
50f7a9e4ceSBarry Smith           these vectors must be orthonormal. These vectors are NOT copied, so do not change them
51f7a9e4ceSBarry Smith           after this call. You should free the array that you pass in.
52f7765cecSBarry Smith 
53f7765cecSBarry Smith    Output Parameter:
54b4fd4287SBarry Smith .  SP - the null space context
55f7765cecSBarry Smith 
5683c3bef8SLois Curfman McInnes    Level: advanced
5783c3bef8SLois Curfman McInnes 
586e1639daSBarry Smith   Users manual sections:
596e1639daSBarry Smith .   sec_singular
606e1639daSBarry Smith 
6183c3bef8SLois Curfman McInnes .keywords: PC, null space, create
6241a59933SSatish Balay 
6372875594SBarry Smith .seealso: MatNullSpaceDestroy(), MatNullSpaceRemove(), KSPSetNullSpace(), MatNullSpace, MatNullSpaceSetFunction()
64f7765cecSBarry Smith @*/
65be1d678aSKris Buschelman PetscErrorCode PETSCMAT_DLLEXPORT MatNullSpaceCreate(MPI_Comm comm,PetscTruth has_cnst,PetscInt n,const Vec vecs[],MatNullSpace *SP)
66f7765cecSBarry Smith {
675cfeda75SBarry Smith   MatNullSpace   sp;
68dfbe8321SBarry Smith   PetscErrorCode ierr;
69c1ac3661SBarry Smith   PetscInt       i;
70f7765cecSBarry Smith 
713a40ed3dSBarry Smith   PetscFunctionBegin;
72574b3360SMatthew Knepley   if (n) PetscValidPointer(vecs,4);
73574b3360SMatthew Knepley   for (i=0; i<n; i++) PetscValidHeaderSpecific(vecs[i],VEC_COOKIE,4);
74574b3360SMatthew Knepley   PetscValidPointer(SP,5);
75574b3360SMatthew Knepley 
76574b3360SMatthew Knepley   *SP = PETSC_NULL;
77574b3360SMatthew Knepley #ifndef PETSC_USE_DYNAMIC_LIBRARIES
78574b3360SMatthew Knepley   ierr = MatInitializePackage(PETSC_NULL);CHKERRQ(ierr);
79574b3360SMatthew Knepley #endif
80574b3360SMatthew Knepley 
8152e6d16bSBarry Smith   ierr = PetscHeaderCreate(sp,_p_MatNullSpace,int,MAT_NULLSPACE_COOKIE,0,"MatNullSpace",comm,MatNullSpaceDestroy,0);CHKERRQ(ierr);
8252e6d16bSBarry Smith   ierr = PetscLogObjectMemory(sp,sizeof(struct _p_MatNullSpace));CHKERRQ(ierr);
83f7765cecSBarry Smith 
84b4fd4287SBarry Smith   sp->has_cnst = has_cnst;
85b4fd4287SBarry Smith   sp->n        = n;
865cfeda75SBarry Smith   sp->vec      = PETSC_NULL;
87f7a9e4ceSBarry Smith   if (n) {
88f7a9e4ceSBarry Smith     ierr = PetscMalloc(n*sizeof(Vec),&sp->vecs);CHKERRQ(ierr);
89f7a9e4ceSBarry Smith     for (i=0; i<n; i++) sp->vecs[i] = vecs[i];
90f7a9e4ceSBarry Smith   } else {
91f7a9e4ceSBarry Smith     sp->vecs = 0;
92f7a9e4ceSBarry Smith   }
93b4fd4287SBarry Smith 
94f7a9e4ceSBarry Smith   for (i=0; i<n; i++) {
95f7a9e4ceSBarry Smith     ierr = PetscObjectReference((PetscObject)sp->vecs[i]);CHKERRQ(ierr);
96f7a9e4ceSBarry Smith   }
97b4fd4287SBarry Smith   *SP          = sp;
983a40ed3dSBarry Smith   PetscFunctionReturn(0);
99f7765cecSBarry Smith }
100f7765cecSBarry Smith 
1014a2ae208SSatish Balay #undef __FUNCT__
1024a2ae208SSatish Balay #define __FUNCT__ "MatNullSpaceDestroy"
103f7765cecSBarry Smith /*@
1045cfeda75SBarry Smith    MatNullSpaceDestroy - Destroys a data structure used to project vectors
105b4fd4287SBarry Smith    out of null spaces.
106b4fd4287SBarry Smith 
1075cfeda75SBarry Smith    Collective on MatNullSpace
1084e472627SLois Curfman McInnes 
109b4fd4287SBarry Smith    Input Parameter:
110b9756687SLois Curfman McInnes .  sp - the null space context to be destroyed
111b9756687SLois Curfman McInnes 
112b9756687SLois Curfman McInnes    Level: advanced
113b4fd4287SBarry Smith 
11483c3bef8SLois Curfman McInnes .keywords: PC, null space, destroy
11541a59933SSatish Balay 
11672875594SBarry Smith .seealso: MatNullSpaceCreate(), MatNullSpaceRemove(), MatNullSpaceSetFunction()
117b4fd4287SBarry Smith @*/
118be1d678aSKris Buschelman PetscErrorCode PETSCMAT_DLLEXPORT MatNullSpaceDestroy(MatNullSpace sp)
119b4fd4287SBarry Smith {
120dfbe8321SBarry Smith   PetscErrorCode ierr;
12185614651SBarry Smith 
1225cfeda75SBarry Smith   PetscFunctionBegin;
12385614651SBarry Smith   if (--sp->refct > 0) PetscFunctionReturn(0);
12485614651SBarry Smith 
1255cfeda75SBarry Smith   if (sp->vec) {ierr = VecDestroy(sp->vec);CHKERRQ(ierr);}
126f7a9e4ceSBarry Smith   if (sp->vecs) {
127f7a9e4ceSBarry Smith     ierr = VecDestroyVecs(sp->vecs,sp->n);CHKERRQ(ierr);
128f7a9e4ceSBarry Smith   }
129d38fa0fbSBarry Smith   ierr = PetscHeaderDestroy(sp);CHKERRQ(ierr);
1303a40ed3dSBarry Smith   PetscFunctionReturn(0);
131b4fd4287SBarry Smith }
132b4fd4287SBarry Smith 
1334a2ae208SSatish Balay #undef __FUNCT__
1344a2ae208SSatish Balay #define __FUNCT__ "MatNullSpaceRemove"
135b4fd4287SBarry Smith /*@
1365cfeda75SBarry Smith    MatNullSpaceRemove - Removes all the components of a null space from a vector.
137f7765cecSBarry Smith 
1385cfeda75SBarry Smith    Collective on MatNullSpace
139f7765cecSBarry Smith 
1404e472627SLois Curfman McInnes    Input Parameters:
1414e472627SLois Curfman McInnes +  sp - the null space context
1424e7234bfSBarry Smith .  vec - the vector from which the null space is to be removed
1435fcf39f4SBarry Smith -  out - if this is requested (not PETSC_NULL) then this is a vector with the null space removed otherwise
1444e7234bfSBarry Smith          the removal is done in-place (in vec)
1454e7234bfSBarry Smith 
146db090513SMatthew Knepley    Note: The user is not responsible for the vector returned and should not destroy it.
1474e472627SLois Curfman McInnes 
148b9756687SLois Curfman McInnes    Level: advanced
149b9756687SLois Curfman McInnes 
15083c3bef8SLois Curfman McInnes .keywords: PC, null space, remove
15141a59933SSatish Balay 
15272875594SBarry Smith .seealso: MatNullSpaceCreate(), MatNullSpaceDestroy(), MatNullSpaceSetFunction()
153f7765cecSBarry Smith @*/
154be1d678aSKris Buschelman PetscErrorCode PETSCMAT_DLLEXPORT MatNullSpaceRemove(MatNullSpace sp,Vec vec,Vec *out)
155f7765cecSBarry Smith {
15687828ca2SBarry Smith   PetscScalar    sum;
1576849ba73SBarry Smith   PetscErrorCode ierr;
158c1ac3661SBarry Smith   PetscInt       j,n = sp->n,N;
1595cfeda75SBarry Smith   Vec            l = vec;
160f7765cecSBarry Smith 
1613a40ed3dSBarry Smith   PetscFunctionBegin;
1623cd8ff7eSMatthew Knepley   PetscValidHeaderSpecific(sp,MAT_NULLSPACE_COOKIE,1);
1633cd8ff7eSMatthew Knepley   PetscValidHeaderSpecific(vec,VEC_COOKIE,2);
1643cd8ff7eSMatthew Knepley 
1655cfeda75SBarry Smith   if (out) {
1663cd8ff7eSMatthew Knepley     PetscValidPointer(out,3);
1675cfeda75SBarry Smith     if (!sp->vec) {
1685cfeda75SBarry Smith       ierr = VecDuplicate(vec,&sp->vec);CHKERRQ(ierr);
1695cfeda75SBarry Smith     }
1705cfeda75SBarry Smith     *out = sp->vec;
1715cfeda75SBarry Smith     ierr = VecCopy(vec,*out);CHKERRQ(ierr);
1725cfeda75SBarry Smith     l    = *out;
1735cfeda75SBarry Smith   }
1745cfeda75SBarry Smith 
175b4fd4287SBarry Smith   if (sp->has_cnst) {
1765cfeda75SBarry Smith     ierr = VecSum(l,&sum);CHKERRQ(ierr);
1775cfeda75SBarry Smith     ierr = VecGetSize(l,&N);CHKERRQ(ierr);
17818a7d68fSSatish Balay     sum  = sum/(-1.0*N);
1792dcb1b2aSMatthew Knepley     ierr = VecShift(l,sum);CHKERRQ(ierr);
180f7765cecSBarry Smith   }
181b4fd4287SBarry Smith 
182b4fd4287SBarry Smith   for (j=0; j<n; j++) {
1835cfeda75SBarry Smith     ierr = VecDot(l,sp->vecs[j],&sum);CHKERRQ(ierr);
1845eb3c597SBarry Smith     ierr = VecAXPY(l,-sum,sp->vecs[j]);CHKERRQ(ierr);
185f7765cecSBarry Smith   }
186b4fd4287SBarry Smith 
18772875594SBarry Smith   if (sp->remove){
188ce0145b1SBarry Smith     ierr = (*sp->remove)(l,sp->rmctx);
18972875594SBarry Smith   }
1903a40ed3dSBarry Smith   PetscFunctionReturn(0);
191f7765cecSBarry Smith }
192a2e34c3dSBarry Smith 
1934a2ae208SSatish Balay #undef __FUNCT__
1944a2ae208SSatish Balay #define __FUNCT__ "MatNullSpaceTest"
195a2e34c3dSBarry Smith /*@
196a2e34c3dSBarry Smith    MatNullSpaceTest  - Tests if the claimed null space is really a
197a2e34c3dSBarry Smith      null space of a matrix
198a2e34c3dSBarry Smith 
199a2e34c3dSBarry Smith    Collective on MatNullSpace
200a2e34c3dSBarry Smith 
201a2e34c3dSBarry Smith    Input Parameters:
202a2e34c3dSBarry Smith +  sp - the null space context
203a2e34c3dSBarry Smith -  mat - the matrix
204a2e34c3dSBarry Smith 
205a2e34c3dSBarry Smith    Level: advanced
206a2e34c3dSBarry Smith 
207a2e34c3dSBarry Smith .keywords: PC, null space, remove
208a2e34c3dSBarry Smith 
20972875594SBarry Smith .seealso: MatNullSpaceCreate(), MatNullSpaceDestroy(), MatNullSpaceSetFunction()
210a2e34c3dSBarry Smith @*/
211be1d678aSKris Buschelman PetscErrorCode PETSCMAT_DLLEXPORT MatNullSpaceTest(MatNullSpace sp,Mat mat)
212a2e34c3dSBarry Smith {
21387828ca2SBarry Smith   PetscScalar    sum;
2148bb6bcc5SSatish Balay   PetscReal      nrm;
215c1ac3661SBarry Smith   PetscInt       j,n = sp->n,N,m;
2166849ba73SBarry Smith   PetscErrorCode ierr;
217a2e34c3dSBarry Smith   Vec            l,r;
218a2e34c3dSBarry Smith   MPI_Comm       comm = sp->comm;
219a2e34c3dSBarry Smith   PetscTruth     flg1,flg2;
220a2e34c3dSBarry Smith 
221a2e34c3dSBarry Smith   PetscFunctionBegin;
222b0a32e0cSBarry Smith   ierr = PetscOptionsHasName(PETSC_NULL,"-mat_null_space_test_view",&flg1);CHKERRQ(ierr);
223b0a32e0cSBarry Smith   ierr = PetscOptionsHasName(PETSC_NULL,"-mat_null_space_test_view_draw",&flg2);CHKERRQ(ierr);
224a2e34c3dSBarry Smith 
225a2e34c3dSBarry Smith   if (!sp->vec) {
226a2e34c3dSBarry Smith     if (n) {
227a2e34c3dSBarry Smith       ierr = VecDuplicate(sp->vecs[0],&sp->vec);CHKERRQ(ierr);
228a2e34c3dSBarry Smith     } else {
229a2e34c3dSBarry Smith       ierr = MatGetLocalSize(mat,&m,PETSC_NULL);CHKERRQ(ierr);
230a2e34c3dSBarry Smith       ierr = VecCreateMPI(sp->comm,m,PETSC_DETERMINE,&sp->vec);CHKERRQ(ierr);
231a2e34c3dSBarry Smith     }
232a2e34c3dSBarry Smith   }
233a2e34c3dSBarry Smith   l    = sp->vec;
234a2e34c3dSBarry Smith 
235a2e34c3dSBarry Smith   if (sp->has_cnst) {
236a2e34c3dSBarry Smith     ierr = VecDuplicate(l,&r);CHKERRQ(ierr);
237a2e34c3dSBarry Smith     ierr = VecGetSize(l,&N);CHKERRQ(ierr);
238a2e34c3dSBarry Smith     sum  = 1.0/N;
2392dcb1b2aSMatthew Knepley     ierr = VecSet(l,sum);CHKERRQ(ierr);
240a2e34c3dSBarry Smith     ierr = MatMult(mat,l,r);CHKERRQ(ierr);
2418bb6bcc5SSatish Balay     ierr = VecNorm(r,NORM_2,&nrm);CHKERRQ(ierr);
2428bb6bcc5SSatish Balay     if (nrm < 1.e-7) {ierr = PetscPrintf(comm,"Constants are likely null vector");CHKERRQ(ierr);}
243a2e34c3dSBarry Smith     else {ierr = PetscPrintf(comm,"Constants are unlikely null vector ");CHKERRQ(ierr);}
2448bb6bcc5SSatish Balay     ierr = PetscPrintf(comm,"|| A * 1 || = %g\n",nrm);CHKERRQ(ierr);
245b0a32e0cSBarry Smith     if (nrm > 1.e-7 && flg1) {ierr = VecView(r,PETSC_VIEWER_STDOUT_(comm));CHKERRQ(ierr);}
246b0a32e0cSBarry Smith     if (nrm > 1.e-7 && flg2) {ierr = VecView(r,PETSC_VIEWER_DRAW_(comm));CHKERRQ(ierr);}
247a2e34c3dSBarry Smith     ierr = VecDestroy(r);CHKERRQ(ierr);
248a2e34c3dSBarry Smith   }
249a2e34c3dSBarry Smith 
250a2e34c3dSBarry Smith   for (j=0; j<n; j++) {
251a2e34c3dSBarry Smith     ierr = (*mat->ops->mult)(mat,sp->vecs[j],l);CHKERRQ(ierr);
2528bb6bcc5SSatish Balay     ierr = VecNorm(l,NORM_2,&nrm);CHKERRQ(ierr);
25377431f27SBarry Smith     if (nrm < 1.e-7) {ierr = PetscPrintf(comm,"Null vector %D is likely null vector",j);CHKERRQ(ierr);}
25477431f27SBarry Smith     else {ierr = PetscPrintf(comm,"Null vector %D unlikely null vector ",j);CHKERRQ(ierr);}
25577431f27SBarry Smith     ierr = PetscPrintf(comm,"|| A * v[%D] || = %g\n",j,nrm);CHKERRQ(ierr);
256b0a32e0cSBarry Smith     if (nrm > 1.e-7 && flg1) {ierr = VecView(l,PETSC_VIEWER_STDOUT_(comm));CHKERRQ(ierr);}
257b0a32e0cSBarry Smith     if (nrm > 1.e-7 && flg2) {ierr = VecView(l,PETSC_VIEWER_DRAW_(comm));CHKERRQ(ierr);}
258a2e34c3dSBarry Smith   }
259a2e34c3dSBarry Smith 
26072875594SBarry Smith   if (sp->remove){
26172875594SBarry Smith     SETERRQ(PETSC_ERR_SUP,"Cannot test a null space provided as a function with MatNullSpaceSetFunction()");
26272875594SBarry Smith   }
26372875594SBarry Smith 
264a2e34c3dSBarry Smith   PetscFunctionReturn(0);
265a2e34c3dSBarry Smith }
266a2e34c3dSBarry Smith 
267