Skip to content

Commit 0efc212

Browse files
committed
Added example pictures
1 parent 5889481 commit 0efc212

6 files changed

Lines changed: 224 additions & 19 deletions

File tree

‎.github/scripts/build-pages.py‎

Lines changed: 193 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
import re
22
import os
33
import argparse
4+
from datetime import datetime
45
from symfem import create_element
6+
from symfem.symbolic import x
57

68
dir_path = os.path.dirname(os.path.realpath(__file__))
79
element_path = os.path.join(dir_path, "../../elements")
@@ -64,6 +66,7 @@ def make_html_page(content):
6466
def markup(content):
6567
out = ""
6668
popen = False
69+
code = False
6770
for line in content.split("\n"):
6871
if line.startswith("#"):
6972
if popen:
@@ -78,13 +81,26 @@ def markup(content):
7881
if popen:
7982
out += "</p>\n"
8083
popen = False
84+
elif line == "```":
85+
code = not code
8186
else:
8287
if not popen:
83-
out += "<p>"
88+
if code:
89+
out += "<p style='margin-left:50px;margin-right:50px;font-family:monospace'>"
90+
else:
91+
out += "<p>"
8492
popen = True
85-
out += line + " "
93+
if code:
94+
out += line.replace(" ", "&nbsp;")
95+
out += "<br />"
96+
else:
97+
out += line
98+
out += " "
8699

87100
out = re.sub(r"\[([^\]]+)\]\(([^\)]+)\)", r"<a href='\2'>\1</a>", out)
101+
now = datetime.now()
102+
out = out.replace("{{date:Y}}", now.strftime("%Y"))
103+
out = out.replace("{{date:D-M-Y}}", now.strftime("%d-%B-%Y"))
88104

89105
return out
90106

@@ -110,10 +126,52 @@ def markup(content):
110126

111127
def to_2d(c):
112128
if len(c) == 1:
113-
return (10 + c[0] * 100, 110)
129+
return (50 + c[0] * 100, 150)
114130
if len(c) == 2:
115-
return (10 + c[0] * 100, 110 - 100 * c[1])
116-
return (10 + c[0] * 100, 110 - 100 * c[1])
131+
return (50 + c[0] * 100, 150 - 100 * c[1])
132+
return (50 + c[0] * 100 + 50 * c[1], 150 - 100 * c[2] + 8 * c[0] - 20 * c[1])
133+
134+
135+
def make_lattice(n, offset=False):
136+
if element.reference.name == "interval":
137+
if offset:
138+
return [((i + 0.5) / (n + 1), ) for i in range(n)]
139+
else:
140+
return [(i / (n - 1), ) for i in range(n)]
141+
elif element.reference.name == "triangle":
142+
if offset:
143+
return [((i + 0.5) / (n + 1), (j + 0.5) / (n + 1)) for i in range(n) for j in range(n - i)]
144+
else:
145+
return [(i / (n - 1), j / (n - 1)) for i in range(n) for j in range(n - i)]
146+
elif element.reference.name == "tetrahedron":
147+
if offset:
148+
return [((i + 0.5) / (n + 1), (j + 0.5) / (n + 1), (k + 0.5) / (n + 1)) for i in range(n) for j in range(n - i) for k in range(n - i - j)]
149+
else:
150+
return [(i / (n - 1), j / (n - 1), k / (n - 1)) for i in range(n) for j in range(n - i) for k in range(n - i - j)]
151+
elif element.reference.name == "quadrilateral":
152+
if offset:
153+
return [((i + 0.5) / (n + 1), (j + 0.5) / (n + 1)) for i in range(n) for j in range(n)]
154+
else:
155+
return [(i / (n - 1), j / (n - 1)) for i in range(n) for j in range(n)]
156+
elif element.reference.name == "hexahedron":
157+
if offset:
158+
return [((i + 0.5) / (n + 1), (j + 0.5) / (n + 1), (k + 0.5) / (n + 1)) for i in range(n) for j in range(n) for k in range(n)]
159+
else:
160+
return [(i / (n - 1), j / (n - 1), k / (n - 1)) for i in range(n) for j in range(n) for k in range(n)]
161+
raise ValueError("Unknown cell type.")
162+
163+
164+
def subs(f, p):
165+
try:
166+
return [subs(i, p) for i in f]
167+
except:
168+
pass
169+
for i, j in zip(x, p):
170+
try:
171+
f = f.subs(i, j)
172+
except:
173+
pass
174+
return float(f)
117175

118176

119177
elementlist = []
@@ -125,16 +183,137 @@ def to_2d(c):
125183

126184
content = f"<h1>{data['name']}</h1>"
127185

