Skip to content

Latest commit

 

History

History
640 lines (481 loc) · 19.2 KB

The k-Scheme.md

File metadata and controls

640 lines (481 loc) · 19.2 KB

Advection using the k-Scheme

CH EN 6355 - Computational Fluid Dynamics

Prof. Tony Saad (www.tsaad.net)
slides at: www.tsaad.net
Department of Chemical Engineering
University of Utah


Here, we will implement the k-scheme or kappa-schemes for advection. It is easiest to implement this scheme since for different values of k, we recover all sorts of high-order flux approximations. We will assume a positive advecting velocity for illustration purposes.

We are solving the constant speed advection equation given by \begin{equation} u_t = - c u_x = - F_x;\quad F = cu \end{equation} We will use a simple Forward Euler explicit method. Using a finite volume integration, we get \begin{equation} u_i^{n+1} = u_i^n - \frac{\Delta t}{\Delta x} (F_{i+\tfrac{1}{2}}^n - F_{i-\tfrac{1}{2}}^n) \end{equation} For constant grid spacing, the k-Scheme is given by \begin{equation} {\phi _f} = {\phi _{\rm{C}}} + \frac{{1 - k}}{4}({\phi _{\rm{C}}} - {\phi _{\rm{U}}}) + \frac{{1 + k}}{4}({\phi _{\rm{D}}} - {\phi {\rm{C}}}) \end{equation} which, for a positive advecting velocity, gives us \begin{equation} F{i + {\textstyle{1 \over 2}}}^n = c\phi _{i + {\textstyle{1 \over 2}}}^n = c{\phi _i} + c\frac{{1 - k}}{4}({\phi _i} - {\phi _{i - 1}}) + c\frac{{1 + k}}{4}({\phi _{i + 1}} - {\phi _i}) \end{equation}

import numpy as np
%matplotlib inline
%config InlineBackend.figure_format = 'svg'
import matplotlib.pyplot as plt
import matplotlib.animation as animation
plt.rcParams['animation.html'] = 'html5'
from matplotlib import cm
def step(x,x0):
    x0 = 0.6
    x1 = 0.8
    result = x - x0
    result[x-x1<x1] = 1.0            
    result[x<x0] = 0.0
    result[x>x1] = 0.0  
    return result

def gaussian(x,x0):
    s = 0.08
    s = s*s
    result = np.exp( -(x-x0)**2/s)
    return result
L = 1.0
n = 128 # cells
dx = L/n # n intervals
x = np.linspace(-3*dx/2, L + 3*dx/2, n+4) # include ghost cells - we will include 2 ghost cells on each side for high order schemes

# create arrays
phi = np.zeros(n+4) # cell centered quantity
f = np.zeros(n+4+1) # flux
u = np.ones(n+4+1) # velocity field - assumed to live on faces same as flux

x0 = 0.3
# u0 = np.zeros(N + 2)
# u0[1:-1] = np.sin(2*np.pi*x)
# u0 = np.zeros(N)
# phi0 = np.sin(np.pi*x)
phi0 = gaussian(x,x0) + step(x,x0)
# u0 = triangle(x,0.5,0.75,1)
# u0[0:N//2] = 1.0
plt.plot(x,phi0)
[<matplotlib.lines.Line2D at 0x1199f8630>]

svg

cfl =0.5
c = 1.0 # use a negative value for left traveling waves
dt = cfl*dx/abs(c)
print('dt=',dt)
print('dx=',dx)
dt= 0.00390625
dx= 0.0078125
# the k scheme
k = 0.5
# finite volume implementation with arrays for fluxes
t = 0
tend= L/abs(c)

sol = []
sol.append(phi0)
ims = []

fig = plt.figure(figsize=[5,3],dpi=200)
plt.rcParams["font.family"] = "serif"
plt.rcParams["font.size"] = 10
plt.rc('text', usetex=True)

# plt.grid()
plt.xlim([0.,L])
plt.ylim([-0.25,1.25])
plt.xlabel('$x$')
plt.ylabel('$\phi$')
plt.tight_layout()
# plot initial condition
plt.plot(x,phi0,'darkred',animated=True)

