pyfemtet 1.1.5__py3-none-any.whl → 1.2.0__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 pyfemtet might be problematic. Click here for more details.

@@ -59,7 +59,6 @@ class Message:
59
59
  ERR_RUN_JOURNAL_NOT_FOUND = _(r'"%UGII_BASE_DIR%\NXBIN\run_journal.exe" is not found. Make sure you have NX installed and the environment variable UGII_BASE_DIR is set.')
60
60
  ERR_MODEL_RECONSTRUCTION_FAILED = _('Model reconstruction failed.')
61
61
  ERR_MODEL_UPDATE_FAILED = _('Model update failed.')
62
- ERR_NO_MAKEPY = _('It was detected that the configuration of Femtet python macro constants has not been completed. The configuration was done automatically (python -m win32com.client.makepy FemtetMacro). Please restart the program. If the error persists, please run "py -m win32com.client.makepy FemtetMacro" or "python -m win32com.client.makepy FemtetMacro" on the command prompt.')
63
62
  ERR_FEMTET_CONNECTION_FAILED = _('Failed to connect to Femtet.')
64
63
 
65
64
  @staticmethod
@@ -0,0 +1,2 @@
1
+ at = '@'
2
+ AT = '_at_'
@@ -0,0 +1,169 @@
1
+ from typing import TypeAlias
2
+
3
+ SWVariables: TypeAlias = dict[str, str]
4
+ """<prm_name>: <expression>. Note that the <prm_name> does not contain `"`."""
5
+
6
+
7
+ class EquationContext:
8
+ def __init__(self, swModel) -> None:
9
+ self.swModel = swModel
10
+ self.swEqnMgr = None
11
+
12
+ def __enter__(self):
13
+ # プロパティを退避
14
+ self.swEqnMgr = self.swModel.GetEquationMgr
15
+ self.buffer_aso = self.swEqnMgr.AutomaticSolveOrder
16
+ self.buffer_ar = self.swEqnMgr.AutomaticRebuild
17
+ self.swEqnMgr.AutomaticSolveOrder = False
18
+ self.swEqnMgr.AutomaticRebuild = False
19
+ return self.swEqnMgr
20
+
21
+ def __exit__(self, exc_type, exc_val, exc_tb):
22
+ # プロパティをもとに戻す
23
+ assert self.swEqnMgr is not None
24
+ self.swEqnMgr.AutomaticSolveOrder = self.buffer_aso
25
+ self.swEqnMgr.AutomaticRebuild = self.buffer_ar
26
+
27
+
28
+ class EditPartContext:
29
+ def __init__(self, swModel, component) -> None:
30
+ self.swModel = swModel
31
+ self.component = component
32
+
33
+ def __enter__(self):
34
+ swSelMgr = self.swModel.SelectionManager
35
+ swSelData = swSelMgr.CreateSelectData
36
+ swSelMgr.AddSelectionListObject(self.component, swSelData)
37
+ # self.swModel.EditPart() # 対象がアセンブリの場合動作しない
38
+ self.swModel.AssemblyPartToggle() # Obsolete だが代わりにこれを使う
39
+
40
+ def __exit__(self, exc_type, exc_val, exc_tb):
41
+ self.swModel.EditAssembly()
42
+
43
+
44
+ def is_assembly(swModel_or_name):
45
+ if isinstance(swModel_or_name, str):
46
+ return swModel_or_name.lower().endswith('.sldasm')
47
+ else:
48
+ return swModel_or_name.GetPathName.lower().endswith('.sldasm')
49
+
50
+
51
+ def _iter_parts(swModel):
52
+ components = swModel.GetComponents(
53
+ False # TopOnly
54
+ )
55
+ return components
56
+
57
+
58
+ # Used by pyfemtet-opt-gui
59
+ class SolidworksVariableManager:
60
+
61
+ def __init__(self, logger=None):
62
+ # Used by pyfemtet-opt-gui
63
+ self.updated_objects = set()
64
+ """Updated variable names, sldprt file paths and linked .txt equation file paths."""
65
+ if logger is None:
66
+ from logging import getLogger
67
+ logger = getLogger('solidworks_variable_manager')
68
+ self.logger = logger
69
+
70
+ # Used by pyfemtet-opt-gui
71
+ def update_global_variables_recourse(self, swModel, x: SWVariables):
72
+ # まず自身のパラメータを更新
73
+ self.logger.debug(f'Processing `{swModel.GetPathName}`')
74
+ self._update_global_variables_core(swModel, x)
75
+
76
+ # アセンブリならば、構成部品のパラメータを更新
77
+ if is_assembly(swModel):
78
+ components = _iter_parts(swModel)
79
+ for component in components:
80
+ swPartModel = component.GetModelDoc2
81
+ self.logger.debug(f'Checking `{swPartModel.GetPathName}`')
82
+ if swPartModel.GetPathName.lower() not in self.updated_objects:
83
+ self.logger.debug(f'Processing `{swPartModel.GetPathName}`')
84
+ with EditPartContext(swModel, component):
85
+ self._update_global_variables_core(swPartModel, x)
86
+ self.updated_objects.add(swPartModel.GetPathName.lower())
87
+
88
+ def _update_global_variables_core(self, swModel, x: SWVariables):
89
+ with EquationContext(swModel) as swEqnMgr:
90
+ # txt にリンクされている場合は txt を更新
91
+ if swEqnMgr.LinkToFile:
92
+ self._update_global_variables_linked_txt(swEqnMgr, x)
93
+ self._update_global_variables_simple(swEqnMgr, x)
94
+ # noinspection PyStatementEffect
95
+ swEqnMgr.EvaluateAll
96
+
97
+ def _update_global_variables_linked_txt(self, swEqnMgr, x: SWVariables):
98
+ txt_path = swEqnMgr.FilePath
99
+ if txt_path in self.updated_objects:
100
+ return
101
+ with open(txt_path, 'r', encoding='utf_8_sig') as f:
102
+ equations = [line.strip() for line in f.readlines() if line.strip() != '']
103
+ for i, eq in enumerate(equations):
104
+ equations[i] = self._update_equation(eq, x)
105
+ with open(txt_path, 'w', encoding='utf_8_sig') as f:
106
+ f.writelines([eq + '\n' for eq in equations])
107
+ self.logger.debug(f'`{txt_path}` is updated.')
108
+ self.updated_objects.add(txt_path)
109
+
110
+ def _update_global_variables_simple(self, swEqnMgr, x: SWVariables):
111
+ nEquation = swEqnMgr.GetCount
112
+
113
+ # equation を列挙
114
+ self.logger.debug(f'{nEquation} equations detected.')
115
+ for i in range(nEquation):
116
+ # name, equation の取得
117
+ eq = swEqnMgr.Equation(i)
118
+ prm_name = self._get_left(eq)
119
+ # COM 経由なので必要な時以外は触らない
120
+ self.logger.debug(f'Checking `{prm_name}`')
121
+ if (prm_name in x) and (prm_name not in self.updated_objects):
122
+ self.logger.debug(f'Processing `{prm_name}`')
123
+ # 特定の Equation がテキストリンク有効か
124
+ # どうかを判定する術がないので、一旦更新する
125
+ new_eq = self._update_equation(eq, x)
126
+ swEqnMgr.Equation(i, new_eq)
127
+ # テキストリンクの場合、COM インスタンスに
128
+ # 更新された値が残ってしまうのでテキストを再読み込み
129
+ if swEqnMgr.LinkToFile:
130
+ # noinspection PyStatementEffect
131
+ swEqnMgr.UpdateValuesFromExternalEquationFile
132
+ self.updated_objects.add(prm_name)
133
+
134
+ def _update_equation(self, equation: str, x: SWVariables):
135
+ prm_name = self._get_left(equation)
136
+ if prm_name not in x:
137
+ return equation
138
+ new_eq = f'"{prm_name}" = {x[prm_name]}'
139
+ self.logger.debug(f'New eq.: `{new_eq}`')
140
+ return new_eq
141
+
142
+ @staticmethod
143
+ def _get_left(equation: str):
144
+ tmp = equation.split('=')
145
+ if len(tmp) == 0:
146
+ raise RuntimeError(f'Invalid solidworks equation: {equation} (no `=` contained)')
147
+ return tmp[0].strip('" ')
148
+
149
+ # Used by pyfemtet-opt-gui
150
+ @staticmethod
151
+ def get_equations_recourse(swModel, global_variables_only=False) -> list[str]:
152
+ out = list()
153
+ swEqnMgr = swModel.GetEquationMgr
154
+ for i in range(swEqnMgr.GetCount):
155
+ if global_variables_only and not swEqnMgr.GlobalVariable(i):
156
+ continue
157
+ eq = swEqnMgr.Equation(i)
158
+ out.append(eq)
159
+ if is_assembly(swModel):
160
+ components = _iter_parts(swModel)
161
+ for component in components:
162
+ swPartModel = component.GetModelDoc2
163
+ swEqnMgr = swPartModel.GetEquationMgr
164
+ for i in range(swEqnMgr.GetCount):
165
+ if global_variables_only and not swEqnMgr.GlobalVariable(i):
166
+ continue
167
+ eq = swEqnMgr.Equation(i)
168
+ out.append(eq)
169
+ return out
pyfemtet/opt/femopt.py CHANGED
@@ -375,19 +375,20 @@ class FEMOpt:
375
375
  def save_history():
