xref: /petsc/src/ksp/pc/impls/deflation/deflationspace.c (revision 63a3b9bc7a1f24f247904ccba9383635fe6abade)
15170378fSJakub Kruzik #include <../src/ksp/pc/impls/deflation/deflation.h> /*I "petscksp.h" I*/
2e53e0a0dSJakub Kruzik 
3e53e0a0dSJakub Kruzik PetscScalar db2[] = {0.7071067811865476,0.7071067811865476};
4e53e0a0dSJakub Kruzik 
5e53e0a0dSJakub Kruzik PetscScalar db4[] = {-0.12940952255092145,0.22414386804185735,0.836516303737469,0.48296291314469025};
6e53e0a0dSJakub Kruzik 
7e53e0a0dSJakub Kruzik PetscScalar db8[] = {-0.010597401784997278,
8e53e0a0dSJakub Kruzik 0.032883011666982945,
9e53e0a0dSJakub Kruzik 0.030841381835986965,
10e53e0a0dSJakub Kruzik -0.18703481171888114,
11e53e0a0dSJakub Kruzik -0.02798376941698385,
12e53e0a0dSJakub Kruzik 0.6308807679295904,
13e53e0a0dSJakub Kruzik 0.7148465705525415,
14e53e0a0dSJakub Kruzik 0.23037781330885523};
15e53e0a0dSJakub Kruzik 
16e53e0a0dSJakub Kruzik PetscScalar db16[] = {-0.00011747678400228192,
17e53e0a0dSJakub Kruzik 0.0006754494059985568,
18e53e0a0dSJakub Kruzik -0.0003917403729959771,
19e53e0a0dSJakub Kruzik -0.00487035299301066,
20e53e0a0dSJakub Kruzik 0.008746094047015655,
21e53e0a0dSJakub Kruzik 0.013981027917015516,
22e53e0a0dSJakub Kruzik -0.04408825393106472,
23e53e0a0dSJakub Kruzik -0.01736930100202211,
24e53e0a0dSJakub Kruzik 0.128747426620186,
25e53e0a0dSJakub Kruzik 0.00047248457399797254,
26e53e0a0dSJakub Kruzik -0.2840155429624281,
27e53e0a0dSJakub Kruzik -0.015829105256023893,
28e53e0a0dSJakub Kruzik 0.5853546836548691,
29e53e0a0dSJakub Kruzik 0.6756307362980128,
30e53e0a0dSJakub Kruzik 0.3128715909144659,
31e53e0a0dSJakub Kruzik 0.05441584224308161};
32e53e0a0dSJakub Kruzik 
33e53e0a0dSJakub Kruzik PetscScalar biorth22[] = {0.0,
34e53e0a0dSJakub Kruzik -0.1767766952966369,
35e53e0a0dSJakub Kruzik 0.3535533905932738,
36e53e0a0dSJakub Kruzik 1.0606601717798214,
37e53e0a0dSJakub Kruzik 0.3535533905932738,
38e53e0a0dSJakub Kruzik -0.1767766952966369};
39e53e0a0dSJakub Kruzik 
4065149469SJakub Kruzik PetscScalar meyer[] = {0.0,-1.009999956941423e-12,8.519459636796214e-09,-1.111944952595278e-08,-1.0798819539621958e-08,6.066975741351135e-08,-1.0866516536735883e-07,8.200680650386481e-08,1.1783004497663934e-07,-5.506340565252278e-07,1.1307947017916706e-06,-1.489549216497156e-06,7.367572885903746e-07,3.20544191334478e-06,-1.6312699734552807e-05,6.554305930575149e-05,-0.0006011502343516092,-0.002704672124643725,0.002202534100911002,0.006045814097323304,-0.006387718318497156,-0.011061496392513451,0.015270015130934803,0.017423434103729693,-0.03213079399021176,-0.024348745906078023,0.0637390243228016,0.030655091960824263,-0.13284520043622938,-0.035087555656258346,0.44459300275757724,0.7445855923188063,0.44459300275757724,-0.035087555656258346,-0.13284520043622938,0.030655091960824263,0.0637390243228016,-0.024348745906078023,-0.03213079399021176,0.017423434103729693,0.015270015130934803,-0.011061496392513451,-0.006387718318497156,0.006045814097323304,0.002202534100911002,-0.002704672124643725,-0.0006011502343516092,6.554305930575149e-05,-1.6312699734552807e-05,3.20544191334478e-06,7.367572885903746e-07,-1.489549216497156e-06,1.1307947017916706e-06,-5.506340565252278e-07,1.1783004497663934e-07,8.200680650386481e-08,-1.0866516536735883e-07,6.066975741351135e-08,-1.0798819539621958e-08,-1.111944952595278e-08,8.519459636796214e-09,-1.009999956941423e-12};
41e53e0a0dSJakub Kruzik 
42e53e0a0dSJakub Kruzik static PetscErrorCode PCDeflationCreateSpaceWave(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt M,PetscInt N,PetscInt ncoeffs,PetscScalar *coeffs,PetscBool trunc,Mat *H)
43e53e0a0dSJakub Kruzik {
44e53e0a0dSJakub Kruzik   Mat            defl;
45e53e0a0dSJakub Kruzik   PetscInt       i,j,k,ilo,ihi,*Iidx;
46e53e0a0dSJakub Kruzik 
47e53e0a0dSJakub Kruzik   PetscFunctionBegin;
489566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(ncoeffs,&Iidx));
49e53e0a0dSJakub Kruzik 
509566063dSJacob Faibussowitsch   PetscCall(MatCreate(comm,&defl));
519566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(defl,m,n,M,N));
529566063dSJacob Faibussowitsch   PetscCall(MatSetUp(defl));
539566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJSetPreallocation(defl,ncoeffs,NULL));
549566063dSJacob Faibussowitsch   PetscCall(MatMPIAIJSetPreallocation(defl,ncoeffs,NULL,ncoeffs,NULL));
559566063dSJacob Faibussowitsch   PetscCall(MatSetOption(defl,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE));
569566063dSJacob Faibussowitsch   PetscCall(MatSetOption(defl,MAT_NO_OFF_PROC_ENTRIES,PETSC_TRUE));
57e53e0a0dSJakub Kruzik 
58e53e0a0dSJakub Kruzik   /* Alg 735 Taswell: fvecmat */
59e53e0a0dSJakub Kruzik   k = ncoeffs -2;
60e53e0a0dSJakub Kruzik   if (trunc) k = k/2;
61e53e0a0dSJakub Kruzik 
629566063dSJacob Faibussowitsch   PetscCall(MatGetOwnershipRange(defl,&ilo,&ihi));
63e53e0a0dSJakub Kruzik   for (i=0; i<ncoeffs; i++) {
64e53e0a0dSJakub Kruzik     Iidx[i] = i+ilo*2 -k;
65e53e0a0dSJakub Kruzik     if (Iidx[i] >= N) Iidx[i] = PETSC_MIN_INT;
66e53e0a0dSJakub Kruzik   }
67e53e0a0dSJakub Kruzik   for (i=ilo; i<ihi; i++) {
689566063dSJacob Faibussowitsch     PetscCall(MatSetValues(defl,1,&i,ncoeffs,Iidx,coeffs,INSERT_VALUES));
69e53e0a0dSJakub Kruzik     for (j=0; j<ncoeffs; j++) {
70e53e0a0dSJakub Kruzik       Iidx[j] += 2;
71e53e0a0dSJakub Kruzik       if (Iidx[j] >= N) Iidx[j] = PETSC_MIN_INT;
72e53e0a0dSJakub Kruzik     }
73e53e0a0dSJakub Kruzik   }
74e53e0a0dSJakub Kruzik 
759566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(defl,MAT_FINAL_ASSEMBLY));
769566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(defl,MAT_FINAL_ASSEMBLY));
77e53e0a0dSJakub Kruzik 
789566063dSJacob Faibussowitsch   PetscCall(PetscFree(Iidx));
79e53e0a0dSJakub Kruzik   *H = defl;
80e53e0a0dSJakub Kruzik   PetscFunctionReturn(0);
81e53e0a0dSJakub Kruzik }
82e53e0a0dSJakub Kruzik 
83e53e0a0dSJakub Kruzik PetscErrorCode PCDeflationGetSpaceHaar(PC pc,Mat *W,PetscInt size)
84e53e0a0dSJakub Kruzik {
85e53e0a0dSJakub Kruzik   Mat            A,defl;
86e53e0a0dSJakub Kruzik   PetscInt       i,j,len,ilo,ihi,*Iidx,m,M;
879e56ec8aSJakub Kruzik   PetscScalar    *col,val;
88e53e0a0dSJakub Kruzik 
89e53e0a0dSJakub Kruzik   PetscFunctionBegin;
90e53e0a0dSJakub Kruzik   /* Haar basis wavelet, level=size */
91e53e0a0dSJakub Kruzik   len = pow(2,size);
929566063dSJacob Faibussowitsch   PetscCall(PetscMalloc2(len,&col,len,&Iidx));
93e53e0a0dSJakub Kruzik   val = 1./pow(2,size/2.);
94e53e0a0dSJakub Kruzik   for (i=0; i<len; i++) col[i] = val;
95e53e0a0dSJakub Kruzik 
969566063dSJacob Faibussowitsch   PetscCall(PCGetOperators(pc,NULL,&A));
979566063dSJacob Faibussowitsch   PetscCall(MatGetLocalSize(A,&m,NULL));
989566063dSJacob Faibussowitsch   PetscCall(MatGetSize(A,&M,NULL));
999566063dSJacob Faibussowitsch   PetscCall(MatCreate(PetscObjectComm((PetscObject)A),&defl));
1009566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(defl,m,PETSC_DECIDE,M,PetscCeilInt(M,len)));
1019566063dSJacob Faibussowitsch   PetscCall(MatSetUp(defl));
1029566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJSetPreallocation(defl,size,NULL));
1039566063dSJacob Faibussowitsch   PetscCall(MatMPIAIJSetPreallocation(defl,size,NULL,size,NULL));
1049566063dSJacob Faibussowitsch   PetscCall(MatSetOption(defl,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE));
105e53e0a0dSJakub Kruzik 
1069566063dSJacob Faibussowitsch   PetscCall(MatGetOwnershipRangeColumn(defl,&ilo,&ihi));
107e53e0a0dSJakub Kruzik   for (i=0; i<len; i++) Iidx[i] = i+ilo*len;
108faa75363SBarry Smith   if (M%len && ihi == PetscCeilInt(M,len)) ihi -= 1;
109e53e0a0dSJakub Kruzik   for (i=ilo; i<ihi; i++) {
1109566063dSJacob Faibussowitsch     PetscCall(MatSetValues(defl,len,Iidx,1,&i,col,INSERT_VALUES));
111e53e0a0dSJakub Kruzik     for (j=0; j<len; j++) Iidx[j] += len;
112e53e0a0dSJakub Kruzik   }
113faa75363SBarry Smith   if (M%len && ihi+1 == PetscCeilInt(M,len)) {
114e53e0a0dSJakub Kruzik     len = M%len;
115e53e0a0dSJakub Kruzik     val = 1./pow(pow(2,len),0.5);
116e53e0a0dSJakub Kruzik     for (i=0; i<len; i++) col[i] = val;
1179566063dSJacob Faibussowitsch     PetscCall(MatSetValues(defl,len,Iidx,1,&ihi,col,INSERT_VALUES));
118e53e0a0dSJakub Kruzik   }
119e53e0a0dSJakub Kruzik 
1209566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(defl,MAT_FINAL_ASSEMBLY));
1219566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(defl,MAT_FINAL_ASSEMBLY));
122e53e0a0dSJakub Kruzik 
1239566063dSJacob Faibussowitsch   PetscCall(PetscFree2(col,Iidx));
124e53e0a0dSJakub Kruzik   *W = defl;
125e53e0a0dSJakub Kruzik   PetscFunctionReturn(0);
126e53e0a0dSJakub Kruzik }
127e53e0a0dSJakub Kruzik 
128e53e0a0dSJakub Kruzik PetscErrorCode PCDeflationGetSpaceWave(PC pc,Mat *W,PetscInt size,PetscInt ncoeffs,PetscScalar *coeffs,PetscBool trunc)
129e53e0a0dSJakub Kruzik {
130e53e0a0dSJakub Kruzik   Mat            A,*H,defl;
131e53e0a0dSJakub Kruzik   PetscInt       i,m,M,Mdefl,Ndefl;
132e53e0a0dSJakub Kruzik   MPI_Comm       comm;
133e53e0a0dSJakub Kruzik 
134e53e0a0dSJakub Kruzik   PetscFunctionBegin;
1359566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)pc,&comm));
1369566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(size,&H));
1379566063dSJacob Faibussowitsch   PetscCall(PCGetOperators(pc,&A,NULL));
1389566063dSJacob Faibussowitsch   PetscCall(MatGetLocalSize(A,&m,NULL));
1399566063dSJacob Faibussowitsch   PetscCall(MatGetSize(A,&M,NULL));
140e53e0a0dSJakub Kruzik   Mdefl = M;
141e53e0a0dSJakub Kruzik   Ndefl = M;
142e53e0a0dSJakub Kruzik   for (i=0; i<size; i++) {
143e53e0a0dSJakub Kruzik     if (Mdefl%2)  {
14420cd032fSJakub Kruzik       if (trunc) Mdefl = (PetscInt)PetscCeilReal(Mdefl/2.);
14520cd032fSJakub Kruzik       else       Mdefl = (PetscInt)PetscFloorReal((ncoeffs+Mdefl-1)/2.);
14620cd032fSJakub Kruzik     } else       Mdefl = Mdefl/2;
1479566063dSJacob Faibussowitsch     PetscCall(PCDeflationCreateSpaceWave(comm,PETSC_DECIDE,m,Mdefl,Ndefl,ncoeffs,coeffs,trunc,&H[i]));
1489566063dSJacob Faibussowitsch     PetscCall(MatGetLocalSize(H[i],&m,NULL));
149e53e0a0dSJakub Kruzik     Ndefl = Mdefl;
150e53e0a0dSJakub Kruzik   }
1519566063dSJacob Faibussowitsch   PetscCall(MatCreateComposite(comm,size,H,&defl));
1529566063dSJacob Faibussowitsch   PetscCall(MatCompositeSetType(defl,MAT_COMPOSITE_MULTIPLICATIVE));
153e53e0a0dSJakub Kruzik   *W = defl;
154e53e0a0dSJakub Kruzik 
155e53e0a0dSJakub Kruzik   for (i=0; i<size; i++) {
1569566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&H[i]));
157e53e0a0dSJakub Kruzik   }
1589566063dSJacob Faibussowitsch   PetscCall(PetscFree(H));
159e53e0a0dSJakub Kruzik   PetscFunctionReturn(0);
160e53e0a0dSJakub Kruzik }
161e53e0a0dSJakub Kruzik 
162e53e0a0dSJakub Kruzik PetscErrorCode PCDeflationGetSpaceAggregation(PC pc,Mat *W)
163e53e0a0dSJakub Kruzik {
164e53e0a0dSJakub Kruzik   Mat            A,defl;
1657b3faf33SJakub Kruzik   PetscInt       i,ilo,ihi,*Iidx,M;
1667b3faf33SJakub Kruzik   PetscMPIInt    m;
1679e56ec8aSJakub Kruzik   PetscScalar    *col;
168e53e0a0dSJakub Kruzik   MPI_Comm       comm;
169e53e0a0dSJakub Kruzik 
170e53e0a0dSJakub Kruzik   PetscFunctionBegin;
1719566063dSJacob Faibussowitsch   PetscCall(PCGetOperators(pc,&A,NULL));
1729566063dSJacob Faibussowitsch   PetscCall(MatGetOwnershipRangeColumn(A,&ilo,&ihi));
1739566063dSJacob Faibussowitsch   PetscCall(MatGetSize(A,&M,NULL));
1749566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)A,&comm));
1759566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm,&m));
1769566063dSJacob Faibussowitsch   PetscCall(MatCreate(comm,&defl));
1779566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(defl,ihi-ilo,1,M,m));
1789566063dSJacob Faibussowitsch   PetscCall(MatSetUp(defl));
1799566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJSetPreallocation(defl,1,NULL));
1809566063dSJacob Faibussowitsch   PetscCall(MatMPIAIJSetPreallocation(defl,1,NULL,0,NULL));
1819566063dSJacob Faibussowitsch   PetscCall(MatSetOption(defl,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE));
1829566063dSJacob Faibussowitsch   PetscCall(MatSetOption(defl,MAT_NO_OFF_PROC_ENTRIES,PETSC_TRUE));
183e53e0a0dSJakub Kruzik 
1849566063dSJacob Faibussowitsch   PetscCall(PetscMalloc2(ihi-ilo,&col,ihi-ilo,&Iidx));
185e53e0a0dSJakub Kruzik   for (i=ilo; i<ihi; i++) {
186e53e0a0dSJakub Kruzik     Iidx[i-ilo] = i;
187e53e0a0dSJakub Kruzik     col[i-ilo] = 1;
188e53e0a0dSJakub Kruzik   }
1899566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm,&m));
1907b3faf33SJakub Kruzik   i = m;
1919566063dSJacob Faibussowitsch   PetscCall(MatSetValues(defl,ihi-ilo,Iidx,1,&i,col,INSERT_VALUES));
192e53e0a0dSJakub Kruzik 
1939566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(defl,MAT_FINAL_ASSEMBLY));
1949566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(defl,MAT_FINAL_ASSEMBLY));
195e53e0a0dSJakub Kruzik 
1969566063dSJacob Faibussowitsch   PetscCall(PetscFree2(col,Iidx));
197e53e0a0dSJakub Kruzik   *W = defl;
198e53e0a0dSJakub Kruzik   PetscFunctionReturn(0);
199e53e0a0dSJakub Kruzik }
200e53e0a0dSJakub Kruzik 
201e53e0a0dSJakub Kruzik PetscErrorCode PCDeflationComputeSpace(PC pc)
202e53e0a0dSJakub Kruzik {
203e53e0a0dSJakub Kruzik   Mat            defl;
204e53e0a0dSJakub Kruzik   PetscBool      transp=PETSC_TRUE;
205e53e0a0dSJakub Kruzik   PC_Deflation   *def = (PC_Deflation*)pc->data;
206e53e0a0dSJakub Kruzik 
207e53e0a0dSJakub Kruzik   PetscFunctionBegin;
2081fdb00f9SJakub Kruzik   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
209*63a3b9bcSJacob Faibussowitsch   PetscCheck(def->spacesize >= 1,PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONG,"Wrong PCDeflation space size specified: %" PetscInt_FMT,def->spacesize);
210e53e0a0dSJakub Kruzik   switch (def->spacetype) {
211e53e0a0dSJakub Kruzik     case PC_DEFLATION_SPACE_HAAR:
212e53e0a0dSJakub Kruzik       transp = PETSC_FALSE;
2139566063dSJacob Faibussowitsch       PetscCall(PCDeflationGetSpaceHaar(pc,&defl,def->spacesize));break;
214e53e0a0dSJakub Kruzik     case PC_DEFLATION_SPACE_DB2:
2159566063dSJacob Faibussowitsch       PetscCall(PCDeflationGetSpaceWave(pc,&defl,def->spacesize,2,db2,PetscNot(def->extendsp)));break;
216e53e0a0dSJakub Kruzik     case PC_DEFLATION_SPACE_DB4:
2179566063dSJacob Faibussowitsch       PetscCall(PCDeflationGetSpaceWave(pc,&defl,def->spacesize,4,db4,PetscNot(def->extendsp)));break;
218e53e0a0dSJakub Kruzik     case PC_DEFLATION_SPACE_DB8:
2199566063dSJacob Faibussowitsch       PetscCall(PCDeflationGetSpaceWave(pc,&defl,def->spacesize,8,db8,PetscNot(def->extendsp)));break;
220e53e0a0dSJakub Kruzik     case PC_DEFLATION_SPACE_DB16:
2219566063dSJacob Faibussowitsch       PetscCall(PCDeflationGetSpaceWave(pc,&defl,def->spacesize,16,db16,PetscNot(def->extendsp)));break;
222e53e0a0dSJakub Kruzik     case PC_DEFLATION_SPACE_BIORTH22:
2239566063dSJacob Faibussowitsch       PetscCall(PCDeflationGetSpaceWave(pc,&defl,def->spacesize,6,biorth22,PetscNot(def->extendsp)));break;
224e53e0a0dSJakub Kruzik     case PC_DEFLATION_SPACE_MEYER:
2259566063dSJacob Faibussowitsch       PetscCall(PCDeflationGetSpaceWave(pc,&defl,def->spacesize,62,meyer,PetscNot(def->extendsp)));break;
226e53e0a0dSJakub Kruzik     case PC_DEFLATION_SPACE_AGGREGATION:
227e53e0a0dSJakub Kruzik       transp = PETSC_FALSE;
2289566063dSJacob Faibussowitsch       PetscCall(PCDeflationGetSpaceAggregation(pc,&defl));break;
2291fdb00f9SJakub Kruzik     default: SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONG,"Wrong PCDeflationSpaceType specified");
230e53e0a0dSJakub Kruzik   }
231e53e0a0dSJakub Kruzik 
2329566063dSJacob Faibussowitsch   PetscCall(PCDeflationSetSpace(pc,defl,transp));
2339566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&defl));
234e53e0a0dSJakub Kruzik   PetscFunctionReturn(0);
235e53e0a0dSJakub Kruzik }
236