186+
element_names = []
187+
element_examples= []
188+
128189
for cell, element_type in data["symfem"].items():
129-
element = create_element(cell, element_type, 1)
130-
131-
content += f"<h2>{cell}</h2>\n"
132-
content += "<svg width='120' height='120'>\n"
133-
for edge in element.reference.edges:
134-
p0 = to_2d(element.reference.vertices[edge[0]])
135-
p1 = to_2d(element.reference.vertices[edge[1]])
136-
content += f"<line x1='{p0[0]}' y1='{p0[1]}' x2='{p1[0]}' y2='{p1[1]}' stroke-width='4px' stroke-linecap='round' stroke='#AAAAAA' />"
137-
content += "</svg>\n"
190+
for order in [1, 2]:
191+
element = create_element(cell, element_type, order)
192+
193+
eg = ""
194+
195+
if element.range_dim == 1:
196+
if element.reference.tdim not in [1, 2]:
197+
continue
198+
199+
reference = ""
200+
for edge in element.reference.edges:
201+
p0 = to_2d(element.reference.vertices[edge[0]] + (0, ))
202+
p1 = to_2d(element.reference.vertices[edge[1]] + (0, ))
203+
reference += f"<line x1='{p0[0]}' y1='{p0[1]}' x2='{p1[0]}' y2='{p1[1]}' stroke-width='4px' stroke-linecap='round' stroke='#AAAAAA' />"
204+
205+
pairs = []
206+
if element.reference.tdim == 1:
207+
eval_points = make_lattice(10, False)
208+
pairs = [(i, i+1) for i, j in enumerate(eval_points[:-1])]
209+
elif element.reference.tdim == 2:
210+
N = 6
211+
eval_points = make_lattice(N, False)
212+
if element.reference.name == "triangle":
213+
s = 0
214+
for j in range(N-1, 0, -1):
215+
pairs += [(i, i+1) for i in range(s, s+j)]
216+
s += j + 1
217+
for k in range(N + 1):
218+
s = k
219+
for i in range(N, k, -1):
220+
if i != k + 1:
221+
pairs += [(s, s + i)]
222+
if k != 0:
223+
pairs += [(s, s + i - 1)]
224+
s += i
225+
if element.reference.name == "quadrilateral":
226+
for i in range(N):
227+
for j in range(N):
228+
node = i * N + j
229+
if j != N - 1:
230+
pairs += [(node, node + 1)]
231+
if i != N - 1:
232+
pairs += [(node, node + N)]
233+
if j != 0:
234+
pairs += [(node, node + N - 1)]
235+
236+
max_l = 0
237+
for f in element.get_basis_functions():
238+
for p in eval_points:
239+
r1 = subs(f, p)
240+
max_l = max(max_l, r1)
241+
242+
for f in element.get_basis_functions():
243+
eg += "<svg width='200' height='200'>\n"
244+
eg += reference
245+
for p, q in pairs:
246+
r1 = subs(f, eval_points[p])
247+
r2 = subs(f, eval_points[q])
248+
start = to_2d(eval_points[p] + (r1 / max_l, ))
249+
end = to_2d(eval_points[q] + (r2 / max_l, ))
250+
eg += f"<line x1='{start[0]}' y1='{start[1]}' x2='{end[0]}' y2='{end[1]}' stroke='#FF8800' stroke-width='2px' stroke-linecap='round' />"
251+
eg += "</svg>\n"
252+
253+
elif element.range_dim == element.reference.tdim:
254+
eval_points = make_lattice(6, True)
255+
256+
reference = ""
257+
for edge in element.reference.edges:
258+
p0 = to_2d(element.reference.vertices[edge[0]])
259+
p1 = to_2d(element.reference.vertices[edge[1]])
260+
reference += f"<line x1='{p0[0]}' y1='{p0[1]}' x2='{p1[0]}' y2='{p1[1]}' stroke-width='4px' stroke-linecap='round' stroke='#AAAAAA' />"
261+
262+
max_l = 0
263+
for f in element.get_basis_functions():
264+
for p in eval_points:
265+
res = subs(f, p)
266+
max_l = max(max_l, sum(i**2 for i in res) ** 0.5)
267+
268+
269+
for f in element.get_basis_functions():
270+
eg += "<svg width='200' height='200'>\n"
271+
eg += reference
272+
for p in eval_points:
273+
res = subs(f, p)
274+
start = to_2d(p)
275+
end = to_2d([i + j * 0.4 / max_l for i, j in zip(p, res)])
276+
a1 = [end[0] + 0.25 * (start[0] - end[0]) - 0.12 * (start[1] - end[1]),
277+
end[1] + 0.25 * (start[1] - end[1]) + 0.12 * (start[0] - end[0])]
278+
a2 = [end[0] + 0.25 * (start[0] - end[0]) + 0.12 * (start[1] - end[1]),
279+
end[1] + 0.25 * (start[1] - end[1]) - 0.12 * (start[0] - end[0])]
280+
wid = 4 * sum(i**2 for i in res) ** 0.5 / max_l
281+
eg += f"<line x1='{start[0]}' y1='{start[1]}' x2='{end[0]}' y2='{end[1]}' stroke='#FF8800' stroke-width='{wid}px' stroke-linecap='round' />"
282+
eg += f"<line x1='{a1[0]}' y1='{a1[1]}' x2='{end[0]}' y2='{end[1]}' stroke='#FF8800' stroke-width='{wid}px' stroke-linecap='round' />"
283+
eg += f"<line x1='{end[0]}' y1='{end[1]}' x2={a2[0]} y2={a2[1]} stroke='#FF8800' stroke-width='{wid}px' stroke-linecap='round' />"
284+
285+
eg += "</svg>\n"
286+
287+
if eg != "":
288+
element_names.append(f"{cell}<br />order {order}")
289+
element_examples.append(eg)
290+
291+
if len(element_names) > 0:
292+
content += f"<h2>Examples</h2>\n"
293+
for i, e in enumerate(element_names):
294+
cl = "eglink"
295+
if i == 0:
296+
cl += " current"
297+
content += f"<a class='{cl}' href='javascript:showeg({i})' id='eg{i}'>{e}</a>"
298+
for i, e in enumerate(element_examples):
299+
cl = "egdetail"
300+
if i == 0:
301+
cl += " current"
302+
content += f"<div class='{cl}' id='egd{i}'>{e}</div>"
303+
304+
content += "<script type='text/javascript'>\n"
305+
content += "function showeg(i){\n"
306+
content += f" for(var j=0;j<{len(element_names)};j++){{\n"
307+
content += " if(i==j){\n"
308+
content += " document.getElementById('eg'+j).className='eglink current'\n"
309+
content += " document.getElementById('egd'+j).className='egdetail current'\n"
310+
content += " } else {\n"
311+
content += " document.getElementById('eg'+j).className='eglink'\n"
312+
content += " document.getElementById('egd'+j).className='egdetail'\n"
313+
content += " }\n"
314+
content += " }\n"
315+
content += "}\n"
316+
content += "</script>"
138317

