Modifying the Cohesive Frictional Contact Law

Asked by behzad

Hi guys,

I'm having a look on Cohesive Frictional Contact Law to see if I can modify it to convert it to a cohesive Burger's model (Maxwell model in series with a Kelvin model).

I have two question:

1- Do I need to create a new class of materials? To input the cohesion strengths and dashpot, springs properties?

2- Let's have a look on CohesiveFrictionalContactLaw.cpp. Let's say I want to add only one dashpot to the model. Where this is defined?

It's not here:

Real un = geom->penetrationDepth;
Real Fn = phys->kn*(un-phys->unp);

If I change it to

Real Fn = phys->kn*(un-phys->unp)+ something

that would be enough modifying the normal force calculation?

;================================

/*************************************************************************
* Copyright (C) 2007 by Bruno Chareyre <email address hidden> *
* Copyright (C) 2008 by Janek Kozicki <email address hidden> *
* *
* 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 "CohesiveFrictionalContactLaw.hpp"
#include<yade/pkg/dem/CohFrictMat.hpp>
#include<yade/pkg/dem/ScGeom.hpp>
#include<yade/pkg/dem/CohFrictPhys.hpp>
#include<yade/core/Omega.hpp>
#include<yade/core/Scene.hpp>

YADE_PLUGIN((CohesiveFrictionalContactLaw)(Law2_ScGeom6D_CohFrictPhys_CohesionMoment));
CREATE_LOGGER(Law2_ScGeom6D_CohFrictPhys_CohesionMoment);

Real Law2_ScGeom6D_CohFrictPhys_CohesionMoment::normElastEnergy()
{
 Real normEnergy=0;
 FOREACH(const shared_ptr<Interaction>& I, *scene->interactions){
  if(!I->isReal()) continue;
  CohFrictPhys* phys = YADE_CAST<CohFrictPhys*>(I->phys.get());
  if (phys) {
   normEnergy += 0.5*(phys->normalForce.squaredNorm()/phys->kn);
  }
 }
 return normEnergy;
}
Real Law2_ScGeom6D_CohFrictPhys_CohesionMoment::shearElastEnergy()
{
 Real shearEnergy=0;
 FOREACH(const shared_ptr<Interaction>& I, *scene->interactions){
  if(!I->isReal()) continue;
  CohFrictPhys* phys = YADE_CAST<CohFrictPhys*>(I->phys.get());
  if (phys) {
   shearEnergy += 0.5*(phys->shearForce.squaredNorm()/phys->ks);
  }
 }
 return shearEnergy;
}

void CohesiveFrictionalContactLaw::action()
{
 if(!functor) functor=shared_ptr<Law2_ScGeom6D_CohFrictPhys_CohesionMoment>(new Law2_ScGeom6D_CohFrictPhys_CohesionMoment);
 functor->always_use_moment_law = always_use_moment_law;
 functor->shear_creep=shear_creep;
 functor->twist_creep=twist_creep;
 functor->creep_viscosity=creep_viscosity;
 functor->scene=scene;
 FOREACH(const shared_ptr<Interaction>& I, *scene->interactions){
  if(!I->isReal()) continue;
  functor->go(I->geom, I->phys, I.get());}
}

void Law2_ScGeom6D_CohFrictPhys_CohesionMoment::go(shared_ptr<IGeom>& ig, shared_ptr<IPhys>& ip, Interaction* contact)
{
 const Real& dt = scene->dt;
 const int &id1 = contact->getId1();
 const int &id2 = contact->getId2();
 ScGeom6D* geom = YADE_CAST<ScGeom6D*> (ig.get());
 CohFrictPhys* phys = YADE_CAST<CohFrictPhys*> (ip.get());
 Vector3r& shearForce = phys->shearForce;

 if (contact->isFresh(scene)) shearForce = Vector3r::Zero();
 Real un = geom->penetrationDepth;
 Real Fn = phys->kn*(un-phys->unp);

 if (phys->fragile && (-Fn)> phys->normalAdhesion) {
  // BREAK due to tension
  scene->interactions->requestErase(contact); return;
 } else {
  if ((-Fn)> phys->normalAdhesion) {//normal plasticity
   Fn=-phys->normalAdhesion;
   phys->unp = un+phys->normalAdhesion/phys->kn;
   if (phys->unpMax && phys->unp<phys->unpMax)
    scene->interactions->requestErase(contact); return;
  }
  phys->normalForce = Fn*geom->normal;
  State* de1 = Body::byId(id1,scene)->state.get();
  State* de2 = Body::byId(id2,scene)->state.get();
  ///////////////////////// CREEP START ///////////
  if (shear_creep) shearForce -= phys->ks*(shearForce*dt/creep_viscosity);
  ///////////////////////// CREEP END ////////////

  Vector3r& shearForce = geom->rotate(phys->shearForce);
  const Vector3r& dus = geom->shearIncrement();

  //Linear elasticity giving "trial" shear force
  shearForce -= phys->ks*dus;

  Real Fs = phys->shearForce.norm();
  Real maxFs = phys->shearAdhesion;
  if (!phys->cohesionDisablesFriction || maxFs==0)
   maxFs += Fn*phys->tangensOfFrictionAngle;
  maxFs = std::max((Real) 0, maxFs);
  if (Fs > maxFs) {//Plasticity condition on shear force
   if (phys->fragile && !phys->cohesionBroken) {
    phys->SetBreakingState();
    maxFs = max((Real) 0, Fn*phys->tangensOfFrictionAngle);
   }
   maxFs = maxFs / Fs;
   Vector3r trialForce=shearForce;
   shearForce *= maxFs;
   if (scene->trackEnergy){
    Real dissip=((1/phys->ks)*(trialForce-shearForce))/*plastic disp*/ .dot(shearForce)/*active force*/;
    if(dissip>0) scene->energy->add(dissip,"plastDissip",plastDissipIx,/*reset*/false);}
   if (Fn<0) phys->normalForce = Vector3r::Zero();//Vector3r::Zero()
  }
  //Apply the force
  applyForceAtContactPoint(-phys->normalForce-shearForce, geom->contactPoint, id1, de1->se3.position, id2, de2->se3.position + (scene->isPeriodic ? scene->cell->intrShiftPos(contact->cellDist): Vector3r::Zero()));
