-
Notifications
You must be signed in to change notification settings - Fork 14
XML.Tools.installable
Jose Luis Cercos-Pita edited this page Feb 17, 2025
·
1 revision
This is kind of a special tool on AQUAgpusph, which allows the user to compile
its own Aqua::CalcServer::Tool
C++ tool as a library.
A good way to illustrate this is the coupling with ProjectChrono done to carry out the Apollo capsule simulation.
First the installable tool source code is required, in this case a single header --chronosim.hpp--:
#ifndef INSTALLABLEDEMO_H_INCLUDED
#define INSTALLABLEDEMO_H_INCLUDED
#include <aquagpusph/CalcServer/Tool.hpp>
#include <chrono/physics/ChSystemNSC.h>
#include <chrono/physics/ChBody.h>
#include <chrono/physics/ChForce.h>
namespace Aqua{ namespace CalcServer{
class ApolloSim : public Aqua::CalcServer::Tool
{
public:
ApolloSim(const std::string tool_name, bool once);
~ApolloSim();
void setup();
protected:
cl_event _execute(const std::vector<cl_event> events);
private:
float _pitch;
float _vel;
float _cogz;
std::shared_ptr<chrono::ChSystemNSC> _sys;
std::shared_ptr<chrono::ChBody> _apollo;
std::shared_ptr<chrono::ChForce> _force;
std::shared_ptr<chrono::ChForce> _moment;
};
}} // namespace
#endif // INSTALLABLEDEMO_H_INCLUDED
as well as a surce code file --chronosim.cpp--:
#include "chronosim.hpp"
#include <aquagpusph/CalcServer/CalcServer.hpp>
#include <aquagpusph/InputOutput/Logger.hpp>
#include <cmath>
extern "C" Aqua::CalcServer::ApolloSim* create_object(
const std::string name, bool once)
{
return new Aqua::CalcServer::ApolloSim(name, once);
}
namespace Aqua{ namespace CalcServer{
ApolloSim::ApolloSim(const std::string name, bool once)
: Tool(name, once)
{
}
ApolloSim::~ApolloSim()
{
}
#define LB2KG 0.4535924
#define IN2M 0.0254
void
ApolloSim::setup()
{
Tool::setup();
// Get the configuration variables
auto vars = CalcServer::singleton()->variables();
_pitch = *((float*)vars->get("pitch")->get(true));
_vel = *((float*)vars->get("u0")->get(true));
_cogz = *((float*)vars->get("cogz")->get(true));
_pitch *= M_PI / 180.0;
_sys = chrono_types::make_shared<chrono::ChSystemNSC>();
_apollo = chrono_types::make_shared<chrono::ChBody>();
_sys->AddBody(_apollo);
_force = chrono_types::make_shared<chrono::ChForce>();
_moment = chrono_types::make_shared<chrono::ChForce>();
_apollo->AddForce(_force);
_apollo->AddForce(_moment);
_apollo->SetName("Apollo");
_sys->SetGravitationalAcceleration(chrono::ChVector3d(0, 0, -9.81));
_apollo->SetMass(3900);
_apollo->SetInertiaXX(chrono::ChVector3d(5560, 5270, 4180));
_force->SetMode(chrono::ChForce::FORCE);
_force->SetFrame(chrono::ChForce::BODY);
_force->SetAlign(chrono::ChForce::WORLD_DIR);
_force->SetVrelpoint(chrono::ChVector3d(0, 0, 0));
_moment->SetMode(chrono::ChForce::TORQUE);
_moment->SetFrame(chrono::ChForce::BODY);
_moment->SetAlign(chrono::ChForce::WORLD_DIR);
_moment->SetVrelpoint(chrono::ChVector3d(0, 0, 0));
_apollo->SetPos(chrono::ChVector3d(0, 0, _cogz));
_apollo->SetLinVel(chrono::ChVector3d(0, 0, -_vel));
chrono::ChQuaternion<double> R;
R.SetFromCardanAnglesXYZ(chrono::ChVector3d(0, _pitch, 0));
_apollo->SetRot(R);
setInputDependencies({"dt", "Force_p", "Moment_p"});
setOutputDependencies({"motion_r", "motion_drdt", "motion_ddrddt",
"motion_a", "motion_dadt", "motion_ddaddt",
"forces_r"});
};
void
setForce(std::shared_ptr<chrono::ChForce> var, vec4 value)
{
chrono::ChVector3d v(value.x, value.y, value.z);
if (v.IsNull()) {
var->SetMforce(0.0);
} else {
const auto norm = v.Length();
v.Scale(1.0 / norm);
var->SetVrelpoint(chrono::ChVector3d(0, 0, 0));
var->SetDir(v);
var->SetMforce(norm);
}
}
void
setVec(Aqua::InputOutput::Variable* var, chrono::ChVector3d value)
{
vec4 v;
v.x = value.x();
v.y = value.y();
v.z = value.z();
v.w = 0.f;
var->set(&v, true);
}
cl_event
ApolloSim::_execute(const std::vector<cl_event> UNUSED_PARAM events)
{
auto vars = CalcServer::singleton()->variables();
// Get the forces from AQUAgpusph
float dt = *((float*)vars->get("dt")->get(true));
const vec4 F = *((vec4*)vars->get("Force_p_iset")->get(true));
const vec4 M = *((vec4*)vars->get("Moment_p_iset")->get(true));
// Simulate the body motion
setForce(_force, F);
setForce(_moment, M);
_sys->DoStepDynamics(dt);
// Get the new position and angle
const chrono::ChVector3d r = _apollo->GetPos();
const chrono::ChVector3d drdt = _apollo->GetLinVel();
const chrono::ChVector3d ddrddt = _apollo->GetLinAcc();
const chrono::ChVector3d a = _apollo->GetRot().GetCardanAnglesXYZ();
const chrono::ChVector3d dadt = _apollo->GetAngVelLocal();
const chrono::ChVector3d ddaddt = _apollo->GetAngAccLocal();
setVec(vars->get("motion_r"), r);
setVec(vars->get("motion_drdt"), drdt);
setVec(vars->get("motion_ddrddt"), ddrddt);
setVec(vars->get("motion_a"), a);
setVec(vars->get("motion_dadt"), dadt);
setVec(vars->get("motion_ddaddt"), ddaddt);
setVec(vars->get("forces_r"), r);
return NULL;
}
}} // namespaces
The code above is compiled with CMake:
find_package(Chrono)
if(NOT Chrono_FOUND)
message(FATAL_ERROR "PROJECTCHRONO required")
endif(NOT Chrono_FOUND)
add_library(apollo_capsule_sim SHARED chronosim.cpp)
target_include_directories(apollo_capsule_sim PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${CHRONO_INCLUDE_DIRS})
target_compile_options(apollo_capsule_sim PRIVATE ${CHRONO_CXX_FLAGS})
target_link_libraries(apollo_capsule_sim aquagpusph ${DEP_LIBS} ${CHRONO_LIBRARIES})
set_target_properties(apollo_capsule_sim PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
which will produce the library file libapollo_capsule_sim.so
, which can be
loaded and executed within AQUAgpusph with the following XML element:
<Tool action="insert" before="some marker" name="chrono sim" type="installable" path="libapollo_capsule_sim.so" />
Note that on Windows the .dll file shall be provided. Look at the example source code itself for a more detailed recipe on how to compile and use the tool.