139318
elementlist.append((data['name'], f"{fname}.html"))
140319

‎files/sty.css‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,3 +33,13 @@ h1, h2, h3, h4, h5, h6 {font-family: 'Varela Round', sans-serif;font-weight:norm
3333
body, p {font-family:sans}
3434

3535
.head a {text-decoration:none}
36+
37+
.egdetail {display:none}
38+
.egdetail.current {display:block; border:2px solid black}
39+
40+
a.eglink {margin-right:10px;display:inline-block;padding:5px;border:2px solid #AAAAAA;color:#AAAAAA; border-bottom:none;border-radius:10px 10px 0px 0px;text-decoration:none;text-align:center}
41+
a.eglink.current {border:2px solid black;color:black; border-bottom:none}
42+
a.eglink.current:hover,
43+
a.eglink.current {color:black}
44+
a.eglink:hover {color:#FF8800}
45+

‎pages/citing.md‎

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Citing this website
2+
3+
On each of the element definition pages, you can find citations for that element.
4+
If you wish to cite this website, you can use the following BibTeX:
5+
6+
```
7+
@misc{defelement,
8+
AUTHOR = {Matthew Scroggs},
9+
TITLE = {{D}ef{E}lement: an encyclopedia of finite element definitions},
10+
YEAR = {{{{date:Y}}}},
11+
HOWPUBLISHED = {\url{https://defelement.com}},
12+
NOTE = {[Online; accessed {{date:D-M-Y}}]}
13+
}
14+
```
15+
16+
This will create a reference along the lines of:
17+
18+
Scroggs, M. <i>DefElement: an encyclopedia of finite element definitions</i>, {{date:Y}}, <a href='https://defelement.com'>https://defelement.com</a> [Online; accessed: {{date:D-M-Y}}].

‎pages/index.md‎

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
# Hello there
22

3-
Testing...
4-
5-
New paragraph
3+
This site is currently under construction.
64

75
[Index of elements](/elements)

‎templates/intro.html‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<html>
22
<head>
3-
<title>defelement</title>
3+
<title>DefElement</title>
44
<link rel="preconnect" href="https://fonts.gstatic.com">
55
<link href="https://fonts.googleapis.com/css2?family=Varela+Round&display=swap" rel="stylesheet">
66
<link rel='stylesheet' type='text/css' href='/sty.css'>

‎templates/outro.html‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
</div>
33
<div class='footer'>
44
<div class='content'>
5-
&copy; <a href='https://mscroggs.co.uk'>Matthew Scroggs</a>, 2020-2021.
5+
Created by <a href='https://mscroggs.co.uk'>Matthew Scroggs</a>, 2020-2021. <a href='/citing.html'>Citing this website</a>.
66
</div>
77
</div>
88
</div>

0 commit comments

Comments
 (0)