// Vector3r force = -phys->normalForce-shearForce;
// scene->forces.addForce(id1,force);
// scene->forces.addForce(id2,-force);
// scene->forces.addTorque(id1,(geom->radius1-0.5*geom->penetrationDepth)* geom->normal.cross(force));
// scene->forces.addTorque(id2,(geom->radius2-0.5*geom->penetrationDepth)* geom->normal.cross(force));

  /// Moment law ///
  if (phys->momentRotationLaw && (!phys->cohesionBroken || always_use_moment_law)) {
   if (!useIncrementalForm){
    if (twist_creep) {
     Real viscosity_twist = creep_viscosity * std::pow((2 * std::min(geom->radius1,geom->radius2)),2) / 16.0;
     Real angle_twist_creeped = geom->getTwist() * (1 - dt/viscosity_twist);
     Quaternionr q_twist(AngleAxisr(geom->getTwist(),geom->normal));
     Quaternionr q_twist_creeped(AngleAxisr(angle_twist_creeped,geom->normal));
     Quaternionr q_twist_delta(q_twist_creeped * q_twist.conjugate());
     geom->twistCreep = geom->twistCreep * q_twist_delta;
    }
    phys->moment_twist = (geom->getTwist()*phys->ktw)*geom->normal;
    phys->moment_bending = geom->getBending() * phys->kr;
   }
   else{ // Use incremental formulation to compute moment_twis and moment_bending (no twist_creep is applied)
    if (twist_creep) throw std::invalid_argument("Law2_ScGeom6D_CohFrictPhys_CohesionMoment: no twis creep is included if the incremental form for the rotations is used.");
    Vector3r relAngVel = geom->getRelAngVel(de1,de2,dt);
    // *** Bending ***//
    Vector3r relAngVelBend = relAngVel - geom->normal.dot(relAngVel)*geom->normal; // keep only the bending part
    Vector3r relRotBend = relAngVelBend*dt; // relative rotation due to rolling behaviour
    // incremental formulation for the bending moment (as for the shear part)
    Vector3r& momentBend = phys->moment_bending;
    momentBend = geom->rotate(momentBend); // rotate moment vector (updated)
    momentBend = momentBend-phys->kr*relRotBend;
    // ----------------------------------------------------------------------------------------
    // *** Torsion ***//
    Vector3r relAngVelTwist = geom->normal.dot(relAngVel)*geom->normal;
    Vector3r relRotTwist = relAngVelTwist*dt; // component of relative rotation along n FIXME: sign?
    // incremental formulation for the torsional moment
    Vector3r& momentTwist = phys->moment_twist;
    momentTwist = geom->rotate(momentTwist); // rotate moment vector (updated)
    momentTwist = momentTwist-phys->ktw*relRotTwist; // FIXME: sign?
   }
   /// Plasticity ///
   // limit rolling moment to the plastic value, if required
   Real RollMax = phys->maxRollPl*phys->normalForce.norm();
   if (RollMax>0.){ // do we want to apply plasticity?
    if (!useIncrementalForm) LOG_WARN("If :yref:`Law2_ScGeom6D_CohFrictPhys_CohesionMoment::useIncrementalForm` is false, then plasticity will not be applied correctly (the total formulation would not reproduce irreversibility).");
    Real scalarRoll = phys->moment_bending.norm();
    if (scalarRoll>RollMax){ // fix maximum rolling moment
     Real ratio = RollMax/scalarRoll;
     phys->moment_bending *= ratio;
    }
   }
   // limit twisting moment to the plastic value, if required
   Real TwistMax = phys->maxTwistMoment.norm();
   if (TwistMax>0.){ // do we want to apply plasticity?
    if (!useIncrementalForm) LOG_WARN("If :yref:`Law2_ScGeom6D_CohFrictPhys_CohesionMoment::useIncrementalForm` is false, then plasticity will not be applied correctly (the total formulation would not reproduce irreversibility).");
    Real scalarTwist= phys->moment_twist.norm();
    if (scalarTwist>TwistMax){ // fix maximum rolling moment
     Real ratio = TwistMax/scalarTwist;
     phys->moment_twist *= ratio;
    }
   }
   // Apply moments now
   Vector3r moment = phys->moment_twist + phys->moment_bending;
   scene->forces.addTorque(id1,-moment);
   scene->forces.addTorque(id2, moment);
  }
  /// Moment law END ///
 }
}

;===================================

Question information

Language:
English Edit question
Status:
Solved
For:
Yade Edit question
Assignee:
No assignee Edit question
Solved by:
Jan Stránský
Solved:
Last query:
Last reply:
Revision history for this message
Bruno Chareyre (bruno-chareyre) said :
#1

1-yes

2-

> If I change it to
>
> Real Fn = phys->kn*(un-phys->unp)+ something
>
> that would be enough modifying the normal force calculation?

Certainly.

Now the choice that you have is:
- add this feature to the existing law in a clean way, so that it can be
integrated in trunk (we can discuss how to do so)
- even better: derive a new law in such a way that you re-use the
existing code by inheritance, and you only type the few lines that
differ (again, we can discuss integration in trunk)
- copy/paste/rename the existing law into new files, and modify them a
little to do what you need. It probably sounds the easiest way. It will
work in short term but in the long run it will be lost because we will
not accept that in trunk.

