Skip to content

Commit

Permalink
modern visitor creation (the old ones)
Browse files Browse the repository at this point in the history
  • Loading branch information
alxbilger committed Nov 19, 2024
1 parent cda3269 commit 7b8af41
Show file tree
Hide file tree
Showing 3 changed files with 231 additions and 12 deletions.
1 change: 1 addition & 0 deletions Sofa/framework/Simulation/Core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ set(HEADER_FILES
${SRC_ROOT}/MechanicalOperations.h
${SRC_ROOT}/MechanicalVPrintVisitor.h
${SRC_ROOT}/MechanicalVisitor.h
${SRC_ROOT}/MechanicalVisitorCreator.h
${SRC_ROOT}/MutationListener.h
${SRC_ROOT}/Node.h
${SRC_ROOT}/Node.inl
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@
#include <numeric>
#include <sofa/core/behavior/BaseForceField.h>
#include <sofa/core/behavior/BaseMass.h>
#include <sofa/core/behavior/BaseProjectiveConstraintSet.h>
#include <sofa/simulation/MechanicalVisitorCreator.h>

using namespace sofa::core;

Expand Down Expand Up @@ -159,8 +161,15 @@ void MechanicalOperations::propagateDxAndResetDf(core::MultiVecDerivId dx, core:
void MechanicalOperations::propagateX(core::MultiVecCoordId x)
{
setX(x);
const MechanicalPropagateOnlyPositionVisitor visitor(&mparams, 0.0, x);
executeVisitor( visitor );
const auto v = sofa::simulation::makeMechanicalVisitor(&mparams,
TopDownMechanicalMappingCallable(
[this, &x](simulation::Node* /*node*/, core::BaseMapping* map) -> Visitor::Result
{
map->apply(&mparams, x, x);
return Visitor::RESULT_CONTINUE;
})
);
executeVisitor( v );
}

/// Propagate the given velocity through all mappings
Expand Down Expand Up @@ -201,10 +210,20 @@ void MechanicalOperations::computeEnergy(SReal &kineticEnergy, SReal &potentialE
{
kineticEnergy = 0;
potentialEnergy = 0;
MechanicalComputeEnergyVisitor energyVisitor(&mparams);
executeVisitor(&energyVisitor);
kineticEnergy = energyVisitor.getKineticEnergy();
potentialEnergy = energyVisitor.getPotentialEnergy();

const auto v = makeMechanicalVisitor(&mparams,
TopDownMassCallable([&kineticEnergy](simulation::Node*, const sofa::core::behavior::BaseMass* mass)
{
kineticEnergy += mass->getKineticEnergy();
return Visitor::RESULT_CONTINUE;
}),
TopDownForceFieldCallable([&potentialEnergy](simulation::Node*, const sofa::core::behavior::BaseForceField* force)
{
potentialEnergy += force->getPotentialEnergy();
return Visitor::RESULT_CONTINUE;
})
);
executeVisitor( v );
}
/// Apply projective constraints to the given velocity vector
void MechanicalOperations::projectVelocity(core::MultiVecDerivId v, SReal time)
Expand Down Expand Up @@ -328,10 +347,41 @@ void MechanicalOperations::computeDfV(core::MultiVecDerivId df, bool clear, bool
setDf(df);
if (clear)
{
executeVisitor( MechanicalResetForceVisitor(&mparams, df, false) );
//finish();
const auto reset = [this, &df](simulation::Node* /*node*/, core::behavior::BaseMechanicalState* mm)
{
mm->resetForce(&mparams, df.getId(mm));
return Visitor::RESULT_CONTINUE;
};

executeVisitor(makeMechanicalVisitor(&mparams,
TopDownMechanicalStateCallable(reset),
TopDownMappedMechanicalStateCallable(reset)
));
}

const auto addDForce = TopDownForceFieldCallable([this, &df](simulation::Node* /*node*/, core::behavior::BaseForceField* ff)
{
ff->addDForce(&mparams, df);
return Visitor::RESULT_CONTINUE;
});

if (accumulate)
{
executeVisitor(makeMechanicalVisitor(&mparams, addDForce,
BottomUpMechanicalMappingCallable([this, &df](simulation::Node* /*node*/, core::BaseMapping* map)
{
map->applyJT(&mparams, df, df); // apply material stiffness: variation of force below the mapping
if( mparams.kFactor() )
{
map->applyDJT(&mparams, df, df); // apply geometric stiffness: variation due to a change of mapping, with a constant force below the mapping
}
})));
}
executeVisitor( MechanicalComputeDfVisitor(&mparams, df, accumulate) );
else
{
executeVisitor(makeMechanicalVisitor(&mparams, addDForce));
}

mparams.setDx(dx);
}

Expand Down Expand Up @@ -411,7 +461,16 @@ void MechanicalOperations::addSeparateGravity(SReal dt, core::MultiVecDerivId re
{
mparams.setDt(dt);
setV(result);
executeVisitor( MechanicalAddSeparateGravityVisitor(&mparams, result) );
executeVisitor( makeMechanicalVisitor(&mparams,
TopDownMassCallable([this, &result](simulation::Node* /*node*/, core::behavior::BaseMass* mass)
{
if( mass->m_separateGravity.getValue() )
{
mass->addGravityToV(&mparams, result);
}
return Visitor::RESULT_CONTINUE;
})
) );
}

void MechanicalOperations::computeContactForce(core::MultiVecDerivId result)
Expand All @@ -436,8 +495,30 @@ void MechanicalOperations::computeAcc(SReal t, core::MultiVecDerivId a, core::Mu
setDx(a);
setX(x);
setV(v);
executeVisitor( MechanicalProjectPositionAndVelocityVisitor(&mparams, t,x,v) );
executeVisitor( MechanicalPropagateOnlyPositionAndVelocityVisitor(&mparams, t,x,v) );

executeVisitor( makeMechanicalVisitor(&mparams,
TopDownMechanicalMappingCallable([](simulation::Node* /*node*/, core::BaseMapping* /*map*/)
{
return Visitor::RESULT_PRUNE;
}),
TopDownProjectiveConstraintSetCallable([this, &x, &v](simulation::Node* /*node*/, core::behavior::BaseProjectiveConstraintSet* c)
{
c->projectPosition(&mparams, x);
c->projectVelocity(&mparams, v);
return Visitor::RESULT_CONTINUE;
})
) );

executeVisitor( makeMechanicalVisitor(&mparams,
TopDownMechanicalMappingCallable([this, &x, &v](simulation::Node* /*node*/, core::BaseMapping* map)
{
map->apply(&mparams, x, x);
map->applyJ(&mparams, v, v);

return Visitor::RESULT_CONTINUE;
})
) );

computeForce(f);

accFromF(a,f);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
/******************************************************************************
* SOFA, Simulation Open-Framework Architecture *
* (c) 2006 INRIA, USTL, UJF, CNRS, MGH *
* *
* This program is free software; you can redistribute it and/or modify it *
* under the terms of the GNU Lesser General Public License as published by *
* the Free Software Foundation; either version 2.1 of the License, or (at *
* your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License *
* for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
*******************************************************************************
* Authors: The SOFA Team and external contributors (see Authors.txt) *
* *
* Contact information: [email protected] *
******************************************************************************/
#pragma once

#include <sofa/simulation/BaseMechanicalVisitor.h>
#include <sofa/simulation/MechanicalVisitor.h>


namespace sofa::simulation
{

template<class Callable>
struct VisitorCallable
{
Callable m_callable;
constexpr explicit VisitorCallable(const Callable& callable) : m_callable(callable) {}
constexpr explicit VisitorCallable(Callable&& callable) : m_callable(std::forward<Callable>(callable)) {}
};

template<class Callable, class TVisitedObject>
struct TopDownCallable : VisitorCallable<Callable>
{
using VisitorCallable<Callable>::VisitorCallable;
using VisitedObject = TVisitedObject;
};

template<class Callable, class TVisitedObject>
struct BottomUpCallable : VisitorCallable<Callable>
{
using VisitorCallable<Callable>::VisitorCallable;
using VisitedObject = TVisitedObject;
};

#define MAKE_CALLABLE(visitorCallable, Base, visitedObject) \
template<class Callable> struct visitorCallable : Base<Callable, visitedObject> { \
constexpr explicit visitorCallable(const Callable& callable) : Base<Callable, visitedObject>(callable) {} \
constexpr explicit visitorCallable(Callable&& callable) : Base<Callable, visitedObject>(std::forward<Callable>(callable)) {} \
};

#define MAKE_CREATORS(className, visitorCallable)\
template<class Callable>\
className<MechanicalVisitor, Callable> makeMechanicalVisitor(const sofa::core::MechanicalParams* mparams, const visitorCallable<Callable>& callable)\
{\
return className<MechanicalVisitor, Callable>(mparams, callable); \
}\
template<class Callable, class... Tail>\
auto makeMechanicalVisitor(const sofa::core::MechanicalParams* mparams, const visitorCallable<Callable>& callable, const Tail&... tail)\
{\
const className<decltype(makeMechanicalVisitor(mparams, tail...)), Callable> r(mparams, callable, tail...); \
return r;\
}

#define MAKE_TOP_DOWN_MECHANICAL_VISITOR_TYPE(className, visitedObject, functionName, visitorCallable) \
MAKE_CALLABLE(visitorCallable, TopDownCallable, visitedObject)\
template<class Base, class Callable>\
class className : public Base\
{\
public:\
template<class... OtherCallables>\
className(const sofa::core::MechanicalParams* mparams, const visitorCallable<Callable>& callable, const OtherCallables&... others)\
: Base(mparams, others...), m_callable(callable.m_callable)\
{}\
\
Visitor::Result functionName(Node* node, visitedObject* solver) override\
{\
return m_callable(node, solver);\
}\
\
protected:\
Callable m_callable;\
};\
MAKE_CREATORS(className, visitorCallable)

#define MAKE_BOTTOM_UP_MECHANICAL_VISITOR_TYPE(className, visitedObject, functionName, visitorCallable) \
MAKE_CALLABLE(visitorCallable, TopDownCallable, visitedObject)\
template<class Base, class Callable>\
class className : public Base\
{\
public:\
template<class... OtherCallables>\
className(const sofa::core::MechanicalParams* mparams, const visitorCallable<Callable>& callable, const OtherCallables&... others)\
: Base(mparams, others...), m_callable(callable.m_callable)\
{}\
\
void functionName(Node* node, visitedObject* solver) override\
{\
m_callable(node, solver);\
}\
\
protected:\
Callable m_callable;\
};\
MAKE_CREATORS(className, visitorCallable)

MAKE_TOP_DOWN_MECHANICAL_VISITOR_TYPE(TopDownMechanicalVisitorOdeSolver, core::behavior::OdeSolver, fwdOdeSolver, TopDownOdeSolverCallable)
MAKE_TOP_DOWN_MECHANICAL_VISITOR_TYPE(TopDownMechanicalVisitorConstraintSolver, core::behavior::ConstraintSolver, fwdConstraintSolver, TopDownConstraintSolverCallable)
MAKE_TOP_DOWN_MECHANICAL_VISITOR_TYPE(TopDownMechanicalVisitorMechanicalMapping, core::BaseMapping, fwdMechanicalMapping, TopDownMechanicalMappingCallable)
MAKE_TOP_DOWN_MECHANICAL_VISITOR_TYPE(TopDownMechanicalVisitorMappedMechanicalState, sofa::core::behavior::BaseMechanicalState, fwdMappedMechanicalState, TopDownMappedMechanicalStateCallable)
MAKE_TOP_DOWN_MECHANICAL_VISITOR_TYPE(TopDownMechanicalVisitorMechanicalState, sofa::core::behavior::BaseMechanicalState, fwdMechanicalState, TopDownMechanicalStateCallable)
MAKE_TOP_DOWN_MECHANICAL_VISITOR_TYPE(TopDownMechanicalVisitorMass, sofa::core::behavior::BaseMass, fwdMass, TopDownMassCallable)
MAKE_TOP_DOWN_MECHANICAL_VISITOR_TYPE(TopDownMechanicalVisitorForceField, sofa::core::behavior::BaseForceField, fwdForceField, TopDownForceFieldCallable)
MAKE_TOP_DOWN_MECHANICAL_VISITOR_TYPE(TopDownMechanicalVisitorInteractionForceField, sofa::core::behavior::BaseInteractionForceField, fwdInteractionForceField, TopDownInteractionForceFieldCallable)
MAKE_TOP_DOWN_MECHANICAL_VISITOR_TYPE(TopDownMechanicalVisitorProjectiveConstraintSet, sofa::core::behavior::BaseProjectiveConstraintSet, fwdProjectiveConstraintSet, TopDownProjectiveConstraintSetCallable)
MAKE_TOP_DOWN_MECHANICAL_VISITOR_TYPE(TopDownMechanicalVisitorConstraintSet, sofa::core::behavior::BaseConstraintSet, fwdConstraintSet, TopDownConstraintSetCallable)
MAKE_TOP_DOWN_MECHANICAL_VISITOR_TYPE(TopDownMechanicalVisitorInteractionProjectiveConstraintSet, sofa::core::behavior::BaseInteractionProjectiveConstraintSet, fwdInteractionProjectiveConstraintSet, TopDownInteractionProjectiveConstraintSetCallable)
MAKE_TOP_DOWN_MECHANICAL_VISITOR_TYPE(TopDownMechanicalVisitorInteractionConstraint, sofa::core::behavior::BaseInteractionConstraint, fwdInteractionConstraint, TopDownInteractionInteractionConstraintCallable)


MAKE_BOTTOM_UP_MECHANICAL_VISITOR_TYPE(BottomUpMechanicalVisitorMechanicalState, core::behavior::BaseMechanicalState, bwdMechanicalState, BottomUpMechanicalStateCallable)
MAKE_BOTTOM_UP_MECHANICAL_VISITOR_TYPE(BottomUpMechanicalVisitorMappedMechanicalState, core::behavior::BaseMechanicalState, bwdMappedMechanicalState, BottomUpMappedMechanicalStateCallable)
MAKE_BOTTOM_UP_MECHANICAL_VISITOR_TYPE(BottomUpMechanicalVisitorMechanicalMapping, core::BaseMapping, bwdMechanicalMapping, BottomUpMechanicalMappingCallable)
MAKE_BOTTOM_UP_MECHANICAL_VISITOR_TYPE(BottomUpMechanicalVisitorOdeSolver, core::behavior::OdeSolver, bwdOdeSolver, BottomUpOdeSolverCallable)
MAKE_BOTTOM_UP_MECHANICAL_VISITOR_TYPE(BottomUpMechanicalVisitorConstraintSolver, core::behavior::ConstraintSolver, bwdConstraintSolver, BottomUpConstraintSolverCallable)
MAKE_BOTTOM_UP_MECHANICAL_VISITOR_TYPE(BottomUpMechanicalVisitorProjectiveConstraintSet, core::behavior::BaseProjectiveConstraintSet, bwdProjectiveConstraintSet, BottomUpProjectiveConstraintSetCallable)
MAKE_BOTTOM_UP_MECHANICAL_VISITOR_TYPE(BottomUpMechanicalVisitorConstraintSet, core::behavior::BaseConstraintSet, bwdConstraintSet, BottomUpConstraintSetCallable)


}

0 comments on commit 7b8af41

Please sign in to comment.