Swarms ====== In Underworld, the swarm is an object that defines a collection of particles. Swarms are usually used to track the Lagrangian quantities required for a given model, such as a material type identifier, or the plastic strain of an advecting parcel of fluid. Swarm may be used passively to record information as they advect, or actively where the values recorded on particles actually feed into rheologies or forces. Swarms of particles may: 1. Advect through the mesh according to a user specified velocity. 2. Store arbitrary data on a per-particle basis. 3. Freely cross process boundaries in parallel simulations. The user is free to create as many swarms as required and each swarm may contain an arbitrary number of particles. The *data layout* for any given swarm is identical across all its particles, though different swarms may have different layouts. For example, *SwarmA* may contain 100 particles, and each particle may encode an ``int`` and a ``float``, while *SwarmB* may contain 15 particles, each particle encoding three ``float`` values. Particles may also be added to a swarm at any stage either directly or through population control mechanisms. It is also possible to delete particles, though currently this is only possible through indirect means. Overview ^^^^^^^^ 1. Creating a swarm object and adding particles. 2. Moving particles. 3. Swarm variables. 4. Shapes with particle swarms. 5. Saving and loading swarms. **Keywords:** swarms, particles, shapes. Creating a swarm object and adding particles -------------------------------------------- Creating a swarm is very simple, but you will first require a mesh. The mesh will inform the swarm of your model geometry. In particular, your model domain is *generally* determined by the mesh, and particles may be deleted if they leave the mesh. For parallel simulations, the mesh also determines the problem partitioning across multiple processes, and therefore the *local* process domain. Note that your newly created swarm will be empty! It is just a container for particles, and you will need to explicitly add particles. To add particles, you will either use a *layout* object, or generate a numpy array with the required particle coordinates. .. raw:: html
import underworld as uw
import underworld.visualisation as vis
import numpy as np
mesh = uw.mesh.FeMesh_Cartesian(maxCoord=(2.,1.))
# create a mesh!
swarm = uw.swarm.Swarm( mesh=mesh )
# now let's add particles. first create a layout object.
swarmLayout = uw.swarm.layouts.PerCellSpaceFillerLayout( swarm=swarm, particlesPerCell=20 )
# now populate using layout.
swarm.populate_using_layout( layout=swarmLayout )
# vis
fig = vis.Figure(figsize=(800,400))
fig.append( vis.objects.Points(swarm=swarm, pointSize=5, colourBar=False) )
fig.append( vis.objects.Mesh(mesh) )
fig.show()
.. raw:: html
import underworld as uw
import underworld.visualisation as vis
import numpy as np
mesh = uw.mesh.FeMesh_Cartesian(maxCoord=(2.,1.))
swarmCustom = uw.swarm.Swarm( mesh=mesh, particleEscape=True )
# create the array
swarmCoords = np.array([ [0.4,0.2], [0.8,0.4],[1.2,0.6],[1.6,0.8],[3.6,1.8]])
# use the array to add particles at the specified coordinates.
result = swarmCustom.add_particles_with_coordinates(swarmCoords)
print("Returned array: {}.".format(result))
fig = vis.Figure(figsize=(800,400))
fig.append( vis.objects.Points(swarm=swarmCustom, pointSize=10, colourBar=False) )
fig.append( vis.objects.Mesh(mesh))
fig.show()
.. parsed-literal::
Returned array: [ 0 1 2 3 -1].
.. raw:: html
# note that this cell requires the previous cell to be executed first.
vel = mesh.add_variable(2)
vel.data[:] = (1.,0.)
advector = uw.systems.SwarmAdvector(vel,swarmCustom)
dt = advector.get_max_dt()
advector.integrate(dt)
fig.show()
.. raw:: html
# note that this cell requires the previous cell to be executed first.
with swarmCustom.deform_swarm():
swarmCustom.data[1] = (0.4,0.5)
fig.show()
.. raw:: html
# note that this cell requires the previous cell to be executed first.
with swarmCustom.deform_swarm():
swarmCustom.data[1] = (9999,9999.)
fig.show()
.. raw:: html
import underworld as uw
import underworld.visualisation as vis
import numpy as np
mesh = uw.mesh.FeMesh_Cartesian(maxCoord=(2.,1.))
swarmCustom = uw.swarm.Swarm( mesh=mesh, particleEscape=True )
swarmCoords = np.array([ [0.4,0.2], [0.8,0.4],[1.2,0.6],[1.6,0.8],[3.6,1.8]])
result = swarmCustom.add_particles_with_coordinates(swarmCoords)
swarmVariable = swarmCustom.add_variable(dataType='double', count=1)
swarmVariable.data[0] = 1.
swarmVariable.data[1] = 10.
swarmVariable.data[2] = 100.
swarmVariable.data[3] = 1000.
fig = vis.Figure(figsize=(800,400))
fig.append( vis.objects.Points( swarm=swarmCustom, pointSize=20,
fn_colour=swarmVariable, colourBar = True,
colours="red green blue", logScale=True) )
fig.append( vis.objects.Mesh(mesh, opacity=0.25))
fig.show()
.. raw:: html
import underworld as uw
import underworld.visualisation as vis
import numpy as np
mesh = uw.mesh.FeMesh_Cartesian( elementRes = (64, 64),
maxCoord = (2., 1.) )
swarm = uw.swarm.Swarm( mesh=mesh )
# add a data variable which will store an index to determine material
materialIndex = swarm.add_variable( dataType="int", count=1 )
# populate our swarm across the mesh domain
swarmLayout = uw.swarm.layouts.PerCellSpaceFillerLayout( swarm=swarm, particlesPerCell=20 )
swarm.populate_using_layout( layout=swarmLayout )
materialIndex.data[:] = 0
# our circles parameters
circleRadius = 0.1
circleCentre = (1., 0.5)
# the particle loop
for index, coord in enumerate(swarm.particleCoordinates.data):
x = coord[0]
z = coord[1]
xx = x - circleCentre[0]
zz = z - circleCentre[1]
condition = (xx*xx + zz*zz < circleRadius**2)
if(condition == True): # inside the circle
materialIndex.data[index] = 1
# vis
fig = vis.Figure(figsize=(800,400))
fig.append( vis.objects.Points( swarm=swarm, fn_colour=materialIndex, colours='blue red',
colourBar=True, pointSize=2.0 ) )
fig.show()
.. raw:: html
# note that this cell requires the previous cell to be executed first.
ignore = swarm.save("SwarmWithCircle.h5")
ignore = materialIndex.save("SwarmWithCircle.materialIndex.h5")
swarmCopy = uw.swarm.Swarm( mesh=mesh )
swarmCopy.load("SwarmWithCircle.h5")
# The swarm geometry is now loaded but the swarmVariables are not restored.
# We have to explicitly create and re-populate any variables we have previously saved
materialIndexCopy = swarmCopy.add_variable("int",1)
materialIndexCopy.load("SwarmWithCircle.materialIndex.h5")
fig = vis.Figure(figsize=(800,400))
fig.append( vis.objects.Points( swarm=swarmCopy, fn_colour=materialIndexCopy, colours='blue red',
colourBar=True, pointSize=2.0 ) )
# Cleanup
if uw.mpi.rank==0:
import os
os.remove( "SwarmWithCircle.h5" )
os.remove( "SwarmWithCircle.materialIndex.h5" )
fig.show()
.. raw:: html