i = 0
while t < tend:    
    phin = sol[-1]

#     if (i%16==0):
#         shift = int(np.ceil(c*(t-dt)/dx))
#         im = plt.plot(x[2:-2], np.roll(phin[2:-2], -shift) ,'k-o',markevery=2,markersize=3.5,markerfacecolor='deepskyblue',
#              markeredgewidth=0.25, markeredgecolor='k',linewidth=0.45, animated=True)
#         ims.append(im)
    
    # impose periodic conditions
    phin[-2] = phin[2]
    phin[-1] = phin[3]    
    phin[0] = phin[-4]        
    phin[1] = phin[-3]            
    
    phi = np.zeros_like(phi0)
    
    # predictor - take half a step and use upwind
    # du/dt = -c*du/dx
    if c >= 0:
        ϕc = phin[1:-2] # phi upwind
    else:
        ϕc = phin[2:-1] # phi upwind
    
    f[2:-2] = c*ϕc
    phi[2:-2] = phin[2:-2] - dt/2.0/dx*(f[3:-2] - f[2:-3])
    phi[-2] = phi[2]
    phi[-1] = phi[3]    
    phi[0] = phi[-4]        
    phi[1] = phi[-3]                
    
    # du/dt = -c*du/dx
    if c >= 0:
        ϕc = phi[1:-2] # phi upwind
        ϕu = phi[:-3]  # phi far upwind
        ϕd = phi[2:-1] # phi downwind
    else:
        ϕc = phi[2:-1] # phi upwind
        ϕu = phi[3:]  # phi far upwind
        ϕd = phi[1:-2] # phi downwind
        
    f[2:-2] = ϕc + (1-k)/4.0*(ϕc - ϕu) + (1+k)/4.0*(ϕd - ϕc)
    f = c*f # multiply the flux by the velocity
    # advect
    phi[2:-2] = phin[2:-2] - c * dt/dx*(f[3:-2] - f[2:-3]) #+ dt/dx/dx*diffusion
    t += dt    
    i+=1
    sol.append(phi)


# plt.annotate('k = '+ str(k), xy=(0.5, 0.8), xytext=(0.015, 0.9),fontsize=8)
# plt.legend(('exact','numerical'),loc='upper left',fontsize=7)
# ani = animation.ArtistAnimation(fig, ims, interval=100, blit=True,
#                                 repeat_delay=1000)

# ani.save('k-scheme-'+str(k)+'.mp4',dpi=300,fps=24)

svg

plt.plot(sol[0], label='initial condition')
plt.plot(sol[-1], label='one residence time')
plt.legend()
plt.grid()

svg

Create Animation in Moving Reference Frame

"""
Create Animation in Moving Reference Frame
"""
import matplotlib
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
matplotlib.use("Agg")
fig, ax = plt.subplots(figsize=(4,3),dpi=150) 
ax.grid(True)
f0 = sol[0]
line0, = ax.plot(x[2:-2], f0[2:-2] ,'r-',linewidth=0.75, animated=True)
line1, = ax.plot(x[2:-2], f0[2:-2] ,'k-o',markevery=2,markersize=3.5,markerfacecolor='deepskyblue',
             markeredgewidth=0.25, markeredgecolor='k',linewidth=0.45, animated=True)

ann = ax.annotate('time ='+str(round(t,3))+' s', xy=(2, 1), xytext=(40, 200),xycoords='figure points')
ax.annotate('k ='+str(k) + ' (k-scheme)', xy=(2, 1), xytext=(40, 190),xycoords='figure points')
plt.tight_layout()


