205 precice::profiling::Event ePreCompute(
"map.pet.preComputeMapping.From" + this->input()->getName() +
"To" + this->output()->getName());
213 PRECICE_ASSERT(this->input()->getDimensions() == this->output()->getDimensions(),
214 this->input()->getDimensions(), this->output()->getDimensions());
215 int const dimensions = this->input()->getDimensions();
219 inMesh = this->output();
220 outMesh = this->input();
222 inMesh = this->input();
223 outMesh = this->output();
230 if (_commState->rank() <= 0)
231 for (
size_t i = 0; i < polyparams; i++)
237 myIndizes.
push_back(v.getGlobalIndex() + polyparams);
239 auto n = myIndizes.
size();
241 auto outputSize = outMesh->nVertices();
243 PetscErrorCode ierr = 0;
244 PRECICE_DEBUG(
"inMesh->nVertices() = {}", inMesh->nVertices());
245 PRECICE_DEBUG(
"outMesh->nVertices() = {}", outMesh->nVertices());
251 _matrixC.init(n, n, PETSC_DETERMINE, PETSC_DETERMINE, MATSBAIJ);
253 ierr = MatSetOption(_matrixC, MAT_SYMMETRIC, PETSC_TRUE);
255 ierr = MatSetOption(_matrixC, MAT_SYMMETRY_ETERNAL, PETSC_TRUE);
259 _matrixQ.init(n, PETSC_DETERMINE, PETSC_DETERMINE, sepPolyparams, MATDENSE);
260 PRECICE_DEBUG(
"Set matrix Q to local size {} x {}", n, sepPolyparams);
263 _matrixV.init(outputSize, PETSC_DETERMINE, PETSC_DETERMINE, sepPolyparams, MATDENSE);
264 PRECICE_DEBUG(
"Set matrix V to local size {} x {}", outputSize, sepPolyparams);
267 _matrixA.init(outputSize, n, PETSC_DETERMINE, PETSC_DETERMINE, MATAIJ);
268 PRECICE_DEBUG(
"Set matrix A to local size {} x {}", outputSize, n);
270 eCreateMatrices.
stop();
273 auto const ownerRangeABegin = _matrixA.ownerRange().first;
274 auto const ownerRangeAEnd = _matrixA.ownerRange().second;
277 ierr = AOCreateMapping(_commState->comm, myIndizes.
size(), myIndizes.
data(),
nullptr, &_AOmapping);
282 Eigen::VectorXd
distance(dimensions);
289 VertexData vertexData = bgPreallocationMatrixC(inMesh);
296 PetscInt
const idxSize =
std::max(_matrixC.getSize().second, _matrixQ.getSize().second);
301 PetscInt row = _matrixC.ownerRange().first + localPolyparams;
302 for (
const mesh::Vertex &inVertex : inMesh->vertices()) {
303 if (not inVertex.isOwner())
310 colIdx[colNum] = colNum;
311 rowVals[colNum++] = 1;
313 for (
int dim = 0; dim < dimensions; dim++) {
314 if (not this->_deadAxis[dim]) {
315 colIdx[colNum] = colNum;
316 rowVals[colNum++] = inVertex.coord(dim);
322 ierr = MatSetValues(_matrixC, colNum, colIdx.
data(), 1, &row, rowVals.
data(), INSERT_VALUES);
325 ierr = MatSetValues(_matrixQ, 1, &row, colNum, colIdx.
data(), rowVals.
data(), INSERT_VALUES);
333 auto const &rowVertices = vertexData[preallocRow];
334 for (
const auto &vertex : rowVertices) {
335 rowVals[colNum] = this->_basisFunction.evaluate(vertex.second);
336 colIdx[colNum++] = vertex.first;
340 ierr = AOApplicationToPetsc(_AOmapping, colNum, colIdx.
data());
342 ierr = MatSetValues(_matrixC, 1, &row, colNum, colIdx.
data(), rowVals.
data(), INSERT_VALUES);
351 _matrixC.assemble(MAT_FLUSH_ASSEMBLY);
352 auto zeros = petsc::Vector::allocate(_matrixC);
353 VecZeroEntries(zeros);
356 MatDiagonalSet(_matrixC, zeros, ADD_VALUES);
359 ierr = MatAssemblyBegin(_matrixC, MAT_FINAL_ASSEMBLY);
361 ierr = MatAssemblyBegin(_matrixQ, MAT_FINAL_ASSEMBLY);
364 vertexData = bgPreallocationMatrixA(inMesh, outMesh);
367 colIdx.
resize(
std::max(_matrixA.getSize().second, _matrixV.getSize().second));
369 rowVals.
resize(
std::max(_matrixA.getSize().second, _matrixV.getSize().second));
375 for (PetscInt row = ownerRangeABegin; row < ownerRangeAEnd; ++row) {
376 mesh::Vertex const &oVertex = outMesh->vertex(row - _matrixA.ownerRange().first);
383 colIdx[colNum] = colNum;
384 rowVals[colNum++] = 1;
386 for (
int dim = 0; dim < dimensions; dim++) {
387 if (not this->_deadAxis[dim]) {
388 colIdx[colNum] = colNum;
389 rowVals[colNum++] = oVertex.
coord(dim);
392 ierr = MatSetValues(*m, 1, &row, colNum, colIdx.
data(), rowVals.
data(), INSERT_VALUES);
400 auto const &rowVertices = vertexData[row - ownerRangeABegin];
401 for (
const auto &vertex : rowVertices) {
402 rowVals[colNum] = this->_basisFunction.evaluate(vertex.second);
403 colIdx[colNum++] = vertex.first;
406 ierr = AOApplicationToPetsc(_AOmapping, colNum, colIdx.
data());
408 ierr = MatSetValues(_matrixA, 1, &row, colNum, colIdx.
data(), rowVals.
data(), INSERT_VALUES);
417 ierr = MatAssemblyBegin(_matrixA, MAT_FINAL_ASSEMBLY);
420 ierr = MatAssemblyEnd(_matrixC, MAT_FINAL_ASSEMBLY);
422 ierr = MatAssemblyEnd(_matrixQ, MAT_FINAL_ASSEMBLY);
424 ierr = MatAssemblyEnd(_matrixA, MAT_FINAL_ASSEMBLY);
435 KSPGetPC(_QRsolver, &pc);
436 PCSetType(pc, PCNONE);
437 KSPSetType(_QRsolver, KSPLSQR);
438 KSPSetOperators(_QRsolver, _matrixQ, _matrixQ);
442 KSPSetOperators(_solver, _matrixC, _matrixC);
453 KSPSetTolerances(_solver, _solverRtol, PETSC_DEFAULT, 1e30, PETSC_DEFAULT);
454 KSPSetInitialGuessNonzero(_solver, PETSC_TRUE);
456 KSPSetOptionsPrefix(_solver,
"solverC_");
457 KSPSetFromOptions(_solver);
473 auto rhs = petsc::Vector::allocate(_matrixC);
474 auto rescalingCoeffs = petsc::Vector::allocate(_matrixC);
477 if (_solver.solve(rhs, rescalingCoeffs) == petsc::KSPSolver::SolverResult::Converged) {
478 PRECICE_INFO(
"Using rescaling. {}", _solver.summaryFor(rhs));
480 PRECICE_WARN(
"Deactivating rescaling! {}", _solver.summaryFor(rhs));
481 useRescaling =
false;
484 eRescaling.
addData(
"Iterations", _solver.getIterationNumber());
485 ierr = MatCreateVecs(_matrixA,
nullptr, &oneInterpolant.vector);
487 ierr = MatMult(_matrixA, rescalingCoeffs, oneInterpolant);
490 ierr = PRECICE_VecFilter(oneInterpolant, 1e-6);
494 this->_hasComputedMapping =
true;
496 PRECICE_DEBUG(
"Number of mallocs for matrix C = {}", _matrixC.getInfo(MAT_LOCAL).mallocs);
497 PRECICE_DEBUG(
"Non-zeros allocated / used / unused for matrix C = {} / {} / {}",
498 _matrixC.getInfo(MAT_LOCAL).nz_allocated, _matrixC.getInfo(MAT_LOCAL).nz_used, _matrixC.getInfo(MAT_LOCAL).nz_unneeded);
499 PRECICE_DEBUG(
"Number of mallocs for matrix A = {}", _matrixA.getInfo(MAT_LOCAL).mallocs);
500 PRECICE_DEBUG(
"Non-zeros allocated / used / unused for matrix A = {} / {} / {}",
501 _matrixA.getInfo(MAT_LOCAL).nz_allocated, _matrixA.getInfo(MAT_LOCAL).nz_used, _matrixA.getInfo(MAT_LOCAL).nz_unneeded);
569 PetscErrorCode ierr = 0;
570 auto const & inValues = inData.
values;
571 auto & outValues = outData;
573 int const valueDim = inData.
dataDims;
576 auto out = petsc::Vector::allocate(_matrixA,
"out");
577 auto in = petsc::Vector::allocate(_matrixC,
"in");
578 auto a = petsc::Vector::allocate(_matrixQ,
"a", petsc::Vector::RIGHT);
580 PetscScalar
const *vecArray;
583 for (
int dim = 0; dim < valueDim; dim++) {
584 printMappingInfo(dim);
588 inVals.
reserve(this->input()->nVertices());
590 inIdx.
reserve(this->input()->nVertices());
591 for (
size_t i = 0; i < this->input()->nVertices(); ++i) {
592 if (not this->input()->vertex(i).isOwner())
597 ierr = VecSetValues(in, inIdx.
size(), inIdx.
data(), inVals.
data(), INSERT_VALUES);
602 switch (_QRsolver.solve(in, a)) {
603 case (petsc::KSPSolver::SolverResult::Converged):
604 PRECICE_DEBUG(
"The polynomial QR system of the RBF mapping from mesh {} to mesh {} converged. {}",
605 this->input()->getName(), this->output()->getName(), _QRsolver.summaryFor(in));
607 case (petsc::KSPSolver::SolverResult::Stopped):
608 PRECICE_WARN(
"The polynomial QR system of the RBF mapping from mesh {} to mesh {} has not converged. "
609 "This means most probably that the mapping problem is not well-posed or your relative tolerance is too conservative. "
610 "Please check if your coupling meshes are correct. "
611 "Maybe you need to fix axis-aligned mapping setups by marking perpendicular axes as dead? {}",
612 this->input()->getName(), this->output()->getName(), _QRsolver.summaryFor(in));
614 case (petsc::KSPSolver::SolverResult::Diverged):
615 KSPView(_QRsolver, PETSC_VIEWER_STDOUT_WORLD);
616 PRECICE_ERROR(
"The polynomial QR system of the RBF mapping from mesh {} to mesh {} has diverged. "
617 "This means most probably that the mapping problem is not well-posed. "
618 "Please check if your coupling meshes are correct. "
619 "Maybe you need to fix axis-aligned mapping setups by marking perpendicular axes as dead? {}",
620 this->input()->getName(), this->output()->getName(), _QRsolver.summaryFor(in));
626 MatMultAdd(_matrixQ, a, in, in);
630 loadInitialGuessForDim(dim, valueDim, p);
633 const auto solverResult = _solver.solve(in, p);
634 eSolve.
addData(
"Iterations", _solver.getIterationNumber());
637 storeInitialGuessForDim(dim, valueDim, p);
639 switch (solverResult) {
640 case (petsc::KSPSolver::SolverResult::Converged):
641 PRECICE_DEBUG(
"The linear system of the RBF mapping from mesh {} to mesh {} converged. {}",
642 this->input()->getName(), this->output()->getName(), _solver.summaryFor(in));
644 case (petsc::KSPSolver::SolverResult::Stopped):
645 PRECICE_WARN(
"The linear system of the RBF mapping from mesh {} to mesh {} has not converged. "
646 "This means most probably that the mapping problem is not well-posed or your relative tolerance is too conservative. "
647 "Please check if your coupling meshes are correct. "
648 "Maybe you need to fix axis-aligned mapping setups by marking perpendicular axes as dead? {}",
649 this->input()->getName(), this->output()->getName(), _solver.summaryFor(in));
651 case (petsc::KSPSolver::SolverResult::Diverged):
652 KSPView(_solver, PETSC_VIEWER_STDOUT_WORLD);
653 PRECICE_ERROR(
"The linear system of the RBF mapping from mesh {} to mesh {} has diverged. "
654 "This means most probably that the mapping problem is not well-posed. "
655 "Please check if your coupling meshes are correct. "
656 "Maybe you need to fix axis-aligned mapping setups by marking perpendicular axes as dead? {}",
657 this->input()->getName(), this->output()->getName(), _solver.summaryFor(in));
661 ierr = MatMult(_matrixA, p,
out);
665 ierr = VecPointwiseDivide(
out,
out, oneInterpolant);
671 ierr = VecScale(a, -1);
673 ierr = MatMultAdd(_matrixV, a,
out,
out);
676 PRECICE_VecFilter(
out, 1e-9);
679 ierr = VecGetArrayRead(
out, &vecArray);
681 int size =
out.getLocalSize();
682 for (
int i = 0; i < size; i++) {
683 outValues[i * valueDim + dim] = vecArray[i];
686 VecRestoreArrayRead(
out, &vecArray);
696 PetscErrorCode ierr = 0;
697 auto const & inValues = inData.
values;
698 auto & outValues = outData;
700 int const valueDim = inData.
dataDims;
703 auto au = petsc::Vector::allocate(_matrixA,
"au", petsc::Vector::RIGHT);
704 auto in = petsc::Vector::allocate(_matrixA,
"in");
705 int inRangeStart, inRangeEnd;
706 std::tie(inRangeStart, inRangeEnd) = in.ownerRange();
707 for (
int dim = 0; dim < valueDim; dim++) {
708 printMappingInfo(dim);
711 for (
size_t i = 0; i < this->input()->nVertices(); i++) {
712 auto const globalIndex = this->input()->vertex(i).getGlobalIndex();
713 if (globalIndex >= inRangeStart and globalIndex < inRangeEnd)
714 ierr = VecSetValue(in, globalIndex, inValues[i * valueDim + dim], INSERT_VALUES);
723 auto epsilon = petsc::Vector::allocate(_matrixV,
"epsilon", petsc::Vector::RIGHT);
725 ierr = MatMultTranspose(_matrixV, in, epsilon);
727 auto eta = petsc::Vector::allocate(_matrixA,
"eta", petsc::Vector::RIGHT);
728 ierr = MatMultTranspose(_matrixA, in, eta);
730 auto mu = petsc::Vector::allocate(_matrixC,
"mu", petsc::Vector::LEFT);
731 loadInitialGuessForDim(dim, valueDim, mu);
732 _solver.solve(eta, mu);
733 storeInitialGuessForDim(dim, valueDim, mu);
734 VecScale(epsilon, -1);
735 auto tau = petsc::Vector::allocate(_matrixQ,
"tau", petsc::Vector::RIGHT);
737 ierr = MatMultTransposeAdd(_matrixQ, mu, epsilon, tau);
739 auto sigma = petsc::Vector::allocate(_matrixQ,
"sigma", petsc::Vector::LEFT);
741 switch (_QRsolver.solveTranspose(tau, sigma)) {
742 case (petsc::KSPSolver::SolverResult::Converged):
743 PRECICE_DEBUG(
"The polynomial linear system of the RBF mapping from mesh {} to mesh {} converged. {}",
744 this->input()->getName(), this->output()->getName(), _QRsolver.summaryFor(tau));
746 case (petsc::KSPSolver::SolverResult::Stopped):
747 PRECICE_WARN(
"The polynomial linear system of the RBF mapping from mesh {} to mesh {} has not converged. "
748 "This means most probably that the mapping problem is not well-posed or your relative tolerance is too conservative. "
749 "Please check if your coupling meshes are correct. "
750 "Maybe you need to fix axis-aligned mapping setups by marking perpendicular axes as dead? {}",
751 this->input()->getName(), this->output()->getName(), _QRsolver.summaryFor(tau));
753 case (petsc::KSPSolver::SolverResult::Diverged):
754 KSPView(_QRsolver, PETSC_VIEWER_STDOUT_WORLD);
755 PRECICE_ERROR(
"The polynomial linear system of the RBF mapping from mesh {} to mesh {} "
756 "has diverged. This means most probably that the mapping problem is not well-posed. "
757 "Please check if your coupling meshes are correct. "
758 "Maybe you need to fix axis-aligned mapping setups by marking perpendicular axes as dead? {}",
759 this->input()->getName(), this->output()->getName(), _QRsolver.summaryFor(tau));
763 VecWAXPY(
out, -1, sigma, mu);
765 ierr = MatMultTranspose(_matrixA, in, au);
768 loadInitialGuessForDim(dim, valueDim,
out);
771 const auto solverResult = _solver.solve(au,
out);
772 eSolve.
addData(
"Iterations", _solver.getIterationNumber());
775 storeInitialGuessForDim(dim, valueDim,
out);
777 switch (solverResult) {
778 case (petsc::KSPSolver::SolverResult::Converged):
779 PRECICE_DEBUG(
"The linear system of the RBF mapping from mesh {} to mesh {} converged. {}",
780 this->input()->getName(), this->output()->getName(), _solver.summaryFor(au));
782 case (petsc::KSPSolver::SolverResult::Stopped):
783 PRECICE_WARN(
"The linear system of the RBF mapping from mesh {} to mesh {} has not converged. "
784 "This means most probably that the mapping problem is not well-posed or your relative tolerance is too conservative. "
785 "Please check if your coupling meshes are correct. "
786 "Maybe you need to fix axis-aligned mapping setups by marking perpendicular axes as dead? {}",
787 this->input()->getName(), this->output()->getName(), _solver.summaryFor(au));
789 case (petsc::KSPSolver::SolverResult::Diverged):
790 KSPView(_solver, PETSC_VIEWER_STDOUT_WORLD);
791 PRECICE_ERROR(
"The linear system of the RBF mapping from mesh {} to mesh {} "
792 "has diverged. This means most probably that the mapping problem is not well-posed. "
793 "Please check if your coupling meshes are correct. "
794 "Maybe you need to fix axis-aligned mapping setups by marking perpendicular axes as dead? {}",
795 this->input()->getName(), this->output()->getName(), _solver.summaryFor(au));
800 PRECICE_VecFilter(
out, 1e-9);
803 const PetscScalar *outArray;
804 VecGetArrayRead(
out, &outArray);
806 int count = 0, ownerCount = 0;
807 for (
const mesh::Vertex &vertex : this->output()->vertices()) {
808 if (vertex.isOwner()) {
809 outValues[count * valueDim + dim] = outArray[ownerCount + localPolyparams];
816 VecRestoreArrayRead(
out, &outArray);
844 PRECICE_INFO(
"Using tree-based preallocation for matrix C");
848 std::tie(n, std::ignore) = _matrixC.getLocalSize();
851 const double supportRadius = this->_basisFunction.getSupportRadius();
853 const int dimensions = this->input()->getDimensions();
854 Eigen::VectorXd
distance(dimensions);
856 PetscInt colOwnerRangeCBegin, colOwnerRangeCEnd;
857 std::tie(colOwnerRangeCBegin, colOwnerRangeCEnd) = _matrixC.ownerRangeColumn();
861 size_t local_row = 0;
864 for (local_row = 0; local_row < localPolyparams; local_row++) {
865 d_nnz[local_row] = colOwnerRangeCEnd - colOwnerRangeCBegin;
866 o_nnz[local_row] = _matrixC.getSize().first - d_nnz[local_row];
870 for (
const mesh::Vertex &inVertex : inMesh->vertices()) {
871 if (not inVertex.isOwner())
874 PetscInt col = polyparams;
875 PetscInt
const global_row = local_row + _matrixC.ownerRange().first;
876 d_nnz[local_row] = 0;
877 o_nnz[local_row] = 0;
881 for (
auto const i : inMesh->index().getVerticesInsideBox(inVertex, supportRadius)) {
885 AOApplicationToPetsc(_AOmapping, 1, &mappedCol);
887 if (global_row > mappedCol)
891 for (
int d = 0; d < dimensions; d++)
892 if (this->_deadAxis[d])
895 double const norm =
distance.norm();
896 if (supportRadius > norm or col == global_row) {
898 if (mappedCol >= colOwnerRangeCBegin and mappedCol < colOwnerRangeCEnd)
908 if (_commState->size() == 1) {
909 MatSeqSBAIJSetPreallocation(_matrixC, _matrixC.blockSize(), 0, d_nnz.data());
911 MatMPISBAIJSetPreallocation(_matrixC, _matrixC.blockSize(), 0, d_nnz.data(), 0, o_nnz.
data());
913 MatSetOption(_matrixC, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_TRUE);
924 PRECICE_INFO(
"Using tree-based preallocation for matrix A");
927 PetscInt ownerRangeABegin, ownerRangeAEnd, colOwnerRangeABegin, colOwnerRangeAEnd;
928 PetscInt
const outputSize = _matrixA.getLocalSize().first;
929 double const supportRadius = this->_basisFunction.getSupportRadius();
931 std::tie(ownerRangeABegin, ownerRangeAEnd) = _matrixA.ownerRange();
932 std::tie(colOwnerRangeABegin, colOwnerRangeAEnd) = _matrixA.ownerRangeColumn();
933 const int dimensions = this->input()->getDimensions();
936 Eigen::VectorXd
distance(dimensions);
941 for (
int localRow = 0; localRow < ownerRangeAEnd - ownerRangeABegin; ++localRow) {
945 mesh::Vertex const &oVertex = outMesh->vertex(localRow);
950 if (col >= colOwnerRangeABegin and col < colOwnerRangeAEnd)
956 for (
int dim = 0; dim < dimensions; dim++) {
957 if (not this->_deadAxis[dim]) {
958 if (col >= colOwnerRangeABegin and col < colOwnerRangeAEnd)
968 for (
auto i : inMesh->index().getVerticesInsideBox(oVertex, supportRadius)) {
972 for (
int d = 0; d < dimensions; d++)
973 if (this->_deadAxis[d])
976 double const norm =
distance.norm();
977 if (supportRadius > norm) {
981 AOApplicationToPetsc(_AOmapping, 1, &col);
982 if (col >= colOwnerRangeABegin and col < colOwnerRangeAEnd)
989 if (_commState->size() == 1) {
990 MatSeqAIJSetPreallocation(_matrixA, 0, d_nnz.data());
992 MatMPIAIJSetPreallocation(_matrixA, 0, d_nnz.data(), 0, o_nnz.
data());
994 MatSetOption(_matrixA, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_TRUE);