Applying normal strain rates in PeriTriaxController engine

Asked by Mehdi Pouragha

Hi all,

I was wondering if there is a straightforward way to apply normal strain rates (de11/dt, ...) when using PeriTriaxController engine. If I understand correctly, unlike the TriaxialStressController engine, the strain goals in PeriTriaxController.goal refers to final desired strain and not the rate.

Would it be possible to set also the normal strain rates using O.cell.velGrad = (du/dx, du/dy, du/dz, dv/dx, dv/dy, dv/dz, dw/dx, dw/dy, dw/dz) command? My concern is that it would lead to a conflict with the engines goals. In case of such conflicts, I am not sure which command is overriding which.

In other words, if I set the normal strain rates with O.cell.velGrad, then what stressMask should be use, and how should I set the PeriTriaxController.goal so that there is no conflict between the set goals and prescribed strain rate?

I hope my question is comprehensible. Thanks a lot.

Question information

Language:
English Edit question
Status:
Solved
For:
Yade Edit question
Assignee:
No assignee Edit question
Solved by:
Bruno Chareyre
Solved:
Last query:
Last reply:
Revision history for this message
Jérôme Duriez (jduriez) said :
#1

Hi Mehdi,

My guess is that the simultaneous use of PeriTriaxController and velGrad assignements may be not possible.

Because, unlike TriaxialStressController again, it seems it is not possible to deactivate PeriTriaxController along certain axes: PeriTriaxController is missing something like e.g. TriaxialStressController.wall_back_activated

Thus, there seems to be no means to avoid the conflict you described (?), at the moment.

Maybe it could be possible to perform yourself the servo-loop on O.Cell.velGrad to maintain the constant stresses in the directions you would like ?

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

Hi,
The diagonal terms of the velocity gradient are controlled by PeriTriaxController.maxStrainRate.
You you change them directly it will be replaced by values from PeriTriaxController.
The off diagonal terms are free, you can change them independently of the controller (e.g. simple shear with imposed normal stress).

@Jérôme
"it is not possible to deactivate PeriTriaxController along certain axes: PeriTriaxController is missing something"

Sorry but no, I don't see anything missing. What would it be to "deactivate" along one axis? Rate=0?
Well, it is straightforward: goal=current.

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

My complete sentence was "PeriTriaxController is missing something like e.g. TriaxialStressController.wall_back_activated"....

Deactivate along one axis would be to cancel the control by the Engine of stress/strain along this axis.

I think this is possible to do with TriaxialStressController, setting e.g. TriaxialStressController.wall_bottom_activated = TriaxialStressController.wall_top_activated = false

PS : my comment still holds even though I know there are no walls in periodic boundary conditions ;-)

Revision history for this message
Chareyre (bruno-chareyre-9) said :
#4

What should happen when it is «not controlled»? Whatever you imagine here
can be obtained with current behavior, i think.
B

Le jeu. 19 juil. 2018 09:33, Jérôme Duriez <
<email address hidden>> a écrit :

> Question #670862 on Yade changed:
> https://answers.launchpad.net/yade/+question/670862
>
> Jérôme Duriez posted a new comment:
> My complete sentence was "PeriTriaxController is missing something like
> e.g. TriaxialStressController.wall_back_activated"....
>
> Deactivate along one axis would be to cancel the control by the Engine
> of stress/strain along this axis.
>
> I think this is possible to do with TriaxialStressController, setting
> e.g. TriaxialStressController.wall_bottom_activated =
> TriaxialStressController.wall_top_activated = false
>
> PS : my comment still holds even though I know there are no walls in
> periodic boundary conditions ;-)
>
> --
> You received this question notification because your team yade-users 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
Mehdi Pouragha (mpouragha) said :
#5

Thanks for your response Bruno.

I did try changing PeriTriaxController.maxStrainRate. But obviously, this is only the maximum rate, not the current rate. It means that as long as the current rate is smaller than the maximum rate, the normal strain rate would keep changing itself.