def animate_moving(i):
    print('time=',i*dt)
    t = i*dt
    xt = x + i*1.1*c*dt
    line0.set_xdata(xt[2:-2])
    line1.set_xdata(xt[2:-2])    
    ax.axes.set_xlim(xt[0],0.0*dx + xt[-1])
    f = sol[i]
    ax.axes.set_ylim(1.1*min(f) - 0.1,1.1*max(f))
    ann.set_text('time ='+str(round(t,4))+'s (' + str(i)+ ').')
    shift =int(np.ceil(i*c*dt/dx))
    line1.set_ydata(np.roll(f[2:-2], -shift))

    f0 = sol[0]
    line0.set_ydata(f0[2:-2])
    return line0,line1


# Init only required for blitting to give a clean slate.
def init():
    line0.set_ydata(np.ma.array(x[2:-2], mask=True))
    line1.set_ydata(np.ma.array(x[2:-2], mask=True))    
    return line0,line1

ani = animation.FuncAnimation(fig, animate_moving, np.arange(0,len(sol),2*int(1/cfl)), init_func=init,
                              interval=20, blit=False)
print('done!')
done!

svg

ani.save('__k-scheme_' + str(k)+'.mp4',fps=24,dpi=300)
time= 0.0
time= 0.0078125
time= 0.015625
time= 0.0234375
time= 0.03125
time= 0.0390625
time= 0.046875
time= 0.0546875
time= 0.0625
time= 0.0703125
time= 0.078125
time= 0.0859375
time= 0.09375
time= 0.1015625
time= 0.109375
time= 0.1171875
time= 0.125
time= 0.1328125
time= 0.140625
time= 0.1484375
time= 0.15625
time= 0.1640625
time= 0.171875



---------------------------------------------------------------------------

KeyboardInterrupt                         Traceback (most recent call last)

<ipython-input-29-f14b34654064> in <module>()
----> 1 ani.save('__k-scheme_' + str(k)+'.mp4',fps=24,dpi=300)


/anaconda3/lib/python3.6/site-packages/matplotlib/animation.py in save(self, filename, writer, fps, dpi, codec, bitrate, extra_args, metadata, extra_anim, savefig_kwargs)
   1172                         # TODO: See if turning off blit is really necessary
   1173                         anim._draw_next_frame(d, blit=False)
-> 1174                     writer.grab_frame(**savefig_kwargs)
   1175 
   1176         # Reconnect signal for first draw if necessary


/anaconda3/lib/python3.6/site-packages/matplotlib/animation.py in grab_frame(self, **savefig_kwargs)
    374             # frame format and dpi.
    375             self.fig.savefig(self._frame_sink(), format=self.frame_format,
--> 376                              dpi=self.dpi, **savefig_kwargs)
    377         except (RuntimeError, IOError) as e:
    378             out, err = self._proc.communicate()


/anaconda3/lib/python3.6/site-packages/matplotlib/figure.py in savefig(self, fname, frameon, transparent, **kwargs)
   2092             self.set_frameon(frameon)
   2093 
-> 2094         self.canvas.print_figure(fname, **kwargs)
   2095 
   2096         if frameon:


/anaconda3/lib/python3.6/site-packages/matplotlib/backend_bases.py in print_figure(self, filename, dpi, facecolor, edgecolor, orientation, format, bbox_inches, **kwargs)
   2073                     orientation=orientation,
   2074                     bbox_inches_restore=_bbox_inches_restore,
-> 2075                     **kwargs)
   2076             finally:
   2077                 if bbox_inches and restore_bbox:


/anaconda3/lib/python3.6/site-packages/matplotlib/backends/backend_agg.py in print_raw(self, filename_or_obj, *args, **kwargs)
    459 
    460     def print_raw(self, filename_or_obj, *args, **kwargs):
--> 461         FigureCanvasAgg.draw(self)
    462         renderer = self.get_renderer()
    463         with cbook._setattr_cm(renderer, dpi=self.figure.dpi), \


/anaconda3/lib/python3.6/site-packages/matplotlib/backends/backend_agg.py in draw(self)
    400         toolbar = self.toolbar
    401         try:
--> 402             self.figure.draw(self.renderer)
    403             # A GUI class may be need to update a window using this draw, so
    404             # don't forget to call the superclass.


/anaconda3/lib/python3.6/site-packages/matplotlib/artist.py in draw_wrapper(artist, renderer, *args, **kwargs)
     48                 renderer.start_filter()
     49 
