Module User
@author: Alexandre Sac–Morane alexandre.sac-morane@uclouvain.be
This is the file where the user can change the different parameters for the simulation.
Expand source code
# -*- coding: utf-8 -*-
"""
@author: Alexandre Sac--Morane
alexandre.sac-morane@uclouvain.be
This is the file where the user can change the different parameters for the simulation.
"""
#-------------------------------------------------------------------------------
#Librairy
#-------------------------------------------------------------------------------
import math
import numpy as np
from pathlib import Path
#Own functions and classes
import Grain
#-------------------------------------------------------------------------------
#User
#-------------------------------------------------------------------------------
def All_parameters():
'''
This function is called in main.py to have all the parameters needed in the simulation.
Input :
Nothing
Output :
an algorithm dictionnary (a dictionnary)
a material dictionnary (a dictionnary)
a sample dictionnary (a dictionnary)
a sollicitation dictionnary (a dictionnary)
'''
#---------------------------------------------------------------------------
#Geometry parameters
N_grain = 40 #total number of grains
R0 = 350 #µm radius to compute the grain distribution
L_R = [1.2*R0,1.1*R0,0.9*R0,0.8*R0] #from larger to smaller
L_percentage_R = [1/6,1/3,1/3,1/6] #distribution of the different radius
#Recompute the mean radius
R_mean = 0
for i in range(len(L_R)):
R_mean = R_mean + L_R[i]*L_percentage_R[i]
#write dict
dict_geometry = {
'R_mean' : R_mean,
'L_R' : L_R,
'L_percentage_R' : L_percentage_R,
'N_grain' : N_grain
}
#---------------------------------------------------------------------------
#Sample parameters
#Box définition
x_box_min = 0 #µm
x_box_max = 2*R_mean*math.sqrt(N_grain*0.6) #µm
y_box_min = 0 #µm
#spatial discretisation
nx = int(60*math.sqrt(N_grain*0.6)) #approx n nodes per grain with a mean radius
ny = int(0.6*nx)
#approximatively the number of vertices for one grain during DEM simulation
grain_discretisation = 40
dict_sample = {
'nx' : nx,
'ny' : ny,
'grain_discretisation' : grain_discretisation,
'x_box_min' : x_box_min,
'x_box_max' : x_box_max,
'y_box_min' : y_box_min
}
#---------------------------------------------------------------------------
#Material parameters
#phase field
Mobility = 1 #L1, L2 in .i
#Diffusion of etai
kappa_eta = 0.01
#Diffusion of c, the solute generated by the dissolution
kappa_c = 50
#Definition of the evolution of the penalty term inside a grain (for interpolation)
tau_kappa_c = 5 #kc = kc0 e(-(R_i-d)/R_i/tau_kappa_c)
#DEM
Y = 70*(10**9)*(10**6)*(10**(-12)) #Young Modulus µN/µm2
nu = 0.3 #Poisson's ratio
rho = 2500*10**(-6*3) #density kg/µm3
rho_surf = 4/3*rho*R_mean #kg/µm2
mu_friction_gg = 0.5 #grain-grain
mu_friction_gw = 0 #grain-wall
coeff_restitution = 0.2 #1 is perfect elastic
dict_material = {
'M' : Mobility,
'kappa_eta' : kappa_eta,
'kappa_c' : kappa_c,
'tau_kappa_c' : tau_kappa_c,
'Y' : Y,
'nu' : nu,
'rho' : rho,
'rho_surf' : rho_surf,
'mu_friction_gg' : mu_friction_gg,
'mu_friction_gw' : mu_friction_gw,
'coeff_restitution' : coeff_restitution
}
#---------------------------------------------------------------------------
#Algorithm parameters
np_proc = 4 #number of processor used
n_t_PFDEM = 50 #number of cycle PF-DEM
#Time step for phase field
n_t_PF = 8
dt_PF_init = 0.05
dt_PF_level1 = dt_PF_init/2
dt_PF_level2 = dt_PF_level1/2
dt_PF_level3 = dt_PF_level2/2
#criteria to switch level
Ed_level1 = 10
Ed_level2 = 20
Ed_level3 = 25
#PF parameters
factor_etai = 1.7 #factor reltaed to the minimal distance between grains with same eta
#DEM parameters
dt_DEM_crit = math.pi*min(L_R)/(0.16*nu+0.88)*math.sqrt(rho*(2+2*nu)/Y) #s critical time step from O'Sullivan 2011
dt_DEM = dt_DEM_crit/7 #s time step during DEM simulation
factor_neighborhood = 1.5 #margin to detect a grain into a neighborhood
i_update_neighborhoods = 100 #the frequency of the update of the neighborhood of the grains and the walls
#Stop criteria of the DEM
i_DEM_stop = 5000 #maximum iteration for one DEM simulation
Ecin_ratio = 0.0001
n_window_stop = 100
dy_box_max_stop = 35
#Margin for sphericity study
sphericity_margin = 0.05
#Discretisation to find the inscribing (number of nodes in one direction)
n_spatial_inscribing = 100
#List of plot to do
Debug = True #plot configuration before and after DEM simulation
Debug_DEM = False #plot configuration inside DEM
i_print_plot = 100 #frenquency of the print and plot (if Debug_DEM) in DEM step
# Config, DEM_tracker, DEM_txt, Diff_Solute, dt, Ed, Etai_distribution, Eta_c, Init_Current_Shape, Kc, Movie (need Config to work), Mesh, Porosity, Sphericity, sum_Ed, YBoxMax
L_flag_plot = ['Config', 'DEM_txt', 'Kc', 'DEM_tracker', 'Sphericity', 'Porosity', 'YBoxMax']
#Visual parameters (for plot Config)
c_min = 0
c_max = 0.1
#structural matrix to build diffusion map and available node map
struct_element = np.array(np.ones((6,6)), dtype = bool)
#Save the simulation
SaveData = True #Save data or not
clean_memory = True #delete Data, Input, Output at the end of the simulation
foldername = 'Data_MG_ACS' #name of the folder where data are saved
template = 'PS_MG' #template of the name of the simulation
if SaveData :
i_run = 1
folderpath = Path('../'+foldername+'/'+template+'_'+str(i_run))
while folderpath.exists():
i_run = i_run + 1
folderpath = Path('../'+foldername+'/'+template+'_'+str(i_run))
namefile = template+'_'+str(i_run)
else :
namefile = template
dict_algorithm = {
'c_min' : c_min,
'c_max' : c_max,
'sphericity_margin' : sphericity_margin,
'n_spatial_inscribing' : n_spatial_inscribing,
'np_proc' : np_proc,
'Debug' : Debug,
'Debug_DEM' : Debug_DEM,
'i_print_plot' : i_print_plot,
'factor_neighborhood' : factor_neighborhood,
'factor_etai': factor_etai,
'clean_memory' : clean_memory,
'SaveData' : SaveData,
'namefile' : namefile,
'dt_PF' : dt_PF_init,
'dt_PF_init' : dt_PF_init,
'dt_PF_level1' : dt_PF_level1,
'dt_PF_level2' : dt_PF_level2,
'dt_PF_level3' : dt_PF_level3,
'Ed_level1' : Ed_level1,
'Ed_level2' : Ed_level2,
'Ed_level3' : Ed_level3,
'n_t_PF' : n_t_PF,
'dt_DEM' : dt_DEM,
'i_update_neighborhoods': i_update_neighborhoods,
'i_DEM_stop' : i_DEM_stop,
'Ecin_ratio' : Ecin_ratio,
'n_window_stop' : n_window_stop,
'dy_box_max_stop' : dy_box_max_stop,
'foldername' : foldername,
'n_t_PFDEM' : n_t_PFDEM,
'L_flag_plot' : L_flag_plot,
'struct_element' : struct_element
}
#---------------------------------------------------------------------------
#External sollicitation parameters
chi = 0.5 #coefficient applied to the chemical energy
gravity = 0
Vertical_Confinement_Linear_Force = Y*2*R_mean/1000 #µN/µm used to compute the Vertical_Confinement_Force
Vertical_Confinement_Force = Vertical_Confinement_Linear_Force*(x_box_max-x_box_min) #µN
contact_gw_for_Emec = False #consider the contact grain - wall to compute Emec
dict_sollicitation = {
'chi' : chi,
'gravity' : gravity,
'contact_gw_for_Emec' : contact_gw_for_Emec,
'Vertical_Confinement_Force' : Vertical_Confinement_Force
}
#---------------------------------------------------------------------------
#Initial condition parameters
n_generation = 1 #number of grains generation
factor_ymax_box = 1.6 #margin to generate grains
N_test_max = 5000 # maximum number of tries to generate a grain without overlap
i_DEM_stop_IC = 3000 #stop criteria for DEM during IC
Debug_DEM_IC = False #plot configuration inside DEM during IC
i_print_plot_IC = 200 #frenquency of the print and plot (if Debug_DEM_IC) for IC
dt_DEM_IC = dt_DEM_crit/5 #s time step during IC
Ecin_ratio_IC = 0.0005
factor_neighborhood_IC = 1.5 #margin to detect a grain into a neighborhood
i_update_neighborhoods_gen = 5 #the frequency of the update of the neighborhood of the grains and the walls during IC generations
i_update_neighborhoods_com = 100 #the frequency of the update of the neighborhood of the grains and the walls during IC combination
#write dict
dict_ic = {
'n_generation' : n_generation,
'i_update_neighborhoods_gen': i_update_neighborhoods_gen,
'i_update_neighborhoods_com': i_update_neighborhoods_com,
'factor_ymax_box' : factor_ymax_box,
'i_DEM_stop_IC' : i_DEM_stop_IC,
'Debug_DEM' : Debug_DEM_IC,
'dt_DEM_IC' : dt_DEM_IC,
'Ecin_ratio_IC' : Ecin_ratio_IC,
'i_print_plot_IC' : i_print_plot_IC,
'factor_neighborhood_IC' : factor_neighborhood_IC,
'N_test_max' : N_test_max
}
#---------------------------------------------------------------------------
return dict_algorithm, dict_geometry, dict_ic, dict_material, dict_sample, dict_sollicitation
#-------------------------------------------------------------------------------
def Add_mesh(dict_geometry, dict_sample):
'''
Generate the mesh in the sample.
Input :
a geometry dictionnary (a dict)
a sample dictionnary (a dictionnary)
Output :
Nothing but the sample dictionnary gets a new grains configuration (a list)
'''
#spatial discretisation
x_min = dict_sample['x_box_min'] - 0.1*dict_geometry['R_mean']
x_max = dict_sample['x_box_max'] + 0.1*dict_geometry['R_mean']
x_L = np.linspace(x_min,x_max,dict_sample['nx'])
y_min = dict_sample['y_box_min'] - 0.1*dict_geometry['R_mean']
y_max = dict_sample['y_box_max'] + 0.1*dict_geometry['R_mean']
y_L = np.linspace(y_min,y_max,dict_sample['nx'])
#add element in dict
dict_sample['x_L'] = x_L
dict_sample['y_L'] = y_L
#-------------------------------------------------------------------------------
def Add_variables_needed(dict_geometry, dict_material, dict_sample, dict_sollicitation):
'''
Add some variables needed in the simulation.
3 arrays are generated to represent the mechanical, chemical and total energy.
The phase field interface width is computed.
The phase field energy barrier is computed.
The coefficient alpha applied to the merchanical energy term is computed.
Input :
a geometry dictionnary (a dict)
a material dictionnary (a dict)
a sample dictionnary (a dict)
a sollicitation dictionnary (a dict)
Output :
Nothing but dictionnaries get new variables
'''
#Arrays with only 0
dict_sample['Emec_M'] = np.array(np.zeros((len(dict_sample['y_L']),len(dict_sample['x_L']))))
dict_sample['Eche_M'] = np.array(np.zeros((len(dict_sample['y_L']),len(dict_sample['x_L']))))
dict_sample['Ed_M'] = np.array(np.zeros((len(dict_sample['y_L']),len(dict_sample['x_L']))))
#compute the phase field width interface
dict_material['w'] = math.sqrt((dict_sample['x_L'][4]-dict_sample['x_L'][0])**2+(dict_sample['y_L'][4]-dict_sample['y_L'][0])**2)
#Energy barrier of etai
dict_material['Energy_barrier'] = 20*dict_material['kappa_eta']/(dict_material['w'])**2
#Compute the coefficient applied to mechanical energy term
#this term is computed considering 2 disk grains under the sollicitation force
k = 4/3*dict_material['Y']/2/(1-dict_material['nu']**2)
overlap = (dict_sollicitation['Vertical_Confinement_Force']/k)**(2/3)
#g1
center_1 = np.array([np.mean(dict_sample['x_L'])-dict_geometry['R_mean']+overlap/2, np.mean(dict_sample['y_L'])])
L_r_1 = []
L_theta_R_1 = []
L_border_1 = []
L_border_x_1 = []
L_border_y_1 = []
for i in range(90):
theta = 2*math.pi*i/90
L_r_1.append(dict_geometry['R_mean'])
L_theta_R_1.append(theta)
L_border_1.append(np.array(center_1)+np.array([dict_geometry['R_mean']*math.cos(theta),dict_geometry['R_mean']*math.sin(theta)]))
L_border_x_1.append(center_1[0]+dict_geometry['R_mean']*math.cos(theta))
L_border_y_1.append(center_1[1]+dict_geometry['R_mean']*math.sin(theta))
L_border_1.append(L_border_1[0])
L_border_x_1.append(L_border_x_1[0])
L_border_y_1.append(L_border_y_1[0])
dict_ic_to_g1_tempo = {'Center' : center_1,'L_r' : L_r_1,'L_theta_r' : L_theta_R_1,'L_border' : L_border_1,'L_border_x' : L_border_x_1,'L_border_y' : L_border_y_1,
'Id' : None,'Y' : None,'Nu' : None,'Rho_surf' : None,'Surface' : None,'Mass' : None,'Inertia' : None}
g1_tempo = Grain.Grain(dict_ic_to_g1_tempo, dict_material, dict_sample)
#g2
center_2 = np.array([np.mean(dict_sample['x_L'])+dict_geometry['R_mean']-overlap/2, np.mean(dict_sample['y_L'])])
L_r_2 = []
L_theta_R_2 = []
L_border_2 = []
L_border_x_2 = []
L_border_y_2 = []
for i in range(90):
theta = 2*math.pi*i/90
L_r_2.append(dict_geometry['R_mean'])
L_theta_R_2.append(theta)
L_border_2.append(np.array(center_2)+np.array([dict_geometry['R_mean']*math.cos(theta),dict_geometry['R_mean']*math.sin(theta)]))
L_border_x_2.append(center_2[0]+dict_geometry['R_mean']*math.cos(theta))
L_border_y_2.append(center_2[1]+dict_geometry['R_mean']*math.sin(theta))
L_border_2.append(L_border_2[0])
L_border_x_2.append(L_border_x_2[0])
L_border_y_2.append(L_border_y_2[0])
dict_ic_to_g2_tempo = {'Center' : center_2,'L_r' : L_r_2,'L_theta_r' : L_theta_R_2,'L_border' : L_border_2,'L_border_x' : L_border_x_2,'L_border_y' : L_border_y_2,
'Id' : None,'Y' : None,'Nu' : None,'Rho_surf' : None,'Surface' : None,'Mass' : None,'Inertia' : None}
g2_tempo = Grain.Grain(dict_ic_to_g2_tempo, dict_material, dict_sample)
#compute the sum_min_etai
#extract a spatial zone
x_min = center_1[0]-dict_geometry['R_mean']-dict_material['w']
x_max = center_2[0]+dict_geometry['R_mean']+dict_material['w']
y_min = center_1[1]-dict_geometry['R_mean']-dict_material['w']
y_max = center_1[1]+dict_geometry['R_mean']+dict_material['w']
#look for this part inside the global mesh
#create search list
x_L_search_min = abs(np.array(dict_sample['x_L'])-x_min)
x_L_search_max = abs(np.array(dict_sample['x_L'])-x_max)
y_L_search_min = abs(np.array(dict_sample['y_L'])-y_min)
y_L_search_max = abs(np.array(dict_sample['y_L'])-y_max)
#get index
i_x_min = list(x_L_search_min).index(min(x_L_search_min))
i_x_max = list(x_L_search_max).index(min(x_L_search_max))
i_y_min = list(y_L_search_min).index(min(y_L_search_min))
i_y_max = list(y_L_search_max).index(min(y_L_search_max))
#Initialisation
sum_min_etai = 0
#compute the sum over the sample of the minimum of etai
for l in range(i_y_min, i_y_max):
for c in range(i_x_min, i_x_max):
sum_min_etai = sum_min_etai + min(g1_tempo.etai_M[-1-l][c],g2_tempo.etai_M[-1-l][c])
#Add element in dict
dict_sollicitation['alpha'] = 0.06*sum_min_etai
#-------------------------------------------------------------------------------
def Add_solute(dict_sample):
'''
Generate solute in the sample.
Input :
a sample dictionnary (a dictionnary)
Output :
Nothing but the sample dictionnary gets a new solute configuration (a n_y x n_x numpy array)
'''
#solute
solute_M = np.zeros((len(dict_sample['y_L']),len(dict_sample['x_L'])))
#add element in dict
dict_sample['solute_M'] = solute_M
#-------------------------------------------------------------------------------
def Criteria_StopSimulation(dict_algorithm):
'''
Define a stop criteria for the PFDEM simulation.
The simulation stops if the number of iterations reaches a maximum value.
Input :
an algorithm dictionnary (a dictionnary)
Output :
The result depends on the fact if the stop criteria is reached or not (a bool)
'''
Criteria_Verified = False
if dict_algorithm['i_PFDEM'] >= dict_algorithm['n_t_PFDEM']:
Criteria_Verified = True
return Criteria_Verified
Functions
def Add_mesh(dict_geometry, dict_sample)
-
Generate the mesh in the sample.
Input : a geometry dictionnary (a dict) a sample dictionnary (a dictionnary) Output : Nothing but the sample dictionnary gets a new grains configuration (a list)
Expand source code
def Add_mesh(dict_geometry, dict_sample): ''' Generate the mesh in the sample. Input : a geometry dictionnary (a dict) a sample dictionnary (a dictionnary) Output : Nothing but the sample dictionnary gets a new grains configuration (a list) ''' #spatial discretisation x_min = dict_sample['x_box_min'] - 0.1*dict_geometry['R_mean'] x_max = dict_sample['x_box_max'] + 0.1*dict_geometry['R_mean'] x_L = np.linspace(x_min,x_max,dict_sample['nx']) y_min = dict_sample['y_box_min'] - 0.1*dict_geometry['R_mean'] y_max = dict_sample['y_box_max'] + 0.1*dict_geometry['R_mean'] y_L = np.linspace(y_min,y_max,dict_sample['nx']) #add element in dict dict_sample['x_L'] = x_L dict_sample['y_L'] = y_L
def Add_solute(dict_sample)
-
Generate solute in the sample.
Input : a sample dictionnary (a dictionnary) Output : Nothing but the sample dictionnary gets a new solute configuration (a n_y x n_x numpy array)
Expand source code
def Add_solute(dict_sample): ''' Generate solute in the sample. Input : a sample dictionnary (a dictionnary) Output : Nothing but the sample dictionnary gets a new solute configuration (a n_y x n_x numpy array) ''' #solute solute_M = np.zeros((len(dict_sample['y_L']),len(dict_sample['x_L']))) #add element in dict dict_sample['solute_M'] = solute_M
def Add_variables_needed(dict_geometry, dict_material, dict_sample, dict_sollicitation)
-
Add some variables needed in the simulation.
3 arrays are generated to represent the mechanical, chemical and total energy. The phase field interface width is computed. The phase field energy barrier is computed. The coefficient alpha applied to the merchanical energy term is computed.
Input : a geometry dictionnary (a dict) a material dictionnary (a dict) a sample dictionnary (a dict) a sollicitation dictionnary (a dict) Output : Nothing but dictionnaries get new variables
Expand source code
def Add_variables_needed(dict_geometry, dict_material, dict_sample, dict_sollicitation): ''' Add some variables needed in the simulation. 3 arrays are generated to represent the mechanical, chemical and total energy. The phase field interface width is computed. The phase field energy barrier is computed. The coefficient alpha applied to the merchanical energy term is computed. Input : a geometry dictionnary (a dict) a material dictionnary (a dict) a sample dictionnary (a dict) a sollicitation dictionnary (a dict) Output : Nothing but dictionnaries get new variables ''' #Arrays with only 0 dict_sample['Emec_M'] = np.array(np.zeros((len(dict_sample['y_L']),len(dict_sample['x_L'])))) dict_sample['Eche_M'] = np.array(np.zeros((len(dict_sample['y_L']),len(dict_sample['x_L'])))) dict_sample['Ed_M'] = np.array(np.zeros((len(dict_sample['y_L']),len(dict_sample['x_L'])))) #compute the phase field width interface dict_material['w'] = math.sqrt((dict_sample['x_L'][4]-dict_sample['x_L'][0])**2+(dict_sample['y_L'][4]-dict_sample['y_L'][0])**2) #Energy barrier of etai dict_material['Energy_barrier'] = 20*dict_material['kappa_eta']/(dict_material['w'])**2 #Compute the coefficient applied to mechanical energy term #this term is computed considering 2 disk grains under the sollicitation force k = 4/3*dict_material['Y']/2/(1-dict_material['nu']**2) overlap = (dict_sollicitation['Vertical_Confinement_Force']/k)**(2/3) #g1 center_1 = np.array([np.mean(dict_sample['x_L'])-dict_geometry['R_mean']+overlap/2, np.mean(dict_sample['y_L'])]) L_r_1 = [] L_theta_R_1 = [] L_border_1 = [] L_border_x_1 = [] L_border_y_1 = [] for i in range(90): theta = 2*math.pi*i/90 L_r_1.append(dict_geometry['R_mean']) L_theta_R_1.append(theta) L_border_1.append(np.array(center_1)+np.array([dict_geometry['R_mean']*math.cos(theta),dict_geometry['R_mean']*math.sin(theta)])) L_border_x_1.append(center_1[0]+dict_geometry['R_mean']*math.cos(theta)) L_border_y_1.append(center_1[1]+dict_geometry['R_mean']*math.sin(theta)) L_border_1.append(L_border_1[0]) L_border_x_1.append(L_border_x_1[0]) L_border_y_1.append(L_border_y_1[0]) dict_ic_to_g1_tempo = {'Center' : center_1,'L_r' : L_r_1,'L_theta_r' : L_theta_R_1,'L_border' : L_border_1,'L_border_x' : L_border_x_1,'L_border_y' : L_border_y_1, 'Id' : None,'Y' : None,'Nu' : None,'Rho_surf' : None,'Surface' : None,'Mass' : None,'Inertia' : None} g1_tempo = Grain.Grain(dict_ic_to_g1_tempo, dict_material, dict_sample) #g2 center_2 = np.array([np.mean(dict_sample['x_L'])+dict_geometry['R_mean']-overlap/2, np.mean(dict_sample['y_L'])]) L_r_2 = [] L_theta_R_2 = [] L_border_2 = [] L_border_x_2 = [] L_border_y_2 = [] for i in range(90): theta = 2*math.pi*i/90 L_r_2.append(dict_geometry['R_mean']) L_theta_R_2.append(theta) L_border_2.append(np.array(center_2)+np.array([dict_geometry['R_mean']*math.cos(theta),dict_geometry['R_mean']*math.sin(theta)])) L_border_x_2.append(center_2[0]+dict_geometry['R_mean']*math.cos(theta)) L_border_y_2.append(center_2[1]+dict_geometry['R_mean']*math.sin(theta)) L_border_2.append(L_border_2[0]) L_border_x_2.append(L_border_x_2[0]) L_border_y_2.append(L_border_y_2[0]) dict_ic_to_g2_tempo = {'Center' : center_2,'L_r' : L_r_2,'L_theta_r' : L_theta_R_2,'L_border' : L_border_2,'L_border_x' : L_border_x_2,'L_border_y' : L_border_y_2, 'Id' : None,'Y' : None,'Nu' : None,'Rho_surf' : None,'Surface' : None,'Mass' : None,'Inertia' : None} g2_tempo = Grain.Grain(dict_ic_to_g2_tempo, dict_material, dict_sample) #compute the sum_min_etai #extract a spatial zone x_min = center_1[0]-dict_geometry['R_mean']-dict_material['w'] x_max = center_2[0]+dict_geometry['R_mean']+dict_material['w'] y_min = center_1[1]-dict_geometry['R_mean']-dict_material['w'] y_max = center_1[1]+dict_geometry['R_mean']+dict_material['w'] #look for this part inside the global mesh #create search list x_L_search_min = abs(np.array(dict_sample['x_L'])-x_min) x_L_search_max = abs(np.array(dict_sample['x_L'])-x_max) y_L_search_min = abs(np.array(dict_sample['y_L'])-y_min) y_L_search_max = abs(np.array(dict_sample['y_L'])-y_max) #get index i_x_min = list(x_L_search_min).index(min(x_L_search_min)) i_x_max = list(x_L_search_max).index(min(x_L_search_max)) i_y_min = list(y_L_search_min).index(min(y_L_search_min)) i_y_max = list(y_L_search_max).index(min(y_L_search_max)) #Initialisation sum_min_etai = 0 #compute the sum over the sample of the minimum of etai for l in range(i_y_min, i_y_max): for c in range(i_x_min, i_x_max): sum_min_etai = sum_min_etai + min(g1_tempo.etai_M[-1-l][c],g2_tempo.etai_M[-1-l][c]) #Add element in dict dict_sollicitation['alpha'] = 0.06*sum_min_etai
def All_parameters()
-
This function is called in main.py to have all the parameters needed in the simulation.
Input : Nothing Output : an algorithm dictionnary (a dictionnary) a material dictionnary (a dictionnary) a sample dictionnary (a dictionnary) a sollicitation dictionnary (a dictionnary)
Expand source code
def All_parameters(): ''' This function is called in main.py to have all the parameters needed in the simulation. Input : Nothing Output : an algorithm dictionnary (a dictionnary) a material dictionnary (a dictionnary) a sample dictionnary (a dictionnary) a sollicitation dictionnary (a dictionnary) ''' #--------------------------------------------------------------------------- #Geometry parameters N_grain = 40 #total number of grains R0 = 350 #µm radius to compute the grain distribution L_R = [1.2*R0,1.1*R0,0.9*R0,0.8*R0] #from larger to smaller L_percentage_R = [1/6,1/3,1/3,1/6] #distribution of the different radius #Recompute the mean radius R_mean = 0 for i in range(len(L_R)): R_mean = R_mean + L_R[i]*L_percentage_R[i] #write dict dict_geometry = { 'R_mean' : R_mean, 'L_R' : L_R, 'L_percentage_R' : L_percentage_R, 'N_grain' : N_grain } #--------------------------------------------------------------------------- #Sample parameters #Box définition x_box_min = 0 #µm x_box_max = 2*R_mean*math.sqrt(N_grain*0.6) #µm y_box_min = 0 #µm #spatial discretisation nx = int(60*math.sqrt(N_grain*0.6)) #approx n nodes per grain with a mean radius ny = int(0.6*nx) #approximatively the number of vertices for one grain during DEM simulation grain_discretisation = 40 dict_sample = { 'nx' : nx, 'ny' : ny, 'grain_discretisation' : grain_discretisation, 'x_box_min' : x_box_min, 'x_box_max' : x_box_max, 'y_box_min' : y_box_min } #--------------------------------------------------------------------------- #Material parameters #phase field Mobility = 1 #L1, L2 in .i #Diffusion of etai kappa_eta = 0.01 #Diffusion of c, the solute generated by the dissolution kappa_c = 50 #Definition of the evolution of the penalty term inside a grain (for interpolation) tau_kappa_c = 5 #kc = kc0 e(-(R_i-d)/R_i/tau_kappa_c) #DEM Y = 70*(10**9)*(10**6)*(10**(-12)) #Young Modulus µN/µm2 nu = 0.3 #Poisson's ratio rho = 2500*10**(-6*3) #density kg/µm3 rho_surf = 4/3*rho*R_mean #kg/µm2 mu_friction_gg = 0.5 #grain-grain mu_friction_gw = 0 #grain-wall coeff_restitution = 0.2 #1 is perfect elastic dict_material = { 'M' : Mobility, 'kappa_eta' : kappa_eta, 'kappa_c' : kappa_c, 'tau_kappa_c' : tau_kappa_c, 'Y' : Y, 'nu' : nu, 'rho' : rho, 'rho_surf' : rho_surf, 'mu_friction_gg' : mu_friction_gg, 'mu_friction_gw' : mu_friction_gw, 'coeff_restitution' : coeff_restitution } #--------------------------------------------------------------------------- #Algorithm parameters np_proc = 4 #number of processor used n_t_PFDEM = 50 #number of cycle PF-DEM #Time step for phase field n_t_PF = 8 dt_PF_init = 0.05 dt_PF_level1 = dt_PF_init/2 dt_PF_level2 = dt_PF_level1/2 dt_PF_level3 = dt_PF_level2/2 #criteria to switch level Ed_level1 = 10 Ed_level2 = 20 Ed_level3 = 25 #PF parameters factor_etai = 1.7 #factor reltaed to the minimal distance between grains with same eta #DEM parameters dt_DEM_crit = math.pi*min(L_R)/(0.16*nu+0.88)*math.sqrt(rho*(2+2*nu)/Y) #s critical time step from O'Sullivan 2011 dt_DEM = dt_DEM_crit/7 #s time step during DEM simulation factor_neighborhood = 1.5 #margin to detect a grain into a neighborhood i_update_neighborhoods = 100 #the frequency of the update of the neighborhood of the grains and the walls #Stop criteria of the DEM i_DEM_stop = 5000 #maximum iteration for one DEM simulation Ecin_ratio = 0.0001 n_window_stop = 100 dy_box_max_stop = 35 #Margin for sphericity study sphericity_margin = 0.05 #Discretisation to find the inscribing (number of nodes in one direction) n_spatial_inscribing = 100 #List of plot to do Debug = True #plot configuration before and after DEM simulation Debug_DEM = False #plot configuration inside DEM i_print_plot = 100 #frenquency of the print and plot (if Debug_DEM) in DEM step # Config, DEM_tracker, DEM_txt, Diff_Solute, dt, Ed, Etai_distribution, Eta_c, Init_Current_Shape, Kc, Movie (need Config to work), Mesh, Porosity, Sphericity, sum_Ed, YBoxMax L_flag_plot = ['Config', 'DEM_txt', 'Kc', 'DEM_tracker', 'Sphericity', 'Porosity', 'YBoxMax'] #Visual parameters (for plot Config) c_min = 0 c_max = 0.1 #structural matrix to build diffusion map and available node map struct_element = np.array(np.ones((6,6)), dtype = bool) #Save the simulation SaveData = True #Save data or not clean_memory = True #delete Data, Input, Output at the end of the simulation foldername = 'Data_MG_ACS' #name of the folder where data are saved template = 'PS_MG' #template of the name of the simulation if SaveData : i_run = 1 folderpath = Path('../'+foldername+'/'+template+'_'+str(i_run)) while folderpath.exists(): i_run = i_run + 1 folderpath = Path('../'+foldername+'/'+template+'_'+str(i_run)) namefile = template+'_'+str(i_run) else : namefile = template dict_algorithm = { 'c_min' : c_min, 'c_max' : c_max, 'sphericity_margin' : sphericity_margin, 'n_spatial_inscribing' : n_spatial_inscribing, 'np_proc' : np_proc, 'Debug' : Debug, 'Debug_DEM' : Debug_DEM, 'i_print_plot' : i_print_plot, 'factor_neighborhood' : factor_neighborhood, 'factor_etai': factor_etai, 'clean_memory' : clean_memory, 'SaveData' : SaveData, 'namefile' : namefile, 'dt_PF' : dt_PF_init, 'dt_PF_init' : dt_PF_init, 'dt_PF_level1' : dt_PF_level1, 'dt_PF_level2' : dt_PF_level2, 'dt_PF_level3' : dt_PF_level3, 'Ed_level1' : Ed_level1, 'Ed_level2' : Ed_level2, 'Ed_level3' : Ed_level3, 'n_t_PF' : n_t_PF, 'dt_DEM' : dt_DEM, 'i_update_neighborhoods': i_update_neighborhoods, 'i_DEM_stop' : i_DEM_stop, 'Ecin_ratio' : Ecin_ratio, 'n_window_stop' : n_window_stop, 'dy_box_max_stop' : dy_box_max_stop, 'foldername' : foldername, 'n_t_PFDEM' : n_t_PFDEM, 'L_flag_plot' : L_flag_plot, 'struct_element' : struct_element } #--------------------------------------------------------------------------- #External sollicitation parameters chi = 0.5 #coefficient applied to the chemical energy gravity = 0 Vertical_Confinement_Linear_Force = Y*2*R_mean/1000 #µN/µm used to compute the Vertical_Confinement_Force Vertical_Confinement_Force = Vertical_Confinement_Linear_Force*(x_box_max-x_box_min) #µN contact_gw_for_Emec = False #consider the contact grain - wall to compute Emec dict_sollicitation = { 'chi' : chi, 'gravity' : gravity, 'contact_gw_for_Emec' : contact_gw_for_Emec, 'Vertical_Confinement_Force' : Vertical_Confinement_Force } #--------------------------------------------------------------------------- #Initial condition parameters n_generation = 1 #number of grains generation factor_ymax_box = 1.6 #margin to generate grains N_test_max = 5000 # maximum number of tries to generate a grain without overlap i_DEM_stop_IC = 3000 #stop criteria for DEM during IC Debug_DEM_IC = False #plot configuration inside DEM during IC i_print_plot_IC = 200 #frenquency of the print and plot (if Debug_DEM_IC) for IC dt_DEM_IC = dt_DEM_crit/5 #s time step during IC Ecin_ratio_IC = 0.0005 factor_neighborhood_IC = 1.5 #margin to detect a grain into a neighborhood i_update_neighborhoods_gen = 5 #the frequency of the update of the neighborhood of the grains and the walls during IC generations i_update_neighborhoods_com = 100 #the frequency of the update of the neighborhood of the grains and the walls during IC combination #write dict dict_ic = { 'n_generation' : n_generation, 'i_update_neighborhoods_gen': i_update_neighborhoods_gen, 'i_update_neighborhoods_com': i_update_neighborhoods_com, 'factor_ymax_box' : factor_ymax_box, 'i_DEM_stop_IC' : i_DEM_stop_IC, 'Debug_DEM' : Debug_DEM_IC, 'dt_DEM_IC' : dt_DEM_IC, 'Ecin_ratio_IC' : Ecin_ratio_IC, 'i_print_plot_IC' : i_print_plot_IC, 'factor_neighborhood_IC' : factor_neighborhood_IC, 'N_test_max' : N_test_max } #--------------------------------------------------------------------------- return dict_algorithm, dict_geometry, dict_ic, dict_material, dict_sample, dict_sollicitation
def Criteria_StopSimulation(dict_algorithm)
-
Define a stop criteria for the PFDEM simulation.
The simulation stops if the number of iterations reaches a maximum value.
Input : an algorithm dictionnary (a dictionnary) Output : The result depends on the fact if the stop criteria is reached or not (a bool)
Expand source code
def Criteria_StopSimulation(dict_algorithm): ''' Define a stop criteria for the PFDEM simulation. The simulation stops if the number of iterations reaches a maximum value. Input : an algorithm dictionnary (a dictionnary) Output : The result depends on the fact if the stop criteria is reached or not (a bool) ''' Criteria_Verified = False if dict_algorithm['i_PFDEM'] >= dict_algorithm['n_t_PFDEM']: Criteria_Verified = True return Criteria_Verified