diff --git a/AMDiS/src/parallel/PetscSolverFeti.cc b/AMDiS/src/parallel/PetscSolverFeti.cc index d16561eb80ca091f03b4096a6138db8450e9c783..d918d32bbceb7ece23494db8abf83622b2f8138b 100644 --- a/AMDiS/src/parallel/PetscSolverFeti.cc +++ b/AMDiS/src/parallel/PetscSolverFeti.cc @@ -187,7 +187,8 @@ namespace AMDiS { PetscSolverFeti::PetscSolverFeti() : PetscSolver(), schurPrimalSolver(0), - multiLevelTest(false) + multiLevelTest(false), + subDomainSolver(NULL) { FUNCNAME("PetscSolverFeti::PetscSolverFeti()"); @@ -213,10 +214,6 @@ namespace AMDiS { schurPrimalSolver); Parameters::get("parallel->multi level test", multiLevelTest); - - if (multiLevelTest) { - subDomainSolver = new SubDomainSolver(meshDistributor, mpiComm, mpiSelfComm); - } } @@ -271,9 +268,7 @@ namespace AMDiS { // If multi level test, inform sub domain solver about coarse space. - if (multiLevelTest) { - subDomainSolver->setCoarseSpace(&primalDofMap); - } + subDomainSolver->setDofMapping(&primalDofMap, &localDofMap); } @@ -492,9 +487,9 @@ namespace AMDiS { if (schurPrimalSolver == 0) { MSG("Create iterative schur primal solver!\n"); - schurPrimalData.mat_primal_primal = &mat_primal_primal; - schurPrimalData.mat_primal_b = &mat_primal_b; - schurPrimalData.mat_b_primal = &mat_b_primal; + schurPrimalData.mat_primal_primal = &(subDomainSolver->getMatCoarseCoarse()); + schurPrimalData.mat_primal_b = &(subDomainSolver->getMatCoarseInt()); + schurPrimalData.mat_b_primal = &(subDomainSolver->getMatIntCoarse()); schurPrimalData.fetiSolver = this; VecCreateMPI(mpiComm, @@ -520,8 +515,6 @@ namespace AMDiS { } else { MSG("Create direct schur primal solver!\n"); - TEST_EXIT(ksp_b)("No solver object for local problem!\n"); - double wtime = MPI::Wtime(); int nRowsRankPrimal = primalDofMap.getRankDofs(); @@ -544,13 +537,13 @@ namespace AMDiS { for (int i = 0; i < nRowsRankB; i++) { PetscInt row = localDofMap.getStartDofs() + i; - MatGetRow(mat_b_primal, row, &nCols, &cols, &values); + MatGetRow(subDomainSolver->getMatIntCoarse(), row, &nCols, &cols, &values); for (int j = 0; j < nCols; j++) if (values[j] != 0.0) mat_b_primal_cols[cols[j]].push_back(make_pair(i, values[j])); - MatRestoreRow(mat_b_primal, row, &nCols, &cols, &values); + MatRestoreRow(subDomainSolver->getMatIntCoarse(), row, &nCols, &cols, &values); } TEST_EXIT(static_cast<int>(mat_b_primal_cols.size()) == @@ -569,7 +562,7 @@ namespace AMDiS { VecAssemblyBegin(tmpVec); VecAssemblyEnd(tmpVec); - KSPSolve(ksp_b, tmpVec, tmpVec); + subDomainSolver->solve(tmpVec, tmpVec); PetscScalar *tmpValues; VecGetArray(tmpVec, &tmpValues); @@ -586,19 +579,21 @@ namespace AMDiS { MatAssemblyBegin(matBPi, MAT_FINAL_ASSEMBLY); MatAssemblyEnd(matBPi, MAT_FINAL_ASSEMBLY); - MatMatMult(mat_primal_b, matBPi, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &matPrimal); - MatAXPY(mat_primal_primal, -1.0, matPrimal, DIFFERENT_NONZERO_PATTERN); + MatMatMult(subDomainSolver->getMatCoarseInt(), matBPi, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &matPrimal); + MatAXPY(subDomainSolver->getMatCoarseCoarse(), -1.0, matPrimal, DIFFERENT_NONZERO_PATTERN); MatDestroy(&matPrimal); MatDestroy(&matBPi); MatInfo minfo; - MatGetInfo(mat_primal_primal, MAT_GLOBAL_SUM, &minfo); + MatGetInfo(subDomainSolver->getMatCoarseCoarse(), MAT_GLOBAL_SUM, &minfo); MSG("Schur primal matrix nnz = %f\n", minfo.nz_used); KSPCreate(mpiComm, &ksp_schur_primal); - KSPSetOperators(ksp_schur_primal, mat_primal_primal, - mat_primal_primal, SAME_NONZERO_PATTERN); + KSPSetOperators(ksp_schur_primal, + subDomainSolver->getMatCoarseCoarse(), + subDomainSolver->getMatCoarseCoarse(), + SAME_NONZERO_PATTERN); KSPSetOptionsPrefix(ksp_schur_primal, "schur_primal_"); KSPSetType(ksp_schur_primal, KSPPREONLY); PC pc_schur_primal; @@ -640,8 +635,8 @@ namespace AMDiS { // === Create FETI-DP solver object. === - fetiData.mat_primal_b = &mat_primal_b; - fetiData.mat_b_primal = &mat_b_primal; + fetiData.mat_primal_b = &(subDomainSolver->getMatCoarseInt()); + fetiData.mat_b_primal = &(subDomainSolver->getMatIntCoarse()); fetiData.mat_lagrange = &mat_lagrange; fetiData.fetiSolver = this; fetiData.ksp_schur_primal = &ksp_schur_primal; @@ -910,6 +905,9 @@ namespace AMDiS { { FUNCNAME("PetscSolverFeti::fillPetscMatrix()"); + if (subDomainSolver == NULL) + subDomainSolver = new SubDomainSolver(meshDistributor, mpiComm, mpiSelfComm); + // === Create all sets and indices. === vector<const FiniteElemSpace*> feSpaces = getFeSpaces(mat); @@ -935,6 +933,7 @@ namespace AMDiS { int nRowsRankPrimal = primalDofMap.getRankDofs(); int nRowsOverallPrimal = primalDofMap.getOverallDofs(); +#if 0 MatCreateSeqAIJ(PETSC_COMM_SELF, nRowsRankB, nRowsRankB, 60, PETSC_NULL, &mat_b_b); @@ -952,7 +951,10 @@ namespace AMDiS { nRowsRankPrimal, nRowsRankB, nRowsOverallPrimal, nRowsOverallB, 30, PETSC_NULL, 30, PETSC_NULL, &mat_primal_b); - +#endif + + subDomainSolver->fillPetscMatrix(mat); + // === Create matrices for FETI-DP preconditioner. === @@ -1098,32 +1100,41 @@ namespace AMDiS { for (unsigned int k = 0; k < cols.size(); k++) cols[k] = primalDofMap.getMatIndex(j, cols[k]); +#if 0 MatSetValues(mat_primal_primal, 1, &rowIndex, cols.size(), &(cols[0]), &(values[0]), ADD_VALUES); +#endif if (colsOther.size()) { for (unsigned int k = 0; k < colsOther.size(); k++) colsOther[k] = localDofMap.getMatIndex(j, colsOther[k]); - + +#if 0 MatSetValues(mat_primal_b, 1, &rowIndex, colsOther.size(), &(colsOther[0]), &(valuesOther[0]), ADD_VALUES); +#endif + } } else { int localRowIndex = localDofMap.getLocalMatIndex(i, *cursor); for (unsigned int k = 0; k < cols.size(); k++) cols[k] = localDofMap.getLocalMatIndex(j, cols[k]); - + +#if 0 MatSetValues(mat_b_b, 1, &localRowIndex, cols.size(), &(cols[0]), &(values[0]), ADD_VALUES); +#endif if (colsOther.size()) { int globalRowIndex = localDofMap.getMatIndex(i, *cursor); for (unsigned int k = 0; k < colsOther.size(); k++) colsOther[k] = primalDofMap.getMatIndex(j, colsOther[k]); +#if 0 MatSetValues(mat_b_primal, 1, &globalRowIndex, colsOther.size(), &(colsOther[0]), &(valuesOther[0]), ADD_VALUES); +#endif } } @@ -1164,6 +1175,7 @@ namespace AMDiS { } } +#if 0 // === Start global assembly procedure. === MatAssemblyBegin(mat_b_b, MAT_FINAL_ASSEMBLY); @@ -1177,7 +1189,7 @@ namespace AMDiS { MatAssemblyBegin(mat_primal_b, MAT_FINAL_ASSEMBLY); MatAssemblyEnd(mat_primal_b, MAT_FINAL_ASSEMBLY); - +#endif // === Start global assembly procedure for preconditioner matrices. === @@ -1203,19 +1215,6 @@ namespace AMDiS { createMatLagrange(feSpaces); - // === Create solver for the non primal (thus local) variables. === - - KSPCreate(PETSC_COMM_SELF, &ksp_b); - KSPSetOperators(ksp_b, mat_b_b, mat_b_b, SAME_NONZERO_PATTERN); - KSPSetOptionsPrefix(ksp_b, "interior_"); - KSPSetType(ksp_b, KSPPREONLY); - PC pc_b; - KSPGetPC(ksp_b, &pc_b); - PCSetType(pc_b, PCLU); - PCFactorSetMatSolverPackage(pc_b, MATSOLVERUMFPACK); - KSPSetFromOptions(ksp_b); - - // === Create PETSc solver for the Schur complement on primal variables. === createSchurPrimalKsp(feSpaces); @@ -1231,6 +1230,7 @@ namespace AMDiS { { FUNCNAME("PetscSolverFeti::fillPetscRhs()"); +#if 0 vector<const FiniteElemSpace*> feSpaces = getFeSpaces(vec); VecCreateMPI(mpiComm, @@ -1258,6 +1258,9 @@ namespace AMDiS { VecAssemblyBegin(f_primal); VecAssemblyEnd(f_primal); +#else + subDomainSolver->fillPetscRhs(vec); +#endif } @@ -1278,7 +1281,7 @@ namespace AMDiS { VecRestoreArray(rhs, &rhsValues); VecRestoreArray(tmp, &tmpValues); - KSPSolve(ksp_b, tmp, tmp); + subDomainSolver->solve(tmp, tmp); VecGetArray(tmp, &tmpValues); VecGetArray(sol, &rhsValues); @@ -1312,32 +1315,36 @@ namespace AMDiS { // Some temporary vectors. Vec tmp_b0, tmp_b1, tmp_lagrange0, tmp_primal0, tmp_primal1; + + VecCreateMPI(mpiComm, + localDofMap.getRankDofs(), localDofMap.getOverallDofs(), &tmp_b0); + VecCreateMPI(mpiComm, + localDofMap.getRankDofs(), localDofMap.getOverallDofs(), &tmp_b1); + MatGetVecs(mat_lagrange, PETSC_NULL, &tmp_lagrange0); MatGetVecs(mat_lagrange, PETSC_NULL, &vec_rhs); - VecDuplicate(f_b, &tmp_b0); - VecDuplicate(f_b, &tmp_b1); - MatGetVecs(mat_primal_primal, PETSC_NULL, &tmp_primal0); - MatGetVecs(mat_primal_primal, PETSC_NULL, &tmp_primal1); + MatGetVecs(subDomainSolver->getMatCoarseCoarse(), PETSC_NULL, &tmp_primal0); + MatGetVecs(subDomainSolver->getMatCoarseCoarse(), PETSC_NULL, &tmp_primal1); // === Create new rhs === // d = L inv(K_BB) f_B - L inv(K_BB) K_BPi inv(S_PiPi) [f_Pi - K_PiB inv(K_BB) f_B] // vec_rhs = L * inv(K_BB) * f_B - solveLocalProblem(f_b, tmp_b0); + solveLocalProblem(subDomainSolver->getRhsInterior(), tmp_b0); MatMult(mat_lagrange, tmp_b0, vec_rhs); // tmp_primal0 = M_PiB * inv(K_BB) * f_B - MatMult(mat_primal_b, tmp_b0, tmp_primal0); + MatMult(subDomainSolver->getMatCoarseInt(), tmp_b0, tmp_primal0); // tmp_primal0 = f_Pi - M_PiB * inv(K_BB) * f_B - VecAXPBY(tmp_primal0, 1.0, -1.0, f_primal); + VecAXPBY(tmp_primal0, 1.0, -1.0, subDomainSolver->getRhsCoarseSpace()); // tmp_primal0 = inv(S_PiPi) (f_Pi - M_PiB * inv(K_BB) * f_B) KSPSolve(ksp_schur_primal, tmp_primal0, tmp_primal0); // - MatMult(mat_b_primal, tmp_primal0, tmp_b0); + MatMult(subDomainSolver->getMatIntCoarse(), tmp_primal0, tmp_b0); solveLocalProblem(tmp_b0, tmp_b0); MatMult(mat_lagrange, tmp_b0, tmp_lagrange0); @@ -1350,13 +1357,13 @@ namespace AMDiS { // === Solve for u_primals. === - VecCopy(f_primal, tmp_primal0); - solveLocalProblem(f_b, tmp_b0); - MatMult(mat_primal_b, tmp_b0, tmp_primal1); + VecCopy(subDomainSolver->getRhsCoarseSpace(), tmp_primal0); + solveLocalProblem(subDomainSolver->getRhsInterior(), tmp_b0); + MatMult(subDomainSolver->getMatCoarseInt(), tmp_b0, tmp_primal1); VecAXPBY(tmp_primal0, -1.0, 1.0, tmp_primal1); MatMultTranspose(mat_lagrange, vec_rhs, tmp_b0); solveLocalProblem(tmp_b0, tmp_b0); - MatMult(mat_primal_b, tmp_b0, tmp_primal1); + MatMult(subDomainSolver->getMatCoarseInt(), tmp_b0, tmp_primal1); VecAXPBY(tmp_primal0, 1.0, 1.0, tmp_primal1); KSPSolve(ksp_schur_primal, tmp_primal0, tmp_primal0); @@ -1364,11 +1371,11 @@ namespace AMDiS { // === Solve for u_b. === - VecCopy(f_b, tmp_b0); + VecCopy(subDomainSolver->getRhsInterior(), tmp_b0); MatMultTranspose(mat_lagrange, vec_rhs, tmp_b1); VecAXPBY(tmp_b0, -1.0, 1.0, tmp_b1); - MatMult(mat_b_primal, tmp_primal0, tmp_b1); + MatMult(subDomainSolver->getMatIntCoarse(), tmp_primal0, tmp_b1); VecAXPBY(tmp_b0, -1.0, 1.0, tmp_b1); solveLocalProblem(tmp_b0, tmp_b0); @@ -1385,9 +1392,13 @@ namespace AMDiS { VecDestroy(&tmp_lagrange0); VecDestroy(&tmp_primal0); VecDestroy(&tmp_primal1); - + +#if 0 VecDestroy(&f_b); VecDestroy(&f_primal); +#else + subDomainSolver->solvePetscMatrix(vec, NULL); +#endif } @@ -1395,10 +1406,13 @@ namespace AMDiS { { FUNCNAME("PetscSolverFeti::destroyMatrixData()"); +#if 0 MatDestroy(&mat_b_b); MatDestroy(&mat_primal_primal); MatDestroy(&mat_b_primal); MatDestroy(&mat_primal_b); +#endif + MatDestroy(&mat_lagrange); // === Destroy preconditioner data structures. === @@ -1415,8 +1429,6 @@ namespace AMDiS { destroySchurPrimalKsp(); destroyFetiKsp(); - - KSPDestroy(&ksp_b); } diff --git a/AMDiS/src/parallel/PetscSolverFeti.h b/AMDiS/src/parallel/PetscSolverFeti.h index 357b4fe4698f2f9522c5081bb1d1c591a3052453..935dc963e85e2ce10e33ae95fc8ec24183b1a662 100644 --- a/AMDiS/src/parallel/PetscSolverFeti.h +++ b/AMDiS/src/parallel/PetscSolverFeti.h @@ -179,6 +179,7 @@ namespace AMDiS { /// ranks in which the DOF is contained in. map<const FiniteElemSpace*, DofIndexToPartitions> boundaryDofRanks; +#if 0 /// Global PETSc matrix of non primal variables. Mat mat_b_b; @@ -188,16 +189,21 @@ namespace AMDiS { /// Global PETSc matrices that connect the primal with the non /// primal variables. Mat mat_b_primal, mat_primal_b; +#endif /// Global PETSc matrix of Lagrange variables. Mat mat_lagrange; +#if 0 /// Right hand side PETSc vectors for primal and non primal variables. Vec f_b, f_primal; +#endif +#if 0 /// PETSc solver object that inverts the matrix of non primal /// variables, \ref mat_b_b KSP ksp_b; +#endif /// 0: Solve the Schur complement on primal variables with iterative solver. /// 1: Create the Schur complement matrix explicitly and solve it with a diff --git a/AMDiS/src/parallel/SubDomainSolver.cc b/AMDiS/src/parallel/SubDomainSolver.cc index 282c6db1e6620c6770cb193a676840352a64a33c..dfd5926437b7d5e6750253c1bdfe33b070ebbea9 100644 --- a/AMDiS/src/parallel/SubDomainSolver.cc +++ b/AMDiS/src/parallel/SubDomainSolver.cc @@ -11,6 +11,7 @@ #include "parallel/SubDomainSolver.h" +#include "SystemVector.h" namespace AMDiS { @@ -19,25 +20,258 @@ namespace AMDiS { void SubDomainSolver::fillPetscMatrix(Matrix<DOFMatrix*> *mat) { + FUNCNAME("SubDomainSolver::fillPetscMatrix()"); + + vector<const FiniteElemSpace*> feSpaces = getFeSpaces(mat); + + int nRowsRankInterior = interiorMap->getRankDofs(); + int nRowsOverallInterior = interiorMap->getOverallDofs(); + int nRowsRankCoarse = coarseSpaceMap->getRankDofs(); + int nRowsOverallCoarse = coarseSpaceMap->getOverallDofs(); + + MatCreateSeqAIJ(mpiCommInterior, nRowsRankInterior, nRowsRankInterior, + 60, PETSC_NULL, &matIntInt); + + MatCreateMPIAIJ(mpiCommCoarseSpace, + nRowsRankCoarse, nRowsRankCoarse, + nRowsOverallCoarse, nRowsOverallCoarse, + 60, PETSC_NULL, 60, PETSC_NULL, &matCoarseCoarse); + + MatCreateMPIAIJ(mpiCommCoarseSpace, + nRowsRankCoarse, nRowsRankInterior, + nRowsOverallCoarse, nRowsOverallInterior, + 60, PETSC_NULL, 60, PETSC_NULL, &matCoarseInt); + + MatCreateMPIAIJ(mpiCommCoarseSpace, + nRowsRankInterior, nRowsRankCoarse, + nRowsOverallInterior, nRowsOverallCoarse, + 60, PETSC_NULL, 60, PETSC_NULL, &matIntCoarse); + + // === Prepare traverse of sequentially created matrices. === + + using mtl::tag::row; using mtl::tag::nz; using mtl::begin; using mtl::end; + namespace traits = mtl::traits; + typedef DOFMatrix::base_matrix_type Matrix; + + typedef traits::range_generator<row, Matrix>::type cursor_type; + typedef traits::range_generator<nz, cursor_type>::type icursor_type; + + vector<int> cols, colsOther; + vector<double> values, valuesOther; + cols.reserve(300); + colsOther.reserve(300); + values.reserve(300); + valuesOther.reserve(300); + + // === Traverse all sequentially created matrices and add the values to === + // === the global PETSc matrices. === + + int nComponents = mat->getSize(); + for (int i = 0; i < nComponents; i++) { + for (int j = 0; j < nComponents; j++) { + if (!(*mat)[i][j]) + continue; + + traits::col<Matrix>::type col((*mat)[i][j]->getBaseMatrix()); + traits::const_value<Matrix>::type value((*mat)[i][j]->getBaseMatrix()); + + // Traverse all rows. + for (cursor_type cursor = begin<row>((*mat)[i][j]->getBaseMatrix()), + cend = end<row>((*mat)[i][j]->getBaseMatrix()); cursor != cend; ++cursor) { + + bool rowPrimal = isCoarseSpace(feSpaces[i], *cursor); + + cols.clear(); + colsOther.clear(); + values.clear(); + valuesOther.clear(); + + // Traverse all columns. + for (icursor_type icursor = begin<nz>(cursor), icend = end<nz>(cursor); + icursor != icend; ++icursor) { + + bool colPrimal = isCoarseSpace(feSpaces[j], col(*icursor)); + + if (colPrimal) { + if (rowPrimal) { + cols.push_back(col(*icursor)); + values.push_back(value(*icursor)); + } else { + colsOther.push_back(col(*icursor)); + valuesOther.push_back(value(*icursor)); + } + } else { + if (rowPrimal) { + colsOther.push_back(col(*icursor)); + valuesOther.push_back(value(*icursor)); + } else { + cols.push_back(col(*icursor)); + values.push_back(value(*icursor)); + } + } + } // for each nnz in row + + + // === Set matrix values. === + + if (rowPrimal) { + int rowIndex = coarseSpaceMap->getMatIndex(i, *cursor); + for (unsigned int k = 0; k < cols.size(); k++) + cols[k] = coarseSpaceMap->getMatIndex(j, cols[k]); + + MatSetValues(matCoarseCoarse, 1, &rowIndex, cols.size(), + &(cols[0]), &(values[0]), ADD_VALUES); + + if (colsOther.size()) { + for (unsigned int k = 0; k < colsOther.size(); k++) + colsOther[k] = interiorMap->getMatIndex(j, colsOther[k]); + + MatSetValues(matCoarseInt, 1, &rowIndex, colsOther.size(), + &(colsOther[0]), &(valuesOther[0]), ADD_VALUES); + } + } else { + int localRowIndex = interiorMap->getLocalMatIndex(i, *cursor); + + for (unsigned int k = 0; k < cols.size(); k++) + cols[k] = interiorMap->getLocalMatIndex(j, cols[k]); + + MatSetValues(matIntInt, 1, &localRowIndex, cols.size(), + &(cols[0]), &(values[0]), ADD_VALUES); + + if (colsOther.size()) { + int globalRowIndex = interiorMap->getMatIndex(i, *cursor); + for (unsigned int k = 0; k < colsOther.size(); k++) + colsOther[k] = coarseSpaceMap->getMatIndex(j, colsOther[k]); + + MatSetValues(matIntCoarse, 1, &globalRowIndex, colsOther.size(), + &(colsOther[0]), &(valuesOther[0]), ADD_VALUES); + } + } + } + } + } + + // === Start global assembly procedure. === + + MatAssemblyBegin(matIntInt, MAT_FINAL_ASSEMBLY); + MatAssemblyEnd(matIntInt, MAT_FINAL_ASSEMBLY); + + MatAssemblyBegin(matCoarseCoarse, MAT_FINAL_ASSEMBLY); + MatAssemblyEnd(matCoarseCoarse, MAT_FINAL_ASSEMBLY); + + MatAssemblyBegin(matIntCoarse, MAT_FINAL_ASSEMBLY); + MatAssemblyEnd(matIntCoarse, MAT_FINAL_ASSEMBLY); + + MatAssemblyBegin(matCoarseInt, MAT_FINAL_ASSEMBLY); + MatAssemblyEnd(matCoarseInt, MAT_FINAL_ASSEMBLY); + + + // === Create solver for the non primal (thus local) variables. === + + KSPCreate(mpiCommInterior, &kspInterior); + KSPSetOperators(kspInterior, matIntInt, matIntInt, SAME_NONZERO_PATTERN); + KSPSetOptionsPrefix(kspInterior, "interior_"); + KSPSetType(kspInterior, KSPPREONLY); + PC pcInterior; + KSPGetPC(kspInterior, &pcInterior); + PCSetType(pcInterior, PCLU); + PCFactorSetMatSolverPackage(pcInterior, MATSOLVERUMFPACK); + KSPSetFromOptions(kspInterior); } void SubDomainSolver::fillPetscRhs(SystemVector *vec) { + FUNCNAME("SubDomainSolver::fillPetscRhs()"); + + VecCreateMPI(mpiCommCoarseSpace, + coarseSpaceMap->getRankDofs(), coarseSpaceMap->getOverallDofs(), + &rhsCoarseSpace); + + VecCreateMPI(mpiCommCoarseSpace, + interiorMap->getRankDofs(), interiorMap->getOverallDofs(), + &rhsInterior); + + for (int i = 0; i < vec->getSize(); i++) { + const FiniteElemSpace *feSpace = vec->getDOFVector(i)->getFeSpace(); + DOFVector<double>::Iterator dofIt(vec->getDOFVector(i), USED_DOFS); + for (dofIt.reset(); !dofIt.end(); ++dofIt) { + int index = dofIt.getDOFIndex(); + if (isCoarseSpace(feSpace, index)) { + index = coarseSpaceMap->getMatIndex(i, index); + VecSetValue(rhsCoarseSpace, index, *dofIt, ADD_VALUES); + } else { + index = interiorMap->getMatIndex(i, index); + VecSetValue(rhsInterior, index, *dofIt, INSERT_VALUES); + } + } + } + + VecAssemblyBegin(rhsCoarseSpace); + VecAssemblyEnd(rhsCoarseSpace); + + VecAssemblyBegin(rhsInterior); + VecAssemblyEnd(rhsInterior); } void SubDomainSolver::solvePetscMatrix(SystemVector &vec, AdaptInfo *adaptInfo) { + FUNCNAME("SubDomainSolver::solvePetscMatrix()"); + + VecDestroy(&rhsCoarseSpace); + VecDestroy(&rhsInterior); } void SubDomainSolver::destroyMatrixData() { + FUNCNAME("SubDomainSolver::destroyMatrixData()"); + + MatDestroy(&matIntInt); + MatDestroy(&matCoarseCoarse); + MatDestroy(&matCoarseInt); + MatDestroy(&matIntCoarse); + + KSPDestroy(&kspInterior); } void SubDomainSolver::solve(Vec &rhs, Vec &sol) { + KSPSolve(kspInterior, rhs, sol); + } + + + vector<const FiniteElemSpace*> SubDomainSolver::getFeSpaces(Matrix<DOFMatrix*> *mat) + { + FUNCNAME("SubDomainSolver::getFeSpaces()"); + + int nComponents = mat->getNumRows(); + vector<const FiniteElemSpace*> result(nComponents); + + for (int i = 0; i < nComponents; i++) + for (int j = 0; j < nComponents; j++) + if ((*mat)[i][j]) { + result[i] = (*mat)[i][j]->getRowFeSpace(); + break; + } + + return result; + } + + + vector<const FiniteElemSpace*> SubDomainSolver::getFeSpaces(SystemVector *vec) + { + FUNCNAME("SubDomainSolver::getFeSpaces()"); + + int nComponents = vec->getSize(); + vector<const FiniteElemSpace*> result(nComponents); + + for (int i = 0; i < nComponents; i++) + result[i] = vec->getFeSpace(i); + + return result; } + } diff --git a/AMDiS/src/parallel/SubDomainSolver.h b/AMDiS/src/parallel/SubDomainSolver.h index 782f2a577de9645df41158125d5c8edbf1e84ad0..709ea19e7644e849984d49b5c26d30492d551a2e 100644 --- a/AMDiS/src/parallel/SubDomainSolver.h +++ b/AMDiS/src/parallel/SubDomainSolver.h @@ -37,17 +37,20 @@ namespace AMDiS { class SubDomainSolver { public: SubDomainSolver(MeshDistributor *md, - MPI::Intracomm &mpiComm0, - MPI::Intracomm &mpiComm1) + MPI::Intracomm mpiComm0, + MPI::Intracomm mpiComm1) : meshDistributor(md), - coarseSpaceMpiComm(mpiComm0), - subDomainMpiComm(mpiComm1), - coarseSpace(NULL) + mpiCommCoarseSpace(mpiComm0), + mpiCommInterior(mpiComm1), + coarseSpaceMap(NULL), + interiorMap(NULL) {} - void setCoarseSpace(ParallelDofMapping *coarseDofs) + void setDofMapping(ParallelDofMapping *coarseDofs, + ParallelDofMapping *interiorDofs) { - coarseSpace = coarseDofs; + coarseSpaceMap = coarseDofs; + interiorMap = interiorDofs; } void fillPetscMatrix(Matrix<DOFMatrix*> *mat); @@ -60,14 +63,67 @@ namespace AMDiS { void solve(Vec &rhs, Vec &sol); + inline bool isCoarseSpace(const FiniteElemSpace *feSpace, DegreeOfFreedom dof) + { + return (*coarseSpaceMap)[feSpace].isSet(dof); + } + + inline Vec& getRhsCoarseSpace() + { + return rhsCoarseSpace; + } + + inline Vec& getRhsInterior() + { + return rhsInterior; + } + + inline Mat& getMatIntInt() + { + return matIntInt; + } + + inline Mat& getMatCoarseCoarse() + { + return matCoarseCoarse; + } + + inline Mat& getMatIntCoarse() + { + return matIntCoarse; + } + + inline Mat& getMatCoarseInt() + { + return matCoarseInt; + } + + protected: + /// Returns a vector with the FE spaces of each row in the matrix. Thus, the + /// resulting vector may contain the same FE space multiple times. + vector<const FiniteElemSpace*> getFeSpaces(Matrix<DOFMatrix*> *mat); + + /// Returns a vector with the FE spaces of all components of a system vector. + vector<const FiniteElemSpace*> getFeSpaces(SystemVector *vec); + protected: MeshDistributor *meshDistributor; - MPI::Intracomm coarseSpaceMpiComm; + MPI::Intracomm mpiCommCoarseSpace; + + MPI::Intracomm mpiCommInterior; + + ParallelDofMapping* coarseSpaceMap; + + ParallelDofMapping* interiorMap; + + Vec rhsCoarseSpace; + + Vec rhsInterior; - MPI::Intracomm subDomainMpiComm; + Mat matIntInt, matCoarseCoarse, matIntCoarse, matCoarseInt; - ParallelDofMapping* coarseSpace; + KSP kspInterior; }; }