---> 50             return draw(artist, renderer, *args, **kwargs)
     51         finally:
     52             if artist.get_agg_filter() is not None:


/anaconda3/lib/python3.6/site-packages/matplotlib/figure.py in draw(self, renderer)
   1647 
   1648             mimage._draw_list_compositing_images(
-> 1649                 renderer, self, artists, self.suppressComposite)
   1650 
   1651             renderer.close_group('figure')


/anaconda3/lib/python3.6/site-packages/matplotlib/image.py in _draw_list_compositing_images(renderer, parent, artists, suppress_composite)
    136     if not_composite or not has_images:
    137         for a in artists:
--> 138             a.draw(renderer)
    139     else:
    140         # Composite any adjacent images together


/anaconda3/lib/python3.6/site-packages/matplotlib/artist.py in draw_wrapper(artist, renderer, *args, **kwargs)
     48                 renderer.start_filter()
     49 
---> 50             return draw(artist, renderer, *args, **kwargs)
     51         finally:
     52             if artist.get_agg_filter() is not None:


/anaconda3/lib/python3.6/site-packages/matplotlib/axes/_base.py in draw(self, renderer, inframe)
   2626             renderer.stop_rasterizing()
   2627 
-> 2628         mimage._draw_list_compositing_images(renderer, self, artists)
   2629 
   2630         renderer.close_group('axes')


/anaconda3/lib/python3.6/site-packages/matplotlib/image.py in _draw_list_compositing_images(renderer, parent, artists, suppress_composite)
    136     if not_composite or not has_images:
    137         for a in artists:
--> 138             a.draw(renderer)
    139     else:
    140         # Composite any adjacent images together


/anaconda3/lib/python3.6/site-packages/matplotlib/artist.py in draw_wrapper(artist, renderer, *args, **kwargs)
     48                 renderer.start_filter()
     49 
---> 50             return draw(artist, renderer, *args, **kwargs)
     51         finally:
     52             if artist.get_agg_filter() is not None:


/anaconda3/lib/python3.6/site-packages/matplotlib/text.py in draw(self, renderer)
   2391         # Draw text, including FancyBboxPatch, after FancyArrowPatch.
   2392         # Otherwise, a wedge arrowstyle can land partly on top of the Bbox.
-> 2393         Text.draw(self, renderer)
   2394 
   2395     def get_window_extent(self, renderer=None):


/anaconda3/lib/python3.6/site-packages/matplotlib/artist.py in draw_wrapper(artist, renderer, *args, **kwargs)
     48                 renderer.start_filter()
     49 
---> 50             return draw(artist, renderer, *args, **kwargs)
     51         finally:
     52             if artist.get_agg_filter() is not None:


