pyfemtet 0.4.3__py3-none-any.whl → 0.4.5__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.

pyfemtet/__init__.py CHANGED
@@ -1 +1 @@
1
- __version__ = "0.4.3"
1
+ __version__ = "0.4.5"
pyfemtet/opt/_femopt.py CHANGED
@@ -81,6 +81,7 @@ class FEMOpt:
81
81
  self.monitor_process_future = None
82
82
  self.monitor_server_kwargs = dict()
83
83
  self.monitor_process_worker_name = None
84
+ self._is_error_exit = False
84
85
 
85
86
  # multiprocess 時に pickle できないオブジェクト参照の削除
86
87
  def __getstate__(self):
@@ -328,12 +329,27 @@ class FEMOpt:
328
329
  subprocess_indices = list(range(n_parallel))
329
330
  worker_addresses = list(self.client.nthreads().keys())
330
331
 
332
+ # worker が足りない場合はエラー
333
+ if n_parallel > len(worker_addresses):
334
+ raise RuntimeError(f'n_parallel({n_parallel}) > n_workers({len(worker_addresses)}). Worker 数が不足しています。')
335
+
336
+ # worker が多い場合は閉じる
337
+ if n_parallel < len(worker_addresses):
338
+ used_worker_addresses = worker_addresses[:n_parallel] # 前から順番に選ぶ:CPU の早い / メモリの多い順に並べることが望ましい
339
+ unused_worker_addresses = worker_addresses[n_parallel:]
340
+ self.client.retire_workers(unused_worker_addresses, close_workers=True)
341
+ worker_addresses = used_worker_addresses
342
+
331
343
  # monitor worker の設定
332
344
  logger.info('Launching monitor server. This may take a few seconds.')
333
- self.monitor_process_worker_name = datetime.datetime.now().strftime("Monitor-%Y%m%d-%H%M%S")
345
+ self.monitor_process_worker_name = datetime.datetime.now().strftime("Monitor%Y%m%d%H%M%S")
334
346
  current_n_workers = len(self.client.nthreads().keys())
335
- from dask.distributed import Worker
336
- Worker(scheduler_ip=self.client.scheduler.address, nthreads=1, name=self.monitor_process_worker_name)
347
+ from subprocess import Popen
348
+ import sys
349
+ Popen(
350
+ f'{sys.executable} -m dask worker {self.client.scheduler.address} --nthreads 1 --nworkers 1 --name {self.monitor_process_worker_name} --no-nanny',
351
+ shell=True
352
+ )
337
353
 
338
354
  # monitor 用 worker が増えるまで待つ
339
355
  self.client.wait_for_workers(n_workers=current_n_workers + 1)
@@ -357,12 +373,17 @@ class FEMOpt:
357
373
  # Femtet 特有の処理
358
374
  metadata = None
359
375
  if isinstance(self.fem, FemtetInterface):
376
+ # 結果 csv に記載する femprj に関する情報
360
377
  metadata = json.dumps(
361
378
  dict(
362
379
  femprj_path=self.fem.original_femprj_path,
363
380
  model_name=self.fem.model_name
364
381
  )
365
382
  )
383
+ # Femtet の parametric 設定を目的関数に用いるかどうか
384
+ if self.fem.parametric_output_indexes_use_as_objective is not None:
385
+ from pyfemtet.opt.interface._femtet_parametric import add_parametric_results_as_objectives
386
+ add_parametric_results_as_objectives(self, self.fem.parametric_output_indexes_use_as_objective)
366
387
 
367
388
  # actor の設定
368
389
  self.status = OptimizationStatus(self.client)
@@ -389,7 +410,7 @@ class FEMOpt:
389
410
  # kwargs
390
411
  **self.monitor_server_kwargs,
391
412
  # kwargs of submit
392
- workers=self.monitor_process_worker_name, # if invalid arg,
413
+ workers=self.monitor_process_worker_name,
393
414
  allow_other_workers=False
394
415
  )
395
416
 
@@ -452,10 +473,13 @@ class FEMOpt:
452
473
  t_save_history.start()
453
474
 
454
475
  # 終了を待つ
455
- self.client.gather(calc_futures)
476
+ local_opt_crashed = False
477
+ opt_crashed_list = self.client.gather(calc_futures)
456
478
  if not self.opt.is_cluster: # 既存の fem を使っているならそれも待つ
457
479
  if t_main is not None:
458
480
  t_main.join()
481
+ local_opt_crashed = self.opt._is_error_exit
482
+ opt_crashed_list.append(local_opt_crashed)
459
483
  self.status.set(OptimizationStatus.TERMINATED)
460
484
  end = time()
461
485
 
@@ -465,6 +489,13 @@ class FEMOpt:
465
489
  logger.info(f'計算が終了しました. 実行時間は {int(end - start)} 秒でした。ウィンドウを閉じると終了します.')
466
490
  logger.info(f'結果は{self.history.path}を確認してください.')
