Buckets:
| import numpy as np | |
| import matplotlib.pyplot as plt | |
| def solver(I, a, T, dt, theta): | |
| """Solve u'=-a*u, u(0)=I, for t in (0,T] with steps of dt.""" | |
| dt = float(dt) # avoid integer division | |
| Nt = int(round(T/dt)) # no of time intervals | |
| T = Nt*dt # adjust T to fit time step dt | |
| u = np.zeros(Nt+1) # array of u[n] values | |
| t = np.linspace(0, T, Nt+1) # time mesh | |
| u[0] = I # assign initial condition | |
| for n in range(0, Nt): # n=0,1,...,Nt-1 | |
| u[n+1] = (1 - (1-theta)*a*dt)/(1 + theta*dt*a)*u[n] | |
| return u, t | |
| def exact_solution(t, I, a): | |
| return I*np.exp(-a*t) | |
| def experiment_print_error(): | |
| I = 1; a = 2; T = 4; dt = 0.4; theta = 1 | |
| u, t = solver(I, a, T, dt, theta) | |
| t_e = np.linspace(0, T, 1001) # very fine mesh for u_e | |
| u_e = exact_solution(t_e, I, a) | |
| eror = exact_solution(t, I, a) - u | |
| E = np.sqrt(dt*np.sum(eror**2)) | |
| print 'Error:', E | |
| def experiment_compare_numerical_and_exact(): | |
| I = 1; a = 2; T = 4; dt = 0.4; theta = 1 | |
| u, t = solver(I, a, T, dt, theta) | |
| t_e = np.linspace(0, T, 1001) # very fine mesh for u_e | |
| u_e = exact_solution(t_e, I, a) | |
| plt.plot(t, u, 'r--o') # dashed red line with circles | |
| plt.plot(t_e, u_e, 'b-') # blue line for u_e | |
| plt.legend(['numerical, theta=%g' % theta, 'exact']) | |
| plt.xlabel('t') | |
| plt.ylabel('u') | |
| plotfile = 'tmp' | |
| plt.savefig(plotfile + '.png'); plt.savefig(plotfile + '.pdf') | |
| error = exact_solution(t, I, a) - u | |
| E = np.sqrt(dt*np.sum(error**2)) | |
| print 'Error:', E | |
| def experiment_compare_schemes(): | |
| """Compare theta=0,1,0.5 in the same plot.""" | |
| I = 1; a = 2; T = 4; dt = 0.4 | |
| legends = [] | |
| for theta in [0, 1, 0.5]: | |
| u, t = solver(I, a, T, dt, theta) | |
| plt.plot(t, u, '--o') # dashed lines with circles | |
| legends.append('theta=%g' % theta) | |
| t_e = np.linspace(0, T, 1001) # very fine mesh for u_e | |
| u_e = exact_solution(t_e, I, a) | |
| plt.plot(t_e, u_e, 'b-') # blue line for u_e | |
| legends.append('exact') | |
| plt.legend(legends, loc='upper right') | |
| plotfile = 'tmp' | |
| plt.savefig(plotfile + '.png'); plt.savefig(plotfile + '.pdf') | |
| import sys | |
| def read_command_line_positional(): | |
| if len(sys.argv) < 6: | |
| print 'Usage: %s I a T on/off BE/FE/CN dt1 dt2 dt3 ...' % \ | |
| sys.argv[0]; sys.exit(1) # abort | |
| I = float(sys.argv[1]) | |
| a = float(sys.argv[2]) | |
| T = float(sys.argv[3]) | |
| # Name of schemes: BE (Backward Euler), FE (Forward Euler), | |
| # CN (Crank-Nicolson) | |
| scheme = sys.argv[4] | |
| scheme2theta = {'BE': 1, 'CN': 0.5, 'FE': 0} | |
| if scheme in scheme2theta: | |
| theta = scheme2theta[scheme] | |
| else: | |
| print 'Invalid scheme name:', scheme; sys.exit(1) | |
| dt_values = [float(arg) for arg in sys.argv[5:]] | |
| return I, a, T, theta, dt_values | |
| def define_command_line_options(): | |
| import argparse | |
| parser = argparse.ArgumentParser() | |
| parser.add_argument( | |
| '--I', '--initial_condition', type=float, | |
| default=1.0, help='initial condition, u(0)', | |
| metavar='I') | |
| parser.add_argument( | |
| '--a', type=float, default=1.0, | |
| help='coefficient in ODE', metavar='a') | |
| parser.add_argument( | |
| '--T', '--stop_time', type=float, | |
| default=1.0, help='end time of simulation', | |
| metavar='T') | |
| parser.add_argument( | |
| '--scheme', type=str, default='CN', | |
| help='FE, BE, or CN') | |
| parser.add_argument( | |
| '--dt', '--time_step_values', type=float, | |
| default=[1.0], help='time step values', | |
| metavar='dt', nargs='+', dest='dt_values') | |
| return parser | |
| def read_command_line_argparse(): | |
| parser = define_command_line_options() | |
| args = parser.parse_args() | |
| scheme2theta = {'BE': 1, 'CN': 0.5, 'FE': 0} | |
| data = (args.I, args.a, args.T, scheme2theta[args.scheme], | |
| args.dt_values) | |
| return data | |
| def experiment_compare_dt(option_value_pairs=False): | |
| I, a, T, theta, dt_values = \ | |
| read_command_line_argparse() if option_value_pairs else \ | |
| read_command_line_positional() | |
| legends = [] | |
| for dt in dt_values: | |
| u, t = solver(I, a, T, dt, theta) | |
| plt.plot(t, u) | |
| legends.append('dt=%g' % dt) | |
| t_e = np.linspace(0, T, 1001) # very fine mesh for u_e | |
| u_e = exact_solution(t_e, I, a) | |
| plt.plot(t_e, u_e, '--') # dashed line for u_e | |
| legends.append('exact') | |
| plt.legend(legends, loc='upper right') | |
| plt.title('theta=%g' % theta) | |
| plotfile = 'tmp' | |
| plt.savefig(plotfile + '.png'); plt.savefig(plotfile + '.pdf') | |
| def compute4web(I, a, T, dt, theta=0.5): | |
| """ | |
| Run a case with the solver, compute error measure, | |
| and plot the numerical and exact solutions in a PNG | |
| plot whose data are embedded in an HTML image tag. | |
| """ | |
| u, t = solver(I, a, T, dt, theta) | |
| u_e = exact_solution(t, I, a) | |
| e = u_e - u | |
| E = np.sqrt(dt*np.sum(e**2)) | |
| plt.figure() | |
| t_e = np.linspace(0, T, 1001) # fine mesh for u_e | |
| u_e = exact_solution(t_e, I, a) | |
| plt.plot(t, u, 'r--o') # red dashes w/circles | |
| plt.plot(t_e, u_e, 'b-') # blue line for exact sol. | |
| plt.legend(['numerical', 'exact']) | |
| plt.xlabel('t') | |
| plt.ylabel('u') | |
| plt.title('theta=%g, dt=%g' % (theta, dt)) | |
| # Save plot to HTML img tag with PNG code as embedded data | |
| from parampool.utils import save_png_to_str | |
| html_text = save_png_to_str(plt, plotwidth=400) | |
| return E, html_text | |
| def main_GUI(I=1.0, a=.2, T=4.0, | |
| dt_values=[1.25, 0.75, 0.5, 0.1], | |
| theta_values=[0, 0.5, 1]): | |
| # Build HTML code for web page. Arrange plots in columns | |
| # corresponding to the theta values, with dt down the rows | |
| theta2name = {0: 'FE', 1: 'BE', 0.5: 'CN'} | |
| html_text = '<table>\n' | |
| for dt in dt_values: | |
| html_text += '<tr>\n' | |
| for theta in theta_values: | |
| E, html = compute4web(I, a, T, dt, theta) | |
| html_text += """ | |
| <td> | |
| <center><b>%s, dt=%g, error: %.3E</b></center><br> | |
| %s | |
| </td> | |
| """ % (theta2name[theta], dt, E, html) | |
| html_text += '</tr>\n' | |
| html_text += '</table>\n' | |
| return html_text | |
| def solver_with_doctest(I, a, T, dt, theta): | |
| """ | |
| Solve u'=-a*u, u(0)=I, for t in (0,T] with steps of dt. | |
| >>> u, t = solver(I=0.8, a=1.2, T=1.5, dt=0.5, theta=0.5) | |
| >>> for t_n, u_n in zip(t, u): | |
| ... print 't=%.1f, u=%.14f' % (t_n, u_n) | |
| t=0.0, u=0.80000000000000 | |
| t=0.5, u=0.43076923076923 | |
| t=1.0, u=0.23195266272189 | |
| t=1.5, u=0.12489758761948 | |
| """ | |
| dt = float(dt) # avoid integer division | |
| Nt = int(round(T/dt)) # no of time intervals | |
| T = Nt*dt # adjust T to fit time step dt | |
| u = np.zeros(Nt+1) # array of u[n] values | |
| t = np.linspace(0, T, Nt+1) # time mesh | |
| u[0] = I # assign initial condition | |
| for n in range(0, Nt): # n=0,1,...,Nt-1 | |
| u[n+1] = (1 - (1-theta)*a*dt)/(1 + theta*dt*a)*u[n] | |
| return u, t | |
| def third(x): | |
| return x/3. | |
| def test_third(): | |
| x = 0.15 | |
| expected = (1/3.)*x | |
| computed = third(x) | |
| tol = 1E-15 | |
| success = abs(expected - computed) < tol | |
| assert success | |
| def exact_discrete_solution(n, I, a, theta, dt): | |
| """Return exact discrete solution of the numerical schemes.""" | |
| dt = float(dt) # avoid integer division | |
| A = (1 - (1-theta)*a*dt)/(1 + theta*dt*a) | |
| return I*A**n | |
| def test_exact_discrete_solution(): | |
| """Check that solver reproduces the exact discr. sol.""" | |
| theta = 0.8; a = 2; I = 0.1; dt = 0.8 | |
| Nt = int(8/dt) # no of steps | |
| u, t = solver(I=I, a=a, T=Nt*dt, dt=dt, theta=theta) | |
| # Evaluate exact discrete solution on the mesh | |
| u_de = np.array([exact_discrete_solution(n, I, a, theta, dt) | |
| for n in range(Nt+1)]) | |
| # Find largest deviation | |
| diff = np.abs(u_de - u).max() | |
| tol = 1E-14 | |
| success = diff < tol | |
| assert success | |
| def test_potential_integer_division(): | |
| """Choose variables that can trigger integer division.""" | |
| theta = 1; a = 1; I = 1; dt = 2 | |
| Nt = 4 | |
| u, t = solver(I=I, a=a, T=Nt*dt, dt=dt, theta=theta) | |
| u_de = np.array([exact_discrete_solution(n, I, a, theta, dt) | |
| for n in range(Nt+1)]) | |
| diff = np.abs(u_de - u).max() | |
| assert diff < 1E-14 | |
| def test_read_command_line_positional(): | |
| # Decide on a data set of input parameters | |
| I = 1.6; a = 1.8; T = 2.2; theta = 0.5 | |
| dt_values = [0.1, 0.2, 0.05] | |
| # Expected return from read_command_line_positional | |
| expected = [I, a, T, theta, dt_values] | |
| # Construct corresponding sys.argv array | |
| sys.argv = [sys.argv[0], str(I), str(a), str(T), 'CN'] + \ | |
| [str(dt) for dt in dt_values] | |
| computed = read_command_line_positional() | |
| for expected_arg, computed_arg in zip(expected, computed): | |
| assert expected_arg == computed_arg | |
| def test_read_command_line_argparse(): | |
| I = 1.6; a = 1.8; T = 2.2; theta = 0.5 | |
| dt_values = [0.1, 0.2, 0.05] | |
| # Expected return from read_command_line_positional | |
| expected = [I, a, T, theta, dt_values] | |
| # Construct corresponding sys.argv array | |
| cml = '%s --a %s --I %s --T %s --scheme CN --dt ' % \ | |
| (sys.argv[0], a, I, T) | |
| cml = cml + ' '.join([str(dt) for dt in dt_values]) | |
| sys.argv = cml.split() | |
| computed = read_command_line_argparse() | |
| for expected_arg, computed_arg in zip(expected, computed): | |
| assert expected_arg == computed_arg | |
| # Classes | |
| class Problem(object): | |
| def __init__(self, I=1, a=1, T=10): | |
| self.T, self.I, self.a = I, float(a), T | |
| def define_command_line_options(self, parser=None): | |
| """Return updated (parser) or new ArgumentParser object.""" | |
| if parser is None: | |
| import argparse | |
| parser = argparse.ArgumentParser() | |
| parser.add_argument( | |
| '--I', '--initial_condition', type=float, | |
| default=1.0, help='initial condition, u(0)', | |
| metavar='I') | |
| parser.add_argument( | |
| '--a', type=float, default=1.0, | |
| help='coefficient in ODE', metavar='a') | |
| parser.add_argument( | |
| '--T', '--stop_time', type=float, | |
| default=1.0, help='end time of simulation', | |
| metavar='T') | |
| return parser | |
| def init_from_command_line(self, args): | |
| """Load attributes from ArgumentParser into instance.""" | |
| self.I, self.a, self.T = args.I, args.a, args.T | |
| def u_exact(self, t): | |
| """Return the exact solution u(t)=I*exp(-a*t).""" | |
| I, a = self.I, self.a | |
| return I*exp(-a*t) | |
| class Solver(object): | |
| def __init__(self, problem, dt=0.1, theta=0.5): | |
| self.problem = problem | |
| self.dt, self.theta = float(dt), theta | |
| def define_command_line_options(self, parser): | |
| """Return updated (parser) or new ArgumentParser object.""" | |
| parser.add_argument( | |
| '--scheme', type=str, default='CN', | |
| help='FE, BE, or CN') | |
| parser.add_argument( | |
| '--dt', '--time_step_values', type=float, | |
| default=[1.0], help='time step values', | |
| metavar='dt', nargs='+', dest='dt_values') | |
| return parser | |
| def init_from_command_line(self, args): | |
| """Load attributes from ArgumentParser into instance.""" | |
| self.dt, self.theta = args.dt, args.theta | |
| def solve(self): | |
| self.u, self.t = solver( | |
| self.problem.I, self.problem.a, self.problem.T, | |
| self.dt, self.theta) | |
| def error(self): | |
| """Return norm of error at the mesh points.""" | |
| u_e = self.problem.u_exact(self.t) | |
| e = u_e - self.u | |
| E = np.sqrt(self.dt*np.sum(e**2)) | |
| return E | |
| def experiment_classes(): | |
| problem = Problem() | |
| solver = Solver(problem) | |
| # Read input from the command line | |
| parser = problem.define_command_line_options() | |
| parser = solver. define_command_line_options(parser) | |
| args = parser.parse_args() | |
| problem.init_from_command_line(args) | |
| solver. init_from_command_line(args) | |
| # Solve and plot | |
| solver.solve() | |
| import matplotlib.pyplot as plt | |
| t_e = np.linspace(0, T, 1001) # very fine mesh for u_e | |
| u_e = problem.u_exact(t_e) | |
| print 'Error:', solver.error() | |
| plt.plot(t, u, 'r--o') # dashed red line with circles | |
| plt.plot(t_e, u_e, 'b-') # blue line for u_e | |
| plt.legend(['numerical, theta=%g' % theta, 'exact']) | |
| plt.xlabel('t') | |
| plt.ylabel('u') | |
| plotfile = 'tmp' | |
| plt.savefig(plotfile + '.png'); plt.savefig(plotfile + '.pdf') | |
| plt.show() | |
| if __name__ == '__main__': | |
| experiment_compare_dt(True) | |
| plt.show() | |
Xet Storage Details
- Size:
- 12.8 kB
- Xet hash:
- 44353488b89c2c5a79e158af3cf7b97b6d026d256ed85ebc1539c277da7b660c
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.