Module dem_base

@author: Alexandre Sac–Morane alexandre.sac-morane@uclouvain.be

File called during the DEM step.

Expand source code

  from yade import pack, utils, plot, export
  import polyhedra_utils
  import pickle
  import numpy as np

  # Own functions
  # -----------------------------------------------------------------------------#

  def create_materials():
      '''
      Create materials.
      '''
      O.materials.append(PolyhedraMat(young=E, poisson=Poisson, frictionAngle=atan(0.5), density=2000, label='frictMat'))

  # -----------------------------------------------------------------------------#

  def create_polyhedral():
      '''
      Recreate polydra from data extrapolated with phase field output.
      '''
      print("Creating polyhedra")

      # grain
      O.bodies.append(
          polyhedra_utils.polyhedra(
              O.materials[-1],
              v = L_vertices_1,
              fixed = True,
              color = [0,0,1]
          )
      )
      O.bodies[-1].state.blockedDOFs = 'xzXYZ'
      O.bodies[-1].state.refPos = O.bodies[-1].state.pos

      # plate
      O.bodies.append(
          polyhedra_utils.polyhedra(
              O.materials[-1],
              v = L_vertices_2,
              fixed = True,
              color = [1,0,0]
          )
      )
      O.bodies[-1].state.refPos = O.bodies[-1].state.pos

      # initial export
      vtkExporter.exportPolyhedra(what=dict(color='b.shape.color'))
      vtkExporter_1.exportPolyhedra(ids=[0])
      vtkExporter_2.exportPolyhedra(ids=[1])

  # -----------------------------------------------------------------------------#

  def applied_force():
      '''
      Apply force on the grain
      '''
      O.forces.addF(0, (0, -force_applied, 0))

  # -----------------------------------------------------------------------------#

  def add_data():
      '''
      Add data to plot :
          - iteration
          - overlap between the two particles (>0 if overlap)
      '''
      if O.interactions.has(0,1) : # check if interaction exists
          if O.interactions[0,1].isReal: # check if interaction is real
              overlap = O.interactions[0,1].geom.equivalentPenetrationDepth
              volume = O.interactions[0,1].geom.penetrationVolume
              normal_force = O.interactions[0,1].phys.normalForce[1]
          else :
              overlap = 0
              volume = 0
              normal_force = 0
      else :
          overlap = 0
          volume = 0
          normal_force = 0
      plot.addData(iteration=O.iter, overlap=overlap, volume=volume, normal_force=normal_force, force_applied=force_applied)

  # -----------------------------------------------------------------------------#

  def check():
      '''
      Try to detect a wteady-state of the overlap between the two particles.
      A maximum number of iteration is used.
      '''
      if O.iter < max(n_ite_max*0.01, n_steady_state_detection):
          return
      window = plot.data['normal_force'][-n_steady_state_detection:]
      if O.iter > n_ite_max or \
         ((max(window)-min(window)) < steady_state_detection*force_applied and
          max(window)>force_applied and min(window) < force_applied):
          vtkExporter.exportPolyhedra(what=dict(color='b.shape.color')) # final export
          vtkExporter_1.exportPolyhedra(ids=[0])
          vtkExporter_2.exportPolyhedra(ids=[1])
          if print_contact_dem:
              if print_all_contact_dem:
                  plot.plot(noShow=True).savefig('plot/contact_dem/'+str(i_DEMPF_ite)+'.png')
              else:
                  plot.plot(noShow=True).savefig('plot/contact_dem.png')
          O.pause() # stop DEM simulation

  # -----------------------------------------------------------------------------#

  def compute_dt():
      '''
      Compute the time step used in the DEM step.
      '''
      O.dt = 0.1 * polyhedra_utils.PWaveTimeStep()
      #O.dt = 0.0004

  # -----------------------------------------------------------------------------#

  def create_engines():
      '''
      Create engines.

      Ip2_PolyhedraMat_PolyhedraMat_PolyhedraPhys
      Normal: 1/kn = 1/Y1 + 1/Y2
      Shear: 1/ks = 1/Y1v1 + 1/Y2v2
      Y is the Young modulus
      v is the Poisson ratio

      Law2_PolyhedraGeom_PolyhedraPhys_Volumetric
      F = k N
      Force is proportionnal to the volume
      '''
      O.engines = [
              ForceResetter(),
              InsertionSortCollider([Bo1_Polyhedra_Aabb()], verletDist=0.00),
              InteractionLoop(
                      [Ig2_Polyhedra_Polyhedra_PolyhedraGeom()],
                      [Ip2_PolyhedraMat_PolyhedraMat_PolyhedraPhys()],
                      [Law2_PolyhedraGeom_PolyhedraPhys_Volumetric()]
              ),
      		PyRunner(command='applied_force()',iterPeriod=1),
      		NewtonIntegrator(damping=0.5, exactAsphericalRot=True, gravity=[0, 0, 0], label='newton'),
      		PyRunner(command='add_data()',iterPeriod=1),
              PyRunner(command='check()',iterPeriod=1, label='checker')
      ]

  # -----------------------------------------------------------------------------#

  def create_plots():
      '''
      Create plots during the DEM step.
      '''
      plot.plots = {'iteration': ('overlap', None, 'volume'),'iteration ':('normal_force','force_applied')}

  # ------------------------------------------------------------------------------------------------------------------------------------------ #
  # Load data

  # from main
  with open('data/main_to_dem.data', 'rb') as handle:
      dict_save = pickle.load(handle)
  E = dict_save['E']
  Poisson = dict_save['Poisson']
  force_applied = dict_save['force_applied']
  pos_1 = dict_save['pos_1']
  n_ite_max = dict_save['n_ite_max']
  steady_state_detection = dict_save['steady_state_detection']
  n_steady_state_detection = dict_save['n_steady_state_detection']
  print_all_contact_dem = dict_save['print_all_contact_dem']
  print_contact_dem = dict_save['print_contact_dem']
  i_DEMPF_ite = dict_save['i_DEMPF_ite']

  # from plane interpolation
  with open('data/planes.data', 'rb') as handle:
      dict_save = pickle.load(handle)
  L_vertices_1 = dict_save['L_vertices_1']
  L_vertices_2 = dict_save['L_vertices_2']

  # ------------------------------------------------------------------------------------------------------------------------------------------ #
  # Plan simulation

  # vtk exporter
  vtkExporter = export.VTKExporter('vtk/2grains')
  vtkExporter_1 = export.VTKExporter('vtk/grain_1')
  vtkExporter_2 = export.VTKExporter('vtk/grain_2')

  # Plot
  create_plots() # from dem.py
  # materials
  create_materials() # from dem.py
  # create grains
  create_polyhedral() # from dem.py
  # Engines
  create_engines() # from dem.py
  # time step
  compute_dt() # from dem.py

  # ------------------------------------------------------------------------------------------------------------------------------------------ #
  # DEM

  O.run()
  O.wait()

  # ------------------------------------------------------------------------------------------------------------------------------------------ #
  # Output

  displacement = np.array(O.bodies[0].state.pos - O.bodies[0].state.refPos)
  contact_volume = float(O.interactions[0,1].geom.penetrationVolume)
  contact_area = float(O.interactions[0,1].geom.equivalentCrossSection) # Volume**(2/3)
  contact_overlap = float(O.interactions[0,1].geom.equivalentPenetrationDepth) # Volume/Surface
  normalForce = np.array(O.interactions[0,1].phys.normalForce)
  pos_1 = [float(O.bodies[0].state.pos[0]), float(O.bodies[0].state.pos[1])]
  overlap = 0
  for v_i in O.bodies[0].shape.v:
      for v_j in O.bodies[1].shape.v:
          overlap_try = (O.bodies[0].state.pos[1]+v_i[1]) - (O.bodies[1].state.pos[1]+v_j[1])
          if overlap_try > overlap:
              overlap = overlap_try
  surface = contact_volume/overlap
  n_v_1 = len(O.bodies[0].shape.v)

  # Save data
  dict_save = {
  'displacement': displacement,
  'contact_area': contact_area,
  'contact_volume': contact_volume,
  'contact_overlap': contact_overlap,
  'distance_extrema': overlap,
  'equivalent_area': surface,
  'normalForce': normalForce,
  'pos_1': pos_1,
  'n_v_1': n_v_1,
  'n_v_1_target': len(L_vertices_1),
  'contact_point': np.array(O.interactions[0,1].geom.contactPoint)
  }
  with open('data/dem_to_main.data', 'wb') as handle:
      pickle.dump(dict_save, handle, protocol=pickle.HIGHEST_PROTOCOL)

