vcfempy.meshgen module

A module containing attributes, functions, classes and methods for mesh generation in the Voronoi Cell Finite Element Method (VCFEM).

See also

numpy.array

The type array_like refers to objects accepted by the numpy.array routine.

class vcfempy.meshgen.PolyMesh2D(name=None, vertices=None, boundary_vertices=None, verbose_printing=False, high_order_quadrature=False)

Bases: object

A class for 2D polygonal mesh generation.

Parameters
  • name (str, optional) – A name for the mesh. If not provided, will be assigned a default value.

  • vertices (array_like, optional) – Initial vertices to be added to vertices. Passed to add_vertices().

  • boundary_vertices (int | list[int], optional) – Initial boundary vertex or list of boundary vertices to be added. Passed to insert_boundary_vertices().

Other Parameters
  • verbose_printing (bool, optional, default=False) – Flag for verbose printing. Will set verbose_printing.

  • high_order_quadrature (bool, optional, default=False) – Flag for high order element quadrature generation. Will set high_order_quadrature.

Examples

>>> # initialize a mesh, no initial input provided
>>> # (mainly for testing: reset _meshes_created counter)
>>> import vcfempy.meshgen
>>> vcfempy.meshgen.PolyMesh2D._num_created = 0
>>> msh = vcfempy.meshgen.PolyMesh2D()
>>> print(msh.name)
Unnamed Mesh 0
>>> print(msh.num_vertices)
0
>>> # initialize another mesh, no initial input
>>> msh = vcfempy.meshgen.PolyMesh2D()
>>> print(msh.name)
Unnamed Mesh 1
>>> # give the mesh a descriptive name and add some vertices to the mesh
>>> msh.name = 'test mesh'
>>> new_verts = [[0, 0], [0, 1], [1, 1], [1, 0]]
>>> msh.add_vertices(new_verts)
>>> print(msh.name)
test mesh
>>> print(msh.num_vertices)
4
>>> print(msh.vertices)
[[0. 0.]
 [0. 1.]
 [1. 1.]
 [1. 0.]]
>>> # define the analysis boundary for the mesh
>>> # this will also generate the boundary edges
>>> bnd_verts = [k for k, _ in enumerate(msh.vertices)]
>>> msh.insert_boundary_vertices(0, bnd_verts)
>>> print(msh.num_boundary_vertices)
4
>>> print(msh.boundary_vertices)
[0, 1, 2, 3]
>>> print(msh.boundary_edges)
[[0, 1], [1, 2], [2, 3], [3, 0]]
>>> # create a material and material region
>>> import vcfempy.materials
>>> m = vcfempy.materials.Material('rock')
>>> mr = vcfempy.meshgen.MaterialRegion2D(msh, bnd_verts, m, 'rock region')
>>> print(msh.num_material_regions)
1
>>> print(msh.material_regions[0].vertices)
[0, 1, 2, 3]
>>> print(msh.material_regions[0].name)
rock region
>>> print(msh.material_regions[0].material.name)
rock
>>> # generate a simple mesh and check some mesh statistics
>>> msh.mesh_scale = 0.4
>>> msh.add_seed_points([0.5, 0.5])
>>> msh.generate_mesh()
>>> print(msh.num_nodes)
16
>>> print(msh.num_elements)
9
>>> print(msh.num_nodes_per_element)
[4, 4, 4, 4, 4, 4, 4, 4, 4]
>>> # print out detailed mesh information
>>> msh.verbose_printing = True
>>> print(msh)
vcfempy.meshgen.PolyMesh2D 'test mesh'
Number of Vertices = 4
Number of Boundary Vertices = 4
Number of Material Regions = 1
Number of Mesh Edges = 0
Verbose Printing = True
High Order Quadrature = False
Mesh Generated = True
Number of Nodes = 16
Number of Elements = 9
Number of Interface Elements = 12
Number of Boundary Elements = 12

Vertices
[[0. 0.]
 [0. 1.]
 [1. 1.]
 [1. 0.]]

Boundary Vertices
[0, 1, 2, 3]

Boundary Edges
[[0, 1], [1, 2], [2, 3], [3, 0]]

Material Region: rock region, Material: rock
[0, 1, 2, 3]

Nodes
[[-2.77555756e-17  1.00000000e+00]
 [ 3.50000000e-01  1.00000000e+00]
 [ 0.00000000e+00  2.77555756e-17]
 [ 3.50000000e-01  2.77555756e-17]
 [ 1.00000000e+00  1.00000000e+00]
 [ 6.50000000e-01  1.00000000e+00]
 [ 6.50000000e-01  6.50000000e-01]
 [ 1.00000000e+00  6.50000000e-01]
 [ 1.00000000e+00 -2.77555756e-17]
 [ 6.50000000e-01 -2.77555756e-17]
 [ 6.50000000e-01  3.50000000e-01]
 [ 1.00000000e+00  3.50000000e-01]
 [ 2.77555756e-17  6.50000000e-01]
 [ 2.77555756e-17  3.50000000e-01]
 [ 3.50000000e-01  6.50000000e-01]
 [ 3.50000000e-01  3.50000000e-01]]

Element Nodes, Areas, Points, Centroids, Materials
[15, 14, 6, 10], 0.09000000000000002, [0.5 0.5], [0.5 0.5], rock
[15, 3, 2, 13], 0.12249999999999998, [0.2 0.2], [0.175 0.175], rock
[12, 0, 1, 14], 0.1225, [0.2 0.8], [0.175 0.825], rock
[7, 4, 5, 6], 0.1225, [0.8 0.8], [0.825 0.825], rock
[11, 8, 9, 10], 0.12249999999999998, [0.8 0.2], [0.825 0.175], rock
[15, 13, 12, 14], 0.10500000000000001, [0.2 0.5], [0.175 0.5  ], rock
[5, 1, 14, 6], 0.10499999999999998, [0.5 0.8], [0.5   0.825], rock
[10, 6, 7, 11], 0.10500000000000001, [0.8 0.5], [0.825 0.5  ], rock
[3, 15, 10, 9], 0.10500000000000001, [0.5 0.2], [0.5   0.175], rock

Interface Element Nodes and Neighbors
[5, 6], [3, 6]
[6, 7], [3, 7]
[9, 10], [4, 8]
[10, 11], [4, 7]
[6, 10], [7, 0]
[12, 14], [5, 2]
[13, 15], [5, 1]
[14, 15], [5, 0]
[1, 14], [2, 6]
[3, 15], [1, 8]
[6, 14], [0, 6]
[10, 15], [0, 8]

Boundary Element Nodes and Neighbors
[0, 1], 2
[2, 3], 1
[4, 5], 3
[4, 7], 3
[1, 5], 6
[8, 9], 4
[8, 11], 4
[7, 11], 7
[3, 9], 8
[12, 13], 5
[0, 12], 2
[2, 13], 1
>>> # plot the mesh and save an image
>>> import matplotlib.pyplot as plt
>>> fig = plt.figure()
>>> ax = plt.gca()
>>> ax = msh.plot_boundaries()
>>> ax = msh.plot_mesh()
>>> ax = msh.plot_vertices()
>>> ax = msh.plot_nodes()
>>> xmin, xmax, ymin, ymax = plt.axis('equal')
>>> xlab_text = ax.set_xlabel('x', fontweight='bold')
>>> ylab_text = ax.set_ylabel('y', fontweight='bold')
>>> title_text = ax.set_title('Simple square mesh', fontweight='bold')
>>> plt.savefig('PolyMesh2D_simple_mesh_example.png')
property name

A descriptive name for the PolyMesh2D.

Parameters

name (str) – The name of the PolyMesh2D. Will be cast to str regardless of type.

Returns

The name of the PolyMesh2D.

Return type

str

Examples

>>> # create a blank mesh without a name (reset mesh counter)
>>> import vcfempy.meshgen
>>> vcfempy.meshgen.PolyMesh2D._num_created = 0
>>> msh = vcfempy.meshgen.PolyMesh2D()
>>> print(msh.name)
Unnamed Mesh 0
>>> # setting the name
>>> msh.name = 'Flow analysis mesh'
>>> print(msh.name)
Flow analysis mesh
>>> # changing the name property to non-str
>>> # will be cast to str
>>> msh.name = 1
>>> print(msh.name)
1
>>> print(type(msh.name).__name__)
str
>>> # initialize a mesh with a name
>>> msh = vcfempy.meshgen.PolyMesh2D('new mesh')
>>> print(msh.name)
new mesh
>>> # initialize another mesh without a name
>>> # notice that the "Untitled" counter increases for every mesh
>>> # created (including those that were assigned an initial name)
>>> msh = vcfempy.meshgen.PolyMesh2D()
>>> print(msh.name)
Unnamed Mesh 2
property num_vertices

Number of vertices defining the PolyMesh2D geometry.

Returns

The number of vertices in the PolyMesh2D.

Return type

int

Examples

>>> # creating a mesh, no initial vertices provided
>>> import vcfempy.meshgen
>>> msh = vcfempy.meshgen.PolyMesh2D()
>>> print(msh.num_vertices)
0
>>> # creating a mesh, providing initial vertices
>>> new_verts = [[0, 0], [0, 1], [1, 1], [1, 0]]
>>> msh = vcfempy.meshgen.PolyMesh2D(vertices=new_verts)
>>> print(msh.num_vertices)
4
>>> # add a vertex and check num_vertices
>>> msh.add_vertices([1.5, 0.5])
>>> print(msh.num_vertices)
5
property vertices

Array of vertex coordinates defining the PolyMesh2D geometry.

Returns

Array of vertex coordinates in the PolyMesh2D.

Return type

numpy.ndarray, shape = (num_vertices, 2)

Note

The vertices property is not intended to be directly mutable. Instead, modify it using the add_vertices() and delete_vertices() methods.

Examples

>>> # initialize a mesh, no initial vertices provided
>>> import vcfempy.meshgen
>>> msh = vcfempy.meshgen.PolyMesh2D()
>>> print(msh.vertices)
[]
>>> # add some vertices
>>> new_verts = [[0, 0], [0, 1], [1, 1], [1, 0]]
>>> msh.add_vertices(new_verts)
>>> print(msh.vertices)
[[0. 0.]
 [0. 1.]
 [1. 1.]
 [1. 0.]]
add_vertices(vertices)

Add vertices to the PolyMesh2D.

Parameters

vertices (array_like, shape = (2, ) | (n, 2)) – A pair of coordinates or array of coordinate pairs to add to the PolyMesh2D.

Raises
  • TypeError – If vertices has no len() property (e.g. an int)

  • ValueError – If contents of vertices cannot be cast to float. If vertices cannot be stacked with vertices (e.g. due to incompatible shape).

Examples

>>> # create a mesh, passing initial vertex list
>>> import vcfempy.meshgen
>>> verts = [[0, 0], [0, 1], [1, 1], [1, 0]]
>>> msh = vcfempy.meshgen.PolyMesh2D(vertices=verts)
>>> print(msh.vertices)
[[0. 0.]
 [0. 1.]
 [1. 1.]
 [1. 0.]]
>>> # add an individual vertex
>>> msh.add_vertices([1.5, 0.5])
>>> print(msh.vertices)
[[0.  0. ]
 [0.  1. ]
 [1.  1. ]
 [1.  0. ]
 [1.5 0.5]]
>>> # add multiple vertices
>>> msh.add_vertices([[-0.5, 0.5], [0.5, 1.5]])
>>> print(msh.vertices)
[[ 0.   0. ]
 [ 0.   1. ]
 [ 1.   1. ]
 [ 1.   0. ]
 [ 1.5  0.5]
 [-0.5  0.5]
 [ 0.5  1.5]]
>>> # add nothing, in two different ways
>>> msh.add_vertices(None)
>>> msh.add_vertices([])
>>> print(msh.vertices)
[[ 0.   0. ]
 [ 0.   1. ]
 [ 1.   1. ]
 [ 1.   0. ]
 [ 1.5  0.5]
 [-0.5  0.5]
 [ 0.5  1.5]]
>>> # try to add some incompatible types/shapes
>>> msh.add_vertices(['one', 'two'])
Traceback (most recent call last):
    ...
ValueError: could not convert string to float: 'one'
>>> msh.add_vertices(1)
Traceback (most recent call last):
    ...
TypeError: object of type 'int' has no len()
>>> msh.add_vertices([1]) 
Traceback (most recent call last):
    ...
ValueError: ...
>>> msh.add_vertices([1, 2, 3]) 
Traceback (most recent call last):
    ...
ValueError: ...
delete_vertices(del_verts)

Remove vertices from the PolyMesh2D.

Parameters

del_verts (list[int]) – List of indices of vertices to remove.

Raises
  • TypeError – If elements in del_verts cannot be cast to int.

  • IndexError – If elements in del_verts are >= num_vertices or are < -num_vertices.

Note

Prior to removing vertices, an attempt is made to cast del_verts to a flattened numpy.array of int. Duplicate indices are deleted, including positive and negative indices that refer to the same vertex. Each vertex removed will result in removal of that vertex from boundary_vertices, mesh_edges, and material_regions and decrementing other vertex indices accordingly.

Examples

>>> # initialize a mesh and add/delete some vertices
>>> import vcfempy.meshgen
>>> msh = vcfempy.meshgen.PolyMesh2D()
>>> msh.add_vertices([[0, 0], [0, 1], [1, 1], [1, 0]])
>>> msh.insert_boundary_vertices(0, [0, 1, 2, 3])
>>> print(msh.num_vertices)
4
>>> print(msh.boundary_vertices)
[0, 1, 2, 3]
>>> msh.delete_vertices(2)
>>> print(msh.num_vertices)
3
>>> print(msh.vertices)
[[0. 0.]
 [0. 1.]
 [1. 0.]]
>>> print(msh.boundary_vertices)
[0, 1, 2]
>>> print(msh.boundary_edges)
[[0, 1], [1, 2], [2, 0]]
>>> # add some vertices, material regions, and mesh edges
>>> # then delete vertices
>>> # note that deleting vertices does not delete material regions
>>> # or mesh edges, even if it leaves them with < 2 vertices
>>> msh.add_vertices([[1, 1], [1.5, 0.5]])
>>> msh.insert_boundary_vertices(2, [3, 4])
>>> print(msh.vertices)
[[0.  0. ]
 [0.  1. ]
 [1.  0. ]
 [1.  1. ]
 [1.5 0.5]]
>>> print(msh.boundary_vertices)
[0, 1, 3, 4, 2]
>>> mr = vcfempy.meshgen.MaterialRegion2D(msh,
...                                       msh.boundary_vertices)
>>> msh.add_vertices([[0.1, 0.1], [0.8, 0.2], [0.1, 0.8], [0.8, 0.9]])
>>> me = [vcfempy.meshgen.MeshEdge2D(msh, [k, k+1]) for k in [5, 7]]
>>> msh.delete_vertices([4, 6])
>>> print(msh.vertices)
[[0.  0. ]
 [0.  1. ]
 [1.  0. ]
 [1.  1. ]
 [0.1 0.1]
 [0.1 0.8]
 [0.8 0.9]]
>>> print(msh.boundary_vertices)
[0, 1, 3, 2]
>>> print(mr.vertices)
[0, 1, 3, 2]
>>> print(msh.boundary_edges)
[[0, 1], [1, 3], [3, 2], [2, 0]]
>>> print(msh.num_mesh_edges)
2
>>> for me in msh.mesh_edges:
...     print(me.vertices)
[4]
[5, 6]
>>> # generate a mesh, then delete a vertex
>>> msh.mesh_scale = 0.4
>>> msh.add_seed_points([0.5, 0.5])
>>> msh.generate_mesh()
>>> print(msh.num_elements)
9
>>> msh.delete_vertices(-1)
>>> print(msh.vertices)
[[0.  0. ]
 [0.  1. ]
 [1.  0. ]
 [1.  1. ]
 [0.1 0.1]
 [0.1 0.8]]
>>> print(msh.boundary_vertices)
[0, 1, 3, 2]
>>> print(msh.boundary_edges)
[[0, 1], [1, 3], [3, 2], [2, 0]]
>>> print(msh.num_mesh_edges)
2
>>> for me in msh.mesh_edges:
...     print(me.vertices)
[4]
[5]
>>> print(msh.mesh_valid)
False
>>> print(msh.num_elements)
0
>>> # delete no vertices, in multiple ways
>>> msh.delete_vertices(None)
>>> msh.delete_vertices([])
>>> print(msh.num_vertices)
6
>>> # try to delete some invalid vertices
>>> msh.delete_vertices('one')
Traceback (most recent call last):
    ...
ValueError: invalid literal for int() with base 10: 'one'
>>> msh.delete_vertices(6)
Traceback (most recent call last):
    ...
IndexError: at least one index out of range
>>> msh.delete_vertices(-7)
Traceback (most recent call last):
    ...
IndexError: at least one index out of range
>>> msh.delete_vertices(
...                 [[1, 2], 3]) 
Traceback (most recent call last):
    ...
ValueError: ...
property num_boundary_vertices

Number of vertices defining the PolyMesh2D boundary geometry.

Returns

The number of boundary_vertices in the PolyMesh2D.

Return type

int

Examples

>>> # create a mesh, add some vertices
>>> # no boundary vertices added yet
>>> import vcfempy.meshgen
>>> msh = vcfempy.meshgen.PolyMesh2D()
>>> msh.add_vertices([[0, 0], [0, 1], [1, 1], [1, 0]])
>>> print(msh.num_boundary_vertices)
0
>>> # add some boundary vertices
>>> msh.insert_boundary_vertices(0, [k for k, _
...                                  in enumerate(msh.vertices)])
>>> print(msh.num_boundary_vertices)
4
>>> # create a new mesh, providing initial vertices
>>> # and boundary vertices
>>> new_verts = [[0, 0], [0, 1], [1, 1], [1.5, 0.5], [1, 0]]
>>> bnd_verts = [k for k, _ in enumerate(new_verts)]
>>> msh = vcfempy.meshgen.PolyMesh2D(vertices=new_verts,
...                                  boundary_vertices=bnd_verts)
>>> print(msh.num_boundary_vertices)
5
property boundary_vertices

List of vertex indices defining PolyMesh2D boundary geometry.

Returns

The list of vertex indices defining the PolyMesh2D boundary.

Return type

list[int]

Note

The boundary_vertices property is not intended to be directly mutable. Instead modify it using the insert_boundary_vertices(), remove_boundary_vertices(), and pop_boundary_vertex() methods.

Examples

>>> # create a new mesh, no initial vertices provided
>>> import vcfempy.meshgen
>>> msh = vcfempy.meshgen.PolyMesh2D()
>>> print(msh.boundary_vertices)
[]
>>> # add some vertices and boundary vertices
>>> new_verts = [[0, 0], [0, 1], [1, 1], [1, 0]]
>>> bnd_verts = [k for k, _ in enumerate(new_verts)]
>>> msh.add_vertices(new_verts)
>>> msh.insert_boundary_vertices(0, bnd_verts)
>>> print(msh.boundary_vertices)
[0, 1, 2, 3]
property boundary_edges

List of lists of vertex indices defining boundary edges in the PolyMesh2D.

Returns

The list of index pairs that define each edge on the boundary of the PolyMesh2D.

Return type

list[list[int]], shape = (num_boundary_vertices, 2)

Note

The boundary_edges property is not intended to be directly mutable. It is updated each time boundary_vertices is changed by a method such as insert_boundary_vertices(), remove_boundary_vertices(), or pop_boundary_vertex(), so the number of boundary_edges should always be num_boundary_vertices since the geometry is a closed polygon.

Examples

>>> # creating a new mesh, no initial vertices provided
>>> import vcfempy.meshgen
>>> msh = vcfempy.meshgen.PolyMesh2D()
>>> print(msh.boundary_edges)
[]
>>> # add some vertices and boundary vertices
>>> new_verts = [[0, 0], [0, 1], [1, 1], [1.5, 0.5], [1, 0]]
>>> bnd_verts = [k for k, _ in enumerate(new_verts)]
>>> msh.add_vertices(new_verts)
>>> msh.insert_boundary_vertices(0, bnd_verts)
>>> print(msh.num_boundary_vertices)
5
>>> print(len(msh.boundary_edges))
5
>>> print(msh.boundary_edges)
[[0, 1], [1, 2], [2, 3], [3, 4], [4, 0]]
>>> # remove a boundary vertex, boundary edges are updated
>>> msh.remove_boundary_vertices([1, 3])
>>> print(msh.num_boundary_vertices)
3
>>> print(msh.boundary_edges)
[[0, 2], [2, 4], [4, 0]]
insert_boundary_vertices(index, boundary_vertices)

Insert one or more boundary vertex indices to the PolyMesh2D.

Parameters
  • index (int) – The index at which to insert the boundary_vertices into boundary_vertices.

  • boundary_vertices (int | list[int]) – The list of vertex indices to add to boundary_vertices.

Note

Before inserting the values in boundary_vertices, an attempt is made to cast to a flattened numpy.ndarray of int.

Raises
  • TypeError – If index cannot be interpreted as int.

  • ValueError – If boundary_vertices is not array_like, such as a jagged list[list[int]]. If any values in boundary_vertices cannot be cast to int, are already in boundary_vertices, are negative, or are >= num_vertices.

Examples

>>> # create mesh, add some vertices, and add boundary vertices
>>> import vcfempy.meshgen
>>> msh = vcfempy.meshgen.PolyMesh2D()
>>> msh.add_vertices([[0, 0], [0, 1], [1, 1], [1, 0]])
>>> msh.insert_boundary_vertices(0, [0, 1, 2, 3])
>>> print(msh.boundary_vertices)
[0, 1, 2, 3]
>>> # add a single vertex and add it as a boundary vertex
>>> msh.add_vertices([1.5, 0.5])
>>> msh.insert_boundary_vertices(index=3, boundary_vertices=4)
>>> print(msh.boundary_vertices)
[0, 1, 2, 4, 3]
>>> # add two more vertices and add multiply boundary vertices
>>> msh.add_vertices([[0.25, 1.25], [0.75, 1.25]])
>>> msh.insert_boundary_vertices(2, [5, 6])
>>> print(msh.boundary_vertices)
[0, 1, 5, 6, 2, 4, 3]
>>> # the list of boundary vertices need not be 1d
>>> # if not, it will be flattened
>>> msh.add_vertices([[-0.5, 0.1], [-0.75, 0.25],
...                   [-0.75, 0.75], [-0.5, 0.9]])
>>> msh.insert_boundary_vertices(1, [[7, 8], [9, 10]])
>>> print(msh.boundary_vertices)
[0, 7, 8, 9, 10, 1, 5, 6, 2, 4, 3]
>>> # add no boundary vertices, in two different ways
>>> msh.insert_boundary_vertices(0, None)
>>> msh.insert_boundary_vertices(0, [])
>>> print(msh.boundary_vertices)
[0, 7, 8, 9, 10, 1, 5, 6, 2, 4, 3]
>>> # try to insert some invalid boundary vertices
>>> msh.insert_boundary_vertices(0, 'one')
Traceback (most recent call last):
    ...
ValueError: invalid literal for int() with base 10: 'one'
>>> msh.insert_boundary_vertices(0, 1)
Traceback (most recent call last):
    ...
ValueError: 1 is already a boundary vertex
>>> msh.insert_boundary_vertices(0, 11)
Traceback (most recent call last):
    ...
ValueError: vertex index 11 out of range
>>> msh.insert_boundary_vertices(0, -1)
Traceback (most recent call last):
    ...
ValueError: vertex index -1 out of range
>>> msh.insert_boundary_vertices(
...             0, [[1, 2], 3]) 
Traceback (most recent call last):
    ...
ValueError: ...
>>> msh.add_vertices([0.5, -0.5])
>>> msh.insert_boundary_vertices('one', 11)
Traceback (most recent call last):
    ...
TypeError: 'str' object cannot be interpreted as an integer
remove_boundary_vertices(remove_vertices)

Remove one or more boundary vertex indices from the PolyMesh2D.

Parameters

remove_vertices (int | list[int]) – The vertex or list of vertices to remove from boundary_vertices.

Note

Before removing the values in remove_vertices, an attempt will be made to cast it to a flattened numpy.ndarray of int.

Raises

