afem/environment/fem_util.py

55 lines
2.0 KiB
Python

import numpy as np
from skfem import Mesh
def get_element_midpoints(mesh: Mesh, transpose: bool = True) -> np.ndarray:
midpoints = np.mean(mesh.p[:, mesh.t], axis=1)
return midpoints.T if transpose else midpoints
# 算三个顶点的mean/std/...
def get_aggregation_per_element(
solution: np.ndarray,
element_indices: np.ndarray,
aggregation_function_str: str = "mean",
) -> np.ndarray:
vals = solution[element_indices]
if aggregation_function_str == "mean":
return vals.mean(axis=1)
elif aggregation_function_str == "std":
return vals.std(axis=1)
elif aggregation_function_str == "min":
return vals.min(axis=1)
elif aggregation_function_str == "max":
return vals.max(axis=1)
elif aggregation_function_str == "median":
return np.median(vals, axis=1)
raise ValueError(f"Unknown aggregation function: {aggregation_function_str}")
# 计算三角形面积
def get_triangle_areas_from_indices(
positions: np.ndarray, triangle_indices: np.ndarray
) -> np.ndarray:
i0, i1, i2 = triangle_indices[:, 0], triangle_indices[:, 1], triangle_indices[:, 2]
return np.abs(0.5 * (
(positions[i1, 0] - positions[i0, 0]) * (positions[i2, 1] - positions[i0, 1])
- (positions[i2, 0] - positions[i0, 0]) * (positions[i1, 1] - positions[i0, 1])
))
# penalty:\alpha的采样方式
def sample_in_range(max_value: float, min_value: float, sampling_type: str) -> float:
if sampling_type == "uniform":
return np.random.uniform(min_value, max_value)
elif sampling_type == "loguniform":
return np.exp(np.random.uniform(np.log(min_value), np.log(max_value)))
raise ValueError(f"Unknown sampling type: {sampling_type}")
def construct_sizing_field_1d(x: np.ndarray, eps: float = 1e-4) -> np.ndarray:
"""Softplus 激活 → 目标网格面积 (numpy 版)。"""
def _softplus(x):
return np.log1p(np.exp(np.clip(x, -50, 50)))
x = np.atleast_1d(np.asarray(x, dtype=np.float64))
return _softplus(x) + eps