yade-users team mailing list archive
Mailing list archive
Re: triaxial test
Bruno Chareyre said: (by the date of Fri, 25 Nov 2005 18:16:58 +0100)
> I will start coding something to control forces on the sides of an "axis
> aligned" box by modifying its size (triaxial test...).
> In my understanding of Yade, the best way is to create a DeusEx engine
> similar to e.g. TranslationEngine (Janek, do you agree?).
yes. you will have to create another DeusEx starting from for example
TranslationEngine. You will subscribe bodies (I mean - walls of the
triaxial test box) to it. And it will control their movement. I think
that in fact it will be easier to assign one wall to one engine. as they
will all go in different directions. So you will have six engines in the
engines (old name: MetaBody::actors) list.
> But in this case, the engine need the total forces Fk (k=1,...,6)
> applied on each side of the wall.
> The fastest way to obtain the Fk is probably to increment them in a
> modified version of ElasticContactLaw.
you already have the total force :) No need to modify ElasticContactLaw.
That is because it is not checking for what kind of body it is
calculating forces. Total sum of forces acting on the wall is stored
inside MetaBody::actionParameters (oh, by the way - I will rename soon
actionParameters to physicalActions, sorry for the mess - I think it
will make things a little bit more clear).
to retreive total sum of forces acting on the wall just do that:
Vector3r totalForce = static_cast<Force*>( ncb->actionParameters->find( id , actionForce->getClassIndex() ).get() )->force;
- ncb is MetaBody casted at the beginning of the function
- id is the id of a wall, taken for example from subscribed bodies
(returned by function Body::getId() )
- actionForce is any instance of class Force (look at constructor of
ElacticContactLaw to see it being created). this variable is used ONLY
to get the index of Force. nothing more. Indexes are actually assigned
during runtime, and you never know what is the index of Momentum or
Force or index of any other class (possibly soon I will add
Displacement - I need it for my lattice model)
> Another way could be to compute the forces inside the DeusEx Engine
> itself, by retrieving all sphere-box interactions and summing the
> corresponding forces. In that case, is there a way to get a list of all
> interactions on a box (more generally, considering a Body b0, is there a
> quick way to get all interactions which have b0 as body?) ? or does it
> need to go through all interactions and see which belong to the box ?
there is an InteractionContainer MetaBody::volatileInteractions, and all
interactions used by ElasticContactLaw are there. And currently the only
way to see which belong to the wall, is to iterate all of them and
compare id1 and id2 with wall's id. I have some idea how to make it
simpler and faster, so I'll improve it at some point in the future.
But since you already have your total force - you don't need to scan all
> Another simple question :
> In "PhysicalActionApplier.cpp", I see
> operator()( action ,
> (*bodies)[id]->physicalParameters,(*bodies)[id].get() );
> Which class operator() belongs to??
this is a very good question indeed :) It's one of those things that
belong to the yade's manual (which hopefully I'll soon release ;)
be detective: PhysicalActionApplier does not contain operator(), but it
inherits from MetaDispatchingEngine2D, so look there. But operator() is
still not there, MetaDispatchingEngine2D is inheriting from
MetaDispatchingEngine and DynLibDispatcher. Look at both of them.
Finally you will find thousands of operator() in DynLibDispatcher.
You will find it. But you will have absolutely no idea what it is doing
:) So I must explain.
DynLibDispatcher is one of fundamental concepts that makes yade easy to
use. It makes sure that correct function is called depending on what
classes we want to process. I won't explain how DynLibDispatcher works
by itself (as it's not easy to explain). But it is very easy to explain
how to use it. Look at SDECSpheresPlane.cpp:
shared_ptr<PhysicalActionApplier> applyActionDispatcher(new PhysicalActionApplier);
here we are telling what arguments PhysicalActionApplier should expect.
And depending on them - what class to call.
so if PhysicalActionApplier gets as an argument class Force, and it is
working on class RigidBodyParameters (or class that derives from it) -
then it should call NewtonsForceLaw.
so basically that line:
> operator()( action , (*bodies)[id]->physicalParameters,(*bodies)[id].get() );
is calling NewtonsForceLaw if:
- action is an instance of class Force, and
- (*bodies)[id]->physicalParameters is an instance of class
RigidBodyParameters (or class deriving from it)
- last argument is additional pointer to the Body* on which NewtonsForceLaw will work
and is calling NewtonsMomentumLaw - you know when :)
if it encounters a situation not mentioned below:
then an error is printed and nothing happens.
All this magic is possible because action and physicalParameters are
indexable clasess, and DynLibDispatcher is taking their index, and based
on that - is calling a right function which is stored in two dimensional
matrix. by calling applyActionDispatcher->add you are simply filling
this 2d matrix with correct data.
- to make your triaxial test you should only modify SDECTriaxialTest
filegenerator, and add a new DeuxEx. nothing more. No need to modify
ElasticContactLaw or anything else.
- inside filegenerator you will create 6 walls, remember their id to
subscribe them later to six instances of your DeuxEx (you choose a name
for it). Also this DeusEx will need some additional arguments - like the
Vector3r direction; that tells it in which direction it should move.
- inside this DeuxEx you retreive the total force acting on the wall as
explained above, calculate your displacement, then apply this
displacement to wall's se3.position (just like TranslationEngine).
I think that's all. shouldn't be too difficult I think?
if anything is unclear - please ask again and I will be happy to explain.
Janek Kozicki |
Yade-users mailing list