ValueError – If remove_vertices is not array_like, such as a jagged list[list[int]]. If any values in remove_vertices cannot be cast to int or are not in boundary_vertices.

Examples

>>> # create mesh, add some vertices, add/remove boundary vertices
>>> import vcfempy.meshgen
>>> msh = vcfempy.meshgen.PolyMesh2D()
>>> msh.add_vertices([[0, 0], [0, 1], [1, 1], [1, 0]])
>>> msh.insert_boundary_vertices(0, [0, 1, 2, 3])
>>> msh.remove_boundary_vertices(1)
>>> print(msh.boundary_vertices)
[0, 2, 3]
>>> # remove multiple boundary vertices
>>> msh.insert_boundary_vertices(0, 1)
>>> msh.remove_boundary_vertices([1, 3])
>>> print(msh.boundary_vertices)
[0, 2]
>>> # the list of boundary vertices to remove need not be 1d
>>> # if not, it will be flattened
>>> msh.insert_boundary_vertices(1, 1)
>>> msh.insert_boundary_vertices(3, 3)
>>> msh.remove_boundary_vertices([[0, 1], [2, 3]])
>>> print(msh.boundary_vertices)
[]
>>> # remove no boundary vertices, in two different ways
>>> msh.insert_boundary_vertices(0, [0, 1, 2, 3])
>>> msh.remove_boundary_vertices(None)
>>> msh.remove_boundary_vertices([])
>>> print(msh.boundary_vertices)
[0, 1, 2, 3]
>>> # try to remove some invalid boundary vertices
>>> msh.remove_boundary_vertices('one')
Traceback (most recent call last):
    ...
ValueError: invalid literal for int() with base 10: 'one'
>>> msh.remove_boundary_vertices(4)
Traceback (most recent call last):
    ...
ValueError: list.remove(x): x not in list
>>> msh.remove_boundary_vertices(
...                 [[1, 2], 3]) 
Traceback (most recent call last):
    ...
ValueError: ...
pop_boundary_vertex(pop_index=-1)

Pop a boundary vertex at a given index of boundary_vertices from the PolyMesh2D.

Parameters

pop_index (int, optional, default=-1) – The index at which to remove the boundary vertex.

Returns

The value of the boundary vertex that was removed.

Return type

int

Raises
  • TypeError – If pop_index cannot be cast to int.

  • IndexError – If pop_index is not a valid index into boundary_vertices.

Examples

>>> # create mesh, add some vertices, add/remove boundary vertices
>>> import vcfempy.meshgen
>>> msh = vcfempy.meshgen.PolyMesh2D()
>>> msh.add_vertices([[0, 0], [0, 1], [1, 1], [1, 0]])
>>> msh.insert_boundary_vertices(0, [0, 1, 2, 3])
>>> msh.pop_boundary_vertex()
3
>>> print(msh.boundary_vertices)
[0, 1, 2]
>>> # remove a boundary vertex from the middle
>>> msh.insert_boundary_vertices(0, 3)
>>> msh.pop_boundary_vertex(1)
0
>>> print(msh.boundary_vertices)
[3, 1, 2]
>>> # try to remove some invalid boundary vertices
>>> msh.pop_boundary_vertex('one')
Traceback (most recent call last):
    ...
TypeError: 'str' object cannot be interpreted as an integer
>>> msh.pop_boundary_vertex(4)
Traceback (most recent call last):
    ...
IndexError: pop index out of range
>>> msh.remove_boundary_vertices([1, 2, 3])
>>> msh.pop_boundary_vertex()
Traceback (most recent call last):
    ...
IndexError: pop from empty list
property num_material_regions

Number of material regions used to assign vcfempy.materials.Material types to the elements in the PolyMesh2D.

Returns

The number of material_regions in the PolyMesh2D.

Return type

int

Examples

>>> # creating a mesh, no initial material_regions provided
>>> import vcfempy.meshgen
>>> msh = vcfempy.meshgen.PolyMesh2D()
>>> new_verts = [[0, 0], [0, 1], [1, 1], [1.5, 0.5], [1, 0]]
>>> bnd_verts = [k for k, _ in enumerate(new_verts)]
>>> msh.add_vertices(new_verts)
>>> msh.insert_boundary_vertices(0, bnd_verts)
>>> print(msh.num_material_regions)
0
>>> # create a new material region, it will be added to the mesh
>>> mr = vcfempy.meshgen.MaterialRegion2D(msh)
>>> print(msh.num_material_regions)
1
>>> # remove the material region from the mesh
>>> msh.remove_material_region(mr)
>>> print(msh.num_material_regions)
0
property material_regions

List of MaterialRegion2D in the PolyMesh2D defining mesh material geometry.

Returns

The list of material regions in the PolyMesh2D.

Return type

list of MaterialRegion2D

Note

The list of material_regions is not intended to be directly mutable. Instead modify it using the add_material_region() and remove_material_region() methods. New MaterialRegion2D objects require a parent mesh to be set, and by default will be added to that parent mesh.

Examples

>>> # initiaize a mesh, no material regions provided yet
>>> import vcfempy.meshgen
>>> msh = vcfempy.meshgen.PolyMesh2D()
>>> new_verts = [[0, 0], [0, 1], [1, 1], [1, 0]]
>>> msh.add_vertices(new_verts)
>>> bnd_verts = [k for k, _ in enumerate(msh.vertices)]
>>> msh.insert_boundary_vertices(0, bnd_verts)
>>> print(msh.vertices)
[[0. 0.]
 [0. 1.]
 [1. 1.]
 [1. 0.]]
>>> print(msh.material_regions)
[]
>>> # add a material region to the mesh
>>> # this material region fills the bottom half of the mesh
>>> import vcfempy.materials
>>> msh.add_vertices([[0, 0.5], [1, 0.5]])
>>> print(msh.vertices)
[[0.  0. ]
 [0.  1. ]
 [1.  1. ]
 [1.  0. ]
 [0.  0.5]
 [1.  0.5]]
>>> rock = vcfempy.materials.Material('rock')
>>> mr_rock_verts = [0, 4, 5, 3]
>>> mr_rock = vcfempy.meshgen.MaterialRegion2D(msh,
...                                            mr_rock_verts,
...                                            rock)
>>> print(msh.num_material_regions)
1
>>> for mr in msh.material_regions:
...     print(mr.vertices)
[0, 4, 5, 3]
>>> # add another material region filling the top half of the mesh
>>> sand = vcfempy.materials.Material('sand')
>>> mr_sand_verts = [4, 1, 2, 5]
>>> mr_sand = vcfempy.meshgen.MaterialRegion2D(msh,
...                                            mr_sand_verts,
...                                            sand)
>>> print(msh.num_material_regions)
2
>>> for mr in msh.material_regions:
...     print(mr.vertices)
[0, 4, 5, 3]
[4, 1, 2, 5]
>>> # remove a material region from the mesh
>>> msh.remove_material_region(mr_rock)
>>> print(msh.num_material_regions)
1
>>> for mr in msh.material_regions:
...     print(mr.vertices)
[4, 1, 2, 5]
add_material_region(material_region)

Add a MaterialRegion2D to the PolyMesh2D.

Parameters

material_region (MaterialRegion2D) – MaterialRegion2D to add to the PolyMesh2D.

Raises

Note

It is not normally necessary to call add_material_region() when creating a new MaterialRegion2D since it will add itself to the parent PolyMesh2D by default. This is only necessary if the MaterialRegion2D was created with add_to_mesh = False or if the MaterialRegion2D was previously removed from the PolyMesh2D using remove_material_region().

Examples

>>> # create a mesh and a material region, this adds the material
>>> # region by default
>>> import vcfempy.meshgen
>>> msh = vcfempy.meshgen.PolyMesh2D('test mesh')
>>> mr = vcfempy.meshgen.MaterialRegion2D(msh)
>>> print(mr.mesh.name)
test mesh
>>> print(mr in msh.material_regions)
True
>>> # create another material region, but do not add it to the mesh
>>> mr_new = vcfempy.meshgen.MaterialRegion2D(msh, add_to_mesh=False)
>>> print(mr_new.mesh.name)
test mesh
>>> print(mr_new in msh.material_regions)
False
>>> # add the new material region to its parent mesh
>>> msh.add_material_region(mr_new)
>>> print(mr_new in msh.material_regions)
True
>>> # try to add invalid material regions
>>> msh.add_material_region(1)
Traceback (most recent call last):
    ...
TypeError: material region not vcfempy.meshgen.MaterialRegion2D
>>> msh.add_material_region(mr)
Traceback (most recent call last):
    ...
ValueError: material region already in list
>>> new_msh = vcfempy.meshgen.PolyMesh2D()
>>> mr_new = vcfempy.meshgen.MaterialRegion2D(new_msh)
>>> msh.add_material_region(mr_new)
Traceback (most recent call last):
    ...
ValueError: material region does not have self as mesh
remove_material_region(material_region)

Remove a MaterialRegion2D from the PolyMesh2D.

Parameters

material_region (MaterialRegion2D) – MaterialRegion2D to remove from the PolyMesh2D.

Raises

ValueError – If material_region is not in material_regions.

Note

When removing a material region from the PolyMesh2D, the MaterialRegion2D.mesh is not changed, and it can be added again using add_material_region() if desired.

Examples

>>> # create a mesh and a material region, then remove it
>>> import vcfempy.meshgen
>>> msh = vcfempy.meshgen.PolyMesh2D()
>>> mr = vcfempy.meshgen.MaterialRegion2D(msh)
>>> msh.remove_material_region(mr)
>>> print(msh.material_regions)
[]
>>> # try to remove a material region that is not in the mesh
>>> msh.remove_material_region(mr)
Traceback (most recent call last):
    ...
ValueError: list.remove(x): x not in list
property num_mesh_edges

Number of non-boundary edges to be preserved in mesh generation for the PolyMesh2D.

Returns

The number of MeshEdge2D in the PolyMesh2D.

Return type

int

Examples

>>> # create a new mesh, no initial information provided
>>> import vcfempy.meshgen
>>> msh = vcfempy.meshgen.PolyMesh2D()
>>> print(msh.num_mesh_edges)
0
>>> # add some vertices, create a new mesh edge, and add it to
>>> # the mesh
>>> new_verts = [[0, 0], [0, 1], [1, 1], [1.5, 0.5], [1, 0]]
>>> bnd_verts = [k for k, _ in enumerate(new_verts)]
>>> msh.add_vertices(new_verts)
>>> msh.insert_boundary_vertices(0, bnd_verts)
>>> new_verts = [[0.1, 0.1], [0.2, 0.2]]
>>> msh.add_vertices(new_verts)
>>> me = vcfempy.meshgen.MeshEdge2D(msh, [5, 6])
>>> print(msh.num_mesh_edges)
1
property mesh_edges

List of MeshEdge2D defining non-boundary edges to be preserved in mesh generation for the PolyMesh2D.

Returns

The list of MeshEdge2D in the PolyMesh2D.

Return type

list of MeshEdge2D

Note

The list of mesh_edges is not intended to be directly mutable. Instead modify it using the add_mesh_edge() and remove_mesh_edge() methods. New MeshEdge2D objects require a parent mesh to be set, and by default will be added to that parent mesh.

Examples

>>> # initialize a mesh, no initial properties provided
>>> import vcfempy.meshgen
>>> msh = vcfempy.meshgen.PolyMesh2D()
>>> print(msh.mesh_edges)
[]
>>> # add some vertices to the mesh and add a mesh edge
>>> new_verts = [[0, 0], [0, 1], [1, 1], [1, 0]]
>>> msh.add_vertices(new_verts)
>>> bnd_verts = [k for k, _ in enumerate(msh.vertices)]
>>> msh.insert_boundary_vertices(0, bnd_verts)
>>> msh.add_vertices([[0.25, 0.25], [0.75, 0.75]])
>>> print(msh.vertices)
[[0.   0.  ]
 [0.   1.  ]
 [1.   1.  ]
 [1.   0.  ]
 [0.25 0.25]
 [0.75 0.75]]
>>> me = vcfempy.meshgen.MeshEdge2D(msh, [4, 5])
>>> print(msh.num_mesh_edges)
1
>>> for me in msh.mesh_edges:
...     print(me.vertices)
[4, 5]
>>> print(msh.vertices[msh.mesh_edges[0].vertices, :])
[[0.25 0.25]
 [0.75 0.75]]
>>> # add two more mesh edges
>>> # mesh edges can overlap the boundaries
>>> msh.add_vertices([[0.5, 0.75], [1, 1.25],
...                   [0.5, 0.25], [0, -0.25]])
>>> print(msh.vertices)
[[ 0.    0.  ]
 [ 0.    1.  ]
 [ 1.    1.  ]
 [ 1.    0.  ]
 [ 0.25  0.25]
 [ 0.75  0.75]
 [ 0.5   0.75]
 [ 1.    1.25]
 [ 0.5   0.25]
 [ 0.   -0.25]]
>>> me_new = [vcfempy.meshgen.MeshEdge2D(msh, [k, k+1])
...                                      for k in [6, 8]]
>>> print(msh.num_mesh_edges)
3
>>> for me in msh.mesh_edges:
...     print(me.vertices)
[4, 5]
[6, 7]
[8, 9]
>>> for k, me in enumerate(msh.mesh_edges):
...     print(f'Mesh edge {k}')
...     print(msh.vertices[me.vertices, :])
...     print()
Mesh edge 0
[[0.25 0.25]
 [0.75 0.75]]

Mesh edge 1
[[0.5  0.75]
 [1.   1.25]]

Mesh edge 2
[[ 0.5   0.25]
 [ 0.   -0.25]]
add_mesh_edge(mesh_edge)

Add a MeshEdge2D to the PolyMesh2D.

Parameters

mesh_edge (MeshEdge2D) – MeshEdge2D to add to the PolyMesh2D.

Raises
  • TypeError – If mesh_edge is not a MeshEdge2D.

  • ValueError – If mesh_edge is already in mesh_edges or does not have this PolyMesh2D as its parent.

Note

It is not normally necessary to call add_mesh_edge() when creating a new MeshEdge2D since it will add itself to the parent PolyMesh2D by default. This is only necessary if the MeshEdge2D was created with add_to_mesh = False or if the MeshEdge2D was previously removed from the PolyMesh2D using remove_mesh_edge().

Examples

>>> # create a mesh and a mesh edge, this adds the mesh edge by default
>>> import vcfempy.meshgen
>>> msh = vcfempy.meshgen.PolyMesh2D('test mesh')
>>> me = vcfempy.meshgen.MeshEdge2D(msh)
>>> print(me.mesh.name)
test mesh
>>> print(me in msh.mesh_edges)
True
>>> # create another mesh edge, but do not add it to the mesh
>>> me_new = vcfempy.meshgen.MeshEdge2D(msh, add_to_mesh=False)
>>> print(me_new.mesh.name)
test mesh
>>> print(me_new in msh.mesh_edges)
False
>>> # add the new mesh edge to its parent mesh
>>> msh.add_mesh_edge(me_new)
>>> print(me_new in msh.mesh_edges)
True
>>> # try to add invalid mesh edges
>>> msh.add_mesh_edge(1)
Traceback (most recent call last):
    ...
TypeError: mesh edge not vcfempy.meshgen.MeshEdge2D
>>> msh.add_mesh_edge(me)
Traceback (most recent call last):
    ...
ValueError: mesh edge already in list
>>> new_msh = vcfempy.meshgen.PolyMesh2D()
>>> me_new = vcfempy.meshgen.MeshEdge2D(new_msh)
>>> msh.add_mesh_edge(me_new)
Traceback (most recent call last):
    ...
ValueError: mesh edge does not have self as mesh
remove_mesh_edge(mesh_edge)

Remove a MeshEdge2D from the PolyMesh2D.

Parameters

mesh_edge (MeshEdge2D) – MeshEdge2D to remove from the PolyMesh2D.

Raises

ValueError – If mesh_edge is not in mesh_edges.

Note

When removing a mesh edge from the PolyMesh2D, the MeshEdge2D.mesh is not changed, and it can be added again using add_mesh_edge() if desired.

Examples

>>> # create a mesh and a mesh edge, then remove it
>>> import vcfempy.meshgen
>>> msh = vcfempy.meshgen.PolyMesh2D()
>>> me = vcfempy.meshgen.MeshEdge2D(msh)
>>> msh.remove_mesh_edge(me)
>>> print(msh.mesh_edges)
[]
>>> # try to remove a mesh edge that is not in the mesh
>>> msh.remove_mesh_edge(me)
Traceback (most recent call last):
    ...
ValueError: list.remove(x): x not in list
property num_seed_points
property seed_points
add_seed_points(seed_points)
delete_seed_points(del_points)
property points

Array of seed point coordinates for mesh generation of the PolyMesh2D.

Returns

The array of seed point coordinates in the PolyMesh2D.

Return type

numpy.ndarray, shape = (num_elements, 2)

Note

The points property is not intended to be directly mutable, rather points are generated by generate_mesh(). If the mesh is reset (by setting mesh_valid to False, or by changing a property that affects the mesh validity), then the points will be cleared. The number of points will always be num_elements.

Examples

>>> # create a mesh and add some vertices, but no mesh generated yet
>>> import vcfempy.meshgen
>>> msh = vcfempy.meshgen.PolyMesh2D()
>>> new_verts = [[0, 0], [0, 1], [1, 1], [1, 0]]
>>> bnd_verts = [k for k, _ in enumerate(new_verts)]
>>> msh.add_vertices(new_verts)
>>> msh.insert_boundary_vertices(0, bnd_verts)
>>> print(msh.num_elements)
0
>>> print(msh.points)
[]
>>> # generate a simple mesh
>>> # note: num_elements == len(msh.points)
>>> msh.mesh_scale = 0.4
>>> msh.add_seed_points([0.5, 0.5])
>>> msh.generate_mesh()
>>> print(msh.num_elements)
9
>>> print(msh.points)
[[0.5 0.5]
 [0.2 0.2]
 [0.2 0.8]
 [0.8 0.8]
 [0.8 0.2]
 [0.2 0.5]
 [0.5 0.8]
 [0.8 0.5]
 [0.5 0.2]]
>>> # explicitly resetting the mesh clears the seed points
>>> msh.mesh_valid = False
>>> print(msh.num_elements)
0
>>> print(msh.points)
[]
>>> # regenerate the mesh
>>> msh.generate_mesh()
>>> print(msh.num_elements)
9
>>> print(msh.points)
[[0.5 0.5]
 [0.2 0.2]
 [0.2 0.8]
 [0.8 0.8]
 [0.8 0.2]
 [0.2 0.5]
 [0.5 0.8]
 [0.8 0.5]
 [0.5 0.2]]
>>> # adding a boundary vertex also resets the mesh
>>> msh.add_vertices([1.5, 0.5])
>>> msh.insert_boundary_vertices(3, 4)
>>> print(msh.points)
[]
property num_nodes

Number of nodes in the generated mesh of the PolyMesh2D.

Returns

The number of nodes in the PolyMesh2D.

Return type

int

Examples

>>> # create a mesh and add some vertices, but no mesh generated yet
>>> import vcfempy.meshgen
>>> msh = vcfempy.meshgen.PolyMesh2D()
>>> new_verts = [[0, 0], [0, 1], [1, 1], [1, 0]]
>>> bnd_verts = [k for k, _ in enumerate(new_verts)]
>>> msh.add_vertices(new_verts)
>>> msh.insert_boundary_vertices(0, bnd_verts)
>>> print(msh.num_nodes)
0
>>> # generate a simple mesh
>>> msh.mesh_scale = 0.4
>>> msh.add_seed_points([0.5, 0.5])
>>> msh.generate_mesh()
>>> print(msh.num_nodes)
16
>>> # explicitly resetting the mesh clears the nodes
>>> msh.mesh_valid = False
>>> print(msh.num_nodes)
0
>>> # regenerate the mesh
>>> msh.generate_mesh()
>>> print(msh.num_nodes)
16
>>> # adding a boundary vertex also resets the mesh
>>> msh.add_vertices([1.5, 0.5])
>>> msh.insert_boundary_vertices(3, 4)
>>> print(msh.num_nodes)
0
property nodes

Array of node coordinates defining the generated mesh geometry of the PolyMesh2D.

Returns

Array of node coordinates defining the mesh of the PolyMesh2D.

Return type

numpy.ndarray, shape = (num_nodes, 2)

Note

The nodes property is not intended to be directly mutable, rather nodes are generated by generate_mesh(). If the mesh is reset (by setting mesh_valid to False, or by changing a property that affects the mesh validity), then the nodes will be cleared.

Examples

>>> # create a mesh and add some vertices, but no mesh generated yet
>>> import vcfempy.meshgen
>>> msh = vcfempy.meshgen.PolyMesh2D()
>>> new_verts = [[0, 0], [0, 1], [1, 1], [1, 0]]
>>> bnd_verts = [k for k, _ in enumerate(new_verts)]
>>> msh.add_vertices(new_verts)
>>> msh.insert_boundary_vertices(0, bnd_verts)
>>> print(msh.nodes)
[]
>>> # generate a simple mesh
>>> msh.mesh_scale = 0.4
>>> msh.add_seed_points([0.5, 0.5])
>>> msh.generate_mesh()
>>> print(msh.nodes.round(14))
[[-0.    1.  ]
 [ 0.35  1.  ]
 [ 0.    0.  ]
 [ 0.35  0.  ]
 [ 1.    1.  ]
 [ 0.65  1.  ]
 [ 0.65  0.65]
 [ 1.    0.65]
 [ 1.   -0.  ]
 [ 0.65 -0.  ]
 [ 0.65  0.35]
 [ 1.    0.35]
 [ 0.    0.65]
 [ 0.    0.35]
 [ 0.35  0.65]
 [ 0.35  0.35]]
>>> # explicitly resetting the mesh clears the nodes
>>> msh.mesh_valid = False
>>> print(msh.nodes)
[]
>>> # regenerate the mesh
>>> msh.generate_mesh()
>>> print(msh.nodes.round(14))
[[-0.    1.  ]
 [ 0.35  1.  ]
 [ 0.    0.  ]
 [ 0.35  0.  ]
 [ 1.    1.  ]
 [ 0.65  1.  ]
 [ 0.65  0.65]
 [ 1.    0.65]
 [ 1.   -0.  ]
 [ 0.65 -0.  ]
 [ 0.65  0.35]
 [ 1.    0.35]
 [ 0.    0.65]
 [ 0.    0.35]
 [ 0.35  0.65]
 [ 0.35  0.35]]
>>> # adding a boundary vertex also resets the mesh
>>> msh.add_vertices([1.5, 0.5])
>>> msh.insert_boundary_vertices(3, 4)
>>> print(msh.nodes)
[]
property num_elements

Number of elements in the generated mesh of the PolyMesh2D.

Returns

The number of elements in the PolyMesh2D.

Return type

int

Examples

>>> # create a mesh and add some vertices, but no mesh generated yet
>>> import vcfempy.meshgen
>>> msh = vcfempy.meshgen.PolyMesh2D()
>>> new_verts = [[0, 0], [0, 1], [1, 1], [1, 0]]
>>> bnd_verts = [k for k, _ in enumerate(new_verts)]
>>> msh.add_vertices(new_verts)
>>> msh.insert_boundary_vertices(0, bnd_verts)
>>> print(msh.num_elements)
0
>>> # generate a simple mesh
>>> msh.mesh_scale = 0.4
>>> msh.add_seed_points([0.5, 0.5])
>>> msh.generate_mesh()
>>> print(msh.num_elements)
9
>>> # explicitly resetting the mesh clears the elements
>>> msh.mesh_valid = False
>>> print(msh.num_elements)
0
>>> # regenerate the mesh
>>> msh.generate_mesh()
>>> print(msh.num_elements)
9
>>> # adding a boundary vertex also resets the mesh
>>> msh.add_vertices([1.5, 0.5])
>>> msh.insert_boundary_vertices(3, 4)
>>> print(msh.num_elements)
0
property elements

List of PolyElement2D elements in the generated mesh for the PolyMesh2D.

Returns

The list of elements in the PolyMesh2D.

Return type

list of PolyElement2D

Note

