# ---
# jupyter:
#   jupytext:
#     text_representation:
#       extension: .py
#       format_name: light
#       format_version: '1.5'
#       jupytext_version: 1.14.4
#   kernelspec:
#     display_name: Python 2
#     language: python
#     name: python2
# ---
# + [markdown] deletable=true editable=true
# # PySPH Tutorial:  Solving a simple problem
#
# *<NAME>*
#
# Department of Aerospace Engineering, IIT Bombay
#
# ----------
#
#
# Let us try to solve a little problem: the motion of an elliptical drop of water.
#
#
# Initial conditions:
#
# - $\rho = 1.0$
# - Particles are inside a circle of $x^2 + y^2 < 1$
# - $dx = 0.025, h = 1.3 dx$
# - $u = -100 x, v = 100 y $
# - Choose $c_s = 1400, dt=5e-6, tf=0.0076$
# - Fluid is incompressible.
#
# The velocity field of the initial condition looks as shown in the picture below:
#
# <img width=400 height=400 src="images/elliptical_drop_ic.png"/>
#
# Let us solve this with the WCSPH scheme.
#
#
# + [markdown] deletable=true editable=true
# ## Solving this with PySPH
#
#
# 1. Subclass the `Application` class (`pysph.solver.application.Application`).
# 2. Add a `create_particles(self)` method which returns a tuple/list of particle arrays.
# 3. Add a `create_scheme(self)` method which returns a suitably configured "WCSPH scheme".
#
#
# ### Exercise
#
# - Starting with the example below, create the particles correctly below.  
# - Put this in a separate file called `ed.py`. 
# - Remember to set the properties: `u, v, rho, h, m`.
# - Don't run this from IPython.
#
# + deletable=true editable=true
import numpy as np
from pysph.solver.application import Application
from pysph.base.utils import get_particle_array

class EllipticalDrop(Application):
    def create_particles(self):
        return []
    
if __name__ == '__main__':
    app = EllipticalDrop()
    app.run()
# + deletable=true editable=true
# -
# ### Solution
#
# Try solving this yourselves and then compare with the solution below.
#
# DON'T run this yet!
# %load solutions/ed0.py
# + [markdown] deletable=true editable=true
# ### Creating the scheme
#
# - Now that the particles are created, let us create the scheme.
#
# + deletable=true editable=true
import numpy as np
from pysph.solver.application import Application
from pysph.base.utils import get_particle_array
from pysph.sph.scheme import WCSPHScheme  #  <--- ADDED
class EllipticalDrop(Application):
    def create_particles(self):
        # ...
        self.scheme.setup_properties([pa])  # <--- ADDED
        return pa
        
    def create_scheme(self):
        s = WCSPHScheme(
            ['fluid'], [], dim=2, rho0=1.0, c0=1400,
            h0=1.3*0.025, hdx=1.3, gamma=7.0, alpha=0.1, beta=0.0
        )
        dt = 5e-6
        tf = 0.0076
        s.configure_solver(
            dt=dt, tf=tf,
        )
        return s        

    
if __name__ == '__main__':
    app = EllipticalDrop()
    app.run()
# + [markdown] deletable=true editable=true
# ### Exercise
#
# - Modify your example to add the changes made above.
# - Run the example as `python ed.py`
# - Visualize the output.
# -

# ### Solution
#
# Try to get the example running, see the solution below if you are stuck.
# %load solutions/ed.py
# ### Solution discussion
#
# Recall that you can run the example as follows (on a terminal):
#
#     > python ed.py
#         
# Try this:
#
#     > python ed.py -h
#     
# You can also run the example to use OpenMP like so:
#
#     > python ed.py --openmp
#     
# With multiple cores this should produce some speed-up.
#
# The runs will produce output inside the `ed_output` directory.
#
# - You can use `-d output_dir` to have the output generated in the `output_dir` instead.
#     
#     
# You can visualize the output using:
#
#     > pysph view ed_output
#     
#     
# Note that the output directory also contains a very useful log file that is handy when debugging, in this case the file would be `ed_output/ed.log`.  
#
# The output directory contains the data saved at different times in either `*.npz` or `*.hdf5` files depending on your installation.  The next chapter explores post-processing a little.
# + [markdown] deletable=true editable=true
# ### Running the example from inside IPython
#
# **NOTE:**  If you want to run the example on an IPython notebook you may do so, but you will need to create the app instance as follows::
#
# ```
# if __name__ == '__main__':
#     app = EllipticalDrop(fname='ed')
# ```
#
# Note the addition of `fname='ed'`.  The filename and output directory to pick is determined by the filename and on IPython this is not meaningful, so if you want the output generated in the right directory, you must explicitly pass fname.  When run externally from Python, this is automatically determined for you.
# -

# + [markdown] deletable=true editable=true
# ### Exploring a bit more
#
# - Learn more about the `WCSPHScheme`
# - Learn about the `configure_solver` method and its options.
# + deletable=true editable=true
from pysph.sph.scheme import WCSPHScheme
WCSPHScheme.configure_solver
# + deletable=true editable=true

# + deletable=true editable=true

# + [markdown] deletable=true editable=true
# ### Homework1
#
# - Go over this tutorial: http://pysph.readthedocs.io/en/latest/tutorial/circular_patch_simple.html
# - Familiarize yourself with it
# + [markdown] deletable=true editable=true
# ## Advanced exercise
#
# - Take the above example `ed.py` as a starting point and copy it to `dam_break.py`.
# - Modify the `dam_break.py` to solve the 2D dam break problem, as below
# - Fluid height = 2
# - Fluid width = 1.0
# - Container height = 4
# - Container width = 4
# - Assume g=9.81 m/s
#
# - Use 2-3 layers of particles for the boundary
#
#
# ```
#     |                         |
#     |                         |           
#     |   1                     |
#     |*******                  |   4     
#     |*******                  |
#     |*******  2               |
#     |*******                  |
#     ---------------------------
#     
#                  4
# ```
#     
#
# + deletable=true editable=true