morphopt 3.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.

Potentially problematic release.


This version of morphopt might be problematic. Click here for more details.

Files changed (49) hide show
  1. morphopt/__init__.py +32 -0
  2. morphopt/opt_runner.py +130 -0
  3. morphopt/optcore/baseobject.py +48 -0
  4. morphopt/optcore/controller.py +404 -0
  5. morphopt/optcore/history.py +440 -0
  6. morphopt/optcore/modelparams/__init__.py +4 -0
  7. morphopt/optcore/modelparams/base_params.py +97 -0
  8. morphopt/optcore/modelparams/feamodel/__init__.py +0 -0
  9. morphopt/optcore/modelparams/feamodel/feainterface/__init__.py +10 -0
  10. morphopt/optcore/modelparams/feamodel/feainterface/basefeainterface.py +50 -0
  11. morphopt/optcore/modelparams/feamodel/feainterface/bodyforceinterface.py +71 -0
  12. morphopt/optcore/modelparams/feamodel/feainterface/boundaryconditioninterface.py +59 -0
  13. morphopt/optcore/modelparams/feamodel/feainterface/contactinterface.py +113 -0
  14. morphopt/optcore/modelparams/feamodel/feainterface/coupleinterface.py +31 -0
  15. morphopt/optcore/modelparams/feamodel/feainterface/pointinterface.py +79 -0
  16. morphopt/optcore/modelparams/feamodel/feainterface/pressureinterface.py +68 -0
  17. morphopt/optcore/modelparams/feamodel/feainterface/referencepointinterface.py +29 -0
  18. morphopt/optcore/modelparams/feamodel/feainterface/springinterface.py +104 -0
  19. morphopt/optcore/modelparams/feamodel/feaparams.py +264 -0
  20. morphopt/optcore/modelparams/geometry/__init__.py +3 -0
  21. morphopt/optcore/modelparams/geometry/geometryinterfaces/__init__.py +1 -0
  22. morphopt/optcore/modelparams/geometry/geometryinterfaces/basesurfaceinterface.py +763 -0
  23. morphopt/optcore/modelparams/geometry/geometryinterfaces/bspsurfaceinterface.py +723 -0
  24. morphopt/optcore/modelparams/geometry/geometryinterfaces/cpgeosurfaceinterface.py +374 -0
  25. morphopt/optcore/modelparams/geometry/geometryparams.py +715 -0
  26. morphopt/optcore/modelparams/materials/__init__.py +1 -0
  27. morphopt/optcore/modelparams/materials/materialparams.py +110 -0
  28. morphopt/optcore/modelparams/params.py +88 -0
  29. morphopt/optcore/objfunc.py +248 -0
  30. morphopt/optcore/solver.py +159 -0
  31. morphopt/optcore/updaters/__init__.py +2 -0
  32. morphopt/optcore/updaters/base_updater.py +110 -0
  33. morphopt/optcore/updaters/geometry/__init__.py +2 -0
  34. morphopt/optcore/updaters/geometry/objectivefuncs/__init__.py +5 -0
  35. morphopt/optcore/updaters/geometry/objectivefuncs/basefuncs.py +117 -0
  36. morphopt/optcore/updaters/geometry/objectivefuncs/boundarys.py +91 -0
  37. morphopt/optcore/updaters/geometry/objectivefuncs/distancesurface.py +123 -0
  38. morphopt/optcore/updaters/geometry/objectivefuncs/shapederivative.py +179 -0
  39. morphopt/optcore/updaters/geometry/objectivefuncs/surfacefairness.py +40 -0
  40. morphopt/optcore/updaters/geometry/update_geometry.py +347 -0
  41. morphopt/optcore/updaters/optimizer.py +177 -0
  42. morphopt/optcore/updaters/updaters.py +82 -0
  43. morphopt/optcore/utils/plot_history_surface.py +239 -0
  44. morphopt/taskoptmization.py +75 -0
  45. morphopt/taskui.py +458 -0
  46. morphopt-3.1.1.dist-info/METADATA +242 -0
  47. morphopt-3.1.1.dist-info/RECORD +49 -0
  48. morphopt-3.1.1.dist-info/WHEEL +5 -0
  49. morphopt-3.1.1.dist-info/top_level.txt +1 -0
@@ -0,0 +1,239 @@
1
+
2
+ from calendar import c
3
+ import math
4
+ import pyvista as pv
5
+ import torch
6
+ import morphopt
7
+
8
+ class SurfacesFigurePlotter:
9
+
10
+ def __init__(self, restart_path: str):
11
+ import importlib.util
12
+ torch.set_default_dtype(torch.float64)
13
+ torch.set_default_device('cpu')
14
+ spec = importlib.util.spec_from_file_location("MAIN_SCRIPT_FOR_RESTART", restart_path + '/scripts/' + 'MAIN_SCRIPT_FOR_RESTART.py')
15
+ MAIN_SCRIPT_FOR_RESTART = importlib.util.module_from_spec(spec)
16
+ spec.loader.exec_module(MAIN_SCRIPT_FOR_RESTART)
17
+
18
+ params: morphopt.Params = MAIN_SCRIPT_FOR_RESTART.ThisController.Params()
19
+
20
+ self.params = params
21
+ self.restart_path = restart_path
22
+
23
+ self.colors = [(40.0 / 255, 120.0 / 255, 181.0 / 255)] * self.params.geometry.num_surface
24
+ self.opacity = [1.0] * self.params.geometry.num_surface
25
+ self.opacity[0] = 0.6
26
+ self.boundary: tuple[float, float, float, float, float, float] = None
27
+
28
+
29
+ def load_parameters(self, iteration: int):
30
+ """
31
+ Load the parameters at a given iteration.
32
+ """
33
+ self.params.geometry.load(foldpath=self.restart_path + '/log/', iteration=iteration)
34
+
35
+ def plot_surfaces(self, iteration: int,
36
+ colors: list[tuple[float, float, float]] | tuple[float, float, float] = None,
37
+ opacity: list[float] = None,
38
+ boundary: tuple[float, float, float, float, float, float] = None,
39
+ plotter=None):
40
+ """
41
+ Plot the surfaces at a given iteration.
42
+ """
43
+
44
+ if colors is None:
45
+ colors = self.colors
46
+ if opacity is None:
47
+ opacity = self.opacity
48
+ if boundary is None:
49
+ boundary = self.boundary
50
+
51
+ self.load_parameters(iteration=iteration)
52
+
53
+ if plotter is None:
54
+ plotter = pv.Plotter()
55
+
56
+ for sf in range(self.params.geometry.num_surface):
57
+ if sf == 0:
58
+ alpha = 0.6
59
+ else:
60
+ alpha = 1.0
61
+ if opacity is not None:
62
+ alpha = opacity[sf]
63
+
64
+ color_to_use = (40.0 / 255, 120.0 / 255, 181.0 / 255)
65
+ if colors is not None and isinstance(colors, list):
66
+ color_to_use = colors[sf]
67
+ elif colors is not None and isinstance(colors, tuple):
68
+ color_to_use = colors
69
+
70
+ mesh = self.params.geometry.surface_list[sf].get_mesh()
71
+ plotter.add_mesh(mesh, opacity=alpha, color=color_to_use,
72
+ diffuse=0.8, specular=0.2, ambient=0.1, specular_power=10,
73
+ smooth_shading=True, show_edges=False)
74
+
75
+ if boundary is not None:
76
+ pass
77
+
78
+ def plot_surface_rotation(self, iteration: int,
79
+ colors: tuple[float, float, float] = None,
80
+ opacity: list[float] = None,
81
+ boundary: tuple[float, float, float, float, float, float] = None,
82
+ n_frames: int = 36,
83
+ total_time: int = 4000,
84
+ view: tuple[float, float] = (45, 70),
85
+ output_gif: str = 'surface_rotation.gif'):
86
+ """
87
+ Plot the surfaces at a given iteration with rotation and save as a gif.
88
+
89
+ Args:
90
+ iteration (int): The iteration number to plot.
91
+ colors (tuple): The RGB color for the surfaces.
92
+ opacity (list): The opacity for each surface.
93
+ boundary (tuple): The boundary points to plot. Should be in the form (x_min, x_max, y_min, y_max, z_min, z_max).
94
+ n_frames (int): The number of frames in the rotation.
95
+ delay (int): The delay between frames in milliseconds.
96
+ view (tuple): The (azimuth, elevation) angles for the view.
97
+ output_gif (str): The output gif file name.
98
+ """
99
+
100
+ plotter = pv.Plotter(off_screen=True, window_size=[2500, 2500])
101
+ plotter.set_background('white')
102
+ plotter.enable_lightkit() # 启用光照效果
103
+
104
+
105
+ self.plot_surfaces(iteration=iteration, colors=colors, opacity=opacity, boundary=boundary, plotter=plotter)
106
+
107
+ plotter.enable_parallel_projection()
108
+ azimuth = 210
109
+ elevation = 20
110
+ plotter.view_vector((math.cos(math.radians(azimuth)) * math.cos(math.radians(elevation)),
111
+ math.sin(math.radians(azimuth)) * math.cos(math.radians(elevation)),
112
+ math.sin(math.radians(elevation))))
113
+
114
+ plotter.open_gif(output_gif)
115
+ plotter.camera_position = 'iso'
116
+
117
+ for i in range(n_frames):
118
+ plotter.write_frame()
119
+ plotter.camera.azimuth += 360 / n_frames
120
+
121
+ plotter.close()
122
+
123
+ def plot_history_surface(self, surface_index: int, history_index: int = 0,
124
+ colors: tuple[float, float, float] = None,
125
+ opacity: float = 0.6,
126
+ boundary: tuple[float, float, float, float, float, float] = None,
127
+ total_time: int = 4000,
128
+ output_gif: str = 'history_surface.gif',
129
+ output_jpg_foldpath: str = None):
130
+ """
131
+ Plot the history of a surface over iterations and save as a gif.
132
+
133
+ Args:
134
+ surface_index (int): The index of the surface to plot.
135
+ history_index (int): The total history index to plot.
136
+ colors (tuple): The RGB color for the surface.
137
+ opacity (float): The opacity for the surface.
138
+ boundary (tuple): The boundary points to plot. Should be in the form (x_min, x_max, y_min, y_max, z_min, z_max).
139
+ total_time (int): The total time for the gif in milliseconds.
140
+ output_gif (str): The output gif file name.
141
+ output_jpg_foldpath (str): The folder path to save individual jpg frames. If None, frames are not saved.
142
+
143
+ """
144
+ if colors is None:
145
+ colors = self.colors[surface_index]
146
+ if boundary is None:
147
+ boundary = self.boundary
148
+
149
+ plotter = pv.Plotter(off_screen=True, window_size=[2500, 2500])
150
+ plotter.set_background('white')
151
+
152
+ plotter.enable_parallel_projection()
153
+ azimuth = 210
154
+ elevation = 20
155
+ plotter.view_vector((math.cos(math.radians(azimuth)) * math.cos(math.radians(elevation)),
156
+ math.sin(math.radians(azimuth)) * math.cos(math.radians(elevation)),
157
+ math.sin(math.radians(elevation))))
158
+ plotter.enable_lightkit() # 启用光照效果
159
+
160
+ plotter.open_gif(output_gif)
161
+
162
+ for iteration in range(history_index + 1):
163
+ self.load_parameters(iteration=iteration)
164
+ plotter.clear()
165
+
166
+ mesh = self.params.geometry.surface_list[surface_index].get_mesh()
167
+ plotter.add_mesh(mesh, opacity=opacity, color=colors,
168
+ diffuse=0.8, specular=0.2, ambient=0.1, specular_power=10,
169
+ smooth_shading=True, show_edges=False)
170
+
171
+ if boundary is not None:
172
+ pass
173
+
174
+
175
+ plotter.write_frame()
176
+
177
+ if output_jpg_foldpath is not None:
178
+ plotter.screenshot(f"{output_jpg_foldpath}/iter_{iteration}.jpg")
179
+
180
+ plotter.close()
181
+
182
+ def plot_history_all_surfaces(self, history_index: int = 0,
183
+ colors: list[tuple[float, float, float]] = None,
184
+ opacity: list[float] = None,
185
+ boundary: tuple[float, float, float, float, float, float] = None,
186
+ total_time: int = 4000,
187
+ output_gif: str = 'history_all_surfaces.gif',
188
+ output_jpg_foldpath: str = None):
189
+ """
190
+ Plot the history of all surfaces over iterations and save as a gif.
191
+
192
+ Args:
193
+ history_index (int): The total history index to plot.
194
+ colors (list): The list of RGB colors for each surface.
195
+ opacity (list): The list of opacities for each surface.
196
+ boundary (tuple): The boundary points to plot. Should be in the form (x_min, x_max, y_min, y_max, z_min, z_max).
197
+ total_time (int): The total time for the gif in milliseconds.
198
+ output_gif (str): The output gif file name.
199
+ output_jpg_foldpath (str): The folder path to save individual jpg frames. If None, frames are not saved.
200
+ """
201
+
202
+ if colors is None:
203
+ colors = self.colors
204
+ if opacity is None:
205
+ opacity = self.opacity
206
+ if boundary is None:
207
+ boundary = self.boundary
208
+
209
+ plotter = pv.Plotter(off_screen=True, window_size=[2500, 2500])
210
+ plotter.set_background('white')
211
+
212
+
213
+ plotter.open_gif(output_gif)
214
+
215
+ for iteration in range(history_index + 1):
216
+ plotter.clear()
217
+ plotter.enable_lightkit() # 启用光照效果
218
+ self.plot_surfaces(iteration=iteration, colors=colors, opacity=opacity, boundary=boundary, plotter=plotter)
219
+
220
+ if iteration == 0:
221
+ plotter.enable_parallel_projection()
222
+ azimuth = 210
223
+ elevation = 20
224
+ plotter.view_vector((math.cos(math.radians(azimuth)) * math.cos(math.radians(elevation)),
225
+ math.sin(math.radians(azimuth)) * math.cos(math.radians(elevation)),
226
+ math.sin(math.radians(elevation))))
227
+
228
+ plotter.write_frame()
229
+
230
+ if output_jpg_foldpath is not None:
231
+ plotter.screenshot(f"{output_jpg_foldpath}/iter_{iteration}.jpg")
232
+
233
+ plotter.close()
234
+
235
+ if __name__ == "__main__":
236
+ plotter = SurfacesFigurePlotter(restart_path='Z:/Results/EXAMPLE_T20260106_165756/')
237
+ plotter.plot_history_all_surfaces(history_index=3,
238
+ output_gif='Z:/temp/example_displacement_history.gif',
239
+ output_jpg_foldpath='Z:/temp/')
@@ -0,0 +1,75 @@
1
+ import multiprocessing as mp
2
+
3
+
4
+ class TaskOptimization:
5
+ @classmethod
6
+ def task_optimization(cls, path_result: str = None,
7
+ main_filepath: str = None,
8
+ device: str = 'cpu',
9
+ target_iteration: int = None,
10
+ restart_per_iteration: int = 20,
11
+ dataqueue: mp.Queue = None):
12
+
13
+ import warnings
14
+ warnings.filterwarnings("ignore", category=UserWarning)
15
+
16
+
17
+ path_queue = mp.Queue()
18
+ while True:
19
+ process = mp.Process(target=cls.optmain, kwargs={'device': device,
20
+ 'target_iteration': target_iteration,
21
+ 'path_result': path_result,
22
+ 'restart_per_iteration': restart_per_iteration,
23
+ 'main_filepath': main_filepath,
24
+ 'pathqueue': path_queue,
25
+ 'dataqueue': dataqueue})
26
+ process.start()
27
+ try:
28
+ process.join() # Wait for process to finish
29
+ if process.exitcode != 0:
30
+ print(f"Process failed with exit code {process.exitcode}, continuing...")
31
+ continue
32
+ path_result = path_queue.get()
33
+ except Exception as e:
34
+ print(f"Error in process or queue: {e}, continuing...")
35
+ continue
36
+ target_iteration = None # after first restart, always continue to the latest iteration
37
+
38
+ @classmethod
39
+ def optmain(cls, device='cpu', target_iteration: int = 0, path_result: str = None, restart_per_iteration: int = 20, main_filepath: str = None, pathqueue: mp.Queue = None, dataqueue: mp.Queue = None):
40
+ import os
41
+ os.environ['KMP_DUPLICATE_LIB_OK']='True'
42
+
43
+
44
+ import warnings
45
+ warnings.filterwarnings("ignore", category=UserWarning)
46
+
47
+ import torch
48
+ torch.set_default_dtype(torch.float64)
49
+ torch.set_default_device(device)
50
+
51
+ import morphopt
52
+
53
+ filename = os.path.splitext(os.path.basename(main_filepath))[0]
54
+ filepath = os.path.dirname(main_filepath)
55
+ os.chdir(filepath)
56
+ import sys
57
+ sys.path.append(os.getcwd())
58
+
59
+
60
+
61
+ Controller: morphopt.Controller = getattr(__import__(filename), 'ThisController')
62
+
63
+ controller: morphopt.Controller = Controller()
64
+ controller.restart_per_iteration = restart_per_iteration
65
+ controller.dataqueue = dataqueue
66
+ controller.optdevice = device
67
+
68
+ if target_iteration == 0 or path_result is None:
69
+ controller.start_optimization(main_filepath=main_filepath)
70
+ else:
71
+ controller.restart_optimization(path_result=path_result, target_iteration=target_iteration)
72
+
73
+ if pathqueue is not None:
74
+ pathqueue.put(controller.path_result)
75
+ return controller.path_result