15 const double absolute_threshold,
16 const unsigned int max_iterations)
22 <<
" target points and " << this->source_density.size() <<
" source points" <<
Color::reset << std::endl;
27 barycenters.resize(this->target_points.size());
28 for (
size_t i = 0; i < barycenters.size(); ++i) {
29 barycenters[i] = this->target_points[i];
31 barycenters_prev.resize(this->target_points.size());
32 for (
size_t i = 0; i < barycenters_prev.size(); ++i) {
33 barycenters_prev[i] = this->target_points[i];
37 for (
unsigned int n_iter = 0; n_iter < max_iterations; ++n_iter)
39 run_sot_iteration(n_iter);
40 run_centroid_iteration(n_iter);
42 compute_step_norm(barycenters, barycenters_prev, l2_norm);
45 barycenters_prev = barycenters;
47 if (l2_norm < absolute_threshold) {
49 << n_iter + 1 <<
" iterations with L2 norm: " << l2_norm
50 <<
" < threshold: " << absolute_threshold <<
Color::reset << std::endl;
54 << n_iter + 1 <<
" iterations with L2 norm: " << l2_norm
55 <<
" > threshold: " << absolute_threshold <<
Color::reset << std::endl;
56 this->sot_solver->setup_target(
57 barycenters, this->target_density);
59 this->pcout << std::endl;
65 const std::vector<Point<spacedim>>& barycenters_next,
66 const std::vector<Point<spacedim>>& barycenters_prev,
69 Assert(barycenters_next.size() == barycenters_prev.size(),
70 ExcDimensionMismatch(barycenters_next.size(), barycenters_prev.size()));
74 for (
size_t i = 0; i < barycenters_next.size(); ++i) {
75 l2_norm += barycenters_next[i].distance_square(barycenters_prev[i]);
79 l2_norm = std::sqrt(l2_norm / barycenters_next.size());
84 const unsigned int n_iter)
86 this->pcout << std::endl <<
Color::yellow <<
Color::bold <<
"Starting weighted barycenter iteration " << n_iter+1 <<
" with " << barycenters.size()
99 this->pcout <<
"Using epsilon scaling with EpsilonScalingHandler:" << std::endl
100 <<
" Initial epsilon: " << solver_config.
epsilon << std::endl
104 std::vector<std::vector<double>> epsilon_distribution =
105 this->epsilon_scaling_handler->compute_epsilon_distribution(1);
107 if (!epsilon_distribution.empty() && !epsilon_distribution[0].empty()) {
108 const auto& epsilon_sequence = epsilon_distribution[0];
111 for (
size_t i = 0; i < epsilon_sequence.size(); ++i) {
112 this->pcout <<
"\nEpsilon scaling step " << i + 1 <<
"/" << epsilon_sequence.size()
113 <<
" (ε = " << epsilon_sequence[i] <<
")" << std::endl;
115 solver_config.
epsilon = epsilon_sequence[i];
118 this->sot_solver->evaluate_weighted_barycenters(
119 potential, barycenters, solver_config);
121 }
catch (
const SolverControl::NoConvergence& exc) {
122 if (exc.last_step >= this->solver_params.max_iterations) {
123 this->pcout <<
Color::red <<
Color::bold <<
" Warning: Barycenter evaluation failed at step " << i + 1
124 <<
" (epsilon=" << epsilon_sequence[i] <<
"): Max iterations reached"
133 this->sot_solver->evaluate_weighted_barycenters(
134 potential, barycenters, solver_config);
135 }
catch (
const SolverControl::NoConvergence& exc) {
139 }
catch (
const std::exception &e){
146 MPI_Comm_rank(this->mpi_communicator, &rank);
148 std::string filename =
"barycenters_" + std::to_string(n_iter) +
".ply";
149 std::ofstream out(filename);
153 out <<
"format ascii 1.0\n";
154 out <<
"element vertex " << barycenters.size() <<
"\n";
155 for (
unsigned int d = 0; d < spacedim; ++d) {
156 out <<
"property float " << (d == 0 ?
'x' : (d == 1 ?
'y' :
'z')) <<
"\n";
158 out <<
"end_header\n";
161 for (
const auto& point : barycenters) {
162 for (
unsigned int d = 0; d < spacedim; ++d) {
163 out << point[d] <<
" ";
168 this->pcout <<
"Barycenters saved to " << filename << std::endl << std::endl;
181 const unsigned int n_iter)
183 this->pcout <<
Color::yellow <<
Color::bold <<
"Starting SOT iteration " << n_iter+1 <<
" with " << this->target_points.size()
184 <<
" target points and " << this->source_density.size() <<
" source points" <<
Color::reset << std::endl;
187 Assert(this->sot_solver->source_measure.initialized,
188 ExcMessage(
"Source measure must be set before running SOT iteration"));
189 Assert(this->sot_solver->target_measure.initialized,
190 ExcMessage(
"Target points must be set before running SOT iteration"));
198 potential.reinit(this->target_points.size());
203 this->pcout <<
"Using epsilon scaling with EpsilonScalingHandler:" << std::endl
204 <<
" Initial epsilon: " << solver_config.
epsilon << std::endl
208 std::vector<std::vector<double>> epsilon_distribution =
209 this->epsilon_scaling_handler->compute_epsilon_distribution(1);
211 if (!epsilon_distribution.empty() && !epsilon_distribution[0].empty())
213 const auto &epsilon_sequence = epsilon_distribution[0];
216 for (
size_t i = 0; i < epsilon_sequence.size(); ++i)
218 this->pcout <<
"\nEpsilon scaling step " << i + 1 <<
"/" << epsilon_sequence.size()
219 <<
" (ε = " << epsilon_sequence[i] <<
")" << std::endl;
221 solver_config.
epsilon = epsilon_sequence[i];
225 this->sot_solver->solve(potential, solver_config);
228 if (i < epsilon_sequence.size() - 1)
230 std::string eps_suffix =
"_eps" + std::to_string(i + 1);
231 this->save_results(potential,
"potential" + eps_suffix);
234 catch (
const SolverControl::NoConvergence &exc)
236 if (exc.last_step >= this->solver_params.max_iterations)
239 <<
" (epsilon=" << epsilon_sequence[i] <<
"): Max iterations reached"
251 this->sot_solver->solve(potential, solver_config);
253 catch (
const SolverControl::NoConvergence &exc)
259 catch (
const std::exception &e)
265 this->save_results(potential,
"potentials");
268 const double total_time = timer.wall_time();
271 if (Utilities::MPI::this_mpi_process(this->mpi_communicator) == 0) {
273 fs::create_directories(eps_dir);
274 std::ofstream conv_info(eps_dir +
"/convergence_info.txt");
275 conv_info <<
"Regularization parameter (ε): " << solver_config.
epsilon <<
"\n";
276 conv_info <<
"Number of iterations: " << this->sot_solver->get_last_iteration_count() <<
"\n";
277 conv_info <<
"Final function value: " << this->sot_solver->get_last_functional_value() <<
"\n";
278 conv_info <<
"Last threshold value: " << this->sot_solver->get_last_distance_threshold() <<
"\n";
279 conv_info <<
"Total execution time: " << total_time <<
" seconds\n";
280 conv_info <<
"Convergence achieved: " << this->sot_solver->get_convergence_status() <<
"\n";
287 param_manager_lloyd.print_parameters();
289 if (this->solver_params.use_epsilon_scaling) {
290 this->epsilon_scaling_handler = std::make_unique<EpsilonScalingHandler>(
291 this->mpi_communicator,
292 this->solver_params.epsilon,
293 this->solver_params.epsilon_scaling_factor,
294 this->solver_params.epsilon_scaling_steps
298 if (this->selected_task ==
"lloyd")
304 this->pcout <<
"No valid task selected" << std::endl;
void compute_step_norm(const std::vector< Point< spacedim > > &barycenters_next, const std::vector< Point< spacedim > > &barycenters_prev, double &l2_norm)
Computes the L2 norm of the step.