/anaconda3/lib/python3.6/site-packages/matplotlib/text.py in draw(self, renderer)
    752                     textrenderer.draw_tex(gc, x, y, clean_line,
    753                                           textobj._fontproperties, angle,
--> 754                                           mtext=mtext)
    755                 else:
    756                     textrenderer.draw_text(gc, x, y, clean_line,


/anaconda3/lib/python3.6/site-packages/matplotlib/backends/backend_agg.py in draw_tex(self, gc, x, y, s, prop, angle, ismath, mtext)
    231         texmanager = self.get_texmanager()
    232 
--> 233         Z = texmanager.get_grey(s, size, self.dpi)
    234         Z = np.array(Z * 255.0, np.uint8)
    235 


/anaconda3/lib/python3.6/site-packages/matplotlib/texmanager.py in get_grey(self, tex, fontsize, dpi)
    418         alpha = self.grey_arrayd.get(key)
    419         if alpha is None:
--> 420             pngfile = self.make_png(tex, fontsize, dpi)
    421             X = _png.read_png(os.path.join(self.texcache, pngfile))
    422             self.grey_arrayd[key] = alpha = X[:, :, -1]


/anaconda3/lib/python3.6/site-packages/matplotlib/texmanager.py in make_png(self, tex, fontsize, dpi)
    383             self._run_checked_subprocess(
    384                 ["dvipng", "-bg", "Transparent", "-D", str(dpi),
--> 385                  "-T", "tight", "-o", pngfile, dvifile], tex)
    386         return pngfile
    387 


/anaconda3/lib/python3.6/site-packages/matplotlib/texmanager.py in _run_checked_subprocess(self, command, tex)
    296             report = subprocess.check_output(command,
    297                                              cwd=self.texcache,
--> 298                                              stderr=subprocess.STDOUT)
    299         except subprocess.CalledProcessError as exc:
    300             raise RuntimeError(


/anaconda3/lib/python3.6/subprocess.py in check_output(timeout, *popenargs, **kwargs)
    354 
    355     return run(*popenargs, stdout=PIPE, timeout=timeout, check=True,
--> 356                **kwargs).stdout
    357 
    358 


/anaconda3/lib/python3.6/subprocess.py in run(input, timeout, check, *popenargs, **kwargs)
    423     with Popen(*popenargs, **kwargs) as process:
    424         try:
--> 425             stdout, stderr = process.communicate(input, timeout=timeout)
    426         except TimeoutExpired:
    427             process.kill()


/anaconda3/lib/python3.6/subprocess.py in communicate(self, input, timeout)
    848                 self._stdin_write(input)
    849             elif self.stdout:
--> 850                 stdout = self.stdout.read()
    851                 self.stdout.close()
    852             elif self.stderr:


KeyboardInterrupt: 
import urllib
import requests
from IPython.core.display import HTML
def css_styling():
    styles = requests.get("https://raw.githubusercontent.com/saadtony/NumericalMethods/master/styles/custom.css")
    return HTML(styles.text)
css_styling()

CSS style adapted from https://github.com/barbagroup/CFDPython. Copyright (c) Barba group

<style> @font-face { font-family: "Computer Modern"; src: url('http://mirrors.ctan.org/fonts/cm-unicode/fonts/otf/cmunss.otf'); } /*div.cell{ width:800px; margin-left:16% !important; margin-right:auto; } */ /* set the font size in tables */ tr, td, th{ font-size:110%; } /* spec for headers */ h1 { font-family: 'Bitter', serif; } h2 { font-family: 'Fenix', serif; } h3{ font-family: 'Fenix', serif; margin-top:12px; margin-bottom: 3px; } h4{ font-family: 'Fenix', serif; } h5 { font-family: 'Alegreya Sans', sans-serif; } div.text_cell_render{ font-family: 'Merriweather','Alegreya Sans','Lora', 'Oxygen', "Helvetica Neue", Arial, Helvetica, Geneva, sans-serif; line-height: 160%; font-size: 130%; } .CodeMirror{ font-family: "Source Code Pro"; font-size: 100%; } .text_cell_render h1 { font-weight: 200; font-size: 32pt; line-height: 120%; color:#CD2305; margin-bottom: 0.5em; margin-top: 0.5em; display: block; } .text_cell_render h2 { font-size: 26pt; text-align: center; } .text_cell_render h3 { font-size: 20pt; } .text_cell_render h4 { font-size: 18pt; } .text_cell_render h5 { font-weight: 300; font-size: 16pt; color: #CD2305; font-style: italic; margin-bottom: .5em; margin-top: 0.5em; display: block; } .warning{ color: rgb( 240, 20, 20 ) } /* div#notebook {background-color: #1e1e1e; border-top: none;} div#notebook-container {background-color: rgb(180, 180, 180);} */ </style> <script> MathJax.Hub.Config({ TeX: { extensions: ["AMSmath.js"] }, tex2jax: { inlineMath: [ ['$','$'], ["\\(","\\)"] ], displayMath: [ ['$$','$$'], ["\\[","\\]"] ] }, displayAlign: 'center', // Change this to 'center' to center equations. "HTML-CSS": { availableFonts: ["TeX"], scale: 100, styles: {'.MathJax_Display': {"margin": 4}} } }); </script>