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 79371c9d4SSatish Balay PetscScalar db8[] = {-0.010597401784997278, 0.032883011666982945, 0.030841381835986965, -0.18703481171888114, -0.02798376941698385, 0.6308807679295904, 0.7148465705525415, 0.23037781330885523}; 8e53e0a0dSJakub Kruzik 99371c9d4SSatish Balay PetscScalar db16[] = {-0.00011747678400228192, 0.0006754494059985568, -0.0003917403729959771, -0.00487035299301066, 0.008746094047015655, 0.013981027917015516, -0.04408825393106472, -0.01736930100202211, 109371c9d4SSatish Balay 0.128747426620186, 0.00047248457399797254, -0.2840155429624281, -0.015829105256023893, 0.5853546836548691, 0.6756307362980128, 0.3128715909144659, 0.05441584224308161}; 11e53e0a0dSJakub Kruzik 129371c9d4SSatish Balay PetscScalar biorth22[] = {0.0, -0.1767766952966369, 0.3535533905932738, 1.0606601717798214, 0.3535533905932738, -0.1767766952966369}; 13e53e0a0dSJakub Kruzik 1465149469SJakub 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}; 15e53e0a0dSJakub Kruzik 169371c9d4SSatish Balay static PetscErrorCode PCDeflationCreateSpaceWave(MPI_Comm comm, PetscInt m, PetscInt n, PetscInt M, PetscInt N, PetscInt ncoeffs, PetscScalar *coeffs, PetscBool trunc, Mat *H) { 17e53e0a0dSJakub Kruzik Mat defl; 18e53e0a0dSJakub Kruzik PetscInt i, j, k, ilo, ihi, *Iidx; 19e53e0a0dSJakub Kruzik 20e53e0a0dSJakub Kruzik PetscFunctionBegin; 219566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(ncoeffs, &Iidx)); 22e53e0a0dSJakub Kruzik 239566063dSJacob Faibussowitsch PetscCall(MatCreate(comm, &defl)); 249566063dSJacob Faibussowitsch PetscCall(MatSetSizes(defl, m, n, M, N)); 259566063dSJacob Faibussowitsch PetscCall(MatSetUp(defl)); 269566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(defl, ncoeffs, NULL)); 279566063dSJacob Faibussowitsch PetscCall(MatMPIAIJSetPreallocation(defl, ncoeffs, NULL, ncoeffs, NULL)); 289566063dSJacob Faibussowitsch PetscCall(MatSetOption(defl, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_TRUE)); 299566063dSJacob Faibussowitsch PetscCall(MatSetOption(defl, MAT_NO_OFF_PROC_ENTRIES, PETSC_TRUE)); 30e53e0a0dSJakub Kruzik 31e53e0a0dSJakub Kruzik /* Alg 735 Taswell: fvecmat */ 32e53e0a0dSJakub Kruzik k = ncoeffs - 2; 33e53e0a0dSJakub Kruzik if (trunc) k = k / 2; 34e53e0a0dSJakub Kruzik 359566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(defl, &ilo, &ihi)); 36e53e0a0dSJakub Kruzik for (i = 0; i < ncoeffs; i++) { 37e53e0a0dSJakub Kruzik Iidx[i] = i + ilo * 2 - k; 38e53e0a0dSJakub Kruzik if (Iidx[i] >= N) Iidx[i] = PETSC_MIN_INT; 39e53e0a0dSJakub Kruzik } 40e53e0a0dSJakub Kruzik for (i = ilo; i < ihi; i++) { 419566063dSJacob Faibussowitsch PetscCall(MatSetValues(defl, 1, &i, ncoeffs, Iidx, coeffs, INSERT_VALUES)); 42e53e0a0dSJakub Kruzik for (j = 0; j < ncoeffs; j++) { 43e53e0a0dSJakub Kruzik Iidx[j] += 2; 44e53e0a0dSJakub Kruzik if (Iidx[j] >= N) Iidx[j] = PETSC_MIN_INT; 45e53e0a0dSJakub Kruzik } 46e53e0a0dSJakub Kruzik } 47e53e0a0dSJakub Kruzik 489566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(defl, MAT_FINAL_ASSEMBLY)); 499566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(defl, MAT_FINAL_ASSEMBLY)); 50e53e0a0dSJakub Kruzik 519566063dSJacob Faibussowitsch PetscCall(PetscFree(Iidx)); 52e53e0a0dSJakub Kruzik *H = defl; 53e53e0a0dSJakub Kruzik PetscFunctionReturn(0); 54e53e0a0dSJakub Kruzik } 55e53e0a0dSJakub Kruzik 569371c9d4SSatish Balay PetscErrorCode PCDeflationGetSpaceHaar(PC pc, Mat *W, PetscInt size) { 57e53e0a0dSJakub Kruzik Mat A, defl; 58e53e0a0dSJakub Kruzik PetscInt i, j, len, ilo, ihi, *Iidx, m, M; 599e56ec8aSJakub Kruzik PetscScalar *col, val; 60e53e0a0dSJakub Kruzik 61e53e0a0dSJakub Kruzik PetscFunctionBegin; 62e53e0a0dSJakub Kruzik /* Haar basis wavelet, level=size */ 63e53e0a0dSJakub Kruzik len = pow(2, size); 649566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(len, &col, len, &Iidx)); 65e53e0a0dSJakub Kruzik val = 1. / pow(2, size / 2.); 66e53e0a0dSJakub Kruzik for (i = 0; i < len; i++) col[i] = val; 67e53e0a0dSJakub Kruzik 689566063dSJacob Faibussowitsch PetscCall(PCGetOperators(pc, NULL, &A)); 699566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(A, &m, NULL)); 709566063dSJacob Faibussowitsch PetscCall(MatGetSize(A, &M, NULL)); 719566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &defl)); 729566063dSJacob Faibussowitsch PetscCall(MatSetSizes(defl, m, PETSC_DECIDE, M, PetscCeilInt(M, len))); 739566063dSJacob Faibussowitsch PetscCall(MatSetUp(defl)); 749566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(defl, size, NULL)); 759566063dSJacob Faibussowitsch PetscCall(MatMPIAIJSetPreallocation(defl, size, NULL, size, NULL)); 769566063dSJacob Faibussowitsch PetscCall(MatSetOption(defl, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_TRUE)); 77e53e0a0dSJakub Kruzik 789566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRangeColumn(defl, &ilo, &ihi)); 79e53e0a0dSJakub Kruzik for (i = 0; i < len; i++) Iidx[i] = i + ilo * len; 80faa75363SBarry Smith if (M % len && ihi == PetscCeilInt(M, len)) ihi -= 1; 81e53e0a0dSJakub Kruzik for (i = ilo; i < ihi; i++) { 829566063dSJacob Faibussowitsch PetscCall(MatSetValues(defl, len, Iidx, 1, &i, col, INSERT_VALUES)); 83e53e0a0dSJakub Kruzik for (j = 0; j < len; j++) Iidx[j] += len; 84e53e0a0dSJakub Kruzik } 85faa75363SBarry Smith if (M % len && ihi + 1 == PetscCeilInt(M, len)) { 86e53e0a0dSJakub Kruzik len = M % len; 87e53e0a0dSJakub Kruzik val = 1. / pow(pow(2, len), 0.5); 88e53e0a0dSJakub Kruzik for (i = 0; i < len; i++) col[i] = val; 899566063dSJacob Faibussowitsch PetscCall(MatSetValues(defl, len, Iidx, 1, &ihi, col, INSERT_VALUES)); 90e53e0a0dSJakub Kruzik } 91e53e0a0dSJakub Kruzik 929566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(defl, MAT_FINAL_ASSEMBLY)); 939566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(defl, MAT_FINAL_ASSEMBLY)); 94e53e0a0dSJakub Kruzik 959566063dSJacob Faibussowitsch PetscCall(PetscFree2(col, Iidx)); 96e53e0a0dSJakub Kruzik *W = defl; 97e53e0a0dSJakub Kruzik PetscFunctionReturn(0); 98e53e0a0dSJakub Kruzik } 99e53e0a0dSJakub Kruzik 1009371c9d4SSatish Balay PetscErrorCode PCDeflationGetSpaceWave(PC pc, Mat *W, PetscInt size, PetscInt ncoeffs, PetscScalar *coeffs, PetscBool trunc) { 101e53e0a0dSJakub Kruzik Mat A, *H, defl; 102e53e0a0dSJakub Kruzik PetscInt i, m, M, Mdefl, Ndefl; 103e53e0a0dSJakub Kruzik MPI_Comm comm; 104e53e0a0dSJakub Kruzik 105e53e0a0dSJakub Kruzik PetscFunctionBegin; 1069566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)pc, &comm)); 1079566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &H)); 1089566063dSJacob Faibussowitsch PetscCall(PCGetOperators(pc, &A, NULL)); 1099566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(A, &m, NULL)); 1109566063dSJacob Faibussowitsch PetscCall(MatGetSize(A, &M, NULL)); 111e53e0a0dSJakub Kruzik Mdefl = M; 112e53e0a0dSJakub Kruzik Ndefl = M; 113e53e0a0dSJakub Kruzik for (i = 0; i < size; i++) { 114e53e0a0dSJakub Kruzik if (Mdefl % 2) { 11520cd032fSJakub Kruzik if (trunc) Mdefl = (PetscInt)PetscCeilReal(Mdefl / 2.); 11620cd032fSJakub Kruzik else Mdefl = (PetscInt)PetscFloorReal((ncoeffs + Mdefl - 1) / 2.); 11720cd032fSJakub Kruzik } else Mdefl = Mdefl / 2; 1189566063dSJacob Faibussowitsch PetscCall(PCDeflationCreateSpaceWave(comm, PETSC_DECIDE, m, Mdefl, Ndefl, ncoeffs, coeffs, trunc, &H[i])); 1199566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(H[i], &m, NULL)); 120e53e0a0dSJakub Kruzik Ndefl = Mdefl; 121e53e0a0dSJakub Kruzik } 1229566063dSJacob Faibussowitsch PetscCall(MatCreateComposite(comm, size, H, &defl)); 1239566063dSJacob Faibussowitsch PetscCall(MatCompositeSetType(defl, MAT_COMPOSITE_MULTIPLICATIVE)); 124e53e0a0dSJakub Kruzik *W = defl; 125e53e0a0dSJakub Kruzik 126*48a46eb9SPierre Jolivet for (i = 0; i < size; i++) PetscCall(MatDestroy(&H[i])); 1279566063dSJacob Faibussowitsch PetscCall(PetscFree(H)); 128e53e0a0dSJakub Kruzik PetscFunctionReturn(0); 129e53e0a0dSJakub Kruzik } 130e53e0a0dSJakub Kruzik 1319371c9d4SSatish Balay PetscErrorCode PCDeflationGetSpaceAggregation(PC pc, Mat *W) { 132e53e0a0dSJakub Kruzik Mat A, defl; 1337b3faf33SJakub Kruzik PetscInt i, ilo, ihi, *Iidx, M; 1347b3faf33SJakub Kruzik PetscMPIInt m; 1359e56ec8aSJakub Kruzik PetscScalar *col; 136e53e0a0dSJakub Kruzik MPI_Comm comm; 137e53e0a0dSJakub Kruzik 138e53e0a0dSJakub Kruzik PetscFunctionBegin; 1399566063dSJacob Faibussowitsch PetscCall(PCGetOperators(pc, &A, NULL)); 1409566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRangeColumn(A, &ilo, &ihi)); 1419566063dSJacob Faibussowitsch PetscCall(MatGetSize(A, &M, NULL)); 1429566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)A, &comm)); 1439566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &m)); 1449566063dSJacob Faibussowitsch PetscCall(MatCreate(comm, &defl)); 1459566063dSJacob Faibussowitsch PetscCall(MatSetSizes(defl, ihi - ilo, 1, M, m)); 1469566063dSJacob Faibussowitsch PetscCall(MatSetUp(defl)); 1479566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(defl, 1, NULL)); 1489566063dSJacob Faibussowitsch PetscCall(MatMPIAIJSetPreallocation(defl, 1, NULL, 0, NULL)); 1499566063dSJacob Faibussowitsch PetscCall(MatSetOption(defl, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_TRUE)); 1509566063dSJacob Faibussowitsch PetscCall(MatSetOption(defl, MAT_NO_OFF_PROC_ENTRIES, PETSC_TRUE)); 151e53e0a0dSJakub Kruzik 1529566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(ihi - ilo, &col, ihi - ilo, &Iidx)); 153e53e0a0dSJakub Kruzik for (i = ilo; i < ihi; i++) { 154e53e0a0dSJakub Kruzik Iidx[i - ilo] = i; 155e53e0a0dSJakub Kruzik col[i - ilo] = 1; 156e53e0a0dSJakub Kruzik } 1579566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &m)); 1587b3faf33SJakub Kruzik i = m; 1599566063dSJacob Faibussowitsch PetscCall(MatSetValues(defl, ihi - ilo, Iidx, 1, &i, col, INSERT_VALUES)); 160e53e0a0dSJakub Kruzik 1619566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(defl, MAT_FINAL_ASSEMBLY)); 1629566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(defl, MAT_FINAL_ASSEMBLY)); 163e53e0a0dSJakub Kruzik 1649566063dSJacob Faibussowitsch PetscCall(PetscFree2(col, Iidx)); 165e53e0a0dSJakub Kruzik *W = defl; 166e53e0a0dSJakub Kruzik PetscFunctionReturn(0); 167e53e0a0dSJakub Kruzik } 168e53e0a0dSJakub Kruzik 1699371c9d4SSatish Balay PetscErrorCode PCDeflationComputeSpace(PC pc) { 170e53e0a0dSJakub Kruzik Mat defl; 171e53e0a0dSJakub Kruzik PetscBool transp = PETSC_TRUE; 172e53e0a0dSJakub Kruzik PC_Deflation *def = (PC_Deflation *)pc->data; 173e53e0a0dSJakub Kruzik 174e53e0a0dSJakub Kruzik PetscFunctionBegin; 1751fdb00f9SJakub Kruzik PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 17663a3b9bcSJacob Faibussowitsch PetscCheck(def->spacesize >= 1, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_WRONG, "Wrong PCDeflation space size specified: %" PetscInt_FMT, def->spacesize); 177e53e0a0dSJakub Kruzik switch (def->spacetype) { 178e53e0a0dSJakub Kruzik case PC_DEFLATION_SPACE_HAAR: 179e53e0a0dSJakub Kruzik transp = PETSC_FALSE; 1809371c9d4SSatish Balay PetscCall(PCDeflationGetSpaceHaar(pc, &defl, def->spacesize)); 1819371c9d4SSatish Balay break; 1829371c9d4SSatish Balay case PC_DEFLATION_SPACE_DB2: PetscCall(PCDeflationGetSpaceWave(pc, &defl, def->spacesize, 2, db2, PetscNot(def->extendsp))); break; 1839371c9d4SSatish Balay case PC_DEFLATION_SPACE_DB4: PetscCall(PCDeflationGetSpaceWave(pc, &defl, def->spacesize, 4, db4, PetscNot(def->extendsp))); break; 1849371c9d4SSatish Balay case PC_DEFLATION_SPACE_DB8: PetscCall(PCDeflationGetSpaceWave(pc, &defl, def->spacesize, 8, db8, PetscNot(def->extendsp))); break; 1859371c9d4SSatish Balay case PC_DEFLATION_SPACE_DB16: PetscCall(PCDeflationGetSpaceWave(pc, &defl, def->spacesize, 16, db16, PetscNot(def->extendsp))); break; 1869371c9d4SSatish Balay case PC_DEFLATION_SPACE_BIORTH22: PetscCall(PCDeflationGetSpaceWave(pc, &defl, def->spacesize, 6, biorth22, PetscNot(def->extendsp))); break; 1879371c9d4SSatish Balay case PC_DEFLATION_SPACE_MEYER: PetscCall(PCDeflationGetSpaceWave(pc, &defl, def->spacesize, 62, meyer, PetscNot(def->extendsp))); break; 188e53e0a0dSJakub Kruzik case PC_DEFLATION_SPACE_AGGREGATION: 189e53e0a0dSJakub Kruzik transp = PETSC_FALSE; 1909371c9d4SSatish Balay PetscCall(PCDeflationGetSpaceAggregation(pc, &defl)); 1919371c9d4SSatish Balay break; 1921fdb00f9SJakub Kruzik default: SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_WRONG, "Wrong PCDeflationSpaceType specified"); 193e53e0a0dSJakub Kruzik } 194e53e0a0dSJakub Kruzik 1959566063dSJacob Faibussowitsch PetscCall(PCDeflationSetSpace(pc, defl, transp)); 1969566063dSJacob Faibussowitsch PetscCall(MatDestroy(&defl)); 197e53e0a0dSJakub Kruzik PetscFunctionReturn(0); 198e53e0a0dSJakub Kruzik } 199