Bruno

Revision history for this message
behzad (behzad-majidi) said :
#2

Good,
 thanks for the answer.

I will need a step by step guide to get it done, if it doesn't bother you.

I will start with creating;

1-new class of materials
2- new class of Law

I will continue sharing my work/questions here.

cheers,
Behzad

Revision history for this message
Jan Stránský (honzik) said :
#3

Hi Behzad,

>
> I will start with creating;
>
> 1-new class of materials
> 2- new class of Law
>

you will also need new Ip2 functor to create IPhys instance based on your
new material. Then most likely you will also need new IPhys class.

cheers
Jan

Revision history for this message
behzad (behzad-majidi) said :
#4

Alright, I tried to modify CohFrictMat.hpp in trunk/pkg/dem to define a new class of material.

This material is supposed to have Burger's model. Thus, it must have four parameters (2 springs stiffness and 2 dashpots viscosity).

Will the following work? Then, I will move on defining the corresponding Ip2 and a Law class.

=====================================================

#pragma once

#include<yade/pkg/common/ElastMat.hpp>

class CohBurgersMat : public FrictMat
{
 public :
  virtual ~CohBurgersMat ();

/// Serialization
 YADE_CLASS_BASE_DOC_ATTRS_CTOR(CohBurgersMat,FrictMat,"",
  ((bool,isCohesive,true,,""))
  ((Real,Em,1e3,,"Stiffness of Maxwell's spring"))
  ((Real,Ek,1e3,,"Stiffness of Kelvin's spring"))
  ((Real,Cm,10,,"Viscosity of Maxwell's dashpot"))
         ((Real,Ck,10,,"Viscosity of Kelvin's dashpot"))
                ((Real,poissonRatio,0.5,,""))
  ((Real,normalCohesion,1e4,,""))
  ((Real,shearCohesion,1e4,,""))
  createIndex();
  );
/// Indexable
 REGISTER_CLASS_INDEX(CohBurgersMat,FrictMat);
};

REGISTER_SERIALIZABLE(CohBurgersMat);

==============================================

Revision history for this message
Jan Stránský (honzik) said :
#5

Hi Behzad,

for the first sight it should work. If everything will work as a complex
will strongly depend on the implementation of the other functors,
especially the Law2..

Cheers
Jan
Dne 29.7.2014 21:37 "behzad" <email address hidden>
napsal(a):

> Question #251218 on Yade changed:
> https://answers.launchpad.net/yade/+question/251218
>
> Status: Answered => Open
>
> behzad is still having a problem:
> Alright, I tried to modify CohFrictMat.hpp in trunk/pkg/dem to define a
> new class of material.
>
> This material is supposed to have Burger's model. Thus, it must have
> four parameters (2 springs stiffness and 2 dashpots viscosity).
>
> Will the following work? Then, I will move on defining the corresponding
> Ip2 and a Law class.
>
>
> =====================================================
>
> #pragma once
>
>
> #include<yade/pkg/common/ElastMat.hpp>
>
>
> class CohBurgersMat : public FrictMat
> {
> public :
> virtual ~CohBurgersMat ();
>
> /// Serialization
> YADE_CLASS_BASE_DOC_ATTRS_CTOR(CohBurgersMat,FrictMat,"",
> ((bool,isCohesive,true,,""))
> ((Real,Em,1e3,,"Stiffness of Maxwell's spring"))
> ((Real,Ek,1e3,,"Stiffness of Kelvin's spring"))
> ((Real,Cm,10,,"Viscosity of Maxwell's dashpot"))
> ((Real,Ck,10,,"Viscosity of Kelvin's dashpot"))
> ((Real,poissonRatio,0.5,,""))
> ((Real,normalCohesion,1e4,,""))
> ((Real,shearCohesion,1e4,,""))
> createIndex();
> );
> /// Indexable
> REGISTER_CLASS_INDEX(CohBurgersMat,FrictMat);
> };
>
> REGISTER_SERIALIZABLE(CohBurgersMat);
>
>
> ==============================================
>
> --
> You received this question notification because you are a member of
> yade-users, which is an answer contact for Yade.
>
> _______________________________________________
> Mailing list: https://launchpad.net/~yade-users
> Post to : <email address hidden>
> Unsubscribe : https://launchpad.net/~yade-users
> More help : https://help.launchpad.net/ListHelp
>

Revision history for this message
behzad (behzad-majidi) said :
#6

Now I save it as CohBurgersMat.hpp in trunk/pkg/dem. Right? Do I need to have CohBurgersMat.cpp as well?

Thanks

Revision history for this message
Jan Stránský (honzik) said :
#7

Hi Behzad,
at least you need YADE_PLUGIN [1], so you need .cpp file.
cheers
Jan

[1] https://yade-dem.org/doc/prog.html#plugin-registration

2014-07-29 22:02 GMT+02:00 behzad <email address hidden>:

> Question #251218 on Yade changed:
> https://answers.launchpad.net/yade/+question/251218
>
> Status: Answered => Open
>
> behzad is still having a problem:
>
> Now I save it as CohBurgersMat.hpp in trunk/pkg/dem. Right? Do I need to
> have CohBurgersMat.cpp as well?
>
> Thanks
>
> --
> You received this question notification because you are a member of
> yade-users, which is an answer contact for Yade.
>
> _______________________________________________
> Mailing list: https://launchpad.net/~yade-users
> Post to : <email address hidden>
> Unsubscribe : https://launchpad.net/~yade-users
> More help : https://help.launchpad.net/ListHelp
>

