Skip to content

Commit de75717

Browse files
committed
Merge remote-tracking branch 'origin/development' into development
2 parents 544e273 + 711050e commit de75717

File tree

2 files changed

+346
-0
lines changed

2 files changed

+346
-0
lines changed

source-code/design-patters/README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,5 @@ Code to illustrate some design patterns in Python.
66

77
1. `decorator_design_pattern.ipynb`: notebook that illustrate how decorators
88
can be used to change the behaviour of objects.
9+
1. `factory_design_pattern.ipynb`: notebook illustrating how a factory class
10+
can be used to conveniently construct many objects with the same properties.
Lines changed: 344 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,344 @@
1+
{
2+
"cells": [
3+
{
4+
"cell_type": "markdown",
5+
"id": "f4ff5324-2ed7-453f-8f4d-6a163ff66266",
6+
"metadata": {},
7+
"source": [
8+
"# Requirements"
9+
]
10+
},
11+
{
12+
"cell_type": "code",
13+
"execution_count": 1,
14+
"id": "d85a7914-7da3-4174-999a-cd573adc5a71",
15+
"metadata": {},
16+
"outputs": [],
17+
"source": [
18+
"import attr\n",
19+
"from math import sqrt\n",
20+
"import matplotlib.pyplot as plt\n",
21+
"%matplotlib inline\n",
22+
"from operator import attrgetter\n",
23+
"import random\n",
24+
"import scipy as sp\n",
25+
"import scipy.stats"
26+
]
27+
},
28+
{
29+
"cell_type": "markdown",
30+
"id": "18fd5d95-b41a-48c5-88d8-29b61037b3de",
31+
"metadata": {},
32+
"source": [
33+
"# Particles"
34+
]
35+
},
36+
{
37+
"cell_type": "markdown",
38+
"id": "04bef303-c1e0-4531-a375-c268048a415c",
39+
"metadata": {},
40+
"source": [
41+
"We define a class that represents particles in two dimensions. Particles have a position, a velocity and a mass. These properties are set when the particle is created, and can not be modified, except through the `move` method that takes a time interval $\\Delta t$ as an argument.\n",
42+
"\n",
43+
"The position, velocity and mass attributes can be accessed using properties, as can the kinetic energy."
44+
]
45+
},
46+
{
47+
"cell_type": "code",
48+
"execution_count": 2,
49+
"id": "8ff84f9a-c19b-4c8a-8fcf-790e43184608",
50+
"metadata": {},
51+
"outputs": [],
52+
"source": [
53+
"@attr.s\n",
54+
"class Particle:\n",
55+
" _x: float = attr.ib()\n",
56+
" _y: float = attr.ib()\n",
57+
" _v_x: float = attr.ib()\n",
58+
" _v_y: float = attr.ib()\n",
59+
" _mass: float = attr.ib()\n",
60+
" \n",
61+
" @property\n",
62+
" def position(self):\n",
63+
" return self._x, self._y\n",
64+
" \n",
65+
" @property\n",
66+
" def velocity(self):\n",
67+
" return self._v_x, self._v_y\n",
68+
" \n",
69+
" @property\n",
70+
" def mass(self):\n",
71+
" return self._mass\n",
72+
" \n",
73+
" @property\n",
74+
" def energy(self):\n",
75+
" return 0.5*self._mass*(self._v_x**2 + self._v_y**2)\n",
76+
" \n",
77+
" def move(self, Δt: float):\n",
78+
" self._x += self._v_x*Δt\n",
79+
" self._y += self._v_y*Δt"
80+
]
81+
},
82+
{
83+
"cell_type": "code",
84+
"execution_count": 3,
85+
"id": "11757da3-6c99-42be-a3d7-ac52a8b726d0",
86+
"metadata": {},
87+
"outputs": [],
88+
"source": [
89+
"p = Particle(x=0.0, y=0.0, v_x=0.3, v_y=0.9, mass=1.0)"
90+
]
91+
},
92+
{
93+
"cell_type": "code",
94+
"execution_count": 4,
95+
"id": "0e074a16-c0b6-46ea-b5d5-e1b9c2803984",
96+
"metadata": {},
97+
"outputs": [
98+
{
99+
"data": {
100+
"text/plain": [
101+
"0.45"
102+
]
103+
},
104+
"execution_count": 4,
105+
"metadata": {},
106+
"output_type": "execute_result"
107+
}
108+
],
109+
"source": [
110+
"p.energy"
111+
]
112+
},
113+
{
114+
"cell_type": "code",
115+
"execution_count": 5,
116+
"id": "2c972952-ecb5-435f-bae5-525fd18552f0",
117+
"metadata": {},
118+
"outputs": [
119+
{
120+
"data": {
121+
"text/plain": [
122+
"(0.0, 0.0)"
123+
]
124+
},
125+
"execution_count": 5,
126+
"metadata": {},
127+
"output_type": "execute_result"
128+
}
129+
],
130+
"source": [
131+
"p.position"
132+
]
133+
},
134+
{
135+
"cell_type": "code",
136+
"execution_count": 6,
137+
"id": "6744e1db-88cb-4714-abab-fa25067e4ffa",
138+
"metadata": {},
139+
"outputs": [],
140+
"source": [
141+
"p.move(Δt=0.01)"
142+
]
143+
},
144+
{
145+
"cell_type": "code",
146+
"execution_count": 7,
147+
"id": "0f405a2e-a984-4a1c-aa19-b073326bcd17",
148+
"metadata": {},
149+
"outputs": [
150+
{
151+
"data": {
152+
"text/plain": [
153+
"(0.003, 0.009000000000000001)"
154+
]
155+
},
156+
"execution_count": 7,
157+
"metadata": {},
158+
"output_type": "execute_result"
159+
}
160+
],
161+
"source": [
162+
"p.position"
163+
]
164+
},
165+
{
166+
"cell_type": "code",
167+
"execution_count": 8,
168+
"id": "20aef05b-f9e4-4f71-8cd1-7bd61b45ff4d",
169+
"metadata": {},
170+
"outputs": [
171+
{
172+
"data": {
173+
"text/plain": [
174+
"0.45"
175+
]
176+
},
177+
"execution_count": 8,
178+
"metadata": {},
179+
"output_type": "execute_result"
180+
}
181+
],
182+
"source": [
183+
"p.energy"
184+
]
185+
},
186+
{
187+
"cell_type": "markdown",
188+
"id": "c135e1d1-e9f9-452b-aa79-705c4abacf12",
189+
"metadata": {},
190+
"source": [
191+
"# Particle factory"
192+
]
193+
},
194+
{
195+
"cell_type": "markdown",
196+
"id": "4b8b0c79-cbc9-4cb2-b9c1-e265d222350c",
197+
"metadata": {},
198+
"source": [
199+
"We want to create an ensemble of particles with a specific mass at a given temperature. To that purpose, we create a factory class that can be instantiated for a specific particle mass and temperature, and that has a `create` method to generate a particle located at the origin and with a random velocity according to a Maxwell distribution determined by the particles' mass and the temperature."
200+
]
201+
},
202+
{
203+
"cell_type": "code",
204+
"execution_count": 9,
205+
"id": "8c0a6088-c8f7-41b9-b345-fc0b6ee1cc4b",
206+
"metadata": {},
207+
"outputs": [],
208+
"source": [
209+
"@attr.s\n",
210+
"class ParticleFactory:\n",
211+
" _T: float = attr.ib()\n",
212+
" _mass: float = attr.ib()\n",
213+
" \n",
214+
" @_T.validator\n",
215+
" def _(self, attribute, value: float):\n",
216+
" if self._T < 0.0:\n",
217+
" raise ValueError('temperature must be positive')\n",
218+
"\n",
219+
" @_mass.validator\n",
220+
" def _(self, attribute, value: float):\n",
221+
" if self._mass < 0.0:\n",
222+
" raise ValueError('mass must be positive')\n",
223+
" \n",
224+
" def create(self):\n",
225+
" v: float = sp.stats.maxwell.rvs(scale=self._T/self._mass, size=1)[0]\n",
226+
" v_x: float = random.choice([-1.0, 1.0])*random.random()*v\n",
227+
" v_y: float = random.choice([-1.0, 1.0])*sqrt(v**2 - v_x**2)\n",
228+
" return Particle(x=0.0, y=0.0, v_x=v_x, v_y=v_y, mass=self._mass)"
229+
]
230+
},
231+
{
232+
"cell_type": "markdown",
233+
"id": "03523738-8ef8-4e3c-80ef-b9483dad33eb",
234+
"metadata": {},
235+
"source": [
236+
"We create a factory for particles with unit mass at a temperature of 5.0, and use the factory to create 5000 of such particles."
237+
]
238+
},
239+
{
240+
"cell_type": "code",
241+
"execution_count": 10,
242+
"id": "e008ec23-b471-49fd-ada7-c8d139b86043",
243+
"metadata": {},
244+
"outputs": [],
245+
"source": [
246+
"particle_factory_5 = ParticleFactory(T=5.0, mass=1.0)"
247+
]
248+
},
249+
{
250+
"cell_type": "code",
251+
"execution_count": 11,
252+
"id": "36858b90-bdf6-4569-b261-56f989967c4a",
253+
"metadata": {},
254+
"outputs": [],
255+
"source": [
256+
"particles_5 = [particle_factory_5.create() for _ in range(5_000)]"
257+
]
258+
},
259+
{
260+
"cell_type": "markdown",
261+
"id": "ed346886-5409-4d1c-978b-8a37b30967d9",
262+
"metadata": {},
263+
"source": [
264+
"We do the same, but now for a temperature of 10.0."
265+
]
266+
},
267+
{
268+
"cell_type": "code",
269+
"execution_count": 12,
270+
"id": "09943eac-5552-4a2f-903d-0766f2303c38",
271+
"metadata": {},
272+
"outputs": [],
273+
"source": [
274+
"particle_factory_10 = ParticleFactory(T=10.0, mass=1.0)"
275+
]
276+
},
277+
{
278+
"cell_type": "code",
279+
"execution_count": 13,
280+
"id": "b3476f9e-46a5-4365-ab7e-2cfc7e9a9192",
281+
"metadata": {},
282+
"outputs": [],
283+
"source": [
284+
"particles_10 = [particle_factory_10.create() for _ in range(5_000)]"
285+
]
286+
},
287+
{
288+
"cell_type": "markdown",
289+
"id": "464ec2a0-0de2-4381-8a94-6c3dcd3c1ffa",
290+
"metadata": {},
291+
"source": [
292+
"We can now plot the velocity distribution for each of the ensembles of particles."
293+
]
294+
},
295+
{
296+
"cell_type": "code",
297+
"execution_count": 14,
298+
"id": "b752496c-f39d-4ef4-8565-2dc1c844eaf6",
299+
"metadata": {},
300+
"outputs": [
301+
{
302+
"data": {
303+
"image/png": "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\n",
304+
"text/plain": [
305+
"<Figure size 432x288 with 1 Axes>"
306+
]
307+
},
308+
"metadata": {
309+
"needs_background": "light"
310+
},
311+
"output_type": "display_data"
312+
}
313+
],
314+
"source": [
315+
"_ = plt.hist(list(map(attrgetter('energy'), particles_5)), bins=50, density=True, alpha=0.5, label='$T = 5$')\n",
316+
"_ = plt.hist(list(map(attrgetter('energy'), particles_10)), bins=50, density=True, alpha=0.5, label='$T = 10$')\n",
317+
"_ = plt.xlabel(r'$v$')\n",
318+
"_ = plt.ylabel(r'$P(v)$')\n",
319+
"_ = plt.legend()"
320+
]
321+
}
322+
],
323+
"metadata": {
324+
"kernelspec": {
325+
"display_name": "Python 3",
326+
"language": "python",
327+
"name": "python3"
328+
},
329+
"language_info": {
330+
"codemirror_mode": {
331+
"name": "ipython",
332+
"version": 3
333+
},
334+
"file_extension": ".py",
335+
"mimetype": "text/x-python",
336+
"name": "python",
337+
"nbconvert_exporter": "python",
338+
"pygments_lexer": "ipython3",
339+
"version": "3.9.5"
340+
}
341+
},
342+
"nbformat": 4,
343+
"nbformat_minor": 5
344+
}

0 commit comments

Comments
 (0)