Skip to content

Commit 4c8a933

Browse files
authored
[test] Unit test describing visitor behavior (#6085)
1 parent c5e35b6 commit 4c8a933

2 files changed

Lines changed: 211 additions & 0 deletions

File tree

Sofa/framework/Simulation/Core/test/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ set(SOURCE_FILES
1414
TaskSchedulerTestTasks.cpp
1515
TaskSchedulerTestTasks.h
1616
TaskSchedulerTests.cpp
17+
Visitor_test.cpp
1718
)
1819

1920
add_executable(${PROJECT_NAME} ${SOURCE_FILES})
Lines changed: 210 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,210 @@
1+
#include <gtest/gtest.h>
2+
#include <sofa/core/behavior/BaseForceField.h>
3+
#include <sofa/core/behavior/BaseInteractionForceField.h>
4+
#include <sofa/core/behavior/BaseMass.h>
5+
#include <sofa/simpleapi/SimpleApi.h>
6+
#include <sofa/simulation/MechanicalVisitor.h>
7+
#include <sofa/simulation/Node.h>
8+
9+
namespace sofa
10+
{
11+
12+
namespace
13+
{
14+
/**
15+
* A visitor counting the number of force fields, mappings and masses visited.
16+
* This visitor considers interaction force fields as BaseForceField, so they are counted as force
17+
* fields.
18+
*/
19+
class TestVisitorWithoutInteractionForceField : public simulation::MechanicalVisitor
20+
{
21+
public:
22+
using simulation::MechanicalVisitor::MechanicalVisitor;
23+
24+
Result fwdMechanicalMapping(simulation::Node* /*node*/, sofa::core::BaseMapping* map) override
25+
{
26+
++m_mappingCount;
27+
return Result::RESULT_CONTINUE;
28+
}
29+
30+
Result fwdForceField(simulation::Node*, sofa::core::behavior::BaseForceField*) override
31+
{
32+
++m_forceFieldCount;
33+
return Result::RESULT_CONTINUE;
34+
}
35+
36+
Result fwdMass(simulation::Node*, sofa::core::behavior::BaseMass*) override
37+
{
38+
++m_massCount;
39+
return Result::RESULT_CONTINUE;
40+
}
41+
42+
std::size_t m_forceFieldCount {};
43+
std::size_t m_interactionForceFieldCount {};
44+
std::size_t m_massCount {};
45+
std::size_t m_mappingCount {};
46+
};
47+
48+
/**
49+
* A visitor counting the number of force fields, interaction force fields, mappings and masses visited.
50+
* This visitor considers interaction force fields as BaseInteractionForceField, so they are counted
51+
* as interaction force fields, not force fields.
52+
*/
53+
class TestVisitorWithInteractionForceField : public simulation::MechanicalVisitor
54+
{
55+
public:
56+
using simulation::MechanicalVisitor::MechanicalVisitor;
57+
58+
Result fwdMechanicalMapping(simulation::Node*, sofa::core::BaseMapping* map) override
59+
{
60+
++m_mappingCount;
61+
return Result::RESULT_CONTINUE;
62+
}
63+
64+
Result fwdForceField(simulation::Node*, sofa::core::behavior::BaseForceField*) override
65+
{
66+
++m_forceFieldCount;
67+
return Result::RESULT_CONTINUE;
68+
}
69+
70+
Result fwdInteractionForceField(simulation::Node*, sofa::core::behavior::BaseInteractionForceField*) override
71+
{
72+
++m_interactionForceFieldCount;
73+
return Result::RESULT_CONTINUE;
74+
}
75+
76+
Result fwdMass(simulation::Node*, sofa::core::behavior::BaseMass*) override
77+
{
78+
++m_massCount;
79+
return Result::RESULT_CONTINUE;
80+
}
81+
82+
std::size_t m_forceFieldCount {};
83+
std::size_t m_interactionForceFieldCount {};
84+
std::size_t m_massCount {};
85+
std::size_t m_mappingCount {};
86+
};
87+
88+
class TestForceField : public core::behavior::BaseForceField
89+
{
90+
public:
91+
void addForce(const core::MechanicalParams* mparams, core::MultiVecDerivId fId) override {}
92+
void addDForce(const core::MechanicalParams* mparams, core::MultiVecDerivId dfId) override {}
93+
SReal getPotentialEnergy(const core::MechanicalParams* mparams) const override { return {}; }
94+
void addKToMatrix(const core::MechanicalParams* mparams, const sofa::core::behavior::MultiMatrixAccessor* matrix) override {}
95+
};
96+
97+
class TestMass : public core::behavior::BaseMass
98+
{
99+
public:
100+
void addMDx(const core::MechanicalParams* mparams, core::MultiVecDerivId fid, SReal factor) override {}
101+
void accFromF(const core::MechanicalParams* mparams, core::MultiVecDerivId aid) override {}
102+
void addGravityToV(const core::MechanicalParams* mparams, core::MultiVecDerivId vid) override {}
103+
SReal getKineticEnergy(const core::MechanicalParams* mparams) const override { return {}; }
104+
SReal getPotentialEnergy(const core::MechanicalParams* mparams) const override { return {}; }
105+
type::Vec6 getMomentum(const core::MechanicalParams* mparams) const override { return {}; }
106+
void addMToMatrix(const core::MechanicalParams* mparams, const sofa::core::behavior::MultiMatrixAccessor* matrix) override {}
107+
void initGnuplot(const std::string path) override {}
108+
void exportGnuplot(const core::MechanicalParams* mparams, SReal time) override {}
109+
SReal getElementMass(sofa::Index index) const override { return {}; }
110+
void getElementMass(sofa::Index index, linearalgebra::BaseMatrix* m) const override {}
111+
bool isDiagonal() const override { return {}; }
112+
};
113+
114+
class TestInteractionForceField : public core::behavior::BaseInteractionForceField
115+
{
116+
public:
117+
void addForce(const core::MechanicalParams* mparams, core::MultiVecDerivId fId) override {}
118+
void addDForce(const core::MechanicalParams* mparams, core::MultiVecDerivId dfId) override {}
119+
SReal getPotentialEnergy(const core::MechanicalParams* mparams) const override { return {}; }
120+
};
121+
122+
class TestMapping : public core::BaseMapping
123+
{
124+
public:
125+
void apply(const core::MechanicalParams* mparams, core::MultiVecCoordId outPos, core::ConstMultiVecCoordId inPos) override {}
126+
void applyJ(const core::MechanicalParams* mparams, core::MultiVecDerivId outVel, core::ConstMultiVecDerivId inVel) override {}
127+
type::vector<core::BaseState*> getFrom() override { return {} ;}
128+
type::vector<core::BaseState*> getTo() override { return {} ;}
129+
void applyJT(const core::MechanicalParams* mparams, core::MultiVecDerivId inForce, core::ConstMultiVecDerivId outForce) override {}
130+
void applyDJT(const core::MechanicalParams* mparams, core::MultiVecDerivId inForce, core::ConstMultiVecDerivId outForce) override {}
131+
void applyJT(const core::ConstraintParams* mparams, core::MultiMatrixDerivId inConst, core::ConstMultiMatrixDerivId outConst) override {}
132+
void computeAccFromMapping(const core::MechanicalParams* mparams, core::MultiVecDerivId outAcc, core::ConstMultiVecDerivId inVel, core::ConstMultiVecDerivId inAcc) override {}
133+
type::vector<core::behavior::BaseMechanicalState*> getMechFrom() override { return {} ;}
134+
type::vector<core::behavior::BaseMechanicalState*> getMechTo() override { return {} ;}
135+
void disable() override {}
136+
};
137+
138+
sofa::simulation::Node::SPtr makeSceneGraph()
139+
{
140+
const sofa::simulation::Node::SPtr root = sofa::simpleapi::createRootNode(sofa::simulation::getSimulation(), "root");
141+
142+
const auto ff_0 = sofa::core::objectmodel::New<TestForceField>();
143+
root->addObject(ff_0);
144+
145+
const auto mass_0 = sofa::core::objectmodel::New<TestMass>();
146+
root->addObject(mass_0);
147+
148+
const auto iff_0 = sofa::core::objectmodel::New<TestInteractionForceField>();
149+
root->addObject(iff_0);
150+
151+
const auto mapping_0 = sofa::core::objectmodel::New<TestMapping>();
152+
root->addObject(mapping_0);
153+
154+
auto child_0 = root->createChild("child_0");
155+
156+
// mapping_0 is in two different nodes
157+
child_0->addObject(mapping_0);
158+
159+
auto child_1 = root->createChild("child_1");
160+
161+
auto child_2 = child_1->createChild("child_2");
162+
// diamond graph
163+
child_0->addChild(child_2);
164+
165+
// the two components are in a Node with two parents. We need to check that they are visited
166+
// only once
167+
const auto mass_1 = sofa::core::objectmodel::New<TestMass>();
168+
child_2->addObject(mass_1);
169+
170+
const auto iff_1 = sofa::core::objectmodel::New<TestInteractionForceField>();
171+
child_2->addObject(iff_1);
172+
173+
return root;
174+
}
175+
176+
}
177+
178+
TEST(Visitor, ComplexGraph_visitorWithoutInteractionForceField)
179+
{
180+
const auto root = makeSceneGraph();
181+
182+
TestVisitorWithoutInteractionForceField visitor(
183+
sofa::core::MechanicalParams::defaultInstance());
184+
185+
static constexpr bool precomputedOrder = false;
186+
root->executeVisitor(&visitor, precomputedOrder);
187+
188+
// the visitor considers the interaction force field as a BaseForceField
189+
EXPECT_EQ(visitor.m_forceFieldCount, 3);
190+
EXPECT_EQ(visitor.m_interactionForceFieldCount, 0);
191+
EXPECT_EQ(visitor.m_massCount, 2);
192+
EXPECT_EQ(visitor.m_mappingCount, 1);
193+
}
194+
195+
TEST(Visitor, ComplexGraph_visitorWithInteractionForceField)
196+
{
197+
const auto root = makeSceneGraph();
198+
199+
TestVisitorWithInteractionForceField visitor(sofa::core::MechanicalParams::defaultInstance());
200+
201+
static constexpr bool precomputedOrder = false;
202+
root->executeVisitor(&visitor, precomputedOrder);
203+
204+
EXPECT_EQ(visitor.m_forceFieldCount, 1);
205+
EXPECT_EQ(visitor.m_interactionForceFieldCount, 2);
206+
EXPECT_EQ(visitor.m_massCount, 2);
207+
EXPECT_EQ(visitor.m_mappingCount, 1);
208+
}
209+
210+
}

0 commit comments

Comments
 (0)