Repository: CALFEM/calfem-python (language: python)

Issue:
Merge from master.



Discussion / hints:

Fix patch:
diff --git a/.gitignore b/.gitignore
index 373ae8f..fc9fc50 100644
--- a/.gitignore
+++ b/.gitignore
@@ -33,29 +33,9 @@ dist/
 *.iml
 .idea/
 .vscode/settings.json
-examples/.ipynb_checkpoints/exm0-checkpoint.ipynb
-examples/.ipynb_checkpoints/exm1-checkpoint.ipynb
-examples/.ipynb_checkpoints/exm2-checkpoint.ipynb
-examples/.ipynb_checkpoints/exm3-checkpoint.ipynb
-examples/.ipynb_checkpoints/exm6-checkpoint.ipynb
-examples/.ipynb_checkpoints/exm7-checkpoint.ipynb
+examples/.ipynb_checkpoints/*
 # .vscode/settings.json
-examples/.ipynb_checkpoints/exm10-checkpoint.ipynb
-examples/.ipynb_checkpoints/exm12-checkpoint.ipynb
-examples/.ipynb_checkpoints/exm13-checkpoint.ipynb
-calfem/.ipynb_checkpoints/core-checkpoint.py
-calfem/.ipynb_checkpoints/geometry-checkpoint.py
-calfem/.ipynb_checkpoints/mesh-checkpoint.py
-calfem/.ipynb_checkpoints/vis_mpl-checkpoint.py
-examples/.ipynb_checkpoints/exed1-checkpoint.py
-examples/.ipynb_checkpoints/exed1-checkpoint.ui
-examples/.ipynb_checkpoints/exm1-checkpoint.py
-examples/.ipynb_checkpoints/exm2_mpl-checkpoint.py
-examples/.ipynb_checkpoints/exm4_mpl-checkpoint.py
-examples/.ipynb_checkpoints/exm7_mpl-checkpoint.py
-examples/.ipynb_checkpoints/exs1-checkpoint.py
-examples/.ipynb_checkpoints/Untitled1-checkpoint.ipynb
-examples/.ipynb_checkpoints/exs4a-checkpoint.py
+calfem/.ipynb_checkpoints/*
 exm6.vtk
 
 # new notebook examples
diff --git a/build-package.py b/build-package.py
index edc6757..9c27f0e 100644
--- a/build-package.py
+++ b/build-package.py
@@ -14,7 +14,7 @@ def build_package():
 
 if __name__ == "__main__":
 
-    package_version = "3.6.4"
+    package_version = "3.6.5"
 
     update_setup("calfem-python", package_version, "'numpy', 'visvis', 'pyvtk', 'matplotlib', 'scipy', 'gmsh', 'qtpy', 'vedo', 'tabulate'")
 
diff --git a/calfem-python.psproj b/calfem-python.psproj
deleted file mode 100644
index 2ee6828..0000000
--- a/calfem-python.psproj
+++ /dev/null
@@ -1,21 +0,0 @@
-﻿[PyScripter]
-Version=4.0.0.6
-
-[Project]
-ClassName=TProjectRootNode
-StoreRelativePaths=TRUE
-ShowFileExtensions=FALSE
-
-[Project\ChildNodes\Node0]
-ClassName=TProjectFilesNode
-
-[Project\ChildNodes\Node1]
-ClassName=TProjectRunConfiguationsNode
-
-[Project\ChildNodes]
-Count=2
-
-[Project\ExtraPythonPath]
-Item0=D:\Users\Jonas\Development\calfem-python
-Count=1
-
diff --git a/calfem/core.py b/calfem/core.py
index 7a8ea54..c491d73 100644
--- a/calfem/core.py
+++ b/calfem/core.py
@@ -4166,7 +4166,7 @@ def plante(ex, ey, ep, D, eq=None):
         if eq is None:
             return Ke
         else:
-            return Ke, fe
+            return Ke, fe.T
 
     #--------- plane strain --------------------------------------
 
@@ -4190,7 +4190,7 @@ def plante(ex, ey, ep, D, eq=None):
         if eq is None:
             return Ke
         else:
-            return Ke, fe
+            return Ke, fe.T
 
     else:
         info("Error ! Check first argument, ptype=1 or 2 allowed")
diff --git a/calfem/utils.py b/calfem/utils.py
index b5faa41..4d84b4b 100644
--- a/calfem/utils.py
+++ b/calfem/utils.py
@@ -9,12 +9,13 @@
 import numpy as np
 import calfem.core as cfc
 import logging as cflog
+import tabulate as tab
 
 have_pyvtk = True
 
 try:
     import pyvtk as vtk
-except:
+except: 
     have_pyvtk = False
 
 haveMatplotLib = True
@@ -23,14 +24,84 @@
 have_mlab = haveMlab
 have_matplotlib = haveMatplotLib
 
+have_ipython = True
+
+try:
+    from IPython.core.display import display, HTML
+except:
+    have_ipython = False
+
+
 
 def error(msg):
     cflog.error(" "+msg)
 
-
 def info(msg):
     cflog.info(" "+msg)
 
+def set_debug_level(level):
+    cflog.getLogger().setLevel(level)
+
+def type_of_script():
+    try:
+        ipy_str = str(type(get_ipython()))
+        if 'zmqshell' in ipy_str:
+            return 'jupyter'
+        if 'terminal' in ipy_str:
+            return 'ipython'
+    except:
+        return 'terminal'
+
+def disp(msg):
+    if type_of_script() == 'jupyter':
+        display(HTML(f"{msg}"))
+    else:
+        print(msg)
+
+def disp_par(msg):
+    if type_of_script() == 'jupyter':
+        display(HTML(f"<p>{msg}</p>"))
+    else:
+        print(f"\nmsg\n")
+
+def disp_bold(msg):
+    if type_of_script() == 'jupyter':
+        display(HTML(f"<b>{msg}</b>"))
+    else:
+        print(f"**{msg}**")
+    
+def disp_bold_par(msg):
+    if type_of_script() == 'jupyter':
+        display(HTML(f"<p><b>{msg}</b></p>"))
+    else:
+        print(f"\n**{msg}**\n")
+
+def disp_h1(msg):
+    if type_of_script() == 'jupyter':
+        display(HTML(f"<h1>{msg}</h1>"))
+    else:
+        print(f"\n# {msg}\n")
+
+def disp_h2(msg):
+    if type_of_script() == 'jupyter':
+        display(HTML(f"<h2>{msg}</h2>"))
+    else:
+        print(f"\n## {msg}\n")
+
+def disp_h3(msg):
+    if type_of_script() == 'jupyter':
+        display(HTML(f"<h3>{msg}</h3>"))
+    else:
+        print(f"\n## {msg}\n")
+
+def disp_array(a, headers=[], fmt=".4e", tablefmt="psql", showindex=False):
+    """
+    Print a numpy array in a nice way.
+    """
+    if type_of_script() == 'jupyter':
+        display(tab.tabulate(np.asarray(a), tablefmt="html", floatfmt=".4e", showindex=showindex, headers=headers))
+    else:
+        print(tab.tabulate(np.asarray(a), tablefmt=tablefmt, floatfmt=fmt, showindex=showindex, headers=headers))
 
 class ElementProperties(object):
     def __init__(self):
@@ -472,7 +543,9 @@ def export_vtk_stress(filename, coords, topo, a=None, el_scalar=None, el_vec1=No
         el_vec2             Vector value for each element (list)
     """
 
-    points = coords.tolist()
+    points = np.zeros([coords.shape[0], 3], dtype=np.float64)
+    points[:,0:2] = coords
+    points = points.tolist()
     polygons = (topo-1).tolist()
 
     displ = []
@@ -485,7 +558,7 @@ def export_vtk_stress(filename, coords, topo, a=None, el_scalar=None, el_vec1=No
 
     if a is not None:
         for i in range(0, len(a), 2):
-            displ.append([np.asscalar(a[i]), np.asscalar(a[i+1]), 0.0])
+            displ.append([a[i].item(), a[i+1].item(), 0.0])
 
         point_data = vtk.PointData(vtk.Vectors(displ, name="displacements"))
 
diff --git a/calfem/vis_mpl.py b/calfem/vis_mpl.py
index b000c13..812b980 100644
--- a/calfem/vis_mpl.py
+++ b/calfem/vis_mpl.py
@@ -5,6 +5,8 @@
 Contains all the functions implementing visualisation routines.
 """
 
+import os
+
 from matplotlib.transforms import Transform
 import numpy as np
 
@@ -21,7 +23,9 @@
 
 try:
     from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
-    from matplotlib.backends.backend_qt5agg import NavigationToolbar2QT as NavigationToolbar
+    from matplotlib.backends.backend_qt5agg import (
+        NavigationToolbar2QT as NavigationToolbar,
+    )
 except:
     print("Could not import Matplotlib backends. Probarbly due to missing Qt.")
 
@@ -32,6 +36,7 @@
 
 g_figures = []
 
+
 def error(msg):
     """Log error message"""
     cflog.error(msg)
@@ -51,11 +56,21 @@ def figure_class():
 
 cfv_def_mappable = None
 
-
 def set_mappable(mappable):
     global cfv_def_mappable
     cfv_def_mappable = mappable
 
+cfv_block_at_show = True
+
+def set_block_at_show(show_block):
+    cfv_block_at_show = show_block
+
+def ioff():
+    plt.ioff()
+
+def ion():
+    plt.ion()
+
 
 def colorbar(**kwargs):
     """Add a colorbar to current figure"""
@@ -67,15 +82,18 @@ def colorbar(**kwargs):
     else:
         return plt.colorbar(**kwargs)
 
+
 def axis(*args, **kwargs):
     """Define axis of figure (Matplotlib passthrough)"""
     plt.axis(*args, **kwargs)
 
+
 def title(*args, **kwargs):
     """Define title of figure (Matplotlib passthrough)"""
     plt.title(*args, **kwargs)
 
-def figure(figure=None, show=True, fig_size=(4, 3)):
+
+def figure(figure=None, show=True, fig_size=(6, 5.33)):
     """Create a visvis figure with extras."""
     f = None
 
@@ -104,7 +122,7 @@ def figure_widget(fig, parent=None):
 
 def close_all():
     """Close all visvis windows."""
-    plt.close('all')
+    plt.close("all")
 
 
 closeAll = close_all
@@ -136,7 +154,12 @@ def camera3d():
 
 def show_and_wait():
     """Wait for plot to show"""
-    plt.show()
+    global cfv_block_at_show
+
+    if "CFV_NO_BLOCK" in os.environ:
+        plt.show(block=False)
+    else:
+        plt.show(block=cfv_block_at_show)
 
 
 showAndWait = show_and_wait
@@ -146,6 +169,7 @@ def show_and_wait_mpl():
     """Wait for plot to show"""
     plt.show()
 
+
 def show():
     """Use in Qt applications"""
     plt.show()
@@ -155,7 +179,7 @@ def show():
 
 
 def set_figure_dpi(dpi):
-    mpl.rcParams['figure.dpi'] = dpi
+    mpl.rcParams["figure.dpi"] = dpi
 
 
 def text(text, pos, angle=0, **kwargs):
@@ -168,7 +192,7 @@ def text(text, pos, angle=0, **kwargs):
 
 
 def ce2vf(coords, edof, dofs_per_node, el_type):
-    '''Duplicate code. Extracts verts, faces and verticesPerFace from input.'''
+    """Duplicate code. Extracts verts, faces and verticesPerFace from input."""
 
     if np.shape(coords)[1] == 2:
         is_3d = False
@@ -178,32 +202,35 @@ def ce2vf(coords, edof, dofs_per_node, el_type):
         is_3d = True
         verts = coords
     else:
-        raise ValueError('coords must be N-by-2 or N-by-3 array')
+        raise ValueError("coords must be N-by-2 or N-by-3 array")
 
     if el_type in [2, 4]:  # elements with triangular faces
         vertices_per_face = 3
     elif el_type in [3, 5, 16]:  # elements with rectangular faces
         vertices_per_face = 4
     else:  # [NOTE] This covers all element types available in CALFEM plus tetrahedrons. If more element types are added it is necessary to include them here and below.
-        raise ValueError('element type not implemented')
+        raise ValueError("element type not implemented")
 
-    faces = (edof[:, 0::dofs_per_node]-1)/dofs_per_node
+    faces = (edof[:, 0::dofs_per_node] - 1) / dofs_per_node
     # 'faces' here are actually lists of nodes in elements, not in faces necessarily if the elements are in 3D. This case is handled below.
 
     if el_type in [4, 5]:  # if hexahedrons or tetrahedrons:
         if el_type == 5:
-            G = np.array([[0, 3, 2, 1],
-                          [0, 1, 5, 4],
-                          [4, 5, 6, 7],
-                          [2, 6, 5, 1],
-                          [2, 3, 7, 6],
-                          [0, 4, 7, 3]])  # G is an array that is used to decomposes hexahedrons into its component faces.
-           # The numbers are from the node orders (see p94 in the Gmsh manual) and each row makes one face.
+            G = np.array(
+                [
+                    [0, 3, 2, 1],
+                    [0, 1, 5, 4],
+                    [4, 5, 6, 7],
+                    [2, 6, 5, 1],
+                    [2, 3, 7, 6],
+                    [0, 4, 7, 3],
+                ]
+            )  # G is an array that is used to decomposes hexahedrons into its component faces.
+        # The numbers are from the node orders (see p94 in the Gmsh manual) and each row makes one face.
         elif el_type == 4:
-            G = np.array([[0, 1, 2],
-                          [0, 3, 2],
-                          [1, 3, 2],
-                          [0, 3, 1]])  # This G decomposes tetrahedrons into faces
+            G = np.array(
+                [[0, 1, 2], [0, 3, 2], [1, 3, 2], [0, 3, 1]]
+            )  # This G decomposes tetrahedrons into faces
         faces = np.vstack([faces[i, G] for i in range(faces.shape[0])])
     elif el_type == 16:  # if 8-node-quads:
         # The first 4 nodes are the corners of the high order quad.
@@ -212,8 +239,19 @@ def ce2vf(coords, edof, dofs_per_node, el_type):
     return verts, np.asarray(faces, dtype=int), vertices_per_face, is_3d
 
 
-def draw_mesh(coords, edof, dofs_per_node, el_type, title=None, color=(0, 0, 0), face_color=(0.8, 0.8, 0.8), node_color=(0, 0, 0), filled=False, show_nodes=False):
-    '''
+def draw_mesh(
+    coords,
+    edof,
+    dofs_per_node,
+    el_type,
+    title=None,
+    color=(0, 0, 0),
+    face_color=(0.8, 0.8, 0.8),
+    node_color=(0, 0, 0),
+    filled=False,
+    show_nodes=False,
+):
+    """
     Draws wire mesh of model in 2D or 3D. Returns the Mesh object that represents
     the mesh.
     Args:
@@ -231,16 +269,15 @@ def draw_mesh(coords, edof, dofs_per_node, el_type, title=None, color=(0, 0, 0),
             Boolean. True if the view should be changed to show the whole model. Default True.
         title:
             String. Changes title of the figure. Default "Mesh".
-        color: 
+        color:
             3-tuple or char. Color of the wire. Defaults to black (0,0,0). Can also be given as a character in 'rgbycmkw'.
         face_color:
             3-tuple or char. Color of the faces. Defaults to white (1,1,1). Parameter filled must be True or faces will not be drawn at all.
         filled:
             Boolean. Faces will be drawn if True. Otherwise only the wire is drawn. Default False.
-    '''
+    """
 
-    verts, faces, vertices_per_face, is_3d = ce2vf(
-        coords, edof, dofs_per_node, el_type)
+    verts, faces, vertices_per_face, is_3d = ce2vf(coords, edof, dofs_per_node, el_type)
 
     y = verts[:, 0]
     z = verts[:, 1]
@@ -248,24 +285,23 @@ def draw_mesh(coords, edof, dofs_per_node, el_type, title=None, color=(0, 0, 0),
     values = np.zeros(faces.shape[0], float)
 
     def quatplot(y, z, quatrangles, values=[], ax=None, **kwargs):
-
         if not ax:
             ax = plt.gca()
         yz = np.c_[y, z]
         v = yz[quatrangles]
         if filled:
             pc = matplotlib.collections.PolyCollection(
-                v, facecolor=face_color, **kwargs)
+                v, facecolor=face_color, **kwargs
+            )
         else:
-            pc = matplotlib.collections.PolyCollection(
-                v, facecolor='none', **kwargs)
+            pc = matplotlib.collections.PolyCollection(v, facecolor="none", **kwargs)
 
         ax.add_collection(pc)
         ax.autoscale()
         return pc
 
     ax = plt.gca()
-    ax.set_aspect('equal')
+    ax.set_aspect("equal")
 
     pc = quatplot(y, z, faces, values, ax=ax, edgecolor=color)
 
@@ -279,8 +315,19 @@ def quatplot(y, z, quatrangles, values=[], ax=None, **kwargs):
 drawMesh = draw_mesh
 
 
-def draw_elements(ex, ey, title='', color=(0, 0, 0), face_color=(0.8, 0.8, 0.8), node_color=(0, 0, 0), line_style='solid', filled=False, closed=True, show_nodes=False):
-    '''
+def draw_elements(
+    ex,
+    ey,
+    title="",
+    color=(0, 0, 0),
+    face_color=(0.8, 0.8, 0.8),
+    node_color=(0, 0, 0),
+    line_style="solid",
+    filled=False,
+    closed=True,
+    show_nodes=False,
+):
+    """
     Draws wire mesh of model in 2D or 3D. Returns the Mesh object that represents
     the mesh.
     Args:
@@ -298,13 +345,13 @@ def draw_elements(ex, ey, title='', color=(0, 0, 0), face_color=(0.8, 0.8, 0.8),
             Boolean. True if the view should be changed to show the whole model. Default True.
         title:
             String. Changes title of the figure. Default "Mesh".
-        color: 
+        color:
             3-tuple or char. Color of the wire. Defaults to black (0,0,0). Can also be given as a character in 'rgbycmkw'.
         face_color:
             3-tuple or char. Color of the faces. Defaults to white (1,1,1). Parameter filled must be True or faces will not be drawn at all.
         filled:
             Boolean. Faces will be drawn if True. Otherwise only the wire is drawn. Default False.
-    '''
+    """
 
     # ex = [
     #        [x1_1, x2_1, xn_1],
@@ -318,7 +365,7 @@ def draw_elements(ex, ey, title='', color=(0, 0, 0), face_color=(0.8, 0.8, 0.8),
     #        [y1_m, y2_m, yn_m]
     #      ]
 
-    if ex.ndim != 1:    
+    if ex.ndim != 1:
         nnodes = ex.shape[1]
         nel = ex.shape[0]
     else:
@@ -338,22 +385,40 @@ def draw_elements(ex, ey, title='', color=(0, 0, 0), face_color=(0.8, 0.8, 0.8),
 
     if filled:
         pc = matplotlib.collections.PolyCollection(
-            polys, facecolor=face_color, edgecolor=color, linestyle=line_style, closed=closed)
+            polys,
+            facecolor=face_color,
+            edgecolor=color,
+            linestyle=line_style,
+            closed=closed,
+        )
     else:
         pc = matplotlib.collections.PolyCollection(
-            polys, facecolor='none', edgecolor=color, linestyle=line_style, closed=closed)
+            polys,
+            facecolor="none",
+            edgecolor=color,
+            linestyle=line_style,
+            closed=closed,
+        )
 
     ax.add_collection(pc)
     ax.autoscale()
 
-    ax.set_aspect('equal')
+    ax.set_aspect("equal")
 
     if title != None:
         ax.set(title=title)
 
 
-def draw_node_circles(ex, ey, title='', color=(0, 0, 0), face_color=(0.8, 0.8, 0.8), filled=False, marker_type='o'):
-    '''
+def draw_node_circles(
+    ex,
+    ey,
+    title="",
+    color=(0, 0, 0),
+    face_color=(0.8, 0.8, 0.8),
+    filled=False,
+    marker_type="o",
+):
+    """
     Draws wire mesh of model in 2D or 3D. Returns the Mesh object that represents
     the mesh.
     Args:
@@ -371,13 +436,13 @@ def draw_node_circles(ex, ey, title='', color=(0, 0, 0), face_color=(0.8, 0.8, 0
             Boolean. True if the view should be changed to show the whole model. Default True.
         title:
             String. Changes title of the figure. Default "Mesh".
-        color: 
+        color:
             3-tuple or char. Color of the wire. Defaults to black (0,0,0). Can also be given as a character in 'rgbycmkw'.
         face_color:
             3-tuple or char. Color of the faces. Defaults to white (1,1,1). Parameter filled must be True or faces will not be drawn at all.
         filled:
             Boolean. Faces will be drawn if True. Otherwise only the wire is drawn. Default False.
-    '''
+    """
 
     # ex = [
     #        [x1_1, x2_1, xn_1],
@@ -409,22 +474,35 @@ def draw_node_circles(ex, ey, title='', color=(0, 0, 0), face_color=(0.8, 0.8, 0
     if filled:
         ax.scatter(x, y, color=color, marker=marker_type)
     else:
-        ax.scatter(x, y, edgecolor=color, color='none', marker=marker_type)
+        ax.scatter(x, y, edgecolor=color, color="none", marker=marker_type)
 
     ax.autoscale()
 
-    ax.set_aspect('equal')
+    ax.set_aspect("equal")
 
     if title != None:
         ax.set(title=title)
 
 
-def draw_element_values(values, coords, edof, dofs_per_node, el_type, displacements=None, draw_elements=True, draw_undisplaced_mesh=False, magnfac=1.0, title=None, color=(0, 0, 0), node_color=(0, 0, 0)):
-    '''
-    Draws scalar element values in 2D or 3D. 
+def draw_element_values(
+    values,
+    coords,
+    edof,
+    dofs_per_node,
+    el_type,
+    displacements=None,
+    draw_elements=True,
+    draw_undisplaced_mesh=False,
+    magnfac=1.0,
+    title=None,
+    color=(0, 0, 0),
+    node_color=(0, 0, 0),
+):
+    """
+    Draws scalar element values in 2D or 3D.
 
     Args:
-        ev: 
+        ev:
             An N-by-1 array or a list of scalars. The Scalar values of the elements. ev[i] should be the value of element i.
 
         coords:
@@ -436,7 +514,7 @@ def draw_element_values(values, coords, edof, dofs_per_node, el_type, displaceme
         dofs_per_node:
             Integer. Dofs per node.
 
-        el_type: 
+        el_type:
             Integer. Element Type. See Gmsh manual for details. Usually 2 for triangles or 3 for quadrangles.
 
         displacements:
@@ -445,15 +523,15 @@ def draw_element_values(values, coords, edof, dofs_per_node, el_type, displaceme
         draw_mesh:
             Boolean. True if mesh wire should be drawn. Default True.
 
-        draw_undisplaced_mesh: 
+        draw_undisplaced_mesh:
             Boolean. True if the wire of the undisplaced mesh should be drawn on top of the displaced mesh. Default False. Use only if displacements != None.
 
-        magnfac: 
+        magnfac:
             Float. Magnification factor. Displacements are multiplied by this value. Use this to make small displacements more visible.
 
-        title: 
+        title:
             String. Changes title of the figure. Default "Element Values".
-    '''
+    """
 
     if draw_undisplaced_mesh:
         draw_mesh(coords, edof, dofs_per_node, el_type, color=(0.5, 0.5, 0.5))
@@ -463,20 +541,17 @@ def draw_element_values(values, coords, edof, dofs_per_node, el_type, displaceme
             displacements = np.reshape(displacements, (-1, coords.shape[1]))
             coords = np.asarray(coords + magnfac * displacements)
 
-    verts, faces, vertices_per_face, is_3d = ce2vf(
-        coords, edof, dofs_per_node, el_type)
+    verts, faces, vertices_per_face, is_3d = ce2vf(coords, edof, dofs_per_node, el_type)
 
     y = verts[:, 0]
     z = verts[:, 1]
 
     def quatplot(y, z, quatrangles, values=[], ax=None, **kwargs):
-
         if not ax:
             ax = plt.gca()
         yz = np.c_[y, z]
         v = yz[quatrangles]
-        pc = matplotlib.collections.PolyCollection(
-            v, **kwargs)
+        pc = matplotlib.collections.PolyCollection(v, **kwargs)
 
         pc.set_array(np.asarray(values))
         ax.add_collection(pc)
@@ -485,14 +560,12 @@ def quatplot(y, z, quatrangles, values=[], ax=None, **kwargs):
 
     fig = plt.gcf()
     ax = plt.gca()
-    ax.set_aspect('equal')
+    ax.set_aspect("equal")
 
     if draw_elements:
-        pc = quatplot(y, z, faces, values, ax=ax,
-                      edgecolor=color)
+        pc = quatplot(y, z, faces, values, ax=ax, edgecolor=color)
     else:
-        pc = quatplot(y, z, faces, values, ax=ax,
-                      edgecolor=None)
+        pc = quatplot(y, z, faces, values, ax=ax, edgecolor=None)
 
     # pc = quatplot(y,z, np.asarray(edof-1), values, ax=ax,
     #         edgecolor="crimson", cmap="rainbow")
@@ -503,33 +576,45 @@ def quatplot(y, z, quatrangles, values=[], ax=None, **kwargs):
         ax.set(title=title)
 
 
-def draw_displacements(a, coords, edof, dofs_per_node, el_type, draw_undisplaced_mesh=False, magnfac=-1.0, magscale=0.25, title=None, color=(0, 0, 0), node_color=(0, 0, 0)):
-    '''
+def draw_displacements(
+    a,
+    coords,
+    edof,
+    dofs_per_node,
+    el_type,
+    draw_undisplaced_mesh=False,
+    magnfac=-1.0,
+    magscale=0.25,
+    title=None,
+    color=(0, 0, 0),
+    node_color=(0, 0, 0),
+):
+    """
     Draws scalar element values in 2D or 3D. Returns the world object
     elementsWobject that represents the mesh.
 
     Args:
-        ev: 
+        ev:
             An N-by-1 array or a list of scalars. The Scalar values of the elements. ev[i] should be the value of element i.
-        coords: 
+        coords:
             An N-by-2 or N-by-3 array. Row i contains the x,y,z coordinates of node i.
-        edof: 
+        edof:
             An E-by-L array. Element topology. (E is the number of elements and L is the number of dofs per element)
-        dofs_per_node: 
+        dofs_per_node:
             Integer. Dofs per node.
-        el_type: 
+        el_type:
             Integer. Element Type. See Gmsh manual for details. Usually 2 for triangles or 3 for quadrangles.
-        displacements:  
+        displacements:
             An N-by-2 or N-by-3 array. Row i contains the x,y,z  displacements of node i.
-        axes: 
+        axes:
             Matlotlib Axes. The Axes where the model will be drawn. If unspecified the current Axes will be used, or a new Axes will be created if none exist.
         draw_undisplaced_mesh:
             Boolean. True if the wire of the undisplaced mesh should be drawn on top of the displaced mesh. Default False. Use only if displacements != None.
-        magnfac:        
+        magnfac:
             Float. Magnification factor. Displacements are multiplied by this value. Use this to make small displacements more visible.
-        title:          
+        title:
             String. Changes title of the figure. Default "Element Values".
-    '''
+    """
 
     if draw_undisplaced_mesh:
         draw_mesh(coords, edof, dofs_per_node, el_type, color=(0.8, 0.8, 0.8))
@@ -553,12 +638,11 @@ def draw_displacements(a, coords, edof, dofs_per_node, el_type, draw_undisplaced
                 max_size = y_size
 
             if magnfac < 0:
-                magnfac = 0.25*max_size
+                magnfac = 0.25 * max_size
 
             coords = np.asarray(coords + magnfac * a)
 
-    verts, faces, vertices_per_face, is_3d = ce2vf(
-        coords, edof, dofs_per_node, el_type)
+    verts, faces, vertices_per_face, is_3d = ce2vf(coords, edof, dofs_per_node, el_type)
 
     y = verts[:, 0]
     z = verts[:, 1]
@@ -566,23 +650,22 @@ def draw_displacements(a, coords, edof, dofs_per_node, el_type, draw_undisplaced
     values = []
 
     def quatplot(y, z, quatrangles, values=[], ax=None, **kwargs):
-
         if not ax:
             ax = plt.gca()
         yz = np.c_[y, z]
         v = yz[quatrangles]
-        pc = matplotlib.collections.PolyCollection(
-            v, **kwargs)
+        pc = matplotlib.collections.PolyCollection(v, **kwargs)
 
         ax.add_collection(pc)
         ax.autoscale()
         return pc
 
     ax = plt.gca()
-    ax.set_aspect('equal')
+    ax.set_aspect("equal")
 
-    pc = quatplot(y, z, faces, values, ax=ax, edgecolor=(
-        0.3, 0.3, 0.3), facecolor='none')
+    pc = quatplot(
+        y, z, faces, values, ax=ax, edgecolor=(0.3, 0.3, 0.3), facecolor="none"
+    )
 
     if title != None:
         ax.set(title=title)
@@ -595,14 +678,12 @@ def create_ordered_polys(geom, N=10):
 
     o_polys = []
 
-    for (id, (surf_name, curve_ids, holes, _, _, _)) in geom.surfaces.items():
-
+    for id, (surf_name, curve_ids, holes, _, _, _) in geom.surfaces.items():
         polygon = np.empty((0, 3), float)
 
         polys = []
 
         for curve_id in curve_ids:
-
             curve_name, curve_points, _, _, _, _ = geom.curves[curve_id]
             points = geom.get_point_coords(curve_points)
 
@@ -640,19 +721,15 @@ def create_ordered_polys(geom, N=10):
 
 
 def draw_ordered_polys(o_polys):
-
     for poly in o_polys:
-
         ax = plt.gca()
         path = mpp.Path(poly[:, 0:2])
-        patch = patches.PathPatch(path, facecolor='orange', lw=1)
+        patch = patches.PathPatch(path, facecolor="orange", lw=1)
         ax.add_patch(patch)
 
 
 def point_in_geometry(o_polys, point):
-
     for poly in o_polys:
-
         path = mpp.Path(poly[:, 0:2])
         inside = path.contains_points([point])
 
@@ -669,7 +746,7 @@ def topo_to_tri(edof):
     if edof.shape[1] == 3:
         return edof
     elif edof.shape[1] == 4:
-        new_edof = np.zeros((edof.shape[0]*2, 3), int)
+        new_edof = np.zeros((edof.shape[0] * 2, 3), int)
         new_edof[0::2, 0] = edof[:, 0]
         new_edof[0::2, 1] = edof[:, 1]
         new_edof[0::2, 2] = edof[:, 2]
@@ -678,7 +755,7 @@ def topo_to_tri(edof):
         new_edof[1::2, 2] = edof[:, 0]
         return new_edof
     elif edof.shape[1] == 8:
-        new_edof = np.zeros((edof.shape[0]*6, 3), int)
+        new_edof = np.zeros((edof.shape[0] * 6, 3), int)
         new_edof[0::6, 0] = edof[:, 0]
         new_edof[0::6, 1] = edof[:, 4]
         new_edof[0::6, 2] = edof[:, 7]
@@ -702,14 +779,23 @@ def topo_to_tri(edof):
         error("Element topology not supported.")
 
 
-def draw_nodal_values_contourf(values, coords, edof, levels=12, title=None, dofs_per_node=None, el_type=None, draw_elements=False):
+def draw_nodal_values_contourf(
+    values,
+    coords,
+    edof,
+    levels=12,
+    title=None,
+    dofs_per_node=None,
+    el_type=None,
+    draw_elements=False,
+):
     """Draws element nodal values as filled contours. Element topologies
     supported are triangles, 4-node quads and 8-node quads."""
 
     edof_tri = topo_to_tri(edof)
 
     ax = plt.gca()
-    ax.set_aspect('equal')
+    ax.set_aspect("equal")
 
     x, y = coords.T
     v = np.asarray(values)
@@ -717,8 +803,7 @@ def draw_nodal_values_contourf(values, coords, edof, levels=12, title=None, dofs
 
     if draw_elements:
         if dofs_per_node != None and el_type != None:
-            draw_mesh(coords, edof, dofs_per_node,
-                      el_type, color=(0.2, 0.2, 0.2))
+            draw_mesh(coords, edof, dofs_per_node, el_type, color=(0.2, 0.2, 0.2))
         else:
             info("dofs_per_node and el_type must be specified to draw the mesh.")
 
@@ -726,14 +811,23 @@ def draw_nodal_values_contourf(values, coords, edof, levels=12, title=None, dofs
         ax.set(title=title)
 
 
-def draw_nodal_values_contour(values, coords, edof, levels=12, title=None, dofs_per_node=None, el_type=None, draw_elements=False):
+def draw_nodal_values_contour(
+    values,
+    coords,
+    edof,
+    levels=12,
+    title=None,
+    dofs_per_node=None,
+    el_type=None,
+    draw_elements=False,
+):
     """Draws element nodal values as filled contours. Element topologies
     supported are triangles, 4-node quads and 8-node quads."""
 
     edof_tri = topo_to_tri(edof)
 
     ax = plt.gca()
-    ax.set_aspect('equal')
+    ax.set_aspect("equal")
 
     x, y = coords.T
     v = np.asarray(values)
@@ -741,8 +835,7 @@ def draw_nodal_values_contour(values, coords, edof, levels=12, title=None, dofs_
 
     if draw_elements:
         if dofs_per_node != None and el_type != None:
-            draw_mesh(coords, edof, dofs_per_node,
-                      el_type, color=(0.2, 0.2, 0.2))
+            draw_mesh(coords, edof, dofs_per_node, el_type, color=(0.2, 0.2, 0.2))
         else:
             info("dofs_per_node and el_type must be specified to draw the mesh.")
 
@@ -750,14 +843,22 @@ def draw_nodal_values_contour(values, coords, edof, levels=12, title=None, dofs_
         ax.set(title=title)
 
 
-def draw_nodal_values_shaded(values, coords, edof, title=None, dofs_per_node=None, el_type=None, draw_elements=False):
+def draw_nodal_values_shaded(
+    values,
+    coords,
+    edof,
+    title=None,
+    dofs_per_node=None,
+    el_type=None,
+    draw_elements=False,
+):
     """Draws element nodal values as shaded triangles. Element topologies
     supported are triangles, 4-node quads and 8-node quads."""
 
     edof_tri = topo_to_tri(edof)
 
     ax = plt.gca()
-    ax.set_aspect('equal')
+    ax.set_aspect("equal")
 
     x, y = coords.T
     v = np.asarray(values)
@@ -765,8 +866,7 @@ def draw_nodal_values_shaded(values, coords, edof, title=None, dofs_per_node=Non
 
     if draw_elements:
         if dofs_per_node != None and el_type != None:
-            draw_mesh(coords, edof, dofs_per_node,
-                      el_type, color=(0.2, 0.2, 0.2))
+            draw_mesh(coords, edof, dofs_per_node, el_type, color=(0.2, 0.2, 0.2))
         else:
             info("dofs_per_node and el_type must be specified to draw the mesh.")
 
@@ -777,8 +877,19 @@ def draw_nodal_values_shaded(values, coords, edof, title=None, dofs_per_node=Non
 draw_nodal_values = draw_nodal_values_contourf
 
 
-def draw_geometry(geometry, draw_points=True, label_points=True, label_curves=True, title=None, font_size=11, N=20, rel_margin=0.05, draw_axis=False, axes=None):
-    '''
+def draw_geometry(
+    geometry,
+    draw_points=True,
+    label_points=True,
+    label_curves=True,
+    title=None,
+    font_size=11,
+    N=20,
+    rel_margin=0.05,
+    draw_axis=False,
+    axes=None,
+):
+    """
     Draws the geometry (points and curves) in geoData
     Args:
         geoData:
@@ -787,7 +898,7 @@ def draw_geometry(geometry, draw_points=True, label_points=True, label_curves=Tr
             Matplotlib Axes. The Axes where the model will be drawn. If unspecified the current Axes will be used, or a new Axes will be created if none exist.
         axes_adjust:
             Boolean. If True the view will be changed to show the whole model. Default True.
-        draw_points: 
+        draw_points:
             Boolean. If True points will be drawn.
         label_points:
             Boolean. If True Points will be labeled. The format is: ID[marker]. If a point has marker==0 only the ID is written.
@@ -799,19 +910,19 @@ def draw_geometry(geometry, draw_points=True, label_points=True, label_curves=Tr
             Integer. The number of discrete points per curve segment. Default 20. Increase for smoother curves. Decrease for better performance.
         rel_margin:
             Extra spacing between geometry and axis
-    '''
+    """
 
     if axes is None:
         ax = plt.gca()
     else:
         ax = axes
-        
-    ax.set_aspect('equal')
+
+    ax.set_aspect("equal")
     ax.set_frame_on(draw_axis)
 
     if draw_points:
         P = np.array(geometry.getPointCoords())  # M-by-3 list of M points.
-        #plotArgs = {'mc':'r', 'mw':5, 'lw':0, 'ms':'o', 'axesAdjust':False, 'axes':axes}
+        # plotArgs = {'mc':'r', 'mw':5, 'lw':0, 'ms':'o', 'axesAdjust':False, 'axes':axes}
         plotArgs = {"marker": "o", "ls": ""}
         if geometry.is3D:
             plt.plot(P[:, 0], P[:, 1], P[:, 2], **plotArgs)
@@ -819,14 +930,19 @@ def draw_geometry(geometry, draw_points=True, label_points=True, label_curves=Tr
             plt.plot(P[:, 0], P[:, 1], **plotArgs)
 
         if label_points:  # Write text label at the points:
-           # [[x, y, z], elSize, marker]
-            for (ID, (xyz, el_size, marker)) in geometry.points.items():
-                text = "  " + str(ID) + ("[%s]" %
-                                         marker if marker is not 0 else '')
-                plt.text(xyz[0], xyz[1], text,
-                         fontsize=font_size, color=(0.5, 0, 0.5))
-
-    for(ID, (curveName, pointIDs, marker, elementsOnCurve, _, _)) in geometry.curves.items():
+            # [[x, y, z], elSize, marker]
+            for ID, (xyz, el_size, marker) in geometry.points.items():
+                text = "  " + str(ID) + ("[%s]" % marker if marker != 0 else "")
+                plt.text(xyz[0], xyz[1], text, fontsize=font_size, color=(0.5, 0, 0.5))
+
+    for ID, (
+        curveName,
+        pointIDs,
+        marker,
+        elementsOnCurve,
+        _,
+        _,
+    ) in geometry.curves.items():
         points = geometry.getPointCoords(pointIDs)
         if curveName == "Spline":
             P = _catmullspline(points, N)
@@ -848,12 +964,12 @@ def draw_geometry(geometry, draw_points=True, label_points=True, label_curves=Tr
 
         if label_curves:
             # Sort of midpoint along the curve. Where the text goes.
-            midP = P[int(P.shape[0]*7.0/12), :].tolist()
+            midP = P[int(P.shape[0] * 7.0 / 12), :].tolist()
             # Create the text for the curve. Includes ID, elementsOnCurve, and marker:
-            text = " "+str(ID)
-            text += "(%s)" % (elementsOnCurve) if elementsOnCurve is not None else ''
+            text = " " + str(ID)
+            text += "(%s)" % (elementsOnCurve) if elementsOnCurve is not None else ""
             # Something like "4(5)[8]"
-            text += "[%s]" % (marker) if marker is not 0 else ''
+            text += "[%s]" % (marker) if marker != 0 else ""
             plt.text(midP[0], midP[1], text, fontsize=font_size)
 
     if title != None:
@@ -865,19 +981,20 @@ def draw_geometry(geometry, draw_points=True, label_points=True, label_curves=Tr
     g_height = max_y - min_y
 
     if g_width > g_height:
-        margin = rel_margin*g_width
+        margin = rel_margin * g_width
     else:
-        margin = rel_margin*g_height
+        margin = rel_margin * g_height
 
     bottom, top = ax.get_ylim()
     left, right = ax.get_xlim()
-    ax.set_ylim(bottom-margin, top+margin)
-    ax.set_xlim(left-margin, right+margin)
+    ax.set_ylim(bottom - margin, top + margin)
+    ax.set_xlim(left - margin, right + margin)
 
     # if axesAdjust:
     #    _adjustaxes(axes, geoData.is3D)
-    #axes.daspectAuto = False
-    #axes.daspect = (1,1,1)
+    # axes.daspectAuto = False
+    # axes.daspect = (1,1,1)
+
 
 # drawGeometry = draw_geometry
 
@@ -900,26 +1017,32 @@ def _catmullspline(controlPoints, pointsOnEachSegment=10):
                         If there are n control points and k samplesPerSegment,
                         then there will be (n+1)*k numeric points on the curve.
     """
-    controlPoints = np.asarray(
-        controlPoints)  # Convert to array if input is a list.
+    controlPoints = np.asarray(controlPoints)  # Convert to array if input is a list.
     if (controlPoints[0, :] == controlPoints[-1, :]).all():
         # If the curve is closed we extend each opposite endpoint to the other side
-        CPs = np.asmatrix(np.vstack((controlPoints[-2, :],
-                                     controlPoints,
-                                     controlPoints[1, :])))
+        CPs = np.asmatrix(
+            np.vstack((controlPoints[-2, :], controlPoints, controlPoints[1, :]))
+        )
     else:  # Else make mirrored endpoints:
-        CPs = np.asmatrix(np.vstack((2*controlPoints[0, :] - controlPoints[1, :],
-                                     controlPoints,
-                                     2*controlPoints[-1, :] - controlPoints[-2, :])))
-    M = 0.5 * np.matrix([[0,  2,  0,  0], [-1,  0,  1,  0],
-                         [2, -5,  4, -1], [-1,  3, -3,  1]])
+        CPs = np.asmatrix(
+            np.vstack(
+                (
+                    2 * controlPoints[0, :] - controlPoints[1, :],
+                    controlPoints,
+                    2 * controlPoints[-1, :] - controlPoints[-2, :],
+                )
+            )
+        )
+    M = 0.5 * np.matrix([[0, 2, 0, 0], [-1, 0, 1, 0], [2, -5, 4, -1], [-1, 3, -3, 1]])
     t = np.linspace(0, 1, pointsOnEachSegment)
     T = np.matrix([[1, s, pow(s, 2), pow(s, 3)] for s in t])
-    return np.asarray(np.vstack([T * M * CPs[j-1:j+3, :] for j in range(1, len(CPs)-2)]))
+    return np.asarray(
+        np.vstack([T * M * CPs[j - 1 : j + 3, :] for j in range(1, len(CPs) - 2)])
+    )
 
 
 def _bspline(controlPoints, pointsOnCurve=20):
-    '''
+    """
     Uniform cubic B-spline.
 
     Params:
@@ -934,26 +1057,32 @@ def _bspline(controlPoints, pointsOnCurve=20):
     Based on descriptions on:
     http://www.siggraph.org/education/materials/HyperGraph/modeling/splines/b_spline.htm
     http://en.wikipedia.org/wiki/B-spline#Uniform_cubic_B-splines
-    '''
-    controlPoints = np.asarray(
-        controlPoints)  # Convert to array if input is a list.
+    """
+    controlPoints = np.asarray(controlPoints)  # Convert to array if input is a list.
     if (controlPoints[0, :] == controlPoints[-1, :]).all():
         # If the curve is closed we extend each opposite endpoint to the other side
-        CPs = np.asmatrix(np.vstack((controlPoints[-2, :],
-                                     controlPoints,
-                                     controlPoints[1, :])))
+        CPs = np.asmatrix(
+            np.vstack((controlPoints[-2, :], controlPoints, controlPoints[1, :]))
+        )
     else:  # Else make mirrored endpoints:
-        CPs = np.asmatrix(np.vstack((2*controlPoints[0, :] - controlPoints[1, :],
-                                     controlPoints,
-                                     2*controlPoints[-1, :] - controlPoints[-2, :])))
-    M = (1.0/6) * np.matrix([[-1,  3, -3, 1],
-                             [3, -6,  3, 0],
-                             [-3,  0,  3, 0],
-                             [1,  4,  1, 0]])
+        CPs = np.asmatrix(
+            np.vstack(
+                (
+                    2 * controlPoints[0, :] - controlPoints[1, :],
+                    controlPoints,
+                    2 * controlPoints[-1, :] - controlPoints[-2, :],
+                )
+            )
+        )
+    M = (1.0 / 6) * np.matrix(
+        [[-1, 3, -3, 1], [3, -6, 3, 0], [-3, 0, 3, 0], [1, 4, 1, 0]]
+    )
     t = np.linspace(0, 1, pointsOnCurve)
     T = np.matrix([[pow(s, 3), pow(s, 2), s, 1] for s in t])
 
-    return np.asarray(np.vstack([T * M * CPs[i-1: i+3, :] for i in range(1, len(CPs)-2)]))
+    return np.asarray(
+        np.vstack([T * M * CPs[i - 1 : i + 3, :] for i in range(1, len(CPs) - 2)])
+    )
 
 
 def _circleArc(start, center, end, pointsOnCurve=20):
@@ -961,17 +1090,26 @@ def _circleArc(start, center, end, pointsOnCurve=20):
 
 
 def _ellipseArc(start, center, majAxP, end, pointsOnCurve=20):
-    '''Input are 3D 1-by-3 numpy arrays or vectors'''
+    """Input are 3D 1-by-3 numpy arrays or vectors"""
     # First part is to find a similarity transform in 3D that transform the ellipse to
     # the XY-plane with the center at the origin and the major axis of the ellipse along the X-axis.
 
     # convert to arrays in case inputs are lists:
-    start, center, majAxP, end, = np.asarray(start), np.asarray(
-        center), np.asarray(majAxP), np.asarray(end)
-
-    zPrim = np.cross(start-center, end-center)
+    (
+        start,
+        center,
+        majAxP,
+        end,
+    ) = (
+        np.asarray(start),
+        np.asarray(center),
+        np.asarray(majAxP),
+        np.asarray(end),
+    )
+
+    zPrim = np.cross(start - center, end - center)
     zPrim = zPrim / np.linalg.norm(zPrim)
-    xPrim = (majAxP-center) / np.linalg.norm(majAxP-center)
+    xPrim = (majAxP - center) / np.linalg.norm(majAxP - center)
     yPrim = np.cross(zPrim, xPrim)
 
     # Rotation matrix from ordinary coords to system where ellipse is in the XY-plane. (Actually hstack)
@@ -993,14 +1131,19 @@ def _ellipseArc(start, center, majAxP, end, pointsOnCurve=20):
     # Just extract x & y from the new start and endpoints
     xe, ye = e[0, 0], e[1, 0]
 
-    a = np.sqrt((pow(ye*xs, 2) - pow(xe*ys, 2)) / (pow(ye, 2) - pow(ys, 2)))
-    b = np.sqrt((pow(ye*xs, 2) - pow(xe*ys, 2)) / ((pow(ye, 2) - pow(ys, 2))
-                                                   * ((pow(xe, 2) - pow(xs, 2)) / (pow(ys, 2) - pow(ye, 2)))))
+    a = np.sqrt((pow(ye * xs, 2) - pow(xe * ys, 2)) / (pow(ye, 2) - pow(ys, 2)))
+    b = np.sqrt(
+        (pow(ye * xs, 2) - pow(xe * ys, 2))
+        / (
+            (pow(ye, 2) - pow(ys, 2))
+            * ((pow(xe, 2) - pow(xs, 2)) / (pow(ys, 2) - pow(ye, 2)))
+        )
+    )
 
     # atan2 is a function that goes from -pi to pi. It gives the signed angle from the X-axis to point (y,x)
-    ts = atan2(ys/b, xs/a)
+    ts = atan2(ys / b, xs / a)
     # We can't use the (transformed) start- and endpoints directly, but we divide x and y by the
-    te = atan2(ye/b, xe/a)
+    te = atan2(ye / b, xe / a)
     # ellipse minor&major axes to get the parameter t that corresponds to the point on the ellipse.
     # See ellipse formula: x = a * cos (t), y = b * sin(t).
     # So ts and te are the parameter values of the start- and endpoints (in the transformed coordinate system).
@@ -1014,17 +1157,16 @@ def _ellipseArc(start, center, majAxP, end, pointsOnCurve=20):
     # the shortest parameter distance between start- and end-point stradles the discontinuity that jumps from pi to -pi.
     else:
         # number of points on the first length.
-        ps1 = round(pointsOnCurve * (pi-te)/(2*pi-te+ts))
+        ps1 = round(pointsOnCurve * (pi - te) / (2 * pi - te + ts))
         # number of points on the first length.
-        ps2 = round(pointsOnCurve * (ts+pi)/(2*pi-te+ts))
-        times = np.concatenate(
-            (np.linspace(te, pi, ps1), np.linspace(-pi, ts, ps2)))
+        ps2 = round(pointsOnCurve * (ts + pi) / (2 * pi - te + ts))
+        times = np.concatenate((np.linspace(te, pi, ps1), np.linspace(-pi, ts, ps2)))
 
-    ellArc = np.array([[a*cos(t), b*sin(t)]
-                       for t in times]).T  # points on arc (in 2D)
+    ellArc = np.array(
+        [[a * cos(t), b * sin(t)] for t in times]
+    ).T  # points on arc (in 2D)
     # Make 3D homogenous coords by adding rows of 0s and 1s.
-    ellArc = np.vstack(
-        (ellArc, np.repeat(np.matrix([[0], [1]]), ellArc.shape[1], 1)))
+    ellArc = np.vstack((ellArc, np.repeat(np.matrix([[0], [1]]), ellArc.shape[1], 1)))
     ellArc = T * ellArc  # Transform back to the original coordinate system
     return np.asarray(ellArc.T[:, 0:3])  # return points as an N-by-3 array.
 
@@ -1063,7 +1205,7 @@ def eldraw2(ex, ey, plotpar=[1, 2, 1], elnum=[]):
     """
 
     if ex.shape == ey.shape:
-        if ex.ndim !=1:
+        if ex.ndim != 1:
             nen = ex.shape[1]
         else:
             nen = ex.shape[0]
@@ -1080,11 +1222,11 @@ def eldraw2(ex, ey, plotpar=[1, 2, 1], elnum=[]):
     # Translate CALFEM plotpar to visvis
 
     if line_type == 1:
-        mpl_line_style = 'solid'
+        mpl_line_style = "solid"
     elif line_type == 2:
         mpl_line_style = (0, (5, 5))
     elif line_type == 3:
-        mpl_line_style = 'dotted'
+        mpl_line_style = "dotted"
 
     if line_color == 1:
         mpl_line_color = (0, 0, 0)  # 'k'
@@ -1096,24 +1238,24 @@ def eldraw2(ex, ey, plotpar=[1, 2, 1], elnum=[]):
         mpl_line_color = (1, 0, 0)  # 'r'
 
     if node_mark == 1:
-        mpl_node_mark = 'o'
+        mpl_node_mark = "o"
     elif node_mark == 2:
-        mpl_node_mark = 'x'
+        mpl_node_mark = "x"
     elif node_mark == 0:
-        mpl_node_mark = ''
+        mpl_node_mark = ""
 
-    plt.axis('equal')
+    plt.axis("equal")
 
     draw_element_numbers = False
 
     if len(elnum) == ex.shape[0]:
         draw_element_numbers = True
 
-    draw_elements(ex, ey, color=mpl_line_color,
-                  line_style=mpl_line_style, filled=False)
-    if mpl_node_mark != '':
-        draw_node_circles(ex, ey, color=mpl_line_color,
-                          filled=False, marker_type=mpl_node_mark)
+    draw_elements(ex, ey, color=mpl_line_color, line_style=mpl_line_style, filled=False)
+    if mpl_node_mark != "":
+        draw_node_circles(
+            ex, ey, color=mpl_line_color, filled=False, marker_type=mpl_node_mark
+        )
 
     return None
 
@@ -1123,8 +1265,8 @@ def scalfact2(ex, ey, ed, rat=0.2):
     [sfac]=scalfact2(ex,ey,ed,rat)
     [sfac]=scalfact2(ex,ey,ed)
     -------------------------------------------------------------
-    PURPOSE 
-    Determine scale factor for drawing computational results, such as 
+    PURPOSE
+    Determine scale factor for drawing computational results, such as
     displacements, section forces or flux.
 
     INPUT
@@ -1132,7 +1274,7 @@ def scalfact2(ex, ey, ed, rat=0.2):
 
         ed:     element displacement matrix or section force matrix
 
-        rat: relation between illustrated quantity and element size. 
+        rat: relation between illustrated quantity and element size.
         If not specified, 0.2 is used.
 
     -------------------------------------------------------------
@@ -1152,15 +1294,15 @@ def scalfact2(ex, ey, ed, rat=0.2):
     #  end
 
     if ex.shape == ey.shape:
-        if ex.ndim !=1:
+        if ex.ndim != 1:
             nen = ex.shape[1]
         else:
             nen = ex.shape[0]
     else:
         raise ValueError("Check size of ex, ey dimensions.")
 
-    dx_max = float(np.max(ex))-float(np.min(ex))
-    dy_max = float(np.max(ey))-float(np.min(ey))
+    dx_max = float(np.max(ex)) - float(np.min(ex))
+    dy_max = float(np.max(ey)) - float(np.min(ey))
     dl_max = max(dx_max, dy_max)
     ed_max = float(np.max(np.max(np.abs(ed))))
 
@@ -1170,12 +1312,11 @@ def scalfact2(ex, ey, ed, rat=0.2):
 
     k = rat
 
-    return k*dl_max/ed_max
+    return k * dl_max / ed_max
 
 
 def eliso2_mpl(ex, ey, ed):
-
-    plt.axis('equal')
+    plt.axis("equal")
 
     gx = []
     gy = []
@@ -1195,10 +1336,10 @@ def eliso2_mpl(ex, ey, ed):
 def pltstyle(plotpar):
     """
     -------------------------------------------------------------
-     PURPOSE 
-       Define define linetype,linecolor and markertype character codes. 
+     PURPOSE
+       Define define linetype,linecolor and markertype character codes.
 
-     INPUT 
+     INPUT
         plotpar=[ linetype, linecolor, nodemark ]
 
                  linetype=1 -> solid    linecolor=1 -> black
@@ -1206,9 +1347,9 @@ def pltstyle(plotpar):
                           3 -> dotted             3 -> magenta
                                                   4 -> red
 
-                 nodemark=1 -> circle       
-                          2 -> star               
-                          0 -> no mark             
+                 nodemark=1 -> circle
+                          2 -> star
+                          0 -> no mark
      OUTPUT
          s1: linetype and color for mesh lines
          s2: type and color for node markers
@@ -1222,52 +1363,53 @@ def pltstyle(plotpar):
     """
     if type(plotpar) != list:
         raise TypeError("plotpar should be a list.")
-    if len(plotpar)!=3:
+    if len(plotpar) != 3:
         raise ValueError("plotpar needs to be a list of 3 values.")
 
     p1, p2, p3 = plotpar
 
-    s1 = ''
-    s2 = ''
+    s1 = ""
+    s2 = ""
 
     if p1 == 1:
-        s1 += '-'
+        s1 += "-"
     elif p1 == 2:
-        s1 += '--'
+        s1 += "--"
     elif p1 == 3:
-        s1 += ':'
+        s1 += ":"
     else:
         raise ValueError("Invalid value for plotpar[0].")
 
     if p2 == 1:
-        s1 += 'k'
+        s1 += "k"
     elif p2 == 2:
-        s1 += 'b'
+        s1 += "b"
     elif p2 == 3:
-        s1 += 'm'
+        s1 += "m"
     elif p2 == 4:
-        s1 += 'r'
+        s1 += "r"
     else:
         raise ValueError("Invalid value for plotpar[1].")
 
     if p3 == 1:
-        s2 = 'ko'
+        s2 = "ko"
     elif p3 == 2:
-        s2 = 'k*'
+        s2 = "k*"
     elif p3 == 3:
-        s2 = 'k.'
+        s2 = "k."
     else:
         raise ValueError("Invalid value for plotpar[2].")
 
     return s1, s2
 
+
 def pltstyle2(plotpar):
     """
     -------------------------------------------------------------
-     PURPOSE 
-       Define define linetype,linecolor and markertype character codes. 
+     PURPOSE
+       Define define linetype,linecolor and markertype character codes.
 
-     INPUT 
+     INPUT
         plotpar=[ linetype, linecolor, nodemark ]
 
                  linetype=1 -> solid    linecolor=1 -> black
@@ -1275,9 +1417,9 @@ def pltstyle2(plotpar):
                           3 -> dotted             3 -> magenta
                                                   4 -> red
 
-                 nodemark=1 -> circle       
-                          2 -> star               
-                          0 -> no mark             
+                 nodemark=1 -> circle
+                          2 -> star
+                          0 -> no mark
      OUTPUT
          s1: linetype and color for mesh lines
          s2: type and color for node markers
@@ -1295,20 +1437,20 @@ def pltstyle2(plotpar):
 
     p1, p2, p3 = plotpar
 
-    s1 = ''
-    s2 = ''
+    s1 = ""
+    s2 = ""
 
-    line_style = ''
-    line_color = ''
-    node_color = ''
-    node_type = ''
+    line_style = ""
+    line_color = ""
+    node_color = ""
+    node_type = ""
 
     if p1 == 1:
-        line_style = 'solid'
+        line_style = "solid"
     elif p1 == 2:
         line_style = (0, (5, 5))
     elif p1 == 3:
-        line_style = 'dotted'
+        line_style = "dotted"
     else:
         raise ValueError("Invalid value for plotpar[0].")
 
@@ -1325,13 +1467,13 @@ def pltstyle2(plotpar):
 
     if p3 == 1:
         node_color = (0, 0, 0)
-        node_type = 'o'
+        node_type = "o"
     elif p3 == 2:
         node_color = (0, 0, 0)
-        node_type = '*'
+        node_type = "*"
     elif p3 == 3:
         node_color = (0, 0, 0)
-        node_type = '.'
+        node_type = "."
     else:
         raise ValueError("Invalid value for plotpar[2].")
 
@@ -1344,32 +1486,32 @@ def eldisp2(ex, ey, ed, plotpar=[2, 1, 1], sfac=None):
     [sfac]=eldisp2(ex,ey,ed,plotpar)
     [sfac]=eldisp2(ex,ey,ed)
     -------------------------------------------------------------
-     PURPOSE 
-       Draw the deformed 2D mesh for a number of elements of 
+     PURPOSE
+       Draw the deformed 2D mesh for a number of elements of
        the same type. Supported elements are:
 
-               1) -> bar element              2) -> beam el.  
-               3) -> triangular 3 node el.    4) -> quadrilateral 4 node el. 
+               1) -> bar element              2) -> beam el.
+               3) -> triangular 3 node el.    4) -> quadrilateral 4 node el.
                5) -> 8-node isopar. element
       INPUT
         ex,ey:.......... nen:   number of element nodes
-                         nel:   number of elements   
+                         nel:   number of elements
         ed:     element displacement matrix
 
-        plotpar=[  linetype, linecolor, nodemark] 
+        plotpar=[  linetype, linecolor, nodemark]
 
                  linetype=1 -> solid    linecolor=1 -> black
                           2 -> dashed             2 -> blue
                           3 -> dotted             3 -> magenta
                                                   4 -> red
-                 nodemark=1 -> circle       
-                          2 -> star              
-                          0 -> no mark 
+                 nodemark=1 -> circle
+                          2 -> star
+                          0 -> no mark
 
-        sfac:  scale factor for displacements 
+        sfac:  scale factor for displacements
 
-        Rem. Default if sfac and plotpar is left out is auto magnification 
-             and dashed black lines with circles at nodes -> plotpar=[2 1 1] 
+        Rem. Default if sfac and plotpar is left out is auto magnification
+             and dashed black lines with circles at nodes -> plotpar=[2 1 1]
     -------------------------------------------------------------
 
      LAST MODIFIED: O Dahlblom 2004-10-01
@@ -1382,7 +1524,7 @@ def eldisp2(ex, ey, ed, plotpar=[2, 1, 1], sfac=None):
     """
 
     if ex.shape == ey.shape:
-        if ex.ndim !=1:
+        if ex.ndim != 1:
             nen = ex.shape[1]
 
             if ed.shape[0] != ex.shape[0]:
@@ -1399,29 +1541,28 @@ def eldisp2(ex, ey, ed, plotpar=[2, 1, 1], sfac=None):
     else:
         raise ValueError("Check size of ex, ey dimensions.")
 
-
-    dx_max = float(np.max(ex))-float(np.min(ex))
-    dy_max = float(np.max(ey))-float(np.min(ey))
+    dx_max = float(np.max(ex)) - float(np.min(ex))
+    dy_max = float(np.max(ey)) - float(np.min(ey))
     dl_max = max(dx_max, dy_max)
     ed_max = float(np.max(np.max(np.abs(ed))))
     krel = 0.1
 
     if sfac is None:
-        sfac = krel*dl_max/ed_max
+        sfac = krel * dl_max / ed_max
 
     k = sfac
 
     line_color, line_style, node_color, node_style = pltstyle2(plotpar)
-  
+
     if nen == 2:
         if ned == 4:
-            x = np.transpose(ex + k*ed[:, [0, 2]])
-            y = np.transpose(ey + k*ed[:, [1, 3]])
+            x = np.transpose(ex + k * ed[:, [0, 2]])
+            y = np.transpose(ey + k * ed[:, [1, 3]])
             xc = np.transpose(x)
             yc = np.transpose(y)
         elif ned == 6:
-            x = np.transpose(ex + k*ed[:, [0, 3]])
-            y = np.transpose(ey + k*ed[:, [1, 4]])
+            x = np.transpose(ex + k * ed[:, [0, 3]])
+            y = np.transpose(ey + k * ed[:, [1, 4]])
             exc, eyc = beam2crd(ex, ey, ed, k)
             xc = exc
             yc = eyc
@@ -1435,13 +1576,12 @@ def eldisp2(ex, ey, ed, plotpar=[2, 1, 1], sfac=None):
         print("Error: Element type is not supported.")
         return
 
-    draw_elements(xc, yc, color=line_color,
-                  line_style=line_style, filled=False, closed=False)
-
-    if node_style != '':
-        draw_node_circles(x, y, color=node_color,
-                          filled=False, marker_type=node_style)
+    draw_elements(
+        xc, yc, color=line_color, line_style=line_style, filled=False, closed=False
+    )
 
+    if node_style != "":
+        draw_node_circles(x, y, color=node_color, filled=False, marker_type=node_style)
 
 
 # % ********** Bar or Beam elements *************
@@ -1584,45 +1724,45 @@ def eldisp2(ex, ey, ed, plotpar=[2, 1, 1], sfac=None):
 
 def dispbeam2(ex, ey, edi, plotpar=[2, 1, 1], sfac=None):
     """
-    dispbeam2(ex,ey,edi,plotpar,sfac)
-    [sfac]=dispbeam2(ex,ey,edi)
-    [sfac]=dispbeam2(ex,ey,edi,plotpar)
-------------------------------------------------------------------------
-    PURPOSE
-    Draw the displacement diagram for a two dimensional beam element.
-	
-    INPUT:   ex = [ x1 x2 ]
-            ey = [ y1 y2 ]	element node coordinates.
-
-            edi = [ u1 v1;
-                   u2 v2;
- 		             .....] 	matrix containing the displacements
- 			                  in Nbr evaluation points along the beam.
- 	
-            plotpar=[linetype, linecolour, nodemark] 
-
-                     linetype=1 -> solid   linecolour=1 -> black
-                              2 -> dashed             2 -> blue
-                              3 -> dotted             3 -> magenta
-                                                     4 -> red
-                     nodemark=0 -> no mark 
-                              1 -> circle       
-                              2 -> star              
-                              3 -> point 
- 
-                     sfac = [scalar] scale factor for displacements. 
-             
-            Rem. Default if sfac and plotpar is left out is auto magnification 
-           and dashed black lines with circles at nodes -> plotpar=[1 1 1] 
-------------------------------------------------------------------------
-
-    LAST MODIFIED: O Dahlblom  2015-11-18
-                   O Dahlblom  2023-01-31 (Python)
-
-    Copyright (c)  Division of Structural Mechanics and
-                   Division of Solid Mechanics.
-                   Lund University
-------------------------------------------------------------------------
+        dispbeam2(ex,ey,edi,plotpar,sfac)
+        [sfac]=dispbeam2(ex,ey,edi)
+        [sfac]=dispbeam2(ex,ey,edi,plotpar)
+    ------------------------------------------------------------------------
+        PURPOSE
+        Draw the displacement diagram for a two dimensional beam element.
+
+        INPUT:   ex = [ x1 x2 ]
+                ey = [ y1 y2 ]	element node coordinates.
+
+                edi = [ u1 v1;
+                       u2 v2;
+                                 .....] 	matrix containing the displacements
+                                              in Nbr evaluation points along the beam.
+
+                plotpar=[linetype, linecolour, nodemark]
+
+                         linetype=1 -> solid   linecolour=1 -> black
+                                  2 -> dashed             2 -> blue
+                                  3 -> dotted             3 -> magenta
+                                                         4 -> red
+                         nodemark=0 -> no mark
+                                  1 -> circle
+                                  2 -> star
+                                  3 -> point
+
+                         sfac = [scalar] scale factor for displacements.
+
+                Rem. Default if sfac and plotpar is left out is auto magnification
+               and dashed black lines with circles at nodes -> plotpar=[1 1 1]
+    ------------------------------------------------------------------------
+
+        LAST MODIFIED: O Dahlblom  2015-11-18
+                       O Dahlblom  2023-01-31 (Python)
+
+        Copyright (c)  Division of Structural Mechanics and
+                       Division of Solid Mechanics.
+                       Lund University
+    ------------------------------------------------------------------------
     """
     if ex.shape != ey.shape:
         raise ValueError("Check size of ex, ey dimensions.")
@@ -1630,45 +1770,44 @@ def dispbeam2(ex, ey, edi, plotpar=[2, 1, 1], sfac=None):
     rows, cols = edi.shape
     if cols != 2:
         raise ValueError("Check size of edi dimension.")
-    Nbr = rows   
+    Nbr = rows
 
     x1, x2 = ex
     y1, y2 = ey
-    dx = x2-x1
-    dy = y2-y1
-    L = np.sqrt(dx*dx+dy*dy)
-    nxX=dx/L
-    nyX=dy/L
+    dx = x2 - x1
+    dy = y2 - y1
+    L = np.sqrt(dx * dx + dy * dy)
+    nxX = dx / L
+    nyX = dy / L
     n = np.array([nxX, nyX])
- 
+
     line_color, line_style, node_color, node_style = pltstyle2(plotpar)
- 
+
     if sfac is None:
-        sfac=(0.1*L)/(np.max(abs(edi)))
-
-    eci = np.arange(0., L+L/(Nbr-1), L/(Nbr-1)).reshape(Nbr,1) 
-         
-    edi1=edi*sfac
-# From local x-coordinates to global coordinates of the beam element.
-    A = np.zeros(2*Nbr).reshape(Nbr,2)
-    A[0,0] = ex[0]
-    A[0,1] = ey[0]
+        sfac = (0.1 * L) / (np.max(abs(edi)))
+
+    eci = np.arange(0.0, L + L / (Nbr - 1), L / (Nbr - 1)).reshape(Nbr, 1)
+
+    edi1 = edi * sfac
+    # From local x-coordinates to global coordinates of the beam element.
+    A = np.zeros(2 * Nbr).reshape(Nbr, 2)
+    A[0, 0] = ex[0]
+    A[0, 1] = ey[0]
     for i in range(1, Nbr):
-	    A[i,0]=A[0,0]+eci[i]*n[0]
-	    A[i,1]=A[0,1]+eci[i]*n[1]
+        A[i, 0] = A[0, 0] + eci[i] * n[0]
+        A[i, 1] = A[0, 1] + eci[i] * n[1]
 
     for i in range(0, Nbr):
-	    A[i,0]=A[i,0]+edi1[i,0]*n[0]-edi1[i,1]*n[1]
-	    A[i,1]=A[i,1]+edi1[i,0]*n[1]+edi1[i,1]*n[0]
-    xc=np.array(A[:,0])
-    yc=np.array(A[:,1])
+        A[i, 0] = A[i, 0] + edi1[i, 0] * n[0] - edi1[i, 1] * n[1]
+        A[i, 1] = A[i, 1] + edi1[i, 0] * n[1] + edi1[i, 1] * n[0]
+    xc = np.array(A[:, 0])
+    yc = np.array(A[:, 1])
+
+    plt.plot(xc, yc, color=line_color, linewidth=1)
 
-    plt.plot(xc,yc, color=line_color, linewidth=1)
- 
-    A1=np.array([A[0,0], A[Nbr-1,0]]).reshape(1,2)
-    A2=np.array([A[0,1], A[Nbr-1,1]]).reshape(1,2)
-    draw_node_circles(A1, A2, color=node_color,
-                          filled=False, marker_type=node_style)
+    A1 = np.array([A[0, 0], A[Nbr - 1, 0]]).reshape(1, 2)
+    A2 = np.array([A[0, 1], A[Nbr - 1, 1]]).reshape(1, 2)
+    draw_node_circles(A1, A2, color=node_color, filled=False, marker_type=node_style)
 
 
 def secforce2(ex, ey, es, plotpar=[2, 1], sfac=None, eci=None):
@@ -1677,33 +1816,33 @@ def secforce2(ex, ey, es, plotpar=[2, 1], sfac=None, eci=None):
     secforce2(ex,ey,es,plotpar,sfac,eci)
     [sfac]=secforce2(ex,ey,es)
     [sfac]=secforce2(ex,ey,es,plotpar)
---------------------------------------------------------------------------
-    PURPOSE: 
+    --------------------------------------------------------------------------
+    PURPOSE:
     Draw section force diagram for a two dimensional bar or beam element.
-  	
+
     INPUT:  ex = [ x1 x2 ]
-        	ey = [ y1 y2 ]	element node coordinates.
+                ey = [ y1 y2 ]	element node coordinates.
 
-        	es = [ S1;
+                es = [ S1;
                    S2;
-            		... ] 	vector containing the section force
-  			                in Nbr evaluation points along the element.
- 	
-            plotpar=[linecolour, elementcolour] 
- 
+                        ... ] 	vector containing the section force
+                                        in Nbr evaluation points along the element.
+
+            plotpar=[linecolour, elementcolour]
+
                 linecolour=1 -> black      elementcolour=1 -> black
                            2 -> blue                     2 -> blue
                            3 -> magenta                  3 -> magenta
                            4 -> red                       4 -> red
- 
-         	sfac = [scalar]	scale factor for section force diagrams.
+
+                sfac = [scalar]	scale factor for section force diagrams.
 
             eci = [  x1;
                      x2;
                    ... ]  local x-coordinates of the evaluation points (Nbr).
                           If not given, the evaluation points are assumed to be uniformly
                           distributed
---------------------------------------------------------------------------
+    --------------------------------------------------------------------------
 
     LAST MODIFIED: O Dahlblom  2019-12-16
                    O Dahlblom  2023-01-31 (Python)
@@ -1711,28 +1850,28 @@ def secforce2(ex, ey, es, plotpar=[2, 1], sfac=None, eci=None):
     Copyright (c)  Division of Structural Mechanics and
                    Division of Solid Mechanics.
                    Lund University
---------------------------------------------------------------------------
+    --------------------------------------------------------------------------
     """
     if ex.shape != ey.shape:
         raise ValueError("Check size of ex, ey dimensions.")
 
-    c=len(es)
-    Nbr=c
+    c = len(es)
+    Nbr = c
 
     x1, x2 = ex
     y1, y2 = ey
-    dx = x2-x1
-    dy = y2-y1
-    L = np.sqrt(dx*dx+dy*dy)
-    nxX=dx/L
-    nyX=dy/L
+    dx = x2 - x1
+    dy = y2 - y1
+    L = np.sqrt(dx * dx + dy * dy)
+    nxX = dx / L
+    nyX = dy / L
     n = np.array([nxX, nyX])
 
     if sfac is None:
-        sfac=(0.2*L)/max(abs(es))
+        sfac = (0.2 * L) / max(abs(es))
 
     if eci is None:
-        eci = np.arange(0., L+L/(Nbr-1), L/(Nbr-1)).reshape(Nbr,1) 
+        eci = np.arange(0.0, L + L / (Nbr - 1), L / (Nbr - 1)).reshape(Nbr, 1)
 
     p1 = plotpar[0]
     if p1 == 1:
@@ -1745,7 +1884,7 @@ def secforce2(ex, ey, es, plotpar=[2, 1], sfac=None, eci=None):
         line_color = (1, 0, 0)
     else:
         raise ValueError("Invalid value for plotpar[1].")
-    line_style = 'solid'
+    line_style = "solid"
 
     p2 = plotpar[1]
     if p2 == 1:
@@ -1763,59 +1902,58 @@ def secforce2(ex, ey, es, plotpar=[2, 1], sfac=None, eci=None):
     if a != c:
         raise ValueError("Check size of eci dimension.")
 
-    es=es*sfac
+    es = es * sfac
 
-# From local x-coordinates to global coordinates of the element
-    A = np.zeros(2*Nbr).reshape(Nbr,2)
-    A[0,0] = ex[0]
-    A[0,1] = ey[0]
+    # From local x-coordinates to global coordinates of the element
+    A = np.zeros(2 * Nbr).reshape(Nbr, 2)
+    A[0, 0] = ex[0]
+    A[0, 1] = ey[0]
     for i in range(Nbr):
-	    A[i,0] = A[0,0]+eci[i]*n[0]
-	    A[i,1] = A[0,1]+eci[i]*n[1]
+        A[i, 0] = A[0, 0] + eci[i] * n[0]
+        A[i, 1] = A[0, 1] + eci[i] * n[1]
 
-    B=np.array(A)
-    
-# Plot diagram
+    B = np.array(A)
+
+    # Plot diagram
     for i in range(0, Nbr):
-	    A[i,0]=A[i,0]+es[i]*n[1]
-	    A[i,1]=A[i,1]-es[i]*n[0]
+        A[i, 0] = A[i, 0] + es[i] * n[1]
+        A[i, 1] = A[i, 1] - es[i] * n[0]
+
+    xc = np.array(A[:, 0])
+    yc = np.array(A[:, 1])
 
-    xc=np.array(A[:,0])
-    yc=np.array(A[:,1])
+    plt.plot(xc, yc, color=line_color, linewidth=1)
 
-    plt.plot(xc,yc, color=line_color, linewidth=1)
-    
-# Plot stripes in diagram
-    xs = np.zeros(2) 
-    ys = np.zeros(2) 
+    # Plot stripes in diagram
+    xs = np.zeros(2)
+    ys = np.zeros(2)
     for i in range(Nbr):
-        xs[0]=B[i,0]
-        xs[1]=A[i,0]
-        ys[0]=B[i,1]
-        ys[1]=A[i,1]
-        print("i,xs,ys=")
-        print(i,xs,ys)
-        plt.plot(xs,ys, color=line_color, linewidth=1)
-# Plot element
-    plt.plot(ex,ey, color=line_color1, linewidth=2)
- 
+        xs[0] = B[i, 0]
+        xs[1] = A[i, 0]
+        ys[0] = B[i, 1]
+        ys[1] = A[i, 1]
+        plt.plot(xs, ys, color=line_color, linewidth=1)
+
+    # Plot element
+    plt.plot(ex, ey, color=line_color1, linewidth=2)
+
 
 def scalgraph2(sfac, magnitude, plotpar=2):
     """
     scalgraph2(sfac, magnitude, plotpar)
     scalgraph2(sfac, magnitude)
     -------------------------------------------------------------
-    PURPOSE 
+    PURPOSE
     Draw a graphic scale
 
     INPUT:  sfac = [scalar]	scale factor.
 
-            magnitude = [Ref x y]	The graphic scale has a length equivalent   
-        	to Ref and starts at coordinates (x,y).
-        	If no coordinates are given the starting
+            magnitude = [Ref x y]	The graphic scale has a length equivalent
+                to Ref and starts at coordinates (x,y).
+                If no coordinates are given the starting
             point will be (0,-0.5).
 
-            plotpar=[linecolor] 
+            plotpar=[linecolor]
                 linecolor=1 -> black
                 2 -> blue
                 3 -> magenta
@@ -1831,23 +1969,16 @@ def scalgraph2(sfac, magnitude, plotpar=2):
     -------------------------------------------------------------
     """
     cols = len(magnitude)
-    if cols != 1 and cols != 3 : 
+    if cols != 1 and cols != 3:
         raise ValueError("Check size of magnitude input argument.")
-    if cols == 1 :
+    if cols == 1:
         N = magnitude
         x = 0
         y = -0.5
-    if cols == 3 :
+    if cols == 3:
         N, x, y = magnitude
-    
-    print("x= y=")
-    print(x,y)
 
-    L = N*sfac
-    print("L=")
-    print(L)
-    print("plotpar")
-    print(plotpar)
+    L = N * sfac
 
     if plotpar == 1:
         line_color = (0, 0, 0)
@@ -1859,10 +1990,10 @@ def scalgraph2(sfac, magnitude, plotpar=2):
         line_color = (1, 0, 0)
     else:
         raise ValueError("Invalid value for plotpar[1].")
-    print("x=")
-    print(x)
-    plt.plot([x, (x+L)],[y, y], color=line_color, linewidth=1)
-    plt.plot([x, x],[(y-L/20), (y+L/20)], color=line_color, linewidth=1)
-    plt.plot([(x+L), (x+L)],[(y-L/20), (y+L/20)], color=line_color, linewidth=1)
-    plt.text(x+L*1.1, (y-L/20), str(N))
 
+    plt.plot([x, (x + L)], [y, y], color=line_color, linewidth=1)
+    plt.plot([x, x], [(y - L / 20), (y + L / 20)], color=line_color, linewidth=1)
+    plt.plot(
+        [(x + L), (x + L)], [(y - L / 20), (y + L / 20)], color=line_color, linewidth=1
+    )
+    plt.text(x + L * 1.1, (y - L / 20), str(N))
diff --git a/examples/.ipynb_checkpoints/Untitled-checkpoint.ipynb b/examples/.ipynb_checkpoints/Untitled-checkpoint.ipynb
deleted file mode 100644
index 2fd6442..0000000
--- a/examples/.ipynb_checkpoints/Untitled-checkpoint.ipynb
+++ /dev/null
@@ -1,6 +0,0 @@
-{
- "cells": [],
- "metadata": {},
- "nbformat": 4,
- "nbformat_minor": 2
-}
diff --git a/examples/.ipynb_checkpoints/exs1-checkpoint.ipynb b/examples/.ipynb_checkpoints/exs1-checkpoint.ipynb
deleted file mode 100644
index 2fd6442..0000000
--- a/examples/.ipynb_checkpoints/exs1-checkpoint.ipynb
+++ /dev/null
@@ -1,6 +0,0 @@
-{
- "cells": [],
- "metadata": {},
- "nbformat": 4,
- "nbformat_minor": 2
-}
diff --git a/examples/.ipynb_checkpoints/exs2-checkpoint.ipynb b/examples/.ipynb_checkpoints/exs2-checkpoint.ipynb
deleted file mode 100644
index 0fc6225..0000000
--- a/examples/.ipynb_checkpoints/exs2-checkpoint.ipynb
+++ /dev/null
@@ -1,273 +0,0 @@
-{
- "cells": [
-  {
-   "cell_type": "markdown",
-   "metadata": {},
-   "source": [
-    "# Example 2: One-dimensional heat flow (exs2.py)  "
-   ]
-  },
-  {
-   "cell_type": "markdown",
-   "metadata": {},
-   "source": [
-    "This example is from the CALFEM manual.\n",
-    "\n",
-    "**Purpose:**\n",
-    "\n",
-    "Analysis of one-dimensional heat flow.\n",
-    "\n",
-    "**Description:**\n",
-    "\n",
-    "Consider a wall built up of concrete and thermal insulation. The outdoor\n",
-    "temperature is −17 ◦C and the temperature inside is 20 ◦C. At the inside of\n",
-    "the thermal insulation there is a heat source yielding $10 ~W/m^2$.\n",
-    "\n",
-    "![](./images/exs2.png)"
-   ]
-  },
-  {
-   "cell_type": "markdown",
-   "metadata": {},
-   "source": [
-    "The wall is subdivided into five elements and the one-dimensional spring\n",
-    "(analogy) element `spring1e` is used. Equivalent spring stiffnesses are\n",
-    "$k_i = λ A/L$ for thermal conductivity and $k_i = A/R$ for thermal\n",
-    "surface resistance. Corresponding spring stiffnesses per $m^2$ of the wall\n",
-    "are:"
-   ]
-  },
-  {
-   "cell_type": "markdown",
-   "metadata": {},
-   "source": [
-    "\\begin{align}\n",
-    "k_1 &= 1/0.04 = 25.0 ~W/K  \\\\\n",
-    "k_2 &= 1.7/0.070 = 24.3 ~W/K  \\\\\n",
-    "k_3 &= 0.040/0.100 = 0.4 ~W/K  \\\\\n",
-    "k_4 &= 1.7/0.100 = 17.0 ~W/K  \\\\\n",
-    "k_5 &= 1/0.13 = 7.7 ~W/K \n",
-    "\\end{align}"
-   ]
-  },
-  {
-   "cell_type": "markdown",
-   "metadata": {},
-   "source": [
-    "A global system matrix K and a heat flow vector f are defined. The heat source\n",
-    "inside the wall is considered by setting $f_4 = 10$. The element matrices\n",
-    "`Ke` are computed using `spring1e`, and the function `assem` assembles the\n",
-    "global stiffness matrix.\n",
-    "\n",
-    "The system of equations is solved using `solveq` with considerations to the\n",
-    "boundary conditions in `bc` and `bcVal`. The prescribed temperatures are \n",
-    "$T_1 = −17 ~^{\\circ}C$ and $T_2 = 20~^{\\circ}C$."
-   ]
-  },
-  {
-   "cell_type": "markdown",
-   "metadata": {},
-   "source": [
-    "Necessary modules are first imported."
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": 1,
-   "metadata": {},
-   "outputs": [],
-   "source": [
-    "import numpy as np\n",
-    "import calfem.core as cfc"
-   ]
-  },
-  {
-   "cell_type": "markdown",
-   "metadata": {},
-   "source": [
-    "Next, the element topology is defined"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": 3,
-   "metadata": {},
-   "outputs": [],
-   "source": [
-    "Edof = np.array([\n",
-    "    [1,2],\n",
-    "    [2,3],\n",
-    "    [3,4],\n",
-    "    [4,5],\n",
-    "    [5,6]\n",
-    "])"
-   ]
-  },
-  {
-   "cell_type": "markdown",
-   "metadata": {},
-   "source": [
-    "Create stiffness matrix K and load vector f"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": 4,
-   "metadata": {},
-   "outputs": [],
-   "source": [
-    "K = np.mat(np.zeros((6,6)))\n",
-    "f = np.mat(np.zeros((6,1)))\n",
-    "f[3] = 10.0"
-   ]
-  },
-  {
-   "cell_type": "markdown",
-   "metadata": {},
-   "source": [
-    "Define element properties (ep) and create element matrices for the different material layers."
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": 5,
-   "metadata": {},
-   "outputs": [],
-   "source": [
-    "ep1 = 25.0\n",
-    "ep2 = 24.3\n",
-    "ep3 = 0.4\n",
-    "ep4 = 17.0\n",
-    "ep5 = 7.7"
-   ]
-  },
-  {
-   "cell_type": "markdown",
-   "metadata": {},
-   "source": [
-    "Element stiffness matrices"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": 6,
-   "metadata": {},
-   "outputs": [],
-   "source": [
-    "Ke1 = cfc.spring1e(ep1)\n",
-    "Ke2 = cfc.spring1e(ep2)\n",
-    "Ke3 = cfc.spring1e(ep3)\n",
-    "Ke4 = cfc.spring1e(ep4)\n",
-    "Ke5 = cfc.spring1e(ep5)"
-   ]
-  },
-  {
-   "cell_type": "markdown",
-   "metadata": {},
-   "source": [
-    "Assemble all element matrices into the global stiffness matrix"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": 7,
-   "metadata": {},
-   "outputs": [
-    {
-     "name": "stdout",
-     "output_type": "stream",
-     "text": [
-      "Stiffness matrix K:\n",
-      "[[ 25.  -25.    0.    0.    0.    0. ]\n",
-      " [-25.   49.3 -24.3   0.    0.    0. ]\n",
-      " [  0.  -24.3  24.7  -0.4   0.    0. ]\n",
-      " [  0.    0.   -0.4  17.4 -17.    0. ]\n",
-      " [  0.    0.    0.  -17.   24.7  -7.7]\n",
-      " [  0.    0.    0.    0.   -7.7   7.7]]\n"
-     ]
-    }
-   ],
-   "source": [
-    "cfc.assem(Edof[0,:], K, Ke1)\n",
-    "cfc.assem(Edof[1,:], K, Ke2) \n",
-    "cfc.assem(Edof[2,:], K, Ke3)\n",
-    "cfc.assem(Edof[3,:], K, Ke4)\n",
-    "cfc.assem(Edof[4,:], K, Ke5)\n",
-    "\n",
-    "print(\"Stiffness matrix K:\")\n",
-    "print(K)"
-   ]
-  },
-  {
-   "cell_type": "markdown",
-   "metadata": {},
-   "source": [
-    "Define the boundary conditions and solve the system of equations"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": 8,
-   "metadata": {},
-   "outputs": [
-    {
-     "name": "stdout",
-     "output_type": "stream",
-     "text": [
-      "Displacements a:\n",
-      "[[-17.        ]\n",
-      " [-16.43842455]\n",
-      " [-15.86067203]\n",
-      " [ 19.23779344]\n",
-      " [ 19.47540439]\n",
-      " [ 20.        ]]\n",
-      "Reaction forces r:\n",
-      "[[-1.40393862e+01]\n",
-      " [ 0.00000000e+00]\n",
-      " [ 0.00000000e+00]\n",
-      " [ 0.00000000e+00]\n",
-      " [ 5.68434189e-14]\n",
-      " [ 4.03938619e+00]]\n"
-     ]
-    }
-   ],
-   "source": [
-    "bc = np.array([1,6])\n",
-    "bcVal = np.array([-17.0, 20.0])\n",
-    "a,r = cfc.solveq(K, f, bc, bcVal)\n",
-    "\n",
-    "print(\"Displacements a:\")\n",
-    "print(a)\n",
-    "\n",
-    "print(\"Reaction forces r:\")\n",
-    "print(r)"
-   ]
-  },
-  {
-   "cell_type": "markdown",
-   "metadata": {},
-   "source": []
-  }
- ],
- "metadata": {
-  "kernelspec": {
-   "display_name": "Python 3",
-   "language": "python",
-   "name": "python3"
-  },
-  "language_info": {
-   "codemirror_mode": {
-    "name": "ipython",
-    "version": 3
-   },
-   "file_extension": ".py",
-   "mimetype": "text/x-python",
-   "name": "python",
-   "nbconvert_exporter": "python",
-   "pygments_lexer": "ipython3",
-   "version": "3.6.13"
-  }
- },
- "nbformat": 4,
- "nbformat_minor": 2
-}
diff --git a/examples/.ipynb_checkpoints/exs3-checkpoint.ipynb b/examples/.ipynb_checkpoints/exs3-checkpoint.ipynb
deleted file mode 100644
index 2fd6442..0000000
--- a/examples/.ipynb_checkpoints/exs3-checkpoint.ipynb
+++ /dev/null
@@ -1,6 +0,0 @@
-{
- "cells": [],
- "metadata": {},
- "nbformat": 4,
- "nbformat_minor": 2
-}
diff --git a/examples/ex_beam2.py b/examples/ex_beam2.py
deleted file mode 100644
index 91608eb..0000000
--- a/examples/ex_beam2.py
+++ /dev/null
@@ -1,153 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# example exs6
-# ----------------------------------------------------------------
-# PURPOSE
-#    Analysis of a plane frame.
-# ----------------------------------------------------------------
-
-# REFERENCES
-#     Göran Sandberg 94-03-08
-#     Karl-Gunnar Olsson 95-09-28
-#     Anders Olsson 99-03-01
-#     Ola Dahlblom 2004-09-14
-# ----------------------------------------------------------------
-
-import numpy as np
-import calfem.core as cfc
-import calfem.utils as cfu
-import calfem.vis_mpl as cfv
-
-# ----- Topology -------------------------------------------------
-
-edof = np.array([
-    [4,  5,  6, 1,  2,  3],
-    [7,  8,  9, 10, 11, 12],
-    [4,  5,  6,  7,  8,  9]
-])
-
-# ----- Stiffness matrix K and load vector f ---------------------
-
-K = np.matrix(np.zeros((12, 12)))
-f = np.matrix(np.zeros((12, 1)))
-f[3] = 2e+3
-
-# ----- Element stiffness and element load matrices  -------------
-
-E = 200e9
-A1 = 2e-3
-A2 = 6e-3
-I1 = 1.6e-5
-I2 = 5.4e-5
-
-ep1 = np.array([E, A1, I1])
-ep3 = np.array([E, A2, I2])
-ex1 = np.array([0, 0])
-ex2 = np.array([6, 6])
-ex3 = np.array([0, 6])
-ey1 = np.array([4, 0])
-ey2 = np.array([4, 0])
-ey3 = np.array([4, 4])
-eq1 = np.array([0, 0])
-eq2 = np.array([0, 0])
-eq3 = np.array([0, -10e+3])
-
-Ke1 = cfc.beam2e(ex1, ey1, ep1)
-Ke2 = cfc.beam2e(ex2, ey2, ep1)
-Ke3, fe3 = cfc.beam2e(ex3, ey3, ep3, eq3)
-
-# ----- Assemble Ke into K ---------------------------------------
-
-cfc.assem(edof[0, :], K, Ke1)
-cfc.assem(edof[1, :], K, Ke2)
-cfc.assem(edof[2, :], K, Ke3, f, fe3)
-
-# ----- Solve the system of equations and compute reactions ------
-
-bc = np.array([1, 2, 3, 10, 11])
-a, r = cfc.solveq(K, f, bc)
-
-print("a = ")
-print(a)
-print("r = ")
-print(r)
-
-# ----- Section forces -------------------------------------------
-
-ed = cfc.extract_ed(edof, a)
-
-es1, ed1, ec1 = cfc.beam2s(ex1, ey1, ep1, ed[0, :], eq1, nep=21)
-es2, ed2, ec2 = cfc.beam2s(ex2, ey2, ep1, ed[1, :], eq2, nep=21)
-es3, ed3, ec3 = cfc.beam2s(ex3, ey3, ep3, ed[2, :], eq3, nep=21)
-
-print("es1 = ")
-print(es1)
-print("es2 = ")
-print(es2)
-print("es3 = ")
-print(es3)
-
-# ----- Draw deformed frame ---------------------------------------
-
-ex = np.array([
-    ex1, ex2, ex3
-])
-print(ex)
-
-ey = np.array([
-    ey1, ey2, ey3
-])
-print(ey)
-
-plotpar = [2, 1, 0]
-sfac = cfv.scalfact2(ex3, ey3, ed[2, :], 0.1)
-
-cfv.figure(1)
-cfv.eldraw2(ex1, ey1, plotpar)
-cfv.eldraw2(ex2, ey2, plotpar)
-cfv.eldraw2(ex3, ey3, plotpar)
-
-plotpar = [1, 2, 1]
-cfv.eldisp2(ex1, ey1, ed[0, :], plotpar, sfac)
-cfv.eldisp2(ex2, ey2, ed[1, :], plotpar, sfac)
-cfv.eldisp2(ex3, ey3, ed[2, :], plotpar, sfac)
-cfv.axis([-1.5, 7.5, -0.5, 5.5])
-# pltscalb2(sfac,[1e-2 0.5 0]);
-cfv.title('displacements')
-cfv.showAndWait()
-
-# ----- Draw normal force diagram --------------------------------
-
-# figure(2)
-# plotpar=[2 1];
-# sfac=scalfact2(ex1,ey1,es1(:,1),0.2);
-# eldia2(ex1,ey1,es1(:,1),plotpar,sfac);
-# eldia2(ex2,ey2,es2(:,1),plotpar,sfac);
-# eldia2(ex3,ey3,es3(:,1),plotpar,sfac);
-# axis([-1.5 7.5 -0.5 5.5]);
-# pltscalb2(sfac,[3e4 1.5 0]);
-#title('normal force')
-
-# ----- Draw shear force diagram ---------------------------------
-
-# figure(3)
-# plotpar=[2 1];
-# sfac=scalfact2(ex3,ey3,es3(:,2),0.2);
-# eldia2(ex1,ey1,es1(:,2),plotpar,sfac);
-# eldia2(ex2,ey2,es2(:,2),plotpar,sfac);
-# eldia2(ex3,ey3,es3(:,2),plotpar,sfac);
-# axis([-1.5 7.5 -0.5 5.5]);
-# pltscalb2(sfac,[3e4 0.5 0]);
-#title('shear force')
-
-# ----- Draw moment diagram --------------------------------------
-
-# figure(4)
-# plotpar=[2 1];
-# sfac=scalfact2(ex3,ey3,es3(:,3),0.2);
-# eldia2(ex1,ey1,es1(:,3),plotpar,sfac);
-# eldia2(ex2,ey2,es2(:,3),plotpar,sfac);
-# eldia2(ex3,ey3,es3(:,3),plotpar,sfac);
-# axis([-1.5 7.5 -0.5 5.5]);
-# pltscalb2(sfac,[3e4 0.5 0]);
-# title('moment')
diff --git a/examples/ex_tutorial_1.py b/examples/ex_tutorial_1.py
deleted file mode 100644
index 66eb8e9..0000000
--- a/examples/ex_tutorial_1.py
+++ /dev/null
@@ -1,53 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-Created on Sat Mar  3 22:08:29 2018
-
-@author: Jonas Lindemann
-"""
-
-import calfem.geometry as cfg
-import calfem.mesh as cfm
-import calfem.vis_mpl as cfv
-
-# ----- Define geometry
-
-g = cfg.Geometry()
-
-g.point([0.0, 0.0]) # point 0
-g.point([5.0, 0.0], marker=20) # point 1
-g.point([2.5, 4.0]) # point 2
-
-g.spline([0, 1]) # line 0
-g.spline([1, 2]) # line 1
-g.spline([2, 0], marker=10) # line 2
-
-g.surface([0, 1, 2])
-
-# ----- Create mesh
-
-mesh = cfm.GmshMesh(g)
-
-mesh.elType = 2 # Degrees of freedom per node.
-mesh.dofsPerNode = 1 # Factor that changes element sizes.
-mesh.elSizeFactor = 0.15
-
-coords, edof, dofs, bdofs, elementmarkers = mesh.create()
-
-print(bdofs)
-
-cfv.draw_geometry(g)
-
-cfv.figure() 
-
-# ----- Draw the mesh.
-
-cfv.draw_mesh(
-    coords=coords, 
-    edof=edof, 
-    dofs_per_node=mesh.dofsPerNode, 
-    el_type=mesh.elType, 
-    filled=True, 
-    title="Example 01"
-    ) 
-
-cfv.showAndWait()
\ No newline at end of file
diff --git a/examples/ex_tutorial_2.py b/examples/ex_tutorial_2.py
deleted file mode 100644
index 233b2bd..0000000
--- a/examples/ex_tutorial_2.py
+++ /dev/null
@@ -1,113 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-Created on Sat Mar  3 22:08:29 2018
-
-@author: Jonas Lindemann
-"""
-
-import calfem.core as cfc
-import calfem.geometry as cfg
-import calfem.mesh as cfm
-import calfem.vis_mpl as cfv
-import calfem.utils as cfu
-
-import numpy as np
-from math import *
-
-# ----- Problem parameters
-
-l = 5.0
-h = 1.0
-t = 0.2
-
-v = 0.35
-E = 2.1e9
-ptype = 1
-ep = [ptype,t]
-D=cfc.hooke(ptype, E, v)
-
-left_support = 10
-right_support = 20
-top_line = 30
-
-# ----- Define geometry
-
-g = cfg.Geometry()
-
-g.point([0.0, 0.0], marker = left_support) # point 0
-g.point([l, 0.0], marker = right_support) # point 1
-g.point([l, h]) # point 2
-g.point([0.0, h]) # point 2
-
-g.spline([0, 1]) # line 0
-g.spline([1, 2]) # line 1
-g.spline([2, 3], marker = top_line) # line 2
-g.spline([3, 0]) # line 2
-
-g.surface([0, 1, 2, 3])
-
-# ----- Create mesh
-
-mesh = cfm.GmshMesh(g)
-
-mesh.elType = 3 # Degrees of freedom per node.
-mesh.dofsPerNode = 2 # Factor that changes element sizes.
-mesh.elSizeFactor = 0.10
-
-coords, edof, dofs, bdofs, elementmarkers = mesh.create()
-
-# ----- Solve problem
-
-nDofs = np.size(dofs)
-ex, ey = cfc.coordxtr(edof, coords, dofs)
-
-K = np.zeros([nDofs,nDofs])
-
-for eltopo, elx, ely in zip(edof, ex, ey):
-    Ke = cfc.planqe(elx, ely, ep, D)
-    cfc.assem(eltopo, K, Ke)
-
-bc = np.array([],'i')
-bcVal = np.array([],'f')
-
-bc, bcVal = cfu.applybc(bdofs, bc, bcVal, left_support, 0.0, 0)
-bc, bcVal = cfu.applybc(bdofs, bc, bcVal, right_support, 0.0, 2)
-
-f = np.zeros([nDofs,1])
-
-cfu.applyforcetotal(bdofs, f, top_line, -10e5, 2)
-
-a,r = cfc.solveq(K,f,bc,bcVal)
-
-ed = cfc.extractEldisp(edof,a)
-vonMises = []
-
-for i in range(edof.shape[0]): 
-    es, et = cfc.planqs(ex[i,:], ey[i,:], ep, D, ed[i,:]) 
-    vonMises.append( sqrt( pow(es[0],2) - es[0]*es[1] + pow(es[1],2) + 3*es[2] ) ) 
-    
-# ----- Draw geometry
-
-cfv.draw_geometry(g)
-
-# ----- Draw the mesh.
-
-cfv.figure() 
-cfv.draw_mesh(
-    coords=coords, 
-    edof=edof, 
-    dofs_per_node=mesh.dofsPerNode, 
-    el_type=mesh.elType, 
-    filled=True, 
-    title="Example 01"
-    ) 
-
-# ----- Draw results
-
-cfv.figure()
-cfv.draw_element_values(vonMises, coords, edof, mesh.dofs_per_node, mesh.el_type, a, draw_elements=True, draw_undisplaced_mesh=False, title="Example 06 effective stress")
-
-cfv.figure()
-cfv.draw_displacements(a, coords, edof, mesh.dofs_per_node, mesh.el_type, draw_undisplaced_mesh=True, title="Example 06", magnfac=10.0)
-
-cfv.showAndWait()
\ No newline at end of file
diff --git a/examples/exd_beam2_b.py b/examples/exd_beam2_b.py
index 71dac27..1516d7b 100644
--- a/examples/exd_beam2_b.py
+++ b/examples/exd_beam2_b.py
@@ -6,75 +6,77 @@
 #
 #    Note: file exd_beam2_m.py must be in the same directory
 # ----------------------------------------------------------------
+
 from exd_beam2_m import *
 
 # ----- Impact, center point, vertical beam ----------------------
+
 dt = 0.002
 T = 1
 
 # ----- Boundary condition, initial condition --------------------
-G = np.array([
-    [0, 0],
-    [0.1, 0.02],
-    [0.2, -0.01],
-    [0.3, 0],
-    [T, 0]
-])
 
-t,g = cfc.gfunc(G,dt)
+G = np.array([[0, 0], [0.1, 0.02], [0.2, -0.01], [0.3, 0], [T, 0]])
 
-bc = np.zeros((4, 1+len(g)))
-bc[0,:] = np.hstack((1,g))
-bc[1,0] = 2
-bc[2,0] = 3
-bc[3,0] = 14
+t, g = cfc.gfunc(G, dt)
 
-a0 = np.zeros((15,1))
-da0 = np.zeros((15,1))
+bc = np.zeros((4, 1 + len(g)))
+bc[0, :] = np.hstack((1, g))
+bc[1, 0] = 2
+bc[2, 0] = 3
+bc[3, 0] = 14
+
+a0 = np.zeros((15, 1))
+da0 = np.zeros((15, 1))
 
 # ----- Output parameters ----------------------------------------
-times = np.arange(0.1,1.1,0.1)
-dofs = np.array([1,4,11])
+
+times = np.arange(0.1, 1.1, 0.1)
+dofs = np.array([1, 4, 11])
 
 # ----- Time integration parameters ------------------------------
+
 ip = np.array([dt, T, 0.25, 0.5])
 
 # ----- Time integration -----------------------------------------
-sol, dofhist = cfc.step2(K,[],M,[],a0,da0,bc,ip,times,dofs)
+
+sol, dofhist = cfc.step2(K, [], M, [], a0, da0, bc, ip, times, dofs)
 
 # ----- Plot time history for two DOFs ---------------------------
-cfv.figure(1,fig_size=(7,4))
-cfv.plt.plot(t,dofhist['a'][0,:], '-')
-cfv.plt.plot(t,dofhist['a'][1,:],'--')
-cfv.plt.plot(t,dofhist['a'][2,:],'-.')
-cfv.plt.xlim([0,1])
-cfv.plt.ylim([-0.02,0.03])
+
+cfv.figure(1, fig_size=(7, 4))
+cfv.plt.plot(t, dofhist["a"][0, :], "-")
+cfv.plt.plot(t, dofhist["a"][1, :], "--")
+cfv.plt.plot(t, dofhist["a"][2, :], "-.")
+cfv.plt.xlim([0, 1])
+cfv.plt.ylim([-0.02, 0.03])
 cfv.plt.xlabel("time (sec)")
 cfv.plt.ylabel("displacement (m)")
 cfv.plt.title("Displacement(time) at the 1st, 4th and 11th degree of freedom")
-cfv.text("solid line = bottom, vertical beam, x-direction", [0.2,0.022])
-cfv.text("dashed line = center, vertical beam, x-direction", [0.2,0.017])
-cfv.text("dashed-dotted line = center, horizontal beam, y-direction", [0.2,0.012])
+cfv.text("solid line = bottom, vertical beam, x-direction", [0.2, 0.022])
+cfv.text("dashed line = center, vertical beam, x-direction", [0.2, 0.017])
+cfv.text("dashed-dotted line = center, horizontal beam, y-direction", [0.2, 0.012])
 cfv.plt.grid()
 
 # ----- Plot displacement for some time increments ----------------
-cfv.figure(2,fig_size=(7,5))
+
+cfv.figure(2, fig_size=(7, 5))
 for i in range(5):
-    Edb = cfc.extract_ed(edof,sol['a'][:,i])
-    ext = ex+i*3.5
-    cfv.eldraw2(ext,ey,[2,3,1])
-    cfv.eldisp2(ext,ey,Edb,[1,2,2],sfac=20)
-    cfv.text(f"{times[i]:.1f}", [3.5*i+0.5,1.5])
-eyt = ey-4
-for i in range(5,10):
-    Edb = cfc.extract_ed(edof,sol['a'][:,i])
-    ext = ex+(i-5)*3.5
-    cfv.eldraw2(ext,eyt,[2,3,1])
-    cfv.eldisp2(ext,eyt,Edb,[1,2,2],sfac=20)
-    cfv.text(f"{times[i]:.1f}", [3.5*(i-5)+0.5,-2.5])
+    Edb = cfc.extract_ed(edof, sol["a"][:, i])
+    ext = ex + i * 3.5
+    cfv.eldraw2(ext, ey, [2, 3, 1])
+    cfv.eldisp2(ext, ey, Edb, [1, 2, 2], sfac=20)
+    cfv.text(f"{times[i]:.1f}", [3.5 * i + 0.5, 1.5])
+eyt = ey - 4
+for i in range(5, 10):
+    Edb = cfc.extract_ed(edof, sol["a"][:, i])
+    ext = ex + (i - 5) * 3.5
+    cfv.eldraw2(ext, eyt, [2, 3, 1])
+    cfv.eldisp2(ext, eyt, Edb, [1, 2, 2], sfac=20)
+    cfv.text(f"{times[i]:.1f}", [3.5 * (i - 5) + 0.5, -2.5])
 cfv.title("Snapshots (sec), magnification = 20")
 ax = cfv.gca()
 ax.set_axis_off()
-cfv.showAndWait()
+cfv.show_and_wait()
 
-# ----- End -------------------------------------------------------
\ No newline at end of file
+# ----- End -------------------------------------------------------
diff --git a/examples/exd_beam2_m.py b/examples/exd_beam2_m.py
index 52fb35a..0b53226 100644
--- a/examples/exd_beam2_m.py
+++ b/examples/exd_beam2_m.py
@@ -5,53 +5,63 @@
 #    for a simple frame structure.
 # ----------------------------------------------------------------
 
-
 import numpy as np
 import calfem.core as cfc
 import calfem.vis_mpl as cfv
 
 # ----- Generate the model ---------------------------------------
 # ----- Material data --------------------------------------------
+
 E = 3e10
-Av=0.1030e-2
-Ah=0.0764e-2
-rho=2500
+Av = 0.1030e-2
+Ah = 0.0764e-2
+rho = 2500
 Iv = 0.0171e-4
-Ih=0.00801e-4
-ep1 = [E, Av, Iv, rho*Av]   #IPE100
-ep2 = [E, Ah, Ih, rho*Ah]   #IPE80
+Ih = 0.00801e-4
+ep1 = [E, Av, Iv, rho * Av]  # IPE100
+ep2 = [E, Ah, Ih, rho * Ah]  # IPE80
 
 # ----- Topology -------------------------------------------------
-edof = np.array([
-    [1,2,3,4,5,6],
-    [4,5,6,7,8,9],
-    [7,8,9,10,11,12],
-    [10,11,12,13,14,15]
-])
+
+edof = np.array(
+    [
+        [1, 2, 3, 4, 5, 6],
+        [4, 5, 6, 7, 8, 9],
+        [7, 8, 9, 10, 11, 12],
+        [10, 11, 12, 13, 14, 15],
+    ]
+)
 
 # ----- List of coordinates --------------------------------------
-coord = np.array([
-    [0.0, 0.0],
-    [0.0, 1.5],
-    [0.0, 3.0],
-    [1.0, 3.0],
-    [2.0, 3.0],
-])
+
+coord = np.array(
+    [
+        [0.0, 0.0],
+        [0.0, 1.5],
+        [0.0, 3.0],
+        [1.0, 3.0],
+        [2.0, 3.0],
+    ]
+)
 
 # ----- List of degrees of freedom -------------------------------
-dof = np.array([
-    [1, 2, 3],
-    [4, 5, 6],
-    [7, 8, 9],
-    [10, 11, 12],
-    [13, 14, 15],
-])
+
+dof = np.array(
+    [
+        [1, 2, 3],
+        [4, 5, 6],
+        [7, 8, 9],
+        [10, 11, 12],
+        [13, 14, 15],
+    ]
+)
 
 # ----- Generate element matrices, assemble in global matrices ---
-K = np.zeros([15,15])
-M = np.zeros([15,15])
 
-ex, ey = cfc.coordxtr(edof, coord, dof);
+K = np.zeros([15, 15])
+M = np.zeros([15, 15])
+
+ex, ey = cfc.coordxtr(edof, coord, dof)
 ep = np.array([ep1, ep1, ep2, ep2])
 
 for elx, ely, eltopo, elprop in zip(ex, ey, edof, ep):
@@ -60,45 +70,48 @@
     cfc.assem(eltopo, M, Me)
 
 # ----- Eigenvalue analysis --------------------------------------
+
 b = np.array([1, 2, 3, 14])
-La, Egv = cfc.eigen(K,M,b)
-freq = np.sqrt(La)/(2*np.pi)
+La, Egv = cfc.eigen(K, M, b)
+freq = np.sqrt(La) / (2 * np.pi)
 
-if __name__=='__main__':
+if __name__ == "__main__":
     # ----- Draw a plot of the element mesh --------------------------
-    cfv.figure(1,fig_size=(5.5, 4.5))
-    cfv.eldraw2(ex,ey,[1, 2, 1])
-    cfv.title('2-D Frame Structure')
+
+    cfv.figure(1, fig_size=(5.5, 4.5))
+    cfv.eldraw2(ex, ey, [1, 2, 1])
+    cfv.title("2-D Frame Structure")
 
     # ----- Plot one eigenmode ---------------------------------------
-    cfv.figure(2,fig_size=(5.5, 4.5))
-    cfv.eldraw2(ex,ey,[2, 3, 1])
-    Edb = cfc.extract_ed(edof, Egv[:,0])
-    cfv.eldisp2(ex,ey,Edb,[1, 2, 2])
-    cfv.title('The first eigenmode')
-    cfv.text(f"{freq[0]:.2f}", [0.5,1.75])
+
+    cfv.figure(2, fig_size=(5.5, 4.5))
+    cfv.eldraw2(ex, ey, [2, 3, 1])
+    Edb = cfc.extract_ed(edof, Egv[:, 0])
+    cfv.eldisp2(ex, ey, Edb, [1, 2, 2])
+    cfv.title("The first eigenmode")
+    cfv.text(f"{freq[0]:.2f}", [0.5, 1.75])
     ax = cfv.gca()
     ax.grid()
 
     # ----- Plot eight eigenmodes ------------------------------------
-    cfv.figure(3,fig_size=(7,5))
+
+    cfv.figure(3, fig_size=(7, 5))
     for i in range(4):
-        Edb = cfc.extract_ed(edof,Egv[:,i])
-        ext = ex+i*3
-        cfv.eldraw2(ext,ey,[2,3,1])
-        cfv.eldisp2(ext,ey,Edb,[1,2,2],sfac=0.5)
-        cfv.text(f"{freq[i]:.2f}", [3*i+0.5,1.5])
-    eyt = ey-4
-    for i in range(4,8):
-        Edb = cfc.extract_ed(edof,Egv[:,i])
-        ext = ex+(i-4)*3
-        cfv.eldraw2(ext,eyt,[2,3,1])
-        cfv.eldisp2(ext,eyt,Edb,[1,2,2],sfac=0.5)
-        cfv.text(f"{freq[i]:.2f}", [3*(i-4)+0.5,-2.5])
+        Edb = cfc.extract_ed(edof, Egv[:, i])
+        ext = ex + i * 3
+        cfv.eldraw2(ext, ey, [2, 3, 1])
+        cfv.eldisp2(ext, ey, Edb, [1, 2, 2], sfac=0.5)
+        cfv.text(f"{freq[i]:.2f}", [3 * i + 0.5, 1.5])
+    eyt = ey - 4
+    for i in range(4, 8):
+        Edb = cfc.extract_ed(edof, Egv[:, i])
+        ext = ex + (i - 4) * 3
+        cfv.eldraw2(ext, eyt, [2, 3, 1])
+        cfv.eldisp2(ext, eyt, Edb, [1, 2, 2], sfac=0.5)
+        cfv.text(f"{freq[i]:.2f}", [3 * (i - 4) + 0.5, -2.5])
     cfv.title("The first eight eigenmodes [Hz]")
     ax = cfv.gca()
     ax.set_axis_off()
-    cfv.showAndWait()
+    cfv.show_and_wait()
 
 # ----- End -------------------------------------------------------
-
diff --git a/examples/exd_beam2_t.py b/examples/exd_beam2_t.py
index 6bac640..c36d902 100644
--- a/examples/exd_beam2_t.py
+++ b/examples/exd_beam2_t.py
@@ -5,76 +5,75 @@
 #
 #    Note: file exd_beam2_m.py must be in the same directory
 # ----------------------------------------------------------------
+
 from exd_beam2_m import *
 
 # ----- Impact, center point, vertical beam ----------------------
+
 dt = 0.002
 T = 1
 
 # ----- The load -------------------------------------------------
-G = np.array([
-    [0, 0],
-    [0.15, 1],
-    [0.25, 0],
-    [T, 0]
-])
-
-t,g = cfc.gfunc(G,dt)
+
+G = np.array([[0, 0], [0.15, 1], [0.25, 0], [T, 0]])
+
+t, g = cfc.gfunc(G, dt)
 f = np.zeros((15, len(g)))
-f[3,:] = 1000*g
+f[3, :] = 1000 * g
 
 # ----- Boundary condition, initial condition --------------------
-bc = np.array([
-    [1, 0],
-    [2, 0],
-    [3, 0],
-    [14, 0]
-])
 
-a0 = np.zeros((15,1))
-da0 = np.zeros((15,1))
+bc = np.array([[1, 0], [2, 0], [3, 0], [14, 0]])
+
+a0 = np.zeros((15, 1))
+da0 = np.zeros((15, 1))
 
 # ----- Output parameters ----------------------------------------
-times = np.arange(0.1,1.1,0.1)
-dofs = np.array([4,11])
+
+times = np.arange(0.1, 1.1, 0.1)
+dofs = np.array([4, 11])
 
 # ----- Time integration parameters ------------------------------
+
 ip = np.array([dt, T, 0.25, 0.5])
 
 # ----- Time integration -----------------------------------------
-sol, dofhist = cfc.step2(K,[],M,f,a0,da0,bc,ip,times,dofs)
+
+sol, dofhist = cfc.step2(K, [], M, f, a0, da0, bc, ip, times, dofs)
 
 # ----- Plot time history for two DOFs ---------------------------
-cfv.figure(1,fig_size=(7,4))
-cfv.plt.plot(t,dofhist['a'][0,:], '-')
-cfv.plt.plot(t,dofhist['a'][1,:],'--')
-cfv.plt.xlim([0,1])
-cfv.plt.ylim([-0.01,0.02])
+
+cfv.figure(1, fig_size=(7, 4))
+cfv.plt.plot(t, dofhist["a"][0, :], "-")
+cfv.plt.plot(t, dofhist["a"][1, :], "--")
+cfv.plt.xlim([0, 1])
+cfv.plt.ylim([-0.01, 0.02])
 cfv.plt.xlabel("time (sec)")
 cfv.plt.ylabel("displacement (m)")
 cfv.plt.title("Displacement(time) at the 4th and 11th degree of freedom")
-cfv.text("solid line = impact point, x-direction", [0.3,0.017])
-cfv.text("dashed line = center, horizontal beam, y-direction", [0.3,0.012])
+cfv.text("solid line = impact point, x-direction", [0.3, 0.017])
+cfv.text("dashed line = center, horizontal beam, y-direction", [0.3, 0.012])
 cfv.plt.grid()
 
 # ----- Plot displacement for some time increments ----------------
-cfv.figure(2,fig_size=(7,5))
+
+cfv.figure(2, fig_size=(7, 5))
 for i in range(5):
-    Edb = cfc.extract_ed(edof,sol['a'][:,i])
-    ext = ex+i*3.5
-    cfv.eldraw2(ext,ey,[2,3,1])
-    cfv.eldisp2(ext,ey,Edb,[1,2,2],sfac=25)
-    cfv.text(f"{times[i]:.1f}", [3.5*i+0.5,1.5])
-eyt = ey-4
-for i in range(5,10):
-    Edb = cfc.extract_ed(edof,sol['a'][:,i])
-    ext = ex+(i-5)*3.5
-    cfv.eldraw2(ext,eyt,[2,3,1])
-    cfv.eldisp2(ext,eyt,Edb,[1,2,2],sfac=25)
-    cfv.text(f"{times[i]:.1f}", [3.5*(i-5)+0.5,-2.5])
+    Edb = cfc.extract_ed(edof, sol["a"][:, i])
+    ext = ex + i * 3.5
+    cfv.eldraw2(ext, ey, [2, 3, 1])
+    cfv.eldisp2(ext, ey, Edb, [1, 2, 2], sfac=25)
+    cfv.text(f"{times[i]:.1f}", [3.5 * i + 0.5, 1.5])
+eyt = ey - 4
+for i in range(5, 10):
+    Edb = cfc.extract_ed(edof, sol["a"][:, i])
+    ext = ex + (i - 5) * 3.5
+    cfv.eldraw2(ext, eyt, [2, 3, 1])
+    cfv.eldisp2(ext, eyt, Edb, [1, 2, 2], sfac=25)
+    cfv.text(f"{times[i]:.1f}", [3.5 * (i - 5) + 0.5, -2.5])
 cfv.title("Snapshots (sec), magnification = 25")
 ax = cfv.gca()
 ax.set_axis_off()
-cfv.showAndWait()
+cfv.show_and_wait()
 
-# ----- End -------------------------------------------------------
\ No newline at end of file
+# ----- End -------------------------------------------------------
diff --git a/examples/exd_beam2_tr.py b/examples/exd_beam2_tr.py
index 0dd929f..685891e 100644
--- a/examples/exd_beam2_tr.py
+++ b/examples/exd_beam2_tr.py
@@ -5,81 +5,90 @@
 #
 #    Note: file exd_beam2_m.py must be in the same directory
 # ----------------------------------------------------------------
+
 from exd_beam2_m import *
 
 # ----- Impact, center point, vertical beam ----------------------
+
 dt = 0.002
 T = 1
 nev = 2
 
 # ----- The load -------------------------------------------------
-G = np.array([
-    [0, 0],
-    [0.15, 1],
-    [0.25, 0],
-    [T, 0]
-])
-
-t,g = cfc.gfunc(G,dt)
+
+G = np.array([[0, 0], [0.15, 1], [0.25, 0], [T, 0]])
+
+t, g = cfc.gfunc(G, dt)
 f = np.zeros((15, len(g)))
-f[3,:] = 1000*g
-fr = np.hstack((np.arange(1,nev+1).reshape(-1,1),Egv[:,:nev].T@f))
+f[3, :] = 1000 * g
+fr = np.hstack((np.arange(1, nev + 1).reshape(-1, 1), Egv[:, :nev].T @ f))
 
 # ----- Reduced system matrices ----------------------------------
-kr = np.diag(np.diag(Egv[:,:nev].T@K@Egv[:,:nev]))
-mr = np.diag(np.diag(Egv[:,:nev].T@M@Egv[:,:nev]))
+
+kr = np.diag(np.diag(Egv[:, :nev].T @ K @ Egv[:, :nev]))
+mr = np.diag(np.diag(Egv[:, :nev].T @ M @ Egv[:, :nev]))
 
 # ----- Initial condition ----------------------------------------
-ar0 = np.zeros((nev,1))
-dar0 = np.zeros((nev,1))
+
+ar0 = np.zeros((nev, 1))
+dar0 = np.zeros((nev, 1))
 
 # ----- Output parameters ----------------------------------------
-times = np.arange(0.1,1.1,0.1)
-dofsr = np.arange(1,nev+1)
-dofs = np.array([4,11])
+
+times = np.arange(0.1, 1.1, 0.1)
+dofsr = np.arange(1, nev + 1)
+dofs = np.array([4, 11])
 
 # ----- Time integration parameters ------------------------------
+
 ip = np.array([dt, T, 0.25, 0.5])
 
 # ----- Time integration -----------------------------------------
-sol, dofhist = cfc.step2(kr,[],mr,fr,ar0,dar0,[],ip,times,dofsr)
+sol, dofhist = cfc.step2(kr, [], mr, fr, ar0, dar0, [], ip, times, dofsr)
 
 # ----- Mapping back to original coordinate system ---------------
-aR = Egv[:,:nev]@sol['a']
-aRhist = Egv[dofs-1,:nev]@dofhist['a']
+
+aR = Egv[:, :nev] @ sol["a"]
+aRhist = Egv[dofs - 1, :nev] @ dofhist["a"]
 
 # ----- Plot time history for two DOFs ---------------------------
-cfv.figure(1,fig_size=(7,4))
-cfv.plt.plot(t,aRhist[0,:], '-')
-cfv.plt.plot(t,aRhist[1,:],'--')
-cfv.plt.xlim([0,1])
-cfv.plt.ylim([-0.01,0.02])
+
+cfv.figure(1, fig_size=(7, 4))
+cfv.plt.plot(t, aRhist[0, :], "-")
+cfv.plt.plot(t, aRhist[1, :], "--")
+cfv.plt.xlim([0, 1])
+cfv.plt.ylim([-0.01, 0.02])
 cfv.plt.xlabel("time (sec)")
 cfv.plt.ylabel("displacement (m)")
 cfv.plt.title("Displacement(time) at the 4th and 11th degree of freedom")
-cfv.text("solid line = impact point, x-direction", [0.3,0.017])
-cfv.text("dashed line = center, horizontal beam, y-direction", [0.3,0.012])
-cfv.text("TWO EIGENVECTORS ARE USED", [0.3,-0.007])
+cfv.text("solid line = impact point, x-direction", [0.3, 0.017])
+cfv.text("dashed line = center, horizontal beam, y-direction", [0.3, 0.012])
+cfv.text("TWO EIGENVECTORS ARE USED", [0.3, -0.007])
 cfv.plt.grid()
 
 # ----- Plot displacement for some time increments ----------------
-cfv.figure(2,fig_size=(7,5))
+
+cfv.figure(2, fig_size=(7, 5))
+
 for i in range(5):
-    Edb = cfc.extract_ed(edof,aR[:,i])
-    ext = ex+i*3.5
-    cfv.eldraw2(ext,ey,[2,3,1])
-    cfv.eldisp2(ext,ey,Edb,[1,2,2],sfac=25)
-    cfv.text(f"{times[i]:.1f}", [3.5*i+0.5,1.5])
-eyt = ey-4
-for i in range(5,10):
-    Edb = cfc.extract_ed(edof,aR[:,i])
-    ext = ex+(i-5)*3.5
-    cfv.eldraw2(ext,eyt,[2,3,1])
-    cfv.eldisp2(ext,eyt,Edb,[1,2,2],sfac=25)
-    cfv.text(f"{times[i]:.1f}", [3.5*(i-5)+0.5,-2.5])
+    Edb = cfc.extract_ed(edof, aR[:, i])
+    ext = ex + i * 3.5
+    cfv.eldraw2(ext, ey, [2, 3, 1])
+    cfv.eldisp2(ext, ey, Edb, [1, 2, 2], sfac=25)
+    cfv.text(f"{times[i]:.1f}", [3.5 * i + 0.5, 1.5])
+
+eyt = ey - 4
+
+for i in range(5, 10):
+    Edb = cfc.extract_ed(edof, aR[:, i])
+    ext = ex + (i - 5) * 3.5
+    cfv.eldraw2(ext, eyt, [2, 3, 1])
+    cfv.eldisp2(ext, eyt, Edb, [1, 2, 2], sfac=25)
+    cfv.text(f"{times[i]:.1f}", [3.5 * (i - 5) + 0.5, -2.5])
+
 cfv.title("Snapshots (sec), magnification = 25")
 ax = cfv.gca()
 ax.set_axis_off()
-cfv.showAndWait()
+cfv.show_and_wait()
 
-# ----- End -------------------------------------------------------
\ No newline at end of file
+# ----- End -------------------------------------------------------
diff --git a/examples/exe_stress_2d_editor.py b/examples/exe_stress_2d_editor.py
index c84bf87..e5aed51 100644
--- a/examples/exe_stress_2d_editor.py
+++ b/examples/exe_stress_2d_editor.py
@@ -18,15 +18,15 @@
 
 g = cfg.Geometry()
 
-g.point([0.0, 0.0])    # point 0
+g.point([0.0, 0.0])  # point 0
 g.point([100.0, 0.0])  # point 1
-g.point([100, 100])    # point 2
-g.point([0, 100])      # point 3
+g.point([100, 100])  # point 2
+g.point([0, 100])  # point 3
 
-g.spline([0, 1])       # line 0
-g.spline([1, 2])       # line 1
-g.spline([2, 3])       # line 2
-g.spline([3, 0])       # line 3
+g.spline([0, 1])  # line 0
+g.spline([1, 2])  # line 1
+g.spline([2, 3])  # line 2
+g.spline([3, 0])  # line 3
 
 g.surface([0, 1, 2, 3])  # Connect lines to form surface
 g.setCurveMarker(0, 10)
@@ -41,33 +41,34 @@
 v = 0.35
 E = 2.1e9
 ptype = 1
-ep = [ptype,t]
+ep = [ptype, t]
 D = cfc.hooke(ptype, E, v)
 
-# --- Every border or point marked with 10 will recieve boundary 
+# --- Every border or point marked with 10 will recieve boundary
 # --- condition value of 0
 
-bcs_new = [[marker_dict[10], 0]]  
+bcs_new = [[marker_dict[10], 0]]
 
-# --- Every border or point marked with 20 will recieve load 
+# --- Every border or point marked with 20 will recieve load
 # --- value of 10e5
 
-loads_new = [[marker_dict[20], 10e5]]  
+loads_new = [[marker_dict[20], 10e5]]
 
-# --- Every border or point marked with A will recieve boundary 
+# --- Every border or point marked with A will recieve boundary
 # --- condition value of 0
 
-bcs_old = [[10, 0]]  
+bcs_old = [[10, 0]]
 
-# --- Every border or point marked with B will recieve load 
+# --- Every border or point marked with B will recieve load
 # --- value of 10e5
 
-loads_old = [[20, 10e5]]  
+loads_old = [[20, 10e5]]
 
 el_size_factor = 5
 el_type = 3
 dofs_per_node = 2
 
+
 def calc(geometry, bcs, loads, text):
     mesh = cfm.GmshMeshGenerator(geometry)
     mesh.el_size_factor = el_size_factor  # Factor that changes element sizes.
@@ -89,7 +90,7 @@ def calc(geometry, bcs, loads, text):
     for eltopo, elx, ely in zip(edof, ex, ey):
         Ke = cfc.planqe(elx, ely, ep, D)
         cfc.assem(eltopo, K, Ke)
-    
+
     # --- Solve equation system
 
     f = np.zeros([nDofs, 1])
@@ -113,16 +114,28 @@ def calc(geometry, bcs, loads, text):
     # --- For each element:
 
     for i in range(edof.shape[0]):
-
         # --- Determine element stresses and strains in the element.
 
-        es, et = cfc.planqs(ex[i,:], ey[i,:], ep, D, ed[i,:])
+        es, et = cfc.planqs(ex[i, :], ey[i, :], ep, D, ed[i, :])
 
         # --- Calc and append effective stress to list.
-        vonMises.append(np.sqrt(np.power(es[0],2) - es[0]*es[1] + np.power(es[1],2) + 3*es[2] ) )
+        vonMises.append(
+            np.sqrt(np.power(es[0], 2) - es[0] * es[1] + np.power(es[1], 2) + 3 * es[2])
+        )
 
     title = "Effective stress" + text
-    cfv.draw_element_values(vonMises, coords, edof, mesh.dofs_per_node, mesh.el_type, None, draw_elements=False, draw_undisplaced_mesh=False, title=title)
+    cfv.draw_element_values(
+        vonMises,
+        coords,
+        edof,
+        mesh.dofs_per_node,
+        mesh.el_type,
+        None,
+        draw_elements=False,
+        draw_undisplaced_mesh=False,
+        title=title,
+    )
+
 
 # --- Display results
 
@@ -131,4 +144,3 @@ def calc(geometry, bcs, loads, text):
 cfv.figure()
 calc(new_geometry, bcs_new, loads_new, " modified")
 cfv.show_and_wait()
-
diff --git a/examples/exm_circle_bsplines.py b/examples/exm_circle_bsplines.py
index 4b04bd0..fff750c 100644
--- a/examples/exm_circle_bsplines.py
+++ b/examples/exm_circle_bsplines.py
@@ -1,10 +1,10 @@
 # -*- coding: utf-8 -*-
 
-'''
+"""
 Example 02
 Creating geometry from B-Splines and circle arcs.
 Also shows how to set ID numbers for geometry entities and how to specify element density. 
-'''
+"""
 
 import matplotlib.pyplot as plt
 import matplotlib.collections
@@ -21,16 +21,16 @@
 # Add points:
 #  In this example we set the IDs manually.
 
-g.point([-2,  0], ID=0)
+g.point([-2, 0], ID=0)
 # el_size determines the size of the elements near this point.
-g.point([0,  1], ID=1, el_size=5)
+g.point([0, 1], ID=1, el_size=5)
 # el_size is 1 by default. Larger number means less dense mesh.
-g.point([1,  0], 2, el_size=5)
+g.point([1, 0], 2, el_size=5)
 g.point([0, -2], 3)  # Size means the length of the sides of the elements.
-g.point([0,  0], 4, el_size=5)
-g.point([.5, .2], 5)
-g.point([-.5, .5], 6)
-g.point([-.7, -.5], 7)
+g.point([0, 0], 4, el_size=5)
+g.point([0.5, 0.2], 5)
+g.point([-0.5, 0.5], 6)
+g.point([-0.7, -0.5], 7)
 
 # Add curves:
 
@@ -78,25 +78,19 @@
 
 # Draw the geometry.
 
-cfv.draw_geometry(
-    g,
-    label_curves=True,
-    title="Example 2 - Geometry"
-)
-
-# New figure window
-
 cfv.figure()
+cfv.draw_geometry(g, label_curves=True, title="Example 2 - Geometry")
 
 # Draws the mesh.
 
+cfv.figure()
 cfv.draw_mesh(
     coords=coords,
     edof=edof,
     dofs_per_node=mesh.dofs_per_node,
     el_type=mesh.el_type,
     filled=True,
-    title="Example 2 - Mesh"
+    title="Example 2 - Mesh",
 )
 
 # Enter main loop
diff --git a/examples/exm_flow_model.py b/examples/exm_flow_model.py
index 76fb6d7..c11c251 100644
--- a/examples/exm_flow_model.py
+++ b/examples/exm_flow_model.py
@@ -8,7 +8,7 @@
 # ----------------------------------------------------------------
 #
 # REFERENCES
-#     J Lindemann  2021-12-29 
+#     J Lindemann  2021-12-29
 # ----------------------------------------------------------------
 
 # ----- Import needed modules ------------------------------------
@@ -25,23 +25,23 @@
 w = 100.0
 h = 10.0
 t = 1.0
-d = h/2
+d = h / 2
 
-D = np.identity(2, 'float')
+D = np.identity(2, "float")
 ep = [1.0, 1]
 
 # ----- Create geometry object -----------------------------------
 
 g = cfg.Geometry()
 
-g.point([0, 0])             # point 1
-g.point([w, 0])             # point 2
-g.point([w, h])             # point 3 
-g.point([w-w/2+t/2, h])     # point 4
-g.point([w-w/2+t/2, h-d])   # point 5
-g.point([w-w/2-t/2, h-d])   # point 6
-g.point([w-w/2-t/2, h])     # point 7
-g.point([0, h])             # point 8
+g.point([0, 0])  # point 1
+g.point([w, 0])  # point 2
+g.point([w, h])  # point 3
+g.point([w - w / 2 + t / 2, h])  # point 4
+g.point([w - w / 2 + t / 2, h - d])  # point 5
+g.point([w - w / 2 - t / 2, h - d])  # point 6
+g.point([w - w / 2 - t / 2, h])  # point 7
+g.point([0, h])  # point 8
 
 # ----- Create lines between points ------------------------------
 
@@ -50,7 +50,7 @@
 
 g.spline([0, 1])
 g.spline([1, 2])
-g.spline([2, 3], marker=left_side)     # marker just to name
+g.spline([2, 3], marker=left_side)  # marker just to name
 g.spline([3, 4])
 g.spline([4, 5])
 g.spline([5, 6])
@@ -63,8 +63,8 @@
 
 # ----- Mesh generation ------------------------------------------
 
-el_type = 3           # quadrature element
-dofs_per_node = 1     # 1 dof
+el_type = 3  # quadrature element
+dofs_per_node = 1  # 1 dof
 
 # ----- Set mesh paramters ---------------------------------------
 
@@ -83,13 +83,13 @@
 ex, ey = cfc.coordxtr(edof, coords, dofs)
 K = np.zeros([nDofs, nDofs])
 
-for eltopo, elx, ely, in zip(edof, ex, ey):
+for eltopo, elx, ely in zip(edof, ex, ey):
     Ke = cfc.flw2i4e(elx, ely, ep, D)
     cfc.assem(eltopo, K, Ke)
 
 # ----- Force vector ---------------------------------------------
 
-f = np.zeros([nDofs, 1])    
+f = np.zeros([nDofs, 1])
 
 # ----- Boundary conditions --------------------------------------
 
@@ -106,7 +106,7 @@
 
 # ----- Calculating element forces -------------------------------
 
-maxFlow = []     # empty list to store flow
+maxFlow = []  # empty list to store flow
 
 for i in range(edof.shape[0]):
     es, et, eci = cfc.flw2i4s(ex[i, :], ey[i, :], ep, D, ed[i, :])
@@ -115,15 +115,14 @@
 # ----- Visualize results ----------------------------------------
 
 cfv.figure()
-cfv.draw_geometry(g, title='Geometry')
+cfv.draw_geometry(g, title="Geometry")
 
 cfv.figure()
-cfv.draw_element_values(maxFlow, coords, edof, dofs_per_node, el_type, None,
-                        title='Max flows')
+cfv.draw_element_values(
+    maxFlow, coords, edof, dofs_per_node, el_type, None, title="Max flows"
+)
 
 cfv.figure()
-cfv.draw_nodal_values(a, coords, edof, 
-                      dofs_per_node=dofs_per_node, 
-                      el_type=el_type)
+cfv.draw_nodal_values(a, coords, edof, dofs_per_node=dofs_per_node, el_type=el_type)
 
 cfv.showAndWait()
diff --git a/examples/exm_geometry.py b/examples/exm_geometry.py
index 9c37d8c..0a92cb9 100644
--- a/examples/exm_geometry.py
+++ b/examples/exm_geometry.py
@@ -1,10 +1,10 @@
 # -*- coding: utf-8 -*-
 
-'''Example 01
+"""Example 01
 
 Shows how to create simple geometry from splines and ellipse arcs, and how to mesh a quad mesh in GmshMesher.
 Also demonstrates drawGeometry(), drawMesh, and drawing texts and labels in a figure.
-'''
+"""
 
 import calfem.geometry as cfg
 import calfem.mesh as cfm
@@ -48,15 +48,15 @@
 
 g.ellipse([7, 8, 9, 10], marker=50)
 
-g.spline([0, 1], marker=80)           # 1 - A spline. Splines pass through the
-                                      #     points in the first parameter.
-g.spline([2, 1])                      # 2
-g.spline([3, 2])                      # 3
-g.spline([0, 3])                      # 4
-g.spline([7, 9], marker=50)           # 5
-g.spline([10, 9])                     # 6
-g.spline([4, 5, 6, 4])                # 7 - This is a closed spline.
-                                      #     The start and end points are the same
+g.spline([0, 1], marker=80)  # 1 - A spline. Splines pass through the
+#     points in the first parameter.
+g.spline([2, 1])  # 2
+g.spline([3, 2])  # 3
+g.spline([0, 3])  # 4
+g.spline([7, 9], marker=50)  # 5
+g.spline([10, 9])  # 6
+g.spline([4, 5, 6, 4])  # 7 - This is a closed spline.
+#     The start and end points are the same
 
 # Add a surface:
 #  Surfaces are defined by its curve boundaries.
@@ -101,21 +101,19 @@
 # Draw the geometry. Note that surfaces and volumes are not drawn at all by
 # this function.
 
-cfv.draw_geometry(g)
-
-# New figure window
-
 cfv.figure()
+cfv.draw_geometry(g)
 
 # Draw the mesh.
 
+cfv.figure()
 cfv.draw_mesh(
     coords=coords,
     edof=edof,
     dofs_per_node=mesh.dofs_per_node,
     el_type=mesh.el_type,
     filled=True,
-    title="Example 01"
+    title="Example 01",
 )
 
 # Adds a text in world space
@@ -129,7 +127,7 @@
 # We can change the attributes of labels and texts, such as color, text, and position.
 
 our_label.set_text("Label, changed.")
-our_label.set_color('r')  # Make it red. (1,0,0) would also have worked.
+our_label.set_color("r")  # Make it red. (1,0,0) would also have worked.
 our_label.set_position((1, 0.3))
 
 # Enter main loop:
diff --git a/examples/exm_stress_2d.py b/examples/exm_stress_2d.py
index 438be0f..d1bd19a 100644
--- a/examples/exm_stress_2d.py
+++ b/examples/exm_stress_2d.py
@@ -1,12 +1,12 @@
 # -*- coding: utf-8 -*-
 
-'''Example 06
+"""Example 06
 
 Solves a plane stress 2D problem using a structured mesh.
 Shows how to draw von Mises effective stress as an element value with 
 drawElementValues(). Shows use of GmshMesher attribute 'nodesOnCurve' 
 (dictionary that says which nodes are on a given geometry curve)
-'''
+"""
 
 import calfem.geometry as cfg
 import calfem.mesh as cfm
@@ -36,37 +36,89 @@
 
 # Just a shorthand. We use this to make the circle arcs.
 
-s2 = 1/sqrt(2)
-
-points = [[0, 3], [2.5, 3], [3, 3], [4-s2, 3-s2], [4, 2],  # 0-4
-          [4+s2, 3-s2], [5, 3], [5.5, 3], [8, 3], [0, 1.5],  # 5-9
-          [2.5, 1.5], [4, 1.5], [5.5, 1.5], [8, 1.5], [0, 0],  # 10-14
-          [2.5, 0], [3, 0], [4-s2, s2], [4, 1], [4+s2, s2],  # 15-19
-          [5, 0], [5.5, 0], [8, 0], [4, 3], [4, 0]]  # 20-24
+s2 = 1 / sqrt(2)
+
+points = [
+    [0, 3],
+    [2.5, 3],
+    [3, 3],
+    [4 - s2, 3 - s2],
+    [4, 2],  # 0-4
+    [4 + s2, 3 - s2],
+    [5, 3],
+    [5.5, 3],
+    [8, 3],
+    [0, 1.5],  # 5-9
+    [2.5, 1.5],
+    [4, 1.5],
+    [5.5, 1.5],
+    [8, 1.5],
+    [0, 0],  # 10-14
+    [2.5, 0],
+    [3, 0],
+    [4 - s2, s2],
+    [4, 1],
+    [4 + s2, s2],  # 15-19
+    [5, 0],
+    [5.5, 0],
+    [8, 0],
+    [4, 3],
+    [4, 0],
+]  # 20-24
 
 for xp, yp in points:
-    g.point([xp*0.1, yp*0.1])
-
-splines = [[0, 1], [1, 2], [6, 7], [7, 8], [8, 13],  # 0-4
-           [13, 22], [22, 21], [21, 20], [16, 15], [15, 14],  # 5-9
-           [14, 9], [9, 0], [9, 10], [10, 1], [10, 15],  # 10-14
-           [10, 11], [11, 4], [11, 18], [11, 12], [12, 7],  # 15-19
-           [12, 21], [12, 13], [3, 10], [5, 12], [10, 17],  # 20-24
-           [12, 19]]  # 25
+    g.point([xp * 0.1, yp * 0.1])
+
+splines = [
+    [0, 1],
+    [1, 2],
+    [6, 7],
+    [7, 8],
+    [8, 13],  # 0-4
+    [13, 22],
+    [22, 21],
+    [21, 20],
+    [16, 15],
+    [15, 14],  # 5-9
+    [14, 9],
+    [9, 0],
+    [9, 10],
+    [10, 1],
+    [10, 15],  # 10-14
+    [10, 11],
+    [11, 4],
+    [11, 18],
+    [11, 12],
+    [12, 7],  # 15-19
+    [12, 21],
+    [12, 13],
+    [3, 10],
+    [5, 12],
+    [10, 17],  # 20-24
+    [12, 19],
+]  # 25
 
 for s in splines:
     g.spline(s, el_on_curve=10)
 
-g.curveMarker(ID=4,  marker=7)  # Assign marker 7 to the splines on the right.
-g.curveMarker(ID=5,  marker=7)  # We will apply a force on nodes with marker 7.
+g.curveMarker(ID=4, marker=7)  # Assign marker 7 to the splines on the right.
+g.curveMarker(ID=5, marker=7)  # We will apply a force on nodes with marker 7.
 g.curveMarker(ID=10, marker=5)  # Assign marker 5 to the splines on the left.
 # The nodes with marker 5 will be locked in place.
 g.curveMarker(ID=11, marker=5)
 
 # Points in circle arcs are [start, center, end]
 
-circlearcs = [[2, 23, 3], [3, 23, 4], [4, 23, 5], [5, 23, 6],  # 26-29
-              [16, 24, 17], [17, 24, 18], [18, 24, 19], [19, 24, 20]]  # 30-33
+circlearcs = [
+    [2, 23, 3],
+    [3, 23, 4],
+    [4, 23, 5],
+    [5, 23, 6],  # 26-29
+    [16, 24, 17],
+    [17, 24, 18],
+    [18, 24, 19],
+    [19, 24, 20],
+]  # 30-33
 
 for c in circlearcs:
     g.circle(c, el_on_curve=10)
@@ -112,8 +164,8 @@
 
 f = np.zeros([nDofs, 1])
 
-bc = np.array([], 'i')
-bcVal = np.array([], 'f')
+bc = np.array([], "i")
+bcVal = np.array([], "f")
 
 bc, bcVal = cfu.applybc(bdofs, bc, bcVal, 5, 0.0, 0)
 
@@ -129,15 +181,13 @@
 # For each element:
 
 for i in range(edof.shape[0]):
-
     # Determine element stresses and strains in the element.
 
     es, et = cfc.planqs(ex[i, :], ey[i, :], ep, D, ed[i, :])
 
     # Calc and append effective stress to list.
 
-    vonMises.append(sqrt(pow(es[0], 2) - es[0] *
-                    es[1] + pow(es[1], 2) + 3*es[2]))
+    vonMises.append(sqrt(pow(es[0], 2) - es[0] * es[1] + pow(es[1], 2) + 3 * es[2]))
 
     # es: [sigx sigy tauxy]
 
@@ -146,21 +196,46 @@
 cfu.info("Visualising...")
 
 cfv.figure()
-cfv.draw_geometry(g, draw_points=True, label_curves=True, label_points=True,
-                  title="Example 6a - Geometry")
+cfv.draw_geometry(
+    g,
+    draw_points=True,
+    label_curves=True,
+    label_points=True,
+    title="Example 6a - Geometry",
+)
 
 cfv.figure()
-cfv.draw_mesh(coords, edof, dofs_per_node=mesh.dofs_per_node,
-              el_type=mesh.el_type, title="Example 6b - Meshing")
+cfv.draw_mesh(
+    coords,
+    edof,
+    dofs_per_node=mesh.dofs_per_node,
+    el_type=mesh.el_type,
+    title="Example 6b - Meshing",
+)
 
 cfv.figure()
-cfv.draw_element_values(vonMises, coords, edof, mesh.dofs_per_node, mesh.el_type, None,
-                        draw_elements=False, draw_undisplaced_mesh=False, title="Example 6c - Effective stress")
+cfv.draw_element_values(
+    vonMises,
+    coords,
+    edof,
+    mesh.dofs_per_node,
+    mesh.el_type,
+    None,
+    draw_elements=False,
+    draw_undisplaced_mesh=False,
+    title="Example 6c - Effective stress",
+)
 
 cfv.figure()
-cfv.draw_displacements(a, coords, edof, mesh.dofs_per_node, mesh.el_type,
-                       draw_undisplaced_mesh=True, 
-                       title="Example 6d - Displacements")
+cfv.draw_displacements(
+    a,
+    coords,
+    edof,
+    mesh.dofs_per_node,
+    mesh.el_type,
+    draw_undisplaced_mesh=True,
+    title="Example 6d - Displacements",
+)
 
 # Make use of attribute 'nodesOnCurve' in GmshMesher to draw some arrows on
 # the right hand side of the mesh: --> currently not working
@@ -170,18 +245,16 @@
 # 4 and 5 are the IDs of the curves where we applied the forces.
 
 for curveID in [4, 5]:
-
     # Get the nodes, without duplicates.
     rightSideNodes = rightSideNodes.union(set(mesh.nodesOnCurve[curveID]))
 
 for i in rightSideNodes:
-
     # Position of the node with displacements.
-    x = coords[i, 0] + a[i*2, 0]
-    y = coords[i, 1] + a[i*2+1, 0]
+    x = coords[i, 0] + a[i * 2, 0]
+    y = coords[i, 1] + a[i * 2 + 1, 0]
 
     # A poor man's force indicator. Could also use vv.plot()
-    cfv.add_text(r'$\rightarrow$', (x, y), color='g')
+    cfv.add_text(r"$\rightarrow$", (x, y), color="g")
 
 # Enter main loop
 cfv.show_and_wait()
diff --git a/examples/exm_stress_2d_export.py b/examples/exm_stress_2d_export.py
index 3aa9af2..4cf2e3e 100644
--- a/examples/exm_stress_2d_export.py
+++ b/examples/exm_stress_2d_export.py
@@ -1,12 +1,12 @@
 # -*- coding: utf-8 -*-
 
-'''Example 06
+"""Example 06
 
 Solves a plane stress 2D problem using a structured mesh.
 Shows how to draw von Mises effective stress as an element value with 
 drawElementValues(). Shows use of GmshMesher attribute 'nodesOnCurve' 
 (dictionary that says which nodes are on a given geometry curve)
-'''
+"""
 
 import calfem.geometry as cfg
 import calfem.mesh as cfm
@@ -25,8 +25,8 @@
 v = 0.35
 E = 2.1e9
 ptype = 1
-ep = [ptype,t]
-D=cfc.hooke(ptype, E, v)
+ep = [ptype, t]
+D = cfc.hooke(ptype, E, v)
 
 # ---- Define geometry ------------------------------------------------------
 
@@ -36,52 +36,104 @@
 
 # Just a shorthand. We use this to make the circle arcs.
 
-s2 = 1/sqrt(2) 
+s2 = 1 / sqrt(2)
+
+points = [
+    [0, 3],
+    [2.5, 3],
+    [3, 3],
+    [4 - s2, 3 - s2],
+    [4, 2],  # 0-4
+    [4 + s2, 3 - s2],
+    [5, 3],
+    [5.5, 3],
+    [8, 3],
+    [0, 1.5],  # 5-9
+    [2.5, 1.5],
+    [4, 1.5],
+    [5.5, 1.5],
+    [8, 1.5],
+    [0, 0],  # 10-14
+    [2.5, 0],
+    [3, 0],
+    [4 - s2, s2],
+    [4, 1],
+    [4 + s2, s2],  # 15-19
+    [5, 0],
+    [5.5, 0],
+    [8, 0],
+    [4, 3],
+    [4, 0],
+]  # 20-24
 
-points = [[0, 3], [2.5, 3], [3, 3], [4-s2, 3-s2], [4, 2],     #0-4
-          [4+s2, 3-s2], [5, 3], [5.5, 3], [8,3], [0, 1.5],    #5-9
-          [2.5, 1.5], [4, 1.5], [5.5, 1.5], [8, 1.5], [0, 0], #10-14
-          [2.5, 0], [3, 0], [4-s2, s2], [4, 1], [4+s2, s2],   #15-19
-          [5, 0], [5.5, 0], [8,0], [4,3], [4,0]]              #20-24
-          
 for xp, yp in points:
-    g.point([xp*0.1, yp*0.1])
-
-splines = [[0,1], [1,2], [6,7], [7,8], [8,13],          #0-4
-           [13,22], [22,21], [21,20], [16,15], [15,14], #5-9
-           [14,9], [9,0], [9,10], [10,1], [10, 15],     #10-14
-           [10,11], [11,4], [11,18], [11,12], [12,7],   #15-19
-           [12,21], [12,13], [3,10], [5,12], [10,17],   #20-24
-           [12,19]]                                     #25
-           
+    g.point([xp * 0.1, yp * 0.1])
+
+splines = [
+    [0, 1],
+    [1, 2],
+    [6, 7],
+    [7, 8],
+    [8, 13],  # 0-4
+    [13, 22],
+    [22, 21],
+    [21, 20],
+    [16, 15],
+    [15, 14],  # 5-9
+    [14, 9],
+    [9, 0],
+    [9, 10],
+    [10, 1],
+    [10, 15],  # 10-14
+    [10, 11],
+    [11, 4],
+    [11, 18],
+    [11, 12],
+    [12, 7],  # 15-19
+    [12, 21],
+    [12, 13],
+    [3, 10],
+    [5, 12],
+    [10, 17],  # 20-24
+    [12, 19],
+]  # 25
+
 for s in splines:
     g.spline(s, el_on_curve=10)
-    
-g.curveMarker(ID=4,  marker=7) #Assign marker 7 to the splines on the right.
-g.curveMarker(ID=5,  marker=7) # We will apply a force on nodes with marker 7.
-g.curveMarker(ID=10, marker=5) #Assign marker 5 to the splines on the left.
-g.curveMarker(ID=11, marker=5) # The nodes with marker 5 will be locked in place.
+
+g.curveMarker(ID=4, marker=7)  # Assign marker 7 to the splines on the right.
+g.curveMarker(ID=5, marker=7)  # We will apply a force on nodes with marker 7.
+g.curveMarker(ID=10, marker=5)  # Assign marker 5 to the splines on the left.
+g.curveMarker(ID=11, marker=5)  # The nodes with marker 5 will be locked in place.
 
 # Points in circle arcs are [start, center, end]
 
-circlearcs = [[2, 23, 3], [3, 23, 4], [4, 23, 5], [5, 23, 6],           #26-29
-              [16, 24, 17], [17, 24, 18], [18, 24, 19], [19, 24, 20]]   #30-33
-              
+circlearcs = [
+    [2, 23, 3],
+    [3, 23, 4],
+    [4, 23, 5],
+    [5, 23, 6],  # 26-29
+    [16, 24, 17],
+    [17, 24, 18],
+    [18, 24, 19],
+    [19, 24, 20],
+]  # 30-33
+
 for c in circlearcs:
     g.circle(c, el_on_curve=10)
 
-g.structuredSurface([11,12,13,0]) #0
+g.structuredSurface([11, 12, 13, 0])  # 0
 g.structuredSurface([14, 12, 10, 9])
 g.structuredSurface([8, 30, 24, 14])
 g.structuredSurface([24, 31, 17, 15])
-g.structuredSurface([15, 16, 27, 22]) #4
-g.structuredSurface([22, 26, 1, 13]) 
+g.structuredSurface([15, 16, 27, 22])  # 4
+g.structuredSurface([22, 26, 1, 13])
 g.structuredSurface([16, 18, 23, 28])
 g.structuredSurface([19, 2, 29, 23])
-g.structuredSurface([19, 21, 4, 3]) #8
+g.structuredSurface([19, 21, 4, 3])  # 8
 g.structuredSurface([20, 6, 5, 21])
 g.structuredSurface([25, 20, 7, 33])
-g.structuredSurface([32, 17, 18, 25]) #11
+g.structuredSurface([32, 17, 18, 25])  # 11
 
 # ---- Create mesh ----------------------------------------------------------
 
@@ -89,7 +141,7 @@
 
 # Create mesh
 
-mesh = cfm.GmshMesh(geometry = g)
+mesh = cfm.GmshMesh(geometry=g)
 mesh.el_type = 3
 mesh.dofs_per_node = 2
 
@@ -102,7 +154,7 @@
 
 nDofs = np.size(dofs)
 ex, ey = cfc.coordxtr(edof, coords, dofs)
-K = np.zeros([nDofs,nDofs])
+K = np.zeros([nDofs, nDofs])
 
 for eltopo, elx, ely in zip(edof, ex, ey):
     Ke = cfc.planqe(elx, ely, ep, D)
@@ -110,44 +162,53 @@
 
 cfu.info("Solving equation system...")
 
-f = np.zeros([nDofs,1])
+f = np.zeros([nDofs, 1])
 
-bc = np.array([],'i')
-bcVal = np.array([],'f')
+bc = np.array([], "i")
+bcVal = np.array([], "f")
 
 bc, bcVal = cfu.applybc(bdofs, bc, bcVal, 5, 0.0, 0)
 
 cfu.applyforcetotal(bdofs, f, 7, 10e5, 1)
 
-a,r = cfc.solveq(K,f,bc,bcVal)
+a, r = cfc.solveq(K, f, bc, bcVal)
 
 cfu.info("Computing element forces...")
 
-ed = cfc.extractEldisp(edof,a)
+ed = cfc.extractEldisp(edof, a)
 von_mises = []
 principal1 = []
 principal2 = []
 
 # For each element:
 
-for i in range(edof.shape[0]): 
-
+for i in range(edof.shape[0]):
     # Determine element stresses and strains in the element.
-    
-    es, et = cfc.planqs(ex[i,:], ey[i,:], ep, D, ed[i,:]) 
-
-    # Calc and append effective stress to list.    
-    
-    von_mises.append( sqrt( pow(es[0],2) - es[0]*es[1] + pow(es[1],2) + 3*es[2] ) ) 
-
-    theta = np.arctan2(2*es[2], es[0]-es[1])*0.5
-    sigma1 = 0.5*(es[0]+es[1])+np.sqrt(np.power(0.5*(es[0]-es[1]),2)+np.power(es[2],2))
-    sigma2 = 0.5*(es[0]+es[1])-np.sqrt(np.power(0.5*(es[0]-es[1]),2)+np.power(es[2],2))
-    s1v = [sigma1*np.cos(theta), sigma1*np.sin(theta), 0.0]
-    s2v = [sigma2*np.cos(theta+0.5*np.pi), sigma2*np.sin(theta+0.5*np.pi), 0.0]
+
+    es, et = cfc.planqs(ex[i, :], ey[i, :], ep, D, ed[i, :])
+
+    # Calc and append effective stress to list.
+
+    von_mises.append(sqrt(pow(es[0], 2) - es[0] * es[1] + pow(es[1], 2) + 3 * es[2]))
+
+    theta = np.arctan2(2 * es[2], es[0] - es[1]) * 0.5
+    sigma1 = 0.5 * (es[0] + es[1]) + np.sqrt(
+        np.power(0.5 * (es[0] - es[1]), 2) + np.power(es[2], 2)
+    )
+    sigma2 = 0.5 * (es[0] + es[1]) - np.sqrt(
+        np.power(0.5 * (es[0] - es[1]), 2) + np.power(es[2], 2)
+    )
+    s1v = [sigma1 * np.cos(theta), sigma1 * np.sin(theta), 0.0]
+    s2v = [
+        sigma2 * np.cos(theta + 0.5 * np.pi),
+        sigma2 * np.sin(theta + 0.5 * np.pi),
+        0.0,
+    ]
     principal1.append(s1v)
     principal2.append(s2v)
 
 # ---- Export to VTK --------------------------------------------------------
 
-cfu.export_vtk_stress("exm6.vtk", coords, mesh.topo-1, a, von_mises, principal1, principal2)
+cfu.export_vtk_stress(
+    "exm6.vtk", coords, mesh.topo - 1, a, von_mises, principal1, principal2
+)
diff --git a/examples/exm_stress_2d_materials.py b/examples/exm_stress_2d_materials.py
index e12f068..fd7e11a 100644
--- a/examples/exm_stress_2d_materials.py
+++ b/examples/exm_stress_2d_materials.py
@@ -1,10 +1,10 @@
 # -*- coding: utf-8 -*-
 
-'''Example 10
+"""Example 10
 
 The use case from the user manual. 
 The example does not contain anything that is not covered in the previous examples.
-'''
+"""
 
 import calfem.core as cfc
 import calfem.geometry as cfg
@@ -12,6 +12,7 @@
 import calfem.vis_mpl as cfv
 import calfem.utils as cfu
 import numpy as np
+import math
 
 from scipy.sparse import lil_matrix
 
@@ -24,7 +25,7 @@
 E1 = 2e9
 E2 = 0.2e9
 ptype = 1
-ep = [ptype,t]
+ep = [ptype, t]
 D1 = cfc.hooke(ptype, E1, v)
 D2 = cfc.hooke(ptype, E2, v)
 
@@ -43,53 +44,53 @@
 
 # Parameters controlling mesh
 
-el_size_factor = 0.05    # Element size factor
-el_type = 3             # Triangle element
-dofs_per_node = 2        # Dof per node
+el_size_factor = 0.05  # Element size factor
+el_type = 3  # Triangle element
+dofs_per_node = 2  # Dof per node
 
 # ---- Create Geometry ------------------------------------------------------
 
 # Create a Geometry object that holds the geometry.
 
-g = cfg.Geometry() 
+g = cfg.Geometry()
 
 # Add points:
 
-g.point([0, 0])		#0
-g.point([1, 0])		#1
-g.point([1, 1])		#2
-g.point([0, 1])		#3
-g.point([0.2, 0.2])	#4
-g.point([0.8, 0.2])	#5
-g.point([0.8, 0.8])	#6
-g.point([0.2, 0.8])	#7
+g.point([0, 0])  # 0
+g.point([1, 0])  # 1
+g.point([1, 1])  # 2
+g.point([0, 1])  # 3
+g.point([0.2, 0.2])  # 4
+g.point([0.8, 0.2])  # 5
+g.point([0.8, 0.8])  # 6
+g.point([0.2, 0.8])  # 7
 
 # Add curves:
 
-g.spline([0, 1], marker = mark_fixed) #0
-g.spline([2, 1])                     #1
-g.spline([3, 2], marker = mark_load)  #2
-g.spline([0, 3])                     #3
-g.spline([4, 5])                     #4
-g.spline([5, 6])                     #5
-g.spline([6, 7])                     #6
-g.spline([7, 4])                     #7
+g.spline([0, 1], marker=mark_fixed)  # 0
+g.spline([2, 1])  # 1
+g.spline([3, 2], marker=mark_load)  # 2
+g.spline([0, 3])  # 3
+g.spline([4, 5])  # 4
+g.spline([5, 6])  # 5
+g.spline([6, 7])  # 6
+g.spline([7, 4])  # 7
 
 # Add surfaces:
 
-g.surface([0,1,2,3], holes = [[4,5,6,7]], marker = mark_E1)
-g.surface([4,5,6,7], marker = mark_E2)
+g.surface([0, 1, 2, 3], holes=[[4, 5, 6, 7]], marker=mark_E1)
+g.surface([4, 5, 6, 7], marker=mark_E2)
 
 # ---- Create Mesh ----------------------------------------------------------
 
 mesh = cfm.GmshMeshGenerator(g)
 mesh.el_size_factor = el_size_factor
-mesh.el_type = el_type  
+mesh.el_type = el_type
 mesh.dofs_per_node = dofs_per_node
 
 # Mesh the geometry:
 #  The first four return values are the same as those that trimesh2d() returns.
-#  value elementmarkers is a list of markers, and is used for finding the 
+#  value elementmarkers is a list of markers, and is used for finding the
 #  marker of a given element (index).
 
 coords, edof, dofs, bdofs, elementmarkers = mesh.create()
@@ -97,34 +98,33 @@
 # ---- Solve problem --------------------------------------------------------
 
 nDofs = np.size(dofs)
-K = lil_matrix((nDofs,nDofs))
+K = lil_matrix((nDofs, nDofs))
 ex, ey = cfc.coordxtr(edof, coords, dofs)
 
-cfu.info("Assembling K... ("+str(nDofs)+")")
+cfu.info("Assembling K... (" + str(nDofs) + ")")
 
 for eltopo, elx, ely, elMarker in zip(edof, ex, ey, elementmarkers):
-
     if el_type == 2:
         Ke = cfc.plante(elx, ely, elprop[elMarker][0], elprop[elMarker][1])
     else:
         Ke = cfc.planqe(elx, ely, elprop[elMarker][0], elprop[elMarker][1])
-        
+
     cfc.assem(eltopo, K, Ke)
-    
+
 cfu.info("Applying bc and loads...")
 
-bc = np.array([],'i')
-bcVal = np.array([],'i')
+bc = np.array([], "i")
+bcVal = np.array([], "i")
 
 bc, bcVal = cfu.applybc(bdofs, bc, bcVal, mark_fixed, 0.0)
 
-f = np.zeros([nDofs,1])
+f = np.zeros([nDofs, 1])
 
-cfu.applyforcetotal(bdofs, f, mark_load, value = -10e5, dimension=2)
+cfu.applyforcetotal(bdofs, f, mark_load, value=-10e5, dimension=2)
 
 cfu.info("Solving system...")
 
-a,r = cfc.spsolveq(K, f, bc, bcVal)
+a, r = cfc.spsolveq(K, f, bc, bcVal)
 
 cfu.info("Extracting ed...")
 
@@ -136,48 +136,85 @@
 cfu.info("Element forces... ")
 
 for i in range(edof.shape[0]):
-    
     # Handle triangle elements
-        
-    if el_type == 2: 
-        es, et = cfc.plants(ex[i,:], ey[i,:], 
-                        elprop[elementmarkers[i]][0], 
-                        elprop[elementmarkers[i]][1], 
-                        ed[i,:])
-        
-        von_mises.append( np.math.sqrt( pow(es[0,0],2) - es[0,0]*es[0,1] + pow(es[0,1],2) + 3*pow(es[0,2],2) ) )
+
+    if el_type == 2:
+        es, et = cfc.plants(
+            ex[i, :],
+            ey[i, :],
+            elprop[elementmarkers[i]][0],
+            elprop[elementmarkers[i]][1],
+            ed[i, :],
+        )
+
+        von_mises.append(
+            np.math.sqrt(
+                pow(es[0, 0], 2)
+                - es[0, 0] * es[0, 1]
+                + pow(es[0, 1], 2)
+                + 3 * pow(es[0, 2], 2)
+            )
+        )
 
     else:
-        
         # Handle quad elements
-        
-        es, et = cfc.planqs(ex[i,:], ey[i,:], 
-                        elprop[elementmarkers[i]][0], 
-                        elprop[elementmarkers[i]][1], 
-                        ed[i,:])
-        
-        von_mises.append( np.math.sqrt( pow(es[0],2) - es[0]*es[1] + pow(es[1],2) + 3*pow(es[2],2) ) )
-        
+
+        es, et = cfc.planqs(
+            ex[i, :],
+            ey[i, :],
+            elprop[elementmarkers[i]][0],
+            elprop[elementmarkers[i]][1],
+            ed[i, :],
+        )
+
+        von_mises.append(
+            math.sqrt(
+                pow(es[0], 2) - es[0] * es[1] + pow(es[1], 2) + 3 * pow(es[2], 2)
+            )
+        )
+
 # ---- Visualise results ----------------------------------------------------
 
 cfu.info("Drawing results...")
 
-cfv.figure() 
+cfv.figure()
 cfv.draw_geometry(g, title="Geometry")
 
-cfv.figure() 
-cfv.draw_mesh(coords=coords, edof=edof, dofs_per_node=dofs_per_node, el_type=el_type, 
-             filled=True, title="Mesh") #Draws the mesh.
+cfv.figure()
+cfv.draw_mesh(
+    coords=coords,
+    edof=edof,
+    dofs_per_node=dofs_per_node,
+    el_type=el_type,
+    filled=True,
+    title="Mesh",
+)  # Draws the mesh.
 
 cfv.figure()
-cfv.draw_displacements(a, coords, edof, dofs_per_node, el_type, 
-                      draw_undisplaced_mesh=False, title="Displacements", 
-                      magnfac=25.0)
+cfv.draw_displacements(
+    a,
+    coords,
+    edof,
+    dofs_per_node,
+    el_type,
+    draw_undisplaced_mesh=False,
+    title="Displacements",
+    magnfac=25.0,
+)
 
 cfv.figure()
-cfv.draw_element_values(von_mises, coords, edof, dofs_per_node, el_type, a, 
-                      draw_elements=True, draw_undisplaced_mesh=False, 
-                      title="Effective Stress", magnfac=25.0)
+cfv.draw_element_values(
+    von_mises,
+    coords,
+    edof,
+    dofs_per_node,
+    el_type,
+    a,
+    draw_elements=True,
+    draw_undisplaced_mesh=False,
+    title="Effective Stress",
+    magnfac=25.0,
+)
 
 cfv.colorbar()
 
diff --git a/examples/exm_stress_2d_pyvtk.py b/examples/exm_stress_2d_pyvtk.py
index 8b67bce..5693bb0 100644
--- a/examples/exm_stress_2d_pyvtk.py
+++ b/examples/exm_stress_2d_pyvtk.py
@@ -1,12 +1,12 @@
 # -*- coding: utf-8 -*-
 
-'''Example 06
+"""Example 06
 
 Solves a plane stress 2D problem using a structured mesh.
 Shows how to draw von Mises effective stress as an element value with 
 drawElementValues(). Shows use of GmshMesher attribute 'nodesOnCurve' 
 (dictionary that says which nodes are on a given geometry curve)
-'''
+"""
 
 import calfem.geometry as cfg
 import calfem.mesh as cfm
@@ -26,8 +26,8 @@
 v = 0.35
 E = 2.1e9
 ptype = 1
-ep = [ptype,t]
-D=cfc.hooke(ptype, E, v)
+ep = [ptype, t]
+D = cfc.hooke(ptype, E, v)
 
 # ---- Define geometry ------------------------------------------------------
 
@@ -37,52 +37,104 @@
 
 # Just a shorthand. We use this to make the circle arcs.
 
-s2 = 1/sqrt(2) 
+s2 = 1 / sqrt(2)
+
+points = [
+    [0, 3],
+    [2.5, 3],
+    [3, 3],
+    [4 - s2, 3 - s2],
+    [4, 2],  # 0-4
+    [4 + s2, 3 - s2],
+    [5, 3],
+    [5.5, 3],
+    [8, 3],
+    [0, 1.5],  # 5-9
+    [2.5, 1.5],
+    [4, 1.5],
+    [5.5, 1.5],
+    [8, 1.5],
+    [0, 0],  # 10-14
+    [2.5, 0],
+    [3, 0],
+    [4 - s2, s2],
+    [4, 1],
+    [4 + s2, s2],  # 15-19
+    [5, 0],
+    [5.5, 0],
+    [8, 0],
+    [4, 3],
+    [4, 0],
+]  # 20-24
 
-points = [[0, 3], [2.5, 3], [3, 3], [4-s2, 3-s2], [4, 2],     #0-4
-          [4+s2, 3-s2], [5, 3], [5.5, 3], [8,3], [0, 1.5],    #5-9
-          [2.5, 1.5], [4, 1.5], [5.5, 1.5], [8, 1.5], [0, 0], #10-14
-          [2.5, 0], [3, 0], [4-s2, s2], [4, 1], [4+s2, s2],   #15-19
-          [5, 0], [5.5, 0], [8,0], [4,3], [4,0]]              #20-24
-          
 for xp, yp in points:
-    g.point([xp*0.1, yp*0.1])
-
-splines = [[0,1], [1,2], [6,7], [7,8], [8,13],          #0-4
-           [13,22], [22,21], [21,20], [16,15], [15,14], #5-9
-           [14,9], [9,0], [9,10], [10,1], [10, 15],     #10-14
-           [10,11], [11,4], [11,18], [11,12], [12,7],   #15-19
-           [12,21], [12,13], [3,10], [5,12], [10,17],   #20-24
-           [12,19]]                                     #25
-           
+    g.point([xp * 0.1, yp * 0.1])
+
+splines = [
+    [0, 1],
+    [1, 2],
+    [6, 7],
+    [7, 8],
+    [8, 13],  # 0-4
+    [13, 22],
+    [22, 21],
+    [21, 20],
+    [16, 15],
+    [15, 14],  # 5-9
+    [14, 9],
+    [9, 0],
+    [9, 10],
+    [10, 1],
+    [10, 15],  # 10-14
+    [10, 11],
+    [11, 4],
+    [11, 18],
+    [11, 12],
+    [12, 7],  # 15-19
+    [12, 21],
+    [12, 13],
+    [3, 10],
+    [5, 12],
+    [10, 17],  # 20-24
+    [12, 19],
+]  # 25
+
 for s in splines:
     g.spline(s, el_on_curve=10)
-    
-g.curveMarker(ID=4,  marker=7) #Assign marker 7 to the splines on the right.
-g.curveMarker(ID=5,  marker=7) # We will apply a force on nodes with marker 7.
-g.curveMarker(ID=10, marker=5) #Assign marker 5 to the splines on the left.
-g.curveMarker(ID=11, marker=5) # The nodes with marker 5 will be locked in place.
+
+g.curveMarker(ID=4, marker=7)  # Assign marker 7 to the splines on the right.
+g.curveMarker(ID=5, marker=7)  # We will apply a force on nodes with marker 7.
+g.curveMarker(ID=10, marker=5)  # Assign marker 5 to the splines on the left.
+g.curveMarker(ID=11, marker=5)  # The nodes with marker 5 will be locked in place.
 
 # Points in circle arcs are [start, center, end]
 
-circlearcs = [[2, 23, 3], [3, 23, 4], [4, 23, 5], [5, 23, 6],           #26-29
-              [16, 24, 17], [17, 24, 18], [18, 24, 19], [19, 24, 20]]   #30-33
-              
+circlearcs = [
+    [2, 23, 3],
+    [3, 23, 4],
+    [4, 23, 5],
+    [5, 23, 6],  # 26-29
+    [16, 24, 17],
+    [17, 24, 18],
+    [18, 24, 19],
+    [19, 24, 20],
+]  # 30-33
+
 for c in circlearcs:
     g.circle(c, el_on_curve=10)
 
-g.structuredSurface([11,12,13,0]) #0
+g.structuredSurface([11, 12, 13, 0])  # 0
 g.structuredSurface([14, 12, 10, 9])
 g.structuredSurface([8, 30, 24, 14])
 g.structuredSurface([24, 31, 17, 15])
-g.structuredSurface([15, 16, 27, 22]) #4
-g.structuredSurface([22, 26, 1, 13]) 
+g.structuredSurface([15, 16, 27, 22])  # 4
+g.structuredSurface([22, 26, 1, 13])
 g.structuredSurface([16, 18, 23, 28])
 g.structuredSurface([19, 2, 29, 23])
-g.structuredSurface([19, 21, 4, 3]) #8
+g.structuredSurface([19, 21, 4, 3])  # 8
 g.structuredSurface([20, 6, 5, 21])
 g.structuredSurface([25, 20, 7, 33])
-g.structuredSurface([32, 17, 18, 25]) #11
+g.structuredSurface([32, 17, 18, 25])  # 11
 
 # ---- Create mesh ----------------------------------------------------------
 
@@ -90,7 +142,7 @@
 
 # Create mesh
 
-mesh = cfm.GmshMesh(geometry = g)
+mesh = cfm.GmshMesh(geometry=g)
 mesh.el_type = 3
 mesh.dofs_per_node = 2
 
@@ -102,7 +154,7 @@
 
 nDofs = np.size(dofs)
 ex, ey = cfc.coordxtr(edof, coords, dofs)
-K = np.zeros([nDofs,nDofs])
+K = np.zeros([nDofs, nDofs])
 
 for eltopo, elx, ely in zip(edof, ex, ey):
     Ke = cfc.planqe(elx, ely, ep, D)
@@ -110,48 +162,57 @@
 
 cfu.info("Solving equation system...")
 
-f = np.zeros([nDofs,1])
+f = np.zeros([nDofs, 1])
 
-bc = np.array([],'i')
-bcVal = np.array([],'f')
+bc = np.array([], "i")
+bcVal = np.array([], "f")
 
 bc, bcVal = cfu.applybc(bdofs, bc, bcVal, 5, 0.0, 0)
 
 cfu.applyforcetotal(bdofs, f, 7, 10e5, 1)
 
-a,r = cfc.solveq(K,f,bc,bcVal)
+a, r = cfc.solveq(K, f, bc, bcVal)
 
 cfu.info("Computing element forces...")
 
-ed = cfc.extractEldisp(edof,a)
+ed = cfc.extractEldisp(edof, a)
 von_mises = []
 principal1 = []
 principal2 = []
 
 # For each element:
 
-for i in range(edof.shape[0]): 
-
+for i in range(edof.shape[0]):
     # Determine element stresses and strains in the element.
-    
-    es, et = cfc.planqs(ex[i,:], ey[i,:], ep, D, ed[i,:]) 
-
-    # Calc and append effective stress to list.    
-    
-    von_mises.append( sqrt( pow(es[0],2) - es[0]*es[1] + pow(es[1],2) + 3*es[2] ) ) 
-
-    theta = np.arctan2(2*es[2], es[0]-es[1])*0.5
-    sigma1 = 0.5*(es[0]+es[1])+np.sqrt(np.power(0.5*(es[0]-es[1]),2)+np.power(es[2],2))
-    sigma2 = 0.5*(es[0]+es[1])-np.sqrt(np.power(0.5*(es[0]-es[1]),2)+np.power(es[2],2))
-    s1v = [sigma1*np.cos(theta), sigma1*np.sin(theta), 0.0]
-    s2v = [sigma2*np.cos(theta+0.5*np.pi), sigma2*np.sin(theta+0.5*np.pi), 0.0]
+
+    es, et = cfc.planqs(ex[i, :], ey[i, :], ep, D, ed[i, :])
+
+    # Calc and append effective stress to list.
+
+    von_mises.append(sqrt(pow(es[0], 2) - es[0] * es[1] + pow(es[1], 2) + 3 * es[2]))
+
+    theta = np.arctan2(2 * es[2], es[0] - es[1]) * 0.5
+    sigma1 = 0.5 * (es[0] + es[1]) + np.sqrt(
+        np.power(0.5 * (es[0] - es[1]), 2) + np.power(es[2], 2)
+    )
+    sigma2 = 0.5 * (es[0] + es[1]) - np.sqrt(
+        np.power(0.5 * (es[0] - es[1]), 2) + np.power(es[2], 2)
+    )
+    s1v = [sigma1 * np.cos(theta), sigma1 * np.sin(theta), 0.0]
+    s2v = [
+        sigma2 * np.cos(theta + 0.5 * np.pi),
+        sigma2 * np.sin(theta + 0.5 * np.pi),
+        0.0,
+    ]
     principal1.append(s1v)
     principal2.append(s2v)
 
 # ---- Export to VTK --------------------------------------------------------
 
-points = coords.tolist()
-polygons = (mesh.topo-1).tolist()
+points = np.zeros([coords.shape[0], 3], dtype=np.float64)
+points[:,0:2] = coords
+points = points.tolist()
+polygons = (mesh.topo - 1).tolist()
 
 displ = []
 
@@ -161,8 +222,8 @@
 vectors2 = None
 cell_data = None
 
-for i in range(0,len(a),2):
-    displ.append([np.asscalar(a[i]), np.asscalar(a[i+1]), 0.0])                    
+for i in range(0, len(a), 2):
+    displ.append([a[i].item(), a[i + 1].item(), 0.0])
     point_data = vtk.PointData(vtk.Vectors(displ, name="displacements"))
 
 scalars = vtk.Scalars(von_mises, name="scalar")
@@ -171,7 +232,7 @@
 
 cell_data = vtk.CellData(scalars, vectors1, vectors2)
 
-structure = vtk.PolyData(points = points, polygons = polygons)
+structure = vtk.PolyData(points=points, polygons=polygons)
 
 vtk_data = vtk.VtkData(structure, cell_data, point_data)
 vtk_data.tofile("exm6.vtk", "ascii")
diff --git a/examples/exm_stress_2d_qt.py b/examples/exm_stress_2d_qt.py
index 3cec9b0..d461b16 100644
--- a/examples/exm_stress_2d_qt.py
+++ b/examples/exm_stress_2d_qt.py
@@ -1,12 +1,12 @@
 # -*- coding: utf-8 -*-
 
-'''Example 06
+"""Example 06
 
 Solves a plane stress 2D problem using a structured mesh.
 Shows how to draw von Mises effective stress as an element value with
 drawElementValues(). Shows use of GmshMesher attribute 'nodesOnCurve'
 (dictionary that says which nodes are on a given geometry curve)
-'''
+"""
 
 import sys
 from math import sqrt
@@ -21,10 +21,12 @@
 import calfem.utils as cfu
 import calfem.core as cfc
 
-#cfu.enableLogging()
+# cfu.enableLogging()
+
 
 class PlaneStress2DProblem(object):
     """Encapsulates our plane stress problem in a single class"""
+
     def __init__(self, t=0.2, v=0.35, E=2.1e9, ptype=1):
         """Setup intial problem values"""
         self.t = t
@@ -42,52 +44,106 @@ def updateGeometry(self):
 
         # Just a shorthand. We use this to make the circle arcs.
 
-        s2 = 1/sqrt(2)
-
-        points = [[0, 3], [2.5, 3], [3, 3], [4-s2, 3-s2], [4, 2],     #0-4
-                  [4+s2, 3-s2], [5, 3], [5.5, 3], [8, 3], [0, 1.5],    #5-9
-                  [2.5, 1.5], [4, 1.5], [5.5, 1.5], [8, 1.5], [0, 0], #10-14
-                  [2.5, 0], [3, 0], [4-s2, s2], [4, 1], [4+s2, s2],   #15-19
-                  [5, 0], [5.5, 0], [8, 0], [4, 3], [4, 0]]              #20-24
+        s2 = 1 / sqrt(2)
+
+        points = [
+            [0, 3],
+            [2.5, 3],
+            [3, 3],
+            [4 - s2, 3 - s2],
+            [4, 2],  # 0-4
+            [4 + s2, 3 - s2],
+            [5, 3],
+            [5.5, 3],
+            [8, 3],
+            [0, 1.5],  # 5-9
+            [2.5, 1.5],
+            [4, 1.5],
+            [5.5, 1.5],
+            [8, 1.5],
+            [0, 0],  # 10-14
+            [2.5, 0],
+            [3, 0],
+            [4 - s2, s2],
+            [4, 1],
+            [4 + s2, s2],  # 15-19
+            [5, 0],
+            [5.5, 0],
+            [8, 0],
+            [4, 3],
+            [4, 0],
+        ]  # 20-24
 
         for xp, yp in points:
-            g.point([xp*0.1, yp*0.1])
-
-        splines = [[0, 1], [1, 2], [6, 7], [7, 8], [8, 13],          #0-4
-                   [13, 22], [22, 21], [21, 20], [16, 15], [15, 14], #5-9
-                   [14, 9], [9, 0], [9, 10], [10, 1], [10, 15],     #10-14
-                   [10, 11], [11, 4], [11, 18], [11, 12], [12, 7],   #15-19
-                   [12, 21], [12, 13], [3, 10], [5, 12], [10, 17],   #20-24
-                   [12, 19]]                                     #25
+            g.point([xp * 0.1, yp * 0.1])
+
+        splines = [
+            [0, 1],
+            [1, 2],
+            [6, 7],
+            [7, 8],
+            [8, 13],  # 0-4
+            [13, 22],
+            [22, 21],
+            [21, 20],
+            [16, 15],
+            [15, 14],  # 5-9
+            [14, 9],
+            [9, 0],
+            [9, 10],
+            [10, 1],
+            [10, 15],  # 10-14
+            [10, 11],
+            [11, 4],
+            [11, 18],
+            [11, 12],
+            [12, 7],  # 15-19
+            [12, 21],
+            [12, 13],
+            [3, 10],
+            [5, 12],
+            [10, 17],  # 20-24
+            [12, 19],
+        ]  # 25
 
         for s in splines:
             g.spline(s, el_on_curve=5)
 
-        g.curveMarker(ID=4, marker=7) #Assign marker 7 to the splines on the right.
-        g.curveMarker(ID=5, marker=7) # We will apply a force on nodes with marker 7.
-        g.curveMarker(ID=10, marker=5) #Assign marker 5 to the splines on the left.
-        g.curveMarker(ID=11, marker=5) # The nodes with marker 5 will be locked in place.
+        g.curveMarker(ID=4, marker=7)  # Assign marker 7 to the splines on the right.
+        g.curveMarker(ID=5, marker=7)  # We will apply a force on nodes with marker 7.
+        g.curveMarker(ID=10, marker=5)  # Assign marker 5 to the splines on the left.
+        g.curveMarker(
+            ID=11, marker=5
+        )  # The nodes with marker 5 will be locked in place.
 
         # Points in circle arcs are [start, center, end]
 
-        circlearcs = [[2, 23, 3], [3, 23, 4], [4, 23, 5], [5, 23, 6],           #26-29
-                      [16, 24, 17], [17, 24, 18], [18, 24, 19], [19, 24, 20]]   #30-33
+        circlearcs = [
+            [2, 23, 3],
+            [3, 23, 4],
+            [4, 23, 5],
+            [5, 23, 6],  # 26-29
+            [16, 24, 17],
+            [17, 24, 18],
+            [18, 24, 19],
+            [19, 24, 20],
+        ]  # 30-33
 
         for c in circlearcs:
             g.circle(c, el_on_curve=5)
 
-        g.structuredSurface([11, 12, 13, 0]) #0
+        g.structuredSurface([11, 12, 13, 0])  # 0
         g.structuredSurface([14, 12, 10, 9])
         g.structuredSurface([8, 30, 24, 14])
         g.structuredSurface([24, 31, 17, 15])
-        g.structuredSurface([15, 16, 27, 22]) #4
+        g.structuredSurface([15, 16, 27, 22])  # 4
         g.structuredSurface([22, 26, 1, 13])
         g.structuredSurface([16, 18, 23, 28])
         g.structuredSurface([19, 2, 29, 23])
-        g.structuredSurface([19, 21, 4, 3]) #8
+        g.structuredSurface([19, 21, 4, 3])  # 8
         g.structuredSurface([20, 6, 5, 21])
         g.structuredSurface([25, 20, 7, 33])
-        g.structuredSurface([32, 17, 18, 25]) #11
+        g.structuredSurface([32, 17, 18, 25])  # 11
 
     def updateMesh(self):
         """Update mesh"""
@@ -105,7 +161,13 @@ def updateMesh(self):
         self.mesh.el_type = self.el_type
         self.mesh.dofs_per_node = self.dofs_per_node
 
-        self.coords, self.edof, self.dofs, self.bdofs, self.elementmarkers = self.mesh.create()
+        (
+            self.coords,
+            self.edof,
+            self.dofs,
+            self.bdofs,
+            self.elementmarkers,
+        ) = self.mesh.create()
 
     def solve(self):
         """Solve problem"""
@@ -130,8 +192,8 @@ def solve(self):
 
         f = np.zeros([nDofs, 1])
 
-        bc = np.array([], 'i')
-        bcVal = np.array([], 'i')
+        bc = np.array([], "i")
+        bcVal = np.array([], "i")
 
         bc, bcVal = cfu.applybc(self.bdofs, bc, bcVal, 5, 0.0, 0)
 
@@ -147,14 +209,15 @@ def solve(self):
         # For each element:
 
         for i in range(self.edof.shape[0]):
-
             # Determine element stresses and strains in the element.
 
             es, et = cfc.planqs(ex[i, :], ey[i, :], self.ep, self.D, ed[i, :])
 
             # Calc and append effective stress to list.
 
-            self.vonMises.append(sqrt(pow(es[0], 2) - es[0]*es[1] + pow(es[1], 2) + 3*es[2]))
+            self.vonMises.append(
+                sqrt(pow(es[0], 2) - es[0] * es[1] + pow(es[1], 2) + 3 * es[2])
+            )
 
             ## es: [sigx sigy tauxy]
 
@@ -168,19 +231,31 @@ def drawElementValues(self, figElementValues):
         """Draws element values in specified figure"""
         cfv.figure(figElementValues.nr)
         cfv.clf()
-        cfv.draw_element_values(self.vonMises, self.coords, self.edof,
-                              self.mesh.dofs_per_node, self.mesh.el_type,
-                              self.a, draw_elements=True,
-                              draw_undisplaced_mesh=False,
-                              title="Example 06 effective stress")
+        cfv.draw_element_values(
+            self.vonMises,
+            self.coords,
+            self.edof,
+            self.mesh.dofs_per_node,
+            self.mesh.el_type,
+            self.a,
+            draw_elements=True,
+            draw_undisplaced_mesh=False,
+            title="Example 06 effective stress",
+        )
 
     def drawDisplacements(self, figDisplacements):
         """Draws displacements in specified figure"""
         cfv.figure(figDisplacements.nr)
         cfv.clf()
-        cfv.draw_displacements(self.a, self.coords, self.edof,
-                              self.mesh.dofs_per_node, self.mesh.el_type,
-                              draw_undisplaced_mesh=True, title="Example 06")
+        cfv.draw_displacements(
+            self.a,
+            self.coords,
+            self.edof,
+            self.mesh.dofs_per_node,
+            self.mesh.el_type,
+            draw_undisplaced_mesh=True,
+            title="Example 06",
+        )
 
         # Make use of attribute 'nodesOnCurve' in GmshMesher to draw some arrows on
         # the right hand side of the mesh:
@@ -190,32 +265,31 @@ def drawDisplacements(self, figDisplacements):
         # 4 and 5 are the IDs of the curves where we applied the forces.
 
         for curveID in [4, 5]:
-
             # Get the nodes, without duplicates.
 
             rightSideNodes = rightSideNodes.union(set(self.mesh.nodesOnCurve[curveID]))
 
         for i in rightSideNodes:
-
             # Position of the node with displacements.
 
-            x = self.coords[i, 0] + self.a[i*2, 0]
-            y = self.coords[i, 1] + self.a[i*2+1, 0]
+            x = self.coords[i, 0] + self.a[i * 2, 0]
+            y = self.coords[i, 1] + self.a[i * 2 + 1, 0]
 
             # A poor man's force indicator. Could also use vv.plot()
 
-            cfv.addText("\rightarrow", (x, y), font_size=20, color='g')
+            cfv.addText("\rightarrow", (x, y), font_size=20, color="g")
 
 
 class MainWindow(QMainWindow):
     """Main window class of our UI"""
+
     def __init__(self):
         """Constructor"""
         super(MainWindow, self).__init__()
 
         # Load user interface from UI-file
 
-        loadUi('exm_stress_2d_qt.ui', self)
+        loadUi("exm_stress_2d_qt.ui", self)
 
         # Query for figure class name
 
@@ -253,7 +327,6 @@ def on_executeButton_clicked(self):
 
 
 if __name__ == "__main__":
-
     app = QApplication(sys.argv)
     widget = MainWindow()
     widget.show()
diff --git a/examples/exm_structured_mesh.py b/examples/exm_structured_mesh.py
index 88f21f2..e045363 100644
--- a/examples/exm_structured_mesh.py
+++ b/examples/exm_structured_mesh.py
@@ -1,9 +1,9 @@
 # -*- coding: utf-8 -*-
 
-'''Example 04.
+"""Example 04.
 
 Structured 3D meshing. Adding texts and labels to figures. Altering axis properties.
-'''
+"""
 
 import calfem.geometry as cfg
 import calfem.mesh as cfm
@@ -63,7 +63,7 @@
 # ---- Create mesh ----------------------------------------------------------
 
 # Element type 5 is hexahedron. (See user manual for more element types)
-el_type = 5         # error here, element type not implemented
+el_type = 5  # error here, element type not implemented
 
 # Degrees of freedom per node.
 dofs_per_node = 1
@@ -90,32 +90,33 @@
 # Draw mesh
 
 cfv.figure()
-cfv.draw_mesh(coords=coords, edof=edof,
-              dofs_per_node=dofs_per_node, el_type=el_type, filled=True)
+cfv.draw_mesh(
+    coords=coords, edof=edof, dofs_per_node=dofs_per_node, el_type=el_type, filled=True
+)
 
 # Add a text in world space
 
-#cfv.add_text("This is a Text", pos=(1, 0.5, 0.5), angle=45)
+# cfv.add_text("This is a Text", pos=(1, 0.5, 0.5), angle=45)
 
 # Add a label in the screen space
 
-#our_label = cfv.add_label("This is a Label", pos=(20,30), angle=-45)
+# our_label = cfv.add_label("This is a Label", pos=(20,30), angle=-45)
 
 # We can change the attributes of labels and texts, such as color and position.
 
-#our_label.text = "Label, changed."
+# our_label.text = "Label, changed."
 
 # Make it red. (1,0,0) would also have worked.
 
-#our_label.textColor = 'r'
+# our_label.textColor = 'r'
 
 # Matlab style axes (three axes in the background instead of a cube)
 
-#cfv.gca().axis.showBox = 0
+# cfv.gca().axis.showBox = 0
 
 # Change the limits of the axes.
 
-#cfv.gca().SetLimits(rangeX=(0,2), rangeY=(-1,1.5), rangeZ=(-0.5,2), margin=0.02)
+# cfv.gca().SetLimits(rangeX=(0,2), rangeY=(-1,1.5), rangeZ=(-0.5,2), margin=0.02)
 
 # Enter main loop
 
diff --git a/examples/exm_structured_mesh_3d.py b/examples/exm_structured_mesh_3d.py
index fbf94c0..2c99beb 100644
--- a/examples/exm_structured_mesh_3d.py
+++ b/examples/exm_structured_mesh_3d.py
@@ -1,9 +1,9 @@
 # -*- coding: utf-8 -*-
 
-'''Example 04.
+"""Example 04.
 
 Structured 3D meshing. Adding texts and labels to figures. Altering axis properties.
-''' 
+"""
 
 import calfem.geometry as cfg
 import calfem.mesh as cfm
@@ -19,27 +19,27 @@
 g.point([0.5, -0.3, -0.3], 1)
 g.point([1, 0, 0], 2)
 g.point([1, 1, 0], 3)
-g.point([0, 1, 0], 4, marker = 11) # Set some markers no reason.
-g.point([0, 0, 1], 5, marker = 11) # (markers can be given to points as well
-                                      # as curves and surfaces)
-g.point([1, 0, 1], 6, marker = 11)
+g.point([0, 1, 0], 4, marker=11)  # Set some markers no reason.
+g.point([0, 0, 1], 5, marker=11)  # (markers can be given to points as well
+# as curves and surfaces)
+g.point([1, 0, 1], 6, marker=11)
 g.point([1, 1, 1], 7)
 g.point([0, 1, 1], 8)
 
 # Add splines
 
-g.spline([0, 1, 2], 0, marker = 33, el_on_curve = 5)
-g.spline([2, 3], 1, marker = 23, el_on_curve = 5)
-g.spline([3, 4], 2, marker = 23, el_on_curve = 5)
-g.spline([4, 0], 3, el_on_curve = 5)
-g.spline([0, 5], 4, el_on_curve = 5)
-g.spline([2, 6], 5, el_on_curve = 5)
-g.spline([3, 7], 6, el_on_curve = 5)
-g.spline([4, 8], 7, el_on_curve = 5)
-g.spline([5, 6], 8, el_on_curve = 5)
-g.spline([6, 7], 9, el_on_curve = 5)
-g.spline([7, 8], 10, el_on_curve = 5)
-g.spline([8, 5], 11, el_on_curve = 5)
+g.spline([0, 1, 2], 0, marker=33, el_on_curve=5)
+g.spline([2, 3], 1, marker=23, el_on_curve=5)
+g.spline([3, 4], 2, marker=23, el_on_curve=5)
+g.spline([4, 0], 3, el_on_curve=5)
+g.spline([0, 5], 4, el_on_curve=5)
+g.spline([2, 6], 5, el_on_curve=5)
+g.spline([3, 7], 6, el_on_curve=5)
+g.spline([4, 8], 7, el_on_curve=5)
+g.spline([5, 6], 8, el_on_curve=5)
+g.spline([6, 7], 9, el_on_curve=5)
+g.spline([7, 8], 10, el_on_curve=5)
+g.spline([8, 5], 11, el_on_curve=5)
 
 # Add surfaces
 
@@ -51,32 +51,32 @@
 g.structuredSurface([3, 4, 11, 7], 5)
 
 # Add Volume:
-#  addStructuredVolume() takes three args. The first is a list of surface IDs 
-#  (structured surfaces). The surfaces should make a hexahedron 
+#  addStructuredVolume() takes three args. The first is a list of surface IDs
+#  (structured surfaces). The surfaces should make a hexahedron
 #  (i.e. 6 surfaces). Other kinds of structured volumes than hexahedra will
-#  not work for hexahedral elements, which is the only type of 3D element that 
-#  CALFEM handles. The two optional parameters are the volume ID and 
+#  not work for hexahedral elements, which is the only type of 3D element that
+#  CALFEM handles. The two optional parameters are the volume ID and
 #  volume marker.
 
-g.structuredVolume([0,1,2,3,4,5], 0, marker=90)
+g.structuredVolume([0, 1, 2, 3, 4, 5], 0, marker=90)
 
 # ---- Create mesh ----------------------------------------------------------
 
 # Element type 5 is hexahedron. (See user manual for more element types)
 
-el_type = 5 
+el_type = 5
 
 # Degrees of freedom per node.
 
-dofs_per_node = 1 
+dofs_per_node = 1
 
 # Create mesh
 
 coords, edof, dofs, bdofs, _ = cfm.mesh(g, el_type, 1, dofs_per_node)
 
-#coords, edof, dofs, bdofs, _ = cfm.mesh(
+# coords, edof, dofs, bdofs, _ = cfm.mesh(
 #        g, el_type, dofs_per_node, gmsh_exec_path="D:\\vsmn20-software\\gmsh\gmsh.exe")
 
 # ---- Visualise mesh -------------------------------------------------------
 
-cfv.draw_mesh(coords, edof, el_type)
\ No newline at end of file
+cfv.draw_mesh(coords, edof, el_type)
diff --git a/examples/exm_structured_mesh_vtk.py b/examples/exm_structured_mesh_vtk.py
index d5d89a8..84c9a1a 100644
--- a/examples/exm_structured_mesh_vtk.py
+++ b/examples/exm_structured_mesh_vtk.py
@@ -1,9 +1,9 @@
 # -*- coding: utf-8 -*-
 
-'''Example 03
+"""Example 03
 
 Shows structured meshing in 2D.
-'''
+"""
 
 import calfem.geometry as cfg
 import calfem.mesh as cfm
@@ -15,35 +15,37 @@
 
 # Add Points:
 
-g.point([0,0])
+g.point([0, 0])
 g.point([1.2, 0])
 g.point([1, 1.3])
 g.point([0, 1])
 g.point([2, 0.5])
 
 # Add Splines:
-# The first four curves are structured curves, i.e the number of nodes along 
-# the curves is pre-determined. Parameter el_on_curve states how many elements 
-# are placed along the curve. Parameters el_distrib_type and el_distrib_val are 
+# The first four curves are structured curves, i.e the number of nodes along
+# the curves is pre-determined. Parameter el_on_curve states how many elements
+# are placed along the curve. Parameters el_distrib_type and el_distrib_val are
 # optional parameters that specify how elements are distributed.
 #   "bump" means elements are bunched up at the ends or the middle of the curve.
 #       In this case el_distrib_val is smaller than 1, so elements crowd at the edges.
 #   "progression" means each element along the curve is larger/smaller than the previous one.
-#       A larger el_distrib_val makes the elements larger at the end of the curves. 
-
-g.spline([0,1], el_on_curve=10, el_distrib_type="bump", el_distrib_val=0.2)
-g.spline([1,2], el_on_curve=20, el_distrib_type="progression", el_distrib_val=1.1)
-g.spline([2,3], el_on_curve=10, el_distrib_type="bump", el_distrib_val=0.2)
-g.spline([0,3], el_on_curve=20, el_distrib_type="progression", el_distrib_val=1.1) #Change order of points to reverse progression distribution
+#       A larger el_distrib_val makes the elements larger at the end of the curves.
+
+g.spline([0, 1], el_on_curve=10, el_distrib_type="bump", el_distrib_val=0.2)
+g.spline([1, 2], el_on_curve=20, el_distrib_type="progression", el_distrib_val=1.1)
+g.spline([2, 3], el_on_curve=10, el_distrib_type="bump", el_distrib_val=0.2)
+g.spline(
+    [0, 3], el_on_curve=20, el_distrib_type="progression", el_distrib_val=1.1
+)  # Change order of points to reverse progression distribution
 g.spline([2, 4, 1])
 
 # Add Surfaces:
-#  A structured surface must contain 4 curves that have the parameter 'el_on_curve' 
-#  defined. The number of elements on two opposite curves must be the same 
+#  A structured surface must contain 4 curves that have the parameter 'el_on_curve'
+#  defined. The number of elements on two opposite curves must be the same
 #  (In this case, curves 0 & 2 and 1 & 3).
 
-g.structuredSurface([0,1,2,3]) 
-g.surface([4,1])
+g.structuredSurface([0, 1, 2, 3])
+g.surface([4, 1])
 
 # ---- Create mesh ----------------------------------------------------------
 
@@ -51,11 +53,11 @@
 
 # Element type 3 is quad. (2 is triangle. See user manual for more element types)
 
-mesh.el_type = 3 
+mesh.el_type = 3
 
 # Degrees of freedom per node.
 
-mesh.dofs_per_node = 1 
+mesh.dofs_per_node = 1
 mesh.el_size_factor = 0.01
 
 # mesh.gmsh_exec_path = "D:\\vsmn20-software\\gmsh\gmsh.exe"
@@ -71,8 +73,10 @@
 # Draw mesh
 
 cfv.figure()
-cfv.draw_mesh(coords, edof, dofs_per_node=mesh.dofs_per_node, el_type=mesh.el_type, filled=True)
+cfv.draw_mesh(
+    coords, edof, dofs_per_node=mesh.dofs_per_node, el_type=mesh.el_type, filled=True
+)
 
 # Enter main loop
 
-cfv.show_and_wait()
\ No newline at end of file
+cfv.show_and_wait()
diff --git a/examples/exm_temp_2d_markers.py b/examples/exm_temp_2d_markers.py
index a0138f9..a662274 100644
--- a/examples/exm_temp_2d_markers.py
+++ b/examples/exm_temp_2d_markers.py
@@ -1,11 +1,11 @@
 # -*- coding: utf-8 -*-
 
-'''Example 07
+"""Example 07
 
 Meshing 8-node-isoparametric elements (second order incomplete quads).
 Shows use of surfacemarkers/elementmarkers to apply different properties to 
 elements in different regions. 
-'''
+"""
 
 import calfem.geometry as cfg
 import calfem.mesh as cfm
@@ -32,14 +32,8 @@
 n = 2
 ep = [t, n]
 
-D1 = np.matrix([
-    [kx1, 0.],
-    [0., ky1]
-])
-D2 = np.matrix([
-    [kx2, 0.],
-    [0., ky2]
-])
+D1 = np.matrix([[kx1, 0.0], [0.0, ky1]])
+D2 = np.matrix([[kx2, 0.0], [0.0, ky2]])
 
 # markers 10 & 11 will be used to specify different regions with different
 # conductivity.
@@ -52,15 +46,7 @@
 
 # Add Points:
 
-points = [
-    [0, 0],
-    [0, 100],
-    [0, 150],
-    [100, 0],
-    [150, 0],
-    [100, -100],
-    [150, -100]
-]
+points = [[0, 0], [0, 100], [0, 150], [100, 0], [150, 0], [100, -100], [150, -100]]
 
 for p in points:
     g.point(p)
@@ -112,7 +98,6 @@
 K = np.zeros([n_dofs, n_dofs])
 
 for eltopo, elx, ely, elMarker in zip(edof, ex, ey, elementmarkers):
-
     # Calc element stiffness matrix: Conductivity matrix D is taken
     # from Ddict and depends on which region (which marker) the element is in.
 
@@ -123,8 +108,8 @@
 
 f = np.zeros([n_dofs, 1])
 
-bc = np.array([], 'i')
-bc_val = np.array([], 'i')
+bc = np.array([], "i")
+bc_val = np.array([], "i")
 
 bc, bc_val = cfu.applybc(bdofs, bc, bc_val, 2, 30.0)
 bc, bc_val = cfu.applybc(bdofs, bc, bc_val, 3, 0.0)
@@ -139,7 +124,8 @@
 
 for i in range(np.shape(ex)[0]):
     es, et, eci = cfc.flw2i8s(
-        ex[i, :], ey[i, :], ep, Ddict[elementmarkers[i]], ed[i, :])
+        ex[i, :], ey[i, :], ep, Ddict[elementmarkers[i]], ed[i, :]
+    )
 
     # Do something with es, et, eci here.
 
@@ -147,18 +133,24 @@
 
 print("Visualising...")
 
-cfv.set_figure_dpi(100)
-cfv.figure(fig_size=(10, 10))
+cfv.figure()
 cfv.draw_geometry(g, title="Geometry")
 
 # 8-node quads are drawn as simple quads.
 
-cfv.figure(fig_size=(10, 10))
+cfv.figure()
 cfv.draw_mesh(coords, edof, dofs_per_node, el_type, filled=False)
 
-cfv.figure(fig_size=(10, 10))
-cfv.draw_nodal_values_shaded(a, coords, edof, title="Temperature",
-                             dofs_per_node=mesh.dofs_per_node, el_type=mesh.el_type, draw_elements=True)
+cfv.figure()
+cfv.draw_nodal_values_shaded(
+    a,
+    coords,
+    edof,
+    title="Temperature",
+    dofs_per_node=mesh.dofs_per_node,
+    el_type=mesh.el_type,
+    draw_elements=True,
+)
 cbar = cfv.colorbar(orientation="vertical")
 cbar.set_label("Temperature")
 
diff --git a/examples/exm_temp_2d_splines_arcs.py b/examples/exm_temp_2d_splines_arcs.py
index 97f6c9e..638c73a 100644
--- a/examples/exm_temp_2d_splines_arcs.py
+++ b/examples/exm_temp_2d_splines_arcs.py
@@ -1,10 +1,10 @@
 # -*- coding: utf-8 -*-
 
-'''Example 01
+"""Example 01
 
 Shows how to create simple geometry from splines and ellipse arcs, and how to mesh a quad mesh in GmshMesher.
 Also demonstrates drawGeometry(), drawMesh, and drawing texts and labels in a figure.
-'''
+"""
 
 import numpy as np
 
@@ -27,10 +27,7 @@
 n = 2
 ep = [t, n]
 
-D = np.matrix([
-    [kx1, 0.],
-    [0., ky1]
-])
+D = np.matrix([[kx1, 0.0], [0.0, ky1]])
 
 # ---- Define geometry ------------------------------------------------------
 
@@ -85,7 +82,6 @@
 K = np.zeros([n_dofs, n_dofs])
 
 for el_topo, elx, ely, marker in zip(edof, ex, ey, element_markers):
-
     # Calc element stiffness matrix: Conductivity matrix D is taken
     # from Ddict and depends on which region (which marker) the element is in.
 
@@ -104,8 +100,8 @@
 
 f = np.zeros([n_dofs, 1])
 
-bc = np.array([], 'i')
-bc_val = np.array([], 'f')
+bc = np.array([], "i")
+bc_val = np.array([], "f")
 
 bc, bc_val = cfu.applybc(bdofs, bc, bc_val, id_outer, 30.0)
 bc, bc_val = cfu.applybc(bdofs, bc, bc_val, id_hole1, 300.0)
@@ -139,21 +135,19 @@
 # Draw the geometry. Note that surfaces and volumes are not drawn at all by
 # this function.
 
-cfv.draw_geometry(g)
-
-# New figure window
-
 cfv.figure()
+cfv.draw_geometry(g)
 
 # Draw the mesh.
 
+cfv.figure()
 cfv.draw_mesh(
     coords=coords,
     edof=edof,
     dofs_per_node=mesh.dofs_per_node,
     el_type=mesh.el_type,
     filled=True,
-    title="Example 01"
+    title="Example 01",
 )
 
 cfv.figure()
@@ -161,7 +155,15 @@
 cfv.colorbar()
 
 cfv.figure()
-cfv.draw_nodal_values_contourf(a, coords, edof, title="Temperature", dofs_per_node=mesh.dofs_per_node, el_type=mesh.el_type, draw_elements=True)
+cfv.draw_nodal_values_contourf(
+    a,
+    coords,
+    edof,
+    title="Temperature",
+    dofs_per_node=mesh.dofs_per_node,
+    el_type=mesh.el_type,
+    draw_elements=True,
+)
 cfv.colorbar()
 
 cfv.figure()
@@ -173,7 +175,7 @@
 # ourLabel = cfv.label("This is a Label", pos=(100,200), angle=-45) #Adds a label in the screen space
 # ourLabel.text = "Label, changed." #We can change the attributes of labels and texts, such as color, text, and position.
 # ourLabel.textColor = 'r'  #Make it red. (1,0,0) would also have worked.
-#ourLabel.position = (20,30)
+# ourLabel.position = (20,30)
 
 # Enter main loop:
 
diff --git a/examples/exm_tet_mesh.py b/examples/exm_tet_mesh.py
index 464fc8a..a45888a 100644
--- a/examples/exm_tet_mesh.py
+++ b/examples/exm_tet_mesh.py
@@ -1,10 +1,10 @@
 # -*- coding: utf-8 -*-
 
-'''Example 05
+"""Example 05
 
 This example shows how to make an unstructured 3D mesh (tetrahedron elements, which calfem cant actually use).
 It also demonstrates how to do subplots and create two axes that are viewed from the same camera.
-''' 
+"""
 
 import calfem.geometry as cfg
 import calfem.mesh as cfm
@@ -14,27 +14,27 @@
 
 g = cfg.geometry()
 
-g.point([0, 0, 0],      0)
-g.point([1, 0, 0],      1)
-g.point([0, 1, 0],      2)
-g.point([0, 1, 1],      3, el_size=0.1)
+g.point([0, 0, 0], 0)
+g.point([1, 0, 0], 1)
+g.point([0, 1, 0], 2)
+g.point([0, 1, 1], 3, el_size=0.1)
 g.point([0.5, -0.3, 0], 4)
 g.point([-0.3, 0.5, 0], 5)
-g.point([0.75, 0.75, 0],6)
+g.point([0.75, 0.75, 0], 6)
 
-g.spline([0,4,1])
-g.spline([1,6,2])
-g.spline([2,5,0])
-g.spline([0,3])
-g.spline([3,2])
-g.spline([3,1])
+g.spline([0, 4, 1])
+g.spline([1, 6, 2])
+g.spline([2, 5, 0])
+g.spline([0, 3])
+g.spline([3, 2])
+g.spline([3, 1])
 
-g.ruledSurface([0,1,2])
-g.ruledSurface([0,5,3])
-g.ruledSurface([1,5,4])
-g.ruledSurface([2,3,4])
+g.ruledSurface([0, 1, 2])
+g.ruledSurface([0, 5, 3])
+g.ruledSurface([1, 5, 4])
+g.ruledSurface([2, 3, 4])
 
-g.volume([0,1,2,3])
+g.volume([0, 1, 2, 3])
 
 # ---- Create mesh ----------------------------------------------------------
 
@@ -44,13 +44,13 @@
 
 # Degrees of freedom per node.
 
-dofs_per_node = 1 
+dofs_per_node = 1
 
 # Create mesh
 
 coords, edof, dofs, bdofs, elementmarkers = cfm.mesh(g, el_type, 0.3, dofs_per_node)
 
-#coords, edof, dofs, bdofs, _ = cfm.mesh(
+# coords, edof, dofs, bdofs, _ = cfm.mesh(
 #        g, el_type, 0.3, dofs_per_node, gmsh_exec_path="D:\\vsmn20-software\\gmsh\gmsh.exe")
 
 
@@ -67,8 +67,15 @@
 # Draw geometry and mesh
 
 cfv.draw_geometry(g, axes=a1)
-cfv.draw_mesh(coords=coords, edof=edof, dofs_per_node=dofs_per_node, el_type=el_type, filled=False, axes=a2)
+cfv.draw_mesh(
+    coords=coords,
+    edof=edof,
+    dofs_per_node=dofs_per_node,
+    el_type=el_type,
+    filled=False,
+    axes=a2,
+)
 
 # Enter main loop
 
-cfv.show_and_wait()
\ No newline at end of file
+cfv.show_and_wait()
diff --git a/examples/exm_tet_mesh_vtk.py b/examples/exm_tet_mesh_vtk.py
index 2378b69..f158f55 100644
--- a/examples/exm_tet_mesh_vtk.py
+++ b/examples/exm_tet_mesh_vtk.py
@@ -1,10 +1,10 @@
 # -*- coding: utf-8 -*-
 
-'''Example 05
+"""Example 05
 
 This example shows how to make an unstructured 3D mesh (tetrahedron elements, which calfem cant actually use).
 It also demonstrates how to do subplots and create two axes that are viewed from the same camera.
-''' 
+"""
 
 import calfem.geometry as cfg
 import calfem.mesh as cfm
@@ -16,27 +16,27 @@
 
 g = cfg.geometry()
 
-g.point([0, 0, 0],      0)
-g.point([1, 0, 0],      1)
-g.point([0, 1, 0],      2)
-g.point([0, 1, 1],      3, el_size=0.1)
+g.point([0, 0, 0], 0)
+g.point([1, 0, 0], 1)
+g.point([0, 1, 0], 2)
+g.point([0, 1, 1], 3, el_size=0.1)
 g.point([0.5, -0.3, 0], 4)
 g.point([-0.3, 0.5, 0], 5)
-g.point([0.75, 0.75, 0],6)
+g.point([0.75, 0.75, 0], 6)
 
-g.spline([0,4,1])
-g.spline([1,6,2])
-g.spline([2,5,0])
-g.spline([0,3])
-g.spline([3,2])
-g.spline([3,1])
+g.spline([0, 4, 1])
+g.spline([1, 6, 2])
+g.spline([2, 5, 0])
+g.spline([0, 3])
+g.spline([3, 2])
+g.spline([3, 1])
 
-g.ruled_surface([0,1,2])
-g.ruled_surface([0,5,3])
-g.ruled_surface([1,5,4])
-g.ruled_surface([2,3,4])
+g.ruled_surface([0, 1, 2])
+g.ruled_surface([0, 5, 3])
+g.ruled_surface([1, 5, 4])
+g.ruled_surface([2, 3, 4])
 
-g.volume([0,1,2,3])
+g.volume([0, 1, 2, 3])
 
 # ---- Create mesh ----------------------------------------------------------
 
@@ -46,16 +46,16 @@
 
 # Degrees of freedom per node.
 
-dofs_per_node = 1 
+dofs_per_node = 1
 
 # Create mesh
 
 coords, edof, dofs, bdofs, elementmarkers = cfm.mesh(g, el_type, 0.3, dofs_per_node)
 
-#coords, edof, dofs, bdofs, _ = cfm.mesh(
+# coords, edof, dofs, bdofs, _ = cfm.mesh(
 #        g, el_type, 0.3, dofs_per_node, gmsh_exec_path="D:\\vsmn20-software\\gmsh\gmsh.exe")
 
 
 # ---- Visualise mesh -------------------------------------------------------
 
-cfv.draw_mesh(coords, edof, el_type)
\ No newline at end of file
+cfv.draw_mesh(coords, edof, el_type)
diff --git a/examples/exm_tutorial_1.py b/examples/exm_tutorial_1.py
new file mode 100644
index 0000000..bc0b095
--- /dev/null
+++ b/examples/exm_tutorial_1.py
@@ -0,0 +1,53 @@
+# -*- coding: utf-8 -*-
+"""
+Created on Sat Mar  3 22:08:29 2018
+
+@author: Jonas Lindemann
+"""
+
+import calfem.geometry as cfg
+import calfem.mesh as cfm
+import calfem.vis_mpl as cfv
+
+# ----- Define geometry
+
+g = cfg.Geometry()
+
+g.point([0.0, 0.0])  # point 0
+g.point([5.0, 0.0], marker=20)  # point 1
+g.point([2.5, 4.0])  # point 2
+
+g.spline([0, 1])  # line 0
+g.spline([1, 2])  # line 1
+g.spline([2, 0], marker=10)  # line 2
+
+g.surface([0, 1, 2])
+
+# ----- Create mesh
+
+mesh = cfm.GmshMesh(g)
+
+mesh.elType = 2  # Degrees of freedom per node.
+mesh.dofsPerNode = 1  # Factor that changes element sizes.
+mesh.elSizeFactor = 0.15
+
+coords, edof, dofs, bdofs, elementmarkers = mesh.create()
+
+print(bdofs)
+
+cfv.figure()
+cfv.draw_geometry(g)
+
+# ----- Draw the mesh.
+
+cfv.figure()
+cfv.draw_mesh(
+    coords=coords,
+    edof=edof,
+    dofs_per_node=mesh.dofsPerNode,
+    el_type=mesh.elType,
+    filled=True,
+    title="Example 01",
+)
+
+cfv.showAndWait()
diff --git a/examples/exm_tutorial_2.py b/examples/exm_tutorial_2.py
new file mode 100644
index 0000000..f820e4e
--- /dev/null
+++ b/examples/exm_tutorial_2.py
@@ -0,0 +1,133 @@
+# -*- coding: utf-8 -*-
+"""
+Created on Sat Mar  3 22:08:29 2018
+
+@author: Jonas Lindemann
+"""
+
+import calfem.core as cfc
+import calfem.geometry as cfg
+import calfem.mesh as cfm
+import calfem.vis_mpl as cfv
+import calfem.utils as cfu
+
+import numpy as np
+from math import *
+
+# ----- Problem parameters
+
+l = 5.0
+h = 1.0
+t = 0.2
+
+v = 0.35
+E = 2.1e9
+ptype = 1
+ep = [ptype, t]
+D = cfc.hooke(ptype, E, v)
+
+left_support = 10
+right_support = 20
+top_line = 30
+
+# ----- Define geometry
+
+g = cfg.Geometry()
+
+g.point([0.0, 0.0], marker=left_support)  # point 0
+g.point([l, 0.0], marker=right_support)  # point 1
+g.point([l, h])  # point 2
+g.point([0.0, h])  # point 2
+
+g.spline([0, 1])  # line 0
+g.spline([1, 2])  # line 1
+g.spline([2, 3], marker=top_line)  # line 2
+g.spline([3, 0])  # line 2
+
+g.surface([0, 1, 2, 3])
+
+# ----- Create mesh
+
+mesh = cfm.GmshMesh(g)
+
+mesh.elType = 3  # Degrees of freedom per node.
+mesh.dofsPerNode = 2  # Factor that changes element sizes.
+mesh.elSizeFactor = 0.10
+
+coords, edof, dofs, bdofs, elementmarkers = mesh.create()
+
+# ----- Solve problem
+
+nDofs = np.size(dofs)
+ex, ey = cfc.coordxtr(edof, coords, dofs)
+
+K = np.zeros([nDofs, nDofs])
+
+for eltopo, elx, ely in zip(edof, ex, ey):
+    Ke = cfc.planqe(elx, ely, ep, D)
+    cfc.assem(eltopo, K, Ke)
+
+bc = np.array([], "i")
+bcVal = np.array([], "f")
+
+bc, bcVal = cfu.applybc(bdofs, bc, bcVal, left_support, 0.0, 0)
+bc, bcVal = cfu.applybc(bdofs, bc, bcVal, right_support, 0.0, 2)
+
+f = np.zeros([nDofs, 1])
+
+cfu.applyforcetotal(bdofs, f, top_line, -10e5, 2)
+
+a, r = cfc.solveq(K, f, bc, bcVal)
+
+ed = cfc.extractEldisp(edof, a)
+vonMises = []
+
+for i in range(edof.shape[0]):
+    es, et = cfc.planqs(ex[i, :], ey[i, :], ep, D, ed[i, :])
+    vonMises.append(sqrt(pow(es[0], 2) - es[0] * es[1] + pow(es[1], 2) + 3 * es[2]))
+
+# ----- Draw geometry
+
+cfv.figure()
+cfv.draw_geometry(g)
+
+# ----- Draw the mesh.
+
+cfv.figure()
+cfv.draw_mesh(
+    coords=coords,
+    edof=edof,
+    dofs_per_node=mesh.dofsPerNode,
+    el_type=mesh.elType,
+    filled=True,
+    title="Example 01",
+)
+
+# ----- Draw results
+
+cfv.figure()
+cfv.draw_element_values(
+    vonMises,
+    coords,
+    edof,
+    mesh.dofs_per_node,
+    mesh.el_type,
+    a,
+    draw_elements=True,
+    draw_undisplaced_mesh=False,
+    title="Example 06 effective stress",
+)
+
+cfv.figure()
+cfv.draw_displacements(
+    a,
+    coords,
+    edof,
+    mesh.dofs_per_node,
+    mesh.el_type,
+    draw_undisplaced_mesh=True,
+    title="Example 06",
+    magnfac=10.0,
+)
+
+cfv.showAndWait()
diff --git a/examples/exn_bar2g.py b/examples/exn_bar2g.py
index 629250e..b319189 100644
--- a/examples/exn_bar2g.py
+++ b/examples/exn_bar2g.py
@@ -1,67 +1,69 @@
 # example exn_bar2g
-#--------------------------------------------------------------------------
+# --------------------------------------------------------------------------
 # PURPOSE
 #    Analysis of a plane truss using second order theory.
-#--------------------------------------------------------------------------
+# --------------------------------------------------------------------------
 
 import numpy as np
 import calfem.core as cfc
+import calfem.utils as cfu
 
 # ----- Topology -----
 
-edof = np.array([[1, 2, 5, 6],
-                 [3, 4, 5, 6]])
+edof = np.array([[1, 2, 5, 6], [3, 4, 5, 6]])
 
 # ----- Element properties and global coordinates -------------------------
 
-E=10e9
-A1=4e-2
-A2=1e-2
-ep1=np.array([E, A1])
-ep2=np.array([E, A2])
+E = 10e9
+A1 = 4e-2
+A2 = 1e-2
+ep1 = np.array([E, A1])
+ep2 = np.array([E, A2])
 
-ex1=np.array([0., 1.6])
-ey1=np.array([0., 0.])
-ex2=np.array([0., 1.6])
-ey2=np.array([1.2, 0])
+ex1 = np.array([0.0, 1.6])
+ey1 = np.array([0.0, 0.0])
+ex2 = np.array([0.0, 1.6])
+ey2 = np.array([1.2, 0])
 
 # ----- Initial values for the iteration ----------------------------------
 
-eps=1e-6           # Error norm
-QX1=0.01
-QX2=0;              # Initial axial forces
-QX01=1              # Axial force of the initial former iteration
-n=0                 # Iteration counter
+eps = 1e-6  # Error norm
+QX1 = 0.01
+QX2 = 0
+# Initial axial forces
+QX01 = 1  # Axial force of the initial former iteration
+n = 0  # Iteration counter
 
 # ----- Iteration procedure -----------------------------------------------
-while abs((QX1-QX01)/QX01) > eps:
+while abs((QX1 - QX01) / QX01) > eps:
     n += 1
 
-    K = np.zeros((6,6))
-    f = np.zeros((6,1))
+    K = np.zeros((6, 6))
+    f = np.zeros((6, 1))
     f[4] = -10e6
     f[5] = -0.2e6
 
-    Ke1 = cfc.bar2ge(ex1,ey1,ep1,QX1)
-    Ke2 = cfc.bar2ge(ex2,ey2,ep2,QX2)
-    K = cfc.assem(edof[0,:],K,Ke1)
-    K=cfc.assem(edof[1,:],K,Ke2)
-    bc = np.array([1,2,3,4])
-    a, r = cfc.solveq(K,f,bc)
+    Ke1 = cfc.bar2ge(ex1, ey1, ep1, QX1)
+    Ke2 = cfc.bar2ge(ex2, ey2, ep2, QX2)
+    K = cfc.assem(edof[0, :], K, Ke1)
+    K = cfc.assem(edof[1, :], K, Ke2)
+    bc = np.array([1, 2, 3, 4])
+    a, r = cfc.solveq(K, f, bc)
 
-    Ed = cfc.extract_ed(edof,a)
+    Ed = cfc.extract_ed(edof, a)
 
     QX01 = QX1
-    es1, QX1 = cfc.bar2gs(ex1,ey1,ep1,Ed[0,:])
-    es2, QX2 = cfc.bar2gs(ex2,ey2,ep2,Ed[1,:])
+    es1, QX1 = cfc.bar2gs(ex1, ey1, ep1, Ed[0, :])
+    es2, QX2 = cfc.bar2gs(ex2, ey2, ep2, Ed[1, :])
 
-    if n>20:
+    if n > 20:
         print("The solution does not converge")
         break
 
 # ----- Results -----------------------------------------------
-print("Displacements:")
-print(a)
-print("Normal forces:")
-print(QX1)
-print(QX2)
\ No newline at end of file
+
+cfu.disp_h1("Displacements:")
+cfu.disp_array(a)
+cfu.disp_h1("Normal forces:")
+cfu.disp(QX1)
+cfu.disp(QX2)
diff --git a/examples/exn_bar2m.py b/examples/exn_bar2m.py
index f9a5082..10510e4 100644
--- a/examples/exn_bar2m.py
+++ b/examples/exn_bar2m.py
@@ -1,101 +1,108 @@
 # example exn_bar2m
-#--------------------------------------------------------------------------
+# --------------------------------------------------------------------------
 # PURPOSE
 #    Analysis of a plane truss considering material nonlinearity.
-#--------------------------------------------------------------------------
+# --------------------------------------------------------------------------
 
 import numpy as np
 import calfem.core as cfc
+import calfem.utils as cfu
 import calfem.vis_mpl as cfv
 
 edof = np.array([
-    [1, 2, 5, 6],
-    [5, 6, 7, 8],
+    [1, 2, 5, 6], 
+    [5, 6, 7, 8], 
     [3, 4, 5, 6]
 ])
 
 bc = np.array([1, 2, 3, 4, 7, 8])
 
 ex = np.array([
-    [0., 1.6],
-    [1.6, 1.6],
-    [0., 1.6]
+    [0.0, 1.6], 
+    [1.6, 1.6], 
+    [0.0, 1.6]
 ])
 
-ey = np.array([
-    [0., 0.],
-    [0., 1.2],
-    [1.2, 0.]
-])
+ey = np.array([[0.0, 0.0], [0.0, 1.2], [1.2, 0.0]])
 
 E = np.array([200e9, 200e9, 200e9])
 A = np.array([6.0e-4, 3.0e-4, 10.0e-4])
 SY = 400e6
-Ns = (SY*A).reshape(-1,1)
+Ns = (SY * A).reshape(-1, 1)
 
 dp = 4e3
 
 incr = 100
 
-a = np.zeros((8,1))
-r = np.zeros((8,1))
-es = np.zeros((3,1))
+a = np.zeros((8, 1))
+r = np.zeros((8, 1))
+es = np.zeros((3, 1))
 
 plbar = 0
-pl = np.array([0., 0.])
+pl = np.array([0.0, 0.0])
 
 # Forward Euler increamental solution
 
 for i in range(incr):
-    K = np.zeros((8,8))
-    df = np.zeros((8,1))
+    K = np.zeros((8, 8))
+    df = np.zeros((8, 1))
     df[5] = -dp
 
     # Create and assemble element tangent stiffness matrix
+
     for j in range(3):
         ep = np.array([E[j], A[j]])
-        Ke = cfc.bar2e(ex[j,:],ey[j,:],ep)
-        K = cfc.assem(edof[j,:], K, Ke)
+        Ke = cfc.bar2e(ex[j, :], ey[j, :], ep)
+        K = cfc.assem(edof[j, :], K, Ke)
 
     # Stop iteration if determinant det(Kr) <= 0
-    fdof = np.setdiff1d(np.arange(1,9),bc) - 1
-    Kr = K[np.ix_(fdof,fdof)]
+
+    fdof = np.setdiff1d(np.arange(1, 9), bc) - 1
+    Kr = K[np.ix_(fdof, fdof)]
     if np.linalg.det(Kr) <= 0:
         print("Determinant zero after increment ", i)
         break
 
     # Solve for the displacement increment and determine total displacements
-    da, dr = cfc.solveq(K,df,bc)
+
+    da, dr = cfc.solveq(K, df, bc)
     a += da
     r += dr
 
     # Determine normal forces in elements
-    ded = cfc.extract_ed(edof,da)
-    des = np.zeros((3,1))
+
+    ded = cfc.extract_ed(edof, da)
+    des = np.zeros((3, 1))
+
     for j in range(3):
         ep = np.array([E[j], A[j]])
-        desj = cfc.bar2s(ex[j,:],ey[j,:],ep,ded[j,:])
-        print('---')
-        print(desj)
-        print('---')
-        des[j,0] = desj[0]
+        desj = cfc.bar2s(ex[j, :], ey[j, :], ep, ded[j, :])
+        des[j, 0] = desj[0]
+
     es += des
+
     for j in range(3):
-        if abs(es[j,0]) >= Ns[j]:
+        if abs(es[j, 0]) >= Ns[j]:
             E[j] = 0
 
     # Determine if the stress in a bar has reached the yield stress
-    newplbar = np.sum(abs(es)>Ns)
+
+    newplbar = np.sum(abs(es) > Ns)
+
     if newplbar > plbar:
         plbar = newplbar
-        print(plbar, "plastic elements for increment ", i+1, " at load = ", (i+1)*dp)
+        print(
+            plbar, "plastic elements for increment ", i + 1, " at load = ", (i + 1) * dp
+        )
 
     # Save variables for curve plotting
-    pl = np.vstack((pl, np.array([-a[5,0], (i+1)*dp])))
+
+    pl = np.vstack((pl, np.array([-a[5, 0], (i + 1) * dp])))
 
 # Plot force-displacement relation
-cfv.figure(1, fig_size=(7,4))
-cfv.plt.plot(pl[:,0],pl[:,1])
+
+cfv.figure(1, fig_size=(7, 4))
+cfv.plt.plot(pl[:, 0], pl[:, 1])
 cfv.plt.xlabel("Displacement")
 cfv.plt.ylabel("Force")
-cfv.showAndWait()
\ No newline at end of file
+cfv.show_and_wait()
diff --git a/examples/exn_beam2.py b/examples/exn_beam2.py
index 6650870..bad147f 100644
--- a/examples/exn_beam2.py
+++ b/examples/exn_beam2.py
@@ -9,34 +9,34 @@
 import calfem.vis_mpl as cfv
 
 
-#----- Topology -------------------------------------------------
+# ----- Topology -------------------------------------------------
 
 edof = np.array([
-    [4, 5, 6, 1, 2, 3],
-    [7, 8, 9, 10, 11, 12],
+    [4, 5, 6, 1, 2, 3], 
+    [7, 8, 9, 10, 11, 12], 
     [4, 5, 6, 7, 8, 9]
 ])
 
-#----- Element stiffness and element load matrices  -------------
+# ----- Element stiffness and element load matrices  -------------
 
-E=200e9
-A1=2e-3
-A2=6e-3
-I1=1.6e-5
-I2=5.4e-5
+E = 200e9
+A1 = 2e-3
+A2 = 6e-3
+I1 = 1.6e-5
+I2 = 5.4e-5
 
 ep1 = np.array([E, A1, I1])
 ep3 = np.array([E, A2, I2])
 
-ex1 = np.array([0.,0.])
-ey1 = np.array([4.,0.])
-ex2 = np.array([6.,6.])
-ey2 = np.array([4.,0.])
-ex3 = np.array([0.,6.])
-ey3 = np.array([4.,4.])
+ex1 = np.array([0.0, 0.0])
+ey1 = np.array([4.0, 0.0])
+ex2 = np.array([6.0, 6.0])
+ey2 = np.array([4.0, 0.0])
+ex3 = np.array([0.0, 6.0])
+ey3 = np.array([4.0, 4.0])
 
-eq1 = np.array([0.])
-eq2 = np.array([0.])
+eq1 = np.array([0.0])
+eq2 = np.array([0.0])
 eq3 = np.array([-50e3])
 
 # ----- Initial axial forces ----------------------------------------------
@@ -49,100 +49,101 @@
 # ----- Iteration for convergence -----------------------------------------
 
 eps = 1e-6
-n=0
+n = 0
 
-while abs((QX1-QX01)/QX01) > eps:
+while abs((QX1 - QX01) / QX01) > eps:
     n += 1
-    K = np.zeros([12,12])
-    f = np.zeros([12,1])
-    f[3,0] = 10e3
+    K = np.zeros([12, 12])
+    f = np.zeros([12, 1])
+    f[3, 0] = 10e3
 
-    Ke1 = cfc.beam2ge(ex1,ey1,ep1,QX1)
-    Ke2 = cfc.beam2ge(ex2,ey2,ep1,QX2)
-    Ke3, fe3 = cfc.beam2ge(ex3,ey3,ep3,QX3,eq3)
+    Ke1 = cfc.beam2ge(ex1, ey1, ep1, QX1)
+    Ke2 = cfc.beam2ge(ex2, ey2, ep1, QX2)
+    Ke3, fe3 = cfc.beam2ge(ex3, ey3, ep3, QX3, eq3)
 
-    K = cfc.assem(edof[0,:],K,Ke1)
-    K = cfc.assem(edof[1,:],K,Ke2)
-    K, f = cfc.assem(edof[2,:],K,Ke3,f,fe3)
+    K = cfc.assem(edof[0, :], K, Ke1)
+    K = cfc.assem(edof[1, :], K, Ke2)
+    K, f = cfc.assem(edof[2, :], K, Ke3, f, fe3)
 
     bc = np.array([1, 2, 3, 10, 11])
     a, r = cfc.solveq(K, f, bc)
 
-    ed = cfc.extract_ed(edof,a)
+    ed = cfc.extract_ed(edof, a)
 
-    QX01=QX1
-    es1 = cfc.beam2gs(ex1,ey1,ep1,ed[0,:],QX1,eq1)
-    es2 = cfc.beam2gs(ex2,ey2,ep1,ed[1,:],QX2,eq2)
-    es3 = cfc.beam2gs(ex3,ey3,ep3,ed[2,:],QX3,eq3)
+    QX01 = QX1
+    es1 = cfc.beam2gs(ex1, ey1, ep1, ed[0, :], QX1, eq1)
+    es2 = cfc.beam2gs(ex2, ey2, ep1, ed[1, :], QX2, eq2)
+    es3 = cfc.beam2gs(ex3, ey3, ep3, ed[2, :], QX3, eq3)
     QX1 = es1[1]
     QX2 = es2[1]
     QX3 = es3[1]
 
-    if n==1:
+    if n == 1:
         ed0 = ed
 
-    if n>20:
+    if n > 20:
         print("The solution does not converge")
         break
 
 
-# #----- Section forces ---------------------------------------
-
-eq1 = np.array([0.,eq1.item()])
-eq2 = np.array([0.,eq2.item()])
-eq3 = np.array([0.,eq3.item()])
-es1, edi1, eci1 = cfc.beam2s(ex1,ey1,ep1,ed[0,:],eq1,21)
-es2, edi2, eci2 = cfc.beam2s(ex2,ey2,ep1,ed[1,:],eq2,21)
-es3, edi3, eci3 = cfc.beam2s(ex3,ey3,ep3,ed[2,:],eq3,21)
-
-
-#----- Draw deformed frame ---------------------------------------
-cfv.figure(1,fig_size=(6,4))
-plotpar=[3,1,0]
-cfv.eldraw2(ex1,ey1,plotpar)
-cfv.eldraw2(ex2,ey2,plotpar)
-cfv.eldraw2(ex3,ey3,plotpar)
-sfac=cfv.scalfact2(ex3,ey3,edi3,0.1)
-plotpar=[1,2,1]
-cfv.eldisp2(ex1,ey1,ed[0,:],plotpar,sfac)
-cfv.eldisp2(ex2,ey2,ed[1,:],plotpar,sfac)
-cfv.eldisp2(ex3,ey3,ed[2,:],plotpar,sfac)
-plotpar=[2,4,2]
-cfv.eldisp2(ex1,ey1,ed0[0,:],plotpar,sfac)
-cfv.eldisp2(ex2,ey2,ed0[1,:],plotpar,sfac)
-cfv.eldisp2(ex3,ey3,ed0[2,:],plotpar,sfac)
+# ----- Section forces ---------------------------------------
+
+eq1 = np.array([0.0, eq1.item()])
+eq2 = np.array([0.0, eq2.item()])
+eq3 = np.array([0.0, eq3.item()])
+es1, edi1, eci1 = cfc.beam2s(ex1, ey1, ep1, ed[0, :], eq1, 21)
+es2, edi2, eci2 = cfc.beam2s(ex2, ey2, ep1, ed[1, :], eq2, 21)
+es3, edi3, eci3 = cfc.beam2s(ex3, ey3, ep3, ed[2, :], eq3, 21)
+
+
+# ----- Draw deformed frame ---------------------------------------
+
+cfv.figure(1, fig_size=(6, 4))
+plotpar = [3, 1, 0]
+cfv.eldraw2(ex1, ey1, plotpar)
+cfv.eldraw2(ex2, ey2, plotpar)
+cfv.eldraw2(ex3, ey3, plotpar)
+sfac = cfv.scalfact2(ex3, ey3, edi3, 0.1)
+plotpar = [1, 2, 1]
+cfv.eldisp2(ex1, ey1, ed[0, :], plotpar, sfac)
+cfv.eldisp2(ex2, ey2, ed[1, :], plotpar, sfac)
+cfv.eldisp2(ex3, ey3, ed[2, :], plotpar, sfac)
+plotpar = [2, 4, 2]
+cfv.eldisp2(ex1, ey1, ed0[0, :], plotpar, sfac)
+cfv.eldisp2(ex2, ey2, ed0[1, :], plotpar, sfac)
+cfv.eldisp2(ex3, ey3, ed0[2, :], plotpar, sfac)
 cfv.plt.axis([-1.5, 7.5, -0.5, 5.5])
 cfv.title("Displacements")
 
 
-#----- Draw normal force diagram --------------------------------
-cfv.figure(2,fig_size=(6,4))
-plotpar=[2,1]
-sfac=cfv.scalfact2(ex1,ey1,es1[:,0],0.2)
-cfv.secforce2(ex1,ey1,es1[:,0],plotpar,sfac)
-cfv.secforce2(ex2,ey2,es2[:,0],plotpar,sfac)
-cfv.secforce2(ex3,ey3,es3[:,0],plotpar,sfac)
+# ----- Draw normal force diagram --------------------------------
+cfv.figure(2, fig_size=(6, 4))
+plotpar = [2, 1]
+sfac = cfv.scalfact2(ex1, ey1, es1[:, 0], 0.2)
+cfv.secforce2(ex1, ey1, es1[:, 0], plotpar, sfac)
+cfv.secforce2(ex2, ey2, es2[:, 0], plotpar, sfac)
+cfv.secforce2(ex3, ey3, es3[:, 0], plotpar, sfac)
 cfv.plt.axis([-1.5, 7.5, -0.5, 5.5])
 cfv.title("Normal force")
 
-#----- Draw shear force diagram ---------------------------------
-cfv.figure(3,fig_size=(6,4))
-plotpar=[2,1]
-sfac=cfv.scalfact2(ex3,ey3,es3[:,1],0.2)
-cfv.secforce2(ex1,ey1,es1[:,1],plotpar,sfac)
-cfv.secforce2(ex2,ey2,es2[:,1],plotpar,sfac)
-cfv.secforce2(ex3,ey3,es3[:,1],plotpar,sfac)
+# ----- Draw shear force diagram ---------------------------------
+cfv.figure(3, fig_size=(6, 4))
+plotpar = [2, 1]
+sfac = cfv.scalfact2(ex3, ey3, es3[:, 1], 0.2)
+cfv.secforce2(ex1, ey1, es1[:, 1], plotpar, sfac)
+cfv.secforce2(ex2, ey2, es2[:, 1], plotpar, sfac)
+cfv.secforce2(ex3, ey3, es3[:, 1], plotpar, sfac)
 cfv.plt.axis([-1.5, 7.5, -0.5, 5.5])
 cfv.title("Shear force")
 
-#----- Draw moment diagram --------------------------------------
-cfv.figure(4,fig_size=(6,4))
-plotpar=[2,1]
-sfac=cfv.scalfact2(ex3,ey3,es3[:,2],0.2)
-cfv.secforce2(ex1,ey1,es1[:,2],plotpar,sfac)
-cfv.secforce2(ex2,ey2,es2[:,2],plotpar,sfac)
-cfv.secforce2(ex3,ey3,es3[:,2],plotpar,sfac)
+# ----- Draw moment diagram --------------------------------------
+cfv.figure(4, fig_size=(6, 4))
+plotpar = [2, 1]
+sfac = cfv.scalfact2(ex3, ey3, es3[:, 2], 0.2)
+cfv.secforce2(ex1, ey1, es1[:, 2], plotpar, sfac)
+cfv.secforce2(ex2, ey2, es2[:, 2], plotpar, sfac)
+cfv.secforce2(ex3, ey3, es3[:, 2], plotpar, sfac)
 cfv.plt.axis([-1.5, 7.5, -0.5, 5.5])
 cfv.title("Bending moment")
-cfv.showAndWait()
-#------------------------ end -----------------------------------
\ No newline at end of file
+cfv.show_and_wait()
+# ------------------------ end -----------------------------------
diff --git a/examples/exn_beam2_b.py b/examples/exn_beam2_b.py
index 0db602b..7ba99c8 100644
--- a/examples/exn_beam2_b.py
+++ b/examples/exn_beam2_b.py
@@ -9,34 +9,30 @@
 import calfem.vis_mpl as cfv
 
 
-#----- Topology -------------------------------------------------
+# ----- Topology -------------------------------------------------
 
-edof = np.array([
-    [4, 5, 6, 1, 2, 3],
-    [7, 8, 9, 10, 11, 12],
-    [4, 5, 6, 7, 8, 9]
-])
+edof = np.array([[4, 5, 6, 1, 2, 3], [7, 8, 9, 10, 11, 12], [4, 5, 6, 7, 8, 9]])
 
-#----- Element stiffness and element load matrices  -------------
+# ----- Element stiffness and element load matrices  -------------
 
-E=200e9
-A1=2e-3
-A2=6e-3
-I1=1.6e-5
-I2=5.4e-5
+E = 200e9
+A1 = 2e-3
+A2 = 6e-3
+I1 = 1.6e-5
+I2 = 5.4e-5
 
 ep1 = np.array([E, A1, I1])
 ep3 = np.array([E, A2, I2])
 
-ex1 = np.array([0.,0.])
-ey1 = np.array([4.,0.])
-ex2 = np.array([6.,6.])
-ey2 = np.array([4.,0.])
-ex3 = np.array([0.,6.])
-ey3 = np.array([4.,4.])
+ex1 = np.array([0.0, 0.0])
+ey1 = np.array([4.0, 0.0])
+ex2 = np.array([6.0, 6.0])
+ey2 = np.array([4.0, 0.0])
+ex3 = np.array([0.0, 6.0])
+ey3 = np.array([4.0, 4.0])
 
-eq1 = np.array([0.])
-eq2 = np.array([0.])
+eq1 = np.array([0.0])
+eq2 = np.array([0.0])
 eq3 = np.array([-50e3])
 
 # ----- Initial axial forces ----------------------------------------------
@@ -49,65 +45,65 @@
 # ----- Iteration for convergence -----------------------------------------
 
 eps = 1e-6
-n=0
+n = 0
 
-while abs((QX1-QX01)/QX01) > eps:
+while abs((QX1 - QX01) / QX01) > eps:
     n += 1
-    K = np.zeros([12,12])
-    f = np.zeros([12,1])
-    f[3,0] = 10e3
-
-    Ke1 = cfc.beam2ge(ex1,ey1,ep1,QX1)
-    Ke2 = cfc.beam2ge(ex2,ey2,ep1,QX2)
-    Ke3, fe3 = cfc.beam2ge(ex3,ey3,ep3,QX3,eq3)
-
-    K = cfc.assem(edof[0,:],K,Ke1)
-    K = cfc.assem(edof[1,:],K,Ke2)
-    K, f = cfc.assem(edof[2,:],K,Ke3,f,fe3)
-    if n==1:
+    K = np.zeros([12, 12])
+    f = np.zeros([12, 1])
+    f[3, 0] = 10e3
+
+    Ke1 = cfc.beam2ge(ex1, ey1, ep1, QX1)
+    Ke2 = cfc.beam2ge(ex2, ey2, ep1, QX2)
+    Ke3, fe3 = cfc.beam2ge(ex3, ey3, ep3, QX3, eq3)
+
+    K = cfc.assem(edof[0, :], K, Ke1)
+    K = cfc.assem(edof[1, :], K, Ke2)
+    K, f = cfc.assem(edof[2, :], K, Ke3, f, fe3)
+    if n == 1:
         K0 = K
 
     bc = np.array([1, 2, 3, 10, 11])
     a, r = cfc.solveq(K, f, bc)
 
-    ed = cfc.extract_ed(edof,a)
+    ed = cfc.extract_ed(edof, a)
 
-    QX01=QX1
-    es1 = cfc.beam2gs(ex1,ey1,ep1,ed[0,:],QX1,eq1)
-    es2 = cfc.beam2gs(ex2,ey2,ep1,ed[1,:],QX2,eq2)
-    es3 = cfc.beam2gs(ex3,ey3,ep3,ed[2,:],QX3,eq3)
+    QX01 = QX1
+    es1 = cfc.beam2gs(ex1, ey1, ep1, ed[0, :], QX1, eq1)
+    es2 = cfc.beam2gs(ex2, ey2, ep1, ed[1, :], QX2, eq2)
+    es3 = cfc.beam2gs(ex3, ey3, ep3, ed[2, :], QX3, eq3)
 
     QX1 = es1[1]
     QX2 = es2[1]
     QX3 = es3[1]
 
-    if n>20:
+    if n > 20:
         print("The solution does not converge")
         break
 
 
 # ----- Buckling analysis -------------------------------------------------
 
-lam, phi = cfc.eigen(K,K0,bc)
+lam, phi = cfc.eigen(K, K0, bc)
 one = np.ones(lam.shape)
-alpha = np.divide(one,one-lam)
+alpha = np.divide(one, one - lam)
 print(alpha[0])
 
 # ----- Draw shape at instability -----------------------------------------
 
-Ed = cfc.extract_ed(edof,-phi[:,0])
-cfv.figure(1,fig_size=(6,4))
-plotpar=[3,1,0]
-cfv.eldraw2(ex1,ey1,plotpar)
-cfv.eldraw2(ex2,ey2,plotpar)
-cfv.eldraw2(ex3,ey3,plotpar)
-sfac=cfv.scalfact2(ex3,ey3,Ed[2,:],0.1)
-plotpar=[1,2,1]
-cfv.eldisp2(ex1,ey1,Ed[0,:],plotpar,sfac)
-cfv.eldisp2(ex2,ey2,Ed[1,:],plotpar,sfac)
-cfv.eldisp2(ex3,ey3,Ed[2,:],plotpar,sfac)
+Ed = cfc.extract_ed(edof, -phi[:, 0])
+cfv.figure(1, fig_size=(6, 4))
+plotpar = [3, 1, 0]
+cfv.eldraw2(ex1, ey1, plotpar)
+cfv.eldraw2(ex2, ey2, plotpar)
+cfv.eldraw2(ex3, ey3, plotpar)
+sfac = cfv.scalfact2(ex3, ey3, Ed[2, :], 0.1)
+plotpar = [1, 2, 1]
+cfv.eldisp2(ex1, ey1, Ed[0, :], plotpar, sfac)
+cfv.eldisp2(ex2, ey2, Ed[1, :], plotpar, sfac)
+cfv.eldisp2(ex3, ey3, Ed[2, :], plotpar, sfac)
 cfv.plt.axis([-1.5, 7.5, -0.5, 5.5])
 cfv.title("Shape at instability")
-cfv.showAndWait()
+cfv.show_and_wait()
 
-#------------------------ end -----------------------------------
\ No newline at end of file
+# ------------------------ end -----------------------------------
diff --git a/examples/experimental/exs6_test.py b/examples/experimental/exs6.py
similarity index 100%
rename from examples/experimental/exs6_test.py
rename to examples/experimental/exs6.py
diff --git a/examples/experimental/gmsh_api_test_2.py b/examples/experimental/gmsh_api.py
similarity index 100%
rename from examples/experimental/gmsh_api_test_2.py
rename to examples/experimental/gmsh_api.py
diff --git a/examples/experimental/gmsh_api_test.py b/examples/experimental/gmsh_api2.py
similarity index 100%
rename from examples/experimental/gmsh_api_test.py
rename to examples/experimental/gmsh_api2.py
diff --git a/examples/experimental/plot_test.py b/examples/experimental/plot_tst.py
similarity index 100%
rename from examples/experimental/plot_test.py
rename to examples/experimental/plot_tst.py
diff --git a/examples/experimental/test_point_in_geom.py b/examples/experimental/point_in_geom.py
similarity index 100%
rename from examples/experimental/test_point_in_geom.py
rename to examples/experimental/point_in_geom.py
diff --git a/examples/experimental/test_tri_mesh.py b/examples/experimental/tri_mesh.py
similarity index 100%
rename from examples/experimental/test_tri_mesh.py
rename to examples/experimental/tri_mesh.py
diff --git a/examples/exs1.py b/examples/exs1.py
deleted file mode 100644
index ad79069..0000000
--- a/examples/exs1.py
+++ /dev/null
@@ -1,75 +0,0 @@
-# example exs1 
-# ----------------------------------------------------------------
-# PURPOSE 
-#     Linear elastic spring analysis. Introduction to the basic 
-#     steps in the finite element method.
-# ----------------------------------------------------------------
-
-# REFERENCES
-#     P-E Austrell 1994-03-08 
-#     K-G Olsson 1995-09-28
-#     O Dahlblom 2004-09-06
-#     J Lindemann 2009-01-25
-# ----------------------------------------------------------------
-
-import numpy as np
-import calfem.core as cfc
-
-# ----- Topology matrix Edof -------------------------------------
-
-Edof = np.array([
-    [1,2],
-    [2,3],
-    [2,3]
-])
-
-# ----- Stiffness matrix K and load vector f ---------------------
-
-K = np.matrix(np.zeros((3,3)))
-f = np.matrix(np.zeros((3,1)))
-
-# ----- Element stiffness matrices  ------------------------------
-
-k = 1500.
-ep1 = k
-ep2 = 2.*k
-Ke1 = cfc.spring1e(ep1)
-Ke2 = cfc.spring1e(ep2)
-
-# ----- Assemble Ke into K ---------------------------------------
-
-cfc.assem(Edof[0,:], K, Ke2)
-cfc.assem(Edof[1,:], K, Ke1)
-cfc.assem(Edof[2,:], K, Ke2)
-
-print("Stiffness matrix K:")
-print(K)
-
-# ----- Solve the system of equations ----------------------------
-
-bc = np.array([1,3])
-f[1]=100
-
-a, r = cfc.solveq(K, f, bc)
-
-print("Displacements a:")
-print(a)
-
-print("Reaction forces Q:")
-print(r)
-
-# ----- Element forces -------------------------------------------
-
-ed1 = cfc.extractEldisp(Edof[0,:],a)
-ed2 = cfc.extractEldisp(Edof[1,:],a)
-ed3 = cfc.extractEldisp(Edof[2,:],a)
-
-es1 = cfc.spring1s(ep2,ed1)
-es2 = cfc.spring1s(ep1,ed2)
-es3 = cfc.spring1s(ep2,ed3)
-
-print("N1 = "+str(es1))
-print("N2 = "+str(es2))
-print("N3 = "+str(es3))
-
-
diff --git a/examples/exs_bar2.py b/examples/exs_bar2.py
index c1d1e20..0524c26 100644
--- a/examples/exs_bar2.py
+++ b/examples/exs_bar2.py
@@ -14,20 +14,23 @@
 
 import numpy as np
 import calfem.core as cfc
+import calfem.utils as cfu
 import calfem.vis_mpl as cfv
 
+cfu.disp_h1("Analysis of a plane truss.")
+
 # ----- Topology matrix Edof -------------------------------------
 
 edof = np.array([
-    [1, 2, 5, 6],
-    [5, 6, 7, 8],
+    [1, 2, 5, 6], 
+    [5, 6, 7, 8], 
     [3, 4, 5, 6]
 ])
 
 # ----- Stiffness matrix K and load vector f ---------------------
 
-K = np.matrix(np.zeros((8, 8)))
-f = np.matrix(np.zeros((8, 1)))
+K = np.array(np.zeros((8, 8)))
+f = np.array(np.zeros((8, 1)))
 
 # ----- Element properties ---------------------------------------
 
@@ -41,13 +44,13 @@
 
 # ----- Element coordinates --------------------------------------
 
-ex1 = np.array([0., 1.6])
+ex1 = np.array([0.0, 1.6])
 ex2 = np.array([1.6, 1.6])
-ex3 = np.array([0., 1.6])
+ex3 = np.array([0.0, 1.6])
 
-ey1 = np.array([0., 0.])
-ey2 = np.array([0., 1.2])
-ey3 = np.array([1.2, 0.])
+ey1 = np.array([0.0, 0.0])
+ey2 = np.array([0.0, 1.2])
+ey3 = np.array([1.2, 0.0])
 
 # ----- Element stiffness matrices  ------------------------------
 
@@ -57,12 +60,12 @@
 
 # ----- Assemble Ke into K ---------------------------------------
 
-cfc.assem(edof[0, :], K, Ke1)
-cfc.assem(edof[1, :], K, Ke2)
-cfc.assem(edof[2, :], K, Ke3)
+K = cfc.assem(edof[0, :], K, Ke1)
+K = cfc.assem(edof[1, :], K, Ke2)
+K = cfc.assem(edof[2, :], K, Ke3)
 
-print("Stiffness matrix K:")
-print(K)
+cfu.disp_h2("Stiffness matrix K:")
+cfu.disp_array(K)
 
 # ----- Solve the system of equations ----------------------------
 
@@ -70,11 +73,11 @@
 f[5] = -80e3
 a, r = cfc.solveq(K, f, bc)
 
-print("Displacements a:")
-print(a)
+cfu.disp_h2("Displacements a:")
+cfu.disp_array(a)
 
-print("Reaction forces r:")
-print(r)
+cfu.disp_h2("Reaction forces r:")
+cfu.disp_array(r)
 
 # ----- Element forces -------------------------------------------
 
@@ -85,6 +88,8 @@
 ed3 = cfc.extract_ed(edof[2, :], a)
 N3 = cfc.bar2s(ex3, ey3, ep3, ed3)
 
+cfu.disp_h2("Element forces r:")
+
 print("N1 = ")
 print(N1)
 print("N2 = ")
@@ -110,19 +115,19 @@
 cfv.eldisp2(ex3, ey3, ed3, plotpar, sfac)
 cfv.axis([-0.4, 2.0, -0.4, 1.4])
 plotpar1 = 2
-cfv.scalgraph2(sfac,[1e-3, 0, -0.3],plotpar1)
-cfv.title('Displacements')
+cfv.scalgraph2(sfac, [1e-3, 0, -0.3], plotpar1)
+cfv.title("Displacements")
 
 # ----- Draw normal force diagram --------------------------------
 
 plotpar = [2, 1]
-sfac = cfv.scalfact2(ex1, ey1, N2[:,0], 0.1)
+sfac = cfv.scalfact2(ex1, ey1, N2[:, 0], 0.1)
 cfv.figure(2)
-cfv.secforce2(ex1, ey1, N1[:,0], plotpar, sfac)
-cfv.secforce2(ex2, ey2, N2[:,0], plotpar, sfac)
-cfv.secforce2(ex3, ey3, N3[:,0], plotpar, sfac)
+cfv.secforce2(ex1, ey1, N1[:, 0], plotpar, sfac)
+cfv.secforce2(ex2, ey2, N2[:, 0], plotpar, sfac)
+cfv.secforce2(ex3, ey3, N3[:, 0], plotpar, sfac)
 cfv.axis([-0.4, 2.0, -0.4, 1.4])
-cfv.scalgraph2(sfac,[5e4, 0, -0.3],plotpar1)
-cfv.title('Normal force')
+cfv.scalgraph2(sfac, [5e4, 0, -0.3], plotpar1)
+cfv.title("Normal force")
 
-cfv.showAndWait()
+cfv.show_and_wait()
diff --git a/examples/exs_bar2_la.py b/examples/exs_bar2_la.py
index a774b0f..929f362 100644
--- a/examples/exs_bar2_la.py
+++ b/examples/exs_bar2_la.py
@@ -16,6 +16,9 @@
 
 import numpy as np
 import calfem.core as cfc
+import calfem.utils as cfu
+
+cfu.disp_h1("Analysis of a plane truss using loops")
 
 # ----- Topology matrix Edof -------------------------------------
 
@@ -29,15 +32,15 @@
     [3, 4, 5, 6],
     [7, 8, 9, 10],
     [1, 2, 7, 8],
-    [5, 6, 11, 12]
+    [5, 6, 11, 12],
 ])
 
 # ----- Stiffness matrix K and load vector f ---------------------
 
 K = np.zeros([12, 12])
 f = np.zeros([12, 1])
-f[10] = 0.5e6*np.sin(np.pi/6)
-f[11] = -0.5e6*np.cos(np.pi/6)
+f[10] = 0.5e6 * np.sin(np.pi / 6)
+f[11] = -0.5e6 * np.cos(np.pi / 6)
 
 # ----- Element properties ---------------------------------------
 
@@ -48,29 +51,29 @@
 # ----- Element coordinates --------------------------------------
 
 ex = np.array([
-    [0., 2.],
-    [0., 2.],
-    [2., 4.],
-    [2., 4.],
-    [2., 2.],
-    [4., 4.],
-    [0., 2.],
-    [2., 4.],
-    [0., 2.],
-    [2., 4.]
+    [0.0, 2.0],
+    [0.0, 2.0],
+    [2.0, 4.0],
+    [2.0, 4.0],
+    [2.0, 2.0],
+    [4.0, 4.0],
+    [0.0, 2.0],
+    [2.0, 4.0],
+    [0.0, 2.0],
+    [2.0, 4.0],
 ])
 
 ey = np.array([
-    [2., 2.],
-    [0., 0.],
-    [2., 2.],
-    [0., 0.],
-    [0., 2.],
-    [0., 2.],
-    [0., 2.],
-    [0., 2.],
-    [2., 0.],
-    [2., 0.]
+    [2.0, 2.0],
+    [0.0, 0.0],
+    [2.0, 2.0],
+    [0.0, 0.0],
+    [0.0, 2.0],
+    [0.0, 2.0],
+    [0.0, 2.0],
+    [0.0, 2.0],
+    [2.0, 0.0],
+    [2.0, 0.0],
 ])
 
 # ----- Create element stiffness matrices Ke and assemble into K -
@@ -79,31 +82,30 @@
     Ke = cfc.bar2e(elx, ely, ep)
     cfc.assem(eltopo, K, Ke)
 
-print("Stiffness matrix K:")
-print(K)
+cfu.disp_h2("Stiffness matrix K:")
+cfu.disp_array(K)
 
 # ----- Solve the system of equations ----------------------------
 
 bc = np.array([1, 2, 3, 4])
 a, r = cfc.solveq(K, f, bc)
 
-print("Displacements a:")
-print(a)
+cfu.disp_h2("Displacements a:")
+cfu.disp_array(a)
 
-print("Reaction forces r:")
-print(r)
+cfu.disp_h2("Reaction forces r:")
+cfu.disp_array(r)
 
 # ----- Element forces -------------------------------------------
 
 ed = cfc.extract_ed(edof, a)
 N = np.zeros([edof.shape[0]])
 
-print("Element forces:")
+cfu.disp_h2("Element forces:")
 
 i = 0
 for elx, ely, eld in zip(ex, ey, ed):
     es = cfc.bar2s(elx, ely, ep, eld)
     N[i] = es[0]
-    print("N%d = %g" % (i+1, N[i]))
+    print("N%d = %g" % (i + 1, N[i]))
     i += 1
-
diff --git a/examples/exs_bar2_lb.py b/examples/exs_bar2_lb.py
index 2fb3d3b..e96bd1d 100644
--- a/examples/exs_bar2_lb.py
+++ b/examples/exs_bar2_lb.py
@@ -3,7 +3,7 @@
 # example exs_bar2_la
 # ----------------------------------------------------------------
 # PURPOSE
-#    Analysis of a plane truss using loops and extraction of  
+#    Analysis of a plane truss using loops and extraction of
 #    element coordinates from a global coordinate matrix.
 # ----------------------------------------------------------------
 
@@ -18,6 +18,9 @@
 
 import numpy as np
 import calfem.core as cfc
+import calfem.utils as cfu
+
+cfu.disp_h1("Analysis of a plane truss using loops and extraction of element coordinates from a global coordinate matrix.")
 
 # ----- Topology matrix Edof -------------------------------------
 
@@ -31,15 +34,15 @@
     [3, 4, 5, 6],
     [7, 8, 9, 10],
     [1, 2, 7, 8],
-    [5, 6, 11, 12]
+    [5, 6, 11, 12],
 ])
 
 # ----- Stiffness matrix K and load vector f ---------------------
 
 K = np.zeros([12, 12])
 f = np.zeros([12, 1])
-f[10] = 0.5e6*np.sin(np.pi/6)
-f[11] = -0.5e6*np.cos(np.pi/6)
+f[10] = 0.5e6 * np.sin(np.pi / 6)
+f[11] = -0.5e6 * np.cos(np.pi / 6)
 
 # ----- Element properties ---------------------------------------
 
@@ -47,61 +50,60 @@
 E = 2.1e11
 ep = [E, A]
 
-#----- Global coordinates and topology --------------------------
+# ----- Global coordinates and topology --------------------------
 
 coord = np.array([
-    [0, 2],
-    [0, 0],
-    [2, 2],
-    [2, 0],
-    [4, 2],
+    [0, 2], 
+    [0, 0], 
+    [2, 2], 
+    [2, 0], 
+    [4, 2], 
     [4, 0]
 ])
- 
+
 dof = np.array([
-    [ 1,  2],
-    [ 3,  4],
-    [ 5,  6],
-    [ 7,  8],
-    [ 9, 10],
+    [1, 2], 
+    [3, 4], 
+    [5, 6], 
+    [7, 8], 
+    [9, 10], 
     [11, 12]
-])    
+])
 
 # ----- Element coordinates --------------------------------------
 
-ex, ey = cfc.coordxtr(edof, coord, dof,2)
- 
+ex, ey = cfc.coordxtr(edof, coord, dof, 2)
+
 # ----- Create element stiffness matrices Ke and assemble into K -
 
 for elx, ely, eltopo in zip(ex, ey, edof):
     Ke = cfc.bar2e(elx, ely, ep)
     cfc.assem(eltopo, K, Ke)
 
-print("Stiffness matrix K:")
-print(K)
+cfu.disp_h2("Stiffness matrix K:")
+cfu.disp_array(K)
 
 # ----- Solve the system of equations ----------------------------
 
 bc = np.array([1, 2, 3, 4])
 a, r = cfc.solveq(K, f, bc)
 
-print("Displacements a:")
-print(a)
+cfu.disp_h2("Displacements a:")
+cfu.disp_array(a)
 
-print("Reaction forces r:")
-print(r)
+cfu.disp_h2("Reaction forces r:")
+cfu.disp_array(r)
 
 # ----- Element forces -------------------------------------------
 
 ed = cfc.extract_ed(edof, a)
 N = np.zeros([edof.shape[0]])
 
-print("Element forces:")
+cfu.disp_h2("Element forces:")
 
 i = 0
 for elx, ely, eld in zip(ex, ey, ed):
     es = cfc.bar2s(elx, ely, ep, eld)
     N[i] = es[0]
-    print("N%d = %g" % (i+1, N[i]))
+    print("N%d = %g" % (i + 1, N[i]))
     i += 1
-
diff --git a/examples/exs_beam1.ipynb b/examples/exs_beam1.ipynb
new file mode 100644
index 0000000..5a203de
--- /dev/null
+++ b/examples/exs_beam1.ipynb
@@ -0,0 +1,636 @@
+{
+ "cells": [
+  {
+   "cell_type": "markdown",
+   "id": "21747083-42dc-453e-8d50-f582c0f8f220",
+   "metadata": {},
+   "source": [
+    "# Analysis of a plane frame"
+   ]
+  },
+  {
+   "attachments": {
+    "59e815f8-32ca-458d-a624-3a504e74e306.png": {
+     "image/png": "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"
+    }
+   },
+   "cell_type": "markdown",
+   "id": "1ebd6b2b-7fac-4d12-bf88-7288c1d41ad1",
+   "metadata": {},
+   "source": [
+    "Consider a beam with the length 9.0 m. The beam is simply supported and loaded\n",
+    "by a point load $P=10000 N$ applied at a point 3.0 m from the left support. The\n",
+    "corresponding computational model has six degrees of freedom and consists of two\n",
+    "beam elements with four degrees of freedom. The beam has Young’s modulus $E=210 GPa$ and moment of inertia $I=2510\\times 10^{−8} m^4$.\n",
+    "<div>\n",
+    "<img src=\"attachment:59e815f8-32ca-458d-a624-3a504e74e306.png\" width=\"800\"/>\n",
+    "</div>"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "748d8d1c-c8d9-4b8d-9465-b250c5bd5677",
+   "metadata": {},
+   "source": [
+    "Install CALFEM (if required)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 2,
+   "id": "fa33f6e7-8616-43c1-ab6d-c033d33d5a4a",
+   "metadata": {
+    "tags": []
+   },
+   "outputs": [
+    {
+     "ename": "AttributeError",
+     "evalue": "'list' object has no attribute 'prepend'",
+     "output_type": "error",
+     "traceback": [
+      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
+      "\u001b[1;31mAttributeError\u001b[0m                            Traceback (most recent call last)",
+      "Cell \u001b[1;32mIn[2], line 5\u001b[0m\n\u001b[0;32m      1\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mimportlib\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mutil\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m find_spec\n\u001b[0;32m      3\u001b[0m \u001b[38;5;28;01mimport\u001b[39;00m \u001b[38;5;21;01msys\u001b[39;00m\n\u001b[1;32m----> 5\u001b[0m sys\u001b[38;5;241m.\u001b[39mpath\u001b[38;5;241m.\u001b[39mprepend(\u001b[38;5;124mr\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mC:\u001b[39m\u001b[38;5;124m\\\u001b[39m\u001b[38;5;124mUsers\u001b[39m\u001b[38;5;124m\\\u001b[39m\u001b[38;5;124mJonas Lindemann\u001b[39m\u001b[38;5;124m\\\u001b[39m\u001b[38;5;124mDevelopment\u001b[39m\u001b[38;5;124m\\\u001b[39m\u001b[38;5;124mcalfem-python\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n\u001b[0;32m      7\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m find_spec(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mcalfem.core\u001b[39m\u001b[38;5;124m\"\u001b[39m) \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[0;32m      8\u001b[0m     get_ipython()\u001b[38;5;241m.\u001b[39msystem(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mpip install calfem-python\u001b[39m\u001b[38;5;124m'\u001b[39m)\n",
+      "\u001b[1;31mAttributeError\u001b[0m: 'list' object has no attribute 'prepend'"
+     ]
+    }
+   ],
+   "source": [
+    "from importlib.util import find_spec\n",
+    "\n",
+    "import sys\n",
+    "\n",
+    "sys.path.prepend(r\"C:\\Users\\Jonas Lindemann\\Development\\calfem-python\")\n",
+    "\n",
+    "if find_spec(\"calfem.core\") is None:\n",
+    "    !pip install calfem-python\n",
+    "else:\n",
+    "    print(\"CALFEM already installed.\")"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "a8fcd0e8-c7d6-4de4-af95-108d20153c7d",
+   "metadata": {},
+   "source": [
+    "Import modules"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 2,
+   "id": "3d33663a-d8e9-46cf-b797-4f280930aac9",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "import numpy as np\n",
+    "import matplotlib.pyplot as plt\n",
+    "import calfem.core as cfc\n",
+    "import calfem.utils as cfu\n",
+    "import calfem.vis_mpl as cfv"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "c4182177-e7f7-423a-a032-ce1259a6ee84",
+   "metadata": {},
+   "source": [
+    "Define topology"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 3,
+   "id": "ba1a0696-f45f-4798-ba51-f08be6dad7df",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "edof = np.array([\n",
+    "     [1, 2, 3, 4], \n",
+    "     [3, 4, 5, 6]\n",
+    "])"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "e7984716-86ed-4d05-a4f9-e41bdeb29dd8",
+   "metadata": {},
+   "source": [
+    "Setup stiffness matrix K and load vector f"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 4,
+   "id": "f0a9449b-b9f7-42bb-b9c4-dabaa01c5875",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "K = np.array(np.zeros((6, 6)))\n",
+    "f = np.array(np.zeros((6, 1)))\n",
+    "f[2] = -10e3"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "30069d9d-a320-4019-b48a-2ef581e719e4",
+   "metadata": {},
+   "source": [
+    "Setup element stiffness and element load matrices"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 5,
+   "id": "9a39be9c-bb81-4caa-9de9-5fafdcb29013",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "E = 210e9\n",
+    "I = 2510e-8\n",
+    "\n",
+    "ep = np.array([E, I])\n",
+    "ex1 = np.array([0, 3])\n",
+    "ex2 = np.array([3, 9])\n",
+    "eq1 = np.array([0])\n",
+    "eq2 = np.array([0])\n",
+    "\n",
+    "Ke1 = cfc.beam1e(ex1, ep)\n",
+    "Ke2 = cfc.beam1e(ex2, ep)"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "0bd2bd78-370c-494e-87ea-528620b992ff",
+   "metadata": {},
+   "source": [
+    "Assemble Ke into K"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 6,
+   "id": "894a19bd-0eb9-42e8-bfff-5f6b92fc8c9a",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "K = cfc.assem(edof[0, :], K, Ke1)\n",
+    "K = cfc.assem(edof[1, :], K, Ke2)"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "f0da7c93-bafe-42d9-87ca-c26959e98f63",
+   "metadata": {},
+   "source": [
+    "Solve the system of equations and compute reactions"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 7,
+   "id": "cc77fe68-7abe-48e2-a5b3-ef891e781d4b",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/html": [
+       "<table>\n",
+       "<thead>\n",
+       "<tr><th style=\"text-align: right;\">          a</th></tr>\n",
+       "</thead>\n",
+       "<tbody>\n",
+       "<tr><td style=\"text-align: right;\"> 0.0000e+00</td></tr>\n",
+       "<tr><td style=\"text-align: right;\">-9.4859e-03</td></tr>\n",
+       "<tr><td style=\"text-align: right;\">-2.2766e-02</td></tr>\n",
+       "<tr><td style=\"text-align: right;\">-3.7943e-03</td></tr>\n",
+       "<tr><td style=\"text-align: right;\"> 0.0000e+00</td></tr>\n",
+       "<tr><td style=\"text-align: right;\"> 7.5887e-03</td></tr>\n",
+       "</tbody>\n",
+       "</table>"
+      ],
+      "text/plain": [
+       "'<table>\\n<thead>\\n<tr><th style=\"text-align: right;\">          a</th></tr>\\n</thead>\\n<tbody>\\n<tr><td style=\"text-align: right;\"> 0.0000e+00</td></tr>\\n<tr><td style=\"text-align: right;\">-9.4859e-03</td></tr>\\n<tr><td style=\"text-align: right;\">-2.2766e-02</td></tr>\\n<tr><td style=\"text-align: right;\">-3.7943e-03</td></tr>\\n<tr><td style=\"text-align: right;\"> 0.0000e+00</td></tr>\\n<tr><td style=\"text-align: right;\"> 7.5887e-03</td></tr>\\n</tbody>\\n</table>'"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
+    },
+    {
+     "data": {
+      "text/html": [
+       "<table>\n",
+       "<thead>\n",
+       "<tr><th style=\"text-align: right;\">          r</th></tr>\n",
+       "</thead>\n",
+       "<tbody>\n",
+       "<tr><td style=\"text-align: right;\"> 6.6667e+03</td></tr>\n",
+       "<tr><td style=\"text-align: right;\">-3.6380e-12</td></tr>\n",
+       "<tr><td style=\"text-align: right;\"> 7.2760e-12</td></tr>\n",
+       "<tr><td style=\"text-align: right;\">-1.0914e-11</td></tr>\n",
+       "<tr><td style=\"text-align: right;\"> 3.3333e+03</td></tr>\n",
+       "<tr><td style=\"text-align: right;\"> 0.0000e+00</td></tr>\n",
+       "</tbody>\n",
+       "</table>"
+      ],
+      "text/plain": [
+       "'<table>\\n<thead>\\n<tr><th style=\"text-align: right;\">          r</th></tr>\\n</thead>\\n<tbody>\\n<tr><td style=\"text-align: right;\"> 6.6667e+03</td></tr>\\n<tr><td style=\"text-align: right;\">-3.6380e-12</td></tr>\\n<tr><td style=\"text-align: right;\"> 7.2760e-12</td></tr>\\n<tr><td style=\"text-align: right;\">-1.0914e-11</td></tr>\\n<tr><td style=\"text-align: right;\"> 3.3333e+03</td></tr>\\n<tr><td style=\"text-align: right;\"> 0.0000e+00</td></tr>\\n</tbody>\\n</table>'"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
+    }
+   ],
+   "source": [
+    "bc = np.array([1, 5])\n",
+    "a, r = cfc.solveq(K, f, bc)\n",
+    "\n",
+    "cfu.disp_array(a, [\"a\"])\n",
+    "cfu.disp_array(r, [\"r\"])"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "607f92c9-6f7e-4f72-b403-26017aacc5c7",
+   "metadata": {},
+   "source": [
+    "Section forces"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 8,
+   "id": "cee82b10-4feb-49d3-ac3c-b4c45a29aa12",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/html": [
+       "<h2>es1</h2>"
+      ],
+      "text/plain": [
+       "<IPython.core.display.HTML object>"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
+    },
+    {
+     "data": {
+      "text/html": [
+       "<table>\n",
+       "<thead>\n",
+       "<tr><th style=\"text-align: right;\">         V1</th><th style=\"text-align: right;\">        M1</th></tr>\n",
+       "</thead>\n",
+       "<tbody>\n",
+       "<tr><td style=\"text-align: right;\">-6.6667e+03</td><td style=\"text-align: right;\">9.1437e-12</td></tr>\n",
+       "<tr><td style=\"text-align: right;\">-6.6667e+03</td><td style=\"text-align: right;\">6.6667e+03</td></tr>\n",
+       "<tr><td style=\"text-align: right;\">-6.6667e+03</td><td style=\"text-align: right;\">1.3333e+04</td></tr>\n",
+       "<tr><td style=\"text-align: right;\">-6.6667e+03</td><td style=\"text-align: right;\">2.0000e+04</td></tr>\n",
+       "</tbody>\n",
+       "</table>"
+      ],
+      "text/plain": [
+       "'<table>\\n<thead>\\n<tr><th style=\"text-align: right;\">         V1</th><th style=\"text-align: right;\">        M1</th></tr>\\n</thead>\\n<tbody>\\n<tr><td style=\"text-align: right;\">-6.6667e+03</td><td style=\"text-align: right;\">9.1437e-12</td></tr>\\n<tr><td style=\"text-align: right;\">-6.6667e+03</td><td style=\"text-align: right;\">6.6667e+03</td></tr>\\n<tr><td style=\"text-align: right;\">-6.6667e+03</td><td style=\"text-align: right;\">1.3333e+04</td></tr>\\n<tr><td style=\"text-align: right;\">-6.6667e+03</td><td style=\"text-align: right;\">2.0000e+04</td></tr>\\n</tbody>\\n</table>'"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
+    },
+    {
+     "data": {
+      "text/html": [
+       "<h2>ed1</h2>"
+      ],
+      "text/plain": [
+       "<IPython.core.display.HTML object>"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
+    },
+    {
+     "data": {
+      "text/html": [
+       "<table>\n",
+       "<thead>\n",
+       "<tr><th style=\"text-align: right;\">         v1</th></tr>\n",
+       "</thead>\n",
+       "<tbody>\n",
+       "<tr><td style=\"text-align: right;\"> 0.0000e+00</td></tr>\n",
+       "<tr><td style=\"text-align: right;\">-9.2751e-03</td></tr>\n",
+       "<tr><td style=\"text-align: right;\">-1.7285e-02</td></tr>\n",
+       "<tr><td style=\"text-align: right;\">-2.2766e-02</td></tr>\n",
+       "</tbody>\n",
+       "</table>"
+      ],
+      "text/plain": [
+       "'<table>\\n<thead>\\n<tr><th style=\"text-align: right;\">         v1</th></tr>\\n</thead>\\n<tbody>\\n<tr><td style=\"text-align: right;\"> 0.0000e+00</td></tr>\\n<tr><td style=\"text-align: right;\">-9.2751e-03</td></tr>\\n<tr><td style=\"text-align: right;\">-1.7285e-02</td></tr>\\n<tr><td style=\"text-align: right;\">-2.2766e-02</td></tr>\\n</tbody>\\n</table>'"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
+    },
+    {
+     "data": {
+      "text/html": [
+       "<h2>ec1</h2>"
+      ],
+      "text/plain": [
+       "<IPython.core.display.HTML object>"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
+    },
+    {
+     "data": {
+      "text/html": [
+       "<table>\n",
+       "<thead>\n",
+       "<tr><th style=\"text-align: right;\">        x1</th></tr>\n",
+       "</thead>\n",
+       "<tbody>\n",
+       "<tr><td style=\"text-align: right;\">0.0000e+00</td></tr>\n",
+       "<tr><td style=\"text-align: right;\">1.0000e+00</td></tr>\n",
+       "<tr><td style=\"text-align: right;\">2.0000e+00</td></tr>\n",
+       "<tr><td style=\"text-align: right;\">3.0000e+00</td></tr>\n",
+       "</tbody>\n",
+       "</table>"
+      ],
+      "text/plain": [
+       "'<table>\\n<thead>\\n<tr><th style=\"text-align: right;\">        x1</th></tr>\\n</thead>\\n<tbody>\\n<tr><td style=\"text-align: right;\">0.0000e+00</td></tr>\\n<tr><td style=\"text-align: right;\">1.0000e+00</td></tr>\\n<tr><td style=\"text-align: right;\">2.0000e+00</td></tr>\\n<tr><td style=\"text-align: right;\">3.0000e+00</td></tr>\\n</tbody>\\n</table>'"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
+    },
+    {
+     "data": {
+      "text/html": [
+       "<h2>es2</h2>"
+      ],
+      "text/plain": [
+       "<IPython.core.display.HTML object>"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
+    },
+    {
+     "data": {
+      "text/html": [
+       "<table>\n",
+       "<thead>\n",
+       "<tr><th style=\"text-align: right;\">        V2</th><th style=\"text-align: right;\">        M2</th></tr>\n",
+       "</thead>\n",
+       "<tbody>\n",
+       "<tr><td style=\"text-align: right;\">3.3333e+03</td><td style=\"text-align: right;\">2.0000e+04</td></tr>\n",
+       "<tr><td style=\"text-align: right;\">3.3333e+03</td><td style=\"text-align: right;\">1.6667e+04</td></tr>\n",
+       "<tr><td style=\"text-align: right;\">3.3333e+03</td><td style=\"text-align: right;\">1.3333e+04</td></tr>\n",
+       "<tr><td style=\"text-align: right;\">3.3333e+03</td><td style=\"text-align: right;\">1.0000e+04</td></tr>\n",
+       "<tr><td style=\"text-align: right;\">3.3333e+03</td><td style=\"text-align: right;\">6.6667e+03</td></tr>\n",
+       "<tr><td style=\"text-align: right;\">3.3333e+03</td><td style=\"text-align: right;\">3.3333e+03</td></tr>\n",
+       "<tr><td style=\"text-align: right;\">3.3333e+03</td><td style=\"text-align: right;\">4.5719e-12</td></tr>\n",
+       "</tbody>\n",
+       "</table>"
+      ],
+      "text/plain": [
+       "'<table>\\n<thead>\\n<tr><th style=\"text-align: right;\">        V2</th><th style=\"text-align: right;\">        M2</th></tr>\\n</thead>\\n<tbody>\\n<tr><td style=\"text-align: right;\">3.3333e+03</td><td style=\"text-align: right;\">2.0000e+04</td></tr>\\n<tr><td style=\"text-align: right;\">3.3333e+03</td><td style=\"text-align: right;\">1.6667e+04</td></tr>\\n<tr><td style=\"text-align: right;\">3.3333e+03</td><td style=\"text-align: right;\">1.3333e+04</td></tr>\\n<tr><td style=\"text-align: right;\">3.3333e+03</td><td style=\"text-align: right;\">1.0000e+04</td></tr>\\n<tr><td style=\"text-align: right;\">3.3333e+03</td><td style=\"text-align: right;\">6.6667e+03</td></tr>\\n<tr><td style=\"text-align: right;\">3.3333e+03</td><td style=\"text-align: right;\">3.3333e+03</td></tr>\\n<tr><td style=\"text-align: right;\">3.3333e+03</td><td style=\"text-align: right;\">4.5719e-12</td></tr>\\n</tbody>\\n</table>'"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
+    },
+    {
+     "data": {
+      "text/html": [
+       "<h2>ed2</h2>"
+      ],
+      "text/plain": [
+       "<IPython.core.display.HTML object>"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
+    },
+    {
+     "data": {
+      "text/html": [
+       "<table>\n",
+       "<thead>\n",
+       "<tr><th style=\"text-align: right;\">         v2</th></tr>\n",
+       "</thead>\n",
+       "<tbody>\n",
+       "<tr><td style=\"text-align: right;\">-2.2766e-02</td></tr>\n",
+       "<tr><td style=\"text-align: right;\">-2.4769e-02</td></tr>\n",
+       "<tr><td style=\"text-align: right;\">-2.3609e-02</td></tr>\n",
+       "<tr><td style=\"text-align: right;\">-1.9920e-02</td></tr>\n",
+       "<tr><td style=\"text-align: right;\">-1.4334e-02</td></tr>\n",
+       "<tr><td style=\"text-align: right;\">-7.4833e-03</td></tr>\n",
+       "<tr><td style=\"text-align: right;\"> 6.9389e-18</td></tr>\n",
+       "</tbody>\n",
+       "</table>"
+      ],
+      "text/plain": [
+       "'<table>\\n<thead>\\n<tr><th style=\"text-align: right;\">         v2</th></tr>\\n</thead>\\n<tbody>\\n<tr><td style=\"text-align: right;\">-2.2766e-02</td></tr>\\n<tr><td style=\"text-align: right;\">-2.4769e-02</td></tr>\\n<tr><td style=\"text-align: right;\">-2.3609e-02</td></tr>\\n<tr><td style=\"text-align: right;\">-1.9920e-02</td></tr>\\n<tr><td style=\"text-align: right;\">-1.4334e-02</td></tr>\\n<tr><td style=\"text-align: right;\">-7.4833e-03</td></tr>\\n<tr><td style=\"text-align: right;\"> 6.9389e-18</td></tr>\\n</tbody>\\n</table>'"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
+    },
+    {
+     "data": {
+      "text/html": [
+       "<h2>ec2</h2>"
+      ],
+      "text/plain": [
+       "<IPython.core.display.HTML object>"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
+    },
+    {
+     "data": {
+      "text/html": [
+       "<table>\n",
+       "<thead>\n",
+       "<tr><th style=\"text-align: right;\">        x2</th></tr>\n",
+       "</thead>\n",
+       "<tbody>\n",
+       "<tr><td style=\"text-align: right;\">0.0000e+00</td></tr>\n",
+       "<tr><td style=\"text-align: right;\">1.0000e+00</td></tr>\n",
+       "<tr><td style=\"text-align: right;\">2.0000e+00</td></tr>\n",
+       "<tr><td style=\"text-align: right;\">3.0000e+00</td></tr>\n",
+       "<tr><td style=\"text-align: right;\">4.0000e+00</td></tr>\n",
+       "<tr><td style=\"text-align: right;\">5.0000e+00</td></tr>\n",
+       "<tr><td style=\"text-align: right;\">6.0000e+00</td></tr>\n",
+       "</tbody>\n",
+       "</table>"
+      ],
+      "text/plain": [
+       "'<table>\\n<thead>\\n<tr><th style=\"text-align: right;\">        x2</th></tr>\\n</thead>\\n<tbody>\\n<tr><td style=\"text-align: right;\">0.0000e+00</td></tr>\\n<tr><td style=\"text-align: right;\">1.0000e+00</td></tr>\\n<tr><td style=\"text-align: right;\">2.0000e+00</td></tr>\\n<tr><td style=\"text-align: right;\">3.0000e+00</td></tr>\\n<tr><td style=\"text-align: right;\">4.0000e+00</td></tr>\\n<tr><td style=\"text-align: right;\">5.0000e+00</td></tr>\\n<tr><td style=\"text-align: right;\">6.0000e+00</td></tr>\\n</tbody>\\n</table>'"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
+    }
+   ],
+   "source": [
+    "ed = cfc.extract_ed(edof, a)\n",
+    "\n",
+    "es1, ed1, ec1 = cfc.beam1s(ex1, ep, ed[0, :], eq1, nep=4)\n",
+    "es2, ed2, ec2 = cfc.beam1s(ex2, ep, ed[1, :], eq2, nep=7)\n",
+    "\n",
+    "cfu.disp_h2(\"es1\")\n",
+    "cfu.disp_array(es1, [\"V1\", \"M1\"])\n",
+    "cfu.disp_h2(\"ed1\")\n",
+    "cfu.disp_array(ed1, [\"v1\"])\n",
+    "cfu.disp_h2(\"ec1\")\n",
+    "cfu.disp_array(ec1, [\"x1\"])\n",
+    "cfu.disp_h2(\"es2\")\n",
+    "cfu.disp_array(es2, [\"V2\", \"M2\"])\n",
+    "cfu.disp_h2(\"ed2\")\n",
+    "cfu.disp_array(ed2, [\"v2\"])\n",
+    "cfu.disp_h2(\"ec2\")\n",
+    "cfu.disp_array(ec2, [\"x2\"])"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "18d2b635-7d45-42e0-8f45-cdfd7e56352c",
+   "metadata": {},
+   "source": [
+    "Draw deformed frame"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 9,
+   "id": "04d68478-5ac0-45cf-8903-5ac389f8faa8",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "image/png": "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\n",
+      "text/plain": [
+       "<Figure size 432x383.76 with 1 Axes>"
+      ]
+     },
+     "metadata": {
+      "needs_background": "light"
+     },
+     "output_type": "display_data"
+    }
+   ],
+   "source": [
+    "cfv.figure(1)\n",
+    "plt.plot([0, 9], [0, 0], color=(0.8, 0.8, 0.8))\n",
+    "plt.plot(\n",
+    "    np.concatenate(([0], ec1[:, 0], 3 + ec2[:, 0], [9]), 0),\n",
+    "    np.concatenate(([0], ed1[:, 0], ed2[:, 0], [0]), 0),\n",
+    "    color=(0.0, 0.0, 0.0),\n",
+    ")\n",
+    "cfv.title(\"displacements\")"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "e6fbdfaa-d28b-49da-9d8d-07b016dcec6e",
+   "metadata": {},
+   "source": [
+    "Draw normal force diagram"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 10,
+   "id": "9e420575-f743-4a5d-80d1-0591e73d1f45",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "image/png": "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\n",
+      "text/plain": [
+       "<Figure size 432x383.76 with 1 Axes>"
+      ]
+     },
+     "metadata": {
+      "needs_background": "light"
+     },
+     "output_type": "display_data"
+    }
+   ],
+   "source": [
+    "cfv.figure(2)\n",
+    "plt.plot([0, 9], [0, 0], color=(0.8, 0.8, 0.8))\n",
+    "plt.plot(\n",
+    "    np.concatenate(([0], ec1[:, 0], 3 + ec2[:, 0], [9]), 0),\n",
+    "    -np.concatenate(([0], es1[:, 0], es2[:, 0], [0]), 0) / 1000,\n",
+    "    color=(0.0, 0.0, 0.0),\n",
+    ")\n",
+    "cfv.title(\"shear force\")"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "57508ff2-21f5-48cd-9bb5-d0ad268b9e13",
+   "metadata": {},
+   "source": [
+    "Draw shear force diagram"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 11,
+   "id": "4734b313-1233-4f7f-bd97-cbbe411ced44",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "image/png": "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TaJo0aIeOY5ffmdxcHCwye/3EZw4cYLatWvTrVs3Ro0aVcDJlFKqYGRkZNCpUydmzZrFwoULad68udv7FJHlxpjgS58PuCuLy5UrR/fu3YmLi+P48eO24yilVLY+/PBDfvzxRz7//PMCKYHcBFwRQObpoZMnTxIfH287ilJK/c3cuXN54403CA8P5x//8OjZciAATw1B5kexmjRpQpUqVfj1118LMJlSSrln9+7dNGvWjGrVqrFs2TLKlStXYPvWU0NZiAhOp5NFixaxfv1623GUUgqA8+fP061bN06fPs3kyZMLtARyE5BFANC7d2+KFSvGmDFjbEdRSikABg0axKJFixg1ahQ33HCD144bsEVQs2ZNOnbsyLhx4zxypZ5SSl2JhIQEvvjiC5555hm6devm1WMHbBFA5qDxgQMH+PHHH21HUUoFsI0bN+JwOGjRogWffPKJ148f0EXQvn17ateuzejRo21HUUoFqJMnTxISEkKpUqWIj4+nRIkSXs8Q0EVQrFgxIiMjmT59Onv3emRWC6WUypExhn79+rFu3TpiYmKoV6+elRwBXQQADoeD9PR0xo8fbzuKUirADB8+nEmTJvHuu+96ZDK5vArI6wgudc8997B//342bNiASHazYiulVMH67bffaNWqFW3btuWHH36gSBHP/16u1xHkwul0smnTJhYuXGg7ilIqABw8eJDQ0FBq167NhAkTvFICudEiAEJDQylfvrwOGiulPC4jI4OIiAj27dtHYmIiVapUsR1JiwCgbNmy9OjRg/j4eI4dO2Y7jlKqEBs8eDA//fQTQ4YMITj4b2dprNAicHE6nZw6dYq4uDjbUZRShdSsWbN4++236d27N/369bMd5790sNjFGEPTpk2pUKECixcvLtB9K6XUzp07adasGbVr12bp0qWUKVPG6xl0sPgyLk5Et2TJEtatW2c7jlKqEDl37hxhYWGcO3eOpKQkKyWQGy2CLCIiIihWrJgOGiulCtTAgQNZunQpo0eP5rrrrrMd52+0CLKoUaMGnTp1Yvz48Zw7d852HKVUIRAbG8vQoUN5/vnnCQ0NtR0nW1oEl3A6naSlpTFt2jTbUZRSfm7dunU89thjtGzZko8++sh2nBxpEVzigQceoE6dOnp6SCnlluPHjxMSEkLZsmWJj4+nePHitiPlSIvgEsWKFaNv377MmDGD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Uvl37bXXcu+99zJ69Gj88boR9VdLlizhhRdeoGPHjrz00ku246hCwBtjBCHASmPM2RyWPyUiq0VktIhU9kKegORwONiyZQv/93//ZzuKckNaWhphYWHUq1eP8ePH62RyqkBc9m+RiMwRkZRsbp3zsO1NwEdATte6fw1cA9wG7AU+zWVfT4hIsogkp6WlXe7Q6hKhoaGUL19eB439WHp6Or169SItLY3ExEQqV9bfm1TBuGwRGGPaGmOaZnObktt2IlIP+A7oY4z5I4d97zfGpBtjMoCRQPNccowwxgQbY4KrV69+udjqEmXKlCE8PJyEhASOHTtmO47Kh3fffZfZs2czdOhQgoKCbMdRhYhH3leKSCXgR+AVY0yOk+KLSO0sD7uSOfisPMTpdHL69GliY2NtR1FXaMaMGbz33nv07dsXp9NpO44qZNyadE5EugJfAdWBI8AqY8yDIvI68AqwOcvqDxhjDojIt8BwY0yyiEwg87SQAbYB/Ywxl/2yXZ10Ln+MMdxyyy2ULVuWJUuW2I6j8mj79u0EBQVRr149Fi9eTJkyZWxHUn4qp0nndPbRAPP555/zwgsvkJKSwk033WQ7jrqMs2fP0qpVKzZt2sTy5cu59tprbUdSfkxnH1UAREREULx4cR009hPPP/88ycnJjB07VktAeYwWQYCpXr06nTp1YsKECZw7d852HJWLiRMn8vXXX/Piiy/StWtX23FUIaZFEICcTid//vknP/zwg+0oKgcpKSk88cQT3HPPPbz//vu246hCTosgAD3wwAPUrVtXv6fARx07doyQkBAqVKhAbGwsxYoVsx1JFXJaBAGoaNGi9O3bl59++ondu3fbjqOyMMbgdDr5448/iIuLo3bt2pffSCk3aREEqKioKDIyMhg7dqztKCqLIUOGkJiYyPvvv8+9995rO44KEPrx0QDWunVrduzYwebNm3XOGh/w66+/ct999/Hwww/z3XffISK2I6lCRj8+qv7G6XSSmprKggWXziKuvO3AgQN069aNq666irFjx2oJKK/SIghgISEhVKxYUQeNLUtPTyc8PJxDhw6RlJREpUqVbEdSAUaLIICVLl2a8PBwEhMTOXr0qO04AevNN99k3rx5/Oc//+HWW2+1HUcFIC2CAHdxIrqYmBjbUQLStGnTeP/993nssceIioqyHUcFKB0sDnDGGG69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\n",
+      "text/plain": [
+       "<Figure size 432x383.76 with 1 Axes>"
+      ]
+     },
+     "metadata": {
+      "needs_background": "light"
+     },
+     "output_type": "display_data"
+    }
+   ],
+   "source": [
+    "cfv.figure(3)\n",
+    "plt.plot([0, 9], [0, 0], color=(0.8, 0.8, 0.8))\n",
+    "plt.plot(\n",
+    "    np.concatenate(([0], ec1[:, 0], 3 + ec2[:, 0], [9]), 0),\n",
+    "    -np.concatenate(([0], es1[:, 1], es2[:, 1], [0]), 0) / 1000,\n",
+    "    color=(0.0, 0.0, 0.0),\n",
+    ")\n",
+    "cfv.title(\"bending moment\")"
+   ]
+  }
+ ],
+ "metadata": {
+  "kernelspec": {
+   "display_name": "Python 3 (ipykernel)",
+   "language": "python",
+   "name": "python3"
+  },
+  "language_info": {
+   "codemirror_mode": {
+    "name": "ipython",
+    "version": 3
+   },
+   "file_extension": ".py",
+   "mimetype": "text/x-python",
+   "name": "python",
+   "nbconvert_exporter": "python",
+   "pygments_lexer": "ipython3",
+   "version": "3.11.5"
+  }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/examples/exs_beam1.py b/examples/exs_beam1.py
index 4608101..0361cd1 100644
--- a/examples/exs_beam1.py
+++ b/examples/exs_beam1.py
@@ -1,10 +1,10 @@
 # -*- coding: utf-8 -*-
 #
 # example exs_beam1
-#----------------------------------------------------------------
-# PURPOSE 
+# ----------------------------------------------------------------
+# PURPOSE
 #    Analysis of a simply supported beam.
-#----------------------------------------------------------------
+# ----------------------------------------------------------------
 
 # REFERENCES
 #     Ola Dahlblom 2015-11-13
@@ -21,15 +21,15 @@
 # ----- Topology -------------------------------------------------
 
 edof = np.array([
-    [1,  2,  3,  4],
-    [3,  4,  5,  6]
+     [1, 2, 3, 4], 
+     [3, 4, 5, 6]
 ])
 
 # ----- Stiffness matrix K and load vector f ---------------------
 
 K = np.array(np.zeros((6, 6)))
 f = np.array(np.zeros((6, 1)))
-f[2] = -10e+3
+f[2] = -10e3
 
 # ----- Element stiffness and element load matrices  -------------
 
@@ -55,10 +55,8 @@
 bc = np.array([1, 5])
 a, r = cfc.solveq(K, f, bc)
 
-print("a = ")
-print(a)
-print("r = ")
-print(r)
+cfu.disp_array(a, ["a"])
+cfu.disp_array(r, ["r"])
 
 # ----- Section forces -------------------------------------------
 
@@ -67,34 +65,50 @@
 es1, ed1, ec1 = cfc.beam1s(ex1, ep, ed[0, :], eq1, nep=4)
 es2, ed2, ec2 = cfc.beam1s(ex2, ep, ed[1, :], eq2, nep=7)
 
-print("es1 = ")
-print(es1)
-print("ed1 = ")
-print(ed1)
-print("es2 = ")
-print(es2)
-print("ed2 = ")
-print(ed2)
-
-#----- Draw deformed beam ---------------------------------------
- 
+cfu.disp_h2("es1")
+cfu.disp_array(es1, ["V1", "M1"])
+cfu.disp_h2("ed1")
+cfu.disp_array(ed1, ["v1"])
+cfu.disp_h2("ec1")
+cfu.disp_array(ec1, ["x1"])
+cfu.disp_h2("es2")
+cfu.disp_array(es2, ["V2", "M2"])
+cfu.disp_h2("ed2")
+cfu.disp_array(ed2, ["v2"])
+cfu.disp_h2("ec2")
+cfu.disp_array(ec2, ["x2"])
+
+# ----- Draw deformed beam ---------------------------------------
+
 cfv.figure(1)
-plt.plot([0, 9],[0, 0], color=(0.8, 0.8, 0.8))
-plt.plot(np.concatenate(([0],ec1[:,0], 3+ec2[:,0],[9]), 0),np.concatenate(([0],ed1[:,0], ed2[:,0],[0]), 0), color=(0.0, 0.0, 0.0))
-cfv.title('displacements')
- 
-#----- Draw shear force diagram----------------------------------
+plt.plot([0, 9], [0, 0], color=(0.8, 0.8, 0.8))
+plt.plot(
+    np.concatenate(([0], ec1[:, 0], 3 + ec2[:, 0], [9]), 0),
+    np.concatenate(([0], ed1[:, 0], ed2[:, 0], [0]), 0),
+    color=(0.0, 0.0, 0.0),
+)
+cfv.title("displacements")
+
+# ----- Draw shear force diagram----------------------------------
 
 cfv.figure(2)
-plt.plot([0, 9],[0, 0], color=(0.8, 0.8, 0.8))
-plt.plot(np.concatenate(([0],ec1[:,0], 3+ec2[:,0],[9]), 0),-np.concatenate(([0],es1[:,0], es2[:,0],[0]), 0)/1000, color=(0.0, 0.0, 0.0))
-cfv.title('shear force')
+plt.plot([0, 9], [0, 0], color=(0.8, 0.8, 0.8))
+plt.plot(
+    np.concatenate(([0], ec1[:, 0], 3 + ec2[:, 0], [9]), 0),
+    -np.concatenate(([0], es1[:, 0], es2[:, 0], [0]), 0) / 1000,
+    color=(0.0, 0.0, 0.0),
+)
+cfv.title("shear force")
 
-#----- Draw moment diagram----------------------------------
+# ----- Draw moment diagram----------------------------------
 
 cfv.figure(3)
-plt.plot([0, 9],[0, 0], color=(0.8, 0.8, 0.8))
-plt.plot(np.concatenate(([0],ec1[:,0], 3+ec2[:,0],[9]), 0),-np.concatenate(([0],es1[:,1], es2[:,1],[0]), 0)/1000, color=(0.0, 0.0, 0.0))
-cfv.title('bending moment')
-
-cfv.showAndWait()
+plt.plot([0, 9], [0, 0], color=(0.8, 0.8, 0.8))
+plt.plot(
+    np.concatenate(([0], ec1[:, 0], 3 + ec2[:, 0], [9]), 0),
+    -np.concatenate(([0], es1[:, 1], es2[:, 1], [0]), 0) / 1000,
+    color=(0.0, 0.0, 0.0),
+)
+cfv.title("bending moment")
+
+cfv.show_and_wait()
diff --git a/examples/exs_beam2.ipynb b/examples/exs_beam2.ipynb
new file mode 100644
index 0000000..a105e86
--- /dev/null
+++ b/examples/exs_beam2.ipynb
@@ -0,0 +1,800 @@
+{
+ "cells": [
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "# Analysis of a simply supported beam"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": []
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {
+    "tags": []
+   },
+   "source": [
+    "Install CALFEM (if required)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 5,
+   "metadata": {
+    "tags": []
+   },
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "CALFEM already installed.\n"
+     ]
+    }
+   ],
+   "source": [
+    "from importlib.util import find_spec\n",
+    "\n",
+    "if find_spec(\"calfem.core\") is None:\n",
+    "    !pip install calfem-python\n",
+    "else:\n",
+    "    print(\"CALFEM already installed.\")"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "Import modules"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 1,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "import sys\n",
+    "import numpy as np\n",
+    "sys.path.insert(0, r'D:\\Users\\Jonas\\Development\\calfem-python')\n",
+    "import calfem.core as cfc\n",
+    "import calfem.utils as cfu\n",
+    "import calfem.vis_mpl as cfv"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "Define topology"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 2,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "edof = np.array([\n",
+    "    [4, 5, 6, 1, 2, 3], \n",
+    "    [7, 8, 9, 10, 11, 12], \n",
+    "    [4, 5, 6, 7, 8, 9]\n",
+    "])"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "Setup stiffness matrix K and load vector f"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 3,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "K = np.array(np.zeros((12, 12)))\n",
+    "f = np.array(np.zeros((12, 1)))\n",
+    "f[3] = 2.0e3"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "Setup element stiffness and element load matrices"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 4,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "E = 200.0e9\n",
+    "A1 = 2.0e-3\n",
+    "A2 = 6.0e-3\n",
+    "I1 = 1.6e-5\n",
+    "I2 = 5.4e-5\n",
+    "\n",
+    "ep1 = np.array([E, A1, I1])\n",
+    "ep3 = np.array([E, A2, I2])\n",
+    "ex1 = np.array([0, 0])\n",
+    "ex2 = np.array([6, 6])\n",
+    "ex3 = np.array([0, 6])\n",
+    "ey1 = np.array([4, 0])\n",
+    "ey2 = np.array([4, 0])\n",
+    "ey3 = np.array([4, 4])\n",
+    "eq1 = np.array([0, 0])\n",
+    "eq2 = np.array([0, 0])\n",
+    "eq3 = np.array([0, -10e3])\n",
+    "\n",
+    "Ke1 = cfc.beam2e(ex1, ey1, ep1)\n",
+    "Ke2 = cfc.beam2e(ex2, ey2, ep1)\n",
+    "Ke3, fe3 = cfc.beam2e(ex3, ey3, ep3, eq3)"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "Assemble Ke into K"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 5,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "K = cfc.assem(edof[0, :], K, Ke1)\n",
+    "K = cfc.assem(edof[1, :], K, Ke2)\n",
+    "K, f = cfc.assem(edof[2, :], K, Ke3, f, fe3)"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "Solve the system of equations and compute reactions"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 6,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/html": [
+       "<table>\n",
+       "<thead>\n",
+       "<tr><th style=\"text-align: right;\">  </th><th style=\"text-align: right;\">      a (m)</th></tr>\n",
+       "</thead>\n",
+       "<tbody>\n",
+       "<tr><td style=\"text-align: right;\"> 0</td><td style=\"text-align: right;\"> 0.0000e+00</td></tr>\n",
+       "<tr><td style=\"text-align: right;\"> 1</td><td style=\"text-align: right;\"> 0.0000e+00</td></tr>\n",
+       "<tr><td style=\"text-align: right;\"> 2</td><td style=\"text-align: right;\"> 0.0000e+00</td></tr>\n",
+       "<tr><td style=\"text-align: right;\"> 3</td><td style=\"text-align: right;\"> 7.5357e-03</td></tr>\n",
+       "<tr><td style=\"text-align: right;\"> 4</td><td style=\"text-align: right;\">-2.8741e-04</td></tr>\n",
+       "<tr><td style=\"text-align: right;\"> 5</td><td style=\"text-align: right;\">-5.3735e-03</td></tr>\n",
+       "<tr><td style=\"text-align: right;\"> 6</td><td style=\"text-align: right;\"> 7.5161e-03</td></tr>\n",
+       "<tr><td style=\"text-align: right;\"> 7</td><td style=\"text-align: right;\">-3.1259e-04</td></tr>\n",
+       "<tr><td style=\"text-align: right;\"> 8</td><td style=\"text-align: right;\"> 4.6656e-03</td></tr>\n",
+       "<tr><td style=\"text-align: right;\"> 9</td><td style=\"text-align: right;\"> 0.0000e+00</td></tr>\n",
+       "<tr><td style=\"text-align: right;\">10</td><td style=\"text-align: right;\"> 0.0000e+00</td></tr>\n",
+       "<tr><td style=\"text-align: right;\">11</td><td style=\"text-align: right;\">-5.1513e-03</td></tr>\n",
+       "</tbody>\n",
+       "</table>"
+      ],
+      "text/plain": [
+       "'<table>\\n<thead>\\n<tr><th style=\"text-align: right;\">  </th><th style=\"text-align: right;\">      a (m)</th></tr>\\n</thead>\\n<tbody>\\n<tr><td style=\"text-align: right;\"> 0</td><td style=\"text-align: right;\"> 0.0000e+00</td></tr>\\n<tr><td style=\"text-align: right;\"> 1</td><td style=\"text-align: right;\"> 0.0000e+00</td></tr>\\n<tr><td style=\"text-align: right;\"> 2</td><td style=\"text-align: right;\"> 0.0000e+00</td></tr>\\n<tr><td style=\"text-align: right;\"> 3</td><td style=\"text-align: right;\"> 7.5357e-03</td></tr>\\n<tr><td style=\"text-align: right;\"> 4</td><td style=\"text-align: right;\">-2.8741e-04</td></tr>\\n<tr><td style=\"text-align: right;\"> 5</td><td style=\"text-align: right;\">-5.3735e-03</td></tr>\\n<tr><td style=\"text-align: right;\"> 6</td><td style=\"text-align: right;\"> 7.5161e-03</td></tr>\\n<tr><td style=\"text-align: right;\"> 7</td><td style=\"text-align: right;\">-3.1259e-04</td></tr>\\n<tr><td style=\"text-align: right;\"> 8</td><td style=\"text-align: right;\"> 4.6656e-03</td></tr>\\n<tr><td style=\"text-align: right;\"> 9</td><td style=\"text-align: right;\"> 0.0000e+00</td></tr>\\n<tr><td style=\"text-align: right;\">10</td><td style=\"text-align: right;\"> 0.0000e+00</td></tr>\\n<tr><td style=\"text-align: right;\">11</td><td style=\"text-align: right;\">-5.1513e-03</td></tr>\\n</tbody>\\n</table>'"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
+    },
+    {
+     "data": {
+      "text/html": [
+       "<table>\n",
+       "<thead>\n",
+       "<tr><th style=\"text-align: right;\">  </th><th style=\"text-align: right;\">      r (N)</th></tr>\n",
+       "</thead>\n",
+       "<tbody>\n",
+       "<tr><td style=\"text-align: right;\"> 0</td><td style=\"text-align: right;\"> 1.9268e+03</td></tr>\n",
+       "<tr><td style=\"text-align: right;\"> 1</td><td style=\"text-align: right;\"> 2.8741e+04</td></tr>\n",
+       "<tr><td style=\"text-align: right;\"> 2</td><td style=\"text-align: right;\"> 4.4527e+02</td></tr>\n",
+       "<tr><td style=\"text-align: right;\"> 3</td><td style=\"text-align: right;\"> 0.0000e+00</td></tr>\n",
+       "<tr><td style=\"text-align: right;\"> 4</td><td style=\"text-align: right;\"> 0.0000e+00</td></tr>\n",
+       "<tr><td style=\"text-align: right;\"> 5</td><td style=\"text-align: right;\"> 0.0000e+00</td></tr>\n",
+       "<tr><td style=\"text-align: right;\"> 6</td><td style=\"text-align: right;\">-2.3283e-10</td></tr>\n",
+       "<tr><td style=\"text-align: right;\"> 7</td><td style=\"text-align: right;\"> 3.6380e-12</td></tr>\n",
+       "<tr><td style=\"text-align: right;\"> 8</td><td style=\"text-align: right;\"> 3.6380e-12</td></tr>\n",
+       "<tr><td style=\"text-align: right;\"> 9</td><td style=\"text-align: right;\">-3.9268e+03</td></tr>\n",
+       "<tr><td style=\"text-align: right;\">10</td><td style=\"text-align: right;\"> 3.1259e+04</td></tr>\n",
+       "<tr><td style=\"text-align: right;\">11</td><td style=\"text-align: right;\"> 0.0000e+00</td></tr>\n",
+       "</tbody>\n",
+       "</table>"
+      ],
+      "text/plain": [
+       "'<table>\\n<thead>\\n<tr><th style=\"text-align: right;\">  </th><th style=\"text-align: right;\">      r (N)</th></tr>\\n</thead>\\n<tbody>\\n<tr><td style=\"text-align: right;\"> 0</td><td style=\"text-align: right;\"> 1.9268e+03</td></tr>\\n<tr><td style=\"text-align: right;\"> 1</td><td style=\"text-align: right;\"> 2.8741e+04</td></tr>\\n<tr><td style=\"text-align: right;\"> 2</td><td style=\"text-align: right;\"> 4.4527e+02</td></tr>\\n<tr><td style=\"text-align: right;\"> 3</td><td style=\"text-align: right;\"> 0.0000e+00</td></tr>\\n<tr><td style=\"text-align: right;\"> 4</td><td style=\"text-align: right;\"> 0.0000e+00</td></tr>\\n<tr><td style=\"text-align: right;\"> 5</td><td style=\"text-align: right;\"> 0.0000e+00</td></tr>\\n<tr><td style=\"text-align: right;\"> 6</td><td style=\"text-align: right;\">-2.3283e-10</td></tr>\\n<tr><td style=\"text-align: right;\"> 7</td><td style=\"text-align: right;\"> 3.6380e-12</td></tr>\\n<tr><td style=\"text-align: right;\"> 8</td><td style=\"text-align: right;\"> 3.6380e-12</td></tr>\\n<tr><td style=\"text-align: right;\"> 9</td><td style=\"text-align: right;\">-3.9268e+03</td></tr>\\n<tr><td style=\"text-align: right;\">10</td><td style=\"text-align: right;\"> 3.1259e+04</td></tr>\\n<tr><td style=\"text-align: right;\">11</td><td style=\"text-align: right;\"> 0.0000e+00</td></tr>\\n</tbody>\\n</table>'"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
+    }
+   ],
+   "source": [
+    "bc = np.array([1, 2, 3, 10, 11])\n",
+    "a, r = cfc.solveq(K, f, bc)\n",
+    "\n",
+    "cfu.disp_array(a, [\"a (m)\"])\n",
+    "cfu.disp_array(r, [\"r (N)\"])"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "Section forces"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 7,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/html": [
+       "<h2>es1</h2>"
+      ],
+      "text/plain": [
+       "<IPython.core.display.HTML object>"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
+    },
+    {
+     "data": {
+      "text/html": [
+       "<table>\n",
+       "<thead>\n",
+       "<tr><th style=\"text-align: right;\">  </th><th style=\"text-align: right;\">          N</th><th style=\"text-align: right;\">        Vy</th><th style=\"text-align: right;\">        Mz</th></tr>\n",
+       "</thead>\n",
+       "<tbody>\n",
+       "<tr><td style=\"text-align: right;\"> 0</td><td style=\"text-align: right;\">-2.8741e+04</td><td style=\"text-align: right;\">1.9268e+03</td><td style=\"text-align: right;\">8.1523e+03</td></tr>\n",
+       "<tr><td style=\"text-align: right;\"> 1</td><td style=\"text-align: right;\">-2.8741e+04</td><td style=\"text-align: right;\">1.9268e+03</td><td style=\"text-align: right;\">7.7670e+03</td></tr>\n",
+       "<tr><td style=\"text-align: right;\"> 2</td><td style=\"text-align: right;\">-2.8741e+04</td><td style=\"text-align: right;\">1.9268e+03</td><td style=\"text-align: right;\">7.3816e+03</td></tr>\n",
+       "<tr><td style=\"text-align: right;\"> 3</td><td style=\"text-align: right;\">-2.8741e+04</td><td style=\"text-align: right;\">1.9268e+03</td><td style=\"text-align: right;\">6.9963e+03</td></tr>\n",
+       "<tr><td style=\"text-align: right;\"> 4</td><td style=\"text-align: right;\">-2.8741e+04</td><td style=\"text-align: right;\">1.9268e+03</td><td style=\"text-align: right;\">6.6109e+03</td></tr>\n",
+       "<tr><td style=\"text-align: right;\"> 5</td><td style=\"text-align: right;\">-2.8741e+04</td><td style=\"text-align: right;\">1.9268e+03</td><td style=\"text-align: right;\">6.2256e+03</td></tr>\n",
+       "<tr><td style=\"text-align: right;\"> 6</td><td style=\"text-align: right;\">-2.8741e+04</td><td style=\"text-align: right;\">1.9268e+03</td><td style=\"text-align: right;\">5.8402e+03</td></tr>\n",
+       "<tr><td style=\"text-align: right;\"> 7</td><td style=\"text-align: right;\">-2.8741e+04</td><td style=\"text-align: right;\">1.9268e+03</td><td style=\"text-align: right;\">5.4548e+03</td></tr>\n",
+       "<tr><td style=\"text-align: right;\"> 8</td><td style=\"text-align: right;\">-2.8741e+04</td><td style=\"text-align: right;\">1.9268e+03</td><td style=\"text-align: right;\">5.0695e+03</td></tr>\n",
+       "<tr><td style=\"text-align: right;\"> 9</td><td style=\"text-align: right;\">-2.8741e+04</td><td style=\"text-align: right;\">1.9268e+03</td><td style=\"text-align: right;\">4.6841e+03</td></tr>\n",
+       "<tr><td style=\"text-align: right;\">10</td><td style=\"text-align: right;\">-2.8741e+04</td><td style=\"text-align: right;\">1.9268e+03</td><td style=\"text-align: right;\">4.2988e+03</td></tr>\n",
+       "<tr><td style=\"text-align: right;\">11</td><td style=\"text-align: right;\">-2.8741e+04</td><td style=\"text-align: right;\">1.9268e+03</td><td style=\"text-align: right;\">3.9134e+03</td></tr>\n",
+       "<tr><td style=\"text-align: right;\">12</td><td style=\"text-align: right;\">-2.8741e+04</td><td style=\"text-align: right;\">1.9268e+03</td><td style=\"text-align: right;\">3.5281e+03</td></tr>\n",
+       "<tr><td style=\"text-align: right;\">13</td><td style=\"text-align: right;\">-2.8741e+04</td><td style=\"text-align: right;\">1.9268e+03</td><td style=\"text-align: right;\">3.1427e+03</td></tr>\n",
+       "<tr><td style=\"text-align: right;\">14</td><td style=\"text-align: right;\">-2.8741e+04</td><td style=\"text-align: right;\">1.9268e+03</td><td style=\"text-align: right;\">2.7574e+03</td></tr>\n",
+       "<tr><td style=\"text-align: right;\">15</td><td style=\"text-align: right;\">-2.8741e+04</td><td style=\"text-align: right;\">1.9268e+03</td><td style=\"text-align: right;\">2.3720e+03</td></tr>\n",
+       "<tr><td style=\"text-align: right;\">16</td><td style=\"text-align: right;\">-2.8741e+04</td><td style=\"text-align: right;\">1.9268e+03</td><td style=\"text-align: right;\">1.9867e+03</td></tr>\n",
+       "<tr><td style=\"text-align: right;\">17</td><td style=\"text-align: right;\">-2.8741e+04</td><td style=\"text-align: right;\">1.9268e+03</td><td style=\"text-align: right;\">1.6013e+03</td></tr>\n",
+       "<tr><td style=\"text-align: right;\">18</td><td style=\"text-align: right;\">-2.8741e+04</td><td style=\"text-align: right;\">1.9268e+03</td><td style=\"text-align: right;\">1.2160e+03</td></tr>\n",
+       "<tr><td style=\"text-align: right;\">19</td><td style=\"text-align: right;\">-2.8741e+04</td><td style=\"text-align: right;\">1.9268e+03</td><td style=\"text-align: right;\">8.3062e+02</td></tr>\n",
+       "<tr><td style=\"text-align: right;\">20</td><td style=\"text-align: right;\">-2.8741e+04</td><td style=\"text-align: right;\">1.9268e+03</td><td style=\"text-align: right;\">4.4527e+02</td></tr>\n",
+       "</tbody>\n",
+       "</table>"
+      ],
+      "text/plain": [
+       "'<table>\\n<thead>\\n<tr><th style=\"text-align: right;\">  </th><th style=\"text-align: right;\">          N</th><th style=\"text-align: right;\">        Vy</th><th style=\"text-align: right;\">        Mz</th></tr>\\n</thead>\\n<tbody>\\n<tr><td style=\"text-align: right;\"> 0</td><td style=\"text-align: right;\">-2.8741e+04</td><td style=\"text-align: right;\">1.9268e+03</td><td style=\"text-align: right;\">8.1523e+03</td></tr>\\n<tr><td style=\"text-align: right;\"> 1</td><td style=\"text-align: right;\">-2.8741e+04</td><td style=\"text-align: right;\">1.9268e+03</td><td style=\"text-align: right;\">7.7670e+03</td></tr>\\n<tr><td style=\"text-align: right;\"> 2</td><td style=\"text-align: right;\">-2.8741e+04</td><td style=\"text-align: right;\">1.9268e+03</td><td style=\"text-align: right;\">7.3816e+03</td></tr>\\n<tr><td style=\"text-align: right;\"> 3</td><td style=\"text-align: right;\">-2.8741e+04</td><td style=\"text-align: right;\">1.9268e+03</td><td style=\"text-align: right;\">6.9963e+03</td></tr>\\n<tr><td style=\"text-align: right;\"> 4</td><td style=\"text-align: right;\">-2.8741e+04</td><td style=\"text-align: right;\">1.9268e+03</td><td style=\"text-align: right;\">6.6109e+03</td></tr>\\n<tr><td style=\"text-align: right;\"> 5</td><td style=\"text-align: right;\">-2.8741e+04</td><td style=\"text-align: right;\">1.9268e+03</td><td style=\"text-align: right;\">6.2256e+03</td></tr>\\n<tr><td style=\"text-align: right;\"> 6</td><td style=\"text-align: right;\">-2.8741e+04</td><td style=\"text-align: right;\">1.9268e+03</td><td style=\"text-align: right;\">5.8402e+03</td></tr>\\n<tr><td style=\"text-align: right;\"> 7</td><td style=\"text-align: right;\">-2.8741e+04</td><td style=\"text-align: right;\">1.9268e+03</td><td style=\"text-align: right;\">5.4548e+03</td></tr>\\n<tr><td style=\"text-align: right;\"> 8</td><td style=\"text-align: right;\">-2.8741e+04</td><td style=\"text-align: right;\">1.9268e+03</td><td style=\"text-align: right;\">5.0695e+03</td></tr>\\n<tr><td style=\"text-align: right;\"> 9</td><td style=\"text-align: right;\">-2.8741e+04</td><td style=\"text-align: right;\">1.9268e+03</td><td style=\"text-align: right;\">4.6841e+03</td></tr>\\n<tr><td style=\"text-align: right;\">10</td><td style=\"text-align: right;\">-2.8741e+04</td><td style=\"text-align: right;\">1.9268e+03</td><td style=\"text-align: right;\">4.2988e+03</td></tr>\\n<tr><td style=\"text-align: right;\">11</td><td style=\"text-align: right;\">-2.8741e+04</td><td style=\"text-align: right;\">1.9268e+03</td><td style=\"text-align: right;\">3.9134e+03</td></tr>\\n<tr><td style=\"text-align: right;\">12</td><td style=\"text-align: right;\">-2.8741e+04</td><td style=\"text-align: right;\">1.9268e+03</td><td style=\"text-align: right;\">3.5281e+03</td></tr>\\n<tr><td style=\"text-align: right;\">13</td><td style=\"text-align: right;\">-2.8741e+04</td><td style=\"text-align: right;\">1.9268e+03</td><td style=\"text-align: right;\">3.1427e+03</td></tr>\\n<tr><td style=\"text-align: right;\">14</td><td style=\"text-align: right;\">-2.8741e+04</td><td style=\"text-align: right;\">1.9268e+03</td><td style=\"text-align: right;\">2.7574e+03</td></tr>\\n<tr><td style=\"text-align: right;\">15</td><td style=\"text-align: right;\">-2.8741e+04</td><td style=\"text-align: right;\">1.9268e+03</td><td style=\"text-align: right;\">2.3720e+03</td></tr>\\n<tr><td style=\"text-align: right;\">16</td><td style=\"text-align: right;\">-2.8741e+04</td><td style=\"text-align: right;\">1.9268e+03</td><td style=\"text-align: right;\">1.9867e+03</td></tr>\\n<tr><td style=\"text-align: right;\">17</td><td style=\"text-align: right;\">-2.8741e+04</td><td style=\"text-align: right;\">1.9268e+03</td><td style=\"text-align: right;\">1.6013e+03</td></tr>\\n<tr><td style=\"text-align: right;\">18</td><td style=\"text-align: right;\">-2.8741e+04</td><td style=\"text-align: right;\">1.9268e+03</td><td style=\"text-align: right;\">1.2160e+03</td></tr>\\n<tr><td style=\"text-align: right;\">19</td><td style=\"text-align: right;\">-2.8741e+04</td><td style=\"text-align: right;\">1.9268e+03</td><td style=\"text-align: right;\">8.3062e+02</td></tr>\\n<tr><td style=\"text-align: right;\">20</td><td style=\"text-align: right;\">-2.8741e+04</td><td style=\"text-align: right;\">1.9268e+03</td><td style=\"text-align: right;\">4.4527e+02</td></tr>\\n</tbody>\\n</table>'"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
+    },
+    {
+     "data": {
+      "text/html": [
+       "<h2>edi1</h2>"
+      ],
+      "text/plain": [
+       "<IPython.core.display.HTML object>"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
+    },
+    {
+     "data": {
+      "text/html": [
+       "<table>\n",
+       "<thead>\n",
+       "<tr><th style=\"text-align: right;\">  </th><th style=\"text-align: right;\">        u1</th><th style=\"text-align: right;\">        v1</th></tr>\n",
+       "</thead>\n",
+       "<tbody>\n",
+       "<tr><td style=\"text-align: right;\"> 0</td><td style=\"text-align: right;\">2.8741e-04</td><td style=\"text-align: right;\">7.5357e-03</td></tr>\n",
+       "<tr><td style=\"text-align: right;\"> 1</td><td style=\"text-align: right;\">2.7304e-04</td><td style=\"text-align: right;\">6.5112e-03</td></tr>\n",
+       "<tr><td style=\"text-align: right;\"> 2</td><td style=\"text-align: right;\">2.5867e-04</td><td style=\"text-align: right;\">5.5837e-03</td></tr>\n",
+       "<tr><td style=\"text-align: right;\"> 3</td><td style=\"text-align: right;\">2.4430e-04</td><td style=\"text-align: right;\">4.7485e-03</td></tr>\n",
+       "<tr><td style=\"text-align: right;\"> 4</td><td style=\"text-align: right;\">2.2993e-04</td><td style=\"text-align: right;\">4.0008e-03</td></tr>\n",
+       "<tr><td style=\"text-align: right;\"> 5</td><td style=\"text-align: right;\">2.1556e-04</td><td style=\"text-align: right;\">3.3357e-03</td></tr>\n",
+       "<tr><td style=\"text-align: right;\"> 6</td><td style=\"text-align: right;\">2.0119e-04</td><td style=\"text-align: right;\">2.7484e-03</td></tr>\n",
+       "<tr><td style=\"text-align: right;\"> 7</td><td style=\"text-align: right;\">1.8682e-04</td><td style=\"text-align: right;\">2.2341e-03</td></tr>\n",
+       "<tr><td style=\"text-align: right;\"> 8</td><td style=\"text-align: right;\">1.7245e-04</td><td style=\"text-align: right;\">1.7880e-03</td></tr>\n",
+       "<tr><td style=\"text-align: right;\"> 9</td><td style=\"text-align: right;\">1.5807e-04</td><td style=\"text-align: right;\">1.4053e-03</td></tr>\n",
+       "<tr><td style=\"text-align: right;\">10</td><td style=\"text-align: right;\">1.4370e-04</td><td style=\"text-align: right;\">1.0811e-03</td></tr>\n",
+       "<tr><td style=\"text-align: right;\">11</td><td style=\"text-align: right;\">1.2933e-04</td><td style=\"text-align: right;\">8.1067e-04</td></tr>\n",
+       "<tr><td style=\"text-align: right;\">12</td><td style=\"text-align: right;\">1.1496e-04</td><td style=\"text-align: right;\">5.8915e-04</td></tr>\n",
+       "<tr><td style=\"text-align: right;\">13</td><td style=\"text-align: right;\">1.0059e-04</td><td style=\"text-align: right;\">4.1173e-04</td></tr>\n",
+       "<tr><td style=\"text-align: right;\">14</td><td style=\"text-align: right;\">8.6223e-05</td><td style=\"text-align: right;\">2.7359e-04</td></tr>\n",
+       "<tr><td style=\"text-align: right;\">15</td><td style=\"text-align: right;\">7.1852e-05</td><td style=\"text-align: right;\">1.6993e-04</td></tr>\n",
+       "<tr><td style=\"text-align: right;\">16</td><td style=\"text-align: right;\">5.7482e-05</td><td style=\"text-align: right;\">9.5907e-05</td></tr>\n",
+       "<tr><td style=\"text-align: right;\">17</td><td style=\"text-align: right;\">4.3111e-05</td><td style=\"text-align: right;\">4.6722e-05</td></tr>\n",
+       "<tr><td style=\"text-align: right;\">18</td><td style=\"text-align: right;\">2.8741e-05</td><td style=\"text-align: right;\">1.7554e-05</td></tr>\n",
+       "<tr><td style=\"text-align: right;\">19</td><td style=\"text-align: right;\">1.4370e-05</td><td style=\"text-align: right;\">3.5858e-06</td></tr>\n",
+       "<tr><td style=\"text-align: right;\">20</td><td style=\"text-align: right;\">0.0000e+00</td><td style=\"text-align: right;\">1.7347e-18</td></tr>\n",
+       "</tbody>\n",
+       "</table>"
+      ],
+      "text/plain": [
+       "'<table>\\n<thead>\\n<tr><th style=\"text-align: right;\">  </th><th style=\"text-align: right;\">        u1</th><th style=\"text-align: right;\">        v1</th></tr>\\n</thead>\\n<tbody>\\n<tr><td style=\"text-align: right;\"> 0</td><td style=\"text-align: right;\">2.8741e-04</td><td style=\"text-align: right;\">7.5357e-03</td></tr>\\n<tr><td style=\"text-align: right;\"> 1</td><td style=\"text-align: right;\">2.7304e-04</td><td style=\"text-align: right;\">6.5112e-03</td></tr>\\n<tr><td style=\"text-align: right;\"> 2</td><td style=\"text-align: right;\">2.5867e-04</td><td style=\"text-align: right;\">5.5837e-03</td></tr>\\n<tr><td style=\"text-align: right;\"> 3</td><td style=\"text-align: right;\">2.4430e-04</td><td style=\"text-align: right;\">4.7485e-03</td></tr>\\n<tr><td style=\"text-align: right;\"> 4</td><td style=\"text-align: right;\">2.2993e-04</td><td style=\"text-align: right;\">4.0008e-03</td></tr>\\n<tr><td style=\"text-align: right;\"> 5</td><td style=\"text-align: right;\">2.1556e-04</td><td style=\"text-align: right;\">3.3357e-03</td></tr>\\n<tr><td style=\"text-align: right;\"> 6</td><td style=\"text-align: right;\">2.0119e-04</td><td style=\"text-align: right;\">2.7484e-03</td></tr>\\n<tr><td style=\"text-align: right;\"> 7</td><td style=\"text-align: right;\">1.8682e-04</td><td style=\"text-align: right;\">2.2341e-03</td></tr>\\n<tr><td style=\"text-align: right;\"> 8</td><td style=\"text-align: right;\">1.7245e-04</td><td style=\"text-align: right;\">1.7880e-03</td></tr>\\n<tr><td style=\"text-align: right;\"> 9</td><td style=\"text-align: right;\">1.5807e-04</td><td style=\"text-align: right;\">1.4053e-03</td></tr>\\n<tr><td style=\"text-align: right;\">10</td><td style=\"text-align: right;\">1.4370e-04</td><td style=\"text-align: right;\">1.0811e-03</td></tr>\\n<tr><td style=\"text-align: right;\">11</td><td style=\"text-align: right;\">1.2933e-04</td><td style=\"text-align: right;\">8.1067e-04</td></tr>\\n<tr><td style=\"text-align: right;\">12</td><td style=\"text-align: right;\">1.1496e-04</td><td style=\"text-align: right;\">5.8915e-04</td></tr>\\n<tr><td style=\"text-align: right;\">13</td><td style=\"text-align: right;\">1.0059e-04</td><td style=\"text-align: right;\">4.1173e-04</td></tr>\\n<tr><td style=\"text-align: right;\">14</td><td style=\"text-align: right;\">8.6223e-05</td><td style=\"text-align: right;\">2.7359e-04</td></tr>\\n<tr><td style=\"text-align: right;\">15</td><td style=\"text-align: right;\">7.1852e-05</td><td style=\"text-align: right;\">1.6993e-04</td></tr>\\n<tr><td style=\"text-align: right;\">16</td><td style=\"text-align: right;\">5.7482e-05</td><td style=\"text-align: right;\">9.5907e-05</td></tr>\\n<tr><td style=\"text-align: right;\">17</td><td style=\"text-align: right;\">4.3111e-05</td><td style=\"text-align: right;\">4.6722e-05</td></tr>\\n<tr><td style=\"text-align: right;\">18</td><td style=\"text-align: right;\">2.8741e-05</td><td style=\"text-align: right;\">1.7554e-05</td></tr>\\n<tr><td style=\"text-align: right;\">19</td><td style=\"text-align: right;\">1.4370e-05</td><td style=\"text-align: right;\">3.5858e-06</td></tr>\\n<tr><td style=\"text-align: right;\">20</td><td style=\"text-align: right;\">0.0000e+00</td><td style=\"text-align: right;\">1.7347e-18</td></tr>\\n</tbody>\\n</table>'"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
+    },
+    {
+     "data": {
+      "text/html": [
+       "<h2>es2</h2>"
+      ],
+      "text/plain": [
+       "<IPython.core.display.HTML object>"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
+    },
+    {
+     "data": {
+      "text/html": [
+       "<table>\n",
+       "<thead>\n",
+       "<tr><th style=\"text-align: right;\">  </th><th style=\"text-align: right;\">          N</th><th style=\"text-align: right;\">         Vy</th><th style=\"text-align: right;\">         Mz</th></tr>\n",
+       "</thead>\n",
+       "<tbody>\n",
+       "<tr><td style=\"text-align: right;\"> 0</td><td style=\"text-align: right;\">-3.1259e+04</td><td style=\"text-align: right;\">-3.9268e+03</td><td style=\"text-align: right;\">-1.5707e+04</td></tr>\n",
+       "<tr><td style=\"text-align: right;\"> 1</td><td style=\"text-align: right;\">-3.1259e+04</td><td style=\"text-align: right;\">-3.9268e+03</td><td style=\"text-align: right;\">-1.4922e+04</td></tr>\n",
+       "<tr><td style=\"text-align: right;\"> 2</td><td style=\"text-align: right;\">-3.1259e+04</td><td style=\"text-align: right;\">-3.9268e+03</td><td style=\"text-align: right;\">-1.4136e+04</td></tr>\n",
+       "<tr><td style=\"text-align: right;\"> 3</td><td style=\"text-align: right;\">-3.1259e+04</td><td style=\"text-align: right;\">-3.9268e+03</td><td style=\"text-align: right;\">-1.3351e+04</td></tr>\n",
+       "<tr><td style=\"text-align: right;\"> 4</td><td style=\"text-align: right;\">-3.1259e+04</td><td style=\"text-align: right;\">-3.9268e+03</td><td style=\"text-align: right;\">-1.2566e+04</td></tr>\n",
+       "<tr><td style=\"text-align: right;\"> 5</td><td style=\"text-align: right;\">-3.1259e+04</td><td style=\"text-align: right;\">-3.9268e+03</td><td style=\"text-align: right;\">-1.1780e+04</td></tr>\n",
+       "<tr><td style=\"text-align: right;\"> 6</td><td style=\"text-align: right;\">-3.1259e+04</td><td style=\"text-align: right;\">-3.9268e+03</td><td style=\"text-align: right;\">-1.0995e+04</td></tr>\n",
+       "<tr><td style=\"text-align: right;\"> 7</td><td style=\"text-align: right;\">-3.1259e+04</td><td style=\"text-align: right;\">-3.9268e+03</td><td style=\"text-align: right;\">-1.0210e+04</td></tr>\n",
+       "<tr><td style=\"text-align: right;\"> 8</td><td style=\"text-align: right;\">-3.1259e+04</td><td style=\"text-align: right;\">-3.9268e+03</td><td style=\"text-align: right;\">-9.4242e+03</td></tr>\n",
+       "<tr><td style=\"text-align: right;\"> 9</td><td style=\"text-align: right;\">-3.1259e+04</td><td style=\"text-align: right;\">-3.9268e+03</td><td style=\"text-align: right;\">-8.6389e+03</td></tr>\n",
+       "<tr><td style=\"text-align: right;\">10</td><td style=\"text-align: right;\">-3.1259e+04</td><td style=\"text-align: right;\">-3.9268e+03</td><td style=\"text-align: right;\">-7.8535e+03</td></tr>\n",
+       "<tr><td style=\"text-align: right;\">11</td><td style=\"text-align: right;\">-3.1259e+04</td><td style=\"text-align: right;\">-3.9268e+03</td><td style=\"text-align: right;\">-7.0682e+03</td></tr>\n",
+       "<tr><td style=\"text-align: right;\">12</td><td style=\"text-align: right;\">-3.1259e+04</td><td style=\"text-align: right;\">-3.9268e+03</td><td style=\"text-align: right;\">-6.2828e+03</td></tr>\n",
+       "<tr><td style=\"text-align: right;\">13</td><td style=\"text-align: right;\">-3.1259e+04</td><td style=\"text-align: right;\">-3.9268e+03</td><td style=\"text-align: right;\">-5.4975e+03</td></tr>\n",
+       "<tr><td style=\"text-align: right;\">14</td><td style=\"text-align: right;\">-3.1259e+04</td><td style=\"text-align: right;\">-3.9268e+03</td><td style=\"text-align: right;\">-4.7121e+03</td></tr>\n",
+       "<tr><td style=\"text-align: right;\">15</td><td style=\"text-align: right;\">-3.1259e+04</td><td style=\"text-align: right;\">-3.9268e+03</td><td style=\"text-align: right;\">-3.9268e+03</td></tr>\n",
+       "<tr><td style=\"text-align: right;\">16</td><td style=\"text-align: right;\">-3.1259e+04</td><td style=\"text-align: right;\">-3.9268e+03</td><td style=\"text-align: right;\">-3.1414e+03</td></tr>\n",
+       "<tr><td style=\"text-align: right;\">17</td><td style=\"text-align: right;\">-3.1259e+04</td><td style=\"text-align: right;\">-3.9268e+03</td><td style=\"text-align: right;\">-2.3561e+03</td></tr>\n",
+       "<tr><td style=\"text-align: right;\">18</td><td style=\"text-align: right;\">-3.1259e+04</td><td style=\"text-align: right;\">-3.9268e+03</td><td style=\"text-align: right;\">-1.5707e+03</td></tr>\n",
+       "<tr><td style=\"text-align: right;\">19</td><td style=\"text-align: right;\">-3.1259e+04</td><td style=\"text-align: right;\">-3.9268e+03</td><td style=\"text-align: right;\">-7.8535e+02</td></tr>\n",
+       "<tr><td style=\"text-align: right;\">20</td><td style=\"text-align: right;\">-3.1259e+04</td><td style=\"text-align: right;\">-3.9268e+03</td><td style=\"text-align: right;\"> 5.5511e-12</td></tr>\n",
+       "</tbody>\n",
+       "</table>"
+      ],
+      "text/plain": [
+       "'<table>\\n<thead>\\n<tr><th style=\"text-align: right;\">  </th><th style=\"text-align: right;\">          N</th><th style=\"text-align: right;\">         Vy</th><th style=\"text-align: right;\">         Mz</th></tr>\\n</thead>\\n<tbody>\\n<tr><td style=\"text-align: right;\"> 0</td><td style=\"text-align: right;\">-3.1259e+04</td><td style=\"text-align: right;\">-3.9268e+03</td><td style=\"text-align: right;\">-1.5707e+04</td></tr>\\n<tr><td style=\"text-align: right;\"> 1</td><td style=\"text-align: right;\">-3.1259e+04</td><td style=\"text-align: right;\">-3.9268e+03</td><td style=\"text-align: right;\">-1.4922e+04</td></tr>\\n<tr><td style=\"text-align: right;\"> 2</td><td style=\"text-align: right;\">-3.1259e+04</td><td style=\"text-align: right;\">-3.9268e+03</td><td style=\"text-align: right;\">-1.4136e+04</td></tr>\\n<tr><td style=\"text-align: right;\"> 3</td><td style=\"text-align: right;\">-3.1259e+04</td><td style=\"text-align: right;\">-3.9268e+03</td><td style=\"text-align: right;\">-1.3351e+04</td></tr>\\n<tr><td style=\"text-align: right;\"> 4</td><td style=\"text-align: right;\">-3.1259e+04</td><td style=\"text-align: right;\">-3.9268e+03</td><td style=\"text-align: right;\">-1.2566e+04</td></tr>\\n<tr><td style=\"text-align: right;\"> 5</td><td style=\"text-align: right;\">-3.1259e+04</td><td style=\"text-align: right;\">-3.9268e+03</td><td style=\"text-align: right;\">-1.1780e+04</td></tr>\\n<tr><td style=\"text-align: right;\"> 6</td><td style=\"text-align: right;\">-3.1259e+04</td><td style=\"text-align: right;\">-3.9268e+03</td><td style=\"text-align: right;\">-1.0995e+04</td></tr>\\n<tr><td style=\"text-align: right;\"> 7</td><td style=\"text-align: right;\">-3.1259e+04</td><td style=\"text-align: right;\">-3.9268e+03</td><td style=\"text-align: right;\">-1.0210e+04</td></tr>\\n<tr><td style=\"text-align: right;\"> 8</td><td style=\"text-align: right;\">-3.1259e+04</td><td style=\"text-align: right;\">-3.9268e+03</td><td style=\"text-align: right;\">-9.4242e+03</td></tr>\\n<tr><td style=\"text-align: right;\"> 9</td><td style=\"text-align: right;\">-3.1259e+04</td><td style=\"text-align: right;\">-3.9268e+03</td><td style=\"text-align: right;\">-8.6389e+03</td></tr>\\n<tr><td style=\"text-align: right;\">10</td><td style=\"text-align: right;\">-3.1259e+04</td><td style=\"text-align: right;\">-3.9268e+03</td><td style=\"text-align: right;\">-7.8535e+03</td></tr>\\n<tr><td style=\"text-align: right;\">11</td><td style=\"text-align: right;\">-3.1259e+04</td><td style=\"text-align: right;\">-3.9268e+03</td><td style=\"text-align: right;\">-7.0682e+03</td></tr>\\n<tr><td style=\"text-align: right;\">12</td><td style=\"text-align: right;\">-3.1259e+04</td><td style=\"text-align: right;\">-3.9268e+03</td><td style=\"text-align: right;\">-6.2828e+03</td></tr>\\n<tr><td style=\"text-align: right;\">13</td><td style=\"text-align: right;\">-3.1259e+04</td><td style=\"text-align: right;\">-3.9268e+03</td><td style=\"text-align: right;\">-5.4975e+03</td></tr>\\n<tr><td style=\"text-align: right;\">14</td><td style=\"text-align: right;\">-3.1259e+04</td><td style=\"text-align: right;\">-3.9268e+03</td><td style=\"text-align: right;\">-4.7121e+03</td></tr>\\n<tr><td style=\"text-align: right;\">15</td><td style=\"text-align: right;\">-3.1259e+04</td><td style=\"text-align: right;\">-3.9268e+03</td><td style=\"text-align: right;\">-3.9268e+03</td></tr>\\n<tr><td style=\"text-align: right;\">16</td><td style=\"text-align: right;\">-3.1259e+04</td><td style=\"text-align: right;\">-3.9268e+03</td><td style=\"text-align: right;\">-3.1414e+03</td></tr>\\n<tr><td style=\"text-align: right;\">17</td><td style=\"text-align: right;\">-3.1259e+04</td><td style=\"text-align: right;\">-3.9268e+03</td><td style=\"text-align: right;\">-2.3561e+03</td></tr>\\n<tr><td style=\"text-align: right;\">18</td><td style=\"text-align: right;\">-3.1259e+04</td><td style=\"text-align: right;\">-3.9268e+03</td><td style=\"text-align: right;\">-1.5707e+03</td></tr>\\n<tr><td style=\"text-align: right;\">19</td><td style=\"text-align: right;\">-3.1259e+04</td><td style=\"text-align: right;\">-3.9268e+03</td><td style=\"text-align: right;\">-7.8535e+02</td></tr>\\n<tr><td style=\"text-align: right;\">20</td><td style=\"text-align: right;\">-3.1259e+04</td><td style=\"text-align: right;\">-3.9268e+03</td><td style=\"text-align: right;\"> 5.5511e-12</td></tr>\\n</tbody>\\n</table>'"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
+    },
+    {
+     "data": {
+      "text/html": [
+       "<h2>edi2</h2>"
+      ],
+      "text/plain": [
+       "<IPython.core.display.HTML object>"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
+    },
+    {
+     "data": {
+      "text/html": [
+       "<table>\n",
+       "<thead>\n",
+       "<tr><th style=\"text-align: right;\">  </th><th style=\"text-align: right;\">        u1</th><th style=\"text-align: right;\">        v1</th></tr>\n",
+       "</thead>\n",
+       "<tbody>\n",
+       "<tr><td style=\"text-align: right;\"> 0</td><td style=\"text-align: right;\">3.1259e-04</td><td style=\"text-align: right;\">7.5161e-03</td></tr>\n",
+       "<tr><td style=\"text-align: right;\"> 1</td><td style=\"text-align: right;\">2.9696e-04</td><td style=\"text-align: right;\">8.3527e-03</td></tr>\n",
+       "<tr><td style=\"text-align: right;\"> 2</td><td style=\"text-align: right;\">2.8133e-04</td><td style=\"text-align: right;\">9.0027e-03</td></tr>\n",
+       "<tr><td style=\"text-align: right;\"> 3</td><td style=\"text-align: right;\">2.6570e-04</td><td style=\"text-align: right;\">9.4761e-03</td></tr>\n",
+       "<tr><td style=\"text-align: right;\"> 4</td><td style=\"text-align: right;\">2.5007e-04</td><td style=\"text-align: right;\">9.7825e-03</td></tr>\n",
+       "<tr><td style=\"text-align: right;\"> 5</td><td style=\"text-align: right;\">2.3444e-04</td><td style=\"text-align: right;\">9.9319e-03</td></tr>\n",
+       "<tr><td style=\"text-align: right;\"> 6</td><td style=\"text-align: right;\">2.1881e-04</td><td style=\"text-align: right;\">9.9341e-03</td></tr>\n",
+       "<tr><td style=\"text-align: right;\"> 7</td><td style=\"text-align: right;\">2.0318e-04</td><td style=\"text-align: right;\">9.7988e-03</td></tr>\n",
+       "<tr><td style=\"text-align: right;\"> 8</td><td style=\"text-align: right;\">1.8755e-04</td><td style=\"text-align: right;\">9.5359e-03</td></tr>\n",
+       "<tr><td style=\"text-align: right;\"> 9</td><td style=\"text-align: right;\">1.7193e-04</td><td style=\"text-align: right;\">9.1552e-03</td></tr>\n",
+       "<tr><td style=\"text-align: right;\">10</td><td style=\"text-align: right;\">1.5630e-04</td><td style=\"text-align: right;\">8.6665e-03</td></tr>\n",
+       "<tr><td style=\"text-align: right;\">11</td><td style=\"text-align: right;\">1.4067e-04</td><td style=\"text-align: right;\">8.0796e-03</td></tr>\n",
+       "<tr><td style=\"text-align: right;\">12</td><td style=\"text-align: right;\">1.2504e-04</td><td style=\"text-align: right;\">7.4044e-03</td></tr>\n",
+       "<tr><td style=\"text-align: right;\">13</td><td style=\"text-align: right;\">1.0941e-04</td><td style=\"text-align: right;\">6.6506e-03</td></tr>\n",
+       "<tr><td style=\"text-align: right;\">14</td><td style=\"text-align: right;\">9.3777e-05</td><td style=\"text-align: right;\">5.8282e-03</td></tr>\n",
+       "<tr><td style=\"text-align: right;\">15</td><td style=\"text-align: right;\">7.8148e-05</td><td style=\"text-align: right;\">4.9468e-03</td></tr>\n",
+       "<tr><td style=\"text-align: right;\">16</td><td style=\"text-align: right;\">6.2518e-05</td><td style=\"text-align: right;\">4.0163e-03</td></tr>\n",
+       "<tr><td style=\"text-align: right;\">17</td><td style=\"text-align: right;\">4.6889e-05</td><td style=\"text-align: right;\">3.0466e-03</td></tr>\n",
+       "<tr><td style=\"text-align: right;\">18</td><td style=\"text-align: right;\">3.1259e-05</td><td style=\"text-align: right;\">2.0474e-03</td></tr>\n",
+       "<tr><td style=\"text-align: right;\">19</td><td style=\"text-align: right;\">1.5630e-05</td><td style=\"text-align: right;\">1.0286e-03</td></tr>\n",
+       "<tr><td style=\"text-align: right;\">20</td><td style=\"text-align: right;\">0.0000e+00</td><td style=\"text-align: right;\">3.4694e-18</td></tr>\n",
+       "</tbody>\n",
+       "</table>"
+      ],
+      "text/plain": [
+       "'<table>\\n<thead>\\n<tr><th style=\"text-align: right;\">  </th><th style=\"text-align: right;\">        u1</th><th style=\"text-align: right;\">        v1</th></tr>\\n</thead>\\n<tbody>\\n<tr><td style=\"text-align: right;\"> 0</td><td style=\"text-align: right;\">3.1259e-04</td><td style=\"text-align: right;\">7.5161e-03</td></tr>\\n<tr><td style=\"text-align: right;\"> 1</td><td style=\"text-align: right;\">2.9696e-04</td><td style=\"text-align: right;\">8.3527e-03</td></tr>\\n<tr><td style=\"text-align: right;\"> 2</td><td style=\"text-align: right;\">2.8133e-04</td><td style=\"text-align: right;\">9.0027e-03</td></tr>\\n<tr><td style=\"text-align: right;\"> 3</td><td style=\"text-align: right;\">2.6570e-04</td><td style=\"text-align: right;\">9.4761e-03</td></tr>\\n<tr><td style=\"text-align: right;\"> 4</td><td style=\"text-align: right;\">2.5007e-04</td><td style=\"text-align: right;\">9.7825e-03</td></tr>\\n<tr><td style=\"text-align: right;\"> 5</td><td style=\"text-align: right;\">2.3444e-04</td><td style=\"text-align: right;\">9.9319e-03</td></tr>\\n<tr><td style=\"text-align: right;\"> 6</td><td style=\"text-align: right;\">2.1881e-04</td><td style=\"text-align: right;\">9.9341e-03</td></tr>\\n<tr><td style=\"text-align: right;\"> 7</td><td style=\"text-align: right;\">2.0318e-04</td><td style=\"text-align: right;\">9.7988e-03</td></tr>\\n<tr><td style=\"text-align: right;\"> 8</td><td style=\"text-align: right;\">1.8755e-04</td><td style=\"text-align: right;\">9.5359e-03</td></tr>\\n<tr><td style=\"text-align: right;\"> 9</td><td style=\"text-align: right;\">1.7193e-04</td><td style=\"text-align: right;\">9.1552e-03</td></tr>\\n<tr><td style=\"text-align: right;\">10</td><td style=\"text-align: right;\">1.5630e-04</td><td style=\"text-align: right;\">8.6665e-03</td></tr>\\n<tr><td style=\"text-align: right;\">11</td><td style=\"text-align: right;\">1.4067e-04</td><td style=\"text-align: right;\">8.0796e-03</td></tr>\\n<tr><td style=\"text-align: right;\">12</td><td style=\"text-align: right;\">1.2504e-04</td><td style=\"text-align: right;\">7.4044e-03</td></tr>\\n<tr><td style=\"text-align: right;\">13</td><td style=\"text-align: right;\">1.0941e-04</td><td style=\"text-align: right;\">6.6506e-03</td></tr>\\n<tr><td style=\"text-align: right;\">14</td><td style=\"text-align: right;\">9.3777e-05</td><td style=\"text-align: right;\">5.8282e-03</td></tr>\\n<tr><td style=\"text-align: right;\">15</td><td style=\"text-align: right;\">7.8148e-05</td><td style=\"text-align: right;\">4.9468e-03</td></tr>\\n<tr><td style=\"text-align: right;\">16</td><td style=\"text-align: right;\">6.2518e-05</td><td style=\"text-align: right;\">4.0163e-03</td></tr>\\n<tr><td style=\"text-align: right;\">17</td><td style=\"text-align: right;\">4.6889e-05</td><td style=\"text-align: right;\">3.0466e-03</td></tr>\\n<tr><td style=\"text-align: right;\">18</td><td style=\"text-align: right;\">3.1259e-05</td><td style=\"text-align: right;\">2.0474e-03</td></tr>\\n<tr><td style=\"text-align: right;\">19</td><td style=\"text-align: right;\">1.5630e-05</td><td style=\"text-align: right;\">1.0286e-03</td></tr>\\n<tr><td style=\"text-align: right;\">20</td><td style=\"text-align: right;\">0.0000e+00</td><td style=\"text-align: right;\">3.4694e-18</td></tr>\\n</tbody>\\n</table>'"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
+    },
+    {
+     "data": {
+      "text/html": [
+       "<h2>es3</h2>"
+      ],
+      "text/plain": [
+       "<IPython.core.display.HTML object>"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
+    },
+    {
+     "data": {
+      "text/html": [
+       "<table>\n",
+       "<thead>\n",
+       "<tr><th style=\"text-align: right;\">  </th><th style=\"text-align: right;\">          N</th><th style=\"text-align: right;\">         Vy</th><th style=\"text-align: right;\">         Mz</th></tr>\n",
+       "</thead>\n",
+       "<tbody>\n",
+       "<tr><td style=\"text-align: right;\"> 0</td><td style=\"text-align: right;\">-3.9268e+03</td><td style=\"text-align: right;\">-2.8741e+04</td><td style=\"text-align: right;\">-8.1523e+03</td></tr>\n",
+       "<tr><td style=\"text-align: right;\"> 1</td><td style=\"text-align: right;\">-3.9268e+03</td><td style=\"text-align: right;\">-2.5741e+04</td><td style=\"text-align: right;\"> 1.9953e+01</td></tr>\n",
+       "<tr><td style=\"text-align: right;\"> 2</td><td style=\"text-align: right;\">-3.9268e+03</td><td style=\"text-align: right;\">-2.2741e+04</td><td style=\"text-align: right;\"> 7.2922e+03</td></tr>\n",
+       "<tr><td style=\"text-align: right;\"> 3</td><td style=\"text-align: right;\">-3.9268e+03</td><td style=\"text-align: right;\">-1.9741e+04</td><td style=\"text-align: right;\"> 1.3664e+04</td></tr>\n",
+       "<tr><td style=\"text-align: right;\"> 4</td><td style=\"text-align: right;\">-3.9268e+03</td><td style=\"text-align: right;\">-1.6741e+04</td><td style=\"text-align: right;\"> 1.9137e+04</td></tr>\n",
+       "<tr><td style=\"text-align: right;\"> 5</td><td style=\"text-align: right;\">-3.9268e+03</td><td style=\"text-align: right;\">-1.3741e+04</td><td style=\"text-align: right;\"> 2.3709e+04</td></tr>\n",
+       "<tr><td style=\"text-align: right;\"> 6</td><td style=\"text-align: right;\">-3.9268e+03</td><td style=\"text-align: right;\">-1.0741e+04</td><td style=\"text-align: right;\"> 2.7381e+04</td></tr>\n",
+       "<tr><td style=\"text-align: right;\"> 7</td><td style=\"text-align: right;\">-3.9268e+03</td><td style=\"text-align: right;\">-7.7409e+03</td><td style=\"text-align: right;\"> 3.0154e+04</td></tr>\n",
+       "<tr><td style=\"text-align: right;\"> 8</td><td style=\"text-align: right;\">-3.9268e+03</td><td style=\"text-align: right;\">-4.7409e+03</td><td style=\"text-align: right;\"> 3.2026e+04</td></tr>\n",
+       "<tr><td style=\"text-align: right;\"> 9</td><td style=\"text-align: right;\">-3.9268e+03</td><td style=\"text-align: right;\">-1.7409e+03</td><td style=\"text-align: right;\"> 3.2998e+04</td></tr>\n",
+       "<tr><td style=\"text-align: right;\">10</td><td style=\"text-align: right;\">-3.9268e+03</td><td style=\"text-align: right;\"> 1.2591e+03</td><td style=\"text-align: right;\"> 3.3070e+04</td></tr>\n",
+       "<tr><td style=\"text-align: right;\">11</td><td style=\"text-align: right;\">-3.9268e+03</td><td style=\"text-align: right;\"> 4.2591e+03</td><td style=\"text-align: right;\"> 3.2243e+04</td></tr>\n",
+       "<tr><td style=\"text-align: right;\">12</td><td style=\"text-align: right;\">-3.9268e+03</td><td style=\"text-align: right;\"> 7.2591e+03</td><td style=\"text-align: right;\"> 3.0515e+04</td></tr>\n",
+       "<tr><td style=\"text-align: right;\">13</td><td style=\"text-align: right;\">-3.9268e+03</td><td style=\"text-align: right;\"> 1.0259e+04</td><td style=\"text-align: right;\"> 2.7887e+04</td></tr>\n",
+       "<tr><td style=\"text-align: right;\">14</td><td style=\"text-align: right;\">-3.9268e+03</td><td style=\"text-align: right;\"> 1.3259e+04</td><td style=\"text-align: right;\"> 2.4359e+04</td></tr>\n",
+       "<tr><td style=\"text-align: right;\">15</td><td style=\"text-align: right;\">-3.9268e+03</td><td style=\"text-align: right;\"> 1.6259e+04</td><td style=\"text-align: right;\"> 1.9932e+04</td></tr>\n",
+       "<tr><td style=\"text-align: right;\">16</td><td style=\"text-align: right;\">-3.9268e+03</td><td style=\"text-align: right;\"> 1.9259e+04</td><td style=\"text-align: right;\"> 1.4604e+04</td></tr>\n",
+       "<tr><td style=\"text-align: right;\">17</td><td style=\"text-align: right;\">-3.9268e+03</td><td style=\"text-align: right;\"> 2.2259e+04</td><td style=\"text-align: right;\"> 8.3762e+03</td></tr>\n",
+       "<tr><td style=\"text-align: right;\">18</td><td style=\"text-align: right;\">-3.9268e+03</td><td style=\"text-align: right;\"> 2.5259e+04</td><td style=\"text-align: right;\"> 1.2484e+03</td></tr>\n",
+       "<tr><td style=\"text-align: right;\">19</td><td style=\"text-align: right;\">-3.9268e+03</td><td style=\"text-align: right;\"> 2.8259e+04</td><td style=\"text-align: right;\">-6.7793e+03</td></tr>\n",
+       "<tr><td style=\"text-align: right;\">20</td><td style=\"text-align: right;\">-3.9268e+03</td><td style=\"text-align: right;\"> 3.1259e+04</td><td style=\"text-align: right;\">-1.5707e+04</td></tr>\n",
+       "</tbody>\n",
+       "</table>"
+      ],
+      "text/plain": [
+       "'<table>\\n<thead>\\n<tr><th style=\"text-align: right;\">  </th><th style=\"text-align: right;\">          N</th><th style=\"text-align: right;\">         Vy</th><th style=\"text-align: right;\">         Mz</th></tr>\\n</thead>\\n<tbody>\\n<tr><td style=\"text-align: right;\"> 0</td><td style=\"text-align: right;\">-3.9268e+03</td><td style=\"text-align: right;\">-2.8741e+04</td><td style=\"text-align: right;\">-8.1523e+03</td></tr>\\n<tr><td style=\"text-align: right;\"> 1</td><td style=\"text-align: right;\">-3.9268e+03</td><td style=\"text-align: right;\">-2.5741e+04</td><td style=\"text-align: right;\"> 1.9953e+01</td></tr>\\n<tr><td style=\"text-align: right;\"> 2</td><td style=\"text-align: right;\">-3.9268e+03</td><td style=\"text-align: right;\">-2.2741e+04</td><td style=\"text-align: right;\"> 7.2922e+03</td></tr>\\n<tr><td style=\"text-align: right;\"> 3</td><td style=\"text-align: right;\">-3.9268e+03</td><td style=\"text-align: right;\">-1.9741e+04</td><td style=\"text-align: right;\"> 1.3664e+04</td></tr>\\n<tr><td style=\"text-align: right;\"> 4</td><td style=\"text-align: right;\">-3.9268e+03</td><td style=\"text-align: right;\">-1.6741e+04</td><td style=\"text-align: right;\"> 1.9137e+04</td></tr>\\n<tr><td style=\"text-align: right;\"> 5</td><td style=\"text-align: right;\">-3.9268e+03</td><td style=\"text-align: right;\">-1.3741e+04</td><td style=\"text-align: right;\"> 2.3709e+04</td></tr>\\n<tr><td style=\"text-align: right;\"> 6</td><td style=\"text-align: right;\">-3.9268e+03</td><td style=\"text-align: right;\">-1.0741e+04</td><td style=\"text-align: right;\"> 2.7381e+04</td></tr>\\n<tr><td style=\"text-align: right;\"> 7</td><td style=\"text-align: right;\">-3.9268e+03</td><td style=\"text-align: right;\">-7.7409e+03</td><td style=\"text-align: right;\"> 3.0154e+04</td></tr>\\n<tr><td style=\"text-align: right;\"> 8</td><td style=\"text-align: right;\">-3.9268e+03</td><td style=\"text-align: right;\">-4.7409e+03</td><td style=\"text-align: right;\"> 3.2026e+04</td></tr>\\n<tr><td style=\"text-align: right;\"> 9</td><td style=\"text-align: right;\">-3.9268e+03</td><td style=\"text-align: right;\">-1.7409e+03</td><td style=\"text-align: right;\"> 3.2998e+04</td></tr>\\n<tr><td style=\"text-align: right;\">10</td><td style=\"text-align: right;\">-3.9268e+03</td><td style=\"text-align: right;\"> 1.2591e+03</td><td style=\"text-align: right;\"> 3.3070e+04</td></tr>\\n<tr><td style=\"text-align: right;\">11</td><td style=\"text-align: right;\">-3.9268e+03</td><td style=\"text-align: right;\"> 4.2591e+03</td><td style=\"text-align: right;\"> 3.2243e+04</td></tr>\\n<tr><td style=\"text-align: right;\">12</td><td style=\"text-align: right;\">-3.9268e+03</td><td style=\"text-align: right;\"> 7.2591e+03</td><td style=\"text-align: right;\"> 3.0515e+04</td></tr>\\n<tr><td style=\"text-align: right;\">13</td><td style=\"text-align: right;\">-3.9268e+03</td><td style=\"text-align: right;\"> 1.0259e+04</td><td style=\"text-align: right;\"> 2.7887e+04</td></tr>\\n<tr><td style=\"text-align: right;\">14</td><td style=\"text-align: right;\">-3.9268e+03</td><td style=\"text-align: right;\"> 1.3259e+04</td><td style=\"text-align: right;\"> 2.4359e+04</td></tr>\\n<tr><td style=\"text-align: right;\">15</td><td style=\"text-align: right;\">-3.9268e+03</td><td style=\"text-align: right;\"> 1.6259e+04</td><td style=\"text-align: right;\"> 1.9932e+04</td></tr>\\n<tr><td style=\"text-align: right;\">16</td><td style=\"text-align: right;\">-3.9268e+03</td><td style=\"text-align: right;\"> 1.9259e+04</td><td style=\"text-align: right;\"> 1.4604e+04</td></tr>\\n<tr><td style=\"text-align: right;\">17</td><td style=\"text-align: right;\">-3.9268e+03</td><td style=\"text-align: right;\"> 2.2259e+04</td><td style=\"text-align: right;\"> 8.3762e+03</td></tr>\\n<tr><td style=\"text-align: right;\">18</td><td style=\"text-align: right;\">-3.9268e+03</td><td style=\"text-align: right;\"> 2.5259e+04</td><td style=\"text-align: right;\"> 1.2484e+03</td></tr>\\n<tr><td style=\"text-align: right;\">19</td><td style=\"text-align: right;\">-3.9268e+03</td><td style=\"text-align: right;\"> 2.8259e+04</td><td style=\"text-align: right;\">-6.7793e+03</td></tr>\\n<tr><td style=\"text-align: right;\">20</td><td style=\"text-align: right;\">-3.9268e+03</td><td style=\"text-align: right;\"> 3.1259e+04</td><td style=\"text-align: right;\">-1.5707e+04</td></tr>\\n</tbody>\\n</table>'"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
+    },
+    {
+     "data": {
+      "text/html": [
+       "<h2>edi3</h2>"
+      ],
+      "text/plain": [
+       "<IPython.core.display.HTML object>"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
+    },
+    {
+     "data": {
+      "text/html": [
+       "<table>\n",
+       "<thead>\n",
+       "<tr><th style=\"text-align: right;\">  </th><th style=\"text-align: right;\">        u1</th><th style=\"text-align: right;\">         v1</th></tr>\n",
+       "</thead>\n",
+       "<tbody>\n",
+       "<tr><td style=\"text-align: right;\"> 0</td><td style=\"text-align: right;\">7.5357e-03</td><td style=\"text-align: right;\">-2.8741e-04</td></tr>\n",
+       "<tr><td style=\"text-align: right;\"> 1</td><td style=\"text-align: right;\">7.5347e-03</td><td style=\"text-align: right;\">-1.9218e-03</td></tr>\n",
+       "<tr><td style=\"text-align: right;\"> 2</td><td style=\"text-align: right;\">7.5337e-03</td><td style=\"text-align: right;\">-3.5566e-03</td></tr>\n",
+       "<tr><td style=\"text-align: right;\"> 3</td><td style=\"text-align: right;\">7.5328e-03</td><td style=\"text-align: right;\">-5.1312e-03</td></tr>\n",
+       "<tr><td style=\"text-align: right;\"> 4</td><td style=\"text-align: right;\">7.5318e-03</td><td style=\"text-align: right;\">-6.5927e-03</td></tr>\n",
+       "<tr><td style=\"text-align: right;\"> 5</td><td style=\"text-align: right;\">7.5308e-03</td><td style=\"text-align: right;\">-7.8952e-03</td></tr>\n",
+       "<tr><td style=\"text-align: right;\"> 6</td><td style=\"text-align: right;\">7.5298e-03</td><td style=\"text-align: right;\">-9.0009e-03</td></tr>\n",
+       "<tr><td style=\"text-align: right;\"> 7</td><td style=\"text-align: right;\">7.5288e-03</td><td style=\"text-align: right;\">-9.8789e-03</td></tr>\n",
+       "<tr><td style=\"text-align: right;\"> 8</td><td style=\"text-align: right;\">7.5279e-03</td><td style=\"text-align: right;\">-1.0506e-02</td></tr>\n",
+       "<tr><td style=\"text-align: right;\"> 9</td><td style=\"text-align: right;\">7.5269e-03</td><td style=\"text-align: right;\">-1.0868e-02</td></tr>\n",
+       "<tr><td style=\"text-align: right;\">10</td><td style=\"text-align: right;\">7.5259e-03</td><td style=\"text-align: right;\">-1.0954e-02</td></tr>\n",
+       "<tr><td style=\"text-align: right;\">11</td><td style=\"text-align: right;\">7.5249e-03</td><td style=\"text-align: right;\">-1.0766e-02</td></tr>\n",
+       "<tr><td style=\"text-align: right;\">12</td><td style=\"text-align: right;\">7.5239e-03</td><td style=\"text-align: right;\">-1.0310e-02</td></tr>\n",
+       "<tr><td style=\"text-align: right;\">13</td><td style=\"text-align: right;\">7.5229e-03</td><td style=\"text-align: right;\">-9.6000e-03</td></tr>\n",
+       "<tr><td style=\"text-align: right;\">14</td><td style=\"text-align: right;\">7.5220e-03</td><td style=\"text-align: right;\">-8.6584e-03</td></tr>\n",
+       "<tr><td style=\"text-align: right;\">15</td><td style=\"text-align: right;\">7.5210e-03</td><td style=\"text-align: right;\">-7.5143e-03</td></tr>\n",
+       "<tr><td style=\"text-align: right;\">16</td><td style=\"text-align: right;\">7.5200e-03</td><td style=\"text-align: right;\">-6.2048e-03</td></tr>\n",
+       "<tr><td style=\"text-align: right;\">17</td><td style=\"text-align: right;\">7.5190e-03</td><td style=\"text-align: right;\">-4.7743e-03</td></tr>\n",
+       "<tr><td style=\"text-align: right;\">18</td><td style=\"text-align: right;\">7.5180e-03</td><td style=\"text-align: right;\">-3.2745e-03</td></tr>\n",
+       "<tr><td style=\"text-align: right;\">19</td><td style=\"text-align: right;\">7.5171e-03</td><td style=\"text-align: right;\">-1.7650e-03</td></tr>\n",
+       "<tr><td style=\"text-align: right;\">20</td><td style=\"text-align: right;\">7.5161e-03</td><td style=\"text-align: right;\">-3.1259e-04</td></tr>\n",
+       "</tbody>\n",
+       "</table>"
+      ],
+      "text/plain": [
+       "'<table>\\n<thead>\\n<tr><th style=\"text-align: right;\">  </th><th style=\"text-align: right;\">        u1</th><th style=\"text-align: right;\">         v1</th></tr>\\n</thead>\\n<tbody>\\n<tr><td style=\"text-align: right;\"> 0</td><td style=\"text-align: right;\">7.5357e-03</td><td style=\"text-align: right;\">-2.8741e-04</td></tr>\\n<tr><td style=\"text-align: right;\"> 1</td><td style=\"text-align: right;\">7.5347e-03</td><td style=\"text-align: right;\">-1.9218e-03</td></tr>\\n<tr><td style=\"text-align: right;\"> 2</td><td style=\"text-align: right;\">7.5337e-03</td><td style=\"text-align: right;\">-3.5566e-03</td></tr>\\n<tr><td style=\"text-align: right;\"> 3</td><td style=\"text-align: right;\">7.5328e-03</td><td style=\"text-align: right;\">-5.1312e-03</td></tr>\\n<tr><td style=\"text-align: right;\"> 4</td><td style=\"text-align: right;\">7.5318e-03</td><td style=\"text-align: right;\">-6.5927e-03</td></tr>\\n<tr><td style=\"text-align: right;\"> 5</td><td style=\"text-align: right;\">7.5308e-03</td><td style=\"text-align: right;\">-7.8952e-03</td></tr>\\n<tr><td style=\"text-align: right;\"> 6</td><td style=\"text-align: right;\">7.5298e-03</td><td style=\"text-align: right;\">-9.0009e-03</td></tr>\\n<tr><td style=\"text-align: right;\"> 7</td><td style=\"text-align: right;\">7.5288e-03</td><td style=\"text-align: right;\">-9.8789e-03</td></tr>\\n<tr><td style=\"text-align: right;\"> 8</td><td style=\"text-align: right;\">7.5279e-03</td><td style=\"text-align: right;\">-1.0506e-02</td></tr>\\n<tr><td style=\"text-align: right;\"> 9</td><td style=\"text-align: right;\">7.5269e-03</td><td style=\"text-align: right;\">-1.0868e-02</td></tr>\\n<tr><td style=\"text-align: right;\">10</td><td style=\"text-align: right;\">7.5259e-03</td><td style=\"text-align: right;\">-1.0954e-02</td></tr>\\n<tr><td style=\"text-align: right;\">11</td><td style=\"text-align: right;\">7.5249e-03</td><td style=\"text-align: right;\">-1.0766e-02</td></tr>\\n<tr><td style=\"text-align: right;\">12</td><td style=\"text-align: right;\">7.5239e-03</td><td style=\"text-align: right;\">-1.0310e-02</td></tr>\\n<tr><td style=\"text-align: right;\">13</td><td style=\"text-align: right;\">7.5229e-03</td><td style=\"text-align: right;\">-9.6000e-03</td></tr>\\n<tr><td style=\"text-align: right;\">14</td><td style=\"text-align: right;\">7.5220e-03</td><td style=\"text-align: right;\">-8.6584e-03</td></tr>\\n<tr><td style=\"text-align: right;\">15</td><td style=\"text-align: right;\">7.5210e-03</td><td style=\"text-align: right;\">-7.5143e-03</td></tr>\\n<tr><td style=\"text-align: right;\">16</td><td style=\"text-align: right;\">7.5200e-03</td><td style=\"text-align: right;\">-6.2048e-03</td></tr>\\n<tr><td style=\"text-align: right;\">17</td><td style=\"text-align: right;\">7.5190e-03</td><td style=\"text-align: right;\">-4.7743e-03</td></tr>\\n<tr><td style=\"text-align: right;\">18</td><td style=\"text-align: right;\">7.5180e-03</td><td style=\"text-align: right;\">-3.2745e-03</td></tr>\\n<tr><td style=\"text-align: right;\">19</td><td style=\"text-align: right;\">7.5171e-03</td><td style=\"text-align: right;\">-1.7650e-03</td></tr>\\n<tr><td style=\"text-align: right;\">20</td><td style=\"text-align: right;\">7.5161e-03</td><td style=\"text-align: right;\">-3.1259e-04</td></tr>\\n</tbody>\\n</table>'"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
+    }
+   ],
+   "source": [
+    "ed = cfc.extract_ed(edof, a)\n",
+    "\n",
+    "es1, edi1, ec1 = cfc.beam2s(ex1, ey1, ep1, ed[0, :], eq1, nep=21)\n",
+    "es2, edi2, ec2 = cfc.beam2s(ex2, ey2, ep1, ed[1, :], eq2, nep=21)\n",
+    "es3, edi3, ec3 = cfc.beam2s(ex3, ey3, ep3, ed[2, :], eq3, nep=21)\n",
+    "\n",
+    "cfu.disp_h2(\"es1\")\n",
+    "cfu.disp_array(es1, [\"N\", \"Vy\", \"Mz\"])\n",
+    "cfu.disp_h2(\"edi1\")\n",
+    "cfu.disp_array(edi1, [\"u1\", \"v1\"])\n",
+    "cfu.disp_h2(\"es2\")\n",
+    "cfu.disp_array(es2, [\"N\", \"Vy\", \"Mz\"])\n",
+    "cfu.disp_h2(\"edi2\")\n",
+    "cfu.disp_array(edi2, [\"u1\", \"v1\"])\n",
+    "cfu.disp_h2(\"es3\")\n",
+    "cfu.disp_array(es3, [\"N\", \"Vy\", \"Mz\"])\n",
+    "cfu.disp_h2(\"edi3\")\n",
+    "cfu.disp_array(edi3, [\"u1\", \"v1\"])\n"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "Draw deformed frame"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 8,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/html": [
+       "sfac=54.77300198398877"
+      ],
+      "text/plain": [
+       "<IPython.core.display.HTML object>"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
+    },
+    {
+     "data": {
+      "image/png": "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",
+      "text/plain": [
+       "<Figure size 720x720 with 1 Axes>"
+      ]
+     },
+     "metadata": {
+      "needs_background": "light"
+     },
+     "output_type": "display_data"
+    }
+   ],
+   "source": [
+    "plotpar = [2, 1, 0]\n",
+    "sfac = cfv.scalfact2(ex3, ey3, edi3, 0.1)\n",
+    "cfu.disp(f\"sfac={sfac}\")\n",
+    "\n",
+    "cfv.figure(1, fig_size=(10, 10))\n",
+    "cfv.eldraw2(ex1, ey1, plotpar)\n",
+    "cfv.eldraw2(ex2, ey2, plotpar)\n",
+    "cfv.eldraw2(ex3, ey3, plotpar)\n",
+    "\n",
+    "plotpar = [1, 2, 1]\n",
+    "cfv.dispbeam2(ex1, ey1, edi1, plotpar, sfac)\n",
+    "cfv.dispbeam2(ex2, ey2, edi2, plotpar, sfac)\n",
+    "cfv.dispbeam2(ex3, ey3, edi3, plotpar, sfac)\n",
+    "cfv.axis([-1.5, 7.5, -0.5, 5.5])\n",
+    "plotpar1 = 2\n",
+    "cfv.scalgraph2(sfac, [1e-2, 0.5, 0], plotpar1)\n",
+    "cfv.title(\"Displacements\")"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "Draw normal force diagram"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 9,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "image/png": "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",
+      "text/plain": [
+       "<Figure size 720x720 with 1 Axes>"
+      ]
+     },
+     "metadata": {
+      "needs_background": "light"
+     },
+     "output_type": "display_data"
+    }
+   ],
+   "source": [
+    "plotpar = [2, 1]\n",
+    "sfac = cfv.scalfact2(ex3, ey3, es3[:, 1], 0.2)\n",
+    "cfv.figure(3, fig_size=(10, 10))\n",
+    "cfv.secforce2(ex1, ey1, es1[:, 1], plotpar, sfac)\n",
+    "cfv.secforce2(ex2, ey2, es2[:, 1], plotpar, sfac)\n",
+    "cfv.secforce2(ex3, ey3, es3[:, 1], plotpar, sfac)\n",
+    "cfv.axis([-1.5, 7.5, -0.5, 5.5])\n",
+    "cfv.scalgraph2(sfac, [3e4, 0.5, 0], plotpar1)\n",
+    "cfv.title(\"Shear force\")"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "Draw shear force diagram"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 10,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/html": [
+       "sfac=3.628630851048567e-05"
+      ],
+      "text/plain": [
+       "<IPython.core.display.HTML object>"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
+    },
+    {
+     "data": {
+      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAkkAAAJOCAYAAACjhZOMAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjUuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/YYfK9AAAACXBIWXMAAAsTAAALEwEAmpwYAAA6lUlEQVR4nO3dd3yV5f3/8feHhJkTRGQqILSgFhyoiAPrQKniFid10P6sfL/u2X7bilqts8MOR5WKe+CeVdzWrRXFiloVrQOaACpDkZlcvz+upAS4Q06Sc851j9fz8bgfSU6Sw/sAOeed67ru6zbnnAAAALCqNqEDAAAAxBElCQAAIAIlCQAAIAIlCQAAIAIlCQAAIAIlCQAAIAIlCQAAIAIlCUDBmNknZrbMzLqtdvs0M3Nm1j9QtDWY2Q1mdkHoHADii5IEoND+LWls/QdmtpmkjuHiAEDLUJIAFNrNko5u8PE4STfVf2Bm65jZTWY218w+NbMJZtam7nM/MrMXzewPZjbfzD42sx3qbv/czOaY2bgG99XezH5nZp+Z2Wwzu9rMOtZ9bhczm2lmZ9R9X5WZ/bjuc+MlHSHpZ2b2jZk9VIK/FwAJQ0kCUGivSOpsZt8zszJJh0m6pcHnL5e0jqTvSNpZvlD9uMHnt5X0T0nrSbpN0mRJ20gaKOlISVeYWa7uay+VtJGkoXWf30DSOQ3uq1fdn7WBpGMkXWlm6zrnJkq6VdJvnHM559y+hXnoANKEkgSgGOpHk0ZJ+pekWXW315emXzjnvnbOfSLp95KOavC9/3bOXe+cq5F0h6S+ks53zi11zj0uaZmkgWZmko6VdJpz7ivn3NeSLpJ0eIP7Wl73vcudc49I+kbSxsV5yADSpjx0AACpdLOk5yQNUIOpNkndJLWT9GmD2z6VH+mpN7vB+4slyTm3+m05Sd0ldZI01fclSZLJF7F6XzrnVjT4+Nu67wWAJjGSBKDgnHOfyi/g3kvSvQ0+9YX86M6GDW7rp5UjTc3xhXxhGuKc61J3rOOcy7cEuRb8mQAyhJIEoFiOkTTSObeowW01ku6UdKGZVZrZhpJO16prlvLinKuV9FdJfzCzHpJkZhuY2R553sVs+XVRABCJkgSgKJxzHznnXo/41EmSFkn6WNIL8ouzr2vhH/N/kmZIesXMFkp6UvmvOZokaXDdWXT3t/DPB5Bi5hwjzgAAAKtjJAkAACACJQkAACACJQkAACACJQkAACBCUTaT7Natm+vfv38x7hoAAKCgpk6d+oVzrvvqtxelJPXv31+vvx515i8AAEC8mNmnUbcz3QYAABCBkgQAABCBkgQAABCBkgQAABCBkgQAABCBkgQAABCBkgQAABCBkgQAABCBkgQAABCBkgQAABCBkgQAABCBkgQAABCBkgQAABCBkgQAABCBkgQAABCBkgQAABCBkgQAABCBkgQAABCBkgQAABCBkgQAABCBkgQAABCBkgQAABCBkgQAABCBkgQAABCBkgQAABCBkgQAABCBkgQAABCBkgQAABCBkgQAABCBkgQAABCBkgQAABCBkgQAABCBkgQAABCBkgQAABCBkgQAABCBkgQAABCBkgQAABCBkgQAABCBkgQAABCBkgQAABChPJ8vMrNPJH0tqUbSCufcsGKGAgAACC2vklRnV+fcF0VLAgAAECNMtwEAAETItyQ5SY+b2VQzG1/MQAAAAHGQ73TbCOfcf8ysh6QnzOxfzrnnGn5BXXkaL0n9+vUrcEwAAIDSymskyTn3n7q3cyTdJ2l4xNdMdM4Nc84N6969e2FTAgAAlFiTJcnMKsyssv59ST+QNL3YwQAAAELKZ7qtp6T7zKz+629zzk0paioAAIDAmixJzrmPJW1RgiwAAACxwRYAAAAAEShJAAAAEShJAAAAEShJAAAAEShJAAAAEShJAAAAEShJAAAAEShJAAAAEShJAAAAEShJAAAAEShJAAAAEShJAAAAEShJAAAAEShJAAAAEShJAAAAEShJAAAAEShJAAAAEShJAAAAEShJAAAAEShJAAAAEShJAAAAEShJAAAAEShJAAAAEShJAAAAEShJAAAAEShJAAAAEShJAAAAEShJAAAAEShJAAAAEShJAAAAEShJAAAAEShJAAAAEShJAADExIIFoROgIUoSAAAxMGuWtMkmklnoJKhHSQIAIAZOPlk69tjQKdAQJQkAgMDuv1+aPl365S9DJ0FD5aEDAACQZQsXSiedJN1yi9ShQ+g0aIiRJAAAAvrlL6U99pB23jl0EqyOkSQAAAJ5+WXp3nuld94JnQRRGEkCACCAZcuk8eOlP/xBWnfd0GkQhZIEAEAAv/ud1K+fdOihoZOgMUy3AQBQYh98IF12mTR1KvsixRkjSQAAlJBz0v/8jzRh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",
+      "text/plain": [
+       "<Figure size 720x720 with 1 Axes>"
+      ]
+     },
+     "metadata": {
+      "needs_background": "light"
+     },
+     "output_type": "display_data"
+    }
+   ],
+   "source": [
+    "plotpar = [2, 1]\n",
+    "sfac = cfv.scalfact2(ex3, ey3, es3[:, 2], 0.2)\n",
+    "cfu.disp(f\"sfac={sfac}\")\n",
+    "\n",
+    "cfv.figure(4, fig_size=(10, 10))\n",
+    "cfv.secforce2(ex1, ey1, es1[:, 2], plotpar, sfac)\n",
+    "cfv.secforce2(ex2, ey2, es2[:, 2], plotpar, sfac)\n",
+    "cfv.secforce2(ex3, ey3, es3[:, 2], plotpar, sfac)\n",
+    "cfv.axis([-1.5, 7.5, -0.5, 5.5])\n",
+    "cfv.scalgraph2(sfac, [3e4, 0.5, 0], plotpar1)\n",
+    "cfv.title(\"Moment\")"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "Draw moment diagram"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 11,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/html": [
+       "sfac=3.628630851048567e-05"
+      ],
+      "text/plain": [
+       "<IPython.core.display.HTML object>"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
+    },
+    {
+     "data": {
+      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAkkAAAJOCAYAAACjhZOMAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjUuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/YYfK9AAAACXBIWXMAAAsTAAALEwEAmpwYAAA6lUlEQVR4nO3dd3yV5f3/8feHhJkTRGQqILSgFhyoiAPrQKniFid10P6sfL/u2X7bilqts8MOR5WKe+CeVdzWrRXFiloVrQOaACpDkZlcvz+upAS4Q06Sc851j9fz8bgfSU6Sw/sAOeed67ru6zbnnAAAALCqNqEDAAAAxBElCQAAIAIlCQAAIAIlCQAAIAIlCQAAIAIlCQAAIAIlCQAAIAIlCUDBmNknZrbMzLqtdvs0M3Nm1j9QtDWY2Q1mdkHoHADii5IEoND+LWls/QdmtpmkjuHiAEDLUJIAFNrNko5u8PE4STfVf2Bm65jZTWY218w+NbMJZtam7nM/MrMXzewPZjbfzD42sx3qbv/czOaY2bgG99XezH5nZp+Z2Wwzu9rMOtZ9bhczm2lmZ9R9X5WZ/bjuc+MlHSHpZ2b2jZk9VIK/FwAJQ0kCUGivSOpsZt8zszJJh0m6pcHnL5e0jqTvSNpZvlD9uMHnt5X0T0nrSbpN0mRJ20gaKOlISVeYWa7uay+VtJGkoXWf30DSOQ3uq1fdn7WBpGMkXWlm6zrnJkq6VdJvnHM559y+hXnoANKEkgSgGOpHk0ZJ+pekWXW315emXzjnvnbOfSLp95KOavC9/3bOXe+cq5F0h6S+ks53zi11zj0uaZmkgWZmko6VdJpz7ivn3NeSLpJ0eIP7Wl73vcudc49I+kbSxsV5yADSpjx0AACpdLOk5yQNUIOpNkndJLWT9GmD2z6VH+mpN7vB+4slyTm3+m05Sd0ldZI01fclSZLJF7F6XzrnVjT4+Nu67wWAJjGSBKDgnHOfyi/g3kvSvQ0+9YX86M6GDW7rp5UjTc3xhXxhGuKc61J3rOOcy7cEuRb8mQAyhJIEoFiOkTTSObeowW01ku6UdKGZVZrZhpJO16prlvLinKuV9FdJfzCzHpJkZhuY2R553sVs+XVRABCJkgSgKJxzHznnXo/41EmSFkn6WNIL8ouzr2vhH/N/kmZIesXMFkp6UvmvOZokaXDdWXT3t/DPB5Bi5hwjzgAAAKtjJAkAACACJQkAACACJQkAACACJQkAACBCUTaT7Natm+vfv38x7hoAAKCgpk6d+oVzrvvqtxelJPXv31+vvx515i8AAEC8mNmnUbcz3QYAABCBkgQAABCBkgQAABCBkgQAABCBkgQAABCBkgQAABCBkgQAABCBkgQAABCBkgQAABCBkgQAABCBkgQAABCBkgQAABCBkgQAABCBkgQAABCBkgQAABCBkgQAABCBkgQAABCBkgQAABCBkgQAABCBkgQAABCBkgQAABCBkgQAABCBkgQAABCBkgQAABCBkgQAABCBkgQAABCBkgQAABCBkgQAABCBkgQAABCBkgQAABCBkgQAABCBkgQAABCBkgQAABCBkgQAABCBkgQAABCBkgQAABCBkgQAABCBkgQAABCBkgQAABCBkgQAABChPJ8vMrNPJH0tqUbSCufcsGKGAgAACC2vklRnV+fcF0VLAgAAECNMtwEAAETItyQ5SY+b2VQzG1/MQAAAAHGQ73TbCOfcf8ysh6QnzOxfzrnnGn5BXXkaL0n9+vUrcEwAAIDSymskyTn3n7q3cyTdJ2l4xNdMdM4Nc84N6969e2FTAgAAlFiTJcnMKsyssv59ST+QNL3YwQAAAELKZ7qtp6T7zKz+629zzk0paioAAIDAmixJzrmPJW1RgiwAAACxwRYAAAAAEShJAAAAEShJAAAAEShJAAAAEShJAAAAEShJAAAAEShJAAAAEShJAAAAEShJAAAAEShJAAAAEShJAAAAEShJAAAAEShJAAAAEShJAAAAEShJAAAAEShJAAAAEShJAAAAEShJAAAAEShJAAAAEShJAAAAEShJAAAAEShJAAAAEShJAAAAEShJAAAAEShJAAAAEShJAAAAEShJAAAAEShJAAAAEShJAAAAEShJAAAAEShJAAAAEShJAAAAEShJAADExIIFoROgIUoSAAAxMGuWtMkmklnoJKhHSQIAIAZOPlk69tjQKdAQJQkAgMDuv1+aPl365S9DJ0FD5aEDAACQZQsXSiedJN1yi9ShQ+g0aIiRJAAAAvrlL6U99pB23jl0EqyOkSQAAAJ5+WXp3nuld94JnQRRGEkCACCAZcuk8eOlP/xBWnfd0GkQhZIEAEAAv/ud1K+fdOihoZOgMUy3AQBQYh98IF12mTR1KvsixRkjSQAAlJBz0v/8jzRhgrThhqHTYG0oSQAAlNANN0jffONP+0e8Md0GAECJzJkj/fzn0pQpUllZ6DRoCiNJAACUyKmnSuPGSVtuGToJ8sFIEgAAJfDoo9Krr0rXXhs6CfJFSQIAoMgWLZKOP1665hqpU6fQaZAvptsAACiyc8+VdtxR+sEPQidBczCSBABAEU2dKt18szR9eugkaC5GkgAAKJIVK6Rjj5V++1upe/fQadBclCQAAIrkT3+SunaVjjoqdBK0BNNtAAAUwb//LV18sfTKK1x6JKkYSQIAoMCck447TjrzTGngwNBp0FKUJAAACuz226WqKumMM0InQWsw3QYAQAF9+aUvRw88ILVtGzoNWoORJAAACuinP5UOPVQaPjx0ErQWI0kpMH26tOmmoVMAAJ5+WnrqKfZESgtGkhJu+XJpzBjOnACA0BYvlv7nf6QrrpAqK0OnQSFQkhKubVvpppv8+1VVYbMAQJZdcIG05ZbSvvuGToJCoSSlwHbb+bc/+Yk/7RQAUFpvvy1NnOg3j0R6UJJSpLra/5ACAEqnpsZfeuTCC6XevUOnQSFRklLk5puls86SZswInQQAsuPKK6V27fxoPtKFkpQigwdLZ58tHX20v6giAKC43n1X+vWvpeefl9rwipo6/JOmzEknSZ06Sb/5TegkAJBuy5ZJRxwhXXRR6CQoFkpSyrRpI11/vfTHP0pvvhk6DQCk19lnS/36Mc2WZmwmmUJ9+0qXXSYdeaQ0darUoUPoRACQLs8+69eBvvUW+9SlGSNJKXXEEdKQIdIvfxk6CQCky/z50rhx0qRJUvfuodOgmChJKWUm/eUv0h13SM88EzoNAKTH8cf7DSNHjw6dBMXGdFuKrbeedO210o9+JP3zn9I664ROBADJdttt0rRp0uuvh06CUmAkKeVGj5b22ks6+eTQSQAg2T79VDr1VOmWW/xZxEg/SlIG/O530ksvSffcEzoJACRTTY3fg+6MM6SttgqdBqVCScqAigp/FsYJJ3ARXABoid/+1q/1PPPM0ElQSpSkjNhuO39tIS6CCwDN88YbfluVm26SyspCp0EpUZIy5Jxz/EVw//rX0EkAIBm+/dZvqfKnP/mNI5EtlKQMaduWi+ACQHP89Kd+DdLYsaGTIARKUsYMHixNmMBFcAGgKY88Ij38sHTllaGTIBRKUgZxEVwAWLs5c/wazptukrp0CZ0GoVCSMoiL4AJA45zzBenoo6Wddw6dBiFRkjKqb1/pD3/wF8FdsiR0GgCIj4kTpZkzpfPPD50EoVGSMuyHP/QXwT3rrNBJACAe3n/fPyfeeqvUrl3oNAiNkpRh9RfBnTyZi+ACwPLlfnT9vPOk730vdBrEQd4lyczKzOxNM3u4mIFQWg0vgrtgQeg0ABDOeedJ3btLxx8fOgniojkjSadIeq9YQRDO6NHS3ntzEVwA2fXCC9KkSdJ11/lRdkCSyvP5IjPrI2lvSRdKOr2oiTJi5kzprbd8OWktq/uJLsQP9k03tf4+ACCpevdu+fcWtlyFv37U88/72YbBg0MnCSevkiTpj5J+JqmysS8ws/GSxktSP/Zub9KMGdI++4ROAQCIoziNZmX5ep9NliQz20fSHOfcVDPbpbGvc85NlDRRkoYNG5bhv9L85HJ+q/upU1t/X/U/TK4A/5OvuMKvUXrpJb/hZGtzFeKHq1D3E9f7IlPp74tMpb+vuGa64w5/FYI335QqKlp/n63P5J/Q41BMRo2SzjwzdIqw8lmTNELSfmb2iaTJkkaa2S1FTZUBlZXSN9+ETrGmE07w2wIcf3w8fkgBoJhOPNGf7h+HghQ3VVWtm35MgyZLknPuF865Ps65/pIOl/S0c+7IoidLuVxO+vrr0CnWZOY3Ups61b8FgDSqrfVvTz5Z2mabsFniipKU/5okFFguF8+RJMn/RnXPPdKOO/opQZ5AAKTNeef5tz//edgccbV0qf9Ffr31QicJq1mbSTrnnnXOsdy4ACoqpEWL4jultdFG0jXXSAcfLH3xReg0AFA4Dz7oT/WvqpLKGSqIVF0t9ezpr/WZZRl/+OGUl0vt20uLF4dO0rgDD5TGjvWXL6mpCZ0GAFrv/ff9xWvvukvq1St0mvhiqs2jJAUU13VJDV1wgbRihfSrX4VOAgCt8/XX/pe/Cy6QttsudJp4oyR5lKSA4rwuqV55ub+22w03SA89FDoNALSMc/7ySyNGSOPHh04Tf5Qkj5IUUBJKkiT16CHdead0zDHSRx+FTgMAzXfJJf5KB1dcETpJMlRVMR0pUZKCiuteSVG231465xzpoIOkb78NnQYA8vfYY9Lll/uzdtu3D50mGRhJ8ihJASVhTVJDbDQJIGk+/lg6+mi/bKBPn9BpkoOS5FGSAkrKdFs9NpoEkCTffiuNGSOddZa0006h0yQLJcljh4iAklaSpFU3mtxyS2n48NCJAGBNzknHHitttpl00kmh0yQPJcljJCmgJK1JamijjfxI0iGHsNEkgHj605+k997zm+LWXwQc+amp8c/tPXuGThIeJSmgpK1JauiAA/xGk2PHstEkgHh55hl/Ntu990qdOoVOkzxz50rrriu1bRs6SXiUpICSON3W0AUX+IJ07rmhkwCA9/nn/ioBt9wi9e8fOk0yMdW2EiUpoKSXpPqNJm+8kY0mAYS3ZIlfqH3aadLuu4dOk1yUpJVYuB1QZaX05z/7I6nqN5rcf3/ppZekgQNDJwKQRc75bUoGDJB++tPQaVqPdVTxQEkKKJfzi5/vvLN19xP6h6nhRpMvv8waAACld8010quvSq+8Ev45sRBC7kV3wQVsGlyP6baAkj7d1tAJJ/hTbY87jo0mAZTWSy/5X9Tuv98/r6J1mG5biZIUUJpKkpn/Te6NN/xbACiFqirp0EOl669nur9QKEkrMd0WUFL3SWpMRYU/5XbECGmrrUKnAZB2y5ZJBx8sjR8v7b136DTpQUlaiZGkgJK8T1JjBg1audEkABTTaadJ3bpJEyaETpIulKSVKEkBpWm6raEDDvAXlJSkRYuCRgGQUtdfLz31lHTTTVIbXskKxjmpupqSVI/ptoDSWpIk6fzzpc8+kw4/XLrvPr+nEgAUys9+Jj33nLTOOqGTpMu8eVKHDlLHjqGTxAP9O6CKCn+aZW1t6CSFZyZde61fM3DCCZzxBqAw5szxb6+5Rvre98JmSSOm2lZFSQqorMw39rTuR9G2rXT33dI//iFdeGHoNACSbsmSlesdx4wJmyWtKEmrYhIksPopt7Tu7VFZKT3yiLTDDtIGG0g//nHoRACSqKZGOuIIqVev0EnSjZK0KkaSAkvzuqR6vXpJjz4q/eIX0pQpodMASBrnpOOPlxYs8Au1mb4vHkrSqihJgaVtr6TGbLyx30Pp6KOlqVNDpwGQJL/6lX/euO8+qX370GnSjZK0KkpSYGncK6kxO+zg91Dabz/p449DpwGQBFddJd12m5+2r6wMnSb9KEmrYk1SYFmYbmvogAOk//xH2nNPf72lbt1CJwIQV3fdJV10kfT881KPHqHTZAMlaVWMJAWWtZIk+bUFBx0k7btves/sA9A6Tz/ttw/529+kAQNCp8kOStKqKEmBZWVN0uouushfwuSHP/RnrQBAvTfe8BvR3nWXtMUWodNkCyVpVZSkwLK0Jqmh+s0mFy2STjqJs1UAeDNmSPvsI119tbTzzqHTZMs33/hfWjt3Dp0kPihJgeVy0imn+NLQ0iOp2rWT7rlHevll6eKLQ6cBEFp1tbTHHv5stqxvFtma14SWHpWV0uLFyX5dKTRKUmC5nN8/yLmWH0nWubNfc/DXv/r9TwBk04IF/oSOH/1IGj8+dJrwWvOa0NLj73+XRowI/cjjhbPbAquslGbPDp0irPXX96f37rqr33jyBz8InQhAKS1Z4s983XFHacKE0Gmyi/VIa2IkKbCsrkla3fe+56fejjzSL9oEkA01Nf7nvnt36U9/YqonJErSmihJgWVxC4DGjBjhF2vuu6/0ySeh0wAoNuekE0+U5s2Tbr7ZX/Qb4VCS1sR0W2CUpFWNGbNys8kXX5TWWy90IgDFcv750muvSc88w+VG4qCqyo/qYyVKUmBZ3SdpbU48Ufr8c3/5kiefDJ0GQDFcfbUfPXrxRU45jwtGktbEdFtgrEmKdvHFfpfdH/4wdBIAhXb33dKvfy09/rjUs2foNKhXVeVPnsFKlKTAmG6L1qaNdN11Kwtk0rc6AOA984y/NNHf/iZ95zuh06AhRpLWREkKjJLUuHbtpHvv9e+feKJUWxs2D4DWefNN6bDDpDvvlIYODZ0GDS1d6n8p5aLjq6IkBcaapLXr3NlvMvfPf0rHHst13oAk23tv6S9/kXbZJXQSrK66WurRw4/iYyX+OgLr1En69ltGSdamc2dpyhS/LcC4cdKKFaETAWiO6mr/9pxzpIMOCpsF0Zhqi0ZJCqxNG1+UFi0KnSTeKiqkhx+WvvxSGjtWWrYsdCIA+fj0U2mnnfz7//u/YbOgcZSkaJSkGGBdUn46dpTuv19avlw6+GB/KQMA8fX++74gnXACJ1/EXXU1JSkKJSkGWJeUv/btpbvukjp0kPbf309VAoifadP89Rh/9SvplFNCp0FTGEmKRkmKAfZKap62baXbbvP7q+y9NwUTiJuXXpL22EP685+lH/84dBrkg5IUjZIUA0y3NV95uXTDDdLAgf7JeMGC0IkASH6X/P33l2680U+LIxkoSdEoSTFASWqZNm2ka66RttpK2n136auvQicCsu2BB/wu+ffe66+/iOSgJEWjJMVAZaWfNjJr2ZFlbdr4If1ddpFGjpTmzg2dCMimW27xZ689+qj0/e+HTpN8LX09aOnxxhvS8OGhH3X8UJJiIJeTrr3Wn/3RkiPrzKTf/MZfEHeXXfxvRABK56qrpF/8QnrqKWnrrUOnSYeWvh605Fixwi9hYGuVNZWHDgCm2wrBTDr/fH/22847+yfrvn1DpwLS75JLpL/+VXruOX9RaiTP3LnSuuv6k2KwKkpSDFCSCuess/x+SvVFiSdtoDic86NHDz0kPf+8tP76oROhpViP1DhKUgxUVkoLF4ZOkR6nn+73UdplF3+mzaBBoRMB6VJb6y86/Y9/SH//OxdFTTpKUuMoSTGQy0mzZoVOkS7HH++n3nbdVXr8cWnw4NCJgHRYscLvffTZZ360tnPn0InQWpSkxlGSYoDptuI45hhflHbbzV8gd4stQicCkm3JEunww/0C30cf9dedRPJVVUm9eoVOEU+UpBigJBXPkUf6qbc99vAXyAXQMt98Ix1wgNS1q3TnnVK7dqEToVCqqqSNNw6dIp4oSTHAtduK6+CD/YjSXnuFTgIk07x5fi+3wYP9Bq5lZaEToZCqqvwaTqyJfZJigGu3Fd+++0q33urfnzgxbBYgaXbdVdpuO3+qPwUpfViT1DhKUgww3VYao0ZJ778v/fGP0nHHsXEa0JTPPvNvDzxQ+v3v2eE/rShJjaMkxQAlqXQ22kh65RV/NuFuu0mzZ4dOBMTT66+vvLzIuedSkNLKOam6mpLUGEpSDLAmqbQ6d5buv99PIWyzjX8xALDSpEl+Dd9ll4VOgmKbN8+v2eRMxWgs3I4B1iSVXps2/jImQ4dKo0f7KbgjjgidCghryRLppJOkF1/0lxnZZBOuD5l2jCKtHSUpBjp29E9ONTUsiiy1MWP8FNwBB/irYF96qb/QI5A1n37qzwQdMEB69VU/wo30Yz3S2jHdFgNt2kgVFdKiRaGTZNOmm0qvvSa9/bafYvjqq9CJgNJ64glp2239RpF33EFByhJK0tpRkmKCdUlhde0qPfKItPnmfp3S9OmhEwHFV1srXXSRNG6cNHmydMYZLNDOGkrS2jGxEBOsSwqvvFz63e/8OqVdd/Wb5o0ZEzoVUBwLFvhyNGeOv1DtBhuEToQQqqqk9dcPnSK+GEmKCUpSfBx5pL/W22mnSeec43/bBtJk+nQ/Ytqnj/TssxSkLGMkae0oSTGRy/knLbPmHyi8rbf265SeecZvpLdwYehEQGHcfrsfKT37bOmKK7gGW1y15LWgJcfkyf4XQ0SjJMVEZaW/AKtzzT9QHD17Sk895X/L3m476YMPQicCWm75cunUU6UJE6Qnn5SOOip0IqxNS14LWnJstJH07ruhH218UZJigum2eGrXTrrqKj/19v3vS48+GjoR0HxVVdLIkdKMGX7z1C22CJ0IccF029pRkmKCS5PE27HHSvfeK/3kJ9IllzCCh+R44QVp2DB/7cIHH5TWXTd0IsTFokV+hHGddUIniS/ObosJSlL8jRjhN9kbM0aaNi10GmDtnJMuv1y68ELphhv8zvJAQ/WjSKxtbRwjSTHBPknJ0KePv1xD167+44ceCpsHaMwRR0jXXy+9/DIFCdGYamsaJSkmWJOUHB06+HVKzz4rnX66NHasNHdu6FSA9/77/m27dtJLL0nf+U7YPIgvSlLTKEkxwXRb8uy8s/TWW1LfvtJmm0m33spaJYSzdKn061/7aWHJjyJ17Bg2E+KNktQ0SlJMUJKSqVMn6Te/8ds3XHqptO++0uefh06FrPn73/0Za1On+gs1O8c6EzSNktQ0SlJMsCYp2YYN86dWb7edtNVW0tVXs1M3iu+LL6Qf/9jveXTJJdL990v9+oVOhaSgJDWNkhQTrElKvnbt/EZ9f/+7dOONfldjNqBEMTjn/49tuqnUpYv0zjvSAQeEToWkoSQ1jZIUE0y3pcfgwX5vmjFjpB128NNxK1aEToW0eP99vzHk5ZdLjzwi/eEPfiQaaC5KUtMoSTFBSUqXsjLplFP81dWfeELadlu/yBtoqSVLpF/9StpxR1/AX33VT+0CLUVJaholKSZYk5ROAwZIjz8unXii3/F4wgT/Ygc0x9NPS5tvLr39tvTmm9JJJ/kiDrTUsmX+wt3duoVOEm+UpJhgTVJ6mfnFtW+95S8kueWWfv8aoClz50pHH+3///z+99I99/gNTYHWqq6WevSQ2tAC1qrJvx4z62Bmr5nZW2b2jpmdV4pgWcN0W/r17u2v/3bBBdLBB0snn8y/OaLV1kqTJvmF2T16+IXZ++4bOhXShKm2/ORz7balkkY6574xs7aSXjCzR51zrxQ5W6Z07OiHP1eskMq5ol6qHXSQP/Pt9NP9JpQS+9pgpXfflf73f/3mkI89Jg0dGjoR0oiSlJ8mR5KcV//7btu6g32FC8yM0aQs6drVX3T06qv9x8OH+yu0s2N3tk2Y4HdyP+wwPyVLQUKxUJLyk9eYhZmVSZoqaaCkK51zr0Z8zXhJ4yWpH7uZtUguJ627bugUKKU99pBqaqT77pPOOUc691z/QnnggawVyIrly6Xbb/fvf/CBX7u2/vphMyG8Uo0sX3NNaf6cpMrradg5V+OcGyqpj6ThZrZpxNdMdM4Nc84N6969e4FjZkMuJ733nh9NaM6BZGvTxk/BvfmmdN55fufkzTeXJk/2BQrp9M03fo+j737XbwwpSXfeSUGC19zXgeYeP/nJypFsNK5Zv6s65+ZLelbSnsUIk3VMt2WbmbTfftJrr0m//a305z9LQ4ZIN9/MZpRpMmeOdPbZfnuIl1/2i/mfeopfeFBaTLflJ5+z27qbWZe69ztK2l3Sv4qcK5PYKwmSL0ujR0svvihdeaV07bXSJptI113np2aQTB9/LJ1wgv+3nDvXF6Q77/TX/QNKjZKUn3xGknpLesbM/inpH5KecM49XNxY2cRIEhoyk3bbzV8LbtIk6bbbpEGD/BD50qWh0yFfb74pjR3rF+evs44/e+3qq6WBA0MnQ5ZRkvKTz9lt/3TObemc29w5t6lz7vxSBMsiNpREY3beWXrySV+UHnjAv8Befrm0eHHoZIjinJ9C22MPv7/R1lv7kaSLLpJ69QqdDllXU+NHM3v0CJ0k/jh/JkYYSUJTdthBevRRv47liSf8ot/LLpMWLQqdDJJ/8bnrLmmbbfylaA47TProI+nMM6XOnUOnA7y5c6UuXaR27UIniT9KUoywJgn52mYbv6/SI4/4/XS++13p0ktDp8quJUv8qdSbbOLPWDv7bL9L9v/7f1L79qHTAatiqi1/lKQYYSQJzTV0qHT33X4q7u23/W2jRkkTJ/rfFlFc8+f7twMGSA895BfXv/iitP/+7HOF+KIk5Y8f4xihJKGlNt1UuuUW//9n/Hi/HmbgQGn33f0i4TlzQidMj5kzpauukvbcU+rb19/2xBPSww9L3/8+l5dB/FGS8kdJihEWbqO1KiqkQw6R7rjDPxEed5w/O26jjaSRI/2Le3V16JTJ4tzKjT633lraYgt/+v4xx0izZvnPb7rG9rpAfFGS8selVGOENUkopE6d/E7eBx3kz4KbMsVPzf3yl36a7pBDpDFjeLKMsnSpL5cPPuiPdu38FNpll0kjRnARaiRbVZW08cahUyQDP+oxwnQbiqVjR389uAMP9IuMH3vMF6YJE6TNNltZmDbYIHTScL76yi+Ef/BB6fHHpcGD/Q7ojz3mF2QzjYa0qKqSdtkldIpkoCTFCCUJpdChgx8V2X9/P2Ly+OO+MJ17ri8Ghxziv8659BeDjz7ypeiBB6Q33vBTkvvt5/eg6tkzdDqgOKqrGUHOFyUpRihJKLX27f1mh/vu6wvTU0/5fX4kab31/FqbhseQIf72JFq61JeiDz7wHw8ZIn35pX/sZ5zhdzfv1ClsRqAUWJOUP0pSjFRWsnAb4bRvL+21lz+uv96fETd9uj+mTfNnz02f7sv86uVp8GB/e2grVkiffCJ9+KEvQw3fVlVJG27oL+0i+dP1t9mGU/WRLc4xktQclKQYYSQJcdKjh59+Gjly5W3OSZ9/vrI8PfusdMUV0r/+5S+3sXp5Ksbi0Npafxp+wwJU//6nn/on/0GD/Bl9gwb50rfRRlL//iy4BubP9yciMGqaH54yYoQtABB3ZlK/fv7Ya6+Vt9fU+GuT1ZenBx6QLrzQ3yb54lJW5ktKWdnKo+HHjb1f/7Fz/r5yOX9JhfoStNFG0k47+bff+Y5fcwUgGlNtzUNJipFczq+RSPtiWaRPWZkvLIMG+TPo6i1d6kvL1Km+SNXU+CmxqPeb+pxzfsPG2bP91DSQZrwOxAMlKUY6dPAvNkuWNG9agB8mxFX79itHgAqhkPcFxFmx/q/fcovf6gL5YclijJixLgkAUDxMtzUPJSlmKEkAgGKhJDUPJSlmKEkAgGKhJDUPJSlmuH4bAKBYKEnNQ0mKGbYBAAAUS1WV39MM+aEkxQzTbQCAYmEkqXkoSTFDSQIAFMOiRdKyZX4zVuSHkhQzrEkCABRD/SgSe+vlj5IUM6xJAgAUA1NtzUdJihmm2wAAxUBJaj5KUsxQkgAAxUBJaj5KUsxUVjLdBgAovOpqSlJzUZJihpEkAEAxMJLUfJSkmKEkAQCKgZLUfJSkmKEkAQCKgZLUfJSkmGFNEgCgGChJzVceOgBWlctJr77KZl8AkGXFeg3o1Utyrjj3nUaMJMVMLidtuKH/T5zvAQBIl+a8BuRzfPaZtP76vGY0FyUpZliTBAAoNKbaWoaSFDOsSQIAFBolqWUoSTHTrp1UW+uv1AwAQCFQklqGkhQzZn7KbdGi0EkAAGlBSWoZSlIMsS4JAFBIlKSWoSTFEOuSAACFRElqGUpSDDGSBAAoJEpSy1CSYoiSBAAoJEpSy1CSYoiSBAAolJoaae5cqWfP0EmSh5IUQ6xJAgAUyhdfSOus47eYQfNQkmKIkSQAQKFUVzPV1lKUpBiiJAEACoX1SC1HSYohShIAoFAoSS1HSYoh1iQBAAqFktRylKQYYiQJAFAolKSWoyTFECUJAFAolKSWKw8dAGvK5aRbb/UHACB7zAp7f/fcIzlX2PvMAkaSYqiyUho50v+HzucAAKRLvs//+RwDBkgzZoR+RMlESYohptsAAIXgHNNtrUFJiiFKEgCgEBYs8Dttd+oUOkkyUZJiiJIEACgERpFah5IUQ+yTBAAohKoqqVev0CmSi5IUQ4wkAQAKgZGk1qEkxVD9lZqXLQubAwCQbJSk1qEkxVRlJaNJAIDWoSS1DiUppnI51iUBAFqHktQ6lKSYYl0SAKC1KEmtQ0mKKUoSAKC1KEmtQ0mKKdYkAQBai5LUOpSkmGJNEgCgNb791p8l3aVL6CTJRUmKKabbAACtUb+RpFnoJMlFSYopShIAoDWYams9SlJMsSYJANAalKTWoyTFFGuSAACtQUlqvfLQARAtl5POPFM6//zQSQAApVbIdURXXFG4+8oaRpJiKpeTxo+XnGv6AACkSz7P/U0d48ZJkyaFfiTJRkmKKdYkAQBag+m21qMkxRRrkgAArUFJaj1KUkyxBQAAoDUoSa1HSYopShIAoKWWLZPmz5e6dQudJNkoSTHFmiQAQEvNni117y6VlYVOkmyUpJhiTRIAoKWYaisMSlJMMd0GAGgpSlJhUJJiqr4ksQ8SAKC5KEmFQUmKqbZt/VzysmWhkwAAkoaSVBiUpBhjXRIAoCUoSYVBSYox1iUBAFqCklQYlKQYoyQBAFqiupqSVAiUpBhjryQAQEswklQYTZYkM+trZs+Y2Xtm9o6ZnVKKYGBNEgCg+WprpTlzpF69QidJvvI8vmaFpDOcc2+YWaWkqWb2hHPu3SJnyzym2wAAzfXFF1LnzlK7dqGTJF+TI0nOuSrn3Bt1738t6T1JGxQ7GChJAIDmY6qtcPIZSfovM+svaUtJr0Z8bryk8ZLUr1+/QmTLvMpK6eij/QEAyA6z0AkgNWPhtpnlJN0j6VTn3MLVP++cm+icG+acG9a9e/dCZsysXE669FK/6/baDgBAujT1vL+247rr+OW6UPIqSWbWVr4g3eqcu7e4kVCP6TYAQHMx3VY4+ZzdZpImSXrPOXdZ8SOhHiUJANBclKTCyWckaYSkoySNNLNpdcdeRc4FUZIAAM1HSSqcJhduO+dekMQSsgAqK9knCQDQPJSkwmHH7RhjJAkA0FyUpMKhJMUYJQkA0BzOUZIKiZIUY5QkAEBzLFggtW0rVVSETpIOlKQY49ptAIDmYBSpsChJMVZZyUgSACB/lKTCoiTFGNNtAIDmoCQVFiUpxioqfEni0iMAgHxQkgqLkhRjbdtK5eXSkiWhkwAAkqC6mpJUSJSkmGPKDQCQL0aSCouSFHOUJABAvihJhUVJijnOcAMA5IuSVFiUpJhjryQAQL4oSYXV5AVuEVYuJ40YEToFAKCUrBWXle/SpWAxMo+RpJjL5aR77vHbADR2AADSZW3P+Y0dH30k9e/fuoKFVVGSYo41SQCAfDDVVniUpJhjTRIAIB+UpMKjJMUcWwAAAPJBSSo8SlLMUZIAAPmgJBUeJSnmWJMEAMhHVZXUq1foFOlCSYo51iQBAPLBSFLhUZJijuk2AEA+KEmFR0mKOUoSACAflKTCoyTFHGuSAABNWb5cmjdP6t49dJJ0oSTFHGuSAABNmT3bF6SystBJ0oWSFHNMtwEAmsJUW3FQkmKOkgQAaAolqTgoSTHHmiQAQFMoScVBSYq5igpfkpwLnQQAEFeUpOKgJMVcebnUrp20eHHoJACAuKIkFQclKQFYlwQAWBtKUnFQkhKgspJtAAAAjaMkFUd56ABoWi4nDRwYOgUAoFTMmv89223H+tVCYyQpAXI56YUX/H/+qAMAkC6NPd9HHTU1Utu20tKloVOnDyUpAViTBABozBdfSJ07+5N8UFiUpARgryQAQGNYj1Q8lKQE4PptAIDGUJKKh5KUAEy3AQAaU1Ul9eoVOkU6UZISgJIEAGgMI0nFQ0lKANYkAQAaQ0kqHkpSArAmCQDQGEpS8VCSEoDpNgBAYyhJxUNJSgBKEgCgMZSk4qEkJQBrkgAAUZyTqqspScVCSUoA1iQBAKIsXCiVlfnXCRQeJSkBmG4DAERhqq24KEkJQEkCAEShJBUXJSkBWJMEAIhCSSouSlICsCYJABCFklRclKQEqKiQFi2SamtDJwEAxAklqbjKQwdA08rKpA4d/FsAQPqZNe/rf/az4uTIOkaSEqKy0u+F4dyaBwAgXaKe66OOXXeVnngidNr0oiQlBOuSAACrY7qtuChJCcE2AACA1VGSiouSlBCUJABAQ4sXS0uWSOuuGzpJelGSEoK9kgAADVVVSb16NX+RN/JHSUoI1iQBABpiqq34KEkJwXQbAKAhSlLxUZISgpIEAGiIklR8lKSEYE0SAKAhSlLxUZISgjVJAICGKEnFR0lKCKbbAAANUZKKj5KUEJQkAEBD1dWUpGKjJCUEa5IAAA0xklR8lKSEYE0SAKDeihXSvHlS9+6hk6QbJSkhmG4DANSbPVvq1k0qKwudJN0oSQlBSQIA1GOqrTQoSQlRWcl0GwDAoySVRnnoAMhPLid99BEXMgSALOC5Ph4oSQmRy0kVFdFTbvwwAUC6OLf2z593nlRTU5osWcZ0W0JUVEjffivV1oZOAgAIjem20qAkJUSbNlKnTr4oAQCyjZJUGpSkBGGvJACAREkqFUpSgrANAABAoiSVCiUpQShJAIDaWr+ZZM+eoZOkHyUpQbh+GwDgyy/960H79qGTpB8lKUFYkwQAYKqtdChJCcJ0GwCAklQ6lKQEoSQBAChJpUNJShCu3wYAoCSVDiUpQRhJAgBQkkqHkpQglCQAACWpdChJCUJJAgBQkkqnyZJkZteZ2Rwzm16KQGgca5IAAJSk0slnJOkGSXsWOQfywEgSAGSbc5SkUmqyJDnnnpP0VQmyoAlsJgkA2bZwoVRW5l8PUHzlhbojMxsvabwk9evXr1B3iwZyOenxxyWz0EkAAMXE83w8FGzhtnNuonNumHNuWPfu3Qt1t2igslLafHM/3NrwAACky+rP8/XH009LO+0UOl12cHZbgrAmCQCyjfVIpUVJShBKEgBkGyWptPLZAuB2SS9L2tjMZprZMcWPhSiUJADINkpSaTW5cNs5N7YUQdC0Tp2kJUukmhp/dgMAIFuqqvzaVJQG020J0qaNL0qLFoVOAgAIgZGk0qIkJQxTbgCQXZSk0qIkJQwlCQCyi5JUWpSkhOH6bQCQTYsX+6Nr19BJsoOSlDCMJAFANlVVSb16sRt3KVGSEoaSBADZxFRb6VGSEoaSBADZVF1NSSo1SlLCsCYJALKJkaTSoyQlDCNJAJBNlKTSoyQlDCUJALKJklR6lKSEoSQBQDZRkkqPkpQwrEkCgGyiJJUeJSlhcjnpqqv8Phn1BwAgXRo+x9cfb70lbb116GTZQklKmFxOGjNGcm7lAQBIl4bP8c5Jy5dL5eXSihWhk2ULJSlhWJMEANkze7bUrZtUVhY6SbZQkhKGNUkAkD2sRwqDkpQwjCQBQPZQksKgJCUMJQkAsqf+4rYoLUpSwlCSACB7GEkKg5KUMKxJAoDsoSSFQUlKmI4dpWXLOA0UALKEkhQGJSlhzKSKCmnRotBJAAClQkkKg5KUQKxLAoBsoSSFQUlKINYlAUB21Nb6zSQ5u630KEkJxEgSAGTHl1/65/0OHUInyR5KUgJRkgAgO6qrmWoLhZKUQJQkAMgO1iOFQ0lKINYkAUB2UJLCoSQlECNJAJAdlKRwKEkJREkCgOygJIVTHjoAmi+Xk04/3R8AgPQxW/O2004rfY6sYyQpgSorpZ/+VHLOHwCAdKl/fndO2nFH6dlnQyfKJkpSAjHdBgDZwXRbOJSkBKIkAUA2OEdJComSlECUJADIhq+/9uuTKitDJ8kmSlICsU8SAGQDo0hhUZISiJEkAMgGSlJYlKQEoiQBQDZQksKiJCUQJQkAsoGSFBYlKYFYkwQA2UBJCouSlECMJAFANlCSwqIkJVCHDtKKFdLy5aGTAACKiZIUFiUpgcz8aNKiRaGTAACKiZIUFiUpoXI51iUBQNpRksKiJCUU65IAIN0WL5a+/Vbq2jV0kuyiJCUUJQkA0q26WurVyy+xQBiUpISqrKQkAUCaMdUWHiUpoViTBADpRkkKrzx0ALRMLiftv3/oFACAYmCKLR4oSQmVy0nXXCONH88PEwCkjXPSWWf5ffEQDtNtCcWaJABIN6bbwqMkJRRrkgAg3ShJ4VGSEootAAAg3ShJ4VGSEoqSBADpRkkKj5KUUKxJAoD0WrFC+uorqXv30EmyjZKUUKxJAoD0mj1bWm89qZxz0IOiJCUU020AkF5MtcUDJSmhKEkAkF6UpHigJCUUa5IAIL0oSfFASUoo1iQBQHpRkuKBkpRQTLcBQHpRkuKBkpRQlCQASK/qakpSHFCSEqp9e6m2Vlq2LHQSAEChMZIUD5SkhDJjNAkA0oqSFA+UpASjJAFAOs2eLfXqFToFKEkJRkkCgHSqqJA6dAidApSkBKuslIYMCZ0CAFBo8+aFTgCJkpRouZz05JOhUwAACm233UIngERJSjSm2wAgnVi0HQ+UpASjJAFAOlGS4oGSlGBcvw0A0omSFA+UpATj+m0AkE6UpHigJCUY020AkE6UpHigJCUYJQkA0omSFA+UpARjTRIApBMlKR4oSQnGmiQASKfKytAJIFGSEo3pNgAAioeSlGCUJAAAioeSlGCsSQIAoHgoSQnGmiQAAIqHkpRgcZluMwudID74uwCA9MirJJnZnmb2vpnNMLOfFzsU8hOXkgQAQBo1WZLMrEzSlZJGSxosaayZDS52MDSNkpQ8S5Ys0fDhw7XFFltoyJAhOvfccyVJX331lUaNGqVBgwZp1KhRmjdv3n+/5+KLL9bAgQO18cYb67HHHvvv7VOnTtVmm22mgQMH6uSTT5ZzTpK0dOlSHXbYYRo4cKC23XZbffLJJ5FZGvt+AICXz0jScEkznHMfO+eWSZosaf/ixkI+2rcPnQDN1b59ez399NN66623NG3aNE2ZMkWvvPKKLrnkEu2222768MMPtdtuu+mSSy6RJL377ruaPHmy3nnnHU2ZMkXHH3+8ampqJEnHHXecJk6cqA8//FAffvihpkyZIkmaNGmS1l13Xc2YMUOnnXaa/u///i8yS2PfDwDw8ilJG0j6vMHHM+tuQwyw4ViymJlyuZwkafny5Vq+fLnMTA888IDGjRsnSRo3bpzuv/9+SdIDDzygww8/XO3bt9eAAQM0cOBAvfbaa6qqqtLChQu1/fbby8x09NFHr/I99fd18MEH66mnnlpjlGht3w8A8PIpSVFLUdcYlzez8Wb2upm9Pnfu3NYnQ17i8ldtxpHvou2amhoNHTpUPXr00KhRo7Tttttq9uzZ6l13HYLevXtrzpw5kqRZs2apb9++//3ePn36aNasWZo1a5b69Omzxu2rf095ebnWWWcdffnll6tkWNv3AwC88jy+Zqakvg0+7iPpP6t/kXNuoqSJkjRs2DAWN5RImzaKxVqSGESIhXyKUllZmaZNm6b58+frwAMP1PTp0xv92qh/WzNr9Pa1fU8+9wsgrDg8n2OlfEaS/iFpkJkNMLN2kg6X9GBxYwHp16VLF+2yyy6aMmWKevbsqaqqKkl+KqxHjx6S/AjP55+vnO2eOXOm1l9/ffXp00czZ85c4/bVv2fFihVasGCBunbtusqfvbbvBwB4TZYk59wKSSdKekzSe5LudM69U+xgQBrNnTtX8+fPlyQtXrxYTz75pDbZZBPtt99+uvHGGyVJN954o/bf358bsd9++2ny5MlaunSp/v3vf+vDDz/U8OHD1bt3b1VWVuqVV16Rc0433XTTKt9Tf1933323Ro4cucYo0dq+HwDg5TPdJufcI5IeKXIWIPWqqqo0btw41dTUqLa2Voceeqj22Wcfbb/99jr00EM1adIk9evXT3fddZckaciQITr00EM1ePBglZeX68orr1RZWZkk6S9/+Yt+9KMfafHixRo9erRGjx4tSTrmmGN01FFHaeDAgeratasmT5783z9/6NChmjZt2lq/HwDgWTHmP4cNG+Zef/31gt8vAABAoZnZVOfcsNVv57IkAAAAEShJAAAAEShJAAAAEShJAAAAEShJAAAAEShJAAAAEShJAAAAEShJAAAAEShJAAAAEShJAAAAEShJAAAAEShJAAAAEShJAAAAEShJAAAAEShJAAAAEShJAAAAEShJAAAAEShJAAAAEShJAAAAEShJAAAAEShJAAAAEShJAAAAEShJAAAAEShJAAAAEShJAAAAEShJAAAAEShJAAAAEShJAAAAEShJAAAAEShJAAAAEShJAAAAEShJAAAAEShJAAAAEShJAAAAEShJAAAAEShJAAAAEShJAAAAEShJAAAAEShJAAAAEcw5V/g7NZsr6dOC33F+ukn6ItCfHRKPO1t43NnC484WHnfpbeic6776jUUpSSGZ2evOuWGhc5QajztbeNzZwuPOFh53fDDdBgAAEIGSBAAAECGNJWli6ACB8LizhcedLTzubOFxx0Tq1iQBAAAUQhpHkgAAAFqNkgQAABAhdSXJzA4xs3fMrNbMYnUqYTGY2Z5m9r6ZzTCzn4fOUypmdp2ZzTGz6aGzlIqZ9TWzZ8zsvbr/46eEzlQKZtbBzF4zs7fqHvd5oTOVkpmVmdmbZvZw6CylYmafmNnbZjbNzF4PnadUzKyLmd1tZv+q+znfPnSmYjOzjev+neuPhWZ2auhc9VK3JsnMviepVtI1ks50zqX2B8zMyiR9IGmUpJmS/iFprHPu3aDBSsDMdpL0jaSbnHObhs5TCmbWW1Jv59wbZlYpaaqkA9L+721mJqnCOfeNmbWV9IKkU5xzrwSOVhJmdrqkYZI6O+f2CZ2nFMzsE0nDnHOZ2lDRzG6U9Lxz7lozayepk3NufuBYJVP3mjZL0rbOuVAbUq8idSNJzrn3nHPvh85RIsMlzXDOfeycWyZpsqT9A2cqCefcc5K+Cp2jlJxzVc65N+re/1rSe5I2CJuq+Jz3Td2HbeuOdP121wgz6yNpb0nXhs6C4jKzzpJ2kjRJkpxzy7JUkOrsJumjuBQkKYUlKWM2kPR5g49nKgMvmpDMrL+kLSW9GjhKSdRNOU2TNEfSE865TDxuSX+U9DP50fEscZIeN7OpZjY+dJgS+Y6kuZKur5tevdbMKkKHKrHDJd0eOkRDiSxJZvakmU2PODIxitKARdyWid+ws8zMcpLukXSqc25h6Dyl4Jyrcc4NldRH0nAzS/0Uq5ntI2mOc25q6CwBjHDObSVptKQT6qbX065c0laS/uKc21LSIklZWmfaTtJ+ku4KnaWh8tABWsI5t3voDDExU1LfBh/3kfSfQFlQAnVrcu6RdKtz7t7QeUrNOTffzJ6VtKektC/aHyFpPzPbS1IHSZ3N7Bbn3JGBcxWdc+4/dW/nmNl98ksLngubquhmSprZYJT0bmWoJMkX4jecc7NDB2kokSNJ+K9/SBpkZgPqWvjhkh4MnAlFUreAeZKk95xzl4XOUypm1t3MutS931HS7pL+FTRUCTjnfuGc6+Oc6y//s/10FgqSmVXUnZiguummHyj9hVjOuWpJn5vZxnU37SYp1SdlrGasYjbVJqWwJJnZgWY2U9L2kv5mZo+FzlQszrkVkk6U9Jj8It47nXPvhE1VGmZ2u6SXJW1sZjPN7JjQmUpghKSjJI1scLrsXqFDlUBvSc+Y2T/lfzF4wjmXmdPhM6inpBfM7C1Jr0n6m3NuSuBMpXKSpFvr/q8PlXRR2DilYWad5M/Sjt3oeOq2AAAAACiE1I0kAQAAFAIlCQAAIAIlCQAAIAIlCQAAIAIlCQAAIAIlCQAAIAIlCQAAIML/B+QmAT7HPkHuAAAAAElFTkSuQmCC",
+      "text/plain": [
+       "<Figure size 720x720 with 1 Axes>"
+      ]
+     },
+     "metadata": {
+      "needs_background": "light"
+     },
+     "output_type": "display_data"
+    }
+   ],
+   "source": [
+    "plotpar = [2, 1]\n",
+    "sfac = cfv.scalfact2(ex3, ey3, es3[:, 2], 0.2)\n",
+    "cfu.disp(f\"sfac={sfac}\")\n",
+    "\n",
+    "cfv.figure(4, fig_size=(10, 10))\n",
+    "cfv.secforce2(ex1, ey1, es1[:, 2], plotpar, sfac)\n",
+    "cfv.secforce2(ex2, ey2, es2[:, 2], plotpar, sfac)\n",
+    "cfv.secforce2(ex3, ey3, es3[:, 2], plotpar, sfac)\n",
+    "cfv.axis([-1.5, 7.5, -0.5, 5.5])\n",
+    "cfv.scalgraph2(sfac, [3e4, 0.5, 0], plotpar1)\n",
+    "cfv.title(\"Moment\")"
+   ]
+  }
+ ],
+ "metadata": {
+  "kernelspec": {
+   "display_name": "Python 3 (ipykernel)",
+   "language": "python",
+   "name": "python3"
+  },
+  "language_info": {
+   "codemirror_mode": {
+    "name": "ipython",
+    "version": 3
+   },
+   "file_extension": ".py",
+   "mimetype": "text/x-python",
+   "name": "python",
+   "nbconvert_exporter": "python",
+   "pygments_lexer": "ipython3",
+   "version": "3.9.12"
+  }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 4
+}
diff --git a/examples/exs_beam2.py b/examples/exs_beam2.py
index ad6594c..0774ee5 100644
--- a/examples/exs_beam2.py
+++ b/examples/exs_beam2.py
@@ -23,22 +23,22 @@
 # ----- Topology -------------------------------------------------
 
 edof = np.array([
-    [4,  5,  6,  1,  2,  3],
-    [7,  8,  9, 10, 11, 12],
-    [4,  5,  6,  7,  8,  9]
+    [4, 5, 6, 1, 2, 3], 
+    [7, 8, 9, 10, 11, 12], 
+    [4, 5, 6, 7, 8, 9]
 ])
 
 # ----- Stiffness matrix K and load vector f ---------------------
 
 K = np.array(np.zeros((12, 12)))
 f = np.array(np.zeros((12, 1)))
-f[3] = 2.e+3
+f[3] = 2.0e3
 
 # ----- Element stiffness and element load matrices  -------------
 
-E = 200.e9
-A1 = 2.e-3
-A2 = 6.e-3
+E = 200.0e9
+A1 = 2.0e-3
+A2 = 6.0e-3
 I1 = 1.6e-5
 I2 = 5.4e-5
 
@@ -52,7 +52,7 @@
 ey3 = np.array([4, 4])
 eq1 = np.array([0, 0])
 eq2 = np.array([0, 0])
-eq3 = np.array([0, -10e+3])
+eq3 = np.array([0, -10e3])
 
 Ke1 = cfc.beam2e(ex1, ey1, ep1)
 Ke2 = cfc.beam2e(ex2, ey2, ep1)
@@ -60,19 +60,17 @@
 
 # ----- Assemble Ke into K ---------------------------------------
 
-cfc.assem(edof[0, :], K, Ke1)
-cfc.assem(edof[1, :], K, Ke2)
-cfc.assem(edof[2, :], K, Ke3, f, fe3)
+K = cfc.assem(edof[0, :], K, Ke1)
+K = cfc.assem(edof[1, :], K, Ke2)
+K, f = cfc.assem(edof[2, :], K, Ke3, f, fe3)
 
 # ----- Solve the system of equations and compute reactions ------
 
 bc = np.array([1, 2, 3, 10, 11])
 a, r = cfc.solveq(K, f, bc)
 
-print("a = ")
-print(a)
-print("r = ")
-print(r)
+cfu.disp_array(a, ["a"])
+cfu.disp_array(r, ["r"])
 
 # ----- Section forces -------------------------------------------
 
@@ -82,18 +80,18 @@
 es2, edi2, ec2 = cfc.beam2s(ex2, ey2, ep1, ed[1, :], eq2, nep=21)
 es3, edi3, ec3 = cfc.beam2s(ex3, ey3, ep3, ed[2, :], eq3, nep=21)
 
-print("es1 = ")
-print(es1)
-print("edi1 = ")
-print(edi1)
-print("es2 = ")
-print(es2)
-print("edi2 = ")
-print(edi2)
-print("es3 = ")
-print(es3)
-print("edi3 = ")
-print(edi3)
+cfu.disp_h2("es1")
+cfu.disp_array(es1, ["N", "Vy", "Mz"])
+cfu.disp_h2("edi1")
+cfu.disp_array(edi1, ["u1", "v1"])
+cfu.disp_h2("es2")
+cfu.disp_array(es2, ["N", "Vy", "Mz"])
+cfu.disp_h2("edi2")
+cfu.disp_array(edi2, ["u1", "v1"])
+cfu.disp_h2("es3")
+cfu.disp_array(es3, ["N", "Vy", "Mz"])
+cfu.disp_h2("edi3")
+cfu.disp_array(edi3, ["u1", "v1"])
 
 # ----- Draw deformed frame ---------------------------------------
 
@@ -113,46 +111,46 @@
 cfv.dispbeam2(ex3, ey3, edi3, plotpar, sfac)
 cfv.axis([-1.5, 7.5, -0.5, 5.5])
 plotpar1 = 2
-cfv.scalgraph2(sfac,[1e-2, 0.5, 0],plotpar1);
-cfv.title('Displacements')
+cfv.scalgraph2(sfac, [1e-2, 0.5, 0], plotpar1)
+cfv.title("Displacements")
 
 # ----- Draw normal force diagram --------------------------------
 
 plotpar = [2, 1]
-sfac = cfv.scalfact2(ex1, ey1, es1[:,0], 0.2)
+sfac = cfv.scalfact2(ex1, ey1, es1[:, 0], 0.2)
 cfv.figure(2)
-cfv.secforce2(ex1, ey1, es1[:,0], plotpar, sfac)
-cfv.secforce2(ex2, ey2, es2[:,0], plotpar, sfac)
-cfv.secforce2(ex3, ey3, es3[:,0], plotpar, sfac)
+cfv.secforce2(ex1, ey1, es1[:, 0], plotpar, sfac)
+cfv.secforce2(ex2, ey2, es2[:, 0], plotpar, sfac)
+cfv.secforce2(ex3, ey3, es3[:, 0], plotpar, sfac)
 cfv.axis([-1.5, 7.5, -0.5, 5.5])
-cfv.scalgraph2(sfac,[3e4, 1.5, 0],plotpar1)
-cfv.title('Normal force')
+cfv.scalgraph2(sfac, [3e4, 1.5, 0], plotpar1)
+cfv.title("Normal force")
 
 # ----- Draw shear force diagram ---------------------------------
 
 plotpar = [2, 1]
-sfac = cfv.scalfact2(ex3, ey3, es3[:,1], 0.2)
+sfac = cfv.scalfact2(ex3, ey3, es3[:, 1], 0.2)
 cfv.figure(3)
-cfv.secforce2(ex1, ey1, es1[:,1], plotpar, sfac)
-cfv.secforce2(ex2, ey2, es2[:,1], plotpar, sfac)
-cfv.secforce2(ex3, ey3, es3[:,1], plotpar, sfac)
+cfv.secforce2(ex1, ey1, es1[:, 1], plotpar, sfac)
+cfv.secforce2(ex2, ey2, es2[:, 1], plotpar, sfac)
+cfv.secforce2(ex3, ey3, es3[:, 1], plotpar, sfac)
 cfv.axis([-1.5, 7.5, -0.5, 5.5])
-cfv.scalgraph2(sfac,[3e4, 0.5, 0],plotpar1)
-cfv.title('Shear force')
+cfv.scalgraph2(sfac, [3e4, 0.5, 0], plotpar1)
+cfv.title("Shear force")
 
 # ----- Draw moment diagram --------------------------------------
 
 plotpar = [2, 1]
-sfac = cfv.scalfact2(ex3, ey3, es3[:,2], 0.2)
+sfac = cfv.scalfact2(ex3, ey3, es3[:, 2], 0.2)
 print("sfac=")
 print(sfac)
 
 cfv.figure(4)
-cfv.secforce2(ex1, ey1, es1[:,2], plotpar, sfac)
-cfv.secforce2(ex2, ey2, es2[:,2], plotpar, sfac)
-cfv.secforce2(ex3, ey3, es3[:,2], plotpar, sfac)
+cfv.secforce2(ex1, ey1, es1[:, 2], plotpar, sfac)
+cfv.secforce2(ex2, ey2, es2[:, 2], plotpar, sfac)
+cfv.secforce2(ex3, ey3, es3[:, 2], plotpar, sfac)
 cfv.axis([-1.5, 7.5, -0.5, 5.5])
-cfv.scalgraph2(sfac,[3e4, 0.5, 0],plotpar1)
-cfv.title('Moment')
+cfv.scalgraph2(sfac, [3e4, 0.5, 0], plotpar1)
+cfv.title("Moment")
 
-cfv.showAndWait()
\ No newline at end of file
+cfv.show_and_wait()
diff --git a/examples/exs_beambar2.py b/examples/exs_beambar2.py
index 70633c4..2dc1ef6 100644
--- a/examples/exs_beambar2.py
+++ b/examples/exs_beambar2.py
@@ -72,21 +72,22 @@
 
 # ----- Assemble Ke into K ---------------------------------------
 
-cfc.assem(edof1[0, :], K, Ke1)
-cfc.assem(edof1[1, :], K, Ke2, f, fe2)
-cfc.assem(edof1[2, :], K, Ke3, f, fe3)
-cfc.assem(edof2[0, :], K, Ke4)
-cfc.assem(edof2[1, :], K, Ke5)
+K = cfc.assem(edof1[0, :], K, Ke1)
+K, f = cfc.assem(edof1[1, :], K, Ke2, f, fe2)
+K, f = cfc.assem(edof1[2, :], K, Ke3, f, fe3)
+K = cfc.assem(edof2[0, :], K, Ke4)
+K = cfc.assem(edof2[1, :], K, Ke5)
 
 # ----- Solve the system of equations and compute reactions ------
 
 bc = np.array([1, 2, 3, 13, 14])
 a, r = cfc.solveq(K, f, bc)
 
-print("a = ")
-print(a)
-print("r = ")
-print(r)
+cfu.disp_h2("Displacements a:")
+cfu.disp_array(a)
+
+cfu.disp_h2("Reaction forces r:")
+cfu.disp_array(r)
 
 # ----- Section forces -------------------------------------------
 
@@ -99,14 +100,14 @@
 es4 = cfc.bar2s(ex4, ey4, ep4, ed2[0, :])
 es5 = cfc.bar2s(ex5, ey5, ep4, ed2[1, :])
 
-print("es1 = ")
-print(es1)
-print("es2 = ")
-print(es2)
-print("es3 = ")
-print(es3)
-print("es4 = ")
-print(es4)
-print("es5 = ")
-print(es5)
+cfu.disp_h2("es1 = ")
+cfu.disp_array(es1, headers=["N", "Q", "M"])
+cfu.disp_h2("es2 = ")
+cfu.disp_array(es2, headers=["N", "Q", "M"])
+cfu.disp_h2("es3 = ")
+cfu.disp_array(es3, headers=["N", "Q", "M"])
+cfu.disp_h2("es4 = ")
+cfu.disp_array(es4, headers=["N"])
+cfu.disp_h2("es5 = ")
+cfu.disp_array(es5, headers=["N"])
 
diff --git a/examples/exs_flw_diff2.py b/examples/exs_flw_diff2.py
index 7943209..570b988 100644
--- a/examples/exs_flw_diff2.py
+++ b/examples/exs_flw_diff2.py
@@ -1,107 +1,103 @@
 # -*- coding: utf-8 -*-
 
 # example exs8
-#----------------------------------------------------------------
-# PURPOSE 
+# ----------------------------------------------------------------
+# PURPOSE
 #    Analysis of two dimensional diffusion
-#----------------------------------------------------------------
+# ----------------------------------------------------------------
 
 # REFERENCES
 #     Karl-Gunnar Olsson 1995-10-08
 #     Ola Dahlblom 2004-09-14
-#----------------------------------------------------------------
+# ----------------------------------------------------------------
 
 import numpy as np
 import calfem.vis_mpl as cfv
 import calfem.core as cfc
+import calfem.utils as cfu
 
 # ----- System matrices -----
 
-K = np.zeros((15,15))
-f = np.zeros((15,1))
-Coord = np.array([
-    [0,     0    ],[0.025, 0    ],
-    [0.05,  0    ],[0,     0.025],
-    [0.025, 0.025],[0.05,  0.025],
-    [0,     0.05 ],[0.025, 0.05 ],
-    [0.05,  0.05 ],[0,     0.075],
-    [0.025, 0.075],[0.05,  0.075],
-    [0,     0.1  ],[0.025, 0.1  ],
-    [0.05,  0.1  ]
-])
-
-Dof = np.array([
-    [1 ],[2 ],[3 ],
-    [4 ],[5 ],[6 ],
-    [7 ],[8 ],[9 ],
-    [10],[11],[12],
-    [13],[14],[15]
-])
+K = np.zeros((15, 15))
+f = np.zeros((15, 1))
+Coord = np.array(
+    [
+        [0, 0],
+        [0.025, 0],
+        [0.05, 0],
+        [0, 0.025],
+        [0.025, 0.025],
+        [0.05, 0.025],
+        [0, 0.05],
+        [0.025, 0.05],
+        [0.05, 0.05],
+        [0, 0.075],
+        [0.025, 0.075],
+        [0.05, 0.075],
+        [0, 0.1],
+        [0.025, 0.1],
+        [0.05, 0.1],
+    ]
+)
+
+Dof = np.array(
+    [[1], [2], [3], [4], [5], [6], [7], [8], [9], [10], [11], [12], [13], [14], [15]]
+)
 
 # ----- Element properties, topology and coordinates -----
 
 ep = np.array([1])
-D = np.array([
-    [1, 0],
-    [0, 1]
-])
-Edof = np.array([
-    [ 1, 2, 5, 4],
-    [ 2, 3, 6, 5],
-    [ 4, 5, 8, 7],
-    [ 5, 6, 9, 8],
-    [ 7, 8,11,10],
-    [ 8, 9,12,11],
-    [10,11,14,13],
-    [11,12,15,14],
-])
-Ex,Ey = cfc.coordxtr(Edof,Coord,Dof)
+D = np.array([[1, 0], [0, 1]])
+Edof = np.array(
+    [
+        [1, 2, 5, 4],
+        [2, 3, 6, 5],
+        [4, 5, 8, 7],
+        [5, 6, 9, 8],
+        [7, 8, 11, 10],
+        [8, 9, 12, 11],
+        [10, 11, 14, 13],
+        [11, 12, 15, 14],
+    ]
+)
+Ex, Ey = cfc.coordxtr(Edof, Coord, Dof)
 
 # ----- Generate FE-mesh -----
 
-#clf; eldraw2(Ex,Ey,[1 3 0],Edof(:,1));
-#disp('PRESS ENTER TO CONTINUE'); pause; clf;
+# clf; eldraw2(Ex,Ey,[1 3 0],Edof(:,1));
+# disp('PRESS ENTER TO CONTINUE'); pause; clf;
 
 # ----- Create and assemble element matrices -----
 
 for i in range(8):
-    Ke = cfc.flw2qe(Ex[i],Ey[i],ep,D)
-    K = cfc.assem(Edof[i],K,Ke)
+    Ke = cfc.flw2qe(Ex[i], Ey[i], ep, D)
+    K = cfc.assem(Edof[i], K, Ke)
 
 # ----- Solve equation system -----
 
-bcPrescr = np.array([1,2,3,4,7,10,13,14,15])
-bcVal = np.array([0,0,0,0,0,0,0.5e-3,1e-3,1e-3])
-a,r = cfc.solveq(K,f,bcPrescr,bcVal)
+bcPrescr = np.array([1, 2, 3, 4, 7, 10, 13, 14, 15])
+bcVal = np.array([0, 0, 0, 0, 0, 0, 0.5e-3, 1e-3, 1e-3])
+a, r = cfc.solveq(K, f, bcPrescr, bcVal)
 
 # ----- Compute element flux vector -----
 
-Ed = cfc.extractEldisp(Edof,a)
-Es = np.zeros((8,2))
+Ed = cfc.extractEldisp(Edof, a)
+Es = np.zeros((8, 2))
 for i in range(8):
-    Es[i],Et = cfc.flw2qs(Ex[i],Ey[i],ep,D,Ed[i])
+    Es[i], Et = cfc.flw2qs(Ex[i], Ey[i], ep, D, Ed[i])
 
-# ----- Draw flux vectors and contourlines -----
-
-print(Ex)
-print(Ey)
-print(a)
-print(Ed)
-
-cfv.eldraw2(Ex, Ey, [1, 2, 1], range(1,Ex.shape[0]+1))
-cfv.eliso2_mpl(Ex,Ey,Ed)
-cfv.showAndWaitMpl()
 
-#cfv.showAndWait()
-#sfac=scalfact2(Ex,Ey,Es,0.5);
-#eldraw2(Ex,Ey); 
-#elflux2(Ex,Ey,Es,[1,4],sfac); 
-#pltscalb2(sfac,[2e-2 0.06 0.01],4);
-#disp('PRESS ENTER TO CONTINUE'); pause; clf;
-#eldraw2(Ex,Ey,[1,3,0]); 
-#eliso2(Ex,Ey,Ed,5,[1,4]);
-#hold off; 
-#echo off;
-
-# ----------------- End --------------------------------
+# ----- Draw flux vectors and contourlines -----
 
+cfu.disp_h2("Ex")
+cfu.disp_array(Ex, headers=["x0", "x1", "x2", "x3"])
+cfu.disp_h2("Ey")
+cfu.disp_array(Ey, headers=["x0", "x1", "x2", "x3"])
+cfu.disp_h2("a")
+cfu.disp_array(a)
+cfu.disp_h2("Ed")
+cfu.disp_array(Ed, headers=["ed0", "ed1", "ed2", "ed3"])
+
+cfv.eldraw2(Ex, Ey, [1, 2, 1], range(1, Ex.shape[0] + 1))
+cfv.eliso2_mpl(Ex, Ey, Ed)
+cfv.show_and_wait()
diff --git a/examples/exs_flw_temp1.py b/examples/exs_flw_temp1.py
index b92c2e1..83010f8 100644
--- a/examples/exs_flw_temp1.py
+++ b/examples/exs_flw_temp1.py
@@ -15,6 +15,7 @@
 
 import numpy as np
 import calfem.core as cfc
+import calfem.utils as cfu
 
 # ----- Topology -------------------------------------------------
 
@@ -60,10 +61,11 @@
 bcVal = np.array([-17, 20])
 a, r = cfc.solveq(K, f, bc, bcVal) 
 
-print("a = ")
-print(a)
-print("r = ")
-print(r)
+cfu.disp_h2("Temperatures a:")
+cfu.disp_array(a)
+
+cfu.disp_h2("Reaction flows r:")
+cfu.disp_array(r)
 
 # ----- Section forces -------------------------------------------
 
@@ -79,6 +81,8 @@
 q4 = cfc.spring1s(ep4, ed4)
 q5 = cfc.spring1s(ep5, ed5)
 
+cfu.disp_h2("Element flows:")
+
 print("q1 = ")
 print(q1)
 print("q2 = ")
diff --git a/examples/exs_flw_temp2.py b/examples/exs_flw_temp2.py
index 5d64d5e..05caa70 100644
--- a/examples/exs_flw_temp2.py
+++ b/examples/exs_flw_temp2.py
@@ -15,6 +15,7 @@
 
 import numpy as np
 import calfem.core as cfc
+import calfem.utils as cfu
 
 # ----- Topology matrix Edof -------------------------------------
 
@@ -56,8 +57,8 @@
 cfc.assem(edof[3, :], K, Ke4)
 cfc.assem(edof[4, :], K, Ke5)
 
-print("Stiffness matrix K:")
-print(K)
+cfu.disp_h2("Stiffness matrix K:")
+cfu.disp_array(K)
 
 # ----- Solve the system of equations ----------------------------
 
@@ -65,11 +66,11 @@
 bcVal = np.array([-17.0, 20.0])
 a, r = cfc.solveq(K, f, bc, bcVal)
 
-print("Displacements a:")
-print(a)
+cfu.disp_h2("Temperatures a:")
+cfu.disp_array(a)
 
-print("Reaction forces r:")
-print(r)
+cfu.disp_h2("Reaction flows r:")
+cfu.disp_array(r)
 
 # ----- Element flows -------------------------------------------
 
@@ -85,6 +86,8 @@
 q4 = cfc.spring1s(ep4, ed4)
 q5 = cfc.spring1s(ep5, ed5)
 
+cfu.disp_h2("Element flows r:")
+
 print("q1 = "+str(q1))
 print("q2 = "+str(q2))
 print("q3 = "+str(q3))
diff --git a/examples/exs_spring.py b/examples/exs_spring.py
index 7fa38ff..b79ba22 100644
--- a/examples/exs_spring.py
+++ b/examples/exs_spring.py
@@ -18,6 +18,7 @@
 
 import numpy as np
 import calfem.core as cfc
+import calfem.utils as cfu
 
 # ----- Topology matrix Edof
 
@@ -46,8 +47,8 @@
 cfc.assem(edof[1, :], K, Ke1)
 cfc.assem(edof[2, :], K, Ke2)
 
-print("Stiffness matrix K:")
-print(K)
+cfu.disp_h2("Stiffness matrix K:")
+cfu.disp_array(K)
 
 # f[1] corresponds to edof 2
 
@@ -58,11 +59,11 @@
 bc = np.array([1, 3])
 a, r = cfc.solveq(K, f, bc)
 
-print("Displacements a:")
-print(a)
+cfu.disp_h2("Displacements a:")
+cfu.disp_array(a)
 
-print("Reaction forces Q:")
-print(r)
+cfu.disp_h2("Reaction forces r:")
+cfu.disp_array(r)
 
 # ----- Caculate element forces
 
@@ -74,7 +75,7 @@
 es2 = cfc.spring1s(ep1, ed2)
 es3 = cfc.spring1s(ep2, ed3)
 
-print("Element forces N:")
+cfu.disp_h2("Element forces N:")
 print("N1 = "+str(es1))
 print("N2 = "+str(es2))
 print("N3 = "+str(es3))


Test patch:
diff --git a/test_calfem.py b/test_calfem.py
index 4ed255c..9fe84a0 100644
--- a/test_calfem.py
+++ b/test_calfem.py
@@ -1,321 +1,71 @@
 # -*- coding: utf-8 -*-
-
-import unittest, sys, io
-
-from subprocess import Popen, PIPE
-
-def exec_process(source_filename):
-    p = Popen(['python', source_filename], stdin=PIPE, stdout=PIPE)
-    s_out, _ = p.communicate()
-
-    return s_out.decode()
-
-
-#print('Here is what the script produced:\n\n', s_out.decode())
-
-exs1_expected_output = """Stiffness matrix K:
-[[ 3000. -3000.     0.]
- [-3000.  7500. -4500.]
- [    0. -4500.  4500.]]
-Displacements a:
-[[0.        ]
- [0.01333333]
- [0.        ]]
-Reaction forces Q:
-[[-40.]
- [  0.]
- [-60.]]
-Element forces N:
-N1 = 40.0
-N2 = -20.0
-N3 = -40.0
-"""
-
-exs2_expected_output = """Stiffness matrix K:
-[[ 25.  -25.    0.    0.    0.    0. ]
- [-25.   49.3 -24.3   0.    0.    0. ]
- [  0.  -24.3  24.7  -0.4   0.    0. ]
- [  0.    0.   -0.4  17.4 -17.    0. ]
- [  0.    0.    0.  -17.   24.7  -7.7]
- [  0.    0.    0.    0.   -7.7   7.7]]
-Displacements a:
-[[-17.        ]
- [-16.43842455]
- [-15.86067203]
- [ 19.23779344]
- [ 19.47540439]
- [ 20.        ]]
-Reaction forces r:
-[[-1.40393862e+01]
- [ 0.00000000e+00]
- [ 0.00000000e+00]
- [ 0.00000000e+00]
- [ 5.68434189e-14]
- [ 4.03938619e+00]]
-q1 = 14.039386189223357
-q2 = 14.039386189223451
-q3 = 14.039386189223485
-q4 = 4.039386189223492
-q5 = 4.03938618922342
-"""
-
-exs3_expected_output = """Stiffness matrix K:
-[[ 7.50e+07  0.00e+00  0.00e+00  0.00e+00 -7.50e+07  0.00e+00  0.00e+00
-   0.00e+00]
- [ 0.00e+00  0.00e+00  0.00e+00  0.00e+00  0.00e+00  0.00e+00  0.00e+00
-   0.00e+00]
- [ 0.00e+00  0.00e+00  6.40e+07 -4.80e+07 -6.40e+07  4.80e+07  0.00e+00
-   0.00e+00]
- [ 0.00e+00  0.00e+00 -4.80e+07  3.60e+07  4.80e+07 -3.60e+07  0.00e+00
-   0.00e+00]
- [-7.50e+07  0.00e+00 -6.40e+07  4.80e+07  1.39e+08 -4.80e+07  0.00e+00
-   0.00e+00]
- [ 0.00e+00  0.00e+00  4.80e+07 -3.60e+07 -4.80e+07  8.60e+07  0.00e+00
-  -5.00e+07]
- [ 0.00e+00  0.00e+00  0.00e+00  0.00e+00  0.00e+00  0.00e+00  0.00e+00
-   0.00e+00]
- [ 0.00e+00  0.00e+00  0.00e+00  0.00e+00  0.00e+00 -5.00e+07  0.00e+00
-   5.00e+07]]
-Displacements a:
-[[ 0.        ]
- [ 0.        ]
- [ 0.        ]
- [ 0.        ]
- [-0.00039793]
- [-0.00115233]
- [ 0.        ]
- [ 0.        ]]
-Reaction forces r:
-[[ 29844.55958549]
- [     0.        ]
- [-29844.55958549]
- [ 22383.41968912]
- [     0.        ]
- [     0.        ]
- [     0.        ]
- [ 57616.58031088]]
-N1 = -29844.559585492225
-N2 = 57616.580310880825
-N3 = 37305.69948186528
 """
+This is very simple test of the calfem package.
 
-exs4_expected_output = """Stiffness matrix K:
-[[ 3.55307765e+08 -9.28077650e+07  0.00000000e+00  0.00000000e+00
-  -2.62500000e+08  0.00000000e+00 -9.28077650e+07  9.28077650e+07
-   0.00000000e+00  0.00000000e+00  0.00000000e+00  0.00000000e+00]
- [-9.28077650e+07  9.28077650e+07  0.00000000e+00  0.00000000e+00
-   0.00000000e+00  0.00000000e+00  9.28077650e+07 -9.28077650e+07
-   0.00000000e+00  0.00000000e+00  0.00000000e+00  0.00000000e+00]
- [ 0.00000000e+00  0.00000000e+00  3.55307765e+08  9.28077650e+07
-  -9.28077650e+07 -9.28077650e+07 -2.62500000e+08  0.00000000e+00
-   0.00000000e+00  0.00000000e+00  0.00000000e+00  0.00000000e+00]
- [ 0.00000000e+00  0.00000000e+00  9.28077650e+07  9.28077650e+07
-  -9.28077650e+07 -9.28077650e+07  0.00000000e+00  0.00000000e+00
-   0.00000000e+00  0.00000000e+00  0.00000000e+00  0.00000000e+00]
- [-2.62500000e+08  0.00000000e+00 -9.28077650e+07 -9.28077650e+07
-   7.10615530e+08  0.00000000e+00  0.00000000e+00  0.00000000e+00
-  -2.62500000e+08  0.00000000e+00 -9.28077650e+07  9.28077650e+07]
- [ 0.00000000e+00  0.00000000e+00 -9.28077650e+07 -9.28077650e+07
-   0.00000000e+00  4.48115530e+08  0.00000000e+00 -2.62500000e+08
-   0.00000000e+00  0.00000000e+00  9.28077650e+07 -9.28077650e+07]
- [-9.28077650e+07  9.28077650e+07 -2.62500000e+08  0.00000000e+00
-   0.00000000e+00  0.00000000e+00  7.10615530e+08  0.00000000e+00
-  -9.28077650e+07 -9.28077650e+07 -2.62500000e+08  0.00000000e+00]
- [ 9.28077650e+07 -9.28077650e+07  0.00000000e+00  0.00000000e+00
-   0.00000000e+00 -2.62500000e+08  0.00000000e+00  4.48115530e+08
-  -9.28077650e+07 -9.28077650e+07  0.00000000e+00  0.00000000e+00]
- [ 0.00000000e+00  0.00000000e+00  0.00000000e+00  0.00000000e+00
-  -2.62500000e+08  0.00000000e+00 -9.28077650e+07 -9.28077650e+07
-   3.55307765e+08  9.28077650e+07  0.00000000e+00  0.00000000e+00]
- [ 0.00000000e+00  0.00000000e+00  0.00000000e+00  0.00000000e+00
-   0.00000000e+00  0.00000000e+00 -9.28077650e+07 -9.28077650e+07
-   9.28077650e+07  3.55307765e+08  0.00000000e+00 -2.62500000e+08]
- [ 0.00000000e+00  0.00000000e+00  0.00000000e+00  0.00000000e+00
-  -9.28077650e+07  9.28077650e+07 -2.62500000e+08  0.00000000e+00
-   0.00000000e+00  0.00000000e+00  3.55307765e+08 -9.28077650e+07]
- [ 0.00000000e+00  0.00000000e+00  0.00000000e+00  0.00000000e+00
-   9.28077650e+07 -9.28077650e+07  0.00000000e+00  0.00000000e+00
-   0.00000000e+00 -2.62500000e+08 -9.28077650e+07  3.55307765e+08]]
-Displacements a:
-[[ 0.        ]
- [ 0.        ]
- [ 0.        ]
- [ 0.        ]
- [ 0.00238453]
- [-0.0044633 ]
- [-0.00161181]
- [-0.00419874]
- [ 0.00303458]
- [-0.01068377]
- [-0.00165894]
- [-0.01133382]]
-Reaction forces r:
-[[-8.66025404e+05]
- [ 2.40086918e+05]
- [ 6.16025404e+05]
- [ 1.92925784e+05]
- [ 2.32830644e-10]
- [-2.32830644e-10]
- [ 1.16415322e-10]
- [-1.16415322e-10]
- [-2.32830644e-10]
- [ 3.49245965e-10]
- [-2.91038305e-11]
- [ 4.65661287e-10]]
-Element forces:
-N1 = 625938
-N2 = -423100
-N3 = 170640
-N4 = -12372.8
-N5 = -69447
-N6 = 170640
-N7 = -272838
-N8 = -241321
-N9 = 339534
-N10 = 371051
+Make sure all examples run without errors.
 """
 
-exs5_expected_output = """[[ 3.17100000e+08  0.00000000e+00  0.00000000e+00 -3.17100000e+08
-   0.00000000e+00  0.00000000e+00]
- [ 0.00000000e+00  2.34266667e+06  3.51400000e+06  0.00000000e+00
-  -2.34266667e+06  3.51400000e+06]
- [ 0.00000000e+00  3.51400000e+06  7.02800000e+06  0.00000000e+00
-  -3.51400000e+06  3.51400000e+06]
- [-3.17100000e+08  0.00000000e+00  0.00000000e+00  3.17100000e+08
-   0.00000000e+00  0.00000000e+00]
- [ 0.00000000e+00 -2.34266667e+06 -3.51400000e+06  0.00000000e+00
-   2.34266667e+06 -3.51400000e+06]
- [ 0.00000000e+00  3.51400000e+06  3.51400000e+06  0.00000000e+00
-  -3.51400000e+06  7.02800000e+06]]
-a=
-[[ 0.        ]
- [ 0.        ]
- [-0.00948587]
- [ 0.        ]
- [-0.02276608]
- [-0.00379435]
- [ 0.        ]
- [-0.01992032]
- [ 0.00474293]
- [ 0.        ]
- [ 0.        ]
- [ 0.00758869]]
-r=
-[[0.00000000e+00]
- [6.66666667e+03]
- [3.63797881e-12]
- [0.00000000e+00]
- [7.27595761e-12]
- [3.63797881e-12]
- [0.00000000e+00]
- [0.00000000e+00]
- [3.63797881e-12]
- [0.00000000e+00]
- [3.33333333e+03]
- [7.27595761e-12]]
-es1=
-[[ 0.00000000e+00 -6.66666667e+03  9.14372744e-12]
- [ 0.00000000e+00 -6.66666667e+03  2.22222222e+03]
- [ 0.00000000e+00 -6.66666667e+03  4.44444444e+03]
- [ 0.00000000e+00 -6.66666667e+03  6.66666667e+03]
- [ 0.00000000e+00 -6.66666667e+03  8.88888889e+03]
- [ 0.00000000e+00 -6.66666667e+03  1.11111111e+04]
- [ 0.00000000e+00 -6.66666667e+03  1.33333333e+04]
- [ 0.00000000e+00 -6.66666667e+03  1.55555556e+04]
- [ 0.00000000e+00 -6.66666667e+03  1.77777778e+04]
- [ 0.00000000e+00 -6.66666667e+03  2.00000000e+04]
- [ 0.00000000e+00 -6.66666667e+03  2.22222222e+04]]
-es2=
-[[    0.          3333.33333333 20000.        ]
- [    0.          3333.33333333 18888.88888889]
- [    0.          3333.33333333 17777.77777778]
- [    0.          3333.33333333 16666.66666667]
- [    0.          3333.33333333 15555.55555556]
- [    0.          3333.33333333 14444.44444444]
- [    0.          3333.33333333 13333.33333333]
- [    0.          3333.33333333 12222.22222222]
- [    0.          3333.33333333 11111.11111111]
- [    0.          3333.33333333 10000.        ]
- [    0.          3333.33333333  8888.88888889]]
-es3=
-[[ 0.00000000e+00  3.33333333e+03  1.00000000e+04]
- [ 0.00000000e+00  3.33333333e+03  8.88888889e+03]
- [ 0.00000000e+00  3.33333333e+03  7.77777778e+03]
- [ 0.00000000e+00  3.33333333e+03  6.66666667e+03]
- [ 0.00000000e+00  3.33333333e+03  5.55555556e+03]
- [ 0.00000000e+00  3.33333333e+03  4.44444444e+03]
- [ 0.00000000e+00  3.33333333e+03  3.33333333e+03]
- [ 0.00000000e+00  3.33333333e+03  2.22222222e+03]
- [ 0.00000000e+00  3.33333333e+03  1.11111111e+03]
- [ 0.00000000e+00  3.33333333e+03  2.17163527e-11]
- [ 0.00000000e+00  3.33333333e+03 -1.11111111e+03]]
-ed1=
-[[ 0.          0.        ]
- [ 0.         -0.00315415]
- [ 0.         -0.00626145]
- [ 0.         -0.00927507]
- [ 0.         -0.01214815]
- [ 0.         -0.01483386]
- [ 0.         -0.01728536]
- [ 0.         -0.01945578]
- [ 0.         -0.02129831]
- [ 0.         -0.02276608]
- [ 0.         -0.02381226]]
-ed2=
-[[ 0.         -0.02276608]
- [ 0.         -0.02382397]
- [ 0.         -0.02448368]
- [ 0.         -0.02476865]
- [ 0.         -0.02470229]
- [ 0.         -0.02430802]
- [ 0.         -0.02360927]
- [ 0.         -0.02262945]
- [ 0.         -0.02139199]
- [ 0.         -0.01992032]
- [ 0.         -0.01823785]]
-ed3=
-[[ 0.00000000e+00 -1.99203187e-02]
- [ 0.00000000e+00 -1.82378462e-02]
- [ 0.00000000e+00 -1.63679985e-02]
- [ 0.00000000e+00 -1.43341976e-02]
- [ 0.00000000e+00 -1.21598653e-02]
- [ 0.00000000e+00 -9.86842362e-03]
- [ 0.00000000e+00 -7.48329434e-03]
- [ 0.00000000e+00 -5.02789938e-03]
- [ 0.00000000e+00 -2.52566063e-03]
- [ 0.00000000e+00  1.73472348e-18]
- [ 0.00000000e+00  2.52566063e-03]]
- """
-
-class TestCalfemCore(unittest.TestCase):
-
-    def run_test(self, filename, expected_output):
-        saved_stdout = sys.stdout
-        try:
-            out = io.StringIO()
-            sys.stdout = out
-            output = exec_process(filename)
-
-            cleaned_output = output.replace("\r", "")
-
-            self.assertEqual(cleaned_output.strip(), expected_output.strip(), "Output from %s differs from expected." % (filename))
-        finally:
-            sys.stdout = saved_stdout        
-
-    def test_exs1(self):
-        self.run_test('examples/exs1.py', exs1_expected_output)
-
-    def test_exs2(self):
-        self.run_test('examples/exs2.py', exs2_expected_output)
-
-    def test_exs3(self):
-        self.run_test('examples/exs3.py', exs3_expected_output)
-
-    def test_exs4(self):
-        self.run_test('examples/exs4a.py', exs4_expected_output)
-
-    def test_exs5(self):
-        self.run_test('examples/exs5.py', exs5_expected_output)
-
-if __name__ == '__main__':
-    unittest.main()
\ No newline at end of file
+import os
+
+
+def test_examples():
+
+    examples_dir = "./examples"
+
+    examples = [
+        "exd_beam2_b.py",
+        "exd_beam2_m.py",
+        "exd_beam2_t.py",
+        "exd_beam2_tr.py",
+        "exm_circle_bsplines.py",
+        "exm_flow_model.py",
+        "exm_geometry.py",
+        "exm_stress_2d.py",
+        "exm_stress_2d_export.py",
+        "exm_stress_2d_materials.py",
+        "exm_stress_2d_pyvtk.py",
+        "exm_structured_mesh.py",
+        "exm_temp_2d_markers.py",
+        "exm_temp_2d_splines_arcs.py",
+        "exm_tutorial_1.py",
+        "exm_tutorial_2.py",
+        "exn_bar2g.py",
+        "exn_bar2m.py",
+        "exn_beam2.py",
+        "exn_beam2_b.py",
+        "exs_bar2.py",
+        "exs_bar2_la.py",
+        "exs_bar2_lb.py",
+        "exs_beam1.py",
+        "exs_beam2.py",
+        "exs_beambar2.py",
+        "exs_flw_diff2.py",
+        "exs_flw_temp1.py",
+        "exs_flw_temp2.py",
+        "exs_spring.py"
+    ]
+
+    if os.path.exists("test_examples.log"):
+        os.remove("test_examples.log")
+
+    os.environ["CFV_NO_BLOCK"] = "YES"
+
+    return_codes = 0
+
+    for example in examples:
+        print(f"Running: {example}", end="")
+
+        echo_string = f"echo ------ {example} "
+        os.system(echo_string + "-"*(40-len(example)) +
+                  " >> test_examples.log 2>&1")
+
+        example_path = os.path.join(examples_dir, example)
+
+        return_code = os.system(
+            f"python {example_path} >> test_examples.log 2>&1")
+
+        return_codes += return_code
+
+        print(f" return_code = {return_code}")
+
+    assert return_codes == 0