11import re
22import os
33import argparse
4+ from datetime import datetime
45from symfem import create_element
6+ from symfem .symbolic import x
57
68dir_path = os .path .dirname (os .path .realpath (__file__ ))
79element_path = os .path .join (dir_path , "../../elements" )
@@ -64,6 +66,7 @@ def make_html_page(content):
6466def 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 (" " , " " )
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
111127def 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
119177elementlist = []
@@ -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
0 commit comments