The elements property is not intended to be directly mutable, rather elements are generated by generate_mesh(). If the mesh is reset (by setting mesh_valid to False, or by changing a property that affects the mesh validity), then the elements will be cleared.

Examples

>>> # create a mesh and add some vertices but no mesh generated yet
>>> import vcfempy.meshgen
>>> msh = vcfempy.meshgen.PolyMesh2D()
>>> new_verts = [[0, 0], [0, 1], [1, 1], [1, 0]]
>>> bnd_verts = [k for k, _ in enumerate(new_verts)]
>>> msh.add_vertices(new_verts)
>>> msh.insert_boundary_vertices(0, bnd_verts)
>>> print(msh.elements)
[]
>>> # generate a simple mesh
>>> msh.mesh_scale = 0.4
>>> msh.add_seed_points([0.5, 0.5])
>>> msh.generate_mesh()
>>> print(msh.nodes.round(14))
[[-0.    1.  ]
 [ 0.35  1.  ]
 [ 0.    0.  ]
 [ 0.35  0.  ]
 [ 1.    1.  ]
 [ 0.65  1.  ]
 [ 0.65  0.65]
 [ 1.    0.65]
 [ 1.   -0.  ]
 [ 0.65 -0.  ]
 [ 0.65  0.35]
 [ 1.    0.35]
 [ 0.    0.65]
 [ 0.    0.35]
 [ 0.35  0.65]
 [ 0.35  0.35]]
>>> for e in msh.elements:
...     print(e.nodes)
[15, 14, 6, 10]
[15, 3, 2, 13]
[12, 0, 1, 14]
[7, 4, 5, 6]
[11, 8, 9, 10]
[15, 13, 12, 14]
[5, 1, 14, 6]
[10, 6, 7, 11]
[3, 15, 10, 9]
>>> # explicitly resetting the mesh clears the elements
>>> msh.mesh_valid = False
>>> print(msh.elements)
[]
>>> # regenerate the mesh
>>> msh.generate_mesh()
>>> for e in msh.elements:
...     print(e.nodes)
[15, 14, 6, 10]
[15, 3, 2, 13]
[12, 0, 1, 14]
[7, 4, 5, 6]
[11, 8, 9, 10]
[15, 13, 12, 14]
[5, 1, 14, 6]
[10, 6, 7, 11]
[3, 15, 10, 9]
>>> # adding a boundary vertex also resets the mesh
>>> msh.add_vertices([1.5, 0.5])
>>> msh.insert_boundary_vertices(3, 4)
>>> print(msh.elements)
[]
property num_nodes_per_element

Number of nodes per element in the generated mesh for the PolyMesh2D.

Returns

The number of nodes in each element in the PolyMesh2D.

Return type

list[int]

Note

The len(num_nodes_per_element) will always be the same as num_elements.

Examples

>>> # initialize a mesh, no initial information provided
>>> import vcfempy.meshgen
>>> msh = vcfempy.meshgen.PolyMesh2D()
>>> print(msh.num_nodes_per_element)
[]
>>> # add some vertices and boundary vertices to the mesh
>>> new_verts = [[0, 0], [0, 1], [1, 1], [1, 0]]
>>> msh.add_vertices(new_verts)
>>> msh.insert_boundary_vertices(0, [k for k, _
...                                  in enumerate(msh.vertices)])
>>> # generate a simple mesh
>>> msh.mesh_scale = 0.4
>>> msh.add_seed_points([0.5, 0.5])
>>> msh.generate_mesh()
>>> for e in msh.elements:
...     print(e.nodes)
[15, 14, 6, 10]
[15, 3, 2, 13]
[12, 0, 1, 14]
[7, 4, 5, 6]
[11, 8, 9, 10]
[15, 13, 12, 14]
[5, 1, 14, 6]
[10, 6, 7, 11]
[3, 15, 10, 9]
>>> print(msh.num_nodes_per_element)
[4, 4, 4, 4, 4, 4, 4, 4, 4]
>>> # changing the boundary geometry clears the mesh
>>> msh.add_vertices([1.5, 0.5])
>>> msh.insert_boundary_vertices(3, 4)
>>> print(msh.num_nodes_per_element)
[]
property element_materials

List of vcfempy.materials.Material types assigned to each element in the generated mesh for the PolyMesh2D.

Returns

The list of material types assigned to each element in the PolyMesh2D.

Return type

list of vcfempy.materials.Material

Note

The len(element_materials) will always be num_elements.

Examples

>>> # initialize a mesh, no mesh generated yet, so list of element
>>> # materials is empty
>>> # material regions can be overlapping and need not be entirely
>>> # inside the boundaries; to ensure all elements get assigned
>>> # materials, it is better to make the regions overlap, with
>>> # later assigned materials overwriting earlier
>>> import vcfempy.meshgen
>>> import vcfempy.materials
>>> msh = vcfempy.meshgen.PolyMesh2D()
>>> new_verts = [[0, 0], [0, 1], [1, 1], [1, 0]]
>>> msh.add_vertices(new_verts)
>>> msh.insert_boundary_vertices(0, [k for k, _
...                                  in enumerate(msh.vertices)])
>>> msh.add_vertices([[0, 0.5], [1, 0.5]])
>>> rock = vcfempy.materials.Material('rock')
>>> sand = vcfempy.materials.Material('sand')
>>> mr_rock = vcfempy.meshgen.MaterialRegion2D(msh,
...                                            [0, 1, 2, 3],
...                                            rock)
>>> mr_sand = vcfempy.meshgen.MaterialRegion2D(msh,
...                                            [4, 1, 2, 5],
...                                            sand)
>>> print(msh.element_materials)
[]
>>> # generate a simple mesh
>>> # now materials will be assigned to elements
>>> msh.mesh_scale = 0.4
>>> msh.add_seed_points([0.5, 0.5])
>>> msh.generate_mesh()
>>> for m in msh.element_materials:
...     print(m.name)
rock
rock
sand
sand
rock
rock
sand
rock
rock
>>> # changing the boundary geometry clears the mesh
>>> msh.add_vertices([1.5, 0.5])
>>> msh.insert_boundary_vertices(3, 4)
>>> print(msh.element_materials)
[]
property element_areas

Array of areas of the elements in the PolyMesh2D.

Returns

The array of areas of the elements in the PolyMesh2D.

Return type

numpy.ndarray, size = (num_elements, )

Examples

>>> # initialize a mesh, no initial information provided
>>> import vcfempy.meshgen
>>> msh = vcfempy.meshgen.PolyMesh2D()
>>> print(msh.element_areas)
[]
>>> # add some vertices and boundary vertices to the mesh
>>> new_verts = [[0, 0], [0, 1], [1, 1], [1, 0]]
>>> msh.add_vertices(new_verts)
>>> msh.insert_boundary_vertices(0, [k for k, _
...                                  in enumerate(msh.vertices)])
>>> # still no element areas
>>> # because the mesh has not been generated
>>> print(msh.element_areas)
[]
>>> # generate a simple mesh
>>> # now element areas can be calculated
>>> msh.mesh_scale = 0.4
>>> msh.add_seed_points([0.5, 0.5])
>>> msh.generate_mesh()
>>> print(msh.element_areas.round(14))
[0.09   0.1225 0.1225 0.1225 0.1225 0.105  0.105  0.105  0.105 ]
>>> # notice that element areas sum to the area of the boundary
>>> import numpy as np
>>> import shapely.geometry as shp
>>> print(np.sum(msh.element_areas))
1.0
>>> print(shp.Polygon(msh.vertices).area)
1.0
>>> # changing the boundary geometry clears the mesh
>>> msh.add_vertices([1.5, 0.5])
>>> msh.insert_boundary_vertices(3, 4)
>>> print(msh.element_areas)
[]
property element_centroids

Array of centroid coordinates for the elements in the PolyMesh2D.

Return type

numpy.ndarray, shape = (num_elements, 2)

Examples

>>> # initialize a mesh, no initial information provided
>>> import vcfempy.meshgen
>>> msh = vcfempy.meshgen.PolyMesh2D()
>>> print(msh.element_centroids)
[]
>>> # add some vertices and boundary vertices to the mesh
>>> new_verts = [[0, 0], [0, 1], [1, 1], [1, 0]]
>>> msh.add_vertices(new_verts)
>>> msh.insert_boundary_vertices(0, [k for k, _
...                                  in enumerate(msh.vertices)])
>>> # still no element centroids
>>> # because the mesh has not been generated
>>> print(msh.element_centroids)
[]
>>> # generate a simple mesh
>>> # now element centroids can be calculated
>>> msh.mesh_scale = 0.4
>>> msh.add_seed_points([0.5, 0.5])
>>> msh.generate_mesh()
>>> print(msh.element_centroids.round(14))
[[0.5   0.5  ]
 [0.175 0.175]
 [0.175 0.825]
 [0.825 0.825]
 [0.825 0.175]
 [0.175 0.5  ]
 [0.5   0.825]
 [0.825 0.5  ]
 [0.5   0.175]]
>>> # changing the boundary geometry clears the mesh
>>> msh.add_vertices([1.5, 0.5])
>>> msh.insert_boundary_vertices(3, 4)
>>> print(msh.element_centroids)
[]
property element_quad_points

List of arrays of quadrature point coordinates for the elements in the PolyMesh2D.

Returns

The list of quadrature point coordinate arrays for the elements in the PolyMesh2D.

Return type

list[numpy.ndarray]

Note

These are returned as a list of 2d arrays because the number of quadrature points is different for each element, in general, so it cannot be converted into a 3d array. This property is mostly provided for plotting convenience (e.g. if performing global integrations over the whole mesh or plotting the quadrature points for the whole mesh). If performing integrations at the element level, it is better to access the PolyElement2D.quad_points property for each element.

Examples

>>> # initialize a mesh, no initial information provided
>>> import vcfempy.meshgen
>>> msh = vcfempy.meshgen.PolyMesh2D()
>>> print(msh.element_quad_points)
[]
>>> # add some vertices and boundary vertices to the mesh
>>> new_verts = [[0, 0], [0, 1], [1, 1], [1, 0]]
>>> msh.add_vertices(new_verts)
>>> msh.insert_boundary_vertices(0, [k for k, _
...                                  in enumerate(msh.vertices)])
>>> # still no element quadrature points
>>> # because the mesh has not been generated
>>> print(msh.element_quad_points)
[]
>>> # generate a simple mesh
>>> # now element quadrature points can be generated
>>> # notice that the quadrature points are listed in a local
>>> # coordinate system relative to the element centroid
>>> msh.mesh_scale = 0.4
>>> msh.add_seed_points([0.5, 0.5])
>>> msh.generate_mesh()
>>> for k, qp in enumerate(msh.element_quad_points):
...     print(f'Element {k} quad points, nq{k} = {len(qp)}')
...     print(qp.round(14))
Element 0 quad points, nq0 = 9
[[-0.1125 -0.1125]
 [-0.1125  0.1125]
 [ 0.1125  0.1125]
 [ 0.1125 -0.1125]
 [-0.075   0.    ]
 [ 0.      0.075 ]
 [ 0.075   0.    ]
 [ 0.     -0.075 ]
 [ 0.      0.    ]]
Element 1 quad points, nq1 = 9
[[ 0.13125  0.13125]
 [ 0.13125 -0.13125]
 [-0.13125 -0.13125]
 [-0.13125  0.13125]
 [ 0.0875   0.     ]
 [ 0.      -0.0875 ]
 [-0.0875   0.     ]
 [ 0.       0.0875 ]
 [ 0.       0.     ]]
Element 2 quad points, nq2 = 9
[[-0.13125 -0.13125]
 [-0.13125  0.13125]
 [ 0.13125  0.13125]
 [ 0.13125 -0.13125]
 [-0.0875   0.     ]
 [-0.       0.0875 ]
 [ 0.0875   0.     ]
 [ 0.      -0.0875 ]
 [ 0.       0.     ]]
Element 3 quad points, nq3 = 9
[[ 0.13125 -0.13125]
 [ 0.13125  0.13125]
 [-0.13125  0.13125]
 [-0.13125 -0.13125]
 [ 0.0875  -0.     ]
 [-0.       0.0875 ]
 [-0.0875  -0.     ]
 [-0.      -0.0875 ]
 [ 0.       0.     ]]
Element 4 quad points, nq4 = 9
[[ 0.13125  0.13125]
 [ 0.13125 -0.13125]
 [-0.13125 -0.13125]
 [-0.13125  0.13125]
 [ 0.0875  -0.     ]
 [ 0.      -0.0875 ]
 [-0.0875  -0.     ]
 [ 0.       0.0875 ]
 [ 0.       0.     ]]
Element 5 quad points, nq5 = 9
[[ 0.13125 -0.1125 ]
 [-0.13125 -0.1125 ]
 [-0.13125  0.1125 ]
 [ 0.13125  0.1125 ]
 [ 0.      -0.075  ]
 [-0.0875  -0.     ]
 [ 0.       0.075  ]
 [ 0.0875  -0.     ]
 [ 0.       0.     ]]
Element 6 quad points, nq6 = 9
[[ 0.1125   0.13125]
 [-0.1125   0.13125]
 [-0.1125  -0.13125]
 [ 0.1125  -0.13125]
 [-0.       0.0875 ]
 [-0.075   -0.     ]
 [ 0.      -0.0875 ]
 [ 0.075   -0.     ]
 [ 0.       0.     ]]
Element 7 quad points, nq7 = 9
[[-0.13125 -0.1125 ]
 [-0.13125  0.1125 ]
 [ 0.13125  0.1125 ]
 [ 0.13125 -0.1125 ]
 [-0.0875  -0.     ]
 [ 0.       0.075  ]
 [ 0.0875  -0.     ]
 [ 0.      -0.075  ]
 [ 0.       0.     ]]
Element 8 quad points, nq8 = 9
[[-0.1125  -0.13125]
 [-0.1125   0.13125]
 [ 0.1125   0.13125]
 [ 0.1125  -0.13125]
 [-0.075    0.     ]
 [-0.       0.0875 ]
 [ 0.075    0.     ]
 [-0.      -0.0875 ]
 [ 0.       0.     ]]
>>> # changing the boundary geometry clears the mesh
>>> msh.add_vertices([1.5, 0.5])
>>> msh.insert_boundary_vertices(3, 4)
>>> print(msh.element_quad_points)
[]
property element_quad_weights

List of arrays of quadrature point weights for the elements in the PolyMesh2D.

Returns

The list of quadrature point weight arrays for the elements in the PolyMesh2D.

Return type

list[numpy.ndarray]

Note

These are returned as a list of 1d arrays because the number of quadrature points is different for each element, in general, so it cannot be converted into a 2d array. This property is mostly provided for plotting convenience (e.g. if performing global integrations over the whole mesh or plotting the quadrature points for the whole mesh). If performing integrations at the element level, it is better to access the PolyElement2D.quad_weights property for each element.

Examples

>>> # initialize a mesh, no initial information provided
>>> import vcfempy.meshgen
>>> msh = vcfempy.meshgen.PolyMesh2D()
>>> print(msh.element_quad_weights)
[]
>>> # add some vertices and boundary vertices to the mesh
>>> new_verts = [[0, 0], [0, 1], [1, 1], [1, 0]]
>>> msh.add_vertices(new_verts)
>>> msh.insert_boundary_vertices(0, [k for k, _
...                                  in enumerate(msh.vertices)])
>>> # still no element quadrature points
>>> # because the mesh has not been generated
>>> print(msh.element_quad_weights)
[]
>>> # generate a simple mesh
>>> # now element quadrature points can be generated
>>> # notice that the quadrature points are listed in a local
>>> # coordinate system relative to the element centroid
>>> msh.mesh_scale = 0.4
>>> msh.add_seed_points([0.5, 0.5])
>>> msh.generate_mesh()
>>> for k, qw in enumerate(msh.element_quad_weights):
...     print(f'Element {k} quad weights, nq{k} = {len(qw)}')
...     print(qw)
Element 0 quad weights, nq0 = 9
[0.1257414  0.1257414  0.1257414  0.1257414  0.10083037 0.10083037
 0.10083037 0.10083037 0.09371293]
Element 1 quad weights, nq1 = 9
[0.1257414  0.1257414  0.1257414  0.1257414  0.10083037 0.10083037
 0.10083037 0.10083037 0.09371293]
Element 2 quad weights, nq2 = 9
[0.1257414  0.1257414  0.1257414  0.1257414  0.10083037 0.10083037
 0.10083037 0.10083037 0.09371293]
Element 3 quad weights, nq3 = 9
[0.1257414  0.1257414  0.1257414  0.1257414  0.10083037 0.10083037
 0.10083037 0.10083037 0.09371293]
Element 4 quad weights, nq4 = 9
[0.1257414  0.1257414  0.1257414  0.1257414  0.10083037 0.10083037
 0.10083037 0.10083037 0.09371293]
Element 5 quad weights, nq5 = 9
[0.1257414  0.1257414  0.1257414  0.1257414  0.10083037 0.10083037
 0.10083037 0.10083037 0.09371293]
Element 6 quad weights, nq6 = 9
[0.1257414  0.1257414  0.1257414  0.1257414  0.10083037 0.10083037
 0.10083037 0.10083037 0.09371293]
Element 7 quad weights, nq7 = 9
[0.1257414  0.1257414  0.1257414  0.1257414  0.10083037 0.10083037
 0.10083037 0.10083037 0.09371293]
Element 8 quad weights, nq8 = 9
[0.1257414  0.1257414  0.1257414  0.1257414  0.10083037 0.10083037
 0.10083037 0.10083037 0.09371293]
>>> # changing the boundary geometry clears the mesh
>>> msh.add_vertices([1.5, 0.5])
>>> msh.insert_boundary_vertices(3, 4)
>>> print(msh.element_quad_weights)
[]
property num_interface_elements

Number of interface_elements in the generated mesh for a PolyMesh2D.

Returns

The number of interface_elements in the PolyMesh2D.

Return type

int

Examples

>>> # create a mesh and add some vertices but no mesh generated yet
>>> import vcfempy.meshgen
>>> msh = vcfempy.meshgen.PolyMesh2D()
>>> new_verts = [[0, 0], [0, 1], [1, 1], [1, 0]]
>>> bnd_verts = [k for k, _ in enumerate(new_verts)]
>>> msh.add_vertices(new_verts)
>>> msh.insert_boundary_vertices(0, bnd_verts)
>>> print(msh.num_interface_elements)
0
>>> # generate a simple mesh
>>> msh.mesh_scale = 0.4
>>> msh.add_seed_points([0.5, 0.5])
>>> msh.generate_mesh()
>>> print(msh.num_interface_elements)
12
>>> # explicitly resetting the mesh clears the interface elements
>>> msh.mesh_valid = False
>>> print(msh.num_interface_elements)
0
>>> # regenerate the mesh
>>> msh.generate_mesh()
>>> print(msh.num_interface_elements)
12
>>> # adding a boundary vertex also resets the mesh
>>> msh.add_vertices([1.5, 0.5])
>>> msh.insert_boundary_vertices(3, 4)
>>> print(msh.num_interface_elements)
0
property interface_elements

List of InterfaceElement2D in the generated mesh for a PolyMesh2D.

Returns

The list of interface elements in the PolyMesh2D.

Return type

list of InterfaceElement2D

Examples

>>> # create a mesh and add some vertices but no mesh generated yet
>>> import vcfempy.meshgen
>>> msh = vcfempy.meshgen.PolyMesh2D()
>>> new_verts = [[0, 0], [0, 1], [1, 1], [1, 0]]
>>> bnd_verts = [k for k, _ in enumerate(new_verts)]
>>> msh.add_vertices(new_verts)
>>> msh.insert_boundary_vertices(0, bnd_verts)
>>> print(msh.interface_elements)
[]
>>> # generate a simple mesh and print the interface elements
>>> # notice that interface node indices are all < msh.num_nodes
>>> # and the neighbor element indices are all < msh.num_elements
>>> # also note that interface elements all include at least one
>>> # node that is not on the boundary
>>> msh.mesh_scale = 0.4
>>> msh.add_seed_points([0.5, 0.5])
>>> msh.generate_mesh()
>>> print(msh.num_nodes)
16
>>> print(msh.nodes.round(14))
[[-0.    1.  ]
 [ 0.35  1.  ]
 [ 0.    0.  ]
 [ 0.35  0.  ]
 [ 1.    1.  ]
 [ 0.65  1.  ]
 [ 0.65  0.65]
 [ 1.    0.65]
 [ 1.   -0.  ]
 [ 0.65 -0.  ]
 [ 0.65  0.35]
 [ 1.    0.35]
 [ 0.    0.65]
 [ 0.    0.35]
 [ 0.35  0.65]
 [ 0.35  0.35]]
>>> for e in msh.interface_elements:
...     print(e.nodes)
[5, 6]
[6, 7]
[9, 10]
[10, 11]
[6, 10]
[12, 14]
[13, 15]
[14, 15]
[1, 14]
[3, 15]
[6, 14]
[10, 15]
>>> print(msh.num_elements)
9
>>> for e in msh.interface_elements:
...     print([msh.elements.index(n) for n in e.neighbors])
[3, 6]
[3, 7]
[4, 8]
[4, 7]
[7, 0]
[5, 2]
[5, 1]
[5, 0]
[2, 6]
[1, 8]
[0, 6]
[0, 8]
>>> # explicitly resetting the mesh clears the interface elements
>>> msh.mesh_valid = False
>>> print(msh.interface_elements)
[]
>>> # regenerate the mesh
>>> msh.generate_mesh()
>>> for e in msh.interface_elements:
...     print(e.nodes)
[5, 6]
[6, 7]
[9, 10]
[10, 11]
[6, 10]
[12, 14]
[13, 15]
[14, 15]
[1, 14]
[3, 15]
[6, 14]
[10, 15]
>>> for e in msh.interface_elements:
...     print([msh.elements.index(n) for n in e.neighbors])
[3, 6]
[3, 7]
[4, 8]
[4, 7]
[7, 0]
[5, 2]
[5, 1]
[5, 0]
[2, 6]
[1, 8]
[0, 6]
[0, 8]
>>> # adding a boundary vertex also resets the mesh
>>> msh.add_vertices([1.5, 0.5])
>>> msh.insert_boundary_vertices(3, 4)
>>> print(msh.interface_elements)
[]
property num_boundary_elements

Number of boundary_elements in the generated mesh for a PolyMesh2D.

Returns

The number of boundary_elements in the PolyMesh2D.

Return type

int

Examples

>>> # create a mesh and add some vertices but no mesh generated yet
>>> import vcfempy.meshgen
>>> msh = vcfempy.meshgen.PolyMesh2D()
>>> new_verts = [[0, 0], [0, 1], [1, 1], [1, 0]]
>>> bnd_verts = [k for k, _ in enumerate(new_verts)]
>>> msh.add_vertices(new_verts)
>>> msh.insert_boundary_vertices(0, bnd_verts)
>>> print(msh.num_boundary_elements)
0
>>> # generate a simple mesh
>>> msh.mesh_scale = 0.4
>>> msh.add_seed_points([0.5, 0.5])
>>> msh.generate_mesh()
>>> print(msh.num_boundary_elements)
12
>>> # explicitly resetting the mesh clears the interface elements
>>> msh.mesh_valid = False
>>> print(msh.num_boundary_elements)
0
>>> # regenerate the mesh
>>> msh.generate_mesh()
>>> print(msh.num_boundary_elements)
12
>>> # adding a boundary vertex also resets the mesh
>>> msh.add_vertices([1.5, 0.5])
>>> msh.insert_boundary_vertices(3, 4)
>>> print(msh.num_boundary_elements)
0
property boundary_elements

List of BoundaryElement2D in the generated mesh for a PolyMesh2D.

Returns

The list of boundary elements in the PolyMesh2D.

Return type

list of BoundaryElement2D

Examples

