<jupyter_start><jupyter_text>PySPH tutorial: Getting started*<NAME>*Department of Aerospace Engineering, IIT Bombay----  Installation and getting startedThis is a simple introduction to PySPH.  The PySPH documentation is here: http://pysph.readthedocs.io1. First install PySPH.  See here: http://pysph.readthedocs.io/en/latest/installation.html2. Go over the installation and getting started pageImportantly, once you have PySPH installed run a simple example, as so:    $ pysph run elliptical_drop    or    $ pysph run rigid_body.bouncing_cubes        Then view the generated output:    $ pysph view elliptical_drop_output        If this produces a nice looking view, you should be mostly set.  It may be handy to be able to run pysph on openmp:    $ pysph run elliptical_drop --openmpIf you get this far and everything works, you should be in good shape.  More on the examplesThe examples are all written in pure Python.  To see the sources for the examples you could either visit the github sources here: https://github.com/pypr/pysph/tree/master/pysph/examplesAlternatively try this:    $ pysph run    Now you can pick among 40 odd examples.  To see the source of a simple one you can do the following:    $ pysph run --cat elliptical_drop        This will simply show you the source code without executing it.  You could have also run the example by changing directory into the `/pysph/examples` directory and running the example, for example let us do this easily as follows:    $ pysph run --cat elliptical_drop > ed.py     This puts the source into ed.py in the current dir.        $ python ed.py    **NOTE: **  there is also a `/old_examples` directory which you should not use.    You can also import the examples from Python and thus could just as well have run this example as:    $ python -m pysph.examples.elliptical_dropThe point I am making is that `pysph run` is not doing anything special at all, it just makes it a tad easier to run the examples.  These examples are usually quite useful and can also be subclassed if you wish to reuse them.  Using the PySPH libraryIn order to simulate your own problems you need to understand the anatomy of a PySPH simulation.  All the examples typically will do the following:1. Create some particles2. Specify the equations for the inter-particle interactions.3. Specify the integrators to use.4. Put these together in an `Application` and run this application. Creating particlesIn this tutorial we will mostly explore the creation of particles in PySPH.  In PySPH, particles are created in a data structure called a `ParticleArray`.  Let us consider an example.  Let us say we have a glass of water.  Clearly we have two "things", a glass vessel and the water inside it.  Since we wish to capture the interaction of the water with the vessel, we would create two `ParticleArray`s.  One for the vessel which we call `"solid"` and the other for the water which we call `"fluid"`.  Some important points to note.  Each particle array - has a name (a string) which should be a valid Python variable name, `"fluid"` and `"solid"` are good as would be `"fluid1"` and `"fluid2"`.- has a collection of various particle properties, like the position `x, y, z`, velocity components `u, v, w`, other scalar properties `m, h, rho` etc.  All of these properties are scalars.- has a collection of "constants", which can have an arbitrary size but are internally stored as 1D arrays.The properties are used for things that typically vary, from particle to particle.The constants are used for things that are constant for all the particles.Let us now try to create a particle array in order to understand it better.<jupyter_code>from __future__ import print_function
from pysph.base.particle_array import ParticleArray
pa = ParticleArray(name='fluid', x=[0.0, 1.0], y=0, m=0.1)
print(pa.name, pa.x, pa.y, pa.m)<jupyter_output><empty_output><jupyter_text>Note that we set the name by a kwarg.  Exercise- Try creating a particle array without the name.- While x was passed as a list, y and m were not, what is going on?- Does this work with numpy arrays?  Try it!- Does it work with numpy arrays of arbitrary shape?- What if you have arrays passed of different sizes?!- Can you add a new "crazy" property?  Solution- You can create a particle array without a name but DON'T.- NumPy arrays work and are ravelled, lists and constants work.- Passing incompatible sizes is a problem and you will get an error.- You can add any kind of property by passing a suitable kwarg.<jupyter_code>pa = ParticleArray(name='fluid', x=[0.0, 1.0], y=0, m=0.1, crazy=25)
pa.crazy<jupyter_output><empty_output><jupyter_text>Doing more- How do we discover the properties?- Use `pa.properties`- What about constants?<jupyter_code>pa.properties<jupyter_output><empty_output><jupyter_text>So what are the other strange properties?  We didn't add `gid, pid and tag`So it looks like PySPH automatically adds some special props, what are these?  - gid: is a global ID for each particle, it is useful in parallel.- pid: represents the process ID for each particle, also relevant in parallel.- tag: represents the kind of particle we have.The `tag` property is probably the most useful.  It is representative of the kind of particles, the ones that are important are:- Local: see `get_local_tag` below- Remote: see `get_remote_tag` below- Ghost: see `get_ghost_tag` below**Questions**- What is this pyzoltan stuff??  - What is a DoubleArray, IntArray?<jupyter_code>pa.gid
pa.pid
pa.tag
from pysph.base.particle_array import get_local_tag, get_ghost_tag, get_remote_tag
print("Local:", get_local_tag())
print("Remote:", get_remote_tag())
print("Ghost:", get_ghost_tag())<jupyter_output><empty_output><jupyter_text>Digression CArraysLet us answer the question "What is this pyzoltan, DoubleArray stuff?"These are internal arrays that allow us to efficiently store and compute with these properties and have some useful features.<jupyter_code>from pyzoltan.core.carray import DoubleArray
a = DoubleArray(5)
x = a.get_npy_array()
x[:] = 100
a[1]
a.append(203)
a.length<jupyter_output><empty_output><jupyter_text>Exercise- Find the default properties.- Can you create a particle array with no properties in the constructor?<jupyter_code>empty = ParticleArray(name='dummy')
empty.properties<jupyter_output><empty_output><jupyter_text>Adding constantsAdd them by passing a dictionary.<jupyter_code>pa = ParticleArray(name='fluid', x=[0.0, 1.0], constants={'rho0': 1000})
pa.rho0
pa.constants<jupyter_output><empty_output><jupyter_text>Exercises- Create different kinds of constants and experiment- Create a vector or a 2d array.  What happens to a 2d array?<jupyter_code>import numpy as np
pa = ParticleArray(name='f', x=[0.0, 1.0], 
                   constants=
                   {'a': 1, 'b': [1,2,3], 'c': np.identity(10)})
