-
Notifications
You must be signed in to change notification settings - Fork 13
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
1 changed file
with
45 additions
and
36 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,95 +1,104 @@ | ||
Composite Regions with Solid Bodies | ||
----------------------------------- | ||
|
||
This section demonstrates how to set up a problem with two regions, each associated to a seperated solid body. | ||
This section demonstrates how to set up a problem with two regions, each associated to a | ||
seperated solid body. Different element formulations are used for the solid bodies. | ||
|
||
.. pyvista-plot:: | ||
:context: | ||
|
||
import felupe as fem | ||
import numpy as np | ||
|
||
m = fem.Rectangle(n=21) | ||
inner = fem.Rectangle(a=(-1, -1), b=(1, 1), n=(5, 5)).triangulate() | ||
|
||
lower = fem.Rectangle(a=(-3, -3), b=(3, -1), n=(13, 5)) | ||
upper = fem.Rectangle(a=(-3, 1), b=(3, 3), n=(13, 5)) | ||
left = fem.Rectangle(a=(-3, -1), b=(-1, 1), n=(5, 5)) | ||
right = fem.Rectangle(a=(1, -1), b=(3, 1), n=(5, 5)) | ||
|
||
outer = fem.MeshContainer([lower, upper, left, right], merge=True).stack() | ||
|
||
container = fem.MeshContainer([inner, outer], merge=True) | ||
|
||
|
||
A top-level (vertex) field, which contains all the unknowns, is required for the | ||
definition of the boundary conditions as well as for the evaluation of the job. | ||
|
||
In a second step, sub-meshes are created. | ||
.. note:: | ||
Ensure to init the mesh container with ``merge=True``, otherwise the points-array of | ||
the container will be empty. | ||
|
||
.. pyvista-plot:: | ||
:context: | ||
|
||
# take some points from the inside for the fiber-reinforced area | ||
eps = 1e-3 | ||
mask = np.arange(m.npoints)[np.logical_and.reduce([ | ||
m.points[:, 0] >= 0.3, | ||
m.points[:, 0] <= 0.7 + eps, | ||
m.points[:, 1] >= 0.3, | ||
m.points[:, 1] <= 0.7 + eps, | ||
])] | ||
|
||
# copies of the mesh | ||
mesh = [m.copy(), m.copy()] | ||
|
||
# create sub-meshes (fiber, matrix) | ||
mesh[0].update(cells=m.cells[ np.all(np.isin(m.cells, mask), axis=1)]) | ||
mesh[1].update(cells=m.cells[~np.all(np.isin(m.cells, mask), axis=1)]) | ||
container = fem.MeshContainer([inner, outer], merge=True) | ||
field = fem.Field.from_mesh_container(container).as_container() | ||
|
||
This is followed by the creation of a global region/field and two sub-regions/sub-fields. | ||
The sub-meshes are available in the global mesh container, on which the sub-fields are | ||
created. | ||
|
||
.. pyvista-plot:: | ||
:context: | ||
|
||
# a global and two sub-regions | ||
region = fem.RegionQuad(m) | ||
regions = [fem.RegionQuad(me) for me in mesh] | ||
|
||
# a global and two sub-fields | ||
field = fem.FieldContainer([fem.FieldPlaneStrain(region, dim=2)]) | ||
|
||
regions = [ | ||
fem.RegionTriangle(container.meshes[0]), | ||
fem.RegionQuad(container.meshes[1]), | ||
] | ||
fields = [ | ||
fem.FieldContainer([fem.FieldPlaneStrain(regions[0], dim=2)]), | ||
fem.FieldContainer([fem.FieldPlaneStrain(regions[1], dim=2)]), | ||
] | ||
|
||
The displacement boundaries are created on the total field. | ||
The displacement boundaries are created on the top-level field. | ||
|
||
.. pyvista-plot:: | ||
:context: | ||
|
||
boundaries = dict( | ||
fixed=fem.Boundary(field[0], fx=0), | ||
move=fem.Boundary(field[0], fx=1), | ||
fixed=fem.Boundary(field[0], fx=field.region.mesh.x.min()), | ||
move=fem.Boundary(field[0], fx=field.region.mesh.x.max()), | ||
) | ||
|
||
|
||
The rubber is associated to a Neo-Hookean material formulation whereas the steel is modeled by a linear elastic material formulation. Due to the large rotation, its large-strain formulation is required. For each material a solid body is created. | ||
The rubber is associated to a Neo-Hookean material formulation whereas the steel is | ||
modeled by a linear elastic material formulation. Due to the large rotation, its | ||
large-strain formulation is required. For each material a solid body is created. | ||
|
||
.. pyvista-plot:: | ||
:context: | ||
|
||
# two material model formulations | ||
neo_hooke = fem.NeoHooke(mu=1, bulk=1) | ||
linear_elastic = fem.LinearElasticLargeStrain(E=100, nu=0.3) | ||
neo_hooke = fem.NeoHooke(mu=1, bulk=1) | ||
|
||
# the solid bodies | ||
fiber = fem.SolidBody(umat=linear_elastic, field=fields[0]) | ||
matrix = fem.SolidBody(umat=neo_hooke, field=fields[1]) | ||
|
||
|
||
A step is created and further added to a job. The global field must be passed to the ``x0`` argument during the evaluation of the job. Internally, all field values are linked automatically, i.e. they share their ``values`` attribute. | ||
A step is created and further added to a job. The global field must be passed as the | ||
``x0`` argument during the evaluation of the job. Internally, all field values are | ||
linked automatically, i.e. they share their ``values`` array. | ||
|
||
.. pyvista-plot:: | ||
:context: | ||
:force_static: | ||
|
||
# prepare a step with substeps | ||
move = fem.math.linsteps([0, 0.5], num=10) | ||
move = fem.math.linsteps([0, 3], num=10) | ||
step = fem.Step( | ||
items=[matrix, fiber], | ||
ramp={boundaries["move"]: move}, | ||
boundaries=boundaries | ||
boundaries=boundaries, | ||
) | ||
|
||
# take care of the x0-argument | ||
job = fem.Job(steps=[step]) | ||
job.evaluate(x0=field) | ||
|
||
field.plot("Principal Values of Logarithmic Strain").show() | ||
plotter = fields[0].plot( | ||
"Principal Values of Logarithmic Strain", show_undeformed=False | ||
) | ||
fields[1].plot( | ||
"Principal Values of Logarithmic Strain", show_undeformed=False, plotter=plotter | ||
).show() |