Composite Regions with Solid Bodies#

This section demonstrates how to set up a problem with two regions, each associated to a seperated solid body.

import felupe as fem
import numpy as np

m = fem.Rectangle(n=21)

In a second step, sub-meshes are created.

# 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)])

This is followed by the creation of a global region/field and two sub-regions/sub-fields.

# 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)])
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.

boundaries = dict(
    fixed=fem.Boundary(field[0], fx=0),
    move=fem.Boundary(field[0], fx=1),
)

The rubber is associated to a Neo-Hookean material formulation whereas the steel is modeled by a linear elastic material formulation. For each material a solid body is created.

# two material model formulations
neo_hooke = fem.NeoHooke(mu=1, bulk=1)
linear_elastic = fem.LinearElastic(E=100, nu=0.3)

# 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.

# prepare a step with substeps
move = fem.math.linsteps([0, 0.5], num=10)
step = fem.Step(
    items=[matrix, fiber],
    ramp={boundaries["move"]: move},
    boundaries=boundaries
)

# take care of the x0-argument
job = fem.Job(steps=[step])
job.evaluate(x0=field, filename="result.xdmf")
../_images/composite.png