simnexus 0.1.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.
@@ -0,0 +1,329 @@
1
+
2
+ import pyvista as pv
3
+ from vtk.util.numpy_support import vtk_to_numpy
4
+ import numpy as np
5
+
6
+ from collections import namedtuple
7
+
8
+ from vtk import VTK_EMPTY_CELL, VTK_TRIANGLE, VTK_QUAD
9
+ from vtk import VTK_HEXAHEDRON, VTK_WEDGE, VTK_TETRA
10
+
11
+ ########################
12
+ # // Linear cells
13
+ # VTK_EMPTY_CELL = 0,
14
+ # VTK_VERTEX = 1,
15
+ # VTK_POLY_VERTEX = 2,
16
+ # VTK_LINE = 3, <<<<<<<<<<
17
+ # VTK_POLY_LINE = 4,
18
+ # VTK_TRIANGLE = 5, <<<<<<<<<<
19
+ # VTK_TRIANGLE_STRIP = 6,
20
+ # VTK_POLYGON = 7,
21
+ # VTK_PIXEL = 8,
22
+ # VTK_QUAD = 9,
23
+ # VTK_TETRA = 10, <<<<<<<<<<
24
+ # VTK_VOXEL = 11,
25
+ # VTK_HEXAHEDRON = 12, <<<<<<<<<<
26
+ # VTK_WEDGE = 13,
27
+ # VTK_PYRAMID = 14, # 5 nodes, rectangular base
28
+ # VTK_PENTAGONAL_PRISM = 15,
29
+ # VTK_HEXAGONAL_PRISM = 16,
30
+
31
+ ElProp = namedtuple( 'ElProp', ['vtk_type', 'num_node'], defaults=[0] )
32
+
33
+ el_props = {
34
+ 0: ElProp(VTK_EMPTY_CELL, 0),
35
+ 5: ElProp(VTK_TRIANGLE, 3),
36
+ 9: ElProp(VTK_QUAD, 4),
37
+ 10: ElProp(VTK_TETRA, 4),
38
+ 12: ElProp(VTK_HEXAHEDRON, 8),
39
+ 13: ElProp(VTK_WEDGE, 6),
40
+ }
41
+ #MAX_CONN = 8 # increase if needed
42
+
43
+
44
+ def print_mesh_data( vtk_file_name ):
45
+
46
+ print( '==========================================================' )
47
+ print( '== MESH DATA for', vtk_file_name )
48
+ print( '==========================================================' )
49
+
50
+ mesh = pv.read( vtk_file_name )
51
+
52
+ print( 'num_points', mesh.n_points ) # nodes for all parts
53
+ print( 'num_cells', mesh.n_cells ) # for all parts
54
+
55
+
56
+ print( '\n\ndata at nodes:\n', mesh.point_data )
57
+ print( '\n\ndata at els:\n', mesh.cell_data )
58
+
59
+
60
+ print( '\n\nSOME ARRAY DATA\n' )
61
+ print( 'points', mesh.points ) # nodes for all parts
62
+
63
+ print( 'cells', mesh.cells ) # nodes for all parts
64
+
65
+
66
+ #node_ids = mesh.point_data['NODE_ID']
67
+ #print( 'node_ids', node_ids )
68
+ #print( mesh.point_data['Contact_Forces'] ) # nodes for all parts
69
+
70
+ #part_ids = mesh.cell_data['PART_ID']
71
+ #print( part_ids )
72
+ #el_ids = mesh.cell_data['ELEMENT_ID']
73
+ #print( el_ids )
74
+ #print( mesh.cell_data['3DELEM_Von_Mises'] ) # nodes for all parts
75
+
76
+ cells = mesh.GetCells()
77
+ num_cell = cells.GetNumberOfCells()
78
+ cellConns = vtk_to_numpy( cells.GetConnectivityArray() )
79
+ cellOffsets = vtk_to_numpy( cells.GetOffsetsArray() )
80
+ cellTypes = vtk_to_numpy( mesh.GetCellTypesArray() )
81
+ coords = vtk_to_numpy( mesh.GetPoints().GetData() )
82
+
83
+ #print( 'part_ids', part_ids )
84
+ print( 'cellConns', cellConns.shape, cellConns.shape[0]+num_cell, cellConns )
85
+ print( 'cellTypes', cellTypes.shape, cellTypes )
86
+ print( 'coords', coords.shape, coords )
87
+ print( 'cellOffsets', cellOffsets )
88
+ print( 'cellOffsets', cellOffsets[0] )
89
+
90
+ print( '==========================================================' )
91
+ print( '== END MESH DATA for', vtk_file_name )
92
+ print( '==========================================================\n\n' )
93
+
94
+
95
+
96
+ def read_mesh_conns( vtk_file_name, required_part_id,
97
+ node_data_names=None, el_data_names=None, el_nodal_data_names=None ):
98
+
99
+ mesh = pv.read( vtk_file_name )
100
+
101
+ node_ids = mesh.point_data['NODE_ID']
102
+
103
+ part_ids = mesh.cell_data['PART_ID']
104
+ el_ids = mesh.cell_data['ELEMENT_ID']
105
+
106
+ cells = mesh.GetCells()
107
+ num_cell = cells.GetNumberOfCells()
108
+ cellConns = vtk_to_numpy( cells.GetConnectivityArray() )
109
+ cellOffsets = vtk_to_numpy( cells.GetOffsetsArray() )
110
+ cellTypes = vtk_to_numpy( mesh.GetCellTypesArray() )
111
+ coords = vtk_to_numpy( mesh.GetPoints().GetData() )
112
+
113
+ if el_data_names :
114
+ el_data = {}
115
+ for d_name in el_data_names:
116
+ el_data[d_name] = mesh.cell_data[ d_name ]
117
+ else: el_data = None
118
+ node_data = {'node_ids':node_ids}
119
+ if node_data_names :
120
+ for d_name in node_data_names:
121
+ node_data[d_name] = mesh.point_data[ d_name ]
122
+ #else: node_data = None
123
+
124
+ if el_nodal_data_names:
125
+ el_nodal_mesh = mesh.cell_data_to_point_data()
126
+ #if node_data is None : node_data = {}
127
+ for d_name in el_nodal_data_names:
128
+ node_data[d_name] = el_nodal_mesh.point_data[ d_name ]
129
+
130
+ #
131
+ # Build connectivity matrix for required part
132
+ #
133
+
134
+ subset_el_types = []
135
+
136
+ if el_data_names:
137
+ subset_el_data = {}
138
+ for d_name in el_data_names:
139
+ subset_el_data[d_name] = []
140
+ else: subset_el_data = None
141
+
142
+ new_conn_offset = 0
143
+ new_cellCons = np.array( [], dtype=np.int64 )
144
+ new_cellOffsets = []
145
+
146
+
147
+ for i, e_type in enumerate( cellTypes ):
148
+ if el_ids[i] == 0:
149
+ pass # internal elements
150
+ elif part_ids[i] == required_part_id:
151
+ if e_type in( VTK_TRIANGLE, VTK_QUAD,VTK_HEXAHEDRON, VTK_WEDGE):
152
+ num_node = el_props[ e_type ].num_node
153
+ #assert( num_node <= MAX_CONN )
154
+ offset = cellOffsets[i]
155
+ conn = cellConns[ offset: offset+num_node]
156
+ if e_type == VTK_QUAD and conn[3] == conn[2]:
157
+ conn = conn[:-1]
158
+ e_type = VTK_TRIANGLE
159
+
160
+ subset_el_types.append( e_type )
161
+
162
+ new_cellCons = np.append( new_cellCons, conn )
163
+ new_cellOffsets.append( new_conn_offset )
164
+ new_conn_offset = new_conn_offset + len(conn)
165
+
166
+ if el_data_names:
167
+ for d_name in el_data_names:
168
+ subset_el_data[d_name].append( el_data[d_name][i] )
169
+
170
+ else:
171
+ pass
172
+
173
+ return coords, node_data, \
174
+ { 'subset_el_data':subset_el_data,
175
+ 'cell_conns':new_cellCons,
176
+ 'cell_offsets': np.array(new_cellOffsets),
177
+ 'el_types': np.array(subset_el_types) }
178
+
179
+ def compact_nodes( coords, node_data, el_dict ):
180
+ """
181
+ Remove nodes not connected to elements (of the part)
182
+ """
183
+
184
+ num_node_all = coords.shape[0]
185
+
186
+ used = np.zeros( num_node_all ).astype( bool )
187
+ new_node_idx = np.zeros( num_node_all )
188
+
189
+ cell_con = el_dict['cell_conns']
190
+ for idx in cell_con:
191
+ used[idx]=True
192
+
193
+ num_node_new = 0
194
+ for old_idx in range( num_node_all ):
195
+ if used[old_idx]:
196
+ new_node_idx[old_idx] = num_node_new
197
+ num_node_new += 1
198
+ else:
199
+ pass
200
+
201
+
202
+ # data at nodes
203
+ if node_data is not None:
204
+ node_data_subset = {}
205
+ for k in node_data.keys():
206
+ shape = list( node_data[k].shape )
207
+ shape[0] = num_node_new
208
+ node_data_subset[k] = np.zeros( shape, dtype=node_data[k].dtype )
209
+
210
+ nidx = 0
211
+ for old_idx in range( num_node_all ):
212
+ if used[old_idx]:
213
+ for k in node_data.keys():
214
+ node_data_subset[k] [ nidx ] = node_data[k][ old_idx ]
215
+ nidx += 1
216
+ else:
217
+ pass
218
+ else:
219
+ node_data_subset = None
220
+
221
+ # reset coords
222
+ coords_subset = np.zeros( (num_node_new,3), dtype=float ) # NYI 2D
223
+ nidx = 0
224
+ for old_idx in range( num_node_all ):
225
+ if used[old_idx]:
226
+ coords_subset[nidx] = coords[old_idx]
227
+ nidx += 1
228
+ else:
229
+ #print( 'idx', old_idx, 'not used' )
230
+ pass
231
+
232
+
233
+
234
+ # reset connectivity
235
+ cell_con = el_dict['cell_conns']
236
+ cell_off = el_dict['cell_offsets']
237
+ new_cell_con = np.zeros_like( cell_con)
238
+ #new_cell_off = np.zeros_like( cell_off )
239
+ for i,n_idx in enumerate( cell_con ):
240
+ new_cell_con[i] = new_node_idx[n_idx]
241
+ el_dict['cell_conns'] = new_cell_con
242
+
243
+ return coords_subset, node_data_subset
244
+
245
+
246
+ def to_cells( el_types, cell_conns, cell_offsets ):
247
+
248
+ cells = {}
249
+ for etype,ep in el_props.items() :
250
+ numn = ep.num_node
251
+ mask = np.where( el_types == etype )
252
+ oo = cell_offsets[mask]
253
+ cells[etype] = [cell_conns[k:k+numn] for k in oo]
254
+ cells = { k:np.array(v) for k,v in cells.items() }
255
+ return cells
256
+
257
+
258
+ def read_part_mesh( vtk_file_name, required_part_id,
259
+ node_data_names=None, el_data_names=None, el_nodal_data_names=None ):
260
+
261
+ coords, node_data, el_dict = read_mesh_conns( vtk_file_name,
262
+ required_part_id,
263
+ node_data_names, el_data_names, el_nodal_data_names )
264
+
265
+
266
+ coords_subset, node_data_subset = compact_nodes( coords, node_data, el_dict )
267
+
268
+ cells = to_cells( el_dict['el_types'], el_dict['cell_conns'], el_dict['cell_offsets'] )
269
+
270
+ return { 'coords' : coords_subset,
271
+ 'data' : node_data_subset,
272
+ }, \
273
+ { #'conns' : new_subset_el_conns,
274
+ #'types' : el_dict['el_types'],
275
+ #'cell_conns' : el_dict['cell_conns'],
276
+ #'cell_conn_offset' : el_dict['cell_offsets'],
277
+ 'cells' : cells,
278
+ 'data' : el_dict['subset_el_data'],
279
+ }
280
+
281
+
282
+ def to_lcl_id( trgt_ids, srcs_ids, srcs_vals):
283
+ """ remap data to follow id sorting in trgt_ids instead of srcs_ids"""
284
+ idx_for_node_id = np.full( int(trgt_ids.max())+1, -1, dtype=int )
285
+ for idx,nid in enumerate(srcs_ids):
286
+ idx_for_node_id [int(nid)] = np.where( trgt_ids==nid )[0][0]
287
+
288
+ lcl_vals = np.zeros_like( srcs_vals )
289
+ #lcl_i = np.zeros_like( trgt_ids )
290
+ for i,nid in enumerate( srcs_ids ):
291
+ lcl_vals[ idx_for_node_id[nid] ] = srcs_vals[i]
292
+ #lcl_i[ idx_for_node_id[nid] ] = nid
293
+
294
+ return lcl_vals
295
+
296
+
297
+
298
+
299
+ if __name__ == '__main__':
300
+ #fname = 'RUBBER_SEAL_IMPDISP_GEOM_001.vtk'
301
+ fname = 'test.vtk'
302
+ #fname = 'test2.vtk'
303
+ #fname = 'test2_us.vtk'
304
+
305
+ required_part_id = 3
306
+ node_data_names = [ 'NODE_ID' ]
307
+ el_data_names = [ 'ELEMENT_ID' ]
308
+
309
+ print_mesh_data( fname )
310
+
311
+ node_data, el_data = \
312
+ read_part_mesh( fname, required_part_id,
313
+ node_data_names = node_data_names,
314
+ el_data_names = el_data_names )
315
+
316
+ print( '****** NODAL' )
317
+ print( 'coords:\n', node_data['coords'] )
318
+ print( 'node_data:\n', node_data['data'])
319
+
320
+ print( '****** ELEMENTS' )
321
+ #print( 'conns:\n', el_data['conns'] )
322
+ #print( 'cell_conns:\n', el_data['cell_conns'] )
323
+ for i,e_type in enumerate( el_data['types'] ):
324
+ co = el_data['cell_conn_offset']
325
+ num_node = el_props[ e_type ].num_node
326
+ #print( e_type, co[i], el_data['cell_conns'][ co[i]:co[i]+num_node ] )
327
+ print( e_type, el_data['cell_conns'][ co[i]:co[i]+num_node ] )
328
+ print( 'data:\n', el_data['data'] )
329
+
simnexus/__init__.py ADDED
@@ -0,0 +1,5 @@
1
+ __version__ = '0.1.0'
2
+
3
+ import logging
4
+ logging.getLogger(__name__).addHandler(logging.NullHandler())
5
+
simnexus/actions.py ADDED
@@ -0,0 +1,250 @@
1
+ import os
2
+ from abc import ABC, abstractmethod
3
+ import pandas
4
+ import numpy as np
5
+
6
+ from simnexus.args import EvalType
7
+
8
+ import logging
9
+ logger = logging.getLogger(__name__)
10
+
11
+ from abc import ABC, abstractmethod
12
+
13
+ from simnexus.util.observer import Subject, notify_observers
14
+
15
+ from simnexus.variables import Variable
16
+
17
+
18
+ class WorkAction(Subject):
19
+ """
20
+ Base class for the nodes in the graph.
21
+ Each action encapsulate an operations on the data stream.
22
+
23
+ args:
24
+ name (str) :
25
+ cmd (str) :
26
+ copy_paths (list) : List of file and directories to be copied to work area.
27
+ lower_bound (float) : Lower bound on output value during design
28
+ upper_bound (float) : Lower bound on output value during design
29
+ Returns:
30
+ Any: outcome of operation
31
+ """
32
+
33
+ def __init__( self, name, cmd=None, copy_paths=[], lower_bound=None, upper_bound=None,
34
+ description=None, data_type = EvalType.NOT_SPECIFIED ):
35
+ """
36
+ """
37
+ super().__init__()
38
+ self.name = name
39
+ self.cmd = cmd # backward compatible with simulation
40
+ self.copy_paths = copy_paths
41
+ self.upper_bound = upper_bound # backward compatible with simulation
42
+ self.lower_bound = lower_bound # backward compatible with simulation
43
+ self.parent = None # typically workflow
44
+ self.description = description if description is not None else (
45
+ self.__class__.__doc__.strip() if self.__class__.__doc__ else ""
46
+ )
47
+
48
+ self._results = None
49
+
50
+ self.data_type = data_type
51
+ self._par_dict = {}
52
+
53
+ def _collect_arg_pars(self ):
54
+ self._par_dict = {}
55
+ for k,v in self.__dict__.items():
56
+ if isinstance(v, Variable ):
57
+ self._par_dict[k] = v
58
+ self.__dict__[k] = v.value
59
+
60
+
61
+ def _set_arg_pars(self, val_dict ):
62
+
63
+ for k,v in self._par_dict.items():
64
+ #breakpoint()
65
+ if v.name in val_dict:
66
+ self.__dict__[k] = val_dict[v.name]
67
+
68
+ def allow_variables_as_arguments( func ):
69
+ """ A decorator for the __init__() method allowing you to
70
+ use variables as arguments constructing this class.
71
+
72
+ The arguments to a class can be declared to be variables,
73
+ e.g. Action( name=, cmd=, arg1=FloatVariable( 'E', 123.4 ) )
74
+ to be used as action.solve( {'E':3.} )
75
+ This requires that the subclass must used the decorators
76
+ allow_variables_as_arguments and
77
+ assign_variables_values_to_members as:
78
+
79
+ @WorkAction.allow_variables_as_arguments
80
+
81
+ def __init__( self, name, cmd=None, v=None ):
82
+ ...
83
+
84
+ @WorkAction.assign_variables_values_to_members
85
+
86
+ def solve(self, val_dict=None ):
87
+ ...
88
+
89
+ Child actions are created with the variables.
90
+
91
+ You cannot do computations with the variables in
92
+ __init__() because the values are only set at the end.
93
+ """
94
+ def wrapper( self, *args, **kwargs ):
95
+ v = func( self, *args, **kwargs )
96
+ self._collect_arg_pars()
97
+ return v
98
+ return wrapper
99
+
100
+ def assign_variables_values_to_members( func ):
101
+ """ A decorator for the solve() method allowing you to
102
+ use variables as arguments constructing this class."""
103
+ def wrapper( self, val_dict ):
104
+ self._set_arg_pars( val_dict )
105
+ v = func( self, val_dict )
106
+ return v
107
+ return wrapper
108
+
109
+
110
+ def _reset_class_member_vals(self, val_dict):
111
+ """
112
+ Reset values of 'action_name.member' in class. val_dict can be {'img_extraction.zoom': 12.3} and
113
+ if the class hass a member 'zoom' then that will be reset to 12.3
114
+
115
+ OUTDATED: use allow_variables_as_arguments and assign_variables_values_to_members decorators
116
+ """
117
+ if val_dict is None: return
118
+ needle = self.name+'.'
119
+ for variable_name in val_dict:
120
+ if needle in variable_name and variable_name.rfind( needle ) == 0:
121
+ subkey = variable_name.replace( needle, '' )
122
+ if subkey in self.__dict__:
123
+ self.__dict__[ subkey] = val_dict[variable_name]
124
+ else:
125
+ exit( f' *** ERROR Key \'{variable_name}\' not found in action \'{self.name}\' ' )
126
+
127
+
128
+ #@notify_observers
129
+ def _observed_eval(self, val_dict=None ):
130
+ """
131
+ used by the call graph to check if jobs have finished
132
+
133
+ returns:
134
+ dict : { self.name:..., .... } # including items in val_dict
135
+ """
136
+ self._results = val_dict.copy()
137
+ e = self.solve( val_dict )
138
+ self._results[self.name] = e
139
+ self._notify_observers( [self, 'Done'] )
140
+ return self._results
141
+
142
+ def _observed_eval_async(self, val_dict=None):
143
+ import multiprocessing
144
+ import threading
145
+
146
+ """
147
+ Asynchronously run solve in a separate process.
148
+ Notifies observers only when the process finishes.
149
+ """
150
+ def eval_worker(val_dict, result_dict):
151
+ e = self.solve(val_dict)
152
+ result_dict[self.name] = e
153
+
154
+ def watcher(proc, result_dict):
155
+ proc.join()
156
+ # Update self._results in the main process
157
+ self._results = dict(result_dict)
158
+ self._notify_observers([self, 'Done'])
159
+
160
+ manager = multiprocessing.Manager()
161
+ result_dict = manager.dict(val_dict.copy() if val_dict else {})
162
+ p = multiprocessing.Process(target=eval_worker, args=(val_dict, result_dict))
163
+ p.start()
164
+ # Start watcher thread to notify when done
165
+ t = threading.Thread(target=watcher, args=(p, result_dict), daemon=True)
166
+ t.start()
167
+ # Return immediately, results will be set when done
168
+ return None
169
+
170
+ @abstractmethod
171
+ def solve(self, val_dict: dict = None ) -> dict:
172
+ """
173
+ Solve/compute for action or graph.
174
+ An action will return any computed results.
175
+
176
+ A graph will append any computed results to
177
+ val_dict and return that.
178
+ So A.solve( {'v1':1.2} ) may return {'v1':1.2, 'A':3.4},
179
+ where the 'A':3.4 was added with 'A' the name of the action.
180
+
181
+ Arguments:
182
+ val_dict (dict) : variable values and input of any type.
183
+ Returns:
184
+ dict : dict with all results and inputs
185
+ """
186
+ assert 0, 'should not be called'
187
+
188
+ def variables( self ):
189
+ """
190
+ These are the variabls defined for the WorkAction
191
+ and used in the solve() method.
192
+ For a graph this would be the variables used in
193
+ all the children.
194
+
195
+ Returns:
196
+ set : Set of type Variable.
197
+ """
198
+ var_set = { v for k,v in self._par_dict.items() }
199
+ return var_set
200
+
201
+ def results(self):
202
+ return self._results
203
+
204
+ def _dump(self, val_dict=None ):
205
+ pass
206
+
207
+ def outputs(self):
208
+ """
209
+ Returns the output type and description of this action.
210
+
211
+ Returns:
212
+ tuple: (data_type, description)
213
+ """
214
+ return (self.data_type, self.description)
215
+
216
+ def _check_names( self, name_list=[] ):
217
+ """ Cannot have duplicates -- create a problem with callbacks """
218
+ if self.name in name_list: exit( f" *** Error Duplicate actions name \'{self.name}\'" )
219
+ name_list.append( self.name )
220
+
221
+ def __str__(self ):
222
+ r = f'WorkAction: \'{self.name}\' {type(self)}'
223
+ return r
224
+
225
+
226
+ class MathEvaluation(WorkAction):
227
+ """
228
+ Mathematical operation on results.
229
+
230
+ args:
231
+ name (str) :
232
+ cmd (str) :
233
+ Returns:
234
+ Any: outcome of operation
235
+ """
236
+
237
+ #def __init__( self, name, cmd ):
238
+ # super().__init__(name, cmd )
239
+
240
+ def solve(self, val_dict=None ):
241
+ try:
242
+ v = eval( self.cmd, None, val_dict )
243
+ except NameError as err:
244
+ exit( f' *** Could not evaluate action \'{self.name}\'. Error is \'{err}\'. Either a named action was not defined or have not finished.' )
245
+ except Exception as err:
246
+ exit( f' *** Error in MathEvaluation \'{self.name}\'. {err}' )
247
+ return v
248
+
249
+
250
+
simnexus/args.py ADDED
@@ -0,0 +1,56 @@
1
+
2
+ from enum import Enum, Flag, auto
3
+ from collections import namedtuple
4
+
5
+ class JobType(Flag):
6
+ """ OpenFOAM job execution stages """
7
+ CREATE_MESH = auto()
8
+ RUN_SIMULATION = auto()
9
+ POST_PRO = auto()
10
+ EXTRACT_VTK = auto()
11
+
12
+ class EvalType(Flag):
13
+ """ Can be multiple types. Use 'if EvalType.NUMERICAL in self.type:' """
14
+ NOT_SPECIFIED = auto()
15
+ FLOAT = auto()
16
+ NUMERICAL = auto() # float or numpy array
17
+ FILE = auto()
18
+ IMAGE = auto()
19
+
20
+ class Location(Enum):
21
+ UNKNOWN = 1
22
+ CELL = 2
23
+ NODAL = 3
24
+
25
+ class OptType(Enum):
26
+ LOCAL_W_GRAD = 1
27
+ RESTART_LOCAL_W_GRAD= 2
28
+ DIRECT = 3
29
+ BRUTE = 4
30
+
31
+ class MetaType(Enum):
32
+ LINEAR = 1
33
+ MLP = 2
34
+
35
+ class ImgComparison(Enum):
36
+ PHASH = 1
37
+ HU_MOMENTS = 2
38
+ HAUSDORFF = 3
39
+ PROCRUSTE = 4
40
+
41
+
42
+ OptPar = namedtuple('OptPar', ['step_size', 'epochs', 'alg'], # epochs should be deleted
43
+ defaults=(0.1, 1, OptType.RESTART_LOCAL_W_GRAD) )
44
+
45
+ MetaPar = namedtuple('MetaPar', ['doe_type', 'num_sample', 'factorial_order', 'meta_type' ],
46
+ defaults=('lhd', 0, 3, MetaType.MLP ) )
47
+
48
+ DesPar = namedtuple('DesPar', ['obj_func', 'start', 'var_bounds', ],
49
+ defaults=(None, None, None ) )
50
+
51
+ RADIOSS_DFLT_FNAME = 'radioss_simnexus_file.k'
52
+ OPT_RESULTS_DIR = 'OptimizationResults'
53
+ ACTIONS_OUTPUT_PATH = 'actions_output.pkl'
54
+
55
+ DYNA_DFLT_CMD = 'ls-dyna'
56
+ DYNA_BASE_FILE_NAME = 'dyna_action_inp'