Source code for felupe.element._base

# -*- coding: utf-8 -*-
"""
This file is part of FElupe.

FElupe is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

FElupe is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with FElupe.  If not, see <http://www.gnu.org/licenses/>.
"""

import numpy as np


[docs] class Element: """ Base-class for a finite element which provides methods for plotting. Examples -------- This example shows how to implement a hexahedron element. .. pyvista-plot:: :force_static: >>> import felupe as fem >>> import numpy as np >>> >>> class Hexahedron(fem.Element): ... def __init__(self): ... a = [-1, 1, 1, -1, -1, 1, 1, -1] ... b = [-1, -1, 1, 1, -1, -1, 1, 1] ... c = [-1, -1, -1, -1, 1, 1, 1, 1] ... self.points = np.vstack([a, b, c]).T ... ... # additional attributes for plotting, optional ... self.cells = np.array([[0, 1, 2, 3, 4, 5, 6, 7]]) ... self.cell_type = "hexahedron" ... ... def function(self, rst): ... r, s, t = rst ... a, b, c = self.points.T ... ar, bs, ct = 1 + a * r, 1 + b * s, 1 + c * t ... return (ar * bs * ct) / 8 ... ... def gradient(self, rst): ... r, s, t = rst ... a, b, c = self.points.T ... ar, bs, ct = 1 + a * r, 1 + b * s, 1 + c * t ... return np.stack([a * bs * ct, ar * b * ct, ar * bs * c], axis=1) >>> >>> mesh = fem.Cube(n=6) >>> element = Hexahedron() >>> quadrature = fem.GaussLegendre(order=1, dim=3) >>> region = fem.Region(mesh, element, quadrature) """
[docs] def view(self, point_data=None, cell_data=None, cell_type=None): """View the element with optional given dicts of point- and cell-data items. Parameters ---------- point_data : dict or None, optional Additional point-data dict (default is None). cell_data : dict or None, optional Additional cell-data dict (default is None). cell_type : pyvista.CellType or None, optional Cell-type of PyVista (default is None). Returns ------- felupe.ViewMesh A object which provides visualization methods for :class:`felupe.element.Element`. See Also -------- felupe.ViewMesh : Visualization methods for :class:`felupe.Mesh`. """ from ..mesh import Mesh mesh = Mesh(points=self.points, cells=self.cells, cell_type=self.cell_type) return mesh.view( point_data=point_data, cell_data=cell_data, cell_type=cell_type, )
[docs] def plot( self, *args, style="wireframe", color="black", add_axes_at_origin=True, add_point_labels=True, show_points=True, font_size=26, **kwargs, ): """Plot the element. See Also -------- felupe.Scene.plot: Plot method of a scene. """ view = self.view() if self.points.shape[1] > 1: view.mesh = view.mesh.extract_surface().extract_feature_edges() plotter = view.plot( *args, show_undeformed=False, opacity=0.8, add_axes=False, show_edges=False, style=style, color=color, **kwargs, ) if add_point_labels: plotter.add_point_labels( points=np.pad(self.points, ((0, 0), (0, 3 - self.points.shape[1]))), labels=[f"{a}" for a in np.arange(len(self.points))], font_size=font_size, show_points=show_points, point_size=20, point_color="black", shape=None, fill_shape=False, render_points_as_spheres=True, always_visible=True, ) if add_axes_at_origin: actor = plotter.add_axes_at_origin(xlabel="r", ylabel="s", zlabel="t") actor.SetNormalizedShaftLength((0.9, 0.9, 0.9)) actor.SetNormalizedTipLength((0.1, 0.1, 0.1)) if self.points.shape[1] == 3: actor.SetTotalLength([1.3, 1.3, 1.3]) elif self.points.shape[1] == 2: actor.SetZAxisLabelText("") actor.SetTotalLength([1.3, 1.3, 0]) elif self.points.shape[1] == 1: actor.SetYAxisLabelText("") actor.SetZAxisLabelText("") actor.SetTotalLength([1.3, 0, 0]) plotter.camera.zoom(0.7) if self.points.shape[1] == 3: plotter.camera.azimuth = -17 return plotter
[docs] def screenshot( self, *args, filename=None, transparent_background=None, scale=None, **kwargs, ): """Take a screenshot of the element. See Also -------- pyvista.Plotter.screenshot: Take a screenshot of a PyVista plotter. """ if filename is None: filename = f"{self.cell_type}.png" return self.plot(*args, off_screen=True, **kwargs).screenshot( filename=filename, transparent_background=transparent_background, scale=scale, )