From d8875954626e8c401f05d0ba231e8ab8e7e773ce Mon Sep 17 00:00:00 2001 From: Syed Mustafa Ahmed Date: Fri, 15 Nov 2024 14:33:06 +0100 Subject: [PATCH 1/2] Added pyproject.toml, output.py, __init__.py. Modified diffusion2d.py, made solev() accept user arguements. Changed src file paths. All changes requirements for exercise to package the python code and upload to TestPyPI --- .gitignore | 3 ++ README.md | 31 +++++++++--- pyproject.toml | 20 ++++++++ setup.py | 4 ++ LICENSE => src/LICENSE | 0 src/__init__.py | 0 diffusion2d.py => src/diffusion2d.py | 75 +++++++++++++++++----------- src/output.py | 15 ++++++ 8 files changed, 113 insertions(+), 35 deletions(-) create mode 100644 .gitignore create mode 100644 pyproject.toml create mode 100644 setup.py rename LICENSE => src/LICENSE (100%) create mode 100644 src/__init__.py rename diffusion2d.py => src/diffusion2d.py (51%) create mode 100644 src/output.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..00c19545 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +__pycache__ +dist +src/ahmedsa_diffusion2d.egg-info \ No newline at end of file diff --git a/README.md b/README.md index fe548354..16ab4d9c 100644 --- a/README.md +++ b/README.md @@ -1,19 +1,36 @@ # diffusion2D -## Instructions for students - -Please follow the instructions in [pypi_exercise.md](https://github.com/Simulation-Software-Engineering/Lecture-Material/blob/main/03_building_and_packaging/pypi_exercise.md). - -The code used in this exercise is based on [Chapter 7 of the book "Learning Scientific Programming with Python"](https://scipython.com/book/chapter-7-matplotlib/examples/the-two-dimensional-diffusion-equation/). - -## Project description +# Project description +A 2D diffusion equation solver with visualization output that used matplotlib and numpy to plot 3 graphs. The project can take arguements for values of dx, dy and D to compute and visualize the 2D diffusion and use matplotlib to plot the figures. ## Installing the package +You can use pip to directly install the package or build it from source using pip from the tar.gz/.whl package from [TestPyPi](link) ### Using pip3 to install from PyPI +To install the package, simply run: +```console +pip install -i https://test.pypi.org/simple/ ahmedsa-diffusion2d==0.0.1 +``` ### Required dependencies +The required dependencies are: +- Python (version >= 3) +- pip +- NumPy +- Matplotlib +If you plan to build from source, you also need to install the **build** pip package. ## Running this package +To run the package, you can use the following command: +```console +python3 diffusion2d.py +``` +Or if you prefer to pass values of dx, dy and D (respectively), you can pass them as arguements as follows: +```console +python3 diffusion2d.py solve +``` ## Citing +- [Chapter 7 of the book "Learning Scientific Programming with Python"](https://scipython.com/book/chapter-7-matplotlib/examples/the-two-dimensional-diffusion-equation/) +- [Simulation Service Engineering Exercise](https://github.com/Simulation-Software-Engineering/diffusion2D) + diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 00000000..e5d7efa4 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,20 @@ +[build-system] +requires = ["setuptools", "wheel", "build"] + +[project] +name = "ahmedsa_diffusion2d" +description = "A 2D diffusion equation solver with visualization output" +authors = [ + { name="Syed Mustafa Ahmed", email="syedmustafaahmad@gmail.com" } +] +readme = "README.md" +keywords = ["diffusion2D", "solver"] +classifiers = [ + "Programming Language :: Python :: 3" +] +dependencies = [ + "matplotlib", + "numpy" +] +requires-python = ">=3.0" +version = "0.0.2" diff --git a/setup.py b/setup.py new file mode 100644 index 00000000..65147441 --- /dev/null +++ b/setup.py @@ -0,0 +1,4 @@ +from setuptools import setup + +if __name__ == "__main__": + setup() \ No newline at end of file diff --git a/LICENSE b/src/LICENSE similarity index 100% rename from LICENSE rename to src/LICENSE diff --git a/src/__init__.py b/src/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/diffusion2d.py b/src/diffusion2d.py similarity index 51% rename from diffusion2d.py rename to src/diffusion2d.py index c0c6083a..eaca19ca 100644 --- a/diffusion2d.py +++ b/src/diffusion2d.py @@ -4,8 +4,10 @@ Example acquired from https://scipython.com/book/chapter-7-matplotlib/examples/the-two-dimensional-diffusion-equation/ """ +import sys import numpy as np import matplotlib.pyplot as plt +from output import create_plot, output_plots # plate size, mm w = h = 10. @@ -45,37 +47,54 @@ def do_timestep(u_nm1, u, D, dt, dx2, dy2): - # Propagate with forward-difference in time, central-difference in space u[1:-1, 1:-1] = u_nm1[1:-1, 1:-1] + D * dt * ( (u_nm1[2:, 1:-1] - 2 * u_nm1[1:-1, 1:-1] + u_nm1[:-2, 1:-1]) / dx2 + (u_nm1[1:-1, 2:] - 2 * u_nm1[1:-1, 1:-1] + u_nm1[1:-1, :-2]) / dy2) - u_nm1 = u.copy() return u_nm1, u - -# Number of timesteps -nsteps = 101 -# Output 4 figures at these timesteps -n_output = [0, 10, 50, 100] -fig_counter = 0 -fig = plt.figure() - -# Time loop -for n in range(nsteps): - u0, u = do_timestep(u0, u, D, dt, dx2, dy2) - - # Create figure - if n in n_output: - fig_counter += 1 - ax = fig.add_subplot(220 + fig_counter) - im = ax.imshow(u.copy(), cmap=plt.get_cmap('hot'), vmin=T_cold, vmax=T_hot) # image for color bar axes - ax.set_axis_off() - ax.set_title('{:.1f} ms'.format(n * dt * 1000)) - -# Plot output figures -fig.subplots_adjust(right=0.85) -cbar_ax = fig.add_axes([0.9, 0.15, 0.03, 0.7]) -cbar_ax.set_xlabel('$T$ / K', labelpad=20) -fig.colorbar(im, cax=cbar_ax) -plt.show() +# Solver function +def solve(dx=0.1, dy=0.1, D=4.0): + w = h = 10.0 + T_cold = 300 + T_hot = 700 + nx, ny = int(w / dx), int(h / dy) + dx2, dy2 = dx * dx, dy * dy + dt = dx2 * dy2 / (2 * D * (dx2 + dy2)) + u0 = T_cold * np.ones((nx, ny)) + u = u0.copy() + r = min(h, w) / 4.0 + cx = w / 2.0 + cy = h / 2.0 + r2 = r ** 2 + for i in range(nx): + for j in range(ny): + p2 = (i * dx - cx) ** 2 + (j * dy - cy) ** 2 + if p2 < r2: + u0[i, j] = T_hot + + nsteps = 101 + n_output = [0, 10, 50, 100] + fig = plt.figure() + fig_counter = 0 + im = None + + for n in range(nsteps): + u0, u = do_timestep(u0, u, D, dt, dx2, dy2) + if n in n_output: + fig_counter += 1 + im = create_plot(fig, u, T_cold, T_hot, dt, n, fig_counter) + + output_plots(fig, im) + +# Running the solve function as a test +if __name__ == "__main__": + if len(sys.argv) < 4: + print("Usage: python3 diffusion2d.py ") + else: + dx = float(sys.argv[2]) + dy = float(sys.argv[3]) + D = float(sys.argv[4]) + print(f'dx={dx}, dy={dy}, D={D}') + + solve(dx, dy, D) \ No newline at end of file diff --git a/src/output.py b/src/output.py new file mode 100644 index 00000000..50c5ed21 --- /dev/null +++ b/src/output.py @@ -0,0 +1,15 @@ +import matplotlib.pyplot as plt + +def create_plot(fig, u, T_cold, T_hot, dt, time_step, fig_counter): + ax = fig.add_subplot(220 + fig_counter) + im = ax.imshow(u, cmap=plt.get_cmap('hot'), vmin=T_cold, vmax=T_hot) + ax.set_axis_off() + ax.set_title(f'{time_step * dt * 1000:.1f} ms') + return im + +def output_plots(fig, im): + fig.subplots_adjust(right=0.85) + cbar_ax = fig.add_axes([0.9, 0.15, 0.03, 0.7]) + cbar_ax.set_xlabel('$T$ / K', labelpad=20) + fig.colorbar(im, cax=cbar_ax) + plt.show() From b508ddfab449c1e257f13a49b735bfdc60db15ae Mon Sep 17 00:00:00 2001 From: Syed Mustafa Ahmad Date: Fri, 15 Nov 2024 14:37:12 +0100 Subject: [PATCH 2/2] Renamed version number to match pip version on TestPyPI --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 16ab4d9c..50d4d89c 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ You can use pip to directly install the package or build it from source using pi ### Using pip3 to install from PyPI To install the package, simply run: ```console -pip install -i https://test.pypi.org/simple/ ahmedsa-diffusion2d==0.0.1 +pip install -i https://test.pypi.org/simple/ ahmedsa-diffusion2d ``` ### Required dependencies