Source code for fenicsxconcrete.sensor_definition.stress_sensor

from __future__ import annotations

import os
from typing import TYPE_CHECKING

import dolfinx as df
import numpy as np

if TYPE_CHECKING:
    from fenicsxconcrete.finite_element_problem.base_material import MaterialProblem

from fenicsxconcrete.sensor_definition.base_sensor import PointSensor
from fenicsxconcrete.util import project, ureg


[docs] class StressSensor(PointSensor): """A sensor that measures stress at a specific point Attributes: data: list of measured values time: list of time stamps units : pint definition of the base unit a sensor returns name : name of the sensor, default is class name, but can be changed where: location where the value is measured """
[docs] def measure(self, problem: MaterialProblem) -> None: """ The stress value at the defined point is added to the data list, as well as the time t to the time list Arguments: problem : FEM problem object t : time of measurement for time dependent problems, default is 1 """ # project stress onto visualization space stress = problem.q_fields.stress mandel_stress = problem.q_fields.mandel_stress if stress is not None: stress_tensor_dim = problem.experiment.mesh.topology.dim stress_function = project( stress, # stress fct from problem df.fem.functionspace( problem.experiment.mesh, ( problem.q_fields.plot_space_type[0], problem.q_fields.plot_space_type[1], (stress_tensor_dim, stress_tensor_dim), ), ), # tensor space problem.q_fields.measure, ) elif mandel_stress is not None: stress_function = project( mandel_stress, # stress fct from problem df.fem.functionspace( problem.experiment.mesh, ( problem.q_fields.plot_space_type[0], problem.q_fields.plot_space_type[1], (problem.mandel_stress_dim,), ), ), problem.q_fields.measure, ) else: raise Exception("Stress and Mandel stress not defined in problem") # finding the cells corresponding to the point bb_tree = df.geometry.bb_tree(problem.experiment.mesh, problem.experiment.mesh.topology.dim) cells = [] # Find cells whose bounding-box collide with the points point = np.array(self.where, dtype=np.float64) cell_candidates = df.geometry.compute_collisions_points(bb_tree, point) # Choose one of the cells that contains the point colliding_cells = df.geometry.compute_colliding_cells(problem.experiment.mesh, cell_candidates, point) if len(colliding_cells.links(0)) > 0: cells.append(colliding_cells.links(0)[0]) else: raise ValueError(f"cells with point {self.where} not found in mesh") # adding correct units to stress stress_data = stress_function.eval([self.where], cells) self.data.append(stress_data) self.time.append(problem.time)
[docs] def report_metadata(self) -> dict: """Generates dictionary with the metadata of this sensor""" metadata = super().report_metadata() metadata["sensor_file"] = os.path.splitext(os.path.basename(__file__))[0] return metadata
[docs] @staticmethod def base_unit() -> ureg: """Defines the base unit of this sensor Returns: the base unit as pint unit object """ return ureg("N/m^2")