Create Custom Items#
Items are supported to be used in a Step and in
newtonraphson(). They provide methods to assemble a vector and a sparse
matrix. An item has to be created as a class which takes a
FieldContainer as input argument. In its __init__(self, field)
method, the helpers Assemble and
Results have to be evaluated and added as attributes.
Internal methods which assemble the sparse vector and matrix, optionally with an updated
FieldContainer provided by the field argument, have to be linked to
Assemble.
注釈
This is a minimal working example for an item. For more details, see the sources of
SolidBody or SolidBodyNearlyIncompressible. It is
considered good practice to add the parameters of the item as attributes to the
Results, so that they are automatically available in the
post-processing. To ramp parameters within a step, the item has to be updated with
its update() method, which is called by the step at the beginning of each
substep. If more parameters have to be updated, it is recommended to add a separate
method for each parameter with the naming convention _update_my_parameter().
Then, UpdateItem can be used to update the item with the
syntax my_item["my_parameter"] = my_parameter_value in a step.
from scipy.sparse import csr_matrix
import felupe as fem
from felupe.mechanics import Assemble, Results, UpdateItem
class MyItem:
def __init__(self, field, my_parameter=1.0, my_other_parameter=2.0):
self.field = field
self.assemble = Assemble(vector=self._vector, matrix=self._matrix)
self.results = Results()
self.results.my_parameter = my_parameter
self.results.my_other_parameter = my_other_parameter
def __getitem__(self, key):
"""Required for ramping parameters. The keys are taken from the names of the
update methods, i.e., ``"my_parameter"`` is taken from the method name
``"_update_my_parameter()"``.
.. code-block:: python
my_item = MyItem(field, my_parameter=1.0, my_other_parameter=2.0)
ramp = dict(my_item['my_parameter']=my_parameter_value)
step = fem.Step(items=[my_item], ramp=ramp)
"""
return UpdateItem(self, key)
def update(self, my_parameter):
"""Required for ramping the primary parameter. This method is used if no key
is given.
.. code-block:: python
my_item = MyItem(field, my_parameter=1.0, my_other_parameter=2.0)
ramp = dict(my_item=my_parameter_value)
step = fem.Step(items=[my_item], ramp=ramp)
"""
self._update_my_parameter(my_parameter)
def _update_my_parameter(self, my_parameter):
self.results.my_parameter = my_parameter
def _update_my_other_parameter(self, my_other_parameter):
self.results.my_other_parameter = my_other_parameter
def _vector(self, field=None, **kwargs):
return csr_matrix(([0.0], ([0], [0])), shape=(1, 1))
def _matrix(self, field=None, **kwargs):
return csr_matrix(([0.0], ([0], [0])), shape=(1, 1))
This item is now added to a basic script.
注釈
The vector- and matrix-shapes are automatically increased to match the shape of the
other items if necessary. Hence, a sparse matrix with shape (1, 1) is a valid
choice for a vector or a matrix filled with zeros.
region = fem.RegionHexahedron(mesh=fem.Cube(n=3))
field = fem.FieldContainer([fem.Field(region, dim=3)])
boundaries = fem.dof.uniaxial(field, clamped=True, move=1.0, return_loadcase=False)
solid = fem.SolidBody(umat=fem.NeoHooke(mu=1, bulk=2), field=field)
my_item = MyItem(field=field, my_parameter=1.0, my_other_parameter=2.0)
table = fem.math.linsteps([0.0, 1.0], num=10)
# ramp only one parameter, while the other one stays constant at its initial value
ramp = {my_item: table} # here, by default, "my_parameter" will be ramped
# ramp one or more parameters simultaneously
ramp = {
my_item["my_parameter"]: table,
my_item["my_other_parameter"]: 1.0 + table,
}
step = fem.Step(items=[solid, my_item], ramp=ramp, boundaries=boundaries)
job = fem.Job(steps=[step]).evaluate()