>>> # create a mesh and add some vertices but no mesh generated yet
>>> import vcfempy.meshgen
>>> msh = vcfempy.meshgen.PolyMesh2D()
>>> new_verts = [[0, 0], [0, 1], [1, 1], [1, 0]]
>>> bnd_verts = [k for k, _ in enumerate(new_verts)]
>>> msh.add_vertices(new_verts)
>>> msh.insert_boundary_vertices(0, bnd_verts)
>>> print(msh.boundary_elements)
[]
>>> # generate a simple mesh and print the boundary elements
>>> # notice that boundary node indices are all < msh.num_nodes
>>> # and the neighbor element indices are all < msh.num_elements
>>> # also note that boundary elements all have both nodes on the
>>> # analysis boundaries
>>> msh.mesh_scale = 0.4
>>> msh.add_seed_points([0.5, 0.5])
>>> msh.generate_mesh()
>>> print(msh.num_nodes)
16
>>> print(msh.nodes.round(14))
[[-0.    1.  ]
 [ 0.35  1.  ]
 [ 0.    0.  ]
 [ 0.35  0.  ]
 [ 1.    1.  ]
 [ 0.65  1.  ]
 [ 0.65  0.65]
 [ 1.    0.65]
 [ 1.   -0.  ]
 [ 0.65 -0.  ]
 [ 0.65  0.35]
 [ 1.    0.35]
 [ 0.    0.65]
 [ 0.    0.35]
 [ 0.35  0.65]
 [ 0.35  0.35]]
>>> for e in msh.boundary_elements:
...     print(e.nodes)
[0, 1]
[2, 3]
[4, 5]
[4, 7]
[1, 5]
[8, 9]
[8, 11]
[7, 11]
[3, 9]
[12, 13]
[0, 12]
[2, 13]
>>> print(msh.num_elements)
9
>>> print([msh.elements.index(e.neighbor)
...        for e in msh.boundary_elements])
[2, 1, 3, 3, 6, 4, 4, 7, 8, 5, 2, 1]
>>> # explicitly resetting the mesh clears the boundary elements
>>> msh.mesh_valid = False
>>> print(msh.boundary_elements)
[]
>>> # regenerate the mesh
>>> msh.generate_mesh()
>>> for e in msh.boundary_elements:
...     print(e.nodes)
[0, 1]
[2, 3]
[4, 5]
[4, 7]
[1, 5]
[8, 9]
[8, 11]
[7, 11]
[3, 9]
[12, 13]
[0, 12]
[2, 13]
>>> print([msh.elements.index(e.neighbor)
...        for e in msh.boundary_elements])
[2, 1, 3, 3, 6, 4, 4, 7, 8, 5, 2, 1]
>>> # adding a boundary vertex also resets the mesh
>>> msh.add_vertices([1.5, 0.5])
>>> msh.insert_boundary_vertices(3, 4)
>>> print(msh.boundary_elements)
[]
property mesh_valid

Flag for whether there is a valid generated mesh for the PolyMesh2D.

Parameters

flag (bool_like) – The new value of the mesh_valid flag.

Returns

The value of the mesh_valid flag.

Return type

bool

Raises

ValueError – If the value of flag cannot be converted to a bool. If flag is True-like, but mesh properties are not set or are invalid or inconsistent.

Note

If setting to False, mesh properties are reset. If setting to True, basic checks of mesh validity are performed before setting the value. str values that can be cast to float are considered True-like if non-zero and False-like if zero. If the str cannot be cast to float, then the values ‘y’, ‘yes’, ‘t’, ‘true’, and ‘on’ (case insensitive) are converted to True and the values ‘n’, ‘no’, ‘f’, ‘false’, and ‘off’ are converted to False. Other str values raise a ValueError. In general, directly setting mesh_valid to False is a way to explicitly clear the mesh, but setting mesh_valid to True should only be done indirectly using the generate_mesh() method, otherwise it is likely that a ValueError will be raised due to invalid mesh properties.

Examples

>>> # create a mesh and add some vertices but no mesh generated yet
>>> import vcfempy.meshgen
>>> msh = vcfempy.meshgen.PolyMesh2D()
>>> new_verts = [[0, 0], [0, 1], [1, 1], [1, 0]]
>>> bnd_verts = [k for k, _ in enumerate(new_verts)]
>>> msh.add_vertices(new_verts)
>>> msh.insert_boundary_vertices(0, bnd_verts)
>>> print(msh.mesh_valid)
False
>>> # generate a simple mesh, which sets mesh_valid as a side effect
>>> msh.mesh_scale = 0.4
>>> msh.add_seed_points([0.5, 0.5])
>>> msh.generate_mesh()
>>> print(msh.mesh_valid)
True
>>> print(msh.num_elements)
9
>>> # explicitly resetting the mesh with a bool value
>>> msh.mesh_valid = False
>>> print(msh.mesh_valid)
False
>>> print(msh.num_elements)
0
>>> # regenerate the mesh
>>> msh.generate_mesh()
>>> print(msh.mesh_valid)
True
>>> # resetting the mesh with a False-like string
>>> msh.mesh_valid = 'no'
>>> print(msh.mesh_valid)
False
>>> print(msh.num_elements)
0
>>> # attempting to set mesh_valid to True-like value, but mesh has
>>> # not been generated
>>> msh.mesh_valid = 'yes'
Traceback (most recent call last):
...
ValueError: trying to set PolyMesh2D.mesh_valid = True, but self.nodes is empty
>>> print(msh.mesh_valid)
False
>>> # attempting to set mesh_valid to non-truth-like str value
>>> msh.mesh_valid = 'dslk'
Traceback (most recent call last):
...
ValueError: invalid truth value 'dslk'
property high_order_quadrature

Flag for whether high order quadrature will be used by the elements of the generated mesh for the PolyMesh2D.

Parameters

flag (bool_like) – The new value of the high_order_quadrature flag.

Returns

The value of the high_order_quadrature flag.

Return type

bool

Raises

ValueError – If the value of flag cannot be converted to a bool.

Note

Setting high_order_quadrature for the PolyMesh2D will clear previously generated quad_points, quad_weights, and quad_integrals for elements in the PolyMesh2D, regardless of the previous value. str values that can be cast to float are considered True-like if non-zero and False-like if zero. If the str cannot be cast to float, then the values ‘y’, ‘yes’, ‘t’, ‘true’, and ‘on’ (case insensitive) are converted to True and the values ‘n’, ‘no’, ‘f’, ‘false’, and ‘off’ are converted to False. Other str values raise a ValueError.

Examples

>>> # create a mesh and add some vertices but no mesh generated yet
>>> import vcfempy.meshgen
>>> msh = vcfempy.meshgen.PolyMesh2D()
>>> new_verts = [[0, 0], [0, 1], [1, 1], [1, 0]]
>>> bnd_verts = [k for k, _ in enumerate(new_verts)]
>>> msh.add_vertices(new_verts)
>>> msh.insert_boundary_vertices(0, bnd_verts)
>>> print(msh.high_order_quadrature)
False
>>> # generate a simple mesh
>>> # elements will use minimum order quadrature
>>> msh.mesh_scale = 0.4
>>> msh.add_seed_points([0.5, 0.5])
>>> msh.generate_mesh()
>>> for k, qp in enumerate(msh.element_quad_points):
...     print(f'Element {k} quad points, nq{k} = {len(qp)}')
...     print(qp.round(14)) 
Element 0 quad points, nq0 = 9
[[-0.1125 -0.1125]
 [-0.1125  0.1125]
 ...
 [ 0.     -0.075 ]
 [ 0.      0.    ]]
Element 1 quad points, nq1 = 9
[[ 0.13125  0.13125]
 [ 0.13125 -0.13125]
 ...
 [ 0.       0.0875 ]
 [ 0.       0.     ]]
Element 2 quad points, nq2 = 9
[[-0.13125 -0.13125]
 [-0.13125  0.13125]
 ...
 [ 0.      -0.0875 ]
 [ 0.       0.     ]]
Element 3 quad points, nq3 = 9
[[ 0.13125 -0.13125]
 [ 0.13125  0.13125]
 ...
 [-0.      -0.0875 ]
 [ 0.       0.     ]]
Element 4 quad points, nq4 = 9
[[ 0.13125  0.13125]
 [ 0.13125 -0.13125]
 ...
 [ 0.       0.0875 ]
 [ 0.       0.     ]]
Element 5 quad points, nq5 = 9
[[ 0.13125 -0.1125 ]
 [-0.13125 -0.1125 ]
 ...
 [ 0.0875  -0.     ]
 [ 0.       0.     ]]
Element 6 quad points, nq6 = 9
[[ 0.1125   0.13125]
 [-0.1125   0.13125]
 ...
 [ 0.075   -0.     ]
 [ 0.       0.     ]]
Element 7 quad points, nq7 = 9
[[-0.13125 -0.1125 ]
 [-0.13125  0.1125 ]
 ...
 [ 0.      -0.075  ]
 [ 0.       0.     ]]
Element 8 quad points, nq8 = 9
[[-0.1125  -0.13125]
 [-0.1125   0.13125]
 ...
 [-0.      -0.0875 ]
 [ 0.       0.     ]]
>>> # switch to high order quadrature
>>> # no need to regenerate mesh, element quadrature will be reset
>>> msh.high_order_quadrature = True
>>> print(msh.high_order_quadrature)
True
>>> for k, qp in enumerate(msh.element_quad_points):
...     print(f'Element {k} quad points, nq{k} = {len(qp)}')
...     print(qp.round(14)) 
Element 0 quad points, nq0 = 17
[[-0.1275 -0.1275]
 [-0.1275  0.1275]
 ...
 [ 0.     -0.051 ]
 [ 0.      0.    ]]
Element 1 quad points, nq1 = 17
[[ 0.14875  0.14875]
 [ 0.14875 -0.14875]
 ...
 [ 0.       0.0595 ]
 [ 0.       0.     ]]
Element 2 quad points, nq2 = 17
[[-0.14875 -0.14875]
 [-0.14875  0.14875]
 ...
 [ 0.      -0.0595 ]
 [ 0.       0.     ]]
Element 3 quad points, nq3 = 17
[[ 0.14875 -0.14875]
 [ 0.14875  0.14875]
 ...
 [-0.      -0.0595 ]
 [ 0.       0.     ]]
Element 4 quad points, nq4 = 17
[[ 0.14875  0.14875]
 [ 0.14875 -0.14875]
 ...
 [ 0.       0.0595 ]
 [ 0.       0.     ]]
Element 5 quad points, nq5 = 17
[[ 0.14875 -0.1275 ]
 [-0.14875 -0.1275 ]
 ...
 [ 0.0595  -0.     ]
 [ 0.       0.     ]]
Element 6 quad points, nq6 = 17
[[ 0.1275   0.14875]
 [-0.1275   0.14875]
 ...
 [ 0.051   -0.     ]
 [ 0.       0.     ]]
Element 7 quad points, nq7 = 17
[[-0.14875 -0.1275 ]
 [-0.14875  0.1275 ]
 ...
 [ 0.      -0.051  ]
 [ 0.       0.     ]]
Element 8 quad points, nq8 = 17
[[-0.1275  -0.14875]
 [-0.1275   0.14875]
 ...
 [-0.      -0.0595 ]
 [ 0.       0.     ]]
>>> # switch back to low order quadrature
>>> # use a False-like string
>>> msh.high_order_quadrature = 'off'
>>> print(msh.high_order_quadrature)
False
>>> for k, qp in enumerate(msh.element_quad_points):
...     print(f'Element {k} quad points, nq{k} = {len(qp)}')
...     print(qp.round(14)) 
Element 0 quad points, nq0 = 9
[[-0.1125 -0.1125]
 [-0.1125  0.1125]
 ...
 [ 0.     -0.075 ]
 [ 0.      0.    ]]
Element 1 quad points, nq1 = 9
[[ 0.13125  0.13125]
 [ 0.13125 -0.13125]
 ...
 [ 0.       0.0875 ]
 [ 0.       0.     ]]
Element 2 quad points, nq2 = 9
[[-0.13125 -0.13125]
 [-0.13125  0.13125]
 ...
 [ 0.      -0.0875 ]
 [ 0.       0.     ]]
Element 3 quad points, nq3 = 9
[[ 0.13125 -0.13125]
 [ 0.13125  0.13125]
 ...
 [-0.      -0.0875 ]
 [ 0.       0.     ]]
Element 4 quad points, nq4 = 9
[[ 0.13125  0.13125]
 [ 0.13125 -0.13125]
 ...
 [ 0.       0.0875 ]
 [ 0.       0.     ]]
Element 5 quad points, nq5 = 9
[[ 0.13125 -0.1125 ]
 [-0.13125 -0.1125 ]
 ...
 [ 0.0875  -0.     ]
 [ 0.       0.     ]]
Element 6 quad points, nq6 = 9
[[ 0.1125   0.13125]
 [-0.1125   0.13125]
 ...
 [ 0.075   -0.     ]
 [ 0.       0.     ]]
Element 7 quad points, nq7 = 9
[[-0.13125 -0.1125 ]
 [-0.13125  0.1125 ]
 ...
 [ 0.      -0.075  ]
 [ 0.       0.     ]]
Element 8 quad points, nq8 = 9
[[-0.1125  -0.13125]
 [-0.1125   0.13125]
 ...
 [-0.      -0.0875 ]
 [ 0.       0.     ]]
>>> # attempting to set high_order_quadrature
>>> # to a non-truth-like str value
>>> msh.high_order_quadrature = 'dslk'
Traceback (most recent call last):
...
ValueError: invalid truth value 'dslk'
property mesh_scale
property mesh_rand
generate_mesh()

Generate polygonal mesh.

property verbose_printing

Flag for whether __str__() will print verbose mesh information for the PolyMesh2D.

Parameters

flag (bool_like) – The new value of the verbose_printing flag.

Returns

The value of the verbose_printing flag.

Return type

bool

Raises

ValueError – If the value of flag cannot be converted to a bool.

Note

str values that can be cast to float are considered True-like if non-zero and False-like if zero. If the str cannot be cast to float, then the values ‘y’, ‘yes’, ‘t’, ‘true’, and ‘on’ (case insensitive) are converted to True and the values ‘n’, ‘no’, ‘f’, ‘false’, and ‘off’ are converted to False. Other str values raise a ValueError.

Examples

>>> # initialize a mesh with no initial information provided
>>> import vcfempy.meshgen
>>> import vcfempy.materials
>>> msh = vcfempy.meshgen.PolyMesh2D('test mesh')
>>> print(msh)
vcfempy.meshgen.PolyMesh2D 'test mesh'
Number of Vertices = 0
Number of Boundary Vertices = 0
Number of Material Regions = 0
Number of Mesh Edges = 0
Verbose Printing = False
High Order Quadrature = False
Mesh Generated = False
>>> # add some vertices and boundary vertices to the mesh
>>> # no mesh generated yet
>>> new_verts = [[0, 0], [0, 1], [1, 1], [1, 0]]
>>> bnd_verts = [k for k, _ in enumerate(new_verts)]
>>> msh.add_vertices(new_verts)
>>> msh.insert_boundary_vertices(0, bnd_verts)
>>> print(msh)
vcfempy.meshgen.PolyMesh2D 'test mesh'
Number of Vertices = 4
Number of Boundary Vertices = 4
Number of Material Regions = 0
Number of Mesh Edges = 0
Verbose Printing = False
High Order Quadrature = False
Mesh Generated = False
>>> # set verbose printing flag
>>> msh.verbose_printing = True
>>> print(msh)
vcfempy.meshgen.PolyMesh2D 'test mesh'
Number of Vertices = 4
Number of Boundary Vertices = 4
Number of Material Regions = 0
Number of Mesh Edges = 0
Verbose Printing = True
High Order Quadrature = False
Mesh Generated = False

Vertices
[[0. 0.]
 [0. 1.]
 [1. 1.]
 [1. 0.]]

Boundary Vertices
[0, 1, 2, 3]

Boundary Edges
[[0, 1], [1, 2], [2, 3], [3, 0]]
>>> # turn off verbose printing and add some vertices
>>> # and two material regions
>>> msh.verbose_printing = 'off'
>>> msh.add_vertices([[0, 0.5], [1, 0.5]])
>>> rock = vcfempy.materials.Material('rock')
>>> sand = vcfempy.materials.Material('sand')
>>> rock_region = vcfempy.meshgen.MaterialRegion2D(mesh=msh,
...     vertices=[0, 1, 2, 3], name='rock region', material=rock)
>>> sand_region = vcfempy.meshgen.MaterialRegion2D(mesh=msh,
...     vertices=[4, 1, 2, 5], name='sand region', material=sand)
>>> print(msh)
vcfempy.meshgen.PolyMesh2D 'test mesh'
Number of Vertices = 6
Number of Boundary Vertices = 4
Number of Material Regions = 2
Number of Mesh Edges = 0
Verbose Printing = False
High Order Quadrature = False
Mesh Generated = False
>>> # turn verbose printing back on and generate the mesh
>>> msh.verbose_printing = 'yes'
>>> msh.mesh_scale = 0.4
>>> msh.add_seed_points([0.5, 0.5])
>>> msh.generate_mesh()
>>> print(msh)
vcfempy.meshgen.PolyMesh2D 'test mesh'
Number of Vertices = 6
Number of Boundary Vertices = 4
Number of Material Regions = 2
Number of Mesh Edges = 0
Verbose Printing = True
High Order Quadrature = False
Mesh Generated = True
Number of Nodes = 16
Number of Elements = 9
Number of Interface Elements = 12
Number of Boundary Elements = 12

Vertices
[[0.  0. ]
 [0.  1. ]
 [1.  1. ]
 [1.  0. ]
 [0.  0.5]
 [1.  0.5]]

Boundary Vertices
[0, 1, 2, 3]

Boundary Edges
[[0, 1], [1, 2], [2, 3], [3, 0]]

Material Region: rock region, Material: rock
[0, 1, 2, 3]

Material Region: sand region, Material: sand
[4, 1, 2, 5]

Nodes
[[-2.77555756e-17  1.00000000e+00]
 [ 3.50000000e-01  1.00000000e+00]
 [ 0.00000000e+00  2.77555756e-17]
 [ 3.50000000e-01  2.77555756e-17]
 [ 1.00000000e+00  1.00000000e+00]
 [ 6.50000000e-01  1.00000000e+00]
 [ 6.50000000e-01  6.50000000e-01]
 [ 1.00000000e+00  6.50000000e-01]
 [ 1.00000000e+00 -2.77555756e-17]
 [ 6.50000000e-01 -2.77555756e-17]
 [ 6.50000000e-01  3.50000000e-01]
 [ 1.00000000e+00  3.50000000e-01]
 [ 2.77555756e-17  6.50000000e-01]
 [ 2.77555756e-17  3.50000000e-01]
 [ 3.50000000e-01  6.50000000e-01]
 [ 3.50000000e-01  3.50000000e-01]]

Element Nodes, Areas, Points, Centroids, Materials
[15, 14, 6, 10], 0.09000000000000002, [0.5 0.5], [0.5 0.5], rock
[15, 3, 2, 13], 0.12249999999999998, [0.2 0.2], [0.175 0.175], rock
[12, 0, 1, 14], 0.1225, [0.2 0.8], [0.175 0.825], sand
[7, 4, 5, 6], 0.1225, [0.8 0.8], [0.825 0.825], sand
[11, 8, 9, 10], 0.12249999999999998, [0.8 0.2], [0.825 0.175], rock
[15, 13, 12, 14], 0.10500000000000001, [0.2 0.5], [0.175 0.5  ], rock
[5, 1, 14, 6], 0.10499999999999998, [0.5 0.8], [0.5   0.825], sand
[10, 6, 7, 11], 0.10500000000000001, [0.8 0.5], [0.825 0.5  ], rock
[3, 15, 10, 9], 0.10500000000000001, [0.5 0.2], [0.5   0.175], rock

Interface Element Nodes and Neighbors
[5, 6], [3, 6]
[6, 7], [3, 7]
[9, 10], [4, 8]
[10, 11], [4, 7]
[6, 10], [7, 0]
[12, 14], [5, 2]
[13, 15], [5, 1]
[14, 15], [5, 0]
[1, 14], [2, 6]
[3, 15], [1, 8]
[6, 14], [0, 6]
[10, 15], [0, 8]

Boundary Element Nodes and Neighbors
[0, 1], 2
[2, 3], 1
[4, 5], 3
[4, 7], 3
[1, 5], 6
[8, 9], 4
[8, 11], 4
[7, 11], 7
[3, 9], 8
[12, 13], 5
[0, 12], 2
[2, 13], 1
>>> # attempting to set verbose_printing
>>> # to a non-truth-like str value
>>> msh.verbose_printing = 'dslk'
Traceback (most recent call last):
...
ValueError: invalid truth value 'dslk'
plot_boundaries(ax=None, **kwargs)

Plot the PolyMesh2D boundary_edges using matplotlib.pyplot.fill().

Parameters

ax (None | matplotlib.axes.Axes) – The axes to plot on. If not provided, will try to get one using matplotlib.pyplot.gca().

Other Parameters

**kwargs (matplotlib.patches.Polygon properties, optional) – Default values: edgecolor = ‘black’ linewidth = 1.0, linestyle = ‘-‘, fill = False.

Returns

The axes that the MaterialRegion2D was plotted on.

Return type

matplotlib.axes.Axes

Examples

>>> # initialize a mesh, then plot the boundaries
>>> import matplotlib.pyplot as plt
>>> import vcfempy.meshgen
>>> msh = vcfempy.meshgen.PolyMesh2D('test mesh')
>>> msh.add_vertices([[0, 0], [0, 1], [1, 1], [1, 0]])
>>> msh.insert_boundary_vertices(0, [0, 1, 2, 3])
>>> fig = plt.figure()
>>> ax = msh.plot_boundaries()
>>> xmin, xmax, ymin, ymax = ax.axis('equal')
>>> xtext = ax.set_xlabel('x')
>>> ytext = ax.set_ylabel('y')
>>> ttext = ax.set_title('PolyMesh2D Boundaries Test Plot')
>>> plt.savefig('PolyMesh2D_boundaries_test_plot.png')
plot_material_regions(ax=None)

Plot the PolyMesh2D material_regions.

Parameters

ax (None | matplotlib.axes.Axes) – The axes to plot on. If not provided, will try to get one using matplotlib.pyplot.gca().

Note

This plot_material_regions() method calls the MaterialRegion2D.plot() method for each material region using default parameters. If you would like to modify the plotting parameters, use the MaterialRegion2D.plot() method directly.

Returns

The axes that the material_regions were plotted on.

Return type

matplotlib.axes.Axes

Examples

>>> # initialize a mesh, then plot the boundaries and material regions
>>> import matplotlib.pyplot as plt
>>> import vcfempy.materials
>>> import vcfempy.meshgen
>>> msh = vcfempy.meshgen.PolyMesh2D('test mesh')
>>> msh.add_vertices([[0, 0], [0, 1], [1, 1], [1, 0]])
>>> msh.add_vertices([[0, 0.5], [1, 0.5]])
>>> msh.insert_boundary_vertices(0, [0, 1, 2, 3])
>>> sand = vcfempy.materials.Material('sand', color='xkcd:sand')
>>> clay = vcfempy.materials.Material('clay', color='xkcd:clay')
>>> sand_reg = vcfempy.meshgen.MaterialRegion2D(msh, [0, 4, 5, 3],
...                                             sand)
>>> clay_reg = vcfempy.meshgen.MaterialRegion2D(msh, [4, 1, 2, 5],
...                                             clay)
>>> fig = plt.figure()
>>> ax = msh.plot_boundaries()
>>> ax = msh.plot_material_regions()
>>> ax = msh.plot_vertices()
>>> xmin, xmax, ymin, ymax = ax.axis('equal')
>>> xtext = ax.set_xlabel('x')
>>> ytext = ax.set_ylabel('y')
>>> ttext = ax.set_title('PolyMesh2D Material Regions Test Plot')
>>> plt.savefig('PolyMesh2D_material_regions_test_plot.png')
plot_vertices(ax=None, **kwargs)

Plot the vertices of the PolyMesh2D using matplotlib.pyplot.plot().

Parameters

ax (matplotlib.axes.Axes, optional) – The axes to plot on. If not provided, will try to get one using matplotlib.pyplot.gca().

Other Parameters

**kwargs (matplotlib.lines.Line2D properties, optional) – Default values: linewidth = 0.0, markeredgecolor = ‘black’ markerfacecolor = ‘white’ marker = ‘s’, markersize = 8.0.

