Skip to content

Commit e44f488

Browse files
committed
Fill empty code blocks in exercise solutions and add exercise files
- Fill 16 empty Python code blocks across 5 QMD files - Add restored exercise solution files (52 files in 6 directories) - Files: diffu_exer.qmd, nonlin_exer.qmd, wave1D_fd2.qmd, softeng2.qmd, wave1D_prog.qmd
1 parent 5fd8878 commit e44f488

63 files changed

Lines changed: 8863 additions & 470 deletions

Some content is hidden

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

chapters/advec/advec.qmd

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1738,7 +1738,6 @@ $$ {#eq-advec-app-heat-PDE}
17381738
where $f$ is some external heating inside the medium.
17391739
17401740
## Exercise: Analyze 1D stationary convection-diffusion problem {#sec-advec-1D-stationary-exer-analysis1}
1741-
file=twopt_BVP_analysis1
17421741
17431742
Explain the observations in the numerical experiments from Sections
17441743
@sec-advec-1D-stationary-fdm and @sec-advec-1D-stationary-upwind by
@@ -1752,7 +1751,6 @@ are determined from the boundary conditions.
17521751
:::
17531752
17541753
## Exercise: Interpret upwind difference as artificial diffusion {#sec-advec-1D-stationary-exer-analysis2}
1755-
file=twopt_BVP_analysis2
17561754
17571755
Consider an upwind, one-sided difference approximation to
17581756
a term $du/dx$ in a differential equation. Show that this
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
import numpy as np
2+
3+
4+
class Savez:
5+
def __init__(self, zipfilename):
6+
import os
7+
import sys
8+
import tempfile
9+
import zipfile
10+
11+
if isinstance(zipfilename, basestring):
12+
if not zipfilename.endswith(".npz"):
13+
zipfilename += ".npz"
14+
15+
# original _savez has no compression
16+
compression = zipfile.ZIP_STORED
17+
18+
if sys.version_info >= (2, 5):
19+
self.zip = zipfile.ZipFile(
20+
zipfilename, mode="w", allowZip64=True, compression=compression
21+
)
22+
23+
# Stage arrays in a temporary file on disk,
24+
# before writing to zip.
25+
fd, tmpfile = tempfile.mkstemp(suffix="-numpy.npy")
26+
os.close(fd)
27+
self.tmpfile = tmpfile
28+
self.i = 0 # array counter
29+
30+
def savez(self, *args, **kwds):
31+
import os
32+
33+
import numpy.lib.format as format
34+
35+
namedict = kwds
36+
for val in args:
37+
key = "arr_%d" % self.i
38+
if key in namedict.keys():
39+
raise ValueError("Cannot use un-named variables and keyword %s" % key)
40+
namedict[key] = val
41+
self.i += 1
42+
43+
try:
44+
for key, val in namedict.iteritems():
45+
fname = key + ".npy"
46+
fid = open(self.tmpfile, "wb")
47+
try:
48+
format.write_array(fid, np.asanyarray(val))
49+
fid.close()
50+
fid = None
51+
self.zip.write(self.tmpfile, arcname=fname)
52+
finally:
53+
if fid:
54+
fid.close()
55+
finally:
56+
os.remove(self.tmpfile)
57+
58+
def close(self):
59+
self.zip.close()
60+
61+
62+
def test_Savez():
63+
import os
64+
65+
tmp = "tmp_testarchive"
66+
database = Savez(tmp)
67+
for i in range(4):
68+
array = np.linspace(0, 5 + i, 3)
69+
kwargs = {"myarray_%02d" % i: array}
70+
database.savez(**kwargs)
71+
database.close()
72+
73+
database = np.load(tmp + ".npz")
74+
75+
expected = {
76+
"myarray_00": np.array([0.0, 2.5, 5.0]),
77+
"myarray_01": np.array([0.0, 3.0, 6.0]),
78+
"myarray_02": np.array([0.0, 3.5, 7.0]),
79+
"myarray_03": np.array([0.0, 4.0, 8.0]),
80+
}
81+
for name in database:
82+
computed = database[name]
83+
diff = np.abs(expected[name] - computed).max()
84+
assert diff < 1e-13
85+
database.close
86+
os.remove(tmp + ".npz")
87+
88+
89+
test_Savez()
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import os
2+
import sys
3+
4+
path = os.path.join(
5+
os.pardir, os.pardir, os.pardir, os.pardir, "wave", "src-wave", "wave1D"
6+
)
7+
# print path, glob.glob(path + '/w*')
8+
sys.path.insert(0, path)
9+
from wave1D_dn_vc import pulse
10+
11+
pulse_tp = sys.argv[1]
12+
C = float(sys.argv[2])
13+
pulse(pulse_tp=pulse_tp, C=C, Nx=100, animate=False, slowness_factor=4)

chapters/appendices/softeng2/softeng2.qmd

Lines changed: 92 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2066,15 +2066,15 @@ plain C/C++ arrays, can be efficiently wrapped in more user-friendly
20662066
C++ array classes in the C++ code, if desired.
20672067
20682068
## Exercise: Explore computational efficiency of numpy.sum versus built-in sum {#sec-softeng2-exer-sum}
2069-
file=sumn
20702069
20712070
Using the task of computing the sum of the first `n` integers, we want to
20722071
compare the efficiency of `numpy.sum` versus Python's built-in function
20732072
`sum`. Use IPython's `%timeit` functionality to time these two functions
20742073
applied to three different arguments: `range(n)`, `xrange(n)`, and
20752074
`arrange(n)`.
20762075
2077-
!bsol
2076+
2077+
::: {.callout-tip collapse="true" title="Solution"}
20782078
Here are experiments in IPython:
20792079
20802080
```python
@@ -2104,10 +2104,10 @@ fastest method. We also see that the plain `sum` function is slow
21042104
when applied to arrays, but faster than `numpy.sum` when applied to
21052105
the `range` list or the `xrange` sequence. There is almost a factor
21062106
of 200 between the best and worst method!
2107-
!esol
2107+
:::
2108+
21082109
21092110
## Exercise: Make an improved `numpy.savez` function {#sec-softeng2-exer-savez}
2110-
file=Savez
21112111
21122112
The `numpy.savez` function can save multiple arrays to a zip archive.
21132113
Unfortunately, if we want to use `savez` in time-dependent problems
@@ -2154,16 +2154,76 @@ def test_Savez():
21542154
Study the [source code](https://github.com/numpy/numpy/blob/master/numpy/lib/npyio.py) for function `savez` (or more precisely, function `_savez`).
21552155
:::
21562156
2157-
!bsol
2157+
2158+
::: {.callout-tip collapse="true" title="Solution"}
21582159
Here is the code:
21592160
21602161
```python
2162+
import numpy as np
2163+
2164+
2165+
class Savez:
2166+
def __init__(self, zipfilename):
2167+
import os
2168+
import sys
2169+
import tempfile
2170+
import zipfile
2171+
2172+
if isinstance(zipfilename, str):
2173+
if not zipfilename.endswith(".npz"):
2174+
zipfilename += ".npz"
2175+
2176+
# original _savez has no compression
2177+
compression = zipfile.ZIP_STORED
2178+
2179+
if sys.version_info >= (2, 5):
2180+
self.zip = zipfile.ZipFile(
2181+
zipfilename, mode="w", allowZip64=True, compression=compression
2182+
)
2183+
2184+
# Stage arrays in a temporary file on disk,
2185+
# before writing to zip.
2186+
fd, tmpfile = tempfile.mkstemp(suffix="-numpy.npy")
2187+
os.close(fd)
2188+
self.tmpfile = tmpfile
2189+
self.i = 0 # array counter
2190+
2191+
def savez(self, *args, **kwds):
2192+
import os
2193+
2194+
import numpy.lib.format as format
2195+
2196+
namedict = kwds
2197+
for val in args:
2198+
key = "arr_%d" % self.i
2199+
if key in namedict.keys():
2200+
raise ValueError("Cannot use un-named variables and keyword %s" % key)
2201+
namedict[key] = val
2202+
self.i += 1
2203+
2204+
try:
2205+
for key, val in namedict.items():
2206+
fname = key + ".npy"
2207+
fid = open(self.tmpfile, "wb")
2208+
try:
2209+
format.write_array(fid, np.asanyarray(val))
2210+
fid.close()
2211+
fid = None
2212+
self.zip.write(self.tmpfile, arcname=fname)
2213+
finally:
2214+
if fid:
2215+
fid.close()
2216+
finally:
2217+
os.remove(self.tmpfile)
2218+
2219+
def close(self):
2220+
self.zip.close()
21612221
```
21622222
2163-
!esol
2223+
:::
2224+
21642225
21652226
## Exercise: Visualize the impact of the Courant number {#sec-softeng2-exer-pulse1D-C}
2166-
file=pulse1D_Courant
21672227
21682228
Use the `pulse` function in the `wave1D_dn_vc.py` to simulate a pulse
21692229
through two media with different wave velocities. The aim is to
@@ -2177,25 +2237,47 @@ the investigations for different types of initial profiles: a Gaussian
21772237
pulse, a "cosine hat" pulse, half a"cosine hat" pulse, and a plug
21782238
pulse.
21792239
2180-
!bsol
2240+
2241+
::: {.callout-tip collapse="true" title="Solution"}
21812242
We make a little Python script for running one "pulse" simulation:
21822243
21832244
```python
2245+
import os
2246+
import sys
2247+
2248+
path = os.path.join(
2249+
os.pardir, os.pardir, os.pardir, os.pardir, "wave", "src-wave", "wave1D"
2250+
)
2251+
sys.path.insert(0, path)
2252+
from wave1D_dn_vc import pulse
2253+
2254+
pulse_tp = sys.argv[1]
2255+
C = float(sys.argv[2])
2256+
pulse(pulse_tp=pulse_tp, C=C, Nx=100, animate=False, slowness_factor=4)
21842257
```
21852258
21862259
Then we can make another (Bash) script running through the different types
21872260
of simulations and also making video files:
21882261
21892262
```bash
2263+
#!/bin/bash
2264+
for pulse_tp in gaussian cosinehat half-cosinehat plug; do
2265+
mkdir -p $pulse_tp
2266+
cd $pulse_tp
2267+
for C in 1 0.9 0.75; do
2268+
python ../pulse.py $pulse_tp $C
2269+
done
2270+
cd ..
2271+
done
21902272
```
21912273
21922274
Note that we make separate directories for the different type initial
21932275
profiles.
21942276
2195-
!esol
2277+
:::
2278+
21962279
21972280
## Exercise: Visualize the impact of the resolution {#sec-softeng2-exer-pulse1D-Nx}
2198-
file=pulse1D_Nx
21992281
22002282
We solve the same set of problems as in Exercise @sec-softeng2-exer-pulse1D-C,
22012283
except that we now fix $C=1$ and instead study the impact of

0 commit comments

Comments
 (0)