yade-dev team mailing list archive
-
yade-dev team
-
Mailing list archive
-
Message #09995
Re: Modified GlobalStiffnessTimeStepper for visco-elastic contact law
Hi Raphaël,
could you, please, attach a diff (or patch) instead of copying it into
the mail-body.
Thanks,
Anton
2013/9/20 Raphaël Maurin <raphael.maurin@xxxxxxxxx>:
> Hi all,
> Here is the final version of GlobalStiffnessTimeStepper that I modified to
> take into account the viscous contribution when using
> Law2_ScGeom_ViscElPhys_Basic.
> I didn't modify the elastic part, so that it will work exactly the same for
> people using it as before (considering only elastic contribution). I just
> added an option : viscEl which, when True, allows to calculate the time step
> for ViscElPhys as described before.
> I tested it and everything works well.
>
> I put the patch below for GlobalStiffnessTimeStepper.cpp and
> GlobalStiffnessTimeStepper.hpp, can someone add the change on github ?
> Thanks
>
> Raphael
>
>
>
> GlobalStiffnessTimeStepper.cpp
>
>
>
> diff --git a/pkg/dem/GlobalStiffnessTimeStepper.cpp
> b/pkg/dem/GlobalStiffnessTimeStepper.cpp
> index 8a41ceb..0205655 100644
> --- a/pkg/dem/GlobalStiffnessTimeStepper.cpp
> +++ b/pkg/dem/GlobalStiffnessTimeStepper.cpp
> @@ -14,6 +14,7 @@
> #include<yade/core/Scene.hpp>
> #include<yade/core/Clump.hpp>
> #include<yade/pkg/dem/Shop.hpp>
> +#include<yade/pkg/dem/ViscoelasticPM.hpp>
>
> CREATE_LOGGER(GlobalStiffnessTimeStepper);
> YADE_PLUGIN((GlobalStiffnessTimeStepper));
> @@ -25,13 +26,16 @@ void
> GlobalStiffnessTimeStepper::findTimeStepFromBody(const shared_ptr<Body>& bo
> State* sdec=body->state.get();
> Vector3r& stiffness= stiffnesses[body->getId()];
> Vector3r& Rstiffness=Rstiffnesses[body->getId()];
> -
> if(body->isClump()) {// if clump, we sum stifnesses of all members
> const shared_ptr<Clump>&
> clump=YADE_PTR_CAST<Clump>(body->shape);
> FOREACH(Clump::MemberMap::value_type& B, clump->members){
> const shared_ptr<Body>& b =
> Body::byId(B.first,scene);
> stiffness+=stiffnesses[b->getId()];
> Rstiffness+=Rstiffnesses[b->getId()];
> + if (viscEl == true){
> +
> viscosities[body->getId()]+=viscosities[b->getId()];
> +
> Rviscosities[body->getId()]+=Rviscosities[b->getId()];
> + }
> }
> }
>
> @@ -39,13 +43,15 @@ void
> GlobalStiffnessTimeStepper::findTimeStepFromBody(const shared_ptr<Body>& bo
> if (densityScaling) sdec->densityScaling =
> min(1.0001*sdec->densityScaling,
> timestepSafetyCoefficient*pow(defaultDt/targetDt,2.0));
> return; // not possible to compute!
> }
> -
> +
> + //Determine the elastic minimum eigenperiod (and if required
> determine also the viscous one separately and take the minimum of the two)
> +
> + //Elastic
> Real dtx, dty, dtz;
> Real dt = max( max (stiffness.x(), stiffness.y()), stiffness.z() );
> if (dt!=0) {
> dt = sdec->mass/dt; computedSomething = true;}//dt =
> squared eigenperiod of translational motion
> else dt = Mathr::MAX_REAL;
> -
> if (Rstiffness.x()!=0) {
> dtx = sdec->inertia.x()/Rstiffness.x(); computedSomething =
> true;}//dtx = squared eigenperiod of rotational motion around x
> else dtx = Mathr::MAX_REAL;
> @@ -56,15 +62,43 @@ void
> GlobalStiffnessTimeStepper::findTimeStepFromBody(const shared_ptr<Body>& bo
> dtz = sdec->inertia.z()/Rstiffness.z(); computedSomething =
> true;}
> else dtz = Mathr::MAX_REAL;
>
> - Real Rdt = std::min( std::min (dtx, dty), dtz );//Rdt = smallest
> squared eigenperiod for rotational motions
> + Real Rdt = std::min( std::min (dtx, dty), dtz );//Rdt = smallest
> squared eigenperiod for elastic rotational motions
> dt =
> 1.41044*timestepSafetyCoefficient*std::sqrt(std::min(dt,Rdt));//1.41044 =
> sqrt(2)
> +
> + //Viscous
> + if (viscEl == true){
> + Vector3r& viscosity = viscosities[body->getId()];
> + Vector3r& Rviscosity = Rviscosities[body->getId()];
> + Real dtx_visc, dty_visc, dtz_visc;
> + Real dt_visc = max(max(viscosity.x(), viscosity.y()),
> viscosity.z() );
> + if (dt_visc!=0) {
> + dt_visc = sdec->mass/dt_visc; computedSomething =
> true;}//dt = eigenperiod of the viscous translational motion
> + else {dt_visc = Mathr::MAX_REAL;}
> +
> + if (Rviscosity.x()!=0) {
> + dtx_visc = sdec->inertia.x()/Rviscosity.x();
> computedSomething = true;}//dtx = eigenperiod of viscous rotational motion
> around x
> + else dtx_visc = Mathr::MAX_REAL;
> + if (Rviscosity.y()!=0) {
> + dty_visc = sdec->inertia.y()/Rviscosity.y();
> computedSomething = true;}
> + else dty_visc = Mathr::MAX_REAL;
> + if (Rviscosity.z()!=0) {
> + dtz_visc = sdec->inertia.z()/Rviscosity.z();
> computedSomething = true;}
> + else dtz_visc = Mathr::MAX_REAL;
> +
> + Real Rdt_visc = std::min( std::min (dtx_visc, dty_visc),
> dtz_visc );//Rdt = smallest squared eigenperiod for viscous rotational
> motions
> + dt_visc =
> 2*timestepSafetyCoefficient*std::min(dt_visc,Rdt_visc);
> +
> + //Take the minimum between the elastic and viscous minimum
> eigenperiod.
> + dt = std::min(dt,dt_visc);
> + }
> +
> //if there is a target dt, then we apply density scaling on the
> body, the inertia used in Newton will be mass*scaling, the weight is
> unmodified
> if (densityScaling) {
> sdec->densityScaling =
> min(sdec->densityScaling,timestepSafetyCoefficient*pow(dt /targetDt,2.0));
> newDt=targetDt;
> }
> //else we update dt normaly
> - else {newDt = std::min(dt,newDt);}
> + else {newDt = std::min(dt,newDt);}
> }
>
> bool GlobalStiffnessTimeStepper::isActivated()
> @@ -97,7 +131,7 @@ void GlobalStiffnessTimeStepper::computeTimeStep(Scene*
> ncb)
> computedOnce = true;}
> else if (!computedOnce) scene->dt=defaultDt;
> LOG_INFO("computed timestep " << newDt <<
> - (scene->dt==newDt ? string(", appplied") :
> + (scene->dt==newDt ? string(", applied") :
> string(", BUT timestep is
> ")+lexical_cast<string>(scene->dt))<<".");
> }
>
> @@ -107,15 +141,24 @@ void
> GlobalStiffnessTimeStepper::computeStiffnesses(Scene* rb){
> if(size<rb->bodies->size()){
> size=rb->bodies->size();
> stiffnesses.resize(size); Rstiffnesses.resize(size);
> + if (viscEl == true){
> + viscosities.resize(size); Rviscosities.resize(size);
> + }
> }
> /* reset stored values */
> memset(& stiffnesses[0],0,sizeof(Vector3r)*size);
> memset(&Rstiffnesses[0],0,sizeof(Vector3r)*size);
> + if (viscEl == true){
> + memset(& viscosities[0],0,sizeof(Vector3r)*size);
> + memset(&Rviscosities[0],0,sizeof(Vector3r)*size);
> + }
> +
> FOREACH(const shared_ptr<Interaction>& contact, *rb->interactions){
> if(!contact->isReal()) continue;
>
> GenericSpheresContact*
> geom=YADE_CAST<GenericSpheresContact*>(contact->geom.get()); assert(geom);
> NormShearPhys*
> phys=YADE_CAST<NormShearPhys*>(contact->phys.get()); assert(phys);
> +
> // all we need for getting stiffness
> Vector3r& normal=geom->normal; Real& kn=phys->kn; Real&
> ks=phys->ks; Real& radius1=geom->refR1; Real& radius2=geom->refR2;
> Real fn = (static_cast<NormShearPhys *>
> (contact->phys.get()))->normalForce.squaredNorm();
> @@ -134,10 +177,35 @@ void
> GlobalStiffnessTimeStepper::computeStiffnesses(Scene* rb){
>
> std::pow(normal.x(),2)+std::pow(normal.z(),2),
>
> std::pow(normal.x(),2)+std::pow(normal.y(),2));
> diag_Rstiffness *= ks;
> +
> +
> //NOTE : contact laws with moments would be handled
> correctly by summing directly bending+twisting stiffness to diag_Rstiffness.
> The fact that there is no problem currently with e.g. cohesiveFrict law is
> probably because final computed dt is constrained by translational motion,
> not rotations.
> stiffnesses [contact->getId1()]+=diag_stiffness;
>
> Rstiffnesses[contact->getId1()]+=diag_Rstiffness*pow(radius1,2);
> stiffnesses [contact->getId2()]+=diag_stiffness;
> -
> Rstiffnesses[contact->getId2()]+=diag_Rstiffness*pow(radius2,2);
> +
> Rstiffnesses[contact->getId2()]+=diag_Rstiffness*pow(radius2,2);
> +
> + //Same for the Viscous part, if required
> + if (viscEl == true){
> + ViscElPhys* viscPhys =
> YADE_CAST<ViscElPhys*>(contact->phys.get()); assert(viscPhys);
> + Real& cn=viscPhys->cn; Real& cs=viscPhys->cs;
> + //Diagonal terms of the translational viscous matrix
> + Vector3r diag_viscosity =
> Vector3r(std::pow(normal.x(),2),std::pow(normal.y(),2),std::pow(normal.z(),2));
> + diag_viscosity *= cn-cs;
> + diag_viscosity = diag_viscosity +
> Vector3r(1,1,1)*cs;
> + //diagonal terms of the rotational viscous matrix
> + Vector3r diag_Rviscosity =
> +
> Vector3r(std::pow(normal.y(),2)+std::pow(normal.z(),2),
> +
> std::pow(normal.x(),2)+std::pow(normal.z(),2),
> +
> std::pow(normal.x(),2)+std::pow(normal.y(),2));
> + diag_Rviscosity *= cs;
> +
> + // Add the contact stiffness matrix to the two
> particles one
> + viscosities [contact->getId1()]+=diag_viscosity;
> +
> Rviscosities[contact->getId1()]+=diag_Rviscosity*pow(radius1,2);
> + viscosities [contact->getId2()]+=diag_viscosity;
> +
> Rviscosities[contact->getId2()]+=diag_Rviscosity*pow(radius2,2);
> + }
> +
> }
> }
>
>
>
>
>
>
> GlobalStiffnessTimeStepper.hpp
>
>
>
>
>
>
> diff --git a/pkg/dem/GlobalStiffnessTimeStepper.hpp
> b/pkg/dem/GlobalStiffnessTimeStepper.hpp
> index 1d60f88..bd657fa 100644
> --- a/pkg/dem/GlobalStiffnessTimeStepper.hpp
> +++ b/pkg/dem/GlobalStiffnessTimeStepper.hpp
> @@ -24,6 +24,8 @@ class GlobalStiffnessTimeStepper : public TimeStepper
> private :
> vector<Vector3r> stiffnesses;
> vector<Vector3r> Rstiffnesses;
> + vector<Vector3r> viscosities;
> + vector<Vector3r> Rviscosities;
> void computeStiffnesses(Scene*);
>
> Real newDt;
> @@ -37,13 +39,14 @@ class GlobalStiffnessTimeStepper : public TimeStepper
> virtual void computeTimeStep(Scene*);
> virtual bool isActivated();
> YADE_CLASS_BASE_DOC_ATTRS_CTOR(
> - GlobalStiffnessTimeStepper,TimeStepper,"An engine
> assigning the time-step as a fraction of the minimum eigen-period in the
> problem. The derivation is detailed in the chapter on `DEM formulation
> <https://www.yade-dem.org/doc/formulation.html#dem-simulations>`_",
> + GlobalStiffnessTimeStepper,TimeStepper,"An engine
> assigning the time-step as a fraction of the minimum eigen-period in the
> problem. The derivation is detailed in the chapter on `DEM formulation
> <https://www.yade-dem.org/doc/formulation.html#dem-simulations>`_. The
> viscEl option enables to evaluate the timestep in a similar way for the
> visco-elastic contact law :yref:`Law2_ScGeom_ViscElPhys_Basic`, more detail
> in :yref:`GlobalStiffnessTimestepper::viscEl`. ",
> ((Real,defaultDt,-1,,"used as the initial value of
> the timestep (especially useful in the first steps when no contact exist).
> If negative, it will be defined by :yref:`utils.PWaveTimeStep` *
> :yref:`GlobalStiffnessTimeStepper::timestepSafetyCoefficient`"))
> ((Real,maxDt,Mathr::MAX_REAL,,"if positive, used as
> max value of the timestep whatever the computed value"))
> ((Real,previousDt,1,,"last computed dt |yupdate|"))
> ((Real,timestepSafetyCoefficient,0.8,,"safety factor
> between the minimum eigen-period and the final assigned dt (less than 1))"))
> ((bool,densityScaling,false,,"|yupdate| don't modify
> this value if you don't plan to modify the scaling factor manually for some
> bodies. In most cases, it is enough to set
> :yref:`NewtonIntegrator::densityScaling` and let this one be adjusted
> automatically."))
> - ((Real,targetDt,1,,"if
> :yref:`NewtonIntegrator::densityScaling` is active, this value will be used
> as the simulation timestep and the scaling will use this value of dt as the
> target value. The value of targetDt is arbitrary and should have no effect
> in the result in general. However if some bodies have imposed velocities,
> for instance, they will move more or less per each step depending on this
> value.")),
> + ((Real,targetDt,1,,"if
> :yref:`NewtonIntegrator::densityScaling` is active, this value will be used
> as the simulation timestep and the scaling will use this value of dt as the
> target value. The value of targetDt is arbitrary and should have no effect
> in the result in general. However if some bodies have imposed velocities,
> for instance, they will move more or less per each step depending on this
> value."))
> + ((bool,viscEl,false,,"To use with
> :yref:`ViscElPhys`. if True, evaluate separetly the minimum eigen-period in
> the problem considering only the elastic contribution on one hand (spring
> only), and only the viscous contribution on the other hand (dashpot only).
> Take then the minimum of the two and use the safety coefficient
> :yref:`GlobalStiffnessTimestepper::timestepSafetyCoefficient` to take into
> account the possible coupling between the two contribution.")),
> computedOnce=false;)
> DECLARE_LOGGER;
> };
>
>
>
>
>
>
>
>
>
>
> -------- Message d'origine--------
> De: Raphaël Maurin
> Date: mar. 03/09/2013 12:21
> À: yade-dev@xxxxxxxxxxxxxxxxxxx
> Objet : Modified GlobalStiffnessTimeStepper for visco-elastic contact law
>
> Hi all,
>
> I developed a "copy" of GlobalStiffnessTimeStepper which evaluate the time
> step of a system of particle with Law2_ScGeom_ViscElPhys_Basic contact law
> (spring + viscous damping).
>
> The principle of the time step evaluation is :
> We consider that the elastic and the viscous degrees of freedom are
> decoupled. From that, we evaluate the critical time step of the system of
> particles considering the elastic part only (dt_el) on one hand, and
> considering the viscous part only (dt_visc) on the other hand. Then, we take
> the minimum of the two timestep and multiply it by a safety factor to
> account for the possible coupling between the two effect (dt =
> alpha*min(dt_el,dt_visc).
>
> To do so, I took GlobalStiffnessTimeStepper (GSTS) which is already
> evaluating the elastic critical time step, and implemented similarly a
> calculation for the viscous critical time step of the system from the the
> viscosity matrix of each particles. The changes are not so important between
> the version I implemented and the last one (see the code below). I tested it
> in cases where the normal viscous part is dominant and the new version gives
> a lower time step which allows to keep the caculus stable, while in the old
> version everything explode, so it seems to work.
>
> I have some questions about that :
> - Does the evaluation of the time step seems reasonable to you?
> - What can I do to test it quantitavely ? (if I try a collision between two
> beads, GSTS does not work..)
> - To add it to the code, should I add it as a new "file"/"function" or
> should I implement it as an option of GSTS ?
>
> And about GSTS in general :
> - why is GSTS not working when we consider a gravity deposition or a
> collision ?? (even when defaultDt is small enough)
>
> Thanks,
>
> Raphael
>
>
>
> GlobalStiffnessTimeStepper.cpp
>
> /*************************************************************************
> * Copyright (C) 2006 by Bruno Chareyre *
> * bruno.chareyre@xxxxxxxxxxx *
> * *
> * This program is free software; it is licensed under the terms of the *
> * GNU General Public License v2 or later. See file LICENSE for details. *
> *************************************************************************/
>
> #include"GlobalStiffnessTimeStepper.hpp"
> #include<yade/pkg/dem/FrictPhys.hpp>
> #include<yade/pkg/dem/ScGeom.hpp>
> #include<yade/pkg/dem/DemXDofGeom.hpp>
> #include<yade/core/Interaction.hpp>
> #include<yade/core/Scene.hpp>
> #include<yade/core/Clump.hpp>
> #include<yade/pkg/dem/Shop.hpp>
> #include<yade/pkg/dem/ViscoelasticPM.hpp>
>
> CREATE_LOGGER(GlobalStiffnessTimeStepper);
> YADE_PLUGIN((GlobalStiffnessTimeStepper));
>
> GlobalStiffnessTimeStepper::~GlobalStiffnessTimeStepper() {}
>
> void GlobalStiffnessTimeStepper::findTimeStepFromBody(const
> shared_ptr<Body>& body, Scene * ncb)
> {
> State* sdec=body->state.get();
> Vector3r& stiffness= stiffnesses[body->getId()];
> Vector3r& Rstiffness=Rstiffnesses[body->getId()];
> Vector3r& viscosity= viscosities[body->getId()];
> Vector3r& Rviscosity= Rviscosities[body->getId()];
>
> if(body->isClump()) {// if clump, we sum stifnesses of all members
> const shared_ptr<Clump>&
> clump=YADE_PTR_CAST<Clump>(body->shape);
> FOREACH(Clump::MemberMap::value_type& B, clump->members){
> const shared_ptr<Body>& b =
> Body::byId(B.first,scene);
> stiffness+=stiffnesses[b->getId()];
> Rstiffness+=Rstiffnesses[b->getId()];
> viscosity+=viscosities[b->getId()];
> Rviscosity+=Rviscosities[b->getId()];
> }
> }
>
> if(!sdec || stiffness==Vector3r::Zero()){
> if (densityScaling) sdec->densityScaling =
> min(1.0001*sdec->densityScaling,
> timestepSafetyCoefficient*pow(defaultDt/targetDt,2.0));
> return; // not possible to compute!
> }
>
> //Determine the elastic critical time step and the viscous one
> separately (as if they were decoupled) and take the minimum time step
> with a safety coefficient.
>
> //Elastic
> Real dtx, dty, dtz;
> Real dt = max( max (stiffness.x(), stiffness.y()), stiffness.z() );
> if (dt!=0) {
> dt = sdec->mass/dt; computedSomething = true;}//dt =
> squared eigenperiod of translational motion
> else dt = Mathr::MAX_REAL;
> if (Rstiffness.x()!=0) {
> dtx = sdec->inertia.x()/Rstiffness.x(); computedSomething =
> true;}//dtx = squared eigenperiod of rotational motion around x
> else dtx = Mathr::MAX_REAL;
> if (Rstiffness.y()!=0) {
> dty = sdec->inertia.y()/Rstiffness.y(); computedSomething =
> true;}
> else dty = Mathr::MAX_REAL;
> if (Rstiffness.z()!=0) {
> dtz = sdec->inertia.z()/Rstiffness.z(); computedSomething =
> true;}
> else dtz = Mathr::MAX_REAL;
>
> Real Rdt = std::min( std::min (dtx, dty), dtz );//Rdt = smallest
> squared eigenperiod for elastic rotational motions
> dt =
> 1.41044*timestepSafetyCoefficient*std::sqrt(std::min(dt,Rdt));//1.41044 =
> sqrt(2)
>
> //Viscous
> Real dtx_visc, dty_visc, dtz_visc;
> Real dt_visc = max(max(viscosity.x(), viscosity.y()), viscosity.z()
> );
> if (dt_visc!=0) {
> dt_visc = sdec->mass/dt_visc; computedSomething =
> true;}//dt = eigenperiod of the viscous translational motion
> else {dt_visc = Mathr::MAX_REAL;}
>
> if (Rviscosity.x()!=0) {
> dtx_visc = sdec->inertia.x()/Rviscosity.x();
> computedSomething = true;}//dtx = eigenperiod of viscous rotational motion
> around x
> else dtx_visc = Mathr::MAX_REAL;
> if (Rviscosity.y()!=0) {
> dty_visc = sdec->inertia.y()/Rviscosity.y();
> computedSomething = true;}
> else dty_visc = Mathr::MAX_REAL;
> if (Rviscosity.z()!=0) {
> dtz_visc = sdec->inertia.z()/Rviscosity.z();
> computedSomething = true;}
> else dtz_visc = Mathr::MAX_REAL;
>
> Real Rdt_visc = std::min( std::min (dtx_visc, dty_visc), dtz_visc
> );//Rdt = smallest squared eigenperiod for viscous rotational motions
> dt_visc = 2*timestepSafetyCoefficient*std::min(dt_visc,Rdt_visc);
>
> //Take the minimum between the elastic and viscous critical time
> step.
> dt = std::min(dt,dt_visc);
>
> //if there is a target dt, then we apply density scaling on the
> body, the inertia used in Newton will be mass*scaling, the weight is
> unmodified
> if (densityScaling) {
> sdec->densityScaling =
> min(sdec->densityScaling,timestepSafetyCoefficient*pow(dt /targetDt,2.0));
> newDt=targetDt;
> }
> //else we update dt normaly
> else {newDt = std::min(dt,newDt);}
> }
>
> bool GlobalStiffnessTimeStepper::isActivated()
> {
> return (active && ((!computedOnce) || (scene->iter %
> timeStepUpdateInterval == 0) || (scene->iter < (long int) 2) ));
> }
>
> void GlobalStiffnessTimeStepper::computeTimeStep(Scene* ncb)
> {
> // for some reason, this line is necessary to have correct
> functioning (no idea _why_)
> // see scripts/test/compare-identical.py, run with or without
> active=active.
> active=active;
> if (defaultDt<0) defaultDt=
> timestepSafetyCoefficient*Shop::PWaveTimeStep(Omega::instance().getScene());
> computeStiffnesses(ncb);
>
> shared_ptr<BodyContainer>& bodies = ncb->bodies;
> newDt = Mathr::MAX_REAL;
> computedSomething=false;
> BodyContainer::iterator bi = bodies->begin();
> BodyContainer::iterator biEnd = bodies->end();
> for( ; bi!=biEnd ; ++bi ){
> shared_ptr<Body> b = *bi;
> if (b->isDynamic() && !b->isClumpMember())
> findTimeStepFromBody(b, ncb);
>
> }
> if(densityScaling) (newDt=targetDt);
> if(computedSomething || densityScaling){
> previousDt = min ( min(newDt , maxDt), 1.05*previousDt );//
> at maximum, dt will be multiplied by 1.05 in one iterration, this is to
> prevent brutal switches from 0.000... to 1 in some computations
> scene->dt=previousDt;
> computedOnce = true;}
> else if (!computedOnce) scene->dt=defaultDt;
> LOG_INFO("computed timestep " << newDt <<
> (scene->dt==newDt ? string(", applied") :
> string(", BUT timestep is
> ")+lexical_cast<string>(scene->dt))<<".");
> }
>
> void GlobalStiffnessTimeStepper::computeStiffnesses(Scene* rb){
> /* check size */
> size_t size=stiffnesses.size();
> if(size<rb->bodies->size()){
> size=rb->bodies->size();
> stiffnesses.resize(size); Rstiffnesses.resize(size);
> viscosities.resize(size); Rviscosities.resize(size);
> }
> /* reset stored values */
> memset(& stiffnesses[0],0,sizeof(Vector3r)*size);
> memset(&Rstiffnesses[0],0,sizeof(Vector3r)*size);
> memset(& viscosities[0],0,sizeof(Vector3r)*size);
> memset(& Rviscosities[0],0,sizeof(Vector3r)*size);
>
> FOREACH(const shared_ptr<Interaction>& contact, *rb->interactions){
> if(!contact->isReal()) continue;
>
> GenericSpheresContact*
> geom=YADE_CAST<GenericSpheresContact*>(contact->geom.get()); assert(geom);
> ViscElPhys* phys =
> YADE_CAST<ViscElPhys*>(contact->phys.get()); assert(phys);
> // all we need for getting stiffness
> Vector3r& normal=geom->normal; Real& kn=phys->kn; Real&
> ks=phys->ks; Real& radius1=geom->refR1; Real& radius2=geom->refR2;
> Real& cn=phys->cn; Real& cs=phys->cs;
> Real fn = (static_cast<NormShearPhys *>
> (contact->phys.get()))->normalForce.squaredNorm();
> if (fn==0) continue;//Is it a problem with some laws? I
> still don't see why.
>
> //Diagonal terms of the translational stiffness matrix
> Vector3r diag_stiffness =
> Vector3r(std::pow(normal.x(),2),std::pow(normal.y(),2),std::pow(normal.z(),2));
> diag_stiffness *= kn-ks;
> diag_stiffness = diag_stiffness + Vector3r(1,1,1)*ks;
>
> //diagonal terms of the rotational stiffness matrix
> // Vector3r branch1 =
> currentContactGeometry->normal*currentContactGeometry->radius1;
> // Vector3r branch2 =
> currentContactGeometry->normal*currentContactGeometry->radius2;
> Vector3r diag_Rstiffness =
>
> Vector3r(std::pow(normal.y(),2)+std::pow(normal.z(),2),
>
> std::pow(normal.x(),2)+std::pow(normal.z(),2),
>
> std::pow(normal.x(),2)+std::pow(normal.y(),2));
> diag_Rstiffness *= ks;
>
> //Diagonal terms of the translational viscous matrix
> Vector3r diag_viscosity =
> Vector3r(std::pow(normal.x(),2),std::pow(normal.y(),2),std::pow(normal.z(),2));
> diag_viscosity *= cn-cs;
> diag_viscosity = diag_viscosity + Vector3r(1,1,1)*cs;
> //diagonal terms of the rotational viscous matrix
> Vector3r diag_Rviscosity =
>
> Vector3r(std::pow(normal.y(),2)+std::pow(normal.z(),2),
>
> std::pow(normal.x(),2)+std::pow(normal.z(),2),
>
> std::pow(normal.x(),2)+std::pow(normal.y(),2));
> diag_Rviscosity *= cs;
>
> //NOTE : contact laws with moments would be handled
> correctly by summing directly bending+twisting stiffness to diag_Rstiffness.
> The fact that there is no problem currently with e.g. cohesiveFrict law is
> probably because final computed dt is constrained by translational motion,
> not rotations.
> stiffnesses [contact->getId1()]+=diag_stiffness;
>
> Rstiffnesses[contact->getId1()]+=diag_Rstiffness*pow(radius1,2);
> viscosities [contact->getId1()]+=diag_viscosity;
>
> Rviscosities[contact->getId1()]+=diag_Rviscosity*pow(radius1,2);
> stiffnesses [contact->getId2()]+=diag_stiffness;
>
> Rstiffnesses[contact->getId2()]+=diag_Rstiffness*pow(radius2,2);
> viscosities [contact->getId2()]+=diag_viscosity;
>
> Rviscosities[contact->getId2()]+=diag_Rviscosity*pow(radius2,2);
> }
> }
>
>
>
>
>
>
>
>
>
>
>
> GlobalStiffnessTimeStepper.hpp
>
>
>
> /*************************************************************************
> * Copyright (C) 2006 by Bruno Chareyre *
> * bruno.chareyre@xxxxxxxxxxx *
> * *
> * This program is free software; it is licensed under the terms of the *
> * GNU General Public License v2 or later. See file LICENSE for details. *
> *************************************************************************/
>
> #pragma once
>
> #include<yade/core/TimeStepper.hpp>
>
>
> /*! \brief Compute the critical timestep of the leap-frog scheme based on
> global stiffness of bodies
> See usage details in TriaxialTest documentation (TriaxialTest is
> also a good example of how to use this class)
> */
>
> class Interaction;
> class BodyContainer;
> class Scene;
>
> class GlobalStiffnessTimeStepper : public TimeStepper
> {
> private :
> vector<Vector3r> stiffnesses;
> vector<Vector3r> Rstiffnesses;
> vector<Vector3r> viscosities;
> vector<Vector3r> Rviscosities;
> void computeStiffnesses(Scene*);
>
> Real newDt;
> bool computedSomething,
> computedOnce;
> void findTimeStepFromBody(const shared_ptr<Body>& body,
> Scene * ncb);
>
> public :
> virtual ~GlobalStiffnessTimeStepper();
>
> virtual void computeTimeStep(Scene*);
> virtual bool isActivated();
> YADE_CLASS_BASE_DOC_ATTRS_CTOR(
> GlobalStiffnessTimeStepper,TimeStepper,"An engine
> assigning the time-step as a fraction of the minimum eigen-period in the
> problem. The derivation is detailed in the chapter on `DEM formulation
> <https://www.yade-dem.org/doc/formulation.html#dem-simulations>`_",
> ((Real,defaultDt,-1,,"used as the initial value of
> the timestep (especially useful in the first steps when no contact exist).
> If negative, it will be defined by :yref:`utils.PWaveTimeStep` *
> :yref:`GlobalStiffnessTimeStepper::timestepSafetyCoefficient`"))
> ((Real,maxDt,Mathr::MAX_REAL,,"if positive, used as
> max value of the timestep whatever the computed value"))
> ((Real,previousDt,1,,"last computed dt |yupdate|"))
> ((Real,timestepSafetyCoefficient,0.8,,"safety factor
> between the minimum eigen-period and the final assigned dt (less than 1))"))
> ((bool,densityScaling,false,,"|yupdate| don't modify
> this value if you don't plan to modify the scaling factor manually for some
> bodies. In most cases, it is enough to set
> :yref:`NewtonIntegrator::densityScaling` and let this one be adjusted
> automatically."))
> ((Real,targetDt,1,,"if
> :yref:`NewtonIntegrator::densityScaling` is active, this value will be used
> as the simulation timestep and the scaling will use this value of dt as the
> target value. The value of targetDt is arbitrary and should have no effect
> in the result in general. However if some bodies have imposed velocities,
> for instance, they will move more or less per each step depending on this
> value.")),
> computedOnce=false;)
> DECLARE_LOGGER;
> };
>
> REGISTER_SERIALIZABLE(GlobalStiffnessTimeStepper);
>
>
>
>
>
> _______________________________________________
> Mailing list: https://launchpad.net/~yade-dev
> Post to : yade-dev@xxxxxxxxxxxxxxxxxxx
> Unsubscribe : https://launchpad.net/~yade-dev
> More help : https://help.launchpad.net/ListHelp
>
Follow ups