Revision history for this message
Jérôme Duriez (jduriez) said :
#8

Side note (I don't know if you are aware of this) : do not hesitate to put all your Law2/Ip2/Mat code in only 2 (cpp and hpp) files, rather than 6 (2 for Law2, 2 for Ip2, 2 for Mat).

According to https://lists.launchpad.net/yade-dev/msg11090.html

Revision history for this message
behzad (behzad-majidi) said :
#9

Thanks guys.

I wrote the cpp file, it includes only this:

=================================
#include "CohBurgersMat.hpp"

CohBurgersMat::~CohBurgersMat()
{
}

YADE_PLUGIN((CohBurgersMat));

================================

@ Jérôme:
Thanks for the remark. I will write them separately to have a clean work and then I mix them up into one file.

Now, I move up to creating Iphys.

cheers,
Behzad

Revision history for this message
behzad (behzad-majidi) said :
#10

Can't I use CohFrictPhys? I mean, does the new model need to have an independent Ip2?

The contacts are supposed to be cohesive and only the force-displacement law is different. Force-displacement law will come from burger's model. So, I guess I can use CohFrictPhys. Right?

Revision history for this message
Jan Stránský (honzik) said :
#11

Hello Behzad,

Law2 functor combines IGeom and IPhys. If everything what you need for
calculating forces is already present in CohFrictPhys (all internal
variables etc.), you can use it. It does not need to have independent IPhys
always. But in that case you wouldn't need new material :-)

IMO you will need some more variables for the dashpots and springs values,
so you will need to create a new IPhys.

cheers
Jan

2014-07-31 17:16 GMT+02:00 behzad <email address hidden>:

> Question #251218 on Yade changed:
> https://answers.launchpad.net/yade/+question/251218
>
> Status: Answered => Open
>
> behzad is still having a problem:
>
> Can't I use CohFrictPhys? I mean, does the new model need to have an
> independent Ip2?
>
> The contacts are supposed to be cohesive and only the force-displacement
> law is different. Force-displacement law will come from burger's model.
> So, I guess I can use CohFrictPhys. Right?
>
> --
> You received this question notification because you are a member of
> yade-users, which is an answer contact for Yade.
>
> _______________________________________________
> Mailing list: https://launchpad.net/~yade-users
> Post to : <email address hidden>
> Unsubscribe : https://launchpad.net/~yade-users
> More help : https://help.launchpad.net/ListHelp
>

Revision history for this message
behzad (behzad-majidi) said :
#12

Alright. I have already created a new class of material, CohBurgersMat. I have shared it above. So, I create a new Iphys now.

But Iphys as I see it doesn't take any parameter from the material. Anyway, I modified CohFrictPhys and named it to CohBurPhys.

Does it look fine?

=====================
#pragma once

#include<yade/pkg/common/NormShearPhys.hpp>
#include<yade/pkg/dem/FrictPhys.hpp>

class CohBurPhys : public FrictPhys
{
 public :
  virtual ~CohBurPhys();
  void SetBreakingState();

 YADE_CLASS_BASE_DOC_ATTRS_CTOR(CohBurPhys,FrictPhys,"",
  ((bool,cohesionDisablesFriction,false))
  ((bool,cohesionBroken,true))
  ((bool,fragile,true,,"do cohesion disapear when contact strength is exceeded?"))
  ((Real,normalAdhesion,0,,"tensile strength"))
  ((Real,shearAdhesion,0))
  ((Real,unp,0,,"plastic normal displacement, only used for tensile behaviour and if :yref:`CohFrictPhys::fragile` =false."))
  ((Real,unpMax,0,,"maximum value of plastic normal displacement, after that the interaction breaks even if :yref:`CohFrictPhys::fragile` =false. The default value (0) means no maximum."))
  ((bool,momentRotationLaw,false,,"use bending/twisting moment at contacts"))
  ((bool,initCohesion,false,,"Initialize the cohesive behaviour with current state as equilibrium state"))
  ((Real,creep_viscosity,-1,,"creep viscosity [Pa.s/m]."))
  // internal attributes
  ,
  createIndex();
 );
/// Indexable
 REGISTER_CLASS_INDEX(CohBurPhys,FrictPhys);

};

REGISTER_SERIALIZABLE(CohBurPhys);
=====================

I'm not sure if the following lines are correct:

#include<yade/pkg/common/NormShearPhys.hpp>
#include<yade/pkg/dem/FrictPhys.hpp>

class CohBurPhys : public FrictPhys

Thanks

Revision history for this message
Jan Stránský (honzik) said :
#13

Hi Behzad,

>
> Alright. I have already created a new class of material, CohBurgersMat. I
> have shared it above. So, I create a new Iphys now.

> But Iphys as I see it doesn't take any parameter from the material.
> Anyway, I modified CohFrictPhys and named it to CohBurPhys.
>

IPhys is created by Ip2 functor, which combine two Material instances
together, so the values of IPhys are somehow computed from the materials,
but not directly in IPhys itself. You will also need new Ip2 class.

> Does it look fine?
>

For the first sight yes, but try to name your classes consistently and
don't do too much abbreviations, i.e. I would name it CohBurgersPhys (in
analogy to the material).

>
>
> I'm not sure if the following lines are correct:
>

I see nothing wrong with them..

>
>
> #include<yade/pkg/common/NormShearPhys.hpp>
> #include<yade/pkg/dem/FrictPhys.hpp>
>
> class CohBurPhys : public FrictPhys
>
>
>

cheers
Jan

Revision history for this message
behzad (behzad-majidi) said :
#14

Good!

and now my Ip2_CohBurgersMat_CohBurgersMat_CohbergersPhys.hpp:

