Skip to content

Commit

Permalink
[mapping] new component (BeamProjectionDifferenceMultiMapping) (#113)
Browse files Browse the repository at this point in the history
* [mapping] new component (BeamProjectionDifferenceMultiMapping)

* [mapping] change files' header
  • Loading branch information
EulalieCoevoet authored Oct 26, 2023
1 parent fc6a7df commit 3b856ad
Show file tree
Hide file tree
Showing 6 changed files with 1,045 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
/******************************************************************************
* 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] *
******************************************************************************/
#include <sofa/testing/BaseSimulationTest.h>
using sofa::testing::BaseSimulationTest;

#include <SceneCreator/SceneCreator.h>

#include <sofa/simulation/graph/DAGSimulation.h>
#include <sofa/defaulttype/VecTypes.h>
#include <sofa/defaulttype/RigidTypes.h>
#include <sofa/component/statecontainer/MechanicalObject.h>
#include <sofa/component/topology/container/constant/MeshTopology.h>
#include <sofa/component/mapping/testing/Multi2MappingTestCreation.h>

#include <BeamAdapter/component/mapping/BeamProjectionDifferenceMultiMapping.h>
#include <BeamAdapter/component/BeamInterpolation.h>

namespace beamadapter::test {

using namespace sofa::core;
using namespace sofa::component;
using sofa::type::Vec;
using sofa::type::Mat;
using sofa::core::objectmodel::New;


/** Test suite for BeamProjectionDifferenceMultiMapping.
The test cases are defined in the #Test_Cases member group.
*/
template <typename _BeamProjectionDifferenceMultiMapping>
struct BeamProjectionDifferenceMultiMappingTest : public sofa::Multi2Mapping_test<_BeamProjectionDifferenceMultiMapping>
{

typedef _BeamProjectionDifferenceMultiMapping BeamProjectionDifferenceMultiMapping;
typedef sofa::Multi2Mapping_test<BeamProjectionDifferenceMultiMapping> Inherit;

typedef typename BeamProjectionDifferenceMultiMapping::In1 In1DataTypes;
typedef typename BeamProjectionDifferenceMultiMapping::In2 In2DataTypes;
typedef statecontainer::MechanicalObject<In1DataTypes> In1MechanicalObject;
typedef statecontainer::MechanicalObject<In2DataTypes> In2MechanicalObject;

typedef typename BeamProjectionDifferenceMultiMapping::Out OutDataTypes;
typedef statecontainer::MechanicalObject<OutDataTypes> OutMechanicalObject;

typedef typename In1DataTypes::VecCoord In1VecCoord;
typedef typename In2DataTypes::VecCoord In2VecCoord;
typedef typename OutDataTypes::VecCoord OutVecCoord;


void SetUp() override
{
}


BeamProjectionDifferenceMultiMapping* m_mapping;
sofa::component::fem::BeamInterpolation<sofa::defaulttype::Rigid3Types>* m_interpolation;
sofa::component::topology::container::constant::MeshTopology* m_topology;


BeamProjectionDifferenceMultiMappingTest()
{
this->setupScene();
this->errorMax = 10;

m_mapping = static_cast<BeamProjectionDifferenceMultiMapping*>( this->mapping );
}


/** @name Test_Cases
For each of these cases, we can test if the mapping work
*/
bool test_oneBeam_twoParticles()
{
const int Nin1=1, Nin2=2;
this->in1Dofs.resize(Nin1);
this->in2Dofs.resize(Nin2);
this->outDofs->resize(Nin1);

// parent position
In1VecCoord xin1(Nin1);
In1DataTypes::set( xin1[0], 0.5, 0., 0.);

// the beam
In2VecCoord xin2(Nin2);
In2DataTypes::set( xin2[0], 0., 0., 0. );
In2DataTypes::set( xin2[1], 1., 0., 0. );

// expected mapped values
OutVecCoord expectedChildCoords(Nin1);
OutDataTypes::set( expectedChildCoords[0], 0., 0., 0.);

m_topology = sofa::modeling::addNew<sofa::component::topology::container::constant::MeshTopology>(this->parentsIn2).get();
m_topology->addEdge(0,1);
m_mapping->l_in2Topology.set(m_topology);
m_interpolation = sofa::modeling::addNew<sofa::component::fem::BeamInterpolation<sofa::defaulttype::Rigid3Types>>(this->parentsIn2).get();
m_mapping->l_interpolation.set(m_interpolation);
m_mapping->d_indices.setValue(sofa::vector<sofa::Index>{0});
sofa::type::vector<bool> directions{0, 1, 1, 0, 0, 0, 0};
m_mapping->d_directions.setValue(directions);

return this->runTest(sofa::vector<In1VecCoord>{xin1}, sofa::vector<In2VecCoord>{xin2}, expectedChildCoords);
}
};



// Define the list of types to instanciate. We do not necessarily need to test all combinations.
using ::testing::Types;
typedef Types<
beamadapter::mapping::BeamProjectionDifferenceMultiMapping<sofa::defaulttype::Rigid3Types, sofa::defaulttype::Rigid3Types, sofa::defaulttype::Rigid3Types>
> DataTypes; // the types to instanciate.

// Test suite for all the instanciations
TYPED_TEST_SUITE(BeamProjectionDifferenceMultiMappingTest, DataTypes);

TYPED_TEST( BeamProjectionDifferenceMultiMappingTest, oneBeam_twoParticles )
{
// child coordinates given directly in parent frame
ASSERT_TRUE(this->test_oneBeam_twoParticles());
}

} // namespace
3 changes: 3 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ set(HEADER_FILES
${BEAMADAPTER_SRC}/component/mapping/AdaptiveBeamMapping.inl
${BEAMADAPTER_SRC}/component/mapping/BeamLengthMapping.h
${BEAMADAPTER_SRC}/component/mapping/BeamLengthMapping.inl
${BEAMADAPTER_SRC}/component/mapping/BeamProjectionDifferenceMultiMapping.h
${BEAMADAPTER_SRC}/component/mapping/BeamProjectionDifferenceMultiMapping.inl
${BEAMADAPTER_SRC}/component/mapping/MultiAdaptiveBeamMapping.h
${BEAMADAPTER_SRC}/component/mapping/MultiAdaptiveBeamMapping.inl

Expand Down Expand Up @@ -94,6 +96,7 @@ set(SOURCE_FILES

${BEAMADAPTER_SRC}/component/mapping/AdaptiveBeamMapping.cpp
${BEAMADAPTER_SRC}/component/mapping/BeamLengthMapping.cpp
${BEAMADAPTER_SRC}/component/mapping/BeamProjectionDifferenceMultiMapping.cpp
${BEAMADAPTER_SRC}/component/mapping/MultiAdaptiveBeamMapping.cpp

${BEAMADAPTER_SRC}/component/model/BaseRodSectionMaterial.cpp
Expand Down
87 changes: 87 additions & 0 deletions examples/python3/component/BeamProjectionDifferenceMultiMapping.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
def createScene(rootnode):
settings = rootnode.addChild('Settings')
settings.addObject('RequiredPlugin', name='BeamAdapter') # Needed to use components [BeamProjectionDifferenceMultiMapping]
settings.addObject('RequiredPlugin', name='Sofa.Component.AnimationLoop') # Needed to use components [FreeMotionAnimationLoop]
settings.addObject('RequiredPlugin', name='Sofa.Component.Constraint.Lagrangian.Correction') # Needed to use components [GenericConstraintCorrection]
settings.addObject('RequiredPlugin', name='Sofa.Component.Constraint.Lagrangian.Solver') # Needed to use components [GenericConstraintSolver]
settings.addObject('RequiredPlugin', name='Sofa.Component.Constraint.Projective') # Needed to use components [FixedConstraint]
settings.addObject('RequiredPlugin', name='Sofa.Component.LinearSolver.Direct') # Needed to use components [SparseLDLSolver]
settings.addObject('RequiredPlugin', name='Sofa.Component.Mass') # Needed to use components [UniformMass]
settings.addObject('RequiredPlugin', name='Sofa.Component.ODESolver.Backward') # Needed to use components [EulerImplicitSolver]
settings.addObject('RequiredPlugin', name='Sofa.Component.SolidMechanics.Spring') # Needed to use components [RestShapeSpringsForceField]
settings.addObject('RequiredPlugin', name='Sofa.Component.StateContainer') # Needed to use components [MechanicalObject]
settings.addObject('RequiredPlugin', name='Sofa.Component.Topology.Container.Dynamic') # Needed to use components [EdgeSetTopologyContainer,PointSetTopologyContainer]
settings.addObject('RequiredPlugin', name='Sofa.Component.Visual') # Needed to use components [VisualStyle]
settings.addObject('RequiredPlugin', name='Sofa.GUI.Component') # Needed to use components [AttachBodyButtonSetting]

rootnode.addObject('VisualStyle', displayFlags='showBehavior showVisual')
rootnode.addObject('AttachBodyButtonSetting', stiffness=0.1)
rootnode.gravity.value = [0, -9810, 0]
rootnode.dt.value = 0.01

rootnode.addObject('FreeMotionAnimationLoop')
rootnode.addObject('GenericConstraintSolver', maxIterations=1000, tolerance=1e-3)

simulation = rootnode.addChild('Simulation')
simulation.addObject('EulerImplicitSolver')
simulation.addObject('SparseLDLSolver', template='CompressedRowSparseMatrixMat3x3d')
simulation.addObject('GenericConstraintCorrection')

# Beam
nbEdges = 3
beam = simulation.addChild('Beam')
beam.addObject('EdgeSetTopologyContainer', edges=[[i, i + 1] for i in range(nbEdges)])
beam.addObject('MechanicalObject', template='Rigid3',
position=[[100 * i, 0, 0, 0, 0, 0, 1] for i in range(nbEdges + 1)])
beam.addObject('AdaptiveBeamForceFieldAndMass', massDensity=1e-6)
beam.addObject('BeamInterpolation', straight=False, dofsAndBeamsAligned=False,
defaultYoungModulus=1e5)

# Particles
particles = simulation.addChild('Particles')
particles.addObject('PointSetTopologyContainer')
particles.addObject('MechanicalObject', template='Rigid3', showObject=True, showObjectScale=30, drawMode=1,
position=[[0, 0, 0, 0, 0, 0, 1], [80, 0, 0, 0, 0, 0, 1], [150, 0, 0, 0, 0, 0, 1]])
particles.addObject('UniformMass', totalMass=0.005)
particles.addObject('FixedConstraint', indices=[0, 2]) # Fix first and last particles

# This will constrain the first particle and its projection on the beam to remain attached together
fixing = particles.addChild('FixingConstraintParticle1')
beam.addChild(fixing)
fixing.addObject('MechanicalObject', template='Rigid3', position=[0, 0, 0, 0, 0, 0, 0])
fixing.addObject('RestShapeSpringsForceField', stiffness=1e6, angularStiffness=1e6)
fixing.addObject('BeamProjectionDifferenceMultiMapping',
directions=[1, 1, 1, 1, 1, 1, 1], # The three positions and rotations
input1=particles.getMechanicalState().linkpath,
indicesInput1=[0],
input2=beam.getMechanicalState().linkpath,
interpolationInput2=beam.BeamInterpolation.linkpath,
output=fixing.getMechanicalState().linkpath)

# This will constrain the second particle to slide along the beam, and it will also constrain the orientation
# of the beam and the particle to remain the same
sliding = particles.addChild('SlidingConstraintParticle2')
beam.addChild(sliding)
sliding.addObject('MechanicalObject', template='Rigid3', position=[0, 0, 0, 0, 0, 0, 0])
sliding.addObject('RestShapeSpringsForceField', stiffness=1e6, angularStiffness=0)
sliding.addObject('BeamProjectionDifferenceMultiMapping',
directions=[0, 1, 1, 1, 1, 1, 1], # Only y, z positions to allow the particle to slide on the beam
# but this time we add the three rotations
input1=particles.getMechanicalState().linkpath,
indicesInput1=[1],
input2=beam.getMechanicalState().linkpath,
interpolationInput2=beam.BeamInterpolation.linkpath,
output=sliding.getMechanicalState().linkpath)

# This will constrain the third particle to slide along the beam
sliding = particles.addChild('SlidingConstraintParticle3')
beam.addChild(sliding)
sliding.addObject('MechanicalObject', template='Rigid3', position=[0, 0, 0, 0, 0, 0, 0])
sliding.addObject('RestShapeSpringsForceField', stiffness=1e6, angularStiffness=1e6)
sliding.addObject('BeamProjectionDifferenceMultiMapping',
directions=[0, 1, 1, 0, 0, 0, 0], # Only y, z positions to allow the particle to slide on the beam
input1=particles.getMechanicalState().linkpath,
indicesInput1=[2],
input2=beam.getMechanicalState().linkpath,
interpolationInput2=beam.BeamInterpolation.linkpath,
output=sliding.getMechanicalState().linkpath)
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/******************************************************************************
* BeamAdapter plugin *
* (c) 2006 Inria, University of Lille, CNRS *
* *
* 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: see Authors.md *
* *
* Contact information: [email protected] *
******************************************************************************/
//
// Author: Eulalie Coevoet
//
// Copyright: See COPYING file that comes with this distribution

#define BEAMADAPTER_MAPPING_BEAMPROJECTIONDIFFERENCEMULTIMAPPING_CPP

#include <BeamAdapter/component/mapping/BeamProjectionDifferenceMultiMapping.inl>

#include <sofa/defaulttype/VecTypes.h>
#include <sofa/core/ObjectFactory.h>

namespace beamadapter::mapping
{

using namespace sofa::defaulttype;

// Register in the Factory
int BeamProjectionDifferenceMultiMappingClass = sofa::core::RegisterObject("Computes the difference between given points and their projection on a beam.")
.add< BeamProjectionDifferenceMultiMapping< Rigid3Types, Rigid3Types, Rigid3Types > >();

} // namespace
Loading

0 comments on commit 3b856ad

Please sign in to comment.