pa.constants
pa.c<jupyter_output><empty_output><jupyter_text>Particle array methodsThere are many methods but some more useful than others.  Let us explore this- `pa.get_number_of_particles()`- `pa.add_constant()`- `pa.add_property(...)`- `pa.add_particles()`- `pa.extend(n)`- `pa.extract_particles(...)`- `pa.remove_particles()`- `pa.remove_property(prop)`- `pa.remove_tagged_particles(tag)`The output property arrays is an important attribute.  It is what determines what is dumped to disk when you save particle arrays or run simulations.- `pa.set_output_arrays(list)`- `pa.output_property_arrays`- `pa.add_output_arrays(list)`  Exercise- Explore all of the above methods.<jupyter_code>pa.output_property_arrays
pa.add_property('x')
pa.x = np.arange(10)
pa.add_output_arrays(['x'])
pa.output_property_arrays<jupyter_output><empty_output><jupyter_text>- `pa.get_carray(prop)`: will get you the c array.- `pa.get(props)`: returns properties.- `pa.set(**props)`: sets the properties in one go  The convenient `pysph.base.utils`- For many standard problems, one requires a bunch of additional properties.- Use the `pysph.base.utils` for these.<jupyter_code>from pysph.base.utils import get_particle_array
from pysph.base.utils import get_particle_array_wcsph, get_particle_array_tvf_fluid, get_particle_array_gasd
pa = get_particle_array_wcsph(name='fluid', x=[1, 2], m=3)
pa.properties<jupyter_output><empty_output><jupyter_text>Exercises- Create particles inside a disk of radius 1.- Visualize the particle positions.- Create a WCSPH compatible particle array with these points.<jupyter_code>%matplotlib inline
from matplotlib import pyplot as plt<jupyter_output><empty_output><jupyter_text>Solution<jupyter_code>%load solutions/particles_in_disk.py<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.08289794496691048, 'fraction_numerical': 0.0073145245559038665, 'mean_word_length': 4.904043865661412, 'pattern_counts': {'":': 0, '<': 50, '<?xml version=': 0, '>': 51, 'https://': 1, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '12', 'dir': 'jupyter-structured-clean-dedup', 'id': '171631', 'license': 'BSD-3-Clause', 'n_tokens_mistral': 2595, 'n_tokens_neox': 2492, 'n_words': 1070, 'path': 'docs/tutorial/1_getting_started.ipynb', 'repo_name': 'suhasjains/pysph', 'size': '8626'}