Returns

The axes that the vertices were plotted on.

Return type

matplotlib.axes.Axes

Examples

>>> # initialize a mesh and plot the nodes
>>> import matplotlib.pyplot as plt
>>> import vcfempy.meshgen
>>> msh = vcfempy.meshgen.PolyMesh2D('test mesh')
>>> msh.add_vertices([[0, 0], [0, 1], [1, 1], [1, 0]])
>>> msh.insert_boundary_vertices(0, [0, 1, 2, 3])
>>> rock = vcfempy.materials.Material('rock', color='xkcd:greenish')
>>> mr = vcfempy.meshgen.MaterialRegion2D(msh, msh.boundary_vertices,
...                                       rock, 'rock region')
>>> fig = plt.figure()
>>> ax = msh.plot_boundaries()
>>> ax = msh.plot_material_regions()
>>> ax = msh.plot_vertices()
>>> xmin, xmax, ymin, ymax = ax.axis('equal')
>>> xtext = ax.set_xlabel('x')
>>> ytext = ax.set_ylabel('y')
>>> ttext = ax.set_title('PolyMesh2D Vertices Test Plot')
>>> plt.savefig('PolyMesh2D_vertices_test_plot.png')
plot_mesh_edges(ax=None)
plot_mesh(ax=None, elements=True, interface_elements=True, boundary_elements=True, element_quad_points=False)
plot_nodes(ax=None, **kwargs)

Plot the nodes of the PolyMesh2D using matplotlib.pyplot.plot().

Parameters

ax (matplotlib.axes.Axes, optional) – The axes to plot on. If not provided, will try to get one using matplotlib.pyplot.gca().

Other Parameters

**kwargs (matplotlib.lines.Line2D properties, optional) – Default values: linewidth = 0.0, markeredgecolor = ‘black’ markerfacecolor = ‘white’ marker = ‘o’, markersize = 4.0.

Returns

The axes that the nodes were plotted on.

Return type

matplotlib.axes.Axes

Examples

>>> # initialize a mesh and plot the nodes
>>> import matplotlib.pyplot as plt
>>> import vcfempy.meshgen
>>> msh = vcfempy.meshgen.PolyMesh2D('test mesh')
>>> msh.add_vertices([[0, 0], [0, 1], [1, 1], [1, 0]])
>>> msh.insert_boundary_vertices(0, [0, 1, 2, 3])
>>> rock = vcfempy.materials.Material('rock', color='xkcd:greenish')
>>> mr = vcfempy.meshgen.MaterialRegion2D(msh, msh.boundary_vertices,
...                                       rock, 'rock region')
>>> msh.mesh_scale = 0.2
>>> msh.mesh_rand = 0.2
>>> msh.generate_mesh()
>>> fig = plt.figure()
>>> ax = msh.plot_mesh()
>>> ax = msh.plot_vertices()
>>> ax = msh.plot_nodes()
>>> xmin, xmax, ymin, ymax = ax.axis('equal')
>>> xtext = ax.set_xlabel('x')
>>> ytext = ax.set_ylabel('y')
>>> ttext = ax.set_title('PolyMesh2D Nodes Test Plot')
>>> plt.savefig('PolyMesh2D_nodes_test_plot.png')
class vcfempy.meshgen.MaterialRegion2D(mesh, vertices=None, material=None, name=None, add_to_mesh=True)

Bases: object

A class for defining material regions and their attributes for meshes generated by a PolyMesh2D..

Parameters
Other Parameters

add_to_mesh (bool, optional, default=True) – Flag for whether to add the MaterialRegion2D to its parent mesh. This is done by default when the MaterialRegion2D is created.

Examples

>>> # initialize a mesh, no material regions added
>>> import vcfempy.meshgen
>>> msh = vcfempy.meshgen.PolyMesh2D('test mesh')
>>> msh.add_vertices([[0, 0], [0, 1], [1, 1], [1, 0]])
>>> msh.insert_boundary_vertices(0, [0, 1, 2, 3])
>>> print(msh.num_material_regions)
0
>>> # create a material region, this will add it to its parent mesh
>>> import vcfempy.materials
>>> rock_material = vcfempy.materials.Material('rock material')
>>> rock_region = vcfempy.meshgen.MaterialRegion2D(msh, [0, 1, 2, 3],
...                                                rock_material,
...                                                'rock region')
>>> print(msh.num_material_regions)
1
>>> print(rock_region in msh.material_regions)
True
>>> print(rock_region.name)
rock region
>>> print(rock_region.material.name)
rock material
>>> print(rock_region.vertices)
[0, 1, 2, 3]
>>> # generate a mesh, then change material region material
>>> # this clears the mesh
>>> msh.mesh_scale = 0.4
>>> msh.add_seed_points([0.5, 0.5])
>>> msh.generate_mesh()
>>> print(msh.mesh_valid)
True
>>> rock_region.material = None
>>> print(rock_region.material)
None
>>> print(msh.mesh_valid)
False
>>> # regenerate the mesh, then change the material region vertices
>>> # this also clears the mesh
>>> # note that the material region need not be fully inside the
>>> # mesh boundaries
>>> msh.generate_mesh()
>>> print(msh.mesh_valid)
True
>>> msh.add_vertices([0.5, 1.5])
>>> print(msh.mesh_valid)
True
>>> rock_region.insert_vertices(2, 4)
>>> print(rock_region.vertices)
[0, 1, 4, 2, 3]
>>> print(msh.mesh_valid)
False
property name

A descriptive name for the MaterialRegion2D.

Parameters

name (str) – The name of the MaterialRegion2D. Will be cast to str regardless of type.

Returns

The name of the MaterialRegion2D.

Return type

str

Examples

>>> # create a blank material region without a name (reset counter)
>>> import vcfempy.meshgen
>>> vcfempy.meshgen.MaterialRegion2D._num_created = 0
>>> msh = vcfempy.meshgen.PolyMesh2D()
>>> mr = vcfempy.meshgen.MaterialRegion2D(msh)
>>> print(mr.name)
Unnamed Material Region 0
>>> # setting the name
>>> mr.name = 'Rock region'
>>> print(mr.name)
Rock region
>>> # changing the name property to non-str
>>> # will be cast to str
>>> mr.name = 1
>>> print(mr.name)
1
>>> print(type(mr.name).__name__)
str
>>> # initialize a material region with a name
>>> mr = vcfempy.meshgen.MaterialRegion2D(mesh=msh, name='new region')
>>> print(mr.name)
new region
>>> # initialize another material region without a name
>>> # notice that the "Unnamed" counter increases for every region
>>> # created (including those that were assigned an initial name)
>>> mr = vcfempy.meshgen.MaterialRegion2D(msh)
>>> print(mr.name)
Unnamed Material Region 2
property mesh

The parent PolyMesh2D of the MaterialRegion2D.

Returns

The parent mesh object

Return type

PolyMesh2D

Note

This property is immutable to ensure connection between a PolyMesh2D and a MaterialRegion2D.

Examples

>>> # create a mesh and a material region
>>> # note that creating the material region requires a parent mesh
>>> # and the material region will add itself to the list of parent
>>> # mesh material regions by default
>>> import vcfempy.meshgen
>>> msh = vcfempy.meshgen.PolyMesh2D('test mesh')
>>> mr = vcfempy.meshgen.MaterialRegion2D(msh)
>>> print(mr.mesh.name)
test mesh
>>> print(mr in msh.material_regions)
True
>>> # try to set parent mesh (immutable)
>>> new_mesh = vcfempy.meshgen.PolyMesh2D()
>>> mr.mesh = new_mesh
Traceback (most recent call last):
    ...
AttributeError: can't set attribute 'mesh'
property num_vertices

Number of vertices defining the MaterialRegion2D geometry.

Returns

The number of vertices in the MaterialRegion2D.

Return type

int

Examples

>>> # creating a material region, no initial vertices provided
>>> import vcfempy.meshgen
>>> msh = vcfempy.meshgen.PolyMesh2D()
>>> mr = vcfempy.meshgen.MaterialRegion2D(msh)
>>> print(mr.num_vertices)
0
>>> # creating a material region, providing initial vertices
>>> # these are indices referencing vertices in the parent mesh
>>> new_verts = [[0, 0], [0, 1], [1, 1], [1, 0]]
>>> msh.add_vertices(new_verts)
>>> mr.insert_vertices(0, [k for k, _ in enumerate(new_verts)])
>>> print(mr.num_vertices)
4
>>> # add a vertex and check num_vertices
>>> msh.add_vertices([1.5, 0.5])
>>> mr.insert_vertices(3, 4)
>>> print(mr.num_vertices)
5
property vertices

List of vertex indices defining the boundary of the MaterialRegion2D.

Returns

The list of vertex indices referencing PolyMesh2D.vertices of mesh.

Return type

list[int]

Examples

>>> # creating a material region, no initial vertices provided
>>> import vcfempy.meshgen
>>> msh = vcfempy.meshgen.PolyMesh2D()
>>> mr = vcfempy.meshgen.MaterialRegion2D(msh)
>>> print(mr.num_vertices)
0
>>> # creating a material region, providing initial vertices
>>> # these are indices referencing vertices in the parent mesh
>>> new_verts = [[0, 0], [0, 1], [1, 1], [1, 0]]
>>> msh.add_vertices(new_verts)
>>> mr.insert_vertices(0, [k for k, _ in enumerate(new_verts)])
>>> print(mr.vertices)
[0, 1, 2, 3]
>>> print(msh.vertices[mr.vertices, :])
[[0. 0.]
 [0. 1.]
 [1. 1.]
 [1. 0.]]
>>> # add a vertex and check vertices
>>> msh.add_vertices([1.5, 0.5])
>>> mr.insert_vertices(3, 4)
>>> print(mr.vertices)
[0, 1, 2, 4, 3]
>>> print(msh.vertices[mr.vertices, :])
[[0.  0. ]
 [0.  1. ]
 [1.  1. ]
 [1.5 0.5]
 [1.  0. ]]
property material

The vcfempy.materials.Material assigned to the MaterialRegion2D.

Parameters

material (None | vcfempy.materials.Material) – The material type to assign to the MaterialRegion2D.

Returns

The material type assigned to the MaterialRegion2D.

Return type

None | vcfempy.materials.Material

Raises

TypeError – If material is not None or a vcfempy.materials.Material.

Examples

>>> # create a material region, no material type assigned
>>> import vcfempy.materials
>>> import vcfempy.meshgen
>>> msh = vcfempy.meshgen.PolyMesh2D()
>>> msh.add_vertices([[0, 0], [0, 1], [1, 1], [1, 0]])
>>> msh.insert_boundary_vertices(0, [0, 1, 2, 3])
>>> mr = vcfempy.meshgen.MaterialRegion2D(msh, msh.boundary_vertices,
...                                       name='rock region')
>>> print(mr in msh.material_regions)
True
>>> print(mr.material)
None
>>> # assign a material type to the material region
>>> rock = vcfempy.materials.Material('rock')
>>> mr.material = rock
>>> print(mr.material.name)
rock
>>> # changing material type of a material region resets the mesh
>>> msh.mesh_scale = 0.4
>>> msh.add_seed_points([0.5, 0.5])
>>> msh.generate_mesh()
>>> print(msh.mesh_valid)
True
>>> mr.material = None
>>> print(mr.material)
None
>>> print(msh.mesh_valid)
False
>>> # try to assign invalid materials to a material region
>>> mr.material = 1
Traceback (most recent call last):
    ...
TypeError: type(material) not in [NoneType, vcfempy.materials.Material]
>>> mr.material = 'rock'
Traceback (most recent call last):
    ...
TypeError: type(material) not in [NoneType, vcfempy.materials.Material]
insert_vertices(index, vertices)

Insert one or more vertex indices to the MaterialRegion2D.

Parameters
  • index (int) – The index at which to insert the vertices into vertices.

  • vertices (int | list[int]) – The list of vertex indices to add to vertices.

Note

Before inserting the values in vertices, an attempt is made to cast to a flattened numpy.ndarray of int.

Raises
  • TypeError – If index cannot be interpreted as int.

  • ValueError – If vertices is not array_like, such as a jagged list[list[int]]. If any values in vertices cannot be cast to int, are already in vertices, are negative, or are >= mesh.num_vertices.

Examples

>>> # create mesh and material region, add some vertices
>>> import vcfempy.meshgen
>>> msh = vcfempy.meshgen.PolyMesh2D()
>>> msh.add_vertices([[0, 0], [0, 1], [1, 1], [1, 0]])
>>> mr = vcfempy.meshgen.MaterialRegion2D(msh)
>>> mr.insert_vertices(0, [0, 1, 2, 3])
>>> print(mr.vertices)
[0, 1, 2, 3]
>>> # add a single vertex and add it to the material region
>>> msh.add_vertices([1.5, 0.5])
>>> mr.insert_vertices(index=3, vertices=4)
>>> print(mr.vertices)
[0, 1, 2, 4, 3]
>>> # add two more vertices and add them to the material region
>>> msh.add_vertices([[0.25, 1.25], [0.75, 1.25]])
>>> mr.insert_vertices(2, [5, 6])
>>> print(mr.vertices)
[0, 1, 5, 6, 2, 4, 3]
>>> # the list of boundary vertices need not be 1d
>>> # if not, it will be flattened
>>> msh.add_vertices([[-0.5, 0.1], [-0.75, 0.25],
...                   [-0.75, 0.75], [-0.5, 0.9]])
>>> mr.insert_vertices(1, [[7, 8], [9, 10]])
>>> print(mr.vertices)
[0, 7, 8, 9, 10, 1, 5, 6, 2, 4, 3]
>>> # add no vertices, in two different ways
>>> mr.insert_vertices(0, None)
>>> mr.insert_vertices(0, [])
>>> print(mr.vertices)
[0, 7, 8, 9, 10, 1, 5, 6, 2, 4, 3]
>>> # try to insert some invalid vertices
>>> mr.insert_vertices(0, 'one')
Traceback (most recent call last):
    ...
ValueError: invalid literal for int() with base 10: 'one'
>>> mr.insert_vertices(0, 1)
Traceback (most recent call last):
    ...
ValueError: 1 is already a vertex
>>> mr.insert_vertices(0, 11)
Traceback (most recent call last):
    ...
ValueError: vertex index 11 out of range
>>> mr.insert_vertices(0, -1)
Traceback (most recent call last):
    ...
ValueError: vertex index -1 out of range
>>> mr.insert_vertices(
...             0, [[1, 2], 3]) 
Traceback (most recent call last):
    ...
ValueError: ...
>>> msh.add_vertices([0.5, -0.5])
>>> mr.insert_vertices('one', 11)
Traceback (most recent call last):
    ...
TypeError: 'str' object cannot be interpreted as an integer
remove_vertices(remove_vertices)

Remove one or more vertex indices from the MaterialRegion2D.

Parameters

remove_vertices (int | list[int]) – The vertex or list of vertices to remove from vertices.

Note

Before removing the values in remove_vertices, an attempt will be made to cast it to a flattened numpy.ndarray of int.

Raises

ValueError – If remove_vertices is not array_like, such as a jagged list[list[int]]. If any values in remove_vertices cannot be cast to int or are not in vertices.

Examples

>>> # create mesh and material region, add/remove some vertices
>>> import vcfempy.meshgen
>>> msh = vcfempy.meshgen.PolyMesh2D()
>>> msh.add_vertices([[0, 0], [0, 1], [1, 1], [1, 0]])
>>> mr = vcfempy.meshgen.MaterialRegion2D(msh)
>>> mr.insert_vertices(0, [0, 1, 2, 3])
>>> mr.remove_vertices(1)
>>> print(mr.vertices)
[0, 2, 3]
>>> # remove multiple vertices
>>> mr.insert_vertices(0, 1)
>>> mr.remove_vertices([1, 3])
>>> print(mr.vertices)
[0, 2]
>>> # the list of vertices to remove need not be 1d
>>> # if not, it will be flattened
>>> mr.insert_vertices(1, 1)
>>> mr.insert_vertices(3, 3)
>>> mr.remove_vertices([[0, 1], [2, 3]])
>>> print(mr.vertices)
[]
>>> # remove no vertices, in two different ways
>>> mr.insert_vertices(0, [0, 1, 2, 3])
>>> mr.remove_vertices(None)
>>> mr.remove_vertices([])
>>> print(mr.vertices)
[0, 1, 2, 3]
>>> # try to remove some invalid vertices
>>> mr.remove_vertices('one')
Traceback (most recent call last):
    ...
ValueError: invalid literal for int() with base 10: 'one'
>>> mr.remove_vertices(4)
Traceback (most recent call last):
    ...
ValueError: list.remove(x): x not in list
>>> mr.remove_vertices(
...                 [[1, 2], 3]) 
Traceback (most recent call last):
    ...
ValueError: ...
plot(ax=None, **kwargs)

Plot the MaterialRegion2D using matplotlib.pyplot.fill().

Parameters

ax (None | matplotlib.axes.Axes) – The axes to plot on. If not provided, will try to get one using matplotlib.pyplot.gca().

Other Parameters

**kwargs (matplotlib.patches.Polygon properties, optional) – Default values: edgecolor = material color (or ‘black’ if material is None) with alpha = 1.0, facecolor = material color (or ‘black’ if material is None) with alpha = 0.8, linewidth = 2.0, linestyle = ‘-‘.

Returns

The axes that the MaterialRegion2D was plotted on.

Return type

matplotlib.axes.Axes

Examples

>>> # initialize a mesh and a material region, then plot the
>>> # material region
>>> import matplotlib.pyplot as plt
>>> import vcfempy.materials
>>> import vcfempy.meshgen
>>> msh = vcfempy.meshgen.PolyMesh2D('test mesh')
>>> msh.add_vertices([[0, 0], [0, 1], [1, 1], [1, 0]])
>>> msh.insert_boundary_vertices(0, [0, 1, 2, 3])
>>> rock = vcfempy.materials.Material('rock', color='xkcd:stone')
>>> mr = vcfempy.meshgen.MaterialRegion2D(msh, msh.boundary_vertices,
...                                       rock, 'rock region')
>>> fig = plt.figure()
>>> ax = mr.plot()
>>> xmin, xmax, ymin, ymax = ax.axis('equal')
>>> xtext = ax.set_xlabel('x')
>>> ytext = ax.set_ylabel('y')
>>> ttext = ax.set_title('MaterialRegion2D Test Plot')
>>> leg = ax.legend(labels=[mr.name])
>>> plt.savefig('MaterialRegion2D_test_plot.png')
class vcfempy.meshgen.MeshEdge2D(mesh, vertices=None, material=None, name=None, add_to_mesh=True)

Bases: object

A class for defining edges to be preserved and their attributes for meshes generated by a PolyMesh2D..

Parameters
Other Parameters

add_to_mesh (bool, optional, default=True) – Flag for whether to add the MeshEdge2D to its parent mesh. This is done by default when the MeshEdge2D is created.

Examples

>>> # initialize a mesh, no mesh edges added
>>> import vcfempy.meshgen
>>> msh = vcfempy.meshgen.PolyMesh2D('test mesh')
>>> msh.add_vertices([[0, 0], [0, 1], [1, 1], [1, 0]])
>>> msh.insert_boundary_vertices(0, [0, 1, 2, 3])
>>> print(msh.num_mesh_edges)
0
>>> # create a mesh edge, this will add it to its parent mesh
>>> import vcfempy.materials
>>> rj_material = vcfempy.materials.Material('rock joint material')
>>> msh.add_vertices([[0.1, 0.1], [0.8, 0.8]])
>>> rock_joint = vcfempy.meshgen.MeshEdge2D(msh, [4, 5], rj_material,
...                                         'rock joint')
>>> print(msh.num_mesh_edges)
1
>>> print(rock_joint in msh.mesh_edges)
True
>>> print(rock_joint.name)
rock joint
>>> print(rock_joint.material.name)
rock joint material
>>> print(rock_joint.vertices)
[4, 5]
>>> print(msh.vertices[rock_joint.vertices, :])
[[0.1 0.1]
 [0.8 0.8]]
>>> # generate a mesh, then change mesh edge material
>>> # this clears the mesh
>>> msh.mesh_scale = 0.4
>>> msh.add_seed_points([0.5, 0.5])
>>> msh.generate_mesh()
>>> print(msh.mesh_valid)
True
>>> rock_joint.material = None
>>> print(rock_joint.material)
None
>>> print(msh.mesh_valid)
False
>>> # regenerate the mesh, then change the mesh edge vertices
>>> # this also clears the mesh
>>> msh.generate_mesh()
>>> print(msh.mesh_valid)
True
>>> msh.add_vertices([0.5, 0.65])
>>> print(msh.mesh_valid)
True
>>> rock_joint.insert_vertices(1, 6)
>>> print(rock_joint.vertices)
[4, 6, 5]
>>> print(msh.mesh_valid)
False
property name

A descriptive name for the MeshEdge2D.

Parameters

name (str) – The name of the MeshEdge2D. Will be cast to str regardless of type.

Returns

The name of the MeshEdge2D.

Return type

str

Examples

>>> # create a blank mesh edge without a name (reset counter)
>>> import vcfempy.meshgen
>>> vcfempy.meshgen.MeshEdge2D._num_created = 0
>>> msh = vcfempy.meshgen.PolyMesh2D()
>>> me = vcfempy.meshgen.MeshEdge2D(msh)
>>> print(me.name)
Unnamed Mesh Edge 0
>>> # setting the name
>>> me.name = 'Rock Joint'
>>> print(me.name)
Rock Joint
>>> # changing the name property to non-str
>>> # will be cast to str
>>> me.name = 1
>>> print(me.name)
1
>>> print(type(me.name).__name__)
str
>>> # initialize a mesh edge with a name
>>> me = vcfempy.meshgen.MeshEdge2D(mesh=msh, name='The Edge')
>>> print(me.name)
The Edge
>>> # initialize another mesh edge without a name
>>> # notice that the "Unnamed" counter increases for every edge
>>> # created (including those that were assigned an initial name)
>>> me = vcfempy.meshgen.MeshEdge2D(msh)
>>> print(me.name)
Unnamed Mesh Edge 2
property mesh

The parent PolyMesh2D of the MeshEdge2D.

Returns

The parent mesh object

Return type

PolyMesh2D

Note

This property is immutable to ensure connection between a PolyMesh2D and a MeshEdge2D.

Examples

>>> # create a mesh and a mesh edge
>>> # note that creating the mesh edge requires a parent mesh
>>> # and the mesh edge will add itself to the list of parent
>>> # mesh edges by default
>>> import vcfempy.meshgen
>>> msh = vcfempy.meshgen.PolyMesh2D('test mesh')
>>> me = vcfempy.meshgen.MeshEdge2D(msh)
>>> print(me.mesh.name)
test mesh
>>> print(me in msh.mesh_edges)
True
>>> # try to set parent mesh (immutable)
>>> new_mesh = vcfempy.meshgen.PolyMesh2D()
>>> me.mesh = new_mesh
Traceback (most recent call last):
    ...
AttributeError: can't set attribute 'mesh'
property num_vertices

Number of vertices defining the MeshEdge2D geometry.

Returns

The number of vertices in the MeshEdge2D.

Return type

int

Examples

>>> # creating a mesh edge, no initial vertices provided
>>> import vcfempy.meshgen
>>> msh = vcfempy.meshgen.PolyMesh2D()
>>> me = vcfempy.meshgen.MeshEdge2D(msh)
>>> print(me.num_vertices)
0
>>> # creating a mesh edge, providing initial vertices
>>> # these are indices referencing vertices in the parent mesh
>>> new_verts = [[0, 0], [0, 1], [1, 1], [1, 0]]
>>> msh.add_vertices(new_verts)
>>> msh.add_vertices([[0.1, 0.1], [0.8, 0.8]])
>>> me = vcfempy.meshgen.MeshEdge2D(msh, [4, 5])
>>> print(msh.num_mesh_edges)
2
>>> print(me.num_vertices)
2
>>> # add a vertex and check num_vertices
>>> msh.add_vertices([0.5, 0.65])
>>> me.insert_vertices(1, 6)
>>> print(me.num_vertices)
3
property vertices

The list of vertex indices in the MeshEdge2D.

Returns

