40 const T *
const constraints,
41 T *
const outputScalarField,
42 const bool useCotanWeights,
44 const double logAlpha)
const {
46#ifdef TTK_ENABLE_EIGEN
48#ifdef TTK_ENABLE_OPENMP
52 if(constraintNumber < 1) {
53 this->
printErr(
"Cannot solve Laplace problem with no boundary constraints");
57 using SpMat = Eigen::SparseMatrix<T>;
58 using SpVec = Eigen::SparseVector<T>;
59 using TripletType = Eigen::Triplet<T>;
63 const auto vertexNumber = triangulation.getNumberOfVertices();
64 const auto edgeNumber = triangulation.getNumberOfEdges();
69 switch(solvingMethod) {
71 res = findBestSolver(vertexNumber, edgeNumber);
83 auto sm = findSolvingMethod();
84 std::string begMsg{
"Beginning computation... ("};
86 begMsg.append(
"cotan weights, ");
88 begMsg.append(
"discrete laplacian, ");
91 begMsg.append(
"iterative method)");
93 begMsg.append(
"Cholesky method)");
99 std::set<SimplexId> uniqueIdentifiersSet;
100 for(
SimplexId i = 0; i < constraintNumber; ++i) {
101 uniqueIdentifiersSet.insert(sources[i]);
105 std::vector<std::pair<SimplexId, T>> idValues{};
107 for(
const auto id : uniqueIdentifiersSet) {
108 for(
SimplexId j = 0; j < constraintNumber; ++j) {
109 if(
id == sources[j]) {
110 idValues.emplace_back(
id, constraints[j]);
117 size_t const uniqueConstraintNumber = idValues.size();
121 if(useCotanWeights) {
128 SpVec constraintsMat(vertexNumber);
129 for(
const auto &pair : idValues) {
131 constraintsMat.coeffRef(pair.first) = pair.second;
135 SpMat penalty(vertexNumber, vertexNumber);
139 std::vector<TripletType> triplets;
140 triplets.reserve(uniqueConstraintNumber);
141 for(
const auto &pair : idValues) {
142 triplets.emplace_back(TripletType(pair.first, pair.first, alpha));
144#ifndef __clang_analyzer__
145 penalty.setFromTriplets(triplets.begin(), triplets.end());
153 res = solve<SpMat, SpVec, Eigen::SimplicialCholesky<SpMat>>(
154 lap, penalty, constraintsMat, sol);
157 res = solve<SpMat, SpVec,
158 Eigen::ConjugateGradient<SpMat, Eigen::Upper | Eigen::Lower>>(
159 lap, penalty, constraintsMat, sol);
163 auto info =
static_cast<Eigen::ComputationInfo
>(res);
165 case Eigen::ComputationInfo::NumericalIssue:
168 case Eigen::ComputationInfo::NoConvergence:
171 case Eigen::ComputationInfo::InvalidInput:
179 Eigen::Matrix<T, Eigen::Dynamic, 1> solDense(sol);
182#ifdef TTK_ENABLE_OPENMP
183#pragma omp parallel for num_threads(threadNumber_)
185 for(
SimplexId i = 0; i < vertexNumber; ++i) {
187 outputScalarField[i] = -solDense(i, 0);
203 std::vector<std::string>{
204 "Eigen support disabled, computation skipped!",
205 "Please re-compile TTK with Eigen support to enable this feature."},
int execute(const TriangulationType &triangulation, const SimplexId constraintNumber, const SimplexId *const sources, const T *const constraints, T *const outputScalarField, const bool useCotanWeights=true, const SolvingMethodUserType solvingMethod=SolvingMethodUserType::AUTO, const double logAlpha=5.0) const
int discreteLaplacian(SparseMatrixType &output, const Debug &dbg, const TriangulationType &triangulation)
Compute the Laplacian matrix of the graph.
int cotanWeights(SparseMatrixType &output, const Debug &dbg, const TriangulationType &triangulation)
Compute the Laplacian matrix of the graph using the cotangente weights method.
printMsg(debug::output::BOLD+" | | | | | . \\ | | (__| | / __/| |_| / __/| (_) |"+debug::output::ENDCOLOR, debug::Priority::PERFORMANCE, debug::LineMode::NEW, stream)