Commit c396e5ce by Jigyasa Watwani

works in 1D, 2D -- visualize both analytical and numerical solutions

parent 9ce31f90
...@@ -4,7 +4,6 @@ import numpy as np ...@@ -4,7 +4,6 @@ import numpy as np
import dolfin as df import dolfin as df
import h5py import h5py
from matplotlib.widgets import Slider from matplotlib.widgets import Slider
import os import os
import argparse, json import argparse, json
from tempfile import TemporaryDirectory from tempfile import TemporaryDirectory
...@@ -22,33 +21,72 @@ DIR = os.path.dirname(args.jsonfile) ...@@ -22,33 +21,72 @@ DIR = os.path.dirname(args.jsonfile)
offscreen=(not args.onscreen) offscreen=(not args.onscreen)
# parameters # parameters
Nt = int(params['maxtime']/params['timestep']) tmax = params['maxtime']
times = np.linspace(0, params['maxtime'], Nt+1)
d = params['dimension'] d = params['dimension']
L = params['system_size'] L = params['system_size']
alpha = params['growth_parameter'] alpha = params['growth_parameter']
dt = params['timestep'] dt = params['timestep']
dts = params['savetime']
Dc = params['Dc'] Dc = params['Dc']
k = params['reaction_rate'] k = params['reaction_rate']
growth = params['growth'] growth = params['growth']
timestamp = params['timestamp']
m = 2 # mth mode of cosine in the initial condition for d=1 m = 2 # mth mode of cosine in the initial condition for d=1
p = 1 # pth zero of bessel 1 in the initial condition for d=2 p = 1 # pth zero of bessel 1 in the initial condition for d=2
# mesh #################### get the numerical solution, the mesh, its geometry and topology ##################################
if d==2: def get_data(params, DIR=''):
mesh = df.Mesh('disk.xml.gz') savesteps = int(params['maxtime']/params['savetime'])
else: times = np.arange(savesteps+1) * params['savetime']
mesh = df.IntervalMesh(params['resolution'], 0, L)
# Read mesh geometry from h5 file
Nv = mesh.num_vertices() # gives params['resolution'] + 1 var = 'concentration'
h5 = h5py.File(os.path.join(DIR, '%s_%s.h5' % (timestamp, var)), "r")
# topology array, initialize geometry arrays # should be in the loop if remeshing
topology_array = mesh.cells() topology = np.array(h5['%s/%s_0/mesh/topology'%(var,var)])
geometry_array = np.zeros(((Nt + 1, Nv, d))) geometry = []
for i in range(len(times)):
geometry.append(np.array(h5['%s/%s_%d/mesh/geometry'%(var,var,i)]))
h5.close()
geometry = np.array(geometry)
if d==1:
geometry, zeros= np.dsplit(geometry, 2)
# initialize r and sol arrays # create a mesh
r_array = np.zeros((Nt + 1, Nv)) if params['dimension']==1:
sol = np.zeros((len(times), len(r_array[0]))) mesh = df.IntervalMesh(params['resolution'], 0, L)
else:
mesh = df.Mesh()
editor = df.MeshEditor()
editor.open(mesh,
type='triangle' if d==2 else 'tetrahedron',
tdim=d, gdim=d)
editor.init_vertices(len(geometry[0]))
editor.init_cells(len(topology))
for i in range(len(geometry[0])):
editor.add_vertex(i, geometry[0][i]) # vertex 0 --> (x0, y0, z0), vertex 1 --> (x1, y1, z1), ...
for i in range(len(topology)):
editor.add_cell(i, topology[i]) # cell 0 --> vertices(0,1,2), cell 1 --> ()...
editor.close()
# Read concentration data
concentration = np.zeros((len(times), len(geometry[0])))
cFile = os.path.join(DIR, '%s_%s.xdmf' % (timestamp,var))
with df.XDMFFile(cFile) as cFile:
for steps in range(savesteps+1):
mesh.coordinates()[:] = geometry[steps]
VFS = df.FunctionSpace(mesh, 'P', 1)
c = df.Function(VFS)
cFile.read_checkpoint(c, var, steps)
concentration[steps] = c.compute_vertex_values(mesh)
return (mesh, times, geometry, topology, concentration)
(mesh, times, geometry, topology, concentration) = get_data(params, DIR)
#################################### get the analytical solution #########################################################
radius = np.zeros((len(times), mesh.num_vertices()))
sol = np.zeros_like(radius)
# velocity to move the mesh # velocity to move the mesh
VFS = df.VectorFunctionSpace(mesh, 'P', 1) VFS = df.VectorFunctionSpace(mesh, 'P', 1)
...@@ -61,7 +99,7 @@ growth_direction = tuple(['x['+str(i)+']' for i in range(0, d)]) ...@@ -61,7 +99,7 @@ growth_direction = tuple(['x['+str(i)+']' for i in range(0, d)])
growth_direction = df.Expression(growth_direction, degree=1) growth_direction = df.Expression(growth_direction, degree=1)
velocity = df.project(sigma * growth_direction, VFS) velocity = df.project(sigma * growth_direction, VFS)
# modes enetering the solution # modes entering the solution
if d == 1: if d == 1:
mode = m * np.pi mode = m * np.pi
else: else:
...@@ -69,29 +107,16 @@ else: ...@@ -69,29 +107,16 @@ else:
# time loop # time loop
t = 0 t = 0
for steps in range(0, Nt+1):
for steps in range(0, len(times)):
# update sigma # update sigma
sigma.t = t sigma.t = t
# update velocity # update velocity
velocity.assign(df.project(sigma*growth_direction, VFS)) velocity.assign(df.project(sigma*growth_direction, VFS))
# find r, geometry and sol arrays on the mesh # r_array
radius[steps] = np.linalg.norm(geometry[steps], axis=1)
# geometry array
if d==1:
x = np.reshape(mesh.coordinates()[:], (Nv, 1))
geometry_array[steps] = x
else:
x = np.reshape(mesh.coordinates()[:,0], (Nv, 1))
y = np.reshape(mesh.coordinates()[:,1], (Nv, 1))
geometry_array[steps] = np.concatenate((x,y),axis=1)
# r array
r_array[steps] = 0
for j in range(0,d):
r_array[steps] += mesh.coordinates()[:,j]**2
r_array[steps] = np.sqrt(r_array[steps])
# sol array # sol array
mode_indep_time_part = {'none': np.exp(k*t), mode_indep_time_part = {'none': np.exp(k*t),
...@@ -108,32 +133,34 @@ for steps in range(0, Nt+1): ...@@ -108,32 +133,34 @@ for steps in range(0, Nt+1):
'exponential': L * np.exp(alpha * t), 'exponential': L * np.exp(alpha * t),
'linear': L + alpha * t} 'linear': L + alpha * t}
if d==1: if d==1:
sol[steps] = (1 + mode_dep_time_part[growth] * np.cos(mode * r_array[steps]/domain_length[growth])) * mode_indep_time_part[growth] sol[steps] = (1 + mode_dep_time_part[growth] * np.cos(mode * radius[steps]/domain_length[growth])) * mode_indep_time_part[growth]
else: else:
sol[steps] = (1 + mode_dep_time_part[growth] * sc.special.j0(mode * r_array[steps]/ domain_length[growth])) * mode_indep_time_part[growth] sol[steps] = (1 + mode_dep_time_part[growth] * sc.special.j0(mode * radius[steps]/ domain_length[growth])) * mode_indep_time_part[growth]
# move the mesh # move the mesh
displacement = df.project(velocity * dt, VFS) displacement = df.project(velocity * dt, VFS)
df.ALE.move(mesh, displacement) df.ALE.move(mesh, displacement)
# update time # update time
t += dt t += dts
# visualise the solution ###################### visualise the analytical solution #######################################################
if d==1: if d==1:
fig, axc = plt.subplots(1,1, figsize=(8,8)) fig, axc = plt.subplots(1,1, figsize=(8,8))
axc.set_xlabel(r'$x$') axc.set_xlabel(r'$x$')
axc.set_xlim(np.min(r_array), np.max(r_array)) axc.set_xlim(np.min(radius), np.max(radius))
axc.set_ylim(np.min(sol), np.max(sol)) axc.set_ylim(min(np.min(sol), np.min(concentration)), max(np.max(sol), np.max(concentration)))
axc.set_ylabel(r'$c(x,t)$') axc.set_ylabel(r'$c(x,t)$')
cplot, = axc.plot(r_array[0], sol[0]) c_exactplot, = axc.plot(radius[0], sol[0])
cplot, = axc.plot(radius[0], concentration[0])
def update(value): def update(value):
ti = np.abs(times-value).argmin() ti = np.abs(times-value).argmin()
cplot.set_ydata(sol[ti]) c_exactplot.set_ydata(sol[ti])
cplot.set_xdata(r_array[ti]) c_exactplot.set_xdata(radius[ti])
cplot.set_ydata(concentration[ti])
cplot.set_xdata(radius[ti])
plt.draw() plt.draw()
sax = plt.axes([0.1, 0.92, 0.7, 0.02]) sax = plt.axes([0.1, 0.92, 0.7, 0.02])
...@@ -145,17 +172,19 @@ if d==1: ...@@ -145,17 +172,19 @@ if d==1:
plt.show() plt.show()
else: else:
# for heat map
n_cmap_vals = 16 n_cmap_vals = 16
scalar_cmap = 'viridis' scalar_cmap = 'viridis'
geometry = np.dstack((geometry_array, np.zeros(geometry_array.shape[0:2]))) geometry = np.dstack((geometry, np.zeros(geometry.shape[0:2])))
cmin, cmax = np.min(sol), np.max(sol) cmin, cmax = np.min(sol), np.max(sol)
plotter = vd.plotter.Plotter(axes=0) plotter = vd.plotter.Plotter(axes=0)
poly = vd.utils.buildPolyData(geometry[0], topology_array) poly = vd.utils.buildPolyData(geometry[0], topology)
scalar_actor = vd.mesh.Mesh(poly) scalar_actor = vd.mesh.Mesh(poly)
scalar_actor.pointdata['concentration'] = sol[0] scalar_actor.pointdata['concentration'] = sol[0]
scalar_actor.cmap(scalar_cmap, sol[0], vmin=cmin, vmax=cmax, n=n_cmap_vals) scalar_actor.cmap(scalar_cmap, sol[0], vmin=cmin, vmax=cmax, n=n_cmap_vals)
scalar_actor.add_scalarbar(title = r'$c$', scalar_actor.add_scalarbar(title = r'$c_{analytical}$',
pos=(0.8, 0.04), nlabels=2, pos=(0.8, 0.04), nlabels=2,
# titleYOffset=15, titleFontSize=28, size=(100, 600) # titleYOffset=15, titleFontSize=28, size=(100, 600)
) )
...@@ -176,24 +205,48 @@ else: ...@@ -176,24 +205,48 @@ else:
vd.show(interactive=(not offscreen), zoom=0.8) vd.show(interactive=(not offscreen), zoom=0.8)
# make movie fig1, axc1 = plt.subplots(1,1, figsize=(8,8))
if offscreen: axc1.set_xlabel(r'$r$')
FPS = 10 axc1.set_xlim(np.min(radius), np.max(radius))
movFile = '%s.mov' % dt axc1.set_ylim(np.min(sol), np.max(sol))
fps = float(FPS) axc1.set_ylabel(r'$c(r,t)$')
command = "ffmpeg -y -r" c_exactplot, = axc1.plot(radius[0], sol[0], 'o', ms=3, label='analytical solution')
options = "-b:v 3600k -qscale:v 4 -vcodec mpeg4" cplot, = axc1.plot(radius[0], concentration[0], 'o', ms=3, label='numerical solution')
tmp_dir = TemporaryDirectory() def update(value):
get_filename = lambda x: os.path.join(tmp_dir.name, x) ti = np.abs(times-value).argmin()
for tt in range(len(times)): c_exactplot.set_ydata(sol[ti])
idx = (abs(times-times[tt])).argmin() c_exactplot.set_xdata(radius[ti])
update(idx) cplot.set_ydata(concentration[ti])
slider.GetRepresentation().SetValue(times[tt]) cplot.set_xdata(radius[ti])
fr = get_filename("%03d.png" % tt) plt.draw()
vd.io.screenshot(fr)
os.system(command + " " + str(fps) sax = plt.axes([0.1, 0.92, 0.7, 0.02])
+ " -i " + tmp_dir.name + os.sep slider = Slider(sax, r'$t/\tau$', min(times), max(times),
+ "%03d.png " + options + " " + movFile) valinit=min(times), valfmt='%3.1f',
tmp_dir.cleanup() fc='#999999')
slider.drawon = False
slider.on_changed(update)
axc1.legend()
plt.show()
# make movie
if offscreen:
FPS = 10
movFile = '%s_analytical.mov' % timestamp
fps = float(FPS)
command = "ffmpeg -y -r"
options = "-b:v 3600k -qscale:v 4 -vcodec mpeg4"
tmp_dir = TemporaryDirectory()
get_filename = lambda x: os.path.join(tmp_dir.name, x)
for tt in range(len(times)):
idx = (abs(times-times[tt])).argmin()
update(idx)
slider.GetRepresentation().SetValue(times[tt])
fr = get_filename("%03d.png" % tt)
vd.io.screenshot(fr)
os.system(command + " " + str(fps)
+ " -i " + tmp_dir.name + os.sep
+ "%03d.png " + options + " " + movFile)
tmp_dir.cleanup()
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment