BUG:The first optimization produces different results compared to the next.

This commit is contained in:
Iason 2020-11-27 12:45:20 +02:00
parent 1c7117c6a0
commit b5ef56dcb7
4 changed files with 469 additions and 212 deletions

View File

@ -56,7 +56,11 @@ find_package(OpenMP)
set(MYSOURCESDIR "/home/iason/Coding/Libraries/MySources") set(MYSOURCESDIR "/home/iason/Coding/Libraries/MySources")
file(GLOB MYSOURCES ${MYSOURCESDIR}/*.hpp ${MYSOURCESDIR}/*.cpp) file(GLOB MYSOURCES ${MYSOURCESDIR}/*.hpp ${MYSOURCESDIR}/*.cpp)
add_executable(${PROJECT_NAME} ${SOURCES} ${MYSOURCES} ) file(GLOB EXT_SOURCES ${vcglib_devel_SOURCE_DIR}/wrap/ply/plylib.cpp
)
add_executable(${PROJECT_NAME} ${SOURCES} ${MYSOURCES} ${EXT_SOURCES} )
target_include_directories(${PROJECT_NAME} target_include_directories(${PROJECT_NAME}
PRIVATE ${vcglib_devel_SOURCE_DIR} PRIVATE ${vcglib_devel_SOURCE_DIR}

View File

@ -13,37 +13,79 @@
#include <string> #include <string>
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
FlatPattern pattern("/home/iason/Models/valid_6777.ply"); // FlatPattern pattern("/home/iason/Models/valid_6777.ply");
// FlatPattern pattern("/home/iason/Models/simple_beam_paper_example.ply"); // FlatPattern pattern("/home/iason/Models/simple_beam_paper_example.ply");
pattern.createFan();
// pattern.savePly("fannedValid.ply"); // pattern.savePly("fannedValid.ply");
FlatPattern reducedModel("/home/iason/Models/reducedModel.ply");
reducedModel.createFan();
// reducedModel.savePly("fannedReduced.ply"); registerWorldAxes();
// Create reduced models
const std::vector<size_t> numberOfNodesPerSlot{1, 0, 0, 2, 1, 2, 1};
std::vector<vcg::Point2i> singleBarReducedModelEdges{vcg::Point2i(0, 3)};
FlatPattern singleBarReducedModel(numberOfNodesPerSlot,
singleBarReducedModelEdges);
singleBarReducedModel.setLabel("Single bar reduced model");
std::unordered_map<VertexIndex, VertexIndex> reducedToFullViMap{ std::vector<vcg::Point2i> CCWreducedModelEdges{vcg::Point2i(1, 5),
{1, 3}, {2, 7}, {3, 11}, {4, 15}, {5, 19}, {6, 23}}; vcg::Point2i(3, 5)};
ReducedModelOptimizer optimizer(pattern, reducedModel, reducedToFullViMap, FlatPattern CWReducedModel(numberOfNodesPerSlot, CCWreducedModelEdges);
{}); // 6 CWReducedModel.setLabel("CW reduced model");
// fan reduced model
// {{1, 3}, {2, 15}}, {}); // 2 fan reduced model std::vector<vcg::Point2i> CWreducedModelEdges{vcg::Point2i(1, 5),
vcg::Point2i(3, 1)};
FlatPattern CCWReducedModel(numberOfNodesPerSlot, CWreducedModelEdges);
CCWReducedModel.setLabel("CCW reduced model");
std::vector<FlatPattern *> reducedModels{&singleBarReducedModel,
&CWReducedModel, &CCWReducedModel};
ReducedModelOptimizer optimizer(numberOfNodesPerSlot);
std::string fullPatternsTestSetDirectory =
"/home/iason/Models/TestSet_validPatterns";
for (const auto &entry :
filesystem::directory_iterator(fullPatternsTestSetDirectory)) {
const auto filepath =
// entry.path();
std::filesystem::path("/home/iason/Models/valid_6777.ply");
const auto filepathString = filepath.string();
// Use only the base triangle version
const std::string tiledSuffix = "_tiled.ply";
if (filepathString.compare(filepathString.size() - tiledSuffix.size(),
tiledSuffix.size(), tiledSuffix) == 0) {
continue;
}
FlatPattern pattern(filepathString);
pattern.setLabel(filepath.stem().string());
std::cout << "Testing Pattern:" << filepathString << std::endl;
for (FlatPattern *pReducedModel : reducedModels) {
pReducedModel = reducedModels[0];
std::unordered_set<size_t> optimizationExcludedEi;
if (pReducedModel !=
reducedModels[0]) { // assumes that the singleBar reduced model is the
// first in the reducedModels vector
optimizationExcludedEi.insert(0);
}
optimizer.initialize(pattern, *pReducedModel, optimizationExcludedEi);
optimizer.initialize(pattern, *pReducedModel, optimizationExcludedEi);
Eigen::VectorXd optimalParameters = optimizer.optimize(); Eigen::VectorXd optimalParameters = optimizer.optimize();
}
}
// Full model simulation // // Full model simulation
std::unordered_map<VertexIndex, std::unordered_set<DoFType>> fixedVertices; // std::unordered_map<VertexIndex, std::unordered_set<DoFType>>
// fixedVertices[0] = std::unordered_set<DoFType>{0, 1, 2, 3, 4, 5}; // fixedVertices;
fixedVertices[3] = std::unordered_set<DoFType>{0, 1, 2, 3, 4, 5}; // // fixedVertices[0] = std::unordered_set<DoFType>{0, 1, 2, 3, 4, 5};
// fixedVertices[7] = std::unordered_set<DoFType>{0, 1, 2}; // fixedVertices[3] = std::unordered_set<DoFType>{0, 1, 2, 3, 4, 5};
std::unordered_map<VertexIndex, Vector6d> nodalForces{ // // fixedVertices[7] = std::unordered_set<DoFType>{0, 1, 2};
{15, {0, 0, 2000, 0, 0, 0}}}; // std::unordered_map<VertexIndex, Vector6d> nodalForces{
SimulationJob fullModelSimulationJob{ // {15, {0, 0, 2000, 0, 0, 0}}};
std::make_shared<ElementalMesh>(pattern), fixedVertices, nodalForces, {}}; // SimulationJob fullModelSimulationJob{
Simulator formFinder; // std::make_shared<ElementalMesh>(pattern), fixedVertices, nodalForces,
SimulationResults fullModelResults = // {}};
formFinder.executeSimulation(fullModelSimulationJob); // Simulator formFinder;
fullModelResults.simulationLabel = "Full Model"; // SimulationResults fullModelResults =
fullModelResults.draw(fullModelSimulationJob); // formFinder.executeSimulation(fullModelSimulationJob);
// fullModelResults.simulationLabel = "Full Model";
// fullModelResults.draw(fullModelSimulationJob);
// fullModelSimulationJob.draw(); // fullModelSimulationJob.draw();
// double stiffnessFactor = 1; // double stiffnessFactor = 1;

View File

@ -1,19 +1,24 @@
#include "reducedmodeloptimizer.hpp" #include "reducedmodeloptimizer.hpp"
#include "bobyqa.h" #include "bobyqa.h"
#include "flatpattern.hpp"
#include "gradientDescent.h" #include "gradientDescent.h"
#include "matplot/matplot.h" #include "matplot/matplot.h"
#include "simulationhistoryplotter.hpp" #include "simulationhistoryplotter.hpp"
#include "trianglepattterntopology.hpp"
const bool draw = true; const bool gShouldDraw = true;
size_t numberOfOptimizationRounds{0}; size_t g_numberOfOptimizationRounds{0};
Simulator simulator; FormFinder simulator;
Eigen::MatrixX3d optimalReducedModelDisplacements; Eigen::MatrixX3d g_optimalReducedModelDisplacements;
SimulationJob reducedModelSimulationJob; SimulationJob gReducedPatternSimulationJob;
std::unordered_map<ReducedModelVertexIndex, FullModelVertexIndex> std::unordered_map<ReducedModelVertexIndex, FullModelVertexIndex>
reducedToFullVertexIndexMap; g_reducedToFullInterfaceViMap;
matplot::line_handle plotHandle; matplot::line_handle gPlotHandle;
std::vector<double> fValueHistory; std::vector<double> gObjectiveValueHistory;
Eigen::Vector4d initialParameters; Eigen::Vector4d g_initialX;
std::unordered_set<size_t> g_reducedPatternExludedEdges;
Eigen::MatrixX4d g_initialStiffnessFactors;
struct OptimizationCallback { struct OptimizationCallback {
double operator()(const size_t &iterations, const Eigen::VectorXd &x, double operator()(const size_t &iterations, const Eigen::VectorXd &x,
const double &fval, Eigen::VectorXd &gradient) const { const double &fval, Eigen::VectorXd &gradient) const {
@ -21,10 +26,10 @@ struct OptimizationCallback {
// SimulationResults reducedModelResults = // SimulationResults reducedModelResults =
// simulator.executeSimulation(reducedModelSimulationJob); // simulator.executeSimulation(reducedModelSimulationJob);
// reducedModelResults.draw(reducedModelSimulationJob); // reducedModelResults.draw(reducedModelSimulationJob);
fValueHistory.push_back(fval); gObjectiveValueHistory.push_back(fval);
auto xPlot = auto xPlot = matplot::linspace(0, gObjectiveValueHistory.size(),
matplot::linspace(0, fValueHistory.size(), fValueHistory.size()); gObjectiveValueHistory.size());
plotHandle = matplot::scatter(xPlot, fValueHistory); gPlotHandle = matplot::scatter(xPlot, gObjectiveValueHistory);
// const std::string plotImageFilename = "objectivePlot.png"; // const std::string plotImageFilename = "objectivePlot.png";
// matplot::save(plotImageFilename); // matplot::save(plotImageFilename);
// if (numberOfOptimizationRounds % 30 == 0) { // if (numberOfOptimizationRounds % 30 == 0) {
@ -50,24 +55,21 @@ struct Objective {
// drawSimulationJob(simulationJob); // drawSimulationJob(simulationJob);
// Set mesh from x // Set mesh from x
std::shared_ptr<ElementalMesh> reducedModel = std::shared_ptr<SimulationMesh> reducedModel =
reducedModelSimulationJob.mesh; gReducedPatternSimulationJob.mesh;
for (EdgeIndex ei = 0; ei < reducedModel->EN(); ei++) { for (EdgeIndex ei = 0; ei < reducedModel->EN(); ei++) {
BeamFormFinder::Element &e = reducedModel->elements[ei]; if (g_reducedPatternExludedEdges.contains(ei)) {
e.properties.A = initialParameters(0) * x(0); continue;
e.properties.J = initialParameters(1) * x(1); }
e.properties.I2 = initialParameters(2) * x(2); Element &e = reducedModel->elements[ei];
e.properties.I3 = initialParameters(3) * x(3); e.axialConstFactor *= x(0);
e.axialConstFactor = e.properties.E * e.properties.A / e.initialLength; e.torsionConstFactor *= x(1);
e.torsionConstFactor = e.properties.G * e.properties.J / e.initialLength; e.firstBendingConstFactor *= x(2);
e.firstBendingConstFactor = e.secondBendingConstFactor *= x(3);
2 * e.properties.E * e.properties.I2 / e.initialLength;
e.secondBendingConstFactor =
2 * e.properties.E * e.properties.I3 / e.initialLength;
} }
// run simulation // run simulation
SimulationResults reducedModelResults = SimulationResults reducedModelResults =
simulator.executeSimulation(reducedModelSimulationJob); simulator.executeSimulation(gReducedPatternSimulationJob);
// std::stringstream ss; // std::stringstream ss;
// ss << x; // ss << x;
// reducedModelResults.simulationLabel = ss.str(); // reducedModelResults.simulationLabel = ss.str();
@ -77,7 +79,7 @@ struct Objective {
// std::filesystem::current_path().append("Results")); // std::filesystem::current_path().append("Results"));
// compute error and return it // compute error and return it
double error = 0; double error = 0;
for (const auto reducedFullViPair : reducedToFullVertexIndexMap) { for (const auto reducedFullViPair : g_reducedToFullInterfaceViMap) {
VertexIndex reducedModelVi = reducedFullViPair.first; VertexIndex reducedModelVi = reducedFullViPair.first;
Eigen::Vector3d vertexDisplacement( Eigen::Vector3d vertexDisplacement(
reducedModelResults.displacements[reducedModelVi][0], reducedModelResults.displacements[reducedModelVi][0],
@ -85,7 +87,7 @@ struct Objective {
reducedModelResults.displacements[reducedModelVi][2]); reducedModelResults.displacements[reducedModelVi][2]);
Eigen::Vector3d errorVector = Eigen::Vector3d errorVector =
Eigen::Vector3d( Eigen::Vector3d(
optimalReducedModelDisplacements.row(reducedModelVi)) - g_optimalReducedModelDisplacements.row(reducedModelVi)) -
vertexDisplacement; vertexDisplacement;
error += errorVector.norm(); error += errorVector.norm();
} }
@ -99,76 +101,217 @@ double objective(long n, const double *x) {
for (size_t xi = 0; xi < n; xi++) { for (size_t xi = 0; xi < n; xi++) {
eigenX(xi) = x[xi]; eigenX(xi) = x[xi];
} }
// Eigen::VectorXd emptyGradient;
// return operator()(eigenX, emptyGradient);
// drawSimulationJob(simulationJob); std::shared_ptr<SimulationMesh> reducedPattern =
// Set mesh from x gReducedPatternSimulationJob.mesh;
std::shared_ptr<ElementalMesh> reducedModel = reducedModelSimulationJob.mesh; for (EdgeIndex ei = 0; ei < reducedPattern->EN(); ei++) {
for (EdgeIndex ei = 0; ei < reducedModel->EN(); ei++) { Element &e = reducedPattern->elements[ei];
BeamFormFinder::Element &e = reducedModel->elements[ei]; if (g_reducedPatternExludedEdges.contains(ei)) {
e.properties.A = initialParameters(0) * eigenX(0); continue;
e.properties.J = initialParameters(1) * eigenX(1); }
e.properties.I2 = initialParameters(2) * eigenX(2); e.axialConstFactor = g_initialStiffnessFactors(ei, 0) * eigenX(0);
e.properties.I3 = initialParameters(3) * eigenX(3); e.torsionConstFactor = g_initialStiffnessFactors(ei, 1) * eigenX(1);
e.axialConstFactor = e.properties.E * e.properties.A / e.initialLength; e.firstBendingConstFactor = g_initialStiffnessFactors(ei, 2) * eigenX(2);
e.torsionConstFactor = e.properties.G * e.properties.J / e.initialLength; e.secondBendingConstFactor = g_initialStiffnessFactors(ei, 3) * eigenX(3);
e.firstBendingConstFactor =
2 * e.properties.E * e.properties.I2 / e.initialLength;
e.secondBendingConstFactor =
2 * e.properties.E * e.properties.I3 / e.initialLength;
} }
// run simulation // run simulation
SimulationResults reducedModelResults = SimulationResults reducedModelResults =
simulator.executeSimulation(reducedModelSimulationJob); simulator.executeSimulation(gReducedPatternSimulationJob, false, false);
// std::stringstream ss;
// ss << x;
// reducedModelResults.simulationLabel = ss.str();
// SimulationResultsReporter resultsReporter;
// resultsReporter.reportResults(
// {reducedModelResults},
// std::filesystem::current_path().append("Results"));
// compute error and return it // compute error and return it
double error = 0; double error = 0;
for (const auto reducedFullViPair : reducedToFullVertexIndexMap) { for (const auto reducedFullViPair : g_reducedToFullInterfaceViMap) {
VertexIndex reducedModelVi = reducedFullViPair.first; VertexIndex reducedModelVi = reducedFullViPair.first;
Eigen::Vector3d vertexDisplacement( Eigen::Vector3d vertexDisplacement(
reducedModelResults.displacements[reducedModelVi][0], reducedModelResults.displacements[reducedModelVi][0],
reducedModelResults.displacements[reducedModelVi][1], reducedModelResults.displacements[reducedModelVi][1],
reducedModelResults.displacements[reducedModelVi][2]); reducedModelResults.displacements[reducedModelVi][2]);
Eigen::Vector3d errorVector = Eigen::Vector3d errorVector =
Eigen::Vector3d(optimalReducedModelDisplacements.row(reducedModelVi)) - Eigen::Vector3d(
g_optimalReducedModelDisplacements.row(reducedModelVi)) -
vertexDisplacement; vertexDisplacement;
error += errorVector.norm(); error += errorVector.norm();
} }
gObjectiveValueHistory.push_back(error);
auto xPlot = matplot::linspace(0, gObjectiveValueHistory.size(),
gObjectiveValueHistory.size());
gPlotHandle = matplot::scatter(xPlot, gObjectiveValueHistory);
return error; return error;
} }
void ReducedModelOptimizer::computeMaps(
FlatPattern &fullPattern, FlatPattern &reducedPattern,
const std::unordered_set<size_t> &reducedModelExcludedEges) {
// 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());
vcg::tri::Allocator<FlatPattern>::PointerUpdater<FlatPattern::VertexPointer>
pu_fullModel;
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
g_reducedPatternExludedEdges.clear();
const size_t fanSize = 6;
const size_t reducedBaseTriangleNumberOfEdges = reducedPattern.EN();
for (size_t fanIndex = 0; fanIndex < fanSize; fanIndex++) {
for (const size_t ei : reducedModelExcludedEges) {
g_reducedPatternExludedEdges.insert(
fanIndex * reducedBaseTriangleNumberOfEdges + ei);
}
}
// Construct reduced->full and full->reduced interface vi map
g_reducedToFullInterfaceViMap.clear();
vcg::tri::Allocator<FlatPattern>::PointerUpdater<FlatPattern::VertexPointer>
pu_reducedModel;
reducedPattern.deleteDanglingVertices(pu_reducedModel);
const size_t reducedModelBaseTriangleInterfaceVi =
pu_reducedModel.remap[baseTriangleInterfaceVi];
const size_t reducedModelInterfaceVertexOffset =
reducedPattern.VN() - 1 /*- reducedModelBaseTriangleInterfaceVi*/;
reducedPattern.createFan();
for (size_t fanIndex = 0; fanIndex < fanSize; fanIndex++) {
g_reducedToFullInterfaceViMap[reducedModelInterfaceVertexOffset * fanIndex +
reducedModelBaseTriangleInterfaceVi] =
fullModelBaseTriangleInterfaceVi +
fanIndex * fullPatternInterfaceVertexOffset;
}
m_fullToReducedInterfaceViMap.clear();
constructInverseMap(g_reducedToFullInterfaceViMap,
m_fullToReducedInterfaceViMap);
// fullPattern.setLabel("FullPattern");
// reducedPattern.setLabel("ReducedPattern");
// Create opposite vertex map
m_fullPatternOppositeInterfaceViMap.clear();
for (size_t fanIndex = 0; fanIndex < fanSize / 2; fanIndex++) {
const size_t vi0 = fullModelBaseTriangleInterfaceVi +
fanIndex * fullPatternInterfaceVertexOffset;
const size_t vi1 = vi0 + (fanSize / 2) * fullPatternInterfaceVertexOffset;
assert(vi0 < fullPattern.VN() && vi1 < fullPattern.VN());
m_fullPatternOppositeInterfaceViMap[vi0] = vi1;
}
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 : g_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));
for (const std::pair<size_t, size_t> oppositeVerts :
m_fullPatternOppositeInterfaceViMap) {
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 (g_reducedToFullInterfaceViMap.contains(vi)) {
auto color = polyscope::getNextUniqueColor();
nodeColorsReducedToFull_reduced[vi] = color;
nodeColorsReducedToFull_full[g_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();
}
}
void ReducedModelOptimizer::createSimulationMeshes(FlatPattern &fullModel,
FlatPattern &reducedModel) {
pReducedModelElementalMesh = std::make_shared<SimulationMesh>(reducedModel);
pFullModelElementalMesh = std::make_shared<SimulationMesh>(fullModel);
}
ReducedModelOptimizer::ReducedModelOptimizer( ReducedModelOptimizer::ReducedModelOptimizer(
ConstVCGEdgeMesh &fullModel, ConstVCGEdgeMesh &reducedModel, const std::vector<size_t> &numberOfNodesPerSlot) {
const std::unordered_map<ReducedModelVertexIndex, FullModelVertexIndex> FlatPatternTopology::constructNodeToSlotMap(numberOfNodesPerSlot, nodeToSlot);
&viMap, FlatPatternTopology::constructSlotToNodeMap(nodeToSlot, slotToNode);
const std::vector<std::pair<ReducedModelVertexIndex, }
ReducedModelVertexIndex>> &oppositeVertices)
: reducedToFullViMap(viMap) {
reducedToFullVertexIndexMap = viMap;
// construct fullToReducedViMap void ReducedModelOptimizer::initialize(
for (const std::pair<ReducedModelVertexIndex, FullModelVertexIndex> &viPair : FlatPattern &fullPattern, FlatPattern &reducedPattern,
viMap) { const std::unordered_set<size_t> &reducedModelExcludedEdges) {
fullToReducedViMap[viPair.second] = viPair.first; assert(fullPattern.VN() == reducedPattern.VN() &&
fullPattern.EN() > reducedPattern.EN());
polyscope::removeAllStructures();
// Create copies of the input models
FlatPattern copyFullPattern;
FlatPattern copyReducedPattern;
copyFullPattern.copy(fullPattern);
copyReducedPattern.copy(reducedPattern);
computeMaps(copyFullPattern, copyReducedPattern, reducedModelExcludedEdges);
createSimulationMeshes(copyFullPattern, copyReducedPattern);
initializeStiffnesses();
int i = 0;
i++;
}
void ReducedModelOptimizer::initializeStiffnesses() {
g_initialStiffnessFactors.resize(pReducedModelElementalMesh->EN(), 4);
// Save save the beam stiffnesses
for (size_t ei = 0; ei < pReducedModelElementalMesh->EN(); ei++) {
Element &e = pReducedModelElementalMesh->elements[ei];
// if (g_reducedPatternExludedEdges.contains(ei)) {
// const double stiffnessFactor = 1;
// e.axialConstFactor *= stiffnessFactor;
// e.torsionConstFactor *= stiffnessFactor;
// e.firstBendingConstFactor *= stiffnessFactor;
// e.secondBendingConstFactor *= stiffnessFactor;
// }
g_initialStiffnessFactors(ei, 0) = e.axialConstFactor;
g_initialStiffnessFactors(ei, 1) = e.torsionConstFactor;
g_initialStiffnessFactors(ei, 2) = e.firstBendingConstFactor;
g_initialStiffnessFactors(ei, 3) = e.secondBendingConstFactor;
} }
// construct opposite vertex map
for (const std::pair<VertexIndex, VertexIndex> &viPair : oppositeVertices) {
oppositeVertexMap[viPair.first] = viPair.second;
oppositeVertexMap[viPair.second] = viPair.first;
}
reducedModelElementalMesh = std::make_shared<ElementalMesh>(reducedModel);
pFullModelElementalMesh = std::make_shared<ElementalMesh>(fullModel);
optimalReducedModelDisplacements.resize(reducedModelElementalMesh->VN(), 3);
} }
void ReducedModelOptimizer::computeReducedModelSimulationJob( void ReducedModelOptimizer::computeReducedModelSimulationJob(
@ -177,18 +320,18 @@ void ReducedModelOptimizer::computeReducedModelSimulationJob(
std::unordered_map<VertexIndex, std::unordered_set<DoFType>> std::unordered_map<VertexIndex, std::unordered_set<DoFType>>
reducedModelFixedVertices; reducedModelFixedVertices;
for (auto fullModelFixedVertex : simulationJobOfFullModel.fixedVertices) { for (auto fullModelFixedVertex : simulationJobOfFullModel.fixedVertices) {
reducedModelFixedVertices[fullToReducedViMap.at( reducedModelFixedVertices[m_fullToReducedInterfaceViMap.at(
fullModelFixedVertex.first)] = fullModelFixedVertex.second; fullModelFixedVertex.first)] = fullModelFixedVertex.second;
} }
std::unordered_map<VertexIndex, Vector6d> reducedModelNodalForces; std::unordered_map<VertexIndex, Vector6d> reducedModelNodalForces;
for (auto fullModelNodalForce : for (auto fullModelNodalForce :
simulationJobOfFullModel.nodalExternalForces) { simulationJobOfFullModel.nodalExternalForces) {
reducedModelNodalForces[fullToReducedViMap.at(fullModelNodalForce.first)] = reducedModelNodalForces[m_fullToReducedInterfaceViMap.at(
fullModelNodalForce.second; fullModelNodalForce.first)] = fullModelNodalForce.second;
} }
simulationJobOfReducedModel = SimulationJob{reducedModelElementalMesh, simulationJobOfReducedModel = SimulationJob{pReducedModelElementalMesh,
reducedModelFixedVertices, reducedModelFixedVertices,
reducedModelNodalForces, reducedModelNodalForces,
{}}; {}};
@ -204,12 +347,19 @@ SimulationJob ReducedModelOptimizer::getReducedSimulationJob(
void ReducedModelOptimizer::computeDesiredReducedModelDisplacements( void ReducedModelOptimizer::computeDesiredReducedModelDisplacements(
const SimulationResults &fullModelResults, const SimulationResults &fullModelResults,
Eigen::MatrixX3d &optimaldisplacementsOfReducedModel) { Eigen::MatrixX3d &optimalDisplacementsOfReducedModel) {
for (auto reducedFullViPair : reducedToFullVertexIndexMap) {
optimalDisplacementsOfReducedModel.resize(pReducedModelElementalMesh->VN(),
3);
optimalDisplacementsOfReducedModel.setZero(
optimalDisplacementsOfReducedModel.rows(),
optimalDisplacementsOfReducedModel.cols());
for (auto reducedFullViPair : g_reducedToFullInterfaceViMap) {
const VertexIndex fullModelVi = reducedFullViPair.second; const VertexIndex fullModelVi = reducedFullViPair.second;
Vector6d fullModelViDisplacements = const Vector6d fullModelViDisplacements =
fullModelResults.displacements[fullModelVi]; fullModelResults.displacements[fullModelVi];
optimaldisplacementsOfReducedModel.row(reducedFullViPair.first) = optimalDisplacementsOfReducedModel.row(reducedFullViPair.first) =
Eigen::Vector3d(fullModelViDisplacements[0], Eigen::Vector3d(fullModelViDisplacements[0],
fullModelViDisplacements[1], fullModelViDisplacements[1],
fullModelViDisplacements[2]); fullModelViDisplacements[2]);
@ -218,27 +368,25 @@ void ReducedModelOptimizer::computeDesiredReducedModelDisplacements(
Eigen::VectorXd ReducedModelOptimizer::optimizeForSimulationJob( Eigen::VectorXd ReducedModelOptimizer::optimizeForSimulationJob(
const SimulationJob &fullModelSimulationJob) { const SimulationJob &fullModelSimulationJob) {
gObjectiveValueHistory.clear();
SimulationResults fullModelResults = SimulationResults fullModelResults =
simulator.executeSimulation(fullModelSimulationJob, false, false); simulator.executeSimulation(fullModelSimulationJob, false, false);
fullModelResults.simulationLabel = "fullModel"; fullModelResults.simulationLabel = "fullModel";
if (draw) {
drawWorldAxes();
fullModelResults.draw(fullModelSimulationJob);
}
computeDesiredReducedModelDisplacements(fullModelResults, computeDesiredReducedModelDisplacements(fullModelResults,
optimalReducedModelDisplacements); g_optimalReducedModelDisplacements);
computeReducedModelSimulationJob(fullModelSimulationJob, computeReducedModelSimulationJob(fullModelSimulationJob,
reducedModelSimulationJob); gReducedPatternSimulationJob);
// fullModelSimulationJob.registerForDrawing();
// polyscope::show();
// gReducedPatternSimulationJob.registerForDrawing();
// polyscope::show();
fullModelResults.registerForDrawing(fullModelSimulationJob);
polyscope::show();
// Set initial guess of solution // Set initial guess of solution
Eigen::VectorXd initialGuess(4); Eigen::VectorXd initialGuess(4);
auto propertiesOfFirstBeamOfFullModel = const double stifnessFactor = 1;
pFullModelElementalMesh->elements[0].properties;
initialParameters(0) = propertiesOfFirstBeamOfFullModel.A;
initialParameters(1) = propertiesOfFirstBeamOfFullModel.J;
initialParameters(2) = propertiesOfFirstBeamOfFullModel.I2;
initialParameters(3) = propertiesOfFirstBeamOfFullModel.I3;
const double stifnessFactor = 2;
initialGuess(0) = stifnessFactor; initialGuess(0) = stifnessFactor;
initialGuess(1) = stifnessFactor; initialGuess(1) = stifnessFactor;
initialGuess(2) = stifnessFactor; initialGuess(2) = stifnessFactor;
@ -282,9 +430,10 @@ Eigen::VectorXd ReducedModelOptimizer::optimizeForSimulationJob(
std::cout << "Final xval: " << result.xval.transpose() << std::endl; std::cout << "Final xval: " << result.xval.transpose() << std::endl;
SimulationResults reducedModelOptimizedResults = SimulationResults reducedModelOptimizedResults =
simulator.executeSimulation(reducedModelSimulationJob); simulator.executeSimulation(gReducedPatternSimulationJob);
reducedModelOptimizedResults.simulationLabel = "reducedModel"; reducedModelOptimizedResults.simulationLabel = "reducedModel";
reducedModelOptimizedResults.draw(reducedModelSimulationJob); reducedModelOptimizedResults.registerForDrawing(
gReducedPatternSimulationJob);
return result.xval; return result.xval;
} else { // use bobyqa } else { // use bobyqa
@ -294,8 +443,9 @@ Eigen::VectorXd ReducedModelOptimizer::optimizeForSimulationJob(
assert(npt <= (n + 1) * (n + 2) / 2 && npt >= n + 2); assert(npt <= (n + 1) * (n + 2) / 2 && npt >= n + 2);
assert(npt < 2 * n + 1 && "The choice of the number of interpolation " assert(npt < 2 * n + 1 && "The choice of the number of interpolation "
"conditions is not recommended."); "conditions is not recommended.");
std::vector<double> x{initialGuess(0), initialGuess(1), initialGuess(2), std::vector<double> x
initialGuess(3)}; // {1.03424, 0.998456, 0.619916, -0.202997};
{initialGuess(0), initialGuess(1), initialGuess(2), initialGuess(3)};
std::vector<double> xLow(x.size(), -100); std::vector<double> xLow(x.size(), -100);
std::vector<double> xUpper(x.size(), 100); std::vector<double> xUpper(x.size(), 100);
const double maxX = *std::max_element( const double maxX = *std::max_element(
@ -318,81 +468,147 @@ Eigen::VectorXd ReducedModelOptimizer::optimizeForSimulationJob(
} }
SimulationResults reducedModelOptimizedResults = SimulationResults reducedModelOptimizedResults =
simulator.executeSimulation(reducedModelSimulationJob); simulator.executeSimulation(gReducedPatternSimulationJob);
reducedModelOptimizedResults.simulationLabel = "reducedModel"; reducedModelOptimizedResults.simulationLabel = "reducedModel";
reducedModelOptimizedResults.draw(reducedModelSimulationJob); reducedModelOptimizedResults.registerForDrawing(
gReducedPatternSimulationJob);
polyscope::show();
return eigenX; return eigenX;
} }
} }
std::vector<SimulationJob> ReducedModelOptimizer::createScenarios( std::vector<SimulationJob> ReducedModelOptimizer::createScenarios(
const std::shared_ptr<ElementalMesh> &pMesh) { const std::shared_ptr<SimulationMesh> &pMesh) {
std::vector<SimulationJob> scenarios; std::vector<SimulationJob> scenarios;
// Pull up std::unordered_map<VertexIndex, std::unordered_set<DoFType>> fixedVertices;
////1Vertex std::unordered_map<VertexIndex, Vector6d> nodalForces;
std::unordered_map<VertexIndex, std::unordered_set<DoFType>> const double forceMagnitude = 250;
pullUp1_FixedVertices;
pullUp1_FixedVertices[3] = std::unordered_set<DoFType>{0, 1, 2, 3, 4, 5};
std::unordered_map<VertexIndex, Vector6d> pullUp1_NodalForces{
{15, {0, 0, 100, 0, 0, 0}}};
scenarios.push_back({pMesh, pullUp1_FixedVertices, pullUp1_NodalForces, {}});
// /// 2Vertices // // Axial
// std::unordered_map<VertexIndex, std::unordered_set<DoFType>> // for (const auto &viPair : m_fullPatternOppositeInterfaceViMap) {
// pullUp1_FixedVertices; // CoordType forceDirection =
// saddleFixedVertices[3] = std::unordered_set<DoFType>{0, 1, 2}; // (pMesh->vert[viPair.first].cP() - pMesh->vert[viPair.second].cP())
// saddleFixedVertices[7] = std::unordered_set<DoFType>{0, 1, 2}; // .Normalize();
// std::unordered_map<VertexIndex, Vector6d> pullUp1_NodalForces{ // nodalForces[viPair.first] = Vector6d({forceDirection[0],
// {15, {0, 0, 0, 0, -900, 0}}, {3, {0, 0, 0, 0, 900, 0}}, // forceDirection[1],
// {7, {0, 0, 0, 700, 0, 0}}, {11, {0, 0, 0, 700, 0, 0}}, // forceDirection[2], 0, 0, 0}) *
// {19, {0, 0, 0, -700, 0, 0}}, {23, {0, 0, 0, -700, 0, 0}}}; // forceMagnitude;
// scenarios.push_back({pMesh, pullUp1_FixedVertices, pullUp1_NodalForces, // fixedVertices[viPair.second] =
// {}}); // std::unordered_set<DoFType>{0, 1, 2, 3, 4, 5};
// }
/// 3Vertices // scenarios.push_back({pMesh, fixedVertices, nodalForces, {}});
// std::unordered_map<VertexIndex, std::unordered_set<DoFType>>
// pullUp1_FixedVertices; // // In-plane Bending
// saddleFixedVertices[3] = std::unordered_set<DoFType>{0, 1, 2}; // // Assuming the patterns lay on the x-y plane
// saddleFixedVertices[7] = std::unordered_set<DoFType>{0, 1, 2}; // const CoordType patternPlane(0, 0, 1);
// saddleFixedVertices[11] = std::unordered_set<DoFType>{0, 1, 2}; // fixedVertices.clear();
// saddleFixedVertices[15] = std::unordered_set<DoFType>{0, 1, 2}; // nodalForces.clear();
// saddleFixedVertices[19] = std::unordered_set<DoFType>{0, 1, 2}; // for (const auto &viPair : m_fullPatternOppositeInterfaceViMap) {
// saddleFixedVertices[23] = std::unordered_set<DoFType>{0, 1, 2}; // CoordType v =
// std::unordered_map<VertexIndex, Vector6d> pullUp1_NodalForces{ // (pMesh->vert[viPair.first].cP() - pMesh->vert[viPair.second].cP())
// {15, {0, 0, 0, 0, -900, 0}}, {3, {0, 0, 0, 0, 900, 0}}, // .Normalize();
// {7, {0, 0, 0, 700, 0, 0}}, {11, {0, 0, 0, 700, 0, 0}}, // CoordType forceDirection = patternPlane ^ v;
// {19, {0, 0, 0, -700, 0, 0}}, {23, {0, 0, 0, -700, 0, 0}}}; // nodalForces[viPair.first] = Vector6d({forceDirection[0],
// scenarios.push_back({pMesh, pullUp1_FixedVertices, pullUp1_NodalForces, // forceDirection[1],
// {}}); // forceDirection[2], 0, 0, 0}) *
// forceMagnitude;
// Single moment // fixedVertices[viPair.second] =
// std::unordered_map<VertexIndex, std::unordered_set<DoFType>> // std::unordered_set<DoFType>{0, 1, 2, 3, 4, 5};
// fixedVertices; fixedVertices[3] = std::unordered_set<DoFType>{0, 1, 2, 3, // }
// 4, 5}; fixedVertices[15] = std::unordered_set<DoFType>{0, 1, 2}; // scenarios.push_back({pMesh, fixedVertices, nodalForces, {}});
// std::unordered_map<VertexIndex, Vector6d> nodalForces{
// {15, {0, 0, 0, 0, 700, 0}}}; // // Torsion
// scenarios.push_back({pMesh, saddleFixedVertices, saddleNodalForces, {}}); // {
// fixedVertices.clear();
// nodalForces.clear();
// for (auto viPairIt = m_fullPatternOppositeInterfaceViMap.begin();
// viPairIt != m_fullPatternOppositeInterfaceViMap.end(); viPairIt++)
// {
// const auto &viPair = *viPairIt;
// if (viPairIt == m_fullPatternOppositeInterfaceViMap.begin()) {
// CoordType v =
// (pMesh->vert[viPair.first].cP() -
// pMesh->vert[viPair.second].cP())
// .Normalize();
// nodalForces[viPair.first] =
// Vector6d({0, 0, 0, v[1], v[0], 0}) * forceMagnitude;
// } else {
// fixedVertices[viPair.first] =
// std::unordered_set<DoFType>{0, 1, 2, 3, 4, 5};
// }
// fixedVertices[viPair.second] =
// std::unordered_set<DoFType>{0, 1, 2, 3, 4, 5};
// }
// scenarios.push_back({pMesh, fixedVertices, nodalForces, {}});
// }
// Out-of-plane bending . Pull towards Z
fixedVertices.clear();
nodalForces.clear();
for (const auto &viPair : m_fullPatternOppositeInterfaceViMap) {
nodalForces[viPair.first] = Vector6d({0, 0, forceMagnitude, 0, 0, 0});
fixedVertices[viPair.second] =
std::unordered_set<DoFType>{0, 1, 2, 3, 4, 5};
}
scenarios.push_back({pMesh, fixedVertices, nodalForces, {}});
// // Dou??
// fixedVertices.clear();
// nodalForces.clear();
// for (const auto &viPair : m_fullPatternOppositeInterfaceViMap) {
// CoordType v =
// (pMesh->vert[viPair.first].cP() - pMesh->vert[viPair.second].cP())
// .Normalize();
// CoordType momentDirection = patternPlane ^ v;
// nodalForces[viPair.first] =
// Vector6d({0, 0, 0, momentDirection[0], momentDirection[1], 0}) *
// forceMagnitude;
// fixedVertices[viPair.first] = std::unordered_set<DoFType>{2};
// fixedVertices[viPair.second] = std::unordered_set<DoFType>{0, 1, 2};
// }
// scenarios.push_back({pMesh, fixedVertices, nodalForces, {}});
// // Saddle
// fixedVertices.clear();
// nodalForces.clear();
// for (auto viPairIt = m_fullPatternOppositeInterfaceViMap.begin();
// viPairIt != m_fullPatternOppositeInterfaceViMap.end(); viPairIt++) {
// const auto &viPair = *viPairIt;
// CoordType v =
// (pMesh->vert[viPair.first].cP() - pMesh->vert[viPair.second].cP())
// .Normalize();
// CoordType momentDirection = patternPlane ^ v;
// if (viPairIt == m_fullPatternOppositeInterfaceViMap.begin()) {
// nodalForces[viPair.first] =
// Vector6d({0, 0, 0, momentDirection[0], momentDirection[1], 0}) * 3
// * forceMagnitude;
// nodalForces[viPair.second] =
// Vector6d({0, 0, 0, momentDirection[0], momentDirection[1], 0}) * 3
// *
// (-forceMagnitude);
// } else {
// fixedVertices[viPair.first] = std::unordered_set<DoFType>{2};
// nodalForces[viPair.first] =
// Vector6d({0, 0, 0, momentDirection[0], momentDirection[1], 0}) *
// (-forceMagnitude);
// fixedVertices[viPair.second] = std::unordered_set<DoFType>{0, 1, 2};
// }
// }
// scenarios.push_back({pMesh, fixedVertices, nodalForces, {}}); // scenarios.push_back({pMesh, fixedVertices, nodalForces, {}});
// Saddle
// std::unordered_map<VertexIndex, std::unordered_set<DoFType>> // std::unordered_map<VertexIndex, std::unordered_set<DoFType>>
// saddle_fixedVertices; // saddleFixedVertices;
// // saddle_fixedVertices[3] = std::unordered_set<DoFType>{0, 1, 2}; // // saddle_fixedVertices[3] = std::unordered_set<DoFType>{0, 1, 2};
// saddle_fixedVertices[7] = std::unordered_set<DoFType>{0, 1, 2}; // saddleFixedVertices[7] = std::unordered_set<DoFType>{0, 1, 2};
// saddle_fixedVertices[11] = std::unordered_set<DoFType>{0, 1, 2}; // saddleFixedVertices[11] = std::unordered_set<DoFType>{0, 1, 2};
// // saddle_fixedVertices[15] = std::unordered_set<DoFType>{0, 1, 2}; // // saddle_fixedVertices[15] = std::unordered_set<DoFType>{0, 1, 2};
// // saddle_fixedVertices[19] = std::unordered_set<DoFType>{0, 1, 2}; // // saddle_fixedVertices[19] = std::unordered_set<DoFType>{0, 1, 2};
// // saddle_fixedVertices[23] = std::unordered_set<DoFType>{0, 1, 2}; // // saddle_fixedVertices[23] = std::unordered_set<DoFType>{0, 1, 2};
// std::unordered_map<VertexIndex, Vector6d> saddle_nodalForces{ // std::unordered_map<VertexIndex, Vector6d> saddleNodalForces{
// {15, {0, 0, 0, 0, -1400, 0}}, {3, {0, 0, 0, 0, 1400, 0}}, // {15, {0, 0, 0, 0, -4 * 90, 0}}, {3, {0, 0, 0, 0, 4 * 90, 0}},
// {7, {0, 0, 0, 700, 0, 0}}, {11, {0, 0, 0, 700, 0, 0}}, // {7, {0, 0, 0, 4 * 70, 0, 0}}, {11, {0, 0, 0, 4 * 70, 0, 0}},
// {19, {0, 0, 0, -700, 0, 0}}, {23, {0, 0, 0, -700, 0, 0}}}; // {19, {0, 0, 0, -4 * 70, 0, 0}}, {23, {0, 0, 0, -4 * 70, 0, 0}}};
// // scenarios.push_back({pMesh, saddleFixedVertices, saddleNodalForces, // scenarios.push_back({pMesh, saddleFixedVertices, saddleNodalForces, {}});
// {}}); std::unordered_map<VertexIndex, Eigen::Vector3d>
// saddle_forcedDisplacements; scenarios.push_back({pMesh,
// saddle_fixedVertices, saddle_nodalForces,
// saddle_forcedDisplacements});
return scenarios; return scenarios;
} }
@ -402,7 +618,7 @@ Eigen::VectorXd ReducedModelOptimizer::optimize() {
createScenarios(pFullModelElementalMesh); createScenarios(pFullModelElementalMesh);
std::vector<Eigen::VectorXd> results; std::vector<Eigen::VectorXd> results;
for (const SimulationJob &job : simulationJobs) { for (const SimulationJob &job : simulationJobs) {
// fullModelSimulationJob.draw(); polyscope::removeAllStructures();
auto result = optimizeForSimulationJob(job); auto result = optimizeForSimulationJob(job);
results.push_back(result); results.push_back(result);
} }

View File

@ -9,34 +9,21 @@
using FullModelVertexIndex = VertexIndex; using FullModelVertexIndex = VertexIndex;
using ReducedModelVertexIndex = VertexIndex; using ReducedModelVertexIndex = VertexIndex;
struct SimulationScenarios {
std::vector<SimulationJob> scenarios;
std::shared_ptr<ElementalMesh> pMesh;
SimulationScenarios(std::shared_ptr<ElementalMesh> pMesh) : pMesh(pMesh) {}
std::vector<SimulationJob> getSimulationJobs() const { return scenarios; }
};
class ReducedModelOptimizer { class ReducedModelOptimizer {
std::shared_ptr<ElementalMesh> reducedModelElementalMesh; std::shared_ptr<SimulationMesh> pReducedModelElementalMesh;
std::shared_ptr<ConstElementalMesh> pFullModelElementalMesh; std::shared_ptr<SimulationMesh> pFullModelElementalMesh;
const std::unordered_map<ReducedModelVertexIndex, FullModelVertexIndex>
&reducedToFullViMap;
std::unordered_map<FullModelVertexIndex, ReducedModelVertexIndex> std::unordered_map<FullModelVertexIndex, ReducedModelVertexIndex>
fullToReducedViMap; m_fullToReducedInterfaceViMap;
std::unordered_map<ReducedModelVertexIndex, ReducedModelVertexIndex> std::unordered_map<ReducedModelVertexIndex, ReducedModelVertexIndex>
oppositeVertexMap; m_fullPatternOppositeInterfaceViMap;
std::unordered_map<size_t, size_t> nodeToSlot;
std::unordered_map<size_t, std::unordered_set<size_t>> slotToNode;
public: public:
Eigen::VectorXd optimize(); Eigen::VectorXd optimize();
double operator()(const Eigen::VectorXd &x, Eigen::VectorXd &) const; double operator()(const Eigen::VectorXd &x, Eigen::VectorXd &) const;
ReducedModelOptimizer( ReducedModelOptimizer(const std::vector<size_t> &numberOfNodesPerSlot);
ConstVCGEdgeMesh &fullModel, ConstVCGEdgeMesh &reducedModel,
const std::unordered_map<ReducedModelVertexIndex, FullModelVertexIndex>
&viMap,
const std::vector<std::pair<ReducedModelVertexIndex,
ReducedModelVertexIndex>> &oppositeVertices);
void computeReducedModelSimulationJob( void computeReducedModelSimulationJob(
const SimulationJob &simulationJobOfFullModel, const SimulationJob &simulationJobOfFullModel,
SimulationJob &simulationJobOfReducedModel); SimulationJob &simulationJobOfReducedModel);
@ -44,14 +31,22 @@ public:
SimulationJob SimulationJob
getReducedSimulationJob(const SimulationJob &fullModelSimulationJob); getReducedSimulationJob(const SimulationJob &fullModelSimulationJob);
void initialize(FlatPattern &fullPattern, FlatPattern &reducedPatterm,
const std::unordered_set<size_t> &reducedModelExcludedEges);
private: private:
void computeDesiredReducedModelDisplacements( void computeDesiredReducedModelDisplacements(
const SimulationResults &fullModelResults, const SimulationResults &fullModelResults,
Eigen::MatrixX3d &optimaldisplacementsOfReducedModel); Eigen::MatrixX3d &optimalDisplacementsOfReducedModel);
Eigen::VectorXd Eigen::VectorXd
optimizeForSimulationJob(const SimulationJob &fullModelSimulationJob); optimizeForSimulationJob(const SimulationJob &fullModelSimulationJob);
std::vector<SimulationJob> std::vector<SimulationJob>
createScenarios(const std::shared_ptr<ElementalMesh> &pMesh); createScenarios(const std::shared_ptr<SimulationMesh> &pMesh);
void computeMaps(FlatPattern &fullModel, FlatPattern &reducedPattern,
const std::unordered_set<size_t> &reducedModelExcludedEges);
void createSimulationMeshes(FlatPattern &fullModel,
FlatPattern &reducedModel);
void initializeStiffnesses();
}; };
#endif // REDUCEDMODELOPTIMIZER_HPP #endif // REDUCEDMODELOPTIMIZER_HPP