def nonrealizable_merge_dissipatives(w, z): from pyphs import Core y = Core.symbols('y:{0}'.format(len(w))) newW = Core.symbols( ('w' + '{}' * len(w)).format(*[str(wn)[1:] for wn in w])) Y = Core.symbols('Y') iz = list( map(lambda arg: sympy.solve(arg[0] - arg[2], arg[1])[0], zip(z, w, y))) iZ = sum([e.subs(yi, Y) for e, yi in zip(iz, y)]).simplify() newZ = sympy.solve(iZ - newW, Y)[0] return newW, newZ
def realizable_merge_storages(x, dxH): from pyphs import Core X = Core.symbols(('x' + '{}' * len(x)).format(*[str(xn)[1:] for xn in x])) HH = [sympy.integrate(dxhn, xn) for dxhn, xn in zip(dxH, x)] newH = sum([Hn.subs(xn, X) for (Hn, xn) in zip(HH, x)]) return X, sympy.simplify(newH)
def nonrealizable_merge_storages(x, dxH): from pyphs import Core y = Core.symbols('y:{0}'.format(len(x))) X = Core.symbols(('x' + '{}' * len(x)).format(*[str(xn)[1:] for xn in x])) Y = Core.symbols('Y') idxH = list( map(lambda arg: sympy.solve(arg[0] - arg[2], arg[1])[0], zip(dxH, x, y))) Q = sum([e.subs(yi, Y) for e, yi in zip(idxH, y)]).simplify() iQ = sympy.solve(Q - X, Y)[0] [e.subs(yi, iQ) for (e, yi) in zip(idxH, y)] HH = [sympy.integrate(dxhn, xn) for dxhn, xn in zip(dxH, x)] newH = sum([ Hn.subs(xn, fn) for (Hn, xn, fn) in zip( HH, x, [idxhn.subs(yi, iQ) for idxhn, yi in zip(idxH, y)]) ]) return X, sympy.simplify(newH)
@author: Falaize """ # Support for Python 2.x and Python 3.x from __future__ import division, print_function, absolute_import # import of external packages import numpy # numerical tools import matplotlib.pyplot as plt # plot tools # load the pyphs.Evaluation class in the current namespace from pyphs import Core, Method, Numeric # instantiate a pyphs.Core object core = Core() xL, L = core.symbols(['xL', 'L']) # define sympy symbols HL = xL**2 / (2 * L) # define sympy expression core.add_storages(xL, HL) # add storage function to the `core` object xC, C = core.symbols(['xC', 'C']) # define sympy symbols HC = xC**2 / (2 * C) # define sympy expression core.add_storages(xC, HC) # add storage function to the `core` object # Set the skew-symetric structure Jxx = numpy.array([[0., -1.], [1., 0.]]) core.set_Jxx(Jxx) # Physical parameters F0 = 100.
# import of the pyphs.PHSCore class from pyphs import Core import sympy """ 1) THE RL CORE """ # instantiate a pyphs.Core object RL= Core(label='my_core') # Adding the components xL, L = RL.symbols(['xL', 'L']) # sympy symbols HL = xL**2/(2*L) # sympy expression RL.add_storages(xL, HL) # add a storage component wR, R = RL.symbols(['wR', 'R']) # sympy symbols zR = R*wR # sympy expression RL.add_dissipations(wR, zR) # add a dissipation component u1, y1, u2, y2 = RL.symbols(['v1', 'i1', 'v2', 'i2']) #sympy symbols RL.add_ports([u1, u2], [y1, y2]) # add the ports #Initialize the interconnexion matrix RL.init_M() # Step by step build of matrix M RL.set_Mxx([0]) RL.set_Jxw([[-1]]) RL.set_Jxy([[-1, -1]])
def __init__(self, core, config=None, label=None): """ Parameters ----------- core: pyphs.Core The core Port-Hamiltonian structure on wich the method is build. config: dict or None A dictionary of simulation parameters. If None, the standard pyphs.config.simulations is used (the default is None). keys and default values are 'fs': 48e3, # Sample rate (Hz) 'grad': 'discret', # In {'discret', 'theta', 'trapez'} 'theta': 0., # Theta-scheme for the structure 'split': False, # split implicit from explicit part 'maxit': 10, # Max number of iterations for NL solvers 'eps': 1e-16, # Global numerical tolerance """ if label is None: label = core.label if VERBOSE >= 1: print('Build method {}...'.format(label)) if VERBOSE >= 2: print(' Init Method...') # INIT Core object Core.__init__(self, label=label) # Save core self._core = core # init linear part size to 0 self._core.dims._xl = 0 self._core.dims._wl = 0 self._core.Q = self._core.Q[:0, :0] self._core.Zl = self._core.Zl[:0, :0] # Copy core content for name in (list(set().union(self._core.attrstocopy, self._core.exprs_names, self._core.symbs_names))): if isinstance(name, str): source = self._core target = self attr_name = name else: source = getattr(self._core, name[0]) target = getattr(self, name[0]) attr_name = name[1] attr = getattr(source, attr_name) setattr(target, attr_name, copy.copy(attr)) # replace every expressions in subs self.substitute(selfexprs=True) # ------------- CLASSES ------------- # # recover Operation class self.Operation = Operation # ------------- ARGUMENTS ------------- # # Configuration parameters self.config = CONFIG_METHOD.copy() # update config if config is None: config = {} else: for k in config.keys(): if not k in self.config.keys(): text = 'Configuration key "{0}" unknown.'.format(k) raise AttributeError(text) self.config.update(config) # list of the method arguments names self.args_names = list() # list of the method expressions names self.funcs_names = list() # list of the method operations names self.ops_names = list() # list of the method update actions self.update_actions = list() # set sample rate as a symbol... self.fs = self.symbols(FS_SYMBS) if self.config['split']: if VERBOSE >= 2: print(' Split Linear/Nonlinear...') self.linear_nonlinear() if VERBOSE >= 2: print(' Build numerical structure...') # build the discrete evaluation for the gradient build_gradient_evaluation(self) # build the discrete evaluation for the structure build_structure_evaluation(self) # build method updates set_structure(self) if self.config['split']: if VERBOSE >= 2: print(' Split Implicit/Resolved...') # Split implicit equations from explicit equations self.explicit_implicit() if VERBOSE >= 2: print(' Re-Build numerical structure...') # build the discrete evaluation for the gradient build_gradient_evaluation(self) # build the discrete evaluation for the structure build_structure_evaluation(self) # build method updates set_structure(self) if VERBOSE >= 2: print(' Init update actions...') set_execactions(self) if VERBOSE >= 2: print(' Init arguments...') self.init_args() if VERBOSE >= 2: print(' Init functions...') self.init_funcs()
# import of the pyphs.PHSCore class from pyphs import Core import sympy """ 1) THE RL CORE """ # instantiate a pyphs.Core object RL = Core(label='my_core') # Adding the components xL, L = RL.symbols(['xL', 'L']) # sympy symbols HL = xL**2 / (2 * L) # sympy expression RL.add_storages(xL, HL) # add a storage component wR, R = RL.symbols(['wR', 'R']) # sympy symbols zR = R * wR # sympy expression RL.add_dissipations(wR, zR) # add a dissipation component u1, y1, u2, y2 = RL.symbols(['v1', 'i1', 'v2', 'i2']) #sympy symbols RL.add_ports([u1, u2], [y1, y2]) # add the ports #Initialize the interconnexion matrix RL.init_M() # Step by step build of matrix M RL.set_Mxx([0]) RL.set_Jxw([[-1]]) RL.set_Jxy([[-1, -1]]) #print('Two-ports RL circuit PHS:') #RL.pprint()
def realizable_merge_dissipatives(w, z): from pyphs import Core W = Core.symbols(('w' + '{}' * len(w)).format(*[str(wn)[1:] for wn in w])) return W, sum([zn.subs(dict([(wn, W) for wn in w])) for zn in z])
def initUI(self): self.core = Core(self.graphWidget.label) self.statusSig = BoolSig() self.initSig= NoneSig() self.dimsLayout = QHBoxLayout() self.dimsLayout.setContentsMargins(0, 0, 0, 0) self.storageWidget = DescriptionWidget('Storages', '0', 'Dimension of the state vector') self.dissipationWidget = DescriptionWidget('Dissipations', '0', 'Dimension of the dissipation vector') self.sourceWidget = DescriptionWidget('Ports', '0', 'Dimension of the inpuut/output vectors') self.dimsLayout.addWidget(self.storageWidget) self.dimsLayout.addWidget(self.dissipationWidget) self.dimsLayout.addWidget(self.sourceWidget) self.dimsLayout.addStretch() self.dimsLayout.setContentsMargins(0, 0, 0, 0) self.dimsWidget = QWidget(self) self.dimsWidget.setLayout(self.dimsLayout) # --------------------------------------------------------------------- # Define Core Actions self.buttonsLayout = QHBoxLayout() self.buttonsLayout.setContentsMargins(0, 0, 0, 0) # Build Action build_icon = QIcon(os.path.join(iconspath, 'work.png')) self.buildAction = QAction(build_icon, '&Build PHS Core', self) self.buildAction.setShortcut('Ctrl+B') self.buildAction.setStatusTip('Build Port-Hamiltonian System equations') self.buildAction.triggered.connect(self._build) self.buildButton = QPushButton(build_icon, '') self.buildButton.setToolTip('Build Port-Hamiltonian System equations') self.buildButton.clicked.connect(self._build) self.buttonsLayout.addWidget(self.buildButton) # Latex export Action export_icon = QIcon(os.path.join(iconspath, 'latex.png')) self.exportAction = QAction(export_icon, '&Export LaTeX document', self) self.exportAction.setShortcut('Ctrl+L') self.exportAction.setStatusTip('Export a LaTeX document that describes the Port-Hamiltonian System') self.exportAction.triggered.connect(self._writelatex) self.exportButton = QPushButton(export_icon, '') self.exportButton.setToolTip('Export a LaTeX document') self.exportButton.clicked.connect(self._writelatex) self.buttonsLayout.addWidget(self.exportButton) # --------------------------------------------------------------------- # title widget title = 'CORE' self.labelWidget = QLineEdit(self.core.label) self.labelWidget.adjustSize() status_labels = {True: 'OK', False: 'Not OK'} self.titleWidget = TitleWidget(title=title, labelWidget=self.labelWidget, status_labels=status_labels, buttonsLayout=self.buttonsLayout) # --------------------------------------------------------------------- # set parameters content = {} content['reduce z'] = {'desc': 'Reduce linear dissipations into the R-matrix.', 'label': 'Reduce z', 'value': self.parameters['reduce z'], 'type': 'bool' } content['substitute'] = {'desc': 'Substitute all symbols by their numerical value.', 'label': 'Substitute', 'value': self.parameters['substitute'], 'type': 'bool' } tooltip = 'Core parameters' self.parametersWidget = ParametersWidget('', content, tooltip) # --------------------------------------------------------------------- # signals self.graphWidget.initSig.sig.connect(self._netlist_init) self.graphWidget.statusSig.sig.connect(self._status_changed) self.parametersWidget.modifiedSig.sig.connect(self._update_parameters) self.titleWidget.labelSignal.sig.connect(self._update_label)
class CoreWidget(QWidget): def get_net(self): net = set(self.graphWidget.netlistWidget.netlist.netlist().splitlines()) return net net = property(get_net) def get_folder(self): return self.graphWidget.netlistWidget.netlist.folder folder = property(get_folder) def get_label(self): return self.titleWidget.label label = property(get_label) def get_status(self): return self.titleWidget.status status = property(get_status) def __init__(self, graphWidget, parent=None): super(CoreWidget, self).__init__(parent) self.parameters = {'reduce z': False, 'substitute': False} self.graphWidget = graphWidget self.initUI() def initUI(self): self.core = Core(self.graphWidget.label) self.statusSig = BoolSig() self.initSig= NoneSig() self.dimsLayout = QHBoxLayout() self.dimsLayout.setContentsMargins(0, 0, 0, 0) self.storageWidget = DescriptionWidget('Storages', '0', 'Dimension of the state vector') self.dissipationWidget = DescriptionWidget('Dissipations', '0', 'Dimension of the dissipation vector') self.sourceWidget = DescriptionWidget('Ports', '0', 'Dimension of the inpuut/output vectors') self.dimsLayout.addWidget(self.storageWidget) self.dimsLayout.addWidget(self.dissipationWidget) self.dimsLayout.addWidget(self.sourceWidget) self.dimsLayout.addStretch() self.dimsLayout.setContentsMargins(0, 0, 0, 0) self.dimsWidget = QWidget(self) self.dimsWidget.setLayout(self.dimsLayout) # --------------------------------------------------------------------- # Define Core Actions self.buttonsLayout = QHBoxLayout() self.buttonsLayout.setContentsMargins(0, 0, 0, 0) # Build Action build_icon = QIcon(os.path.join(iconspath, 'work.png')) self.buildAction = QAction(build_icon, '&Build PHS Core', self) self.buildAction.setShortcut('Ctrl+B') self.buildAction.setStatusTip('Build Port-Hamiltonian System equations') self.buildAction.triggered.connect(self._build) self.buildButton = QPushButton(build_icon, '') self.buildButton.setToolTip('Build Port-Hamiltonian System equations') self.buildButton.clicked.connect(self._build) self.buttonsLayout.addWidget(self.buildButton) # Latex export Action export_icon = QIcon(os.path.join(iconspath, 'latex.png')) self.exportAction = QAction(export_icon, '&Export LaTeX document', self) self.exportAction.setShortcut('Ctrl+L') self.exportAction.setStatusTip('Export a LaTeX document that describes the Port-Hamiltonian System') self.exportAction.triggered.connect(self._writelatex) self.exportButton = QPushButton(export_icon, '') self.exportButton.setToolTip('Export a LaTeX document') self.exportButton.clicked.connect(self._writelatex) self.buttonsLayout.addWidget(self.exportButton) # --------------------------------------------------------------------- # title widget title = 'CORE' self.labelWidget = QLineEdit(self.core.label) self.labelWidget.adjustSize() status_labels = {True: 'OK', False: 'Not OK'} self.titleWidget = TitleWidget(title=title, labelWidget=self.labelWidget, status_labels=status_labels, buttonsLayout=self.buttonsLayout) # --------------------------------------------------------------------- # set parameters content = {} content['reduce z'] = {'desc': 'Reduce linear dissipations into the R-matrix.', 'label': 'Reduce z', 'value': self.parameters['reduce z'], 'type': 'bool' } content['substitute'] = {'desc': 'Substitute all symbols by their numerical value.', 'label': 'Substitute', 'value': self.parameters['substitute'], 'type': 'bool' } tooltip = 'Core parameters' self.parametersWidget = ParametersWidget('', content, tooltip) # --------------------------------------------------------------------- # signals self.graphWidget.initSig.sig.connect(self._netlist_init) self.graphWidget.statusSig.sig.connect(self._status_changed) self.parametersWidget.modifiedSig.sig.connect(self._update_parameters) self.titleWidget.labelSignal.sig.connect(self._update_label) def _update_parameters(self): if not self.parameters == self.parametersWidget.parameters: self.parameters.update(self.parametersWidget.parameters) self._change_status(False) def _update(self): self.storageWidget.desc.setText(str(self.core.dims.x())) self.dissipationWidget.desc.setText(str(self.core.dims.w())) self.sourceWidget.desc.setText(str(self.core.dims.y())) def _status_changed(self, s=False): if not s: self._change_status(s) def _change_status(self, s=False): self.titleWidget._change_status(s) self.statusSig.sig.emit(s) def _netlist_init(self): label = self.graphWidget.label self._update_label(label) self.initSig.sig.emit() def _update_label(self, label): if not self.core.label == label: self.graphWidget.graph.label = label self.core.label = label self.titleWidget._change_label(label) def _change_label(self, label): self.titleWidget._change_label(label) self._update_label(label) def _build(self): if not self.graphWidget.status: self.graphWidget._build() if self.graphWidget.status: self.core = self.graphWidget.graph.to_core(self.core.label) if self.parameters['reduce z']: self.core.reduce_z() if self.parameters['substitute']: self.core.substitute(selfall=True) self._update() self._change_status(True) def _writelatex(self): options = QFileDialog.Options() options |= QFileDialog.DontUseNativeDialog dialog = QFileDialog() filename = os.path.join(self.folder, self.label + '.tex') dialog.selectFile(filename) fileName, _ = dialog.getSaveFileName(self, "Save LaTeX file as...", filename, "All Files (*);;Latex Files (*.tex)", "Latex Files (*.tex)", options=options) if not fileName == '': folder = filename[:filename.rfind(os.sep)] content = netlist2tex(self.graphWidget.netlistWidget.netlist) content += graphplot2tex(self.graphWidget.graph, folder=folder) content += core2tex(self.core) title = self.core.label texdocument(content, fileName, title)
def __init__(self, core, config=None, args=None): """ Parameters ----------- core: pyphs.Core The core Port-Hamiltonian structure on wich the method is build. config: dict or None A dictionary of simulation parameters. If None, the standard pyphs.config.simulations is used (the default is None): config has 'fs': {}, 'grad': {}, 'theta': {}, 'path': {}, 'lang': {}, 'timer': {}, 'pbar': {}, 'files': {}, 'eps': {}, 'maxit': {}, 'split': {}, 'eigen': {}, 'load': {} args: list of strings or None A list of symbols string names for symbols considered as arguments. If None, core.args() is used (the default is None). """.format(FS, GRADIENT, THETA, SIMULATION_PATH, LANGUAGE, TIMER, PBAR, FILES, EPS, int(MAXIT), SPLIT, EIGEN_PATH, LOAD_OPTS) if VERBOSE >= 1: print('Build numerical method...') if VERBOSE >= 2: print(' Init Method...') # INIT Core object Core.__init__(self, label=core.label + '_method') # Copy core content for name in (list(set().union(core.attrstocopy, core.exprs_names, core.symbs_names))): if isinstance(name, str): source = core target = self attr_name = name else: source = getattr(core, name[0]) target = getattr(self, name[0]) attr_name = name[1] attr = getattr(source, attr_name) setattr(target, attr_name, copy.deepcopy(attr)) # replace every expressions in subs self.substitute(selfexprs=True) # ------------- CLASSES ------------- # # recover Operation class self.Operation = Operation # ------------- ARGUMENTS ------------- # # Configuration parameters self.config = simulations.copy() # update config if config is None: config = {} self.config.update(config) # list of the method arguments names self.args_names = list() # list of the method expressions names self.funcs_names = list() # list of the method operations names self.ops_names = list() # list of the method update actions self.update_actions = list() # set sample rate as a symbol... self.fs = self.symbols(FS_SYMBS) # ... with associated parameter... if self.config['fs'] is None: self.add_parameters(self.fs) # ... or subs if an object is provided else: self.subs.update({self.fs: self.config['fs']}) if self.config['split']: if VERBOSE >= 2: print(' Split Linear/Nonlinear...') self.linear_nonlinear() if VERBOSE >= 2: print(' Build numerical structure...') # build the discrete evaluation for the gradient build_gradient_evaluation(self) # build the discrete evaluation for the structure build_structure_evaluation(self) # build method updates set_structure(self) if self.config['split']: if VERBOSE >= 2: print(' Split Implicit/Resolved...') # Split implicit equations from explicit equations self.explicit_implicit() if VERBOSE >= 2: print(' Re-Build numerical structure...') # build the discrete evaluation for the gradient build_gradient_evaluation(self) # build the discrete evaluation for the structure build_structure_evaluation(self) # build method updates set_structure(self) if VERBOSE >= 2: print(' Init update actions...') set_execactions(self) if VERBOSE >= 2: print(' Init arguments...') self.init_args() if VERBOSE >= 2: print(' Init functions...') self.init_funcs()