Added chronos interface class
This commit is contained in:
parent
3e5dc29bc1
commit
54da8ac343
|
@ -156,6 +156,13 @@ PUBLIC ${ENSMALLEN_SOURCE_DIR}/include)
|
||||||
add_compile_definitions(USE_ENSMALLEN)
|
add_compile_definitions(USE_ENSMALLEN)
|
||||||
#endif()
|
#endif()
|
||||||
|
|
||||||
|
#set(Chrono_DIR "/home/iason/Coding/build/external dependencies/CHRONO-src/cmake")
|
||||||
|
#find_package(Chrono
|
||||||
|
# CONFIG REQUIRED)
|
||||||
|
#target_include_directories(${PROJECT_NAME} PRIVATE ${CHRONO_INCLUDE_DIRS} )
|
||||||
|
target_link_libraries(${PROJECT_NAME} PRIVATE "/home/iason/Coding/build/external dependencies/CHRONO-src/build/RelWithDebInfo/lib/libChronoEngine.so")
|
||||||
|
target_include_directories(${PROJECT_NAME} PRIVATE "/home/iason/Coding/build/external dependencies/CHRONO-src/src" PRIVATE "/home/iason/Coding/build/external dependencies/CHRONO-src/build/RelWithDebInfo/" )
|
||||||
|
|
||||||
#find_package(OpenMP REQUIRED)
|
#find_package(OpenMP REQUIRED)
|
||||||
#target_link_libraries(${PROJECT_NAME} OpenMP::OpenMP_CXX)
|
#target_link_libraries(${PROJECT_NAME} OpenMP::OpenMP_CXX)
|
||||||
#target_include_directories(${PROJECT_NAME} OpenMP::OpenMP_CXX)
|
#target_include_directories(${PROJECT_NAME} OpenMP::OpenMP_CXX)
|
||||||
|
|
|
@ -0,0 +1,175 @@
|
||||||
|
#include "chronoseulersimulationmodel.hpp"
|
||||||
|
#include <chrono/fea/ChBeamSectionEuler.h>
|
||||||
|
#include <chrono/fea/ChBuilderBeam.h>
|
||||||
|
#include <chrono/fea/ChMesh.h>
|
||||||
|
#include <chrono/fea/ChNodeFEAxyzrot.h>
|
||||||
|
#include <chrono/physics/ChSystemSMC.h>
|
||||||
|
#include <chrono/solver/ChIterativeSolverLS.h>
|
||||||
|
|
||||||
|
using namespace chrono;
|
||||||
|
using namespace chrono::fea;
|
||||||
|
std::shared_ptr<ChMesh> ChronosEulerSimulationModel::convertToChronosMesh_Euler(
|
||||||
|
const std::shared_ptr<SimulationMesh> &pMesh,
|
||||||
|
std::vector<std::shared_ptr<ChNodeFEAxyzrot>> &edgeMeshVertsToChronosNodes)
|
||||||
|
{
|
||||||
|
auto mesh_chronos = chrono_types::make_shared<ChMesh>();
|
||||||
|
edgeMeshVertsToChronosNodes.clear();
|
||||||
|
edgeMeshVertsToChronosNodes.resize(pMesh->VN(), nullptr);
|
||||||
|
|
||||||
|
//add nodes
|
||||||
|
for (int vi = 0; vi < pMesh->VN(); vi++) {
|
||||||
|
const auto &vertex = pMesh->vert[vi];
|
||||||
|
edgeMeshVertsToChronosNodes[vi] = std::make_shared<ChNodeFEAxyzrot>(
|
||||||
|
ChFrame<>(ChVector<>(vertex.cP()[0], vertex.cP()[1], vertex.cP()[2]),
|
||||||
|
ChVector<>(0, 1, 0)));
|
||||||
|
mesh_chronos->AddNode(edgeMeshVertsToChronosNodes[vi]);
|
||||||
|
}
|
||||||
|
//add elements
|
||||||
|
ChBuilderBeamEuler builder;
|
||||||
|
for (int ei = 0; ei < pMesh->EN(); ei++) {
|
||||||
|
const SimulationMesh::EdgeType &edge = pMesh->edge[ei];
|
||||||
|
//define end-points
|
||||||
|
const auto vi0 = pMesh->getIndex(edge.cV(0));
|
||||||
|
const auto vi1 = pMesh->getIndex(edge.cV(1));
|
||||||
|
//define cross section
|
||||||
|
const Element &element = pMesh->elements[ei];
|
||||||
|
const double beam_wz = element.dimensions.b;
|
||||||
|
const double beam_wy = element.dimensions.h;
|
||||||
|
const double E = element.material.youngsModulus;
|
||||||
|
const double poisson = element.material.poissonsRatio;
|
||||||
|
const double density = 1e4;
|
||||||
|
|
||||||
|
auto msection = chrono_types::make_shared<ChBeamSectionEulerAdvanced>();
|
||||||
|
msection->SetDensity(density);
|
||||||
|
msection->SetYoungModulus(E);
|
||||||
|
msection->SetGwithPoissonRatio(poisson);
|
||||||
|
msection->SetBeamRaleyghDamping(0.0);
|
||||||
|
msection->SetAsRectangularSection(beam_wy, beam_wz);
|
||||||
|
builder
|
||||||
|
.BuildBeam(mesh_chronos, // the mesh where to put the created nodes and elements
|
||||||
|
msection, // the ChBeamSectionEuler to use for the ChElementBeamEuler elements
|
||||||
|
5, // the number of ChElementBeamEuler to create
|
||||||
|
edgeMeshVertsToChronosNodes[vi0], // the 'A' point in space (beginning of beam)
|
||||||
|
edgeMeshVertsToChronosNodes[vi1], // the 'B' point in space (end of beam)
|
||||||
|
ChVector<>(0, 0, 1)
|
||||||
|
// ChVector<>(0, cos(rot_rad), sin(rot_rad))
|
||||||
|
); // the 'Y' up direction of the section for the beam
|
||||||
|
}
|
||||||
|
|
||||||
|
return mesh_chronos;
|
||||||
|
}
|
||||||
|
|
||||||
|
ChronosEulerSimulationModel::ChronosEulerSimulationModel() {}
|
||||||
|
|
||||||
|
SimulationResults ChronosEulerSimulationModel::executeSimulation(
|
||||||
|
const std::shared_ptr<SimulationJob> &pJob)
|
||||||
|
{
|
||||||
|
chrono::ChSystemSMC my_system;
|
||||||
|
my_system.SetTimestepperType(chrono::ChTimestepper::Type::EULER_IMPLICIT_LINEARIZED);
|
||||||
|
std::vector<std::shared_ptr<ChNodeFEAxyzrot>> edgeMeshVertsToChronosNodes;
|
||||||
|
auto mesh_chronos = convertToChronosMesh_Euler(pJob->pMesh, edgeMeshVertsToChronosNodes);
|
||||||
|
// mesh_chronos->SetAutomaticGravity(false);
|
||||||
|
//parse constrained vertices
|
||||||
|
for (const std::pair<VertexIndex, std::unordered_set<int>> &constrainedVertex :
|
||||||
|
pJob->constrainedVertices) {
|
||||||
|
const int &constrainedVi = constrainedVertex.first;
|
||||||
|
const std::unordered_set<int> &constrainedDoF = constrainedVertex.second;
|
||||||
|
const bool vertexIsFullyConstrained = constrainedDoF.size() == 6
|
||||||
|
&& constrainedDoF.contains(0)
|
||||||
|
&& constrainedDoF.contains(1)
|
||||||
|
&& constrainedDoF.contains(2)
|
||||||
|
&& constrainedDoF.contains(3)
|
||||||
|
&& constrainedDoF.contains(4)
|
||||||
|
&& constrainedDoF.contains(5);
|
||||||
|
if (vertexIsFullyConstrained) {
|
||||||
|
edgeMeshVertsToChronosNodes[constrainedVi]->SetFixed(true);
|
||||||
|
} else {
|
||||||
|
std::cerr << "Currently only rigid vertices are handled." << std::endl;
|
||||||
|
SimulationResults simulationResults;
|
||||||
|
simulationResults.converged = false;
|
||||||
|
assert(false);
|
||||||
|
return simulationResults;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// std::dynamic_pointer_cast<std::shared_ptr<ChNodeFEAxyzrot>>(mesh_chronos->GetNode(1))
|
||||||
|
// ->SetFixed(true);
|
||||||
|
//parse external forces
|
||||||
|
for (const std::pair<VertexIndex, Vector6d> &externalForce : pJob->nodalExternalForces) {
|
||||||
|
const int &forceVi = externalForce.first;
|
||||||
|
const Vector6d &force = externalForce.second;
|
||||||
|
if (Eigen::Vector3d(force[3], force[4], force[5]).norm() > 1e-10) {
|
||||||
|
std::cerr << "Moments are currently not supported." << std::endl;
|
||||||
|
SimulationResults simulationResults;
|
||||||
|
simulationResults.converged = false;
|
||||||
|
assert(false);
|
||||||
|
return simulationResults;
|
||||||
|
} else {
|
||||||
|
edgeMeshVertsToChronosNodes[forceVi]->SetForce(ChVector<>(force[0], force[1], force[2]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// edgeMeshVertsToChronosNodes[0]->SetFixed(true);
|
||||||
|
// edgeMeshVertsToChronosNodes[1]->SetForce(ChVector<>(1e-10, 0, 0));
|
||||||
|
// edgeMeshVertsToChronosNodes[0]->SetFixed(true);
|
||||||
|
// builder.GetLastBeamNodes().front()->SetFixed(true);
|
||||||
|
// builder.GetLastBeamNodes().back()->SetForce(ChVector<>(0, 0, 1e1));
|
||||||
|
|
||||||
|
// edgeMeshVertsToChronosNodes[3]->SetFixed(true);
|
||||||
|
// edgeMeshVertsToChronosNodes[7]->SetFixed(true);
|
||||||
|
// edgeMeshVertsToChronosNodes[11]->SetFixed(true);
|
||||||
|
// edgeMeshVertsToChronosNodes[15]->SetForce(ChVector<>(0.0, 0, 1e-1));
|
||||||
|
// edgeMeshVertsToChronosNodes[19]->SetForce(ChVector<>(0.0, 0, 1e-1));
|
||||||
|
// edgeMeshVertsToChronosNodes[23]->SetForce(ChVector<>(0.0, 0, 1e-1));
|
||||||
|
// builder.GetLastBeamNodes().back()->SetForce(ChVector<>(0.0, 1e2, 0.0));
|
||||||
|
|
||||||
|
my_system.Add(mesh_chronos);
|
||||||
|
|
||||||
|
auto solver = chrono_types::make_shared<ChSolverMINRES>();
|
||||||
|
solver->SetMaxIterations(5000);
|
||||||
|
solver->SetTolerance(1e-10);
|
||||||
|
solver->EnableDiagonalPreconditioner(true);
|
||||||
|
solver->SetVerbose(true);
|
||||||
|
my_system.SetSolver(solver);
|
||||||
|
SimulationResults simulationResults;
|
||||||
|
simulationResults.converged = my_system.DoStaticNonlinear();
|
||||||
|
if (!simulationResults.converged) {
|
||||||
|
std::cerr << "Simulation failed" << std::endl;
|
||||||
|
assert(false);
|
||||||
|
return simulationResults;
|
||||||
|
}
|
||||||
|
// my_system.DoStaticLinear();
|
||||||
|
simulationResults.pJob = pJob;
|
||||||
|
simulationResults.displacements.resize(pJob->pMesh->VN());
|
||||||
|
simulationResults.rotationalDisplacementQuaternion.resize(pJob->pMesh->VN());
|
||||||
|
for (size_t vi = 0; vi < pJob->pMesh->VN(); vi++) {
|
||||||
|
std::shared_ptr<ChNodeFEAxyzrot> node_chronos = edgeMeshVertsToChronosNodes[vi];
|
||||||
|
const auto posDisplacement = node_chronos->GetPos() - node_chronos->GetX0().GetPos();
|
||||||
|
//Translations
|
||||||
|
simulationResults.displacements[vi][0] = posDisplacement[0];
|
||||||
|
simulationResults.displacements[vi][1] = posDisplacement[1];
|
||||||
|
simulationResults.displacements[vi][2] = posDisplacement[2];
|
||||||
|
//Rotations
|
||||||
|
const chrono::ChQuaternion<double> rotQuat = node_chronos->GetRot();
|
||||||
|
simulationResults.rotationalDisplacementQuaternion[vi]
|
||||||
|
= Eigen::Quaternion<double>(rotQuat.e0(), rotQuat.e1(), rotQuat.e2(), rotQuat.e3());
|
||||||
|
const ChVector<double> eulerAngles = rotQuat.Q_to_Euler123();
|
||||||
|
simulationResults.displacements[vi][3] = eulerAngles[0];
|
||||||
|
simulationResults.displacements[vi][4] = eulerAngles[1];
|
||||||
|
simulationResults.displacements[vi][5] = eulerAngles[2];
|
||||||
|
}
|
||||||
|
return simulationResults;
|
||||||
|
|
||||||
|
// VCGEdgeMesh deformedMesh;
|
||||||
|
// deformedMesh.copy(*(pJob->pMesh));
|
||||||
|
// for (size_t vi = 0; vi < pJob->pMesh->VN(); vi++) {
|
||||||
|
// const std::shared_ptr<ChNodeFEAxyzrot> node_chronos = edgeMeshVertsToChronosNodes[vi];
|
||||||
|
// deformedMesh.vert[vi].P() = CoordType(node_chronos->GetPos()[0],
|
||||||
|
// node_chronos->GetPos()[1],
|
||||||
|
// node_chronos->GetPos()[2]);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// deformedMesh.updateEigenEdgeAndVertices();
|
||||||
|
// deformedMesh.setLabel("deformed");
|
||||||
|
// deformedMesh.registerForDrawing();
|
||||||
|
// polyscope::show();
|
||||||
|
// return simulationResults;
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
#ifndef CHRONOSEULERSIMULATIONMODEL_HPP
|
||||||
|
#define CHRONOSEULERSIMULATIONMODEL_HPP
|
||||||
|
|
||||||
|
#include "simulationmodel.hpp"
|
||||||
|
|
||||||
|
namespace chrono {
|
||||||
|
namespace fea {
|
||||||
|
class ChMesh;
|
||||||
|
class ChNodeFEAxyzrot;
|
||||||
|
} // namespace fea
|
||||||
|
} // namespace chrono
|
||||||
|
|
||||||
|
class ChronosEulerSimulationModel : public SimulationModel
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ChronosEulerSimulationModel();
|
||||||
|
SimulationResults executeSimulation(const std::shared_ptr<SimulationJob> &pJob) override;
|
||||||
|
static std::shared_ptr<chrono::fea::ChMesh> convertToChronosMesh_Euler(
|
||||||
|
const std::shared_ptr<SimulationMesh> &pMesh,
|
||||||
|
std::vector<std::shared_ptr<chrono::fea::ChNodeFEAxyzrot>> &edgeMeshVertsToChronosNodes);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CHRONOSEULERSIMULATIONMODEL_HPP
|
Loading…
Reference in New Issue