376
376
  while True:
377
377
  sleep(2)
378
- try:
379
- self.opt.history.save()
380
- logger.debug('History saved!')
381
- except PermissionError:
382
- logger.error(
383
- _('Cannot save history. '
384
- 'The most common reason is '
385
- 'that the csv is opened by '
386
- 'another program (such as Excel). '
387
- 'Please free {path} or lost the '
388
- 'optimization history.',
389
- path=self.opt.history.path)
390
- )
378
+ if len(self.opt.history.get_df()) > 0:
379
+ try:
380
+ self.opt.history.save()
381
+ logger.debug('History saved!')
382
+ except PermissionError:
383
+ logger.error(
384
+ _('Cannot save history. '
385
+ 'The most common reason is '
386
+ 'that the csv is opened by '
387
+ 'another program (such as Excel). '
388
+ 'Please free {path} or lost the '
389
+ 'optimization history.',
390
+ path=self.opt.history.path)
391
+ )
391
392
  if entire_status.value >= WorkerStatus.finished:
392
393
  break
393
394
  logger.debug('History save thread finished!')
@@ -1,5 +1,5 @@
1
1
  from __future__ import annotations
2
- from typing import TYPE_CHECKING
2
+ from typing import TYPE_CHECKING, Callable, Any
3
3
 
4
4
  import os
5
5
  import tempfile
@@ -105,7 +105,7 @@ class AbstractFEMInterface:
105
105
 
106
106
  return dst_path_
107
107
 
108
- def _get_worker_space(self) -> str | None:
108
+ def _get_worker_space(self) -> str:
109
109
  worker = get_worker()
110
110
  if worker is None:
111
111
  assert hasattr(self, '_tmp_dir'), 'Internal Error! Run _distribute_files() first!'
@@ -176,12 +176,12 @@ class AbstractFEMInterface:
176
176
  pass
177
177
 
178
178
  # noinspection PyMethodMayBeStatic,PyUnusedLocal
179
- def _check_using_fem(self, fun: callable) -> bool:
179
+ def _check_using_fem(self, fun: Callable) -> bool:
180
180
  return False
181
181
 
182
182
  # ===== postprocessing after recording =====
183
183
 
184
- def _create_postprocess_args(self) -> dict[str, ...]:
184
+ def _create_postprocess_args(self) -> dict[str, Any]:
185
185
  return {}
186
186
 
187
187
  @staticmethod
@@ -505,8 +505,10 @@ class ExcelInterface(COMInterface):
505
505
  if not os.path.exists(xla_file_path):
506
506
  raise FileNotFoundError(
507
507
  _(
508
- en_message='Femtet XLA file not found: {xla_file_path}',
509
- jp_message='Femtet XLA ファイルが見つかりません: {xla_file_path}',
508
+ en_message='Femtet XLA file ({xla_file_path}) not found. '
509
+ 'Please run `Enable Macros` command.',
510
+ jp_message='Femtet XLA ファイル ({xla_file_path}) が見つかりません。'
511
+ '「マクロ機能の有効化」を実行してください。',
510
512
  xla_file_path=xla_file_path
511
513
  )
512
514
  )
@@ -7,13 +7,13 @@ import sys
7
7
  import subprocess
8
8
  from time import sleep
9
9
  from contextlib import nullcontext
10
+ import importlib
10
11
 
11
12
  # noinspection PyUnresolvedReferences
12
13
  from pywintypes import com_error, error
13
14
  # noinspection PyUnresolvedReferences
14
15
  from pythoncom import CoInitialize, CoUninitialize
15
- # noinspection PyUnresolvedReferences
16
- from win32com.client import constants
16
+ from win32com.client import constants, Dispatch
17
17
  import win32con
18
18
  import win32gui
19
19
 
@@ -353,6 +353,8 @@ class FemtetInterface(COMInterface):
353
353
  it will not try existing another Femtet process.
354
354
 
