Degrees of Freedom#
This module contains the definition of a boundary condition as well as tools related to the partition of degrees of freedom and the application of boundary conditions on a field container.
- class felupe.Boundary(field, name='default', fx=<ufunc 'isnan'>, fy=<ufunc 'isnan'>, fz=<ufunc 'isnan'>, value=0.0, skip=(False, False, False), mask=None, mode='or')[source]#
A Boundary as a collection of prescribed degrees of freedom (numbered coordinate components of a field at points of a mesh).
- Parameters:
field (felupe.Field) – Field on wich the boundary is created.
name (str, optional (default is "default")) – Name of the boundary.
fx (float or callable, optional) – Mask-function for x-component of mesh-points which returns True at points on which the boundary will be applied (default is
np.isnan
). If a float is passed, this is transformed tolambda x: np.isclose(x, fx)
.fy (float or callable, optional) – Mask-function for y-component of mesh-points which returns True at points on which the boundary will be applied (default is
np.isnan
). If a float is passed, this is transformed tolambda y: np.isclose(y, fy)
.fz (float or callable, optional) – Mask-function for z-component of mesh-points which returns True at points on which the boundary will be applied (default is
np.isnan
). If a float is passed, this is transformed tolambda z: np.isclose(z, fz)
.value (ndarray or float, optional) – Value(s) of the selected (prescribed) degrees of freedom (default is 0.0).
skip (tuple of bool or int, optional) – A tuple to define which axes of the selected points should be skipped, i.e. not prescribed (default is
(False, False, False)
).mask (ndarray) – Boolean mask for the prescribed degrees of freedom. If a mask is passed,
fx
,fy
andfz
are ignored. However,skip
is still applied on the mask.mode (string, optional) – A string which defines the logical operation for the selected points per axis (default is or).
- mask#
1d- or 2d-boolean mask array for the prescribed degrees of freedom.
- Type:
ndarray
- dof#
1d-array of ints which contains the prescribed degrees of freedom.
- Type:
ndarray
- points#
1d-array of ints which contains the point ids on which one or more degrees of freedom are prescribed.
- Type:
ndarray
- value#
Value of the selected (prescribed) degrees of freedom.
- Type:
ndarray or float
Examples
A boundary condition prescribes values for chosen degrees of freedom of a given field (not a field container). This is demonstrated for a plane-strain vector field on a quad-mesh of a circle.
>>> import felupe as fem
>>> mesh = fem.Circle(radius=1, n=6) >>> x, y = mesh.points.T >>> region = fem.RegionQuad(mesh) >>> displacement = fem.FieldPlaneStrain(region, dim=2) >>> field = fem.FieldContainer([displacement])
A boundary on the displacement field which prescribes all components of the field on the outermost left point of the circle is created. The easiest way is to pass the desired value to
fx
. The same result is obtained if a callable function is passed tofx
.>>> left = fem.Boundary(displacement, fx=x.min()) >>> left = fem.Boundary(displacement, fx=lambda x: np.isclose(x, x.min()))
>>> plotter = mesh.plot(off_screen=True) >>> plotter.add_points( >>> np.pad(mesh.points[left.points], ((0, 0), (0, 1))), >>> point_size=20, >>> color="red", >>> ) >>> img = plotter.screenshot("boundary_left.png", transparent_background=True)
If
fx
andfy
are given, the masks are combined by logical-or.>>> axes = fem.Boundary(displacement, fx=0, fy=0, mode="or")
This may be changed to logical-and if desired.
>>> center = fem.Boundary(displacement, fx=0, fy=0, mode="and")
For the most-general case, a user-defined boolean mask for the selection of the mesh-points is provided. While the two upper methods are useful to select points separated per point-coordinates, providing a mask is more flexible as it may involve all three coordinates (or any other quantities of interest).
>>> mask = np.logical_and(np.isclose(x**2 + y**2, 1), x <= 0) >>> surface = fem.Boundary(displacement, mask=mask)
A boundary condition may be skipped on given axes, i.e. if only the x-components of a field should be prescribed on the selected points, then the y-axis must be skipped.
>>> axes_x = fem.Boundary(displacement, fx=0, fy=0, skip=(False, True))
Values for the prescribed degress of freedom are either applied during creation or by the update-method.
>>> left = fem.Boundary(displacement, fx=x.min(), value=-0.2) >>> left.update(-0.3)
Sometimes it is useful to create a boundary with all axes skipped. This boundary has no prescribed degrees of freedom and hence, is without effect. However, it may still be used in a characteristic job for the boundary to be tracked.
See also
felupe.CharacteristicCurve
A job with a boundary to be tracked.
felupe.dof.partition
Partition degrees of freedom into prescribed and active dof.
felupe.dof.apply
Apply prescribed values for a list of boundaries.
- felupe.dof.partition(field, bounds)[source]#
Partition a list of degrees of freedom into prescribed (dof0) and active (dof1) degrees of freedom.
- Parameters:
field (felupe.FieldContainer) – FieldContainer which holds the fields used in the boundaries.
bounds (dict of felupe.Boundary) – Dict of boundaries.
- Returns:
dof0 (ndarray) – 1d-array of int with all prescribed degress of freedom.
dof1 (ndarray) – 1d-array of int with all active degrees of freedom.
Examples
>>> import felupe as fem
>>> mesh = fem.Rectangle(a=(0, 0), b=(1, 1), n=(3, 3)) >>> region = fem.RegionQuad(mesh) >>> displacement = fem.FieldPlaneStrain(region, dim=2) >>> field = fem.FieldContainer([displacement])
A plot shows the point-ids along with the associated degrees of freedom.
>>> plotter = mesh.plot(off_screen=True) >>> plotter.add_point_labels( >>> points=np.pad(mesh.points, ((0, 0), (0, 1))), >>> labels=[ >>> f"Point {i}: DOF {a}, {b}" >>> for i, (a, b) in enumerate(displacement.indices.dof) >>> ], >>> ) >>> img = plotter.screenshot("dof_partition.png", transparent_background=True)
>>> boundaries = dict( >>> left=fem.Boundary(displacement, fx=0, value=0.2), >>> right=fem.Boundary(displacement, fx=1), >>> )
>>> dof0, dof1 = fem.dof.partition(field, boundaries) >>> ext0 = fem.dof.apply(field, boundaries, dof0=dof0)
>>> dof0 array([ 0, 1, 4, 5, 6, 7, 10, 11, 12, 13, 16, 17])
>>> dof1 array([ 2, 3, 8, 9, 14, 15])
>>> ext0 array([0.2, 0.2, 0. , 0. , 0.2, 0.2, 0. , 0. , 0.2, 0.2, 0. , 0. ])
dof0=None
is required (default) if the prescribed displacement array should be returned for all degrees of freedom.>>> fem.dof.apply(field, boundaries).reshape( >>> displacement.values.shape >>> ) array([[0.2, 0.2], [0. , 0. ], [0. , 0. ], [0.2, 0.2], [0. , 0. ], [0. , 0. ], [0.2, 0.2], [0. , 0. ], [0. , 0. ]])
See also
felupe.Boundary
A collection of prescribed degrees of freedom.
felupe.dof.apply
Apply prescribed values for a list of boundaries.
- felupe.dof.apply(field, bounds, dof0=None)[source]#
Apply prescribed values for a list of boundaries and return all (default) or only the prescribed components of the
field
based ondof0
.- Parameters:
field (felupe.FieldContainer) – FieldContainer which holds the fields used in the boundaries.
bounds (dict of felupe.Boundary) – Dict of boundaries.
dof0 (ndarray or None, optional) – 1d-array of int with prescribed degrees of freedom (default is None). If not None, only the given deegrees of freedom
dof0
of the field values, prescribed by the boundaries, are returned.
- Returns:
Field values at mesh-points for all (default) or only the prescribed components of the
field
based ondof0
.- Return type:
ndarray
Examples
>>> import felupe as fem
>>> mesh = fem.Rectangle(a=(0, 0), b=(1, 1), n=(3, 3)) >>> region = fem.RegionQuad(mesh) >>> displacement = fem.FieldPlaneStrain(region, dim=2) >>> field = fem.FieldContainer([displacement])
>>> boundaries = dict( >>> left=fem.Boundary(displacement, fx=0, value=0.2), >>> right=fem.Boundary(displacement, fx=1), >>> )
>>> dof0, dof1 = fem.dof.partition(field, boundaries) >>> ext0 = fem.dof.apply(field, boundaries, dof0=dof0)
>>> dof0 array([ 0, 1, 4, 5, 6, 7, 10, 11, 12, 13, 16, 17])
>>> dof1 array([ 2, 3, 8, 9, 14, 15])
>>> ext0 array([0.2, 0.2, 0. , 0. , 0.2, 0.2, 0. , 0. , 0.2, 0.2, 0. , 0. ])
dof0=None
is required (default) if the prescribed displacement array should be returned for all degrees of freedom.>>> fem.dof.apply(field, boundaries).reshape( >>> displacement.values.shape >>> ) array([[0.2, 0.2], [0. , 0. ], [0. , 0. ], [0.2, 0.2], [0. , 0. ], [0. , 0. ], [0.2, 0.2], [0. , 0. ], [0. , 0. ]])
See also
felupe.Boundary
A collection of prescribed degrees of freedom.
felupe.dof.partition
Partition degrees of freedom into prescribed and active dof.