loadpath 0.1.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (220) hide show
  1. loadpath/README.md +294 -0
  2. loadpath/SKILL.md +584 -0
  3. loadpath/__init__.py +17 -0
  4. loadpath/__main__.py +1202 -0
  5. loadpath/am.py +316 -0
  6. loadpath/amgfast.py +326 -0
  7. loadpath/assembly.py +985 -0
  8. loadpath/benchmarks/__init__.py +0 -0
  9. loadpath/benchmarks/beams.py +266 -0
  10. loadpath/benchmarks/cases/ge-bracket.json +380 -0
  11. loadpath/benchmarks/evaluate.py +172 -0
  12. loadpath/benchmarks/mechanisms.py +416 -0
  13. loadpath/benchmarks/problems.py +140 -0
  14. loadpath/benchmarks/reference/bridge-3d.top3d.npz +0 -0
  15. loadpath/benchmarks/reference/cantilever-3d.top3d.npz +0 -0
  16. loadpath/benchmarks/reference/lbracket-2d.top88-ft2.npz +0 -0
  17. loadpath/benchmarks/reference/mbb-2d.top88-ft1.npz +0 -0
  18. loadpath/benchmarks/reference/mbb-2d.top88-ft2.npz +0 -0
  19. loadpath/benchmarks/reference.py +138 -0
  20. loadpath/benchmarks/run.py +301 -0
  21. loadpath/brep.py +1470 -0
  22. loadpath/bucklingopt.py +300 -0
  23. loadpath/buildsim.py +1490 -0
  24. loadpath/cadimport.py +904 -0
  25. loadpath/calibration.py +885 -0
  26. loadpath/cavities.py +211 -0
  27. loadpath/checks/__init__.py +0 -0
  28. loadpath/checks/dfm.py +354 -0
  29. loadpath/checks/exchanger.py +7 -0
  30. loadpath/checks/fea.py +212 -0
  31. loadpath/checks/fit.py +475 -0
  32. loadpath/checks/networks.py +260 -0
  33. loadpath/checks/opening.py +67 -0
  34. loadpath/checks/sdf_kit.py +7 -0
  35. loadpath/conjugate.py +267 -0
  36. loadpath/constrained.py +329 -0
  37. loadpath/contact.py +691 -0
  38. loadpath/coopt.py +342 -0
  39. loadpath/cores.py +163 -0
  40. loadpath/crease.py +1138 -0
  41. loadpath/critic.py +212 -0
  42. loadpath/crosscheck.py +1107 -0
  43. loadpath/cutcell.py +510 -0
  44. loadpath/data/lattice_buckling.json +439 -0
  45. loadpath/data/lattice_tensors.json +27449 -0
  46. loadpath/data/published_experiments.json +71 -0
  47. loadpath/decimate.py +177 -0
  48. loadpath/delivery.py +190 -0
  49. loadpath/directions.py +262 -0
  50. loadpath/domain.py +630 -0
  51. loadpath/drains.py +615 -0
  52. loadpath/durability.py +413 -0
  53. loadpath/editor.html +3135 -0
  54. loadpath/editor.py +610 -0
  55. loadpath/escape.py +354 -0
  56. loadpath/evals/__init__.py +0 -0
  57. loadpath/evals/baselines/coarse.json +1543 -0
  58. loadpath/evals/baselines/full.json +1497 -0
  59. loadpath/evals/brief_kinds/__init__.py +1 -0
  60. loadpath/evals/brief_kinds/heatx.py +387 -0
  61. loadpath/evals/brief_kinds/lattice.py +571 -0
  62. loadpath/evals/brief_kinds/multimat.py +593 -0
  63. loadpath/evals/briefs/assets/bracket.step +1201 -0
  64. loadpath/evals/briefs/assets/desk_arm.urdf +22 -0
  65. loadpath/evals/briefs/assets/elbow-gearbox.stl +0 -0
  66. loadpath/evals/briefs/assets/motor-body.stl +0 -0
  67. loadpath/evals/briefs/assets/sketch.png +0 -0
  68. loadpath/evals/briefs/base-adapter-fdm.json +492 -0
  69. loadpath/evals/briefs/bell-crank-lpbf.json +180 -0
  70. loadpath/evals/briefs/belt-tensioner-fdm.json +151 -0
  71. loadpath/evals/briefs/camera-boom-mjf.json +339 -0
  72. loadpath/evals/briefs/camera-mount-pla.json +203 -0
  73. loadpath/evals/briefs/coolant-isolator-petg.json +100 -0
  74. loadpath/evals/briefs/elbow-bearing-bracket-sls.json +300 -0
  75. loadpath/evals/briefs/elbow-gearbox-forearm-mjf.json +558 -0
  76. loadpath/evals/briefs/elbow-link-fatigue-fdm.json +251 -0
  77. loadpath/evals/briefs/elbow-stop-pad-tpu.json +39 -0
  78. loadpath/evals/briefs/forearm-fdm.json +146 -0
  79. loadpath/evals/briefs/forearm-servo-link-fdm.json +327 -0
  80. loadpath/evals/briefs/grip-pad-finger-mm.json +354 -0
  81. loadpath/evals/briefs/gripper-bracket-creep-fdm.json +340 -0
  82. loadpath/evals/briefs/gripper-finger-fdm.json +155 -0
  83. loadpath/evals/briefs/gripper-jaw-fatigue-mjf.json +328 -0
  84. loadpath/evals/briefs/gripper-palm-fdm.json +715 -0
  85. loadpath/evals/briefs/hot-stepper-mount-asa-fdm.json +471 -0
  86. loadpath/evals/briefs/hpu-oil-cooler-lpbf.json +121 -0
  87. loadpath/evals/briefs/isolated-camera-mount-mm.json +675 -0
  88. loadpath/evals/briefs/kart-charge-cooler-lpbf.json +93 -0
  89. loadpath/evals/briefs/lighten-step-bracket.json +220 -0
  90. loadpath/evals/briefs/nema17-mount-stl.json +429 -0
  91. loadpath/evals/briefs/pillow-block-sls.json +220 -0
  92. loadpath/evals/briefs/polyjet-fingertip-mm.json +305 -0
  93. loadpath/evals/briefs/rod-hook-pla.json +154 -0
  94. loadpath/evals/briefs/sensor-arm-resin.json +150 -0
  95. loadpath/evals/briefs/shelf-bracket-pla.json +158 -0
  96. loadpath/evals/briefs/shoulder-riser-mjf.json +487 -0
  97. loadpath/evals/briefs/sketch-clevis.json +229 -0
  98. loadpath/evals/briefs/spring-bracket-pacf.json +294 -0
  99. loadpath/evals/briefs/tool-flange-ti64.json +280 -0
  100. loadpath/evals/briefs/tray-arm-lattice-fdm.json +260 -0
  101. loadpath/evals/briefs/turret-fdm.json +281 -0
  102. loadpath/evals/briefs/upper-arm-sls.json +179 -0
  103. loadpath/evals/briefs/urdf-forearm.json +233 -0
  104. loadpath/evals/briefs/wrist-link-mjf.json +278 -0
  105. loadpath/evals/briefs/wrist-yoke-mjf.json +245 -0
  106. loadpath/evals/briefs.py +393 -0
  107. loadpath/evals/cases/arm-link-cast.json +157 -0
  108. loadpath/evals/cases/arm-link-driven.json +171 -0
  109. loadpath/evals/cases/arm-link-sandwich.json +315 -0
  110. loadpath/evals/cases/arm-link.json +111 -0
  111. loadpath/evals/cases/bell-crank.json +116 -0
  112. loadpath/evals/cases/grip-turret.json +479 -0
  113. loadpath/evals/cases/grip-upper-arm.json +253 -0
  114. loadpath/evals/cases/grip-wrist-link-mjf.json +929 -0
  115. loadpath/evals/cases/grip-wrist-yoke.json +831 -0
  116. loadpath/evals/cases/lpbf-intercooler-core.json +59 -0
  117. loadpath/evals/cases/mbb-beam.json +61 -0
  118. loadpath/evals/cases/motor-body.stl +0 -0
  119. loadpath/evals/cases/motor-mount.json +265 -0
  120. loadpath/evals/cases/printed-hook.json +77 -0
  121. loadpath/evals/cases/wall-bracket-fasteners.json +125 -0
  122. loadpath/evals/cases/wall-bracket.json +126 -0
  123. loadpath/evals/corpus.py +179 -0
  124. loadpath/evals/pareto.py +90 -0
  125. loadpath/evals/run.py +860 -0
  126. loadpath/examples/arm-link.json +25 -0
  127. loadpath/examples/bumpered-bracket-compression.json +225 -0
  128. loadpath/examples/bumpered-bracket-lattice.json +204 -0
  129. loadpath/examples/bumpered-bracket.json +34 -0
  130. loadpath/examples/gripper-finger-mm.json +185 -0
  131. loadpath/examples/heat-exchanger-counterflow.json +21 -0
  132. loadpath/examples/heat-exchanger-crossflow-tuned.json +48 -0
  133. loadpath/examples/heat-exchanger-crossflow.json +20 -0
  134. loadpath/examples/pedal-lattice.json +23 -0
  135. loadpath/examples/pressure-plenum.json +12 -0
  136. loadpath/examples/shelf-bracket.json +27 -0
  137. loadpath/exchanger.py +831 -0
  138. loadpath/fasteners.py +199 -0
  139. loadpath/fem.py +668 -0
  140. loadpath/femops.py +70 -0
  141. loadpath/fieldjit.py +981 -0
  142. loadpath/fieldops.py +119 -0
  143. loadpath/fields.py +3697 -0
  144. loadpath/fieldtorch.py +464 -0
  145. loadpath/flow.py +984 -0
  146. loadpath/flowtopo.py +300 -0
  147. loadpath/gpu.py +521 -0
  148. loadpath/heatx.py +1067 -0
  149. loadpath/heatx_thermal.py +432 -0
  150. loadpath/homogenized.py +886 -0
  151. loadpath/ibrep.py +552 -0
  152. loadpath/impact.py +693 -0
  153. loadpath/infill.py +376 -0
  154. loadpath/interface_library.py +340 -0
  155. loadpath/interlock.py +186 -0
  156. loadpath/isolator.py +149 -0
  157. loadpath/knn.py +204 -0
  158. loadpath/lattice.py +1065 -0
  159. loadpath/lattice3mf.py +760 -0
  160. loadpath/lattice_buckling.py +245 -0
  161. loadpath/lattice_grade.py +325 -0
  162. loadpath/lattice_orient.py +595 -0
  163. loadpath/lattice_print.py +159 -0
  164. loadpath/lattice_tensors.py +558 -0
  165. loadpath/latticestep.py +1210 -0
  166. loadpath/manufacture.py +446 -0
  167. loadpath/material_library.py +489 -0
  168. loadpath/materials.py +144 -0
  169. loadpath/mcp_server.py +786 -0
  170. loadpath/mechanism.py +218 -0
  171. loadpath/mechanism_nl.py +811 -0
  172. loadpath/meshops.py +452 -0
  173. loadpath/mg.py +853 -0
  174. loadpath/mma.py +214 -0
  175. loadpath/modal.py +210 -0
  176. loadpath/multimat.py +1788 -0
  177. loadpath/narrowband.py +418 -0
  178. loadpath/nlkernel.py +241 -0
  179. loadpath/nonlinear.py +1095 -0
  180. loadpath/orient.py +334 -0
  181. loadpath/porous.py +994 -0
  182. loadpath/pressure.py +171 -0
  183. loadpath/preview.py +335 -0
  184. loadpath/printcheck.py +263 -0
  185. loadpath/printsetup.py +207 -0
  186. loadpath/processcheck.py +376 -0
  187. loadpath/quick.py +113 -0
  188. loadpath/recall.py +406 -0
  189. loadpath/reconstruct.py +797 -0
  190. loadpath/render.py +436 -0
  191. loadpath/resolved.py +189 -0
  192. loadpath/schema.py +1701 -0
  193. loadpath/sdf_kit.py +843 -0
  194. loadpath/selfx.py +292 -0
  195. loadpath/shapes.py +584 -0
  196. loadpath/sharp.py +717 -0
  197. loadpath/simp.py +1170 -0
  198. loadpath/sizing.py +312 -0
  199. loadpath/slicer.py +321 -0
  200. loadpath/spec.py +1072 -0
  201. loadpath/step.py +806 -0
  202. loadpath/struts.py +639 -0
  203. loadpath/study.py +1937 -0
  204. loadpath/tasks.py +822 -0
  205. loadpath/thermal.py +1691 -0
  206. loadpath/threemf.py +487 -0
  207. loadpath/tune.py +437 -0
  208. loadpath/validation.py +145 -0
  209. loadpath/verify.py +1215 -0
  210. loadpath/viewer.html +694 -0
  211. loadpath/viewer.py +446 -0
  212. loadpath/viscoelastic.py +106 -0
  213. loadpath/voxelprint.py +582 -0
  214. loadpath/voxels.py +402 -0
  215. loadpath-0.1.1.dist-info/METADATA +319 -0
  216. loadpath-0.1.1.dist-info/RECORD +220 -0
  217. loadpath-0.1.1.dist-info/WHEEL +5 -0
  218. loadpath-0.1.1.dist-info/entry_points.txt +2 -0
  219. loadpath-0.1.1.dist-info/licenses/LICENSE +21 -0
  220. loadpath-0.1.1.dist-info/top_level.txt +1 -0