A list of vertex indices referencing PolyMesh2D.vertices.

Return type

list[int]

Examples

>>> # creating a mesh edge, no initial vertices provided
>>> import vcfempy.meshgen
>>> msh = vcfempy.meshgen.PolyMesh2D()
>>> me = vcfempy.meshgen.MeshEdge2D(msh)
>>> print(me.vertices)
[]
>>> # creating a mesh edge, providing initial vertices
>>> # these are indices referencing vertices in the parent mesh
>>> new_verts = [[0, 0], [0, 1], [1, 1], [1, 0]]
>>> msh.add_vertices(new_verts)
>>> msh.add_vertices([[0.1, 0.1], [0.8, 0.8]])
>>> me = vcfempy.meshgen.MeshEdge2D(msh, [4, 5])
>>> print(me.vertices)
[4, 5]
>>> print(msh.vertices[me.vertices, :])
[[0.1 0.1]
 [0.8 0.8]]
>>> # add a vertex and check vertices
>>> msh.add_vertices([0.5, 0.65])
>>> me.insert_vertices(1, 6)
>>> print(me.vertices)
[4, 6, 5]
>>> print(msh.vertices[me.vertices, :])
[[0.1  0.1 ]
 [0.5  0.65]
 [0.8  0.8 ]]
property material

The vcfempy.materials.Material assigned to the MeshEdge2D.

Parameters

material (None | vcfempy.materials.Material) – The material type to assign to the MeshEdge2D.

Returns

The material type assigned to the MeshEdge2D.

Return type

None | vcfempy.materials.Material

Raises

TypeError – If material is not None or a vcfempy.materials.Material.

Examples

>>> # create a mesh edge, no material type assigned
>>> import vcfempy.materials
>>> import vcfempy.meshgen
>>> msh = vcfempy.meshgen.PolyMesh2D()
>>> msh.add_vertices([[0, 0], [0, 1], [1, 1], [1, 0]])
>>> msh.insert_boundary_vertices(0, [0, 1, 2, 3])
>>> me = vcfempy.meshgen.MeshEdge2D(msh)
>>> msh.add_vertices([[0.1, 0.1], [0.8, 0.8]])
>>> me.insert_vertices(0, [4, 5])
>>> print(me.material)
None
>>> # create a mesh edge, assigning a material type
>>> rock_joint = vcfempy.materials.Material('rock joint')
>>> rj_edge = vcfempy.meshgen.MeshEdge2D(msh, material=rock_joint)
>>> msh.add_vertices([[0.1, 0.4], [0.3, 0.9]])
>>> rj_edge.insert_vertices(0, [6, 7])
>>> print(rj_edge in msh.mesh_edges)
True
>>> print(rj_edge.material.name)
rock joint
>>> # assign a new material to an edge
>>> sandy_joint = vcfempy.materials.Material('sandy joint')
>>> me.material = sandy_joint
>>> print(me in msh.mesh_edges)
True
>>> print(me.material.name)
sandy joint
>>> # changing material type of an edge resets the mesh
>>> msh.mesh_scale = 0.4
>>> msh.add_seed_points([0.5, 0.5])
>>> msh.generate_mesh()
>>> print(msh.mesh_valid)
True
>>> me.material = None
>>> print(me.material)
None
>>> print(msh.mesh_valid)
False
>>> # try to assign invalid materials to an edge
>>> me.material = 1
Traceback (most recent call last):
    ...
TypeError: type(material) not in [NoneType, vcfempy.materials.Material]
>>> me.material = 'rock joint'
Traceback (most recent call last):
    ...
TypeError: type(material) not in [NoneType, vcfempy.materials.Material]
insert_vertices(index, vertices)

Insert one or more vertex indices to the MeshEdge2D.

Parameters
  • index (int) – The index at which to insert the vertices into vertices.

  • vertices (int | list[int]) – The list of vertex indices to add to vertices.

Note

Before inserting the values in vertices, an attempt is made to cast to a flattened numpy.ndarray of int.

Raises
  • TypeError – If index cannot be interpreted as int.

  • ValueError – If vertices is not array_like, such as a jagged list[list[int]]. If any values in vertices cannot be cast to int, are already in vertices, are negative, or are >= mesh.num_vertices.

Examples

>>> # create mesh and material region, add some vertices
>>> import vcfempy.meshgen
>>> msh = vcfempy.meshgen.PolyMesh2D()
>>> msh.add_vertices([[0, 0], [0, 1], [1, 1], [1, 0]])
>>> msh.add_vertices([[0.1, 0.1], [0.8, 0.8]])
>>> me = vcfempy.meshgen.MeshEdge2D(msh)
>>> me.insert_vertices(0, [4, 5])
>>> print(me.vertices)
[4, 5]
>>> # add a single vertex and add it to the mesh edge
>>> msh.add_vertices([0.5, 0.9])
>>> me.insert_vertices(index=1, vertices=6)
>>> print(me.vertices)
[4, 6, 5]
>>> # add two more vertices and add them to the mesh edge
>>> msh.add_vertices([[0.25, 0.65], [0.35, 0.75]])
>>> me.insert_vertices(1, [7, 8])
>>> print(me.vertices)
[4, 7, 8, 6, 5]
>>> # the list of boundary vertices need not be 1d
>>> # if not, it will be flattened
>>> msh.add_vertices([[0.55, 0.85], [0.6, 0.75],
...                   [0.65, 0.85], [0.75, 0.75]])
>>> me.insert_vertices(4, [[9, 10], [11, 12]])
>>> print(me.vertices)
[4, 7, 8, 6, 9, 10, 11, 12, 5]
>>> # add no vertices, in two different ways
>>> me.insert_vertices(0, None)
>>> me.insert_vertices(0, [])
>>> print(me.vertices)
[4, 7, 8, 6, 9, 10, 11, 12, 5]
>>> # try to insert some invalid vertices
>>> me.insert_vertices(0, 'one')
Traceback (most recent call last):
    ...
ValueError: invalid literal for int() with base 10: 'one'
>>> me.insert_vertices(0, 6)
Traceback (most recent call last):
    ...
ValueError: 6 is already a vertex
>>> me.insert_vertices(0, 13)
Traceback (most recent call last):
    ...
ValueError: vertex index 13 out of range
>>> me.insert_vertices(0, -1)
Traceback (most recent call last):
    ...
ValueError: vertex index -1 out of range
>>> me.insert_vertices(
...             0, [[1, 2], 3]) 
Traceback (most recent call last):
    ...
ValueError: ...
>>> msh.add_vertices([0.5, -0.5])
>>> me.insert_vertices('one', 13)
Traceback (most recent call last):
    ...
TypeError: 'str' object cannot be interpreted as an integer
remove_vertices(remove_vertices)

Remove one or more vertex indices from the MeshEdge2D.

Parameters

remove_vertices (int | list[int]) – The vertex or list of vertices to remove from vertices.

Note

Before removing the values in remove_vertices, an attempt will be made to cast it to a flattened numpy.ndarray of int.

Raises

ValueError – If remove_vertices is not array_like, such as a jagged list[list[int]]. If any values in remove_vertices cannot be cast to int or are not in vertices.

Examples

>>> # create mesh and mesh edge, add/remove some vertices
>>> import vcfempy.meshgen
>>> msh = vcfempy.meshgen.PolyMesh2D()
>>> msh.add_vertices([[0, 0], [0, 1], [1, 1], [1, 0]])
>>> msh.add_vertices([[0.1, 0.1], [0.5, 0.65], [0.8, 0.8]])
>>> me = vcfempy.meshgen.MeshEdge2D(msh)
>>> me.insert_vertices(0, [4, 5, 6])
>>> me.remove_vertices(5)
>>> print(me.vertices)
[4, 6]
>>> # remove multiple vertices
>>> msh.add_vertices([0.25, 0.9])
>>> me.insert_vertices(1, [7, 5])
>>> me.remove_vertices([4, 6])
>>> print(me.vertices)
[7, 5]
>>> # the list of vertices to remove need not be 1d
>>> # if not, it will be flattened
>>> me.insert_vertices(0, 4)
>>> me.insert_vertices(4, 6)
>>> me.remove_vertices([[4, 5], [6, 7]])
>>> print(me.vertices)
[]
>>> # remove no vertices, in two different ways
>>> me.insert_vertices(0, [4, 7, 5, 6])
>>> me.remove_vertices(None)
>>> me.remove_vertices([])
>>> print(me.vertices)
[4, 7, 5, 6]
>>> # try to remove some invalid vertices
>>> me.remove_vertices('one')
Traceback (most recent call last):
    ...
ValueError: invalid literal for int() with base 10: 'one'
>>> me.remove_vertices(1)
Traceback (most recent call last):
    ...
ValueError: list.remove(x): x not in list
>>> me.remove_vertices(
...                 [[1, 2], 3]) 
Traceback (most recent call last):
    ...
ValueError: ...
plot(ax=None, **kwargs)

Plot the MeshEdge2D.

Parameters

ax (None | matplotlib.axes.Axes) – The axes to plot on. If not provided, will try to get one using matplotlib.pyplot.gca().

Other Parameters

**kwargs (matplotlib.pyplot.Line2D properties, optional) – Default values: linewidth = 3.0, linestyle = ‘–‘, color = material color (or ‘black’ if material is None), marker = ‘s’, markersize = 8.0, markeredgecolor = ‘black’, markerfacecolor = material color (or ‘black’ if material is None)

Returns

The axes that the MeshEdge2D was plotted on.

Return type

matplotlib.axes.Axes

Examples

>>> # initialize a mesh, a material region, and a mesh edge, then
>>> # plot the material region and mesh edge
>>> import matplotlib.pyplot as plt
>>> import vcfempy.materials
>>> import vcfempy.meshgen
>>> msh = vcfempy.meshgen.PolyMesh2D('test mesh')
>>> msh.add_vertices([[0, 0], [0, 1], [1, 1], [1, 0]])
>>> msh.insert_boundary_vertices(0, [0, 1, 2, 3])
>>> rock = vcfempy.materials.Material('rock', color='xkcd:stone')
>>> mr = vcfempy.meshgen.MaterialRegion2D(msh, msh.boundary_vertices,
...                                       rock, 'rock region')
>>> rock_joint = vcfempy.materials.Material('rock joint',
...                                         color='xkcd:greenish')
>>> msh.add_vertices([[0.1, 0.1], [0.5, 0.65], [0.8, 0.8]])
>>> me = vcfempy.meshgen.MeshEdge2D(msh, [4, 5, 6], rock_joint,
...                                 'rock joint')
>>> fig = plt.figure()
>>> ax = mr.plot()
>>> ax = me.plot()
>>> xmin, xmax, ymin, ymax = ax.axis('equal')
>>> xtext = ax.set_xlabel('x')
>>> ytext = ax.set_ylabel('y')
>>> ttext = ax.set_title('MeshEdge2D Test Plot')
>>> leg = ax.legend(labels=[mr.name, me.name])
>>> plt.savefig('MeshEdge2D_test_plot.png')
class vcfempy.meshgen.PolyElement2D(mesh, nodes=None, material=None)

Bases: object

A class for polygonal element geometry and quadrature generation. Used by PolyMesh2D to generate polygonal meshes.

Parameters

Examples

>>> # create a simple mesh and check the element properties
>>> import vcfempy.materials
>>> import vcfempy.meshgen
>>> msh = vcfempy.meshgen.PolyMesh2D()
>>> msh.add_vertices([[0, 0], [0, 1], [1, 1], [1, 0]])
>>> msh.insert_boundary_vertices(0, [0, 1, 2, 3])
>>> rock = vcfempy.materials.Material('rock')
>>> mr = vcfempy.meshgen.MaterialRegion2D(msh, [0, 1, 2, 3], rock)
>>> msh.mesh_scale = 0.4
>>> msh.add_seed_points([0.5, 0.5])
>>> msh.generate_mesh()
>>> print(msh.elements[0].mesh is msh)
True
>>> print(msh.elements[0].num_nodes)
4
>>> print(msh.elements[0].nodes)
[15, 14, 6, 10]
>>> print(msh.elements[0].material.name)
rock
>>> print(np.round(msh.elements[0].area, 14))
0.09
>>> print(msh.elements[0].centroid.round(14))
[0.5 0.5]
>>> print(msh.elements[0].quad_points.round(14))
[[-0.1125 -0.1125]
 [-0.1125  0.1125]
 [ 0.1125  0.1125]
 [ 0.1125 -0.1125]
 [-0.075   0.    ]
 [ 0.      0.075 ]
 [ 0.075   0.    ]
 [ 0.     -0.075 ]
 [ 0.      0.    ]]
>>> print(msh.elements[0].quad_weights.round(14))
[0.1257414  0.1257414  0.1257414  0.1257414  0.10083037 0.10083037
 0.10083037 0.10083037 0.09371293]
>>> print(np.sum(msh.elements[0].quad_weights).round(14))
1.0
property mesh

The parent PolyMesh2D.

Returns

The parent mesh assigned to the PolyElement2D.

Return type

PolyMesh2D

Note

The mesh is immutable and can only be assigned when the PolyElement2D is created. A PolyElement2D should not usually be created explicitly, but rather should be created indirectly by calling the PolyMesh2D.generate_mesh() method.

Examples

>>> # create a simple mesh and check the element properties
>>> import vcfempy.meshgen
>>> msh = vcfempy.meshgen.PolyMesh2D()
>>> msh.add_vertices([[0, 0], [0, 1], [1, 1], [1, 0]])
>>> msh.insert_boundary_vertices(0, [0, 1, 2, 3])
>>> msh.mesh_scale = 0.4
>>> msh.add_seed_points([0.5, 0.5])
>>> msh.generate_mesh()
>>> print(msh.elements[0].mesh is msh)
True
property material

Material type assigned to the PolyElement2D.

Parameters

material (None | vcfempy.materials.Material) – The material to assign to the PolyElement2D.

Returns

The material assigned to the PolyElement2D.

Return type

None | vcfempy.materials.Material

Raises

TypeError – If type(material) not in [NoneType, vcfempy.materials.Material]

Examples

>>> # create a simple mesh and check the element properties
>>> import vcfempy.materials
>>> import vcfempy.meshgen
>>> msh = vcfempy.meshgen.PolyMesh2D()
>>> msh.add_vertices([[0, 0], [0, 1], [1, 1], [1, 0]])
>>> msh.insert_boundary_vertices(0, [0, 1, 2, 3])
>>> rock = vcfempy.materials.Material('rock')
>>> mr = vcfempy.meshgen.MaterialRegion2D(msh, [0, 1, 2, 3], rock)
>>> msh.mesh_scale = 0.4
>>> msh.add_seed_points([0.5, 0.5])
>>> msh.generate_mesh()
>>> print(msh.elements[0].material.name)
rock
property num_nodes

Number of nodes in the PolyElement2D.

Returns

The number of nodes in the PolyElement2D.

Return type

int

Examples

>>> # create a simple mesh and check the element properties
>>> import vcfempy.meshgen
>>> msh = vcfempy.meshgen.PolyMesh2D()
>>> msh.add_vertices([[0, 0], [0, 1], [1, 1], [1, 0]])
>>> msh.insert_boundary_vertices(0, [0, 1, 2, 3])
>>> msh.mesh_scale = 0.4
>>> msh.add_seed_points([0.5, 0.5])
>>> msh.generate_mesh()
>>> print(msh.elements[0].num_nodes)
4
property nodes

List of node indices in the PolyElement2D. References the PolyMesh2D.nodes of the parent mesh.

Returns

The list of node indices in the PolyElement2D.

Return type

list[int]

Examples

>>> # create a simple mesh and check the element properties
>>> import vcfempy.meshgen
>>> msh = vcfempy.meshgen.PolyMesh2D()
>>> msh.add_vertices([[0, 0], [0, 1], [1, 1], [1, 0]])
>>> msh.insert_boundary_vertices(0, [0, 1, 2, 3])
>>> msh.mesh_scale = 0.4
>>> msh.add_seed_points([0.5, 0.5])
>>> msh.generate_mesh()
>>> print(msh.elements[0].nodes)
[15, 14, 6, 10]
insert_nodes(index, nodes)

Insert one or more node indices to the PolyElement2D.

Parameters
  • index (int) – The index at which to insert the nodes into nodes.

  • nodes (int | list[int]) – The list of node indices to add to nodes.

Note

Before inserting the values in nodes, an attempt is made to cast to a flattened numpy.ndarray of int.

Raises
  • TypeError – If index cannot be interpreted as int.

  • ValueError – If nodes is not array_like, such as a jagged list[list[int]]. If any values in nodes cannot be cast to int, are already in nodes, are negative, or are >= mesh.num_nodes.

Examples

>>> # create a simple mesh
>>> import vcfempy.meshgen
>>> msh = vcfempy.meshgen.PolyMesh2D()
>>> msh.add_vertices([[0, 0], [0, 1], [1, 1], [1, 0]])
>>> msh.insert_boundary_vertices(0, [0, 1, 2, 3])
>>> msh.mesh_scale = 0.4
>>> msh.add_seed_points([0.5, 0.5])
>>> msh.generate_mesh()
>>> print(msh.nodes.round(14))
[[-0.    1.  ]
 [ 0.35  1.  ]
 [ 0.    0.  ]
 [ 0.35  0.  ]
 [ 1.    1.  ]
 [ 0.65  1.  ]
 [ 0.65  0.65]
 [ 1.    0.65]
 [ 1.   -0.  ]
 [ 0.65 -0.  ]
 [ 0.65  0.35]
 [ 1.    0.35]
 [ 0.    0.65]
 [ 0.    0.35]
 [ 0.35  0.65]
 [ 0.35  0.35]]
>>> # create a new element
>>> # note, this is normally not done explicitly, but is shown here
>>> # for testing and documentation
>>> e = vcfempy.meshgen.PolyElement2D(msh)
>>> print(e.nodes)
[]
>>> e.insert_nodes(0, [0, 1, 14, 12])
>>> print(e.nodes)
[0, 1, 14, 12]
>>> print(np.round(e.area, 14))
0.1225
>>> # insert no nodes in multiple ways
>>> e.insert_nodes(0, None)
>>> e.insert_nodes(0, [])
>>> print(e.nodes)
[0, 1, 14, 12]
>>> # try to insert some invalid nodes
>>> e.insert_nodes(0, 'one')
Traceback (most recent call last):
    ...
ValueError: invalid literal for int() with base 10: 'one'
>>> e.insert_nodes(0, 1)
Traceback (most recent call last):
    ...
ValueError: 1 is already a node
>>> e.insert_nodes(0, 16)
Traceback (most recent call last):
    ...
ValueError: node index 16 out of range
>>> e.insert_nodes(0, -1)
Traceback (most recent call last):
    ...
ValueError: node index -1 out of range
>>> e.insert_nodes(
...             0, [[1, 2], 3]) 
Traceback (most recent call last):
    ...
ValueError: ...
>>> e.insert_nodes('one', 2)
Traceback (most recent call last):
    ...
TypeError: 'str' object cannot be interpreted as an integer
remove_nodes(remove_nodes)

Remove one or more node indices from the PolyElement2D.

Parameters

remove_nodes (int | list[int]) – The node or list of nodes to remove from nodes.

Note

Before removing the values in remove_nodes, an attempt will be made to cast it to a flattened numpy.ndarray of int.

Raises

ValueError – If remove_nodes is not array_like, such as a jagged list[list[int]]. If any values in remove_nodes cannot be cast to int or are not in nodes.

Examples

>>> # create a simple mesh, and remove a node from an element
>>> # this should not normally be done explicitly unless you know
>>> # what you are doing
>>> import vcfempy.meshgen
>>> msh = vcfempy.meshgen.PolyMesh2D()
>>> msh.add_vertices([[0, 0], [0, 1], [1, 1], [1, 0]])
>>> msh.insert_boundary_vertices(0, [0, 1, 2, 3])
>>> msh.mesh_scale = 0.02
>>> msh.generate_mesh()
>>> print(msh.elements[0].nodes)
[714, 710, 711, 712, 713]
>>> msh.elements[0].remove_nodes(714)
>>> print(msh.elements[0].nodes)
[710, 711, 712, 713]
>>> # remove multiple nodes
>>> print(msh.elements[1].nodes)
[1328, 276, 81, 714, 710, 1327]
>>> msh.elements[1].remove_nodes([276, 81])
>>> print(msh.elements[1].nodes)
[1328, 714, 710, 1327]
>>> # the list of nodes to remove need not be 1d
>>> # if not, it will be flattened
>>> i7 = msh.num_nodes_per_element.index(7)
>>> print(msh.elements[i7].nodes)
[446, 162, 7, 9, 8, 10, 445]
>>> msh.elements[i7].remove_nodes([[7, 8], [9, 10]])
>>> print(msh.elements[i7].nodes)
[446, 162, 445]
>>> # remove no nodes, in two different ways
>>> msh.elements[0].remove_nodes(None)
>>> msh.elements[0].remove_nodes([])
>>> print(msh.elements[0].nodes)
[710, 711, 712, 713]
>>> # try to remove some invalid nodes
>>> msh.elements[0].remove_nodes('one')
Traceback (most recent call last):
    ...
ValueError: invalid literal for int() with base 10: 'one'
>>> msh.elements[0].remove_nodes(4)
Traceback (most recent call last):
    ...
ValueError: list.remove(x): x not in list
>>> msh.elements[0].remove_nodes(
...                 [[1, 2], 3]) 
Traceback (most recent call last):
    ...
ValueError: ...
property area

The area of the PolyElement2D.

Returns

The area of the PolyElement2D.

Return type

float

Examples

>>> # create a simple mesh and check the element properties
>>> import vcfempy.meshgen
>>> msh = vcfempy.meshgen.PolyMesh2D()
>>> msh.add_vertices([[0, 0], [0, 1], [1, 1], [1, 0]])
>>> msh.insert_boundary_vertices(0, [0, 1, 2, 3])
>>> msh.mesh_scale = 0.4
>>> msh.add_seed_points([0.5, 0.5])
>>> msh.generate_mesh()
>>> print(np.round(msh.elements[0].area, 14))
0.09
property centroid

The centroid coordinates of the PolyElement2D.

Returns

The coordinates of the centroid of the PolyElement2D.

Return type

numpy.ndarray, shape = (2, )

Examples

>>> # create a simple mesh and check the element properties
>>> import vcfempy.meshgen
>>> msh = vcfempy.meshgen.PolyMesh2D()
>>> msh.add_vertices([[0, 0], [0, 1], [1, 1], [1, 0]])
>>> msh.insert_boundary_vertices(0, [0, 1, 2, 3])
>>> msh.mesh_scale = 0.4
>>> msh.add_seed_points([0.5, 0.5])
>>> msh.generate_mesh()
>>> print(msh.elements[0].centroid)
[0.5 0.5]
property num_quad_points

The number of quadrature points in the PolyElement2D.

Returns

The number of quadrature points in the PolyElement2D.

Return type

int

Examples

>>> # create a simple mesh and check the element properties
>>> import vcfempy.meshgen
>>> msh = vcfempy.meshgen.PolyMesh2D()
>>> msh.add_vertices([[0, 0], [0, 1], [1, 1], [1, 0]])
>>> msh.insert_boundary_vertices(0, [0, 1, 2, 3])
>>> msh.mesh_scale = 0.4
>>> msh.add_seed_points([0.5, 0.5])
>>> msh.generate_mesh()
>>> print(msh.elements[0].num_quad_points)
9
property quad_points

The quadrature point coordinates for the PolyElement2D.

Returns

The coordinates of the quadrature points for the PolyElement2D.

Return type

numpy.ndarray, shape = (num_quad_points, 2)

Note

The quadrature point coordinates are provided in a local coordinate system with the centroid at the origin.

Examples

>>> # create a simple mesh and check the element properties
>>> import vcfempy.meshgen
>>> msh = vcfempy.meshgen.PolyMesh2D()
>>> msh.add_vertices([[0, 0], [0, 1], [1, 1], [1, 0]])
>>> msh.insert_boundary_vertices(0, [0, 1, 2, 3])
>>> msh.mesh_scale = 0.4
>>> msh.add_seed_points([0.5, 0.5])
>>> msh.generate_mesh()
>>> print(msh.elements[0].quad_points.round(14))
[[-0.1125 -0.1125]
 [-0.1125  0.1125]
 [ 0.1125  0.1125]
 [ 0.1125 -0.1125]
 [-0.075   0.    ]
 [ 0.      0.075 ]
 [ 0.075   0.    ]
 [ 0.     -0.075 ]
 [ 0.      0.    ]]