================

#pragma once

#include<yade/pkg/common/Dispatching.hpp>
#include<yade/pkg/dem/CohBurgersMat.hpp>

class Ip2_CohBurgersMat_CohBurgersMat_CohBurgersPhys : public IPhysFunctor
{
 public :
  virtual void go( const shared_ptr<Material>& b1,
     const shared_ptr<Material>& b2,
     const shared_ptr<Interaction>& interaction);
  int cohesionDefinitionIteration;

  YADE_CLASS_BASE_DOC_ATTRS_CTOR(Ip2_CohBurgersMat_CohBurgersMat_CohBurgersPhys,IPhysFunctor,
  ((bool,setCohesionNow,false,,"If true, assign cohesion to all existing contacts in current time-step. The flag is turned false automatically, so that assignment is done in the current timestep only."))
  ((bool,setCohesionOnNewContacts,true))
  ,
  cohesionDefinitionIteration = -1;
  );
 FUNCTOR2D(CohBurgersMat,CohBurgersMat);
};

REGISTER_SERIALIZABLE(Ip2_CohBurgersMat_CohBurgersMat_CohBurgersPhys);

=======================

and my Ip2_CohBurgersMat_CohBurgersMat_CohbergersPhys.cpp:

================================

#include"Ip2_CohBurgersMat_CohBurgersMat_CohbergersPhys.hpp"
#include<yade/pkg/dem/ScGeom.hpp>
#include<yade/pkg/dem/CohBurgersPhys.hpp>
#include<yade/pkg/dem/CohBurgersMat.hpp>
#include<yade/core/Omega.hpp>
#include<yade/core/Scene.hpp>

void Ip2_CohBurgersMat_CohBurgersMat_CohBurgersPhys::go(const shared_ptr<Material>& b1 // CohBurgersMat
                                        , const shared_ptr<Material>& b2 // CohBurgersMat
                                        , const shared_ptr<Interaction>& interaction)
{
 CohBurgersMat* sdec1 = static_cast<CohBurgersMat*>(b1.get());
 CohBurgersMat* sdec2 = static_cast<CohBurgersMat*>(b2.get());
 ScGeom6D* geom = YADE_CAST<ScGeom6D*>(interaction->geom.get());

 //Create cohesive interractions only once
 if (setCohesionNow && cohesionDefinitionIteration==-1) cohesionDefinitionIteration=scene->iter;
 if (setCohesionNow && cohesionDefinitionIteration!=-1 && cohesionDefinitionIteration!=scene->iter) {
  cohesionDefinitionIteration = -1;
  setCohesionNow = 0;}

 if (geom) {
  if (!interaction->phys) {
   interaction->phys = shared_ptr<CohBurgersPhys>(new CohBurgersPhys());
   CohBurgersPhys* contactPhysics = YADE_CAST<CohBurgersPhys*>(interaction->phys.get());
   Real Ea = sdec1->young;
   Real Eb = sdec2->young;
   Real Va = sdec1->poisson;
   Real Vb = sdec2->poisson;
   Real Da = geom->radius1;
   Real Db = geom->radius2;
   Real fa = sdec1->frictionAngle;
   Real fb = sdec2->frictionAngle;
   Real Kn = 2.0*Ea*Da*Eb*Db/(Ea*Da+Eb*Db);//harmonic average of two stiffnesses

   // harmonic average of alphas parameters
   Real AlphaKr = 2.0*sdec1->alphaKr*sdec2->alphaKr/(sdec1->alphaKr+sdec2->alphaKr);
   Real AlphaKtw;
   if (sdec1->alphaKtw && sdec2->alphaKtw) AlphaKtw = 2.0*sdec1->alphaKtw*sdec2->alphaKtw/(sdec1->alphaKtw+sdec2->alphaKtw);
   else AlphaKtw=0;

   Real Ks;
   if (Va && Vb) Ks = 2.0*Ea*Da*Va*Eb*Db*Vb/(Ea*Da*Va+Eb*Db*Vb);//harmonic average of two stiffnesses with ks=V*kn for each sphere
   else Ks=0;

   // Jean-Patrick Plassiard, Noura Belhaine, Frederic
   // Victor Donze, "Calibration procedure for spherical
   // discrete elements using a local moemnt law".
   contactPhysics->kr = Da*Db*Ks*AlphaKr;
   contactPhysics->ktw = Da*Db*Ks*AlphaKtw;
   contactPhysics->tangensOfFrictionAngle = std::tan(std::min(fa,fb));

   if ((setCohesionOnNewContacts || setCohesionNow) && sdec1->isCohesive && sdec2->isCohesive)
   {
    contactPhysics->cohesionBroken = false;
    contactPhysics->normalAdhesion = std::min(sdec1->normalCohesion,sdec2->normalCohesion)*pow(std::min(Db, Da),2);
    contactPhysics->shearAdhesion = std::min(sdec1->shearCohesion,sdec2->shearCohesion)*pow(std::min(Db, Da),2);
    geom->initRotations(*(Body::byId(interaction->getId1(),scene)->state),*(Body::byId(interaction->getId2(),scene)->state));
   }
   contactPhysics->kn = Kn;
   contactPhysics->ks = Ks;

   contactPhysics->maxRollPl = min(sdec1->etaRoll*Da,sdec2->etaRoll*Db);
   contactPhysics->momentRotationLaw=(sdec1->momentRotationLaw && sdec2->momentRotationLaw);
   //contactPhysics->elasticRollingLimit = elasticRollingLimit;
  }
  else {// !isNew, but if setCohesionNow, all contacts are initialized like if they were newly created
   CohBurgersPhys* contactPhysics = YADE_CAST<CohBurgersPhys*>(interaction->phys.get());
   if ((setCohesionNow && sdec1->isCohesive && sdec2->isCohesive) || contactPhysics->initCohesion)
   {
    contactPhysics->cohesionBroken = false;
    contactPhysics->normalAdhesion = std::min(sdec1->normalCohesion,sdec2->normalCohesion)*pow(std::min(geom->radius2, geom->radius1),2);
    contactPhysics->shearAdhesion = std::min(sdec1->shearCohesion,sdec2->shearCohesion)*pow(std::min(geom->radius2, geom->radius1),2);

    geom->initRotations(*(Body::byId(interaction->getId1(),scene)->state),*(Body::byId(interaction->getId2(),scene)->state));
    contactPhysics->initCohesion=false;
   }
  }
 }
};
YADE_PLUGIN((Ip2_CohBurgersMat_CohBurgersMat_CohBurgersPhys));

