#include "reducedmodelevaluator.hpp" #include #include #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 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::Scale(*pTileIntoSurface, scaleFactor); #ifdef POLYSCOPE_DEFINED pTileIntoSurface->registerForDrawing(color_tileIntoSurface, false); #endif // Tile full pattern into surface std::vector patterns(1); patterns[0].copy(optimizationResult.baseTrianglePattern); patterns[0].interfaceNodeIndex = 3; patterns[0].deleteDanglingVertices(); std::vector perSurfaceFacePatternIndices(pTileIntoSurface->FN(), 0); std::vector> perPatternIndexTiledFullPatternEdgeIndices; std::vector tileIntoEdgeToTiledFullVi; std::shared_ptr pTilled_pattern = PatternGeometry::tilePattern(patterns, {}, *pTileIntoSurface, perSurfaceFacePatternIndices, tileIntoEdgeToTiledFullVi, perPatternIndexTiledFullPatternEdgeIndices); pTilled_pattern->setLabel("Tilled_pattern"); // Tile reduced pattern into surface std::vector reducedModels(1); reducedModels[0].copy(reducedModel); std::vector> perPatternIndexTiledReducedPatternEdgeIndices; std::vector tileIntoEdgeToTiledReducedVi; std::shared_ptr pTilled_reducedModel = PatternGeometry::tilePattern( reducedModels, {0}, *pTileIntoSurface, perSurfaceFacePatternIndices, tileIntoEdgeToTiledReducedVi, perPatternIndexTiledReducedPatternEdgeIndices); pTilled_reducedModel->setLabel("Tilled_reduced_model"); std::unordered_map patternToReducedViMap; // of only the common vertices std::unordered_map reducedToFullViMap; // of only the common vertices for (int ei = 0; ei < pTileIntoSurface->EN(); ei++) { patternToReducedViMap[tileIntoEdgeToTiledFullVi[ei]] = tileIntoEdgeToTiledReducedVi[ei]; } constructInverseMap(patternToReducedViMap, reducedToFullViMap); std::vector tilledFullPatternInterfaceVi; tilledFullPatternInterfaceVi.clear(); tilledFullPatternInterfaceVi.resize(patternToReducedViMap.size()); size_t viIndex = 0; for (std::pair fullToReducedPair : patternToReducedViMap) { tilledFullPatternInterfaceVi[viIndex++] = fullToReducedPair.first; } // Create simulation meshes ////Tessellated full pattern simulation mesh std::shared_ptr pSimulationEdgeMesh_tilledPattern = std::make_shared(*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 pSimulationEdgeMesh_tilledReducedModel; pSimulationEdgeMesh_tilledReducedModel = std::make_shared(*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 pJob_tiledReducedModel; pJob_tiledReducedModel = std::make_shared(SimulationJob()); pJob_tiledReducedModel->load(tiledReducedPatternJobFilePath, false); std::for_each(pJob_tiledReducedModel->nodalExternalForces.begin(), pJob_tiledReducedModel->nodalExternalForces.end(), [&](std::pair& viForcePair) { viForcePair.second = viForcePair.second * forceScalingFactor; }); pJob_tiledReducedModel->pMesh = pSimulationEdgeMesh_tilledReducedModel; std::shared_ptr pJob_tilledPattern; pJob_tilledPattern = std::make_shared(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 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( 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 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 distance_perVertexPatternToReduced = SimulationResults::computeDistance_PerVertex( simulationResults_tilledPattern, simulationResults_tiledReducedModel, patternToReducedViMap); std::vector distance_normalizedPerVertexPatternToReduced = distance_perVertexPatternToReduced; // compute the full2reduced distance double distance_patternSumOfAllVerts = 0; for (const std::pair& 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& 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 distances_perVertexAverage( pSimulationEdgeMesh_tilledPattern->VN(), 0.0); int interfaceVi = 0; for (const std::pair& 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; }