Functions

def create_materials()

Create material.

Expand source code

  def create_materials():
      '''
      Create materials.
      '''
      O.materials.append(PolyhedraMat(young=E, poisson=Poisson, frictionAngle=atan(0.5), density=2000, label='frictMat'))
def create_polyhedral()

recreate polyhedra from data extrapolated with phase field output.

Expand source code

  def create_polyhedral():
      '''
      Recreate polyhedra from data extrapolated with phase field output.
      '''
      print("Creating polyhedra")

      # grain
      O.bodies.append(
          polyhedra_utils.polyhedra(
              O.materials[-1],
              v = L_vertices_1,
              fixed = True,
              color = [0,0,1]
          )
      )
      O.bodies[-1].state.blockedDOFs = 'xzXYZ'
      O.bodies[-1].state.refPos = O.bodies[-1].state.pos

      # plate
      O.bodies.append(
          polyhedra_utils.polyhedra(
              O.materials[-1],
              v = L_vertices_2,
              fixed = True,
              color = [1,0,0]
          )
      )
      O.bodies[-1].state.refPos = O.bodies[-1].state.pos

      # initial export
      vtkExporter.exportPolyhedra(what=dict(color='b.shape.color'))
      vtkExporter_1.exportPolyhedra(ids=[0])
      vtkExporter_2.exportPolyhedra(ids=[1])