==============================

Thanks for having a look on it! I appreciate it

Revision history for this message
Bruno Chareyre (bruno-chareyre) said :
#15

Dear Behzad,
It seems you decided to give the copy/paste method a go (option 3 in #1).
Please keep in mind that it is only a quick hack for testing equations.
If you want the new model to be functional for at least a couple years, you will need to implement more cleanly. Namely, to inherit (*) from CohFrictMat and add the missing data only. For the moment you are duplicating many variables which are already in the code (kn,ks,normalCohesion,etc.).
Please let us know if/how you need help for clean intergration.

(*) Inheriting is exactly what CohFrictMat does wrt. FrictMat, same for CohFrictPhys vs. FrictPhys.

Revision history for this message
Bruno Chareyre (bruno-chareyre) said :
#16

Another thing: it is better and easier to put all classes (Material, Ip2, Ig2, Law2, etc.) in the same pair of .hpp/.cpp files.
No need to have 10 files for one contact law. It is done that way for most classes if you look at a recent version of the source code.

Revision history for this message
behzad (behzad-majidi) said :
#17

Hi Bruno,

- where's #1? (option 3 in #1)

- Yes, would you please let me know how I can make a clean integration? I did not notice that I'm duplicating parameters! So, how can I inherit the new model CohBurgers... from CohFrict... ?

Thanks

Revision history for this message
behzad (behzad-majidi) said :
#18

Bruno,

As I see this (duplicating the already existing parameters) is only happening in what I wrote for CohBurgersPhys.hpp.
and the reason was I derived it from FictPhys and not CohFrictPhys. If you look above, CohBurgersPhys has no more parameters than CohFrictPhys. It has less parameters! I removed 3 parameters;

(Real,ktw,0,,"twist stiffness [N.m/rad]"))
((Real,maxRollPl,0.0,,"Coefficient to determine the maximum plastic rolling moment."))
((Vector3r,maxTwistMoment,Vector3r::Zero()

I wonder how can I derive CohBurgersPhys from CohFrictPhy by removing three parameters.

Revision history for this message
behzad (behzad-majidi) said :
#19

Hi guys,

It's appreciated if one can help me out making a clean model integration.

cheers,
Behzad

Revision history for this message
Jan Stránský (honzik) said :
#20

Hi Behzad,

as mentioned by Bruno, the first step should be to make the model work ("quick
hack for testing equations"). In this stage, it is not so important if the
code is perfect or not. When you are sure that the model works as expected,
then it is the time to make it nice from the point of yade design view.

A "clean model" means, that instead of repeating almost all variables as in
CohFrictPhys, you will inherit from CohFrictPhys (having already all the
variables available, so reducing code duplication). You will add some your
variables.

There are some variables in CohFrictPhys, that are not used in your case.
Either you can ignore it, or it would be possible to create something like
CohFrictPhysBase, containing all common variables, and then inherit
CohFrictPhys and CohBurgerPhys from this class..

let me finish with the same idea I begun with: Before your implementation
works using any code, it is not important to make the code perfect.

in case of any questions, let us know :-)

cheers
Jan

2014-08-07 17:37 GMT+02:00 behzad <email address hidden>:

> Question #251218 on Yade changed:
> https://answers.launchpad.net/yade/+question/251218
>
> behzad posted a new comment:
> Hi guys,
>
> It's appreciated if one can help me out making a clean model
> integration.
>
> cheers,
> Behzad
>
> --
> You received this question notification because you are a member of
> yade-users, which is an answer contact for Yade.
>
> _______________________________________________
> Mailing list: https://launchpad.net/~yade-users
> Post to : <email address hidden>
> Unsubscribe : https://launchpad.net/~yade-users
> More help : https://help.launchpad.net/ListHelp
>

Revision history for this message
Bruno Chareyre (bruno-chareyre) said :
#21

I was away from keyboard. Sorry for slow reply Behzad.
I think you can keep the 3 variables of CohFrictPhys even if you don't need them. It is harmless, and there is in fact a very good reason to keep them. If later you or somebody else wants to combine the Burger model with contact moments - and trust me it is likely to happen, it will be possible (for free! no need to write new code).
Jan's suggestion to introduce an intermediate class is also good, but it does not enable such combination of components.

I agree with Jan to delay the clean integration, just it is good to anticipate it as it can guide the way you do the dirty tricks already.

As a simple example of how a good integration can look like, Ip2_CohBurgersMat can inherit from Ip2_CohFrictMat so that:

void Ip2_CohBurgersMat_CohBurgersMat_CohBurgersPhys::go(b1,b2,i)
{
    Ip2_CohFrictMat_CohFrictMat_CohFrictPhys::go(b1,b2,i); //here re-use
    i->phys->kelvinViscosity = ... //here do the additional stuff
}

In this case you don't duplicate lines. If someone is fixing something in Ip2_CohFrictMat_CohFrictMat_CohFrictPhys you will recieve the fix. If you duplicate, the duplicated code will slowly diverge and bugs may never be fixed.

Notes:
1/ This requires that you inherit from
2/ I don't see any kelvin/maxwell viscosity and stiffness in CohBurgersPhys at the moment. I guess you will have to add something for some of them (not all, since they can be partly covered by the inherited stiffness and viscosity values).
3/ the example above can apply for Law2 functor as well (see [1]), but not always. If you find that the burger model needs to insert lines in the middle of the Law2::go() block of code (I mean if there is really no way to put all new lines before or after the inherited go()) then we will need to think a bit more.

I hope it helps

[1] https://github.com/yade/trunk/blob/master/pkg/dem/ElasticContactLaw.cpp#L102

Revision history for this message
behzad (behzad-majidi) said :
#22

Hi,

here I'm deriving CohBurgersPhys from CohFrictPhys. Is this what you mean? :

class Ip2_CohBurgersMat_CohBurgersMat_CohBurgersPhys : public CohFrictPhys
{
 public :
  virtual void go( const shared_ptr<Material>& b1,
     const shared_ptr<Material>& b2,
     const shared_ptr<Interaction>& interaction);
  int cohesionDefinitionIteration;

  YADE_CLASS_BASE_DOC_ATTRS_CTOR(Ip2_CohBurgersMat_CohBurgersMat_CohBurgersPhys,IPhysFunctor,
  ((bool,setCohesionNow,false,,"If true, assign cohesion to all existing contacts in current time-step. The flag is turned false automatically, so that assignment is done in the current timestep only."))
  ((bool,setCohesionOnNewContacts,true))
  ,
  cohesionDefinitionIteration = -1;
  );
 FUNCTOR2D(CohBurgersMat,CohBurgersMat);
};

REGISTER_SERIALIZABLE(Ip2_CohBurgersMat_CohBurgersMat_CohBurgersPhys);

Revision history for this message
Jan Stránský (honzik) said :
#23

Hi Behzad,
you should derive CohBurgersPhys (as mentioned in the beginning of your
question), *not* Ip2...
Jan

2014-10-07 20:56 GMT+02:00 behzad <email address hidden>:

> Question #251218 on Yade changed:
> https://answers.launchpad.net/yade/+question/251218
>
> Status: Answered => Open
>
> behzad is still having a problem:
> Hi,
>
> here I'm deriving CohBurgersPhys from CohFrictPhys. Is this what you
> mean? :
>
>
> class Ip2_CohBurgersMat_CohBurgersMat_CohBurgersPhys : public CohFrictPhys
> {
> public :
> virtual void go( const shared_ptr<Material>& b1,
> const shared_ptr<Material>& b2,
> const shared_ptr<Interaction>&
> interaction);
> int cohesionDefinitionIteration;
>
>
> YADE_CLASS_BASE_DOC_ATTRS_CTOR(Ip2_CohBurgersMat_CohBurgersMat_CohBurgersPhys,IPhysFunctor,
> ((bool,setCohesionNow,false,,"If true, assign cohesion to
> all existing contacts in current time-step. The flag is turned false
> automatically, so that assignment is done in the current timestep only."))
> ((bool,setCohesionOnNewContacts,true))
> ,
> cohesionDefinitionIteration = -1;
> );
> FUNCTOR2D(CohBurgersMat,CohBurgersMat);
> };
>
> REGISTER_SERIALIZABLE(Ip2_CohBurgersMat_CohBurgersMat_CohBurgersPhys);
>
> --
> You received this question notification because you are a member of
> yade-users, which is an answer contact for Yade.
>
> _______________________________________________
> Mailing list: https://launchpad.net/~yade-users
> Post to : <email address hidden>
> Unsubscribe : https://launchpad.net/~yade-users
> More help : https://help.launchpad.net/ListHelp
>

Revision history for this message
behzad (behzad-majidi) said :
#24

CohBurgersPhys from CohFrictPhys:

class CohBurgersPhys : public CohFrictPhys
{
 public :
  virtual ~CohBurgersPhys();
  void SetBreakingState();

 YADE_CLASS_BASE_DOC_ATTRS_CTOR(CohBurgersPhys,CohFrictPhys,"",
  ((bool,cohesionDisablesFriction,false))
  ((bool,cohesionBroken,true))
  ((bool,fragile,true,,"do cohesion disapear when contact strength is exceeded?"))
  ((Real,normalAdhesion,0,,"tensile strength"))
  ((Real,shearAdhesion,0))
  ((Real,unp,0,,"plastic normal displacement, only used for tensile behaviour and if :yref:`CohFrictPhys::fragile` =false."))
  ((Real,unpMax,0,,"maximum value of plastic normal displacement, after that the interaction breaks even if :yref:`CohFrictPhys::fragile` =false. The default value (0) means no maximum."))
  ((bool,momentRotationLaw,false,,"use bending/twisting moment at contacts"))
  ((bool,initCohesion,false,,"Initialize the cohesive behaviour with current state as equilibrium state"))
  ((Real,creep_viscosity,-1,,"creep viscosity [Pa.s/m]."))
  // internal attributes
  ,
  createIndex();
 );
/// Indexable
 REGISTER_CLASS_INDEX(CohBurgersPhys,CohFrictPhys);

};

REGISTER_SERIALIZABLE(CohBurgersPhys);

Revision history for this message
Jan Stránský (honzik) said :
#25

Hi Behzad,

it is and is not what we mean :-) syntax is ok, but the content is not (see
below)

the best approach would really be to try your model without any bother with
inheritance and when it works, you can reimplement it. I have a feeling
that the example you gave is just copy-paste CohFrictPhys with a little
class rename..

One of the purposes of inheritance is to reduce duplication, so in your
case, when all of defined attributes are already present in CohFrictPhys
(result of copy-paste?), you should not declare them again in the derived
class. As a result, you would not create this class at all and use
CohFrictPhys directly, but it would certainly not work for Burger's model,
as you should store some internal variables (of the dampers)..

please try to implement and test the model first, and when it works, we can
proceed to the other step of nice and long-term maintainable code. When you
have a working implementation, it would also be very easy to indentify
proper inheritance as it would be clear which variables are common with
base classes etc.

cheers
Jan

2014-10-07 21:11 GMT+02:00 behzad <email address hidden>:

> Question #251218 on Yade changed:
> https://answers.launchpad.net/yade/+question/251218
>
> Status: Answered => Open
>
> behzad is still having a problem:
>
> CohBurgersPhys from CohFrictPhys:
>
>
> class CohBurgersPhys : public CohFrictPhys
> {
> public :
> virtual ~CohBurgersPhys();
> void SetBreakingState();
>
> YADE_CLASS_BASE_DOC_ATTRS_CTOR(CohBurgersPhys,CohFrictPhys,"",
> ((bool,cohesionDisablesFriction,false))
> ((bool,cohesionBroken,true))
> ((bool,fragile,true,,"do cohesion disapear when contact
> strength is exceeded?"))
> ((Real,normalAdhesion,0,,"tensile strength"))
> ((Real,shearAdhesion,0))
> ((Real,unp,0,,"plastic normal displacement, only used for
> tensile behaviour and if :yref:`CohFrictPhys::fragile` =false."))
> ((Real,unpMax,0,,"maximum value of plastic normal
> displacement, after that the interaction breaks even if
> :yref:`CohFrictPhys::fragile` =false. The default value (0) means no
> maximum."))
> ((bool,momentRotationLaw,false,,"use bending/twisting
> moment at contacts"))
> ((bool,initCohesion,false,,"Initialize the cohesive
> behaviour with current state as equilibrium state"))
> ((Real,creep_viscosity,-1,,"creep viscosity [Pa.s/m]."))
> // internal attributes
> ,
> createIndex();
> );
> /// Indexable
> REGISTER_CLASS_INDEX(CohBurgersPhys,CohFrictPhys);
>
> };
>
> REGISTER_SERIALIZABLE(CohBurgersPhys);
>
> --
> You received this question notification because you are a member of
> yade-users, which is an answer contact for Yade.
>
> _______________________________________________
> Mailing list: https://launchpad.net/~yade-users
> Post to : <email address hidden>
> Unsubscribe : https://launchpad.net/~yade-users
> More help : https://help.launchpad.net/ListHelp
>

Revision history for this message
behzad (behzad-majidi) said :
#26

Hi,

So, just to wrap up I ask the last question.
How do you inherit a new class from a parent class without duplicating the parameters. Let's say we want the new class to have only one new parameter. How do we do this? If I learn this I can apply it to all changes I need to make for material, Phys, Law and etc. I appreciate if you can show this with an example like CohBurgersPhys and CohFrictPhys. Let's say CohBurgersPhys will have only one new parameter or properties.

Thank you

Revision history for this message
Best Jan Stránský (honzik) said :
#27

Hi Behzad,

quite nice example of this is CohFrictPhys itself. You can see all the way
from IPhys [1], NormPhys [2], NormShearPhys [3], FrictPhys [4] and
CohFrictPhys [5]. In every new class there are some new attributes
added(sometimes just one) and attributes from base classes are not
declared, but inherited.

So FrictPhys has parameters kn and ks (and others) without explicitly
declaring them in FrictPhys itself.

cheers
Jan

[1]
http://bazaar.launchpad.net/~yade-pkg/yade/git-trunk/view/head:/core/IPhys.hpp#L16
[2]
http://bazaar.launchpad.net/~yade-pkg/yade/git-trunk/view/head:/pkg/common/NormShearPhys.hpp#L9
[3]
http://bazaar.launchpad.net/~yade-pkg/yade/git-trunk/view/head:/pkg/common/NormShearPhys.hpp#L19
[4]
http://bazaar.launchpad.net/~yade-pkg/yade/git-trunk/view/head:/pkg/dem/FrictPhys.hpp#L15
[5]
http://bazaar.launchpad.net/~yade-pkg/yade/git-trunk/view/head:/pkg/dem/CohesiveFrictionalContactLaw.hpp#L46

2014-10-08 20:26 GMT+02:00 behzad <email address hidden>:

> Question #251218 on Yade changed:
> https://answers.launchpad.net/yade/+question/251218
>
> Status: Answered => Open
>
> behzad is still having a problem:
> Hi,
>
> So, just to wrap up I ask the last question.
> How do you inherit a new class from a parent class without duplicating the
> parameters. Let's say we want the new class to have only one new parameter.
> How do we do this? If I learn this I can apply it to all changes I need to
> make for material, Phys, Law and etc. I appreciate if you can show this
> with an example like CohBurgersPhys and CohFrictPhys. Let's say
> CohBurgersPhys will have only one new parameter or properties.
>
> Thank you
>
> --
> You received this question notification because you are a member of
> yade-users, which is an answer contact for Yade.
>
> _______________________________________________
> Mailing list: https://launchpad.net/~yade-users
> Post to : <email address hidden>
> Unsubscribe : https://launchpad.net/~yade-users
> More help : https://help.launchpad.net/ListHelp
>

Revision history for this message
behzad (behzad-majidi) said :
#28

Thanks Jan Stránský, that solved my question.