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]
@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")