So unless I am missing something, in the general case, the normal strain rate in PeriTriaxController cannot be constant. (?)

Mehdi

Revision history for this message
Chareyre (bruno-chareyre-9) said :
#6

Is current different from max? Any example script?
B

Le sam. 28 juil. 2018 01:22, Mehdi Pouragha <
<email address hidden>> a écrit :

> Question #670862 on Yade changed:
> https://answers.launchpad.net/yade/+question/670862
>
> Mehdi Pouragha posted a new comment:
> Thanks for your response Bruno.
>
> I did try changing PeriTriaxController.maxStrainRate. But obviously,
> this is only the maximum rate, not the current rate. It means that as
> long as the current rate is smaller than the maximum rate, the normal
> strain rate would keep changing itself.
>
> So unless I am missing something, in the general case, the normal strain
> rate in PeriTriaxController cannot be constant. (?)
>
> Mehdi
>
> --
> You received this question notification because your team yade-users 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
Mehdi Pouragha (mpouragha) said :
#7

Here is a simple example. 2D though. As long as the maxStrain rate is 0.5, it is maintained. But if I increase it to 1000 then the current rate changes.

Of course these rates are meaningless when we have such a small sample. As the sample becomes larger, the maximum rate at which the strain rate follows the maxStrainRate drastically decreases.

Mehdi
----------------------------------------------------
from yade import pack,qt
from yade import plot
import numpy as np

## computing sample size
num_spheres=500# number of spheres
key='_shearTest_'
compFricDegree = 10
finalFricDegree = 30
stabilityThreshold=0.01
young=1e6
max_Strainrate = 0.5

rMin,rMax = 0.5e-3,1.0e-3
vSol = num_spheres * pi * ((rMin + rMax)/2.)**2
volTot = vSol / (1-0.9)
size = volTot**(1./2.)

O.materials.append(FrictMat(young=young,poisson=1,frictionAngle=radians(compFricDegree),density=2600,label='spheres'))

O.periodic=True
#O.cell.setBox(size,size,1)
O.cell.hSize=Matrix3(size,0,0, 0,size,0, 0,0,1)
sp=pack.SpherePack()
radius=(rMin + rMax)/2.
num=sp.makeCloud((0,0,0.5),(size,size,0.5),radius,.2,num_spheres,periodic=True) # min,max,radius,rRelFuzz,spheresInCell,periodic
#O.bodies.append([sphere(s[0],s[1]) for s in sp])
sp.toSimulation(material='spheres')

for k in O.bodies:
 if isinstance(k.shape, Sphere): k.state.blockedDOFs='zXY'

O.engines=[
 ForceResetter(),
 InsertionSortCollider([Bo1_Sphere_Aabb()],verletDist=.05*radius),
 InteractionLoop(
  [Ig2_Sphere_Sphere_ScGeom()],
  [Ip2_FrictMat_FrictMat_FrictPhys()],
  [Law2_ScGeom_FrictPhys_CundallStrack()]
 ),
 PeriTriaxController(dynCell=True,mass=0.2,maxUnbalanced=0.01,relStressTol=0.001,globUpdate=5,maxStrainRate=[max_Strainrate,max_Strainrate,max_Strainrate],label='triax'),
 NewtonIntegrator(damping=.2),
]

O.dt=PWaveTimeStep()
## compaction
conf = -5 #kPa
triax.stressMask=3
triax.goal = [conf,conf,0]
stabilityThreshold = 1e-2

while 1:
  O.run(1000, True)
  #the global unbalanced force on dynamic bodies, thus excluding boundaries, which are not at equilibrium
  unb=unbalancedForce()
  print 'unbalanced force:',unb,' xx stress: ',triax.stressTensor[0,0]
  if unb<stabilityThreshold and abs((conf-triax.stressTensor[0,0])/conf)<0.01 and abs((conf-triax.stressTensor[1,1])/conf)<0.01:
    break

