Calculates the design field and the magnitude of its gradient for lengthscale indicators [1]. Parameters ---------- x : array_like Design parameters filter_f : function_handle Filter function. Must be differntiable by autograd. threshold_f : function_handle
(x, filter_f, threshold_f, resolution, periodic_axes=None)
| 986 | |
| 987 | |
| 988 | def length_indicator(x, filter_f, threshold_f, resolution, periodic_axes=None): |
| 989 | """Calculates the design field and the magnitude of its gradient for lengthscale indicators [1]. |
| 990 | |
| 991 | Parameters |
| 992 | ---------- |
| 993 | x : array_like |
| 994 | Design parameters |
| 995 | filter_f : function_handle |
| 996 | Filter function. Must be differntiable by autograd. |
| 997 | threshold_f : function_handle |
| 998 | Threshold function. Must be differntiable by autograd. |
| 999 | periodic_axes: array_like (1D) |
| 1000 | List of axes (x, y = 0, 1) that are to be treated as periodic (default is none: all axes are non-periodic) |
| 1001 | |
| 1002 | Returns |
| 1003 | ------- |
| 1004 | A two-element tuple composed of the design field and the magnitude of its gradient |
| 1005 | |
| 1006 | References |
| 1007 | ---------- |
| 1008 | [1] Zhou, M., Lazarov, B. S., Wang, F., & Sigmund, O. (2015). Minimum length scale in topology optimization by |
| 1009 | geometric constraints. Computer Methods in Applied Mechanics and Engineering, 293, 266-282. |
| 1010 | """ |
| 1011 | |
| 1012 | filtered_field = npa.squeeze(filter_f(x)) |
| 1013 | design_field = threshold_f(filtered_field) |
| 1014 | design_dim = filtered_field.ndim |
| 1015 | resolution = _get_resolution(resolution) |
| 1016 | |
| 1017 | if periodic_axes is None: |
| 1018 | gradient_filtered_field = npa.gradient(filtered_field) |
| 1019 | else: |
| 1020 | periodic_axes = np.array(periodic_axes) |
| 1021 | if 0 in periodic_axes: |
| 1022 | if design_dim == 2: |
| 1023 | filtered_field = npa.tile(filtered_field, (3, 1)) |
| 1024 | if design_dim == 1 and resolution[0] > resolution[1]: |
| 1025 | filtered_field = npa.tile(filtered_field, 3) |
| 1026 | |
| 1027 | if 1 in periodic_axes: |
| 1028 | if design_dim == 2: |
| 1029 | filtered_field = npa.tile(filtered_field, (1, 3)) |
| 1030 | if design_dim == 1 and resolution[0] < resolution[1]: |
| 1031 | filtered_field = npa.tile(filtered_field, 3) |
| 1032 | |
| 1033 | if design_dim == 2: |
| 1034 | gradient_filtered_field = _centered( |
| 1035 | npa.array(npa.gradient(filtered_field)), (2,) + x.shape |
| 1036 | ) |
| 1037 | elif design_dim == 1: |
| 1038 | gradient_filtered_field = _centered( |
| 1039 | npa.array(npa.gradient(filtered_field)), design_field.shape |
| 1040 | ) |
| 1041 | else: |
| 1042 | raise ValueError( |
| 1043 | "The design fields must be 1d or 2d. Check input array and filter functions." |
| 1044 | ) |
| 1045 |
no test coverage detected