355
355
  """
356
+ # noinspection PyGlobalUndefined
357
+ global constants
356
358
 
357
359
  if connect_method == "new":
358
360
  self._connect_new_femtet()
@@ -373,32 +375,39 @@ class FemtetInterface(COMInterface):
373
375
  if not hasattr(constants, "STATIC_C"):
374
376
  cmd = f"{sys.executable} -m win32com.client.makepy FemtetMacro"
375
377
  subprocess.run(cmd, shell=True)
378
+ sleep(1)
379
+
380
+ import win32com.client
381
+ importlib.reload(win32com.client)
382
+ from win32com.client import Dispatch, constants
383
+ Dispatch('FemtetMacro.Femtet')
384
+
385
+ if not hasattr(constants, "STATIC_C"):
386
+ message = _(
387
+ en_message='It was detected that the configuration of '
388
+ 'Femtet python macro constants has not been '
389
+ 'completed. The configuration was done '
390
+ 'automatically '
391
+ '(python -m win32com.client.makepy FemtetMacro). '
392
+ 'Please restart the program. '
393
+ 'If the error persists, please run '
394
+ '"py -m win32com.client.makepy FemtetMacro" '
395
+ 'or "python -m win32com.client.makepy FemtetMacro" '
396
+ 'on the command prompt.',
397
+ jp_message='Femtet Pythonマクロ定数の設定が完了していない'
398
+ 'ことが検出されました。設定は自動で行われました'
399
+ '(py -m win32com.client.makepy FemtetMacro)。 '
400
+ 'プログラムを再起動してください。'
401
+ 'エラーが解消されない場合は、'
402
+ '"py -m win32com.client.makepy FemtetMacro" か '
403
+ '"python -m win32com.client.makepy FemtetMacro" '
404
+ 'コマンドをコマンドプロンプトで実行してください。'
405
+ )
376
406
 
377
- message = _(
378
- en_message='It was detected that the configuration of '
379
- 'Femtet python macro constants has not been '
380
- 'completed. The configuration was done '
381
- 'automatically '
382
- '(python -m win32com.client.makepy FemtetMacro). '
383
- 'Please restart the program. '
384
- 'If the error persists, please run '
385
- '"py -m win32com.client.makepy FemtetMacro" '
386
- 'or "python -m win32com.client.makepy FemtetMacro" '
387
- 'on the command prompt.',
388
- jp_message='Femtet Pythonマクロ定数の設定が完了していない'
389
- 'ことが検出されました。設定は自動で行われました'
390
- '(py -m win32com.client.makepy FemtetMacro)。 '
391
- 'プログラムを再起動してください。'
392
- 'エラーが解消されない場合は、'
393
- '"py -m win32com.client.makepy FemtetMacro" か '
394
- '"python -m win32com.client.makepy FemtetMacro" '
395
- 'コマンドをコマンドプロンプトで実行してください。'
396
- )
397
-
398
- logger.error("================")
399
- logger.error(message)
400
- logger.error("================")
401
- raise RuntimeError(message)
407
+ logger.error("================")
408
+ logger.error(message)
409
+ logger.error("================")
410
+ raise RuntimeError(message)
402
411
 
403
412
  if self.Femtet is None:
404
413
  raise RuntimeError(_(
@@ -1,14 +1,11 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  from time import sleep
4
- from typing import TYPE_CHECKING
5
-
4
+ from typing import TYPE_CHECKING, Any
6
5
  import os
7
- import re
8
6
 
9
- from win32com.client import DispatchEx, CDispatch
10
- # noinspection PyUnresolvedReferences
11
- from pythoncom import CoInitialize, CoUninitialize, com_error
7
+ from win32com.client import Dispatch
8
+ from pythoncom import com_error, CoInitialize
12
9
 
13
10
  from pyfemtet._util.dask_util import *
14
11
  from pyfemtet.opt.exceptions import *
@@ -17,12 +14,13 @@ from pyfemtet._i18n import _
17
14
  from pyfemtet.opt.problem.problem import *
18
15
  from pyfemtet.logger import get_module_logger
19
16
 
17
+ from pyfemtet._util.solidworks_variable import SolidworksVariableManager, is_assembly, SWVariables
18
+
20
19
  if TYPE_CHECKING:
21
20
  from pyfemtet.opt.optimizer import AbstractOptimizer
22
21
 
23
-
24
22
  logger = get_module_logger('opt.interface', False)
25
-
23
+ asm_logger = get_module_logger('opt.interface.sldasm', False)
26
24
 
27
25
  # 定数の宣言
28
26
  swThisConfiguration = 1 # https://help.solidworks.com/2023/english/api/swconst/SOLIDWORKS.Interop.swconst~SOLIDWORKS.Interop.swconst.swInConfigurationOpts_e.html
@@ -33,6 +31,7 @@ swSaveAsOptions_Copy = 2 #
33
31
  swSaveAsOptions_Silent = 1 # https://help.solidworks.com/2021/english/api/swconst/solidworks.interop.swconst~solidworks.interop.swconst.swsaveasoptions_e.html
34
32
  swSaveWithReferencesOptions_None = 0 # https://help-solidworks-com.translate.goog/2023/english/api/swconst/SolidWorks.Interop.swconst~SolidWorks.Interop.swconst.swSaveWithReferencesOptions_e.html?_x_tr_sl=auto&_x_tr_tl=ja&_x_tr_hl=ja&_x_tr_pto=wapp
35
33
  swDocPART = 1 # https://help.solidworks.com/2023/english/api/swconst/SOLIDWORKS.Interop.swconst~SOLIDWORKS.Interop.swconst.swDocumentTypes_e.html
34
+ swDocASSEMBLY = 2
36
35
 
37
36
 
38
37
  class FileNotOpenedError(Exception):
@@ -63,7 +62,7 @@ class SolidworksInterface(COMInterface):
63
62
  AssertionError: If the specified part file does not exist.
64
63
  """
65
64
 
66
- swApp: CDispatch
65
+ swApp: Any
67
66
  com_members = {'swApp': 'SLDWORKS.Application'}
68
67
  _access_sw_lock_name = 'access_sw'
69
68
 
@@ -77,7 +76,8 @@ class SolidworksInterface(COMInterface):
77
76
  self.quit_solidworks_on_terminate = close_solidworks_on_terminate
78
77
  self.solidworks_visible = visible
79
78
 
80
- assert os.path.isfile(self.sldprt_path)
79
+ if not os.path.isfile(self.sldprt_path):
80
+ raise FileNotFoundError(self.sldprt_path)
81
81
  self._original_sldprt_path = self.sldprt_path
82
82
 
83
83
  def connect_sw(self):
@@ -86,9 +86,9 @@ class SolidworksInterface(COMInterface):
86
86
  jp_message='Solidworks に接続しています...'
87
87
  ))
88
88
  try:
89
- self.swApp = DispatchEx('SLDWORKS.Application')
89
+ self.swApp = Dispatch('SLDWORKS.Application')
90
90
  except com_error:
91
- raise Exception(_(
91
+ raise RuntimeError(_(
92
92
  en_message='Failed to instantiate Solidworks. '
93
93
  'Please check installation and enabling macro.',
94
94
  jp_message='Solidworks のインスタンス化に失敗しました。'
@@ -97,18 +97,32 @@ class SolidworksInterface(COMInterface):
97
97
  self.swApp.Visible = self.solidworks_visible
98
98
 
99
99
  def _setup_before_parallel(self, scheduler_address=None):
100
- self._distribute_files([self.sldprt_path], scheduler_address)
101
-
102
- def _setup_after_parallel(self, opt: AbstractOptimizer = None):
100
+ if not is_assembly(self.sldprt_path):
101
+ self._distribute_files([self.sldprt_path], scheduler_address)
102
+
103
+ def _setup_after_parallel(self, opt: AbstractOptimizer):
104
+
105
+ # validation
106
+ if is_assembly(self.sldprt_path) and get_worker() is not None:
107
+ # 現在の仕様だと sldprt_path だけが
108
+ # worker_space に保存される。
109
+ # 並列処理に対応するためには
110
+ # すべてのファイルを distribute したうえで
111
+ # 構成部品の置換を実行する必要がある。
112
+ raise RuntimeError(_(
113
+ en_message='Parallel processing is not supported when handling assembly parts with SolidworksInterface.',
114
+ jp_message='SolidworksInterfaceでアセンブリパーツを対象とする場合、並列処理はサポートされていません。'
115
+ ))
103
116
 
104
- # get suffix
105
- suffix = self._get_file_suffix(opt)
117
+ if not is_assembly(self.sldprt_path):
118
+ # get suffix
119
+ suffix = self._get_file_suffix(opt)
106
120
 
107
- # rename and get worker path
108
- self.sldprt_path = self._rename_and_get_path_on_worker_space(
109
- self._original_sldprt_path,
110
- suffix,
111
- )
121
+ # rename and get worker path
122
+ self.sldprt_path = self._rename_and_get_path_on_worker_space(
123
+ self._original_sldprt_path,
124
+ suffix,
125
+ )
112
126
 
113
127
  # connect solidworks
114
128
  CoInitialize()
@@ -116,10 +130,13 @@ class SolidworksInterface(COMInterface):
116
130
  self.connect_sw()
117
131
 
118
132
  # open it
119
- self.swApp.OpenDoc(self.sldprt_path, swDocPART)
133
+ if is_assembly(self.sldprt_path):
134
+ self.swApp.OpenDoc(self.sldprt_path, swDocASSEMBLY)
135
+ else:
136
+ self.swApp.OpenDoc(self.sldprt_path, swDocPART)
120
137
 
121
138
  @property
122
- def swModel(self) -> CDispatch:
139
+ def swModel(self):
123
140
  return _get_model_by_basename(self.swApp, os.path.basename(self.sldprt_path))
124
141
 
125
142
  def update(self) -> None:
@@ -131,54 +148,25 @@ class SolidworksInterface(COMInterface):
131
148
 
132
149
  # sw はプロセスが一つなので Lock
133
150
  with Lock(self._access_sw_lock_name):
134
-
135
151
  sleep(0.2)
136
-
137
- # ===== model を取得 =====
138
152
  swModel = self.swModel
139
-
140
- # ===== equation manager を取得 =====
141
- swEqnMgr = swModel.GetEquationMgr
142
- nEquation = swEqnMgr.GetCount
143
-
144
- # プロパティを退避
145
- buffer_aso = swEqnMgr.AutomaticSolveOrder
146
- buffer_ar = swEqnMgr.AutomaticRebuild
147
- swEqnMgr.AutomaticSolveOrder = False
148
- swEqnMgr.AutomaticRebuild = False
149
-
150
- # 値を更新
151
- for i in range(nEquation):
152
- # name, equation の取得
153
- eq = swEqnMgr.Equation(i)
154
- prm_name = _get_name_from_equation(eq)
155
- # 対象なら処理
156
- if prm_name in self.current_prm_values:
157
- prm = self.current_prm_values[prm_name]
158
- right = str(prm.value) + prm.properties.get('unit', '')
159
- new_equation = f'"{prm_name}" = {right}'
160
- swEqnMgr.Equation(i, new_equation)
161
-
162
- # 式の計算
163
- # noinspection PyStatementEffect
164
- swEqnMgr.EvaluateAll # always returns -1
165
-
166
- # プロパティをもとに戻す
167
- swEqnMgr.AutomaticSolveOrder = buffer_aso
168
- swEqnMgr.AutomaticRebuild = buffer_ar
153
+ mgr = SolidworksVariableManager(asm_logger)
154
+ sw_variables: SWVariables = {
155
+ name: str(param.value) + param.properties.get('unit', '')
156
+ for name, param in
157
+ self.current_prm_values.items()
158
+ if isinstance(param.value, float | int)
159
+ }
160
+ mgr.update_global_variables_recourse(swModel, sw_variables)
169
161
 
170
162
  def update_model(self):
171
163
  """Update .sldprt"""
172
164
 
173
165
  # sw はプロセスが一つなので Lock
174
166
  with Lock(self._access_sw_lock_name):
175
-
176
167
  sleep(0.2)
177
168
 
178
- # ===== model を取得 =====
179
169
  swModel = self.swModel
180
-
181
- # モデル再構築
182
170
  result = swModel.EditRebuild3 # モデル再構築
183
171
  if not result:
184
172
  raise ModelError(_(
@@ -218,12 +206,3 @@ def _get_model_by_basename(swApp, basename):
218
206
  if swModel is None:
219
207
  raise FileNotOpenedError(f'Model {basename} is not opened.')
220
208
  return swModel
221
-
222
-
223
- def _get_name_from_equation(equation: str):
224
- pattern = r'^\s*"(.+?)"\s*$'
225
- matched = re.match(pattern, equation.split('=')[0])
226
- if matched:
227
- return matched.group(1)
228
- else:
229
- return None
@@ -0,0 +1,32 @@
1
+ # https://help.solidworks.com/2026/English/api/swconst/SOLIDWORKS.Interop.swconst~SOLIDWORKS.Interop.swconst.swDocumentTypes_e.html
2
+ swDocASSEMBLY = 2
3
+ swDocDRAWING = 3
4
+ swDocIMPORTED_ASSEMBLY = 7
5
+ swDocIMPORTED_PART = 6
6
+ swDocLAYOUT = 5
7
+ swDocNONE = 0
8
+ swDocPART = 1
9
+ swDocSDM = 4
10
+
11
+ # https://help.solidworks.com/2026/English/api/swconst/SOLIDWORKS.Interop.swconst~SOLIDWORKS.Interop.swconst.swOpenDocOptions_e.html
12
+ swOpenDocOptions_AdvancedConfig = 8192 or 0x2000 # Open assembly using an advanced configuration
13
+ swOpenDocOptions_AutoMissingConfig = 32 or 0x20 # Obsolete # do not use
14
+ # The software automatically uses the last-used configuration of a model when it discovers missing configurations or component references as it silently opens drawings and assemblies.
15
+
16
+ swOpenDocOptions_DontLoadHiddenComponents = 256 or 0x100 # By default, hidden components are loaded when you open an assembly document. Set swOpenDocOptions_DontLoadHiddenComponents to not load hidden components when opening an assembly document
17
+ swOpenDocOptions_LDR_EditAssembly = 2048 or 0x800 # Open in Large Design Review (resolved) mode with edit assembly enabled # use in combination with swOpenDocOptions_ViewOnly
18
+ swOpenDocOptions_LoadExternalReferencesInMemory = 512 or 0x200 # Open external references in memory only # this setting is valid only if swUserPreferenceIntegerValue_e.swLoadExternalReferences is not set to swLoadExternalReferences_e.swLoadExternalReferences_None
19
+ # swUserPreferenceToggle_e.swExtRefLoadRefDocsInMemory (System Options > External References > Load documents in memory only) is ignored when opening documents through the API because IDocumentSpecification::LoadExternalReferencesInMemory and ISldWorks::OpenDoc6 (swOpenDocOptions_e.swOpenDocOptions_LoadExternalReferencesInMemory) have sole control of reference loading
20
+
21
+ swOpenDocOptions_LoadLightweight = 128 or 0x80 # Open assembly document as lightweight
22
+ # NOTE: The default for whether an assembly document is opened lightweight is based on a registry setting accessed via Tools, Options, Assemblies or with the user preference setting swAutoLoadPartsLightweight
23
+ # To override the default and specify a value with ISldWorks::OpenDoc6, set swOpenDocOptions_OverrideDefaultLoadLightweight. If set, then you can set swOpenDocOptions_LoadLightweight to open an assembly document as lightweight
24
+
25
+ swOpenDocOptions_LoadModel = 16 or 0x10 # Load Detached model upon opening document (drawings only)
26
+ swOpenDocOptions_OpenDetailingMode = 1024 or 0x400 # Open document in detailing mode
27
+ swOpenDocOptions_OverrideDefaultLoadLightweight = 64 or 0x40 # Override default setting whether to open an assembly document as lightweight
28
+ swOpenDocOptions_RapidDraft = 8 or 0x8 # Convert document to Detached format (drawings only)
29
+ swOpenDocOptions_ReadOnly = 2 or 0x2 # Open document read only
30
+ swOpenDocOptions_Silent = 1 or 0x1 # Open document silently
31
+ swOpenDocOptions_SpeedPak = 4096 or 0x1000 # Open document using the SpeedPak option
32
+ swOpenDocOptions_ViewOnly = 4 or 0x4 # Open document in Large Design Review mode (assemblies only)
@@ -4,6 +4,7 @@ import datetime
4
4
  from typing import Callable, TypeAlias, Sequence, Literal
5
5
  from numbers import Real # マイナーなので型ヒントでは使わず、isinstance で使う
6
6
  from time import sleep
7
+ import os
7
8
 
8
9
  import sympy
9
10
 
@@ -132,6 +133,8 @@ class AbstractOptimizer:
132
133
  *,
133
134
  pass_to_fem: bool = True,
134
135
  ):
136
+ var: Variable
137
+ # noinspection PyUnreachableCode
135
138
  if isinstance(value, Real):
136
139
  var = NumericVariable()
137
140
  elif isinstance(value, str):
@@ -147,7 +150,7 @@ class AbstractOptimizer:
147
150
  var.pass_to_fem = pass_to_fem
148
151
  var.properties = properties if properties is not None else {}
149
152
  _duplicated_name_check(name, self.variable_manager.variables.keys())
150
- self.variable_manager.variables.update({name: var})
153
+ self.variable_manager.set_variable(var)
151
154
 
152
155
  def add_parameter(
153
156
  self,
@@ -175,7 +178,7 @@ class AbstractOptimizer:
175
178
  prm.properties = properties
176
179
  prm.pass_to_fem = pass_to_fem
177
180
  _duplicated_name_check(name, self.variable_manager.variables.keys())
178
- self.variable_manager.variables.update({name: prm})
181
+ self.variable_manager.set_variable(prm)
179
182
 
180
183
  def add_expression_string(
181
184
  self,
@@ -184,14 +187,18 @@ class AbstractOptimizer:
184
187
  properties: dict[str, ...] | None = None,
185
188
  *,
186
189
  pass_to_fem: bool = True,
190
+ _disable_matmul_operator: bool = True
187
191
  ) -> None:
188
192
  var = ExpressionFromString()
189
193
  var.name = name
190
- var._expr = ExpressionFromString.InternalClass(expression_string=expression_string)
194
+ var._expr = ExpressionFromString.InternalClass(
195
+ expression_string=expression_string,
196
+ _disable_matmul_operator=_disable_matmul_operator,
197
+ )
191
198
  var.properties = properties or dict()
192
199
  var.pass_to_fem = pass_to_fem
193
200
  _duplicated_name_check(name, self.variable_manager.variables.keys())
194
- self.variable_manager.variables.update({name: var})
201
+ self.variable_manager.set_variable(var)
195
202
 
196
203
  def add_expression_sympy(
197
204
  self,
@@ -207,7 +214,7 @@ class AbstractOptimizer:
207
214
  var.properties = properties or dict()
208
215
  var.pass_to_fem = pass_to_fem
209
216
  _duplicated_name_check(name, self.variable_manager.variables.keys())
210
- self.variable_manager.variables.update({name: var})
217
+ self.variable_manager.set_variable(var)
211
218
 
212
219
  def add_expression(
213
220
  self,
@@ -227,7 +234,7 @@ class AbstractOptimizer:
227
234
  var.properties = properties or dict()
228
235
  var.pass_to_fem = pass_to_fem
229
236
  _duplicated_name_check(name, self.variable_manager.variables.keys())
230
- self.variable_manager.variables.update({name: var})
237
+ self.variable_manager.set_variable(var)
231
238
 
232
239
  def add_categorical_parameter(
233
240
  self,
@@ -251,7 +258,7 @@ class AbstractOptimizer:
251
258
  prm.properties = properties
252
259
  prm.pass_to_fem = pass_to_fem
253
260
  _duplicated_name_check(name, self.variable_manager.variables.keys())
254
- self.variable_manager.variables.update({name: prm})
261
+ self.variable_manager.set_variable(prm)
255
262
 
256
263
  def add_objective(
257
264
  self,
@@ -279,6 +286,7 @@ class AbstractOptimizer:
279
286
  kwargs: dict | None = None,
280
287
  ):
281
288
  # argument processing
289
+ # noinspection PyUnreachableCode
282
290
  if isinstance(names, str):
283
291
  names = [f'{names}_{i}' for i in range(n_return)]
284
292
  elif isinstance(names, Sequence):
@@ -465,7 +473,7 @@ class AbstractOptimizer:
465
473
  raise NotImplementedError
466
474
  return violation_names
467
475
 
468
- def _check_and_raise_interruption(self) -> ...:
476
+ def _check_and_raise_interruption(self):
469
477
  # raise Interrupt
470
478
  interrupted = self.entire_status.value >= WorkerStatus.interrupting
471
479
  if interrupted:
@@ -703,7 +711,7 @@ class AbstractOptimizer:
703
711
  self,
704
712
  x: TrialInput,
705
713
  opt_: AbstractOptimizer | None = None,
706
- trial_id: str =None,
714
+ trial_id: str = None,
707
715
  ) -> _FReturnValue | None:
708
716
  """Nothing will be raised even if infeasible."""
709
717
 
@@ -871,6 +879,10 @@ class AbstractOptimizer:
871
879
 
872
880
  self.worker_status.value = WorkerStatus.running
873
881
 
882
+ if os.environ.get('DEBUG_FEMOPT_PARALLEL'):
883
+ if isinstance(worker_idx, int):
884
+ sleep(worker_idx)
885
+
874
886
  self.run()
875
887
 
876
888
  logger.info(_(
@@ -4,6 +4,8 @@ from sympy import sympify
4
4
  from sympy.core.sympify import SympifyError
5
5
  from sympy import Min, Max, Add, Symbol, Expr, Basic # TODO: Add sqrt, pow
6
6
 
7
+ from pyfemtet._util.atmark_support_for_param_name import at, AT
8
+
7
9
  __all__ = [
8
10
  '_ExpressionFromString', 'InvalidExpression', 'SympifyError'
9
11
  ]
@@ -27,7 +29,12 @@ class _ExpressionFromString:
27
29
  _expr_str: str
28
30
  _sympy_expr: Expr
29
31
 
30
- def __init__(self, expression_string: str | Number = None, sympy_expr: Expr = None):
32
+ def __init__(
33
+ self,
34
+ expression_string: str | Number = None,
35
+ sympy_expr: Expr = None,
36
+ _disable_matmul_operator: bool = True, # @ を文字式で使えるように文字列中の @ を AT に変換する
37
+ ):
31
38
  """
32
39
  Raises:
33
40
  SympifyError: Sympy が認識できない場合
@@ -66,6 +73,8 @@ class _ExpressionFromString:
66
73
 
67
74
  else:
68
75
  assert expression_string is not None
76
+ if _disable_matmul_operator:
77
+ expression_string = expression_string.replace(at, AT)
69
78
  self._expr_str: str = str(expression_string)
70
79
 
71
80
  # max(name1, name2) など関数を入れる際に問題になるので
@@ -3,12 +3,14 @@ from typing import Callable, TypeAlias, Literal
3
3
  import inspect
4
4
  from numbers import Real # マイナーなので型ヒントには使わず isinstance で使う
5
5
  from graphlib import TopologicalSorter
6
+ import unicodedata
6
7
 
7
8
  import numpy as np
8
9
 
9
10
  from ._string_as_expression import _ExpressionFromString
10
11
 
11
12
  from pyfemtet._i18n import _
13
+ from pyfemtet._util.atmark_support_for_param_name import at, AT
12
14
 
13
15
  __all__ = [
14
16
  'SupportedVariableTypes',
@@ -320,13 +322,16 @@ class VariableManager:
320
322
  if filter is not None:
321
323
  if 'pass_to_fem' in filter:
322
324
  if var.pass_to_fem:
325
+ name = var.properties.get('original_name', name)
323
326
  raw.update({name: var})
324
327
 
325
328
  if 'parameter' in filter:
326
329
  if isinstance(var, Parameter):
330
+ name = var.properties.get('original_name', name)
327
331
  raw.update({name: var})
328
332
 
329
333
  else:
334
+ name = var.properties.get('original_name', name)
330
335
  raw.update({name: var})
331
336
 
332
337
  if format is None:
@@ -350,3 +355,14 @@ class VariableManager:
350
355
  format=format,
351
356
  )
352
357
  )
358
+
359
+ def set_variable(self, variable: Variable):
360
+ original_name = variable.name
361
+ variable.properties.update(
362
+ {'original_name': original_name}
363
+ )
364
+ if at in variable.name:
365
+ variable.name = variable.name.replace(at, AT)
366
+ if not unicodedata.is_normalized('NFKC', variable.name):
367
+ variable.name = unicodedata.normalize('NFKC', variable.name)
368
+ self.variables.update({variable.name: variable})
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pyfemtet
3
- Version: 1.1.5
3
+ Version: 1.2.0
4
4
  Summary: Design parameter optimization using Femtet.
5
5
  License-Expression: MIT
6
6
  License-File: LICENSE
@@ -7,8 +7,9 @@ pyfemtet/_i18n/i18n.py,sha256=zBbatQO7bkyO1MU6Y8TtrhGpDoUMP2PetRyWsINVcHc,808
7
7
  pyfemtet/_i18n/locales/ja/LC_MESSAGES/messages.mo,sha256=wjYhvR2TUpjHCBowrW2bQYUxKmnEi3d8GBPgseadRGw,34424
8
8
  pyfemtet/_i18n/locales/ja/LC_MESSAGES/messages.po,sha256=ktqUESvDUja2LQJDo-oEv58FH6klUmpu3lAoITtR_NQ,48313
9
9
  pyfemtet/_i18n/locales/messages.pot,sha256=krqoEumXnY45pG5dm-dQPmynb-eNx1BbIfbHB0URCvE,30025
10
- pyfemtet/_i18n/messages.py,sha256=mzTARnpZPZ-Pmcq8RdOyy5a4XGCCSxwxuoHjN_HJ0TM,17382
10
+ pyfemtet/_i18n/messages.py,sha256=AvGLbs_ELTIBm4nCeDyaXWsEiTPuGkYVAjlp_TCfxmo,16994
11
11
  pyfemtet/_util/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
12
+ pyfemtet/_util/atmark_support_for_param_name.py,sha256=VYEqcyJ_rZIPT2irNtGVyOp163XZuO6jWlC_NyFwVOw,21
12
13
  pyfemtet/_util/closing.py,sha256=JPcgHDbW249YF20bMOX6UX-LquWoCWA14KhX-qFouR4,502
13
14
  pyfemtet/_util/dask_util.py,sha256=ekzOFqSOIHyB8KK5--ndM2xBdueIfS1pi-inOLj6JT4,2198
14
15
  pyfemtet/_util/df_util.py,sha256=UVJZcTqVe_98aGAqF9Sp4b6BC5c_c3ADRsZ2RUJcN0Y,1889
@@ -21,6 +22,7 @@ pyfemtet/_util/femtet_version.py,sha256=9bWRMC_Exb-3rh5bg9eKfwBcgkxz_vg_eX99RPuk
21
22
  pyfemtet/_util/helper.py,sha256=chlfSDQ764kn0mVgBXj8WXKBrje25AX6Riia8W5zkJo,2543
22
23
  pyfemtet/_util/process_util.py,sha256=_hiRTZVZll8tnlBfXvz6GcBue4aE__jA0KnsVXe6m2A,3038
23
24
  pyfemtet/_util/sample.xlsx,sha256=OU8mBY48YESJFQrdt4OkntlE1z-6WiyUyOV-PMr09DQ,9423
25
+ pyfemtet/_util/solidworks_variable.py,sha256=aZqDH1Jx5rpK2paFyKL8RODV0jmEfq1pKVCsSmr40GA,6969
24
26
  pyfemtet/_util/str_enum.py,sha256=b-mQRUsSZvk4zupYTxxSaOm3rtxfNyOajywZ82x9rmk,1441
25
27
  pyfemtet/core.py,sha256=t5tvWGrBNzCL9cP-91hbTR8q5lzULPsVeIEybeslhxQ,936
26
28
  pyfemtet/dispatch_extensions/__init__.py,sha256=BzxYq3x8YdkdClq4VvH4G5HTGxu5nyAhN7xlFsnTv8c,159
@@ -29,20 +31,20 @@ pyfemtet/logger/__init__.py,sha256=lofBrZHr0P1hsxPUiPG1SQqKxCuSBk8zGnR7vUfCHYw,5
29
31
  pyfemtet/logger/_impl.py,sha256=tR71WZbjUvnZqULzxD4Y8Vhq8eBnJhMm360-JXxB5Dc,7012
30
32
  pyfemtet/opt/__init__.py,sha256=1LcwTddtoi8plemxkzmX0YEKiNpAZvKn9OoNQysyDLE,339
31
33
  pyfemtet/opt/exceptions.py,sha256=M_O7jm20Y4e_QxsKF6tnEl-OrAtErUOj6hNT7eEXCO4,1327
32
- pyfemtet/opt/femopt.py,sha256=Zht_H_eaTUwUcA7XFlzod0mGoJzTOZckqRK3VuwjaHM,23716
34
+ pyfemtet/opt/femopt.py,sha256=d-w9enC_XG-4ScIE26PvnoQNqVBXWyveade0wrEcDTM,23827
33
35
  pyfemtet/opt/history/__init__.py,sha256=pUp3SO4R7RGzmpNDLBg_pQH0X2yzBd-oqsHXWmB33os,201
34
36
  pyfemtet/opt/history/_history.py,sha256=K1k-iOSFoowqKPVZgvWEhdysO9ZsMuqEQ-P_kvO-T3U,54587
35
37
  pyfemtet/opt/history/_hypervolume.py,sha256=_IvGH71ZNreWvDQCG815Q2hS1OEvPFPQhUnNXf1UxRQ,4449
36
38
  pyfemtet/opt/history/_optimality.py,sha256=6vLySZmrrklr04Qir0hGethTykf8NYFod88NDGrBrG0,2407
37
39
  pyfemtet/opt/interface/__init__.py,sha256=b2lfkBL-UPbzJppIqSgtUqHSHitPLQa6DRuH91nDZK8,1905
38
- pyfemtet/opt/interface/_base_interface.py,sha256=QODB9d4xZu8-T7-BxOiz6s33HXtX9FG6kfA8qv4qWs8,6681
40
+ pyfemtet/opt/interface/_base_interface.py,sha256=iWJmJ8kxRH-Cztfhy3QKfRhSKRMytBtjGqgVjVavoPw,6689
39
41
  pyfemtet/opt/interface/_dummy_classes.py,sha256=847zs3SwetMpRsGtivhvST_z2UKavKvTfUBZvkYfqB0,505
40
42
  pyfemtet/opt/interface/_excel_interface/__init__.py,sha256=bFOmY18-j4RJc_dHQMe62GsxFwQSj7RWdvi6jxWuqyg,74
41
43
  pyfemtet/opt/interface/_excel_interface/debug-excel-interface.xlsm,sha256=TM1CEOC5XtU7qYKNnHScO02kdtXT-gc5y29m2hatsm0,114259
42
- pyfemtet/opt/interface/_excel_interface/excel_interface.py,sha256=x_pKZzjCc_c2HuypHY5wIaRVtjKa48SYbmqtmduLldM,39680
44
+ pyfemtet/opt/interface/_excel_interface/excel_interface.py,sha256=Sghavj7bcslQ5ue9xJzV6DdBfhv6XKn-XxKD-T39KEo,39854
43
45
  pyfemtet/opt/interface/_femtet_interface/__init__.py,sha256=snQruC8Rl_5rFeVmiqw9lmzdJ5mL42HpIlHIn5ytd8s,77
44
46
  pyfemtet/opt/interface/_femtet_interface/_femtet_parametric.py,sha256=dEe6udq2CBpXAcKCye90sXC0UVKok14LORitobc8DK8,10282
45
- pyfemtet/opt/interface/_femtet_interface/femtet_interface.py,sha256=8Z4yNpyqXXaqj_aBg7x4l2x63lAOfLQ6VKSP4sx-X5g,45309
47
+ pyfemtet/opt/interface/_femtet_interface/femtet_interface.py,sha256=ptvklQdKwSq9sW712Y4-sO4nTZPVfjrDdBToGOyQoIE,45717
46
48
  pyfemtet/opt/interface/_femtet_with_nx_interface/__init__.py,sha256=ppeoWVSmVsTmDNKpuFRVTnhjcoefQVEog3-FRiKpEe4,104
47
49
  pyfemtet/opt/interface/_femtet_with_nx_interface/femtet_with_nx_interface.py,sha256=IPIoNMtcJmtiv7eM3yDMWDOynTf0mXd-438LoDVqZCU,8628
48
50
  pyfemtet/opt/interface/_femtet_with_nx_interface/model1.prt,sha256=cYVw2izr4_9PCPHOpi46XmDVOuNZ5ksuwKqzBtCZfNA,104833
@@ -51,7 +53,8 @@ pyfemtet/opt/interface/_femtet_with_nx_interface/update_model.py,sha256=2U5SJWnG
51
53
  pyfemtet/opt/interface/_femtet_with_solidworks/__init__.py,sha256=5McSpy2uTmJNBylCrKt4xMSq90hlSpqyXYsjwZT3yGA,128
52
54
  pyfemtet/opt/interface/_femtet_with_solidworks/femtet_with_solidworks_interface.py,sha256=xBAmHbzNrmHI6zzwUMX_mdjUkhRfyqzmYQN2_QNZcfE,5897
53
55
  pyfemtet/opt/interface/_solidworks_interface/__init__.py,sha256=2c52Hfme1xdJepewRGVkPT4yhrZMQgzlCuqvHzEZPVk,95
54
- pyfemtet/opt/interface/_solidworks_interface/solidworks_interface.py,sha256=KkXfXJ5IaTl2pJXBlH25rdmsKFWUbqNTk3sGjD3Qgys,8408
56
+ pyfemtet/opt/interface/_solidworks_interface/solidworks_interface.py,sha256=qJIC6Qg7slskDwKDRTFYKzbftqseUaYveRTtOdZA_EQ,8370
57
+ pyfemtet/opt/interface/_solidworks_interface/sw_const.py,sha256=M6KV0KmRiSOofW4ydV-3Zxqzofz4ij13CsM3Ggw6HS4,3085
55
58
  pyfemtet/opt/interface/_surrogate_model_interface/__init__.py,sha256=9sjzQjJsMLdpBSpURyl8x4VQHEO_PGYgAshCHoycAPI,252
56
59
  pyfemtet/opt/interface/_surrogate_model_interface/base_surrogate_interface.py,sha256=48mUOPgOVi_SRs_VnElgh6BMUJHQG9jzWpCocK_gjiY,6355
57
60
  pyfemtet/opt/interface/_surrogate_model_interface/botorch_interface.py,sha256=JsFDs5GzlsstpyXjTYpUi_ctWlcEKliX3qMr4HBPj_E,10570
@@ -64,7 +67,7 @@ pyfemtet/opt/meta_script/__main__.py,sha256=9-QM6eZOLpZ_CxERpRu3RAMqpudorSJdPCiK
64
67
  pyfemtet/opt/meta_script/sample/sample.bas,sha256=2iuSYMgPDyAdiSDVGxRu3avjcZYnULz0l8e25YBa7SQ,27966
65
68
  pyfemtet/opt/meta_script/sample/sample.femprj,sha256=6_0ywhgXxZjdzZzQFog8mgMUEjKNCFVNlEgAWoptovk,292885
66
69
  pyfemtet/opt/optimizer/__init__.py,sha256=A4QYeF0KHEFdwoxLfkDND7ikDQ186Ryy3oXEGdakFSg,463
67
- pyfemtet/opt/optimizer/_base_optimizer.py,sha256=o7XYqAJywX-gnXu2iyKXRKAhyIklZxbAuLitTn23_-Q,37445
70
+ pyfemtet/opt/optimizer/_base_optimizer.py,sha256=z3NQyKSQkRHHlf1UWYWVnAQaBIMpX92qWdBlh-NfE4A,37760
68
71
  pyfemtet/opt/optimizer/_trial_queue.py,sha256=Yv6JlfVCYOiCukllfxk79xU4_utmxwRA3gcCWpdyG9k,2919
69
72
  pyfemtet/opt/optimizer/optuna_optimizer/__init__.py,sha256=u2Bwc79tkZTU5dMbhzzrPQi0RlFg22UgXc-m9K9G6wQ,242
70
73
  pyfemtet/opt/optimizer/optuna_optimizer/_optuna_attribute.py,sha256=7eZsruVCGgMlcnf3a9Vf55FOEE-D7V777MJQajI12Cw,1842
@@ -84,8 +87,8 @@ pyfemtet/opt/prediction/_model.py,sha256=uw3CW_sNkoFa3Cn_ek3_Tr2lYl4ClptKGIpmRF2
84
87
  pyfemtet/opt/problem/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
85
88
  pyfemtet/opt/problem/problem.py,sha256=X9mro2yVJ6Uw9ck0F0OjG-0M2ReKtuWltu-JUEFIkzQ,10025
86
89
  pyfemtet/opt/problem/variable_manager/__init__.py,sha256=uzuraWUZfLzB3uZHIQHFL7uMxWvv7Oaf940zEozXtNY,476
87
- pyfemtet/opt/problem/variable_manager/_string_as_expression.py,sha256=aTJ9W9Gs6BS0Z_OsxWByJs9dAt32opD2_9913MCggPg,3626
88
- pyfemtet/opt/problem/variable_manager/_variable_manager.py,sha256=jtIHFWgVP2jhA3c5uSD388VZHuShR25ZZ8SYz5-6Rro,12785
90
+ pyfemtet/opt/problem/variable_manager/_string_as_expression.py,sha256=cMi4yuBHwypXFj3LVCGwkoP95jPzy_Uf17j9td5qciE,3975
91
+ pyfemtet/opt/problem/variable_manager/_variable_manager.py,sha256=A0EAsv5fIfVq_ehml4ZGt_jaopIT6HEWgvUaM-CtcLE,13542
89
92
  pyfemtet/opt/visualization/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
90
93
  pyfemtet/opt/visualization/_create_wrapped_components.py,sha256=9AltJHr1DM6imZfpNp867rC-uAYqQ-emdgTLChKDrl8,2513
91
94
  pyfemtet/opt/visualization/history_viewer/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -171,9 +174,9 @@ pyfemtet/opt/visualization/plotter/parallel_plot_creator.py,sha256=VRhT0CUG1mCHD
171
174
  pyfemtet/opt/visualization/plotter/pm_graph_creator.py,sha256=7EwmoJlnHwDrpw65NchiA63FIjgGTLq6vTcpTzrSnJo,11841
172
175
  pyfemtet/opt/wat_ex14_parametric_jp.femprj,sha256=dMwQMt6yok_PbZLyxPYdmg5wJQwgQDZ4RhS76zdGLGk,177944
173
176
  pyfemtet/opt/worker_status.py,sha256=simvPa1AkO1idmPXrF5WjYVEBx3tO7hLhbM3J1rFjdo,3824
174
- pyfemtet-1.1.5.dist-info/METADATA,sha256=wWktO1slosfUsyfHUxASVT6iauIeAypOMwE2A7YvbeE,3410
175
- pyfemtet-1.1.5.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
176
- pyfemtet-1.1.5.dist-info/entry_points.txt,sha256=Tsb_l_8Z6pyyq2tRfuKiwfJUV3nq_cHoLS61foALtsg,134
177
- pyfemtet-1.1.5.dist-info/licenses/LICENSE,sha256=LWUL5LlMGjSRTvsalS8_fFuwS4VMw18fJSNWFwDK8pc,1060
178
- pyfemtet-1.1.5.dist-info/licenses/LICENSE_THIRD_PARTY.txt,sha256=8_9-cgzTpmeuCqItPZb9-lyAZcH2Qp9sZTU_hYuOZIQ,191
179
- pyfemtet-1.1.5.dist-info/RECORD,,
177
+ pyfemtet-1.2.0.dist-info/METADATA,sha256=YboufM-Eq_m9_BjcX9ckcoGuCDVC44kIVCj0q22ufj8,3410
178
+ pyfemtet-1.2.0.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
179
+ pyfemtet-1.2.0.dist-info/entry_points.txt,sha256=Tsb_l_8Z6pyyq2tRfuKiwfJUV3nq_cHoLS61foALtsg,134
180
+ pyfemtet-1.2.0.dist-info/licenses/LICENSE,sha256=LWUL5LlMGjSRTvsalS8_fFuwS4VMw18fJSNWFwDK8pc,1060
181
+ pyfemtet-1.2.0.dist-info/licenses/LICENSE_THIRD_PARTY.txt,sha256=8_9-cgzTpmeuCqItPZb9-lyAZcH2Qp9sZTU_hYuOZIQ,191
182
+ pyfemtet-1.2.0.dist-info/RECORD,,