def applied_force()

Apply force on the grain.

Expand source code

  def applied_force():
      '''
      Apply force on the grain
      '''
      O.forces.addF(0, (0, -force_applied, 0))
def add_data()

Add data to plot : iteration and overlap.

Expand source code

  def add_data():
    '''
    Add data to plot :
        - iteration
        - overlap between the two particles (>0 if overlap)
    '''
    if O.interactions.has(0,1) : # check if interaction exists
        if O.interactions[0,1].isReal: # check if interaction is real
            overlap = O.interactions[0,1].geom.equivalentPenetrationDepth
            volume = O.interactions[0,1].geom.penetrationVolume
            normal_force = O.interactions[0,1].phys.normalForce[1]
        else :
            overlap = 0
            volume = 0
            normal_force = 0
    else :
        overlap = 0
        volume = 0
        normal_force = 0
    plot.addData(iteration=O.iter, overlap=overlap, volume=volume, normal_force=normal_force, force_applied=force_applied)
def check()

Try to detect a steady-state of the overlap between the two particles. A maximum number of iterations is used.

Expand source code

  def check():
      '''
      Try to detect a steady-state of the overlap between the two particles.
      A maximum number of iterations is used.
      '''
      if O.iter < max(n_ite_max*0.01, n_steady_state_detection):
          return
      window = plot.data['normal_force'][-n_steady_state_detection:]
      if O.iter > n_ite_max or \
         ((max(window)-min(window)) < steady_state_detection*force_applied and
          max(window)>force_applied and min(window) < force_applied):
          vtkExporter.exportPolyhedra(what=dict(color='b.shape.color')) # final export
          vtkExporter_1.exportPolyhedra(ids=[0])
          vtkExporter_2.exportPolyhedra(ids=[1])
          if print_contact_dem:
              if print_all_contact_dem:
                  plot.plot(noShow=True).savefig('plot/contact_dem/'+str(i_DEMPF_ite)+'.png')
              else:
                  plot.plot(noShow=True).savefig('plot/contact_dem.png')
          O.pause() # stop DEM simulation
def compute_dt()

Compute the time step used in the DEM step.

Expand source code

  def compute_dt():
      '''
      Compute the time step used in the DEM step.
      '''
      O.dt = 0.1 * polyhedra_utils.PWaveTimeStep()
      #O.dt = 0.0004
def create_engines()

Create engines.


    Ip2_PolyhedraMat_PolyhedraMat_PolyhedraPhys
    Normal: 1/kn = 1/Y1 + 1/Y2
    Shear: 1/ks = 1/Y1v1 + 1/Y2v2
    Y is the Young modulus
    v is the Poisson ratio

    Law2_PolyhedraGeom_PolyhedraPhys_Volumetric
    F = k N
    Force is proportionnal to the volume
Expand source code

  def create_engines():
      '''
      Create engines.

      Ip2_PolyhedraMat_PolyhedraMat_PolyhedraPhys
      Normal: 1/kn = 1/Y1 + 1/Y2
      Shear: 1/ks = 1/Y1v1 + 1/Y2v2
      Y is the Young modulus
      v is the Poisson ratio

      Law2_PolyhedraGeom_PolyhedraPhys_Volumetric
      F = k N
      Force is proportionnal to the volume
      '''
      O.engines = [
              ForceResetter(),
              InsertionSortCollider([Bo1_Polyhedra_Aabb()], verletDist=0.00),
              InteractionLoop(
                      [Ig2_Polyhedra_Polyhedra_PolyhedraGeom()],
                      [Ip2_PolyhedraMat_PolyhedraMat_PolyhedraPhys()],
                      [Law2_PolyhedraGeom_PolyhedraPhys_Volumetric()]
              ),
      		PyRunner(command='applied_force()',iterPeriod=1),
      		NewtonIntegrator(damping=0.5, exactAsphericalRot=True, gravity=[0, 0, 0], label='newton'),
      		PyRunner(command='add_data()',iterPeriod=1),
              PyRunner(command='check()',iterPeriod=1, label='checker')
      ]
def create_plots()

Create plots during the DEM step.

Expand source code

  def create_plots():
      '''
      Create plots during the DEM step.
      '''
      plot.plots = {'iteration': ('overlap', None, 'volume'),'iteration ':('normal_force','force_applied')}