yade-dev team mailing list archive
-
yade-dev team
-
Mailing list archive
-
Message #12781
[Branch ~yade-pkg/yade/git-trunk] Rev 3919: Add two example scripts for the use of HydroForceEngine
------------------------------------------------------------
revno: 3919
committer: Raphael Maurin <raph_maurin@xxxxxxxxxxx>
timestamp: Sat 2016-07-09 00:21:49 +0200
message:
Add two example scripts for the use of HydroForceEngine
One simple example to get familiar with the application of buoyancy (buoyantParticles.py).
One example simulating a fluidized bed configuration to get familiar with both the application of a fluid velocity profile and of turbulent fluctuation with the DRW models (fluidizedBed.py)
added:
examples/HydroForceEngine/buoyantParticles.py
examples/HydroForceEngine/fluidizedBed.py
--
lp:yade
https://code.launchpad.net/~yade-pkg/yade/git-trunk
Your team Yade developers is subscribed to branch lp:yade.
To unsubscribe from this branch go to https://code.launchpad.net/~yade-pkg/yade/git-trunk/+edit-subscription
=== added file 'examples/HydroForceEngine/buoyantParticles.py'
--- examples/HydroForceEngine/buoyantParticles.py 1970-01-01 00:00:00 +0000
+++ examples/HydroForceEngine/buoyantParticles.py 2016-07-08 22:21:49 +0000
@@ -0,0 +1,104 @@
+#########################################################################################################################################################################
+# Author: Raphael Maurin, raphael.maurin@xxxxxxx
+# 07/07/2016
+#
+# Example script to use HydroForceEngine in order to apply buoyancy force to particles.
+# The fluid is supposed at rest (vxFluidPY is a zero vector) so that the particles are only submitted to a drag force opposing the motion of the particle.
+# Three spheres with density 1500, 1000 and 500kg/m3 are positionned at the middle of a fluid sample of density 1000 kg/m3, and let evolved with time
+# We observe clearly that one sphere sediment down to the bottom, another one is rising to the top of the water free-surface and the third one does not move
+#
+############################################################################################################################################################################
+
+#Import libraries
+from yade import pack, plot
+import math
+import random as rand
+import numpy as np
+
+
+##
+## Main parameters of the simulation
+##
+
+#Particles
+diameterPart = 6e-3 #Diameter of the particles, in meter
+restitCoef = 0.5 #Restitution coefficient of the particles
+partFrictAngle = atan(0.4) #friction angle of the particles, in radian
+densPart1 = 1050 #density of the particles, in kg/m3
+densPart2 = 1000 #density of the particles, in kg/m3
+densPart3 = 950 #density of the particles, in kg/m3
+
+#fluid
+densFluidPY = 1000. #Density of the fluid
+kinematicViscoFluid = 1e-6 #kinematic viscosity of the fluid
+fluidHeight = 20.*diameterPart #Water depth in m.
+ndimz = 1
+groundPosition = 0.#Definition of the position of the ground, in m
+gravityVector = Vector3(0,0.0,-9.81) #Gravity vector
+
+#Particles contact law/material parameters
+normalStiffness = 1e4
+youngMod = normalStiffness/diameterPart #Young modulus of the particles from the stiffness wanted.
+poissonRatio = 0.5 #poisson's ratio of the particles. Classical values, does not have much influence
+
+#Material of particle 1, 2, and 3, with different density densPart1, densPart2 and densPart3 defined above (1500, 1000 and 500kg/m3 by default)
+O.materials.append(ViscElMat(en=restitCoef, et=0., young=youngMod, poisson=poissonRatio, density=densPart1, frictionAngle=partFrictAngle, label='Mat1'))
+O.materials.append(ViscElMat(en=restitCoef, et=0., young=youngMod, poisson=poissonRatio, density=densPart2, frictionAngle=partFrictAngle, label='Mat2'))
+O.materials.append(ViscElMat(en=restitCoef, et=0., young=youngMod, poisson=poissonRatio, density=densPart3, frictionAngle=partFrictAngle, label='Mat3'))
+
+#Time of simulation
+endTime = 2.
+
+########################
+## FRAMEWORK CREATION ##
+########################
+
+# Reference walls: build a wall at the ground and draw the position of the free-surface to have a reference for the eyes in the 3D view
+lowPlane = box(center= (0, 0,groundPosition),extents=(200,200,0),fixed=True,wire=False,color = (0.,1.,0.))
+WaterSurface = box(center= (0,0,groundPosition+fluidHeight),extents=(200,200,0),fixed=True,wire=False,color = (0,0,1),mask = 0)
+O.bodies.append([lowPlane,WaterSurface]) #add to simulation
+
+id1 = O.bodies.append(sphere(center = (0,2*diameterPart,groundPosition + fluidHeight/2.), radius = diameterPart/2.,material = 'Mat1'))
+id2 = O.bodies.append(sphere(center = (0,0,groundPosition + fluidHeight/2.), radius = diameterPart/2.,material = 'Mat2'))
+id3 = O.bodies.append(sphere(center = (0,-2*diameterPart,groundPosition + fluidHeight/2.), radius = diameterPart/2.,material = 'Mat3'))
+
+# Collect the ids of the spheres which are dynamic to add a fluid force through HydroForceEngines
+idApplyForce = [id1,id2,id3]
+
+
+#########################
+#### SIMULATION LOOP#####
+#########################
+
+O.engines = [
+ # Reset the forces
+ ForceResetter(),
+ # Detect the potential contacts
+ InsertionSortCollider([Bo1_Sphere_Aabb(), Bo1_Wall_Aabb(),Bo1_Facet_Aabb(),Bo1_Box_Aabb()],label='contactDetection',allowBiggerThanPeriod = True),
+ # Calculate the different interactions
+ InteractionLoop(
+ [Ig2_Sphere_Sphere_ScGeom(), Ig2_Box_Sphere_ScGeom()],
+ [Ip2_ViscElMat_ViscElMat_ViscElPhys()],
+ [Law2_ScGeom_ViscElPhys_Basic()]
+ ,label = 'interactionLoop'),
+ #Apply an hydrodynamic force to the particles
+ HydroForceEngine(densFluid = densFluidPY,viscoDyn = kinematicViscoFluid*densFluidPY,zRef = groundPosition,gravity = gravityVector,deltaZ = fluidHeight/ndimz,expoRZ = 0.,lift = False,nCell = ndimz,vCell = 1.,vxFluid = np.zeros(ndimz),phiPart = np.zeros(ndimz),vxPart = np.zeros(ndimz),vFluctX = np.zeros(len(O.bodies)),vFluctY = np.zeros(len(O.bodies)),vFluctZ = np.zeros(len(O.bodies)),ids = idApplyForce, label = 'hydroEngine'),
+ #To plot the wall normal position of the spheres with time
+ PyRunner(command = 'plotPos()', virtPeriod = 0.01, label = 'plot'),
+ # Integrate the equation and calculate the new position/velocities...
+ NewtonIntegrator(gravity=gravityVector, label='newtonIntegr')
+ ]
+#save the initial configuration to be able to recharge the simulation starting configuration easily
+O.saveTmp()
+#Time step
+O.dt = 5e-7 #Low no purpose, in order to observe the sedimentation
+
+#Plot the wall normal position of the spheres with time
+def plotPos():
+ plot.addData(z1 = O.bodies[2].state.pos[2]/fluidHeight,z2 = O.bodies[3].state.pos[2]/fluidHeight,z3 = O.bodies[4].state.pos[2]/fluidHeight, time = O.time)
+ if O.time>endTime:
+ print('\nEnd of the simulation, {0}s simulated as asked!\n'.format(endTime))
+ O.pause()
+
+plot.plots={'time':('z1','z2','z3')}
+plot.plot()
=== added file 'examples/HydroForceEngine/fluidizedBed.py'
--- examples/HydroForceEngine/fluidizedBed.py 1970-01-01 00:00:00 +0000
+++ examples/HydroForceEngine/fluidizedBed.py 2016-07-08 22:21:49 +0000
@@ -0,0 +1,172 @@
+#########################################################################################################################################################################
+# Author: Raphael Maurin, raphael.maurin@xxxxxxx
+# 08/07/2016
+#
+# Very simplified fluidized bed simulations in order to underline the possibility of HydroForceEngine.
+# Particles are deposited under gravity inside a box. Once the particles at rest, a constant fluid velocity is applied against gravity, submitting the
+# particles to a constant drag force. Then, a discrete random walk model is applied to mimick the effect of the turbulent fluid velocity fluctuations.
+# It associates to each particle a random fluid velocity fluctuations in the x, y and z directions, which are taken into account in the evaluation
+# of the drag applied by the fluid on the particle. The intensity of the fluctuation is based on the value of u*, which is imposed through simplifiedReynoldsStress = u*^2
+# The values taken for the fluid velocity and simplifiedReynolds stress have been arbitrarily chosen to have a nice rendering
+#
+# The example allows to get familiar with HydroForceEngine and in particular with the included DRW model functions (turbulentFluctuationFluidizedBed() here)
+# For details on the process, it is necessary to have a look to the documentation and the C++ code in pkg/common/ForceEngine.cpp and hpp as HydroForceEngine contains
+# multiple parameters
+############################################################################################################################################################################
+
+# ATTENTION: to fit the formulation of HydroForceEngine, the fluid velocity can only be applied along the x axis. Therefore, the gravity is here aligned with x, and all the
+# configuration is defined accordingly. For the 3D visualization, two walls of the cell have been made transparent and clicking on the right xyz button after openning the
+# 3D view allows one to see the sample in the usual way with gravity going from top to bottom.
+
+
+#Import libraries
+from yade import pack, plot
+import math
+import random as rand
+import numpy as np
+
+
+##
+## Main parameters of the simulation
+##
+
+#Particles
+diameterPart = 6e-3 #Diameter of the particles, in meter
+densPart = 2500 #density of the particles, in kg/m3
+restitCoef = 0.8 #Restitution coefficient of the particles
+partFrictAngle = atan(0.4) #friction angle of the particles, in radian
+
+#fluid
+densFluidPY = 1.225 #Density of the fluid, (air) in kg/m3
+kinematicViscoFluid = 1.48e-5 #kinematic viscosity of the fluid, (air) in m2/s
+
+#Configuration: inclined channel
+lengthCell = 100 #length cell along the gravity axis (x), in diameter
+widthCell = 10 #length cell along the two other axis, in diameter
+Nlayer = 2.5 #nb of layer of particle deposited, in diameter
+phiPartMax = 0.61 #Value of the dense packing solid volume fraction
+
+endTime = 10 #Time simulated (in seconds)
+
+
+##
+## Secondary parameters of the simulation
+##
+
+expoDrag_PY = 3.1 # Richardson Zaki exponent for the hindrance function of the drag force applied to the particles
+ndimz = 20 #Number of cells in the height
+dz = widthCell*diameterPart/ndimz # Fluid discretization step in the wall-normal direction
+
+# Initialization of the main vectors
+vxFluidPY = np.ones(ndimz)*18.5 # Vertical fluid velocity profile: u^f = u_x^f(z) e_x, with x the streamwise direction and z the wall-normal
+
+phiPartPY = np.zeros(ndimz) # Vertical particle volume fraction profile
+vxPartPY = np.zeros(ndimz) # Vertical average particle velocity profile
+
+#Geometrical configuration, define useful quantities
+length = lengthCell*diameterPart #length of the stream, in m
+width = widthCell*diameterPart #width of the stream, in m
+groundPosition = 0. #Definition of the position of the ground, in m
+gravityVector = Vector3(-9.81,0.0,0.) #Gravity vector. Inclined along x to have an effect opposed to the fluid flow (which can only be along x)
+
+#Particles contact law/material parameters
+maxPressure = (densPart-densFluidPY)*phiPartMax*Nlayer*diameterPart*9.81#Estimated max particle pressure from the static load
+normalStiffness = maxPressure*diameterPart*1e4 #Evaluate the minimal normal stiffness to be in the rigid particle limit (cf Roux and Combe 2002)
+youngMod = normalStiffness/diameterPart #Young modulus of the particles from the stiffness wanted.
+poissonRatio = 0.5 #poisson's ratio of the particles. Classical values, does not have much influence
+O.materials.append(ViscElMat(en=restitCoef, et=0., young=youngMod, poisson=poissonRatio, density=densPart, frictionAngle=partFrictAngle, label='Mat'))
+
+
+########################
+## FRAMEWORK CREATION ##
+########################
+
+# Walls to create a box
+lowPlane = box(center= (groundPosition, width/2.0,width/2.),extents=(0,width/2.,width/2.),fixed=True,wire=False,color = (0.,1.,0.),material = 'Mat')
+sidePlane1 = box(center= (length/2., width,width/2.),extents=(length/2.,0.,width/2.),fixed=True,wire=True,color = (0.,1.,0.),material = 'Mat')
+sidePlane2 = box(center= (length/2., 0.,width/2.),extents=(length/2.,0.,width/2.),fixed=True,wire=True,color = (0.,1.,0.),material = 'Mat')
+sidePlane3 = box(center= (length/2.,width/2., 0.),extents=(length/2.,width/2.,0.),fixed=True,wire=False,color = (0.,1.,0.),material = 'Mat') #Made invisible (wire = True) in order to see inside the cell
+sidePlane4 = box(center= (length/2.,width/2., width),extents=(length/2.,width/2.,0.),fixed=True,wire=False,color = (0.,1.,0.),material = 'Mat') #Made invisible (wire = True) in order to see inside the cell
+O.bodies.append([lowPlane,sidePlane1,sidePlane2,sidePlane3,sidePlane4])
+
+#Create a loose cloud of particle inside the cell
+partCloud = pack.SpherePack()
+partVolume = pi/6.*pow(diameterPart,3) #Volume of a particle
+partNumber = int(Nlayer*phiPartMax*diameterPart*width*width/partVolume) #Volume of beads to obtain Nlayer layers of particles
+partCloud.makeCloud(minCorner=(0,0.,0),maxCorner=(length,width,width),rRelFuzz=0., rMean=diameterPart/2.0, num = partNumber)
+partCloud.toSimulation(material='Mat') #Send this packing to simulation with material Mat
+#Evaluate the deposition time considering the free-fall time of the highest particle to the ground
+depoTime = sqrt(length*2/9.31)
+
+# Collect the ids of the spheres which are dynamic to add a fluid force through HydroForceEngines
+idApplyForce = []
+for b in O.bodies:
+ if isinstance(b.shape,Sphere) and b.dynamic:
+ idApplyForce+=[b.id]
+
+
+#########################
+#### SIMULATION LOOP#####
+#########################
+
+O.engines = [
+ # Reset the forces
+ ForceResetter(),
+ # Detect the potential contacts
+ InsertionSortCollider([Bo1_Sphere_Aabb(), Bo1_Wall_Aabb(),Bo1_Facet_Aabb(),Bo1_Box_Aabb()],label='contactDetection',allowBiggerThanPeriod = True),
+ # Calculate the different interactions
+ InteractionLoop(
+ [Ig2_Sphere_Sphere_ScGeom(), Ig2_Box_Sphere_ScGeom()],
+ [Ip2_ViscElMat_ViscElMat_ViscElPhys()],
+ [Law2_ScGeom_ViscElPhys_Basic()]
+ ,label = 'interactionLoop'),
+ #Apply an hydrodynamic force to the particles
+ HydroForceEngine(densFluid = densFluidPY,viscoDyn = kinematicViscoFluid*densFluidPY,zRef = groundPosition,gravity = gravityVector,deltaZ = dz,expoRZ = expoDrag_PY,lift = False,nCell = ndimz,vCell = length*width*dz ,vxFluid = vxFluidPY,phiPart = phiPartPY,vxPart = vxPartPY,ids = idApplyForce,vFluctX = np.zeros(len(O.bodies)),vFluctY = np.zeros(len(O.bodies)),vFluctZ = np.zeros(len(O.bodies)), label = 'hydroEngine', dead = True),
+ #Measurement, output files
+ PyRunner(command = 'measure()', virtPeriod = 0.1, label = 'measurement', dead = True),
+ # Check if the packing is stabilized, if yes activate the hydro force on the grains and the slope.
+ PyRunner(command='gravityDeposition(depoTime)',virtPeriod = 0.01,label = 'gravDepo'),
+ #Apply fluid turbulent fluctuations from a discrete random walk model
+ PyRunner(command='turbulentFluctuations()',virtPeriod = 0.01,label = 'turbFluct'),
+ #GlobalStiffnessTimeStepper, determine the time step
+ GlobalStiffnessTimeStepper(defaultDt = 1e-4, viscEl = True,timestepSafetyCoefficient = 0.7, label = 'GSTS'),
+ # Integrate the equation and calculate the new position/velocities...
+ NewtonIntegrator(damping=0.2, gravity=gravityVector, label='newtonIntegr')
+ ]
+#save the initial configuration to be able to recharge the simulation starting configuration easily
+O.saveTmp()
+#run
+#O.run()
+#####################################################################################################################################
+##################################################### FUNCTION DEFINITION #########################################################
+#####################################################################################################################################
+
+
+
+###### ######
+### LET THE TIME FOR THE GRAVITY DEPOSITION AND ACTIVATE THE FLUID AT THE END ###
+###### ######
+def gravityDeposition(lim):
+ if O.time<lim : return
+ else :
+ print('\n Gravity deposition finished, apply fluid forces !\n')
+ newtonIntegr.damping = 0.0 # Set the artificial numerical damping to zero
+ gravDepo.dead = True # Remove the present engine for the following
+ hydroEngine.dead = False # Activate the HydroForceEngine
+ turbFluct.dead = False # Activate the turbulent fluctuations model
+ return
+###############
+#########################################
+
+
+###### ######
+### APPLY TURBULENT FLUID VELOCITY FLUCTUATIONS FROM A DISCRETE RANDOM WALK MODEL ###
+# Associate a random fluctuation to each particles from the value of the Reynolds #
+# stresses Rxz imposed in simplifiedReynoldsStress = Rxz/densFluid #
+#Details in the C++ code: function turbulentFluctuationsFluidizedBed in ForceEngine.cpp #
+###### ######
+hydroEngine.simplifiedReynoldStresses = np.ones(ndimz)*4.
+def turbulentFluctuations():
+ hydroEngine.turbulentFluctuationFluidizedBed()
+
+