triax.stressMask=4 ## stress controlled along z
deps = -0.1
eps_xx, eps_yy = triax.strain[0], triax.strain[1]
triax.goal=[eps_xx+deps, eps_yy+deps ,0]
O.run(2,True)
print 'current maxStrainRate=', triax.maxStrainRate
print 'current strain rates: xx=', O.cell.velGrad[0,0], ' yy=',O.cell.velGrad[1,1], ' zz=', O.cell.velGrad[2,2]

ps_xx, eps_yy = triax.strain[0], triax.strain[1]
triax.goal=[eps_xx+deps, eps_yy+deps ,0]
print 'setting triax.maxStrainRate=1000'
triax.maxStrainRate = [1000,1000,1000]
O.run(2,True)
print 'current maxStrainRate=', triax.maxStrainRate
print 'current strain rates: xx=', O.cell.velGrad[0,0], ' yy=',O.cell.velGrad[1,1], ' zz=', O.cell.velGrad[2,2]

Revision history for this message
Chareyre (bruno-chareyre-9) said :
#8

Would 1000/sec for one iter not simply exceed the target 0.1 strain?
Why this would be related to sample size is unclear to me.
B

Le sam. 28 juil. 2018 02:22, Mehdi Pouragha <
<email address hidden>> a écrit :

> Question #670862 on Yade changed:
> https://answers.launchpad.net/yade/+question/670862
>
> Mehdi Pouragha posted a new comment:
> Here is a simple example. 2D though. As long as the maxStrain rate is
> 0.5, it is maintained. But if I increase it to 1000 then the current
> rate changes.
>
> Of course these rates are meaningless when we have such a small sample.
> As the sample becomes larger, the maximum rate at which the strain rate
> follows the maxStrainRate drastically decreases.
>
>
> Mehdi
> ----------------------------------------------------
> from yade import pack,qt
> from yade import plot
> import numpy as np
>
>
> ## computing sample size
> num_spheres=500# number of spheres
> key='_shearTest_'
> compFricDegree = 10
> finalFricDegree = 30
> stabilityThreshold=0.01
> young=1e6
> max_Strainrate = 0.5
>
> rMin,rMax = 0.5e-3,1.0e-3
> vSol = num_spheres * pi * ((rMin + rMax)/2.)**2
> volTot = vSol / (1-0.9)
> size = volTot**(1./2.)
>
>
>
> O.materials.append(FrictMat(young=young,poisson=1,frictionAngle=radians(compFricDegree),density=2600,label='spheres'))
>
> O.periodic=True
> #O.cell.setBox(size,size,1)
> O.cell.hSize=Matrix3(size,0,0, 0,size,0, 0,0,1)
> sp=pack.SpherePack()
> radius=(rMin + rMax)/2.
> num=sp.makeCloud((0,0,0.5),(size,size,0.5),radius,.2,num_spheres,periodic=True)
> # min,max,radius,rRelFuzz,spheresInCell,periodic
> #O.bodies.append([sphere(s[0],s[1]) for s in sp])
> sp.toSimulation(material='spheres')
>
> for k in O.bodies:
> if isinstance(k.shape, Sphere): k.state.blockedDOFs='zXY'
>
>
> O.engines=[
> ForceResetter(),
> InsertionSortCollider([Bo1_Sphere_Aabb()],verletDist=.05*radius),
> InteractionLoop(
> [Ig2_Sphere_Sphere_ScGeom()],
> [Ip2_FrictMat_FrictMat_FrictPhys()],
> [Law2_ScGeom_FrictPhys_CundallStrack()]
> ),
>
> PeriTriaxController(dynCell=True,mass=0.2,maxUnbalanced=0.01,relStressTol=0.001,globUpdate=5,maxStrainRate=[max_Strainrate,max_Strainrate,max_Strainrate],label='triax'),
> NewtonIntegrator(damping=.2),
> ]
>
> O.dt=PWaveTimeStep()
> ## compaction
> conf = -5 #kPa
> triax.stressMask=3
> triax.goal = [conf,conf,0]
> stabilityThreshold = 1e-2
>
> while 1:
> O.run(1000, True)
> #the global unbalanced force on dynamic bodies, thus excluding
> boundaries, which are not at equilibrium
> unb=unbalancedForce()
> print 'unbalanced force:',unb,' xx stress: ',triax.stressTensor[0,0]
> if unb<stabilityThreshold and
> abs((conf-triax.stressTensor[0,0])/conf)<0.01 and
> abs((conf-triax.stressTensor[1,1])/conf)<0.01:
> break
>
>
> triax.stressMask=4 ## stress controlled along z
> deps = -0.1
> eps_xx, eps_yy = triax.strain[0], triax.strain[1]
> triax.goal=[eps_xx+deps, eps_yy+deps ,0]
> O.run(2,True)
> print 'current maxStrainRate=', triax.maxStrainRate
> print 'current strain rates: xx=', O.cell.velGrad[0,0], '
> yy=',O.cell.velGrad[1,1], ' zz=', O.cell.velGrad[2,2]
>
> ps_xx, eps_yy = triax.strain[0], triax.strain[1]
> triax.goal=[eps_xx+deps, eps_yy+deps ,0]
> print 'setting triax.maxStrainRate=1000'
> triax.maxStrainRate = [1000,1000,1000]
> O.run(2,True)
> print 'current maxStrainRate=', triax.maxStrainRate
> print 'current strain rates: xx=', O.cell.velGrad[0,0], '
> yy=',O.cell.velGrad[1,1], ' zz=', O.cell.velGrad[2,2]
>
> --
> You received this question notification because your team yade-users 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
Mehdi Pouragha (mpouragha) said :
#9

