695 lines
30 KiB
C++
695 lines
30 KiB
C++
#include "reducedmodelevaluator.hpp"
|
|
|
|
#include <execution>
|
|
#include <filesystem>
|
|
|
|
#include "hexagonremesher.hpp"
|
|
#include "reducedmodel.hpp"
|
|
#include "reducedmodeloptimizer.hpp"
|
|
#include "simulationmodelfactory.hpp"
|
|
#include "trianglepatterngeometry.hpp"
|
|
|
|
using PatternVertexIndex = VertexIndex;
|
|
using ReducedModelVertexIndex = VertexIndex;
|
|
|
|
ReducedModelEvaluator::ReducedModelEvaluator() {
|
|
pTileIntoSurface = [&]() {
|
|
std::istringstream inputStream_tileIntoTriSurface(
|
|
tileIntoSurfaceFileContent);
|
|
VCGTriMesh tileInto_triMesh;
|
|
const bool surfaceLoadSuccessfull =
|
|
tileInto_triMesh.load(inputStream_tileIntoTriSurface);
|
|
tileInto_triMesh.setLabel("instantMeshes_plane_34");
|
|
assert(surfaceLoadSuccessfull);
|
|
return PolygonalRemeshing::remeshWithPolygons(tileInto_triMesh);
|
|
}();
|
|
}
|
|
|
|
ReducedModelEvaluator::Results ReducedModelEvaluator::evaluateReducedModel(
|
|
ReducedModelOptimization::Results& optimizationResult,
|
|
const Settings& settings) {
|
|
const std::filesystem::path scenariosDirectoryPath =
|
|
"/home/iason/Coding/Projects/Approximating shapes with flat "
|
|
"patterns/ReducedModelEvaluator/Scenarios";
|
|
const std::filesystem::path fullPatternTessellatedResultsDirectoryPath =
|
|
"/home/iason/Coding/Projects/Approximating shapes with flat "
|
|
"patterns/ReducedModelEvaluator/TessellatedResults";
|
|
|
|
return evaluateReducedModel(optimizationResult, scenariosDirectoryPath,
|
|
fullPatternTessellatedResultsDirectoryPath,
|
|
settings);
|
|
}
|
|
|
|
void ReducedModelEvaluator::printResults(const Results& evaluationResults,
|
|
const std::string& resultsLabel) {
|
|
CSVFile csvOutputToCout({}, true);
|
|
ExportingSettings exportSettings;
|
|
exportSettings.direction = Vertical;
|
|
exportSettings.shouldWriteHeader = false;
|
|
exportSettings.resultsLabel = resultsLabel;
|
|
printResults(evaluationResults, exportSettings, csvOutputToCout);
|
|
}
|
|
|
|
void ReducedModelEvaluator::printResults(
|
|
const Results& evaluationResults,
|
|
const ExportingSettings& exportingSettings,
|
|
CSVFile& csvOutput) {
|
|
if (exportingSettings.shouldWriteHeader) {
|
|
csvOutput << csvExportingDataStrings[exportingSettings.data];
|
|
printHeader(exportingSettings, csvOutput);
|
|
csvOutput << endrow;
|
|
}
|
|
if (!exportingSettings.resultsLabel.empty()) {
|
|
csvOutput << exportingSettings.resultsLabel;
|
|
}
|
|
if (exportingSettings.direction == Vertical) {
|
|
printResultsVertically(evaluationResults, csvOutput);
|
|
} else {
|
|
printResultsHorizontally(evaluationResults, csvOutput);
|
|
}
|
|
}
|
|
|
|
void ReducedModelEvaluator::printHeader(
|
|
const ExportingSettings& exportingSettings,
|
|
CSVFile& csvOutput) {
|
|
if (exportingSettings.direction == Horizontal) {
|
|
// csvOutput << "Job label";
|
|
for (int jobIndex = 0;
|
|
jobIndex < ReducedModelEvaluator::scenariosTestSetLabels.size();
|
|
jobIndex++) {
|
|
const std::string& jobLabel =
|
|
ReducedModelEvaluator::scenariosTestSetLabels[jobIndex];
|
|
csvOutput << jobLabel;
|
|
}
|
|
} else {
|
|
std::cout << "Vertical header not defined" << std::endl;
|
|
assert(false);
|
|
std::terminate();
|
|
}
|
|
}
|
|
|
|
void ReducedModelEvaluator::printResultsHorizontally(
|
|
const Results& evaluationResults,
|
|
CSVFile& csvOutput) {
|
|
// print header
|
|
// print raw error
|
|
constexpr bool shouldPrintRawError = false;
|
|
if (shouldPrintRawError) {
|
|
double sumOfFull2Reduced = 0;
|
|
int numOfNonEvaluatedScenarios = 0;
|
|
for (int jobIndex = 0;
|
|
jobIndex < ReducedModelEvaluator::scenariosTestSetLabels.size();
|
|
jobIndex++) {
|
|
const double& distance_fullDrmToReduced =
|
|
evaluationResults.distances_drm2reduced[jobIndex];
|
|
if (distance_fullDrmToReduced == -1) {
|
|
csvOutput << "notEvaluated";
|
|
numOfNonEvaluatedScenarios++;
|
|
} else {
|
|
csvOutput << distance_fullDrmToReduced;
|
|
sumOfFull2Reduced += distance_fullDrmToReduced;
|
|
}
|
|
}
|
|
}
|
|
// print normalized error
|
|
double sumOfNormalizedFull2Reduced = 0;
|
|
for (int jobIndex = 0;
|
|
jobIndex < ReducedModelEvaluator::scenariosTestSetLabels.size();
|
|
jobIndex++) {
|
|
const double& distance_normalizedFullDrmToReduced =
|
|
evaluationResults.distances_normalizedGroundTruth2reduced[jobIndex];
|
|
if (distance_normalizedFullDrmToReduced == -1) {
|
|
csvOutput << "notEvaluated";
|
|
} else {
|
|
csvOutput << distance_normalizedFullDrmToReduced;
|
|
sumOfNormalizedFull2Reduced += distance_normalizedFullDrmToReduced;
|
|
}
|
|
}
|
|
}
|
|
|
|
void ReducedModelEvaluator::printResultsVertically(
|
|
const Results& evaluationResults,
|
|
CSVFile& csvOutput) {
|
|
#ifdef POLYSCOPE_DEFINED
|
|
csvOutput << "pattern2Reduced"
|
|
<< "norm_pattern2Reduced";
|
|
#else
|
|
csvOutput << "Job Label"
|
|
<< "drm2Reduced"
|
|
<< "norm_drm2Reduced";
|
|
|
|
#endif
|
|
csvOutput << endrow;
|
|
double sumOfFull2Reduced = 0;
|
|
double sumOfNormalizedFull2Reduced = 0;
|
|
int numOfNonEvaluatedScenarios = 0;
|
|
for (int jobIndex = 0;
|
|
jobIndex < ReducedModelEvaluator::scenariosTestSetLabels.size();
|
|
jobIndex++) {
|
|
const double& distance_fullDrmToReduced =
|
|
evaluationResults.distances_drm2reduced[jobIndex];
|
|
const double& distance_normalizedFullDrmToReduced =
|
|
evaluationResults.distances_normalizedGroundTruth2reduced[jobIndex];
|
|
#ifndef POLYSCOPE_DEFINED
|
|
const std::string& jobLabel =
|
|
ReducedModelEvaluator::scenariosTestSetLabels[jobIndex];
|
|
csvOutput << jobLabel;
|
|
#endif
|
|
if (distance_fullDrmToReduced == -1) {
|
|
csvOutput << "notEvaluated"
|
|
<< "notEvaluated";
|
|
numOfNonEvaluatedScenarios++;
|
|
} else {
|
|
csvOutput << distance_fullDrmToReduced
|
|
<< distance_normalizedFullDrmToReduced;
|
|
sumOfFull2Reduced += distance_fullDrmToReduced;
|
|
sumOfNormalizedFull2Reduced += distance_normalizedFullDrmToReduced;
|
|
}
|
|
csvOutput << endrow;
|
|
}
|
|
const int numOfEvaluatedScenarios =
|
|
ReducedModelEvaluator::scenariosTestSetLabels.size() -
|
|
numOfNonEvaluatedScenarios;
|
|
const double averageDistance_full2Reduced =
|
|
sumOfFull2Reduced / numOfEvaluatedScenarios;
|
|
const double averageDistance_normalizedFull2Reduced =
|
|
sumOfNormalizedFull2Reduced / numOfEvaluatedScenarios;
|
|
#ifndef POLYSCOPE_DEFINED
|
|
csvOutput << "Average error";
|
|
#endif
|
|
csvOutput << averageDistance_full2Reduced
|
|
<< averageDistance_normalizedFull2Reduced;
|
|
csvOutput << endrow;
|
|
#ifndef POLYSCOPE_DEFINED
|
|
csvOutput << "Cumulative error";
|
|
#endif
|
|
csvOutput << sumOfFull2Reduced << sumOfNormalizedFull2Reduced;
|
|
csvOutput << endrow;
|
|
csvOutput << endrow;
|
|
}
|
|
|
|
ReducedModelEvaluator::Results ReducedModelEvaluator::evaluateReducedModel(
|
|
ReducedModelOptimization::Results& optimizationResult,
|
|
const std::filesystem::path& scenariosDirectoryPath,
|
|
const std::filesystem::path& patternTessellatedResultsDirectoryPath,
|
|
const ReducedModelEvaluator::Settings& evaluationSettings) {
|
|
std::cout << evaluationSettings.toString() << std::endl;
|
|
// Apply optimization results to the reduced model
|
|
ReducedModel reducedModel;
|
|
reducedModel.deleteDanglingVertices();
|
|
std::unordered_map<std::string, double> optimalXVariables_set(
|
|
optimizationResult.optimalXNameValuePairs.begin(),
|
|
optimizationResult.optimalXNameValuePairs.end());
|
|
reducedModel.updateBaseTriangleGeometry_R(optimalXVariables_set.at("R"));
|
|
reducedModel.updateBaseTriangleGeometry_theta(
|
|
optimalXVariables_set.at("Theta"));
|
|
|
|
// reducedModel.registerForDrawing();
|
|
|
|
// Scale tile-into surface
|
|
pTileIntoSurface->moveToCenter();
|
|
const double scaleFactor =
|
|
optimizationResult.settings.targetBaseTriangleSize /
|
|
pTileIntoSurface->getAverageFaceRadius();
|
|
vcg::tri::UpdatePosition<VCGPolyMesh>::Scale(*pTileIntoSurface, scaleFactor);
|
|
#ifdef POLYSCOPE_DEFINED
|
|
pTileIntoSurface->registerForDrawing(color_tileIntoSurface, false);
|
|
#endif
|
|
|
|
// Tile full pattern into surface
|
|
std::vector<PatternGeometry> patterns(1);
|
|
patterns[0].copy(optimizationResult.baseTrianglePattern);
|
|
patterns[0].interfaceNodeIndex = 3;
|
|
patterns[0].deleteDanglingVertices();
|
|
std::vector<int> perSurfaceFacePatternIndices(pTileIntoSurface->FN(), 0);
|
|
std::vector<std::vector<size_t>> perPatternIndexTiledFullPatternEdgeIndices;
|
|
std::vector<size_t> tileIntoEdgeToTiledFullVi;
|
|
std::shared_ptr<PatternGeometry> pTilled_pattern =
|
|
PatternGeometry::tilePattern(patterns, {}, *pTileIntoSurface,
|
|
perSurfaceFacePatternIndices,
|
|
tileIntoEdgeToTiledFullVi,
|
|
perPatternIndexTiledFullPatternEdgeIndices);
|
|
pTilled_pattern->setLabel("Tilled_pattern");
|
|
|
|
// Tile reduced pattern into surface
|
|
std::vector<PatternGeometry> reducedModels(1);
|
|
reducedModels[0].copy(reducedModel);
|
|
std::vector<std::vector<size_t>>
|
|
perPatternIndexTiledReducedPatternEdgeIndices;
|
|
std::vector<size_t> tileIntoEdgeToTiledReducedVi;
|
|
std::shared_ptr<PatternGeometry> pTilled_reducedModel =
|
|
PatternGeometry::tilePattern(
|
|
reducedModels, {0}, *pTileIntoSurface, perSurfaceFacePatternIndices,
|
|
tileIntoEdgeToTiledReducedVi,
|
|
perPatternIndexTiledReducedPatternEdgeIndices);
|
|
pTilled_reducedModel->setLabel("Tilled_reduced_model");
|
|
|
|
std::unordered_map<PatternVertexIndex, ReducedModelVertexIndex>
|
|
patternToReducedViMap; // of only the common vertices
|
|
std::unordered_map<ReducedModelVertexIndex, PatternVertexIndex>
|
|
reducedToFullViMap; // of only the common vertices
|
|
for (int ei = 0; ei < pTileIntoSurface->EN(); ei++) {
|
|
patternToReducedViMap[tileIntoEdgeToTiledFullVi[ei]] =
|
|
tileIntoEdgeToTiledReducedVi[ei];
|
|
}
|
|
constructInverseMap(patternToReducedViMap, reducedToFullViMap);
|
|
|
|
std::vector<size_t> tilledFullPatternInterfaceVi;
|
|
tilledFullPatternInterfaceVi.clear();
|
|
tilledFullPatternInterfaceVi.resize(patternToReducedViMap.size());
|
|
size_t viIndex = 0;
|
|
for (std::pair<size_t, size_t> fullToReducedPair : patternToReducedViMap) {
|
|
tilledFullPatternInterfaceVi[viIndex++] = fullToReducedPair.first;
|
|
}
|
|
|
|
// Create simulation meshes
|
|
////Tessellated full pattern simulation mesh
|
|
std::shared_ptr<SimulationEdgeMesh> pSimulationEdgeMesh_tilledPattern =
|
|
std::make_shared<SimulationEdgeMesh>(*pTilled_pattern);
|
|
pSimulationEdgeMesh_tilledPattern->setBeamCrossSection(
|
|
optimizationResult.settings.beamDimensions_pattern);
|
|
if (optimizationResult.settings.youngsModulus_pattern == 0) {
|
|
std::cerr << "Full pattern's young modulus not found." << std::endl;
|
|
std::terminate();
|
|
}
|
|
pSimulationEdgeMesh_tilledPattern->setBeamMaterial(
|
|
0.3, optimizationResult.settings.youngsModulus_pattern);
|
|
pSimulationEdgeMesh_tilledPattern->reset();
|
|
// optimizationResult.draw();
|
|
#ifdef POLYSCOPE_DEFINED
|
|
pSimulationEdgeMesh_tilledPattern->registerForDrawing(
|
|
color_tesselatedPatterns);
|
|
#endif
|
|
|
|
////Tessellated reduced pattern simulation mesh
|
|
std::shared_ptr<SimulationEdgeMesh> pSimulationEdgeMesh_tilledReducedModel;
|
|
pSimulationEdgeMesh_tilledReducedModel =
|
|
std::make_shared<SimulationEdgeMesh>(*pTilled_reducedModel);
|
|
ReducedModelOptimization::Results::applyOptimizationResults_elements(
|
|
optimizationResult, pSimulationEdgeMesh_tilledReducedModel);
|
|
pSimulationEdgeMesh_tilledReducedModel->reset();
|
|
#ifdef POLYSCOPE_DEFINED
|
|
pSimulationEdgeMesh_tilledReducedModel->registerForDrawing(
|
|
color_tesselatedReducedModels, false,
|
|
pSimulationEdgeMesh_tilledPattern->elements[0]
|
|
.dimensions.getDrawingRadius());
|
|
#endif
|
|
|
|
Results evaluationResults;
|
|
evaluationResults.evaluationScenarioLabels = scenariosTestSetLabels;
|
|
evaluationResults.distances_drm2reduced.fill(-1);
|
|
evaluationResults.distances_normalizedGroundTruth2reduced.fill(-1);
|
|
DRMSimulationModel::Settings drmSimulationSettings;
|
|
// drmSimulationSettings.threshold_residualToExternalForcesNorm = 1e-3;
|
|
// drmSimulationSettings.load(drmSettingsFilePath);
|
|
drmSimulationSettings.beVerbose = evaluationSettings.beVerbose;
|
|
drmSimulationSettings.maxDRMIterations = 5e6;
|
|
drmSimulationSettings.debugModeStep = 100000;
|
|
drmSimulationSettings.threshold_totalTranslationalKineticEnergy = 1e-14;
|
|
// drmSimulationSettings.threshold_currentToFirstPeakTranslationalKineticEnergy
|
|
// =
|
|
// 1e-10;
|
|
drmSimulationSettings.threshold_averageResidualToExternalForcesNorm = 1e-5;
|
|
// drmSimulationSettings.linearGuessForceScaleFactor = 0.8;
|
|
// drmSimulationSettings.viscousDampingFactor = 7e-3;
|
|
// drmSimulationSettings.xi = 0.9999;
|
|
// drmSimulationSettings.gamma = 0.25;
|
|
#ifdef POLYSCOPE_DEFINED
|
|
// drmSimulationSettings.shouldDraw = true;
|
|
drmSimulationSettings.shouldCreatePlots = false;
|
|
if (evaluationSettings.shouldDraw) {
|
|
pSimulationEdgeMesh_tilledPattern->registerForDrawing(
|
|
ReducedModelOptimization::Colors::patternInitial, true);
|
|
}
|
|
#endif
|
|
const std::string& simulationModelLabel_pattern =
|
|
optimizationResult.settings.simulationModelLabel_groundTruth;
|
|
const std::string& simulationModelLabel_reducedModel =
|
|
optimizationResult.settings.simulationModelLabel_reducedModel;
|
|
// ChronosEulerLinearSimulationModel::label;
|
|
|
|
std::for_each(
|
|
#ifndef POLYSCOPE_DEFINED
|
|
std::execution::par_unseq,
|
|
#endif
|
|
scenariosTestSetLabels.begin(), scenariosTestSetLabels.end(),
|
|
[&](const std::string& jobLabel) {
|
|
// check if reduced model scenario exists
|
|
// const std::string &jobLabel =
|
|
// scenariosTestSetLabels[jobIndex];
|
|
const std::filesystem::path tiledReducedPatternJobFilePath =
|
|
std::filesystem::path(scenariosDirectoryPath)
|
|
.append(pTileIntoSurface->getLabel())
|
|
.append(jobLabel)
|
|
.append("ReducedJob")
|
|
.append(SimulationJob::jsonDefaultFileName);
|
|
if (!std::filesystem::exists(tiledReducedPatternJobFilePath)) {
|
|
if (evaluationSettings.beVerbose) {
|
|
std::cerr << "Scenario " << jobLabel
|
|
<< " not found in:" << tiledReducedPatternJobFilePath
|
|
<< std::endl;
|
|
}
|
|
// continue; //if not move on to the next scenario
|
|
return;
|
|
}
|
|
// Map the reduced job to the job on the pattern tessellation
|
|
// set jobs
|
|
std::shared_ptr<SimulationJob> pJob_tiledReducedModel;
|
|
pJob_tiledReducedModel =
|
|
std::make_shared<SimulationJob>(SimulationJob());
|
|
pJob_tiledReducedModel->load(tiledReducedPatternJobFilePath, false);
|
|
std::for_each(pJob_tiledReducedModel->nodalExternalForces.begin(),
|
|
pJob_tiledReducedModel->nodalExternalForces.end(),
|
|
[&](std::pair<const VertexIndex, Vector6d>& viForcePair) {
|
|
viForcePair.second =
|
|
viForcePair.second * forceScalingFactor;
|
|
});
|
|
pJob_tiledReducedModel->pMesh = pSimulationEdgeMesh_tilledReducedModel;
|
|
std::shared_ptr<SimulationJob> pJob_tilledPattern;
|
|
pJob_tilledPattern = std::make_shared<SimulationJob>(SimulationJob());
|
|
pJob_tilledPattern->pMesh = pSimulationEdgeMesh_tilledPattern;
|
|
pJob_tiledReducedModel->remap(reducedToFullViMap, *pJob_tilledPattern);
|
|
// pJob_tiledReducedPattern->registerForDrawing(pTiledReducedPattern->getLabel());
|
|
// pJob_tiledFullPattern->registerForDrawing(pTiledFullPattern->getLabel());
|
|
// polyscope::show();
|
|
const std::filesystem::path surfaceFolderPath =
|
|
std::filesystem::path(patternTessellatedResultsDirectoryPath)
|
|
.append(simulationModelLabel_pattern + "_" +
|
|
pTileIntoSurface->getLabel());
|
|
const std::string scenarioLabel = pJob_tilledPattern->getLabel();
|
|
const std::filesystem::path scenarioDirectoryPath =
|
|
std::filesystem::path(surfaceFolderPath).append(scenarioLabel);
|
|
// Save reduced job
|
|
constexpr bool exportReducedJob = false;
|
|
if (exportReducedJob) {
|
|
const std::filesystem::path reducedJobDirectoryPath =
|
|
std::filesystem::path(scenarioDirectoryPath).append("ReducedJob");
|
|
std::filesystem::create_directories(reducedJobDirectoryPath);
|
|
pJob_tiledReducedModel->save(reducedJobDirectoryPath);
|
|
}
|
|
// Check if the drm simulation of the full pattern has already been
|
|
// computed
|
|
////Full
|
|
const std::string& patternLabel = [&]() {
|
|
const std::string patternLabel =
|
|
optimizationResult.baseTrianglePattern.getLabel();
|
|
if (patternLabel.find("_") == std::string::npos) {
|
|
return std::to_string(optimizationResult.baseTrianglePattern.EN()) +
|
|
"_" + patternLabel;
|
|
} else {
|
|
return patternLabel;
|
|
}
|
|
}();
|
|
const auto tilledPatternResultsFolderPath =
|
|
std::filesystem::path(scenarioDirectoryPath)
|
|
.append(patternLabel)
|
|
.append("Results");
|
|
if (evaluationSettings.shouldRecomputeGroundTruthResults &&
|
|
std::filesystem::exists(tilledPatternResultsFolderPath)) {
|
|
std::filesystem::remove_all(tilledPatternResultsFolderPath);
|
|
}
|
|
|
|
const std::filesystem::path fullPatternJobFolderPath =
|
|
std::filesystem::path(scenarioDirectoryPath)
|
|
.append(patternLabel)
|
|
.append("SimulationJob");
|
|
SimulationResults simulationResults_tilledPattern;
|
|
if (std::filesystem::exists(tilledPatternResultsFolderPath)) {
|
|
// Load full pattern results
|
|
assert(std::filesystem::exists(fullPatternJobFolderPath));
|
|
simulationResults_tilledPattern.load(tilledPatternResultsFolderPath,
|
|
fullPatternJobFolderPath);
|
|
|
|
simulationResults_tilledPattern.converged = true;
|
|
} else {
|
|
if (evaluationSettings.beVerbose) {
|
|
std::cout << "Executing:" << jobLabel << std::endl;
|
|
}
|
|
SimulationModelFactory factory;
|
|
std::unique_ptr<SimulationModel> pTilledPatternSimulationModel =
|
|
factory.create(simulationModelLabel_pattern);
|
|
// TODO: since the drm simulation model does not have a common
|
|
// interface with the rest of simulation models I need to cast it in
|
|
// order to pass simulation settings. Fix it by removing the
|
|
// SimulationSettings argument
|
|
if (simulationModelLabel_pattern == DRMSimulationModel::label) {
|
|
simulationResults_tilledPattern =
|
|
reinterpret_cast<DRMSimulationModel*>(
|
|
pTilledPatternSimulationModel.get())
|
|
->executeSimulation(pJob_tilledPattern,
|
|
drmSimulationSettings);
|
|
} else {
|
|
simulationResults_tilledPattern =
|
|
pTilledPatternSimulationModel->executeSimulation(
|
|
pJob_tilledPattern);
|
|
}
|
|
}
|
|
if (!simulationResults_tilledPattern.converged) {
|
|
std::cerr << "Full pattern simulation failed." << std::endl;
|
|
std::cerr << "Not saving results" << std::endl;
|
|
// continue;
|
|
return;
|
|
}
|
|
std::filesystem::create_directories(tilledPatternResultsFolderPath);
|
|
const std::filesystem::path drmResultsOutputPath =
|
|
std::filesystem::path(scenarioDirectoryPath).append(patternLabel);
|
|
simulationResults_tilledPattern.save(drmResultsOutputPath);
|
|
|
|
// LinearSimulationModel linearSimulationModel;
|
|
SimulationModelFactory factory;
|
|
std::unique_ptr<SimulationModel> pSimulationModel_tilledReducedModel =
|
|
factory.create(simulationModelLabel_reducedModel);
|
|
SimulationResults simulationResults_tiledReducedModel =
|
|
pSimulationModel_tilledReducedModel->executeSimulation(
|
|
pJob_tiledReducedModel);
|
|
|
|
// ChronosEulerNonLinearSimulationModel
|
|
// debug_chronosNonLinearSimulationModel;
|
|
// const auto debug_chronosResults =
|
|
// debug_chronosNonLinearSimulationModel.executeSimulation(
|
|
// pJob_tilledPattern);
|
|
// LinearSimulationModel debug_linearSimulationModel;
|
|
// const auto debug_linearSimResults =
|
|
// debug_linearSimulationModel.executeSimulation(pJob_tilledPattern);
|
|
|
|
const int jobIndex = &jobLabel - &scenariosTestSetLabels[0];
|
|
evaluationResults.maxDisplacements[jobIndex] =
|
|
std::max_element(
|
|
simulationResults_tilledPattern.displacements.begin(),
|
|
simulationResults_tilledPattern.displacements.end(),
|
|
[](const Vector6d& d1, const Vector6d& d2) {
|
|
return d1.getTranslation().norm() <
|
|
d2.getTranslation().norm();
|
|
})
|
|
->getTranslation()
|
|
.norm();
|
|
const std::vector<double> distance_perVertexPatternToReduced =
|
|
SimulationResults::computeDistance_PerVertex(
|
|
simulationResults_tilledPattern,
|
|
simulationResults_tiledReducedModel, patternToReducedViMap);
|
|
std::vector<double> distance_normalizedPerVertexPatternToReduced =
|
|
distance_perVertexPatternToReduced;
|
|
// compute the full2reduced distance
|
|
double distance_patternSumOfAllVerts = 0;
|
|
for (const std::pair<size_t, size_t>& fullToReducedPair :
|
|
patternToReducedViMap) {
|
|
VertexIndex patternVi = fullToReducedPair.first;
|
|
const double patternVertexDisplacement =
|
|
simulationResults_tilledPattern.displacements[patternVi]
|
|
.getTranslation()
|
|
.norm();
|
|
distance_patternSumOfAllVerts += patternVertexDisplacement;
|
|
}
|
|
int pairIndex = 0;
|
|
for (const std::pair<size_t, size_t>& fullToReducedPair :
|
|
patternToReducedViMap) {
|
|
VertexIndex patternVi = fullToReducedPair.first;
|
|
const double patternVertexDisplacement =
|
|
simulationResults_tilledPattern.displacements[patternVi]
|
|
.getTranslation()
|
|
.norm();
|
|
distance_normalizedPerVertexPatternToReduced[pairIndex] =
|
|
distance_perVertexPatternToReduced[pairIndex] /
|
|
evaluationResults.maxDisplacements[jobIndex];
|
|
assert(!std::isnan(
|
|
distance_normalizedPerVertexPatternToReduced[pairIndex]));
|
|
pairIndex++;
|
|
}
|
|
|
|
double distance_averageNormalizedPerVertexPatternToReduced =
|
|
std::accumulate(
|
|
distance_normalizedPerVertexPatternToReduced.begin(),
|
|
distance_normalizedPerVertexPatternToReduced.end(), 0.0) /
|
|
patternToReducedViMap.size();
|
|
const double distance_patternToReduced =
|
|
simulationResults_tilledPattern.computeDistance_comulative(
|
|
simulationResults_tiledReducedModel, patternToReducedViMap);
|
|
const double distance_normalizedPatternToReduced =
|
|
distance_patternToReduced / distance_patternSumOfAllVerts;
|
|
evaluationResults.distances_drm2reduced[jobIndex] =
|
|
distance_patternToReduced;
|
|
// evaluationResults.distances_normalizedGroundTruth2reduced[jobIndex]
|
|
// =
|
|
// distance_normalizedPatternToReduced;
|
|
evaluationResults.distances_normalizedGroundTruth2reduced[jobIndex] =
|
|
distance_averageNormalizedPerVertexPatternToReduced;
|
|
|
|
#ifdef POLYSCOPE_DEFINED
|
|
if (evaluationSettings.shouldDraw) {
|
|
std::cout << "maxError/maxDisp="
|
|
<< *std::max_element(
|
|
distance_perVertexPatternToReduced.begin(),
|
|
distance_perVertexPatternToReduced.end()) /
|
|
evaluationResults.maxDisplacements[jobIndex]
|
|
<< std::endl;
|
|
std::cout << "max displacement:"
|
|
<< evaluationResults.maxDisplacements[jobIndex]
|
|
<< std::endl;
|
|
std::cout << "average normalized per vertex:"
|
|
<< distance_averageNormalizedPerVertexPatternToReduced
|
|
<< std::endl;
|
|
simulationResults_tiledReducedModel.registerForDrawing(
|
|
ReducedModelOptimization::Colors::reducedDeformed, false,
|
|
simulationResults_tilledPattern.pJob->pMesh
|
|
->getBeamDimensions()[0]
|
|
.getDrawingRadius());
|
|
polyscope::CurveNetwork* patternHandle =
|
|
simulationResults_tilledPattern.registerForDrawing(
|
|
ReducedModelOptimization::Colors::patternDeformed);
|
|
pJob_tilledPattern->registerForDrawing(patternHandle->name, true);
|
|
pJob_tilledPattern->registerForDrawing(
|
|
pSimulationEdgeMesh_tilledPattern->getLabel(), false);
|
|
std::vector<double> distances_perVertexAverage(
|
|
pSimulationEdgeMesh_tilledPattern->VN(), 0.0);
|
|
int interfaceVi = 0;
|
|
for (const std::pair<size_t, size_t>& fullToReducedPair :
|
|
patternToReducedViMap) {
|
|
VertexIndex patternVi = fullToReducedPair.first;
|
|
distances_perVertexAverage[patternVi] =
|
|
distance_normalizedPerVertexPatternToReduced[interfaceVi++];
|
|
}
|
|
|
|
// patternHandle
|
|
// ->addNodeScalarQuantity(
|
|
// "average normalized distance "
|
|
// "per vertex ",
|
|
// distances_perVertexAverage)
|
|
// ->setEnabled(true);
|
|
|
|
// pJob_tiledReducedModel->registerForDrawing(
|
|
// pSimulationEdgeMesh_tilledReducedModel->getLabel());
|
|
// debug_chronosResults.registerForDrawing();
|
|
// debug_linearSimResults.registerForDrawing();
|
|
std::cout << "normalized distance pattern2reduced:"
|
|
<< distance_normalizedPatternToReduced << std::endl;
|
|
// std::filesystem::path outputFolderPath(
|
|
// "/home/iason/Documents/PhD/Thesis/images/RME/scenarios/"
|
|
// "screenshots/");
|
|
polyscope::show();
|
|
// const std::string screenshotOutputFilePath_custom =
|
|
// (std::filesystem::path(outputFolderPath)
|
|
// .append(optimizationResult.label + "_" +
|
|
// pJob_tilledPattern->getLabel()))
|
|
// .string() +
|
|
// "_custom"
|
|
// ".png";
|
|
// polyscope::screenshot(screenshotOutputFilePath_custom,
|
|
// false);
|
|
// top
|
|
// const std::filesystem::path jsonFilePath_topView(
|
|
// "/home/iason/Documents/PhD/Thesis/images/RME/scenarios/"
|
|
// "cammeraSettings_.json");
|
|
// std::ifstream f_top(jsonFilePath_topView);
|
|
// polyscope::view::setCameraFromJson(
|
|
// nlohmann::json::parse(f_top).dump(), false);
|
|
// // polyscope::show();
|
|
// const std::string screenshotOutputFilePath_top =
|
|
// (std::filesystem::path(outputFolderPath)
|
|
// .append(optimizationResult.label + "_" +
|
|
// pJob_tilledPattern->getLabel()))
|
|
// .string() +
|
|
// "_top"
|
|
// ".png";
|
|
// std::cout << "Saving image to:" <<
|
|
// screenshotOutputFilePath_top
|
|
// << std::endl;
|
|
// polyscope::screenshot(screenshotOutputFilePath_top,
|
|
// false);
|
|
// side
|
|
// const std::filesystem::path jsonFilePath_sideView(
|
|
// "/home/iason/Documents/PhD/Thesis/images/RME/scenarios/"
|
|
// "cammeraSettings_sideView.json");
|
|
// std::ifstream f_side(jsonFilePath_sideView);
|
|
// polyscope::view::setCameraFromJson(
|
|
// nlohmann::json::parse(f_side).dump(), false);
|
|
// // polyscope::show();
|
|
// const std::string screenshotOutputFilePath_side =
|
|
// (std::filesystem::path(outputFolderPath)
|
|
// .append(optimizationResult.label + "_" +
|
|
// pJob_tilledPattern->getLabel()))
|
|
// .string() +
|
|
// "_side"
|
|
// ".png";
|
|
// std::cout << "Saving image to:" <<
|
|
// screenshotOutputFilePath_side
|
|
// << std::endl;
|
|
// polyscope::screenshot(screenshotOutputFilePath_side,
|
|
// false);
|
|
pJob_tilledPattern->unregister(
|
|
pSimulationEdgeMesh_tilledPattern->getLabel());
|
|
pJob_tiledReducedModel->unregister(
|
|
pSimulationEdgeMesh_tilledReducedModel->getLabel());
|
|
// debug_linearSimResults.unregister();
|
|
simulationResults_tiledReducedModel.unregister();
|
|
simulationResults_tilledPattern.unregister();
|
|
// debug_chronosResults.unregister();
|
|
}
|
|
#endif
|
|
});
|
|
|
|
return evaluationResults;
|
|
}
|
|
|
|
bool ReducedModelEvaluator::Settings::save(
|
|
const std::filesystem::path& jsonFilePath) const {
|
|
if (std::filesystem::path(jsonFilePath).extension() != ".json") {
|
|
std::cerr << "A json file is expected as input. The given file has the "
|
|
"following extension:"
|
|
<< std::filesystem::path(jsonFilePath).extension() << std::endl;
|
|
assert(false);
|
|
return false;
|
|
}
|
|
|
|
nlohmann::json json = *this;
|
|
std::ofstream jsonFile(jsonFilePath.string());
|
|
jsonFile << json;
|
|
jsonFile.close();
|
|
}
|
|
|
|
bool ReducedModelEvaluator::Settings::load(
|
|
const std::filesystem::path& jsonFilePath) {
|
|
if (!std::filesystem::exists(jsonFilePath)) {
|
|
std::cerr << "Evaluation settings could not be loaded because input "
|
|
"filepath does "
|
|
"not exist:"
|
|
<< jsonFilePath << std::endl;
|
|
assert(false);
|
|
return false;
|
|
}
|
|
|
|
if (std::filesystem::path(jsonFilePath).extension() != ".json") {
|
|
std::cerr << "A json file is expected as input. The given file has the "
|
|
"following extension:"
|
|
<< std::filesystem::path(jsonFilePath).extension() << std::endl;
|
|
assert(false);
|
|
return false;
|
|
}
|
|
|
|
std::ifstream ifs(jsonFilePath);
|
|
nlohmann::json json;
|
|
ifs >> json;
|
|
*this = json;
|
|
|
|
return true;
|
|
}
|