2020-11-27 11:45:20 +01:00
|
|
|
|
#include "reducedmodeloptimizer.hpp"
|
2021-03-15 18:56:14 +01:00
|
|
|
|
#include "linearsimulationmodel.hpp"
|
2020-11-23 10:06:45 +01:00
|
|
|
|
#include "simulationhistoryplotter.hpp"
|
2021-03-15 18:56:14 +01:00
|
|
|
|
#include "trianglepatterngeometry.hpp"
|
2020-11-27 11:45:20 +01:00
|
|
|
|
#include "trianglepattterntopology.hpp"
|
2021-01-12 13:41:40 +01:00
|
|
|
|
#include <chrono>
|
2020-11-23 10:06:45 +01:00
|
|
|
|
|
2021-04-08 19:55:56 +02:00
|
|
|
|
using namespace ReducedPatternOptimization;
|
2021-03-23 18:20:46 +01:00
|
|
|
|
|
2021-02-01 15:10:24 +01:00
|
|
|
|
struct GlobalOptimizationVariables {
|
2021-03-26 10:58:13 +01:00
|
|
|
|
// std::vector<std::vector<Vector6d>> fullPatternDisplacements;
|
|
|
|
|
std::vector<SimulationResults> fullPatternResults;
|
2021-03-30 11:35:00 +02:00
|
|
|
|
std::vector<double> translationalDisplacementNormalizationValues;
|
|
|
|
|
std::vector<double> rotationalDisplacementNormalizationValues;
|
2021-03-15 18:56:14 +01:00
|
|
|
|
std::vector<std::shared_ptr<SimulationJob>> fullPatternSimulationJobs;
|
|
|
|
|
std::vector<std::shared_ptr<SimulationJob>> reducedPatternSimulationJobs;
|
|
|
|
|
std::unordered_map<ReducedPatternVertexIndex, FullPatternVertexIndex>
|
|
|
|
|
reducedToFullInterfaceViMap;
|
2021-04-16 10:41:40 +02:00
|
|
|
|
std::vector<std::pair<FullPatternVertexIndex, FullPatternVertexIndex>>
|
|
|
|
|
fullPatternInterfaceViPairs;
|
2021-03-15 18:56:14 +01:00
|
|
|
|
matplot::line_handle gPlotHandle;
|
2021-03-23 18:20:46 +01:00
|
|
|
|
std::vector<double> objectiveValueHistory;
|
2021-03-16 10:57:27 +01:00
|
|
|
|
Eigen::VectorXd initialParameters;
|
2021-04-05 11:41:05 +02:00
|
|
|
|
std::vector<int> simulationScenarioIndices;
|
2021-03-15 18:56:14 +01:00
|
|
|
|
double minY{DBL_MAX};
|
|
|
|
|
std::vector<double> minX;
|
|
|
|
|
int numOfSimulationCrashes{false};
|
|
|
|
|
int numberOfFunctionCalls{0};
|
|
|
|
|
int numberOfOptimizationParameters{5};
|
2021-04-08 19:55:56 +02:00
|
|
|
|
ReducedPatternOptimization::Settings optimizationSettings;
|
2021-03-26 10:58:13 +01:00
|
|
|
|
vcg::Triangle3<double> baseTriangle;
|
2021-04-16 10:41:40 +02:00
|
|
|
|
//Variables for finding the full pattern simulation forces
|
|
|
|
|
std::shared_ptr<SimulationMesh> pFullPatternSimulationMesh;
|
|
|
|
|
std::function<void(const double &,
|
|
|
|
|
const std::vector<std::pair<FullPatternVertexIndex, FullPatternVertexIndex>> &,
|
|
|
|
|
SimulationJob &)>
|
|
|
|
|
constructScenarioFunction;
|
|
|
|
|
FullPatternVertexIndex interfaceViForComputingScenarioError;
|
|
|
|
|
double desiredMaxDisplacementValue;
|
2021-04-30 11:47:50 +02:00
|
|
|
|
double desiredMaxRotationAngle;
|
2021-02-22 10:28:01 +01:00
|
|
|
|
} global;
|
2020-12-09 16:58:48 +01:00
|
|
|
|
|
2021-03-26 10:58:13 +01:00
|
|
|
|
double ReducedModelOptimizer::computeDisplacementError(
|
2021-02-18 11:12:52 +01:00
|
|
|
|
const std::vector<Vector6d> &fullPatternDisplacements,
|
2021-03-30 18:30:49 +02:00
|
|
|
|
const std::vector<Vector6d> &reducedPatternDisplacements,
|
2021-02-24 21:21:09 +01:00
|
|
|
|
const std::unordered_map<ReducedPatternVertexIndex, FullPatternVertexIndex>
|
|
|
|
|
&reducedToFullInterfaceViMap,
|
2021-03-26 10:58:13 +01:00
|
|
|
|
const double &normalizationFactor)
|
|
|
|
|
{
|
2021-04-08 19:55:56 +02:00
|
|
|
|
const double rawError = computeRawTranslationalError(fullPatternDisplacements,
|
|
|
|
|
reducedPatternDisplacements,
|
|
|
|
|
reducedToFullInterfaceViMap);
|
2021-04-05 11:41:05 +02:00
|
|
|
|
return rawError / normalizationFactor;
|
2021-02-24 21:21:09 +01:00
|
|
|
|
}
|
|
|
|
|
|
2021-04-08 19:55:56 +02:00
|
|
|
|
double ReducedModelOptimizer::computeRawTranslationalError(
|
2021-02-24 21:21:09 +01:00
|
|
|
|
const std::vector<Vector6d> &fullPatternDisplacements,
|
2021-03-30 18:30:49 +02:00
|
|
|
|
const std::vector<Vector6d> &reducedPatternDisplacements,
|
2021-02-11 12:52:27 +01:00
|
|
|
|
const std::unordered_map<ReducedPatternVertexIndex, FullPatternVertexIndex>
|
2021-03-26 10:58:13 +01:00
|
|
|
|
&reducedToFullInterfaceViMap)
|
|
|
|
|
{
|
2021-03-15 18:56:14 +01:00
|
|
|
|
double error = 0;
|
|
|
|
|
for (const auto reducedFullViPair : reducedToFullInterfaceViMap) {
|
|
|
|
|
const VertexIndex reducedModelVi = reducedFullViPair.first;
|
|
|
|
|
const VertexIndex fullModelVi = reducedFullViPair.second;
|
2021-04-08 19:55:56 +02:00
|
|
|
|
const Eigen::Vector3d fullPatternVertexDiplacement = fullPatternDisplacements[fullModelVi]
|
|
|
|
|
.getTranslation();
|
|
|
|
|
const Eigen::Vector3d reducedPatternVertexDiplacement
|
|
|
|
|
= reducedPatternDisplacements[reducedModelVi].getTranslation();
|
|
|
|
|
const double vertexError = (fullPatternVertexDiplacement - reducedPatternVertexDiplacement)
|
|
|
|
|
.norm();
|
|
|
|
|
error += vertexError;
|
2021-02-11 12:52:27 +01:00
|
|
|
|
}
|
2021-03-15 18:56:14 +01:00
|
|
|
|
|
|
|
|
|
return error;
|
2021-02-11 12:52:27 +01:00
|
|
|
|
}
|
2021-03-30 18:30:49 +02:00
|
|
|
|
|
|
|
|
|
double ReducedModelOptimizer::computeRawRotationalError(
|
|
|
|
|
const std::vector<Eigen::Quaternion<double>> &rotatedQuaternion_fullPattern,
|
|
|
|
|
const std::vector<Eigen::Quaternion<double>> &rotatedQuaternion_reducedPattern,
|
|
|
|
|
const std::unordered_map<ReducedPatternVertexIndex, FullPatternVertexIndex>
|
|
|
|
|
&reducedToFullInterfaceViMap)
|
|
|
|
|
{
|
|
|
|
|
double rawRotationalError = 0;
|
|
|
|
|
for (const auto &reducedToFullInterfaceViPair : reducedToFullInterfaceViMap) {
|
|
|
|
|
const double vertexRotationalError
|
|
|
|
|
= rotatedQuaternion_fullPattern[reducedToFullInterfaceViPair.second].angularDistance(
|
|
|
|
|
rotatedQuaternion_reducedPattern[reducedToFullInterfaceViPair.first]);
|
|
|
|
|
rawRotationalError += vertexRotationalError;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return rawRotationalError;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
double ReducedModelOptimizer::computeRotationalError(
|
|
|
|
|
const std::vector<Eigen::Quaternion<double>> &rotatedQuaternion_fullPattern,
|
|
|
|
|
const std::vector<Eigen::Quaternion<double>> &rotatedQuaternion_reducedPattern,
|
|
|
|
|
const std::unordered_map<ReducedPatternVertexIndex, FullPatternVertexIndex>
|
|
|
|
|
&reducedToFullInterfaceViMap,
|
|
|
|
|
const double &normalizationFactor)
|
|
|
|
|
{
|
|
|
|
|
const double rawRotationalError = computeRawRotationalError(rotatedQuaternion_fullPattern,
|
|
|
|
|
rotatedQuaternion_reducedPattern,
|
|
|
|
|
reducedToFullInterfaceViMap);
|
|
|
|
|
return rawRotationalError / normalizationFactor;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
double ReducedModelOptimizer::computeError(
|
|
|
|
|
const SimulationResults &simulationResults_fullPattern,
|
|
|
|
|
const SimulationResults &simulationResults_reducedPattern,
|
|
|
|
|
const std::unordered_map<ReducedPatternVertexIndex, FullPatternVertexIndex>
|
|
|
|
|
&reducedToFullInterfaceViMap,
|
|
|
|
|
const double &normalizationFactor_translationalDisplacement,
|
|
|
|
|
const double &normalizationFactor_rotationalDisplacement)
|
|
|
|
|
{
|
|
|
|
|
const double translationalError
|
|
|
|
|
= computeDisplacementError(simulationResults_fullPattern.displacements,
|
|
|
|
|
simulationResults_reducedPattern.displacements,
|
|
|
|
|
reducedToFullInterfaceViMap,
|
|
|
|
|
normalizationFactor_translationalDisplacement);
|
|
|
|
|
const double rotationalError
|
|
|
|
|
= computeRotationalError(simulationResults_fullPattern.rotationalDisplacementQuaternion,
|
|
|
|
|
simulationResults_reducedPattern.rotationalDisplacementQuaternion,
|
|
|
|
|
reducedToFullInterfaceViMap,
|
|
|
|
|
normalizationFactor_rotationalDisplacement);
|
2021-04-16 10:41:40 +02:00
|
|
|
|
return global.optimizationSettings.objectiveWeights.translational * translationalError
|
|
|
|
|
+ global.optimizationSettings.objectiveWeights.rotational * rotationalError;
|
2021-03-30 18:30:49 +02:00
|
|
|
|
}
|
|
|
|
|
|
2021-03-16 10:57:27 +01:00
|
|
|
|
double ReducedModelOptimizer::objective(double E,double A,double J,double I2,double I3,
|
2021-03-15 18:56:14 +01:00
|
|
|
|
double innerHexagonSize,
|
|
|
|
|
double innerHexagonRotationAngle) {
|
2021-03-16 10:57:27 +01:00
|
|
|
|
std::vector<double> x{E,A,J,I2,I3, innerHexagonSize, innerHexagonRotationAngle};
|
2021-03-15 18:56:14 +01:00
|
|
|
|
return ReducedModelOptimizer::objective(x.size(), x.data());
|
2021-01-12 13:41:40 +01:00
|
|
|
|
}
|
|
|
|
|
|
2021-01-04 13:12:25 +01:00
|
|
|
|
double ReducedModelOptimizer::objective(long n, const double *x) {
|
2021-03-15 18:56:14 +01:00
|
|
|
|
// std::cout.precision(17);
|
2021-04-16 10:41:40 +02:00
|
|
|
|
// for (int i = 0; i < n; i++) {
|
|
|
|
|
// std::cout << x[i] << " ";
|
|
|
|
|
// }
|
2021-03-26 10:58:13 +01:00
|
|
|
|
// std::cout << std::endl;
|
2021-03-15 18:56:14 +01:00
|
|
|
|
|
2021-04-16 10:41:40 +02:00
|
|
|
|
// std::cout << x[n - 2] << " " << x[n - 1] << std::endl;
|
2021-03-15 18:56:14 +01:00
|
|
|
|
// const Element &e =
|
|
|
|
|
// global.reducedPatternSimulationJobs[0]->pMesh->elements[0]; std::cout <<
|
|
|
|
|
// e.axialConstFactor << " " << e.torsionConstFactor << " "
|
|
|
|
|
// << e.firstBendingConstFactor << " " <<
|
|
|
|
|
// e.secondBendingConstFactor
|
|
|
|
|
// << std::endl;
|
|
|
|
|
updateMesh(n, x);
|
2021-04-16 10:41:40 +02:00
|
|
|
|
// global.reducedPatternSimulationJobs[0]->pMesh->registerForDrawing();
|
|
|
|
|
// global.fullPatternSimulationJobs[0]->pMesh->registerForDrawing();
|
|
|
|
|
// polyscope::show();
|
|
|
|
|
// global.reducedPatternSimulationJobs[0]->pMesh->unregister();
|
|
|
|
|
|
2021-03-15 18:56:14 +01:00
|
|
|
|
// std::cout << e.axialConstFactor << " " << e.torsionConstFactor << " "
|
|
|
|
|
// << e.firstBendingConstFactor << " " <<
|
|
|
|
|
// e.secondBendingConstFactor
|
|
|
|
|
// << std::endl;
|
|
|
|
|
|
|
|
|
|
// run simulations
|
|
|
|
|
double totalError = 0;
|
|
|
|
|
LinearSimulationModel simulator;
|
2021-04-16 10:41:40 +02:00
|
|
|
|
// FormFinder simulator;
|
2021-03-15 18:56:14 +01:00
|
|
|
|
for (const int simulationScenarioIndex : global.simulationScenarioIndices) {
|
2021-04-16 10:41:40 +02:00
|
|
|
|
const std::shared_ptr<SimulationJob> &reducedJob
|
|
|
|
|
= global.reducedPatternSimulationJobs[simulationScenarioIndex];
|
|
|
|
|
SimulationResults reducedModelResults = simulator.executeSimulation(reducedJob);
|
2021-03-15 18:56:14 +01:00
|
|
|
|
// std::string filename;
|
|
|
|
|
if (!reducedModelResults.converged) {
|
|
|
|
|
totalError += std::numeric_limits<double>::max();
|
|
|
|
|
global.numOfSimulationCrashes++;
|
|
|
|
|
#ifdef POLYSCOPE_DEFINED
|
|
|
|
|
std::cout << "Failed simulation" << std::endl;
|
|
|
|
|
#endif
|
|
|
|
|
} else {
|
2021-03-26 10:58:13 +01:00
|
|
|
|
const bool usePotentialEnergy = false;
|
|
|
|
|
double simulationScenarioError;
|
|
|
|
|
if (usePotentialEnergy) {
|
|
|
|
|
simulationScenarioError = std::abs(
|
|
|
|
|
reducedModelResults.internalPotentialEnergy
|
|
|
|
|
- global.fullPatternResults[simulationScenarioIndex].internalPotentialEnergy);
|
|
|
|
|
} else {
|
2021-04-05 11:41:05 +02:00
|
|
|
|
simulationScenarioError = computeError(
|
2021-03-30 18:30:49 +02:00
|
|
|
|
global.fullPatternResults[simulationScenarioIndex],
|
|
|
|
|
reducedModelResults,
|
2021-03-26 10:58:13 +01:00
|
|
|
|
global.reducedToFullInterfaceViMap,
|
2021-03-30 18:30:49 +02:00
|
|
|
|
global.translationalDisplacementNormalizationValues[simulationScenarioIndex],
|
|
|
|
|
global.rotationalDisplacementNormalizationValues[simulationScenarioIndex]);
|
2021-03-26 10:58:13 +01:00
|
|
|
|
}
|
|
|
|
|
//#ifdef POLYSCOPE_DEFINED
|
|
|
|
|
// std::cout << "sim error:" << simulationScenarioError << std::endl;
|
|
|
|
|
// global.reducedPatternSimulationJobs[simulationScenarioIndex]->pMesh->registerForDrawing(
|
|
|
|
|
// ReducedModelOptimization::Colors::reducedInitial);
|
|
|
|
|
// reducedModelResults.registerForDrawing(
|
|
|
|
|
// ReducedModelOptimization::Colors::reducedDeformed);
|
|
|
|
|
// polyscope::show();
|
|
|
|
|
// reducedModelResults.unregister();
|
|
|
|
|
//#endif
|
2021-03-15 18:56:14 +01:00
|
|
|
|
// if (global.optimizationSettings.normalizationStrategy !=
|
|
|
|
|
// NormalizationStrategy::Epsilon &&
|
|
|
|
|
// simulationScenarioError > 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
|
|
|
|
|
// ReducedModelOptimizer::visualizeResults(
|
|
|
|
|
// global.fullPatternSimulationJobs[simulationScenarioIndex],
|
|
|
|
|
// global.reducedPatternSimulationJobs[simulationScenarioIndex],
|
|
|
|
|
// global.reducedToFullInterfaceViMap, false);
|
|
|
|
|
|
|
|
|
|
// ReducedModelOptimizer::visualizeResults(
|
|
|
|
|
// global.fullPatternSimulationJobs[simulationScenarioIndex],
|
|
|
|
|
// std::make_shared<SimulationJob>(
|
|
|
|
|
// reducedPatternMaximumDisplacementSimulationJobs
|
|
|
|
|
// [simulationScenarioIndex]),
|
|
|
|
|
// global.reducedToFullInterfaceViMap, true);
|
|
|
|
|
// polyscope::removeAllStructures();
|
|
|
|
|
//#endif // POLYSCOPE_DEFINED
|
|
|
|
|
totalError += simulationScenarioError;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// std::cout << error << std::endl;
|
|
|
|
|
if (totalError < global.minY) {
|
|
|
|
|
global.minY = totalError;
|
|
|
|
|
global.minX.assign(x, x + n);
|
|
|
|
|
}
|
|
|
|
|
#ifdef POLYSCOPE_DEFINED
|
2021-04-08 19:55:56 +02:00
|
|
|
|
++global.numberOfFunctionCalls;
|
2021-04-16 10:41:40 +02:00
|
|
|
|
if (global.numberOfFunctionCalls % 1000 == 0) {
|
2021-04-08 19:55:56 +02:00
|
|
|
|
std::cout << "Number of function calls:" << global.numberOfFunctionCalls << std::endl;
|
|
|
|
|
}
|
2021-03-15 18:56:14 +01:00
|
|
|
|
#endif
|
2021-03-23 18:20:46 +01:00
|
|
|
|
// compute error and return it
|
|
|
|
|
// global.objectiveValueHistory.push_back(totalError);
|
|
|
|
|
// auto xPlot = matplot::linspace(0, global.objectiveValueHistory.size(),
|
|
|
|
|
// global.objectiveValueHistory.size());
|
|
|
|
|
// std::vector<double> colors(global.gObjectiveValueHistory.size(), 2);
|
|
|
|
|
// if (global.g_firstRoundIterationIndex != 0) {
|
|
|
|
|
// for_each(colors.begin() + g_firstRoundIterationIndex, colors.end(),
|
|
|
|
|
// [](double &c) { c = 0.7; });
|
|
|
|
|
// }
|
|
|
|
|
// global.gPlotHandle = matplot::scatter(xPlot, global.objectiveValueHistory);
|
|
|
|
|
// SimulationResultsReporter::createPlot("Number of Steps", "Objective value",
|
|
|
|
|
// global.objectiveValueHistory);
|
2021-03-15 18:56:14 +01:00
|
|
|
|
|
|
|
|
|
return totalError;
|
2020-11-23 10:06:45 +01:00
|
|
|
|
}
|
|
|
|
|
|
2021-02-11 12:52:27 +01:00
|
|
|
|
void ReducedModelOptimizer::createSimulationMeshes(
|
2021-03-15 18:56:14 +01:00
|
|
|
|
PatternGeometry &fullModel, PatternGeometry &reducedModel,
|
2021-02-11 12:52:27 +01:00
|
|
|
|
std::shared_ptr<SimulationMesh> &pFullPatternSimulationMesh,
|
|
|
|
|
std::shared_ptr<SimulationMesh> &pReducedPatternSimulationMesh) {
|
2021-03-15 18:56:14 +01:00
|
|
|
|
if (typeid(CrossSectionType) != typeid(RectangularBeamDimensions)) {
|
|
|
|
|
std::cerr << "Error: A rectangular cross section is expected." << std::endl;
|
|
|
|
|
terminate();
|
|
|
|
|
}
|
|
|
|
|
// Full pattern
|
|
|
|
|
pFullPatternSimulationMesh = std::make_shared<SimulationMesh>(fullModel);
|
|
|
|
|
pFullPatternSimulationMesh->setBeamCrossSection(
|
|
|
|
|
CrossSectionType{0.002, 0.002});
|
|
|
|
|
pFullPatternSimulationMesh->setBeamMaterial(0.3, 1 * 1e9);
|
|
|
|
|
|
|
|
|
|
// Reduced pattern
|
|
|
|
|
pReducedPatternSimulationMesh =
|
|
|
|
|
std::make_shared<SimulationMesh>(reducedModel);
|
|
|
|
|
pReducedPatternSimulationMesh->setBeamCrossSection(
|
|
|
|
|
CrossSectionType{0.002, 0.002});
|
|
|
|
|
pReducedPatternSimulationMesh->setBeamMaterial(0.3, 1 * 1e9);
|
2021-02-11 12:52:27 +01:00
|
|
|
|
}
|
|
|
|
|
|
2021-03-15 18:56:14 +01:00
|
|
|
|
void ReducedModelOptimizer::createSimulationMeshes(
|
|
|
|
|
PatternGeometry &fullModel, PatternGeometry &reducedModel) {
|
|
|
|
|
ReducedModelOptimizer::createSimulationMeshes(
|
|
|
|
|
fullModel, reducedModel, m_pFullPatternSimulationMesh,
|
|
|
|
|
m_pReducedPatternSimulationMesh);
|
2021-02-11 12:52:27 +01:00
|
|
|
|
}
|
|
|
|
|
|
2020-11-27 11:45:20 +01:00
|
|
|
|
void ReducedModelOptimizer::computeMaps(
|
2021-02-11 12:52:27 +01:00
|
|
|
|
const std::unordered_map<size_t, std::unordered_set<size_t>> &slotToNode,
|
2021-04-05 11:41:05 +02:00
|
|
|
|
PatternGeometry &fullPattern,
|
|
|
|
|
PatternGeometry &reducedPattern,
|
2021-02-11 12:52:27 +01:00
|
|
|
|
std::unordered_map<ReducedPatternVertexIndex, FullPatternVertexIndex>
|
|
|
|
|
&reducedToFullInterfaceViMap,
|
|
|
|
|
std::unordered_map<FullPatternVertexIndex, ReducedPatternVertexIndex>
|
|
|
|
|
&fullToReducedInterfaceViMap,
|
2021-04-05 11:41:05 +02:00
|
|
|
|
std::vector<std::pair<FullPatternVertexIndex, ReducedPatternVertexIndex>>
|
2021-04-16 10:41:40 +02:00
|
|
|
|
&fullPatternOppositeInterfaceViPairs)
|
2021-04-05 11:41:05 +02:00
|
|
|
|
{
|
2021-03-15 18:56:14 +01:00
|
|
|
|
// Compute the offset between the interface nodes
|
|
|
|
|
const size_t interfaceSlotIndex = 4; // bottom edge
|
|
|
|
|
assert(slotToNode.find(interfaceSlotIndex) != slotToNode.end() &&
|
|
|
|
|
slotToNode.find(interfaceSlotIndex)->second.size() == 1);
|
|
|
|
|
// Assuming that in the bottom edge there is only one vertex which is also the
|
|
|
|
|
// interface
|
|
|
|
|
const size_t baseTriangleInterfaceVi =
|
|
|
|
|
*(slotToNode.find(interfaceSlotIndex)->second.begin());
|
|
|
|
|
|
2021-03-26 10:58:13 +01:00
|
|
|
|
vcg::tri::Allocator<VCGEdgeMesh>::PointerUpdater<PatternGeometry::VertexPointer> pu_fullModel;
|
2021-03-15 18:56:14 +01:00
|
|
|
|
fullPattern.deleteDanglingVertices(pu_fullModel);
|
|
|
|
|
const size_t fullModelBaseTriangleInterfaceVi =
|
|
|
|
|
pu_fullModel.remap.empty() ? baseTriangleInterfaceVi
|
|
|
|
|
: pu_fullModel.remap[baseTriangleInterfaceVi];
|
|
|
|
|
const size_t fullModelBaseTriangleVN = fullPattern.VN();
|
|
|
|
|
fullPattern.createFan();
|
|
|
|
|
const size_t duplicateVerticesPerFanPair =
|
|
|
|
|
fullModelBaseTriangleVN - fullPattern.VN() / 6;
|
|
|
|
|
const size_t fullPatternInterfaceVertexOffset =
|
|
|
|
|
fullModelBaseTriangleVN - duplicateVerticesPerFanPair;
|
|
|
|
|
// std::cout << "Dups in fan pair:" << duplicateVerticesPerFanPair <<
|
|
|
|
|
// std::endl;
|
|
|
|
|
|
|
|
|
|
// Save excluded edges TODO:this changes the global object. Should this be a
|
|
|
|
|
// function parameter?
|
|
|
|
|
// global.reducedPatternExludedEdges.clear();
|
|
|
|
|
// const size_t reducedBaseTriangleNumberOfEdges = reducedPattern.EN();
|
|
|
|
|
// for (size_t fanIndex = 0; fanIndex < fanSize; fanIndex++) {
|
|
|
|
|
// for (const size_t ei : reducedModelExcludedEdges) {
|
|
|
|
|
// global.reducedPatternExludedEdges.insert(
|
|
|
|
|
// fanIndex * reducedBaseTriangleNumberOfEdges + ei);
|
|
|
|
|
// }
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
// Construct reduced->full and full->reduced interface vi map
|
|
|
|
|
reducedToFullInterfaceViMap.clear();
|
2021-03-26 10:58:13 +01:00
|
|
|
|
vcg::tri::Allocator<VCGEdgeMesh>::PointerUpdater<PatternGeometry::VertexPointer> pu_reducedModel;
|
2021-03-15 18:56:14 +01:00
|
|
|
|
reducedPattern.deleteDanglingVertices(pu_reducedModel);
|
|
|
|
|
const size_t reducedModelBaseTriangleInterfaceVi =
|
|
|
|
|
pu_reducedModel.remap[baseTriangleInterfaceVi];
|
2021-03-26 10:58:13 +01:00
|
|
|
|
const size_t reducedModelInterfaceVertexOffset
|
|
|
|
|
= reducedPattern.VN() /*- 1*/ /*- reducedModelBaseTriangleInterfaceVi*/;
|
2021-04-16 10:41:40 +02:00
|
|
|
|
Results::applyOptimizationResults_innerHexagon(initialHexagonSize,
|
|
|
|
|
0,
|
|
|
|
|
global.baseTriangle,
|
|
|
|
|
reducedPattern);
|
|
|
|
|
reducedPattern.createFan({0}); //TODO: should be an input parameter from main
|
2021-03-15 18:56:14 +01:00
|
|
|
|
for (size_t fanIndex = 0; fanIndex < fanSize; fanIndex++) {
|
|
|
|
|
reducedToFullInterfaceViMap[reducedModelInterfaceVertexOffset * fanIndex +
|
|
|
|
|
reducedModelBaseTriangleInterfaceVi] =
|
|
|
|
|
fullModelBaseTriangleInterfaceVi +
|
|
|
|
|
fanIndex * fullPatternInterfaceVertexOffset;
|
2020-11-27 11:45:20 +01:00
|
|
|
|
}
|
2021-03-15 18:56:14 +01:00
|
|
|
|
fullToReducedInterfaceViMap.clear();
|
|
|
|
|
constructInverseMap(reducedToFullInterfaceViMap, fullToReducedInterfaceViMap);
|
|
|
|
|
|
|
|
|
|
// Create opposite vertex map
|
2021-04-16 10:41:40 +02:00
|
|
|
|
fullPatternOppositeInterfaceViPairs.clear();
|
|
|
|
|
fullPatternOppositeInterfaceViPairs.reserve(fanSize / 2);
|
2021-04-05 11:41:05 +02:00
|
|
|
|
// for (int fanIndex = fanSize / 2 - 1; fanIndex >= 0; fanIndex--) {
|
|
|
|
|
for (int fanIndex = 0; fanIndex < fanSize / 2; fanIndex++) {
|
|
|
|
|
const size_t vi0 = fullModelBaseTriangleInterfaceVi
|
|
|
|
|
+ fanIndex * fullPatternInterfaceVertexOffset;
|
2021-03-15 18:56:14 +01:00
|
|
|
|
const size_t vi1 = vi0 + (fanSize / 2) * fullPatternInterfaceVertexOffset;
|
|
|
|
|
assert(vi0 < fullPattern.VN() && vi1 < fullPattern.VN());
|
2021-04-16 10:41:40 +02:00
|
|
|
|
fullPatternOppositeInterfaceViPairs.emplace_back(std::make_pair(vi0, vi1));
|
2020-11-27 11:45:20 +01:00
|
|
|
|
}
|
2021-04-16 10:41:40 +02:00
|
|
|
|
global.fullPatternInterfaceViPairs = fullPatternOppositeInterfaceViPairs;
|
2021-03-15 18:56:14 +01:00
|
|
|
|
|
2021-04-16 10:41:40 +02:00
|
|
|
|
#if POLYSCOPE_DEFINED
|
2021-03-15 18:56:14 +01:00
|
|
|
|
const bool debugMapping = false;
|
|
|
|
|
if (debugMapping) {
|
|
|
|
|
reducedPattern.registerForDrawing();
|
|
|
|
|
|
|
|
|
|
// std::vector<glm::vec3> colors_reducedPatternExcludedEdges(
|
|
|
|
|
// reducedPattern.EN(), glm::vec3(0, 0, 0));
|
|
|
|
|
// for (const size_t ei : global.reducedPatternExludedEdges) {
|
|
|
|
|
// colors_reducedPatternExcludedEdges[ei] = glm::vec3(1, 0, 0);
|
|
|
|
|
// }
|
|
|
|
|
// const std::string label = reducedPattern.getLabel();
|
|
|
|
|
// polyscope::getCurveNetwork(label)
|
|
|
|
|
// ->addEdgeColorQuantity("Excluded edges",
|
|
|
|
|
// colors_reducedPatternExcludedEdges)
|
|
|
|
|
// ->setEnabled(true);
|
|
|
|
|
// polyscope::show();
|
|
|
|
|
|
|
|
|
|
std::vector<glm::vec3> nodeColorsOpposite(fullPattern.VN(),
|
|
|
|
|
glm::vec3(0, 0, 0));
|
2021-04-16 10:41:40 +02:00
|
|
|
|
for (const std::pair<size_t, size_t> oppositeVerts : fullPatternOppositeInterfaceViPairs) {
|
2021-03-15 18:56:14 +01:00
|
|
|
|
auto color = polyscope::getNextUniqueColor();
|
|
|
|
|
nodeColorsOpposite[oppositeVerts.first] = color;
|
|
|
|
|
nodeColorsOpposite[oppositeVerts.second] = color;
|
|
|
|
|
}
|
|
|
|
|
fullPattern.registerForDrawing();
|
|
|
|
|
polyscope::getCurveNetwork(fullPattern.getLabel())
|
|
|
|
|
->addNodeColorQuantity("oppositeMap", nodeColorsOpposite)
|
|
|
|
|
->setEnabled(true);
|
|
|
|
|
polyscope::show();
|
|
|
|
|
|
|
|
|
|
std::vector<glm::vec3> nodeColorsReducedToFull_reduced(reducedPattern.VN(),
|
|
|
|
|
glm::vec3(0, 0, 0));
|
|
|
|
|
std::vector<glm::vec3> nodeColorsReducedToFull_full(fullPattern.VN(),
|
|
|
|
|
glm::vec3(0, 0, 0));
|
|
|
|
|
for (size_t vi = 0; vi < reducedPattern.VN(); vi++) {
|
|
|
|
|
if (global.reducedToFullInterfaceViMap.contains(vi)) {
|
|
|
|
|
|
|
|
|
|
auto color = polyscope::getNextUniqueColor();
|
|
|
|
|
nodeColorsReducedToFull_reduced[vi] = color;
|
|
|
|
|
nodeColorsReducedToFull_full[global.reducedToFullInterfaceViMap[vi]] =
|
|
|
|
|
color;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
polyscope::getCurveNetwork(reducedPattern.getLabel())
|
|
|
|
|
->addNodeColorQuantity("reducedToFull_reduced",
|
|
|
|
|
nodeColorsReducedToFull_reduced)
|
|
|
|
|
->setEnabled(true);
|
|
|
|
|
polyscope::getCurveNetwork(fullPattern.getLabel())
|
|
|
|
|
->addNodeColorQuantity("reducedToFull_full",
|
|
|
|
|
nodeColorsReducedToFull_full)
|
|
|
|
|
->setEnabled(true);
|
|
|
|
|
polyscope::show();
|
|
|
|
|
}
|
2021-04-16 10:41:40 +02:00
|
|
|
|
#endif
|
2020-11-27 11:45:20 +01:00
|
|
|
|
}
|
2020-11-23 10:06:45 +01:00
|
|
|
|
|
2021-03-30 18:30:49 +02:00
|
|
|
|
void ReducedModelOptimizer::computeMaps(PatternGeometry &fullPattern,
|
|
|
|
|
PatternGeometry &reducedPattern)
|
|
|
|
|
{
|
|
|
|
|
ReducedModelOptimizer::computeMaps(slotToNode,
|
|
|
|
|
fullPattern,
|
|
|
|
|
reducedPattern,
|
|
|
|
|
global.reducedToFullInterfaceViMap,
|
|
|
|
|
m_fullToReducedInterfaceViMap,
|
2021-04-05 11:41:05 +02:00
|
|
|
|
m_fullPatternOppositeInterfaceViPairs);
|
2020-11-27 11:45:20 +01:00
|
|
|
|
}
|
|
|
|
|
|
2021-04-05 11:41:05 +02:00
|
|
|
|
ReducedModelOptimizer::ReducedModelOptimizer(const std::vector<size_t> &numberOfNodesPerSlot)
|
|
|
|
|
{
|
2021-03-15 18:56:14 +01:00
|
|
|
|
FlatPatternTopology::constructNodeToSlotMap(numberOfNodesPerSlot, nodeToSlot);
|
|
|
|
|
FlatPatternTopology::constructSlotToNodeMap(nodeToSlot, slotToNode);
|
2020-11-27 11:45:20 +01:00
|
|
|
|
}
|
|
|
|
|
|
2021-03-30 18:30:49 +02:00
|
|
|
|
void ReducedModelOptimizer::initializePatterns(PatternGeometry &fullPattern,
|
|
|
|
|
PatternGeometry &reducedPattern,
|
|
|
|
|
const int &optimizationParameters)
|
|
|
|
|
{
|
2021-03-15 18:56:14 +01:00
|
|
|
|
assert(fullPattern.VN() == reducedPattern.VN() &&
|
|
|
|
|
fullPattern.EN() >= reducedPattern.EN());
|
2021-02-22 18:23:58 +01:00
|
|
|
|
#if POLYSCOPE_DEFINED
|
2021-03-15 18:56:14 +01:00
|
|
|
|
polyscope::removeAllStructures();
|
2021-02-22 18:23:58 +01:00
|
|
|
|
#endif
|
2021-03-15 18:56:14 +01:00
|
|
|
|
// Create copies of the input models
|
|
|
|
|
PatternGeometry copyFullPattern;
|
|
|
|
|
PatternGeometry copyReducedPattern;
|
|
|
|
|
copyFullPattern.copy(fullPattern);
|
|
|
|
|
copyReducedPattern.copy(reducedPattern);
|
2021-03-26 10:58:13 +01:00
|
|
|
|
global.baseTriangle = copyReducedPattern.getBaseTriangle();
|
2021-03-30 18:30:49 +02:00
|
|
|
|
|
|
|
|
|
computeMaps(copyFullPattern, copyReducedPattern);
|
2021-03-15 18:56:14 +01:00
|
|
|
|
createSimulationMeshes(copyFullPattern, copyReducedPattern);
|
2021-03-23 18:20:46 +01:00
|
|
|
|
initializeOptimizationParameters(m_pReducedPatternSimulationMesh,optimizationParameters);
|
2020-11-27 11:45:20 +01:00
|
|
|
|
}
|
|
|
|
|
|
2021-03-23 18:20:46 +01:00
|
|
|
|
void updateMesh(long n, const double *x) {
|
|
|
|
|
std::shared_ptr<SimulationMesh> &pReducedPatternSimulationMesh =
|
|
|
|
|
global.reducedPatternSimulationJobs[global.simulationScenarioIndices[0]]
|
|
|
|
|
->pMesh;
|
|
|
|
|
|
|
|
|
|
const double E=global.initialParameters(0)*x[0];
|
|
|
|
|
const double A=global.initialParameters(1) * x[1];
|
|
|
|
|
const double beamWidth=std::sqrt(A);
|
|
|
|
|
const double beamHeight=beamWidth;
|
|
|
|
|
|
|
|
|
|
const double J=global.initialParameters(2) * x[2];
|
|
|
|
|
const double I2=global.initialParameters(3) * x[3];
|
|
|
|
|
const double I3=global.initialParameters(4) * x[4];
|
|
|
|
|
for (EdgeIndex ei = 0; ei < pReducedPatternSimulationMesh->EN(); ei++) {
|
|
|
|
|
Element &e = pReducedPatternSimulationMesh->elements[ei];
|
|
|
|
|
e.setDimensions(
|
|
|
|
|
RectangularBeamDimensions(beamWidth,
|
|
|
|
|
beamHeight));
|
|
|
|
|
e.setMaterial(ElementMaterial(e.material.poissonsRatio,
|
|
|
|
|
E));
|
|
|
|
|
e.J = J;
|
|
|
|
|
e.I2 = I2;
|
|
|
|
|
e.I3 = I3;
|
|
|
|
|
}
|
|
|
|
|
assert(pReducedPatternSimulationMesh->EN() == 12);
|
2021-04-16 10:41:40 +02:00
|
|
|
|
assert(n >= 2);
|
|
|
|
|
|
|
|
|
|
// CoordType center_barycentric(1, 0, 0);
|
|
|
|
|
// CoordType interfaceEdgeMiddle_barycentric(0, 0.5, 0.5);
|
|
|
|
|
// CoordType movableVertex_barycentric((center_barycentric + interfaceEdgeMiddle_barycentric)
|
|
|
|
|
// * x[n - 2]);
|
2021-03-26 10:58:13 +01:00
|
|
|
|
|
2021-04-16 10:41:40 +02:00
|
|
|
|
CoordType movableVertex_barycentric(1 - x[n - 2], x[n - 2] / 2, x[n - 2] / 2);
|
2021-03-26 10:58:13 +01:00
|
|
|
|
CoordType baseTriangleMovableVertexPosition = global.baseTriangle.cP(0)
|
|
|
|
|
* movableVertex_barycentric[0]
|
|
|
|
|
+ global.baseTriangle.cP(1)
|
|
|
|
|
* movableVertex_barycentric[1]
|
|
|
|
|
+ global.baseTriangle.cP(2)
|
|
|
|
|
* movableVertex_barycentric[2];
|
|
|
|
|
baseTriangleMovableVertexPosition
|
|
|
|
|
= vcg::RotationMatrix(ReducedModelOptimizer::patternPlaneNormal, vcg::math::ToRad(x[n - 1]))
|
|
|
|
|
* baseTriangleMovableVertexPosition;
|
|
|
|
|
|
2021-03-23 18:20:46 +01:00
|
|
|
|
for (int rotationCounter = 0;
|
|
|
|
|
rotationCounter < ReducedModelOptimizer::fanSize; rotationCounter++) {
|
2021-04-16 10:41:40 +02:00
|
|
|
|
pReducedPatternSimulationMesh->vert[2 * rotationCounter].P()
|
2021-03-26 10:58:13 +01:00
|
|
|
|
= vcg::RotationMatrix(ReducedModelOptimizer::patternPlaneNormal,
|
|
|
|
|
vcg::math::ToRad(60.0 * rotationCounter))
|
|
|
|
|
* baseTriangleMovableVertexPosition;
|
2021-03-23 18:20:46 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pReducedPatternSimulationMesh->reset();
|
2021-03-26 10:58:13 +01:00
|
|
|
|
//#ifdef POLYSCOPE_DEFINED
|
|
|
|
|
// pReducedPatternSimulationMesh->updateEigenEdgeAndVertices();
|
|
|
|
|
// pReducedPatternSimulationMesh->registerForDrawing();
|
|
|
|
|
// std::cout << "Angle:" + std::to_string(x[n - 1]) + " size:" + std::to_string(x[n - 2])
|
|
|
|
|
// << std::endl;
|
|
|
|
|
// std::cout << "Verts:" << pReducedPatternSimulationMesh->VN() << std::endl;
|
|
|
|
|
// polyscope::show();
|
|
|
|
|
//#endif
|
2021-03-23 18:20:46 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2021-01-17 12:46:33 +01:00
|
|
|
|
void ReducedModelOptimizer::initializeOptimizationParameters(
|
2021-03-23 18:20:46 +01:00
|
|
|
|
const std::shared_ptr<SimulationMesh> &mesh,const int& optimizationParamters) {
|
|
|
|
|
global.numberOfOptimizationParameters = optimizationParamters;
|
2021-03-16 10:57:27 +01:00
|
|
|
|
global.initialParameters.resize(global.numberOfOptimizationParameters);
|
2021-03-23 18:20:46 +01:00
|
|
|
|
|
2021-03-16 10:57:27 +01:00
|
|
|
|
global.initialParameters(0) = mesh->elements[0].material.youngsModulus;
|
|
|
|
|
global.initialParameters(1) = mesh->elements[0].A;
|
|
|
|
|
global.initialParameters(2) = mesh->elements[0].J;
|
|
|
|
|
global.initialParameters(3) = mesh->elements[0].I2;
|
|
|
|
|
global.initialParameters(4) = mesh->elements[0].I3;
|
2020-11-23 10:06:45 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ReducedModelOptimizer::computeReducedModelSimulationJob(
|
|
|
|
|
const SimulationJob &simulationJobOfFullModel,
|
2021-03-26 10:58:13 +01:00
|
|
|
|
const std::unordered_map<size_t, size_t> &fullToReducedMap,
|
|
|
|
|
SimulationJob &simulationJobOfReducedModel)
|
|
|
|
|
{
|
2021-03-15 18:56:14 +01:00
|
|
|
|
assert(simulationJobOfReducedModel.pMesh->VN() != 0);
|
|
|
|
|
std::unordered_map<VertexIndex, std::unordered_set<DoFType>>
|
|
|
|
|
reducedModelFixedVertices;
|
|
|
|
|
for (auto fullModelFixedVertex :
|
|
|
|
|
simulationJobOfFullModel.constrainedVertices) {
|
2021-03-26 10:58:13 +01:00
|
|
|
|
reducedModelFixedVertices[fullToReducedMap.at(fullModelFixedVertex.first)]
|
|
|
|
|
= fullModelFixedVertex.second;
|
2021-03-15 18:56:14 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::unordered_map<VertexIndex, Vector6d> reducedModelNodalForces;
|
|
|
|
|
for (auto fullModelNodalForce :
|
|
|
|
|
simulationJobOfFullModel.nodalExternalForces) {
|
2021-03-26 10:58:13 +01:00
|
|
|
|
reducedModelNodalForces[fullToReducedMap.at(fullModelNodalForce.first)]
|
|
|
|
|
= fullModelNodalForce.second;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::unordered_map<VertexIndex, Eigen::Vector3d> reducedNodalForcedDisplacements;
|
|
|
|
|
for (auto fullForcedDisplacement : simulationJobOfFullModel.nodalForcedDisplacements) {
|
|
|
|
|
reducedNodalForcedDisplacements[fullToReducedMap.at(fullForcedDisplacement.first)]
|
|
|
|
|
= fullForcedDisplacement.second;
|
2021-03-15 18:56:14 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
simulationJobOfReducedModel.constrainedVertices = reducedModelFixedVertices;
|
|
|
|
|
simulationJobOfReducedModel.nodalExternalForces = reducedModelNodalForces;
|
|
|
|
|
simulationJobOfReducedModel.label = simulationJobOfFullModel.getLabel();
|
2021-03-26 10:58:13 +01:00
|
|
|
|
simulationJobOfReducedModel.nodalForcedDisplacements = reducedNodalForcedDisplacements;
|
2020-11-23 10:06:45 +01:00
|
|
|
|
}
|
|
|
|
|
|
2021-04-05 11:41:05 +02:00
|
|
|
|
//#if POLYSCOPE_DEFINED
|
|
|
|
|
//void ReducedModelOptimizer::visualizeResults(
|
|
|
|
|
// const std::vector<std::shared_ptr<SimulationJob>> &fullPatternSimulationJobs,
|
|
|
|
|
// const std::vector<std::shared_ptr<SimulationJob>> &reducedPatternSimulationJobs,
|
|
|
|
|
// const std::vector<BaseSimulationScenario> &simulationScenarios,
|
|
|
|
|
// const std::unordered_map<ReducedPatternVertexIndex, FullPatternVertexIndex>
|
|
|
|
|
// &reducedToFullInterfaceViMap)
|
|
|
|
|
//{
|
|
|
|
|
// DRMSimulationModel simulator;
|
|
|
|
|
// std::shared_ptr<SimulationMesh> pFullPatternSimulationMesh =
|
|
|
|
|
// fullPatternSimulationJobs[0]->pMesh;
|
|
|
|
|
// pFullPatternSimulationMesh->registerForDrawing();
|
|
|
|
|
// pFullPatternSimulationMesh->save(pFullPatternSimulationMesh->getLabel() + "_undeformed.ply");
|
|
|
|
|
// reducedPatternSimulationJobs[0]->pMesh->save(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 !=
|
|
|
|
|
// ReducedModelOptimization::Settings::NormalizationStrategy::NonNormalized) {
|
|
|
|
|
// normalizationFactor
|
|
|
|
|
// = global.translationalDisplacementNormalizationValues[simulationScenarioIndex];
|
|
|
|
|
// }
|
|
|
|
|
// reducedModelResults.saveDeformedModel();
|
|
|
|
|
// fullModelResults.saveDeformedModel();
|
|
|
|
|
// double error = computeDisplacementError(reducedModelResults.displacements,
|
|
|
|
|
// fullModelResults.displacements,
|
|
|
|
|
// reducedToFullInterfaceViMap,
|
|
|
|
|
// normalizationFactor);
|
|
|
|
|
// std::cout << "Error of simulation scenario "
|
|
|
|
|
// <baseSimulationScenarioNames[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() + "_"
|
|
|
|
|
// + baseSimulationScenarioNames[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> &pReducedPatternSimulationJob,
|
|
|
|
|
// const std::unordered_map<ReducedPatternVertexIndex, FullPatternVertexIndex>
|
|
|
|
|
// &reducedToFullInterfaceViMap) {
|
|
|
|
|
// DRMSimulationModel simulator;
|
|
|
|
|
// std::shared_ptr<SimulationMesh> pFullPatternSimulationMesh =
|
|
|
|
|
// pFullPatternSimulationJob->pMesh;
|
|
|
|
|
// pFullPatternSimulationMesh->registerForDrawing();
|
|
|
|
|
// // pFullPatternSimulationMesh->savePly(pFullPatternSimulationMesh->getLabel()
|
|
|
|
|
// // +
|
|
|
|
|
// // "_undeformed.ply");
|
|
|
|
|
// // reducedPatternSimulationJobs[0]->pMesh->savePly(
|
|
|
|
|
// // reducedPatternSimulationJobs[0]->pMesh->getLabel() +
|
|
|
|
|
// // "_undeformed.ply");
|
|
|
|
|
// pFullPatternSimulationJob->registerForDrawing(
|
|
|
|
|
// pFullPatternSimulationMesh->getLabel());
|
|
|
|
|
// SimulationResults fullModelResults =
|
|
|
|
|
// simulator.executeSimulation(pFullPatternSimulationJob);
|
|
|
|
|
// fullModelResults.registerForDrawing();
|
|
|
|
|
// // fullModelResults.saveDeformedModel();
|
|
|
|
|
// SimulationResults reducedModelResults =
|
|
|
|
|
// simulator.executeSimulation(pReducedPatternSimulationJob);
|
|
|
|
|
// // reducedModelResults.saveDeformedModel();
|
|
|
|
|
// // fullModelResults.saveDeformedModel();
|
|
|
|
|
// double error = computeRawDisplacementError(
|
|
|
|
|
// reducedModelResults.displacements, fullModelResults.displacements,
|
|
|
|
|
// reducedToFullInterfaceViMap/*,
|
|
|
|
|
// global.reducedPatternMaximumDisplacementNormSum[simulationScenarioIndex]*/);
|
|
|
|
|
// std::cout << "Error is " << error << std::endl;
|
|
|
|
|
// reducedModelResults.registerForDrawing();
|
|
|
|
|
//}
|
|
|
|
|
//#endif // POLYSCOPE_DEFINED
|
2021-02-22 18:23:58 +01:00
|
|
|
|
|
2020-11-23 10:06:45 +01:00
|
|
|
|
void ReducedModelOptimizer::computeDesiredReducedModelDisplacements(
|
|
|
|
|
const SimulationResults &fullModelResults,
|
2021-01-04 13:12:25 +01:00
|
|
|
|
const std::unordered_map<size_t, size_t> &displacementsReducedToFullMap,
|
2020-11-27 11:45:20 +01:00
|
|
|
|
Eigen::MatrixX3d &optimalDisplacementsOfReducedModel) {
|
|
|
|
|
|
2021-03-15 18:56:14 +01:00
|
|
|
|
assert(optimalDisplacementsOfReducedModel.rows() != 0 &&
|
|
|
|
|
optimalDisplacementsOfReducedModel.cols() == 3);
|
|
|
|
|
optimalDisplacementsOfReducedModel.setZero(
|
|
|
|
|
optimalDisplacementsOfReducedModel.rows(),
|
|
|
|
|
optimalDisplacementsOfReducedModel.cols());
|
|
|
|
|
|
|
|
|
|
for (auto reducedFullViPair : displacementsReducedToFullMap) {
|
|
|
|
|
const VertexIndex fullModelVi = reducedFullViPair.second;
|
|
|
|
|
const Vector6d fullModelViDisplacements =
|
|
|
|
|
fullModelResults.displacements[fullModelVi];
|
|
|
|
|
optimalDisplacementsOfReducedModel.row(reducedFullViPair.first) =
|
|
|
|
|
Eigen::Vector3d(fullModelViDisplacements[0],
|
|
|
|
|
fullModelViDisplacements[1],
|
|
|
|
|
fullModelViDisplacements[2]);
|
|
|
|
|
}
|
2020-11-23 10:06:45 +01:00
|
|
|
|
}
|
|
|
|
|
|
2021-04-30 11:47:50 +02:00
|
|
|
|
void ReducedModelOptimizer::getResults(const dlib::function_evaluation &optimizationResult_dlib,
|
|
|
|
|
const Settings &settings,
|
|
|
|
|
ReducedPatternOptimization::Results &results)
|
2021-04-08 19:55:56 +02:00
|
|
|
|
{
|
|
|
|
|
results.baseTriangle = global.baseTriangle;
|
|
|
|
|
//Number of crashes
|
2021-03-15 18:56:14 +01:00
|
|
|
|
results.numberOfSimulationCrashes = global.numOfSimulationCrashes;
|
2021-04-08 19:55:56 +02:00
|
|
|
|
//Value of optimal objective Y
|
|
|
|
|
results.objectiveValue.total = optimizationResult_dlib.y;
|
|
|
|
|
//Optimal X values
|
2021-03-30 11:35:00 +02:00
|
|
|
|
results.optimalXNameValuePairs.resize(settings.xRanges.size());
|
2021-04-08 19:55:56 +02:00
|
|
|
|
std::vector<double> optimalX(settings.xRanges.size());
|
|
|
|
|
for (int xVariableIndex = 0; xVariableIndex < settings.xRanges.size(); xVariableIndex++) {
|
|
|
|
|
if (xVariableIndex < 5) {
|
|
|
|
|
results.optimalXNameValuePairs[xVariableIndex]
|
|
|
|
|
= std::make_pair(settings.xRanges[xVariableIndex].label,
|
|
|
|
|
global.minX[xVariableIndex]
|
|
|
|
|
* global.initialParameters(xVariableIndex));
|
|
|
|
|
} else {
|
|
|
|
|
//Hex size and angle are pure values (not multipliers of the initial values)
|
|
|
|
|
results.optimalXNameValuePairs[xVariableIndex]
|
|
|
|
|
= std::make_pair(settings.xRanges[xVariableIndex].label,
|
|
|
|
|
global.minX[xVariableIndex]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
assert(global.minX[xVariableIndex] == optimizationResult_dlib.x(xVariableIndex));
|
|
|
|
|
optimalX[xVariableIndex] = optimizationResult_dlib.x(xVariableIndex);
|
2021-04-30 11:47:50 +02:00
|
|
|
|
#ifdef POLYSCOPE_DEFINED
|
2021-04-16 10:41:40 +02:00
|
|
|
|
std::cout << results.optimalXNameValuePairs[xVariableIndex].first << ":"
|
|
|
|
|
<< optimalX[xVariableIndex] << " ";
|
2021-04-30 11:47:50 +02:00
|
|
|
|
#endif
|
2021-03-23 18:20:46 +01:00
|
|
|
|
}
|
2021-04-30 11:47:50 +02:00
|
|
|
|
#ifdef POLYSCOPE_DEFINED
|
2021-04-16 10:41:40 +02:00
|
|
|
|
std::cout << std::endl;
|
2021-04-30 11:47:50 +02:00
|
|
|
|
#endif
|
2020-11-23 10:06:45 +01:00
|
|
|
|
|
2021-03-16 10:57:27 +01:00
|
|
|
|
// Compute obj value per simulation scenario and the raw objective value
|
2021-03-23 18:20:46 +01:00
|
|
|
|
updateMesh(optimalX.size(), optimalX.data());
|
2021-04-08 19:55:56 +02:00
|
|
|
|
// results.objectiveValue.totalPerSimulationScenario.resize(totalNumberOfSimulationScenarios);
|
2021-04-16 10:41:40 +02:00
|
|
|
|
//TODO:use push_back it will make the code more readable
|
2021-03-23 18:20:46 +01:00
|
|
|
|
LinearSimulationModel simulator;
|
2021-04-08 19:55:56 +02:00
|
|
|
|
results.objectiveValue.totalRaw = 0;
|
|
|
|
|
results.objectiveValue.perSimulationScenario_translational.resize(
|
2021-04-16 10:41:40 +02:00
|
|
|
|
global.simulationScenarioIndices.size());
|
2021-04-08 19:55:56 +02:00
|
|
|
|
results.objectiveValue.perSimulationScenario_rawTranslational.resize(
|
2021-04-16 10:41:40 +02:00
|
|
|
|
global.simulationScenarioIndices.size());
|
|
|
|
|
results.objectiveValue.perSimulationScenario_rotational.resize(
|
|
|
|
|
global.simulationScenarioIndices.size());
|
2021-04-08 19:55:56 +02:00
|
|
|
|
results.objectiveValue.perSimulationScenario_rawRotational.resize(
|
2021-04-16 10:41:40 +02:00
|
|
|
|
global.simulationScenarioIndices.size());
|
|
|
|
|
results.objectiveValue.perSimulationScenario_total.resize(
|
|
|
|
|
global.simulationScenarioIndices.size());
|
|
|
|
|
for (int i = 0; i < global.simulationScenarioIndices.size(); i++) {
|
|
|
|
|
const int simulationScenarioIndex = global.simulationScenarioIndices[i];
|
2021-03-15 18:56:14 +01:00
|
|
|
|
SimulationResults reducedModelResults = simulator.executeSimulation(
|
2021-03-23 18:20:46 +01:00
|
|
|
|
global.reducedPatternSimulationJobs[simulationScenarioIndex]);
|
2021-03-30 18:30:49 +02:00
|
|
|
|
|
2021-04-16 10:41:40 +02:00
|
|
|
|
results.objectiveValue.perSimulationScenario_total[i] = computeError(
|
2021-04-05 11:41:05 +02:00
|
|
|
|
global.fullPatternResults[simulationScenarioIndex],
|
|
|
|
|
reducedModelResults,
|
|
|
|
|
global.reducedToFullInterfaceViMap,
|
|
|
|
|
global.translationalDisplacementNormalizationValues[simulationScenarioIndex],
|
|
|
|
|
global.rotationalDisplacementNormalizationValues[simulationScenarioIndex]);
|
|
|
|
|
|
2021-04-08 19:55:56 +02:00
|
|
|
|
//Raw translational
|
|
|
|
|
const double rawTranslationalError = computeRawTranslationalError(
|
2021-03-26 10:58:13 +01:00
|
|
|
|
global.fullPatternResults[simulationScenarioIndex].displacements,
|
|
|
|
|
reducedModelResults.displacements,
|
|
|
|
|
global.reducedToFullInterfaceViMap);
|
2021-04-16 10:41:40 +02:00
|
|
|
|
results.objectiveValue.perSimulationScenario_rawTranslational[i] = rawTranslationalError;
|
2021-04-08 19:55:56 +02:00
|
|
|
|
//Raw rotational
|
2021-03-30 18:30:49 +02:00
|
|
|
|
const double rawRotationalError = computeRawRotationalError(
|
|
|
|
|
global.fullPatternResults[simulationScenarioIndex].rotationalDisplacementQuaternion,
|
|
|
|
|
reducedModelResults.rotationalDisplacementQuaternion,
|
|
|
|
|
global.reducedToFullInterfaceViMap);
|
2021-04-16 10:41:40 +02:00
|
|
|
|
results.objectiveValue.perSimulationScenario_rawRotational[i] = rawRotationalError;
|
2021-03-30 18:30:49 +02:00
|
|
|
|
|
2021-04-08 19:55:56 +02:00
|
|
|
|
//Normalized translational
|
|
|
|
|
const double normalizedTranslationalError = computeDisplacementError(
|
2021-04-05 11:41:05 +02:00
|
|
|
|
global.fullPatternResults[simulationScenarioIndex].displacements,
|
|
|
|
|
reducedModelResults.displacements,
|
|
|
|
|
global.reducedToFullInterfaceViMap,
|
|
|
|
|
global.translationalDisplacementNormalizationValues[simulationScenarioIndex]);
|
2021-04-16 10:41:40 +02:00
|
|
|
|
results.objectiveValue.perSimulationScenario_translational[i] = normalizedTranslationalError;
|
2021-04-08 19:55:56 +02:00
|
|
|
|
// const double test_normalizedTranslationError = computeDisplacementError(
|
|
|
|
|
// global.fullPatternResults[simulationScenarioIndex].displacements,
|
|
|
|
|
// reducedModelResults.displacements,
|
|
|
|
|
// global.reducedToFullInterfaceViMap,
|
|
|
|
|
// global.translationalDisplacementNormalizationValues[simulationScenarioIndex]);
|
|
|
|
|
//Normalized rotational
|
|
|
|
|
const double normalizedRotationalError = computeRotationalError(
|
2021-04-05 11:41:05 +02:00
|
|
|
|
global.fullPatternResults[simulationScenarioIndex].rotationalDisplacementQuaternion,
|
|
|
|
|
reducedModelResults.rotationalDisplacementQuaternion,
|
|
|
|
|
global.reducedToFullInterfaceViMap,
|
|
|
|
|
global.rotationalDisplacementNormalizationValues[simulationScenarioIndex]);
|
2021-04-16 10:41:40 +02:00
|
|
|
|
results.objectiveValue.perSimulationScenario_rotational[i] = normalizedRotationalError;
|
2021-04-08 19:55:56 +02:00
|
|
|
|
// const double test_normalizedRotationalError = computeRotationalError(
|
|
|
|
|
// global.fullPatternResults[simulationScenarioIndex].rotationalDisplacementQuaternion,
|
|
|
|
|
// reducedModelResults.rotationalDisplacementQuaternion,
|
|
|
|
|
// global.reducedToFullInterfaceViMap,
|
|
|
|
|
// global.rotationalDisplacementNormalizationValues[simulationScenarioIndex]);
|
|
|
|
|
// assert(test_normalizedTranslationError == normalizedTranslationalError);
|
|
|
|
|
// assert(test_normalizedRotationalError == normalizedRotationalError);
|
2021-04-30 11:47:50 +02:00
|
|
|
|
results.objectiveValue.totalRaw += rawTranslationalError + rawRotationalError;
|
|
|
|
|
#ifdef POLYSCOPE_DEFINED
|
2021-04-08 19:55:56 +02:00
|
|
|
|
std::cout << "Simulation scenario:"
|
|
|
|
|
<< global.reducedPatternSimulationJobs[simulationScenarioIndex]->getLabel()
|
2021-04-05 11:41:05 +02:00
|
|
|
|
<< std::endl;
|
|
|
|
|
std::cout << "raw translational error:" << rawTranslationalError << std::endl;
|
|
|
|
|
std::cout << "translation normalization value:"
|
|
|
|
|
<< global.translationalDisplacementNormalizationValues[simulationScenarioIndex]
|
2021-03-30 18:30:49 +02:00
|
|
|
|
<< std::endl;
|
2021-04-05 11:41:05 +02:00
|
|
|
|
std::cout << "raw Rotational error:" << rawRotationalError << std::endl;
|
|
|
|
|
std::cout << "rotational normalization value:"
|
|
|
|
|
<< global.rotationalDisplacementNormalizationValues[simulationScenarioIndex]
|
|
|
|
|
<< std::endl;
|
2021-04-16 10:41:40 +02:00
|
|
|
|
std::cout << "Translational error:" << normalizedTranslationalError << std::endl;
|
2021-03-30 18:30:49 +02:00
|
|
|
|
std::cout << "Rotational error:" << normalizedRotationalError << std::endl;
|
2021-04-08 19:55:56 +02:00
|
|
|
|
// results.objectiveValuePerSimulationScenario[simulationScenarioIndex]
|
|
|
|
|
// = normalizedTranslationalError + normalizedRotationalError;
|
2021-04-16 10:41:40 +02:00
|
|
|
|
std::cout << "Total Error value:" << results.objectiveValue.perSimulationScenario_total[i]
|
2021-04-05 11:41:05 +02:00
|
|
|
|
<< std::endl;
|
|
|
|
|
std::cout << std::endl;
|
2021-04-30 11:47:50 +02:00
|
|
|
|
#endif
|
2021-04-05 11:41:05 +02:00
|
|
|
|
}
|
|
|
|
|
|
2021-03-15 18:56:14 +01:00
|
|
|
|
const bool printDebugInfo = false;
|
|
|
|
|
if (printDebugInfo) {
|
|
|
|
|
std::cout << "Finished optimizing." << endl;
|
2021-04-08 19:55:56 +02:00
|
|
|
|
std::cout << "Total optimal objective value:" << results.objectiveValue.total << std::endl;
|
|
|
|
|
assert(global.minY == optimizationResult_dlib.y);
|
2021-04-16 10:41:40 +02:00
|
|
|
|
if (global.minY != optimizationResult_dlib.y) {
|
|
|
|
|
std::cerr << "ERROR in objective value" << std::endl;
|
|
|
|
|
}
|
2021-04-08 19:55:56 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (int simulationScenarioIndex : global.simulationScenarioIndices) {
|
|
|
|
|
results.fullPatternSimulationJobs.push_back(
|
|
|
|
|
global.fullPatternSimulationJobs[simulationScenarioIndex]);
|
|
|
|
|
results.reducedPatternSimulationJobs.push_back(
|
|
|
|
|
global.reducedPatternSimulationJobs[simulationScenarioIndex]);
|
|
|
|
|
// const std::string temp = global.reducedPatternSimulationJobs[simulationScenarioIndex]
|
|
|
|
|
// ->pMesh->getLabel();
|
|
|
|
|
// global.reducedPatternSimulationJobs[simulationScenarioIndex]->pMesh->setLabel("temp");
|
|
|
|
|
// global.reducedPatternSimulationJobs[simulationScenarioIndex]->pMesh->registerForDrawing();
|
|
|
|
|
// global.reducedPatternSimulationJobs[simulationScenarioIndex]->pMesh->setLabel(temp);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-04-30 11:47:50 +02:00
|
|
|
|
void ReducedModelOptimizer::runOptimization(const Settings &settings,
|
|
|
|
|
ReducedPatternOptimization::Results &results)
|
2021-04-08 19:55:56 +02:00
|
|
|
|
{
|
|
|
|
|
global.objectiveValueHistory.clear();
|
|
|
|
|
dlib::matrix<double, 0, 1> xMin(global.numberOfOptimizationParameters);
|
|
|
|
|
dlib::matrix<double, 0, 1> xMax(global.numberOfOptimizationParameters);
|
|
|
|
|
for (int i = 0; i < global.numberOfOptimizationParameters; i++) {
|
|
|
|
|
xMin(i) = settings.xRanges[i].min;
|
|
|
|
|
xMax(i) = settings.xRanges[i].max;
|
2021-03-15 18:56:14 +01:00
|
|
|
|
}
|
|
|
|
|
|
2021-04-08 19:55:56 +02:00
|
|
|
|
auto start = std::chrono::system_clock::now();
|
|
|
|
|
dlib::function_evaluation result_dlib;
|
|
|
|
|
double (*objF)(double, double, double, double, double,double,double) = &objective;
|
|
|
|
|
result_dlib = dlib::find_min_global(objF,
|
|
|
|
|
xMin,
|
|
|
|
|
xMax,
|
|
|
|
|
dlib::max_function_calls(settings.numberOfFunctionCalls),
|
|
|
|
|
std::chrono::hours(24 * 365 * 290),
|
2021-04-30 11:47:50 +02:00
|
|
|
|
settings.solverAccuracy);
|
2021-04-08 19:55:56 +02:00
|
|
|
|
auto end = std::chrono::system_clock::now();
|
|
|
|
|
auto elapsed =
|
|
|
|
|
std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
|
2021-04-30 11:47:50 +02:00
|
|
|
|
getResults(result_dlib, settings, results);
|
2021-04-08 19:55:56 +02:00
|
|
|
|
results.time = elapsed.count() / 1000.0;
|
2020-12-16 20:31:58 +01:00
|
|
|
|
}
|
|
|
|
|
|
2021-04-16 10:41:40 +02:00
|
|
|
|
void ReducedModelOptimizer::constructAxialSimulationScenario(
|
|
|
|
|
const double &forceMagnitude,
|
|
|
|
|
const std::vector<std::pair<FullPatternVertexIndex, FullPatternVertexIndex>>
|
|
|
|
|
&oppositeInterfaceViPairs,
|
|
|
|
|
SimulationJob &job)
|
|
|
|
|
{
|
|
|
|
|
for (auto viPairIt = oppositeInterfaceViPairs.begin();
|
|
|
|
|
viPairIt != oppositeInterfaceViPairs.end();
|
|
|
|
|
viPairIt++) {
|
|
|
|
|
if (viPairIt != oppositeInterfaceViPairs.begin()) {
|
|
|
|
|
CoordType forceDirection(1, 0, 0);
|
|
|
|
|
job.nodalExternalForces[viPairIt->first]
|
|
|
|
|
= Vector6d({forceDirection[0], forceDirection[1], forceDirection[2], 0, 0, 0})
|
|
|
|
|
* forceMagnitude;
|
|
|
|
|
job.constrainedVertices[viPairIt->second] = std::unordered_set<DoFType>{0, 1, 2, 3, 4, 5};
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ReducedModelOptimizer::constructShearSimulationScenario(
|
|
|
|
|
const double &forceMagnitude,
|
|
|
|
|
const std::vector<std::pair<FullPatternVertexIndex, FullPatternVertexIndex>>
|
|
|
|
|
&oppositeInterfaceViPairs,
|
|
|
|
|
SimulationJob &job)
|
|
|
|
|
{
|
|
|
|
|
for (auto viPairIt = oppositeInterfaceViPairs.begin();
|
|
|
|
|
viPairIt != oppositeInterfaceViPairs.end();
|
|
|
|
|
viPairIt++) {
|
|
|
|
|
if (viPairIt != oppositeInterfaceViPairs.begin()) {
|
|
|
|
|
CoordType forceDirection(0, 1, 0);
|
|
|
|
|
const auto viPair = *viPairIt;
|
|
|
|
|
job.nodalExternalForces[viPair.first]
|
|
|
|
|
= Vector6d({forceDirection[0], forceDirection[1], forceDirection[2], 0, 0, 0})
|
|
|
|
|
* forceMagnitude;
|
|
|
|
|
job.constrainedVertices[viPair.second] = std::unordered_set<DoFType>{0, 1, 2, 3, 4, 5};
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ReducedModelOptimizer::constructBendingSimulationScenario(
|
|
|
|
|
const double &forceMagnitude,
|
|
|
|
|
const std::vector<std::pair<FullPatternVertexIndex, FullPatternVertexIndex>>
|
|
|
|
|
&oppositeInterfaceViPairs,
|
|
|
|
|
SimulationJob &job)
|
|
|
|
|
{
|
|
|
|
|
for (const auto &viPair : oppositeInterfaceViPairs) {
|
|
|
|
|
job.nodalExternalForces[viPair.first] = Vector6d({0, 0, 1, 0, 0, 0}) * forceMagnitude;
|
|
|
|
|
job.constrainedVertices[viPair.second] = std::unordered_set<DoFType>{0, 1, 2, 3, 4, 5};
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-04-30 11:47:50 +02:00
|
|
|
|
/*NOTE: From the results it seems as if the forced displacements are different in the linear and in the drm
|
|
|
|
|
* */
|
2021-04-16 10:41:40 +02:00
|
|
|
|
void ReducedModelOptimizer::constructDomeSimulationScenario(
|
|
|
|
|
const double &forceMagnitude,
|
|
|
|
|
const std::vector<std::pair<FullPatternVertexIndex, FullPatternVertexIndex>>
|
|
|
|
|
&oppositeInterfaceViPairs,
|
|
|
|
|
SimulationJob &job)
|
|
|
|
|
{
|
|
|
|
|
for (auto viPairIt = oppositeInterfaceViPairs.begin();
|
|
|
|
|
viPairIt != oppositeInterfaceViPairs.end();
|
|
|
|
|
viPairIt++) {
|
|
|
|
|
const auto viPair = *viPairIt;
|
|
|
|
|
CoordType interfaceVector = (job.pMesh->vert[viPair.first].cP()
|
|
|
|
|
- job.pMesh->vert[viPair.second].cP());
|
|
|
|
|
VectorType momentAxis = vcg::RotationMatrix(VectorType(0, 0, 1), vcg::math::ToRad(90.0))
|
|
|
|
|
* interfaceVector.Normalize();
|
|
|
|
|
if (viPairIt == oppositeInterfaceViPairs.begin()) {
|
|
|
|
|
job.nodalForcedDisplacements[viPair.first]
|
|
|
|
|
= Eigen::Vector3d(-interfaceVector[0],
|
|
|
|
|
-interfaceVector[1],
|
|
|
|
|
0)
|
|
|
|
|
* 0.001
|
|
|
|
|
* std::abs(
|
|
|
|
|
forceMagnitude); //NOTE:Should the forced displacement change relatively to the magnitude?
|
|
|
|
|
// * std::abs(forceMagnitude / maxForceMagnitude_dome);
|
|
|
|
|
job.nodalForcedDisplacements[viPair.second] = Eigen::Vector3d(interfaceVector[0],
|
|
|
|
|
interfaceVector[1],
|
|
|
|
|
0)
|
|
|
|
|
* 0.001 * std::abs(forceMagnitude);
|
|
|
|
|
// * std::abs(forceMagnitude / maxForceMagnitude_dome);
|
|
|
|
|
// CoordType v = (pMesh->vert[viPair.first].cP() - pMesh->vert[viPair.second].cP())
|
|
|
|
|
// ^ CoordType(0, 0, -1).Normalize();
|
|
|
|
|
// nodalForces[viPair.first] = Vector6d({0, 0, 0, v[0], v[1], 0}) * forceMagnitude
|
|
|
|
|
// * 0.0001;
|
|
|
|
|
// nodalForces[viPair.second] = Vector6d({0, 0, 0, -v[0], -v[1], 0}) * forceMagnitude
|
|
|
|
|
// * 0.0001;
|
|
|
|
|
} else {
|
|
|
|
|
job.nodalExternalForces[viPair.first]
|
|
|
|
|
= Vector6d({0, 0, 0, momentAxis[0], momentAxis[1], momentAxis[2]}) * forceMagnitude
|
2021-04-30 11:47:50 +02:00
|
|
|
|
/ 3;
|
2021-04-16 10:41:40 +02:00
|
|
|
|
job.nodalExternalForces[viPair.second]
|
|
|
|
|
= Vector6d({0, 0, 0, -momentAxis[0], -momentAxis[1], -momentAxis[2]})
|
2021-04-30 11:47:50 +02:00
|
|
|
|
* forceMagnitude / 3;
|
2021-04-16 10:41:40 +02:00
|
|
|
|
job.constrainedVertices[viPair.first] = std::unordered_set<DoFType>{2};
|
|
|
|
|
job.constrainedVertices[viPair.second] = std::unordered_set<DoFType>{2};
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ReducedModelOptimizer::constructSaddleSimulationScenario(
|
|
|
|
|
const double &forceMagnitude,
|
|
|
|
|
const std::vector<std::pair<FullPatternVertexIndex, FullPatternVertexIndex>>
|
|
|
|
|
&oppositeInterfaceViPairs,
|
|
|
|
|
SimulationJob &job)
|
|
|
|
|
{
|
|
|
|
|
for (auto viPairIt = oppositeInterfaceViPairs.begin();
|
|
|
|
|
viPairIt != oppositeInterfaceViPairs.end();
|
|
|
|
|
viPairIt++) {
|
|
|
|
|
const auto &viPair = *viPairIt;
|
|
|
|
|
CoordType v = (job.pMesh->vert[viPair.first].cP() - job.pMesh->vert[viPair.second].cP())
|
|
|
|
|
^ CoordType(0, 0, -1).Normalize();
|
|
|
|
|
if (viPairIt == oppositeInterfaceViPairs.begin()) {
|
|
|
|
|
job.nodalExternalForces[viPair.first] = Vector6d({0, 0, 0, v[0], v[1], 0})
|
|
|
|
|
* forceMagnitude;
|
|
|
|
|
job.nodalExternalForces[viPair.second] = Vector6d({0, 0, 0, -v[0], -v[1], 0})
|
|
|
|
|
* forceMagnitude;
|
|
|
|
|
} else {
|
|
|
|
|
job.constrainedVertices[viPair.first] = std::unordered_set<DoFType>{2};
|
|
|
|
|
job.constrainedVertices[viPair.second] = std::unordered_set<DoFType>{0, 1, 2};
|
|
|
|
|
|
|
|
|
|
job.nodalExternalForces[viPair.first] = Vector6d({0, 0, 0, -v[0], -v[1], 0})
|
|
|
|
|
* forceMagnitude / 2;
|
|
|
|
|
job.nodalExternalForces[viPair.second] = Vector6d({0, 0, 0, v[0], v[1], 0})
|
|
|
|
|
* forceMagnitude / 2;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-04-30 11:47:50 +02:00
|
|
|
|
double fullPatternMaxSimulationForceRotationalObjective(const double &forceMagnitude)
|
|
|
|
|
{
|
|
|
|
|
SimulationJob job;
|
|
|
|
|
job.pMesh = global.pFullPatternSimulationMesh;
|
|
|
|
|
global.constructScenarioFunction(forceMagnitude, global.fullPatternInterfaceViPairs, job);
|
|
|
|
|
// ReducedModelOptimizer::axialSimulationScenario(forceMagnitude,
|
|
|
|
|
// global.fullPatternInterfaceViPairs,
|
|
|
|
|
// job);
|
|
|
|
|
|
|
|
|
|
DRMSimulationModel simulator;
|
|
|
|
|
DRMSimulationModel::Settings settings;
|
|
|
|
|
settings.totalExternalForcesNormPercentageTermination = 1e-2;
|
|
|
|
|
// settings.shouldUseTranslationalKineticEnergyThreshold = true;
|
|
|
|
|
// settings.totalTranslationalKineticEnergyThreshold = 1e-7;
|
|
|
|
|
SimulationResults results = simulator.executeSimulation(std::make_shared<SimulationJob>(job),
|
|
|
|
|
settings);
|
|
|
|
|
const double &desiredRotationAngle = global.desiredMaxRotationAngle;
|
|
|
|
|
const double error = std::abs(
|
|
|
|
|
// results.displacements[global.fullPatternInterfaceViPairs[1].first].getTranslation().norm()
|
|
|
|
|
results.rotationalDisplacementQuaternion[global.interfaceViForComputingScenarioError]
|
|
|
|
|
.angularDistance(Eigen::Quaterniond::Identity())
|
|
|
|
|
- desiredRotationAngle);
|
|
|
|
|
|
|
|
|
|
//#ifdef POLYSCOPE_DEFINED
|
|
|
|
|
// std::cout << "Force:" << forceMagnitude << " Error is:" << vcg::math::ToDeg(error) << std::endl;
|
|
|
|
|
//#endif
|
|
|
|
|
return error;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
double fullPatternMaxSimulationForceTranslationalObjective(const double &forceMagnitude)
|
2021-04-16 10:41:40 +02:00
|
|
|
|
{
|
|
|
|
|
SimulationJob job;
|
|
|
|
|
job.pMesh = global.pFullPatternSimulationMesh;
|
|
|
|
|
global.constructScenarioFunction(forceMagnitude, global.fullPatternInterfaceViPairs, job);
|
|
|
|
|
// ReducedModelOptimizer::axialSimulationScenario(forceMagnitude,
|
|
|
|
|
// global.fullPatternInterfaceViPairs,
|
|
|
|
|
// job);
|
|
|
|
|
|
|
|
|
|
DRMSimulationModel simulator;
|
|
|
|
|
DRMSimulationModel::Settings settings;
|
|
|
|
|
settings.totalExternalForcesNormPercentageTermination = 1e-2;
|
|
|
|
|
// settings.shouldUseTranslationalKineticEnergyThreshold = true;
|
|
|
|
|
// settings.totalTranslationalKineticEnergyThreshold = 1e-7;
|
|
|
|
|
SimulationResults results = simulator.executeSimulation(std::make_shared<SimulationJob>(job),
|
|
|
|
|
settings);
|
2021-04-30 11:47:50 +02:00
|
|
|
|
const double &desiredDisplacementValue = global.desiredMaxDisplacementValue;
|
2021-04-16 10:41:40 +02:00
|
|
|
|
const double error = std::abs(
|
|
|
|
|
// results.displacements[global.fullPatternInterfaceViPairs[1].first].getTranslation().norm()
|
|
|
|
|
results.displacements[global.interfaceViForComputingScenarioError].getTranslation().norm()
|
|
|
|
|
- desiredDisplacementValue);
|
|
|
|
|
|
|
|
|
|
return error;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
double ReducedModelOptimizer::getFullPatternMaxSimulationForce(const BaseSimulationScenario &scenario)
|
|
|
|
|
{
|
|
|
|
|
double forceMagnitude = 1;
|
|
|
|
|
global.desiredMaxDisplacementValue = 0.1
|
|
|
|
|
* vcg::Distance(global.baseTriangle.cP(0),
|
|
|
|
|
(global.baseTriangle.cP(1)
|
|
|
|
|
+ global.baseTriangle.cP(2))
|
|
|
|
|
/ 2);
|
2021-05-03 18:13:52 +02:00
|
|
|
|
const double optimizationEpsilon = 1e-1;
|
2021-04-16 10:41:40 +02:00
|
|
|
|
switch (scenario) {
|
|
|
|
|
case Axial:
|
2021-05-03 18:13:52 +02:00
|
|
|
|
global.desiredMaxDisplacementValue = 0.04
|
2021-04-30 11:47:50 +02:00
|
|
|
|
* vcg::Distance(global.baseTriangle.cP(0),
|
|
|
|
|
(global.baseTriangle.cP(1)
|
|
|
|
|
+ global.baseTriangle.cP(2))
|
|
|
|
|
/ 2);
|
2021-04-16 10:41:40 +02:00
|
|
|
|
global.constructScenarioFunction = &ReducedModelOptimizer::constructAxialSimulationScenario;
|
|
|
|
|
global.interfaceViForComputingScenarioError = global.fullPatternInterfaceViPairs[1].first;
|
2021-04-30 11:47:50 +02:00
|
|
|
|
dlib::find_min_single_variable(&fullPatternMaxSimulationForceTranslationalObjective,
|
2021-04-16 10:41:40 +02:00
|
|
|
|
forceMagnitude,
|
|
|
|
|
1e-8,
|
|
|
|
|
1e8,
|
|
|
|
|
optimizationEpsilon);
|
|
|
|
|
break;
|
|
|
|
|
case Shear:
|
2021-05-03 18:13:52 +02:00
|
|
|
|
global.desiredMaxDisplacementValue = 0.04
|
2021-04-30 11:47:50 +02:00
|
|
|
|
* vcg::Distance(global.baseTriangle.cP(0),
|
|
|
|
|
(global.baseTriangle.cP(1)
|
|
|
|
|
+ global.baseTriangle.cP(2))
|
|
|
|
|
/ 2);
|
2021-04-16 10:41:40 +02:00
|
|
|
|
global.constructScenarioFunction = &ReducedModelOptimizer::constructShearSimulationScenario;
|
|
|
|
|
global.interfaceViForComputingScenarioError = global.fullPatternInterfaceViPairs[1].first;
|
2021-04-30 11:47:50 +02:00
|
|
|
|
dlib::find_min_single_variable(&fullPatternMaxSimulationForceTranslationalObjective,
|
2021-04-16 10:41:40 +02:00
|
|
|
|
forceMagnitude,
|
|
|
|
|
1e-8,
|
|
|
|
|
1e8,
|
|
|
|
|
optimizationEpsilon);
|
|
|
|
|
break;
|
|
|
|
|
case Bending:
|
2021-05-03 18:13:52 +02:00
|
|
|
|
global.desiredMaxDisplacementValue = 0.05
|
2021-04-30 11:47:50 +02:00
|
|
|
|
* vcg::Distance(global.baseTriangle.cP(0),
|
|
|
|
|
(global.baseTriangle.cP(1)
|
|
|
|
|
+ global.baseTriangle.cP(2))
|
|
|
|
|
/ 2);
|
2021-04-16 10:41:40 +02:00
|
|
|
|
global.constructScenarioFunction = &ReducedModelOptimizer::constructBendingSimulationScenario;
|
|
|
|
|
global.interfaceViForComputingScenarioError = global.fullPatternInterfaceViPairs[0].first;
|
2021-04-30 11:47:50 +02:00
|
|
|
|
dlib::find_min_single_variable(&fullPatternMaxSimulationForceTranslationalObjective,
|
2021-04-16 10:41:40 +02:00
|
|
|
|
forceMagnitude,
|
|
|
|
|
1e-8,
|
|
|
|
|
1e8,
|
|
|
|
|
optimizationEpsilon,
|
|
|
|
|
200);
|
|
|
|
|
break;
|
|
|
|
|
case Dome:
|
2021-05-03 18:13:52 +02:00
|
|
|
|
global.desiredMaxRotationAngle = vcg::math::ToRad(20.0);
|
2021-04-16 10:41:40 +02:00
|
|
|
|
global.constructScenarioFunction = &ReducedModelOptimizer::constructDomeSimulationScenario;
|
|
|
|
|
global.interfaceViForComputingScenarioError = global.fullPatternInterfaceViPairs[1].first;
|
2021-04-30 11:47:50 +02:00
|
|
|
|
dlib::find_min_single_variable(
|
|
|
|
|
&fullPatternMaxSimulationForceRotationalObjective,
|
|
|
|
|
forceMagnitude,
|
|
|
|
|
1e-8,
|
|
|
|
|
1e8,
|
2021-05-03 18:13:52 +02:00
|
|
|
|
vcg::math::ToRad(1.0),
|
2021-04-30 11:47:50 +02:00
|
|
|
|
// global.desiredMaxRotationAngle * 0.5,
|
|
|
|
|
// optimizationEpsilon,
|
|
|
|
|
500);
|
2021-04-16 10:41:40 +02:00
|
|
|
|
break;
|
|
|
|
|
case Saddle:
|
2021-04-30 11:47:50 +02:00
|
|
|
|
// global.desiredMaxDisplacementValue *= 2;
|
2021-05-03 18:13:52 +02:00
|
|
|
|
global.desiredMaxDisplacementValue = 0.05
|
2021-04-30 11:47:50 +02:00
|
|
|
|
* vcg::Distance(global.baseTriangle.cP(0),
|
|
|
|
|
(global.baseTriangle.cP(1)
|
|
|
|
|
+ global.baseTriangle.cP(2))
|
|
|
|
|
/ 2);
|
|
|
|
|
// std::cout << "Saddle des disp:" << global.desiredMaxDisplacementValue << std::endl;
|
2021-04-16 10:41:40 +02:00
|
|
|
|
global.constructScenarioFunction = &ReducedModelOptimizer::constructSaddleSimulationScenario;
|
|
|
|
|
global.interfaceViForComputingScenarioError = global.fullPatternInterfaceViPairs[0].first;
|
2021-04-30 11:47:50 +02:00
|
|
|
|
dlib::find_min_single_variable(&fullPatternMaxSimulationForceTranslationalObjective,
|
2021-04-16 10:41:40 +02:00
|
|
|
|
forceMagnitude,
|
|
|
|
|
1e-8,
|
|
|
|
|
1e8,
|
2021-05-03 18:13:52 +02:00
|
|
|
|
1e-2,
|
2021-04-16 10:41:40 +02:00
|
|
|
|
150);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return forceMagnitude;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//TODO: Make more compact
|
2021-01-04 13:12:25 +01:00
|
|
|
|
std::vector<std::shared_ptr<SimulationJob>>
|
2021-04-08 19:55:56 +02:00
|
|
|
|
ReducedModelOptimizer::createFullPatternSimulationScenarios(
|
|
|
|
|
const std::shared_ptr<SimulationMesh> &pMesh)
|
|
|
|
|
{
|
2021-03-15 18:56:14 +01:00
|
|
|
|
std::vector<std::shared_ptr<SimulationJob>> scenarios;
|
2021-04-05 11:41:05 +02:00
|
|
|
|
scenarios.resize(totalNumberOfSimulationScenarios);
|
2021-04-16 10:41:40 +02:00
|
|
|
|
|
|
|
|
|
SimulationJob job;
|
|
|
|
|
job.pMesh = pMesh;
|
2021-03-15 18:56:14 +01:00
|
|
|
|
|
|
|
|
|
//// Axial
|
2021-04-16 10:41:40 +02:00
|
|
|
|
const double maxForceMagnitude_axial = getFullPatternMaxSimulationForce(
|
|
|
|
|
BaseSimulationScenario::Axial);
|
|
|
|
|
const double minForceMagnitude_axial = -maxForceMagnitude_axial;
|
2021-04-08 19:55:56 +02:00
|
|
|
|
const int numberOfSimulationScenarios_axial
|
|
|
|
|
= simulationScenariosResolution[BaseSimulationScenario::Axial];
|
|
|
|
|
const double forceMagnitudeStep_axial = numberOfSimulationScenarios_axial == 1
|
|
|
|
|
? maxForceMagnitude_axial
|
|
|
|
|
: (maxForceMagnitude_axial - minForceMagnitude_axial)
|
|
|
|
|
/ (numberOfSimulationScenarios_axial - 1);
|
|
|
|
|
const int baseSimulationScenarioIndexOffset_axial
|
|
|
|
|
= std::accumulate(simulationScenariosResolution.begin(),
|
|
|
|
|
simulationScenariosResolution.begin() + BaseSimulationScenario::Axial,
|
|
|
|
|
0);
|
|
|
|
|
for (int axialSimulationScenarioIndex = 0;
|
|
|
|
|
axialSimulationScenarioIndex < numberOfSimulationScenarios_axial;
|
|
|
|
|
axialSimulationScenarioIndex++) {
|
2021-04-16 10:41:40 +02:00
|
|
|
|
job.nodalExternalForces.clear();
|
|
|
|
|
job.constrainedVertices.clear();
|
|
|
|
|
job.nodalForcedDisplacements.clear();
|
|
|
|
|
job.label = baseSimulationScenarioNames[BaseSimulationScenario::Axial] + "_"
|
|
|
|
|
+ std::to_string(axialSimulationScenarioIndex);
|
|
|
|
|
|
2021-04-08 19:55:56 +02:00
|
|
|
|
const double forceMagnitude = (forceMagnitudeStep_axial * axialSimulationScenarioIndex
|
|
|
|
|
+ minForceMagnitude_axial);
|
2021-04-16 10:41:40 +02:00
|
|
|
|
constructAxialSimulationScenario(forceMagnitude, m_fullPatternOppositeInterfaceViPairs, job);
|
2021-04-08 19:55:56 +02:00
|
|
|
|
|
|
|
|
|
scenarios[baseSimulationScenarioIndexOffset_axial + axialSimulationScenarioIndex]
|
2021-04-16 10:41:40 +02:00
|
|
|
|
= std::make_shared<SimulationJob>(job);
|
2021-03-02 19:32:43 +01:00
|
|
|
|
}
|
2021-03-15 18:56:14 +01:00
|
|
|
|
|
|
|
|
|
//// Shear
|
2021-04-16 10:41:40 +02:00
|
|
|
|
const double maxForceMagnitude_shear = getFullPatternMaxSimulationForce(
|
|
|
|
|
BaseSimulationScenario::Shear);
|
|
|
|
|
const double minForceMagnitude_shear = -maxForceMagnitude_shear;
|
2021-04-08 19:55:56 +02:00
|
|
|
|
const int numberOfSimulationScenarios_shear
|
|
|
|
|
= simulationScenariosResolution[BaseSimulationScenario::Shear];
|
|
|
|
|
const double forceMagnitudeStep_shear = numberOfSimulationScenarios_shear == 1
|
|
|
|
|
? maxForceMagnitude_shear
|
|
|
|
|
: (maxForceMagnitude_shear - minForceMagnitude_shear)
|
|
|
|
|
/ (numberOfSimulationScenarios_shear - 1);
|
|
|
|
|
const int baseSimulationScenarioIndexOffset_shear
|
|
|
|
|
= std::accumulate(simulationScenariosResolution.begin(),
|
|
|
|
|
simulationScenariosResolution.begin() + BaseSimulationScenario::Shear,
|
|
|
|
|
0);
|
|
|
|
|
for (int shearSimulationScenarioIndex = 0;
|
|
|
|
|
shearSimulationScenarioIndex < numberOfSimulationScenarios_shear;
|
|
|
|
|
shearSimulationScenarioIndex++) {
|
2021-04-16 10:41:40 +02:00
|
|
|
|
job.constrainedVertices.clear();
|
|
|
|
|
job.nodalExternalForces.clear();
|
|
|
|
|
job.label = baseSimulationScenarioNames[BaseSimulationScenario::Shear] + "_"
|
|
|
|
|
+ std::to_string(shearSimulationScenarioIndex);
|
2021-04-08 19:55:56 +02:00
|
|
|
|
const double forceMagnitude = (forceMagnitudeStep_shear * shearSimulationScenarioIndex
|
|
|
|
|
+ minForceMagnitude_shear);
|
2021-04-16 10:41:40 +02:00
|
|
|
|
constructShearSimulationScenario(forceMagnitude, m_fullPatternOppositeInterfaceViPairs, job);
|
2021-04-08 19:55:56 +02:00
|
|
|
|
scenarios[baseSimulationScenarioIndexOffset_shear + shearSimulationScenarioIndex]
|
2021-04-16 10:41:40 +02:00
|
|
|
|
= std::make_shared<SimulationJob>(job);
|
2021-03-02 19:32:43 +01:00
|
|
|
|
}
|
2021-03-15 18:56:14 +01:00
|
|
|
|
|
|
|
|
|
//// Bending
|
2021-04-16 10:41:40 +02:00
|
|
|
|
const double maxForceMagnitude_bending = getFullPatternMaxSimulationForce(
|
|
|
|
|
BaseSimulationScenario::Bending);
|
2021-04-30 11:47:50 +02:00
|
|
|
|
const double minForceMagnitude_bending = 0;
|
2021-04-08 19:55:56 +02:00
|
|
|
|
const int numberOfSimulationScenarios_bending
|
|
|
|
|
= simulationScenariosResolution[BaseSimulationScenario::Bending];
|
2021-04-30 11:47:50 +02:00
|
|
|
|
const double forceMagnitudeStep_bending = (maxForceMagnitude_bending - minForceMagnitude_bending)
|
|
|
|
|
/ (numberOfSimulationScenarios_bending);
|
2021-04-08 19:55:56 +02:00
|
|
|
|
const int baseSimulationScenarioIndexOffset_bending
|
|
|
|
|
= std::accumulate(simulationScenariosResolution.begin(),
|
|
|
|
|
simulationScenariosResolution.begin() + BaseSimulationScenario::Bending,
|
|
|
|
|
0);
|
|
|
|
|
for (int bendingSimulationScenarioIndex = 0;
|
|
|
|
|
bendingSimulationScenarioIndex < numberOfSimulationScenarios_bending;
|
|
|
|
|
bendingSimulationScenarioIndex++) {
|
2021-04-16 10:41:40 +02:00
|
|
|
|
job.nodalExternalForces.clear();
|
|
|
|
|
job.constrainedVertices.clear();
|
|
|
|
|
job.label = baseSimulationScenarioNames[BaseSimulationScenario::Bending] + "_"
|
|
|
|
|
+ std::to_string(bendingSimulationScenarioIndex);
|
2021-04-30 11:47:50 +02:00
|
|
|
|
const double forceMagnitude = (forceMagnitudeStep_bending
|
|
|
|
|
* (bendingSimulationScenarioIndex + 1)
|
2021-04-08 19:55:56 +02:00
|
|
|
|
+ minForceMagnitude_bending);
|
2021-04-16 10:41:40 +02:00
|
|
|
|
constructBendingSimulationScenario(forceMagnitude,
|
|
|
|
|
m_fullPatternOppositeInterfaceViPairs,
|
|
|
|
|
job);
|
2021-04-08 19:55:56 +02:00
|
|
|
|
scenarios[baseSimulationScenarioIndexOffset_bending + bendingSimulationScenarioIndex]
|
2021-04-16 10:41:40 +02:00
|
|
|
|
= std::make_shared<SimulationJob>(job);
|
2020-12-16 20:31:58 +01:00
|
|
|
|
}
|
2021-03-15 18:56:14 +01:00
|
|
|
|
|
2021-03-26 10:58:13 +01:00
|
|
|
|
//// Dome
|
2021-04-16 10:41:40 +02:00
|
|
|
|
const double maxForceMagnitude_dome = getFullPatternMaxSimulationForce(
|
|
|
|
|
BaseSimulationScenario::Dome);
|
2021-04-30 11:47:50 +02:00
|
|
|
|
const double minForceMagnitude_dome = 0;
|
2021-04-08 19:55:56 +02:00
|
|
|
|
const int numberOfSimulationScenarios_dome
|
|
|
|
|
= simulationScenariosResolution[BaseSimulationScenario::Dome];
|
2021-04-30 11:47:50 +02:00
|
|
|
|
const double forceMagnitudeStep_dome = (maxForceMagnitude_dome - minForceMagnitude_dome)
|
|
|
|
|
/ (numberOfSimulationScenarios_dome);
|
2021-04-08 19:55:56 +02:00
|
|
|
|
const int baseSimulationScenarioIndexOffset_dome
|
|
|
|
|
= std::accumulate(simulationScenariosResolution.begin(),
|
|
|
|
|
simulationScenariosResolution.begin() + BaseSimulationScenario::Dome,
|
|
|
|
|
0);
|
|
|
|
|
for (int domeSimulationScenarioIndex = 0;
|
|
|
|
|
domeSimulationScenarioIndex < numberOfSimulationScenarios_dome;
|
|
|
|
|
domeSimulationScenarioIndex++) {
|
2021-04-16 10:41:40 +02:00
|
|
|
|
job.constrainedVertices.clear();
|
|
|
|
|
job.nodalExternalForces.clear();
|
|
|
|
|
job.nodalForcedDisplacements.clear();
|
|
|
|
|
job.label = baseSimulationScenarioNames[BaseSimulationScenario::Dome] + "_"
|
|
|
|
|
+ std::to_string(domeSimulationScenarioIndex);
|
2021-04-30 11:47:50 +02:00
|
|
|
|
const double forceMagnitude = (forceMagnitudeStep_dome * (domeSimulationScenarioIndex + 1)
|
2021-04-08 19:55:56 +02:00
|
|
|
|
+ minForceMagnitude_dome);
|
2021-04-16 10:41:40 +02:00
|
|
|
|
constructDomeSimulationScenario(forceMagnitude, m_fullPatternOppositeInterfaceViPairs, job);
|
2021-04-08 19:55:56 +02:00
|
|
|
|
scenarios[baseSimulationScenarioIndexOffset_dome + domeSimulationScenarioIndex]
|
2021-04-16 10:41:40 +02:00
|
|
|
|
= std::make_shared<SimulationJob>(job);
|
2021-03-15 18:56:14 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//// Saddle
|
2021-04-16 10:41:40 +02:00
|
|
|
|
const double maxForceMagnitude_saddle = getFullPatternMaxSimulationForce(
|
|
|
|
|
BaseSimulationScenario::Saddle);
|
2021-04-30 11:47:50 +02:00
|
|
|
|
const double minForceMagnitude_saddle = 0;
|
2021-04-08 19:55:56 +02:00
|
|
|
|
const int numberOfSimulationScenarios_saddle
|
|
|
|
|
= simulationScenariosResolution[BaseSimulationScenario::Saddle];
|
2021-04-30 11:47:50 +02:00
|
|
|
|
const double forceMagnitudeStep_saddle = (maxForceMagnitude_saddle - minForceMagnitude_saddle)
|
|
|
|
|
/ numberOfSimulationScenarios_saddle;
|
2021-04-08 19:55:56 +02:00
|
|
|
|
const int baseSimulationScenarioIndexOffset_saddle
|
|
|
|
|
= std::accumulate(simulationScenariosResolution.begin(),
|
|
|
|
|
simulationScenariosResolution.begin() + BaseSimulationScenario::Saddle,
|
|
|
|
|
0);
|
|
|
|
|
for (int saddleSimulationScenarioIndex = 0;
|
|
|
|
|
saddleSimulationScenarioIndex < numberOfSimulationScenarios_saddle;
|
|
|
|
|
saddleSimulationScenarioIndex++) {
|
2021-04-16 10:41:40 +02:00
|
|
|
|
job.constrainedVertices.clear();
|
|
|
|
|
job.nodalExternalForces.clear();
|
|
|
|
|
job.nodalForcedDisplacements.clear();
|
|
|
|
|
job.label = baseSimulationScenarioNames[BaseSimulationScenario::Saddle] + "_"
|
|
|
|
|
+ std::to_string(saddleSimulationScenarioIndex);
|
2021-04-30 11:47:50 +02:00
|
|
|
|
const double forceMagnitude = (forceMagnitudeStep_saddle
|
|
|
|
|
* (saddleSimulationScenarioIndex + 1)
|
2021-04-08 19:55:56 +02:00
|
|
|
|
+ minForceMagnitude_saddle);
|
2021-04-16 10:41:40 +02:00
|
|
|
|
constructSaddleSimulationScenario(forceMagnitude,
|
|
|
|
|
m_fullPatternOppositeInterfaceViPairs,
|
|
|
|
|
job);
|
2021-04-08 19:55:56 +02:00
|
|
|
|
scenarios[baseSimulationScenarioIndexOffset_saddle + saddleSimulationScenarioIndex]
|
2021-04-16 10:41:40 +02:00
|
|
|
|
= std::make_shared<SimulationJob>(job);
|
2020-12-09 16:58:48 +01:00
|
|
|
|
}
|
2020-11-23 10:06:45 +01:00
|
|
|
|
|
2021-04-30 11:47:50 +02:00
|
|
|
|
#ifdef POLYSCOPE_DEFINED
|
|
|
|
|
std::cout << "Computed full pattern scenario magnitudes" << std::endl;
|
|
|
|
|
#endif
|
2021-03-15 18:56:14 +01:00
|
|
|
|
return scenarios;
|
2020-11-23 10:06:45 +01:00
|
|
|
|
}
|
|
|
|
|
|
2021-03-01 13:34:27 +01:00
|
|
|
|
void ReducedModelOptimizer::computeObjectiveValueNormalizationFactors() {
|
2021-03-15 18:56:14 +01:00
|
|
|
|
|
|
|
|
|
// Compute the sum of the displacement norms
|
2021-04-05 11:41:05 +02:00
|
|
|
|
std::vector<double> fullPatternTranslationalDisplacementNormSum(
|
|
|
|
|
totalNumberOfSimulationScenarios);
|
|
|
|
|
std::vector<double> fullPatternAngularDistance(totalNumberOfSimulationScenarios);
|
2021-03-15 18:56:14 +01:00
|
|
|
|
for (int simulationScenarioIndex : global.simulationScenarioIndices) {
|
2021-03-30 11:35:00 +02:00
|
|
|
|
double translationalDisplacementNormSum = 0;
|
2021-03-15 18:56:14 +01:00
|
|
|
|
for (auto interfaceViPair : global.reducedToFullInterfaceViMap) {
|
2021-03-30 11:35:00 +02:00
|
|
|
|
const int fullPatternVi = interfaceViPair.second;
|
|
|
|
|
//If the full pattern vertex is translationally constrained dont take it into account
|
|
|
|
|
if (global.fullPatternSimulationJobs[simulationScenarioIndex]
|
|
|
|
|
->constrainedVertices.contains(fullPatternVi)) {
|
|
|
|
|
const std::unordered_set<int> constrainedDof
|
|
|
|
|
= global.fullPatternSimulationJobs[simulationScenarioIndex]
|
|
|
|
|
->constrainedVertices.at(fullPatternVi);
|
|
|
|
|
if (constrainedDof.contains(0) && constrainedDof.contains(1)
|
|
|
|
|
&& constrainedDof.contains(2)) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-03-26 10:58:13 +01:00
|
|
|
|
const Vector6d &vertexDisplacement = global
|
|
|
|
|
.fullPatternResults[simulationScenarioIndex]
|
2021-03-30 11:35:00 +02:00
|
|
|
|
.displacements[fullPatternVi];
|
|
|
|
|
translationalDisplacementNormSum += vertexDisplacement.getTranslation().norm();
|
2021-04-05 11:41:05 +02:00
|
|
|
|
}
|
|
|
|
|
double angularDistanceSum = 0;
|
|
|
|
|
for (auto interfaceViPair : global.reducedToFullInterfaceViMap) {
|
|
|
|
|
const int fullPatternVi = interfaceViPair.second;
|
2021-03-30 11:35:00 +02:00
|
|
|
|
//If the full pattern vertex is rotationally constrained dont take it into account
|
|
|
|
|
if (global.fullPatternSimulationJobs[simulationScenarioIndex]
|
|
|
|
|
->constrainedVertices.contains(fullPatternVi)) {
|
|
|
|
|
const std::unordered_set<int> constrainedDof
|
|
|
|
|
= global.fullPatternSimulationJobs[simulationScenarioIndex]
|
|
|
|
|
->constrainedVertices.at(fullPatternVi);
|
|
|
|
|
if (constrainedDof.contains(3) && constrainedDof.contains(5)
|
|
|
|
|
&& constrainedDof.contains(4)) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
angularDistanceSum += global.fullPatternResults[simulationScenarioIndex]
|
|
|
|
|
.rotationalDisplacementQuaternion[fullPatternVi]
|
|
|
|
|
.angularDistance(Eigen::Quaterniond::Identity());
|
2021-03-15 18:56:14 +01:00
|
|
|
|
}
|
2021-04-05 11:41:05 +02:00
|
|
|
|
|
2021-03-30 11:35:00 +02:00
|
|
|
|
fullPatternTranslationalDisplacementNormSum[simulationScenarioIndex]
|
|
|
|
|
= translationalDisplacementNormSum;
|
|
|
|
|
fullPatternAngularDistance[simulationScenarioIndex] = angularDistanceSum;
|
2021-03-15 18:56:14 +01:00
|
|
|
|
}
|
2021-03-01 13:34:27 +01:00
|
|
|
|
|
2021-03-15 18:56:14 +01:00
|
|
|
|
for (int simulationScenarioIndex : global.simulationScenarioIndices) {
|
|
|
|
|
if (global.optimizationSettings.normalizationStrategy ==
|
|
|
|
|
Settings::NormalizationStrategy::Epsilon) {
|
2021-03-30 11:35:00 +02:00
|
|
|
|
const double epsilon_translationalDisplacement = global.optimizationSettings
|
|
|
|
|
.normalizationParameter;
|
|
|
|
|
global.translationalDisplacementNormalizationValues[simulationScenarioIndex]
|
|
|
|
|
= std::max(fullPatternTranslationalDisplacementNormSum[simulationScenarioIndex],
|
|
|
|
|
epsilon_translationalDisplacement);
|
2021-04-05 11:41:05 +02:00
|
|
|
|
// const double epsilon_rotationalDisplacement = vcg::math::ToRad(10.0);
|
2021-03-30 11:35:00 +02:00
|
|
|
|
global.rotationalDisplacementNormalizationValues[simulationScenarioIndex]
|
2021-04-05 11:41:05 +02:00
|
|
|
|
= /*std::max(*/ fullPatternAngularDistance[simulationScenarioIndex] /*,
|
|
|
|
|
epsilon_rotationalDisplacement)*/
|
|
|
|
|
;
|
2021-03-30 18:30:49 +02:00
|
|
|
|
} else {
|
|
|
|
|
global.translationalDisplacementNormalizationValues[simulationScenarioIndex] = 1;
|
|
|
|
|
global.rotationalDisplacementNormalizationValues[simulationScenarioIndex] = 1;
|
2021-03-15 18:56:14 +01:00
|
|
|
|
}
|
2021-03-01 13:34:27 +01:00
|
|
|
|
}
|
2021-04-05 11:41:05 +02:00
|
|
|
|
}
|
2021-01-04 13:12:25 +01:00
|
|
|
|
|
2021-04-30 11:47:50 +02:00
|
|
|
|
void ReducedModelOptimizer::optimize(
|
2021-02-14 13:27:14 +01:00
|
|
|
|
const Settings &optimizationSettings,
|
2021-04-30 11:47:50 +02:00
|
|
|
|
ReducedPatternOptimization::Results &results,
|
2021-04-05 11:41:05 +02:00
|
|
|
|
const std::vector<BaseSimulationScenario> &desiredBaseSimulationScenarioIndices)
|
|
|
|
|
{
|
|
|
|
|
for (int baseSimulationScenarioIndex : desiredBaseSimulationScenarioIndices) {
|
|
|
|
|
//Increase the size of the vector holding the simulation scenario indices
|
|
|
|
|
global.simulationScenarioIndices.resize(
|
|
|
|
|
global.simulationScenarioIndices.size()
|
|
|
|
|
+ simulationScenariosResolution[baseSimulationScenarioIndex]);
|
|
|
|
|
//Add the simulation scenarios indices that correspond to this base simulation scenario
|
|
|
|
|
std::iota(global.simulationScenarioIndices.end()
|
|
|
|
|
- simulationScenariosResolution[baseSimulationScenarioIndex],
|
|
|
|
|
global.simulationScenarioIndices.end(),
|
|
|
|
|
std::accumulate(simulationScenariosResolution.begin(),
|
|
|
|
|
simulationScenariosResolution.begin()
|
|
|
|
|
+ baseSimulationScenarioIndex,
|
|
|
|
|
0));
|
|
|
|
|
}
|
|
|
|
|
if (desiredBaseSimulationScenarioIndices.empty()) {
|
|
|
|
|
global.simulationScenarioIndices.resize(totalNumberOfSimulationScenarios);
|
|
|
|
|
std::iota(global.simulationScenarioIndices.begin(),
|
|
|
|
|
global.simulationScenarioIndices.end(),
|
|
|
|
|
0);
|
2021-03-15 18:56:14 +01:00
|
|
|
|
}
|
|
|
|
|
|
2021-04-05 11:41:05 +02:00
|
|
|
|
global.reducedPatternSimulationJobs.resize(totalNumberOfSimulationScenarios);
|
|
|
|
|
global.fullPatternResults.resize(totalNumberOfSimulationScenarios);
|
|
|
|
|
global.translationalDisplacementNormalizationValues.resize(totalNumberOfSimulationScenarios);
|
|
|
|
|
global.rotationalDisplacementNormalizationValues.resize(totalNumberOfSimulationScenarios);
|
2021-03-15 18:56:14 +01:00
|
|
|
|
global.minY = std::numeric_limits<double>::max();
|
|
|
|
|
global.numOfSimulationCrashes = 0;
|
|
|
|
|
global.numberOfFunctionCalls = 0;
|
|
|
|
|
global.optimizationSettings = optimizationSettings;
|
2021-04-16 10:41:40 +02:00
|
|
|
|
global.pFullPatternSimulationMesh = m_pFullPatternSimulationMesh;
|
2021-04-08 19:55:56 +02:00
|
|
|
|
global.fullPatternSimulationJobs = createFullPatternSimulationScenarios(
|
|
|
|
|
m_pFullPatternSimulationMesh);
|
2021-03-15 18:56:14 +01:00
|
|
|
|
// polyscope::removeAllStructures();
|
|
|
|
|
|
2021-03-26 10:58:13 +01:00
|
|
|
|
DRMSimulationModel::Settings simulationSettings;
|
|
|
|
|
simulationSettings.shouldDraw = false;
|
2021-04-30 11:47:50 +02:00
|
|
|
|
#ifdef POLYSCOPE_DEFINED
|
|
|
|
|
const bool drawFullPatternSimulationResults = true;
|
|
|
|
|
;
|
2021-04-16 10:41:40 +02:00
|
|
|
|
if (drawFullPatternSimulationResults) {
|
|
|
|
|
global.fullPatternSimulationJobs[0]->pMesh->registerForDrawing(
|
|
|
|
|
ReducedPatternOptimization::Colors::fullInitial);
|
|
|
|
|
}
|
2021-04-30 11:47:50 +02:00
|
|
|
|
#endif
|
2021-04-05 11:41:05 +02:00
|
|
|
|
// LinearSimulationModel linearSimulator;
|
2021-03-15 18:56:14 +01:00
|
|
|
|
for (int simulationScenarioIndex : global.simulationScenarioIndices) {
|
2021-04-05 11:41:05 +02:00
|
|
|
|
const std::shared_ptr<SimulationJob> &pFullPatternSimulationJob
|
|
|
|
|
= global.fullPatternSimulationJobs[simulationScenarioIndex];
|
2021-03-26 10:58:13 +01:00
|
|
|
|
SimulationResults fullPatternResults = simulator.executeSimulation(pFullPatternSimulationJob,
|
|
|
|
|
simulationSettings);
|
2021-04-30 11:47:50 +02:00
|
|
|
|
#ifdef POLYSCOPE_DEFINED
|
2021-04-16 10:41:40 +02:00
|
|
|
|
if (drawFullPatternSimulationResults) {
|
|
|
|
|
// SimulationResults fullPatternResults_linear = linearSimulator.executeSimulation(
|
|
|
|
|
// pFullPatternSimulationJob);
|
|
|
|
|
fullPatternResults.registerForDrawing(ReducedPatternOptimization::Colors::fullDeformed,
|
|
|
|
|
true,
|
|
|
|
|
true);
|
|
|
|
|
// fullPatternResults_linear.labelPrefix += "_linear";
|
|
|
|
|
// fullPatternResults_linear.registerForDrawing(ReducedModelOptimization::Colors::fullDeformed,
|
|
|
|
|
// true,
|
|
|
|
|
// true);
|
|
|
|
|
polyscope::show();
|
|
|
|
|
fullPatternResults.unregister();
|
|
|
|
|
// fullPatternResults_linear.unregister();
|
|
|
|
|
}
|
2021-04-30 11:47:50 +02:00
|
|
|
|
#endif
|
2021-03-26 10:58:13 +01:00
|
|
|
|
global.fullPatternResults[simulationScenarioIndex] = fullPatternResults;
|
2021-03-15 18:56:14 +01:00
|
|
|
|
SimulationJob reducedPatternSimulationJob;
|
|
|
|
|
reducedPatternSimulationJob.pMesh = m_pReducedPatternSimulationMesh;
|
|
|
|
|
computeReducedModelSimulationJob(*pFullPatternSimulationJob,
|
|
|
|
|
m_fullToReducedInterfaceViMap,
|
|
|
|
|
reducedPatternSimulationJob);
|
2021-04-05 11:41:05 +02:00
|
|
|
|
global.reducedPatternSimulationJobs[simulationScenarioIndex]
|
|
|
|
|
= std::make_shared<SimulationJob>(reducedPatternSimulationJob);
|
2021-04-08 19:55:56 +02:00
|
|
|
|
// std::cout << "Ran sim scenario:" << simulationScenarioIndex << std::endl;
|
2021-03-15 18:56:14 +01:00
|
|
|
|
}
|
2021-04-30 11:47:50 +02:00
|
|
|
|
|
|
|
|
|
#ifdef POLYSCOPE_DEFINED
|
2021-04-16 10:41:40 +02:00
|
|
|
|
if (drawFullPatternSimulationResults) {
|
|
|
|
|
global.fullPatternSimulationJobs[0]->pMesh->unregister();
|
|
|
|
|
}
|
2021-04-30 11:47:50 +02:00
|
|
|
|
#endif
|
2021-04-05 11:41:05 +02:00
|
|
|
|
// if (global.optimizationSettings.normalizationStrategy
|
|
|
|
|
// != Settings::NormalizationStrategy::NonNormalized) {
|
|
|
|
|
computeObjectiveValueNormalizationFactors();
|
|
|
|
|
// }
|
2021-04-30 11:47:50 +02:00
|
|
|
|
#ifdef POLYSCOPE_DEFINED
|
|
|
|
|
std::cout << "Running reduced model optimization" << std::endl;
|
|
|
|
|
#endif
|
|
|
|
|
runOptimization(optimizationSettings, results);
|
2020-11-23 10:06:45 +01:00
|
|
|
|
}
|