Module Contact_gw
@author: Alexandre Sac–Morane alexandre.sac-morane@uclouvain.be
The goal of this file is to define a new class. The new class is about the contact between a wall and a grain
Expand source code
# -*- coding: utf-8 -*-
"""
@author: Alexandre Sac--Morane
alexandre.sac-morane@uclouvain.be
The goal of this file is to define a new class.
The new class is about the contact between a wall and a grain
"""
#-------------------------------------------------------------------------------
#Librairies
#-------------------------------------------------------------------------------
import numpy as np
import math
#-------------------------------------------------------------------------------
#Class
#-------------------------------------------------------------------------------
class Contact_gw:
#-------------------------------------------------------------------------------
def __init__(self, ID, G, dict_material, Nature, Limit, Overlap):
"""
Defining the contact grain - wall.
Input :
itself (a contact grain - wall)
an id (a int)
a grain (a grain)
a material dictionnary (a dict)
a nature to identify the wall (a string)
the coordinate of the wall (a float)
an overlap (a float)
Output :
a contact grain - wall is generated
"""
self.id = ID
self.g = G
factor = 5 #factor just to increase the stiffness
self.k = factor*4/3*self.g.y/(1-self.g.nu*self.g.nu)*math.sqrt(self.g.r_mean) #Hertz law
self.kt = 0
self.ft = 0
self.limit = Limit
self.nature = Nature
self.mu = dict_material['mu_friction_gw']
self.coeff_restitution = dict_material['coeff_restitution']
self.overlap = Overlap
self.tangential_old_statut = False
self.overlap_tangential = 0
#-------------------------------------------------------------------------------
def update_overlap(self,new_overlap):
"""
Update the overlap of a contact already created.
Input :
itself (a contact grain - wall)
a new overlap (a float)
Output :
Nothing, but the attribute is updated (a float)
"""
self.overlap = new_overlap
#-------------------------------------------------------------------------------
def init_contact_gw(self,L_g):
"""
Initialize the contact.
The grain is updated, the tangential reaction is set at 0 and a boolean is set at False (new contact grain-wall)
Input :
itself (a contact grain - wall)
the list of the grain (a list)
Output :
Nothing, but the attributes are updated (a grain, a float and a boolean)
"""
self.g = L_g[self.g.id]
self.ft = 0
self.tangential_old_statut = False
#-------------------------------------------------------------------------------
def DEM_gw_Polyhedral_normal(self):
"""
Compute the normal reaction of a contact grain-wall.
Here a pontual spring is considered.
Input :
itself (a contact grain - wall)
Output :
Nothing, but the interaction between grain and wall is computed. Differents attributes are updated.
"""
#conditions "if" are defined and same for each wall nature
if self.nature == 'gwy_min':
#unlinear stiffness
nwg = np.array([0,1])
self.nwg = nwg
Fwg_n = self.k*self.overlap**(3/2)
Fwg = Fwg_n*nwg
self.Fwg_n = Fwg_n
self.g.update_f(Fwg[0],Fwg[1],self.g.l_border[self.g.l_border_y.index(min(self.g.l_border_y))])
#damping
gamma = -math.log(self.coeff_restitution)/math.sqrt(math.pi**2+math.log(self.coeff_restitution)**2)
mass_eq = self.g.mass
eta = 2 * gamma * math.sqrt(mass_eq*self.k)
Fwg_damp_n = -np.dot(self.g.v,nwg)*eta
Fwg_damp = Fwg_damp_n*nwg
self.Fwg_damp_n = Fwg_damp_n
self.g.update_f(Fwg_damp[0],Fwg_damp[1],self.g.l_border[self.g.l_border_y.index(min(self.g.l_border_y))])
elif self.nature == 'gwy_max':
#unlinear stiffness
nwg = np.array([0,-1])
self.nwg = nwg
Fwg_n = self.k*self.overlap**(3/2)
Fwg = Fwg_n*nwg
self.Fwg_n = Fwg_n
self.g.update_f(Fwg[0],Fwg[1],self.g.l_border[self.g.l_border_y.index(max(self.g.l_border_y))])
#damping
Fwg_damp_n = 0
self.Fwg_damp_n = Fwg_damp_n
elif self.nature == 'gwx_min':
#unlinear stiffness
nwg = np.array([1,0])
self.nwg = nwg
Fwg_n = self.k*self.overlap**(3/2)
Fwg = Fwg_n*nwg
self.Fwg_n = Fwg_n
self.g.update_f(Fwg[0],Fwg[1],self.g.l_border[self.g.l_border_x.index(min(self.g.l_border_x))])
#damping
gamma = -math.log(self.coeff_restitution)/math.sqrt(math.pi**2+math.log(self.coeff_restitution)**2)
mass_eq = self.g.mass
eta = 2 * gamma * math.sqrt(mass_eq*self.k)
Fwg_damp_n = -np.dot(self.g.v,nwg)*eta
Fwg_damp = Fwg_damp_n*nwg
self.Fwg_damp_n = Fwg_damp_n
self.g.update_f(Fwg_damp[0],Fwg_damp[1],self.g.l_border[self.g.l_border_x.index(min(self.g.l_border_x))])
elif self.nature == 'gwx_max':
#unlinear stiffness
nwg = np.array([-1,0])
self.nwg = nwg
Fwg_n = self.k*self.overlap**(3/2)
Fwg = Fwg_n*nwg
self.Fwg_n = Fwg_n
self.g.update_f(Fwg[0],Fwg[1],self.g.l_border[self.g.l_border_x.index(max(self.g.l_border_x))])
#damping
gamma = -math.log(self.coeff_restitution)/math.sqrt(math.pi**2+math.log(self.coeff_restitution)**2)
mass_eq = self.g.mass
eta = 2 * gamma * math.sqrt(mass_eq*self.k)
Fwg_damp_n = -np.dot(self.g.v,nwg)*eta
Fwg_damp = Fwg_damp_n*nwg
self.Fwg_damp_n = Fwg_damp_n
self.g.update_f(Fwg_damp[0],Fwg_damp[1],self.g.l_border[self.g.l_border_x.index(max(self.g.l_border_x))])
#-------------------------------------------------------------------------------
def DEM_gw_Polyhedral_tangential(self, dt_DEM):
"""
Compute the tangential reaction of a contact grain-wall.
Here a pontual spring is considered.
Input :
itself (a contact grain - wall)
Output :
Nothing, but the interaction between grain and wall is computed. Differents attributes are updated.
"""
#conditions "if" are defined and same for each wall nature
if self.nature == 'gwy_min':
#unlinear stiffness
twg = np.array([-1, 0])
self.twg = twg
r = np.linalg.norm(self.g.l_border[:-1][self.g.l_border_y.index(min(self.g.l_border_y))] - self.g.center) - self.overlap
Delta_Us = (np.dot(self.g.v,self.twg) - r*self.g.w) * dt_DEM
self.overlap_tangential = self.overlap_tangential + Delta_Us
self.ft = self.ft - self.kt*Delta_Us
if abs(self.ft) > abs(self.mu*self.Fwg_n) :
self.ft = self.mu * abs(self.Fwg_n) * np.sign(self.ft)
Fwg = self.ft*twg
self.g.update_f(Fwg[0],Fwg[1],self.g.l_border[self.g.l_border_y.index(min(self.g.l_border_y))])
elif self.nature == 'gwy_max':
#unlinear stiffness
twg = np.array([1, 0])
self.twg = twg
r = np.linalg.norm(self.g.l_border[:-1][self.g.l_border_y.index(max(self.g.l_border_y))] - self.g.center) - self.overlap
Delta_Us = (np.dot(self.g.v,self.twg) - r*self.g.w) * dt_DEM
self.overlap_tangential = self.overlap_tangential + Delta_Us
self.ft = self.ft - self.kt*Delta_Us
if abs(self.ft) > abs(self.mu*self.Fwg_n) :
self.ft = self.mu * abs(self.Fwg_n) * np.sign(self.ft)
Fwg = self.ft*twg
self.g.update_f(Fwg[0],Fwg[1],self.g.l_border[self.g.l_border_y.index(max(self.g.l_border_y))])
elif self.nature == 'gwx_min':
#unlinear stiffness
twg = np.array([0, 1])
self.twg = twg
r = np.linalg.norm(self.g.l_border[:-1][self.g.l_border_x.index(min(self.g.l_border_x))] - self.g.center) - self.overlap
Delta_Us = (np.dot(self.g.v,self.twg) - r*self.g.w) * dt_DEM
self.overlap_tangential = self.overlap_tangential + Delta_Us
self.ft = self.ft - self.kt*Delta_Us
if abs(self.ft) > abs(self.mu*self.Fwg_n) :
self.ft = self.mu * abs(self.Fwg_n) * np.sign(self.ft)
Fwg = self.ft*twg
self.g.update_f(Fwg[0],Fwg[1],self.g.l_border[self.g.l_border_x.index(min(self.g.l_border_x))])
elif self.nature == 'gwx_max':
#linear stiffness
twg = np.array([0, -1])
self.twg = twg
r = np.linalg.norm(self.g.l_border[:-1][self.g.l_border_x.index(max(self.g.l_border_x))] - self.g.center) - self.overlap
Delta_Us = (np.dot(self.g.v,self.twg) - r*self.g.w) * dt_DEM
self.overlap_tangential = self.overlap_tangential + Delta_Us
self.ft = self.ft - self.kt*Delta_Us
if abs(self.ft) > abs(self.mu*self.Fwg_n) :
self.ft = self.mu * abs(self.Fwg_n) * np.sign(self.ft)
Fwg = self.ft*twg
self.g.update_f(Fwg[0],Fwg[1],self.g.l_border[self.g.l_border_x.index(max(self.g.l_border_x))])
#-------------------------------------------------------------------------------
# Functions
#-------------------------------------------------------------------------------
def Grains_Polyhedral_Wall_contact_Neighborhood(dict_material,dict_sample):
"""
Detect contact grain in the neighborhood of the wall and the wall.
The neighborhood is updated with Update_wall_Neighborhoods().
An iteration over the grain list and a comparison with the coordinate of the different walls are done.
Input :
a material dictionnary (a dict)
a sample dict (a dict)
Output :
Nothing, but the sample dict is updated with the different grain - wall in contact
"""
for grain in dict_sample['wall_neighborhood']:
p_x_min = min(grain.l_border_x)
p_x_max = max(grain.l_border_x)
p_y_min = min(grain.l_border_y)
p_y_max = max(grain.l_border_y)
#grain-wall x_min
if p_x_min < dict_sample['x_box_min'] and (grain.id,-1) not in dict_sample['L_ij_contact_gw']:
overlap = dict_sample['x_box_min'] - p_x_min
dict_sample['L_contact_gw'].append(Contact_gw(dict_sample['id_contact_gw'], grain, dict_material, 'gwx_min', dict_sample['x_box_min'], overlap))
dict_sample['L_ij_contact_gw'].append((grain.id,-1))
dict_sample['id_contact_gw'] = dict_sample['id_contact_gw'] + 1
elif p_x_min < dict_sample['x_box_min'] and (grain.id,-1) in dict_sample['L_ij_contact_gw']:
overlap = dict_sample['x_box_min'] - p_x_min
dict_sample['L_contact_gw'][dict_sample['L_ij_contact_gw'].index((grain.id,-1))].update_overlap(overlap)
elif p_x_min > dict_sample['x_box_min'] and (grain.id,-1) in dict_sample['L_ij_contact_gw']:
i_contact = dict_sample['L_ij_contact_gw'].index((grain.id,-1))
dict_sample['L_contact_gw'].pop(i_contact)
dict_sample['L_ij_contact_gw'].pop(i_contact)
#grain-wall x_max
if p_x_max > dict_sample['x_box_max'] and (grain.id,-2) not in dict_sample['L_ij_contact_gw']:
overlap = p_x_max - dict_sample['x_box_max']
dict_sample['L_contact_gw'].append(Contact_gw(dict_sample['id_contact_gw'], grain, dict_material, 'gwx_max', dict_sample['x_box_max'], overlap))
dict_sample['L_ij_contact_gw'].append((grain.id,-2))
dict_sample['id_contact_gw'] = dict_sample['id_contact_gw'] + 1
elif p_x_max > dict_sample['x_box_max'] and (grain.id,-2) in dict_sample['L_ij_contact_gw']:
overlap = p_x_max - dict_sample['x_box_max']
dict_sample['L_contact_gw'][dict_sample['L_ij_contact_gw'].index((grain.id,-2))].update_overlap(overlap)
elif p_x_max < dict_sample['x_box_max'] and (grain.id,-2) in dict_sample['L_ij_contact_gw']:
i_contact = dict_sample['L_ij_contact_gw'].index((grain.id,-2))
dict_sample['L_contact_gw'].pop(i_contact)
dict_sample['L_ij_contact_gw'].pop(i_contact)
#grain-wall y_min
if p_y_min < dict_sample['y_box_min'] and (grain.id,-3) not in dict_sample['L_ij_contact_gw']:
overlap = dict_sample['y_box_min'] - p_y_min
dict_sample['L_contact_gw'].append(Contact_gw(dict_sample['id_contact_gw'], grain, dict_material, 'gwy_min', dict_sample['y_box_min'], overlap))
dict_sample['L_ij_contact_gw'].append((grain.id,-3))
dict_sample['id_contact_gw'] = dict_sample['id_contact_gw'] + 1
elif p_y_min < dict_sample['y_box_min'] and (grain.id,-3) in dict_sample['L_ij_contact_gw']:
overlap = dict_sample['y_box_min'] - p_y_min
dict_sample['L_contact_gw'][dict_sample['L_ij_contact_gw'].index((grain.id,-3))].update_overlap(overlap)
elif p_y_min > dict_sample['y_box_min'] and (grain.id,-3) in dict_sample['L_ij_contact_gw']:
i_contact = dict_sample['L_ij_contact_gw'].index((grain.id,-3))
dict_sample['L_contact_gw'].pop(i_contact)
dict_sample['L_ij_contact_gw'].pop(i_contact)
#grain-wall y_max
if p_y_max > dict_sample['y_box_max'] and (grain.id,-4) not in dict_sample['L_ij_contact_gw']:
overlap = p_y_max - dict_sample['y_box_max']
dict_sample['L_contact_gw'].append(Contact_gw(dict_sample['id_contact_gw'], grain, dict_material, 'gwy_max', dict_sample['y_box_max'], overlap))
dict_sample['L_ij_contact_gw'].append((grain.id,-4))
dict_sample['id_contact_gw'] = dict_sample['id_contact_gw'] + 1
elif p_y_max > dict_sample['y_box_max'] and (grain.id,-4) in dict_sample['L_ij_contact_gw']:
overlap = p_y_max - dict_sample['y_box_max']
dict_sample['L_contact_gw'][dict_sample['L_ij_contact_gw'].index((grain.id,-4))].update_overlap(overlap)
elif p_y_max < dict_sample['y_box_max'] and (grain.id,-4) in dict_sample['L_ij_contact_gw']:
i_contact = dict_sample['L_ij_contact_gw'].index((grain.id,-4))
dict_sample['L_contact_gw'].pop(i_contact)
dict_sample['L_ij_contact_gw'].pop(i_contact)
#-------------------------------------------------------------------------------
def Update_wall_Neighborhoods(dict_algorithm, dict_sample):
"""
Determine a neighborhoods for wall.
This function is called every x time step. A contact grain - wall is determined by Grains_Polyhedral_Wall_contact_Neighborhood().
A factor determines the size of the neighborhood window.
"""
wall_neighborhood = []
for grain in dict_sample['L_g']:
p_x_min = min(grain.l_border_x)
p_x_max = max(grain.l_border_x)
p_y_min = min(grain.l_border_y)
p_y_max = max(grain.l_border_y)
#grain-wall x_min
if abs(p_x_min-dict_sample['x_box_min']) < dict_algorithm['factor_neighborhood']*grain.r_max :
wall_neighborhood.append(grain)
#grain-wall x_max
if abs(p_x_max-dict_sample['x_box_max']) < dict_algorithm['factor_neighborhood']*grain.r_max :
wall_neighborhood.append(grain)
#grain-wall y_min
if abs(p_y_min-dict_sample['y_box_min']) < dict_algorithm['factor_neighborhood']*grain.r_max :
wall_neighborhood.append(grain)
#grain-wall y_max
if abs(p_y_max-dict_sample['y_box_max']) < dict_algorithm['factor_neighborhood']*grain.r_max :
wall_neighborhood.append(grain)
dict_sample['wall_neighborhood'] = wall_neighborhood
Functions
def Grains_Polyhedral_Wall_contact_Neighborhood(dict_material, dict_sample)
-
Detect contact grain in the neighborhood of the wall and the wall.
The neighborhood is updated with Update_wall_Neighborhoods(). An iteration over the grain list and a comparison with the coordinate of the different walls are done.
Input : a material dictionnary (a dict) a sample dict (a dict) Output : Nothing, but the sample dict is updated with the different grain - wall in contact
Expand source code
def Grains_Polyhedral_Wall_contact_Neighborhood(dict_material,dict_sample): """ Detect contact grain in the neighborhood of the wall and the wall. The neighborhood is updated with Update_wall_Neighborhoods(). An iteration over the grain list and a comparison with the coordinate of the different walls are done. Input : a material dictionnary (a dict) a sample dict (a dict) Output : Nothing, but the sample dict is updated with the different grain - wall in contact """ for grain in dict_sample['wall_neighborhood']: p_x_min = min(grain.l_border_x) p_x_max = max(grain.l_border_x) p_y_min = min(grain.l_border_y) p_y_max = max(grain.l_border_y) #grain-wall x_min if p_x_min < dict_sample['x_box_min'] and (grain.id,-1) not in dict_sample['L_ij_contact_gw']: overlap = dict_sample['x_box_min'] - p_x_min dict_sample['L_contact_gw'].append(Contact_gw(dict_sample['id_contact_gw'], grain, dict_material, 'gwx_min', dict_sample['x_box_min'], overlap)) dict_sample['L_ij_contact_gw'].append((grain.id,-1)) dict_sample['id_contact_gw'] = dict_sample['id_contact_gw'] + 1 elif p_x_min < dict_sample['x_box_min'] and (grain.id,-1) in dict_sample['L_ij_contact_gw']: overlap = dict_sample['x_box_min'] - p_x_min dict_sample['L_contact_gw'][dict_sample['L_ij_contact_gw'].index((grain.id,-1))].update_overlap(overlap) elif p_x_min > dict_sample['x_box_min'] and (grain.id,-1) in dict_sample['L_ij_contact_gw']: i_contact = dict_sample['L_ij_contact_gw'].index((grain.id,-1)) dict_sample['L_contact_gw'].pop(i_contact) dict_sample['L_ij_contact_gw'].pop(i_contact) #grain-wall x_max if p_x_max > dict_sample['x_box_max'] and (grain.id,-2) not in dict_sample['L_ij_contact_gw']: overlap = p_x_max - dict_sample['x_box_max'] dict_sample['L_contact_gw'].append(Contact_gw(dict_sample['id_contact_gw'], grain, dict_material, 'gwx_max', dict_sample['x_box_max'], overlap)) dict_sample['L_ij_contact_gw'].append((grain.id,-2)) dict_sample['id_contact_gw'] = dict_sample['id_contact_gw'] + 1 elif p_x_max > dict_sample['x_box_max'] and (grain.id,-2) in dict_sample['L_ij_contact_gw']: overlap = p_x_max - dict_sample['x_box_max'] dict_sample['L_contact_gw'][dict_sample['L_ij_contact_gw'].index((grain.id,-2))].update_overlap(overlap) elif p_x_max < dict_sample['x_box_max'] and (grain.id,-2) in dict_sample['L_ij_contact_gw']: i_contact = dict_sample['L_ij_contact_gw'].index((grain.id,-2)) dict_sample['L_contact_gw'].pop(i_contact) dict_sample['L_ij_contact_gw'].pop(i_contact) #grain-wall y_min if p_y_min < dict_sample['y_box_min'] and (grain.id,-3) not in dict_sample['L_ij_contact_gw']: overlap = dict_sample['y_box_min'] - p_y_min dict_sample['L_contact_gw'].append(Contact_gw(dict_sample['id_contact_gw'], grain, dict_material, 'gwy_min', dict_sample['y_box_min'], overlap)) dict_sample['L_ij_contact_gw'].append((grain.id,-3)) dict_sample['id_contact_gw'] = dict_sample['id_contact_gw'] + 1 elif p_y_min < dict_sample['y_box_min'] and (grain.id,-3) in dict_sample['L_ij_contact_gw']: overlap = dict_sample['y_box_min'] - p_y_min dict_sample['L_contact_gw'][dict_sample['L_ij_contact_gw'].index((grain.id,-3))].update_overlap(overlap) elif p_y_min > dict_sample['y_box_min'] and (grain.id,-3) in dict_sample['L_ij_contact_gw']: i_contact = dict_sample['L_ij_contact_gw'].index((grain.id,-3)) dict_sample['L_contact_gw'].pop(i_contact) dict_sample['L_ij_contact_gw'].pop(i_contact) #grain-wall y_max if p_y_max > dict_sample['y_box_max'] and (grain.id,-4) not in dict_sample['L_ij_contact_gw']: overlap = p_y_max - dict_sample['y_box_max'] dict_sample['L_contact_gw'].append(Contact_gw(dict_sample['id_contact_gw'], grain, dict_material, 'gwy_max', dict_sample['y_box_max'], overlap)) dict_sample['L_ij_contact_gw'].append((grain.id,-4)) dict_sample['id_contact_gw'] = dict_sample['id_contact_gw'] + 1 elif p_y_max > dict_sample['y_box_max'] and (grain.id,-4) in dict_sample['L_ij_contact_gw']: overlap = p_y_max - dict_sample['y_box_max'] dict_sample['L_contact_gw'][dict_sample['L_ij_contact_gw'].index((grain.id,-4))].update_overlap(overlap) elif p_y_max < dict_sample['y_box_max'] and (grain.id,-4) in dict_sample['L_ij_contact_gw']: i_contact = dict_sample['L_ij_contact_gw'].index((grain.id,-4)) dict_sample['L_contact_gw'].pop(i_contact) dict_sample['L_ij_contact_gw'].pop(i_contact)
def Update_wall_Neighborhoods(dict_algorithm, dict_sample)
-
Determine a neighborhoods for wall.
This function is called every x time step. A contact grain - wall is determined by Grains_Polyhedral_Wall_contact_Neighborhood(). A factor determines the size of the neighborhood window.
Expand source code
def Update_wall_Neighborhoods(dict_algorithm, dict_sample): """ Determine a neighborhoods for wall. This function is called every x time step. A contact grain - wall is determined by Grains_Polyhedral_Wall_contact_Neighborhood(). A factor determines the size of the neighborhood window. """ wall_neighborhood = [] for grain in dict_sample['L_g']: p_x_min = min(grain.l_border_x) p_x_max = max(grain.l_border_x) p_y_min = min(grain.l_border_y) p_y_max = max(grain.l_border_y) #grain-wall x_min if abs(p_x_min-dict_sample['x_box_min']) < dict_algorithm['factor_neighborhood']*grain.r_max : wall_neighborhood.append(grain) #grain-wall x_max if abs(p_x_max-dict_sample['x_box_max']) < dict_algorithm['factor_neighborhood']*grain.r_max : wall_neighborhood.append(grain) #grain-wall y_min if abs(p_y_min-dict_sample['y_box_min']) < dict_algorithm['factor_neighborhood']*grain.r_max : wall_neighborhood.append(grain) #grain-wall y_max if abs(p_y_max-dict_sample['y_box_max']) < dict_algorithm['factor_neighborhood']*grain.r_max : wall_neighborhood.append(grain) dict_sample['wall_neighborhood'] = wall_neighborhood
Classes
class Contact_gw (ID, G, dict_material, Nature, Limit, Overlap)
-
Defining the contact grain - wall.
Input : itself (a contact grain - wall) an id (a int) a grain (a grain) a material dictionnary (a dict) a nature to identify the wall (a string) the coordinate of the wall (a float) an overlap (a float) Output : a contact grain - wall is generated
Expand source code
class Contact_gw: #------------------------------------------------------------------------------- def __init__(self, ID, G, dict_material, Nature, Limit, Overlap): """ Defining the contact grain - wall. Input : itself (a contact grain - wall) an id (a int) a grain (a grain) a material dictionnary (a dict) a nature to identify the wall (a string) the coordinate of the wall (a float) an overlap (a float) Output : a contact grain - wall is generated """ self.id = ID self.g = G factor = 5 #factor just to increase the stiffness self.k = factor*4/3*self.g.y/(1-self.g.nu*self.g.nu)*math.sqrt(self.g.r_mean) #Hertz law self.kt = 0 self.ft = 0 self.limit = Limit self.nature = Nature self.mu = dict_material['mu_friction_gw'] self.coeff_restitution = dict_material['coeff_restitution'] self.overlap = Overlap self.tangential_old_statut = False self.overlap_tangential = 0 #------------------------------------------------------------------------------- def update_overlap(self,new_overlap): """ Update the overlap of a contact already created. Input : itself (a contact grain - wall) a new overlap (a float) Output : Nothing, but the attribute is updated (a float) """ self.overlap = new_overlap #------------------------------------------------------------------------------- def init_contact_gw(self,L_g): """ Initialize the contact. The grain is updated, the tangential reaction is set at 0 and a boolean is set at False (new contact grain-wall) Input : itself (a contact grain - wall) the list of the grain (a list) Output : Nothing, but the attributes are updated (a grain, a float and a boolean) """ self.g = L_g[self.g.id] self.ft = 0 self.tangential_old_statut = False #------------------------------------------------------------------------------- def DEM_gw_Polyhedral_normal(self): """ Compute the normal reaction of a contact grain-wall. Here a pontual spring is considered. Input : itself (a contact grain - wall) Output : Nothing, but the interaction between grain and wall is computed. Differents attributes are updated. """ #conditions "if" are defined and same for each wall nature if self.nature == 'gwy_min': #unlinear stiffness nwg = np.array([0,1]) self.nwg = nwg Fwg_n = self.k*self.overlap**(3/2) Fwg = Fwg_n*nwg self.Fwg_n = Fwg_n self.g.update_f(Fwg[0],Fwg[1],self.g.l_border[self.g.l_border_y.index(min(self.g.l_border_y))]) #damping gamma = -math.log(self.coeff_restitution)/math.sqrt(math.pi**2+math.log(self.coeff_restitution)**2) mass_eq = self.g.mass eta = 2 * gamma * math.sqrt(mass_eq*self.k) Fwg_damp_n = -np.dot(self.g.v,nwg)*eta Fwg_damp = Fwg_damp_n*nwg self.Fwg_damp_n = Fwg_damp_n self.g.update_f(Fwg_damp[0],Fwg_damp[1],self.g.l_border[self.g.l_border_y.index(min(self.g.l_border_y))]) elif self.nature == 'gwy_max': #unlinear stiffness nwg = np.array([0,-1]) self.nwg = nwg Fwg_n = self.k*self.overlap**(3/2) Fwg = Fwg_n*nwg self.Fwg_n = Fwg_n self.g.update_f(Fwg[0],Fwg[1],self.g.l_border[self.g.l_border_y.index(max(self.g.l_border_y))]) #damping Fwg_damp_n = 0 self.Fwg_damp_n = Fwg_damp_n elif self.nature == 'gwx_min': #unlinear stiffness nwg = np.array([1,0]) self.nwg = nwg Fwg_n = self.k*self.overlap**(3/2) Fwg = Fwg_n*nwg self.Fwg_n = Fwg_n self.g.update_f(Fwg[0],Fwg[1],self.g.l_border[self.g.l_border_x.index(min(self.g.l_border_x))]) #damping gamma = -math.log(self.coeff_restitution)/math.sqrt(math.pi**2+math.log(self.coeff_restitution)**2) mass_eq = self.g.mass eta = 2 * gamma * math.sqrt(mass_eq*self.k) Fwg_damp_n = -np.dot(self.g.v,nwg)*eta Fwg_damp = Fwg_damp_n*nwg self.Fwg_damp_n = Fwg_damp_n self.g.update_f(Fwg_damp[0],Fwg_damp[1],self.g.l_border[self.g.l_border_x.index(min(self.g.l_border_x))]) elif self.nature == 'gwx_max': #unlinear stiffness nwg = np.array([-1,0]) self.nwg = nwg Fwg_n = self.k*self.overlap**(3/2) Fwg = Fwg_n*nwg self.Fwg_n = Fwg_n self.g.update_f(Fwg[0],Fwg[1],self.g.l_border[self.g.l_border_x.index(max(self.g.l_border_x))]) #damping gamma = -math.log(self.coeff_restitution)/math.sqrt(math.pi**2+math.log(self.coeff_restitution)**2) mass_eq = self.g.mass eta = 2 * gamma * math.sqrt(mass_eq*self.k) Fwg_damp_n = -np.dot(self.g.v,nwg)*eta Fwg_damp = Fwg_damp_n*nwg self.Fwg_damp_n = Fwg_damp_n self.g.update_f(Fwg_damp[0],Fwg_damp[1],self.g.l_border[self.g.l_border_x.index(max(self.g.l_border_x))]) #------------------------------------------------------------------------------- def DEM_gw_Polyhedral_tangential(self, dt_DEM): """ Compute the tangential reaction of a contact grain-wall. Here a pontual spring is considered. Input : itself (a contact grain - wall) Output : Nothing, but the interaction between grain and wall is computed. Differents attributes are updated. """ #conditions "if" are defined and same for each wall nature if self.nature == 'gwy_min': #unlinear stiffness twg = np.array([-1, 0]) self.twg = twg r = np.linalg.norm(self.g.l_border[:-1][self.g.l_border_y.index(min(self.g.l_border_y))] - self.g.center) - self.overlap Delta_Us = (np.dot(self.g.v,self.twg) - r*self.g.w) * dt_DEM self.overlap_tangential = self.overlap_tangential + Delta_Us self.ft = self.ft - self.kt*Delta_Us if abs(self.ft) > abs(self.mu*self.Fwg_n) : self.ft = self.mu * abs(self.Fwg_n) * np.sign(self.ft) Fwg = self.ft*twg self.g.update_f(Fwg[0],Fwg[1],self.g.l_border[self.g.l_border_y.index(min(self.g.l_border_y))]) elif self.nature == 'gwy_max': #unlinear stiffness twg = np.array([1, 0]) self.twg = twg r = np.linalg.norm(self.g.l_border[:-1][self.g.l_border_y.index(max(self.g.l_border_y))] - self.g.center) - self.overlap Delta_Us = (np.dot(self.g.v,self.twg) - r*self.g.w) * dt_DEM self.overlap_tangential = self.overlap_tangential + Delta_Us self.ft = self.ft - self.kt*Delta_Us if abs(self.ft) > abs(self.mu*self.Fwg_n) : self.ft = self.mu * abs(self.Fwg_n) * np.sign(self.ft) Fwg = self.ft*twg self.g.update_f(Fwg[0],Fwg[1],self.g.l_border[self.g.l_border_y.index(max(self.g.l_border_y))]) elif self.nature == 'gwx_min': #unlinear stiffness twg = np.array([0, 1]) self.twg = twg r = np.linalg.norm(self.g.l_border[:-1][self.g.l_border_x.index(min(self.g.l_border_x))] - self.g.center) - self.overlap Delta_Us = (np.dot(self.g.v,self.twg) - r*self.g.w) * dt_DEM self.overlap_tangential = self.overlap_tangential + Delta_Us self.ft = self.ft - self.kt*Delta_Us if abs(self.ft) > abs(self.mu*self.Fwg_n) : self.ft = self.mu * abs(self.Fwg_n) * np.sign(self.ft) Fwg = self.ft*twg self.g.update_f(Fwg[0],Fwg[1],self.g.l_border[self.g.l_border_x.index(min(self.g.l_border_x))]) elif self.nature == 'gwx_max': #linear stiffness twg = np.array([0, -1]) self.twg = twg r = np.linalg.norm(self.g.l_border[:-1][self.g.l_border_x.index(max(self.g.l_border_x))] - self.g.center) - self.overlap Delta_Us = (np.dot(self.g.v,self.twg) - r*self.g.w) * dt_DEM self.overlap_tangential = self.overlap_tangential + Delta_Us self.ft = self.ft - self.kt*Delta_Us if abs(self.ft) > abs(self.mu*self.Fwg_n) : self.ft = self.mu * abs(self.Fwg_n) * np.sign(self.ft) Fwg = self.ft*twg self.g.update_f(Fwg[0],Fwg[1],self.g.l_border[self.g.l_border_x.index(max(self.g.l_border_x))])
Methods
def DEM_gw_Polyhedral_normal(self)
-
Compute the normal reaction of a contact grain-wall.
Here a pontual spring is considered.
Input : itself (a contact grain - wall) Output : Nothing, but the interaction between grain and wall is computed. Differents attributes are updated.
Expand source code
def DEM_gw_Polyhedral_normal(self): """ Compute the normal reaction of a contact grain-wall. Here a pontual spring is considered. Input : itself (a contact grain - wall) Output : Nothing, but the interaction between grain and wall is computed. Differents attributes are updated. """ #conditions "if" are defined and same for each wall nature if self.nature == 'gwy_min': #unlinear stiffness nwg = np.array([0,1]) self.nwg = nwg Fwg_n = self.k*self.overlap**(3/2) Fwg = Fwg_n*nwg self.Fwg_n = Fwg_n self.g.update_f(Fwg[0],Fwg[1],self.g.l_border[self.g.l_border_y.index(min(self.g.l_border_y))]) #damping gamma = -math.log(self.coeff_restitution)/math.sqrt(math.pi**2+math.log(self.coeff_restitution)**2) mass_eq = self.g.mass eta = 2 * gamma * math.sqrt(mass_eq*self.k) Fwg_damp_n = -np.dot(self.g.v,nwg)*eta Fwg_damp = Fwg_damp_n*nwg self.Fwg_damp_n = Fwg_damp_n self.g.update_f(Fwg_damp[0],Fwg_damp[1],self.g.l_border[self.g.l_border_y.index(min(self.g.l_border_y))]) elif self.nature == 'gwy_max': #unlinear stiffness nwg = np.array([0,-1]) self.nwg = nwg Fwg_n = self.k*self.overlap**(3/2) Fwg = Fwg_n*nwg self.Fwg_n = Fwg_n self.g.update_f(Fwg[0],Fwg[1],self.g.l_border[self.g.l_border_y.index(max(self.g.l_border_y))]) #damping Fwg_damp_n = 0 self.Fwg_damp_n = Fwg_damp_n elif self.nature == 'gwx_min': #unlinear stiffness nwg = np.array([1,0]) self.nwg = nwg Fwg_n = self.k*self.overlap**(3/2) Fwg = Fwg_n*nwg self.Fwg_n = Fwg_n self.g.update_f(Fwg[0],Fwg[1],self.g.l_border[self.g.l_border_x.index(min(self.g.l_border_x))]) #damping gamma = -math.log(self.coeff_restitution)/math.sqrt(math.pi**2+math.log(self.coeff_restitution)**2) mass_eq = self.g.mass eta = 2 * gamma * math.sqrt(mass_eq*self.k) Fwg_damp_n = -np.dot(self.g.v,nwg)*eta Fwg_damp = Fwg_damp_n*nwg self.Fwg_damp_n = Fwg_damp_n self.g.update_f(Fwg_damp[0],Fwg_damp[1],self.g.l_border[self.g.l_border_x.index(min(self.g.l_border_x))]) elif self.nature == 'gwx_max': #unlinear stiffness nwg = np.array([-1,0]) self.nwg = nwg Fwg_n = self.k*self.overlap**(3/2) Fwg = Fwg_n*nwg self.Fwg_n = Fwg_n self.g.update_f(Fwg[0],Fwg[1],self.g.l_border[self.g.l_border_x.index(max(self.g.l_border_x))]) #damping gamma = -math.log(self.coeff_restitution)/math.sqrt(math.pi**2+math.log(self.coeff_restitution)**2) mass_eq = self.g.mass eta = 2 * gamma * math.sqrt(mass_eq*self.k) Fwg_damp_n = -np.dot(self.g.v,nwg)*eta Fwg_damp = Fwg_damp_n*nwg self.Fwg_damp_n = Fwg_damp_n self.g.update_f(Fwg_damp[0],Fwg_damp[1],self.g.l_border[self.g.l_border_x.index(max(self.g.l_border_x))])
def DEM_gw_Polyhedral_tangential(self, dt_DEM)
-
Compute the tangential reaction of a contact grain-wall.
Here a pontual spring is considered.
Input : itself (a contact grain - wall) Output : Nothing, but the interaction between grain and wall is computed. Differents attributes are updated.
Expand source code
def DEM_gw_Polyhedral_tangential(self, dt_DEM): """ Compute the tangential reaction of a contact grain-wall. Here a pontual spring is considered. Input : itself (a contact grain - wall) Output : Nothing, but the interaction between grain and wall is computed. Differents attributes are updated. """ #conditions "if" are defined and same for each wall nature if self.nature == 'gwy_min': #unlinear stiffness twg = np.array([-1, 0]) self.twg = twg r = np.linalg.norm(self.g.l_border[:-1][self.g.l_border_y.index(min(self.g.l_border_y))] - self.g.center) - self.overlap Delta_Us = (np.dot(self.g.v,self.twg) - r*self.g.w) * dt_DEM self.overlap_tangential = self.overlap_tangential + Delta_Us self.ft = self.ft - self.kt*Delta_Us if abs(self.ft) > abs(self.mu*self.Fwg_n) : self.ft = self.mu * abs(self.Fwg_n) * np.sign(self.ft) Fwg = self.ft*twg self.g.update_f(Fwg[0],Fwg[1],self.g.l_border[self.g.l_border_y.index(min(self.g.l_border_y))]) elif self.nature == 'gwy_max': #unlinear stiffness twg = np.array([1, 0]) self.twg = twg r = np.linalg.norm(self.g.l_border[:-1][self.g.l_border_y.index(max(self.g.l_border_y))] - self.g.center) - self.overlap Delta_Us = (np.dot(self.g.v,self.twg) - r*self.g.w) * dt_DEM self.overlap_tangential = self.overlap_tangential + Delta_Us self.ft = self.ft - self.kt*Delta_Us if abs(self.ft) > abs(self.mu*self.Fwg_n) : self.ft = self.mu * abs(self.Fwg_n) * np.sign(self.ft) Fwg = self.ft*twg self.g.update_f(Fwg[0],Fwg[1],self.g.l_border[self.g.l_border_y.index(max(self.g.l_border_y))]) elif self.nature == 'gwx_min': #unlinear stiffness twg = np.array([0, 1]) self.twg = twg r = np.linalg.norm(self.g.l_border[:-1][self.g.l_border_x.index(min(self.g.l_border_x))] - self.g.center) - self.overlap Delta_Us = (np.dot(self.g.v,self.twg) - r*self.g.w) * dt_DEM self.overlap_tangential = self.overlap_tangential + Delta_Us self.ft = self.ft - self.kt*Delta_Us if abs(self.ft) > abs(self.mu*self.Fwg_n) : self.ft = self.mu * abs(self.Fwg_n) * np.sign(self.ft) Fwg = self.ft*twg self.g.update_f(Fwg[0],Fwg[1],self.g.l_border[self.g.l_border_x.index(min(self.g.l_border_x))]) elif self.nature == 'gwx_max': #linear stiffness twg = np.array([0, -1]) self.twg = twg r = np.linalg.norm(self.g.l_border[:-1][self.g.l_border_x.index(max(self.g.l_border_x))] - self.g.center) - self.overlap Delta_Us = (np.dot(self.g.v,self.twg) - r*self.g.w) * dt_DEM self.overlap_tangential = self.overlap_tangential + Delta_Us self.ft = self.ft - self.kt*Delta_Us if abs(self.ft) > abs(self.mu*self.Fwg_n) : self.ft = self.mu * abs(self.Fwg_n) * np.sign(self.ft) Fwg = self.ft*twg self.g.update_f(Fwg[0],Fwg[1],self.g.l_border[self.g.l_border_x.index(max(self.g.l_border_x))])
def init_contact_gw(self, L_g)
-
Initialize the contact.
The grain is updated, the tangential reaction is set at 0 and a boolean is set at False (new contact grain-wall)
Input : itself (a contact grain - wall) the list of the grain (a list) Output : Nothing, but the attributes are updated (a grain, a float and a boolean)
Expand source code
def init_contact_gw(self,L_g): """ Initialize the contact. The grain is updated, the tangential reaction is set at 0 and a boolean is set at False (new contact grain-wall) Input : itself (a contact grain - wall) the list of the grain (a list) Output : Nothing, but the attributes are updated (a grain, a float and a boolean) """ self.g = L_g[self.g.id] self.ft = 0 self.tangential_old_statut = False
def update_overlap(self, new_overlap)
-
Update the overlap of a contact already created.
Input : itself (a contact grain - wall) a new overlap (a float) Output : Nothing, but the attribute is updated (a float)
Expand source code
def update_overlap(self,new_overlap): """ Update the overlap of a contact already created. Input : itself (a contact grain - wall) a new overlap (a float) Output : Nothing, but the attribute is updated (a float) """ self.overlap = new_overlap