2020-11-27 11:47:21 +01:00
|
|
|
#ifndef SIMULATIONHISTORYPLOTTER_HPP
|
|
|
|
#define SIMULATIONHISTORYPLOTTER_HPP
|
|
|
|
|
2021-04-08 20:03:23 +02:00
|
|
|
#include "simulationmesh.hpp"
|
|
|
|
#include "simulation_structs.hpp"
|
2020-11-27 11:47:21 +01:00
|
|
|
#include "utilities.hpp"
|
|
|
|
#include <algorithm>
|
|
|
|
#include <matplot/matplot.h>
|
|
|
|
|
|
|
|
struct SimulationResultsReporter {
|
|
|
|
using VertexType = VCGEdgeMesh::VertexType;
|
|
|
|
using CoordType = VCGEdgeMesh::CoordType;
|
|
|
|
|
|
|
|
SimulationResultsReporter() {}
|
|
|
|
|
|
|
|
void writeStatistics(const SimulationResults &results,
|
|
|
|
const std::string &reportFolderPath) {
|
|
|
|
|
|
|
|
ofstream file;
|
|
|
|
file.open(
|
|
|
|
std::filesystem::path(reportFolderPath).append("results.txt").string());
|
|
|
|
|
|
|
|
const size_t numberOfSteps = results.history.numberOfSteps;
|
|
|
|
file << "Number of steps " << numberOfSteps << "\n";
|
|
|
|
|
|
|
|
// file << "Force threshold used " << 1000 << "\n";
|
|
|
|
|
|
|
|
// assert(numberOfSteps == results.history.potentialEnergy.size() &&
|
|
|
|
// numberOfSteps == results.history.residualForces.size());
|
|
|
|
// Write kinetic energies
|
|
|
|
const SimulationHistory &history = results.history;
|
|
|
|
if (!history.kineticEnergy.empty()) {
|
|
|
|
file << "Kinetic energies"
|
|
|
|
<< "\n";
|
|
|
|
for (size_t step = 0; step < numberOfSteps; step++) {
|
|
|
|
file << history.kineticEnergy[step] << "\n";
|
|
|
|
}
|
|
|
|
file << "\n";
|
|
|
|
}
|
|
|
|
|
2021-06-24 09:02:20 +02:00
|
|
|
if (!history.logResidualForces.empty()) {
|
|
|
|
file << "Residual forces"
|
|
|
|
<< "\n";
|
|
|
|
for (size_t step = 0; step < numberOfSteps; step++) {
|
|
|
|
file << history.logResidualForces[step] << "\n";
|
|
|
|
}
|
|
|
|
file << "\n";
|
2020-11-27 11:47:21 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!history.potentialEnergies.empty()) {
|
|
|
|
file << "Potential energies"
|
|
|
|
<< "\n";
|
|
|
|
for (size_t step = 0; step < numberOfSteps; step++) {
|
|
|
|
file << history.potentialEnergies[step] << "\n";
|
|
|
|
}
|
|
|
|
file << "\n";
|
|
|
|
}
|
|
|
|
file.close();
|
|
|
|
}
|
|
|
|
|
2021-06-24 09:02:20 +02:00
|
|
|
void reportHistory(const SimulationHistory &history,
|
|
|
|
const std::string &reportFolderPath,
|
|
|
|
const std::string &graphSuffix = std::string())
|
|
|
|
{
|
|
|
|
const auto simulationResultPath = std::filesystem::path(reportFolderPath).append(history.label);
|
2021-06-30 09:28:13 +02:00
|
|
|
std::filesystem::create_directories(simulationResultPath);
|
2021-07-13 08:02:55 +02:00
|
|
|
createPlots(history, simulationResultPath.string(), graphSuffix);
|
2021-06-24 09:02:20 +02:00
|
|
|
}
|
|
|
|
|
2021-01-04 13:30:22 +01:00
|
|
|
void reportResults(const std::vector<SimulationResults> &results,
|
|
|
|
const std::string &reportFolderPath,
|
|
|
|
const std::string &graphSuffix = std::string()) {
|
2020-11-27 11:47:21 +01:00
|
|
|
if (results.empty()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// std::filesystem::remove_all(debuggerFolder);
|
|
|
|
std::filesystem::create_directory(reportFolderPath);
|
|
|
|
for (const SimulationResults &simulationResult : results) {
|
|
|
|
const auto simulationResultPath =
|
|
|
|
std::filesystem::path(reportFolderPath)
|
2021-01-04 13:30:22 +01:00
|
|
|
.append(simulationResult.getLabel());
|
2020-11-27 11:47:21 +01:00
|
|
|
std::filesystem::create_directory(simulationResultPath.string());
|
|
|
|
|
|
|
|
createPlots(simulationResult.history, simulationResultPath.string(),
|
|
|
|
graphSuffix);
|
2021-02-04 13:58:41 +01:00
|
|
|
writeStatistics(simulationResult, simulationResultPath.string());
|
2020-11-27 11:47:21 +01:00
|
|
|
}
|
|
|
|
}
|
2021-06-24 09:02:20 +02:00
|
|
|
static void createPlot(const std::string &xLabel,
|
|
|
|
const std::string &yLabel,
|
|
|
|
const std::vector<double> &x,
|
|
|
|
const std::vector<double> &y,
|
|
|
|
const std::vector<double> &markerSizes,
|
|
|
|
const std::vector<double> &c,
|
|
|
|
const std::string &saveTo = {})
|
|
|
|
{
|
|
|
|
// matplot::figure(true);
|
|
|
|
matplot::xlabel(xLabel);
|
|
|
|
matplot::ylabel(yLabel);
|
|
|
|
matplot::grid(matplot::on);
|
|
|
|
matplot::scatter(x, y, markerSizes, c)->marker_face(true);
|
|
|
|
if (!saveTo.empty()) {
|
|
|
|
matplot::save(saveTo);
|
|
|
|
}
|
2021-01-29 18:39:15 +01:00
|
|
|
}
|
|
|
|
|
2021-05-24 13:43:32 +02:00
|
|
|
static void createPlot(const std::string &xLabel,
|
|
|
|
const std::string &yLabel,
|
2021-01-29 18:39:15 +01:00
|
|
|
const std::vector<double> &YvaluesToPlot,
|
2021-06-24 09:02:20 +02:00
|
|
|
const std::string &saveTo = {},
|
|
|
|
const std::vector<size_t> &markPoints = {})
|
2021-05-24 13:43:32 +02:00
|
|
|
{
|
|
|
|
if (YvaluesToPlot.size() < 2) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
auto x = matplot::linspace(0, YvaluesToPlot.size() - 1, YvaluesToPlot.size());
|
2021-06-24 09:02:20 +02:00
|
|
|
std::vector<double> colors(x.size(), 0.5);
|
|
|
|
std::vector<double> markerSizes(x.size(), 5);
|
|
|
|
if (!markPoints.empty()) {
|
|
|
|
for (const auto pointIndex : markPoints) {
|
|
|
|
colors[pointIndex] = 0.9;
|
|
|
|
markerSizes[pointIndex] = 14;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
createPlot(xLabel, yLabel, x, YvaluesToPlot, markerSizes, colors, saveTo);
|
|
|
|
// matplot::figure(true);
|
|
|
|
// matplot::hold(matplot::on);
|
2021-05-24 13:43:32 +02:00
|
|
|
|
|
|
|
// ->marker_indices(history.redMarks)
|
|
|
|
// ->marker_indices(truncatedRedMarks)
|
|
|
|
// .marker_color("r")
|
|
|
|
// ->marker_size(1)
|
2021-06-24 09:02:20 +02:00
|
|
|
// ;
|
|
|
|
// auto greenMarksY = matplot::transform(history.greenMarks,
|
|
|
|
// [&](auto x) { return YvaluesToPlot[x]; });
|
|
|
|
// matplot::scatter(history.greenMarks, greenMarksY)->color("green").marker_size(10);
|
|
|
|
// matplot::hold(matplot::off);
|
2020-11-27 11:47:21 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void createPlots(const SimulationHistory &history,
|
|
|
|
const std::string &reportFolderPath,
|
|
|
|
const std::string &graphSuffix) {
|
|
|
|
const auto graphsFolder =
|
|
|
|
std::filesystem::path(reportFolderPath).append("Graphs");
|
|
|
|
std::filesystem::remove_all(graphsFolder);
|
|
|
|
std::filesystem::create_directory(graphsFolder.string());
|
|
|
|
|
|
|
|
if (!history.kineticEnergy.empty()) {
|
2021-05-24 13:43:32 +02:00
|
|
|
createPlot("Number of Iterations",
|
|
|
|
"Log of Kinetic Energy log",
|
|
|
|
history.kineticEnergy,
|
|
|
|
std::filesystem::path(graphsFolder)
|
|
|
|
.append("KineticEnergyLog_" + graphSuffix + ".png")
|
2021-07-16 13:16:53 +02:00
|
|
|
.string(),
|
|
|
|
history.redMarks);
|
2020-11-27 11:47:21 +01:00
|
|
|
}
|
|
|
|
|
2021-06-24 09:02:20 +02:00
|
|
|
if (!history.logResidualForces.empty()) {
|
2021-05-24 13:43:32 +02:00
|
|
|
createPlot("Number of Iterations",
|
|
|
|
"Residual Forces norm log",
|
2021-06-24 09:02:20 +02:00
|
|
|
history.logResidualForces,
|
2021-05-24 13:43:32 +02:00
|
|
|
std::filesystem::path(graphsFolder)
|
|
|
|
.append("ResidualForcesLog_" + graphSuffix + ".png")
|
2021-07-16 13:16:53 +02:00
|
|
|
.string(),
|
|
|
|
history.redMarks);
|
2020-11-27 11:47:21 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!history.potentialEnergies.empty()) {
|
2021-05-24 13:43:32 +02:00
|
|
|
createPlot("Number of Iterations",
|
|
|
|
"Potential energy",
|
|
|
|
history.potentialEnergies,
|
|
|
|
std::filesystem::path(graphsFolder)
|
|
|
|
.append("PotentialEnergy_" + graphSuffix + ".png")
|
2021-07-16 13:16:53 +02:00
|
|
|
.string(),
|
|
|
|
history.redMarks);
|
2021-05-24 13:43:32 +02:00
|
|
|
}
|
|
|
|
if (!history.residualForcesMovingAverage.empty()) {
|
|
|
|
createPlot("Number of Iterations",
|
|
|
|
"Residual forces moving average",
|
|
|
|
history.residualForcesMovingAverage,
|
|
|
|
std::filesystem::path(graphsFolder)
|
|
|
|
.append("ResidualForcesMovingAverage_" + graphSuffix + ".png")
|
2021-07-16 13:16:53 +02:00
|
|
|
.string(),
|
|
|
|
history.redMarks);
|
2021-05-24 13:43:32 +02:00
|
|
|
}
|
|
|
|
// if (!history.residualForcesMovingAverageDerivativesLog.empty()) {
|
|
|
|
// createPlot("Number of Iterations",
|
|
|
|
// "Residual forces moving average derivative log",
|
|
|
|
// history.residualForcesMovingAverageDerivativesLog,
|
|
|
|
// std::filesystem::path(graphsFolder)
|
|
|
|
// .append("ResidualForcesMovingAverageDerivativesLog_" + graphSuffix + ".png")
|
|
|
|
// .string());
|
|
|
|
// }
|
|
|
|
if (!history.sumOfNormalizedDisplacementNorms.empty()) {
|
|
|
|
createPlot("Number of Iterations",
|
|
|
|
"Sum of normalized displacement norms",
|
|
|
|
history.sumOfNormalizedDisplacementNorms,
|
|
|
|
std::filesystem::path(graphsFolder)
|
|
|
|
.append("SumOfNormalizedDisplacementNorms_" + graphSuffix + ".png")
|
2021-07-16 13:16:53 +02:00
|
|
|
.string(),
|
|
|
|
history.redMarks);
|
2020-11-27 11:47:21 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
#endif // SIMULATIONHISTORYPLOTTER_HPP
|