felupe.mechanics._job のソースコード

# -*- 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/>.
"""

import warnings

from ..plugins import ProgressPlugin, XDMFWriterPlugin
from ..region import RegionVertex
from ..tools import Context, EventDispatcher


[ドキュメント] class JobState: "A class to keep track of the state of a Job during evaluation." def __init__(self, stepnumber=None, substepnumber=None, time=None): self.stepnumber = stepnumber self.substepnumber = substepnumber self.time = time
[ドキュメント] class Job: r"""A job with a list of steps and a method to evaluate them. Parameters ---------- steps : list of Step A list with steps, where each step subsequently depends on the solution of the previous step. callback : callable, optional A callable which is called after each completed substep. Function signature must be ``lambda stepnumber, substepnumber, substep, **kwargs: None``, where ``substep`` is an instance of :class:`~felupe.tools.NewtonResult`. The field container of the completed substep is available as ``substep.x``. Default is ``callback=lambda stepnumber, substepnumber, substep, **kwargs: None``. plugins : list or None, optional A list of plugins with hooks to be used during evaluation. Available hooks are ``before_job``, ``after_job``, ``before_step``, ``after_step`` and ``after_substep``. Each hook takes the job and the current state as arguments. All hooks are optional. Default is None, which is equivalent to an empty list. Simple callable plugins are dispatched at the ``after_substep`` hook. **kwargs : dict, optional Optional keyword-arguments for the ``callback`` function. Attributes ---------- nsteps : int The number of steps. timetrack : list of int A list with times at which the results are written to the XDMF result file. fnorms : list of list of float List with norms of the objective function for each completed substep of each step. See also class:`~felupe.tools.NewtonResult`. Examples -------- .. pyvista-plot:: :force_static: >>> import felupe as fem >>> >>> mesh = fem.Cube(n=6) >>> region = fem.RegionHexahedron(mesh) >>> field = fem.FieldContainer([fem.Field(region, dim=3)]) >>> >>> boundaries = fem.dof.symmetry(field[0]) >>> boundaries["clamped"] = fem.Boundary(field[0], fx=1, skip=(True, False, False)) >>> boundaries["move"] = fem.Boundary(field[0], fx=1, skip=(False, True, True)) >>> >>> umat = fem.NeoHooke(mu=1, bulk=2) >>> solid = fem.SolidBody(umat, field) >>> >>> move = fem.math.linsteps([0, 1], num=5) >>> step = fem.Step(items=[solid], ramp={boundaries["move"]: move}, boundaries=boundaries) >>> >>> job = fem.Job(steps=[step]).evaluate() >>> solid.plot("Principal Values of Cauchy Stress").show() See Also -------- Step : A Step with multiple substeps, subsequently depending on the solution of the previous substep. CharacteristicCurve : A job with a list of steps and a method to evaluate them. Force-displacement curve data is tracked during evaluation for a given :class:`~felupe.Boundary`. tools.NewtonResult : A data class which represents the result found by Newton's method. """ def __init__( self, steps, callback=lambda stepnumber, substepnumber, substep, **kwargs: None, plugins=None, **kwargs, ): self.steps = steps self.nsteps = len(steps) self.callback = callback self.timetrack = [] self.fnorms = [] self.kwargs = kwargs self.dispatcher = EventDispatcher(plugins=plugins)
[ドキュメント] def evaluate( self, filename=None, mesh=None, point_data=None, cell_data=None, point_data_default=True, cell_data_default=True, verbose=None, parallel=False, tqdm="tqdm", **kwargs, ): """Evaluate the steps. Parameters ---------- filename : str or None, optional The filename of the XDMF result file. Must include the file extension ``my_result.xdmf``. If None, no result file is written during evaluation. Default is None. mesh : Mesh or None, optional A mesh which is used for the XDMF time series writer. If None, it is taken from the field of the first item of the first step if no keyword argument ``x0`` is given. If None and ``x0=field``, the mesh is taken from the ``x0`` field container. Default is None. point_data : dict or None, optional Additional dict of point-data for the meshio XDMF time series writer. cell_data : dict or None, optional Additional dict of cell-data for the meshio XDMF time series writer. point_data_default : bool, optional Flag to write default point-data to the XDMF result file. This includes ``"Displacement"``. Default is True. cell_data_default : bool, optional Flag to write default cell-data to the XDMF result file. This includes ``"Principal Values of Logarithmic Strain"``, ``"Logarithmic Strain"`` and ``"Deformation Gradient"``. Default is True. verbose : bool or int or None, optional Verbosity level to control how messages are printed during evaluation. If 1 or True and ``tqdm`` is installed, a progress bar is shown. If ``tqdm`` is missing or verbose is 2, more detailed text-based messages are printed. Default is None. If None, verbosity is set to True. If None and the environmental variable FELUPE_VERBOSE is set and its value is not ``true``, then logging is turned off. parallel : bool, optional Flag to use a threaded version of :func:`numpy.einsum` during assembly. Requires ``einsumt``. This may add additional overhead to small-sized problems. Default is False. tqdm : str, optional If verbose is True, choose a backend for ``tqdm`` ("tqdm", ``"auto"`` or ``"notebook"``. Default is ``"tqdm"``. **kwargs : dict Optional keyword arguments for :meth:`~felupe.Step.generate`. If ``parallel=True``, it is added as ``kwargs["parallel"] = True`` to the dict of additional keyword arguments. If ``x0`` is present in ``kwargs.keys()``, it is used as the mesh for the XDMF time series writer. Returns ------- Job The job object. Notes ----- Requires ``meshio`` and ``h5py`` if ``filename`` is not None. Also requires ``tqdm`` for an interactive progress bar if ``verbose=True``. See Also -------- Step : A Step with multiple substeps, subsequently depending on the solution of the previous substep. CharacteristicCurve : A job with a list of steps and a method to evaluate them. Force-displacement curve data is tracked during evaluation for a given :class:`~felupe.Boundary` condition. tools.NewtonResult : A data class which represents the result found by Newton's method. """ # configure plugins if verbose is not False: progress_plugin = ProgressPlugin(verbose=verbose, tqdm=tqdm) self.dispatcher.add_plugin(progress_plugin) if filename is not None: writer_plugin = XDMFWriterPlugin( filename=filename, mesh=mesh, point_data=point_data, cell_data=cell_data, point_data_default=point_data_default, cell_data_default=cell_data_default, kwargs=kwargs, ) self.dispatcher.add_plugin(writer_plugin) context = Context(job=self) state = JobState() self.dispatcher.trigger("before_job", context, state) if parallel: if "kwargs" not in kwargs.keys(): kwargs["kwargs"] = {} kwargs["kwargs"]["parallel"] = True time = 0 for j, step in enumerate(self.steps): context = Context(job=self, step=step) state = JobState(stepnumber=j, time=time) self.dispatcher.trigger("before_step", context, state) substeps = step.generate(dispatcher=self.dispatcher, **kwargs) for i, substep in enumerate(substeps): self.fnorms.append(substep.fnorms) self.callback(j, i, substep, **self.kwargs) # update x0 after each completed substep if "x0" in kwargs.keys(): kwargs["x0"].link(substep.x) context = Context(job=self, step=step, substep=substep) state = JobState(stepnumber=j, substepnumber=i, time=time) self.dispatcher.trigger("after_substep", context, state) self.timetrack.append(time) time += 1 context = Context(job=self, step=step) state = JobState(stepnumber=j, time=time) self.dispatcher.trigger("after_step", context, state) context = Context(job=self) state = JobState() self.dispatcher.trigger("after_job", context, state) return self