loadpath/mechanism.py ADDED
@@ -0,0 +1,218 @@
1
+ """
2
+ Compliant mechanisms: parts that are meant to bend.
3
+
4
+ Everything else in loadpath makes a part as stiff as possible for its mass.
5
+ A gripper finger, a flexure hinge, a snap fit or a clip needs the opposite:
6
+ a push at one place (the input) should move another place (the output) as
7
+ far as possible in a chosen direction, against something that pushes back
8
+ (the workpiece). That is the classic compliant-mechanism problem (Sigmund
9
+ 1997; Bendsøe & Sigmund, "Topology Optimization", ch. 2.6):
10
+
11
+ maximize u_out = l . u
12
+ subject to (K(x) + springs) u = f_in, sum(x) <= V
13
+
14
+ with a spring k_in at the input (the actuator is not infinitely stiff) and
15
+ k_out at the output (the object being gripped). Without the springs the
16
+ optimum is a mechanism of one-node hinges with no strength at all; the
17
+ output spring is what makes the result carry a grip force.
18
+
19
+ The sensitivity needs one adjoint solve, K lambda = l, and is
20
+ lambda_e . k_e u_e scaled by the SIMP derivative: unlike compliance, it can
21
+ take either sign. Sigmund's 104-line code uses damped optimality criteria
22
+ with the sensitivities clipped positive; here it is MMA (mma.py), which
23
+ takes the gradient whole.
24
+
25
+ The density filter, Heaviside projection, extrusion (2.5D) and
26
+ reconstruction are the same as for stiffness designs, so the result comes
27
+ back as a smooth, printable part. The optimization is linear: a TPU finger
28
+ that curls 60 degrees is well outside small deflections, so treat the output
29
+ as the layout. `verify_nonlinear` re-solves the solid cells of the result
30
+ with large deflections and a buckling check (nonlinear.verify_mechanism):
31
+ how far the output really travels, and whether the input force buckles a
32
+ thin member first.
33
+ """
34
+ from __future__ import annotations
35
+
36
+ import time
37
+ from dataclasses import dataclass, field
38
+
39
+ import numpy as np
40
+ import scipy.sparse as sp
41
+
42
+ from .domain import Domain
43
+ from .fem import Solver, Stiffness
44
+ from .simp import E_MIN, PENALTY, _dproject, _extrude, _project, density_filter
45
+
46
+ __all__ = ["MechanismOptions", "MechanismResult", "optimize_mechanism"]
47
+
48
+
49
+ @dataclass
50
+ class MechanismOptions:
51
+ volume_fraction: float
52
+ filter_radius: float
53
+ input_case: int = 0 # domain load case that is the actuator force
54
+ output_case: int = 1 # domain load case whose force direction is the output (any magnitude)
55
+ # Several (input, output) pairs at once, e.g. contact anywhere along a
56
+ # finger: the objective is the sum of the pairs' output displacements.
57
+ pairs: list | None = None
58
+ k_in: float = 0.0 # N/mm, spread over the input's loaded dofs
59
+ k_out: float = 0.0 # N/mm, spread over the output's dofs
60
+ modulus: float = 1.0 # MPa: the material's E (springs are in real units)
61
+ max_iterations: int = 120
62
+ beta_max: float = 16.0
63
+ beta_every: int = 20
64
+ move: float = 0.1
65
+ extrusion: int | None = None
66
+ tol: float = 0.005
67
+ verify_nonlinear: bool = False # large-deflection + buckling check of the result (first pair)
68
+ # Robust formulation (Wang, Lazarov & Sigmund 2011): also project the
69
+ # filtered field at 0.5 + robust (eroded) and 0.5 - robust (dilated) and
70
+ # maximize the worst of the three outputs. A one-node hinge disconnects
71
+ # in the eroded design, so the optimum keeps hinges at least about a
72
+ # filter radius wide: printable flexures instead of corner contacts.
73
+ robust: float | None = None
74
+
75
+
76
+ @dataclass
77
+ class MechanismResult:
78
+ x: np.ndarray
79
+ xphys: np.ndarray
80
+ output_displacement: float # mm along the output direction, under the input force
81
+ iterations: int
82
+ seconds: float
83
+ history: list = field(default_factory=list)
84
+ nonlinear: dict | None = None # nonlinear.verify_mechanism's report, with verify_nonlinear
85
+
86
+
87
+ def _spring_diag(f, k, n_dof):
88
+ """A grounded spring of k N/mm in all, shared evenly by the nodes the
89
+ vector f loads, on the dofs it loads (so an x push gets an x spring of
90
+ k, whatever the number of nodes)."""
91
+ dofs = np.nonzero(np.abs(f) > 0)[0]
92
+ d = np.zeros(n_dof)
93
+ if len(dofs) and k > 0:
94
+ d[dofs] = k / len(np.unique(dofs // 3))
95
+ return d
96
+
97
+
98
+ def optimize_mechanism(domain: Domain, nu: float, opts: MechanismOptions, on_iter=None) -> MechanismResult:
99
+ t0 = time.time()
100
+ mesh = domain.mesh
101
+ n = mesh.n_elem
102
+ pres = domain.preserve
103
+ design = ~pres
104
+ pairs = opts.pairs or [(opts.input_case, opts.output_case)]
105
+ ins = sorted({i for i, _ in pairs})
106
+ outs = sorted({o for _, o in pairs})
107
+ # l . u = the output region's mean displacement along the output direction
108
+ ls = {o: domain.loads[o] / max(np.linalg.norm(domain.loads[o].reshape(-1, 3).sum(axis=0)), 1e-30) for o in outs}
109
+ sd = sum(_spring_diag(domain.loads[i], opts.k_in, mesh.n_dof) for i in ins) + \
110
+ sum(_spring_diag(domain.loads[o], opts.k_out, mesh.n_dof) for o in outs)
111
+ sd[domain.fixed] = 0.0
112
+ springs = sp.diags(sd).tocsr()
113
+
114
+ stiff = Stiffness(mesh, nu, domain.fixed)
115
+ solver = Solver(mesh, rtol=1e-5)
116
+ columns = None
117
+ if opts.extrusion is not None:
118
+ a = opts.extrusion
119
+ others = [i for i in range(3) if i != a]
120
+ ij = mesh.elem_ijk[:, others]
121
+ _, columns = np.unique(ij[:, 0] * (domain.dims[others[1]] + 1) + ij[:, 1], return_inverse=True)
122
+ h, hs = density_filter(domain, opts.filter_radius, pad=opts.extrusion is None)
123
+ ht = h.T.tocsr()
124
+ from .fem import hex8_ke
125
+ ke = hex8_ke(nu) * mesh.pitch # as Stiffness assembles it
126
+ edof = mesh.edof
127
+
128
+ x = np.full(n, opts.volume_fraction)
129
+ x[pres] = 1.0
130
+ target = opts.volume_fraction * design.sum()
131
+ beta, since = 1.0, 0
132
+ prev = {}
133
+ u0 = None
134
+ etas = [0.5] if not opts.robust else [0.5 + opts.robust, 0.5, 0.5 - opts.robust]
135
+ from .mma import MMA
136
+ mma = MMA(int(design.sum()), 1, xmin=0.0, xmax=1.0, move=opts.move)
137
+ history = []
138
+ it = 0
139
+ for it in range(1, opts.max_iterations + 1):
140
+ xt = _extrude((h @ x) / hs, columns, design)
141
+ dE_scale = opts.modulus * PENALTY * (1 - E_MIN)
142
+ real = [] # per realization: (raw outputs, d sum / d xt)
143
+ for eta in etas:
144
+ xp = _project(xt, beta, eta)
145
+ xp[pres] = 1.0
146
+ e = opts.modulus * (E_MIN + xp ** PENALTY * (1 - E_MIN))
147
+ k = (stiff.assemble(e) + springs).tocsr()
148
+ sol = solver.solve_many(k, [domain.loads[i] for i in ins] + [ls[o] for o in outs], prev.get(eta))
149
+ prev[eta] = sol
150
+ U = dict(zip(ins, sol[:len(ins)]))
151
+ LAM = dict(zip(outs, sol[len(ins):]))
152
+ raw = [float(ls[o] @ U[i]) for i, o in pairs]
153
+ # d(u_out)/d(xp_e) = -lambda_e . k_e u_e * dE/dxp (K lambda = l, K symmetric)
154
+ g = np.zeros(n)
155
+ for i, o in pairs:
156
+ g -= np.einsum("ij,jk,ik->i", LAM[o][edof], ke, U[i][edof])
157
+ g = g * dE_scale * xp ** (PENALTY - 1) * _dproject(xt, beta, eta)
158
+ real.append((raw, g))
159
+ raw = real[len(etas) // 2][0] # the blueprint (eta 0.5) is what is delivered
160
+ # Sum the outputs in mm, with one overall scale for MMA. (Scaling each
161
+ # pair by its own starting value let a pair that started near zero
162
+ # dominate; the fin-ray finger traded one contact's wrap for another's.)
163
+ if u0 is None:
164
+ u0 = max(abs(sum(raw)), max(abs(r) for r in raw), 1e-12)
165
+ vals = np.array([sum(r) / u0 for r, _ in real])
166
+ if len(etas) == 1:
167
+ uout, g = vals[0], real[0][1] / u0
168
+ else:
169
+ # smooth minimum (KS) of the realizations' outputs
170
+ q = 30.0
171
+ w = np.exp(-q * (vals - vals.min()))
172
+ uout = float(vals.min() - np.log(w.sum()) / q)
173
+ w /= w.sum()
174
+ g = sum(wk * gk for wk, (_, gk) in zip(w, real)) / u0
175
+ g = _extrude(g, columns, design)
176
+ g = ht @ (g / hs)
177
+ dv = ht @ (_extrude(_dproject(xt, beta, 0.5), columns, design) / hs)
178
+ # MMA on (-u_out, volume): the output sensitivity takes both signs,
179
+ # which optimality criteria can only handle by clipping (the first
180
+ # version did, and stalled on the fin-ray problem with half its
181
+ # gradient thrown away)
182
+ xp = _project(xt, beta, 0.5)
183
+ xp[pres] = 1.0
184
+ vol = float(xp[design].sum())
185
+ xn = x.copy()
186
+ xn[design] = mma.update(x[design], -uout * 10.0, (-g * 10.0)[design],
187
+ np.array([vol / target - 1.0]), np.array([(dv / target)[design]]))
188
+ change = float(np.abs(xn - x).max())
189
+ x = xn
190
+ rec = {"iteration": it, "outputDisplacement": raw[0], "objective": uout, "outputs": raw, "beta": beta, "change": change,
191
+ "volume": float(xp[design].mean())}
192
+ if len(etas) > 1:
193
+ rec["robustOutputs"] = [float(v * u0) for v in vals] # eroded, blueprint, dilated
194
+ history.append(rec)
195
+ if on_iter is not None:
196
+ on_iter(rec, xp)
197
+ since += 1
198
+ if beta < opts.beta_max and (since >= opts.beta_every or change < opts.tol * 2):
199
+ beta, since = min(beta * 2, opts.beta_max), 0
200
+ elif beta >= opts.beta_max:
201
+ if change < opts.tol:
202
+ break
203
+ # mechanisms chatter at the move limit on a few hinge cells while
204
+ # the output has stopped moving: stop on the output instead
205
+ if since >= 10 and len(history) > 10:
206
+ old = history[-11]["objective"]
207
+ if abs(uout - old) <= 2e-3 * abs(old):
208
+ break
209
+ xt = _extrude((h @ x) / hs, columns, design)
210
+ xp = _project(xt, beta, 0.5)
211
+ xp[pres] = 1.0
212
+ nonlinear = None
213
+ if opts.verify_nonlinear:
214
+ from .nonlinear import verify_mechanism
215
+ nonlinear = verify_mechanism(domain, xp, opts.modulus, nu, input_case=pairs[0][0], output_case=pairs[0][1],
216
+ k_in=opts.k_in, k_out=opts.k_out)
217
+ return MechanismResult(x=x, xphys=xp, output_displacement=float(history[-1]["outputDisplacement"]),
218
+ iterations=it, seconds=time.time() - t0, history=history, nonlinear=nonlinear)