Bruno:

The sample size affects the rate chosen by the engine.

But, anyways, I think I have found a way to solve the problem;

As far as I understand, in PeriTriaxController engine, when the goal is strain, the strain rate will initially be equal to the maxStrainRate. The rate starts to decrease only when the target strain is being reached (?). This final ramping stage is probably not a big deal in most cases, but for cases involving small strain probing, it quickly shows up.

The solution I came up with, is that I make sure the strain goal is always far from the current stage (but on the right side, i.e. larger or smaller than current state). This way, the final ramping stage never takes place. I then stop the straining manually.

Thanks for all the help.

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

For the record:

- despite above statements I confirm that the strain rate is simply imposed by maxStrainRate independently of sample size.

 - there is no "ramping" at any point (ramping is linear and defined with a specific slope). Simply: if you want to go from 0 to N by steps S, and if N is not a multiple of S then the last step needs to be less than S. It causes the apparent ramping but it happens only at one specific iteration and it is not linear in general, hence not really a ramp in the classical sense.
For instance if O.dt=1, (target-current) = 0.1 and maxStrainRate=0.3, the sequence will be {0.3, 0.3, 0.3, 0.1, 0}
If O.dt!=1 the sequence will different.

- clearly if one wants to impose rate of strain for a number of iterations, instead of a final target strain, the absolute value of target strain is arbitrary but it must be large enough. I would set it to e.g. +/-1e10 depending on desired direction.

@Mehdi
- All this should not matter at all even for small strain probing. If I understand correctly you think smaller strain increments can be achieved with fewer iterations, but it is not really the case. If you reach a given strain in less than, say, 100 iterations then the final state is probably not equilibrated enough to get a relevant measure of anything. What you get is just numerical noise.
On the other if you go from one state to another in 1000+ iterations then the fact that the last iteration has a smaller rate is probably not an issue.

- your apparent size dependency is due to using different particle sizes, hence different O.dt.

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

erratum: the sequence will be {0.03, 0.03, 0.03, 0.01, 0}

Revision history for this message
Mehdi Pouragha (mpouragha) said :
#12

Thanks a lot Bruno for the ample explanation. It clarifies everything.

Mehdi

Revision history for this message
Mehdi Pouragha (mpouragha) said :
#13

Thanks Bruno Chareyre, that solved my question.