property quad_weights

The quadrature point weights for the PolyElement2D.

Returns

The weights of the quadrature points in the PolyElement2D.

Return type

numpy.ndarray, shape = (num_quad_points, )

Note

The quadrature point weights should always sum to 1.0.

Examples

>>> # create a simple mesh and check the element properties
>>> import vcfempy.meshgen
>>> msh = vcfempy.meshgen.PolyMesh2D()
>>> msh.add_vertices([[0, 0], [0, 1], [1, 1], [1, 0]])
>>> msh.insert_boundary_vertices(0, [0, 1, 2, 3])
>>> msh.mesh_scale = 0.4
>>> msh.add_seed_points([0.5, 0.5])
>>> msh.generate_mesh()
>>> print(msh.elements[0].quad_weights)
[0.1257414  0.1257414  0.1257414  0.1257414  0.10083037 0.10083037
 0.10083037 0.10083037 0.09371293]
>>> print(np.sum(msh.elements[0].quad_weights).round(14))
1.0
property num_quad_integrals

The number of quadrature basis function integrals used in generating the quadrature for the PolyElement2D.

Returns

The number of quadrature basis function integrals for the PolyElement2D.

Return type

int

Note

The number of quadrature integrals corresponds to the number of basis functions used to develop the quadrature rule. The number depends on the order of interpolation for the flux field in the hybrid finite element approach. The flux field interpolation uses complete polynomials in 2D and the order depends on the number of nodes in the element (and whether PolyMesh2D.high_order_quadrature is True for the parent mesh). In integrating finite element matrices, it is necessary to integrate terms containing the square of the flux field basis functions, so the quadrature rule must increment the maximum order of basis function by 2 for each increase in order of flux field interpolation. The number of basis functions is as follows: [3 nodes: constant: 1 basis function, 4-5 nodes: quadratic: 6 basis functions, 6-7 nodes: 4th order: 15 basis functions, 8-10 nodes: 6th order: 28 basis functions, PolyMesh2D.high_order_quadrature for mesh: 6th order: 28 basis functions].

Examples

>>> # create a simple mesh and check the element properties
>>> import vcfempy.meshgen
>>> msh = vcfempy.meshgen.PolyMesh2D()
>>> msh.add_vertices([[0, 0], [0, 1], [1, 1], [1, 0]])
>>> msh.insert_boundary_vertices(0, [0, 1, 2, 3])
>>> msh.mesh_scale = 0.02
>>> msh.mesh_rand = 0.7
>>> msh.generate_mesh()
>>> i3 = msh.num_nodes_per_element.index(3)
>>> print(msh.elements[i3].num_quad_integrals)
1
>>> i5 = msh.num_nodes_per_element.index(5)
>>> print(msh.elements[i5].num_quad_integrals)
6
>>> i7 = msh.num_nodes_per_element.index(7)
>>> print(msh.elements[i7].num_quad_integrals)
15
>>> i8 = msh.num_nodes_per_element.index(8)
>>> print(msh.elements[i8].num_quad_integrals)
28
>>> # set high order quadrature and check number of basis functions
>>> msh.high_order_quadrature = True
>>> msh.generate_mesh()
>>> i3 = msh.num_nodes_per_element.index(3)
>>> print(msh.elements[i3].num_quad_integrals)
28
>>> i5 = msh.num_nodes_per_element.index(5)
>>> print(msh.elements[i5].num_quad_integrals)
28
>>> i7 = msh.num_nodes_per_element.index(7)
>>> print(msh.elements[i7].num_quad_integrals)
28
>>> i8 = msh.num_nodes_per_element.index(8)
>>> print(msh.elements[i8].num_quad_integrals)
28
property quad_integrals

The quadrature basis function integrals for the PolyElement2D.

Returns

The values of the element quadrature basis function integrals for the PolyElement2D.

Return type

numpy.ndarray, size = (num_quad_integrals, )

See also

num_quad_integrals

For explanatory Note on number of basis functions.

Examples

>>> # create a simple mesh and check the element properties
>>> # note that the first basis function integral is always equal
>>> # to the element area
>>> import vcfempy.meshgen
>>> msh = vcfempy.meshgen.PolyMesh2D()
>>> msh.add_vertices([[0, 0], [0, 1], [1, 1], [1, 0]])
>>> msh.insert_boundary_vertices(0, [0, 1, 2, 3])
>>> msh.mesh_scale = 0.4
>>> msh.add_seed_points([0.5, 0.5])
>>> msh.generate_mesh()
>>> print(msh.elements[0].quad_integrals.round(14))
[ 0.09     -0.        0.        0.000675  0.        0.000675]
>>> print(np.round(msh.elements[0].area, 14))
0.09
invalidate_properties()

Resets cached values of computed attributes area, centroid, quad_points, quad_weights, and quad_integrals for the PolyElement2D.

Note

The invalidate_properties() method should be called whenever nodes is changed. This is done by insert_nodes() and remove_nodes(), but needs to be done explicitly if making manual changes to nodes.

Examples

>>> # create a simple mesh, check the element properties
>>> # invalidate properties and check the values of (private) cache
>>> # attributes
>>> import vcfempy.meshgen
>>> msh = vcfempy.meshgen.PolyMesh2D()
>>> msh.add_vertices([[0, 0], [0, 1], [1, 1], [1, 0]])
>>> msh.insert_boundary_vertices(0, [0, 1, 2, 3])
>>> msh.mesh_scale = 0.4
>>> msh.add_seed_points([0.5, 0.5])
>>> msh.generate_mesh()
>>> print(msh.elements[0]._area)
None
>>> print(msh.elements[0]._centroid)
None
>>> print(msh.elements[0]._quad_points)
None
>>> print(msh.elements[0]._quad_weights)
None
>>> print(msh.elements[0]._quad_integrals)
None
>>> print(np.round(msh.elements[0].area, 14))
0.09
>>> print(msh.elements[0].centroid.round(14))
[0.5 0.5]
>>> print(msh.elements[0].quad_points.round(14))
[[-0.1125 -0.1125]
 [-0.1125  0.1125]
 [ 0.1125  0.1125]
 [ 0.1125 -0.1125]
 [-0.075   0.    ]
 [ 0.      0.075 ]
 [ 0.075   0.    ]
 [ 0.     -0.075 ]
 [ 0.      0.    ]]
>>> print(msh.elements[0].quad_weights.round(14))
[0.1257414  0.1257414  0.1257414  0.1257414  0.10083037 0.10083037
 0.10083037 0.10083037 0.09371293]
>>> print(msh.elements[0].quad_integrals.round(14))
[ 0.09     -0.        0.        0.000675  0.        0.000675]
>>> msh.elements[0].invalidate_properties()
>>> print(msh.elements[0]._area)
None
>>> print(msh.elements[0]._centroid)
None
>>> print(msh.elements[0]._quad_points)
None
>>> print(msh.elements[0]._quad_weights)
None
>>> print(msh.elements[0]._quad_integrals)
None
generate_quadrature()

Generate quadrature points and weights for the PolyElement2D.

Note

The generate_quadrature() method determines the correct (private) _quadconX() method to call depending on the values of num_nodes and PolyMesh2D.high_order_quadrature for mesh. Elements with 8 or more nodes (or PolyMesh2D.high_order_quadrature set) call _quadcon10(), elements with 6-7 nodes call _quadcon7(), elements with 4-5 nodes call _quadcon5(), and elements with 3 nodes call _quadcon3(). This method does not have a direct return value, but sets the cached values of private attributes corresponding to area, centroid, quad_points, quad_weights, and quad_integrals.

Examples

>>> # create a simple mesh and check the element (private) attributes
>>> import vcfempy.meshgen
>>> msh = vcfempy.meshgen.PolyMesh2D()
>>> msh.add_vertices([[0, 0], [0, 1], [1, 1], [1, 0]])
>>> msh.insert_boundary_vertices(0, [0, 1, 2, 3])
>>> msh.mesh_scale = 0.4
>>> msh.add_seed_points([0.5, 0.5])
>>> msh.generate_mesh()
>>> print(msh.elements[0]._area)
None
>>> print(msh.elements[0]._centroid)
None
>>> print(msh.elements[0]._quad_points)
None
>>> print(msh.elements[0]._quad_weights)
None
>>> print(msh.elements[0]._quad_integrals)
None
>>> msh.elements[0].generate_quadrature()
>>> print(np.round(msh.elements[0]._area, 14))
0.09
>>> print(msh.elements[0]._centroid.round(14))
[0.5 0.5]
>>> print(msh.elements[0]._quad_points.round(14))
[[-0.1125 -0.1125]
 [-0.1125  0.1125]
 [ 0.1125  0.1125]
 [ 0.1125 -0.1125]
 [-0.075   0.    ]
 [ 0.      0.075 ]
 [ 0.075   0.    ]
 [ 0.     -0.075 ]
 [ 0.      0.    ]]
>>> print(msh.elements[0]._quad_weights.round(14))
[0.1257414  0.1257414  0.1257414  0.1257414  0.10083037 0.10083037
 0.10083037 0.10083037 0.09371293]
>>> print(msh.elements[0]._quad_integrals.round(14))
[ 0.09     -0.        0.        0.000675  0.        0.000675]
plot(ax=None, **kwargs)

Plot the PolyElement2D using matplotlib.pyplot.fill().

Parameters

ax (matplotlib.axes.Axes, optional) – The axes to plot on. If not provided, will try to get one using matplotlib.pyplot.gca().

Other Parameters

**kwargs (matplotlib.patches.Polygon properties, optional) – Default values: edgecolor = material color (or ‘black’ if material is None) with alpha = 1.0, facecolor = material color (or ‘black’ if material is None) with alpha = 0.6, linewidth = 1.0, linestyle = ‘:’.

Returns

The axes that the PolyElement2D was plotted on.

Return type

matplotlib.axes.Axes

Examples

>>> # initialize a mesh and material region, then plot the elements
>>> import matplotlib.pyplot as plt
>>> import vcfempy.materials
>>> import vcfempy.meshgen
>>> msh = vcfempy.meshgen.PolyMesh2D('test mesh')
>>> msh.add_vertices([[0, 0], [0, 1], [1, 1], [1, 0]])
>>> msh.insert_boundary_vertices(0, [0, 1, 2, 3])
>>> rock = vcfempy.materials.Material('rock', color='xkcd:clay')
>>> mr = vcfempy.meshgen.MaterialRegion2D(msh, msh.boundary_vertices,
...                                       rock, 'rock region')
>>> msh.mesh_scale = 0.2
>>> msh.mesh_rand = 0.2
>>> msh.generate_mesh()
>>> fig = plt.figure()
>>> for e in msh.elements:
...     ax = e.plot()
>>> xmin, xmax, ymin, ymax = ax.axis('equal')
>>> xtext = ax.set_xlabel('x')
>>> ytext = ax.set_ylabel('y')
>>> ttext = ax.set_title('PolyElement2D Test Plot')
>>> plt.savefig('PolyElement2D_test_plot.png')
plot_quad_points(ax=None, **kwargs)

Plot the quad_points of the PolyElement2D using matplotlib.pyplot.plot().

Parameters

ax (matplotlib.axes.Axes, optional) – The axes to plot on. If not provided, will try to get one using matplotlib.pyplot.gca().

Other Parameters

**kwargs (matplotlib.lines.Line2D properties, optional) – Default values: linewidth = 0.0, markeredgecolor = material color with alpha = 1.0 (or ‘black’ if material is None), markerfacecolor = material color with alpha = 1.0 (or ‘black’ if material is None), marker = ‘P’, markersize = 6.0.

Returns

The axes that the quad_points were plotted on.

Return type

matplotlib.axes.Axes

Examples

>>> # initialize a mesh and material region, then plot the elements
>>> # and quad points
>>> import matplotlib.pyplot as plt
>>> import vcfempy.materials
>>> import vcfempy.meshgen
>>> msh = vcfempy.meshgen.PolyMesh2D('test mesh')
>>> msh.add_vertices([[0, 0], [0, 1], [1, 1], [1, 0]])
>>> msh.insert_boundary_vertices(0, [0, 1, 2, 3])
>>> rock = vcfempy.materials.Material('rock', color='xkcd:greenish')
>>> mr = vcfempy.meshgen.MaterialRegion2D(msh, msh.boundary_vertices,
...                                       rock, 'rock region')
>>> msh.mesh_scale = 0.2
>>> msh.mesh_rand = 0.2
>>> msh.generate_mesh()
>>> fig = plt.figure()
>>> for e in msh.elements:
...     ax = e.plot()
...     ax = e.plot_quad_points()
>>> xmin, xmax, ymin, ymax = ax.axis('equal')
>>> xtext = ax.set_xlabel('x')
>>> ytext = ax.set_ylabel('y')
>>> ttext = ax.set_title('PolyElement2D Test Plot')
>>> plt.savefig('PolyElement2D_quad_points_test_plot.png')
class vcfempy.meshgen.InterfaceElement2D(mesh, nodes=None, material=None, neighbors=None, width=0.0)

Bases: object

A class for interfaces between neighboring PolyElement2D elements in a PolyMesh2D.

Parameters

Examples

>>> # create a simple mesh and check the element properties
>>> import vcfempy.materials
>>> import vcfempy.meshgen
>>> msh = vcfempy.meshgen.PolyMesh2D()
>>> msh.add_vertices([[0, 0], [0, 1], [1, 1], [1, 0]])
>>> msh.insert_boundary_vertices(0, [0, 1, 2, 3])
>>> rock = vcfempy.materials.Material('rock')
>>> mr = vcfempy.meshgen.MaterialRegion2D(msh, [0, 1, 2, 3], rock)
>>> msh.mesh_scale = 0.4
>>> msh.add_seed_points([0.5, 0.5])
>>> msh.generate_mesh()
>>> print(msh.interface_elements[0].mesh is msh)
True
>>> print(msh.interface_elements[0].num_nodes)
2
>>> print(msh.interface_elements[0].nodes)
[5, 6]
>>> print(msh.interface_elements[0].material.name)
rock
>>> print(np.round(msh.interface_elements[0].length, 14))
0.35
>>> print(msh.interface_elements[0].centroid.round(14))
[0.65  0.825]
property mesh

The parent PolyMesh2D.

Returns

The parent mesh assigned to the InterfaceElement2D.

Return type

PolyMesh2D

Note

The mesh is immutable and can only be assigned when the InterfaceElement2D is created. An InterfaceElement2D should not usually be created explicitly, but rather should be created indirectly by calling the PolyMesh2D.generate_mesh() method.

Examples

>>> # create a simple mesh and check the element properties
>>> import vcfempy.meshgen
>>> msh = vcfempy.meshgen.PolyMesh2D()
>>> msh.add_vertices([[0, 0], [0, 1], [1, 1], [1, 0]])
>>> msh.insert_boundary_vertices(0, [0, 1, 2, 3])
>>> msh.mesh_scale = 0.4
>>> msh.add_seed_points([0.5, 0.5])
>>> msh.generate_mesh()
>>> print(msh.interface_elements[0].mesh is msh)
True
property material

Material type assigned to the InterfaceElement2D.

Parameters

material (None | vcfempy.materials.Material) – The material to assign to the InterfaceElement2D.

Returns

The material assigned to the InterfaceElement2D.

Return type

None | vcfempy.materials.Material

Raises

TypeError – If type(material) not in [NoneType, vcfempy.materials.Material]

Examples

>>> # create a simple mesh and check the element properties
>>> import vcfempy.materials
>>> import vcfempy.meshgen
>>> msh = vcfempy.meshgen.PolyMesh2D()
>>> msh.add_vertices([[0, 0], [0, 1], [1, 1], [1, 0]])
>>> msh.insert_boundary_vertices(0, [0, 1, 2, 3])
>>> rock = vcfempy.materials.Material('rock')
>>> mr = vcfempy.meshgen.MaterialRegion2D(msh, [0, 1, 2, 3], rock)
>>> msh.mesh_scale = 0.4
>>> msh.add_seed_points([0.5, 0.5])
>>> msh.generate_mesh()
>>> print(msh.interface_elements[0].material.name)
rock
property width

The width of the InterfaceElement2D in the normal direction.

Parameters

val (float) – The width to assign to the InterfaceElement2D.

Returns

The width of the InterfaceElement2D.

Return type

float

Raises
  • TypeError – If val is not a str or a number.

  • ValueError – If val cannot be cast to float or is < 0.0.

Examples

>>> # create a simple mesh and check the element properties
>>> import vcfempy.materials
>>> import vcfempy.meshgen
>>> msh = vcfempy.meshgen.PolyMesh2D()
>>> msh.add_vertices([[0, 0], [0, 1], [1, 1], [1, 0]])
>>> msh.insert_boundary_vertices(0, [0, 1, 2, 3])
>>> rock = vcfempy.materials.Material('rock')
>>> mr = vcfempy.meshgen.MaterialRegion2D(msh, [0, 1, 2, 3], rock)
>>> msh.mesh_scale = 0.4
>>> msh.add_seed_points([0.5, 0.5])
>>> msh.generate_mesh()
>>> print(msh.interface_elements[0].width)
0.0
>>> msh.interface_elements[0].width = 0.5
>>> print(msh.interface_elements[0].width)
0.5
>>> msh.interface_elements[0].width = None
Traceback (most recent call last):
    ...
TypeError: float() argument must be a string or a real number, not 'NoneType'
>>> msh.interface_elements[0].width = -0.1
Traceback (most recent call last):
    ...
ValueError: width must be >= 0.0
>>> msh.interface_elements[0].width = 'abc'
Traceback (most recent call last):
    ...
ValueError: could not convert string to float: 'abc'
property num_nodes

Number of nodes in the InterfaceElement2D.

Returns

The number of nodes in the InterfaceElement2D.

Return type

int

Examples

>>> # create a simple mesh and check the element properties
>>> import vcfempy.meshgen
>>> msh = vcfempy.meshgen.PolyMesh2D()
>>> msh.add_vertices([[0, 0], [0, 1], [1, 1], [1, 0]])
>>> msh.insert_boundary_vertices(0, [0, 1, 2, 3])
>>> msh.mesh_scale = 0.4
>>> msh.add_seed_points([0.5, 0.5])
>>> msh.generate_mesh()
>>> print(msh.interface_elements[0].num_nodes)
2
property nodes

List of node indices in the InterfaceElement2D. References the PolyMesh2D.nodes of the parent mesh.

Returns

The list of node indices in the InterfaceElement2D.

Return type

list[int]

Examples

>>> # create a simple mesh and check the element properties
>>> import vcfempy.meshgen
>>> msh = vcfempy.meshgen.PolyMesh2D()
>>> msh.add_vertices([[0, 0], [0, 1], [1, 1], [1, 0]])
>>> msh.insert_boundary_vertices(0, [0, 1, 2, 3])
>>> msh.mesh_scale = 0.4
>>> msh.add_seed_points([0.5, 0.5])
>>> msh.generate_mesh()
>>> print(msh.interface_elements[0].nodes)
[5, 6]
insert_nodes(index, nodes)

Insert node indices to the InterfaceElement2D.

Parameters
  • index (int) – The index at which to insert the nodes into nodes.

  • nodes (list[int]) – The list of node indices to add to nodes. Length must be a multiple of 2 and the maximum number of nodes is 4.

Note

Before inserting the values in nodes, an attempt is made to cast to a flattened numpy.ndarray of int. The new number of nodes after insertion must be 0, 2, or 4.

Raises
  • TypeError – If index cannot be interpreted as int.

  • ValueError – If nodes is not array_like, such as a jagged list[list[int]]. If any values in nodes cannot be cast to int, are already in nodes, are negative, are >= mesh.num_nodes, or the list of nodes to be added would result in nodes having a length other than 0, 2, or 4.

Examples

>>> # create a simple mesh
>>> import vcfempy.meshgen
>>> msh = vcfempy.meshgen.PolyMesh2D()
>>> msh.add_vertices([[0, 0], [0, 1], [1, 1], [1, 0]])
>>> msh.insert_boundary_vertices(0, [0, 1, 2, 3])
>>> msh.mesh_scale = 0.4
>>> msh.add_seed_points([0.5, 0.5])
>>> msh.generate_mesh()
>>> print(msh.nodes.round(14))
[[-0.    1.  ]
 [ 0.35  1.  ]
 [ 0.    0.  ]
 [ 0.35  0.  ]
 [ 1.    1.  ]
 [ 0.65  1.  ]
 [ 0.65  0.65]
 [ 1.    0.65]
 [ 1.   -0.  ]
 [ 0.65 -0.  ]
 [ 0.65  0.35]
 [ 1.    0.35]
 [ 0.    0.65]
 [ 0.    0.35]
 [ 0.35  0.65]
 [ 0.35  0.35]]
>>> # create a new element
>>> # note, this is normally not done explicitly, but is shown here
>>> # for testing and documentation
>>> e = vcfempy.meshgen.InterfaceElement2D(msh)
>>> print(e.nodes)
[]
>>> e.insert_nodes(0, [1, 14])
>>> print(e.nodes)
[1, 14]
>>> print(np.round(e.length, 14))
0.35
>>> # insert no nodes in multiple ways
>>> e.insert_nodes(0, None)
>>> e.insert_nodes(0, [])
>>> print(e.nodes)
[1, 14]
>>> # try to insert some invalid nodes
>>> e.insert_nodes(0, 'one')
Traceback (most recent call last):
    ...
ValueError: invalid literal for int() with base 10: 'one'
>>> e.insert_nodes(0, [1, 14])
Traceback (most recent call last):
    ...
ValueError: 14 is already a node
>>> e.insert_nodes(0, [14, 2])
Traceback (most recent call last):
    ...
ValueError: 14 is already a node
>>> print(e.nodes)
[1, 14]
>>> e.insert_nodes(0, [16, 17])
Traceback (most recent call last):
    ...
ValueError: node index 17 out of range
>>> e.insert_nodes(0, [-1, -2])
Traceback (most recent call last):
    ...
ValueError: node index -2 out of range
>>> e.insert_nodes(
...             0, [[1, 2], 3]) 
Traceback (most recent call last):
    ...
ValueError: ...
>>> e.insert_nodes('one', [2, 3])
Traceback (most recent call last):
    ...
TypeError: 'str' object cannot be interpreted as an integer
>>> e.insert_nodes(0, [2])
Traceback (most recent call last):
    ...
ValueError: number of nodes in InterfaceElement2D can only be 0, 2, or 4
>>> e.insert_nodes(0, [2, 3, 4, 5])
Traceback (most recent call last):
    ...
ValueError: number of nodes in InterfaceElement2D can only be 0, 2, or 4
remove_nodes(remove_nodes)

Remove node indices from the InterfaceElement2D.

Parameters

remove_nodes (list[int]) – The list of nodes to remove from nodes.

Note

Before removing the values in remove_nodes, an attempt will be made to cast it to a flattened numpy.ndarray of int.

Raises

ValueError – If remove_nodes is not array_like, such as a jagged list[list[int]]. If any values in remove_nodes cannot be cast to int or are not in nodes. If the number of remove_nodes would result in the length of nodes being other than 0, 2, or 4.

Examples

>>> # create a simple mesh, and remove nodes from an element
>>> # this should not normally be done explicitly unless you know
>>> # what you are doing
>>> import vcfempy.meshgen
>>> msh = vcfempy.meshgen.PolyMesh2D()
>>> msh.add_vertices([[0, 0], [0, 1], [1, 1], [1, 0]])
>>> msh.insert_boundary_vertices(0, [0, 1, 2, 3])
>>> msh.mesh_scale = 0.4
>>> msh.add_seed_points([0.5, 0.5])
>>> msh.generate_mesh()
>>> print(msh.interface_elements[0].nodes)
[5, 6]
>>> msh.interface_elements[0].remove_nodes([5, 6])
>>> print(msh.interface_elements[0].nodes)
[]
>>> # remove no nodes, in two different ways
>>> msh.interface_elements[0].insert_nodes(0, [5, 6])
>>> msh.interface_elements[0].remove_nodes(None)
>>> msh.interface_elements[0].remove_nodes([])
>>> print(msh.interface_elements[0].nodes)
[5, 6]
>>> # try to remove some invalid nodes
>>> msh.interface_elements[0].remove_nodes('one')
Traceback (most recent call last):
    ...
