Changed Element properties

This commit is contained in:
Iason 2021-01-14 15:39:19 +02:00
parent d933f92eeb
commit 2e7aa6e1e0
5 changed files with 82 additions and 71 deletions

View File

@ -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

View File

@ -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();
} }
} }

View File

@ -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;

View File

@ -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;
} }

View File

@ -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