Made normalization strategy member of the optimization settings.

This commit is contained in:
Iason 2021-03-01 14:34:27 +02:00
commit bd41cc31eb
4 changed files with 540 additions and 542 deletions

View File

@ -37,16 +37,15 @@ download_project(PROJ MYSOURCES
endif() endif()
##Polyscope
#Polyscope #download_project(PROJ POLYSCOPE
download_project(PROJ POLYSCOPE # GIT_REPOSITORY https://github.com/nmwsharp/polyscope.git
GIT_REPOSITORY https://github.com/nmwsharp/polyscope.git # GIT_TAG master
GIT_TAG master # PREFIX ${CMAKE_CURRENT_SOURCE_DIR}/build/external/
PREFIX ${CMAKE_CURRENT_SOURCE_DIR}/build/external/ # ${UPDATE_DISCONNECTED_IF_AVAILABLE}
${UPDATE_DISCONNECTED_IF_AVAILABLE} #)
) #add_subdirectory(${POLYSCOPE_SOURCE_DIR})
add_subdirectory(${POLYSCOPE_SOURCE_DIR}) #add_compile_definitions(POLYSCOPE_DEFINED)
add_compile_definitions(POLYSCOPE_DEFINED)
#dlib #dlib
download_project(PROJ DLIB download_project(PROJ DLIB
@ -89,4 +88,5 @@ target_include_directories(${PROJECT_NAME}
) )
link_directories(${MYSOURCES_SOURCE_DIR}/boost_graph/libs) link_directories(${MYSOURCES_SOURCE_DIR}/boost_graph/libs)
target_link_libraries(${PROJECT_NAME} polyscope Eigen3::Eigen matplot dlib::dlib) #target_link_libraries(${PROJECT_NAME} polyscope Eigen3::Eigen matplot dlib::dlib)
target_link_libraries(${PROJECT_NAME} -static Eigen3::Eigen matplot dlib::dlib)

View File

@ -2,9 +2,6 @@
#include "csvfile.hpp" #include "csvfile.hpp"
#include "edgemesh.hpp" #include "edgemesh.hpp"
#include "flatpattern.hpp" #include "flatpattern.hpp"
#include "polyscope/curve_network.h"
#include "polyscope/point_cloud.h"
#include "polyscope/polyscope.h"
#include "reducedmodeloptimizer.hpp" #include "reducedmodeloptimizer.hpp"
#include "simulationhistoryplotter.hpp" #include "simulationhistoryplotter.hpp"
#include "trianglepattterntopology.hpp" #include "trianglepattterntopology.hpp"
@ -16,6 +13,11 @@
#include <string> #include <string>
#include <vcg/complex/algorithms/update/position.h> #include <vcg/complex/algorithms/update/position.h>
#ifdef POLYSCOPE_DEFINED
#include "polyscope/curve_network.h"
#include "polyscope/point_cloud.h"
#include "polyscope/polyscope.h"
#endif
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
if (argc < 3) { if (argc < 3) {
std::cerr << "Specify at least the two pattern filepaths to be " std::cerr << "Specify at least the two pattern filepaths to be "
@ -49,7 +51,10 @@ int main(int argc, char *argv[]) {
const bool input_numberOfFunctionCallsDefined = argc >= 4; const bool input_numberOfFunctionCallsDefined = argc >= 4;
settings_optimization.numberOfFunctionCalls = settings_optimization.numberOfFunctionCalls =
input_numberOfFunctionCallsDefined ? std::atoi(argv[3]) : 100; input_numberOfFunctionCallsDefined ? std::atoi(argv[3]) : 100;
settings_optimization.shouldNormalizeObjectiveValue = true; settings_optimization.normalizationStrategy =
ReducedModelOptimizer::Settings::NormalizationStrategy::Epsilon;
settings_optimization.normalizationParameter = 0.003;
settings_optimization.solutionAccuracy = 0.01;
// Optimize pair // Optimize pair
const std::string pairName = const std::string pairName =
@ -65,21 +70,24 @@ int main(int argc, char *argv[]) {
const bool input_resultDirectoryDefined = argc >= 5; const bool input_resultDirectoryDefined = argc >= 5;
std::string optimizationResultsDirectory = std::string optimizationResultsDirectory =
input_resultDirectoryDefined ? argv[4] : "OptimizationResults"; input_resultDirectoryDefined ? argv[4] : "OptimizationResults";
std::string resultsOutputDir;
if (optimizationResults.numberOfSimulationCrashes != 0) { if (optimizationResults.numberOfSimulationCrashes != 0) {
const auto crashedJobsDirPath = const auto crashedJobsDirPath =
std::filesystem::path(optimizationResultsDirectory) std::filesystem::path(optimizationResultsDirectory)
.append("CrashedJobs") .append("CrashedJobs")
.append(pairName); .append(pairName);
std::filesystem::create_directories(crashedJobsDirPath); std::filesystem::create_directories(crashedJobsDirPath);
optimizationResults.save(crashedJobsDirPath.string()); resultsOutputDir = crashedJobsDirPath.string();
} else { } else {
std::filesystem::path convergedJobsDirPath( std::filesystem::path convergedJobsDirPath(
std::filesystem::path(optimizationResultsDirectory) std::filesystem::path(optimizationResultsDirectory)
.append("ConvergedJobs") .append("ConvergedJobs")
.append(pairName)); .append(pairName));
std::filesystem::create_directories(convergedJobsDirPath); std::filesystem::create_directories(convergedJobsDirPath);
optimizationResults.save(convergedJobsDirPath.string()); resultsOutputDir = convergedJobsDirPath.string();
} }
optimizationResults.save(resultsOutputDir);
// Write results in csv
csvFile csv_results({}, false); csvFile csv_results({}, false);
// csvFile csv_results(std::filesystem::path(dirPath_thisOptimization) // csvFile csv_results(std::filesystem::path(dirPath_thisOptimization)
// .append("results.csv") // .append("results.csv")

View File

@ -9,7 +9,7 @@
struct GlobalOptimizationVariables { struct GlobalOptimizationVariables {
std::vector<Eigen::MatrixX3d> g_optimalReducedModelDisplacements; std::vector<Eigen::MatrixX3d> g_optimalReducedModelDisplacements;
std::vector<std::vector<Vector6d>> fullPatternDisplacements; std::vector<std::vector<Vector6d>> fullPatternDisplacements;
std::vector<double> reducedPatternMaximumDisplacementNormSum; std::vector<double> objectiveNormalizationValues;
std::vector<std::shared_ptr<SimulationJob>> fullPatternSimulationJobs; std::vector<std::shared_ptr<SimulationJob>> fullPatternSimulationJobs;
std::vector<std::shared_ptr<SimulationJob>> reducedPatternSimulationJobs; std::vector<std::shared_ptr<SimulationJob>> reducedPatternSimulationJobs;
std::unordered_map<ReducedPatternVertexIndex, FullPatternVertexIndex> std::unordered_map<ReducedPatternVertexIndex, FullPatternVertexIndex>
@ -46,16 +46,10 @@ double ReducedModelOptimizer::computeError(
const double rawError = const double rawError =
computeRawError(reducedPatternDisplacements, fullPatternDisplacements, computeRawError(reducedPatternDisplacements, fullPatternDisplacements,
reducedToFullInterfaceViMap); reducedToFullInterfaceViMap);
if (global.optimizationSettings.shouldNormalizeObjectiveValue) { if (global.optimizationSettings.normalizationStrategy !=
assert(rawError <= normalizationFactor); Settings::NormalizationStrategy::NonNormalized) {
if (rawError > normalizationFactor) { return rawError / normalizationFactor;
std::cout << "Normalized error is bigger than one." << std::endl;
}
return rawError /
normalizationFactor; // std::max(interfaceDisplacementsNormSum,
// 0.00003);
} }
return rawError; return rawError;
} }
@ -66,24 +60,22 @@ double ReducedModelOptimizer::computeRawError(
&reducedToFullInterfaceViMap) { &reducedToFullInterfaceViMap) {
double error = 0; double error = 0;
for (const auto reducedFullViPair : reducedToFullInterfaceViMap) { for (const auto reducedFullViPair : reducedToFullInterfaceViMap) {
// const auto pos = const VertexIndex reducedModelVi = reducedFullViPair.first;
// g_reducedPatternSimulationJob.mesh->vert[reducedModelVi].cP();
// std::cout << "Interface vi " << reducedModelVi << " is at position "
// << pos[0] << " " << pos[1] << " " << pos[2] << std::endl;
Eigen::Vector3d reducedVertexDisplacement( Eigen::Vector3d reducedVertexDisplacement(
reducedPatternDisplacements[reducedFullViPair.first][0], reducedPatternDisplacements[reducedModelVi][0],
reducedPatternDisplacements[reducedFullViPair.first][1], reducedPatternDisplacements[reducedModelVi][1],
reducedPatternDisplacements[reducedFullViPair.first][2]); reducedPatternDisplacements[reducedModelVi][2]);
if (!std::isfinite(reducedVertexDisplacement[0]) || if (!std::isfinite(reducedVertexDisplacement[0]) ||
!std::isfinite(reducedVertexDisplacement[1]) || !std::isfinite(reducedVertexDisplacement[1]) ||
!std::isfinite(reducedVertexDisplacement[2])) { !std::isfinite(reducedVertexDisplacement[2])) {
std::cout << "Displacements are not finite" << std::endl; std::cout << "Displacements are not finite" << std::endl;
std::terminate(); std::terminate();
} }
const VertexIndex fullModelVi = reducedFullViPair.second;
Eigen::Vector3d fullVertexDisplacement( Eigen::Vector3d fullVertexDisplacement(
fullPatternDisplacements[reducedFullViPair.second][0], fullPatternDisplacements[fullModelVi][0],
fullPatternDisplacements[reducedFullViPair.second][1], fullPatternDisplacements[fullModelVi][1],
fullPatternDisplacements[reducedFullViPair.second][2]); fullPatternDisplacements[fullModelVi][2]);
Eigen::Vector3d errorVector = Eigen::Vector3d errorVector =
fullVertexDisplacement - reducedVertexDisplacement; fullVertexDisplacement - reducedVertexDisplacement;
// error += errorVector.squaredNorm(); // error += errorVector.squaredNorm();
@ -179,7 +171,7 @@ double ReducedModelOptimizer::objective(long n, const double *x) {
// << std::endl; // << std::endl;
// run simulations // run simulations
double error = 0; double totalError = 0;
FormFinder simulator; FormFinder simulator;
FormFinder::Settings simulationSettings; FormFinder::Settings simulationSettings;
// simulationSettings.shouldDraw = true; // simulationSettings.shouldDraw = true;
@ -192,75 +184,54 @@ double ReducedModelOptimizer::objective(long n, const double *x) {
simulationSettings); simulationSettings);
// std::string filename; // std::string filename;
if (!reducedModelResults.converged) { if (!reducedModelResults.converged) {
error += std::numeric_limits<double>::max(); totalError += std::numeric_limits<double>::max();
global.numOfSimulationCrashes++; global.numOfSimulationCrashes++;
bool beVerbose = false; // TODO: use an extern or data member for that bool beVerbose = false; // TODO: use an extern or data member for that
if (beVerbose) { if (beVerbose) {
std::cout << "Failed simulation" << std::endl; std::cout << "Failed simulation" << std::endl;
} }
} else { } else {
const double thisSimulationScenarioError = double simulationScenarioError = computeError(
computeError(reducedModelResults.displacements, reducedModelResults.displacements,
global.fullPatternDisplacements[simulationScenarioIndex], global.fullPatternDisplacements[simulationScenarioIndex],
global.reducedToFullInterfaceViMap, global.reducedToFullInterfaceViMap,
global.reducedPatternMaximumDisplacementNormSum global.objectiveNormalizationValues[simulationScenarioIndex]);
[simulationScenarioIndex]);
if (thisSimulationScenarioError > 1) {
std::cout << "Simulation scenario "
<< simulationScenarioStrings[simulationScenarioIndex]
<< " results in an error bigger than one." << std::endl;
for (size_t parameterIndex = 0; parameterIndex < n; parameterIndex++) {
std::cout << "x[" + std::to_string(parameterIndex) + "]="
<< x[parameterIndex] << std::endl;
}
//#ifdef POLYSCOPE_DEFINED // if (global.optimizationSettings.normalizationStrategy !=
// ReducedModelOptimizer::visualizeResults( // NormalizationStrategy::Epsilon &&
// global.fullPatternSimulationJobs[simulationScenarioIndex], // simulationScenarioError > 1) {
// global.reducedPatternSimulationJobs[simulationScenarioIndex], // std::cout << "Simulation scenario "
// global.reducedToFullInterfaceViMap, false); // <<
// simulationScenarioStrings[simulationScenarioIndex]
// << " results in an error bigger than one." <<
// std::endl;
// for (size_t parameterIndex = 0; parameterIndex < n;
// parameterIndex++) {
// std::cout << "x[" + std::to_string(parameterIndex) + "]="
// << x[parameterIndex] << std::endl;
// }
// }
// ReducedModelOptimizer::visualizeResults( //#ifdef POLYSCOPE_DEFINED
// global.fullPatternSimulationJobs[simulationScenarioIndex], // ReducedModelOptimizer::visualizeResults(
// std::make_shared<SimulationJob>( // global.fullPatternSimulationJobs[simulationScenarioIndex],
// reducedPatternMaximumDisplacementSimulationJobs // global.reducedPatternSimulationJobs[simulationScenarioIndex],
// [simulationScenarioIndex]), // global.reducedToFullInterfaceViMap, false);
// global.reducedToFullInterfaceViMap, true);
// polyscope::removeAllStructures(); // ReducedModelOptimizer::visualizeResults(
//#endif // POLYSCOPE_DEFINED // global.fullPatternSimulationJobs[simulationScenarioIndex],
} // std::make_shared<SimulationJob>(
error += thisSimulationScenarioError; // reducedPatternMaximumDisplacementSimulationJobs
// [simulationScenarioIndex]),
// global.reducedToFullInterfaceViMap, true);
// polyscope::removeAllStructures();
//#endif // POLYSCOPE_DEFINED
totalError += simulationScenarioError;
} }
// std::ofstream out(filename, std::ios_base::app);
// auto pMesh =
// global
// .reducedPatternSimulationJobs[global.simulationScenarioIndices[0]]
// ->pMesh;
// for (size_t parameterIndex = 0; parameterIndex < n; parameterIndex++)
// {
// out << "x[" + std::to_string(parameterIndex) + "]=" <<
// x[parameterIndex]
// << std::endl;
// }
// out << pMesh->elements[0].dimensions.toString() + "\n" +
// pMesh->elements[0].material.toString() + " \nA="
// << pMesh->elements[0].A << " \nratio="
// << pMesh->elements[0].dimensions.b /
// pMesh->elements[0].dimensions.h
// << " \naxialRig:" << pMesh->elements[0].rigidity.axial
// << " \ntorsionalRig:" << pMesh->elements[0].rigidity.torsional
// << " \nfirstBendingRig:" <<
// pMesh->elements[0].rigidity.firstBending
// << " \nsecondBendingRig:" <<
// pMesh->elements[0].rigidity.secondBending
// << " \nscenario:" +
// simulationScenarioStrings[simulationScenarioIndex] +
// "\n\n";
// out.close();
} }
// std::cout << error << std::endl; // std::cout << error << std::endl;
if (error < global.minY) { if (totalError < global.minY) {
global.minY = error; global.minY = totalError;
global.minX.assign(x, x + n); global.minX.assign(x, x + n);
} }
// if (++global.numberOfFunctionCalls %100== 0) { // if (++global.numberOfFunctionCalls %100== 0) {
@ -269,7 +240,7 @@ double ReducedModelOptimizer::objective(long n, const double *x) {
//} //}
// compute error and return it // compute error and return it
global.gObjectiveValueHistory.push_back(error); // global.gObjectiveValueHistory.push_back(error);
// auto xPlot = matplot::linspace(0, gObjectiveValueHistory.size(), // auto xPlot = matplot::linspace(0, gObjectiveValueHistory.size(),
// gObjectiveValueHistory.size()); // gObjectiveValueHistory.size());
// std::vector<double> colors(gObjectiveValueHistory.size(), 2); // std::vector<double> colors(gObjectiveValueHistory.size(), 2);
@ -282,7 +253,7 @@ double ReducedModelOptimizer::objective(long n, const double *x) {
// value", // value",
// gObjectiveValueHistory); // gObjectiveValueHistory);
return error; return totalError;
} }
void ReducedModelOptimizer::createSimulationMeshes( void ReducedModelOptimizer::createSimulationMeshes(
@ -578,11 +549,73 @@ void ReducedModelOptimizer::computeReducedModelSimulationJob(
#if POLYSCOPE_DEFINED #if POLYSCOPE_DEFINED
void ReducedModelOptimizer::visualizeResults( void ReducedModelOptimizer::visualizeResults(
const std::vector<std::shared_ptr<SimulationJob>>
&fullPatternSimulationJobs,
const std::vector<std::shared_ptr<SimulationJob>>
&reducedPatternSimulationJobs,
const std::vector<SimulationScenario> &simulationScenarios,
const std::unordered_map<ReducedPatternVertexIndex, FullPatternVertexIndex>
&reducedToFullInterfaceViMap) {
FormFinder simulator;
std::shared_ptr<SimulationMesh> pFullPatternSimulationMesh =
fullPatternSimulationJobs[0]->pMesh;
pFullPatternSimulationMesh->registerForDrawing();
pFullPatternSimulationMesh->savePly(pFullPatternSimulationMesh->getLabel() +
"_undeformed.ply");
reducedPatternSimulationJobs[0]->pMesh->savePly(
reducedPatternSimulationJobs[0]->pMesh->getLabel() + "_undeformed.ply");
double totalError = 0;
for (const int simulationScenarioIndex : simulationScenarios) {
const std::shared_ptr<SimulationJob> &pFullPatternSimulationJob =
fullPatternSimulationJobs[simulationScenarioIndex];
pFullPatternSimulationJob->registerForDrawing(
pFullPatternSimulationMesh->getLabel());
SimulationResults fullModelResults =
simulator.executeSimulation(pFullPatternSimulationJob);
fullModelResults.registerForDrawing();
// fullModelResults.saveDeformedModel();
const std::shared_ptr<SimulationJob> &pReducedPatternSimulationJob =
reducedPatternSimulationJobs[simulationScenarioIndex];
SimulationResults reducedModelResults =
simulator.executeSimulation(pReducedPatternSimulationJob);
double normalizationFactor = 1;
if (global.optimizationSettings.normalizationStrategy !=
Settings::NormalizationStrategy::NonNormalized) {
normalizationFactor =
global.objectiveNormalizationValues[simulationScenarioIndex];
}
reducedModelResults.saveDeformedModel();
fullModelResults.saveDeformedModel();
double error = computeError(
reducedModelResults.displacements, fullModelResults.displacements,
reducedToFullInterfaceViMap, normalizationFactor);
std::cout << "Error of simulation scenario "
<< simulationScenarioStrings[simulationScenarioIndex] << " is "
<< error << std::endl;
totalError += error;
reducedModelResults.registerForDrawing();
// firstOptimizationRoundResults[simulationScenarioIndex].registerForDrawing();
// registerWorldAxes();
const std::string screenshotFilename =
"/home/iason/Coding/Projects/Approximating shapes with flat "
"patterns/RodModelOptimizationForPatterns/build/OptimizationResults/"
"Images/" +
pFullPatternSimulationMesh->getLabel() + "_" +
simulationScenarioStrings[simulationScenarioIndex];
polyscope::show();
polyscope::screenshot(screenshotFilename, false);
fullModelResults.unregister();
reducedModelResults.unregister();
// firstOptimizationRoundResults[simulationScenarioIndex].unregister();
}
std::cout << "Total error:" << totalError << std::endl;
}
void ReducedModelOptimizer::registerResultsForDrawing(
const std::shared_ptr<SimulationJob> &pFullPatternSimulationJob, const std::shared_ptr<SimulationJob> &pFullPatternSimulationJob,
const std::shared_ptr<SimulationJob> &pReducedPatternSimulationJob, const std::shared_ptr<SimulationJob> &pReducedPatternSimulationJob,
const std::unordered_map<ReducedPatternVertexIndex, FullPatternVertexIndex> const std::unordered_map<ReducedPatternVertexIndex, FullPatternVertexIndex>
&reducedToFullInterfaceViMap, &reducedToFullInterfaceViMap) {
const bool &draw = true) {
FormFinder simulator; FormFinder simulator;
std::shared_ptr<SimulationMesh> pFullPatternSimulationMesh = std::shared_ptr<SimulationMesh> pFullPatternSimulationMesh =
pFullPatternSimulationJob->pMesh; pFullPatternSimulationJob->pMesh;
@ -609,19 +642,6 @@ void ReducedModelOptimizer::visualizeResults(
global.reducedPatternMaximumDisplacementNormSum[simulationScenarioIndex]*/); global.reducedPatternMaximumDisplacementNormSum[simulationScenarioIndex]*/);
std::cout << "Error is " << error << std::endl; std::cout << "Error is " << error << std::endl;
reducedModelResults.registerForDrawing(); reducedModelResults.registerForDrawing();
if (draw) {
polyscope::show();
const std::string screenshotFilename =
"/home/iason/Coding/Projects/Approximating shapes with flat "
"patterns/RodModelOptimizationForPatterns/Results/"
"Images/" +
pFullPatternSimulationMesh->getLabel() + "_" + "noScenarioName";
// simulationScenarioStrings[simulationScenarioIndex];
polyscope::screenshot(screenshotFilename, false);
fullModelResults.unregister();
reducedModelResults.unregister();
pFullPatternSimulationMesh->unregister();
}
} }
#endif // POLYSCOPE_DEFINED #endif // POLYSCOPE_DEFINED
@ -651,46 +671,6 @@ ReducedModelOptimizer::Results
ReducedModelOptimizer::runOptimization(const Settings &settings) { ReducedModelOptimizer::runOptimization(const Settings &settings) {
global.gObjectiveValueHistory.clear(); global.gObjectiveValueHistory.clear();
// g_optimizeInnerHexagonSize ? 5: 4;
// const size_t npt = (n + 1) * (n + 2) / 2;
// // ((n + 2) + ((n + 1) * (n + 2) / 2)) / 2;
// assert(npt <= (n + 1) * (n + 2) / 2 && npt >= n + 2);
// assert(npt <= 2 * n + 1 && "The choice of the number of interpolation "
// "conditions is not recommended.");
// Set initial guess of solution
// const size_t initialGuess = 1;
// std::vector<double> x(n, initialGuess);
// if (global.optimizeInnerHexagonSize) {
// x[n - 1] = global.g_innerHexagonInitialPos;
//}
/*if (!initialGuess.empty()) {
x = g_optimizationInitialGuess;
}*/ // {0.10000000000000 001,
// 2, 1.9999999971613847, 6.9560343643347764};
// {1, 5.9277};
// {0.0001, 2, 2.000000005047502, 1.3055270196964464};
// {initialGuess(0), initialGuess(1), initialGuess(2),
// initialGuess(3)};
// assert(x.end() == find_if(x.begin(), x.end(), [&](const double &d) {
// return d >= xMax || d <= xMin;
// }));
// std::vector<double> xLow(x.size(), xMin);
// std::vector<double> xUpper(x.size(), xMax);
// if (g_optimizeInnerHexagonSize) {
// xLow[n - 1] = 0.1;
// xUpper[n - 1] = 0.9;
// }
// const double maxX = *std::max_element(
// x.begin(), x.end(),
// [](const double &a, const double &b) { return abs(a) < abs(b); });
// const double rhobeg = std::min(0.95, 0.2 * maxX);
// double rhobeg = 1;
// double rhoend = rhobeg * 1e-8;
// const size_t wSize = (npt + 5) * (npt + n) + 3 * n * (n + 5) / 2;
// std::vector<double> w(wSize);
// const size_t maxFun = std::min(100.0 * (x.size() + 1), 1000.0);
dlib::matrix<double, 0, 1> xMin(global.numberOfOptimizationParameters); dlib::matrix<double, 0, 1> xMin(global.numberOfOptimizationParameters);
dlib::matrix<double, 0, 1> xMax(global.numberOfOptimizationParameters); dlib::matrix<double, 0, 1> xMax(global.numberOfOptimizationParameters);
for (int i = 0; i < global.numberOfOptimizationParameters; i++) { for (int i = 0; i < global.numberOfOptimizationParameters; i++) {
@ -720,17 +700,59 @@ ReducedModelOptimizer::runOptimization(const Settings &settings) {
results.numberOfSimulationCrashes = global.numOfSimulationCrashes; results.numberOfSimulationCrashes = global.numOfSimulationCrashes;
results.x = global.minX; results.x = global.minX;
results.objectiveValue = global.minY; results.objectiveValue = global.minY;
if (settings.shouldNormalizeObjectiveValue) { if (global.minY != result.y) {
global.optimizationSettings.shouldNormalizeObjectiveValue = false; std::cerr << "Global min objective is not equal to result objective"
<< std::endl;
}
// Compute raw objective value
if (global.optimizationSettings.normalizationStrategy !=
Settings::NormalizationStrategy::NonNormalized) {
auto temp = global.optimizationSettings.normalizationStrategy;
global.optimizationSettings.normalizationStrategy =
Settings::NormalizationStrategy::NonNormalized;
if (global.optimizeInnerHexagonSize) { if (global.optimizeInnerHexagonSize) {
results.objectiveValue = objective(4, results.x.data()); results.rawObjectiveValue = objective(4, results.x.data());
} else { } else {
results.objectiveValue = results.rawObjectiveValue =
objective(results.x[0], results.x[1], results.x[2]); objective(results.x[0], results.x[1], results.x[2]);
} }
global.optimizationSettings.shouldNormalizeObjectiveValue = true; global.optimizationSettings.normalizationStrategy = temp;
} else {
results.rawObjectiveValue = results.objectiveValue;
} }
// Compute obj value per simulation scenario
updateMesh(results.x.size(), results.x.data());
results.objectiveValuePerSimulationScenario.resize(
NumberOfSimulationScenarios);
FormFinder::Settings simulationSettings;
FormFinder simulator;
for (int simulationScenarioIndex = 0;
simulationScenarioIndex < NumberOfSimulationScenarios;
simulationScenarioIndex++) {
SimulationResults reducedModelResults = simulator.executeSimulation(
global.reducedPatternSimulationJobs[simulationScenarioIndex],
simulationSettings);
const double error = computeError(
reducedModelResults.displacements,
global.fullPatternDisplacements[simulationScenarioIndex],
global.reducedToFullInterfaceViMap,
global.objectiveNormalizationValues[simulationScenarioIndex]);
results.objectiveValuePerSimulationScenario[simulationScenarioIndex] =
error;
}
// if (result.y !=
// std::accumulate(results.objectiveValuePerSimulationScenario.begin(),
// results.objectiveValuePerSimulationScenario.end(), 0))
// {
// std::cerr
// << "Sum of per scenario objectives is not equal to result objective"
// << std::endl;
// }
results.time = elapsed.count() / 1000.0; results.time = elapsed.count() / 1000.0;
const bool printDebugInfo = false; const bool printDebugInfo = false;
if (printDebugInfo) { if (printDebugInfo) {
@ -739,33 +761,6 @@ ReducedModelOptimizer::runOptimization(const Settings &settings) {
// std::cout << result.x << endl; // std::cout << result.x << endl;
std::cout << "Objective value:" << global.minY << endl; std::cout << "Objective value:" << global.minY << endl;
} }
// std::cout << result.y << endl;
// std::cout << minY << endl;
// std::cout << "Time(sec):" << elapsed.count() << std::endl;
// std::cout << "Max function evaluations:" << maxFun << std::endl;
// std::cout << "Initial guess:" << initialGuess << std::endl;
// const size_t maxFun = 200;
// bobyqa(pObjectiveFunction, n, npt, x.data(), xLow.data(), xUpper.data(),
// rhobeg, rhoend, maxFun, w.data());
// std::cout << "Finished first optimization round" << std::endl;
// firstOptimizationRoundResults.resize(6);
// for (int simulationScenarioIndex = SimulationScenario::Axial;
// simulationScenarioIndex !=
// SimulationScenario::NumberOfSimulationScenarios;
// simulationScenarioIndex++) {
// SimulationResults reducedModelResults = simulator.executeSimulation(
// g_reducedPatternSimulationJob[simulationScenarioIndex], false,
// false);
// reducedModelResults.setLabelPrefix("FirstRound");
// firstOptimizationRoundResults[simulationScenarioIndex] =
// std::move(reducedModelResults);
// }
// g_firstRoundIterationIndex = gObjectiveValueHistory.size();
// rhobeg *= 1e1;
// // rhoend *= 1e2;
// bobyqa(pObjectiveFunction, n, npt, x.data(), xLow.data(), xUpper.data(),
// rhobeg, rhoend, maxFun, w.data());
// std::cout << "Finished second optimization round" << std::endl;
return results; return results;
} }
@ -784,37 +779,7 @@ ReducedModelOptimizer::createScenarios(
const double forceMagnitude = 1; const double forceMagnitude = 1;
// Assuming the patterns lays on the x-y plane // Assuming the patterns lays on the x-y plane
const CoordType patternPlaneNormal(0, 0, 1); const CoordType patternPlaneNormal(0, 0, 1);
// Make the first interface node lay on the x axis // Assumes that the first interface node lay on the x axis
// const size_t fullPatternFirstInterfaceNodeIndex =
// m_fullPatternOppositeInterfaceViMap.begin()->second;
// CoordType fullPatternFirstInterfaceNodePosition =
// m_pFullModelSimulationMesh->vert[fullPatternFirstInterfaceNodeIndex].cP();
// CoordType centerOfMass(0, 0, 0);
// for (size_t vi = 0; vi < pMesh->VN(); vi++) {
// centerOfMass = centerOfMass + pMesh->vert[vi].P();
// }
// centerOfMass /= pMesh->VN();
// vcg::tri::UpdatePosition<SimulationMesh>::Translate(
// *m_pFullModelSimulationMesh, -centerOfMass);
// vcg::tri::UpdatePosition<SimulationMesh>::Translate(
// *m_pReducedPatternSimulationMesh, centerOfMass);
// const vcg::Matrix33d R = vcg::RotationMatrix(
// fullPatternFirstInterfaceNodePosition,
// CoordType(fullPatternFirstInterfaceNodePosition.Norm(), 0, 0), false);
// std::for_each(m_pFullModelSimulationMesh->vert.begin(),
// m_pFullModelSimulationMesh->vert.end(), [&](auto &v) {
// v.P() = R * v.P();
// v.N() = R * v.N();
// });
// std::for_each(m_pReducedPatternSimulationMesh->vert.begin(),
// m_pReducedPatternSimulationMesh->vert.end(), [&](auto &v) {
// v.P() = R * v.P();
// v.N() = R * v.N();
// });
// m_pFullModelSimulationMesh->updateEigenEdgeAndVertices();
// m_pReducedPatternSimulationMesh->updateEigenEdgeAndVertices();
//// Axial //// Axial
SimulationScenario scenarioName = SimulationScenario::Axial; SimulationScenario scenarioName = SimulationScenario::Axial;
@ -945,89 +910,87 @@ ReducedModelOptimizer::createScenarios(
return scenarios; return scenarios;
} }
// void ReducedModelOptimizer::runBeamOptimization() { void ReducedModelOptimizer::computeObjectiveValueNormalizationFactors() {
// // load beams assert(global.optimizationSettings.shouldNormalizeObjectiveValue);
// VCGEdgeMesh fullBeam; if (global.optimizationSettings.normalizationStrategy ==
// fullBeam.loadPly("/home/iason/Models/simple_beam_model_10elem_1m.ply"); Settings::NormalizationStrategy::Epsilon ||
// VCGEdgeMesh reducedBeam; global.optimizationSettings.normalizationStrategy ==
// reducedBeam.loadPly("/home/iason/Models/simple_beam_model_4elem_1m.ply"); Settings::NormalizationStrategy::EqualDisplacements) {
// fullBeam.registerForDrawing();
// reducedBeam.registerForDrawing();
// // polyscope::show();
// // maps
// std::unordered_map<size_t, size_t> displacementReducedToFullMap;
// displacementReducedToFullMap[reducedBeam.VN() / 2] = fullBeam.VN() / 2;
// g_reducedToFullViMap = displacementReducedToFullMap;
// std::unordered_map<size_t, size_t> jobFullToReducedMap;
// jobFullToReducedMap[0] = 0;
// jobFullToReducedMap[fullBeam.VN() - 1] = reducedBeam.VN() - 1;
// // full model simuilation job // Compute the sum of the displacement norms
// auto pFullPatternSimulationMesh = std::vector<double> fullPatternDisplacementNormSum(
// std::make_shared<SimulationMesh>(fullBeam); NumberOfSimulationScenarios);
// pFullPatternSimulationMesh->setBeamCrossSection(CrossSectionType{0.02, for (int simulationScenarioIndex : global.simulationScenarioIndices) {
// 0.02}); pFullPatternSimulationMesh->setBeamMaterial(0.3, 1 * 1e9); double displacementNormSum = 0;
// std::unordered_map<VertexIndex, std::unordered_set<int>> fixedVertices; for (auto interfaceViPair : global.reducedToFullInterfaceViMap) {
// fixedVertices[0] = ::unordered_set<int>({0, 1, 2, 3, 4, 5}); const Vector6d &vertexDisplacement =
// std::unordered_map<VertexIndex, Vector6d> forces; global.fullPatternDisplacements[simulationScenarioIndex]
// forces[fullBeam.VN() - 1] = Vector6d({0, 0, 10, 0, 0, 0}); [interfaceViPair.second];
// const std::string fullBeamSimulationJobLabel = "Pull_Z"; displacementNormSum += vertexDisplacement.getTranslation().norm();
// std::shared_ptr<SimulationJob> pFullModelSimulationJob = }
// make_shared<SimulationJob>(SimulationJob(pFullPatternSimulationMesh, fullPatternDisplacementNormSum[simulationScenarioIndex] =
// fullBeamSimulationJobLabel, displacementNormSum;
// fixedVertices, forces)); }
// auto fullModelResults =
// formFinder.executeSimulation(pFullModelSimulationJob);
// // Optimal reduced model displacements for (int simulationScenarioIndex : global.simulationScenarioIndices) {
// const size_t numberOfSimulationScenarios = 1; if (global.optimizationSettings.normalizationStrategy ==
// g_optimalReducedModelDisplacements.resize(numberOfSimulationScenarios); Settings::NormalizationStrategy::Epsilon) {
// g_optimalReducedModelDisplacements[numberOfSimulationScenarios - 1].resize( const double epsilon =
// reducedBeam.VN(), 3); global.optimizationSettings.normalizationParameter;
// computeDesiredReducedModelDisplacements( if (epsilon > fullPatternDisplacementNormSum[simulationScenarioIndex]) {
// fullModelResults, displacementReducedToFullMap, // std::cout << "Epsilon used in "
// g_optimalReducedModelDisplacements[numberOfSimulationScenarios - 1]); // <<
// simulationScenarioStrings[simulationScenarioIndex]
// // reduced model simuilation job // << std::endl;
// auto reducedSimulationMesh = std::make_shared<SimulationMesh>(reducedBeam); }
// reducedSimulationMesh->setBeamCrossSection(CrossSectionType{0.02, 0.02}); global.objectiveNormalizationValues[simulationScenarioIndex] = std::max(
// reducedSimulationMesh->setBeamMaterial(0.3, 1 * 1e9); fullPatternDisplacementNormSum[simulationScenarioIndex], epsilon);
// g_reducedPatternSimulationJob.resize(numberOfSimulationScenarios); // displacementNormSum;
// SimulationJob reducedSimJob; } else { // NormalizationStrategy::EqualDisplacements
// computeReducedModelSimulationJob(*pFullModelSimulationJob, global.objectiveNormalizationValues[simulationScenarioIndex] =
// jobFullToReducedMap, reducedSimJob); fullPatternDisplacementNormSum[simulationScenarioIndex] /
// reducedSimJob.nodalExternalForces[reducedBeam.VN() - 1] = fullPatternDisplacementNormSum[SimulationScenario::Shear];
// reducedSimJob.nodalExternalForces[reducedBeam.VN() - 1] * 0.1; }
// g_reducedPatternSimulationJob[numberOfSimulationScenarios - 1] = }
// make_shared<SimulationJob>( } else if (global.optimizationSettings.normalizationStrategy ==
// reducedSimulationMesh, fullBeamSimulationJobLabel, Settings::NormalizationStrategy::MaxDisplacement) {
// reducedSimJob.constrainedVertices, for (int simulationScenarioIndex : global.simulationScenarioIndices) {
// reducedSimJob.nodalExternalForces); // Compute the quantities for normalizing the obj value
// initializeOptimizationParameters(reducedSimulationMesh); const double minB = global.optimizationSettings.xRanges[0].min;
const double maxRatio = global.optimizationSettings.xRanges[1].max;
// // const std::string simulationJobsPath = "SimulationJobs"; const double minE = global.optimizationSettings.xRanges[2].min;
// // std::filesystem::create_directory(simulationJobsPath); const double minHS = 0.3;
// // g_reducedPatternSimulationJob[0].save(simulationJobsPath); std::vector<double> mostFlexibleOptimizationParameters{minB, maxRatio,
// // g_reducedPatternSimulationJob[0].load( minE, minHS};
// // std::filesystem::path(simulationJobsPath) if (global.optimizeInnerHexagonSize) {
// // .append(g_reducedPatternSimulationJob[0].mesh->getLabel() + updateMesh(4, mostFlexibleOptimizationParameters.data());
// // "_simScenario.json")); } else {
updateMesh(3, mostFlexibleOptimizationParameters.data());
// runOptimization({}, &objective); }
reducedPatternMaximumDisplacementSimulationJobs[simulationScenarioIndex] =
// fullModelResults.registerForDrawing(); global.reducedPatternSimulationJobs[simulationScenarioIndex]
// SimulationResults reducedModelResults = simulator.executeSimulation( ->getCopy();
// g_reducedPatternSimulationJob[numberOfSimulationScenarios - 1]); reducedPatternMaximumDisplacementSimulationJobs[simulationScenarioIndex]
// double error = computeError( .pMesh->setLabel("reduced_maxDisplacement");
// reducedModelResults, SimulationResults reducedModelResults = simulator.executeSimulation(
// g_optimalReducedModelDisplacements[numberOfSimulationScenarios - 1]); global.reducedPatternSimulationJobs[simulationScenarioIndex]);
// reducedModelResults.registerForDrawing(); const double errorOfMaxDisplacedReduced = computeRawError(
// std::cout << "Error between beams:" << error << endl; reducedModelResults.displacements,
// // registerWorldAxes(); global.fullPatternDisplacements[simulationScenarioIndex],
// polyscope::show(); global.reducedToFullInterfaceViMap);
// fullModelResults.unregister(); const double errorOfNonDisplacedReduced = computeRawError(
// reducedModelResults.unregister(); std::vector<Vector6d>(reducedModelResults.displacements.size(),
//} Vector6d(0)),
global.fullPatternDisplacements[simulationScenarioIndex],
global.reducedToFullInterfaceViMap);
const double displacementMultiplier =
global.optimizationSettings.normalizationParameter;
global.objectiveNormalizationValues[simulationScenarioIndex] =
displacementMultiplier *
std::max(errorOfMaxDisplacedReduced, errorOfNonDisplacedReduced);
}
}
}
ReducedModelOptimizer::Results ReducedModelOptimizer::optimize( ReducedModelOptimizer::Results ReducedModelOptimizer::optimize(
const Settings &optimizationSettings, const Settings &optimizationSettings,
@ -1041,10 +1004,10 @@ ReducedModelOptimizer::Results ReducedModelOptimizer::optimize(
SimulationScenario::Saddle}; SimulationScenario::Saddle};
} }
global.g_optimalReducedModelDisplacements.resize(6); global.g_optimalReducedModelDisplacements.resize(NumberOfSimulationScenarios);
global.reducedPatternSimulationJobs.resize(6); global.reducedPatternSimulationJobs.resize(NumberOfSimulationScenarios);
global.fullPatternDisplacements.resize(6); global.fullPatternDisplacements.resize(NumberOfSimulationScenarios);
global.reducedPatternMaximumDisplacementNormSum.resize(6); global.objectiveNormalizationValues.resize(NumberOfSimulationScenarios);
global.g_firstRoundIterationIndex = 0; global.g_firstRoundIterationIndex = 0;
global.minY = std::numeric_limits<double>::max(); global.minY = std::numeric_limits<double>::max();
global.numOfSimulationCrashes = 0; global.numOfSimulationCrashes = 0;
@ -1052,7 +1015,8 @@ ReducedModelOptimizer::Results ReducedModelOptimizer::optimize(
global.optimizationSettings = optimizationSettings; global.optimizationSettings = optimizationSettings;
global.fullPatternSimulationJobs = global.fullPatternSimulationJobs =
createScenarios(m_pFullPatternSimulationMesh); createScenarios(m_pFullPatternSimulationMesh);
reducedPatternMaximumDisplacementSimulationJobs.resize(6); reducedPatternMaximumDisplacementSimulationJobs.resize(
NumberOfSimulationScenarios);
// polyscope::removeAllStructures(); // polyscope::removeAllStructures();
FormFinder::Settings simulationSettings; FormFinder::Settings simulationSettings;
@ -1071,40 +1035,11 @@ ReducedModelOptimizer::Results ReducedModelOptimizer::optimize(
reducedPatternSimulationJob); reducedPatternSimulationJob);
global.reducedPatternSimulationJobs[simulationScenarioIndex] = global.reducedPatternSimulationJobs[simulationScenarioIndex] =
std::make_shared<SimulationJob>(reducedPatternSimulationJob); std::make_shared<SimulationJob>(reducedPatternSimulationJob);
}
if (optimizationSettings.shouldNormalizeObjectiveValue) { if (global.optimizationSettings.normalizationStrategy !=
// Compute the quantities for normalizing the obj value Settings::NormalizationStrategy::NonNormalized) {
const double minB = optimizationSettings.xRanges[0].min; computeObjectiveValueNormalizationFactors();
const double maxRatio = optimizationSettings.xRanges[1].max;
const double minE = optimizationSettings.xRanges[2].min;
const double minHS = 0.3;
std::vector<double> mostFlexibleOptimizationParameters{minB, maxRatio,
minE, minHS};
if (global.optimizeInnerHexagonSize) {
updateMesh(4, mostFlexibleOptimizationParameters.data());
} else {
updateMesh(3, mostFlexibleOptimizationParameters.data());
}
reducedPatternMaximumDisplacementSimulationJobs[simulationScenarioIndex] =
global.reducedPatternSimulationJobs[simulationScenarioIndex]
->getCopy();
reducedPatternMaximumDisplacementSimulationJobs[simulationScenarioIndex]
.pMesh->setLabel("reduced_maxDisplacement");
SimulationResults reducedModelResults = simulator.executeSimulation(
global.reducedPatternSimulationJobs[simulationScenarioIndex],
simulationSettings);
const double errorOfMaxDisplacedReduced = computeRawError(
reducedModelResults.displacements, fullModelResults.displacements,
global.reducedToFullInterfaceViMap);
const double errorOfNonDisplacedReduced = computeRawError(
std::vector<Vector6d>(reducedModelResults.displacements.size(),
Vector6d(0)),
fullModelResults.displacements, global.reducedToFullInterfaceViMap);
const double displacementMultiplier = 2;
global.reducedPatternMaximumDisplacementNormSum[simulationScenarioIndex] =
displacementMultiplier *
std::max(errorOfMaxDisplacedReduced, errorOfNonDisplacedReduced);
}
} }
Results optResults = runOptimization(optimizationSettings); Results optResults = runOptimization(optimizationSettings);
for (int simulationScenarioIndex : global.simulationScenarioIndices) { for (int simulationScenarioIndex : global.simulationScenarioIndices) {
@ -1113,12 +1048,9 @@ ReducedModelOptimizer::Results ReducedModelOptimizer::optimize(
optResults.reducedPatternSimulationJobs.push_back( optResults.reducedPatternSimulationJobs.push_back(
global.reducedPatternSimulationJobs[simulationScenarioIndex]); global.reducedPatternSimulationJobs[simulationScenarioIndex]);
} }
optResults.draw();
#ifdef POLYSCOPE_DEFINED #ifdef POLYSCOPE_DEFINED
// visualizeResults( optResults.draw();
// global.fullPatternSimulationJobs, global.reducedPatternSimulationJobs,
// global.simulationScenarioIndices, global.reducedToFullInterfaceViMap);
#endif // POLYSCOPE_DEFINED #endif // POLYSCOPE_DEFINED
return optResults; return optResults;
} }

View File

@ -8,6 +8,9 @@
#include "matplot/matplot.h" #include "matplot/matplot.h"
#include <Eigen/Dense> #include <Eigen/Dense>
#ifdef POLYSCOPE_DEFINED
#include "polyscope/color_management.h"
#endif // POLYSCOPE_DEFINED
using FullPatternVertexIndex = VertexIndex; using FullPatternVertexIndex = VertexIndex;
using ReducedPatternVertexIndex = VertexIndex; using ReducedPatternVertexIndex = VertexIndex;
@ -21,6 +24,21 @@ class ReducedModelOptimizer {
std::unordered_map<size_t, size_t> nodeToSlot; std::unordered_map<size_t, size_t> nodeToSlot;
std::unordered_map<size_t, std::unordered_set<size_t>> slotToNode; std::unordered_map<size_t, std::unordered_set<size_t>> slotToNode;
std::vector<double> initialGuess; std::vector<double> initialGuess;
#ifdef POLYSCOPE_DEFINED
struct StaticColors {
glm::vec3 fullInitial;
glm::vec3 fullDeformed;
glm::vec3 reducedInitial;
glm::vec3 reducedDeformed;
StaticColors() {
fullInitial = {0.416666, 0.109804, 0.890196};
fullDeformed = {0.583333, 0.890196, 0.109804};
reducedInitial = {0.890196, 0.109804, 0.193138};
reducedDeformed = {0.109804, 0.890196, 0.806863};
}
};
inline static StaticColors colors;
#endif // POLYSCOPE_DEFINED
public: public:
enum SimulationScenario { enum SimulationScenario {
@ -44,10 +62,19 @@ public:
struct Results; struct Results;
struct Settings { struct Settings {
enum NormalizationStrategy {
NonNormalized,
Epsilon,
MaxDisplacement,
EqualDisplacements
};
inline static vector<std::string> normalizationStrategyStrings{
"NonNormalized", "Epsilon", "MaxDsiplacement", "EqualDisplacements"};
std::vector<xRange> xRanges; std::vector<xRange> xRanges;
int numberOfFunctionCalls{100}; int numberOfFunctionCalls{100};
double solutionAccuracy{1e-2}; double solutionAccuracy{1e-2};
bool shouldNormalizeObjectiveValue{true}; NormalizationStrategy normalizationStrategy{Epsilon};
double normalizationParameter{0.003};
std::string toString() const { std::string toString() const {
std::string settingsString; std::string settingsString;
@ -61,7 +88,7 @@ public:
settingsString += settingsString +=
"FuncCalls=" + std::to_string(numberOfFunctionCalls) + "FuncCalls=" + std::to_string(numberOfFunctionCalls) +
" Accuracy=" + std::to_string(solutionAccuracy) + " Accuracy=" + std::to_string(solutionAccuracy) +
" Norm=" + (shouldNormalizeObjectiveValue ? "yes" : "no"); " Norm=" + normalizationStrategyStrings[normalizationStrategy];
return settingsString; return settingsString;
} }
@ -75,6 +102,7 @@ public:
} }
os << "Function Calls"; os << "Function Calls";
os << "Solution Accuracy"; os << "Solution Accuracy";
os << "Normalization strategy";
// os << std::endl; // os << std::endl;
} }
@ -87,11 +115,211 @@ public:
} }
os << numberOfFunctionCalls; os << numberOfFunctionCalls;
os << solutionAccuracy; os << solutionAccuracy;
os << normalizationStrategyStrings[normalizationStrategy] + "_" +
std::to_string(normalizationParameter);
}
};
struct Results {
double time{-1};
int numberOfSimulationCrashes{0};
std::vector<double> x;
double objectiveValue;
double rawObjectiveValue;
std::vector<double> objectiveValuePerSimulationScenario;
std::vector<std::shared_ptr<SimulationJob>> fullPatternSimulationJobs;
std::vector<std::shared_ptr<SimulationJob>> 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<SimulationJob> &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<SimulationJob> &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<SimulationJob>(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<SimulationJob>(job));
}
}
}
}
#if POLYSCOPE_DEFINED
void draw() const {
initPolyscope();
FormFinder simulator;
assert(fullPatternSimulationJobs.size() ==
reducedPatternSimulationJobs.size());
fullPatternSimulationJobs[0]->pMesh->registerForDrawing(
colors.fullInitial);
reducedPatternSimulationJobs[0]->pMesh->registerForDrawing(
colors.reducedInitial);
const int numberOfSimulationJobs = fullPatternSimulationJobs.size();
for (int simulationJobIndex = 0;
simulationJobIndex < numberOfSimulationJobs; simulationJobIndex++) {
// Drawing of full pattern results
const std::shared_ptr<SimulationJob> &pFullPatternSimulationJob =
fullPatternSimulationJobs[simulationJobIndex];
pFullPatternSimulationJob->registerForDrawing(
fullPatternSimulationJobs[0]->pMesh->getLabel());
SimulationResults fullModelResults =
simulator.executeSimulation(pFullPatternSimulationJob);
fullModelResults.registerForDrawing(colors.fullDeformed);
// Drawing of reduced pattern results
const std::shared_ptr<SimulationJob> &pReducedPatternSimulationJob =
reducedPatternSimulationJobs[simulationJobIndex];
SimulationResults reducedModelResults =
simulator.executeSimulation(pReducedPatternSimulationJob);
reducedModelResults.registerForDrawing(colors.reducedDeformed);
polyscope::options::programName =
fullPatternSimulationJobs[0]->pMesh->getLabel();
polyscope::show();
// Save a screensh
const std::string screenshotFilename =
"/home/iason/Coding/Projects/Approximating shapes with flat "
"patterns/RodModelOptimizationForPatterns/Results/Images/" +
pFullPatternSimulationJob->pMesh->getLabel() + "_" +
simulationScenarioStrings[simulationJobIndex];
polyscope::screenshot(screenshotFilename, false);
fullModelResults.unregister();
reducedModelResults.unregister();
// double error = computeError(
// reducedModelResults.displacements,fullModelResults.displacements,
// );
// std::cout << "Error of simulation scenario "
// <<
// simulationScenarioStrings[simulationScenarioIndex]
// << " is "
// << error << std::endl;
}
}
#endif // POLYSCOPE_DEFINED
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<SimulationJob> &pFullPatternSimulationJob =
fullPatternSimulationJobs[simulationJobIndex];
SimulationResults fullModelResults =
simulator.executeSimulation(pFullPatternSimulationJob);
fullModelResults.saveDeformedModel();
// Drawing of reduced pattern results
const std::shared_ptr<SimulationJob> &pReducedPatternSimulationJob =
reducedPatternSimulationJobs[simulationJobIndex];
SimulationResults reducedModelResults =
simulator.executeSimulation(pReducedPatternSimulationJob);
reducedModelResults.saveDeformedModel();
}
}
void
writeHeaderTo(const ReducedModelOptimizer::Settings &settings_optimization,
csvFile &os) {
os << "Total raw Obj value";
os << "Total Obj value";
for (int simulationScenarioIndex = 0;
simulationScenarioIndex <
SimulationScenario::NumberOfSimulationScenarios;
simulationScenarioIndex++) {
os << "Obj value " + simulationScenarioStrings[simulationScenarioIndex];
}
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 << rawObjectiveValue;
os << objectiveValue;
for (double scenarioObjValue : objectiveValuePerSimulationScenario) {
os << scenarioObjValue;
}
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;
}
} }
}; };
inline static const std::string simulationScenarioStrings[] = { inline static const std::string simulationScenarioStrings[] = {
"Axial", "Shear", "Bending", "Double", "Saddle"}; "Axial", "Shear", "Bending", "Dome", "Saddle"};
Results optimize(const Settings &xRanges, Results optimize(const Settings &xRanges,
const std::vector<SimulationScenario> &simulationScenarios = const std::vector<SimulationScenario> &simulationScenarios =
std::vector<SimulationScenario>()); std::vector<SimulationScenario>());
@ -118,7 +346,7 @@ public:
std::vector<double> &x); std::vector<double> &x);
static double objective(double x0, double x1, double x2, double x3); static double objective(double x0, double x1, double x2, double x3);
static double objective(double b, double h, double E); static double objective(double b, double r, double E);
static std::vector<std::shared_ptr<SimulationJob>> static std::vector<std::shared_ptr<SimulationJob>>
createScenarios(const std::shared_ptr<SimulationMesh> &pMesh, createScenarios(const std::shared_ptr<SimulationMesh> &pMesh,
@ -138,20 +366,36 @@ public:
&fullToReducedInterfaceViMap, &fullToReducedInterfaceViMap,
std::unordered_map<FullPatternVertexIndex, ReducedPatternVertexIndex> std::unordered_map<FullPatternVertexIndex, ReducedPatternVertexIndex>
&fullPatternOppositeInterfaceViMap); &fullPatternOppositeInterfaceViMap);
static void visualizeResults( static void
const std::shared_ptr<SimulationJob> &fullPatternSimulationJobs, visualizeResults(const std::vector<std::shared_ptr<SimulationJob>>
const std::shared_ptr<SimulationJob> &reducedPatternSimulationJobs, &fullPatternSimulationJobs,
const std::vector<std::shared_ptr<SimulationJob>>
&reducedPatternSimulationJobs,
const std::vector<SimulationScenario> &simulationScenarios,
const std::unordered_map<ReducedPatternVertexIndex,
FullPatternVertexIndex>
&reducedToFullInterfaceViMap);
static void registerResultsForDrawing(
const std::shared_ptr<SimulationJob> &pFullPatternSimulationJob,
const std::shared_ptr<SimulationJob> &pReducedPatternSimulationJob,
const std::unordered_map<ReducedPatternVertexIndex, const std::unordered_map<ReducedPatternVertexIndex,
FullPatternVertexIndex> FullPatternVertexIndex>
&reducedToFullInterfaceViMap, &reducedToFullInterfaceViMap);
const bool &shouldDraw);
static double computeError(const std::vector<Vector6d> &reducedPatternResults, static double
const std::vector<Vector6d> &fullPatternResults, computeRawError(const std::vector<Vector6d> &reducedPatternDisplacements,
const std::unordered_map<ReducedPatternVertexIndex, const std::vector<Vector6d> &fullPatternDisplacements,
FullPatternVertexIndex> const std::unordered_map<ReducedPatternVertexIndex,
&reducedToFullInterfaceViMap, FullPatternVertexIndex>
const double &normalizationFactor); &reducedToFullInterfaceViMap);
static double
computeError(const std::vector<Vector6d> &reducedPatternDisplacements,
const std::vector<Vector6d> &fullPatternDisplacements,
const std::unordered_map<ReducedPatternVertexIndex,
FullPatternVertexIndex>
&reducedToFullInterfaceViMap,
const double &normalizationFactor);
private: private:
static void computeDesiredReducedModelDisplacements( static void computeDesiredReducedModelDisplacements(
@ -168,194 +412,8 @@ private:
static void static void
initializeOptimizationParameters(const std::shared_ptr<SimulationMesh> &mesh); initializeOptimizationParameters(const std::shared_ptr<SimulationMesh> &mesh);
static double
computeError(const SimulationResults &reducedPatternResults,
const Eigen::MatrixX3d &optimalReducedPatternDisplacements);
static double objective(long n, const double *x); static double objective(long n, const double *x);
FormFinder simulator; FormFinder simulator;
double static computeRawError( void computeObjectiveValueNormalizationFactors();
const std::vector<Vector6d> &reducedPatternDisplacements,
const std::vector<Vector6d> &fullPatternDisplacements,
const std::unordered_map<ReducedPatternVertexIndex,
FullPatternVertexIndex>
&reducedToFullInterfaceViMap);
}; };
struct ReducedModelOptimizer::Results {
double time{-1};
int numberOfSimulationCrashes{0};
std::vector<double> x;
double objectiveValue;
std::vector<std::shared_ptr<SimulationJob>> fullPatternSimulationJobs;
std::vector<std::shared_ptr<SimulationJob>> 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<SimulationJob> &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<SimulationJob> &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<SimulationJob>(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<SimulationJob>(job));
}
}
}
}
#if POLYSCOPE_DEFINED
void draw() const {
initPolyscope();
FormFinder simulator;
assert(fullPatternSimulationJobs.size() ==
reducedPatternSimulationJobs.size());
fullPatternSimulationJobs[0]->pMesh->registerForDrawing();
reducedPatternSimulationJobs[0]->pMesh->registerForDrawing();
const int numberOfSimulationJobs = fullPatternSimulationJobs.size();
for (int simulationJobIndex = 0;
simulationJobIndex < numberOfSimulationJobs; simulationJobIndex++) {
// Drawing of full pattern results
const std::shared_ptr<SimulationJob> &pFullPatternSimulationJob =
fullPatternSimulationJobs[simulationJobIndex];
pFullPatternSimulationJob->registerForDrawing(
fullPatternSimulationJobs[0]->pMesh->getLabel());
SimulationResults fullModelResults =
simulator.executeSimulation(pFullPatternSimulationJob);
fullModelResults.registerForDrawing();
// Drawing of reduced pattern results
const std::shared_ptr<SimulationJob> &pReducedPatternSimulationJob =
reducedPatternSimulationJobs[simulationJobIndex];
SimulationResults reducedModelResults =
simulator.executeSimulation(pReducedPatternSimulationJob);
reducedModelResults.registerForDrawing();
polyscope::show();
// Save a screensh
// const std::string screenshotFilename =
// "/home/iason/Coding/Projects/Approximating shapes with flat "
// "patterns/RodModelOptimizationForPatterns/build/OptimizationResults/"
// + m_pFullPatternSimulationMesh->getLabel() + "_" +
// simulationScenarioStrings[simulationScenarioIndex];
// polyscope::screenshot(screenshotFilename, false);
fullModelResults.unregister();
reducedModelResults.unregister();
// double error = computeError(
// reducedModelResults,
// global.g_optimalReducedModelDisplacements[simulationScenarioIndex]);
// std::cout << "Error of simulation scenario "
// << simulationScenarioStrings[simulationScenarioIndex] << "
// is "
// << error << std::endl;
}
}
#endif // POLYSCOPE_DEFINED
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<SimulationJob> &pFullPatternSimulationJob =
fullPatternSimulationJobs[simulationJobIndex];
SimulationResults fullModelResults =
simulator.executeSimulation(pFullPatternSimulationJob);
fullModelResults.saveDeformedModel();
// Drawing of reduced pattern results
const std::shared_ptr<SimulationJob> &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 #endif // REDUCEDMODELOPTIMIZER_HPP