Skip to content

Commit

Permalink
Merged from upstream
Browse files Browse the repository at this point in the history
Merge remote-tracking branch 'upstream/master'
  • Loading branch information
maojrs committed Apr 20, 2017
2 parents 24baffc + c7ffbfa commit 5269171
Show file tree
Hide file tree
Showing 8 changed files with 455 additions and 50 deletions.
2 changes: 1 addition & 1 deletion Euler_approximate_solvers.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
"editable": true
},
"source": [
"In the [last notebook](Euler_equations.ipynb) we studied the Euler equations of inviscid, compressible fluid flow -- including the Riemann problem and its solution. As we saw, the exact solution of the Riemann problem is computationally expensive, since it requires solving a set of nonlinear algebraic equations. In the context of finite volume methods, the detailed structure of the Riemann solution is almost immediately discarded -- only its impact on the neighboring cell averages is used. So it makes sense to consider whether we can approximate the solution with less computation. In this notebook, we investigate approximate solvers for the Euler equations."
"In the [Part I](Euler_equations.ipynb) we studied the Riemann problem for Euler equations of inviscid, compressible fluid flow . As we saw, the exact solution of the Riemann problem is computationally expensive, since it requires solving a set of nonlinear algebraic equations. In the context of finite volume methods, the detailed structure of the Riemann solution is almost immediately discarded -- only its impact on the neighboring cell averages is used. So it makes sense to consider whether we can approximate the solution with less computation. In this chapter, we investigate approximate solvers for the Euler equations."
]
},
{
Expand Down
6 changes: 5 additions & 1 deletion Index.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
" \n",
"## Part II: Approximate solvers\n",
"\n",
" 1. [Euler approximate solvers](Euler_approximate_solvers.ipynb)\n",
"\n",
"## Part III: Riemann problems with spatially-varying flux\n",
" 1. Advection\n",
" 2. Acoustics\n",
Expand All @@ -35,10 +37,12 @@
" \n",
"## Part V: Non-classical problems\n",
" 1. [Nonconvex flux for a scalar problem](Nonconvex_Scalar_Osher_Solution.ipynb)\n",
" 2. [Pressureless flow](Pressureless_flow.ipynb)\n",
" \n",
"## Part VI: Multidimensional systems\n",
" 1. [Acoustics](http://nbviewer.jupyter.org/github/maojrs/ipynotebooks/blob/master/acoustics_riemann.ipynb)\n",
" 2. [Elasticity](http://nbviewer.jupyter.org/github/maojrs/ipynotebooks/blob/master/elasticity_riemann.ipynb)"
" 2. [Elasticity](http://nbviewer.jupyter.org/github/maojrs/ipynotebooks/blob/master/elasticity_riemann.ipynb)\n",
" 3. [The Kitchen Sink: shallow water in cylindrical coordinates](Kitchen_sink_problem.ipynb)"
]
}
],
Expand Down
13 changes: 1 addition & 12 deletions Kitchen_sink_problem.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
"from clawpack import riemann\n",
"from clawpack.visclaw.ianimate import ianimate\n",
"import matplotlib\n",
"matplotlib.rcParams['font.size'] = 12\n",
"plt.style.use('seaborn-talk')\n",
"from IPython.display import HTML"
]
},
Expand Down Expand Up @@ -745,17 +745,6 @@
"plt.xlim(r[0],r[-1]);"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false,
"deletable": true,
"editable": true
},
"outputs": [],
"source": []
},
{
"cell_type": "markdown",
"metadata": {
Expand Down
373 changes: 373 additions & 0 deletions Pressureless_flow.ipynb

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ Parentheticals indicate concepts introduced for the first time.
1. [Acoustics](https://github.com/clawpack/riemann_book/blob/master/Acoustics.ipynb) (eigenvalue analysis, characteristics, similarity solutions)
2. [Traffic flow](https://github.com/clawpack/riemann_book/blob/master/Traffic_flow.ipynb) (shocks, rarefactions, conservation, jump conditions)
3. Burgers' (weak solutions)
4. [Shallow water](https://github.com/clawpack/riemann_book/blob/master/Shallow_tracer.ipynb) (jump conditions for a nonlinear system; Riemann invariants, integral curves, Hugoniot Loci) (see also [this](http://nbviewer.jupyter.org/url/faculty.washington.edu/rjl/notebooks/shallow/SW_riemann_tester.ipynb) and [this](http://nbviewer.jupyter.org/gist/rjleveque/8994740))
4. [Shallow water](https://github.com/clawpack/riemann_book/blob/master/Shallow_water.ipynb) (jump conditions for a nonlinear system; Riemann invariants, integral curves, Hugoniot Loci) (see also [this](http://nbviewer.jupyter.org/url/faculty.washington.edu/rjl/notebooks/shallow/SW_riemann_tester.ipynb) and [this](http://nbviewer.jupyter.org/gist/rjleveque/8994740))
5. How to solve the Riemann problem exactly -- go in depth into SW solver, including Newton iteration to find root of piecewise function
5. Shallow water with a tracer (contact waves)
5. [Shallow water with a tracer](https://github.com/clawpack/riemann_book/blob/master/Shallow_tracer.ipynb) (contact waves)
5. [Euler equations](https://github.com/clawpack/riemann_book/blob/master/Euler_equations.ipynb)

**Part II: Approximate solvers**
Expand Down
24 changes: 17 additions & 7 deletions Shallow_water.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -532,7 +532,10 @@
},
{
"cell_type": "markdown",
"metadata": {},
"metadata": {
"deletable": true,
"editable": true
},
"source": [
"## Comparison of integral curves and Hugoniot loci\n",
"You may have noticed that the integral curves look very similar to the Hugoniot loci, especially when plotted in the $h-hu$ plane. Below we plot the curve from each of these families that passes through a specified point. This divergence is less noticeable in the $h-hu$ plane since all of the curves approach the origin."
Expand All @@ -542,7 +545,9 @@
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
"collapsed": false,
"deletable": true,
"editable": true
},
"outputs": [],
"source": [
Expand All @@ -561,15 +566,18 @@
" plt.show()\n",
" \n",
"interact(compare_curves,\n",
" wave_family=widgets.RadioButtons(options=[1,2]),\n",
" wave_family=widgets.RadioButtons(options=[1,2],description='Wave family:'),\n",
" y_axis=widgets.RadioButtons(options=['u','hu'],description='Vertical axis:'),\n",
" h0=widgets.FloatSlider(min=1.e-1,max=3.,value=1.,description='$h_*$'),\n",
" u0=widgets.FloatSlider(min=-3,max=3,description='$u_*$'));"
]
},
{
"cell_type": "markdown",
"metadata": {},
"metadata": {
"deletable": true,
"editable": true
},
"source": [
"Near the point of intersection, the curves are very close; indeed, they must be tangent at this point since their direction is parallel to the corresponding eigenvector there. Far from this point they diverge; for small depths they must diverge greatly, since the Hugoniot locus never reaches $h=0$ at any finite depth."
]
Expand Down Expand Up @@ -706,7 +714,7 @@
"editable": true
},
"source": [
"Plot the 2-characteristics and notice that they cross each other within the 2-rarefaction. This rarefaction is not physical and should be replaced with a shock; the corresponding part of the integral curve is hence shown as a dashed line."
"Plot the 2-characteristics and notice that they cross each other within the 2-rarefaction. This means that the solution we constructed is triple-valued and nonsensical as a solution to this one-dimensional conservation law, and so this portion of the solution is omitted in the plots of depth and momentum. In this case a rarefaction wave is not physical and should be replaced with a shock; the corresponding part of the integral curve is hence shown as a dashed line."
]
},
{
Expand Down Expand Up @@ -792,7 +800,7 @@
" shallow_water.phase_plane_curves(q_r[0], q_r[1], 'qright', wave_family=2,ax=ax[0])\n",
" shallow_water.phase_plane_curves(q_l[0], q_l[1], 'qleft', wave_family=1,y_axis='hu',ax=ax[1])\n",
" shallow_water.phase_plane_curves(q_r[0], q_r[1], 'qright', wave_family=2,y_axis='hu',ax=ax[1])\n",
" ax[0].set_title('h-u plane'); ax[1].set_title('h-hu plane')\n",
" ax[0].set_title('h-u plane'); ax[1].set_title('h-hu plane'); ax[0].set_xlim(0,3); ax[1].set_xlim(0,3);\n",
" ax[0].set_ylim(-10,10); ax[1].set_ylim(-10,10); plt.tight_layout(); plt.show()\n",
"interact(connect_states,\n",
" h_l=widgets.FloatSlider(min=0.001,max=2,value=1),\n",
Expand All @@ -810,6 +818,8 @@
"source": [
"You should find that by making the initial states flow sufficiently fast away from each other, there is no intersection in the $h-u$ plane. In the $h-hu$ plane, the integral curves always intersect at the origin. The reason for this ambiguity is that, for zero depth it isn't meaningful to assign a velocity. Thus in the $h-u$ plane we could think of the entire $u$-axis as being part of every integral curve. That means that we can always connect the left and right states via an intermediate state with depth $h=0$ (a dry state). \n",
"\n",
"Since the 1-integral curve through $q_l$ reaches $h=0$ at $u = u_l + 2 \\sqrt{gh_l}$ and the 2-integral curve reaches $h=0$ at $u=u_r-2\\sqrt{gh_r}$, we see that a dry middle state occurs if and only if $u_l + 2 \\sqrt{gh_l} < u_r-2\\sqrt{gh_r}$.\n",
"\n",
"It is clear in this case that the solution must consist of two centered rarefaction waves, connecting the left and right states to the middle dry state. These centered rarefactions still have the structure derived above; to complete the solution we only need to know the range of centered characteristics included in each rarefaction. This is most conveniently determined by considering the $h-u$ plane. The 1-integral curve passing through $q_l$ is given by $u = u_l + 2(\\sqrt{gh_l}-\\sqrt{gh_r})$; it reaches a dry state $h=0$ at $u=u_l + 2\\sqrt{gh_l}$. Similarly, the 2-integral curve passing through $q_r$ reaches a dry state $h=0$ at $u=u_r - 2\\sqrt{gh_r}$. Thus the dry state solution is given by\n",
"\n",
"\\begin{align}\n",
Expand Down Expand Up @@ -944,7 +954,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython2",
"version": "2.7.13"
"version": "2.7.12"
}
},
"nbformat": 4,
Expand Down
61 changes: 37 additions & 24 deletions exact_solvers/shallow_water.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,14 @@ def primitive_to_conservative(h, u):
hu = h*u
return h, hu


def conservative_to_primitive(h, hu):
assert np.all(h>=0)
# We should instead check that hu is zero everywhere that h is
u = hu/pospart(h)
return h, u

def cons_to_prim(q):
return conservative_to_primitive(*q)

def exact_riemann_solution(q_l, q_r, grav=1., force_waves=None, primitive_inputs=False):
"""Return the exact solution to the Riemann problem with initial states q_l, q_r.
Expand Down Expand Up @@ -173,18 +174,29 @@ def raref2(xi):
speeds[1] = (ws[2],ws[3])

def reval(xi):
"""
Function that evaluates the Riemann solution for arbitrary xi = x/t.
Sets the solution to nan in an over-turning rarefaction wave
for illustration purposes of this non-physical solution.
"""
rar1 = raref1(xi)
rar2 = raref2(xi)
h_out = (xi<=ws[0])*h_l + \
(xi>ws[0])*(xi<=ws[1])*rar1[0] + \
(xi>ws[1])*(xi<=ws[0])*1e9 + \
(xi>ws[1])*(xi<=ws[2])*h_m + \
(xi>ws[2])*(xi<=ws[3])*rar2[0] + \
(xi>ws[3])*(xi<=ws[2])*1e9 + \
(xi>ws[3])*h_r
h_out[h_out>1e8] = np.nan
hu_out = (xi<=ws[0])*hu_l + \
(xi>ws[0])*(xi<=ws[1])*rar1[1] + \
(xi>ws[1])*(xi<=ws[0])*1e9 + \
(xi>ws[1])*(xi<=ws[2])*hu_m + \
(xi>ws[2])*(xi<=ws[3])*rar2[1] + \
(xi>ws[3])*(xi<=ws[2])*1e9 + \
(xi>ws[3])*hu_r
hu_out[hu_out>1e8] = np.nan
return h_out, hu_out

return states, speeds, reval, wave_types
Expand Down Expand Up @@ -217,17 +229,18 @@ def hugoniot_locus(h, hstar, hustar, wave_family, g=1., y_axis='u'):
d = np.sqrt(g*hstar*(1 + alpha/hstar)*(1 + alpha/(2*hstar)))
if wave_family == 1:
if y_axis == 'u':
return (hustar + alpha*(ustar - d))/h
return (hustar + alpha*(ustar - d))/pospart(h)
else:
return hustar + alpha*(ustar - d)
else:
if y_axis == 'u':
return (hustar + alpha*(ustar + d))/h
return (hustar + alpha*(ustar + d))/pospart(h)
else:
return hustar + alpha*(ustar + d)


def phase_plane_curves(hstar, hustar, state, wave_family='both', y_axis='u', ax=None):
def phase_plane_curves(hstar, hustar, state, g=1., wave_family='both', y_axis='u', ax=None,
plot_unphysical=False):
"""
Plot the curves of points in the h - u or h-hu phase plane that can be
connected to (hstar,hustar).
Expand All @@ -241,37 +254,37 @@ def phase_plane_curves(hstar, hustar, state, wave_family='both', y_axis='u', ax=
h = np.linspace(0, hstar, 200)

if wave_family in [1,'both']:
if state == 'qleft':
u = integral_curve(h, hstar, hustar, 1, y_axis=y_axis)
if state == 'qleft' or plot_unphysical:
u = integral_curve(h, hstar, hustar, 1, g, y_axis=y_axis)
ax.plot(h,u,'b', label='1-rarefactions')
else:
u = hugoniot_locus(h, hstar, hustar, 1, y_axis=y_axis)
if state == 'qright' or plot_unphysical:
u = hugoniot_locus(h, hstar, hustar, 1, g, y_axis=y_axis)
ax.plot(h,u,'--r', label='1-shocks')

if wave_family in [2,'both']:
if state == 'qleft':
u = hugoniot_locus(h, hstar, hustar, 2, y_axis=y_axis)
if state == 'qleft' or plot_unphysical:
u = hugoniot_locus(h, hstar, hustar, 2, g, y_axis=y_axis)
ax.plot(h,u,'--r', label='2-shocks')
else:
u = integral_curve(h, hstar, hustar, 2, y_axis=y_axis)
if state == 'qright' or plot_unphysical:
u = integral_curve(h, hstar, hustar, 2, g, y_axis=y_axis)
ax.plot(h,u,'b', label='2-rarefactions')

h = np.linspace(hstar, 3, 200)

if wave_family in [1,'both']:
if state == 'qright':
u = integral_curve(h, hstar, hustar, 1, y_axis=y_axis)
if state == 'qright' or plot_unphysical:
u = integral_curve(h, hstar, hustar, 1, g, y_axis=y_axis)
ax.plot(h,u,'--b', label='1-rarefactions')
else:
u = hugoniot_locus(h, hstar, hustar, 1, y_axis=y_axis)
if state == 'qleft' or plot_unphysical:
u = hugoniot_locus(h, hstar, hustar, 1, g, y_axis=y_axis)
ax.plot(h,u,'r', label='1-shocks')

if wave_family in [2,'both']:
if state == 'qright':
u = hugoniot_locus(h, hstar, hustar, 2, y_axis=y_axis)
if state == 'qright' or plot_unphysical:
u = hugoniot_locus(h, hstar, hustar, 2, g, y_axis=y_axis)
ax.plot(h,u,'r', label='2-shocks')
else:
u = integral_curve(h, hstar, hustar, 2, y_axis=y_axis)
if state == 'qleft' or plot_unphysical:
u = integral_curve(h, hstar, hustar, 2, g, y_axis=y_axis)
ax.plot(h,u,'--b', label='2-rarefactions')

# plot and label the point (hstar, hustar)
Expand Down Expand Up @@ -315,11 +328,11 @@ def phase_plane_plot(q_l, q_r, g=1., ax=None, force_waves=None, y_axis='u'):
(dry_velocity_l+dry_velocity_r)

xmax, xmin = max(x), min(x)
ymax, ymin = max(y), min(y)
dx, dy = xmax - xmin, ymax - ymin
ymax = max(abs(y))
dx = xmax - xmin
ymax = max(abs(y))
ax.set_xlim(0, xmax + 0.5*dx)
ax.set_ylim(-ymax - 0.5*dy, ymax + 0.5*dy)
ax.set_ylim(-1.5*ymax, 1.5*ymax)
ax.set_xlabel('Depth (h)')
if y_axis == 'u':
ax.set_ylabel('Velocity (u)')
Expand Down Expand Up @@ -359,7 +372,7 @@ def phase_plane_plot(q_l, q_r, g=1., ax=None, force_waves=None, y_axis='u'):
ax.plot(xp,yp,'ok',markersize=10)
# Label states
for i,label in enumerate(('Left', 'Middle', 'Right')):
ax.text(x[i] + 0.025*dx,y[i] + 0.025*dy,label)
ax.text(x[i] + 0.025*dx,y[i] + 0.025*ymax,label)

def plot_hugoniot_loci(plot_1=True,plot_2=False,y_axis='hu'):
h = np.linspace(0.001,3,100)
Expand Down
22 changes: 19 additions & 3 deletions utils/riemann_tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -288,8 +288,8 @@ def plot_riemann(states, s, riemann_eval, wave_types=None, t=0.1, ax=None,

for i in range(num_vars):
ax[i+1].set_xlim((-1,1))
qmax = q_sample[i][:].max()
qmin = q_sample[i][:].min()
qmax = max(np.nanmax(q_sample[i][:]), np.nanmax(states[i,:]))
qmin = min(np.nanmin(q_sample[i][:]), np.nanmin(states[i,:]))
qdiff = qmax - qmin
ax[i+1].set_xlim(-xmax,xmax)
ax[i+1].set_ylim((qmin-0.1*qdiff,qmax+0.1*qdiff))
Expand All @@ -299,6 +299,19 @@ def plot_riemann(states, s, riemann_eval, wave_types=None, t=0.1, ax=None,
ax[i+1].set_ylabel(variable_names[i])

x = np.linspace(-xmax,xmax,1000)
# Make sure we have a point between each pair of waves
# Important e.g. for nearly-pressureless gas
wavespeeds = []
for speed in s:
from numbers import Number
if isinstance(speed, Number):
wavespeeds.append(speed)
else:
wavespeeds += speed
wavespeeds = np.array(wavespeeds)
xm = 0.5*(wavespeeds[1:]+wavespeeds[:-1])*t
iloc = np.searchsorted(x,xm)
x = np.insert(x, iloc, xm)

if t == 0:
q = riemann_eval(x/1e-10)
Expand All @@ -309,7 +322,10 @@ def plot_riemann(states, s, riemann_eval, wave_types=None, t=0.1, ax=None,
q = derived_variables(q)

for i in range(num_vars):
ax[i+1].plot(x,q[i][:],'-k',lw=2)
if color == 'multi':
ax[i+1].plot(x,q[i][:],'-k',lw=2)
else:
ax[i+1].plot(x,q[i][:],'-',color=color,lw=2)
if i in fill:
ax[i+1].fill_between(x,q[i][:],color='b')
ax[i+1].set_ybound(lower=0)
Expand Down

0 comments on commit 5269171

Please sign in to comment.