#ifndef REDUCEDMODELOPTIMIZER_HPP #define REDUCEDMODELOPTIMIZER_HPP #include "beamformfinder.hpp" #include "csvfile.hpp" #include "edgemesh.hpp" #include "elementalmesh.hpp" #include "matplot/matplot.h" #include using FullPatternVertexIndex = VertexIndex; using ReducedPatternVertexIndex = VertexIndex; class ReducedModelOptimizer { std::shared_ptr m_pReducedPatternSimulationMesh; std::shared_ptr m_pFullPatternSimulationMesh; std::unordered_map m_fullToReducedInterfaceViMap; std::unordered_map m_fullPatternOppositeInterfaceViMap; std::unordered_map nodeToSlot; std::unordered_map> slotToNode; std::vector initialGuess; public: enum SimulationScenario { Axial, Shear, Bending, Dome, Saddle, NumberOfSimulationScenarios }; struct xRange { std::string label; double min; double max; std::string toString() const { return label + "=[" + std::to_string(min) + "," + std::to_string(max) + "]"; } }; struct Results; struct Settings { std::vector xRanges; int numberOfFunctionCalls{100}; double solutionAccuracy{1e-2}; bool normalizeObjectiveValue{true}; std::string toString() const { std::string settingsString; if (!xRanges.empty()) { std::string xRangesString; for (const xRange &range : xRanges) { xRangesString += range.toString() + " "; } settingsString += xRangesString; } settingsString += "FuncCalls=" + std::to_string(numberOfFunctionCalls) + " Accuracy=" + std::to_string(solutionAccuracy) + " Norm=" + (normalizeObjectiveValue ? "yes" : "no"); return settingsString; } void writeHeaderTo(csvFile &os) const { if (!xRanges.empty()) { for (const xRange &range : xRanges) { os << range.label + " max"; os << range.label + " min"; } } os << "Function Calls"; os << "Solution Accuracy"; // os << std::endl; } void writeSettingsTo(csvFile &os) const { if (!xRanges.empty()) { for (const xRange &range : xRanges) { os << range.max; os << range.min; } } os << numberOfFunctionCalls; os << solutionAccuracy; } }; inline static const std::string simulationScenarioStrings[] = { "Axial", "Shear", "Bending", "Double", "Saddle"}; Results optimize(const Settings &xRanges, const std::vector &simulationScenarios = std::vector()); double operator()(const Eigen::VectorXd &x, Eigen::VectorXd &) const; ReducedModelOptimizer(const std::vector &numberOfNodesPerSlot); static void computeReducedModelSimulationJob( const SimulationJob &simulationJobOfFullModel, const std::unordered_map &simulationJobFullToReducedMap, SimulationJob &simulationJobOfReducedModel); SimulationJob getReducedSimulationJob(const SimulationJob &fullModelSimulationJob); void initializePatterns( FlatPattern &fullPattern, FlatPattern &reducedPatterm, const std::unordered_set &reducedModelExcludedEges); void setInitialGuess(std::vector v); static void runBeamOptimization(); static void runSimulation(const std::string &filename, std::vector &x); static double objective(double x0, double x1, double x2, double x3); static double objective(double b, double h, double E); static std::vector> createScenarios(const std::shared_ptr &pMesh, const std::unordered_map &fullPatternOppositeInterfaceViMap); static void createSimulationMeshes( FlatPattern &fullModel, FlatPattern &reducedModel, std::shared_ptr &pFullPatternSimulationMesh, std::shared_ptr &pReducedPatternSimulationMesh); static void computeMaps( const std::unordered_set &reducedModelExcludedEdges, const std::unordered_map> &slotToNode, FlatPattern &fullPattern, FlatPattern &reducedPattern, std::unordered_map &reducedToFullInterfaceViMap, std::unordered_map &fullToReducedInterfaceViMap, std::unordered_map &fullPatternOppositeInterfaceViMap); static void visualizeResults(const std::vector> &fullPatternSimulationJobs, const std::vector> &reducedPatternSimulationJobs, const std::vector &simulationScenarios, const std::unordered_map &reducedToFullInterfaceViMap); static double computeError(const std::vector &reducedPatternResults, const std::vector &fullPatternResults, const double &interfaceDisplacementNormSum, const std::unordered_map &reducedToFullInterfaceViMap); private: void visualizeResults(const std::vector> &fullPatternSimulationJobs, const std::vector &simulationScenarios); static void computeDesiredReducedModelDisplacements( const SimulationResults &fullModelResults, const std::unordered_map &displacementsReducedToFullMap, Eigen::MatrixX3d &optimalDisplacementsOfReducedModel); static Results runOptimization(const Settings &settings); std::vector> createScenarios(const std::shared_ptr &pMesh); void computeMaps(FlatPattern &fullModel, FlatPattern &reducedPattern, const std::unordered_set &reducedModelExcludedEges); void createSimulationMeshes(FlatPattern &fullModel, FlatPattern &reducedModel); static void initializeOptimizationParameters(const std::shared_ptr &mesh); static double computeError(const SimulationResults &reducedPatternResults, const Eigen::MatrixX3d &optimalReducedPatternDisplacements); static double objective(long n, const double *x); FormFinder simulator; }; struct ReducedModelOptimizer::Results { double time{-1}; int numberOfSimulationCrashes{0}; std::vector x; double objectiveValue; std::vector> fullPatternSimulationJobs; std::vector> reducedPatternSimulationJobs; void save(const string &saveToPath) const { assert(std::filesystem::is_directory(saveToPath)); const int numberOfSimulationJobs = fullPatternSimulationJobs.size(); for (int simulationJobIndex = 0; simulationJobIndex < numberOfSimulationJobs; simulationJobIndex++) { const std::shared_ptr &pFullPatternSimulationJob = fullPatternSimulationJobs[simulationJobIndex]; std::filesystem::path simulationJobFolderPath( std::filesystem::path(saveToPath) .append(pFullPatternSimulationJob->label)); std::filesystem::create_directory(simulationJobFolderPath); const auto fullPatternDirectoryPath = std::filesystem::path(simulationJobFolderPath).append("Full"); std::filesystem::create_directory(fullPatternDirectoryPath); pFullPatternSimulationJob->save(fullPatternDirectoryPath.string()); const std::shared_ptr &pReducedPatternSimulationJob = reducedPatternSimulationJobs[simulationJobIndex]; const auto reducedPatternDirectoryPath = std::filesystem::path(simulationJobFolderPath).append("Reduced"); if (!std::filesystem::exists(reducedPatternDirectoryPath)) { std::filesystem::create_directory(reducedPatternDirectoryPath); } pReducedPatternSimulationJob->save(reducedPatternDirectoryPath.string()); } } void load(const string &loadFromPath) { assert(std::filesystem::is_directory(loadFromPath)); for (const auto &directoryEntry : filesystem::directory_iterator(loadFromPath)) { const auto simulationScenarioPath = directoryEntry.path(); if (!std::filesystem::is_directory(simulationScenarioPath)) { continue; } // Load reduced pattern files for (const auto &fileEntry : filesystem::directory_iterator( std::filesystem::path(simulationScenarioPath).append("Full"))) { const auto filepath = fileEntry.path(); if (filepath.extension() == ".json") { SimulationJob job; job.load(filepath.string()); fullPatternSimulationJobs.push_back( std::make_shared(job)); } } // Load full pattern files for (const auto &fileEntry : filesystem::directory_iterator( std::filesystem::path(simulationScenarioPath) .append("Reduced"))) { const auto filepath = fileEntry.path(); if (filepath.extension() == ".json") { SimulationJob job; job.load(filepath.string()); reducedPatternSimulationJobs.push_back( std::make_shared(job)); } } } } void saveMeshFiles() const { const int numberOfSimulationJobs = fullPatternSimulationJobs.size(); assert(numberOfSimulationJobs != 0 && fullPatternSimulationJobs.size() == reducedPatternSimulationJobs.size()); fullPatternSimulationJobs[0]->pMesh->savePly("FullPattern_undeformed.ply"); reducedPatternSimulationJobs[0]->pMesh->savePly( "ReducedPattern_undeformed.ply"); FormFinder simulator; for (int simulationJobIndex = 0; simulationJobIndex < numberOfSimulationJobs; simulationJobIndex++) { // Drawing of full pattern results const std::shared_ptr &pFullPatternSimulationJob = fullPatternSimulationJobs[simulationJobIndex]; SimulationResults fullModelResults = simulator.executeSimulation(pFullPatternSimulationJob); fullModelResults.saveDeformedModel(); // Drawing of reduced pattern results const std::shared_ptr &pReducedPatternSimulationJob = reducedPatternSimulationJobs[simulationJobIndex]; SimulationResults reducedModelResults = simulator.executeSimulation(pReducedPatternSimulationJob); reducedModelResults.saveDeformedModel(); } } void writeHeaderTo(const ReducedModelOptimizer::Settings &settings_optimization, csvFile &os) { os << "Obj value"; for (const ReducedModelOptimizer::xRange &range : settings_optimization.xRanges) { os << range.label; } os << "Time(s)"; os << "#Crashes"; } void writeResultsTo(const ReducedModelOptimizer::Settings &settings_optimization, csvFile &os) const { os << objectiveValue; for (const double &optimalX : x) { os << optimalX; } for (int unusedXVarCounter = 0; unusedXVarCounter < settings_optimization.xRanges.size() - x.size(); unusedXVarCounter++) { os << "-"; } os << time; if (numberOfSimulationCrashes == 0) { os << "-"; } else { os << numberOfSimulationCrashes; } } }; #endif // REDUCEDMODELOPTIMIZER_HPP