Added code for exporting pe.gradual application of external forces. average residual forces threshold
This commit is contained in:
parent
992f0fe6ae
commit
2509b0a795
|
|
@ -231,6 +231,7 @@ void DRMSimulationModel::reset()
|
||||||
Dt = mSettings.Dtini;
|
Dt = mSettings.Dtini;
|
||||||
numOfDampings = 0;
|
numOfDampings = 0;
|
||||||
shouldTemporarilyDampForces = false;
|
shouldTemporarilyDampForces = false;
|
||||||
|
externalLoadStep = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
VectorType DRMSimulationModel::computeDisplacementDifferenceDerivative(
|
VectorType DRMSimulationModel::computeDisplacementDifferenceDerivative(
|
||||||
|
|
@ -958,7 +959,6 @@ void DRMSimulationModel::updateResidualForcesOnTheFly(
|
||||||
force.residual = force.external;
|
force.residual = force.external;
|
||||||
force.internal = 0;
|
force.internal = 0;
|
||||||
}
|
}
|
||||||
double totalResidualForcesNorm = 0;
|
|
||||||
for (size_t ei = 0; ei < pMesh->EN(); ei++) {
|
for (size_t ei = 0; ei < pMesh->EN(); ei++) {
|
||||||
for (int i = 0; i < 4; i++) {
|
for (int i = 0; i < 4; i++) {
|
||||||
std::pair<int, Vector6d> internalForcePair
|
std::pair<int, Vector6d> internalForcePair
|
||||||
|
|
@ -972,6 +972,7 @@ void DRMSimulationModel::updateResidualForcesOnTheFly(
|
||||||
force.residual = force.residual + (internalForcePair.second * -1);
|
force.residual = force.residual + (internalForcePair.second * -1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
double totalResidualForcesNorm = 0;
|
||||||
Vector6d sumOfResidualForces(0);
|
Vector6d sumOfResidualForces(0);
|
||||||
for (size_t vi = 0; vi < pMesh->VN(); vi++) {
|
for (size_t vi = 0; vi < pMesh->VN(); vi++) {
|
||||||
Node::Forces &force = pMesh->nodes[vi].force;
|
Node::Forces &force = pMesh->nodes[vi].force;
|
||||||
|
|
@ -984,7 +985,8 @@ void DRMSimulationModel::updateResidualForcesOnTheFly(
|
||||||
}
|
}
|
||||||
pMesh->previousTotalResidualForcesNorm = pMesh->totalResidualForcesNorm;
|
pMesh->previousTotalResidualForcesNorm = pMesh->totalResidualForcesNorm;
|
||||||
pMesh->totalResidualForcesNorm = totalResidualForcesNorm;
|
pMesh->totalResidualForcesNorm = totalResidualForcesNorm;
|
||||||
// mesh->totalResidualForcesNorm = sumOfResidualForces.norm();
|
pMesh->averageResidualForcesNorm = totalResidualForcesNorm / pMesh->VN();
|
||||||
|
// pMesh->averageResidualForcesNorm = sumOfResidualForces.norm() / pMesh->VN();
|
||||||
|
|
||||||
// plotYValues.push_back(totalResidualForcesNorm);
|
// plotYValues.push_back(totalResidualForcesNorm);
|
||||||
// auto xPlot = matplot::linspace(0, plotYValues.size(), plotYValues.size());
|
// auto xPlot = matplot::linspace(0, plotYValues.size(), plotYValues.size());
|
||||||
|
|
@ -1147,7 +1149,7 @@ DRMSimulationModel::DRMSimulationModel() {}
|
||||||
void DRMSimulationModel::updateNodalMasses()
|
void DRMSimulationModel::updateNodalMasses()
|
||||||
{
|
{
|
||||||
double gamma = mSettings.gamma;
|
double gamma = mSettings.gamma;
|
||||||
const size_t untilStep = 500;
|
const size_t untilStep = 4000;
|
||||||
if (shouldTemporarilyDampForces && mCurrentSimulationStep < untilStep) {
|
if (shouldTemporarilyDampForces && mCurrentSimulationStep < untilStep) {
|
||||||
gamma *= 1e6 * (1 - static_cast<double>(mCurrentSimulationStep) / untilStep);
|
gamma *= 1e6 * (1 - static_cast<double>(mCurrentSimulationStep) / untilStep);
|
||||||
}
|
}
|
||||||
|
|
@ -1233,10 +1235,9 @@ void DRMSimulationModel::updateNodalVelocities()
|
||||||
const VertexIndex vi = pMesh->getIndex(v);
|
const VertexIndex vi = pMesh->getIndex(v);
|
||||||
Node &node = pMesh->nodes[v];
|
Node &node = pMesh->nodes[v];
|
||||||
node.velocity = node.velocity + node.acceleration * Dt;
|
node.velocity = node.velocity + node.acceleration * Dt;
|
||||||
// if (vi == 10) {
|
if (std::isnan(node.velocity.norm())) {
|
||||||
// std::cout << "Velocity:" << node.velocity[0] << " " << node.velocity[1] << " "
|
std::cout << "Velocity:" << node.velocity.toString() << std::endl;
|
||||||
// << node.velocity[2] << std::endl;
|
}
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
updateKineticEnergy();
|
updateKineticEnergy();
|
||||||
}
|
}
|
||||||
|
|
@ -1461,7 +1462,7 @@ void DRMSimulationModel::updateKineticEnergy()
|
||||||
+ node.mass.rotationalI3 * pow(node.velocity[4], 2)
|
+ node.mass.rotationalI3 * pow(node.velocity[4], 2)
|
||||||
+ node.mass.rotationalI2 * pow(node.velocity[5], 2));
|
+ node.mass.rotationalI2 * pow(node.velocity[5], 2));
|
||||||
|
|
||||||
node.kineticEnergy += nodeTranslationalKineticEnergy + nodeRotationalKineticEnergy;
|
node.kineticEnergy = nodeTranslationalKineticEnergy + nodeRotationalKineticEnergy;
|
||||||
assert(node.kineticEnergy < 1e15);
|
assert(node.kineticEnergy < 1e15);
|
||||||
|
|
||||||
pMesh->currentTotalKineticEnergy += node.kineticEnergy;
|
pMesh->currentTotalKineticEnergy += node.kineticEnergy;
|
||||||
|
|
@ -1959,26 +1960,10 @@ SimulationResults DRMSimulationModel::executeSimulation(const std::shared_ptr<Si
|
||||||
const SimulationResults &solutionGuess)
|
const SimulationResults &solutionGuess)
|
||||||
{
|
{
|
||||||
assert(pJob->pMesh.operator bool());
|
assert(pJob->pMesh.operator bool());
|
||||||
auto t1 = std::chrono::high_resolution_clock::now();
|
auto beginTime = std::chrono::high_resolution_clock::now();
|
||||||
mSettings = settings;
|
mSettings = settings;
|
||||||
reset();
|
reset();
|
||||||
double totalExternalForcesNorm = 0;
|
|
||||||
for (const std::pair<VertexIndex, Vector6d> &externalForce : pJob->nodalExternalForces) {
|
|
||||||
totalExternalForcesNorm += externalForce.second.norm();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!pJob->nodalExternalForces.empty()) {
|
|
||||||
mSettings.totalResidualForcesNormThreshold
|
|
||||||
= settings.totalExternalForcesNormPercentageTermination * totalExternalForcesNorm;
|
|
||||||
} else {
|
|
||||||
mSettings.totalResidualForcesNormThreshold = 1e-3;
|
|
||||||
std::cout << "No forces setted default residual forces norm threshold" << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mSettings.beVerbose) {
|
|
||||||
std::cout << "totalResidualForcesNormThreshold:"
|
|
||||||
<< mSettings.totalResidualForcesNormThreshold << std::endl;
|
|
||||||
}
|
|
||||||
history.label = pJob->pMesh->getLabel() + "_" + pJob->getLabel();
|
history.label = pJob->pMesh->getLabel() + "_" + pJob->getLabel();
|
||||||
|
|
||||||
// if (!pJob->nodalExternalForces.empty()) {
|
// if (!pJob->nodalExternalForces.empty()) {
|
||||||
|
|
@ -2044,12 +2029,38 @@ SimulationResults DRMSimulationModel::executeSimulation(const std::shared_ptr<Si
|
||||||
}
|
}
|
||||||
|
|
||||||
updateNodalMasses();
|
updateNodalMasses();
|
||||||
updateNodalExternalForces(pJob->nodalExternalForces, constrainedVertices);
|
std::unordered_map<VertexIndex, Vector6d> nodalExternalForces = pJob->nodalExternalForces;
|
||||||
const size_t movingAverageSampleSize = 200;
|
double totalExternalForcesNorm = 0;
|
||||||
std::queue<double> residualForcesMovingAverageHistorySample;
|
// Vector6d sumOfExternalForces(0);
|
||||||
|
for (auto &nodalForce : nodalExternalForces) {
|
||||||
|
const double percentageOfExternalLoads = double(externalLoadStep)
|
||||||
|
/ mSettings.desiredGradualExternalLoadsSteps;
|
||||||
|
nodalForce.second = nodalForce.second * percentageOfExternalLoads;
|
||||||
|
totalExternalForcesNorm += nodalForce.second.norm();
|
||||||
|
// sumOfExternalForces = sumOfExternalForces + nodalForce.second;
|
||||||
|
}
|
||||||
|
updateNodalExternalForces(nodalExternalForces, constrainedVertices);
|
||||||
|
double averageExternalForcesNorm =
|
||||||
|
// sumOfExternalForces.norm() / pMesh->VN();
|
||||||
|
totalExternalForcesNorm / pMesh->VN();
|
||||||
|
if (!nodalExternalForces.empty()) {
|
||||||
|
mSettings.totalResidualForcesNormThreshold
|
||||||
|
= std::min(settings.totalExternalForcesNormPercentageTermination
|
||||||
|
* totalExternalForcesNorm,
|
||||||
|
1e-3);
|
||||||
|
} else {
|
||||||
|
mSettings.totalResidualForcesNormThreshold = 1e-3;
|
||||||
|
std::cout << "No forces setted default residual forces norm threshold" << std::endl;
|
||||||
|
}
|
||||||
|
if (mSettings.beVerbose) {
|
||||||
|
std::cout << "totalResidualForcesNormThreshold:"
|
||||||
|
<< mSettings.totalResidualForcesNormThreshold << std::endl;
|
||||||
|
}
|
||||||
|
// const size_t movingAverageSampleSize = 200;
|
||||||
|
// std::queue<double> residualForcesMovingAverageHistorySample;
|
||||||
std::vector<double> percentageOfConvergence;
|
std::vector<double> percentageOfConvergence;
|
||||||
|
|
||||||
double residualForcesMovingAverageDerivativeMax = 0;
|
// double residualForcesMovingAverageDerivativeMax = 0;
|
||||||
while (settings.maxDRMIterations == 0 || mCurrentSimulationStep < settings.maxDRMIterations) {
|
while (settings.maxDRMIterations == 0 || mCurrentSimulationStep < settings.maxDRMIterations) {
|
||||||
if ((mSettings.isDebugMode && mCurrentSimulationStep == 50000)) {
|
if ((mSettings.isDebugMode && mCurrentSimulationStep == 50000)) {
|
||||||
// std::filesystem::create_directory("./PatternOptimizationNonConv");
|
// std::filesystem::create_directory("./PatternOptimizationNonConv");
|
||||||
|
|
@ -2087,39 +2098,47 @@ SimulationResults DRMSimulationModel::executeSimulation(const std::shared_ptr<Si
|
||||||
// }
|
// }
|
||||||
updateElementalLengths();
|
updateElementalLengths();
|
||||||
mCurrentSimulationStep++;
|
mCurrentSimulationStep++;
|
||||||
|
if (std::isnan(pMesh->currentTotalKineticEnergy)) {
|
||||||
double sumOfDisplacementsNorm = 0;
|
std::cout << pMesh->currentTotalKineticEnergy << std::endl;
|
||||||
for (size_t vi = 0; vi < pMesh->VN(); vi++) {
|
if (mSettings.beVerbose) {
|
||||||
sumOfDisplacementsNorm += pMesh->nodes[vi].displacements.getTranslation().norm();
|
std::cerr << "Infinite kinetic energy at step " << mCurrentSimulationStep
|
||||||
|
<< ". Exiting.." << std::endl;
|
||||||
}
|
}
|
||||||
sumOfDisplacementsNorm /= pMesh->bbox.Diag();
|
break;
|
||||||
pMesh->sumOfNormalizedDisplacementNorms = sumOfDisplacementsNorm;
|
|
||||||
// pMesh->residualForcesMovingAverage = (pMesh->totalResidualForcesNorm
|
|
||||||
// + mCurrentSimulationStep
|
|
||||||
// * pMesh->residualForcesMovingAverage)
|
|
||||||
// / (1 + mCurrentSimulationStep);
|
|
||||||
pMesh->residualForcesMovingAverage += pMesh->totalResidualForcesNorm
|
|
||||||
/ movingAverageSampleSize;
|
|
||||||
residualForcesMovingAverageHistorySample.push(pMesh->residualForcesMovingAverage);
|
|
||||||
if (movingAverageSampleSize < residualForcesMovingAverageHistorySample.size()) {
|
|
||||||
const double firstElementValue = residualForcesMovingAverageHistorySample.front();
|
|
||||||
pMesh->residualForcesMovingAverage -= firstElementValue / movingAverageSampleSize;
|
|
||||||
residualForcesMovingAverageHistorySample.pop();
|
|
||||||
|
|
||||||
pMesh->residualForcesMovingAverageDerivativeNorm
|
|
||||||
= std::abs((residualForcesMovingAverageHistorySample.back()
|
|
||||||
- residualForcesMovingAverageHistorySample.front()))
|
|
||||||
/ (movingAverageSampleSize);
|
|
||||||
residualForcesMovingAverageDerivativeMax
|
|
||||||
= std::max(pMesh->residualForcesMovingAverageDerivativeNorm,
|
|
||||||
residualForcesMovingAverageDerivativeMax);
|
|
||||||
pMesh->residualForcesMovingAverageDerivativeNorm
|
|
||||||
/= residualForcesMovingAverageDerivativeMax;
|
|
||||||
// std::cout << "Normalized derivative:"
|
|
||||||
// << residualForcesMovingAverageDerivativeNorm
|
|
||||||
// << std::endl;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// double sumOfDisplacementsNorm = 0;
|
||||||
|
// for (size_t vi = 0; vi < pMesh->VN(); vi++) {
|
||||||
|
// sumOfDisplacementsNorm += pMesh->nodes[vi].displacements.getTranslation().norm();
|
||||||
|
// }
|
||||||
|
// sumOfDisplacementsNorm /= pMesh->bbox.Diag();
|
||||||
|
// pMesh->sumOfNormalizedDisplacementNorms = sumOfDisplacementsNorm;
|
||||||
|
// // pMesh->residualForcesMovingAverage = (pMesh->totalResidualForcesNorm
|
||||||
|
// // + mCurrentSimulationStep
|
||||||
|
// // * pMesh->residualForcesMovingAverage)
|
||||||
|
// // / (1 + mCurrentSimulationStep);
|
||||||
|
// pMesh->residualForcesMovingAverage += pMesh->totalResidualForcesNorm
|
||||||
|
// / movingAverageSampleSize;
|
||||||
|
// residualForcesMovingAverageHistorySample.push(pMesh->residualForcesMovingAverage);
|
||||||
|
// if (movingAverageSampleSize < residualForcesMovingAverageHistorySample.size()) {
|
||||||
|
// const double firstElementValue = residualForcesMovingAverageHistorySample.front();
|
||||||
|
// pMesh->residualForcesMovingAverage -= firstElementValue / movingAverageSampleSize;
|
||||||
|
// residualForcesMovingAverageHistorySample.pop();
|
||||||
|
|
||||||
|
// pMesh->residualForcesMovingAverageDerivativeNorm
|
||||||
|
// = std::abs((residualForcesMovingAverageHistorySample.back()
|
||||||
|
// - residualForcesMovingAverageHistorySample.front()))
|
||||||
|
// / (movingAverageSampleSize);
|
||||||
|
// residualForcesMovingAverageDerivativeMax
|
||||||
|
// = std::max(pMesh->residualForcesMovingAverageDerivativeNorm,
|
||||||
|
// residualForcesMovingAverageDerivativeMax);
|
||||||
|
// pMesh->residualForcesMovingAverageDerivativeNorm
|
||||||
|
// /= residualForcesMovingAverageDerivativeMax;
|
||||||
|
// // std::cout << "Normalized derivative:"
|
||||||
|
// // << residualForcesMovingAverageDerivativeNorm
|
||||||
|
// // << std::endl;
|
||||||
|
// }
|
||||||
|
|
||||||
// pMesh->previousTotalPotentialEnergykN =
|
// pMesh->previousTotalPotentialEnergykN =
|
||||||
// pMesh->currentTotalPotentialEnergykN;
|
// pMesh->currentTotalPotentialEnergykN;
|
||||||
// pMesh->currentTotalPotentialEnergykN = computeTotalPotentialEnergy() / 1000;
|
// pMesh->currentTotalPotentialEnergykN = computeTotalPotentialEnergy() / 1000;
|
||||||
|
|
@ -2127,10 +2146,21 @@ SimulationResults DRMSimulationModel::executeSimulation(const std::shared_ptr<Si
|
||||||
if (mSettings.beVerbose && mSettings.isDebugMode
|
if (mSettings.beVerbose && mSettings.isDebugMode
|
||||||
&& mCurrentSimulationStep % mSettings.debugModeStep == 0) {
|
&& mCurrentSimulationStep % mSettings.debugModeStep == 0) {
|
||||||
printCurrentState();
|
printCurrentState();
|
||||||
|
|
||||||
|
// auto t2 = std::chrono::high_resolution_clock::now();
|
||||||
|
// const double executionTime_min
|
||||||
|
// = std::chrono::duration_cast<std::chrono::minutes>(t2 - beginTime).count();
|
||||||
|
// std::cout << "Execution time(min):" << executionTime_min << std::endl;
|
||||||
|
if (mSettings.useAverageResidualForcesNorm) {
|
||||||
|
const double percOfConv = averageExternalForcesNorm
|
||||||
|
/ pMesh->averageResidualForcesNorm;
|
||||||
|
std::cout << "Percentage of target:" << percOfConv << "%" << std::endl;
|
||||||
|
} else {
|
||||||
std::cout << "Percentage of target:"
|
std::cout << "Percentage of target:"
|
||||||
<< 100 * mSettings.totalResidualForcesNormThreshold
|
<< 100 * mSettings.totalResidualForcesNormThreshold
|
||||||
/ pMesh->totalResidualForcesNorm
|
/ pMesh->totalResidualForcesNorm
|
||||||
<< "%" << std::endl;
|
<< "%" << std::endl;
|
||||||
|
}
|
||||||
// SimulationResultsReporter::createPlot("Number of Steps",
|
// SimulationResultsReporter::createPlot("Number of Steps",
|
||||||
// "Residual Forces mov aver",
|
// "Residual Forces mov aver",
|
||||||
// movingAverages);
|
// movingAverages);
|
||||||
|
|
@ -2149,13 +2179,6 @@ SimulationResults DRMSimulationModel::executeSimulation(const std::shared_ptr<Si
|
||||||
/ pMesh->totalResidualForcesNorm);
|
/ pMesh->totalResidualForcesNorm);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (std::isnan(pMesh->currentTotalKineticEnergy)) {
|
|
||||||
if (mSettings.beVerbose) {
|
|
||||||
std::cout << "Infinite kinetic energy detected.Exiting.." << std::endl;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mSettings.shouldCreatePlots && mSettings.isDebugMode
|
if (mSettings.shouldCreatePlots && mSettings.isDebugMode
|
||||||
&& mCurrentSimulationStep % mSettings.debugModeStep == 0) {
|
&& mCurrentSimulationStep % mSettings.debugModeStep == 0) {
|
||||||
// SimulationResultsReporter::createPlot("Number of Steps",
|
// SimulationResultsReporter::createPlot("Number of Steps",
|
||||||
|
|
@ -2164,18 +2187,18 @@ SimulationResults DRMSimulationModel::executeSimulation(const std::shared_ptr<Si
|
||||||
// SimulationResultsReporter::createPlot("Number of Steps",
|
// SimulationResultsReporter::createPlot("Number of Steps",
|
||||||
// "Residual Forces mov aver",
|
// "Residual Forces mov aver",
|
||||||
// history.residualForcesMovingAverage);
|
// history.residualForcesMovingAverage);
|
||||||
// SimulationResultsReporter::createPlot("Number of Steps",
|
SimulationResultsReporter::createPlot("Number of Steps",
|
||||||
// "Log of Residual Forces",
|
"Log of Residual Forces",
|
||||||
// history.logResidualForces,
|
history.logResidualForces,
|
||||||
// {},
|
{},
|
||||||
// history.redMarks);
|
history.redMarks);
|
||||||
// SimulationResultsReporter::createPlot("Number of Steps",
|
// SimulationResultsReporter::createPlot("Number of Steps",
|
||||||
// "Log of Kinetic energy",
|
// "Log of Kinetic energy",
|
||||||
// history.kineticEnergy,
|
// history.kineticEnergy,
|
||||||
// {},
|
// {},
|
||||||
// history.redMarks);
|
// history.redMarks);
|
||||||
SimulationResultsReporter reporter;
|
// SimulationResultsReporter reporter;
|
||||||
reporter.reportHistory(history, "IntermediateResults", pJob->pMesh->getLabel());
|
// reporter.reportHistory(history, "IntermediateResults", pJob->pMesh->getLabel());
|
||||||
// SimulationResultsReporter::createPlot("Number of Iterations",
|
// SimulationResultsReporter::createPlot("Number of Iterations",
|
||||||
// "Sum of normalized displacement norms",
|
// "Sum of normalized displacement norms",
|
||||||
// history.sumOfNormalizedDisplacementNorms /*,
|
// history.sumOfNormalizedDisplacementNorms /*,
|
||||||
|
|
@ -2234,8 +2257,12 @@ mesh->currentTotalPotentialEnergykN*/
|
||||||
&& pMesh->currentTotalTranslationalKineticEnergy
|
&& pMesh->currentTotalTranslationalKineticEnergy
|
||||||
< mSettings.totalTranslationalKineticEnergyThreshold
|
< mSettings.totalTranslationalKineticEnergyThreshold
|
||||||
&& mCurrentSimulationStep > 20 && numOfDampings > 0;
|
&& mCurrentSimulationStep > 20 && numOfDampings > 0;
|
||||||
|
const bool fullfillsAverageResidualForcesNormCriterion
|
||||||
|
= mSettings.useAverageResidualForcesNorm
|
||||||
|
&& pMesh->averageResidualForcesNorm / averageExternalForcesNorm < 1e-2;
|
||||||
const bool fullfillsResidualForcesNormTerminationCriterion
|
const bool fullfillsResidualForcesNormTerminationCriterion
|
||||||
= pMesh->totalResidualForcesNorm < mSettings.totalResidualForcesNormThreshold;
|
= mSettings.useResidualForcesNorm
|
||||||
|
&& pMesh->totalResidualForcesNorm < mSettings.totalResidualForcesNormThreshold;
|
||||||
const bool fullfillsMovingAverageNormTerminationCriterion
|
const bool fullfillsMovingAverageNormTerminationCriterion
|
||||||
= pMesh->residualForcesMovingAverage
|
= pMesh->residualForcesMovingAverage
|
||||||
< mSettings.residualForcesMovingAverageNormThreshold;
|
< mSettings.residualForcesMovingAverageNormThreshold;
|
||||||
|
|
@ -2246,7 +2273,8 @@ mesh->currentTotalPotentialEnergykN*/
|
||||||
= fullfillsKineticEnergyTerminationCriterion
|
= fullfillsKineticEnergyTerminationCriterion
|
||||||
// || fullfillsMovingAverageNormTerminationCriterion
|
// || fullfillsMovingAverageNormTerminationCriterion
|
||||||
// || fullfillsMovingAverageDerivativeNormTerminationCriterion
|
// || fullfillsMovingAverageDerivativeNormTerminationCriterion
|
||||||
|| fullfillsResidualForcesNormTerminationCriterion;
|
|| fullfillsResidualForcesNormTerminationCriterion
|
||||||
|
|| fullfillsAverageResidualForcesNormCriterion;
|
||||||
if (shouldTerminate) {
|
if (shouldTerminate) {
|
||||||
if (mSettings.beVerbose && !mSettings.isDebugMode) {
|
if (mSettings.beVerbose && !mSettings.isDebugMode) {
|
||||||
std::cout << "Simulation converged." << std::endl;
|
std::cout << "Simulation converged." << std::endl;
|
||||||
|
|
@ -2265,29 +2293,52 @@ mesh->currentTotalPotentialEnergykN*/
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (mSettings.desiredGradualExternalLoadsSteps == externalLoadStep) {
|
||||||
break;
|
break;
|
||||||
|
} else {
|
||||||
|
externalLoadStep++;
|
||||||
|
std::unordered_map<VertexIndex, Vector6d> nodalExternalForces
|
||||||
|
= pJob->nodalExternalForces;
|
||||||
|
double totalExternalForcesNorm = 0;
|
||||||
|
for (auto &nodalForce : nodalExternalForces) {
|
||||||
|
const double percentageOfExternalLoads
|
||||||
|
= double(externalLoadStep) / mSettings.desiredGradualExternalLoadsSteps;
|
||||||
|
nodalForce.second = nodalForce.second * percentageOfExternalLoads;
|
||||||
|
totalExternalForcesNorm += nodalForce.second.norm();
|
||||||
|
}
|
||||||
|
updateNodalExternalForces(nodalExternalForces, constrainedVertices);
|
||||||
|
|
||||||
|
averageExternalForcesNorm = totalExternalForcesNorm / pMesh->VN();
|
||||||
|
if (!nodalExternalForces.empty()) {
|
||||||
|
mSettings.totalResidualForcesNormThreshold = 1e-2 * totalExternalForcesNorm;
|
||||||
|
}
|
||||||
|
if (mSettings.beVerbose) {
|
||||||
|
std::cout << "totalResidualForcesNormThreshold:"
|
||||||
|
<< mSettings.totalResidualForcesNormThreshold << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
// const bool shouldCapDisplacements = mSettings.displacementCap.has_value();
|
const bool shouldCapDisplacements = mSettings.displacementCap.has_value();
|
||||||
// for (VertexType &v : pMesh->vert) {
|
for (VertexType &v : pMesh->vert) {
|
||||||
// Node &node = pMesh->nodes[v];
|
Node &node = pMesh->nodes[v];
|
||||||
// Vector6d stepDisplacement = node.velocity * Dt;
|
Vector6d stepDisplacement = node.velocity * Dt;
|
||||||
// if (shouldCapDisplacements
|
if (shouldCapDisplacements
|
||||||
// && stepDisplacement.getTranslation().norm() > mSettings.displacementCap) {
|
&& stepDisplacement.getTranslation().norm() > mSettings.displacementCap) {
|
||||||
// stepDisplacement = stepDisplacement
|
stepDisplacement = stepDisplacement
|
||||||
// * (*mSettings.displacementCap
|
* (*mSettings.displacementCap
|
||||||
// / stepDisplacement.getTranslation().norm());
|
/ stepDisplacement.getTranslation().norm());
|
||||||
// }
|
}
|
||||||
// node.displacements = node.displacements - stepDisplacement;
|
node.displacements = node.displacements - stepDisplacement;
|
||||||
// }
|
}
|
||||||
// applyDisplacements(constrainedVertices);
|
applyDisplacements(constrainedVertices);
|
||||||
// if (!pJob->nodalForcedDisplacements.empty()) {
|
if (!pJob->nodalForcedDisplacements.empty()) {
|
||||||
// applyForcedDisplacements(
|
applyForcedDisplacements(
|
||||||
|
|
||||||
// pJob->nodalForcedDisplacements);
|
pJob->nodalForcedDisplacements);
|
||||||
// }
|
}
|
||||||
// updateElementalLengths();
|
updateElementalLengths();
|
||||||
|
|
||||||
// const double triggerPercentage = 0.01;
|
// const double triggerPercentage = 0.01;
|
||||||
// const double xi_min = 0.55;
|
// const double xi_min = 0.55;
|
||||||
|
|
@ -2313,8 +2364,11 @@ mesh->currentTotalPotentialEnergykN*/
|
||||||
// draw();
|
// draw();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
auto endTime = std::chrono::high_resolution_clock::now();
|
||||||
|
|
||||||
SimulationResults results = computeResults(pJob);
|
SimulationResults results = computeResults(pJob);
|
||||||
|
results.executionTime = std::chrono::duration_cast<std::chrono::seconds>(endTime - beginTime)
|
||||||
|
.count();
|
||||||
|
|
||||||
if (mCurrentSimulationStep == settings.maxDRMIterations && mCurrentSimulationStep != 0) {
|
if (mCurrentSimulationStep == settings.maxDRMIterations && mCurrentSimulationStep != 0) {
|
||||||
if (mSettings.beVerbose) {
|
if (mSettings.beVerbose) {
|
||||||
|
|
|
||||||
|
|
@ -39,10 +39,13 @@ public:
|
||||||
int maxDRMIterations{0};
|
int maxDRMIterations{0};
|
||||||
bool shouldUseTranslationalKineticEnergyThreshold{false};
|
bool shouldUseTranslationalKineticEnergyThreshold{false};
|
||||||
int gradualForcedDisplacementSteps{100};
|
int gradualForcedDisplacementSteps{100};
|
||||||
|
int desiredGradualExternalLoadsSteps{1};
|
||||||
double gamma{0.8};
|
double gamma{0.8};
|
||||||
std::optional<double> displacementCap;
|
std::optional<double> displacementCap;
|
||||||
double totalResidualForcesNormThreshold{1e-3};
|
double totalResidualForcesNormThreshold{1e-3};
|
||||||
double totalExternalForcesNormPercentageTermination{1e-3};
|
double totalExternalForcesNormPercentageTermination{1e-3};
|
||||||
|
bool useResidualForcesNorm{true};
|
||||||
|
bool useAverageResidualForcesNorm{false};
|
||||||
Settings() {}
|
Settings() {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -57,6 +60,7 @@ private:
|
||||||
matplot::line_handle plotHandle;
|
matplot::line_handle plotHandle;
|
||||||
std::vector<double> plotYValues;
|
std::vector<double> plotYValues;
|
||||||
size_t numOfDampings{0};
|
size_t numOfDampings{0};
|
||||||
|
int externalLoadStep{1};
|
||||||
|
|
||||||
const std::string meshPolyscopeLabel{"Simulation mesh"};
|
const std::string meshPolyscopeLabel{"Simulation mesh"};
|
||||||
std::unique_ptr<SimulationMesh> pMesh;
|
std::unique_ptr<SimulationMesh> pMesh;
|
||||||
|
|
|
||||||
|
|
@ -267,6 +267,7 @@ struct Colors
|
||||||
std::vector<double> perSimulationScenario_rotational;
|
std::vector<double> perSimulationScenario_rotational;
|
||||||
std::vector<double> perSimulationScenario_total;
|
std::vector<double> perSimulationScenario_total;
|
||||||
} objectiveValue;
|
} objectiveValue;
|
||||||
|
std::vector<double> perScenario_fullPatternPotentialEnergy;
|
||||||
// std::vector<std::pair<std::string,double>> optimalXNameValuePairs;
|
// std::vector<std::pair<std::string,double>> optimalXNameValuePairs;
|
||||||
std::vector<std::pair<std::string, double>> optimalXNameValuePairs;
|
std::vector<std::pair<std::string, double>> optimalXNameValuePairs;
|
||||||
std::vector<std::shared_ptr<SimulationJob>> fullPatternSimulationJobs;
|
std::vector<std::shared_ptr<SimulationJob>> fullPatternSimulationJobs;
|
||||||
|
|
@ -284,6 +285,7 @@ struct Colors
|
||||||
inline static std::string Label{"Label"};
|
inline static std::string Label{"Label"};
|
||||||
inline static std::string FullPatternLabel{"FullPatternLabel"};
|
inline static std::string FullPatternLabel{"FullPatternLabel"};
|
||||||
inline static std::string Settings{"OptimizationSettings"};
|
inline static std::string Settings{"OptimizationSettings"};
|
||||||
|
inline static std::string FullPatternPotentialEnergies{"PE"};
|
||||||
};
|
};
|
||||||
|
|
||||||
void save(const string &saveToPath, const bool shouldExportDebugFiles = false)
|
void save(const string &saveToPath, const bool shouldExportDebugFiles = false)
|
||||||
|
|
@ -323,6 +325,16 @@ struct Colors
|
||||||
baseTriangle.cP2(0)[2]};
|
baseTriangle.cP2(0)[2]};
|
||||||
baseTriangleFullPattern.save(std::filesystem::path(saveToPath).string());
|
baseTriangleFullPattern.save(std::filesystem::path(saveToPath).string());
|
||||||
json_optimizationResults[JsonKeys::FullPatternLabel] = baseTriangleFullPattern.getLabel();
|
json_optimizationResults[JsonKeys::FullPatternLabel] = baseTriangleFullPattern.getLabel();
|
||||||
|
|
||||||
|
//potential energies
|
||||||
|
const int numberOfSimulationJobs = fullPatternSimulationJobs.size();
|
||||||
|
std::vector<double> fullPatternPE(numberOfSimulationJobs);
|
||||||
|
for (int simulationScenarioIndex = 0; simulationScenarioIndex < numberOfSimulationJobs;
|
||||||
|
simulationScenarioIndex++) {
|
||||||
|
fullPatternPE[simulationScenarioIndex]
|
||||||
|
= perScenario_fullPatternPotentialEnergy[simulationScenarioIndex];
|
||||||
|
}
|
||||||
|
json_optimizationResults[JsonKeys::FullPatternPotentialEnergies] = fullPatternPE;
|
||||||
////Save to json file
|
////Save to json file
|
||||||
std::filesystem::path jsonFilePath(
|
std::filesystem::path jsonFilePath(
|
||||||
std::filesystem::path(saveToPath).append(JsonKeys::filename));
|
std::filesystem::path(saveToPath).append(JsonKeys::filename));
|
||||||
|
|
@ -652,6 +664,13 @@ struct Colors
|
||||||
os << "Obj value Rot " + simulationScenarioName;
|
os << "Obj value Rot " + simulationScenarioName;
|
||||||
os << "Obj value Total " + simulationScenarioName;
|
os << "Obj value Total " + simulationScenarioName;
|
||||||
}
|
}
|
||||||
|
for (int simulationScenarioIndex = 0;
|
||||||
|
simulationScenarioIndex < fullPatternSimulationJobs.size();
|
||||||
|
simulationScenarioIndex++) {
|
||||||
|
const std::string simulationScenarioName
|
||||||
|
= fullPatternSimulationJobs[simulationScenarioIndex]->getLabel();
|
||||||
|
os << "PE " + simulationScenarioName;
|
||||||
|
}
|
||||||
for (const auto &nameValuePair : optimalXNameValuePairs) {
|
for (const auto &nameValuePair : optimalXNameValuePairs) {
|
||||||
os << nameValuePair.first;
|
os << nameValuePair.first;
|
||||||
}
|
}
|
||||||
|
|
@ -671,6 +690,11 @@ struct Colors
|
||||||
os << objectiveValue.perSimulationScenario_rotational[simulationScenarioIndex];
|
os << objectiveValue.perSimulationScenario_rotational[simulationScenarioIndex];
|
||||||
os << objectiveValue.perSimulationScenario_total[simulationScenarioIndex];
|
os << objectiveValue.perSimulationScenario_total[simulationScenarioIndex];
|
||||||
}
|
}
|
||||||
|
for (int simulationScenarioIndex = 0;
|
||||||
|
simulationScenarioIndex < fullPatternSimulationJobs.size();
|
||||||
|
simulationScenarioIndex++) {
|
||||||
|
os << perScenario_fullPatternPotentialEnergy[simulationScenarioIndex];
|
||||||
|
}
|
||||||
for (const auto &optimalXNameValuePair : optimalXNameValuePairs) {
|
for (const auto &optimalXNameValuePair : optimalXNameValuePairs) {
|
||||||
os << optimalXNameValuePair.second;
|
os << optimalXNameValuePair.second;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -492,7 +492,7 @@ struct SimulationResults
|
||||||
return labelPrefix + deliminator + job->pMesh->getLabel() + deliminator + job->getLabel();
|
return labelPrefix + deliminator + job->pMesh->getLabel() + deliminator + job->getLabel();
|
||||||
}
|
}
|
||||||
|
|
||||||
void saveDeformedModel(const std::string &outputFolder = std::string())
|
bool saveDeformedModel(const std::string &outputFolder = std::string())
|
||||||
{
|
{
|
||||||
VCGEdgeMesh m;
|
VCGEdgeMesh m;
|
||||||
vcg::tri::Append<VCGEdgeMesh, SimulationMesh>::MeshCopy(m, *job->pMesh);
|
vcg::tri::Append<VCGEdgeMesh, SimulationMesh>::MeshCopy(m, *job->pMesh);
|
||||||
|
|
@ -503,7 +503,7 @@ struct SimulationResults
|
||||||
displacements[vi][1],
|
displacements[vi][1],
|
||||||
displacements[vi][2]);
|
displacements[vi][2]);
|
||||||
}
|
}
|
||||||
m.save(std::filesystem::path(outputFolder).append(getLabel() + ".ply").string());
|
return m.save(std::filesystem::path(outputFolder).append(getLabel() + ".ply").string());
|
||||||
}
|
}
|
||||||
|
|
||||||
void save(const std::string &outputFolder = std::string())
|
void save(const std::string &outputFolder = std::string())
|
||||||
|
|
|
||||||
|
|
@ -43,6 +43,7 @@ public:
|
||||||
double currentTotalKineticEnergy{0};
|
double currentTotalKineticEnergy{0};
|
||||||
double currentTotalTranslationalKineticEnergy{0};
|
double currentTotalTranslationalKineticEnergy{0};
|
||||||
double totalResidualForcesNorm{0};
|
double totalResidualForcesNorm{0};
|
||||||
|
double averageResidualForcesNorm{0};
|
||||||
double currentTotalPotentialEnergykN{0};
|
double currentTotalPotentialEnergykN{0};
|
||||||
double previousTotalPotentialEnergykN{0};
|
double previousTotalPotentialEnergykN{0};
|
||||||
double residualForcesMovingAverageDerivativeNorm{0};
|
double residualForcesMovingAverageDerivativeNorm{0};
|
||||||
|
|
|
||||||
|
|
@ -116,6 +116,16 @@ struct Vector6d : public std::array<double, 6> {
|
||||||
{
|
{
|
||||||
return Eigen::Vector3d(this->operator[](3), this->operator[](4), this->operator[](5));
|
return Eigen::Vector3d(this->operator[](3), this->operator[](4), this->operator[](5));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string toString() const
|
||||||
|
{
|
||||||
|
std::string s;
|
||||||
|
for (int i = 0; i < 6; i++) {
|
||||||
|
s.append(std::to_string(this->operator[](i)) + ",");
|
||||||
|
}
|
||||||
|
s.pop_back();
|
||||||
|
return s;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace Utilities {
|
namespace Utilities {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue