Added tests for the form finder for the 3 cases of the paper as a static function of the form finder.
This commit is contained in:
parent
5d8445fbca
commit
db500efd05
2
beam.hpp
2
beam.hpp
|
|
@ -6,6 +6,7 @@
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
struct RectangularBeamDimensions {
|
struct RectangularBeamDimensions {
|
||||||
|
inline static std::string name{"Rectangular"};
|
||||||
float b;
|
float b;
|
||||||
float h;
|
float h;
|
||||||
RectangularBeamDimensions(const float &width, const float &height)
|
RectangularBeamDimensions(const float &width, const float &height)
|
||||||
|
|
@ -16,6 +17,7 @@ struct RectangularBeamDimensions {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CylindricalBeamDimensions {
|
struct CylindricalBeamDimensions {
|
||||||
|
inline static std::string name{"Cylindrical"};
|
||||||
float od; // Cylinder outside diameter
|
float od; // Cylinder outside diameter
|
||||||
float
|
float
|
||||||
id; // Cylinder inside diameter
|
id; // Cylinder inside diameter
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,10 @@
|
||||||
#include <execution>
|
#include <execution>
|
||||||
#include <omp.h>
|
#include <omp.h>
|
||||||
|
|
||||||
|
void FormFinder::setTotalResidualForcesNormThreshold(double value) {
|
||||||
|
totalResidualForcesNormThreshold = value;
|
||||||
|
}
|
||||||
|
|
||||||
void FormFinder::reset() {
|
void FormFinder::reset() {
|
||||||
Dt = Dtini;
|
Dt = Dtini;
|
||||||
mCurrentSimulationStep = 0;
|
mCurrentSimulationStep = 0;
|
||||||
|
|
@ -17,6 +21,8 @@ void FormFinder::reset() {
|
||||||
mesh.release();
|
mesh.release();
|
||||||
plotYValues.clear();
|
plotYValues.clear();
|
||||||
plotHandle.reset();
|
plotHandle.reset();
|
||||||
|
shouldUseKineticEnergyThreshold = false;
|
||||||
|
externalMomentsNorm = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
VectorType FormFinder::computeDisplacementDifferenceDerivative(
|
VectorType FormFinder::computeDisplacementDifferenceDerivative(
|
||||||
|
|
@ -779,13 +785,17 @@ void FormFinder::updateResidualForcesOnTheFly(
|
||||||
force.residual = force.residual + (internalForcePair.second * -1);
|
force.residual = force.residual + (internalForcePair.second * -1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Vector6d sumOfResidualForces(0);
|
||||||
for (size_t vi = 0; vi < mesh->VN(); vi++) {
|
for (size_t vi = 0; vi < mesh->VN(); vi++) {
|
||||||
const Vector6d &nodeResidualForce = mesh->nodes[vi].force.residual;
|
Node::Forces &force = mesh->nodes[vi].force;
|
||||||
|
const Vector6d &nodeResidualForce = force.residual;
|
||||||
|
// sumOfResidualForces = sumOfResidualForces + nodeResidualForce;
|
||||||
const double residualForceNorm = nodeResidualForce.norm();
|
const double residualForceNorm = nodeResidualForce.norm();
|
||||||
totalResidualForcesNorm += residualForceNorm;
|
totalResidualForcesNorm += residualForceNorm;
|
||||||
}
|
}
|
||||||
mesh->previousTotalResidualForcesNorm = mesh->totalResidualForcesNorm;
|
mesh->previousTotalResidualForcesNorm = mesh->totalResidualForcesNorm;
|
||||||
mesh->totalResidualForcesNorm = totalResidualForcesNorm;
|
mesh->totalResidualForcesNorm = totalResidualForcesNorm;
|
||||||
|
// mesh->totalResidualForcesNorm = sumOfResidualForces.norm();
|
||||||
|
|
||||||
// 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());
|
||||||
|
|
@ -797,6 +807,7 @@ void FormFinder::updateNodalExternalForces(
|
||||||
const std::unordered_map<VertexIndex, std::unordered_set<DoFType>>
|
const std::unordered_map<VertexIndex, std::unordered_set<DoFType>>
|
||||||
&fixedVertices) {
|
&fixedVertices) {
|
||||||
|
|
||||||
|
externalMomentsNorm = 0;
|
||||||
for (const std::pair<VertexIndex, Vector6d> &nodalForce : nodalForces) {
|
for (const std::pair<VertexIndex, Vector6d> &nodalForce : nodalForces) {
|
||||||
const VertexIndex nodeIndex = nodalForce.first;
|
const VertexIndex nodeIndex = nodalForce.first;
|
||||||
const bool isNodeConstrained = fixedVertices.contains(nodeIndex);
|
const bool isNodeConstrained = fixedVertices.contains(nodeIndex);
|
||||||
|
|
@ -810,6 +821,12 @@ void FormFinder::updateNodalExternalForces(
|
||||||
}
|
}
|
||||||
nodalExternalForce[dofi] = nodalForce.second[dofi];
|
nodalExternalForce[dofi] = nodalForce.second[dofi];
|
||||||
}
|
}
|
||||||
|
externalMomentsNorm += std::sqrt(pow(nodalExternalForce[3], 2) +
|
||||||
|
pow(nodalExternalForce[4], 2));
|
||||||
|
// CoordType v = (mesh->vert[nodeIndex].cP() -
|
||||||
|
// mesh->vert[0].cP()).Normalize(); const double forceMagnitude = 0.1;
|
||||||
|
// nodalExternalForce[3] = v[0] * forceMagnitude;
|
||||||
|
// nodalExternalForce[4] = v[1] * forceMagnitude;
|
||||||
node.force.external = nodalExternalForce;
|
node.force.external = nodalExternalForce;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1032,7 +1049,7 @@ void FormFinder::updateNodePosition(
|
||||||
node.previousLocation = previousLocation;
|
node.previousLocation = previousLocation;
|
||||||
v.P() = node.initialLocation + displacementVector;
|
v.P() = node.initialLocation + displacementVector;
|
||||||
if (shouldApplyInitialDistortion && mCurrentSimulationStep < 40) {
|
if (shouldApplyInitialDistortion && mCurrentSimulationStep < 40) {
|
||||||
VectorType desiredInitialDisplacement(0, 0, 0.001);
|
VectorType desiredInitialDisplacement(0, 0, 0.01);
|
||||||
v.P() = v.P() + desiredInitialDisplacement;
|
v.P() = v.P() + desiredInitialDisplacement;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1061,11 +1078,34 @@ void FormFinder::updateNodeNormal(
|
||||||
const double &nx = v.N()[0], ny = v.N()[1], nz = v.N()[2];
|
const double &nx = v.N()[0], ny = v.N()[1], nz = v.N()[2];
|
||||||
const double nxnyMagnitude = std::pow(nx, 2) + std::pow(ny, 2);
|
const double nxnyMagnitude = std::pow(nx, 2) + std::pow(ny, 2);
|
||||||
VectorType n = v.N();
|
VectorType n = v.N();
|
||||||
const bool shouldBreak = mCurrentSimulationStep == 118 && vi == 1;
|
const bool shouldBreak = mCurrentSimulationStep == 118 && vi == 3;
|
||||||
if (nxnyMagnitude > 1) {
|
if (nxnyMagnitude > 1) {
|
||||||
VectorType newNormal(nx / std::sqrt(nxnyMagnitude),
|
VectorType newNormal(nx / std::sqrt(nxnyMagnitude),
|
||||||
ny / std::sqrt(nxnyMagnitude), 0);
|
ny / std::sqrt(nxnyMagnitude), 0);
|
||||||
v.N() = newNormal;
|
v.N() = newNormal;
|
||||||
|
|
||||||
|
/*If an external moment caused the normal to lay on the xy plane this means
|
||||||
|
* that in order to disable its effect a greater internal force is needed
|
||||||
|
* than what is possible (the constraint on the z of the normals imposes a
|
||||||
|
* constraint on the maximum internal force). Because of that the
|
||||||
|
* totalResidualForcesNorm can't drop below the magnitude of external moment
|
||||||
|
* applied on vertex vi. In order to allow termination of the simulation
|
||||||
|
* when the described phenomenon happens we allow the termination of the
|
||||||
|
* algorithm if the kinetic energy of the system drops below the set
|
||||||
|
* threshold.
|
||||||
|
* */
|
||||||
|
static bool wasExecuted{false};
|
||||||
|
const bool viHasMoments =
|
||||||
|
node.force.external[3] != 0 || node.force.external[4] != 0;
|
||||||
|
if (!wasExecuted && viHasMoments) {
|
||||||
|
shouldUseKineticEnergyThreshold = true;
|
||||||
|
std::cout
|
||||||
|
<< "Maximum moment reached.The Kinetic energy of the system will "
|
||||||
|
"be used as a convergence criterion"
|
||||||
|
<< std::endl;
|
||||||
|
wasExecuted = true;
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
const double nzSquared = 1.0 - nxnyMagnitude;
|
const double nzSquared = 1.0 - nxnyMagnitude;
|
||||||
const double nz = std::sqrt(nzSquared);
|
const double nz = std::sqrt(nzSquared);
|
||||||
|
|
@ -1358,6 +1398,7 @@ void FormFinder::draw(const std::string &screenshotsFolder = {}) {
|
||||||
|
|
||||||
std::vector<std::array<double, 3>> internalForces(mesh->VN());
|
std::vector<std::array<double, 3>> internalForces(mesh->VN());
|
||||||
std::vector<std::array<double, 3>> externalForces(mesh->VN());
|
std::vector<std::array<double, 3>> externalForces(mesh->VN());
|
||||||
|
std::vector<std::array<double, 3>> externalMoments(mesh->VN());
|
||||||
std::vector<double> internalForcesNorm(mesh->VN());
|
std::vector<double> internalForcesNorm(mesh->VN());
|
||||||
for (const VertexType &v : mesh->vert) {
|
for (const VertexType &v : mesh->vert) {
|
||||||
// per node internal forces
|
// per node internal forces
|
||||||
|
|
@ -1369,6 +1410,8 @@ void FormFinder::draw(const std::string &screenshotsFolder = {}) {
|
||||||
const Vector6d nodeExternalForce = mesh->nodes[v].force.external;
|
const Vector6d nodeExternalForce = mesh->nodes[v].force.external;
|
||||||
externalForces[mesh->getIndex(v)] = {
|
externalForces[mesh->getIndex(v)] = {
|
||||||
nodeExternalForce[0], nodeExternalForce[1], nodeExternalForce[2]};
|
nodeExternalForce[0], nodeExternalForce[1], nodeExternalForce[2]};
|
||||||
|
externalMoments[mesh->getIndex(v)] = {nodeExternalForce[3],
|
||||||
|
nodeExternalForce[4], 0};
|
||||||
}
|
}
|
||||||
polyscope::getCurveNetwork("Deformed edge mesh")
|
polyscope::getCurveNetwork("Deformed edge mesh")
|
||||||
->addNodeVectorQuantity("Internal force", internalForces);
|
->addNodeVectorQuantity("Internal force", internalForces);
|
||||||
|
|
@ -1380,6 +1423,10 @@ void FormFinder::draw(const std::string &screenshotsFolder = {}) {
|
||||||
polyscope::getCurveNetwork("Deformed edge mesh")
|
polyscope::getCurveNetwork("Deformed edge mesh")
|
||||||
->getQuantity("External force")
|
->getQuantity("External force")
|
||||||
->setEnabled(true);
|
->setEnabled(true);
|
||||||
|
polyscope::getCurveNetwork("Deformed edge mesh")
|
||||||
|
->addNodeVectorQuantity("External Moments", externalMoments)
|
||||||
|
->setEnabled(true);
|
||||||
|
|
||||||
polyscope::getCurveNetwork("Deformed edge mesh")
|
polyscope::getCurveNetwork("Deformed edge mesh")
|
||||||
->addNodeScalarQuantity("Internal force norm", internalForcesNorm);
|
->addNodeScalarQuantity("Internal force norm", internalForcesNorm);
|
||||||
polyscope::getCurveNetwork("Deformed edge mesh")
|
polyscope::getCurveNetwork("Deformed edge mesh")
|
||||||
|
|
@ -1651,6 +1698,9 @@ FormFinder::executeSimulation(const SimulationJob &job, const bool &beVerbose,
|
||||||
}
|
}
|
||||||
updateElementalLengths();
|
updateElementalLengths();
|
||||||
|
|
||||||
|
if (mCurrentSimulationStep != 0) {
|
||||||
|
history.stepPulse(*mesh);
|
||||||
|
}
|
||||||
if (mShouldDraw &&
|
if (mShouldDraw &&
|
||||||
mCurrentSimulationStep % mDrawingStep == 0 /* &&
|
mCurrentSimulationStep % mDrawingStep == 0 /* &&
|
||||||
currentSimulationStep > maxDRMIterations*/) {
|
currentSimulationStep > maxDRMIterations*/) {
|
||||||
|
|
@ -1661,11 +1711,15 @@ currentSimulationStep > maxDRMIterations*/) {
|
||||||
// draw(saveTo);
|
// draw(saveTo);
|
||||||
std::cout << "Residual forces norm: " << mesh->totalResidualForcesNorm
|
std::cout << "Residual forces norm: " << mesh->totalResidualForcesNorm
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
|
std::cout << "Kinetic energy:" << mesh->currentTotalKineticEnergy
|
||||||
|
<< std::endl;
|
||||||
|
const auto yValues = history.residualForces;
|
||||||
|
auto xPlot = matplot::linspace(0, yValues.size(), yValues.size());
|
||||||
|
plotHandle = matplot::scatter(xPlot, yValues);
|
||||||
|
const std::string label = "Residual forces";
|
||||||
|
plotHandle->legend_string(label);
|
||||||
draw();
|
draw();
|
||||||
}
|
}
|
||||||
if (mCurrentSimulationStep != 0) {
|
|
||||||
history.stepPulse(*mesh);
|
|
||||||
}
|
|
||||||
// t = t + Dt;
|
// t = t + Dt;
|
||||||
mCurrentSimulationStep++;
|
mCurrentSimulationStep++;
|
||||||
// std::cout << "Kinetic energy:" << mesh.currentTotalKineticEnergy
|
// std::cout << "Kinetic energy:" << mesh.currentTotalKineticEnergy
|
||||||
|
|
@ -1674,7 +1728,10 @@ currentSimulationStep > maxDRMIterations*/) {
|
||||||
// << std::endl;
|
// << std::endl;
|
||||||
if (mesh->previousTotalKineticEnergy > mesh->currentTotalKineticEnergy) {
|
if (mesh->previousTotalKineticEnergy > mesh->currentTotalKineticEnergy) {
|
||||||
if (/*mesh.totalPotentialEnergykN < 10 ||*/
|
if (/*mesh.totalPotentialEnergykN < 10 ||*/
|
||||||
mesh->totalResidualForcesNorm < totalResidualForcesNormThreshold) {
|
// mesh->totalResidualForcesNorm <
|
||||||
|
// totalResidualForcesNormThreshold ||
|
||||||
|
(shouldUseKineticEnergyThreshold &&
|
||||||
|
mesh->currentTotalKineticEnergy < totalKineticEnergyThreshold)) {
|
||||||
if (beVerbose) {
|
if (beVerbose) {
|
||||||
std::cout << "Convergence after " << mCurrentSimulationStep
|
std::cout << "Convergence after " << mCurrentSimulationStep
|
||||||
<< " steps" << std::endl;
|
<< " steps" << std::endl;
|
||||||
|
|
@ -1686,6 +1743,12 @@ currentSimulationStep > maxDRMIterations*/) {
|
||||||
std::cout << "Total potential:" << mesh->totalPotentialEnergykN
|
std::cout << "Total potential:" << mesh->totalPotentialEnergykN
|
||||||
<< " kNm" << std::endl;
|
<< " kNm" << std::endl;
|
||||||
}
|
}
|
||||||
|
if (shouldUseKineticEnergyThreshold) {
|
||||||
|
std::cout << "Warning: Since maximum applied external moment reached "
|
||||||
|
"the kinetic energy of the system was "
|
||||||
|
" used as a convergence criterion"
|
||||||
|
<< std::endl;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|
@ -1721,37 +1784,188 @@ currentSimulationStep > maxDRMIterations*/) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void FormFinder::runUnitTests() {
|
void FormFinder::runUnitTests() {
|
||||||
|
const std::filesystem::path groundOfTruthFolder{
|
||||||
|
"/home/iason/Coding/Libraries/MySources/formFinder_unitTestFiles"};
|
||||||
|
|
||||||
FormFinder formFinder;
|
FormFinder formFinder;
|
||||||
VCGEdgeMesh mesh;
|
formFinder.setTotalResidualForcesNormThreshold(1);
|
||||||
|
|
||||||
|
// First example of the paper
|
||||||
|
VCGEdgeMesh beam;
|
||||||
// const size_t spanGridSize = 11;
|
// const size_t spanGridSize = 11;
|
||||||
// mesh.createSpanGrid(spanGridSize);
|
// mesh.createSpanGrid(spanGridSize);
|
||||||
mesh.loadFromPly("/home/iason/Models/simple_beam_paper_example.ply");
|
beam.loadFromPly(
|
||||||
|
std::filesystem::path(groundOfTruthFolder).append("simpleBeam.ply"));
|
||||||
std::unordered_map<VertexIndex, std::unordered_set<DoFType>> fixedVertices;
|
std::unordered_map<VertexIndex, std::unordered_set<DoFType>> fixedVertices;
|
||||||
fixedVertices[0] = std::unordered_set<DoFType>{0, 1, 2, 3};
|
fixedVertices[0] = std::unordered_set<DoFType>{0, 1, 2, 3};
|
||||||
fixedVertices[mesh.VN() - 1] = std::unordered_set<DoFType>{1, 2};
|
fixedVertices[beam.VN() - 1] = std::unordered_set<DoFType>{1, 2};
|
||||||
std::unordered_map<VertexIndex, Vector6d> nodalForces{
|
std::unordered_map<VertexIndex, Vector6d> nodalForces{
|
||||||
{2, Vector6d({0, 1000, 1000, 0, 0, 0})}};
|
{2, Vector6d({0, 1000, 1000, 0, 0, 0})}};
|
||||||
// Forced displacements
|
// Forced displacements
|
||||||
std::unordered_map<size_t, Eigen::Vector3d> nodalForcedDisplacements;
|
std::unordered_map<size_t, Eigen::Vector3d> nodalForcedDisplacements;
|
||||||
nodalForcedDisplacements.insert({mesh.VN() - 1, Eigen::Vector3d(-0.2, 0, 0)});
|
nodalForcedDisplacements.insert({beam.VN() - 1, Eigen::Vector3d(-0.2, 0, 0)});
|
||||||
|
|
||||||
SimulationJob beamSimulationJob{
|
SimulationJob beamSimulationJob{
|
||||||
std::make_shared<SimulationMesh>(mesh),
|
std::make_shared<SimulationMesh>(beam),
|
||||||
// SimulationJob::constructFixedVerticesSpanGrid(spanGridSize,
|
// SimulationJob::constructFixedVerticesSpanGrid(spanGridSize,
|
||||||
// mesh.VN()),
|
// mesh.VN()),
|
||||||
fixedVertices, nodalForces, nodalForcedDisplacements};
|
fixedVertices, nodalForces, nodalForcedDisplacements};
|
||||||
beamSimulationJob.mesh->setBeamMaterial(0.3, 200);
|
beamSimulationJob.mesh->setBeamMaterial(0.3, 200);
|
||||||
assert(typeid(CrossSectionType) == typeid(CylindricalBeamDimensions));
|
assert(CrossSectionType::name == CylindricalBeamDimensions::name);
|
||||||
beamSimulationJob.mesh->setBeamCrossSection(CrossSectionType{0.03, 0.026});
|
|
||||||
SimulationResults beamSimulationResults =
|
|
||||||
formFinder.executeSimulation(beamSimulationJob, true, false);
|
|
||||||
|
|
||||||
const bool testSuccessful =
|
beamSimulationJob.mesh->setBeamCrossSection(CrossSectionType{0.03, 0.026});
|
||||||
beamSimulationResults.displacements[2][0] - (-0.09556) < 1e-5 &&
|
SimulationResults simpleBeam_simulationResults =
|
||||||
beamSimulationResults.displacements[2][1] - 0.40666 < 1e-5 &&
|
formFinder.executeSimulation(beamSimulationJob, false, true);
|
||||||
beamSimulationResults.displacements[2][2] - 0.40666 < 1e-5;
|
simpleBeam_simulationResults.label = "SimpleBeam";
|
||||||
assert(testSuccessful);
|
simpleBeam_simulationResults.save();
|
||||||
beamSimulationResults.simulationLabel = "Beam";
|
const std::string simpleBeamGroundOfTruthBinaryFilename =
|
||||||
beamSimulationResults.registerForDrawing(beamSimulationJob);
|
std::filesystem::path(groundOfTruthFolder)
|
||||||
polyscope::show();
|
.append("SimpleBeam_displacements.eigenBin");
|
||||||
|
assert(std::filesystem::exists(
|
||||||
|
std::filesystem::path(simpleBeamGroundOfTruthBinaryFilename)));
|
||||||
|
Eigen::MatrixXd simpleBeam_groundOfTruthDisplacements;
|
||||||
|
Eigen::read_binary(simpleBeamGroundOfTruthBinaryFilename,
|
||||||
|
simpleBeam_groundOfTruthDisplacements);
|
||||||
|
if (!simpleBeam_simulationResults.isEqual(
|
||||||
|
simpleBeam_groundOfTruthDisplacements)) {
|
||||||
|
std::cerr << "Error:Beam simulation produces wrong results." << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Second example of the paper
|
||||||
|
VCGEdgeMesh shortSpanGrid;
|
||||||
|
// const size_t spanGridSize = 11;
|
||||||
|
// mesh.createSpanGrid(spanGridSize);
|
||||||
|
shortSpanGrid.loadFromPly(std::filesystem::path(groundOfTruthFolder)
|
||||||
|
.append("shortSpanGridshell.ply")
|
||||||
|
.string());
|
||||||
|
|
||||||
|
fixedVertices.clear();
|
||||||
|
//// Corner nodes
|
||||||
|
fixedVertices[0] = std::unordered_set<DoFType>{2};
|
||||||
|
fixedVertices[4] = std::unordered_set<DoFType>{2};
|
||||||
|
fixedVertices[16] = std::unordered_set<DoFType>{2};
|
||||||
|
fixedVertices[20] = std::unordered_set<DoFType>{2};
|
||||||
|
//// Center node
|
||||||
|
fixedVertices[10] = std::unordered_set<DoFType>{0, 1, 3, 4, 5};
|
||||||
|
|
||||||
|
nodalForcedDisplacements.clear();
|
||||||
|
nodalForcedDisplacements.insert({{0, Eigen::Vector3d(0.1, 0.1, 0)},
|
||||||
|
{4, Eigen::Vector3d(-0.1, 0.1, 0)},
|
||||||
|
{16, Eigen::Vector3d(0.1, -0.1, 0)},
|
||||||
|
{20, Eigen::Vector3d(-0.1, -0.1, 0)}});
|
||||||
|
|
||||||
|
SimulationJob shortSpanGridshellSimulationJob{
|
||||||
|
std::make_shared<SimulationMesh>(shortSpanGrid),
|
||||||
|
fixedVertices,
|
||||||
|
{},
|
||||||
|
nodalForcedDisplacements};
|
||||||
|
shortSpanGridshellSimulationJob.mesh->setBeamMaterial(0.3, 200);
|
||||||
|
assert(typeid(CrossSectionType) == typeid(CylindricalBeamDimensions));
|
||||||
|
shortSpanGridshellSimulationJob.mesh->setBeamCrossSection(
|
||||||
|
CrossSectionType{0.03, 0.026});
|
||||||
|
SimulationResults shortSpanGridshellSimulationResults =
|
||||||
|
formFinder.executeSimulation(shortSpanGridshellSimulationJob, false,
|
||||||
|
false);
|
||||||
|
shortSpanGridshellSimulationResults.label = "ShortSpanGridshell";
|
||||||
|
shortSpanGridshellSimulationResults.save();
|
||||||
|
|
||||||
|
const std::string groundOfTruthBinaryFilename =
|
||||||
|
std::filesystem::path(groundOfTruthFolder)
|
||||||
|
.append("ShortSpanGridshell_displacements.eigenBin")
|
||||||
|
.string();
|
||||||
|
assert(std::filesystem::exists(
|
||||||
|
std::filesystem::path(groundOfTruthBinaryFilename)));
|
||||||
|
Eigen::MatrixXd shortSpanGridshell_groundOfTruthDisplacements;
|
||||||
|
Eigen::read_binary(groundOfTruthBinaryFilename,
|
||||||
|
shortSpanGridshell_groundOfTruthDisplacements);
|
||||||
|
// shortSpanGridshellSimulationResults.registerForDrawing(
|
||||||
|
// shortSpanGridshellSimulationJob);
|
||||||
|
// polyscope::show();
|
||||||
|
assert(shortSpanGridshellSimulationResults.isEqual(
|
||||||
|
shortSpanGridshell_groundOfTruthDisplacements));
|
||||||
|
if (!shortSpanGridshellSimulationResults.isEqual(
|
||||||
|
shortSpanGridshell_groundOfTruthDisplacements)) {
|
||||||
|
std::cerr << "Error:Short span simulation produces wrong results."
|
||||||
|
<< std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Third example of the paper
|
||||||
|
VCGEdgeMesh longSpanGrid;
|
||||||
|
longSpanGrid.loadFromPly(std::filesystem::path(groundOfTruthFolder)
|
||||||
|
.append("longSpanGridshell.ply")
|
||||||
|
.string());
|
||||||
|
const size_t spanGridSize = 11;
|
||||||
|
|
||||||
|
fixedVertices.clear();
|
||||||
|
for (size_t vi = 0; vi < spanGridSize - 1; vi++) {
|
||||||
|
fixedVertices[vi] = {0, 2};
|
||||||
|
}
|
||||||
|
for (size_t vi = longSpanGrid.VN() - 1 - (spanGridSize - 2);
|
||||||
|
vi < longSpanGrid.VN(); vi++) {
|
||||||
|
fixedVertices[vi] = {0, 2};
|
||||||
|
}
|
||||||
|
for (size_t vi = spanGridSize - 1;
|
||||||
|
vi < longSpanGrid.VN() - 1 - (spanGridSize - 2) - spanGridSize + 1;
|
||||||
|
vi += spanGridSize + 1) {
|
||||||
|
fixedVertices[vi] = {1, 2};
|
||||||
|
fixedVertices[vi + spanGridSize] = {1, 2};
|
||||||
|
}
|
||||||
|
|
||||||
|
nodalForcedDisplacements.clear();
|
||||||
|
const size_t horizontalOffset = std::floor((spanGridSize - 2) / 2);
|
||||||
|
nodalForcedDisplacements.insert(
|
||||||
|
{{horizontalOffset, Eigen::Vector3d(0, 0.3, 0)},
|
||||||
|
{horizontalOffset + 1, Eigen::Vector3d(0, 0.3, 0)},
|
||||||
|
{spanGridSize * (spanGridSize + 1) - 2 + horizontalOffset,
|
||||||
|
Eigen::Vector3d(0, -0.3, 0)},
|
||||||
|
{spanGridSize * (spanGridSize + 1) - 2 + horizontalOffset + 1,
|
||||||
|
Eigen::Vector3d(0, -0.3, 0)},
|
||||||
|
{std::floor(spanGridSize / 2) * (spanGridSize + 1) - 2,
|
||||||
|
Eigen::Vector3d(0.3, 0, 0)},
|
||||||
|
{(std::floor(spanGridSize / 2) + 1) * (spanGridSize + 1) - 2,
|
||||||
|
Eigen::Vector3d(0.3, 0, 0)},
|
||||||
|
{std::floor(spanGridSize / 2) * (spanGridSize + 1) - 2 + spanGridSize,
|
||||||
|
Eigen::Vector3d(-0.3, 0, 0)},
|
||||||
|
{(std::floor(spanGridSize / 2) + 1) * (spanGridSize + 1) - 2 +
|
||||||
|
spanGridSize,
|
||||||
|
Eigen::Vector3d(-0.3, 0, 0)}});
|
||||||
|
|
||||||
|
SimulationJob longSpanGridshell_simulationJob{
|
||||||
|
std::make_shared<SimulationMesh>(longSpanGrid),
|
||||||
|
fixedVertices,
|
||||||
|
{},
|
||||||
|
nodalForcedDisplacements};
|
||||||
|
longSpanGridshell_simulationJob.mesh->setBeamMaterial(0.3, 200);
|
||||||
|
assert(typeid(CrossSectionType) == typeid(CylindricalBeamDimensions));
|
||||||
|
longSpanGridshell_simulationJob.mesh->setBeamCrossSection(
|
||||||
|
CrossSectionType{0.03, 0.026});
|
||||||
|
SimulationResults longSpanGridshell_simulationResults =
|
||||||
|
formFinder.executeSimulation(longSpanGridshell_simulationJob, false,
|
||||||
|
false);
|
||||||
|
longSpanGridshell_simulationResults.label = "LongSpanGridshell";
|
||||||
|
longSpanGridshell_simulationResults.save();
|
||||||
|
|
||||||
|
const std::string longSpan_groundOfTruthBinaryFilename =
|
||||||
|
std::filesystem::path(groundOfTruthFolder)
|
||||||
|
.append("LongSpanGridshell_displacements.eigenBin")
|
||||||
|
.string();
|
||||||
|
assert(std::filesystem::exists(
|
||||||
|
std::filesystem::path(longSpan_groundOfTruthBinaryFilename)));
|
||||||
|
Eigen::MatrixXd longSpanGridshell_groundOfTruthDisplacements;
|
||||||
|
Eigen::read_binary(longSpan_groundOfTruthBinaryFilename,
|
||||||
|
longSpanGridshell_groundOfTruthDisplacements);
|
||||||
|
assert(longSpanGridshell_simulationResults.isEqual(
|
||||||
|
longSpanGridshell_groundOfTruthDisplacements));
|
||||||
|
if (!longSpanGridshell_simulationResults.isEqual(
|
||||||
|
longSpanGridshell_groundOfTruthDisplacements)) {
|
||||||
|
std::cerr << "Error:Long span simulation produces wrong results."
|
||||||
|
<< std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << "Form finder unit tests succesufully passed." << std::endl;
|
||||||
|
|
||||||
|
// polyscope::show();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,10 @@ private:
|
||||||
const double Dtini{0.1};
|
const double Dtini{0.1};
|
||||||
double Dt{Dtini};
|
double Dt{Dtini};
|
||||||
const double xi{0.9969};
|
const double xi{0.9969};
|
||||||
const double totalResidualForcesNormThreshold{0.01};
|
double totalResidualForcesNormThreshold{0.001};
|
||||||
|
bool shouldUseKineticEnergyThreshold{true};
|
||||||
|
const double totalKineticEnergyThreshold{1e-11};
|
||||||
|
double externalMomentsNorm{0};
|
||||||
size_t mCurrentSimulationStep{0};
|
size_t mCurrentSimulationStep{0};
|
||||||
int mDrawingStep{5};
|
int mDrawingStep{5};
|
||||||
bool mShouldDraw{false};
|
bool mShouldDraw{false};
|
||||||
|
|
@ -188,6 +191,7 @@ public:
|
||||||
inline static const size_t maxDRMIterations{500000};
|
inline static const size_t maxDRMIterations{500000};
|
||||||
|
|
||||||
static void runUnitTests();
|
static void runUnitTests();
|
||||||
|
void setTotalResidualForcesNormThreshold(double value);
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename PointType> PointType Cross(PointType p1, PointType p2) {
|
template <typename PointType> PointType Cross(PointType p1, PointType p2) {
|
||||||
|
|
@ -211,28 +215,4 @@ inline bool TriggerBreakpoint(const VertexIndex &vi, const EdgeIndex &ei) {
|
||||||
return (vi == 1 && ei == 0) || (vi == 9 && ei == 9);
|
return (vi == 1 && ei == 0) || (vi == 9 && ei == 9);
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace Eigen {
|
|
||||||
template <class Matrix>
|
|
||||||
void write_binary(const std::string &filename, const Matrix &matrix) {
|
|
||||||
std::ofstream out(filename,
|
|
||||||
std::ios::out | std::ios::binary | std::ios::trunc);
|
|
||||||
typename Matrix::Index rows = matrix.rows(), cols = matrix.cols();
|
|
||||||
out.write((char *)(&rows), sizeof(typename Matrix::Index));
|
|
||||||
out.write((char *)(&cols), sizeof(typename Matrix::Index));
|
|
||||||
out.write((char *)matrix.data(),
|
|
||||||
rows * cols * sizeof(typename Matrix::Scalar));
|
|
||||||
out.close();
|
|
||||||
}
|
|
||||||
template <class Matrix>
|
|
||||||
void read_binary(const std::string &filename, Matrix &matrix) {
|
|
||||||
std::ifstream in(filename, std::ios::in | std::ios::binary);
|
|
||||||
typename Matrix::Index rows = 0, cols = 0;
|
|
||||||
in.read((char *)(&rows), sizeof(typename Matrix::Index));
|
|
||||||
in.read((char *)(&cols), sizeof(typename Matrix::Index));
|
|
||||||
matrix.resize(rows, cols);
|
|
||||||
in.read((char *)matrix.data(), rows * cols * sizeof(typename Matrix::Scalar));
|
|
||||||
in.close();
|
|
||||||
}
|
|
||||||
} // namespace Eigen
|
|
||||||
|
|
||||||
#endif // BEAMFORMFINDER_HPP
|
#endif // BEAMFORMFINDER_HPP
|
||||||
|
|
|
||||||
14
edgemesh.cpp
14
edgemesh.cpp
|
|
@ -12,7 +12,17 @@ Eigen::MatrixX3d VCGEdgeMesh::getEigenEdgeNormals() const {
|
||||||
return eigenEdgeNormals;
|
return eigenEdgeNormals;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VCGEdgeMesh::savePly(const std::string plyFilename) {}
|
bool VCGEdgeMesh::savePly(const std::string plyFilename) {
|
||||||
|
unsigned int mask = 0;
|
||||||
|
mask |= nanoply::NanoPlyWrapper<VCGEdgeMesh>::IO_VERTCOORD;
|
||||||
|
mask |= nanoply::NanoPlyWrapper<VCGEdgeMesh>::IO_EDGEINDEX;
|
||||||
|
mask |= nanoply::NanoPlyWrapper<VCGEdgeMesh>::IO_VERTNORMAL;
|
||||||
|
if (nanoply::NanoPlyWrapper<VCGEdgeMesh>::SaveModel(
|
||||||
|
plyFilename.c_str(), *this, mask, false) != 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void VCGEdgeMesh::GeneratedRegularSquaredPattern(
|
void VCGEdgeMesh::GeneratedRegularSquaredPattern(
|
||||||
const double angleDeg, std::vector<std::vector<vcg::Point2d>> &pattern,
|
const double angleDeg, std::vector<std::vector<vcg::Point2d>> &pattern,
|
||||||
|
|
@ -90,7 +100,7 @@ bool VCGEdgeMesh::createSpanGrid(const size_t squareGridDimension) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VCGEdgeMesh::createSpanGrid(const size_t desiredWidth,
|
bool VCGEdgeMesh::createSpanGrid(const size_t desiredWidth,
|
||||||
const size_t desiredHeight) {
|
const size_t desiredHeight) {
|
||||||
std::cout << "Grid of dimensions:" << desiredWidth << "," << desiredHeight
|
std::cout << "Grid of dimensions:" << desiredWidth << "," << desiredHeight
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
const VCGEdgeMesh::CoordType n(0, 0, 1);
|
const VCGEdgeMesh::CoordType n(0, 0, 1);
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,8 @@
|
||||||
|
|
||||||
struct Element;
|
struct Element;
|
||||||
struct Node;
|
struct Node;
|
||||||
using CrossSectionType = RectangularBeamDimensions;
|
// using CrossSectionType = RectangularBeamDimensions;
|
||||||
// using CrossSectionType = CylindricalBeamDimensions;
|
using CrossSectionType = CylindricalBeamDimensions;
|
||||||
|
|
||||||
class SimulationMesh : public VCGEdgeMesh {
|
class SimulationMesh : public VCGEdgeMesh {
|
||||||
private:
|
private:
|
||||||
|
|
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -0,0 +1,374 @@
|
||||||
|
ply
|
||||||
|
format ascii 1.0
|
||||||
|
comment nanoply generated
|
||||||
|
element vertex 140
|
||||||
|
property double x
|
||||||
|
property double y
|
||||||
|
property double z
|
||||||
|
property double nx
|
||||||
|
property double ny
|
||||||
|
property double nz
|
||||||
|
element edge 220
|
||||||
|
property int vertex1
|
||||||
|
property int vertex2
|
||||||
|
end_header
|
||||||
|
1.000000 0.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
2.000000 0.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
3.000000 0.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
4.000000 0.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
5.000000 0.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
6.000000 0.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
7.000000 0.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
8.000000 0.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
9.000000 0.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
10.000000 0.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
0.000000 1.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
1.000000 1.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
2.000000 1.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
3.000000 1.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
4.000000 1.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
5.000000 1.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
6.000000 1.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
7.000000 1.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
8.000000 1.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
9.000000 1.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
10.000000 1.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
11.000000 1.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
0.000000 2.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
1.000000 2.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
2.000000 2.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
3.000000 2.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
4.000000 2.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
5.000000 2.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
6.000000 2.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
7.000000 2.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
8.000000 2.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
9.000000 2.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
10.000000 2.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
11.000000 2.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
0.000000 3.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
1.000000 3.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
2.000000 3.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
3.000000 3.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
4.000000 3.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
5.000000 3.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
6.000000 3.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
7.000000 3.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
8.000000 3.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
9.000000 3.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
10.000000 3.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
11.000000 3.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
0.000000 4.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
1.000000 4.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
2.000000 4.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
3.000000 4.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
4.000000 4.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
5.000000 4.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
6.000000 4.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
7.000000 4.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
8.000000 4.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
9.000000 4.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
10.000000 4.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
11.000000 4.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
0.000000 5.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
1.000000 5.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
2.000000 5.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
3.000000 5.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
4.000000 5.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
5.000000 5.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
6.000000 5.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
7.000000 5.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
8.000000 5.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
9.000000 5.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
10.000000 5.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
11.000000 5.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
0.000000 6.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
1.000000 6.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
2.000000 6.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
3.000000 6.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
4.000000 6.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
5.000000 6.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
6.000000 6.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
7.000000 6.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
8.000000 6.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
9.000000 6.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
10.000000 6.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
11.000000 6.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
0.000000 7.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
1.000000 7.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
2.000000 7.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
3.000000 7.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
4.000000 7.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
5.000000 7.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
6.000000 7.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
7.000000 7.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
8.000000 7.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
9.000000 7.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
10.000000 7.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
11.000000 7.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
0.000000 8.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
1.000000 8.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
2.000000 8.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
3.000000 8.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
4.000000 8.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
5.000000 8.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
6.000000 8.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
7.000000 8.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
8.000000 8.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
9.000000 8.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
10.000000 8.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
11.000000 8.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
0.000000 9.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
1.000000 9.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
2.000000 9.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
3.000000 9.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
4.000000 9.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
5.000000 9.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
6.000000 9.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
7.000000 9.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
8.000000 9.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
9.000000 9.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
10.000000 9.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
11.000000 9.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
0.000000 10.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
1.000000 10.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
2.000000 10.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
3.000000 10.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
4.000000 10.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
5.000000 10.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
6.000000 10.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
7.000000 10.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
8.000000 10.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
9.000000 10.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
10.000000 10.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
11.000000 10.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
1.000000 11.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
2.000000 11.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
3.000000 11.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
4.000000 11.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
5.000000 11.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
6.000000 11.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
7.000000 11.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
8.000000 11.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
9.000000 11.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
10.000000 11.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
|
0 11
|
||||||
|
1 12
|
||||||
|
2 13
|
||||||
|
3 14
|
||||||
|
4 15
|
||||||
|
5 16
|
||||||
|
6 17
|
||||||
|
7 18
|
||||||
|
8 19
|
||||||
|
9 20
|
||||||
|
10 11
|
||||||
|
11 23
|
||||||
|
11 12
|
||||||
|
12 24
|
||||||
|
12 13
|
||||||
|
13 25
|
||||||
|
13 14
|
||||||
|
14 26
|
||||||
|
14 15
|
||||||
|
15 27
|
||||||
|
15 16
|
||||||
|
16 28
|
||||||
|
16 17
|
||||||
|
17 29
|
||||||
|
17 18
|
||||||
|
18 30
|
||||||
|
18 19
|
||||||
|
19 31
|
||||||
|
19 20
|
||||||
|
20 32
|
||||||
|
20 21
|
||||||
|
22 23
|
||||||
|
23 35
|
||||||
|
23 24
|
||||||
|
24 36
|
||||||
|
24 25
|
||||||
|
25 37
|
||||||
|
25 26
|
||||||
|
26 38
|
||||||
|
26 27
|
||||||
|
27 39
|
||||||
|
27 28
|
||||||
|
28 40
|
||||||
|
28 29
|
||||||
|
29 41
|
||||||
|
29 30
|
||||||
|
30 42
|
||||||
|
30 31
|
||||||
|
31 43
|
||||||
|
31 32
|
||||||
|
32 44
|
||||||
|
32 33
|
||||||
|
34 35
|
||||||
|
35 47
|
||||||
|
35 36
|
||||||
|
36 48
|
||||||
|
36 37
|
||||||
|
37 49
|
||||||
|
37 38
|
||||||
|
38 50
|
||||||
|
38 39
|
||||||
|
39 51
|
||||||
|
39 40
|
||||||
|
40 52
|
||||||
|
40 41
|
||||||
|
41 53
|
||||||
|
41 42
|
||||||
|
42 54
|
||||||
|
42 43
|
||||||
|
43 55
|
||||||
|
43 44
|
||||||
|
44 56
|
||||||
|
44 45
|
||||||
|
46 47
|
||||||
|
47 59
|
||||||
|
47 48
|
||||||
|
48 60
|
||||||
|
48 49
|
||||||
|
49 61
|
||||||
|
49 50
|
||||||
|
50 62
|
||||||
|
50 51
|
||||||
|
51 63
|
||||||
|
51 52
|
||||||
|
52 64
|
||||||
|
52 53
|
||||||
|
53 65
|
||||||
|
53 54
|
||||||
|
54 66
|
||||||
|
54 55
|
||||||
|
55 67
|
||||||
|
55 56
|
||||||
|
56 68
|
||||||
|
56 57
|
||||||
|
58 59
|
||||||
|
59 71
|
||||||
|
59 60
|
||||||
|
60 72
|
||||||
|
60 61
|
||||||
|
61 73
|
||||||
|
61 62
|
||||||
|
62 74
|
||||||
|
62 63
|
||||||
|
63 75
|
||||||
|
63 64
|
||||||
|
64 76
|
||||||
|
64 65
|
||||||
|
65 77
|
||||||
|
65 66
|
||||||
|
66 78
|
||||||
|
66 67
|
||||||
|
67 79
|
||||||
|
67 68
|
||||||
|
68 80
|
||||||
|
68 69
|
||||||
|
70 71
|
||||||
|
71 83
|
||||||
|
71 72
|
||||||
|
72 84
|
||||||
|
72 73
|
||||||
|
73 85
|
||||||
|
73 74
|
||||||
|
74 86
|
||||||
|
74 75
|
||||||
|
75 87
|
||||||
|
75 76
|
||||||
|
76 88
|
||||||
|
76 77
|
||||||
|
77 89
|
||||||
|
77 78
|
||||||
|
78 90
|
||||||
|
78 79
|
||||||
|
79 91
|
||||||
|
79 80
|
||||||
|
80 92
|
||||||
|
80 81
|
||||||
|
82 83
|
||||||
|
83 95
|
||||||
|
83 84
|
||||||
|
84 96
|
||||||
|
84 85
|
||||||
|
85 97
|
||||||
|
85 86
|
||||||
|
86 98
|
||||||
|
86 87
|
||||||
|
87 99
|
||||||
|
87 88
|
||||||
|
88 100
|
||||||
|
88 89
|
||||||
|
89 101
|
||||||
|
89 90
|
||||||
|
90 102
|
||||||
|
90 91
|
||||||
|
91 103
|
||||||
|
91 92
|
||||||
|
92 104
|
||||||
|
92 93
|
||||||
|
94 95
|
||||||
|
95 107
|
||||||
|
95 96
|
||||||
|
96 108
|
||||||
|
96 97
|
||||||
|
97 109
|
||||||
|
97 98
|
||||||
|
98 110
|
||||||
|
98 99
|
||||||
|
99 111
|
||||||
|
99 100
|
||||||
|
100 112
|
||||||
|
100 101
|
||||||
|
101 113
|
||||||
|
101 102
|
||||||
|
102 114
|
||||||
|
102 103
|
||||||
|
103 115
|
||||||
|
103 104
|
||||||
|
104 116
|
||||||
|
104 105
|
||||||
|
106 107
|
||||||
|
107 119
|
||||||
|
107 108
|
||||||
|
108 120
|
||||||
|
108 109
|
||||||
|
109 121
|
||||||
|
109 110
|
||||||
|
110 122
|
||||||
|
110 111
|
||||||
|
111 123
|
||||||
|
111 112
|
||||||
|
112 124
|
||||||
|
112 113
|
||||||
|
113 125
|
||||||
|
113 114
|
||||||
|
114 126
|
||||||
|
114 115
|
||||||
|
115 127
|
||||||
|
115 116
|
||||||
|
116 128
|
||||||
|
116 117
|
||||||
|
118 119
|
||||||
|
119 130
|
||||||
|
119 120
|
||||||
|
120 131
|
||||||
|
120 121
|
||||||
|
121 132
|
||||||
|
121 122
|
||||||
|
122 133
|
||||||
|
122 123
|
||||||
|
123 134
|
||||||
|
123 124
|
||||||
|
124 135
|
||||||
|
124 125
|
||||||
|
125 136
|
||||||
|
125 126
|
||||||
|
126 137
|
||||||
|
126 127
|
||||||
|
127 138
|
||||||
|
127 128
|
||||||
|
128 139
|
||||||
|
128 129
|
||||||
|
|
@ -0,0 +1,69 @@
|
||||||
|
ply
|
||||||
|
format ascii 1.0
|
||||||
|
element vertex 21 { define "vertex" element, 8 of them in file }
|
||||||
|
property float x { vertex contains float "x" coordinate }
|
||||||
|
property float y { y coordinate is also a vertex property }
|
||||||
|
property float z { z coordinate, too }
|
||||||
|
property float nx
|
||||||
|
property float ny
|
||||||
|
property float nz
|
||||||
|
element edge 24 { there are 6 "face" elements in the file }
|
||||||
|
property int vertex1
|
||||||
|
property int vertex2
|
||||||
|
property list uchar float beam_dimensions
|
||||||
|
property list uchar float beam_material {poissons ratio , young's modulus in GPascal}
|
||||||
|
end_header
|
||||||
|
|
||||||
|
0 0 0 0 0 1
|
||||||
|
1 0 0 0 0 1
|
||||||
|
2 0 0 0 0 1
|
||||||
|
3 0 0 0 0 1
|
||||||
|
4 0 0 0 0 1
|
||||||
|
0 1 0 0 0 1
|
||||||
|
2 1 0 0 0 1
|
||||||
|
4 1 0 0 0 1
|
||||||
|
0 2 0 0 0 1
|
||||||
|
1 2 0 0 0 1
|
||||||
|
2 2 0 0 0 1
|
||||||
|
3 2 0 0 0 1
|
||||||
|
4 2 0 0 0 1
|
||||||
|
0 3 0 0 0 1
|
||||||
|
2 3 0 0 0 1
|
||||||
|
4 3 0 0 0 1
|
||||||
|
0 4 0 0 0 1
|
||||||
|
1 4 0 0 0 1
|
||||||
|
2 4 0 0 0 1
|
||||||
|
3 4 0 0 0 1
|
||||||
|
4 4 0 0 0 1
|
||||||
|
|
||||||
|
0 1 2 0.03 0.026 2 0.3 200
|
||||||
|
1 2 2 0.03 0.026 2 0.3 200
|
||||||
|
2 3 2 0.03 0.026 2 0.3 200
|
||||||
|
3 4 2 0.03 0.026 2 0.3 200
|
||||||
|
|
||||||
|
0 5 2 0.03 0.026 2 0.3 200
|
||||||
|
2 6 2 0.03 0.026 2 0.3 200
|
||||||
|
4 7 2 0.03 0.026 2 0.3 200
|
||||||
|
|
||||||
|
|
||||||
|
8 9 2 0.03 0.026 2 0.3 200
|
||||||
|
9 10 2 0.03 0.026 2 0.3 200
|
||||||
|
10 11 2 0.03 0.026 2 0.3 200
|
||||||
|
11 12 2 0.03 0.026 2 0.3 200
|
||||||
|
|
||||||
|
8 5 2 0.03 0.026 2 0.3 200
|
||||||
|
10 6 2 0.03 0.026 2 0.3 200
|
||||||
|
12 7 2 0.03 0.026 2 0.3 200
|
||||||
|
|
||||||
|
8 13 2 0.03 0.026 2 0.3 200
|
||||||
|
10 14 2 0.03 0.026 2 0.3 200
|
||||||
|
12 15 2 0.03 0.026 2 0.3 200
|
||||||
|
|
||||||
|
16 13 2 0.03 0.026 2 0.3 200
|
||||||
|
18 14 2 0.03 0.026 2 0.3 200
|
||||||
|
20 15 2 0.03 0.026 2 0.3 200
|
||||||
|
|
||||||
|
16 17 2 0.03 0.026 2 0.3 200
|
||||||
|
17 18 2 0.03 0.026 2 0.3 200
|
||||||
|
18 19 2 0.03 0.026 2 0.3 200
|
||||||
|
19 20 2 0.03 0.026 2 0.3 200
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
ply
|
||||||
|
format ascii 1.0
|
||||||
|
element vertex 5 { define "vertex" element, 8 of them in file }
|
||||||
|
property float x { vertex contains float "x" coordinate }
|
||||||
|
property float y { y coordinate is also a vertex property }
|
||||||
|
property float z { z coordinate, too }
|
||||||
|
property float nx
|
||||||
|
property float ny
|
||||||
|
property float nz
|
||||||
|
|
||||||
|
element edge 4 { there are 6 "face" elements in the file }
|
||||||
|
property int vertex1
|
||||||
|
property int vertex2
|
||||||
|
property list uchar float beam_dimensions
|
||||||
|
property list uchar float beam_material {poissons ratio , young's modulus in GPascal}
|
||||||
|
end_header
|
||||||
|
|
||||||
|
0 0 0 0 0 1
|
||||||
|
1 0 0 0 0 1
|
||||||
|
2 0 0 0 0 1
|
||||||
|
3 0 0 0 0 1
|
||||||
|
4 0 0 0 0 1
|
||||||
|
|
||||||
|
0 1 2 0.03 0.026 2 0.3 200
|
||||||
|
1 2 2 0.03 0.026 2 0.3 200
|
||||||
|
2 3 2 0.03 0.026 2 0.3 200
|
||||||
|
3 4 2 0.03 0.026 2 0.3 200
|
||||||
|
|
@ -73,7 +73,7 @@ struct SimulationResultsReporter {
|
||||||
for (const SimulationResults &simulationResult : results) {
|
for (const SimulationResults &simulationResult : results) {
|
||||||
const auto simulationResultPath =
|
const auto simulationResultPath =
|
||||||
std::filesystem::path(reportFolderPath)
|
std::filesystem::path(reportFolderPath)
|
||||||
.append(simulationResult.simulationLabel);
|
.append(simulationResult.label);
|
||||||
std::filesystem::create_directory(simulationResultPath.string());
|
std::filesystem::create_directory(simulationResultPath.string());
|
||||||
|
|
||||||
createPlots(simulationResult.history, simulationResultPath.string(),
|
createPlots(simulationResult.history, simulationResultPath.string(),
|
||||||
|
|
|
||||||
|
|
@ -98,33 +98,37 @@ struct SimulationJob {
|
||||||
->setEnabled(true);
|
->setEnabled(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
static std::unordered_map<size_t, std::unordered_set<int>>
|
|
||||||
constructFixedVerticesSpanGrid(const size_t &spanGridSize,
|
|
||||||
const size_t &gridVertices) {
|
|
||||||
std::unordered_map<size_t, std::unordered_set<int>> fixedVertices;
|
|
||||||
for (size_t vi = 0; vi < spanGridSize - 1; vi++) {
|
|
||||||
fixedVertices[vi] = {0, 1, 2};
|
|
||||||
}
|
|
||||||
for (size_t vi = gridVertices - 1 - (spanGridSize - 2); vi < gridVertices;
|
|
||||||
vi++) {
|
|
||||||
fixedVertices[vi] = {0, 1, 2};
|
|
||||||
}
|
|
||||||
for (size_t vi = spanGridSize - 1;
|
|
||||||
vi < gridVertices - 1 - (spanGridSize - 2) - spanGridSize + 1;
|
|
||||||
vi += spanGridSize + 1) {
|
|
||||||
fixedVertices[vi] = {0, 1, 2};
|
|
||||||
fixedVertices[vi + spanGridSize] = {0, 1, 2};
|
|
||||||
}
|
|
||||||
|
|
||||||
return fixedVertices;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
namespace Eigen {
|
||||||
|
template <class Matrix>
|
||||||
|
void write_binary(const std::string &filename, const Matrix &matrix) {
|
||||||
|
std::ofstream out(filename,
|
||||||
|
std::ios::out | std::ios::binary | std::ios::trunc);
|
||||||
|
typename Matrix::Index rows = matrix.rows(), cols = matrix.cols();
|
||||||
|
out.write((char *)(&rows), sizeof(typename Matrix::Index));
|
||||||
|
out.write((char *)(&cols), sizeof(typename Matrix::Index));
|
||||||
|
out.write((char *)matrix.data(),
|
||||||
|
rows * cols * sizeof(typename Matrix::Scalar));
|
||||||
|
out.close();
|
||||||
|
}
|
||||||
|
template <class Matrix>
|
||||||
|
void read_binary(const std::string &filename, Matrix &matrix) {
|
||||||
|
std::ifstream in(filename, std::ios::in | std::ios::binary);
|
||||||
|
typename Matrix::Index rows = 0, cols = 0;
|
||||||
|
in.read((char *)(&rows), sizeof(typename Matrix::Index));
|
||||||
|
in.read((char *)(&cols), sizeof(typename Matrix::Index));
|
||||||
|
matrix.resize(rows, cols);
|
||||||
|
in.read((char *)matrix.data(), rows * cols * sizeof(typename Matrix::Scalar));
|
||||||
|
in.close();
|
||||||
|
}
|
||||||
|
} // namespace Eigen
|
||||||
|
|
||||||
struct SimulationResults {
|
struct SimulationResults {
|
||||||
SimulationHistory history;
|
SimulationHistory history;
|
||||||
std::vector<Vector6d> displacements;
|
std::vector<Vector6d> displacements;
|
||||||
double executionTime{0};
|
double executionTime{0};
|
||||||
std::string simulationLabel{"NoLabel"};
|
std::string label{"NoLabel"};
|
||||||
|
|
||||||
void registerForDrawing(const SimulationJob &job) const {
|
void registerForDrawing(const SimulationJob &job) const {
|
||||||
polyscope::options::groundPlaneEnabled = false;
|
polyscope::options::groundPlaneEnabled = false;
|
||||||
|
|
@ -136,12 +140,12 @@ struct SimulationResults {
|
||||||
} /* else {
|
} /* else {
|
||||||
polyscope::removeAllStructures();
|
polyscope::removeAllStructures();
|
||||||
}*/
|
}*/
|
||||||
const std::string undeformedMeshName = "Undeformed_" + simulationLabel;
|
const std::string undeformedMeshName = "Undeformed_" + label;
|
||||||
polyscope::registerCurveNetwork(undeformedMeshName,
|
polyscope::registerCurveNetwork(undeformedMeshName,
|
||||||
job.mesh->getEigenVertices(),
|
job.mesh->getEigenVertices(),
|
||||||
job.mesh->getEigenEdges());
|
job.mesh->getEigenEdges());
|
||||||
|
|
||||||
const std::string deformedMeshName = "Deformed_" + simulationLabel;
|
const std::string deformedMeshName = "Deformed_" + label;
|
||||||
polyscope::registerCurveNetwork(deformedMeshName,
|
polyscope::registerCurveNetwork(deformedMeshName,
|
||||||
job.mesh->getEigenVertices(),
|
job.mesh->getEigenVertices(),
|
||||||
job.mesh->getEigenEdges());
|
job.mesh->getEigenEdges());
|
||||||
|
|
@ -214,6 +218,24 @@ struct SimulationResults {
|
||||||
|
|
||||||
// polyscope::show();
|
// polyscope::show();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void save() {
|
||||||
|
const std::string filename(label + "_displacements.eigenBin");
|
||||||
|
|
||||||
|
Eigen::MatrixXd m = Utilities::toEigenMatrix(displacements);
|
||||||
|
Eigen::write_binary(filename, m);
|
||||||
|
}
|
||||||
|
|
||||||
|
// The comparison of the results happens comparing the 6-dof nodal
|
||||||
|
// displacements
|
||||||
|
bool isEqual(const Eigen::MatrixXd &nodalDisplacements) {
|
||||||
|
assert(nodalDisplacements.cols() == 6);
|
||||||
|
Eigen::MatrixXd eigenDisplacements =
|
||||||
|
Utilities::toEigenMatrix(this->displacements);
|
||||||
|
const double errorNorm = (eigenDisplacements - nodalDisplacements).norm();
|
||||||
|
return errorNorm < 1e-10;
|
||||||
|
// return eigenDisplacements.isApprox(nodalDisplacements);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // SIMULATIONHISTORY_HPP
|
#endif // SIMULATIONHISTORY_HPP
|
||||||
|
|
|
||||||
102
utilities.hpp
102
utilities.hpp
|
|
@ -6,53 +6,6 @@
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <regex>
|
#include <regex>
|
||||||
|
|
||||||
namespace Utilities {
|
|
||||||
inline void parseIntegers(const std::string &str, std::vector<size_t> &result) {
|
|
||||||
typedef std::regex_iterator<std::string::const_iterator> re_iterator;
|
|
||||||
typedef re_iterator::value_type re_iterated;
|
|
||||||
|
|
||||||
std::regex re("(\\d+)");
|
|
||||||
|
|
||||||
re_iterator rit(str.begin(), str.end(), re);
|
|
||||||
re_iterator rend;
|
|
||||||
|
|
||||||
std::transform(rit, rend, std::back_inserter(result),
|
|
||||||
[](const re_iterated &it) { return std::stoi(it[1]); });
|
|
||||||
}
|
|
||||||
|
|
||||||
// std::string convertToLowercase(const std::string &s) {
|
|
||||||
// std::string lowercase;
|
|
||||||
// std::transform(s.begin(), s.end(), lowercase.begin(),
|
|
||||||
// [](unsigned char c) { return std::tolower(c); });
|
|
||||||
// return lowercase;
|
|
||||||
//}
|
|
||||||
// bool hasExtension(const std::string &filename, const std::string &extension)
|
|
||||||
// {
|
|
||||||
// const std::filesystem::path path(filename);
|
|
||||||
// if (!path.has_extension()) {
|
|
||||||
// std::cerr << "Error: No file extension found in " << filename <<
|
|
||||||
// std::endl; return false;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// const std::string detectedExtension = path.extension().string();
|
|
||||||
|
|
||||||
// if (convertToLowercase(detectedExtension) != convertToLowercase(extension))
|
|
||||||
// {
|
|
||||||
// std::cerr << "Error: detected extension is " + detectedExtension +
|
|
||||||
// " and not " + extension
|
|
||||||
// << std::endl;
|
|
||||||
// return false;
|
|
||||||
// }
|
|
||||||
// return true;
|
|
||||||
//}
|
|
||||||
|
|
||||||
} // namespace Utilities
|
|
||||||
|
|
||||||
struct NodalForce {
|
|
||||||
size_t index;
|
|
||||||
size_t dof;
|
|
||||||
double magnitude;
|
|
||||||
};
|
|
||||||
struct Vector6d : public std::array<double, 6> {
|
struct Vector6d : public std::array<double, 6> {
|
||||||
Vector6d() {
|
Vector6d() {
|
||||||
for (size_t i = 0; i < 6; i++) {
|
for (size_t i = 0; i < 6; i++) {
|
||||||
|
|
@ -145,6 +98,61 @@ struct Vector6d : public std::array<double, 6> {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
namespace Utilities {
|
||||||
|
inline void parseIntegers(const std::string &str, std::vector<size_t> &result) {
|
||||||
|
typedef std::regex_iterator<std::string::const_iterator> re_iterator;
|
||||||
|
typedef re_iterator::value_type re_iterated;
|
||||||
|
|
||||||
|
std::regex re("(\\d+)");
|
||||||
|
|
||||||
|
re_iterator rit(str.begin(), str.end(), re);
|
||||||
|
re_iterator rend;
|
||||||
|
|
||||||
|
std::transform(rit, rend, std::back_inserter(result),
|
||||||
|
[](const re_iterated &it) { return std::stoi(it[1]); });
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Eigen::MatrixXd toEigenMatrix(const std::vector<Vector6d> &v) {
|
||||||
|
Eigen::MatrixXd m(v.size(), 6);
|
||||||
|
|
||||||
|
for (size_t vi = 0; vi < v.size(); vi++) {
|
||||||
|
const Vector6d &vec = v[vi];
|
||||||
|
for (size_t i = 0; i < 6; i++) {
|
||||||
|
m(vi, i) = vec[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
|
// std::string convertToLowercase(const std::string &s) {
|
||||||
|
// std::string lowercase;
|
||||||
|
// std::transform(s.begin(), s.end(), lowercase.begin(),
|
||||||
|
// [](unsigned char c) { return std::tolower(c); });
|
||||||
|
// return lowercase;
|
||||||
|
//}
|
||||||
|
// bool hasExtension(const std::string &filename, const std::string &extension)
|
||||||
|
// {
|
||||||
|
// const std::filesystem::path path(filename);
|
||||||
|
// if (!path.has_extension()) {
|
||||||
|
// std::cerr << "Error: No file extension found in " << filename <<
|
||||||
|
// std::endl; return false;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// const std::string detectedExtension = path.extension().string();
|
||||||
|
|
||||||
|
// if (convertToLowercase(detectedExtension) != convertToLowercase(extension))
|
||||||
|
// {
|
||||||
|
// std::cerr << "Error: detected extension is " + detectedExtension +
|
||||||
|
// " and not " + extension
|
||||||
|
// << std::endl;
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
// return true;
|
||||||
|
//}
|
||||||
|
|
||||||
|
} // namespace Utilities
|
||||||
|
|
||||||
// namespace ConfigurationFile {
|
// namespace ConfigurationFile {
|
||||||
|
|
||||||
// inline void getPlyFilename(const std::string jsonFilepath,
|
// inline void getPlyFilename(const std::string jsonFilepath,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue