morphopt 4.0.0__tar.gz → 4.0.2__tar.gz

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 (241) hide show
  1. {morphopt-4.0.0 → morphopt-4.0.2}/PKG-INFO +22 -13
  2. {morphopt-4.0.0 → morphopt-4.0.2}/README.md +21 -12
  3. {morphopt-4.0.0 → morphopt-4.0.2}/pyproject.toml +9 -2
  4. {morphopt-4.0.0 → morphopt-4.0.2}/src/morphopt/__init__.py +55 -7
  5. morphopt-4.0.2/src/morphopt/codesign/__init__.py +16 -0
  6. {morphopt-4.0.0 → morphopt-4.0.2}/src/morphopt/codesign/constraints.py +48 -30
  7. morphopt-4.0.0/src/morphopt/codesign/geometry.py → morphopt-4.0.2/src/morphopt/codesign/offset_boundary_part.py +32 -34
  8. morphopt-4.0.2/src/morphopt/codesign/update_offset_boundary_part.py +29 -0
  9. morphopt-4.0.2/src/morphopt/constants.py +1188 -0
  10. {morphopt-4.0.0 → morphopt-4.0.2}/src/morphopt/optcore/__init__.py +5 -5
  11. {morphopt-4.0.0 → morphopt-4.0.2}/src/morphopt/optcore/controller.py +15 -9
  12. morphopt-4.0.2/src/morphopt/optcore/modelparams/__init__.py +27 -0
  13. morphopt-4.0.2/src/morphopt/optcore/modelparams/base_model_component.py +16 -0
  14. morphopt-4.0.2/src/morphopt/optcore/modelparams/fea/__init__.py +10 -0
  15. morphopt-4.0.0/src/morphopt/optcore/modelparams/feainterface/basefeainterface.py → morphopt-4.0.2/src/morphopt/optcore/modelparams/fea/base_component.py +7 -15
  16. morphopt-4.0.0/src/morphopt/optcore/modelparams/feainterface/bodyforceinterface.py → morphopt-4.0.2/src/morphopt/optcore/modelparams/fea/body_force.py +6 -6
  17. morphopt-4.0.0/src/morphopt/optcore/modelparams/feainterface/boundaryconditioninterface.py → morphopt-4.0.2/src/morphopt/optcore/modelparams/fea/boundary_condition.py +24 -7
  18. morphopt-4.0.0/src/morphopt/optcore/modelparams/feainterface/contactinterface.py → morphopt-4.0.2/src/morphopt/optcore/modelparams/fea/contact.py +30 -26
  19. morphopt-4.0.0/src/morphopt/optcore/modelparams/feainterface/coupleinterface.py → morphopt-4.0.2/src/morphopt/optcore/modelparams/fea/couple.py +8 -4
  20. morphopt-4.0.0/src/morphopt/optcore/modelparams/feainterface/pointinterface.py → morphopt-4.0.2/src/morphopt/optcore/modelparams/fea/point_load.py +3 -3
  21. morphopt-4.0.0/src/morphopt/optcore/modelparams/feainterface/pressureinterface.py → morphopt-4.0.2/src/morphopt/optcore/modelparams/fea/pressure.py +10 -6
  22. morphopt-4.0.0/src/morphopt/optcore/modelparams/feainterface/referencepointinterface.py → morphopt-4.0.2/src/morphopt/optcore/modelparams/fea/reference_point.py +4 -4
  23. morphopt-4.0.0/src/morphopt/optcore/modelparams/feainterface/springinterface.py → morphopt-4.0.2/src/morphopt/optcore/modelparams/fea/spring.py +4 -4
  24. {morphopt-4.0.0 → morphopt-4.0.2}/src/morphopt/optcore/modelparams/feaparams.py +18 -15
  25. {morphopt-4.0.0 → morphopt-4.0.2}/src/morphopt/optcore/modelparams/geometry.py +7 -6
  26. morphopt-4.0.2/src/morphopt/optcore/modelparams/materials/__init__.py +11 -0
  27. morphopt-4.0.0/src/morphopt/optcore/modelparams/materialinterface/basematerialinterface.py → morphopt-4.0.2/src/morphopt/optcore/modelparams/materials/base_material.py +13 -12
  28. morphopt-4.0.0/src/morphopt/optcore/modelparams/materialinterface/homogeneousmaterial.py → morphopt-4.0.2/src/morphopt/optcore/modelparams/materials/homogeneous_material.py +3 -3
  29. morphopt-4.0.0/src/morphopt/optcore/modelparams/materials.py → morphopt-4.0.2/src/morphopt/optcore/modelparams/materialsparams.py +2 -2
  30. {morphopt-4.0.0 → morphopt-4.0.2}/src/morphopt/optcore/modelparams/params.py +9 -4
  31. morphopt-4.0.2/src/morphopt/optcore/modelparams/parts/__init__.py +13 -0
  32. morphopt-4.0.0/src/morphopt/optcore/modelparams/partinterface/basepartinterface.py → morphopt-4.0.2/src/morphopt/optcore/modelparams/parts/base_part.py +13 -6
  33. morphopt-4.0.2/src/morphopt/optcore/modelparams/parts/box_part.py +146 -0
  34. morphopt-4.0.2/src/morphopt/optcore/modelparams/parts/cad_part.py +128 -0
  35. morphopt-4.0.0/src/morphopt/optcore/modelparams/partinterface/inppartinterface.py → morphopt-4.0.2/src/morphopt/optcore/modelparams/parts/inp_part.py +3 -3
  36. {morphopt-4.0.0 → morphopt-4.0.2}/src/morphopt/optcore/objfunc.py +15 -9
  37. {morphopt-4.0.0 → morphopt-4.0.2}/src/morphopt/optcore/protocal.py +9 -1
  38. morphopt-4.0.2/src/morphopt/optcore/quadrature.py +78 -0
  39. {morphopt-4.0.0 → morphopt-4.0.2}/src/morphopt/optcore/solver.py +45 -45
  40. {morphopt-4.0.0 → morphopt-4.0.2}/src/morphopt/optcore/updaters.py +12 -10
  41. morphopt-4.0.2/src/morphopt/postprocess/__init__.py +9 -0
  42. morphopt-4.0.2/src/morphopt/postprocess/exporters.py +117 -0
  43. morphopt-4.0.2/src/morphopt/postprocess/fields.py +329 -0
  44. morphopt-4.0.2/src/morphopt/postprocess/native.py +81 -0
  45. morphopt-4.0.2/src/morphopt/shapeopt/__init__.py +25 -0
  46. morphopt-4.0.0/src/morphopt/shapeopt/boundarypartinterface.py → morphopt-4.0.2/src/morphopt/shapeopt/boundary_part.py +69 -39
  47. {morphopt-4.0.0 → morphopt-4.0.2}/src/morphopt/shapeopt/meshgenerator.py +7 -4
  48. {morphopt-4.0.0 → morphopt-4.0.2}/src/morphopt/shapeopt/objectivefuncs/boundarys.py +17 -9
  49. {morphopt-4.0.0 → morphopt-4.0.2}/src/morphopt/shapeopt/objectivefuncs/distancesurface.py +27 -10
  50. {morphopt-4.0.0 → morphopt-4.0.2}/src/morphopt/shapeopt/objectivefuncs/shapederivative.py +3 -3
  51. {morphopt-4.0.0 → morphopt-4.0.2}/src/morphopt/shapeopt/objectivefuncs/surfacefairness.py +4 -4
  52. {morphopt-4.0.0 → morphopt-4.0.2}/src/morphopt/shapeopt/objectivefuncs/volumemaximization.py +10 -7
  53. morphopt-4.0.2/src/morphopt/shapeopt/surfaces/__init__.py +28 -0
  54. morphopt-4.0.2/src/morphopt/shapeopt/surfaces/base_constraints.py +116 -0
  55. morphopt-4.0.0/src/morphopt/shapeopt/surfaceinterfaces/basesurfaceinterface.py → morphopt-4.0.2/src/morphopt/shapeopt/surfaces/base_surface.py +69 -32
  56. morphopt-4.0.2/src/morphopt/shapeopt/surfaces/bsp_constraints.py +91 -0
  57. morphopt-4.0.0/src/morphopt/shapeopt/surfaceinterfaces/bspsurfaceinterface.py → morphopt-4.0.2/src/morphopt/shapeopt/surfaces/bsp_surface.py +116 -46
  58. morphopt-4.0.2/src/morphopt/shapeopt/surfaces/cpgeo_constraints.py +211 -0
  59. morphopt-4.0.0/src/morphopt/shapeopt/surfaceinterfaces/cpgeosurfaceinterface.py → morphopt-4.0.2/src/morphopt/shapeopt/surfaces/cpgeo_surface.py +74 -42
  60. morphopt-4.0.0/src/morphopt/shapeopt/update_boundarypart.py → morphopt-4.0.2/src/morphopt/shapeopt/update_boundary_part.py +25 -17
  61. {morphopt-4.0.0 → morphopt-4.0.2}/src/morphopt/simp/objectivefuncs/boundarys.py +17 -12
  62. {morphopt-4.0.0 → morphopt-4.0.2}/src/morphopt/simp/objectivefuncs/densityfield.py +5 -1
  63. {morphopt-4.0.0 → morphopt-4.0.2}/src/morphopt/simp/simpmaterial.py +29 -14
  64. {morphopt-4.0.0 → morphopt-4.0.2}/src/morphopt/simp/update_simpmaterial.py +18 -11
  65. {morphopt-4.0.0 → morphopt-4.0.2}/src/morphopt/ui/__init__.py +10 -6
  66. morphopt-4.0.2/src/morphopt/ui/app.py +59 -0
  67. {morphopt-4.0.0 → morphopt-4.0.2}/src/morphopt/ui/application/__init__.py +12 -2
  68. morphopt-4.0.2/src/morphopt/ui/application/cad.py +96 -0
  69. morphopt-4.0.0/src/morphopt/ui/widgets/code_completion.py → morphopt-4.0.2/src/morphopt/ui/application/completion.py +12 -18
  70. morphopt-4.0.2/src/morphopt/ui/application/definitions.py +215 -0
  71. morphopt-4.0.2/src/morphopt/ui/application/devices.py +14 -0
  72. morphopt-4.0.2/src/morphopt/ui/application/edit_history.py +202 -0
  73. morphopt-4.0.2/src/morphopt/ui/application/editing.py +404 -0
  74. morphopt-4.0.2/src/morphopt/ui/application/editor_routing.py +116 -0
  75. morphopt-4.0.2/src/morphopt/ui/application/expressions.py +43 -0
  76. morphopt-4.0.2/src/morphopt/ui/application/fields.py +113 -0
  77. morphopt-4.0.2/src/morphopt/ui/application/finite_element.py +216 -0
  78. morphopt-4.0.2/src/morphopt/ui/application/part_sets.py +101 -0
  79. morphopt-4.0.2/src/morphopt/ui/application/quickstart.py +741 -0
  80. morphopt-4.0.2/src/morphopt/ui/application/result_fields.py +94 -0
  81. {morphopt-4.0.0 → morphopt-4.0.2}/src/morphopt/ui/application/results.py +44 -2
  82. morphopt-4.0.2/src/morphopt/ui/application/runs.py +289 -0
  83. morphopt-4.0.2/src/morphopt/ui/application/updaters.py +187 -0
  84. {morphopt-4.0.0/src/morphopt/ui/widgets → morphopt-4.0.2/src/morphopt/ui/application}/values.py +35 -38
  85. morphopt-4.0.2/src/morphopt/ui/application_icon.py +49 -0
  86. morphopt-4.0.2/src/morphopt/ui/assets/morphopt.svg +48 -0
  87. morphopt-4.0.2/src/morphopt/ui/codegen/assets.py +88 -0
  88. morphopt-4.0.2/src/morphopt/ui/codegen/custom_classes.py +450 -0
  89. morphopt-4.0.2/src/morphopt/ui/codegen/generator.py +1317 -0
  90. morphopt-4.0.2/src/morphopt/ui/fea_worker.py +67 -0
  91. morphopt-4.0.2/src/morphopt/ui/i18n.py +134 -0
  92. {morphopt-4.0.0 → morphopt-4.0.2}/src/morphopt/ui/launcher.py +28 -43
  93. morphopt-4.0.2/src/morphopt/ui/locales/en-US.json +1181 -0
  94. morphopt-4.0.2/src/morphopt/ui/locales/zh-CN.json +1181 -0
  95. morphopt-4.0.2/src/morphopt/ui/mainwindow.py +681 -0
  96. morphopt-4.0.2/src/morphopt/ui/model/__init__.py +38 -0
  97. morphopt-4.0.2/src/morphopt/ui/model/base_nodes.py +691 -0
  98. morphopt-4.0.2/src/morphopt/ui/model/chamberlayout.py +164 -0
  99. morphopt-4.0.2/src/morphopt/ui/model/configuration.py +101 -0
  100. morphopt-4.0.2/src/morphopt/ui/model/fields.py +38 -0
  101. {morphopt-4.0.0 → morphopt-4.0.2}/src/morphopt/ui/model/loaders.py +3 -4
  102. morphopt-4.0.2/src/morphopt/ui/model/material_models.py +15 -0
  103. morphopt-4.0.2/src/morphopt/ui/model/node_types/__init__.py +168 -0
  104. morphopt-4.0.2/src/morphopt/ui/model/node_types/cad.py +665 -0
  105. morphopt-4.0.2/src/morphopt/ui/model/node_types/custom_code.py +116 -0
  106. morphopt-4.0.2/src/morphopt/ui/model/node_types/loads.py +426 -0
  107. morphopt-4.0.2/src/morphopt/ui/model/node_types/materials.py +347 -0
  108. morphopt-4.0.2/src/morphopt/ui/model/node_types/objectives.py +68 -0
  109. morphopt-4.0.2/src/morphopt/ui/model/node_types/parts.py +351 -0
  110. morphopt-4.0.2/src/morphopt/ui/model/node_types/penalties.py +321 -0
  111. morphopt-4.0.2/src/morphopt/ui/model/node_types/structural.py +616 -0
  112. morphopt-4.0.2/src/morphopt/ui/model/node_types/surfaces.py +267 -0
  113. morphopt-4.0.2/src/morphopt/ui/model/node_types/symmetry.py +172 -0
  114. morphopt-4.0.2/src/morphopt/ui/model/problem.py +1521 -0
  115. morphopt-4.0.2/src/morphopt/ui/model/registry.py +280 -0
  116. morphopt-4.0.2/src/morphopt/ui/observe_panel.py +611 -0
  117. morphopt-4.0.2/src/morphopt/ui/presentation/__init__.py +1 -0
  118. morphopt-4.0.2/src/morphopt/ui/presentation/edit_history.py +12 -0
  119. morphopt-4.0.2/src/morphopt/ui/presentation/history.py +83 -0
  120. morphopt-4.0.2/src/morphopt/ui/presentation/labels.py +329 -0
  121. morphopt-4.0.2/src/morphopt/ui/presentation/navigation.py +337 -0
  122. morphopt-4.0.2/src/morphopt/ui/refresh.py +116 -0
  123. morphopt-4.0.2/src/morphopt/ui/schemes/__init__.py +26 -0
  124. morphopt-4.0.2/src/morphopt/ui/schemes/base.py +391 -0
  125. {morphopt-4.0.0 → morphopt-4.0.2}/src/morphopt/ui/schemes/snippets.py +24 -39
  126. morphopt-4.0.2/src/morphopt/ui/theme/__init__.py +56 -0
  127. morphopt-4.0.2/src/morphopt/ui/theme/manager.py +135 -0
  128. morphopt-4.0.2/src/morphopt/ui/theme/palette.py +389 -0
  129. morphopt-4.0.2/src/morphopt/ui/theme/styles/__init__.py +9 -0
  130. morphopt-4.0.2/src/morphopt/ui/theme/styles/base.qss +26 -0
  131. morphopt-4.0.2/src/morphopt/ui/theme/styles/controls.qss +119 -0
  132. morphopt-4.0.2/src/morphopt/ui/theme/styles/inputs.qss +23 -0
  133. morphopt-4.0.2/src/morphopt/ui/theme/stylesheet.py +34 -0
  134. morphopt-4.0.2/src/morphopt/ui/theme/themes/__init__.py +11 -0
  135. morphopt-4.0.2/src/morphopt/ui/theme/themes/dark.py +86 -0
  136. morphopt-4.0.2/src/morphopt/ui/theme/themes/light.py +114 -0
  137. morphopt-4.0.2/src/morphopt/ui/visualization/__init__.py +42 -0
  138. morphopt-4.0.2/src/morphopt/ui/visualization/assets.py +50 -0
  139. morphopt-4.0.2/src/morphopt/ui/visualization/geometry.py +1059 -0
  140. morphopt-4.0.2/src/morphopt/ui/visualization/loads.py +554 -0
  141. morphopt-4.0.2/src/morphopt/ui/visualization/scene.py +165 -0
  142. morphopt-4.0.2/src/morphopt/ui/widgets/asset_browser.py +240 -0
  143. {morphopt-4.0.0 → morphopt-4.0.2}/src/morphopt/ui/widgets/codeeditor.py +119 -65
  144. morphopt-4.0.2/src/morphopt/ui/widgets/collection_controls.py +147 -0
  145. morphopt-4.0.2/src/morphopt/ui/widgets/controller_editor.py +138 -0
  146. morphopt-4.0.2/src/morphopt/ui/widgets/custom_classes.py +585 -0
  147. morphopt-4.0.2/src/morphopt/ui/widgets/definition_actions.py +669 -0
  148. morphopt-4.0.2/src/morphopt/ui/widgets/definition_manager.py +648 -0
  149. morphopt-4.0.2/src/morphopt/ui/widgets/edit_history.py +364 -0
  150. morphopt-4.0.2/src/morphopt/ui/widgets/editor.py +305 -0
  151. morphopt-4.0.2/src/morphopt/ui/widgets/editor_pages.py +64 -0
  152. morphopt-4.0.2/src/morphopt/ui/widgets/elided_label.py +47 -0
  153. morphopt-4.0.2/src/morphopt/ui/widgets/file_dialogs.py +216 -0
  154. morphopt-4.0.2/src/morphopt/ui/widgets/finite_element.py +768 -0
  155. morphopt-4.0.2/src/morphopt/ui/widgets/helper_editor.py +223 -0
  156. morphopt-4.0.2/src/morphopt/ui/widgets/language_selector.py +43 -0
  157. morphopt-4.0.2/src/morphopt/ui/widgets/model_tree.py +627 -0
  158. morphopt-4.0.2/src/morphopt/ui/widgets/objective_editor.py +905 -0
  159. morphopt-4.0.2/src/morphopt/ui/widgets/observation_pages.py +375 -0
  160. morphopt-4.0.2/src/morphopt/ui/widgets/param_form.py +282 -0
  161. morphopt-4.0.2/src/morphopt/ui/widgets/plot_style.py +44 -0
  162. morphopt-4.0.2/src/morphopt/ui/widgets/preview_renderer.py +840 -0
  163. morphopt-4.0.2/src/morphopt/ui/widgets/quickstart.py +1179 -0
  164. morphopt-4.0.2/src/morphopt/ui/widgets/result_path.py +73 -0
  165. morphopt-4.0.2/src/morphopt/ui/widgets/run_dialogs.py +69 -0
  166. {morphopt-4.0.0 → morphopt-4.0.2}/src/morphopt/ui/widgets/solver_editor.py +89 -70
  167. morphopt-4.0.2/src/morphopt/ui/widgets/source_view.py +23 -0
  168. morphopt-4.0.2/src/morphopt/ui/widgets/stepmatrix.py +207 -0
  169. morphopt-4.0.2/src/morphopt/ui/widgets/template_insert_dialog.py +153 -0
  170. morphopt-4.0.2/src/morphopt/ui/widgets/theme_selector.py +48 -0
  171. morphopt-4.0.2/src/morphopt/ui/widgets/updater_editor.py +929 -0
  172. morphopt-4.0.2/src/morphopt/ui/widgets/values.py +31 -0
  173. morphopt-4.0.2/src/morphopt/ui/widgets/viewer.py +441 -0
  174. morphopt-4.0.2/src/morphopt/ui/workbench.py +890 -0
  175. {morphopt-4.0.0 → morphopt-4.0.2}/src/morphopt/utils/__init__.py +1 -1
  176. {morphopt-4.0.0 → morphopt-4.0.2}/src/morphopt/utils/gradient_check.py +57 -33
  177. {morphopt-4.0.0 → morphopt-4.0.2}/src/morphopt/utils/history_read.py +5 -3
  178. {morphopt-4.0.0 → morphopt-4.0.2}/src/morphopt.egg-info/PKG-INFO +22 -13
  179. morphopt-4.0.2/src/morphopt.egg-info/SOURCES.txt +197 -0
  180. morphopt-4.0.0/src/morphopt/codesign/__init__.py +0 -23
  181. morphopt-4.0.0/src/morphopt/codesign/feaparams.py +0 -66
  182. morphopt-4.0.0/src/morphopt/codesign/geometryparams.py +0 -47
  183. morphopt-4.0.0/src/morphopt/codesign/params.py +0 -4
  184. morphopt-4.0.0/src/morphopt/optcore/modelparams/__init__.py +0 -14
  185. morphopt-4.0.0/src/morphopt/optcore/modelparams/feainterface/__init__.py +0 -10
  186. morphopt-4.0.0/src/morphopt/optcore/modelparams/materialinterface/__init__.py +0 -11
  187. morphopt-4.0.0/src/morphopt/optcore/modelparams/partinterface/__init__.py +0 -17
  188. morphopt-4.0.0/src/morphopt/optcore/modelparams/partinterface/torchfeapartinterface.py +0 -177
  189. morphopt-4.0.0/src/morphopt/shapeopt/__init__.py +0 -12
  190. morphopt-4.0.0/src/morphopt/shapeopt/surfaceinterfaces/__init__.py +0 -21
  191. morphopt-4.0.0/src/morphopt/ui/app.py +0 -64
  192. morphopt-4.0.0/src/morphopt/ui/application/definitions.py +0 -171
  193. morphopt-4.0.0/src/morphopt/ui/application/editor_routing.py +0 -52
  194. morphopt-4.0.0/src/morphopt/ui/application/runs.py +0 -138
  195. morphopt-4.0.0/src/morphopt/ui/codegen/generator.py +0 -816
  196. morphopt-4.0.0/src/morphopt/ui/i18n.py +0 -74
  197. morphopt-4.0.0/src/morphopt/ui/mainwindow.py +0 -205
  198. morphopt-4.0.0/src/morphopt/ui/model/__init__.py +0 -20
  199. morphopt-4.0.0/src/morphopt/ui/model/modelinfo.py +0 -118
  200. morphopt-4.0.0/src/morphopt/ui/model/problem.py +0 -2487
  201. morphopt-4.0.0/src/morphopt/ui/model/schemas.py +0 -1343
  202. morphopt-4.0.0/src/morphopt/ui/observe_panel.py +0 -788
  203. morphopt-4.0.0/src/morphopt/ui/schemes/__init__.py +0 -16
  204. morphopt-4.0.0/src/morphopt/ui/schemes/base.py +0 -353
  205. morphopt-4.0.0/src/morphopt/ui/templates/cantilever_beam.npz +0 -0
  206. morphopt-4.0.0/src/morphopt/ui/templates/multidesign.morph +0 -443
  207. morphopt-4.0.0/src/morphopt/ui/templates/shapeopt.morph +0 -202
  208. morphopt-4.0.0/src/morphopt/ui/templates/simp.morph +0 -262
  209. morphopt-4.0.0/src/morphopt/ui/widgets/editor.py +0 -565
  210. morphopt-4.0.0/src/morphopt/ui/widgets/model_tree.py +0 -868
  211. morphopt-4.0.0/src/morphopt/ui/widgets/objective_editor.py +0 -236
  212. morphopt-4.0.0/src/morphopt/ui/widgets/observation_pages.py +0 -380
  213. morphopt-4.0.0/src/morphopt/ui/widgets/param_form.py +0 -159
  214. morphopt-4.0.0/src/morphopt/ui/widgets/run_dialogs.py +0 -149
  215. morphopt-4.0.0/src/morphopt/ui/widgets/stepmatrix.py +0 -225
  216. morphopt-4.0.0/src/morphopt/ui/widgets/template_insert_dialog.py +0 -204
  217. morphopt-4.0.0/src/morphopt/ui/widgets/torchfea_model_editor.py +0 -508
  218. morphopt-4.0.0/src/morphopt/ui/widgets/updater_editor.py +0 -826
  219. morphopt-4.0.0/src/morphopt/ui/widgets/viewer.py +0 -505
  220. morphopt-4.0.0/src/morphopt/ui/workbench.py +0 -639
  221. morphopt-4.0.0/src/morphopt.egg-info/SOURCES.txt +0 -118
  222. {morphopt-4.0.0 → morphopt-4.0.2}/setup.cfg +0 -0
  223. {morphopt-4.0.0 → morphopt-4.0.2}/src/morphopt/opt_runner.py +0 -0
  224. {morphopt-4.0.0 → morphopt-4.0.2}/src/morphopt/optcore/history.py +0 -0
  225. {morphopt-4.0.0 → morphopt-4.0.2}/src/morphopt/optcore/modelparams/baseparam.py +0 -0
  226. /morphopt-4.0.0/src/morphopt/optcore/modelparams/materialinterface/materialmodels.py → /morphopt-4.0.2/src/morphopt/optcore/modelparams/materials/models.py +0 -0
  227. {morphopt-4.0.0 → morphopt-4.0.2}/src/morphopt/shapeopt/objectivefuncs/__init__.py +0 -0
  228. {morphopt-4.0.0 → morphopt-4.0.2}/src/morphopt/shapeopt/objectivefuncs/basefuncs.py +0 -0
  229. {morphopt-4.0.0 → morphopt-4.0.2}/src/morphopt/simp/__init__.py +0 -0
  230. {morphopt-4.0.0 → morphopt-4.0.2}/src/morphopt/simp/objectivefuncs/__init__.py +0 -0
  231. {morphopt-4.0.0 → morphopt-4.0.2}/src/morphopt/simp/objectivefuncs/basefuncs.py +0 -0
  232. {morphopt-4.0.0 → morphopt-4.0.2}/src/morphopt/simp/objectivefuncs/sensitivity.py +0 -0
  233. {morphopt-4.0.0 → morphopt-4.0.2}/src/morphopt/simp/objectivefuncs/volfrac.py +0 -0
  234. {morphopt-4.0.0 → morphopt-4.0.2}/src/morphopt/taskoptmization.py +0 -0
  235. {morphopt-4.0.0 → morphopt-4.0.2}/src/morphopt/ui/__main__.py +0 -0
  236. {morphopt-4.0.0 → morphopt-4.0.2}/src/morphopt/ui/codegen/__init__.py +0 -0
  237. {morphopt-4.0.0 → morphopt-4.0.2}/src/morphopt/ui/widgets/__init__.py +0 -0
  238. {morphopt-4.0.0 → morphopt-4.0.2}/src/morphopt.egg-info/dependency_links.txt +0 -0
  239. {morphopt-4.0.0 → morphopt-4.0.2}/src/morphopt.egg-info/entry_points.txt +0 -0
  240. {morphopt-4.0.0 → morphopt-4.0.2}/src/morphopt.egg-info/requires.txt +0 -0
  241. {morphopt-4.0.0 → morphopt-4.0.2}/src/morphopt.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: morphopt
3
- Version: 4.0.0
3
+ Version: 4.0.2
4
4
  Summary: A morphing optimization framework using PyTorch and torchfea.
5
5
  Requires-Python: >=3.12
6
6
  Description-Content-Type: text/markdown
@@ -28,14 +28,14 @@ Requires-Dist: pytest>=8.0; extra == "test"
28
28
 
29
29
  **Developed by Zenan Song**
30
30
 
31
- A differentiable structural optimization framework that eliminates manual sensitivity derivation by fusing the adjoint method with automatic differentiation (AD). The sensitivity corresponds to the virtual work of residual force derivatives on the adjoint displacement field, computed via a single backpropagation through the residual graph. MorphOpt provides a unified interface for geometry, load, and material definition, calls torchfea for GPU-accelerated differentiable nonlinear FEA and adjoint-AD sensitivity, and employs a trust-region optimizer with L-BFGS for design updates. Validated on SIMP topology optimization with B-spline density fields and pneumatic soft robot shape optimization with deformation-dependent follower loads.
31
+ MorphOpt is a differentiable structural optimization framework that combines the adjoint method with automatic differentiation (AD). The sensitivity corresponds to the virtual work of residual force derivatives on the adjoint displacement field, computed via a single backpropagation through the residual graph. MorphOpt provides a unified interface for geometry, load, and material definition, calls torchfea for GPU-accelerated differentiable nonlinear FEA and adjoint-AD sensitivity, and employs a trust-region optimizer with L-BFGS for design updates. Validated on SIMP topology optimization with B-spline density fields and pneumatic soft robot shape optimization with deformation-dependent follower loads.
32
32
 
33
33
  ## Features
34
34
 
35
35
  - Custom model definition covering geometry, material, and load parameters
36
36
  - Differentiable FEA via torchfea with automatic solving and sensitivity propagation
37
37
  - L-BFGS and trust-region methods for parameter updates within a subproblem framework
38
- - Fully extensible via inheritance — users customize every component in their definition scripts
38
+ - Component customization through framework class inheritance
39
39
 
40
40
  ## Quick Start
41
41
 
@@ -47,7 +47,7 @@ pip install morphopt
47
47
 
48
48
  Requirements: Python ≥ 3.12; a PyTorch **float64** build is recommended.
49
49
 
50
- > **Optimizations are run as scripts.** Each job is an ordinary Python file that calls `morphopt.start_optimization(...)`. It runs headlessly in a terminal (local or remote), and a finished run can be stopped and resumed later from its result folder. Script execution is the recommended way to run jobs.
50
+ > **Optimizations are run as scripts.** Each job is an ordinary Python file that calls `morphopt.start_optimization(...)`. It runs headlessly in a terminal (local or remote), and optimization runs can be stopped and resumed from their result folders. Script execution is the recommended way to run jobs.
51
51
 
52
52
  1. **Run a minimal example** — execute it directly in a terminal:
53
53
 
@@ -59,7 +59,7 @@ Requirements: Python ≥ 3.12; a PyTorch **float64** build is recommended.
59
59
  python examples/gripper.py
60
60
  ```
61
61
 
62
- 2. **Run your own job** — copy an example as a starting point, adapt the definition (geometry, material, load, updater, objective), and launch it as a script:
62
+ 2. **Run a custom job** — copy an example as a starting point, configure the geometry, material, loads, updater, and objective, and launch it as a script:
63
63
 
64
64
  ```bash
65
65
  python my_task.py
@@ -67,20 +67,29 @@ Requirements: Python ≥ 3.12; a PyTorch **float64** build is recommended.
67
67
 
68
68
  Each run writes its results (logs, FEA files, restart script) into a timestamped result folder under the run root.
69
69
 
70
- 3. **Optional — the GUI** is a visual aid for authoring a problem definition and inspecting finished runs in one window. It can also export a runnable script (`.py`), which you can either run directly in the UI or further customize before executing it via Step 2 in a terminal.
70
+ 3. **Graphical interface.** The GUI supports problem definition, optimization monitoring, and result inspection in one window. It also exports runnable Python scripts (`.py`) for execution in the UI or a terminal.
71
71
 
72
72
  ```bash
73
73
  morphopt-ui # console command, available after `pip install morphopt`
74
- # python -m morphopt.ui works too (handy when running from a source code directory)
74
+ # Alternative entry point: python -m morphopt.ui
75
75
  ```
76
76
 
77
- The complete UI workflow (definition part + observer part) is described in [`docs/UI_usage.md`](docs/UI_usage.md).
77
+ The GUI opens directly into the full definition workbench with its standard sections present and no problem setup prefilled. Definitions can be created directly in the workbench or generated through **Quickstart**. Quickstart provides shape and topology optimization settings, geometry definitions, and weighted objective terms with associated load conditions. Workspace terms select their driving pressure channels and use boundary integration. Generated problems stay editable and can be saved or exported as runnable scripts.
78
78
 
79
- Further references:
79
+ The [UI quick start](docs/UIguide.md) covers the complete example from model definition to optimization and result inspection. The [script quick start](docs/scriptguide.md) provides the equivalent runnable Python task.
80
80
 
81
- - Task definition guide: `docs/module_definition_guide.md`
82
- - Module API reference: `docs/module_reference.md`
83
- - Theory & papers: `docs/theory/`
81
+ ### Numeric configuration
82
+
83
+ Shared UI defaults and tunable kernel parameters live in [`src/morphopt/constants.py`](src/morphopt/constants.py), grouped under `CONSTANT.UI` and `CONSTANT.KERNEL`. Code accesses them directly, for example `CONSTANT.UI.VIEWER.RENDER.LABEL_FONT_SIZE` or `CONSTANT.KERNEL.SOLVER.NUM_PROCESS`. Edit a value there to change its default; restart MorphOpt for the change to take effect. Coordinate indices, tensor dimensions, and coefficients that define mathematical formulas remain in code. UI translations remain in JSON files under `src/morphopt/ui/locales/`.
84
+
85
+ ### Documentation
86
+
87
+ | Workflow | Quick start | Module and interface reference |
88
+ |---|---|---|
89
+ | Python script | [Start an optimization](docs/scriptguide.md) | [Define and extend each module](docs/scriptreference.md) |
90
+ | Graphical UI | [Create and run the example](docs/UIguide.md) | [Modules, parameters and interface definitions](docs/UIreference.md) |
91
+
92
+ The [documentation index](docs/README.md) includes the reading order and automatic section numbering commands. Theory and code architecture are documented separately under `docs/theory/` and `docs/codestructure/`.
84
93
 
85
94
  ## Directory Overview
86
95
 
@@ -101,7 +110,7 @@ Research use preferred. For production or commercial use, please evaluate and en
101
110
 
102
111
  ## Citation
103
112
 
104
- If you use MorphOpt in your research, please cite:
113
+ Research using MorphOpt can cite the following publications:
105
114
 
106
115
  - TRO 2023
107
116
 
@@ -2,14 +2,14 @@
2
2
 
3
3
  **Developed by Zenan Song**
4
4
 
5
- A differentiable structural optimization framework that eliminates manual sensitivity derivation by fusing the adjoint method with automatic differentiation (AD). The sensitivity corresponds to the virtual work of residual force derivatives on the adjoint displacement field, computed via a single backpropagation through the residual graph. MorphOpt provides a unified interface for geometry, load, and material definition, calls torchfea for GPU-accelerated differentiable nonlinear FEA and adjoint-AD sensitivity, and employs a trust-region optimizer with L-BFGS for design updates. Validated on SIMP topology optimization with B-spline density fields and pneumatic soft robot shape optimization with deformation-dependent follower loads.
5
+ MorphOpt is a differentiable structural optimization framework that combines the adjoint method with automatic differentiation (AD). The sensitivity corresponds to the virtual work of residual force derivatives on the adjoint displacement field, computed via a single backpropagation through the residual graph. MorphOpt provides a unified interface for geometry, load, and material definition, calls torchfea for GPU-accelerated differentiable nonlinear FEA and adjoint-AD sensitivity, and employs a trust-region optimizer with L-BFGS for design updates. Validated on SIMP topology optimization with B-spline density fields and pneumatic soft robot shape optimization with deformation-dependent follower loads.
6
6
 
7
7
  ## Features
8
8
 
9
9
  - Custom model definition covering geometry, material, and load parameters
10
10
  - Differentiable FEA via torchfea with automatic solving and sensitivity propagation
11
11
  - L-BFGS and trust-region methods for parameter updates within a subproblem framework
12
- - Fully extensible via inheritance — users customize every component in their definition scripts
12
+ - Component customization through framework class inheritance
13
13
 
14
14
  ## Quick Start
15
15
 
@@ -21,7 +21,7 @@ pip install morphopt
21
21
 
22
22
  Requirements: Python ≥ 3.12; a PyTorch **float64** build is recommended.
23
23
 
24
- > **Optimizations are run as scripts.** Each job is an ordinary Python file that calls `morphopt.start_optimization(...)`. It runs headlessly in a terminal (local or remote), and a finished run can be stopped and resumed later from its result folder. Script execution is the recommended way to run jobs.
24
+ > **Optimizations are run as scripts.** Each job is an ordinary Python file that calls `morphopt.start_optimization(...)`. It runs headlessly in a terminal (local or remote), and optimization runs can be stopped and resumed from their result folders. Script execution is the recommended way to run jobs.
25
25
 
26
26
  1. **Run a minimal example** — execute it directly in a terminal:
27
27
 
@@ -33,7 +33,7 @@ Requirements: Python ≥ 3.12; a PyTorch **float64** build is recommended.
33
33
  python examples/gripper.py
34
34
  ```
35
35
 
36
- 2. **Run your own job** — copy an example as a starting point, adapt the definition (geometry, material, load, updater, objective), and launch it as a script:
36
+ 2. **Run a custom job** — copy an example as a starting point, configure the geometry, material, loads, updater, and objective, and launch it as a script:
37
37
 
38
38
  ```bash
39
39
  python my_task.py
@@ -41,20 +41,29 @@ Requirements: Python ≥ 3.12; a PyTorch **float64** build is recommended.
41
41
 
42
42
  Each run writes its results (logs, FEA files, restart script) into a timestamped result folder under the run root.
43
43
 
44
- 3. **Optional — the GUI** is a visual aid for authoring a problem definition and inspecting finished runs in one window. It can also export a runnable script (`.py`), which you can either run directly in the UI or further customize before executing it via Step 2 in a terminal.
44
+ 3. **Graphical interface.** The GUI supports problem definition, optimization monitoring, and result inspection in one window. It also exports runnable Python scripts (`.py`) for execution in the UI or a terminal.
45
45
 
46
46
  ```bash
47
47
  morphopt-ui # console command, available after `pip install morphopt`
48
- # python -m morphopt.ui works too (handy when running from a source code directory)
48
+ # Alternative entry point: python -m morphopt.ui
49
49
  ```
50
50
 
51
- The complete UI workflow (definition part + observer part) is described in [`docs/UI_usage.md`](docs/UI_usage.md).
51
+ The GUI opens directly into the full definition workbench with its standard sections present and no problem setup prefilled. Definitions can be created directly in the workbench or generated through **Quickstart**. Quickstart provides shape and topology optimization settings, geometry definitions, and weighted objective terms with associated load conditions. Workspace terms select their driving pressure channels and use boundary integration. Generated problems stay editable and can be saved or exported as runnable scripts.
52
52
 
53
- Further references:
53
+ The [UI quick start](docs/UIguide.md) covers the complete example from model definition to optimization and result inspection. The [script quick start](docs/scriptguide.md) provides the equivalent runnable Python task.
54
54
 
55
- - Task definition guide: `docs/module_definition_guide.md`
56
- - Module API reference: `docs/module_reference.md`
57
- - Theory & papers: `docs/theory/`
55
+ ### Numeric configuration
56
+
57
+ Shared UI defaults and tunable kernel parameters live in [`src/morphopt/constants.py`](src/morphopt/constants.py), grouped under `CONSTANT.UI` and `CONSTANT.KERNEL`. Code accesses them directly, for example `CONSTANT.UI.VIEWER.RENDER.LABEL_FONT_SIZE` or `CONSTANT.KERNEL.SOLVER.NUM_PROCESS`. Edit a value there to change its default; restart MorphOpt for the change to take effect. Coordinate indices, tensor dimensions, and coefficients that define mathematical formulas remain in code. UI translations remain in JSON files under `src/morphopt/ui/locales/`.
58
+
59
+ ### Documentation
60
+
61
+ | Workflow | Quick start | Module and interface reference |
62
+ |---|---|---|
63
+ | Python script | [Start an optimization](docs/scriptguide.md) | [Define and extend each module](docs/scriptreference.md) |
64
+ | Graphical UI | [Create and run the example](docs/UIguide.md) | [Modules, parameters and interface definitions](docs/UIreference.md) |
65
+
66
+ The [documentation index](docs/README.md) includes the reading order and automatic section numbering commands. Theory and code architecture are documented separately under `docs/theory/` and `docs/codestructure/`.
58
67
 
59
68
  ## Directory Overview
60
69
 
@@ -75,7 +84,7 @@ Research use preferred. For production or commercial use, please evaluate and en
75
84
 
76
85
  ## Citation
77
86
 
78
- If you use MorphOpt in your research, please cite:
87
+ Research using MorphOpt can cite the following publications:
79
88
 
80
89
  - TRO 2023
81
90
 
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "morphopt"
3
- version = "4.0.0"
3
+ version = "4.0.2"
4
4
  description = "A morphing optimization framework using PyTorch and torchfea."
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.12"
@@ -39,5 +39,12 @@ testpaths = ["tests"]
39
39
  pythonpath = ["src"]
40
40
  addopts = "-ra"
41
41
 
42
+ [tool.ruff.lint]
43
+ extend-select = ["RUF022"]
44
+
42
45
  [tool.setuptools.package-data]
43
- "morphopt.ui" = ["templates/*.morph", "templates/*.npz"]
46
+ "morphopt.ui" = [
47
+ "locales/*.json",
48
+ "theme/styles/*.qss",
49
+ "assets/*.svg",
50
+ ]
@@ -67,21 +67,22 @@ def enable_logging(level=__logging.INFO, log_file=None, file_log_level=__logging
67
67
 
68
68
  # region modules (loaded after the core classes they subclass)
69
69
  from . import codesign, shapeopt, simp
70
+ from .codesign import OffsetBoundaryPart, UpdaterOffsetBoundaryPart
70
71
  from .opt_runner import debug_optimization, start_optimization
71
72
  from .optcore.controller import Controller
72
73
  from .optcore.history import History
73
74
  from .optcore.modelparams import (
74
- BasePartInterface,
75
+ BaseModelComponent,
76
+ BasePart,
77
+ BoxPart,
78
+ CADPart,
75
79
  FEAParams,
76
80
  GeometryParams,
77
- INPPartInterface,
81
+ INPPart,
78
82
  MaterialsParams,
79
83
  Params,
80
- TorchFEAPartInterface,
81
- load_model_assembly,
82
- resolve_model_path,
83
84
  )
84
- from .optcore.modelparams.materialinterface import HomogeneousMaterial
85
+ from .optcore.modelparams.materials import HomogeneousMaterial
85
86
  from .optcore.objfunc import ObjectiveFunction
86
87
  from .optcore.protocal import (
87
88
  ProtocalInitializable,
@@ -91,7 +92,14 @@ from .optcore.protocal import (
91
92
  )
92
93
  from .optcore.solver import Solver
93
94
  from .optcore.updaters import Updaters
94
- from .shapeopt import BoundaryPartInterface, UpdaterBoundaryPart
95
+ from .shapeopt import (
96
+ BaseSurfaceConstraints,
97
+ BoundaryPart,
98
+ BspSurfaceRelationConstraint,
99
+ CPGEOSurfaceRelationConstraint,
100
+ SurfaceRelationConstraint,
101
+ UpdaterBoundaryPart,
102
+ )
95
103
  from .simp import SIMP_BSPFieldMaterials, UpdaterSIMPMaterial
96
104
 
97
105
  # endregion
@@ -101,3 +109,43 @@ from .utils import check_gradients, get_controller
101
109
  # endregion
102
110
 
103
111
  controller: Controller = None
112
+
113
+
114
+ __all__ = [
115
+ "BaseModelComponent",
116
+ "BasePart",
117
+ "BaseSurfaceConstraints",
118
+ "BoundaryPart",
119
+ "BoxPart",
120
+ "BspSurfaceRelationConstraint",
121
+ "CADPart",
122
+ "CPGEOSurfaceRelationConstraint",
123
+ "Controller",
124
+ "FEAParams",
125
+ "GeometryParams",
126
+ "History",
127
+ "HomogeneousMaterial",
128
+ "INPPart",
129
+ "MaterialsParams",
130
+ "ObjectiveFunction",
131
+ "OffsetBoundaryPart",
132
+ "Params",
133
+ "ProtocalInitializable",
134
+ "ProtocalSavable",
135
+ "ProtocalUpdatable",
136
+ "ProtocalVisualizable",
137
+ "SIMP_BSPFieldMaterials",
138
+ "Solver",
139
+ "SurfaceRelationConstraint",
140
+ "UpdaterBoundaryPart",
141
+ "UpdaterOffsetBoundaryPart",
142
+ "UpdaterSIMPMaterial",
143
+ "Updaters",
144
+ "check_gradients",
145
+ "codesign",
146
+ "debug_optimization",
147
+ "get_controller",
148
+ "shapeopt",
149
+ "simp",
150
+ "start_optimization",
151
+ ]
@@ -0,0 +1,16 @@
1
+ """Cavity offset Parts and their geometry updater.
2
+
3
+ Compose parameters, objectives, solvers and updater collections using the
4
+ common morphopt interfaces. SIMP materials use the simp interfaces.
5
+ """
6
+
7
+ from .offset_boundary_part import OffsetBoundaryPart
8
+ from .update_offset_boundary_part import UpdaterOffsetBoundaryPart
9
+ from .constraints import InwardCurvatureRadius, OffsetSurfaceMinThickness
10
+
11
+ __all__ = [
12
+ "OffsetBoundaryPart",
13
+ "UpdaterOffsetBoundaryPart",
14
+ "InwardCurvatureRadius",
15
+ "OffsetSurfaceMinThickness",
16
+ ]
@@ -1,7 +1,8 @@
1
1
  import torch
2
2
 
3
+ from ..constants import CONSTANT
3
4
  from ..shapeopt.objectivefuncs.basefuncs import BaseConstraints
4
- from .geometry import CodesignBoundaryPartInterface
5
+ from .offset_boundary_part import OffsetBoundaryPart
5
6
 
6
7
 
7
8
  class InwardCurvatureRadius(BaseConstraints):
@@ -17,13 +18,13 @@ class InwardCurvatureRadius(BaseConstraints):
17
18
  self,
18
19
  surface_start: int = 1,
19
20
  surface_ids: list[int] | None = None,
20
- margin: float = 0.4,
21
- margin_ratio: float = 0.45,
22
- barrier_thre_ratio: float = 0.1,
23
- barrier_ratio: float = 0.0,
24
- p: int = 8,
25
- penalty_scale: float = 1e3,
26
- hard_violation_beta: float = 8.0,
21
+ margin: float = CONSTANT.KERNEL.CODESIGN.CURVATURE_MARGIN,
22
+ margin_ratio: float = CONSTANT.KERNEL.CODESIGN.CURVATURE_MARGIN_RATIO,
23
+ barrier_thre_ratio: float = CONSTANT.KERNEL.CODESIGN.CURVATURE_BARRIER_THRESHOLD_RATIO,
24
+ barrier_ratio: float = CONSTANT.KERNEL.CODESIGN.BARRIER_PENALTY_RATIO,
25
+ p: int = CONSTANT.KERNEL.CODESIGN.BARRIER_EXPONENT,
26
+ penalty_scale: float = CONSTANT.KERNEL.CODESIGN.PENALTY_SCALE,
27
+ hard_violation_beta: float = CONSTANT.KERNEL.CODESIGN.HARD_VIOLATION_BETA,
27
28
  normal_sign: float = 1.0,
28
29
  ) -> None:
29
30
  """
@@ -71,7 +72,9 @@ class InwardCurvatureRadius(BaseConstraints):
71
72
 
72
73
  @staticmethod
73
74
  def _principal_curvatures(
74
- rdu: torch.Tensor, rdu2: torch.Tensor, eps: float = 1e-12
75
+ rdu: torch.Tensor,
76
+ rdu2: torch.Tensor,
77
+ eps: float = CONSTANT.KERNEL.CODESIGN.GEOMETRY_TOLERANCE,
75
78
  ) -> tuple[torch.Tensor, torch.Tensor]:
76
79
  normal0 = torch.cross(rdu[:, :, 1], rdu[:, :, 0], dim=1)
77
80
  normal = normal0 / (normal0.norm(dim=1, keepdim=True) + eps)
@@ -96,11 +99,11 @@ class InwardCurvatureRadius(BaseConstraints):
96
99
  """Take the Part this constraint is evaluated for.
97
100
 
98
101
  The geometry updater hands over the Part it evaluates; only a
99
- :class:`~morphopt.codesign.CodesignBoundaryPartInterface` carries a
102
+ :class:`~morphopt.codesign.OffsetBoundaryPart` carries a
100
103
  shell, so anything else is rejected here.
101
104
  """
102
105
  super().initialize(r0=r0, rdu0=rdu0, *args, **kwargs)
103
- if not isinstance(part_interface, CodesignBoundaryPartInterface):
106
+ if not isinstance(part_interface, OffsetBoundaryPart):
104
107
  raise TypeError(
105
108
  f"{type(self).__name__} is evaluated for one co-design Part "
106
109
  f"(got {type(part_interface).__name__})."
@@ -127,9 +130,15 @@ class InwardCurvatureRadius(BaseConstraints):
127
130
  if t <= 0:
128
131
  continue
129
132
 
130
- margin_abs = max(float((self.margin_ratio * t) + self.margin), 1e-12)
133
+ margin_abs = max(
134
+ float((self.margin_ratio * t) + self.margin),
135
+ CONSTANT.KERNEL.CODESIGN.GEOMETRY_TOLERANCE,
136
+ )
131
137
  k_limit = 1.0 / (t + margin_abs)
132
- barrier_thre = max(k_limit * self.barrier_thre_ratio, 1e-12)
138
+ barrier_thre = max(
139
+ k_limit * self.barrier_thre_ratio,
140
+ CONSTANT.KERNEL.CODESIGN.GEOMETRY_TOLERANCE,
141
+ )
133
142
 
134
143
  k1, k2 = self._principal_curvatures(rdu[i], rdu2[i])
135
144
 
@@ -146,7 +155,8 @@ class InwardCurvatureRadius(BaseConstraints):
146
155
  rel_violation = (violation[index] / barrier_thre).clamp(min=0.0)
147
156
  hard_boost = torch.exp(
148
157
  (self.hard_violation_beta * (rel_violation - 1.0)).clamp(
149
- min=0.0, max=20.0
158
+ min=0.0,
159
+ max=CONSTANT.KERNEL.CODESIGN.HARD_VIOLATION_EXPONENT_MAX,
150
160
  )
151
161
  )
152
162
  penalty_strong = self.penalty_scale * penalty * hard_boost
@@ -168,16 +178,16 @@ class OffsetSurfaceMinThickness(BaseConstraints):
168
178
  surface_start: int = 1,
169
179
  surface_ids: list[int] | None = None,
170
180
  min_distance: float | None = None,
171
- search_ratio: float = 1.5,
172
- barrier_thre_ratio: float = 0.05,
173
- barrier_ratio: float = 0.0,
174
- p: int = 8,
175
- penalty_scale: float = 1e3,
176
- hard_violation_beta: float = 8.0,
181
+ search_ratio: float = CONSTANT.KERNEL.CODESIGN.THICKNESS_SEARCH_RATIO,
182
+ barrier_thre_ratio: float = CONSTANT.KERNEL.CODESIGN.THICKNESS_BARRIER_THRESHOLD_RATIO,
183
+ barrier_ratio: float = CONSTANT.KERNEL.CODESIGN.BARRIER_PENALTY_RATIO,
184
+ p: int = CONSTANT.KERNEL.CODESIGN.BARRIER_EXPONENT,
185
+ penalty_scale: float = CONSTANT.KERNEL.CODESIGN.PENALTY_SCALE,
186
+ hard_violation_beta: float = CONSTANT.KERNEL.CODESIGN.HARD_VIOLATION_BETA,
177
187
  normal_sign: float = 1.0,
178
- normal_opposition_thre: float = 0.0,
179
- normal_min: float = -0.7,
180
- normal_max: float = -0.5,
188
+ normal_opposition_thre: float = CONSTANT.KERNEL.CODESIGN.NORMAL_OPPOSITION_THRESHOLD,
189
+ normal_min: float = CONSTANT.KERNEL.CODESIGN.NORMAL_TRANSITION_MIN,
190
+ normal_max: float = CONSTANT.KERNEL.CODESIGN.NORMAL_TRANSITION_MAX,
181
191
  ) -> None:
182
192
  """
183
193
  Initialize the minimum thickness constraint for the offset surface.
@@ -233,7 +243,10 @@ class OffsetSurfaceMinThickness(BaseConstraints):
233
243
  @staticmethod
234
244
  def _surface_normals(rdu_sf: torch.Tensor) -> torch.Tensor:
235
245
  normal0 = torch.cross(rdu_sf[:, :, 1], rdu_sf[:, :, 0], dim=1)
236
- normals = normal0 / (normal0.norm(dim=1, keepdim=True) + 1e-12)
246
+ normals = normal0 / (
247
+ normal0.norm(dim=1, keepdim=True)
248
+ + CONSTANT.KERNEL.CODESIGN.GEOMETRY_TOLERANCE
249
+ )
237
250
  return normals
238
251
 
239
252
  def _offset_points(
@@ -249,17 +262,17 @@ class OffsetSurfaceMinThickness(BaseConstraints):
249
262
  if self.min_distance is not None
250
263
  else (2.0 * thickness)
251
264
  )
252
- return max(dmin, 1e-12)
265
+ return max(dmin, CONSTANT.KERNEL.CODESIGN.GEOMETRY_TOLERANCE)
253
266
 
254
267
  def initialize(self, r0, rdu0, *args, part_interface=None, **kwargs) -> None:
255
268
  """Take the Part this constraint is evaluated for and pair its points.
256
269
 
257
270
  The geometry updater hands over the Part it evaluates; only a
258
- :class:`~morphopt.codesign.CodesignBoundaryPartInterface` carries a
271
+ :class:`~morphopt.codesign.OffsetBoundaryPart` carries a
259
272
  shell, so anything else is rejected here.
260
273
  """
261
274
  super().initialize(r0=r0, rdu0=rdu0, *args, **kwargs)
262
- if not isinstance(part_interface, CodesignBoundaryPartInterface):
275
+ if not isinstance(part_interface, OffsetBoundaryPart):
263
276
  raise TypeError(
264
277
  f"{type(self).__name__} is evaluated for one co-design Part "
265
278
  f"(got {type(part_interface).__name__})."
@@ -318,7 +331,8 @@ class OffsetSurfaceMinThickness(BaseConstraints):
318
331
  if thickness <= 0:
319
332
  continue
320
333
  barrier_thre = max(
321
- self._min_distance(thickness) * self.barrier_thre_ratio, 1e-12
334
+ self._min_distance(thickness) * self.barrier_thre_ratio,
335
+ CONSTANT.KERNEL.CODESIGN.GEOMETRY_TOLERANCE,
322
336
  )
323
337
 
324
338
  # Base surface normals (offset surface shares same normal direction)
@@ -343,7 +357,10 @@ class OffsetSurfaceMinThickness(BaseConstraints):
343
357
  r_sf=r[sf_idx], rdu_sf=rdu[sf_idx], thickness=thickness
344
358
  )
345
359
  delta = roff[pairs_n[0]] - roff[pairs_n[1]]
346
- dist = torch.sqrt((delta * delta).sum(dim=1) + 1e-18)
360
+ dist = torch.sqrt(
361
+ (delta * delta).sum(dim=1)
362
+ + CONSTANT.KERNEL.CODESIGN.DISTANCE_SQUARED_TOLERANCE
363
+ )
347
364
 
348
365
  violation = mindist_n - dist + barrier_thre
349
366
  indexl, l = self.barrier_function(
@@ -361,7 +378,8 @@ class OffsetSurfaceMinThickness(BaseConstraints):
361
378
  rel_violation = (violation[indexl] / barrier_thre).clamp(min=0.0)
362
379
  hard_boost = torch.exp(
363
380
  (self.hard_violation_beta * (rel_violation - 1.0)).clamp(
364
- min=0.0, max=20.0
381
+ min=0.0,
382
+ max=CONSTANT.KERNEL.CODESIGN.HARD_VIOLATION_EXPONENT_MAX,
365
383
  )
366
384
  )
367
385
  penalty_strong = self.penalty_scale * l * hard_boost * np_smooth
@@ -1,4 +1,4 @@
1
- """Co-design boundary part interface: cavity surfaces with an offset shell.
1
+ """Co-design boundary part: cavity surfaces with an offset shell.
2
2
 
3
3
  The co-design (``codesign``) scheme extends the shape-optimization boundary
4
4
  description with a solid shell: every cavity surface (index ``1..n``) is offset
@@ -13,12 +13,13 @@ import numpy as np
13
13
  import torch
14
14
  import torchfea
15
15
 
16
- from ..shapeopt.boundarypartinterface import BoundaryPartInterface
16
+ from ..constants import CONSTANT
17
+ from ..shapeopt.boundary_part import BoundaryPart
17
18
 
18
- __all__ = ["CodesignBoundaryPartInterface"]
19
+ __all__ = ["OffsetBoundaryPart"]
19
20
 
20
21
 
21
- class CodesignBoundaryPartInterface(BoundaryPartInterface):
22
+ class OffsetBoundaryPart(BoundaryPart):
22
23
  """Boundary-surface geometry whose cavity surfaces carry a solid shell.
23
24
 
24
25
  Parameters
@@ -31,7 +32,7 @@ class CodesignBoundaryPartInterface(BoundaryPartInterface):
31
32
 
32
33
  def __init__(
33
34
  self,
34
- shell_thickness: float = 1.0,
35
+ shell_thickness: float = CONSTANT.KERNEL.CODESIGN_GEOMETRY.DEFAULT_SHELL_THICKNESS,
35
36
  num_layers: int = 1,
36
37
  **kwargs: object,
37
38
  ) -> None:
@@ -40,17 +41,16 @@ class CodesignBoundaryPartInterface(BoundaryPartInterface):
40
41
  self.shell_thickness: float = float(shell_thickness)
41
42
  """Total thickness of the offset shell on the cavity surfaces."""
42
43
 
43
- self.num_layers: int = max(1, int(num_layers))
44
+ self.num_layers: int = int(num_layers)
44
45
  """Number of wedge layers through the shell thickness."""
45
46
 
46
47
  self._node_idx: list[np.ndarray] = []
47
48
  """Node indices of each offset layer (0 = base surface mesh)."""
48
49
 
49
- self._tri_local: np.ndarray | None = None
50
- """Cavity triangle connectivity stored with local node indices."""
51
-
52
- self._shell_elem_offset: int | None = None
53
- """Element-id offset of the shell block (0-based)."""
50
+ if self.shell_thickness <= 0:
51
+ raise ValueError("shell_thickness must be positive.")
52
+ if self.num_layers < 1:
53
+ raise ValueError("num_layers must be at least one.")
54
54
 
55
55
  # ------------------------------------------------------------- shell mesh
56
56
  def _compute_normals(self, base_nodes: torch.Tensor) -> torch.Tensor:
@@ -60,8 +60,9 @@ class CodesignBoundaryPartInterface(BoundaryPartInterface):
60
60
  surface = self.surfaceinterfaces[index]
61
61
  normals.append(
62
62
  surface.get_normals(
63
- torch.from_numpy(surface.surf_node_uv).to(
64
- torch.get_default_device()
63
+ torch.as_tensor(
64
+ surface.surf_node_uv, device=base_nodes.device,
65
+ dtype=base_nodes.dtype,
65
66
  )
66
67
  )
67
68
  )
@@ -76,16 +77,19 @@ class CodesignBoundaryPartInterface(BoundaryPartInterface):
76
77
  """Add the offset shell wedge elements to the meshed Part."""
77
78
  return self._build_shell_c3d6(part)
78
79
 
79
- def _build_shell_c3d6(self, part: torchfea.Part) -> torchfea.Part:
80
- thickness = float(self.shell_thickness)
81
- if thickness <= 0 or self.num_layers <= 0:
82
- return part
80
+ def build_part(self, path_result=None, pools=None) -> torchfea.Part:
81
+ """Build and validate the offset wedges, including quadratic conversion."""
82
+ part = super().build_part(path_result=path_result, pools=pools)
83
+ shell = part.elems["C3D6"]
84
+ shell.initialize(nodes=part.nodes)
85
+ weights = shell.gaussian_weight
86
+ if not torch.isfinite(weights).all() or (weights <= 0).any():
87
+ raise ValueError(f"Invalid offset shell mesh on Part {self.part_name!r}.")
88
+ return part
83
89
 
90
+ def _build_shell_c3d6(self, part: torchfea.Part) -> torchfea.Part:
84
91
  # Ensure surface elements exist so we can query triangle meshes.
85
- try:
86
- part.surfaces.initialize(part)
87
- except Exception:
88
- pass
92
+ part.surfaces.initialize(part)
89
93
 
90
94
  tri_by_surface: dict[int, np.ndarray] = {}
91
95
  tri_local_by_surface: dict[int, np.ndarray] = {}
@@ -100,7 +104,7 @@ class CodesignBoundaryPartInterface(BoundaryPartInterface):
100
104
  cavity_order.append(sidx)
101
105
  tri_by_surface[sidx] = tri
102
106
  base_ids_blocks.append(
103
- np.sort(np.asarray(part.set_nodes[surf_name], dtype=int))
107
+ np.asarray(self.surfaceinterfaces[sidx].surf_node_idx, dtype=int)
104
108
  )
105
109
 
106
110
  if len(tri_by_surface) == 0:
@@ -115,7 +119,6 @@ class CodesignBoundaryPartInterface(BoundaryPartInterface):
115
119
  local_map = -np.ones((int(part.nodes.shape[0]),), dtype=int)
116
120
  local_map[base_ids] = np.arange(base_ids.shape[0], dtype=int)
117
121
 
118
- tri_local_all = []
119
122
  for sidx in cavity_order:
120
123
  tri_global = tri_by_surface[sidx]
121
124
  tri_local = local_map[tri_global]
@@ -125,8 +128,6 @@ class CodesignBoundaryPartInterface(BoundaryPartInterface):
125
128
  )
126
129
  tri_local = tri_local.astype(int)
127
130
  tri_local_by_surface[sidx] = tri_local
128
- tri_local_all.append(tri_local)
129
- self._tri_local = np.concatenate(tri_local_all, axis=0).astype(int)
130
131
 
131
132
  device = part.nodes.device
132
133
  base_ids_t = torch.as_tensor(base_ids, dtype=torch.long, device=device)
@@ -155,7 +156,6 @@ class CodesignBoundaryPartInterface(BoundaryPartInterface):
155
156
  continue
156
157
  existing_max = max(existing_max, int(element._elems_index.max().item()))
157
158
  elem_offset = int(existing_max + 1)
158
- self._shell_elem_offset = elem_offset
159
159
 
160
160
  # Build linear wedge connectivity (C3D6) for all layers.
161
161
  wedge6_blocks = []
@@ -217,10 +217,7 @@ class CodesignBoundaryPartInterface(BoundaryPartInterface):
217
217
  )
218
218
 
219
219
  # Refresh the surfaces cache to include the newly added offset surfaces.
220
- try:
221
- part.surfaces.initialize(part)
222
- except Exception:
223
- pass
220
+ part.surfaces.initialize(part)
224
221
 
225
222
  return part
226
223
 
@@ -231,9 +228,6 @@ class CodesignBoundaryPartInterface(BoundaryPartInterface):
231
228
  """Update the Part nodes and keep the offset layers consistent."""
232
229
  super().modify_assembly(design_sensitivity_vars, assembly)
233
230
 
234
- if len(self._node_idx) == 0 or self._tri_local is None:
235
- return
236
-
237
231
  part = assembly.get_part(self.part_name)
238
232
  nodes = part.nodes.clone()
239
233
 
@@ -262,4 +256,8 @@ class CodesignBoundaryPartInterface(BoundaryPartInterface):
262
256
  @staticmethod
263
257
  def _default_opacity(index: int) -> float:
264
258
  """The solid volume is hidden so the shell stays visible."""
265
- return 0.0 if index == 0 else 1.0
259
+ return (
260
+ 0.0
261
+ if index == 0
262
+ else CONSTANT.KERNEL.VISUALIZATION.OFFSET_SHELL_SURFACE_OPACITY
263
+ )