Skip to content

Commit 5f32e73

Browse files
committed
Change folder names.
1 parent 8b58822 commit 5f32e73

File tree

130 files changed

+18696
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

130 files changed

+18696
-0
lines changed
Lines changed: 203 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,203 @@
1+
{
2+
"cells": [
3+
{
4+
"cell_type": "markdown",
5+
"id": "0",
6+
"metadata": {},
7+
"source": [
8+
"# Code cleanup example\n",
9+
"\n",
10+
"Original code, based on code from the free E-book _Computational Physics: Problem Solving with Python, 3rd edition_, by Landau, Páez, and Bordeianu. Modified primarily to use matplotlib instead of VPython."
11+
]
12+
},
13+
{
14+
"cell_type": "code",
15+
"execution_count": null,
16+
"id": "1",
17+
"metadata": {},
18+
"outputs": [],
19+
"source": [
20+
"from numpy import *\n",
21+
"import matplotlib.pyplot as plt\n",
22+
"\n",
23+
"Xmax = 40.\n",
24+
"Xmin = 0.25\n",
25+
"step = 0.1 # Global class variables\n",
26+
"order = 10; start = 50 # Plot j_order\n",
27+
"graph1, ax1 = plt.subplots(figsize = (5, 5))\n",
28+
"ax1.set_title('Sperical Bessel, \\\n",
29+
" L = 1 (red), 10')\n",
30+
"ax1.set_xlabel(\"x\"); ax1.set_ylabel('j(x)')\n",
31+
"ax1.set_xlim(left=Xmin , \\\n",
32+
" right=Xmax)\n",
33+
"ax1.set_ylim(bottom=-0.2 , top=0.5)\n",
34+
"\n",
35+
"\n",
36+
"def down(x, n, m): # Method down, recurs downward\n",
37+
" j = zeros( (start + 2), float)\n",
38+
" j[m + 1] = j[m] = 1. # Start with anything\n",
39+
" for k in range(m, 0, -1):\n",
40+
" j[k - 1] = ( (2.*k + 1.)/x)*j[k] - j[k + 1]\n",
41+
" scale = (sin(x)/x)/j[0] # Scale solution to known j[0]\n",
42+
" return j[n] * scale\n",
43+
"\n",
44+
"\n",
45+
"for x in arange(Xmin, Xmax, step):\n",
46+
" ax1.plot(x, down(x, order, start), \"r.\")\n",
47+
"\n",
48+
"for x in arange(Xmin, Xmax, step):\n",
49+
" ax1.plot(x, down(x,1,start), \"g.\")\n",
50+
"\n",
51+
"plt.show()"
52+
]
53+
},
54+
{
55+
"cell_type": "markdown",
56+
"id": "2",
57+
"metadata": {},
58+
"source": [
59+
"Try to clean it up. Two possible solutions: one closer to the original (but fixing some bugs, like the plot title color being wrong!):"
60+
]
61+
},
62+
{
63+
"cell_type": "code",
64+
"execution_count": null,
65+
"id": "3",
66+
"metadata": {
67+
"jupyter": {
68+
"source_hidden": true
69+
},
70+
"tags": [
71+
"hide-cell"
72+
]
73+
},
74+
"outputs": [],
75+
"source": [
76+
"import numpy as np\n",
77+
"import matplotlib.pyplot as plt\n",
78+
"\n",
79+
"x_max = 40.0\n",
80+
"x_min = 0.25\n",
81+
"step = 0.1\n",
82+
"start = 50 # Plot j_order\n",
83+
"\n",
84+
"\n",
85+
"def down(x, order, start):\n",
86+
" \"\"\"\n",
87+
" Method down, recurse downward.\n",
88+
" \"\"\"\n",
89+
" j = np.zeros((start + 2), dtype=float)\n",
90+
"\n",
91+
" # Start with anything\n",
92+
" j[start + 1] = j[start] = 1.0\n",
93+
"\n",
94+
" for k in range(start, 0, -1):\n",
95+
" j[k - 1] = ((2.0 * k + 1.0) / x) * j[k] - j[k + 1]\n",
96+
"\n",
97+
" # Scale solution to known j[0]\n",
98+
" scale = (np.sin(x) / x) / j[0]\n",
99+
" return j[order] * scale\n",
100+
"\n",
101+
"\n",
102+
"fig, ax = plt.subplots(figsize=(5, 5))\n",
103+
"ax.set_title(\"Spherical Bessel, L = 1, 10 (red)\")\n",
104+
"ax.set_xlabel(\"x\")\n",
105+
"ax.set_ylabel(\"j(x)\")\n",
106+
"ax.set_xlim(x_min, x_max)\n",
107+
"ax.set_ylim(-0.2, 0.5)\n",
108+
"\n",
109+
"x = np.arange(x_min, x_max, step)\n",
110+
"\n",
111+
"# Warning! red/green are bad colors to use, default colors are better\n",
112+
"ax.plot(x, [down(x_i, 10, start) for x_i in x], \"r.\")\n",
113+
"ax.plot(x, np.vectorize(down)(x, 1, start), \"g.\")\n",
114+
"\n",
115+
"plt.show()"
116+
]
117+
},
118+
{
119+
"cell_type": "markdown",
120+
"id": "4",
121+
"metadata": {},
122+
"source": [
123+
"And one going a bit further and vectorizing the function properly, and fixing the color display:"
124+
]
125+
},
126+
{
127+
"cell_type": "code",
128+
"execution_count": null,
129+
"id": "5",
130+
"metadata": {
131+
"jupyter": {
132+
"source_hidden": true
133+
},
134+
"tags": [
135+
"hide-cell"
136+
]
137+
},
138+
"outputs": [],
139+
"source": [
140+
"import numpy as np\n",
141+
"import matplotlib.pyplot as plt\n",
142+
"\n",
143+
"x_min = 0.25\n",
144+
"x_max = 40.0\n",
145+
"step = 0.1\n",
146+
"\n",
147+
"\n",
148+
"def down(x, order, start):\n",
149+
" \"\"\"\n",
150+
" Method down, recurse downward.\n",
151+
" \"\"\"\n",
152+
" j = np.zeros((start + 2, len(x)), dtype=float)\n",
153+
"\n",
154+
" # Start with anything\n",
155+
" j[start + 1] = j[start] = 1.0\n",
156+
"\n",
157+
" for k in range(start, 0, -1):\n",
158+
" j[k - 1] = ((2.0 * k + 1.0) / x) * j[k] - j[k + 1]\n",
159+
"\n",
160+
" # Scale solution to known j[0]\n",
161+
" scale = np.sin(x) / (x * j[0])\n",
162+
" return j[order] * scale\n",
163+
"\n",
164+
"\n",
165+
"fig, ax = plt.subplots(figsize=(5, 5))\n",
166+
"ax.set_title(\"Spherical Bessel\")\n",
167+
"ax.set_xlabel(\"x\")\n",
168+
"ax.set_ylabel(\"j(x)\")\n",
169+
"ax.set_xlim(x_min, x_max)\n",
170+
"ax.set_ylim(-0.2, 0.5)\n",
171+
"\n",
172+
"x = np.arange(x_min, x_max, step)\n",
173+
"\n",
174+
"ax.plot(x, down(x, 10, 50), \"r.\", label=\"L=10\")\n",
175+
"ax.plot(x, down(x, 1, 50), \"g.\", label=\"L=1\")\n",
176+
"ax.legend()\n",
177+
"\n",
178+
"plt.show()"
179+
]
180+
}
181+
],
182+
"metadata": {
183+
"kernelspec": {
184+
"display_name": "Python [conda env:se-for-sci] *",
185+
"language": "python",
186+
"name": "conda-env-se-for-sci-py"
187+
},
188+
"language_info": {
189+
"codemirror_mode": {
190+
"name": "ipython",
191+
"version": 3
192+
},
193+
"file_extension": ".py",
194+
"mimetype": "text/x-python",
195+
"name": "python",
196+
"nbconvert_exporter": "python",
197+
"pygments_lexer": "ipython3",
198+
"version": "3.10.6"
199+
}
200+
},
201+
"nbformat": 4,
202+
"nbformat_minor": 5
203+
}
Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
# Introductions and motivation
2+
3+
[Slides](https://henryiii.github.io/se-for-sci/slides/week-01-1)
4+
5+
## The importance of software engineering in scientific computing
6+
7+
It's really easy to learn to code. In fact, it's easier to _write_ code than
8+
_read_ code. Often this leads to the desire to rewrite legacy codebases instead
9+
of deciphering what the original author intended. Since a main goal of good
10+
software engineering is to reuse code, this is clearly wasteful! Good code is
11+
easy to read, always strive for readability.
12+
13+
What does someone working on code spend time on? Rewriting code that others have
14+
already written. The action of rewriting code to improve its readability or
15+
performance without changing how it operates is commonly called refactoring.
16+
Other reasons to rewrite code is because it didn't scale or was not flexible
17+
enough. It also can feel like you spend a lot of time debugging. Lots of painful
18+
debugging. Having strong unit tests and using version control can simplify or
19+
eliminate some debugging problems.
20+
21+
There are a lot of tools, practices, and techniques available to help you read
22+
other people's code, write code that others can read (including yourself in six
23+
months), manage scale and flexibility, and make debugging easier.
24+
25+
But deadlines get in the way. Your PI cares about results, not how maintainable
26+
your codebase is. Learning new tools to accelerate your development doesn't fit
27+
into tight schedules or isn't seen as necessary at the beginning of a project.
28+
Frequently, a small script will morph and evolve into a full codebase without
29+
much planning or design. It's much easier just to get something working than
30+
study design principles. You pay the price in the end, when trying to publish,
31+
distribute, or replicate your results.
32+
33+
This course aims to fix that by providing a structured introduction to common,
34+
useful tools and practices.
35+
36+
## Some important overarching concepts
37+
38+
- Version control
39+
- Testing and debugging
40+
- Continuous integration
41+
- Packaging and distribution
42+
- Design principles
43+
- Compiled code
44+
- Performance
45+
46+
Over the course, we will go over these concepts. Missing from the above list:
47+
how to code (you should already know the basics, like loops, functions, and
48+
such, in at least one language). Also, we won't cover specific algorithms, which
49+
is enough for its own course.
50+
51+
Also, we will be using Python for the first 2/3 of the course, followed by a
52+
compiled language. The specific language doesn't matter that much, but you have
53+
to pick one, and Python is an excellent choice. It's one of the most widely used
54+
languages, the one you are statistically the most likely to already be familiar
55+
with, and one of the best "teaching" languages (as it was actually developed
56+
based on a language specifically designed for teaching, the "ABC" language).
57+
58+
We will be working with a lot of specific tooling, but the concepts are general;
59+
if you are working in a different language, just find the matching tooling for
60+
that language. Again, we have to pick something, but once you know the concepts,
61+
you can find similar tools in almost any language.
62+
63+
## Problem-solution ordering
64+
65+
[Problem-solution ordering](https://mkremins.github.io/blog/doors-headaches-intellectual-need/)
66+
is a problem for many courses, but is especially true for Software Engineering.
67+
68+
The classic example of problem-solution ordering is in game design. Let's say
69+
you design a tutorial level that teaches players about locked doors. You give
70+
them a key, then they open a door that is unlocked by that key. Assuming players
71+
now know how to open locked doors, you put a locked door in a real level - and
72+
players have no idea how to open it; they don't know to go look for a key. Why?
73+
Because they didn't encounter the locked door before they picked up the key, so
74+
they don't know that it was the key that made the door open. (The "key" and the
75+
"door" could be any cause and effect relationship.)
76+
77+
This occurs in a lot of fields, like math. How do you convince someone who
78+
hasn't needed math yet that it's a useful skill to learn?
79+
80+
This is what we face in Software Engineering. If you've never had to collaborate
81+
with others or manage a large software project, you might not see why "git" is
82+
worth learning. If you haven't spent days or weeks trying to track down a
83+
hard-to-find bug, you might not get why you should spend time learning a
84+
debugger or unit testing your code. If you've never had a compiler catch a bug
85+
that would have been disastrous at runtime, you might not recognize the
86+
usefulness of static typing. If you've never had a memory leak or segfault, you
87+
might not see why it's worth effort to design with memory safety in mind. And so
88+
on.
89+
90+
We'll try to motivate what we do, but the best motivator is experience and
91+
exposure to the "simple" way to do things and its shortcomings; then you will
92+
understand why the more advanced method was created.
93+
94+
### New features are restrictions
95+
96+
Each new concept in programming _restricts_ rather than _enables_. When we go
97+
further into topics like functional programming, this will continue to be the
98+
case. This is odd but true: we could write any program with a very small set of
99+
constructs; very simple languages are Turing Complete. However, the most
100+
important feature of programming is _organization_ (also called design).
101+
102+
Compare this hypothetical pseudo-code:
103+
104+
```text
105+
i = 0
106+
label start
107+
compute(i)
108+
i = i + 1
109+
if i < 10: goto start
110+
```
111+
112+
Versus real code:
113+
114+
```python
115+
for i in range(10):
116+
compute(i)
117+
```
118+
119+
Now imagine a complex program with thousands of `goto` statements; you would
120+
have to work through every line of code to understand it. But if you restrict
121+
yourself to common structures, like loops, objects, functions, etc., you no
122+
longer have to look at the whole program, but just smaller, digestible parts.
123+
124+
Everyone learning a language will know what these common constructs are. No one
125+
will know what your special constructs are.
126+
127+
#### Example: match
128+
129+
Let's quickly apply this to a much newer example. Take the following code that
130+
provides different printouts for different structures:
131+
132+
```python
133+
if isinstance(x, list):
134+
print(*x)
135+
elif isinstance(x, dict):
136+
print(*(f"{k}={v}" for k, v in x.items()))
137+
else:
138+
print(x)
139+
```
140+
141+
versus using pattern matching:
142+
143+
```python
144+
match x:
145+
case [*_]:
146+
print(*x)
147+
case {}:
148+
print(*(f"{k}={v}" for k, v in x.items()))
149+
case _:
150+
print(x)
151+
```
152+
153+
The pattern matching case is more focused, so it takes less reading. You know
154+
from the first line `match x` that this is based on the variable `x`; in the if
155+
chain, you could have switched to some other variable partway down the chain, so
156+
the reader has to look at each branch to verify you are just processing one
157+
variable. The language has built-in support for various situations, while the
158+
manual form would require you write everything out. There's a learning curve to
159+
the more specific structure, but anyone learning the language learns it once,
160+
rather than rereading it or rewriting it every time in every codebase.
161+
162+
## Course structure
163+
164+
The challenges of this course:
165+
166+
- Often introducing solutions before problems
167+
- Large variance in the audience in terms of skill and background
168+
- Good coding basics rarely taught elsewhere
169+
170+
## Introductions
171+
172+
I'd like to know who you are and what you are interested in! Let's do a round of
173+
introductions. Suggested topics:
174+
175+
- Name
176+
- Field of study
177+
- Preferred programming Language(s)
178+
- A project you are working on or want to work on

0 commit comments

Comments
 (0)