From d9619d4fafbf38512642b1d8095caa05c3d18fad Mon Sep 17 00:00:00 2001 From: Eric Dalissier <Eric.Dalissier@imag.fr> Date: Thu, 6 Dec 2012 17:33:12 +0000 Subject: [PATCH] EDO solver : validated --- .../hysop/operator/differentialOperator_d.py | 52 +++++ HySoP/hysop/operator/stretching_d.py | 5 - .../particular_solvers/integrator/euler.py | 29 ++- .../integrator/integrator.py | 4 +- .../integrator/runge_kutta2.py | 30 ++- .../integrator/runge_kutta2stretching.py | 2 + .../integrator/runge_kutta3.py | 69 +++++++ .../integrator/runge_kutta4.py | 35 +++- .../integrator/runge_kutta4stretching.py | 1 + .../test_EDO_erreur.py | 179 ++++++++++++++++++ .../test/test_particular_solvers/test_RK.py | 136 +++++++------ 11 files changed, 445 insertions(+), 97 deletions(-) create mode 100755 HySoP/hysop/particular_solvers/integrator/runge_kutta3.py create mode 100644 HySoP/hysop/test/test_particular_solvers/test_EDO_erreur.py diff --git a/HySoP/hysop/operator/differentialOperator_d.py b/HySoP/hysop/operator/differentialOperator_d.py index 9493292fb..3200094aa 100755 --- a/HySoP/hysop/operator/differentialOperator_d.py +++ b/HySoP/hysop/operator/differentialOperator_d.py @@ -265,6 +265,58 @@ class DifferentialOperator_d(DiscreteOperator): self.maxgersh[0] = max(max1,max2,max3) # self.maxgersh[0] = max(maxadv1,maxadv2,maxadv3) + elif self.choice == 'divConservationGradU': + +## fourth order scheme +# First line of Grad U matrix + self.result[0][...] = (1.0 * self.field2[0][np.roll(ind,+2),...] - + 8.0 * self.field2[0][np.roll(ind,+1),...] +\ + 8.0 * self.field2[0][np.roll(ind,-1),...] -\ + 1.0 * self.field2[0][np.roll(ind,-2),...]) / (12. * mesh_size[0]) + + self.result[1][...] = (1.0 * self.field2[0][:,np.roll(ind,+2),:] -\ + 8.0 * self.field2[0][:,np.roll(ind,+1),:] +\ + 8.0 * self.field2[0][:,np.roll(ind,-1),:] -\ + 1.0 * self.field2[0][:,np.roll(ind,-2),:]) / (12. * mesh_size[1]) + + self.result[2][...] = (1.0 * self.field2[0][...,np.roll(ind,+2)] -\ + 8.0 * self.field2[0][...,np.roll(ind,+1)] +\ + 8.0 * self.field2[0][...,np.roll(ind,-1)] -\ + 1.0 * self.field2[0][...,np.roll(ind,-2)]) / (12. * mesh_size[2]) + +# Second line of Grad U matrix + self.result[3][...] = (1.0 * self.field2[1][np.roll(ind,+2),...] - + 8.0 * self.field2[1][np.roll(ind,+1),...] +\ + 8.0 * self.field2[1][np.roll(ind,-1),...] -\ + 1.0 * self.field2[1][np.roll(ind,-2),...]) / (12. * mesh_size[0]) + + self.result[4][...] = (1.0 * self.field2[1][:,np.roll(ind,+2),:] -\ + 8.0 * self.field2[1][:,np.roll(ind,+1),:] +\ + 8.0 * self.field2[1][:,np.roll(ind,-1),:] -\ + 1.0 * self.field2[1][:,np.roll(ind,-2),:]) / (12. * mesh_size[1]) + + self.result[5][...] = (1.0 * self.field2[1][...,np.roll(ind,+2)] -\ + 8.0 * self.field2[1][...,np.roll(ind,+1)] +\ + 8.0 * self.field2[1][...,np.roll(ind,-1)] -\ + 1.0 * self.field2[1][...,np.roll(ind,-2)]) / (12. * mesh_size[2]) + +# Third line of Grad U matrix + self.result[6][...] = (1.0 * self.field2[2][np.roll(ind,+2),...] - + 8.0 * self.field2[2][np.roll(ind,+1),...] +\ + 8.0 * self.field2[2][np.roll(ind,-1),...] -\ + 1.0 * self.field2[2][np.roll(ind,-2),...]) / (12. * mesh_size[0]) + + self.result[7][...] = (1.0 * self.field2[2][:,np.roll(ind,+2),:] -\ + 8.0 * self.field2[2][:,np.roll(ind,+1),:] +\ + 8.0 * self.field2[2][:,np.roll(ind,-1),:] -\ + 1.0 * self.field2[2][:,np.roll(ind,-2),:]) / (12. * mesh_size[1]) + + self.result[8][...] = (1.0 * self.field2[2][...,np.roll(ind,+2)] -\ + 8.0 * self.field2[2][...,np.roll(ind,+1)] +\ + 8.0 * self.field2[2][...,np.roll(ind,-1)] -\ + 1.0 * self.field2[2][...,np.roll(ind,-2)]) / (12. * mesh_size[2]) + + elif self.choice == 'curl': temp1 = (1.0 * self.field1[2][:,np.roll(ind,+2),:] - diff --git a/HySoP/hysop/operator/stretching_d.py b/HySoP/hysop/operator/stretching_d.py index 88ed5c5f1..0271e9b8c 100755 --- a/HySoP/hysop/operator/stretching_d.py +++ b/HySoP/hysop/operator/stretching_d.py @@ -72,7 +72,6 @@ class Stretching_d(DiscreteOperator): self.stretchTerm.discreteOperator.apply() # Time integration of dw/dt = div(wu) -# self.method=Euler ndt = self.stabilityTest(dt, self.maxgersh, self.method) dtstretch = dt/float(ndt) @@ -84,20 +83,16 @@ class Stretching_d(DiscreteOperator): for i in range(self.vorticity.topology.dim): self.res_vorticity[i][...] = methodInt.integrate(self.vorticity, self.stretchTermResult, t, dtstretch, direction=i) -# self.method=RK2Stretch if RK2Stretch == self.method : print "RK2" methodInt=self.method(self.stretchTerm.discreteOperator) self.res_vorticity = methodInt.integrate(self.stretchTerm, self.stretchTermResult, self.vorticity, self.velocity, self.res_vorticity, t, dtstretch, self.vorticity.topology.dim) -# self.method=RK3Stretch if RK3Stretch == self.method : print "RK3" methodInt=self.method(self.stretchTerm.discreteOperator) self.res_vorticity = methodInt.integrate(self.stretchTerm, self.stretchTermResult, self.vorticity, self.velocity, self.res_vorticity, t, dtstretch, self.vorticity.topology.dim) - -# self.method=RK4Stretch if RK4Stretch == self.method : print "RK4" methodInt=self.method(self.stretchTerm.discreteOperator) diff --git a/HySoP/hysop/particular_solvers/integrator/euler.py b/HySoP/hysop/particular_solvers/integrator/euler.py index 8c5f8468c..7fbca8814 100755 --- a/HySoP/hysop/particular_solvers/integrator/euler.py +++ b/HySoP/hysop/particular_solvers/integrator/euler.py @@ -4,6 +4,7 @@ Forward Euler method. """ from .integrator import ODESolver +import numpy as np #providedClass = "Euler" @@ -27,17 +28,31 @@ class Euler(ODESolver): """ ODESolver.__init__(self, f) - def integrate(self, y, f, t, dt, direction): +# def integrate(self, y, f, t, dt, direction): +# """ +# Integration step for forward Euler method. +# y(t_{n+1}) = y(t_n) + dt*f(y(t_n)) + +# @param y : position at time t. +# @param t : current time. +# @param dt : time step. +# @return y at t+dt. +# """ +# return y[direction][...] +dt * f[direction][...] + + def integrate(self, f, t , dt , u, topo ): """ - Integration step for forward Euler method. - y(t_{n+1}) = y(t_n) + dt*f(y(t_n)) + Integration step for Euler Method. + up = f[t, u(t,x,y,z)]. - @param y : position at time t. + @param u : function of position at time t. + @param f : function of function of position at time t. @param t : current time. @param dt : time step. - @return y at t+dt. - """ - return y[direction][...] +dt * f[direction][...] +# """ + result = u[:,:,:,:] + dt * np.asarray(f(t,u[:,:,:,:])) + return result + def __str__(self): """ToString method""" diff --git a/HySoP/hysop/particular_solvers/integrator/integrator.py b/HySoP/hysop/particular_solvers/integrator/integrator.py index f915d1a96..f418635a0 100644 --- a/HySoP/hysop/particular_solvers/integrator/integrator.py +++ b/HySoP/hysop/particular_solvers/integrator/integrator.py @@ -4,7 +4,7 @@ ODESolver interface. """ from ...constants import * - +import numpy as np class ODESolver: """ @@ -23,7 +23,7 @@ class ODESolver: if f != None: self.f = f else: - self.f = lambda t, y: [0. for x in y] + self.f = lambda t, y: np.vectorize(f)(t,y)# [0. for x in y] def integrate(self, y, t, dt): """ diff --git a/HySoP/hysop/particular_solvers/integrator/runge_kutta2.py b/HySoP/hysop/particular_solvers/integrator/runge_kutta2.py index b9056f0c3..98982cf82 100755 --- a/HySoP/hysop/particular_solvers/integrator/runge_kutta2.py +++ b/HySoP/hysop/particular_solvers/integrator/runge_kutta2.py @@ -4,6 +4,7 @@ RK2 method interface. """ from .integrator import ODESolver +import numpy as np class RK2(ODESolver): @@ -24,18 +25,35 @@ class RK2(ODESolver): """ ODESolver.__init__(self, f) - def integrate(self, y, fy, yp, t, dt, dir): +# def integrate(self, y, fy, yp, t, dt, dir): +# """ +# Integration step for RK2 Method. +# yp= y + dt*y'[y+dt/2*y'(y)]. + +# @param y : position at time t. +# @param fy : y'(y) value at time t. +# @param yp : result position at time t + dt +# @param t : current time. +# @param dt : time step. +# """ +# pass + + def integrate(self, f, t , dt , u, topo ): + """ Integration step for RK2 Method. - yp= y + dt*y'[y+dt/2*y'(y)]. + up = f[t, u(t,x,y,z)]. - @param y : position at time t. - @param fy : y'(y) value at time t. - @param yp : result position at time t + dt + @param u : function of position at time t. + @param f : function of function of position at time t. @param t : current time. @param dt : time step. """ - pass +#K1 = dt *f[t,u(t,x,y,z)] + K1 = dt * np.asarray(f(t,u)) +#result = u(t,x,y,z)] + dt *f[t + dt/2 , u(t,x,y,z) + k1/2.] + result = u + dt *np.asarray(f(t+dt/2.,u + K1/2.)) + return result def __str__(self): """ToString method""" diff --git a/HySoP/hysop/particular_solvers/integrator/runge_kutta2stretching.py b/HySoP/hysop/particular_solvers/integrator/runge_kutta2stretching.py index 8fb0bca80..25e7b282c 100755 --- a/HySoP/hysop/particular_solvers/integrator/runge_kutta2stretching.py +++ b/HySoP/hysop/particular_solvers/integrator/runge_kutta2stretching.py @@ -32,6 +32,7 @@ class RK2Stretch(ODESolver): def integrate(self, f, fd ,field1 , field2, res_vorticity, t, dt, dimension): +# def integrate(self, f,field1 , field2, res_vorticity, t, dt, dimension): """ Integration step for RK4 Method yp= y + dt*y'[y+dt/2*y'(y)]. @@ -44,6 +45,7 @@ class RK2Stretch(ODESolver): @param t : current time. @param dt : time step. """ + print "ehoh bis" maxgersh = np.zeros(1, dtype=PARMES_REAL, order=ORDER) resultTmp = np.asarray([np.zeros((field2.topology.resolution), dtype=PARMES_REAL, order=ORDER) for d in xrange(field2.topology.dim)]) K1=np.asarray(fd) diff --git a/HySoP/hysop/particular_solvers/integrator/runge_kutta3.py b/HySoP/hysop/particular_solvers/integrator/runge_kutta3.py new file mode 100755 index 000000000..6438426ef --- /dev/null +++ b/HySoP/hysop/particular_solvers/integrator/runge_kutta3.py @@ -0,0 +1,69 @@ +# -*- coding: utf-8 -*- +""" +@package Utils +RK3 method interface. +""" +from .integrator import ODESolver +import numpy as np + + +class RK3(ODESolver): + """ + ODESolver implementation for solving an equation system with RK3 method. + y'(t) = f(t,y) + + y(t_n+1)= y(t_n) + dt*y'[y(t_n)+dt/2*y'(y(t_n))]. + + """ + def __init__(self, f=None, dim=3): + """ + Constructor. + + @param f function f(t,y) : Right hand side of the equation to solve. + @param dim : dimensions + @param conditions : function to apply boundary conditions. + """ + ODESolver.__init__(self, f) + +# def integrate(self, y, fy, yp, t, dt, dir): +# """ +# Integration step for RK3 Method. +# yp= y + dt*y'[y+dt/2*y'(y)]. + +# @param y : position at time t. +# @param fy : y'(y) value at time t. +# @param yp : result position at time t + dt +# @param t : current time. +# @param dt : time step. +# """ +# pass + + def integrate(self, f, t , dt , u, topo ): + + """ + Integration step for RK3 Method. + up = f[t, u(t,x,y,z)]. + + @param u : function of position at time t. + @param f : function of function of position at time t. + @param t : current time. + @param dt : time step. + """ +#K1 = dt *f[t,u(t,x,y,z)] + K1 = dt * np.asarray(f(t,u)) +#result = u(t,x,y,z)] + dt *f[t + dt/2 , u(t,x,y,z) + k1/2.] + K2 = dt *np.asarray(f(t+dt/3.,u + K1[:,:,:,:]/3.)) + K3 = dt *np.asarray(f(t+dt*2./3.,u + K2[:,:,:,:]*2./3.)) +#result = u(t,x,y,z)] + 1/4 [ k1 + 3 k3] + result = u + 1./4.*(K1+3.*K3) + return result + + def __str__(self): + """ToString method""" + return "RK3 Method" + + +if __name__ == "__main__": + print __doc__ + print "- Provided class : RK3" + print RK3.__doc__ diff --git a/HySoP/hysop/particular_solvers/integrator/runge_kutta4.py b/HySoP/hysop/particular_solvers/integrator/runge_kutta4.py index 6abd3e777..1bbedadc1 100755 --- a/HySoP/hysop/particular_solvers/integrator/runge_kutta4.py +++ b/HySoP/hysop/particular_solvers/integrator/runge_kutta4.py @@ -4,6 +4,7 @@ RK4 method interface. """ from .integrator import ODESolver +import numpy as np class RK4(ODESolver): @@ -24,18 +25,38 @@ class RK4(ODESolver): """ ODESolver.__init__(self, f) - def integrate(self, y, fy, yp, t, dt): +# def integrate(self, y, fy, yp, t, dt, dir): +# """ +# Integration step for RK4 Method. +# yp= y + dt*y'[y+dt/2*y'(y)]. + +# @param y : position at time t. +# @param fy : y'(y) value at time t. +# @param yp : result position at time t + dt +# @param t : current time. +# @param dt : time step. +# """ +# pass + + def integrate(self, f, t , dt , u, topo ): + """ - Integration step for RK2 Method. - yp= y + dt*y'[y+dt/2*y'(y)]. + Integration step for RK4 Method. + up = f[t, u(t,x,y,z)]. - @param y : position at time t. - @param fy : y'(y) value at time t. - @param yp : result position at time t + dt + @param u : function of position at time t. + @param f : function of function of position at time t. @param t : current time. @param dt : time step. """ - pass +#K1 = dt *f[t,u(t,x,y,z)] + K1 = dt * np.asarray(f(t,u)) + K2 = dt *np.asarray(f(t+dt/2.,u + K1[:,:,:,:]/2.)) + K3 = dt *np.asarray(f(t+dt/2.,u + K2[:,:,:,:]/2.)) + K4 = dt *np.asarray(f(t+dt,u + K3[:,:,:,:])) +#result = u(t,x,y,z)] + dt *f[t + dt/2 , u(t,x,y,z) + k1/2.] + result = u + 1./6. * (K1[:,:,:,:] + 2.*K2[:,:,:,:] + 2.*K3[:,:,:,:]+ K4[:,:,:,:]) + return result def __str__(self): """ToString method""" diff --git a/HySoP/hysop/particular_solvers/integrator/runge_kutta4stretching.py b/HySoP/hysop/particular_solvers/integrator/runge_kutta4stretching.py index 6f35ba8f2..b16238fbd 100755 --- a/HySoP/hysop/particular_solvers/integrator/runge_kutta4stretching.py +++ b/HySoP/hysop/particular_solvers/integrator/runge_kutta4stretching.py @@ -42,6 +42,7 @@ class RK4Stretch(ODESolver): @param t : current time. @param dt : time step. """ + print "ehoh" maxgersh = np.zeros(1, dtype=PARMES_REAL, order=ORDER) resultTmp = np.asarray([np.zeros((field2.topology.resolution), dtype=PARMES_REAL, order=ORDER) for d in xrange(field2.topology.dim)]) K1=np.asarray(fd) diff --git a/HySoP/hysop/test/test_particular_solvers/test_EDO_erreur.py b/HySoP/hysop/test/test_particular_solvers/test_EDO_erreur.py new file mode 100644 index 000000000..64487fbc4 --- /dev/null +++ b/HySoP/hysop/test/test_particular_solvers/test_EDO_erreur.py @@ -0,0 +1,179 @@ +# -*- coding: utf-8 -*- +import time +import parmepy as pp +from parmepy.particular_solvers.integrator.euler import Euler +from parmepy.particular_solvers.integrator.runge_kutta2 import RK2 +from parmepy.particular_solvers.integrator.runge_kutta3 import RK3 +from parmepy.particular_solvers.integrator.runge_kutta4 import RK4 +from parmepy.particular_solvers.integrator.runge_kutta2stretching import RK2Stretch +from parmepy.particular_solvers.integrator.runge_kutta3stretching import RK3Stretch +from parmepy.particular_solvers.integrator.runge_kutta4stretching import RK4Stretch +from math import * +import unittest +import numpy as np +import numpy.testing as npt +import copy +import matplotlib.pyplot as plt +from parmepy.constants import * + + +class test_EDO(unittest.TestCase): + """ + DiscreteVariable test class + """ + + def analyticalSolution(self,t, x, y, z): + sx = (t*np.exp(t) + 1.) * np.exp(-t) + sy = (t*np.exp(t) + 1.) * np.exp(-t) + sz = (t*np.exp(t) + 1.) * np.exp(-t) + return sx, sy, sz + + def f (self, t, u): + fx = -u[0][:,:,:] + t + 1. + fy = -u[1][:,:,:] + t + 1. + fz = -u[2][:,:,:] + t + 1. + return fx , fy ,fz + + def U (self, t, x, y, z) : + wx = 1. + wy = 1. + wz = 1. + return wx, wy, wz + + def testIntegratorEDO(self): + # Parameters + nb = 32 + timeStep = 0.1 + finalTime = 1.0 + multi = 2. + maxerror=0. + + t0 = time.time() + self.t = 0. + ## Domain + box = pp.Box(3, length=[4.*np.pi, 4.*np.pi, 4.*np.pi], + origin=[- 2.*np.pi,- 2.*np.pi,- 2.*np.pi]) + + +##################################################################################### + + ## Solver creation (discretisation of objects is done in solver initialisation) + topo3D = pp.CartesianTopology(domain=box, resolution=[nb, nb, nb], dim=3) + + Result=np.asarray([np.zeros([nb, nb, nb], + dtype=PARMES_REAL, order=ORDER) for d in xrange(3)]) + Analvorty=np.asarray([np.zeros([nb, nb, nb], + dtype=PARMES_REAL, order=ORDER) for d in xrange(3)]) + + compteur = 0 + taille = int(finalTime / timeStep) +1 + compteur = 0 + dt = np.zeros([taille], dtype=PARMES_REAL, order=ORDER) + errEuler = np.zeros([taille], dtype=PARMES_REAL, order=ORDER) + errRK2 = np.zeros([taille], dtype=PARMES_REAL, order=ORDER) + errRK3 = np.zeros([taille], dtype=PARMES_REAL, order=ORDER) + errRK4 = np.zeros([taille], dtype=PARMES_REAL, order=ORDER) + UEuler = np.asarray([np.zeros([nb, nb, nb], dtype=PARMES_REAL, + order=ORDER) for d in xrange(3)]) + URK2 = np.asarray([np.zeros([nb, nb, nb], dtype=PARMES_REAL, + order=ORDER) for d in xrange(3)]) + URK3 = np.asarray([np.zeros([nb, nb, nb], dtype=PARMES_REAL, + order=ORDER) for d in xrange(3)]) + URK4 = np.asarray([np.zeros([nb, nb, nb], dtype=PARMES_REAL, + order=ORDER) for d in xrange(3)]) + + UEuler[:,:,:,:] = 1. + URK2[:,:,:,:] = 1. + URK3[:,:,:,:] = 1. + URK4[:,:,:,:] = 1. + + Analvorty[:,:,:,:]=np.vectorize(self.analyticalSolution)(timeStep, + topo3D.mesh.coords[0], \ + topo3D.mesh.coords[1], \ + topo3D.mesh.coords[2])[:] + + while self.t < finalTime : + print "t", self.t + + # Euler + self.method= Euler + methodInt=self.method(self.f) + Result = methodInt.integrate(self.f, self.t , timeStep , UEuler, topo3D) + UEuler = Result + errEuler[compteur]= np.max (abs(Analvorty[:,:,:,:] - Result[:,:,:,:])) + + # RK2 + self.method= RK2 + methodInt=self.method(self.f) + Result = methodInt.integrate(self.f, self.t , timeStep , URK2, topo3D) + URK2 = Result + errRK2[compteur]= np.max (abs(Analvorty[:,:,:,:] - Result[:,:,:,:])) + + # RK3 + self.method= RK3 + methodInt=self.method(self.f) + Result = methodInt.integrate(self.f, self.t , timeStep , URK3, topo3D) + URK3 = Result + errRK3[compteur]= np.max (abs(Analvorty[:,:,:,:] - Result[:,:,:,:])) + + # RK4 + self.method= RK4 + methodInt=self.method(self.f) + Result = methodInt.integrate(self.f, self.t , timeStep , URK4, topo3D) + URK4 = Result + errRK4[compteur]= np.max (abs(Analvorty[:,:,:,:] - Result[:,:,:,:])) + dt[compteur] = self.t + + self.t = self.t + timeStep + Analvorty[:,:,:,:]=np.vectorize(self.analyticalSolution)(self.t + timeStep, + topo3D.mesh.coords[0], \ + topo3D.mesh.coords[1], \ + topo3D.mesh.coords[2])[:] + compteur = compteur + 1 + + npt.assert_array_less(errEuler,timeStep) + npt.assert_array_less(errRK2,timeStep**2) + npt.assert_array_less(errRK3,timeStep**3) + npt.assert_array_less(errRK4,timeStep**4) + + ## Table of error values +# print "erreur Euler", errEuler +# print "erreur RK2", errRK2 +# print "erreur RK3", errRK3 +# print "erreur RK4", errRK4 + + ## Plot error_scheme vs time +# plt.figure(1) +# plt.subplot(211) +# plt.xlabel('dt') +# plt.xscale('log') +# plt.ylabel('Erreur') +# plt.yscale('log') +# plt.plot(dt, errEuler, '+-',dt ,errRK2, '+-' ,dt, errRK3, '+-',dt,errRK4, '+-') +# plt.legend([u"Euler", u"RK2", u"RK3", u"RK4"], loc=4) +# plt.subplot(212) +# plt.xlabel('dt') +# plt.ylabel('Erreur') +# plt.plot(dt, errEuler, '+-',dt ,errRK2, '+-' ,dt, errRK3, '+-',dt,errRK4, '+-') +# plt.legend([u"Euler", u"RK2", u"RK3", u"RK4"], loc=4) + + plt.show() + + t1 = time.time() + + print "\n" +# print "Total time : ", tf - t0, "sec (CPU)" +# print "Init time : ", t1 - t0, "sec (CPU)" +# print "Solving time : ", tf - t1, "sec (CPU)" + + + def runTest(self): + self.testIntegratorEDO() + +def suite(): + suite = unittest.TestSuite() + suite.addTest(unittest.makeSuite(test_EDO)) + return suite + +if __name__ == "__main__": + unittest.TextTestRunner(verbosity=2).run(suite()) diff --git a/HySoP/hysop/test/test_particular_solvers/test_RK.py b/HySoP/hysop/test/test_particular_solvers/test_RK.py index 7281ecb4e..70ed6aa89 100644 --- a/HySoP/hysop/test/test_particular_solvers/test_RK.py +++ b/HySoP/hysop/test/test_particular_solvers/test_RK.py @@ -2,6 +2,9 @@ import time import parmepy as pp from parmepy.particular_solvers.integrator.euler import Euler +from parmepy.particular_solvers.integrator.runge_kutta2 import RK2 +from parmepy.particular_solvers.integrator.runge_kutta3 import RK3 +from parmepy.particular_solvers.integrator.runge_kutta4 import RK4 from parmepy.particular_solvers.integrator.runge_kutta2stretching import RK2Stretch from parmepy.particular_solvers.integrator.runge_kutta3stretching import RK3Stretch from parmepy.particular_solvers.integrator.runge_kutta4stretching import RK4Stretch @@ -15,7 +18,7 @@ from parmepy.constants import * -class test_Stretching(unittest.TestCase): +class test_RK(unittest.TestCase): """ DiscreteVariable test class """ @@ -27,43 +30,37 @@ class test_Stretching(unittest.TestCase): return vx, vy, vz def vorticite(self, x, y, z): - wx = self.t+1. - wy = self.t+1. - wz = self.t+1. + wx = self.t**2+1. + wy = self.t**2+1. + wz = self.t**2+1. return wx, wy, wz - def analyticalSolution(self, x, y, z): - sx = (0.5*(self.t*self.t)+self.t) * np.cos(x) - sy = (0.5*(self.t*self.t)+self.t) * np.cos(y) - sz = (0.5*(self.t*self.t)+self.t) * np.cos(z) + def analyticalSolution(self,t, x, y, z): + sx = t**2 - (t + t**3 /3.) * np.cos(x) + sy = t**2 - (t + t**3 /3.) * np.cos(y) + sz = t**2 - (t + t**3 /3.) * np.cos(z) return sx, sy, sz - def correctionRK2(self,x, y ,z): - cx = np.cos(x) * np.cos(x)* self.t*self.t*( ( 1./2. + self.t/4. ) ) - cy = np.cos(y) * np.cos(y)* self.t*self.t*( ( 1./2. + self.t/4. ) ) - cz = np.cos(z) * np.cos(z)* self.t*self.t*( ( 1./2. + self.t/4. ) ) - return cx, cy, cz - - def correctionRK3(self,x, y ,z): - cx = np.cos(x) * np.cos(x)* self.t*self.t*( ( 1./2. + self.t/2. ) + np.cos(x) * self.t *(1./6. + self.t/6.) ) - cy = np.cos(y) * np.cos(y)* self.t*self.t*( ( 1./2. + self.t/2. ) + np.cos(y) * self.t *(1./6. + self.t/6.) ) - cz = np.cos(z) * np.cos(z)* self.t*self.t*( ( 1./2. + self.t/2. ) + np.cos(z) * self.t *(1./6. + self.t/6.) ) - return cx, cy, cz - - def correctionRK4(self,x, y ,z): - cx = 1./6. * (-np.cos(x) * (self.t)**2 + (np.cos(x))**2 * (self.t)**2 * (3. + 7./2. * self.t) + \ - 1./2. * (self.t)**3 * (np.cos(x))**3 * (2. + 3. * self.t) + 1./4. * (self.t)**4 * (np.cos(x))**4 * (1. + 2. * self.t)) - cy = 1./6. * (-np.cos(y) * (self.t)**2 + (np.cos(y))**2 * (self.t)**2 * (3. + 7./2. * self.t) + \ - 1./2. * (self.t)**3 * (np.cos(y))**3 * (2. + 3. * self.t) + 1./4. * (self.t)**4 * (np.cos(y))**4 * (1. + 2. * self.t)) - cz = 1./6. * (-np.cos(z) * (self.t)**2 + (np.cos(z))**2 * (self.t)**2 * (3. + 7./2. * self.t) + \ - 1./2. * (self.t)**3 * (np.cos(z))**3 * (2. + 3. * self.t) + 1./4. * (self.t)**4 * (np.cos(z))**4 * (1. + 2. * self.t)) - return cx, cy, cz - - def testOperatorStretching(self): + def f (self, t, u): + fx = 2.*t -u[0][:,:,:] + fy = 2.*t -u[1][:,:,:] + fz = 2.*t -u[2][:,:,:] + return fx , fy ,fz + + + def wgradu (self, t, x, y, z) : + wx =( 1 + t**2 )* np.cos(x) + wy =( 1 + t**2 )* np.cos(y) + wz =( 1 + t**2 )* np.cos(z) + return wx, wy, wz + + + def testIntegratorRK(self): # Parameters - nb = 64 + nb = 32 timeStep = 0.01 finalTime = 0.01 + maxerror=0. t0 = time.time() self.t = 0. @@ -74,70 +71,69 @@ class test_Stretching(unittest.TestCase): ##################################################################################### ## Fields - velo = pp.AnalyticalField(domain=box, formula=self.vitesse, name='Velocity', vector=True) - vorti = pp.AnalyticalField(domain=box, formula=self.vorticite, name='Vorticity', vector=True) +# velo = pp.AnalyticalField(domain=box, formula=self.vitesse, name='Velocity', vector=True) +# vorti = pp.AnalyticalField(domain=box, formula=self.vorticite, name='Vorticity', vector=True) ## Operators - stretch = pp.Stretching(velo,vorti) +# stretch = pp.Stretching(velo,vorti) ## Solver creation (discretisation of objects is done in solver initialisation) topo3D = pp.CartesianTopology(domain=box, resolution=[nb, nb, nb], dim=3) ##Problem - pb = pp.Problem(topo3D, [stretch]) +# pb = pp.Problem(topo3D, [stretch]) ## Setting solver to Problem - pb.setSolver(finalTime, timeStep, solver_type='basic') +# pb.setSolver(finalTime, timeStep, solver_type='basic') + + Result=np.asarray([np.zeros([nb, nb, nb], dtype=PARMES_REAL, order=ORDER) for d in xrange(3)]) Analvorty=np.asarray([np.zeros([nb, nb, nb], dtype=PARMES_REAL, order=ORDER) for d in xrange(3)]) - Analvorty[:,:,:,:]= np.vectorize(self.vorticite)(topo3D.mesh.coords[0], \ - topo3D.mesh.coords[1], \ - topo3D.mesh.coords[2])[:] - Analvorty2=np.asarray([np.zeros([nb, nb, nb], dtype=PARMES_REAL, order=ORDER) for d in xrange(3)]) - Analvorty2[:,:,:,:]= np.vectorize(self.vorticite)(topo3D.mesh.coords[0], \ + Analvorty[:,:,:,:]= np.vectorize(self.wgradu)(self.t,topo3D.mesh.coords[0], \ topo3D.mesh.coords[1], \ topo3D.mesh.coords[2])[:] - pb.solver.ODESolver= RK3Stretch #RK2Stretch #Euler#RK4Stretch # + self.method= RK3 # RK3Stretch #RK2Stretch #RK4Stretch #Euler #RK4 # + + print "\nODE SOLVER :: ", self.method + + methodInt=self.method(self.f) + Result = methodInt.integrate(self.f, self.t , timeStep , self.wgradu, topo3D) - print "\nODE SOLVER :: ", pb.solver.ODESolver - pb.initSolver() + if Euler == self.method : + maxerror = abs((timeStep**2 - 1./3. * timeStep**3)-.0) + timeStep**3 + if RK2 == self.method : + maxerror = abs((-1./3. * timeStep**3) - (0.5* timeStep**2)) + timeStep**8 + if RK3 == self.method : + maxerror = abs(0. - (0.5* timeStep**2 - 1./6. * timeStep**3)) + timeStep**3 + if RK4 == self.method : + maxerror = abs((timeStep**2 - 1./3. * timeStep**3) - (7./6.* timeStep**2 - 1./2. * timeStep**3 + 1./8. * timeStep**4)) + + +# pb.initSolver() t1 = time.time() ## Solve problem - pb.solve() - self.t = pb.timer.t - Analvorty[:,:,:,:]=Analvorty[:,:,:,:]+np.vectorize(self.analyticalSolution)(topo3D.mesh.coords[0], \ +# pb.solve() + self.t = self.t + timeStep + Analvorty[:,:,:,:]=Analvorty[:,:,:,:]+np.vectorize(self.analyticalSolution)(self.t, topo3D.mesh.coords[0], \ topo3D.mesh.coords[1], \ topo3D.mesh.coords[2])[:] - Analvorty2[:,:,:,:]=Analvorty2[:,:,:,:]+np.vectorize(self.analyticalSolution)(topo3D.mesh.coords[0], \ - topo3D.mesh.coords[1], \ - topo3D.mesh.coords[2])[:] + np.vectorize(self.correctionRK3)(topo3D.mesh.coords[0], \ - topo3D.mesh.coords[1], \ - topo3D.mesh.coords[2])[:] - - ## Visual comparison between the numerical resolution and the analytical resolution for i in range(1): plt.figure(1) - plt.subplot(221) + plt.subplot(211) plt.axis([-2*np.pi,2*np.pi,np.min(Analvorty[i][:,0,0]),np.max(Analvorty[i][:,0,0])]) - plt.plot(topo3D.mesh.coords[0][:,0,0], Analvorty[i][:,0,0], '-' ,topo3D.mesh.coords[0][:,0,0],vorti.discreteField[i].data[i][:,0,0], '-' ) - plt.legend([u"Solution Analytique", u"Solution Numérique"]) - plt.subplot(223) - plt.axis([-2*np.pi,2*np.pi,0,max(abs(Analvorty[i][:,0,0] - vorti.discreteField[i].data[i][:,0,0]))]) - plt.plot(topo3D.mesh.coords[0][:,0,0], abs(Analvorty[i][:,0,0] - vorti.discreteField[i].data[i][:,0,0]), '-' ) - plt.legend([u"Erreur"]) - plt.subplot(222) - plt.axis([-2*np.pi,2*np.pi,np.min(Analvorty2[i][:,0,0]),np.max(Analvorty2[i][:,0,0])]) - plt.plot(topo3D.mesh.coords[0][:,0,0], Analvorty2[i][:,0,0], '-' ,topo3D.mesh.coords[0][:,0,0],vorti.discreteField[i].data[i][:,0,0], '-' ) + plt.plot(topo3D.mesh.coords[0][:,0,0], Analvorty[i][:,0,0], '-' ,topo3D.mesh.coords[0][:,0,0],Result[i][:,0,0], '-' ) plt.legend([u"Solution Analytique", u"Solution Numérique"]) - plt.subplot(224) - plt.axis([-2*np.pi,2*np.pi,0,max(abs(Analvorty2[i][:,0,0] - vorti.discreteField[i].data[i][:,0,0]))]) - plt.plot(topo3D.mesh.coords[0][:,0,0], abs(Analvorty2[i][:,0,0] - vorti.discreteField[i].data[i][:,0,0]), '-' ) + plt.subplot(212) + plt.axis([-2*np.pi,2*np.pi,0,max(abs(Analvorty[i][:,0,0] - Result[i][:,0,0]))]) + plt.plot(topo3D.mesh.coords[0][:,0,0], abs(Analvorty[i][:,0,0] - Result[i][:,0,0]), '-' ) plt.legend([u"Erreur"]) + plt.ax = plt.gca() + plt.ax.ticklabel_format(style='sci', axis='y') plt.show() - npt.assert_array_less(abs(Analvorty[:,:,:,:] - vorti.discreteField[0].data[:,:,:]),0.002) + npt.assert_array_less(abs(Analvorty[:,:,:,:] - Result[:,:,:,:]),maxerror) tf = time.time() print "\n" @@ -147,11 +143,11 @@ class test_Stretching(unittest.TestCase): def runTest(self): - self.testOperatorStretching() + self.testIntegratorRK() def suite(): suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(test_Stretching)) + suite.addTest(unittest.makeSuite(test_RK)) return suite if __name__ == "__main__": -- GitLab