#include "reducedmodelevaluator.hpp" #include "hexagonremesher.hpp" #include "trianglepatterngeometry.hpp" #include using FullPatternVertexIndex = VertexIndex; using ReducedPatternVertexIndex = VertexIndex; ReducedModelEvaluator::ReducedModelEvaluator() { } ReducedModelEvaluator::Results ReducedModelEvaluator::evaluateReducedModel( ReducedModelOptimization::Results &optimizationResult) { const std::filesystem::path tileInto_triMesh_filePath = "/home/iason/Coding/build/PatternTillingReducedModel/Meshes/" "instantMeshes_plane_34.ply"; const std::filesystem::path scenariosDirectoryPath = "/home/iason/Coding/Projects/Approximating shapes with flat " "patterns/ReducedModelEvaluator/Scenarios"; const std::filesystem::path reducedPatternFilePath = "/home/iason/Coding/Projects/Approximating shapes with flat " "patterns/ReducedModelOptimization/TestSet/ReducedPatterns/single_reduced.ply"; const std::filesystem::path fullPatternTessellatedResultsDirectoryPath = "/home/iason/Coding/Projects/Approximating shapes with flat " "patterns/ReducedModelEvaluator/TessellatedResults"; return evaluateReducedModel(optimizationResult, tileInto_triMesh_filePath, scenariosDirectoryPath, reducedPatternFilePath, fullPatternTessellatedResultsDirectoryPath); } void ReducedModelEvaluator::printResults(const Results &evaluationResults, const std::string &resultsLabel, const std::filesystem::path &resultsOutputDirPath) { //report distance // csvFile csv_results("", flse); if (!resultsOutputDirPath.empty()) { std::filesystem::create_directories(resultsOutputDirPath); } #ifdef POLYSCOPE_DEFINED csvFile csv_results({}, false); #else std::filesystem::path csvOutputFilePath = resultsOutputDirPath.empty() ? "" : std::filesystem::path(resultsOutputDirPath) .append("distances_" + resultsLabel + ".csv") .string(); csvFile csv_results(csvOutputFilePath, true); #endif csv_results << resultsLabel; csv_results << endrow; #ifdef POLYSCOPE_DEFINED csv_results /*<< "Job Label"*/ << "drm2Reduced" << "norm_drm2Reduced"; #else csv_results << "Job Label" << "drm2Reduced" << "norm_drm2Reduced"; #endif csv_results << endrow; // double sumOfNormalizedFull2Reduced = 0; for (int jobIndex = 0; jobIndex < ReducedModelEvaluator::scenariosTestSetLabels.size(); jobIndex++) { const std::string &jobLabel = ReducedModelEvaluator::scenariosTestSetLabels[jobIndex]; const double &distance_fullDrmToReduced = evaluationResults.distances_drm2reduced[jobIndex]; const double &distance_normalizedFullDrmToReduced = evaluationResults.distances_normalizedDrm2reduced[jobIndex]; #ifdef POLYSCOPE_DEFINED csv_results /*<< jobLabel*/ << distance_fullDrmToReduced << distance_normalizedFullDrmToReduced; #else csv_results << jobLabel << distance_fullDrmToReduced << distance_normalizedFullDrmToReduced; #endif csv_results << endrow; // sumOfNormalizedFull2Reduced += distance_normalizedFullDrmToReduced; } } ReducedModelEvaluator::Results ReducedModelEvaluator::evaluateReducedModel( ReducedModelOptimization::Results &optimizationResult, const std::filesystem::path &tileInto_triMesh_filePath, const std::filesystem::path &scenariosDirectoryPath, const std::filesystem::path &reducedPatternFilePath, const std::filesystem::path &fullPatternTessellatedResultsDirectoryPath) { // std::shared_ptr pTileIntoSurface = std::make_shared(); // std::filesystem::path tileIntoSurfaceFilePath{ // "/home/iason/Coding/Projects/Approximating shapes with flat " // "patterns/ReducedModelOptimization/TestSet/TileIntoSurface/plane_34Polygons.ply"}; // assert(std::filesystem::exists(tileIntoSurfaceFilePath)); // pTileIntoSurface->load(tileIntoSurfaceFilePath); //Set required file paths // const std::filesystem::path drmSettingsFilePath // = "/home/iason/Coding/Projects/Approximating shapes with flat " // "patterns/ReducedModelOptimization/DefaultSettings/DRMSettings/" // "defaultDRMSimulationSettings.json"; DRMSimulationModel::Settings drmSimulationSettings; drmSimulationSettings.totalExternalForcesNormPercentageTermination = 1e-3; // drmSimulationSettings.load(drmSettingsFilePath); drmSimulationSettings.linearGuessForceScaleFactor = 0.5; drmSimulationSettings.debugModeStep = 10000; drmSimulationSettings.beVerbose = true; drmSimulationSettings.maxDRMIterations = 1e6; // drmSimulationSettings.translationalKineticEnergyThreshold = 1e-15; // drmSimulationSettings.viscousDampingFactor = 1e-2; constexpr bool shouldRerunFullPatternSimulation = false; //Load surface std::shared_ptr pTileIntoSurface = [&]() { VCGTriMesh tileInto_triMesh; const bool surfaceLoadSuccessfull = tileInto_triMesh.load(tileInto_triMesh_filePath); assert(surfaceLoadSuccessfull); return PolygonalRemeshing::remeshWithPolygons(tileInto_triMesh); }(); const double optimizedBaseTriangleHeight = vcg::Distance(optimizationResult.baseTriangle.cP(0), (optimizationResult.baseTriangle.cP(1) + optimizationResult.baseTriangle.cP( 2)) / 2); pTileIntoSurface->moveToCenter(); const double scaleFactor = optimizedBaseTriangleHeight / pTileIntoSurface->getAverageFaceRadius(); vcg::tri::UpdatePosition::Scale(*pTileIntoSurface, scaleFactor); // tileIntoSurface.registerForDrawing(); // polyscope::show(); //Tile full pattern into surface std::vector fullPatterns(1); fullPatterns[0].copy(optimizationResult.baseTriangleFullPattern); //// Base triangle pattern might contain dangling vertices.Remove those fullPatterns[0].interfaceNodeIndex = 3; fullPatterns[0].deleteDanglingVertices(); std::vector perSurfaceFacePatternIndices(pTileIntoSurface->FN(), 0); std::vector> perPatternIndexTiledFullPatternEdgeIndices; std::vector tileIntoEdgeToTiledFullVi; std::shared_ptr pTiledFullPattern = PatternGeometry::tilePattern(fullPatterns, {}, *pTileIntoSurface, perSurfaceFacePatternIndices, tileIntoEdgeToTiledFullVi, perPatternIndexTiledFullPatternEdgeIndices); pTiledFullPattern->setLabel("Tiled_full_patterns"); // pTiledFullPattern->registerForDrawing(); //Tile reduced pattern into surface PatternGeometry reducedPattern; reducedPattern.load(reducedPatternFilePath); reducedPattern.deleteDanglingVertices(); reducedPattern.interfaceNodeIndex = 1; assert(reducedPattern.interfaceNodeIndex == 1); std::vector reducedPatterns(1); reducedPatterns[0].copy(reducedPattern); const auto reducedPatternBaseTriangle = reducedPattern.computeBaseTriangle(); ReducedModelOptimization::Results::applyOptimizationResults_innerHexagon( optimizationResult, reducedPatternBaseTriangle, reducedPatterns[0]); std::vector> perPatternIndexTiledReducedPatternEdgeIndices; std::vector tileIntoEdgeToTiledReducedVi; std::shared_ptr pTiledReducedPattern = PatternGeometry::tilePattern(reducedPatterns, {0}, *pTileIntoSurface, perSurfaceFacePatternIndices, tileIntoEdgeToTiledReducedVi, perPatternIndexTiledReducedPatternEdgeIndices); pTiledReducedPattern->setLabel("Tiled_reduced_patterns"); // pTiledReducedPattern->registerForDrawing(); std::unordered_map fullToReducedViMap; //of only the common vertices std::unordered_map reducedToFullViMap; //of only the common vertices for (int ei = 0; ei < pTileIntoSurface->EN(); ei++) { fullToReducedViMap[tileIntoEdgeToTiledFullVi[ei]] = tileIntoEdgeToTiledReducedVi[ei]; } constructInverseMap(fullToReducedViMap, reducedToFullViMap); std::vector tilledFullPatternInterfaceVi; tilledFullPatternInterfaceVi.clear(); tilledFullPatternInterfaceVi.resize(fullToReducedViMap.size()); size_t viIndex = 0; for (std::pair fullToReducedPair : fullToReducedViMap) { tilledFullPatternInterfaceVi[viIndex++] = fullToReducedPair.first; } //Create simulation meshes ////Tessellated full pattern simulation mesh std::shared_ptr pTiledFullPattern_simulationMesh; pTiledFullPattern_simulationMesh = std::make_shared(*pTiledFullPattern); //NOTE: Those should be derived from the optimization results instead of hardcoding them pTiledFullPattern_simulationMesh->setBeamCrossSection(CrossSectionType{0.002, 0.002}); if (optimizationResult.fullPatternYoungsModulus == 0) { std::cerr << "Full pattern's young modulus not found." << std::endl; std::terminate(); } pTiledFullPattern_simulationMesh->setBeamMaterial(0.3, optimizationResult.fullPatternYoungsModulus); pTiledFullPattern_simulationMesh->reset(); ////Tessellated reduced pattern simulation mesh std::shared_ptr pTiledReducedPattern_simulationMesh; pTiledReducedPattern_simulationMesh = std::make_shared(*pTiledReducedPattern); const std::vector &tiledPatternElementIndicesForReducedPattern = perPatternIndexTiledReducedPatternEdgeIndices[0]; ReducedModelOptimization::Results::applyOptimizationResults_elements( optimizationResult, pTiledReducedPattern_simulationMesh); pTiledReducedPattern_simulationMesh->reset(); Results evaluationResults; evaluationResults.distances_drm2reduced; evaluationResults.distances_normalizedDrm2reduced; for (int jobIndex = 0; jobIndex < scenariosTestSetLabels.size(); jobIndex++) { 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)) { std::cerr << "Scenario " << jobLabel << " not found in:" << tiledReducedPatternJobFilePath << std::endl; continue; } //set jobs std::shared_ptr pJob_tiledReducedPattern; pJob_tiledReducedPattern = std::make_shared(SimulationJob()); pJob_tiledReducedPattern->load(tiledReducedPatternJobFilePath, false); pJob_tiledReducedPattern->pMesh = pTiledReducedPattern_simulationMesh; std::shared_ptr pJob_tiledFullPattern; pJob_tiledFullPattern = std::make_shared(SimulationJob()); pJob_tiledFullPattern->pMesh = pTiledFullPattern_simulationMesh; pJob_tiledReducedPattern->remap(reducedToFullViMap, *pJob_tiledFullPattern); // pJob_tiledReducedPattern->registerForDrawing(pTiledReducedPattern->getLabel()); // pJob_tiledFullPattern->registerForDrawing(pTiledFullPattern->getLabel()); // polyscope::show(); //Save reduced job const std::filesystem::path surfaceFolderPath = std::filesystem::path(fullPatternTessellatedResultsDirectoryPath) .append(pTileIntoSurface->getLabel()); const std::string scenarioLabel = pJob_tiledFullPattern->getLabel(); const std::filesystem::path scenarioDirectoryPath = std::filesystem::path(surfaceFolderPath) .append(scenarioLabel); const std::filesystem::path reducedJobDirectoryPath = std::filesystem::path(scenarioDirectoryPath).append("ReducedJob"); std::filesystem::create_directories(reducedJobDirectoryPath); pJob_tiledReducedPattern->save(reducedJobDirectoryPath); //Run scenario ////Full const std::string patternLabel = optimizationResult.baseTriangleFullPattern.getLabel(); const auto fullResultsFolderPath = std::filesystem::path(scenarioDirectoryPath).append(patternLabel).append("Results"); if (shouldRerunFullPatternSimulation && std::filesystem::exists(fullResultsFolderPath)) { std::filesystem::remove_all(fullResultsFolderPath); } const std::filesystem::path fullPatternJobFolderPath = std::filesystem::path( scenarioDirectoryPath) .append(patternLabel) .append("SimulationJob"); SimulationResults simulationResults_tiledFullPattern_drm; if (std::filesystem::exists(fullResultsFolderPath)) { //Load full pattern results assert(std::filesystem::exists(fullPatternJobFolderPath)); simulationResults_tiledFullPattern_drm.load(fullResultsFolderPath, fullPatternJobFolderPath); simulationResults_tiledFullPattern_drm.converged = true; } else { //Full std::cout << "Executing:" << jobLabel << std::endl; DRMSimulationModel drmSimulationModel; simulationResults_tiledFullPattern_drm = drmSimulationModel.executeSimulation(pJob_tiledFullPattern, drmSimulationSettings); simulationResults_tiledFullPattern_drm.setLabelPrefix("DRM"); } std::filesystem::create_directories(fullResultsFolderPath); const std::filesystem::path drmResultsOutputPath = std::filesystem::path(scenarioDirectoryPath).append(patternLabel); simulationResults_tiledFullPattern_drm.save(drmResultsOutputPath); if (!simulationResults_tiledFullPattern_drm.converged) { std::cerr << "Full pattern simulation failed." << std::endl; std::cerr << "Saved failed simulation to:" << drmResultsOutputPath << std::endl; continue; } LinearSimulationModel linearSimulationModel; SimulationResults simulationResults_tiledReducedPattern = linearSimulationModel.executeSimulation(pJob_tiledReducedPattern); // simulationResults_tiledReducedPattern.registerForDrawing(); // simulationResults_tiledFullPattern_drm.registerForDrawing(); // polyscope::show(); //measure distance const double distance_fullDrmToReduced = simulationResults_tiledFullPattern_drm .computeDistance(simulationResults_tiledReducedPattern, fullToReducedViMap); double distance_fullSumOfAllVerts = 0; for (std::pair fullToReducedPair : fullToReducedViMap) { distance_fullSumOfAllVerts += simulationResults_tiledFullPattern_drm .displacements[fullToReducedPair.first] .getTranslation() .norm(); } const double distance_normalizedFullDrmToReduced = distance_fullDrmToReduced / distance_fullSumOfAllVerts; evaluationResults.distances_drm2reduced[jobIndex] = distance_fullDrmToReduced; evaluationResults.distances_normalizedDrm2reduced[jobIndex] = distance_normalizedFullDrmToReduced; } return evaluationResults; }