467
491
 
492
+ # ひとつでも crashed ならばフラグを立てる
493
+ if any(opt_crashed_list):
494
+ self._is_error_exit = True
495
+
496
+ return self.history.local_data
497
+
498
+
468
499
  def terminate_all(self):
469
500
  """Try to terminate all launched processes.
470
501
 
@@ -476,7 +507,10 @@ class FEMOpt:
476
507
  sleep(1)
477
508
 
478
509
  # terminate monitor process
479
- self.status.set(OptimizationStatus.TERMINATE_ALL)
510
+ if self._is_error_exit:
511
+ self.status.set(OptimizationStatus.CRASHED)
512
+ else:
513
+ self.status.set(OptimizationStatus.TERMINATE_ALL)
480
514
  logger.info(self.monitor_process_future.result())
481
515
  sleep(1)
482
516
 
@@ -514,22 +548,20 @@ class FEMOpt:
514
548
  else:
515
549
  logger.warn('Monitor process worker not found.')
516
550
 
517
- # close scheduler, other workers(, cluster)
518
- self.client.close()
519
- while self.client.scheduler is not None:
520
- sleep(1)
521
- logger.info('Terminate client.')
522
-
523
551
  # close FEM (if specified to quit when deconstruct)
524
552
  del self.fem
525
553
  logger.info('Terminate FEM.')
554
+ sleep(1)
526
555
 
527
- # terminate dask relative processes.
528
- if not self.opt.is_cluster:
529
- self.client.shutdown()
530
- logger.info('Terminate all relative processes.')
556
+ # close scheduler, other workers(, cluster)
557
+ self.client.shutdown()
558
+ logger.info('Terminate all relative processes.')
531
559
  sleep(3)
532
560
 
561
+ # if optimization was crashed, raise Exception
562
+ if self._is_error_exit:
563
+ raise RuntimeError('At least 1 of optimization processes have been crashed. See console log.')
564
+
533
565
 
534
566
  def _start_monitor_server(
535
567
  history,
@@ -7,6 +7,7 @@ import datetime
7
7
  import inspect
8
8
  import ast
9
9
  import csv
10
+ import ctypes
10
11
 
11
12
  # 3rd-party
12
13
  import numpy as np
@@ -197,9 +198,12 @@ class Function:
197
198
 
198
199
  # serializable でない COM 定数を parallelize するため
199
200
  # COM 定数を一度 _Scapegoat 型のオブジェクトにする
200
- for varname in fun.__globals__:
201
- if isinstance(fun.__globals__[varname], Constants):
202
- fun.__globals__[varname] = _Scapegoat()
201
+ # ParametricIF で使う dll 関数は _FuncPtr 型であって __globals__ を持たないが、
202
+ # これは絶対に constants を持たないので単に無視すればよい。
203
+ if not isinstance(fun, ctypes._CFuncPtr):
204
+ for varname in fun.__globals__:
205
+ if isinstance(fun.__globals__[varname], Constants):
206
+ fun.__globals__[varname] = _Scapegoat()
203
207
 
204
208
  self.fun = fun
205
209
  self.name = name
@@ -224,10 +228,11 @@ class Function:
224
228
  def _restore_constants(self):
225
229
  """Helper function for parallelize Femtet."""
226
230
  fun = self.fun
227
- for varname in fun.__globals__:
228
- if isinstance(fun.__globals__[varname], _Scapegoat):
229
- if not fun.__globals__[varname]._ignore_when_restore_constants:
230
- fun.__globals__[varname] = constants
231
+ if not isinstance(fun, ctypes._CFuncPtr):
232
+ for varname in fun.__globals__:
233
+ if isinstance(fun.__globals__[varname], _Scapegoat):
234
+ if not fun.__globals__[varname]._ignore_when_restore_constants:
235
+ fun.__globals__[varname] = constants
231
236
 
232
237
 
233
238
  class Objective(Function):
@@ -691,6 +696,7 @@ class OptimizationStatus:
691
696
  RUNNING = 30
692
697
  INTERRUPTING = 40
693
698
  TERMINATED = 50
699
+ CRASHED = 55
694
700
  TERMINATE_ALL = 60
695
701
 
696
702
  def __init__(self, client, name='entire'):
@@ -712,6 +718,7 @@ class OptimizationStatus:
712
718
  if status_const == cls.INTERRUPTING: return 'Interrupting'
713
719
  if status_const == cls.TERMINATED: return 'Terminated'
714
720
  if status_const == cls.TERMINATE_ALL: return 'Terminate_all'
721
+ if status_const == cls.CRASHED: return 'Crashed'
715
722
 
716
723
  def set(self, status_const):
717
724
  """Set optimization status."""
@@ -39,6 +39,9 @@ class FemtetInterface(FEMInterface):
39
39
  model_name (str or None, optional): The name of the analysis model. Defaults to None.
40
40
  connect_method (str, optional): The connection method to use. Can be 'new', 'existing', or 'auto'. Defaults to 'auto'.
41
41
  strictly_pid_specify (bool, optional): If True and connect_method=='new', search launched Femtet process strictly based on its process id.
42
+ allow_without_project (bool, optional): Allow to launch Femtet with no project file. Default to False.
43
+ open_result_with_gui (bool, optional): Open analysis result with Femtet GUI. Default to True.
44
+ parametric_output_indexes_use_as_objective (list of int, optional): Parametric output indexes which will be used as objective functions. Parametric output should be set on Femtet parametric analysis dialog. Note that output 'No.' in dialog is starts with 1, but this 'index' is starts with 0. Default to None.
42
45
 
43
46
  Warning:
44
47
  Even if you specify ``strictly_pid_specify=True`` on the constructor,
@@ -60,6 +63,7 @@ class FemtetInterface(FEMInterface):
60
63
  strictly_pid_specify=True,
61
64
  allow_without_project=False,
62
65
  open_result_with_gui=True,
66
+ parametric_output_indexes_use_as_objective=None,
63
67
  **kwargs # 継承されたクラスからの引数
64
68
  ):
65
69
 
@@ -85,6 +89,10 @@ class FemtetInterface(FEMInterface):
85
89
  self.parameters = None
86
90
  self.max_api_retry = 3
87
91
  self.strictly_pid_specify = strictly_pid_specify
92
+ if parametric_output_indexes_use_as_objective is None:
93
+ self.parametric_output_indexes_use_as_objective = []
94
+ else:
95
+ self.parametric_output_indexes_use_as_objective = parametric_output_indexes_use_as_objective
88
96
 
89
97
  # dask サブプロセスのときは femprj を更新し connect_method を new にする
90
98
  try:
@@ -111,6 +119,7 @@ class FemtetInterface(FEMInterface):
111
119
  femprj_path=self.femprj_path,
112
120
  model_name=self.model_name,
113
121
  open_result_with_gui=self.open_result_with_gui,
122
+ parametric_output_indexes_use_as_objective=self.parametric_output_indexes_use_as_objective,
114
123
  **kwargs
115
124
  )
116
125
 
@@ -203,7 +212,7 @@ class FemtetInterface(FEMInterface):
203
212
  def _call_femtet_api(
204
213
  self,
205
214
  fun,
206
- ret_if_failed,
215
+ return_value_if_failed,
207
216
  if_error,
208
217
  error_message,
209
218
  is_Gaudi_method=False,
@@ -219,7 +228,7 @@ class FemtetInterface(FEMInterface):
219
228
  ----------
220
229
  fun : Callable
221
230
  Femtet API
222
- ret_if_failed : Any
231
+ return_value_if_failed : Any
223
232
  API が失敗した時の戻り値
224
233
  if_error : Type
225
234
  エラーが発生していたときに送出したい Exception
@@ -278,9 +287,9 @@ class FemtetInterface(FEMInterface):
278
287
  except com_error:
279
288
  # パターン 2 エラーが生じたことは確定なのでエラーが起こるよう returns を作る
280
289
  if ret_for_check_idx is None:
281
- returns = ret_if_failed
290
+ returns = return_value_if_failed
282
291
  else:
283
- returns = [ret_if_failed] * (ret_for_check_idx + 1)
292
+ returns = [return_value_if_failed] * (ret_for_check_idx + 1)
284
293
  logger.debug(' ' * print_indent + f'Femtet API result:{returns}')
285
294
 
286
295
  # チェックすべき値の抽出
@@ -290,7 +299,7 @@ class FemtetInterface(FEMInterface):
290
299
  ret_for_check = returns[ret_for_check_idx]
291
300
 
292
301
  # エラーのない場合は戻り値を return する
293
- if ret_for_check != ret_if_failed:
302
+ if ret_for_check != return_value_if_failed:
294
303
  return returns
295
304
 
296
305
  # エラーがある場合は Femtet の生死をチェックし,
@@ -324,7 +333,7 @@ class FemtetInterface(FEMInterface):
324
333
  logger.info(' ' * print_indent + f'Femtet が回復されました。コマンド {fun.__name__} を再試行します。')
325
334
  return self._call_femtet_api(
326
335
  fun,
327
- ret_if_failed,
336
+ return_value_if_failed,
328
337
  if_error,
329
338
  error_message,
330
339
  is_Gaudi_method,
@@ -453,7 +462,7 @@ class FemtetInterface(FEMInterface):
453
462
  # Femtet の設計変数の更新
454
463
  existing_variable_names = self._call_femtet_api(
455
464
  fun=self.Femtet.GetVariableNames_py,
456
- ret_if_failed=False, # 意味がない
465
+ return_value_if_failed=False, # 意味がない
457
466
  if_error=ModelError, # 生きてるのに失敗した場合
458
467
  error_message=f'GetVariableNames_py に失敗しました。',
459
468
  is_Gaudi_method=True,
@@ -474,7 +483,7 @@ class FemtetInterface(FEMInterface):
474
483
  if name in existing_variable_names:
475
484
  self._call_femtet_api(
476
485
  fun=self.Femtet.UpdateVariable,
477
- ret_if_failed=False,
486
+ return_value_if_failed=False,
478
487
  if_error=ModelError, # 生きてるのに失敗した場合
479
488
  error_message=f'変数の更新に失敗しました:変数{name}, 値{value}',
480
489
  is_Gaudi_method=True,
@@ -493,7 +502,7 @@ class FemtetInterface(FEMInterface):
493
502
  value = row['value']
494
503
  self._call_femtet_api(
495
504
  fun=self.Femtet.UpdateVariable,
496
- ret_if_failed=False,
505
+ return_value_if_failed=False,
497
506
  if_error=ModelError, # 生きてるのに失敗した場合
498
507
  error_message=f'変数の更新に失敗しました:変数{name}, 値{value}',
499
508
  is_Gaudi_method=True,
@@ -546,14 +555,25 @@ class FemtetInterface(FEMInterface):
546
555
  is_Gaudi_method=True,
547
556
  )
548
557
 
549
- # # ソルブする
550
- self._call_femtet_api(
551
- self.Femtet.Solve,
552
- False,
553
- SolveError,
554
- 'ソルブに失敗しました',
555
- is_Gaudi_method=True,
556
- )
558
+ if self.parametric_output_indexes_use_as_objective is not None:
559
+ from pyfemtet.opt.interface._femtet_parametric import solve_via_parametric_dll
560
+ self._call_femtet_api(
561
+ fun=solve_via_parametric_dll,
562
+ return_value_if_failed=False,
563
+ if_error=SolveError,
564
+ error_message='パラメトリック解析を用いたソルブに失敗しました',
565
+ is_Gaudi_method=True,
566
+ args=(self.Femtet,),
567
+ )
568
+ else:
569
+ # # ソルブする
570
+ self._call_femtet_api(
571
+ self.Femtet.Solve,
572
+ False,
573
+ SolveError,
574
+ 'ソルブに失敗しました',
575
+ is_Gaudi_method=True,
576
+ )
557
577
 
558
578
  # 次に呼ばれるはずのユーザー定義コスト関数の記述を簡単にするため先に解析結果を開いておく
559
579
  self._call_femtet_api(
@@ -0,0 +1,88 @@
1
+ from pyfemtet.dispatch_extensions import _get_pid
2
+
3
+ import winreg
4
+ import ctypes
5
+
6
+
7
+ def _get_dll(Femtet):
8
+ femtet_major_version = _get_femtet_major_version(Femtet)
9
+ dll_path = _get_parametric_dll_path(femtet_major_version)
10
+ return ctypes.cdll.LoadLibrary(dll_path)
11
+
12
+
13
+ def _get_femtet_major_version(Femtet):
14
+ from pyfemtet.core import _version
15
+ version_int8 = _version(Femtet=Femtet)
16
+ return str(version_int8)[0:4]
17
+
18
+
19
+ def _get_parametric_dll_path(femtet_major_version) -> str:
20
+ key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, r'SOFTWARE\FemtetInfo\InstallVersion\x64')
21
+ _, nValues, _ = winreg.QueryInfoKey(key)
22
+ for i in range(nValues):
23
+ name, data, _ = winreg.EnumValue(key, i)
24
+ if name == str(femtet_major_version):
25
+ winreg.CloseKey(key)
26
+ import os
27
+ dll_path = os.path.join(data, 'Program', 'ParametricIF.dll')
28
+ return dll_path
29
+ # ここまで来ていたら失敗
30
+ winreg.CloseKey(key)
31
+ raise RuntimeError('パラメトリック解析機能へのアクセスに失敗しました')
32
+
33
+
34
+ def _get_dll_with_set_femtet(Femtet):
35
+ dll = _get_dll(Femtet)
36
+ pid = _get_pid(Femtet.hWnd)
37
+ dll.SetCurrentFemtet.restype = ctypes.c_bool
38
+ dll.SetCurrentFemtet(pid)
39
+ return dll
40
+
41
+
42
+ def _get_prm_result_names(Femtet):
43
+ out = []
44
+
45
+ # load dll and set target femtet
46
+ dll = _get_dll_with_set_femtet(Femtet)
47
+ n = dll.GetPrmnResult()
48
+ for i in range(n):
49
+ # objective name
50
+ dll.GetPrmResultName.restype = ctypes.c_char_p
51
+ result = dll.GetPrmResultName(i)
52
+ name = result.decode('mbcs')
53
+ # objective value function
54
+ out.append(name)
55
+ return out
56
+
57
+
58
+ def add_parametric_results_as_objectives(femopt, indexes) -> bool:
59
+ # load dll and set target femtet
60
+ dll = _get_dll_with_set_femtet(femopt.fem.Femtet)
61
+
62
+ # get objective names
63
+ dll.GetPrmnResult.restype = ctypes.c_int
64
+ n = dll.GetPrmnResult()
65
+ for i in indexes:
66
+ # objective name
67
+ dll.GetPrmResultName.restype = ctypes.c_char_p
68
+ result = dll.GetPrmResultName(i)
69
+ name = result.decode('mbcs')
70
+ # objective value function
71
+ femopt.add_objective(_parametric_objective, name, args=(i,))
72
+ return True # ここまで来たら成功
73
+
74
+
75
+ def _parametric_objective(Femtet, parametric_result_index):
76
+ # load dll and set target femtet
77
+ dll = _get_dll_with_set_femtet(Femtet)
78
+ dll.GetPrmResult.restype = ctypes.c_double
79
+ return dll.GetPrmResult(parametric_result_index)
80
+
81
+
82
+ def solve_via_parametric_dll(Femtet) -> bool:
83
+ # load dll and set target femtet
84
+ dll = _get_dll_with_set_femtet(Femtet)
85
+ # solve
86
+ dll.PrmCalcExecute.restype = ctypes.c_bool
87
+ succeed = dll.PrmCalcExecute()
88
+ return succeed # 成功した場合はTRUE、失敗した場合はFALSEを返す
pyfemtet/opt/opt/_base.py CHANGED
@@ -57,6 +57,7 @@ class AbstractOptimizer(ABC):
57
57
  self.n_trials = None
58
58
  self.is_cluster = False
59
59
  self.subprocess_idx = None
60
+ self._is_error_exit = False
60
61
 
61
62
  def f(self, x):
62
63
  """Get x, update fem analysis, return objectives (and constraints)."""
@@ -141,7 +142,8 @@ class AbstractOptimizer(ABC):
141
142
  def _finalize(self):
142
143
  """Destruct fem and set worker status."""
143
144
  del self.fem
144
- self.worker_status.set(OptimizationStatus.TERMINATED)
145
+ if not self.worker_status.get() == OptimizationStatus.CRASHED:
146
+ self.worker_status.set(OptimizationStatus.TERMINATED)
145
147
 
146
148
  def _run(
147
149
  self,
@@ -149,7 +151,7 @@ class AbstractOptimizer(ABC):
149
151
  worker_status_list,
150
152
  wait_setup,
151
153
  skip_set_fem=False,
152
- ) -> None:
154
+ ) -> bool:
153
155
 
154
156
  # 自分の worker_status の取得
155
157
  self.subprocess_idx = subprocess_idx
@@ -186,10 +188,17 @@ class AbstractOptimizer(ABC):
186
188
  # run and finalize
187
189
  try:
188
190
  self.run()
191
+ except Exception as e:
192
+ logger.error("================================")
193
+ logger.error("An unexpected error has occured!")
194
+ logger.error("================================")
195
+ logger.error(e)
196
+ self._is_error_exit = True
197
+ self.worker_status.set(OptimizationStatus.CRASHED)
189
198
  finally:
190
199
  self._finalize()
191
200
 
192
- return None
201
+ return self._is_error_exit
193
202
 
194
203
  @abstractmethod
195
204
  def run(self) -> None:
@@ -922,8 +922,8 @@ class ProcessMonitorAppWorkerPage:
922
922
  colors.append('warning')
923
923
  elif status_int == OptimizationStatus.TERMINATED:
924
924
  colors.append('dark')
925
- elif status_int == OptimizationStatus.TERMINATE_ALL:
926
- colors.append('dark')
925
+ elif status_int == OptimizationStatus.CRASHED:
926
+ colors.append('danger')
927
927
  else:
928
928
  colors.append('primary')
929
929
 
@@ -0,0 +1,97 @@
1
+ Metadata-Version: 2.1
2
+ Name: pyfemtet
3
+ Version: 0.4.5
4
+ Summary: Design parameter optimization using Femtet.
5
+ Home-page: https://github.com/pyfemtet/pyfemtet
6
+ License: BSD-3-Clause
7
+ Author: kazuma.naito
8
+ Author-email: kazuma.naito@murata.com
9
+ Requires-Python: >=3.9.3,<3.13
10
+ Classifier: License :: OSI Approved :: BSD License
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Programming Language :: Python :: 3.10
13
+ Classifier: Programming Language :: Python :: 3.11
14
+ Classifier: Programming Language :: Python :: 3.12
15
+ Requires-Dist: botorch (>=0.9.5) ; python_version >= "3.12" and python_version < "3.13"
16
+ Requires-Dist: botorch (>=0.9.5,<0.10.0) ; python_version < "3.12"
17
+ Requires-Dist: colorlog (>=6.8.0,<7.0.0)
18
+ Requires-Dist: dash (>=2.14.2,<3.0.0)
19
+ Requires-Dist: dash-bootstrap-components (>=1.5.0,<2.0.0)
20
+ Requires-Dist: dask (>=2023.12.1,<2024.0.0)
21
+ Requires-Dist: distributed (>=2023.12.1,<2024.0.0)
22
+ Requires-Dist: femtetutils (>=1.0.0,<2.0.0)
23
+ Requires-Dist: numpy (>=1.26.2,<2.0.0)
24
+ Requires-Dist: openpyxl (>=3.1.2,<4.0.0)
25
+ Requires-Dist: optuna (>=3.4.0,<4.0.0)
26
+ Requires-Dist: optuna-integration (>=3.6.0,<4.0.0)
27
+ Requires-Dist: pandas (>=2.1.3,<3.0.0)
28
+ Requires-Dist: plotly (>=5.18.0,<6.0.0)
29
+ Requires-Dist: psutil (>=5.9.6,<6.0.0)
30
+ Requires-Dist: pywin32 (>=306,<307)
31
+ Requires-Dist: scipy (>=1.11.4,<2.0.0)
32
+ Requires-Dist: tqdm (>=4.66.1,<5.0.0)
33
+ Project-URL: Repository, https://github.com/pyfemtet/pyfemtet
34
+ Description-Content-Type: text/markdown
35
+
36
+ # Welcome! PyFemtet is the extension package for Femtet.
37
+
38
+ ## Main Features
39
+
40
+ <img src="img/pyfemtet_conceptual_diagram.png" width="450">
41
+
42
+ > [!NOTE]
43
+ > For details, see the documentation of "Related Pages" section.
44
+
45
+ ### Design Parameter Optimization
46
+ - Single or multiple objective optimization
47
+ - Progress monitor GUI
48
+ - Parallel computation with controling multiple Femtet processes
49
+ - Result output in easy-to-analyze csv format for Excel and other tools
50
+
51
+ ### Dispatch Extensions
52
+ - Create `CFemtet` object with process ID specification
53
+
54
+ ## Related Pages
55
+
56
+ - Femtet Website: https://www.muratasoftware.com/
57
+ - Documentation (English): https://pyfemtet.readthedocs.io/en/stable/
58
+ - ドキュメント(日本語): https://pyfemtet.readthedocs.io/jp/stable/
59
+ - Source code: https://github.com/pyfemtet/pyfemtet
60
+ - Bug reports: https://github.com/pyfemtet/pyfemtet/issues
61
+
62
+
63
+ ## Getting Started
64
+
65
+ > [!NOTE]
66
+ > Currently Femtet and `pyfemtet` supports **Windows only**.
67
+
68
+ ### 1. Install Femtet
69
+
70
+ - Access [Murata Software Website](https://www.muratasoftware.com/) and get **Femtet trial version** or purchase a lisence.
71
+ - Get installer and launch it.
72
+ - **Run 'EnableMacros'** from the start menu.
73
+ > [!NOTE]
74
+ > This procedure requires administrator privileges.
75
+
76
+
77
+ ### 2. Install PyFemtet
78
+
79
+ > [!NOTE]
80
+ > The commands on this section are for `CMD` or `PowerShell` on with `py launcher`.
81
+ > For a virtual environment, replace `py` to `python`.
82
+ > If you do not have Python, please install it first.
83
+
84
+ - Get `pyfemtet` via following command:
85
+
86
+ ```py -m pip install pyfemtet```
87
+
88
+
89
+ ### 3. Setting `win32com` Constants
90
+
91
+ - Run following command to enable COM constants:
92
+
93
+ ```py -m win32com.client.makepy FemtetMacro```
94
+
95
+ That's all! Now you can use Femtet's extention features via `pyfemtet`.
96
+ For more information including sample code and FEM projects, see the documentation of "Related Pages" section.
97
+
@@ -12,13 +12,13 @@ pyfemtet/FemtetPJTSample/her_ex40_parametric.py,sha256=B5PQoh71Q3KN2CyLU1gP_Yh9g
12
12
  pyfemtet/FemtetPJTSample/wat_ex14_parallel_parametric.py,sha256=UfhJffuXyhzdIWNpOrpV6xLTK1fuVvgyhlyg4Rp-628,2148
13
13
  pyfemtet/FemtetPJTSample/wat_ex14_parametric.femprj,sha256=pxacKe0NPNUPAcxqo2cATFApsMKiVt2g2e_FOk4fpjA,172895
14
14
  pyfemtet/FemtetPJTSample/wat_ex14_parametric.py,sha256=LGbWxCek0Ad2YrDCKykiQkE3aIypM4g8P3mLd_2anEE,2052
15
- pyfemtet/__init__.py,sha256=-0DFAS3GW84dLmJEuzbtUA7qvIf_cBb4LhqSg0oFfeI,21
15
+ pyfemtet/__init__.py,sha256=LHFUavV7Y99A-kKkHFv_mfCPFBihywzHsYRHNSa6xBs,21
16
16
  pyfemtet/core.py,sha256=3lqfBGJ5IuKz2Nqj5pRo7YQqKwx_0ZDL72u95Ur_1p0,1386
17
17
  pyfemtet/dispatch_extensions.py,sha256=MhWiUXVt2Cq8vDeajMK4SrajjiAmb4m2fK8gXwHLrWA,16177
18
18
  pyfemtet/logger.py,sha256=JYD0FvzijMS2NvZN7VT7vZA5hqtHEkvS93AHlIMDePw,2507
19
19
  pyfemtet/opt/__init__.py,sha256=_P8unESvqCRD5pmuo6-5yo7BbrPi7c0aE6UZpqUD-_I,596
20
- pyfemtet/opt/_femopt.py,sha256=mkawFpY0UXENeJYuH2mkLpNgUncIWY3QYMHUj-lL-4o,20602
21
- pyfemtet/opt/_femopt_core.py,sha256=bCSb1XvqeEfX6T2Z24eLI8nIa82omy8_Pnf5HXEmEsQ,24361
20
+ pyfemtet/opt/_femopt.py,sha256=QiEaf7EToNQDufBzL82TALclTkQA3ufJHQovI0mC0DY,22367
21
+ pyfemtet/opt/_femopt_core.py,sha256=n_m-GIW82uvKNAn_N1ypBZQ4sOjngfNly7-SEkOXfuU,24774
22
22
  pyfemtet/opt/femprj_sample/cad_ex01_NX.femprj,sha256=KC8JlHqHzqgyKriK911QSnQByQpRlw-SX5OSQ_GNe5M,149193
23
23
  pyfemtet/opt/femprj_sample/cad_ex01_NX.prt,sha256=3okHLeMdslrRA_wkhppZtxIe-2-ZPMfNqWCdQwUV31o,226626
24
24
  pyfemtet/opt/femprj_sample/cad_ex01_NX.py,sha256=qpfbU41qsJSMWnROzTOU1mpmHngGoa0cjnLHqNkt0EY,4519
@@ -53,19 +53,20 @@ pyfemtet/opt/femprj_sample_jp/wat_ex14_parametric_jp.femprj,sha256=dMwQMt6yok_Pb
53
53
  pyfemtet/opt/femprj_sample_jp/wat_ex14_parametric_jp.py,sha256=vnfI4WuCvyjQN1MhnzyB-jcAPtTwz3yNiwtTm2yQZHU,2311
54
54
  pyfemtet/opt/interface/__init__.py,sha256=qz5BszPuU3jZIoDnPjkPDAgvgHLlx1sYhuqh5ID798k,480
55
55
  pyfemtet/opt/interface/_base.py,sha256=lDjdvKYmBMxSc7SfoWSu91qVijGaQ2Ng-0C7z_f4eFM,2079
56
- pyfemtet/opt/interface/_femtet.py,sha256=4FoDG5OBMPh3mIy-_EPIgQ9v37XOa3jKLTIqpjf3vAA,24754
56
+ pyfemtet/opt/interface/_femtet.py,sha256=rsfLEjnBFybjcA-38MoPmxr2ctcjqIWwwJ68eX7QSWs,26355
57
+ pyfemtet/opt/interface/_femtet_parametric.py,sha256=BmKeha6ivYIqNieA7iYSEoo-_xn8TSte-jzsmhlwy38,2822
57
58
  pyfemtet/opt/interface/_femtet_with_nx/__init__.py,sha256=-6W2g2FDEcKzGHmI5KAKQe-4U5jDpMj0CXuma-GZca0,83
58
59
  pyfemtet/opt/interface/_femtet_with_nx/_interface.py,sha256=kTEmfAyLMEZvYTYjGXgYnoyhi-wDzhKK7opyVp7rOcY,3931
59
60
  pyfemtet/opt/interface/_femtet_with_nx/update_model.py,sha256=t0AB7mKY7rmrI_9stP1-5qhzmugEQ19DnZ4CCrCdTSw,2856
60
61
  pyfemtet/opt/interface/_femtet_with_sldworks.py,sha256=400FidHp7mBAVLyxzLlLtGYNzK_TtK61ycd4vFjHES0,6254
61
62
  pyfemtet/opt/opt/__init__.py,sha256=eQh-7PJN2YEUbHZnjinbeIyb0bk1wSh76TaEAa2l8SU,191
62
- pyfemtet/opt/opt/_base.py,sha256=aO71a8lIHHb5xIEoIu7oO_maynrNIEHfwt4uFFOUY58,7101
63
+ pyfemtet/opt/opt/_base.py,sha256=yEnPWAxFUIRNmUV-nbfCW4N3naDkkzQGME3qsDgEBFQ,7571
63
64
  pyfemtet/opt/opt/_optuna.py,sha256=TWtp9auU6GBWtEJVOuo8aWSvLcCHCUNUyOQRnqyln4I,9996
64
65
  pyfemtet/opt/visualization/__init__.py,sha256=PUCHoZnuZrHjTd0QQQBgzWkCpKY2noBPTvi-lyvxQyw,193
65
66
  pyfemtet/opt/visualization/_graphs.py,sha256=G6HaoGD3GpuwXih1nuTeFQMD0zv4jrhogedP9hxaG1c,5306
66
- pyfemtet/opt/visualization/_monitor.py,sha256=WcbuMjnp5LiybwCYBnJ78ju2h7sBJJtqUf1CbUacfXI,42104
67
- pyfemtet-0.4.3.dist-info/LICENSE,sha256=sVQBhyoglGJUu65-BP3iR6ujORI6YgEU2Qm-V4fGlOA,1485
68
- pyfemtet-0.4.3.dist-info/METADATA,sha256=8OEDM6wEqTEZc_6SJN8sBd55ie3OHYQZRguABCT_ulA,1848
69
- pyfemtet-0.4.3.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
70
- pyfemtet-0.4.3.dist-info/entry_points.txt,sha256=E_NUq8BEuKLM3z6Ou0sh6HyvaKE5O6NBDlmO-wgEGaQ,67
71
- pyfemtet-0.4.3.dist-info/RECORD,,
67
+ pyfemtet/opt/visualization/_monitor.py,sha256=X2KR6fd8qf1U58Qr_o0jn0FTm1w9ARMPhs4eMYgGipI,42100
68
+ pyfemtet-0.4.5.dist-info/LICENSE,sha256=sVQBhyoglGJUu65-BP3iR6ujORI6YgEU2Qm-V4fGlOA,1485
69
+ pyfemtet-0.4.5.dist-info/METADATA,sha256=IHy7m5bxdS1M3jy8UBrjk5NFm0pW0HFfxW2fHuog-NY,3332
70
+ pyfemtet-0.4.5.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
71
+ pyfemtet-0.4.5.dist-info/entry_points.txt,sha256=E_NUq8BEuKLM3z6Ou0sh6HyvaKE5O6NBDlmO-wgEGaQ,67
72
+ pyfemtet-0.4.5.dist-info/RECORD,,
@@ -1,48 +0,0 @@
1
- Metadata-Version: 2.1
2
- Name: pyfemtet
3
- Version: 0.4.3
4
- Summary: Design parameter optimization using Femtet.
5
- Home-page: https://github.com/pyfemtet/pyfemtet
6
- License: BSD-3-Clause
7
- Author: kazuma.naito
8
- Author-email: kazuma.naito@murata.com
9
- Requires-Python: >=3.9.3,<3.13
10
- Classifier: License :: OSI Approved :: BSD License
11
- Classifier: Programming Language :: Python :: 3
12
- Classifier: Programming Language :: Python :: 3.10
13
- Classifier: Programming Language :: Python :: 3.11
14
- Classifier: Programming Language :: Python :: 3.12
15
- Requires-Dist: botorch (>=0.9.5,<0.10.0) ; python_version < "3.12"
16
- Requires-Dist: colorlog (>=6.8.0,<7.0.0)
17
- Requires-Dist: dash (>=2.14.2,<3.0.0)
18
- Requires-Dist: dash-bootstrap-components (>=1.5.0,<2.0.0)
19
- Requires-Dist: dask (>=2023.12.1,<2024.0.0)
20
- Requires-Dist: distributed (>=2023.12.1,<2024.0.0)
21
- Requires-Dist: femtetutils (>=1.0.0,<2.0.0)
22
- Requires-Dist: numpy (>=1.26.2,<2.0.0)
23
- Requires-Dist: openpyxl (>=3.1.2,<4.0.0)
24
- Requires-Dist: optuna (>=3.4.0,<4.0.0)
25
- Requires-Dist: optuna-integration (>=3.6.0,<4.0.0)
26
- Requires-Dist: pandas (>=2.1.3,<3.0.0)
27
- Requires-Dist: plotly (>=5.18.0,<6.0.0)
28
- Requires-Dist: psutil (>=5.9.6,<6.0.0)
29
- Requires-Dist: pywin32 (>=306,<307)
30
- Requires-Dist: scipy (>=1.11.4,<2.0.0)
31
- Requires-Dist: tqdm (>=4.66.1,<5.0.0)
32
- Project-URL: Repository, https://github.com/pyfemtet/pyfemtet
33
- Description-Content-Type: text/markdown
34
-
35
- PyFemtet is the extension package for Femtet with Python.
36
-
37
- - Femtet Website: https://www.muratasoftware.com/
38
- - Documentation (English): https://pyfemtet.readthedocs.io/en/stable/
39
- - ドキュメント(日本語): https://pyfemtet.readthedocs.io/jp/stable/
40
- - Source code: https://github.com/pyfemtet/pyfemtet
41
- - Bug reports: https://github.com/pyfemtet/pyfemtet/issues
42
-
43
-
44
- It provides:
45
-
46
- - single and multi objective parameter optimization
47
- - tools for connect Femtet and Python by pid
48
-