Changed Element properties
This commit is contained in:
parent
d933f92eeb
commit
2e7aa6e1e0
11
beam.hpp
11
beam.hpp
|
|
@ -31,14 +31,13 @@ struct CylindricalBeamDimensions {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ElementMaterial {
|
struct ElementMaterial {
|
||||||
float poissonsRatio;
|
float G; // poisson's ratio
|
||||||
float youngsModulusGPascal;
|
float E; // ym in pascal
|
||||||
ElementMaterial(const float &poissonsRatio, const float &youngsModulusGPascal)
|
ElementMaterial(const float &poissonsRatio, const float &youngsModulus)
|
||||||
: poissonsRatio(poissonsRatio),
|
: G(poissonsRatio), E(youngsModulus) {
|
||||||
youngsModulusGPascal(youngsModulusGPascal) {
|
|
||||||
assert(poissonsRatio <= 0.5 && poissonsRatio >= -1);
|
assert(poissonsRatio <= 0.5 && poissonsRatio >= -1);
|
||||||
}
|
}
|
||||||
ElementMaterial() : poissonsRatio(0.3), youngsModulusGPascal(200) {}
|
ElementMaterial() : G(0.3), E(200 * 1e10) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // BEAM_HPP
|
#endif // BEAM_HPP
|
||||||
|
|
|
||||||
|
|
@ -8,8 +8,6 @@
|
||||||
#include <execution>
|
#include <execution>
|
||||||
#include <omp.h>
|
#include <omp.h>
|
||||||
|
|
||||||
const bool debug = true;
|
|
||||||
|
|
||||||
void FormFinder::runUnitTests() {
|
void FormFinder::runUnitTests() {
|
||||||
const std::filesystem::path groundOfTruthFolder{
|
const std::filesystem::path groundOfTruthFolder{
|
||||||
"/home/iason/Coding/Libraries/MySources/formFinder_unitTestFiles"};
|
"/home/iason/Coding/Libraries/MySources/formFinder_unitTestFiles"};
|
||||||
|
|
@ -36,7 +34,7 @@ void FormFinder::runUnitTests() {
|
||||||
// SimulationJob::constructFixedVerticesSpanGrid(spanGridSize,
|
// SimulationJob::constructFixedVerticesSpanGrid(spanGridSize,
|
||||||
// mesh.VN()),
|
// mesh.VN()),
|
||||||
fixedVertices, nodalForces, nodalForcedDisplacements};
|
fixedVertices, nodalForces, nodalForcedDisplacements};
|
||||||
beamSimulationJob.pMesh->setBeamMaterial(0.3, 200);
|
beamSimulationJob.pMesh->setBeamMaterial(0.3, 200 * 1e10);
|
||||||
assert(CrossSectionType::name == CylindricalBeamDimensions::name);
|
assert(CrossSectionType::name == CylindricalBeamDimensions::name);
|
||||||
|
|
||||||
beamSimulationJob.pMesh->setBeamCrossSection(CrossSectionType{0.03, 0.026});
|
beamSimulationJob.pMesh->setBeamCrossSection(CrossSectionType{0.03, 0.026});
|
||||||
|
|
@ -45,6 +43,8 @@ void FormFinder::runUnitTests() {
|
||||||
settings.xi = 0.9969;
|
settings.xi = 0.9969;
|
||||||
settings.maxDRMIterations = 0;
|
settings.maxDRMIterations = 0;
|
||||||
settings.totalResidualForcesNormThreshold = 1;
|
settings.totalResidualForcesNormThreshold = 1;
|
||||||
|
settings.shouldDraw = true;
|
||||||
|
settings.beVerbose = true;
|
||||||
SimulationResults simpleBeam_simulationResults = formFinder.executeSimulation(
|
SimulationResults simpleBeam_simulationResults = formFinder.executeSimulation(
|
||||||
std::make_shared<SimulationJob>(beamSimulationJob), settings);
|
std::make_shared<SimulationJob>(beamSimulationJob), settings);
|
||||||
simpleBeam_simulationResults.save();
|
simpleBeam_simulationResults.save();
|
||||||
|
|
@ -59,7 +59,7 @@ void FormFinder::runUnitTests() {
|
||||||
if (!simpleBeam_simulationResults.isEqual(
|
if (!simpleBeam_simulationResults.isEqual(
|
||||||
simpleBeam_groundOfTruthDisplacements)) {
|
simpleBeam_groundOfTruthDisplacements)) {
|
||||||
std::cerr << "Error:Beam simulation produces wrong results." << std::endl;
|
std::cerr << "Error:Beam simulation produces wrong results." << std::endl;
|
||||||
return;
|
// return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Second example of the paper
|
// Second example of the paper
|
||||||
|
|
@ -91,7 +91,7 @@ void FormFinder::runUnitTests() {
|
||||||
fixedVertices,
|
fixedVertices,
|
||||||
{},
|
{},
|
||||||
nodalForcedDisplacements};
|
nodalForcedDisplacements};
|
||||||
shortSpanGridshellSimulationJob.pMesh->setBeamMaterial(0.3, 200);
|
shortSpanGridshellSimulationJob.pMesh->setBeamMaterial(0.3, 200 * 1e10);
|
||||||
assert(typeid(CrossSectionType) == typeid(CylindricalBeamDimensions));
|
assert(typeid(CrossSectionType) == typeid(CylindricalBeamDimensions));
|
||||||
shortSpanGridshellSimulationJob.pMesh->setBeamCrossSection(
|
shortSpanGridshellSimulationJob.pMesh->setBeamCrossSection(
|
||||||
CrossSectionType{0.03, 0.026});
|
CrossSectionType{0.03, 0.026});
|
||||||
|
|
@ -169,7 +169,7 @@ void FormFinder::runUnitTests() {
|
||||||
fixedVertices,
|
fixedVertices,
|
||||||
{},
|
{},
|
||||||
nodalForcedDisplacements};
|
nodalForcedDisplacements};
|
||||||
longSpanGridshell_simulationJob.pMesh->setBeamMaterial(0.3, 200);
|
longSpanGridshell_simulationJob.pMesh->setBeamMaterial(0.3, 200 * 1e10);
|
||||||
if (typeid(CrossSectionType) != typeid(CylindricalBeamDimensions)) {
|
if (typeid(CrossSectionType) != typeid(CylindricalBeamDimensions)) {
|
||||||
std::cerr << "A cylindrical cross section is expected for running the "
|
std::cerr << "A cylindrical cross section is expected for running the "
|
||||||
"paper examples."
|
"paper examples."
|
||||||
|
|
@ -752,27 +752,28 @@ double FormFinder::computeTotalPotentialEnergy() const {
|
||||||
const Element &element = mesh->elements[e];
|
const Element &element = mesh->elements[e];
|
||||||
const EdgeIndex ei = mesh->getIndex(e);
|
const EdgeIndex ei = mesh->getIndex(e);
|
||||||
const double e_k = element.length - element.initialLength;
|
const double e_k = element.length - element.initialLength;
|
||||||
const double axialPE = pow(e_k, 2) * element.properties.E *
|
const double axialPE = pow(e_k, 2) * element.properties.material.E *
|
||||||
element.properties.A / (2 * element.initialLength);
|
element.properties.A / (2 * element.initialLength);
|
||||||
const double theta1Diff = element.rotationalDisplacements_jplus1.theta1 -
|
const double theta1Diff = element.rotationalDisplacements_jplus1.theta1 -
|
||||||
element.rotationalDisplacements_j.theta1;
|
element.rotationalDisplacements_j.theta1;
|
||||||
const double torsionalPE = element.properties.G * element.properties.J *
|
const double torsionalPE = element.properties.material.G *
|
||||||
pow(theta1Diff, 2) / (2 * element.initialLength);
|
element.properties.J * pow(theta1Diff, 2) /
|
||||||
|
(2 * element.initialLength);
|
||||||
const double &theta2_j = element.rotationalDisplacements_j.theta2;
|
const double &theta2_j = element.rotationalDisplacements_j.theta2;
|
||||||
const double &theta2_jplus1 = element.rotationalDisplacements_jplus1.theta2;
|
const double &theta2_jplus1 = element.rotationalDisplacements_jplus1.theta2;
|
||||||
const double firstBendingPE_inBracketsTerm = 4 * pow(theta2_j, 2) +
|
const double firstBendingPE_inBracketsTerm = 4 * pow(theta2_j, 2) +
|
||||||
4 * theta2_j * theta2_jplus1 +
|
4 * theta2_j * theta2_jplus1 +
|
||||||
4 * pow(theta2_jplus1, 2);
|
4 * pow(theta2_jplus1, 2);
|
||||||
const double firstBendingPE = firstBendingPE_inBracketsTerm *
|
const double firstBendingPE =
|
||||||
element.properties.E * element.properties.I2 /
|
firstBendingPE_inBracketsTerm * element.properties.material.E *
|
||||||
(2 * element.initialLength);
|
element.properties.I2 / (2 * element.initialLength);
|
||||||
const double &theta3_j = element.rotationalDisplacements_j.theta3;
|
const double &theta3_j = element.rotationalDisplacements_j.theta3;
|
||||||
const double &theta3_jplus1 = element.rotationalDisplacements_jplus1.theta3;
|
const double &theta3_jplus1 = element.rotationalDisplacements_jplus1.theta3;
|
||||||
const double secondBendingPE_inBracketsTerm = 4 * pow(theta3_j, 2) +
|
const double secondBendingPE_inBracketsTerm = 4 * pow(theta3_j, 2) +
|
||||||
4 * theta3_j * theta3_jplus1 +
|
4 * theta3_j * theta3_jplus1 +
|
||||||
4 * pow(theta3_jplus1, 2);
|
4 * pow(theta3_jplus1, 2);
|
||||||
const double secondBendingPE =
|
const double secondBendingPE =
|
||||||
secondBendingPE_inBracketsTerm * 2 * element.properties.E *
|
secondBendingPE_inBracketsTerm * 2 * element.properties.material.E *
|
||||||
element.properties.I3 / element.initialLength;
|
element.properties.I3 / element.initialLength;
|
||||||
|
|
||||||
totalInternalPotentialEnergy +=
|
totalInternalPotentialEnergy +=
|
||||||
|
|
@ -1143,17 +1144,17 @@ void FormFinder::updateNodalMasses() {
|
||||||
const size_t ei = mesh->getIndex(ep);
|
const size_t ei = mesh->getIndex(ep);
|
||||||
const Element &elem = mesh->elements[ep];
|
const Element &elem = mesh->elements[ep];
|
||||||
const double SkTranslational =
|
const double SkTranslational =
|
||||||
elem.properties.E * elem.properties.A / elem.length;
|
elem.properties.material.E * elem.properties.A / elem.length;
|
||||||
translationalSumSk += SkTranslational;
|
translationalSumSk += SkTranslational;
|
||||||
const double lengthToThe3 = std::pow(elem.length, 3);
|
const double lengthToThe3 = std::pow(elem.length, 3);
|
||||||
const double SkRotational_I2 =
|
const long double SkRotational_I2 =
|
||||||
elem.properties.E * elem.properties.I2 /
|
elem.properties.material.E * elem.properties.I2 /
|
||||||
lengthToThe3; // TODO: I2->t2,I3->t3,t1->polar inertia
|
lengthToThe3; // TODO: I2->t2,I3->t3,t1->polar inertia
|
||||||
const double SkRotational_I3 =
|
const long double SkRotational_I3 =
|
||||||
elem.properties.E * elem.properties.I3 /
|
elem.properties.material.E * elem.properties.I3 /
|
||||||
lengthToThe3; // TODO: I2->t2,I3->t3,t1->polar inertia
|
lengthToThe3; // TODO: I2->t2,I3->t3,t1->polar inertia
|
||||||
const double SkRotational_J =
|
const long double SkRotational_J =
|
||||||
elem.properties.E * elem.properties.J /
|
elem.properties.material.E * elem.properties.J /
|
||||||
lengthToThe3; // TODO: I2->t2,I3->t3,t1->polar inertia
|
lengthToThe3; // TODO: I2->t2,I3->t3,t1->polar inertia
|
||||||
rotationalSumSk_I2 += SkRotational_I2;
|
rotationalSumSk_I2 += SkRotational_I2;
|
||||||
rotationalSumSk_I3 += SkRotational_I3;
|
rotationalSumSk_I3 += SkRotational_I3;
|
||||||
|
|
@ -1344,7 +1345,7 @@ void FormFinder::applyDisplacements(
|
||||||
updateNodeNormal(v, fixedVertices);
|
updateNodeNormal(v, fixedVertices);
|
||||||
}
|
}
|
||||||
updateElementalFrames();
|
updateElementalFrames();
|
||||||
if (mSettings.shouldDraw || true) {
|
if (mSettings.shouldDraw) {
|
||||||
mesh->updateEigenEdgeAndVertices();
|
mesh->updateEigenEdgeAndVertices();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1370,9 +1371,15 @@ void FormFinder::applyForcedDisplacements(
|
||||||
VectorType displacementVector(vertexDisplacement(0), vertexDisplacement(1),
|
VectorType displacementVector(vertexDisplacement(0), vertexDisplacement(1),
|
||||||
vertexDisplacement(2));
|
vertexDisplacement(2));
|
||||||
mesh->vert[vi].P() = node.initialLocation + displacementVector;
|
mesh->vert[vi].P() = node.initialLocation + displacementVector;
|
||||||
node.displacements = Vector6d(
|
// node.displacements = Vector6d(
|
||||||
{vertexDisplacement(0), vertexDisplacement(1), vertexDisplacement(2),
|
// {vertexDisplacement(0), vertexDisplacement(1),
|
||||||
node.displacements[3], node.displacements[4], node.displacements[5]});
|
// vertexDisplacement(2),
|
||||||
|
// node.displacements[3], node.displacements[4],
|
||||||
|
// node.displacements[5]});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mSettings.shouldDraw) {
|
||||||
|
mesh->updateEigenEdgeAndVertices();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1447,17 +1454,17 @@ void FormFinder::updatePositionsOnTheFly(
|
||||||
for (const EdgePointer &ep : mesh->nodes[v].incidentElements) {
|
for (const EdgePointer &ep : mesh->nodes[v].incidentElements) {
|
||||||
const Element &elem = mesh->elements[ep];
|
const Element &elem = mesh->elements[ep];
|
||||||
const double SkTranslational =
|
const double SkTranslational =
|
||||||
elem.properties.E * elem.properties.A / elem.length;
|
elem.properties.material.E * elem.properties.A / elem.length;
|
||||||
translationalSumSk += SkTranslational;
|
translationalSumSk += SkTranslational;
|
||||||
const double lengthToThe3 = std::pow(elem.length, 3);
|
const double lengthToThe3 = std::pow(elem.length, 3);
|
||||||
const double SkRotational_I2 =
|
const double SkRotational_I2 =
|
||||||
elem.properties.E * elem.properties.I2 /
|
elem.properties.material.E * elem.properties.I2 /
|
||||||
lengthToThe3; // TODO: I2->t2,I3->t3,t1->polar inertia
|
lengthToThe3; // TODO: I2->t2,I3->t3,t1->polar inertia
|
||||||
const double SkRotational_I3 =
|
const double SkRotational_I3 =
|
||||||
elem.properties.E * elem.properties.I3 /
|
elem.properties.material.E * elem.properties.I3 /
|
||||||
lengthToThe3; // TODO: I2->t2,I3->t3,t1->polar inertia
|
lengthToThe3; // TODO: I2->t2,I3->t3,t1->polar inertia
|
||||||
const double SkRotational_J =
|
const double SkRotational_J =
|
||||||
elem.properties.E * elem.properties.J /
|
elem.properties.material.E * elem.properties.J /
|
||||||
lengthToThe3; // TODO: I2->t2,I3->t3,t1->polar inertia
|
lengthToThe3; // TODO: I2->t2,I3->t3,t1->polar inertia
|
||||||
rotationalSumSk_I2 += SkRotational_I2;
|
rotationalSumSk_I2 += SkRotational_I2;
|
||||||
rotationalSumSk_I3 += SkRotational_I3;
|
rotationalSumSk_I3 += SkRotational_I3;
|
||||||
|
|
@ -1738,7 +1745,7 @@ void FormFinder::draw(const std::string &screenshotsFolder = {}) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FormFinder::printCurrentState() {
|
void FormFinder::printCurrentState() const {
|
||||||
std::cout << "Simulation steps executed:" << mCurrentSimulationStep
|
std::cout << "Simulation steps executed:" << mCurrentSimulationStep
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
std::cout << "Residual forces norm: " << mesh->totalResidualForcesNorm
|
std::cout << "Residual forces norm: " << mesh->totalResidualForcesNorm
|
||||||
|
|
@ -1750,6 +1757,7 @@ void FormFinder::printCurrentState() {
|
||||||
void FormFinder::printDebugInfo() const {
|
void FormFinder::printDebugInfo() const {
|
||||||
std::cout << mesh->elements[0].rigidity.toString() << std::endl;
|
std::cout << mesh->elements[0].rigidity.toString() << std::endl;
|
||||||
std::cout << "Number of dampings:" << numOfDampings << endl;
|
std::cout << "Number of dampings:" << numOfDampings << endl;
|
||||||
|
printCurrentState();
|
||||||
}
|
}
|
||||||
|
|
||||||
SimulationResults
|
SimulationResults
|
||||||
|
|
@ -1760,13 +1768,13 @@ FormFinder::executeSimulation(const std::shared_ptr<SimulationJob> &pJob,
|
||||||
reset();
|
reset();
|
||||||
mSettings = settings;
|
mSettings = settings;
|
||||||
|
|
||||||
if (!pJob->nodalExternalForces.empty()) {
|
// if (!pJob->nodalExternalForces.empty()) {
|
||||||
double externalForcesNorm = 0;
|
// double externalForcesNorm = 0;
|
||||||
for (const auto &externalForce : pJob->nodalExternalForces) {
|
// for (const auto &externalForce : pJob->nodalExternalForces) {
|
||||||
externalForcesNorm += externalForce.second.norm();
|
// externalForcesNorm += externalForce.second.norm();
|
||||||
}
|
// }
|
||||||
mSettings.totalResidualForcesNormThreshold = externalForcesNorm * 1e-3;
|
// mSettings.totalResidualForcesNormThreshold = externalForcesNorm * 1e-2;
|
||||||
}
|
// }
|
||||||
|
|
||||||
constrainedVertices = pJob->constrainedVertices;
|
constrainedVertices = pJob->constrainedVertices;
|
||||||
if (!pJob->nodalForcedDisplacements.empty()) {
|
if (!pJob->nodalForcedDisplacements.empty()) {
|
||||||
|
|
@ -1796,7 +1804,7 @@ FormFinder::executeSimulation(const std::shared_ptr<SimulationJob> &pJob,
|
||||||
}
|
}
|
||||||
polyscope::registerCurveNetwork(
|
polyscope::registerCurveNetwork(
|
||||||
meshPolyscopeLabel, mesh->getEigenVertices(), mesh->getEigenEdges());
|
meshPolyscopeLabel, mesh->getEigenVertices(), mesh->getEigenEdges());
|
||||||
registerWorldAxes();
|
// registerWorldAxes();
|
||||||
}
|
}
|
||||||
for (auto fixedVertex : pJob->constrainedVertices) {
|
for (auto fixedVertex : pJob->constrainedVertices) {
|
||||||
assert(fixedVertex.first < mesh->VN());
|
assert(fixedVertex.first < mesh->VN());
|
||||||
|
|
@ -1912,7 +1920,7 @@ currentSimulationStep > maxDRMIterations*/
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// Residual forces norm convergence
|
// Residual forces norm convergence
|
||||||
if (mesh->previousTotalKineticEnergy > mesh->currentTotalKineticEnergy
|
if (mesh->previousTotalKineticEnergy >= mesh->currentTotalKineticEnergy
|
||||||
/*||
|
/*||
|
||||||
mesh->previousTotalPotentialEnergykN >
|
mesh->previousTotalPotentialEnergykN >
|
||||||
mesh->currentTotalPotentialEnergykN*/
|
mesh->currentTotalPotentialEnergykN*/
|
||||||
|
|
@ -1944,7 +1952,7 @@ mesh->currentTotalPotentialEnergykN*/
|
||||||
++numOfDampings;
|
++numOfDampings;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (debug) {
|
if (mSettings.debugMessages) {
|
||||||
printDebugInfo();
|
printDebugInfo();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@ struct DifferentiateWithRespectTo {
|
||||||
class FormFinder {
|
class FormFinder {
|
||||||
public:
|
public:
|
||||||
struct Settings {
|
struct Settings {
|
||||||
|
bool debugMessages{false};
|
||||||
bool shouldDraw{false};
|
bool shouldDraw{false};
|
||||||
bool beVerbose{false};
|
bool beVerbose{false};
|
||||||
bool shouldCreatePlots{false};
|
bool shouldCreatePlots{false};
|
||||||
|
|
@ -194,7 +195,7 @@ private:
|
||||||
void applyForcedNormals(
|
void applyForcedNormals(
|
||||||
const std::unordered_map<VertexIndex, VectorType> nodalForcedRotations);
|
const std::unordered_map<VertexIndex, VectorType> nodalForcedRotations);
|
||||||
|
|
||||||
void printCurrentState();
|
void printCurrentState() const;
|
||||||
|
|
||||||
void printDebugInfo() const;
|
void printDebugInfo() const;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -335,18 +335,18 @@ bool SimulationMesh::savePly(const std::string &plyFilename) {
|
||||||
customAttrib.AddEdgeAttribDescriptor<vcg::Point2f, float, 2>(
|
customAttrib.AddEdgeAttribDescriptor<vcg::Point2f, float, 2>(
|
||||||
plyPropertyBeamMaterialID, nanoply::NNP_LIST_INT8_FLOAT32,
|
plyPropertyBeamMaterialID, nanoply::NNP_LIST_INT8_FLOAT32,
|
||||||
material.data());
|
material.data());
|
||||||
std::vector<std::array<double, 6>> beamProperties(EN());
|
// std::vector<std::array<double, 6>> beamProperties(EN());
|
||||||
for (size_t ei = 0; ei < EN(); ei++) {
|
// for (size_t ei = 0; ei < EN(); ei++) {
|
||||||
auto props = elements[ei].properties.toArray();
|
// auto props = elements[ei].properties.toArray();
|
||||||
for (auto p : props) {
|
// for (auto p : props) {
|
||||||
std::cout << p << " ";
|
// std::cout << p << " ";
|
||||||
}
|
// }
|
||||||
std::cout << std::endl;
|
// std::cout << std::endl;
|
||||||
beamProperties[ei] = props;
|
// beamProperties[ei] = props;
|
||||||
}
|
// }
|
||||||
customAttrib.AddEdgeAttribDescriptor<std::array<double, 6>, double, 6>(
|
// customAttrib.AddEdgeAttribDescriptor<std::array<double, 6>, double, 6>(
|
||||||
plyPropertyBeamProperties, nanoply::NNP_LIST_INT8_FLOAT64,
|
// plyPropertyBeamProperties, nanoply::NNP_LIST_INT8_FLOAT64,
|
||||||
beamProperties.data());
|
// beamProperties.data());
|
||||||
// Load the ply file
|
// Load the ply file
|
||||||
unsigned int mask = 0;
|
unsigned int mask = 0;
|
||||||
mask |= nanoply::NanoPlyWrapper<VCGEdgeMesh>::IO_VERTCOORD;
|
mask |= nanoply::NanoPlyWrapper<VCGEdgeMesh>::IO_VERTCOORD;
|
||||||
|
|
@ -418,12 +418,12 @@ double computeAngle(const VectorType &vector0, const VectorType &vector1,
|
||||||
|
|
||||||
void Element::Properties::computeMaterialProperties(
|
void Element::Properties::computeMaterialProperties(
|
||||||
const ElementMaterial &material) {
|
const ElementMaterial &material) {
|
||||||
E = material.youngsModulusGPascal * std::pow(10, 9);
|
this->material = material;
|
||||||
G = E / (2 * (1 + material.poissonsRatio));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Element::Properties::computeDimensionsProperties(
|
void Element::Properties::computeDimensionsProperties(
|
||||||
const RectangularBeamDimensions &dimensions) {
|
const RectangularBeamDimensions &dimensions) {
|
||||||
|
assert(typeid(CrossSectionType) == typeid(RectangularBeamDimensions));
|
||||||
A = (dimensions.b * dimensions.h);
|
A = (dimensions.b * dimensions.h);
|
||||||
I2 = dimensions.b * std::pow(dimensions.h, 3) / 12;
|
I2 = dimensions.b * std::pow(dimensions.h, 3) / 12;
|
||||||
I3 = dimensions.h * std::pow(dimensions.b, 3) / 12;
|
I3 = dimensions.h * std::pow(dimensions.b, 3) / 12;
|
||||||
|
|
@ -432,6 +432,7 @@ void Element::Properties::computeDimensionsProperties(
|
||||||
|
|
||||||
void Element::Properties::computeDimensionsProperties(
|
void Element::Properties::computeDimensionsProperties(
|
||||||
const CylindricalBeamDimensions &dimensions) {
|
const CylindricalBeamDimensions &dimensions) {
|
||||||
|
assert(typeid(CrossSectionType) == typeid(CylindricalBeamDimensions));
|
||||||
A = M_PI * (std::pow(dimensions.od / 2, 2) - std::pow(dimensions.id / 2, 2));
|
A = M_PI * (std::pow(dimensions.od / 2, 2) - std::pow(dimensions.id / 2, 2));
|
||||||
I2 = M_PI * (std::pow(dimensions.od, 4) - std::pow(dimensions.id, 4)) / 64;
|
I2 = M_PI * (std::pow(dimensions.od, 4) - std::pow(dimensions.id, 4)) / 64;
|
||||||
I3 = I2;
|
I3 = I2;
|
||||||
|
|
@ -457,8 +458,8 @@ Element::Properties::Properties(const CrossSectionType &dimensions,
|
||||||
|
|
||||||
Element::Properties::Properties(const std::array<double, 6> &arr) {
|
Element::Properties::Properties(const std::array<double, 6> &arr) {
|
||||||
assert(arr.size() == 6);
|
assert(arr.size() == 6);
|
||||||
E = arr[0];
|
material.E = arr[0];
|
||||||
G = arr[1];
|
material.G = arr[1];
|
||||||
A = arr[2];
|
A = arr[2];
|
||||||
I2 = arr[3];
|
I2 = arr[3];
|
||||||
I3 = arr[4];
|
I3 = arr[4];
|
||||||
|
|
@ -466,12 +467,16 @@ Element::Properties::Properties(const std::array<double, 6> &arr) {
|
||||||
}
|
}
|
||||||
|
|
||||||
std::array<double, 6> Element::Properties::toArray() const {
|
std::array<double, 6> Element::Properties::toArray() const {
|
||||||
return std::array<double, 6>({E, G, A, I2, I3, J});
|
return std::array<double, 6>({material.E, material.G, A,
|
||||||
|
static_cast<double>(I2),
|
||||||
|
static_cast<double>(I3), J});
|
||||||
}
|
}
|
||||||
|
|
||||||
void Element::updateRigidity() {
|
void Element::updateRigidity() {
|
||||||
rigidity.axial = properties.E * properties.A / initialLength;
|
rigidity.axial = properties.material.E * properties.A / initialLength;
|
||||||
rigidity.torsional = properties.G * properties.J / initialLength;
|
rigidity.torsional = properties.material.G * properties.J / initialLength;
|
||||||
rigidity.firstBending = 2 * properties.E * properties.I2 / initialLength;
|
rigidity.firstBending =
|
||||||
rigidity.secondBending = 2 * properties.E * properties.I3 / initialLength;
|
2 * properties.material.E * properties.I2 / initialLength;
|
||||||
|
rigidity.secondBending =
|
||||||
|
2 * properties.material.E * properties.I3 / initialLength;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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:
|
||||||
|
|
@ -56,8 +56,6 @@ struct Element {
|
||||||
struct Properties {
|
struct Properties {
|
||||||
CrossSectionType dimensions;
|
CrossSectionType dimensions;
|
||||||
ElementMaterial material;
|
ElementMaterial material;
|
||||||
double E{0}; // youngs modulus in pascal
|
|
||||||
double G{0}; // shear modulus
|
|
||||||
double A{0}; // cross sectional area
|
double A{0}; // cross sectional area
|
||||||
double I2{0}; // second moment of inertia
|
double I2{0}; // second moment of inertia
|
||||||
double I3{0}; // third moment of inertia
|
double I3{0}; // third moment of inertia
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue