Module dem_base_ic

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

File called for the initialization.

Expand source code

# -----------------------------------------------------------------------------#
# Imports
# -----------------------------------------------------------------------------#

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

# -----------------------------------------------------------------------------#
# Functions called once
# -----------------------------------------------------------------------------#

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

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

def create_grains():
    '''
    Recreate level set from data extrapolated with phase field output.
    '''
    print("Creating level set")

    for i_data in range(1, n_data_base+1):
        # load data
        with open('ms/level_set_part'+str(i_data)+'.data', 'rb') as handle:
            dict_save = pickle.load(handle)
        L_sdf_i_map = dict_save['L_sdf_i_map']
        L_x_L = dict_save['L_x_L']
        L_y_L = dict_save['L_y_L']
        L_rbm = dict_save['L_rbm']

        # create grain
        for i_grain in range(len(L_sdf_i_map)):
            # grid
            spacing = L_x_L[i_grain][1]-L_x_L[i_grain][0]
            grid = RegularGrid(
                min=(min(L_x_L[i_grain]), min(L_y_L[i_grain]), -extrude_z*spacing/2),
                nGP=(len(L_x_L[i_grain]), len(L_y_L[i_grain]), extrude_z),
                spacing=spacing
            )  
            # grains
            O.bodies.append(
                levelSetBody(grid=grid,
                            distField=L_sdf_i_map[i_grain].tolist(),
                            material=0)
            )
            O.bodies[-1].state.blockedDOFs = 'zXYZ'
            O.bodies[-1].state.pos = L_rbm[i_grain]
            O.bodies[-1].state.refPos = L_rbm[i_grain]
        
# -----------------------------------------------------------------------------#

def create_walls():
    '''
    Recreate walls.
    '''
    for i_wall in range(len(L_pos_w)):
        O.bodies.append(wall((L_pos_w[i_wall][0], L_pos_w[i_wall][1], L_pos_w[i_wall][2]), L_pos_w[i_wall][3], material=1))

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

def create_plots():
    '''
    Create plots during the DEM step.
    '''
    plot.plots = {'iteration': ('force_applied'), 'pos_w': ('force_applied'),\
                  'iteration ': ('unbalForce', None, 'nb_contact')}

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

def compute_dt():
    '''
    Compute the time step used in the DEM step.
    '''
    O.dt = 0.2*SpherePWaveTimeStep(radius=5*m_size, density=density, young=E)

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

def create_engines():
    '''
    Create engines.

    Overlap based on the distance

    Ip2:
        kn = given
        ks = given    

    Law2:
        Fn = kn.un
        Fs = ks.us
    '''
    O.engines = [
            VTKRecorder(recorders=["lsBodies"], fileName='./ms/ic_ite_', iterPeriod=f_vtk, multiblockLS=True, label='vtk_export'),   
            ForceResetter(),
            InsertionSortCollider([Bo1_LevelSet_Aabb(), Bo1_Wall_Aabb()], verletDist=0.00),
            InteractionLoop(
                    [Ig2_LevelSet_LevelSet_ScGeom(), Ig2_Wall_LevelSet_ScGeom()],
                    [Ip2_FrictMat_FrictMat_FrictPhys(kn=MatchMaker(algo='val', val=kn), ks=MatchMaker(algo='val', val=ks))],
                    [Law2_ScGeom_FrictPhys_CundallStrack(sphericalBodies=False)]),
    		PyRunner(command='applied_force()', iterPeriod=1, label='force'),
            NewtonIntegrator(damping=0.1, label='newton', gravity=(0, 0, 0)),
            PyRunner(command='add_data()', iterPeriod=f_data, label='data'),
            PyRunner(command='check()', iterPeriod=1, label='checker')
    ]

# -----------------------------------------------------------------------------#
# Functions called multiple times
# -----------------------------------------------------------------------------#

def applied_force():
    '''
    Apply a constant force on the control wall.
    '''
    v_plate_max = 1000*(1-0.6)/(O.dt*max_simu) # modify here
    kp = v_plate_max/(force_applied*0.1)
    Fy = O.forces.f(wall_control.id)[1]
    if Fy == 0:
        wall_control.state.vel = (0, -v_plate_max, 0)  
    else :
        dF = Fy - force_applied
        v_try_abs = kp*abs(dF) 
        # maximal speed is applied to top wall
        if v_try_abs < v_plate_max :
            wall_control.state.vel = (0, np.sign(dF)*v_try_abs, 0)
        else :
            wall_control.state.vel = (0, np.sign(dF)*v_plate_max, 0)

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

def check():
    '''
    Try to detect a steady-state.
    A maximum number of iteration is used.
    '''
    if O.iter > max_simu:
        plot.plot(noShow=True).savefig('ms/ic_dem.png')
        O.pause() # stop DEM simulation
    
# -----------------------------------------------------------------------------#

def add_data():
    '''
    Add data to plot.
    '''
    plot.addData(iteration=O.iter, unbalForce=round(unbalancedForce(),3), nb_contact=avgNumInteractions(),\
                 force_applied=O.forces.f(wall_control.id)[1], pos_w=(wall_control.state.refPos[1]-wall_control.state.pos[1]))
    
# -----------------------------------------------------------------------------#
# Load data
# -----------------------------------------------------------------------------#

# other
density = 2000

# from main
with open('ms/from_main_to_ic.data', 'rb') as handle:
    dict_save = pickle.load(handle)
Poisson = dict_save['Poisson']
E = dict_save['E']
kn = dict_save['kn']
ks = dict_save['ks']
force_applied = dict_save['force_applied']

# main information
with open('ms/level_set_part0.data', 'rb') as handle:
    dict_save = pickle.load(handle)
m_size = dict_save['m_size']
L_pos_w = dict_save['L_pos_w']
n_data_base = dict_save['n_data_base']
extrude_z = dict_save['extrude_z']

# data simulation
f_data   = 200
f_vtk    = 20000
max_simu = 200000

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

# materials
create_materials()
# create grains and walls
create_grains()
create_walls() 
# define loading
wall_control = O.bodies[-3]
# Engines
create_engines()
# time step
compute_dt()
# plot
create_plots()

# -----------------------------------------------------------------------------#
# MAIN DEM
# -----------------------------------------------------------------------------#

O.run()
O.wait()

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

# walls
L_pos_w = [O.bodies[-6].state.pos[0], # -x
           O.bodies[-5].state.pos[0], # +x
           O.bodies[-4].state.pos[1], # -y
           O.bodies[-3].state.pos[1]] # +y         

# data
plot.saveDataTxt('ms/ic_data.txt')

# dict grains
i_grain = 0
for b in O.bodies:
    if isinstance(b.shape, LevelSet):
        print('save grain', i_grain,\
              '(size = '+str(b.shape.lsGrid.nGP[0])+'-'+str(b.shape.lsGrid.nGP[1])+')')

        # compute grid
        x_L = []
        for i in range(b.shape.lsGrid.nGP[0]):
            x_L.append(b.shape.lsGrid.gridPoint(i,0,0)[0]+b.state.pos[0])    
        y_L = []
        for i in range(b.shape.lsGrid.nGP[1]):
            y_L.append(b.shape.lsGrid.gridPoint(0,i,0)[1]+b.state.pos[1])

        # compute distance field
        ls_map = np.zeros((len(y_L), len(x_L)))
        for i in range(len(x_L)):
            for j in range(len(y_L)):
                ls_map[-1-j, i] = b.shape.distField[i][j][int(b.shape.lsGrid.nGP[2]/2)]
        # save dict
        dict_save = {
                    'x_L': x_L,
                    'y_L': y_L,
                    'ls_map': ls_map
                    }
        with open('ms/from_ic_grain_'+str(i_grain)+'.data', 'wb') as handle:
            pickle.dump(dict_save, handle, protocol=pickle.HIGHEST_PROTOCOL)

        # prepare for next one
        i_grain = i_grain + 1

# load data
with open('ms/level_set_part0.data', 'rb') as handle:
    dict_save = pickle.load(handle)

# dict global
dict_save = {
'n_grains': i_grain,
'L_pos_w': L_pos_w,
'm_size': m_size,
'extrude_z': dict_save['extrude_z'],
'margins': dict_save['margins']
}
with open('ms/from_ic.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(FrictMat(young=E, poisson=Poisson, frictionAngle=atan(0.5), density=density, label='frictMat'))
    O.materials.append(FrictMat(young=E, poisson=Poisson, frictionAngle=0, density=density, label='frictlessMat'))
def create_grains()

Recreate level set from data extrapolated with phase field output.

Expand source code

def create_grains():
    '''
    Recreate level set from data extrapolated with phase field output.
    '''
    print("Creating level set")

    for i_data in range(1, n_data_base+1):
        # load data
        with open('ms/level_set_part'+str(i_data)+'.data', 'rb') as handle:
            dict_save = pickle.load(handle)
        L_sdf_i_map = dict_save['L_sdf_i_map']
        L_x_L = dict_save['L_x_L']
        L_y_L = dict_save['L_y_L']
        L_rbm = dict_save['L_rbm']

        # create grain
        for i_grain in range(len(L_sdf_i_map)):
            # grid
            spacing = L_x_L[i_grain][1]-L_x_L[i_grain][0]
            grid = RegularGrid(
                min=(min(L_x_L[i_grain]), min(L_y_L[i_grain]), -extrude_z*spacing/2),
                nGP=(len(L_x_L[i_grain]), len(L_y_L[i_grain]), extrude_z),
                spacing=spacing
            )  
            # grains
            O.bodies.append(
                levelSetBody(grid=grid,
                            distField=L_sdf_i_map[i_grain].tolist(),
                            material=0)
            )
            O.bodies[-1].state.blockedDOFs = 'zXYZ'
            O.bodies[-1].state.pos = L_rbm[i_grain]
            O.bodies[-1].state.refPos = L_rbm[i_grain]
def create_walls()

Recreate walls.

Expand source code

def create_walls():
    '''
    Recreate walls.
    '''
    for i_wall in range(len(L_pos_w)):
        O.bodies.append(wall((L_pos_w[i_wall][0], L_pos_w[i_wall][1], L_pos_w[i_wall][2]), L_pos_w[i_wall][3], material=1))
def create_plots()

Create plots during the DEM step.

Expand source code

def create_plots():
    '''
    Create plots during the DEM step.
    '''
    plot.plots = {'iteration': ('force_applied'), 'pos_w': ('force_applied'),\
                  'iteration ': ('unbalForce', None, 'nb_contact')}
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.2*SpherePWaveTimeStep(radius=5*m_size, density=density, young=E)
def create_engines()

Create engines.

Overlap based on the distance
    Ip2:
        kn = given
        ks = given    

    Law2:
        Fn = kn.un
        Fs = ks.us
Expand source code

def create_engines():
    '''
    Create engines.

    Overlap based on the distance

    Ip2:
        kn = given
        ks = given    

    Law2:
        Fn = kn.un
        Fs = ks.us
    '''
    O.engines = [
            VTKRecorder(recorders=["lsBodies"], fileName='./ms/ic_ite_', iterPeriod=f_vtk, multiblockLS=True, label='vtk_export'),   
            ForceResetter(),
            InsertionSortCollider([Bo1_LevelSet_Aabb(), Bo1_Wall_Aabb()], verletDist=0.00),
            InteractionLoop(
                    [Ig2_LevelSet_LevelSet_ScGeom(), Ig2_Wall_LevelSet_ScGeom()],
                    [Ip2_FrictMat_FrictMat_FrictPhys(kn=MatchMaker(algo='val', val=kn), ks=MatchMaker(algo='val', val=ks))],
                    [Law2_ScGeom_FrictPhys_CundallStrack(sphericalBodies=False)]),
    		PyRunner(command='applied_force()', iterPeriod=1, label='force'),
            NewtonIntegrator(damping=0.1, label='newton', gravity=(0, 0, 0)),
            PyRunner(command='add_data()', iterPeriod=f_data, label='data'),
            PyRunner(command='check()', iterPeriod=1, label='checker')
    ]
def applied_force()

Apply a constant force on the control wall.

Expand source code

def applied_force():
    '''
    Apply a constant force on the control wall.
    '''
    v_plate_max = 1000*(1-0.6)/(O.dt*20000) # modify here
    kp = v_plate_max/(force_applied_target*0.1)
    Fy = O.forces.f(wall_control.id)[1]
    if Fy == 0:
        wall_control.state.vel = (0, -v_plate_max, 0)  
    else :
        dF = Fy - force_applied_target
        v_try_abs = kp*abs(dF) 
        # maximal speed is applied to top wall
        if v_try_abs < v_plate_max :
            wall_control.state.vel = (0, np.sign(dF)*v_try_abs, 0)
        else :
            wall_control.state.vel = (0, np.sign(dF)*v_plate_max, 0)
def check()

Try to detect a steady-state.

A maximum number of iteration is used.
Expand source code

def check():
    '''
    Try to detect a steady-state.
    A maximum number of iteration is used.
    '''
    if O.iter > max_simu:
        plot.plot(noShow=True).savefig('ms/ic_dem.png')
        O.pause() # stop DEM simulation
def add_data()

Add data to plot

Expand source code

def add_data():
    '''
    Add data to plot.
    '''
        plot.addData(iteration=O.iter, unbalForce=round(unbalancedForce(),3), nb_contact=avgNumInteractions(),\
                 force_applied=O.forces.f(wall_control.id)[1], pos_w=(wall_control.state.refPos[1]-wall_control.state.pos[1]))