MySources/simulationhistoryplotter.hpp

208 lines
7.9 KiB
C++
Raw Normal View History

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";
}
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();
}
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-16 13:33:06 +02:00
createPlots(history, simulationResultPath.string(), graphSuffix);
}
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)
.append(simulationResult.getLabel());
2020-11-27 11:47:21 +01:00
std::filesystem::create_directory(simulationResultPath.string());
createPlots(simulationResult.history, simulationResultPath.string(),
graphSuffix);
writeStatistics(simulationResult, simulationResultPath.string());
2020-11-27 11:47:21 +01: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-05-24 13:43:32 +02:00
static void createPlot(const std::string &xLabel,
const std::string &yLabel,
const std::vector<double> &YvaluesToPlot,
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());
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)
// ;
// 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:33:06 +02:00
.string(),
history.redMarks);
2020-11-27 11:47:21 +01:00
}
if (!history.logResidualForces.empty()) {
2021-05-24 13:43:32 +02:00
createPlot("Number of Iterations",
"Residual Forces norm log",
history.logResidualForces,
2021-05-24 13:43:32 +02:00
std::filesystem::path(graphsFolder)
.append("ResidualForcesLog_" + graphSuffix + ".png")
2021-07-16 13:33:06 +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:33:06 +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:33:06 +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:33:06 +02:00
.string(),
history.redMarks);
2020-11-27 11:47:21 +01:00
}
}
};
#endif // SIMULATIONHISTORYPLOTTER_HPP