ValueError: invalid literal for int() with base 10: 'one'
>>> msh.interface_elements[0].remove_nodes([5, 8])
Traceback (most recent call last):
    ...
ValueError: list.remove(x): x not in list
>>> print(msh.interface_elements[0].nodes)
[5, 6]
>>> msh.interface_elements[0].remove_nodes(4)
Traceback (most recent call last):
    ...
ValueError: number of nodes in InterfaceElement2D can only be 0, 2, or 4
>>> msh.interface_elements[0].remove_nodes(
...                 [[1, 2], 3]) 
Traceback (most recent call last):
    ...
ValueError: ...
property num_neighbors

Number of neighboring PolyElement2D elements to the InterfaceElement2D.

Returns

The number of neighbors to the InterfaceElement2D.

Return type

int

Examples

>>> # create a simple mesh and check the element properties
>>> import vcfempy.meshgen
>>> msh = vcfempy.meshgen.PolyMesh2D()
>>> msh.add_vertices([[0, 0], [0, 1], [1, 1], [1, 0]])
>>> msh.insert_boundary_vertices(0, [0, 1, 2, 3])
>>> msh.mesh_scale = 0.4
>>> msh.add_seed_points([0.5, 0.5])
>>> msh.generate_mesh()
>>> print(msh.interface_elements[0].num_neighbors)
2
property neighbors

The list of neighboring PolyElement2D elements to the InterfaceElement2D.

Returns

The list of neighbors to the InterfaceElement2D.

Return type

list of PolyElement2D

Examples

>>> # create a simple mesh and check the element properties
>>> import vcfempy.meshgen
>>> msh = vcfempy.meshgen.PolyMesh2D()
>>> msh.add_vertices([[0, 0], [0, 1], [1, 1], [1, 0]])
>>> msh.insert_boundary_vertices(0, [0, 1, 2, 3])
>>> msh.mesh_scale = 0.4
>>> msh.add_seed_points([0.5, 0.5])
>>> msh.generate_mesh()
>>> print([msh.elements.index(n)
...        for n in msh.interface_elements[0].neighbors])
[3, 6]
add_neighbors(neighbors)

Add neighboring PolyElement2D to the InterfaceElement2D.

Parameters

neighbors (list of PolyElement2D) – The list of neighboring PolyElement2D to the InterfaceElement2D.

Note

An InterfaceElement2D can only have 0 or 2 neighbors.

Raises

ValueError – If any values in neighbors are not PolyElement2D, are already in neighbors, do not have the same mesh as the InterfaceElement2D, or the list of neighbors to be added would result in neighbors having a length other than 0 or 2.

Examples

>>> # create a simple mesh
>>> import vcfempy.meshgen
>>> msh = vcfempy.meshgen.PolyMesh2D()
>>> msh.add_vertices([[0, 0], [0, 1], [1, 1], [1, 0]])
>>> msh.insert_boundary_vertices(0, [0, 1, 2, 3])
>>> msh.mesh_scale = 0.4
>>> msh.add_seed_points([0.5, 0.5])
>>> msh.generate_mesh()
>>> # create a new element
>>> # note, this is normally not done explicitly, but is shown here
>>> # for testing and documentation
>>> e = vcfempy.meshgen.InterfaceElement2D(msh)
>>> print(e.neighbors)
[]
>>> e.add_neighbors(msh.elements[0:2])
>>> print([msh.elements.index(n) for n in e.neighbors])
[0, 1]
>>> # add no neighbors in multiple ways
>>> e.add_neighbors(None)
>>> e.add_neighbors([])
>>> print([msh.elements.index(n) for n in e.neighbors])
[0, 1]
>>> # try to add some invalid neighbors
>>> e.add_neighbors(msh.elements[0:2])
Traceback (most recent call last):
    ...
ValueError: number of neighbors to InterfaceElement2D can only be 0 or 2
property length

The length of the InterfaceElement2D.

Returns

The length of the InterfaceElement2D.

Return type

float

Examples

>>> # create a simple mesh and check the element properties
>>> import vcfempy.meshgen
>>> msh = vcfempy.meshgen.PolyMesh2D()
>>> msh.add_vertices([[0, 0], [0, 1], [1, 1], [1, 0]])
>>> msh.insert_boundary_vertices(0, [0, 1, 2, 3])
>>> msh.mesh_scale = 0.4
>>> msh.add_seed_points([0.5, 0.5])
>>> msh.generate_mesh()
>>> print(np.round(msh.interface_elements[0].length, 14))
0.35
property area

The area of the InterfaceElement2D.

Returns

The area of the InterfaceElement2D.

Return type

float

Note

The method uses the length and width properties to calculate the area. It does not use the polygon formed by the nodes.

Examples

>>> # create a simple mesh and check the element properties
>>> import vcfempy.meshgen
>>> msh = vcfempy.meshgen.PolyMesh2D()
>>> msh.add_vertices([[0, 0], [0, 1], [1, 1], [1, 0]])
>>> msh.insert_boundary_vertices(0, [0, 1, 2, 3])
>>> msh.mesh_scale = 0.4
>>> msh.add_seed_points([0.5, 0.5])
>>> msh.generate_mesh()
>>> print(np.round(msh.interface_elements[0].area, 14))
0.0
property centroid

The centroid coordinates of the InterfaceElement2D.

Returns

The coordinates of the centroid of the InterfaceElement2D.

Return type

numpy.ndarray, shape = (2, )

Examples

>>> # create a simple mesh and check the element properties
>>> import vcfempy.meshgen
>>> msh = vcfempy.meshgen.PolyMesh2D()
>>> msh.add_vertices([[0, 0], [0, 1], [1, 1], [1, 0]])
>>> msh.insert_boundary_vertices(0, [0, 1, 2, 3])
>>> msh.mesh_scale = 0.4
>>> msh.add_seed_points([0.5, 0.5])
>>> msh.generate_mesh()
>>> print(msh.interface_elements[0].centroid)
[0.65  0.825]
invalidate_properties()

Resets cached value of computed attributes length, area, and centroid.

Note

The invalidate_properties() method should be called whenever nodes or width are changed. This is done by insert_nodes(), remove_nodes(), and the setter for width, but needs to be done explicitly if making manual changes to nodes.

Examples

>>> # create a simple mesh, check the element properties
>>> # invalidate properties and check the values of (private) cache
>>> # attributes
>>> import vcfempy.meshgen
>>> msh = vcfempy.meshgen.PolyMesh2D()
>>> msh.add_vertices([[0, 0], [0, 1], [1, 1], [1, 0]])
>>> msh.insert_boundary_vertices(0, [0, 1, 2, 3])
>>> msh.mesh_scale = 0.4
>>> msh.add_seed_points([0.5, 0.5])
>>> msh.generate_mesh()
>>> print(msh.interface_elements[0].width)
0.0
>>> print(msh.interface_elements[0]._length)
None
>>> print(msh.interface_elements[0]._area)
None
>>> print(msh.interface_elements[0]._centroid)
None
>>> print(np.round(msh.interface_elements[0].length, 14))
0.35
>>> print(msh.interface_elements[0].area)
0.0
>>> print(msh.interface_elements[0].centroid.round(14))
[0.65  0.825]
>>> msh.interface_elements[0].invalidate_properties()
>>> print(msh.interface_elements[0]._length)
None
>>> print(msh.interface_elements[0]._area)
None
>>> print(msh.interface_elements[0]._centroid)
None
plot(ax=None, **kwargs)

Plot the InterfaceElement2D using matplotlib.pyplot.fill().

Parameters

ax (None | matplotlib.axes.Axes) – The axes to plot on. If not provided, will try to get one using matplotlib.pyplot.gca().

Other Parameters

**kwargs (matplotlib.patches.Polygon properties, optional) – Default values: edgecolor = material color with alpha = 1.0 (or ‘black’ with alpha = 1.0 if material is None), facecolor = material color with alpha = 0.6 (or ‘black’ with alpha = 0.6 if material is None), linewidth = 2.0, linestyle = ‘–‘.

Returns

The axes that the InterfaceElement2D was plotted on.

Return type

matplotlib.axes.Axes

Examples

>>> # initialize a mesh and a material region, then generate a mesh
>>> # and plot the elements and interface elements
>>> import matplotlib.pyplot as plt
>>> import vcfempy.materials
>>> import vcfempy.meshgen
>>> msh = vcfempy.meshgen.PolyMesh2D('test mesh')
>>> msh.add_vertices([[0, 0], [0, 1], [1, 1], [1, 0]])
>>> msh.insert_boundary_vertices(0, [0, 1, 2, 3])
>>> rock = vcfempy.materials.Material('rock', color='xkcd:clay')
>>> mr = vcfempy.meshgen.MaterialRegion2D(msh, msh.boundary_vertices,
...                                       rock, 'rock region')
>>> msh.mesh_scale = 0.2
>>> msh.mesh_rand = 0.2
>>> msh.generate_mesh()
>>> fig = plt.figure()
>>> for e in msh.elements:
...     ax = e.plot(edgecolor=None)
...     ax = e.plot_quad_points()
>>> for e in msh.interface_elements:
...     ax = e.plot()
>>> xmin, xmax, ymin, ymax = ax.axis('equal')
>>> xtext = ax.set_xlabel('x')
>>> ytext = ax.set_ylabel('y')
>>> ttext = ax.set_title('InterfaceElement2D Test Plot')
>>> plt.savefig('InterfaceElement2D_test_plot.png')
class vcfempy.meshgen.BoundaryElement2D(mesh, nodes=None, neighbor=None)

Bases: object

A class for interfaces between PolyElement2D elements and the boundaries in a PolyMesh2D.

Parameters

Examples

property mesh

The parent PolyMesh2D.

Returns

The parent mesh assigned to the BoundaryElement2D.

Return type

PolyMesh2D

Note

The mesh is immutable and can only be assigned when the BoundaryElement2D is created. An BoundaryElement2D should not usually be created explicitly, but rather should be created indirectly by calling the PolyMesh2D.generate_mesh() method.

Examples

>>> # create a simple mesh and check the element properties
>>> import vcfempy.meshgen
>>> msh = vcfempy.meshgen.PolyMesh2D()
>>> msh.add_vertices([[0, 0], [0, 1], [1, 1], [1, 0]])
>>> msh.insert_boundary_vertices(0, [0, 1, 2, 3])
>>> msh.mesh_scale = 0.4
>>> msh.add_seed_points([0.5, 0.5])
>>> msh.generate_mesh()
>>> print(msh.boundary_elements[0].mesh is msh)
True
property num_nodes

Number of nodes in the BoundaryElement2D.

Returns

The number of nodes in the BoundaryElement2D.

Return type

int

Examples

>>> # create a simple mesh and check the element properties
>>> import vcfempy.meshgen
>>> msh = vcfempy.meshgen.PolyMesh2D()
>>> msh.add_vertices([[0, 0], [0, 1], [1, 1], [1, 0]])
>>> msh.insert_boundary_vertices(0, [0, 1, 2, 3])
>>> msh.mesh_scale = 0.4
>>> msh.add_seed_points([0.5, 0.5])
>>> msh.generate_mesh()
>>> print(msh.boundary_elements[0].num_nodes)
2
property nodes

List of node indices in the BoundaryElement2D. References the PolyMesh2D.nodes of the parent mesh.

Returns

The list of node indices in the BoundaryElement2D.

Return type

list[int]

Examples

>>> # create a simple mesh and check the element properties
>>> import vcfempy.meshgen
>>> msh = vcfempy.meshgen.PolyMesh2D()
>>> msh.add_vertices([[0, 0], [0, 1], [1, 1], [1, 0]])
>>> msh.insert_boundary_vertices(0, [0, 1, 2, 3])
>>> msh.mesh_scale = 0.4
>>> msh.add_seed_points([0.5, 0.5])
>>> msh.generate_mesh()
>>> print(msh.boundary_elements[0].nodes)
[0, 1]
insert_nodes(index, nodes)

Insert node indices to the BoundaryElement2D.

Parameters
  • index (int) – The index at which to insert the nodes into nodes.

  • nodes (list[int]) – The list of node indices to add to nodes. Length must be a multiple of 2 and the maximum number of nodes is 2.

Note

Before inserting the values in nodes, an attempt is made to cast to a flattened numpy.ndarray of int. The new number of nodes after insertion must be 0 or 2.

Raises
  • TypeError – If index cannot be interpreted as int.

  • ValueError – If nodes is not array_like, such as a jagged list[list[int]]. If any values in nodes cannot be cast to int, are already in nodes, are negative, are >= mesh.num_nodes, or the list of nodes to be added would result in nodes having a length other than 0 or 2.

Examples

>>> # create a simple mesh
>>> import vcfempy.meshgen
>>> msh = vcfempy.meshgen.PolyMesh2D()
>>> msh.add_vertices([[0, 0], [0, 1], [1, 1], [1, 0]])
>>> msh.insert_boundary_vertices(0, [0, 1, 2, 3])
>>> msh.mesh_scale = 0.4
>>> msh.add_seed_points([0.5, 0.5])
>>> msh.generate_mesh()
>>> print(msh.nodes.round(14))
[[-0.    1.  ]
 [ 0.35  1.  ]
 [ 0.    0.  ]
 [ 0.35  0.  ]
 [ 1.    1.  ]
 [ 0.65  1.  ]
 [ 0.65  0.65]
 [ 1.    0.65]
 [ 1.   -0.  ]
 [ 0.65 -0.  ]
 [ 0.65  0.35]
 [ 1.    0.35]
 [ 0.    0.65]
 [ 0.    0.35]
 [ 0.35  0.65]
 [ 0.35  0.35]]
>>> # create a new element
>>> # note, this is normally not done explicitly, but is shown here
>>> # for testing and documentation
>>> e = vcfempy.meshgen.BoundaryElement2D(msh)
>>> print(e.nodes)
[]
>>> e.insert_nodes(0, [0, 1])
>>> print(e.nodes)
[0, 1]
>>> print(np.round(e.length, 14))
0.35
>>> # insert no nodes in multiple ways
>>> e.insert_nodes(0, None)
>>> e.insert_nodes(0, [])
>>> print(e.nodes)
[0, 1]
>>> # try to insert some invalid nodes
>>> e = vcfempy.meshgen.BoundaryElement2D(msh)
>>> e.insert_nodes(0, 'one')
Traceback (most recent call last):
    ...
ValueError: invalid literal for int() with base 10: 'one'
>>> e.insert_nodes(0, [0, 0])
Traceback (most recent call last):
    ...
ValueError: 0 is already a node
>>> print(e.nodes)
[]
>>> e.insert_nodes(0, [16, 17])
Traceback (most recent call last):
    ...
ValueError: node index 17 out of range
>>> print(e.nodes)
[]
>>> e.insert_nodes(0, [-1, -2])
Traceback (most recent call last):
    ...
ValueError: node index -2 out of range
>>> print(e.nodes)
[]
>>> e.insert_nodes(
...             0, [[1, 2], 3]) 
Traceback (most recent call last):
    ...
ValueError: ...
>>> print(e.nodes)
[]
>>> e.insert_nodes('one', [0, 1])
Traceback (most recent call last):
    ...
TypeError: 'str' object cannot be interpreted as an integer
>>> print(e.nodes)
[]
>>> e.insert_nodes(0, [2])
Traceback (most recent call last):
    ...
ValueError: number of nodes in BoundaryElement2D can only be 0 or 2
>>> print(e.nodes)
[]
remove_nodes(remove_nodes)

Remove node indices from the BoundaryElement2D.

Parameters

remove_nodes (list[int]) – The list of nodes to remove from nodes.

Note

Before removing the values in remove_nodes, an attempt will be made to cast it to a flattened numpy.ndarray of int.

Raises

ValueError – If remove_nodes is not array_like, such as a jagged list[list[int]]. If any values in remove_nodes cannot be cast to int or are not in nodes. If the number of remove_nodes would result in the length of nodes being other than 0 or 2.

Examples

>>> # create a simple mesh, and remove nodes from an element
>>> # this should not normally be done explicitly unless you know
>>> # what you are doing
>>> import vcfempy.meshgen
>>> msh = vcfempy.meshgen.PolyMesh2D()
>>> msh.add_vertices([[0, 0], [0, 1], [1, 1], [1, 0]])
>>> msh.insert_boundary_vertices(0, [0, 1, 2, 3])
>>> msh.mesh_scale = 0.4
>>> msh.add_seed_points([0.5, 0.5])
>>> msh.generate_mesh()
>>> print(msh.boundary_elements[0].nodes)
[0, 1]
>>> msh.boundary_elements[0].remove_nodes([0, 1])
>>> print(msh.boundary_elements[0].nodes)
[]
>>> # remove no nodes, in two different ways
>>> msh.boundary_elements[0].insert_nodes(0, [0, 1])
>>> msh.boundary_elements[0].remove_nodes(None)
>>> msh.boundary_elements[0].remove_nodes([])
>>> print(msh.boundary_elements[0].nodes)
[0, 1]
>>> # try to remove some invalid nodes
>>> msh.boundary_elements[0].remove_nodes('one')
Traceback (most recent call last):
    ...
ValueError: invalid literal for int() with base 10: 'one'
>>> msh.boundary_elements[0].remove_nodes([5, 0])
Traceback (most recent call last):
    ...
ValueError: list.remove(x): x not in list
>>> print(msh.boundary_elements[0].nodes)
[0, 1]
>>> msh.boundary_elements[0].remove_nodes(4)
Traceback (most recent call last):
    ...
ValueError: number of nodes in BoundaryElement2D can only be 0 or 2
>>> msh.boundary_elements[0].remove_nodes(
...                 [[1, 2], 3]) 
Traceback (most recent call last):
    ...
ValueError: ...
property neighbor

The neighboring PolyElement2D to the BoundaryElement2D.

Parameters

neighbor (PolyElement2D) – The new neighboring PolyElement2D to the BoundaryElement2D.

Returns

The neighboring PolyElement2D to the BoundaryElement2D. If no neighbor has been assigned, returns None.

Return type

None | PolyElement2D

Note

A BoundaryElement2D can only have 0 or 1 neighbors.

Raises

Examples

>>> # create a simple mesh
>>> import vcfempy.meshgen
>>> msh = vcfempy.meshgen.PolyMesh2D()
>>> msh.add_vertices([[0, 0], [0, 1], [1, 1], [1, 0]])
>>> msh.insert_boundary_vertices(0, [0, 1, 2, 3])
>>> msh.mesh_scale = 0.4
>>> msh.add_seed_points([0.5, 0.5])
>>> msh.generate_mesh()
>>> # create a new element
>>> # note, this is normally not done explicitly, but is shown here
>>> # for testing and documentation
>>> e = vcfempy.meshgen.BoundaryElement2D(msh)
>>> print(e.neighbor)
None
>>> e.neighbor = msh.elements[0]
>>> print(msh.elements.index(e.neighbor))
0
>>> # try to add some invalid neighbors
>>> e.neighbor = 0
Traceback (most recent call last):
    ...
TypeError: neighbor must be a PolyElement2D
>>> msh_new = vcfempy.meshgen.PolyMesh2D()
>>> pe = vcfempy.meshgen.PolyElement2D(msh_new)
>>> e.neighbor = pe
Traceback (most recent call last):
    ...
ValueError: neighbor must have same parent mesh
property length

The length of the BoundaryElement2D.

Returns

The length of the BoundaryElement2D.

Return type

float

Examples

>>> # create a simple mesh and check the element properties
>>> import vcfempy.meshgen
>>> msh = vcfempy.meshgen.PolyMesh2D()
>>> msh.add_vertices([[0, 0], [0, 1], [1, 1], [1, 0]])
>>> msh.insert_boundary_vertices(0, [0, 1, 2, 3])
>>> msh.mesh_scale = 0.4
>>> msh.add_seed_points([0.5, 0.5])
>>> msh.generate_mesh()
>>> print(np.round(msh.boundary_elements[0].length, 14))
0.35
property centroid

The centroid coordinates of the BoundaryElement2D.

Returns

The coordinates of the centroid of the BoundaryElement2D.

Return type

numpy.ndarray, shape = (2, )

Examples

>>> # create a simple mesh and check the element properties
>>> import vcfempy.meshgen
>>> msh = vcfempy.meshgen.PolyMesh2D()
>>> msh.add_vertices([[0, 0], [0, 1], [1, 1], [1, 0]])
>>> msh.insert_boundary_vertices(0, [0, 1, 2, 3])
>>> msh.mesh_scale = 0.4
>>> msh.add_seed_points([0.5, 0.5])
>>> msh.generate_mesh()
>>> print(msh.boundary_elements[0].centroid)
[0.175 1.   ]
invalidate_properties()

Resets cached value of computed attributes length and centroid.

Note

The invalidate_properties() method should be called whenever nodes is changed. This is done by insert_nodes() and remove_nodes(), but needs to be done explicitly if making manual changes to nodes.

Examples

>>> # create a simple mesh, check the element properties
>>> # invalidate properties and check the values of (private) cache
>>> # attributes
>>> import vcfempy.meshgen
>>> msh = vcfempy.meshgen.PolyMesh2D()
>>> msh.add_vertices([[0, 0], [0, 1], [1, 1], [1, 0]])
>>> msh.insert_boundary_vertices(0, [0, 1, 2, 3])
>>> msh.mesh_scale = 0.4
>>> msh.add_seed_points([0.5, 0.5])
>>> msh.generate_mesh()
>>> print(msh.boundary_elements[0]._length)
None
>>> print(msh.boundary_elements[0]._centroid)
None
>>> print(np.round(msh.boundary_elements[0].length, 14))
0.35
>>> print(msh.boundary_elements[0].centroid.round(14))
[0.175 1.   ]
>>> msh.boundary_elements[0].invalidate_properties()
>>> print(msh.interface_elements[0]._length)
None
>>> print(msh.interface_elements[0]._centroid)
None
plot(ax=None, **kwargs)

Plot the BoundaryElement2D using matplotlib.pyplot.plot().

Parameters

ax (None | matplotlib.axes.Axes) – The axes to plot on. If not provided, will try to get one using matplotlib.pyplot.gca().

Other Parameters

**kwargs (matplotlib.lines.Line2D properties, optional) – Default values: linewidth = 2.0, linestyle = ‘–‘. color = ‘black’

Returns

The axes that the BoundaryElement2D was plotted on.

Return type

matplotlib.axes.Axes

Examples

>>> # initialize a mesh and a material region, then generate a mesh
>>> # and plot the elements, interface elements, and boundary
>>> # elements
>>> import matplotlib.pyplot as plt
>>> import vcfempy.materials
>>> import vcfempy.meshgen
>>> msh = vcfempy.meshgen.PolyMesh2D('test mesh')
>>> msh.add_vertices([[0, 0], [0, 1], [1, 1], [1, 0]])
>>> msh.insert_boundary_vertices(0, [0, 1, 2, 3])
>>> rock = vcfempy.materials.Material('rock', color='xkcd:clay')
>>> mr = vcfempy.meshgen.MaterialRegion2D(msh, msh.boundary_vertices,
...                                       rock, 'rock region')
>>> msh.mesh_scale = 0.2
>>> msh.mesh_rand = 0.2
>>> msh.generate_mesh()
>>> fig = plt.figure()
>>> for e in msh.elements:
...     ax = e.plot(edgecolor=None)
...     ax = e.plot_quad_points()
>>> for e in msh.interface_elements:
...     ax = e.plot()
>>> for e in msh.boundary_elements:
...     ax = e.plot()
>>> xmin, xmax, ymin, ymax = ax.axis('equal')
>>> xtext = ax.set_xlabel('x')
>>> ytext = ax.set_ylabel('y')
>>> ttext = ax.set_title('BoundaryElement2D Test Plot')
>>> plt.savefig('BoundaryElement2D_test_plot.png')