# -*- 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/>.
"""
from ..region import (
RegionBiQuadraticQuad,
RegionConstantHexahedron,
RegionConstantQuad,
RegionHexahedron,
RegionLagrange,
RegionQuad,
RegionQuadraticHexahedron,
RegionQuadraticQuad,
RegionQuadraticTetra,
RegionQuadraticTriangle,
RegionTetra,
RegionTetraMINI,
RegionTriangle,
RegionTriangleMINI,
RegionTriQuadraticHexahedron,
)
from ._base import Field
[docs]
class FieldDual(Field):
r"""A dual field on points of a :class:`~felupe.Region` with dimension ``dim`` and
initial point ``values``.
Parameters
----------
region : Region
The region on which the field will be created.
dim : int, optional
The dimension of the field (default is 1).
values : float or array
A single value for all components of the field or an array of shape
`(region.mesh.npoints, dim)`. Default is 0.0.
offset : int, optional
Offset for cell connectivity of the dual mesh (default is 0).
npoints : int or None, optional
Specified number of mesh points for the dual mesh (default is None).
mesh: Mesh or None, optional
A mesh which is used for the dual region (default is None). If None, the mesh
is taken from the region.
disconnect : bool or None, optional
A flag to disconnect the dual mesh (default is None). If None, a disconnected
mesh is used except for regions with quadratic-triangle or -tetra or MINI
element formulations.
**kwargs : dict, optional
Optional keyword arguments for the dual region.
Examples
--------
.. pyvista-plot::
>>> import felupe as fem
>>>
>>> mesh = fem.Cube(n=6)
>>> region = fem.RegionHexahedron(mesh)
>>>
>>> displacement = fem.Field(region, dim=3)
>>> pressure = fem.FieldDual(region)
>>>
>>> field = fem.FieldContainer([displacement, pressure])
>>> field
<felupe FieldContainer object>
Number of fields: 2
Dimension of fields:
Field: 3
FieldDual: 1
See Also
--------
felupe.FieldContainer : A container which holds one or multiple (mixed) fields.
felupe.Field : Field on points of a :class:`~felupe.Region` with dimension ``dim``
and initial point ``values``.
felupe.FieldAxisymmetric : Axisymmetric field on points of a
:class:`~felupe.Region` with dimension ``dim`` and initial point ``values``.
felupe.FieldPlaneStrain : Plane strain field on points of a
:class:`~felupe.Region` with dimension ``dim`` and initial point ``values``.
felupe.mesh.dual : Create a dual :class:`~felupe.Mesh`.
"""
def __init__(
self,
region,
dim=1,
values=0.0,
offset=0,
npoints=None,
mesh=None,
disconnect=None,
**kwargs,
):
# create dual regions
region_dual_dict = {
RegionHexahedron: RegionConstantHexahedron,
RegionQuad: RegionConstantQuad,
RegionQuadraticQuad: RegionConstantQuad,
RegionBiQuadraticQuad: RegionQuad,
RegionQuadraticHexahedron: RegionConstantHexahedron,
RegionTriQuadraticHexahedron: RegionHexahedron,
RegionQuadraticTetra: RegionTetra,
RegionQuadraticTriangle: RegionTriangle,
RegionTetraMINI: RegionTetra,
RegionTriangleMINI: RegionTriangle,
RegionLagrange: RegionLagrange,
}
mesh_kwargs = {
RegionHexahedron: {},
RegionQuad: {},
RegionQuadraticQuad: {},
RegionBiQuadraticQuad: {},
RegionQuadraticHexahedron: {},
RegionTriQuadraticHexahedron: {},
RegionQuadraticTetra: {"disconnect": False},
RegionQuadraticTriangle: {"disconnect": False},
RegionTetraMINI: {"disconnect": False},
RegionTriangleMINI: {"disconnect": False},
RegionLagrange: {},
}[type(region)]
if disconnect is not None:
mesh_kwargs["disconnect"] = disconnect
points_per_cell = {
RegionConstantHexahedron: 1,
RegionConstantQuad: 1,
RegionQuad: 4,
RegionHexahedron: 8,
RegionTriangle: 3,
RegionTetra: 4,
RegionLagrange: None,
}
kwargs0 = {"quadrature": region.quadrature, "grad": False}
if isinstance(region, RegionLagrange):
kwargs0["order"] = region.order - 1
kwargs0["dim"] = region.mesh.dim
points_per_cell[RegionLagrange] = region.order**region.element.dim
RegionDual = region_dual_dict[type(region)]
if mesh is None and points_per_cell[RegionDual] is not None:
mesh = region.mesh.dual(
points_per_cell=points_per_cell[RegionDual],
offset=offset,
npoints=npoints,
**mesh_kwargs,
)
region_dual = RegionDual(mesh, **{**kwargs0, **kwargs})
super().__init__(region_dual, dim=dim, values=values)