2020-11-27 11:47:21 +01:00
|
|
|
#ifndef BEAMFORMFINDER_HPP
|
|
|
|
#define BEAMFORMFINDER_HPP
|
|
|
|
|
|
|
|
#include "elementalmesh.hpp"
|
2020-12-03 19:56:03 +01:00
|
|
|
#include "matplot/matplot.h"
|
2020-11-27 11:47:21 +01:00
|
|
|
#include "polyscope/curve_network.h"
|
|
|
|
#include "polyscope/polyscope.h"
|
|
|
|
#include "simulationresult.hpp"
|
|
|
|
#include <Eigen/Dense>
|
|
|
|
#include <filesystem>
|
|
|
|
#include <unordered_set>
|
|
|
|
|
|
|
|
struct SimulationJob;
|
|
|
|
|
|
|
|
enum DoF { Ux = 0, Uy, Uz, Nx, Ny, Nr, NumDoF };
|
|
|
|
using DoFType = int;
|
|
|
|
using EdgeType = VCGEdgeMesh::EdgeType;
|
|
|
|
using VertexType = VCGEdgeMesh::VertexType;
|
|
|
|
|
|
|
|
struct DifferentiateWithRespectTo {
|
|
|
|
const VertexType &v;
|
|
|
|
const DoFType &dofi;
|
|
|
|
};
|
|
|
|
class FormFinder {
|
|
|
|
|
|
|
|
private:
|
|
|
|
const double Dtini{0.1};
|
|
|
|
double Dt{Dtini};
|
|
|
|
const double xi{0.9969};
|
2020-12-03 19:56:03 +01:00
|
|
|
const double totalResidualForcesNormThreshold{10};
|
|
|
|
size_t mCurrentSimulationStep{0};
|
|
|
|
int mDrawingStep{5};
|
|
|
|
bool mShouldDraw{false};
|
|
|
|
matplot::line_handle plotHandle;
|
|
|
|
std::vector<double> plotYValues;
|
|
|
|
|
2020-11-27 11:47:21 +01:00
|
|
|
std::unique_ptr<SimulationMesh> mesh;
|
|
|
|
std::unordered_map<VertexIndex, std::unordered_set<DoFType>>
|
|
|
|
constrainedVertices;
|
|
|
|
SimulationHistory history;
|
|
|
|
// Eigen::Tensor<double, 4> theta3Derivatives;
|
|
|
|
// std::unordered_map<MyKeyType, double, key_hash> theta3Derivatives;
|
|
|
|
bool shouldApplyInitialDistortion = false;
|
|
|
|
std::unordered_set<VertexIndex> rigidSupports;
|
|
|
|
|
|
|
|
void reset();
|
|
|
|
void updateNodalInternalForces(
|
|
|
|
const std::unordered_map<VertexIndex, std::unordered_set<DoFType>>
|
|
|
|
&fixedVertices);
|
|
|
|
void updateNodalExternalForces(
|
|
|
|
const std::unordered_map<VertexIndex, Vector6d> &nodalForces,
|
|
|
|
const std::unordered_map<VertexIndex, std::unordered_set<DoFType>>
|
|
|
|
&fixedVertices);
|
|
|
|
void updateResidualForces();
|
|
|
|
void updateRotationalDisplacements();
|
|
|
|
void updateElementalLengths();
|
|
|
|
|
|
|
|
void updateNodalMasses();
|
|
|
|
|
|
|
|
void updateNodalAccelerations();
|
|
|
|
|
|
|
|
void updateNodalVelocities();
|
|
|
|
|
|
|
|
void updateNodalDisplacements();
|
|
|
|
|
|
|
|
void applyForcedDisplacements(
|
|
|
|
const std::unordered_map<VertexIndex, Eigen::Vector3d>
|
|
|
|
nodalForcedDisplacements);
|
|
|
|
|
2020-12-03 19:56:03 +01:00
|
|
|
Vector6d computeElementTorsionalForce(
|
2020-11-27 11:47:21 +01:00
|
|
|
const Element &element, const Vector6d &displacementDifference,
|
|
|
|
const std::unordered_set<DoFType> &constrainedDof);
|
|
|
|
|
|
|
|
// BeamFormFinder::Vector6d computeElementFirstBendingForce(
|
|
|
|
// const Element &element, const Vector6d &displacementDifference,
|
|
|
|
// const std::unordered_set<gsl::index> &constrainedDof);
|
|
|
|
|
|
|
|
// BeamFormFinder::Vector6d computeElementSecondBendingForce(
|
|
|
|
// const Element &element, const Vector6d &displacementDifference,
|
|
|
|
// const std::unordered_set<gsl::index> &constrainedDof);
|
|
|
|
|
|
|
|
void updateKineticEnergy();
|
|
|
|
|
|
|
|
void resetVelocities();
|
|
|
|
|
|
|
|
SimulationResults computeResults(const SimulationMesh &initialiMesh);
|
|
|
|
|
|
|
|
void updateNodePosition(
|
|
|
|
VertexType &v,
|
|
|
|
const std::unordered_map<VertexIndex, std::unordered_set<DoFType>>
|
|
|
|
&fixedVertices);
|
|
|
|
|
|
|
|
void applyDisplacements(
|
|
|
|
const std::unordered_map<VertexIndex, std::unordered_set<DoFType>>
|
|
|
|
&fixedVertices);
|
|
|
|
|
|
|
|
void draw(const string &screenshotsFolder);
|
|
|
|
|
|
|
|
void
|
|
|
|
updateNodalInternalForce(Vector6d &nodalInternalForce,
|
|
|
|
const Vector6d &elementInternalForce,
|
|
|
|
const std::unordered_set<DoFType> &nodalFixedDof);
|
|
|
|
|
2020-12-03 19:56:03 +01:00
|
|
|
Vector6d computeElementInternalForce(
|
2020-11-27 11:47:21 +01:00
|
|
|
const Element &elem, const Node &n0, const Node &n1,
|
|
|
|
const std::unordered_set<DoFType> &n0ConstrainedDof,
|
|
|
|
const std::unordered_set<DoFType> &n1ConstrainedDof);
|
|
|
|
|
2020-12-03 19:56:03 +01:00
|
|
|
Vector6d computeElementAxialForce(const ::EdgeType &e) const;
|
2020-11-27 11:47:21 +01:00
|
|
|
VectorType computeDisplacementDifferenceDerivative(
|
|
|
|
const EdgeType &e, const DifferentiateWithRespectTo &dui) const;
|
|
|
|
double
|
|
|
|
computeDerivativeElementLength(const EdgeType &e,
|
|
|
|
const DifferentiateWithRespectTo &dui) const;
|
|
|
|
|
|
|
|
VectorType computeDerivativeT1(const EdgeType &e,
|
|
|
|
const DifferentiateWithRespectTo &dui) const;
|
|
|
|
|
|
|
|
VectorType
|
|
|
|
computeDerivativeOfNormal(const VertexType &v,
|
|
|
|
const DifferentiateWithRespectTo &dui) const;
|
|
|
|
|
|
|
|
VectorType computeDerivativeT3(const EdgeType &e,
|
|
|
|
const DifferentiateWithRespectTo &dui) const;
|
|
|
|
|
|
|
|
VectorType computeDerivativeT2(const EdgeType &e,
|
|
|
|
const DifferentiateWithRespectTo &dui) const;
|
|
|
|
|
|
|
|
double computeDerivativeTheta2(const EdgeType &e, const VertexIndex &evi,
|
|
|
|
const VertexIndex &dwrt_evi,
|
|
|
|
const DoFType &dwrt_dofi) const;
|
|
|
|
|
|
|
|
void updateElementalFrames();
|
|
|
|
|
|
|
|
VectorType computeDerivativeOfR(const EdgeType &e,
|
|
|
|
const DifferentiateWithRespectTo &dui) const;
|
|
|
|
|
|
|
|
bool isRigidSupport(const VertexType &v) const;
|
|
|
|
|
|
|
|
static double computeDerivativeOfNorm(const VectorType &x,
|
|
|
|
const VectorType &derivativeOfX);
|
|
|
|
static VectorType computeDerivativeOfCrossProduct(
|
|
|
|
const VectorType &a, const VectorType &derivativeOfA, const VectorType &b,
|
|
|
|
const VectorType &derivativeOfB);
|
|
|
|
|
|
|
|
double computeTheta3(const EdgeType &e, const VertexType &v);
|
|
|
|
double computeDerivativeTheta3(const EdgeType &e, const VertexType &v,
|
|
|
|
const DifferentiateWithRespectTo &dui) const;
|
|
|
|
double computeTotalPotentialEnergy() const;
|
|
|
|
void computeRigidSupports();
|
|
|
|
void updateNormalDerivatives();
|
|
|
|
void updateT1Derivatives();
|
|
|
|
void updateT2Derivatives();
|
|
|
|
void updateT3Derivatives();
|
|
|
|
void updateRDerivatives();
|
|
|
|
|
|
|
|
double computeDerivativeTheta1(const EdgeType &e, const VertexIndex &evi,
|
|
|
|
const VertexIndex &dwrt_evi,
|
|
|
|
const DoFType &dwrt_dofi) const;
|
|
|
|
|
|
|
|
// void updatePositionsOnTheFly(
|
|
|
|
// const std::unordered_map<VertexIndex,
|
|
|
|
// std::unordered_set<gsl::index>>
|
|
|
|
// &fixedVertices);
|
|
|
|
|
|
|
|
void updateResidualForcesOnTheFly(
|
|
|
|
const std::unordered_map<VertexIndex, std::unordered_set<DoFType>>
|
|
|
|
&fixedVertices);
|
|
|
|
|
|
|
|
void updatePositionsOnTheFly(
|
|
|
|
const std::unordered_map<VertexIndex, std::unordered_set<DoFType>>
|
|
|
|
&fixedVertices);
|
|
|
|
|
2020-12-03 19:56:03 +01:00
|
|
|
void updateNodeNormal(
|
|
|
|
VertexType &v,
|
|
|
|
const std::unordered_map<VertexIndex, std::unordered_set<DoFType>>
|
|
|
|
&fixedVertices);
|
|
|
|
|
2020-11-27 11:47:21 +01:00
|
|
|
public:
|
|
|
|
FormFinder();
|
|
|
|
SimulationResults executeSimulation(
|
|
|
|
const SimulationJob &job, const bool &beVerbose = false,
|
|
|
|
const bool &shouldDraw = false,
|
|
|
|
const size_t &maxDRMIterations = FormFinder::maxDRMIterations);
|
|
|
|
inline static const size_t maxDRMIterations{50000};
|
|
|
|
};
|
|
|
|
|
|
|
|
template <typename PointType> PointType Cross(PointType p1, PointType p2) {
|
|
|
|
return p1 ^ p2;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline size_t currentStep{0};
|
|
|
|
inline bool TriggerBreakpoint(const VertexIndex &vi, const EdgeIndex &ei,
|
|
|
|
const DoFType &dofi) {
|
|
|
|
const size_t numberOfVertices = 10;
|
|
|
|
const VertexIndex middleNodeIndex = numberOfVertices / 2;
|
|
|
|
// return vi == middleNodeIndex && dofi == 1;
|
|
|
|
return dofi == 1 && ((vi == 1 && ei == 0) || (vi == 9 && ei == 9));
|
|
|
|
}
|
|
|
|
|
|
|
|
inline bool TriggerBreakpoint(const VertexIndex &vi, const EdgeIndex &ei) {
|
|
|
|
const size_t numberOfVertices = 10;
|
|
|
|
const VertexIndex middleNodeIndex = numberOfVertices / 2;
|
|
|
|
return (vi == middleNodeIndex);
|
|
|
|
// return (vi == 0 || vi == numberOfVertices - 1) && currentStep == 1;
|
|
|
|
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
|