class Capacitor(StorageNonLinear): def __init__(self, label, nodes, **kwargs): # parameters parameters = parametersDefault(self.metadata['parameters']) parameters.update(kwargs) if not label == nodes[0]: text = "The node label associated with a heat capacitor must be the\ same as the component label:\n{}\nis not \n{}".format(label, nodes[0]) raise NameError(text) pars = ['C', 'T0'] C, T0 = symbols(pars) # state variable x = symbols("x"+label) # storage funcion H = C*T0*sp.exp(x/C) N1, N2 = datum, nodes[0] # edge data data = {'label': x, 'type': 'storage', 'ctrl': 'f', 'link': None} # edge edge = (N1, N2, data) # init component StorageNonLinear.__init__(self, label, [edge], x, H, **parameters) metadata = {'title': 'Thermal Capacitor', 'component': 'Capacitor', 'label': 'T', 'dico': 'thermics', 'desc': (r'Heat capacity (or mass) with entropy :math:`\sigma\in\mathbb R`, energy (exponential law):' + equation(r'H(\sigma)= C\,T_0\,\exp{\left(\frac{\sigma}{C}\right)},') + 'and temperature:' + equation(r'\theta(\sigma) = \frac{d H}{d \sigma}(\sigma) = T_0\,\exp{\left(\frac{\sigma}{C}\right)}.')), 'nodesdesc': "Thermal point associated with the heat mass. The node label must be the same as the component label. The capacity temperature is measured from the reference node (datum).", 'nodes': ('T', ), 'parametersdesc': 'Component parameter.', 'parameters': [['C', "Thermal capacity", 'J/K', 1e3], ['T0', "Initial temperature", 'K', 273.16]], 'refs': {}, 'nnodes': 2, 'nedges': 1, 'flux': dicmetadata['flux'], 'effort': dicmetadata['effort'], } __doc__ = componentDoc(metadata)
class Capacitor(StorageLinear): def __init__(self, label, nodes, **kwargs): parameters = parametersDefault(self.metadata['parameters']) parameters.update(kwargs) par_name = 'C' par_val = parameters[par_name] kwargs = { 'name': par_name, 'value': par_val, 'inv_coeff': True, 'ctrl': 'f' } StorageLinear.__init__(self, label, nodes, **kwargs) metadata = { 'title': 'Magnetic capacitor', 'component': 'Capacitor', 'label': 'capa', 'dico': 'magnetics', 'desc': r'Magnetic capacity from [1]_ (chap 7). In Laplace domain with :math:`s\in\mathbb C`:' + equation(r'e(s) = \frac{1}{C s} \, f(s).'), 'nodesdesc': "Component terminals with positive flux N1->N2.", 'nodes': ('N1', 'N2'), 'parametersdesc': 'Component parameters', 'parameters': [['C', "Magnetic capacitance", 'H', 1e-9]], 'refs': { 1: "Antoine Falaize. Modelisation, simulation, generation de code et correction de systemes multi-physiques audios: Approche par reseau de composants et formulation hamiltonienne a ports. PhD thesis, ecole Doctorale d'Informatique, Telecommunication et electronique de Paris, Universite Pierre et Marie Curie, Paris 6, EDITE UPMC ED130, july 2016." }, 'nnodes': 2, 'nedges': 1, 'flux': dicmetadata['flux'], 'effort': dicmetadata['effort'], } # Write documentation __doc__ = componentDoc(metadata)
class Stiffness(StorageLinear): def __init__(self, label, nodes, **kwargs): parameters = parametersDefault(self.metadata['parameters']) parameters.update(kwargs) par_name = 'K' par_val = parameters[par_name] kwargs = { 'name': par_name, 'value': par_val, 'inv_coeff': False, 'ctrl': 'e' } StorageLinear.__init__(self, label, nodes, **kwargs) metadata = { 'title': 'Stiffness', 'component': 'Stiffness', 'label': 'stiff', 'dico': 'mechanics', 'desc': r'Linear stiffness between two points in a 1D space. In Laplace domain with :math:`s\in\mathbb C`:' + equation(r'f(s) = \frac{K\,e(s)}{s}.'), 'nodesdesc': "Mechanical points associated with the stiffness endpoints with positive flux P1->P2.", 'nodes': ('P1', 'P2'), 'parametersdesc': 'Component parameter.', 'parameters': [['K', "Mechanical stiffness", 'N/m', 1e3]], 'refs': {}, 'nnodes': 2, 'nedges': 1, 'flux': dicmetadata['flux'], 'effort': dicmetadata['effort'], } __doc__ = componentDoc(metadata)
class Damper(DissipativeLinear): def __init__(self, label, nodes, **kwargs): parameters = parametersDefault(self.metadata['parameters']) parameters.update(kwargs) if parameters['A'] is None: coeff = 0. else: coeff = parameters['A'] DissipativeLinear.__init__(self, label, nodes, coeff=coeff, inv_coeff=False) metadata = { 'title': 'Linear Damper', 'component': 'Damper', 'label': 'damp', 'dico': 'mechanics_dual', 'desc': r'Linear mechanical damping (i.e. opposing force proportional to the velocity). In Laplace domain with :math:`s\in\mathbb C`:' + equation(r'e(s) = A \, f(s).'), 'nodesdesc': "Nodes associated with the component terminals with positive flux N1->N2.", 'nodes': ('N1', 'N2'), 'parametersdesc': 'Component parameter', 'parameters': [['A', "Damping coefficient", 'N.s/m', 1.]], 'refs': {}, 'nnodes': 2, 'nedges': 1, 'flux': dicmetadata['flux'], 'effort': dicmetadata['effort'], } __doc__ = componentDoc(metadata)
class Gyrator(Connector): def __init__(self, label, nodes, **kwargs): pars = parametersDefault(self.metadata['parameters']) pars.update(kwargs) pars.update({'connector_type': 'gyrator'}) Connector.__init__(self, label, nodes, **pars) metadata = { 'title': 'Gyrator', 'component': 'Gyrator', 'label': 'gyr', 'dico': 'connectors', 'desc': r'Quadripole connector of gyrator type with:' + equation( r'\left\{\begin{array}{rcl} e_A &=& -\alpha\,f_B, \\ e_B &=& + \alpha\,f_A. \end{array}\right.' ), 'nodesdesc': "Connected edges are edge A = A1->A2 and edge B = B1->B2.", 'nodes': ('A1', 'A2', 'B1', 'B2'), 'parameters': [['alpha', 'Ratio', 'unknown', 1.]], 'refs': {}, 'nedges': 2, 'nnodes': 4, 'flux': dicmetadata['flux'], 'effort': dicmetadata['effort'], } # Write documentation __doc__ = componentDoc(metadata)
class Capacitorsat(StorageNonLinear): def __init__(self, label, nodes, **kwargs): parameters = parametersDefault(self.metadata['parameters']) parameters.update(kwargs) # parameters pars = ['C0', 'Csat', 'phisat'] C_0, C_sat, phi_sat = symbols(pars) # state variable x = symbols("x" + label) # storage funcion Hlin = x**2 / 2 t1 = sp.pi * x / (2 * phi_sat) c1 = (8 * phi_sat / (sp.pi * (4 - sp.pi))) Hsat = c1 * (sp.log(sp.cos(t1)) + (t1**2) / 2.) H = (Hlin - C_sat * Hsat) / C_0 N1, N2 = nodes # edge data data = {'label': x, 'type': 'storage', 'ctrl': 'f', 'link': None} # edge edge = (N1, N2, data) # init component StorageNonLinear.__init__(self, label, [edge], x, H, **parameters) metadata = { 'title': 'Saturating magnetic capacitor', 'component': 'Capacitorsat', 'label': 'capa', 'dico': 'magnetics', 'desc': (r'Saturating magnetic capacity from [1]_ (chap 7) with state :math:`\phi\in [-\phi_{sat}, \phi_{sat}]` and parameters described below. The energy is' + equation( 'H(\\phi) = \\frac{1}{C_{0}} \, \\left( \\frac{\\phi^2}{2} + C_{sat} H_{sat}(\\phi)\\right),' ) + 'with' + equation( 'H_{sat}(\\phi) = - \\frac{8 \\phi_{sat}}{\\pi \\left(4-\\pi\\right)} \, \\left(\\frac{\\pi^{2} \\phi^{2}}{8\\phi_{sat}^{2}} + \\log{\\left (\\cos{\\left (\\frac{\\pi \\phi}{2 \\phi_{sat}} \\right)} \\right)}\\right).' ) + 'The resulting magnetomotive force is:' + equation( '\\psi(\\phi)= \\frac{d\\,H(\\phi)}{d \\phi} = \\frac{ 1}{C_{0}} \\left(\\phi + C_{sat} \\frac{d\\,H_{sat}(\\phi)}{d \\phi}\\right),' ) + 'with' + equation( '\\frac{d\\,H_{sat}(\\phi)}{d \\phi}= \\frac{4}{4- \\pi} \\left(\\tan{\\left (\\frac{\\pi \\phi}{2 \\phi_{sat}} \\right )} - \\frac{\\pi \\phi}{2\\phi_{sat}} \\right).' )), 'nodesdesc': "Component terminals with positive flux N1->N2.", 'nodes': ('N1', 'N2'), 'parametersdesc': 'Component parameters', 'parameters': [['C0', "Magnetic capacitance around zero", 'H', 1e3], ['Csat', "Nonlinearity parameter", 'd.u.', 1e3], ['phisat', "Magnetic capacitance", 'Wb', 1e-1]], 'refs': { 1: "Antoine Falaize. Modelisation, simulation, generation de code et correction de systemes multi-physiques audios: Approche par reseau de composants et formulation hamiltonienne a ports. PhD thesis, ecole Doctorale d'Informatique, Telecommunication et electronique de Paris, Universite Pierre et Marie Curie, Paris 6, EDITE UPMC ED130, july 2016." }, 'nnodes': 2, 'nedges': 1, 'flux': dicmetadata['flux'], 'effort': dicmetadata['effort'], } # Write documentation __doc__ = componentDoc(metadata)
class Springcubic(StorageNonLinear): def __init__(self, label, nodes, **kwargs): parameters = parametersDefault(self.metadata['parameters']) parameters.update(kwargs) # parameters pars = ['F1', 'F3', 'xref'] F1, F3, xref = symbols(pars) # state variable x = symbols("x" + label) # storage funcion H = F1 * x**2 / (2. * xref) + F3 * x**4 / (4 * xref**3) N1, N2 = nodes # edge data data = {'label': x, 'type': 'storage', 'ctrl': 'e', 'link': None} # edge edge = (N1, N2, data) # init component StorageNonLinear.__init__(self, label, [edge], x, H, **parameters) metadata = { 'title': 'Cubic spring', 'component': 'Springcubic', 'label': 'spring', 'dico': 'mechanics', 'desc': (r'Cubic spring with state :math:`q\in \mathbb R` and parameters described below. The energy is' + equation( r'H(q) = \frac{F_1\,q^2}{2\,q_{ref}} + \frac{F_3\,q^4}{4q_{ref}^3}.' ) + 'The resulting force is:' + equation( r'f(q)= \frac{d \, H(q)}{d q} = F_1 \,\frac{q}{q_{ref}} + F_3 \, \frac{q^3}{q_{ref}^3}.' ) + 'so that :math:`f(q_{ref}) = F1+F3`.'), 'nodesdesc': "Mechanical points associated with component endpoints (positive flux P1->P2).", 'nodes': ('P1', 'P2'), 'parametersdesc': 'Component parameters', 'parameters': [['F1', "Linear contribution to restoring force", 'N', 1e1], ['F3', "Cubic contribution to restoring force", 'N', 1e1], ['xref', "Reference elongation", 'N', 1e-2]], 'refs': {}, 'nnodes': 2, 'nedges': 1, 'flux': dicmetadata['flux'], 'effort': dicmetadata['effort'], } __doc__ = componentDoc(metadata)
class Mass(StorageLinear): def __init__(self, label, nodes, **kwargs): parameters = parametersDefault(self.metadata['parameters']) parameters.update(kwargs) par_name = 'M' par_val = parameters[par_name] kwargs = {'name': par_name, 'value': par_val, 'inv_coeff': True, 'ctrl': 'f'} StorageLinear.__init__(self, label, (datum, nodes[0]), **kwargs) metadata = {'title': 'Mass', 'component': 'Mass', 'label': 'mass', 'dico': 'mechanics', 'desc': r'Mass moving in 1D space. In Laplace domain with :math:`s\in\mathbb C`:' + equation(r'e(s) = \frac{f(s)}{M\,s}.'), 'nodesdesc': "Mechanical point associated with the mass. The velocity is measured from a reference point with edge datum->P.", 'nodes': ('P', ), 'parametersdesc': 'Component parameter.', 'parameters': [['M', "Mechanical mass", 'kg', 1e-2]], 'refs': {}, 'nnodes': 2, 'nedges': 1, 'flux': dicmetadata['flux'], 'effort': dicmetadata['effort'], } __doc__ = componentDoc(metadata)
class Mass(StorageLinear): def __init__(self, label, nodes, **kwargs): parameters = parametersDefault(self.metadata['parameters']) parameters.update(kwargs) par_name = 'M' par_val = parameters[par_name] kwargs = {'name': par_name, 'value': par_val, 'inv_coeff': True, 'ctrl': 'e'} StorageLinear.__init__(self, label, (nodes[0], nodes[1]), **kwargs) metadata = {'title': 'Mass', 'component': 'Mass', 'label': 'mass', 'dico': 'mechanics_dual', 'desc': r'Mass moving in 1D space. In Laplace domain with :math:`s\in\mathbb C`:' + equation(r'f(s) = \frac{e(s)}{M\,s}.'), 'nodesdesc': "Nodes associated with the component terminals with positive flux N1->N2.", 'nodes': ('N1', 'N2'), 'parametersdesc': 'Component parameter.', 'parameters': [['M', "Mechanical mass", 'kg', 1e-2]], 'refs': {}, 'nnodes': 2, 'nedges': 1, 'flux': dicmetadata['flux'], 'effort': dicmetadata['effort'], } __doc__ = componentDoc(metadata)
class Felt(Graph): def __init__(self, label, nodes, **kwargs): Graph.__init__(self, label=label) parameters = parametersDefault(self.metadata['parameters']) parameters.update(kwargs) dicpars, subs = mappars(self, **parameters) # parameters pars = ['L', 'F', 'A', 'B'] L, F, A, B = symbols(pars) N1, N2 = nodes N3 = label+'_N3' xnl = symbols('q'+label) hnl = sp.Piecewise((0., xnl <= 0.), ((L*F/(B+1))*(xnl/L)**(B+1), True)) hnl = hnl.subs(dicpars) # edge data data = {'label': xnl, 'type': 'storage', 'ctrl': 'f', 'link': None} self.add_edges_from([(N1, N3, data), ]) self.core.add_storages(xnl, hnl) r = sp.Piecewise((0., xnl <= 0.), ((A * L/B)*(xnl/L)**(B-1), True)) r = r.subs(dicpars) wnl = symbols('dtq'+label) # edge data data = {'label': wnl, 'type': 'dissipative', 'ctrl': 'f', 'z': {'f_ctrl': r*wnl, 'e_ctrl': sp.sympify(0)}, 'link': None} self.add_edges_from([(N3, N2, data), ]) self.core.add_dissipations(wnl, r*wnl) self.core.subs.update(subs) metadata = {'title': 'Felt material', 'component': 'Felt', 'label': 'felt', 'dico': 'mechanics_dual', 'desc': (r'Nonlinear felt material used in piano-hammer. The model is that found in [1]_ eq. (11). It includes a nonlinear restoring force and a nonlinear damper as follows:' + equation(r'e_{total}\left(c, \dot c\right) = e_{elastic}(c) + e_{damper}\left(c, \dot c\right),') + 'with' + equation(r'e_{elastic}(c) = F \,c ^B,') + 'and' + equation(r'e_{damper}\left(c, \dot c\right) = \frac{A \, L}{B} c^{B-1} \,\dot c,') + 'where :math:`c = \\frac{\\max (q, 0)}{L}` is the crush of the hammer with contraction :math:`q\\in\\mathbb R`.'), 'nodesdesc': "Nodes associated with the component terminals with positive flux N1->N2.", 'nodes': ('N1', 'N2'), 'parametersdesc': 'Component parameters.', 'parameters': [['L', "Height at rest", 'm', 1e-2], ['F', "Elastic characteristic force", 'N', 10.], ['A', "Damping coefficient", 'N.s/m', 1e2], ['B', "Hysteresis coefficient", 'd.u.', 2.5]], 'refs': {1: 'Antoine Falaize and Thomas Helie. Passive simulation of the nonlinear port-hamiltonian modeling of a rhodes piano. Journal of Sound and Vibration, 2016.'}, 'nnodes': 3, 'nedges': 2, 'flux': dicmetadata['flux'], 'effort': dicmetadata['effort'], } __doc__ = componentDoc(metadata)
class Fracderec(Graph): def __init__(self, label, nodes, **kwargs): parameters = parametersDefault(self.metadata['parameters']) parameters.update(kwargs) Graph.__init__(self, label=label) g = parameters.pop('g') alpha = parameters.pop('alpha') diagR, diagQ = fractionalDifferenciatorWeights(g, alpha, **parameters) # Truncation of poles with null Q nbPoles = diagR.__len__() Ndeb, Nend = nodes for n in range(nbPoles): Rn = diagR[n] # here, diagR[n] is a conductance (e-ctrl) N1 = 'N' + label + str(n) + "_1" N2 = 'N' + label + str(n) + "_2" self += DissipativeLinear(label + 'R' + str(n), (N1, Ndeb), inv_coeff=True, coeff=Rn, ctrl='e') Qn = diagQ[n] self += StorageLinear(label + 'Q' + str(n), (N2, datum), value=Qn, ctrl='f', inv_coeff=False) self += Transformer(label + 'alpha' + str(n), (N1, Nend, N2, datum), alpha=Rn**-1) metadata = { 'title': 'Effort-controlled fractional derivator', 'component': 'Fracderec', 'label': 'fracder', 'dico': 'fraccalc', 'desc': r'Effort-controlled fractional derivator from [1]_ (chap 7):' + equation(r'f(s) = g \, s^{alpha} \, e(s).'), 'nodesdesc': "Component terminals with positive flux N1->N2.", 'nodes': ('N1', 'N2'), 'parametersdesc': 'Component parameters', 'parameters': [['g', "Gain", 'unknown', 1.], ['alpha', "Derivation order in (0, 1)", 'd.u.', 0.5], ['NbPoles', "Approximation order", 'd.u.', 20], [ 'PolesMinMax', "Poles modules in :math:`(10^{min}, 10^{max})`", 'Hz', (-5, 10) ], ['NbFreqPoints', "Number of optimization points", 'd.u.', 200], ['FreqsMinMax', "Optimization interval", 'Hz', (1, 48e3)], ['DoPlot', "Plot transfer function", 'bool', False]], 'refs': { 1: "Antoine Falaize. Modelisation, simulation, generation de code et correction de systemes multi-physiques audios: Approche par reseau de composants et formulation hamiltonienne a ports. PhD thesis, ecole Doctorale d'Informatique, Telecommunication et electronique de Paris, Universite Pierre et Marie Curie, Paris 6, EDITE UPMC ED130, july 2016." }, 'nnodes': 37, 'nedges': 68, 'flux': dicmetadata['flux'], 'effort': dicmetadata['effort'], } # Write documentation __doc__ = componentDoc(metadata)
class Springsat(StorageNonLinear): def __init__(self, label, nodes, **kwargs): parameters = parametersDefault(self.metadata['parameters']) parameters.update(kwargs) # parameters pars = ['K0', 'Ksat', 'xsat'] K0, Ksat, xsat = symbols(pars) # state variable x = symbols("x" + label) # storage funcion Hlin = x**2 / 2 t1 = sp.pi * x / (2 * xsat) c1 = (8 * xsat / (sp.pi * (4 - sp.pi))) Hsat = c1 * (sp.log(sp.cos(t1)) + (t1**2) / 2.) H = K0 * (Hlin - Ksat * Hsat) N1, N2 = nodes # edge data data = {'label': x, 'type': 'storage', 'ctrl': 'f', 'link': None} # edge edge = (N1, N2, data) # init component StorageNonLinear.__init__(self, label, [edge], x, H, **parameters) metadata = { 'title': 'Saturating spring', 'component': 'Springsat', 'label': 'spring', 'dico': 'mechanics_dual', 'desc': (r'Saturating spring from [1]_ (chap 7) with state :math:`q\in [-q_{sat}, q_{sat}]` and parameters described below. The energy is' + equation( 'H(q) = K_0 \, \\left( \\frac{q^2}{2} + K_{sat} H_{sat}(q)\\right),' ) + 'with' + equation( 'H_{sat}(q) = - \\frac{8 q_{sat}}{\\pi \\left(4-\\pi\\right)} \, \\left(\\frac{\\pi^{2} q^{2}}{8q_{sat}^{2}} + \\log{\\left (\\cos{\\left (\\frac{\\pi q}{2 q_{sat}} \\right)} \\right)}\\right).' ) + 'The resulting force is:' + equation( 'f(q)= \\frac{d\\,H(q)}{d q} = K_{0} \\left(q + K_{sat} \\frac{d\\,H_{sat}(q)}{d q}\\right),' ) + 'with' + equation( '\\frac{d\\,H_{sat}(q)}{d q}= \\frac{4}{4- \\pi} \\left(\\tan{\\left (\\frac{\\pi q}{2 q_{sat}} \\right )} - \\frac{\\pi q}{2q_{sat}} \\right).' )), 'nodesdesc': "Nodes associated with the component terminals with positive flux N1->N2.", 'nodes': ('N1', 'N2'), 'parametersdesc': 'Component parameters.', 'parameters': [['K0', "Stiffness around zero", 'H', 1e3], ['Ksat', "Nonlinearity parameter", 'd.u.', 1e3], ['xsat', "Saturating position", 'm', 1e-2]], 'refs': { 1: "Antoine Falaize. Modelisation, simulation, generation de code et correction de systemes multi-physiques audios: Approche par reseau de composants et formulation hamiltonienne a ports. PhD thesis, ecole Doctorale d'Informatique, Telecommunication et electronique de Paris, Universite Pierre et Marie Curie, Paris 6, EDITE UPMC ED130, july 2016." }, 'nnodes': 2, 'nedges': 1, 'flux': dicmetadata['flux'], 'effort': dicmetadata['effort'], } # Write documentation __doc__ = componentDoc(metadata)
class Fracintec(Graph): def __init__(self, label, nodes, **kwargs): Graph.__init__(self, label=label) parameters = parametersDefault(self.metadata['parameters']) parameters.update(kwargs) g = parameters.pop('g') beta = parameters.pop('beta') self.core.subs.update({ self.core.symbols('g_' + label): g, self.core.symbols('beta_' + label): beta }) diagRmu, diagQmu = fractionalIntegratorWeights(g, beta, **parameters) # Truncation of poles with null Q nbPoles = diagRmu.__len__() for n in range(nbPoles): Rn = diagRmu[n] # here, diagRmu[n] is a resistance (f-ctrl) Nend = nodes[1] Ncomp = 'iN_' + label + str(n) comp = DissipativeLinear('R_' + label + str(n), (Ncomp, Nend), coeff=Rn, ctrl='f') self += comp Qn = diagQmu[n] Ndeb = nodes[0] comp = StorageLinear(label + str(n), (Ndeb, Ncomp), value=Qn, name='pL_', inv_coeff=False, ctrl='e') self += comp metadata = { 'title': 'Effort-controlled fractional integrator', 'component': 'Fracintec', 'label': 'fracint', 'dico': 'fraccalc', 'desc': 'Effort-controlled fractional integrator from [1]_ (chap 7):' + equation(r'f(s) = g \, s^{-beta} \, e(s).'), 'nodesdesc': "Component terminals with positive flux N1->N2.", 'nodes': ('N1', 'N2'), 'parametersdesc': 'Component parameters', 'parameters': [['g', "Gain", 'unknown', 1.], ['beta', "Integration order in (0, 1)", 'd.u.', 0.5], ['NbPoles', "Approximation order", 'd.u.', 20], [ 'PolesMinMax', "Poles modules in :math:`(10^{min}, 10^{max})`", 'Hz', (-5, 10) ], ['NbFreqPoints', "Number of optimization points", 'd.u.', 200], ['FreqsMinMax', "Optimization interval", 'Hz', (1, 48e3)], ['DoPlot', "Plot transfer function", 'bool', False]], 'refs': { 1: "Antoine Falaize. Modelisation, simulation, generation de code et correction de systemes multi-physiques audios: Approche par reseau de composants et formulation hamiltonienne a ports. PhD thesis, ecole Doctorale d'Informatique, Telecommunication et electronique de Paris, Universite Pierre et Marie Curie, Paris 6, EDITE UPMC ED130, july 2016." }, 'nnodes': 19, 'nedges': 34, 'flux': dicmetadata['flux'], 'effort': dicmetadata['effort'] } # Write documentation __doc__ = componentDoc(metadata)
class Transfer(DissipativeNonLinear): def __init__(self, label, nodes, **kwargs): # parameters pars = [ 'R', ] for par in pars: assert par in kwargs.keys() R, = symbols(pars) # dissipation variable w = symbols('w{}_(:2)'.format(label)) t1, t2 = symbols(['gx' + str(n) for n in nodes]) # dissipation funcion zero = (w[0] - w[0]).simplify() z1 = R * (w[0] - w[1]) / t1 z2 = R * (w[1] - w[0]) / t2 N1, N2 = nodes # edge diode data data1 = { 'label': w[0], 'z': { 'e_ctrl': z1, 'f_ctrl': zero }, 'type': 'dissipative', 'ctrl': 'e', 'link': None } # edge edge1 = (datum, N1, data1) # edge diode data data2 = { 'label': w[1], 'z': { 'e_ctrl': z2, 'f_ctrl': zero }, 'type': 'dissipative', 'ctrl': 'e', 'link': None } # edge edge2 = (datum, N2, data2) # init component DissipativeNonLinear.__init__(self, label, [edge1, edge2], w, [z1, z2], **kwargs) metadata = { 'title': 'Thermal transfer', 'component': 'Transfer', 'label': 'trans', 'dico': 'thermics', 'desc': (r'Irreversible heat transfer between two thermal nodes. It is made from two dissipative edges. The dissipation variables are temperatures (:math:`w_1=T_1` and :math:`w_2=T_2`). The dissipation functions are:' + equation( r'\begin{array}{rcl} \dot \sigma _1 = z_1(w_1, w_2) & = & R\frac{w_1-w_2}{w_1}, \\ \dot \sigma _2 = z_2(w_1, w_2) & = & R\frac{w_2-w_1}{w_2}. \end{array}' )), 'nodesdesc': "The thermal transfer occurs between thermal points 'T1' and 'T2'.", 'nodes': ('T1', 'T2'), 'parametersdesc': 'Component parameter.', 'parameters': [['R', "Thermal transfer coefficient", 'W/K', 1e3]], 'refs': {}, 'nnodes': 3, 'nedges': 2, 'flux': dicmetadata['flux'], 'effort': dicmetadata['effort'], } __doc__ = componentDoc(metadata)