"""
"""
#! /usr/bin/python
# -*- coding: utf-8 -*-
# interest of this program :
# numerical experiment of heat equation (1D)
# especially time step (dt) stability
doc = """
# Heat equation
# physics : d phi / d t = alpha nabla^2 phi
# alpha = 1
# numeric : (phi_1 - phi_0) / dt = nabla2(phi_0)
# phi_1 = phi_0 + dt * nabla2(phi_0)
"""
import sys
import os
import math
import cmath
import matplotlib.pyplot
import numpy
x_min = -float(10)
x_max = float(10)
x = [ ]
nb_phi0_plot = 0
phi_initial = [ ]
def step(n):
"""
# état initial :
# definition on xmin < 0 < xmax
# xmin < x < xmin/2 : phi(x) = 0
# xmin/2 < x < xmax/2 : phi(x) = 1 # îlot central à 1
# xmax/2 < x < xmax : phi(x) = 0
"""
global x, phi_initial
if nb_phi0_plot == 0 :
print("step function phi_0(x) on [0.5 * x_min ; 0.5 * x_max ]")
x = [ float(0) for i in range(n) ]
phi_0 = [ float(0) for i in range(n) ]
for i in range(n) :
x[i] = x_min + (x_max - x_min) * float(i) / float(n-1)
if 0.5 * x_min < x[i] and x[i] < 0.5 * x_max :
# phi = step
phi_0[i] = float(1)
phi_initial = list(phi_0)
return (phi_0)
def window(i, phi) :
# we add a x symmetry on the 2 boundaries
# as if the system was surrounded by same systems
n = len(x)
x0 = x[i]
if i < n-1 :
x1 = x[i+1]
else : # i == n-1
x1 = 2 * x[i] - x[i-1]
dx = x1 - x0 # constant : does not need to be centered
# x0 boundary : phi(x0-a) = phi(x0+a)
iminus1 = i-1
if iminus1 < 0 : iminus1 +=2
iplus1 = i+1
if iplus1 > n-1 : iplus1 -=2
phim1 = phi[iminus1]
phi0 = phi[i]
phip1 = phi[iplus1]
return (phim1, phi0, phip1, dx)
def nabla2(phi) :
""" d^2phi / dx^2 : (1D laplacian)
# dphi[i+1/2] = (phi[i+1] - phi[i]) / dx
# dphi[i-1/2] = (phi[i] - phi[i-1]) / dx
# d2phi[i] = (dphi[i+1/2] - dphi[i-1/2]) / dx
# d2phi[i] = (phi[i+1] - 2 phi[i] + phi[i-1]) / dx^2
"""
n = len(x)
d2_phi = [ float(0) for i in range(n) ]
for i in range(n) :
# with x symmetry boundary conditions :
(phim1, phi0, phip1, dx) = window(i, phi)
d2_phi[i] = (phip1 - float(2) * phi0 + phim1) / pow(dx, 2)
return d2_phi
def draw_phi_initial( ):
matplotlib.pyplot.plot(x, phi_initial)
def plot_phi(x, phi) :
# displays the position of phi versus x
# print("phi=", phi)
matplotlib.pyplot.text( 0. , 0. , "O")
matplotlib.pyplot.plot(x, phi)
def mean(phi) :
# boundary points belong to two domains
phi_moy = float(0)
n = len(phi)
phi_moy += 0.5 * abs(phi[0])
for i in range(1, n-1) :
phi_moy += abs(phi[i])
phi_moy += 0.5 * abs(phi[n-1])
phi_moy /= (n-1)
return phi_moy
def analysis(phi) :
phi_moy = mean(phi)
phi_initial_moy = mean(phi_initial)
if phi_moy > float(2) * phi_initial_moy :
print(" phi_moy=", phi_moy, "(ref :", phi_initial_moy,")")
print(" -> Warning : function phi diverges !")
def heat(n, dt) :
"""
# étude de la convergence de la solution du problème de la chaleur
# selon la discrétisation dx en espace
# selon la discrétisation dt en temps
# notion : pas de temps limite de stabilité dt = 0.5 dx²
"""
global nb_phi0_plot
# print(doc)
dt_stability = 0.5 * (x_max -x_min)**2 / float((n-1)**2)
if dt > dt_stability :
print("# Pas de temps trop grand (divergence) :")
elif dt == dt_stability :
print("# Pas de temps limite de la stabilité (oscillations) :")
elif dt < dt_stability :
print("# Pas de temps assurant la stabilité de l'algorithme :")
print(" n =", n, "; dt =", dt, " (dt_stability =", dt_stability, ")")
temps = float(0)
# initial state
step(n)
# initial state drawn once
if nb_phi0_plot == 0 :
matplotlib.pyplot.title("t = 0")
plot_phi(x, phi_initial)
nb_phi0_plot += 1
# heat evolution :
phi_0 = list(phi_initial)
for i in range(1000) :
d2_phi = nabla2(phi_0)
# print("nabla^2 phi : d2_phi=", d2_phi)
phi_1 = [ float(0) for j in range(n) ]
for j in range(n) :
# phi_1 = phi_0 + dt * nabla2(phi_0)
phi_1[j] = phi_0[j] + dt * d2_phi[j]
phi_0 = phi_1
# print("phi_0[",point,"]=", phi_0[point])
if i < 10 or \
i < 100 and i % 20 == 19 :
# matplotlib.pyplot.title("t = " + str(i+1))
plot_phi(x, phi_0)
# final state
# detection of divergence : negative phi
analysis(phi_0)
title = "t = " + str(i+1) + "(n=" + str(n) + ", dt=" + str(dt) + ")"
matplotlib.pyplot.title(title)
plot_phi(x, phi_0)
draw_phi_initial()
matplotlib.pyplot.show( )
# heat equation
# equation de la chaleur
# relation de stabilite
# stability relation : dt < 0.5 dx^2
help(heat)
for n in [ 11, 21, 31 ] :
dx = (x_max -x_min) / float(n-1)
dt_stability = 0.5 * dx**2
heat(n, 1.1 * dt_stability) # diverges
heat(n, 1.0 * dt_stability) # limit diverges (does not converge)
heat(n, 0.9 * dt_stability) # stable mais oscillant
heat(n, 0.5 * dt_stability) # stable
"""
"""