def test_build_templated_model(): root = new(name="System") model = new(name="Vs") root.add(model) ss = new("SS", name="pout") Se = new("Se", name="Vs") zero = new("0", name="0_0") model.add(ss, Se, zero) connect(ss, zero) connect(Se, zero) file = file_path / "temp.bg" assert root.name == "System" with TempFile(file): save(root, file) with open(file, 'r') as fs: temp_data = yaml.load(fs, Loader=yaml.SafeLoader) assert temp_data["root"] == root.name assert temp_data["models"].keys() == {"/", "/Vs"} assert temp_data["models"]["/"]["components"] == ["Vs /Vs"] assert set(temp_data["models"]["/Vs"]["components"]) == { "pout base/SS", "Vs base/Se", "0_0 base/0" } assert set(temp_data["models"]["/Vs"]["netlist"]) == {"pout 0_0", "Vs 0_0"}
def test_ab_to_c_model(): A = bgt.new("Ce", library="BioChem", value=[1, 1, 1]) B = bgt.new("Ce", library="BioChem", value=[1, 1, 1]) C = bgt.new("Ce", library="BioChem", value=[1, 1, 1]) Re = bgt.new("Re", library="BioChem", value={'r': 1, "R": 1, "T": 1}) Y_AB = bgt.new('1') Y_C = bgt.new('1') bg = bgt.new() bg.add(A, B, Re, Y_AB, C, Y_C) connect(A, Y_AB) connect(B, Y_AB) connect(Y_AB, Re) connect(Re, Y_C) connect(Y_C, C) state_basis, _, _ = bg.basis_vectors (x_0, dx_0), = (k for k, (v, _) in state_basis.items() if v is A) (x_1, dx_1), = (k for k, (v, _) in state_basis.items() if v is B) (x_2, dx_2), = (k for k, (v, _) in state_basis.items() if v is C) eqns = { dx_0 + x_0 * x_1 - x_2, dx_1 + x_0 * x_1 - x_2, dx_2 - x_0 * x_1 + x_2 } relations = set(bg.constitutive_relations) assert not relations ^ eqns
def test_build_junction_dict(): c = bgt.new("C") kvl = bgt.new("0") bg = bgt.new() bg.add([c, kvl]) connect(kvl, c) cp, kp = list(c.ports) + list(kvl.ports) index_map = {cp: 0, kp: 1} M = adjacency_to_dict(index_map, bg.bonds, offset=1) assert M[(0, 1)] == 1 assert M[(0, 3)] == -1 assert M[(1, 2)] == 1 assert M[(1, 4)] == 1
def test_failstate(self): # see issue 110 from BondGraphTools import new, expose, connect from BondGraphTools.exceptions import InvalidPortException model = new() port = new('SS') model.add(port) expose(port, label='port_1') test_model = new() component = new("0") ## could be anything test_model.add(component, model) target_port = (model, 'port_') # typo in port name with pytest.raises(InvalidPortException): connect(component, target_port)
def test_connection_feedback(self): from BondGraphTools import new, connect, add from BondGraphTools.exceptions import InvalidPortException model = new() c1 = new('C') c2 = new('C') c3 = new('C') add(model, c1, c2, c3) connect(c1, (c2, 0)) with pytest.raises(InvalidPortException) as ex: connect((c2, 0), c3) assert "Port is already connected: " in str(ex)
def test_make_a_to_b_inplicit(): A = bgt.new("Ce", library="BioChem", value=[1, 1, 1]) B = bgt.new("Ce", library="BioChem", value=[1, 1, 1]) Re = bgt.new("Re", library="BioChem", value={"R": 1, "T": 1}) a_to_b = bgt.new() a_to_b.add(A, Re, B) connect(A, Re) connect(B, Re) assert Re.control_vars == ['r'] assert list(a_to_b.state_vars.keys()) == ['x_0', 'x_1'] assert list(a_to_b.control_vars.keys()) == ['u_0'] assert not a_to_b.ports
def test_ported_cap(): model = new() c = new("C", value=3) zero = new("0") ss = new("SS") model.add(c, zero, ss) connect(c, zero) connect(ss, zero) expose(ss) assert len(model.ports) == 1 assert model.constitutive_relations == [ sympy.sympify("dx_0 - f_0"), sympy.sympify("e_0 - x_0/3") ]
def test_ss_exposure(): model = new() ss = new("SS") sf = new("Sf", name="Sf") zero = new("0") model.add(ss, sf, zero) connect(sf, zero) connect(ss, zero) assert not model.ports assert set(model.control_vars.values()) == {(sf, 'f'), (ss, 'e'), (ss, 'f')} expose(ss, 'pin') assert model.ports p, = list(model.ports) assert p.name is "pin" assert set(model.control_vars.values()) == {(sf, 'f')}
def test_c_se_sim(): c = new("C", value=1) se = new("Se") r = new("R", value=1) kcl = new("1") bg = new() bg.add([c, se, kcl, r]) connect(c, (kcl, kcl.non_inverting)) connect(r, (kcl, kcl.non_inverting)) connect(se, (kcl, kcl.non_inverting)) def u(t, x, dx): return -np.exp(-t) assert str(bg.constitutive_relations) == '[dx_0 + u_0 + x_0]' with pytest.raises(ModelException) as ex: _ = simulate( c, timespan=[0, 10], x0=[0] ) assert "Control variable u_0 must be specified" in ex.args t, x = simulate( bg, timespan=[0, 10], x0=[0], control_vars=[u] ) assert t[0] == 0 assert t[-1] == 10 assert (len(t), 1) == x.shape assert x[0, 0] == 0 solution = t * np.exp(-t) res = abs(x - solution) assert (res < 0.001).all()
def test_ported_cr(): model = bgt.new() Sf = bgt.new('Sf', name="Sf") R = bgt.new("R", value=2) zero = bgt.new("0") ss = bgt.new("SS") model.add(Sf, R, zero, ss) connect(Sf, zero) connect(R, zero) connect(ss, zero) bgt.expose(ss, 'A') assert len(model.control_vars) == 1 ts, ps, cs = model._build_internal_basis_vectors() assert len(cs) == 1 assert len(ps) == 7 assert len(ts) == 0 mapping, coords = inverse_coord_maps(ts, ps, cs) assert len(coords) == 15 coords, mappings, lin_op, nl_op, conttr = model.system_model() assert nl_op.is_zero_matrix assert not conttr assert model.constitutive_relations == [ sympy.sympify('e_0 - 2*f_0 - 2*u_0') ]
def test_c_se_build_ode(): c = new("C", value=1) se = new("Se") r = new("R", value=1) kcl = new("1") bg = new() bg.add([c, se, kcl, r]) connect(c, (kcl, kcl.non_inverting)) connect(r, (kcl, kcl.non_inverting)) connect(se, (kcl, kcl.non_inverting)) # "dx_0 - u_0 + x_0" # so f(x,t) = exp(-t) - x def u(t, x, dx): return -np.exp(-t) residual_func, diff_vars = _bondgraph_to_residuals(bg, control_vars=[u]) r = [0] residual_func(0, [0], [0], r) assert r == [-1] residual_func(0, [0], [2], r) assert r == [1] residual_func(0, [2], [0], r) assert r == [1] residual_func(0, [0], [1], r) assert r == [0] t_test = np.log(4) residual_func(t_test, [1 / 8], [1 / 8], r) assert r == [0]
def test_make_a_to_b(): A = bgt.new("Ce", library="BioChem", value=[1, 1, 1]) B = bgt.new("Ce", library="BioChem", value=[1, 1, 1]) Re = bgt.new("Re", library="BioChem", value={"R": 1, "T": 1}) a_to_b = bgt.new() a_to_b.add(A, Re, B) connect(A, (Re, 0)) connect(B, (Re, 1)) with pytest.raises(InvalidPortException): connect(A, Re) assert Re.control_vars == ['r'] assert list(a_to_b.state_vars.keys()) == ['x_0', 'x_1'] assert list(a_to_b.control_vars.keys()) == ['u_0'] assert not a_to_b.ports state_basis, _, control_basis = a_to_b.basis_vectors (x_A, dx_A), = (k for k, (v, _) in state_basis.items() if v is A) (x_B, dx_B), = (k for k, (v, _) in state_basis.items() if v is B) (r,) = (k for k, (v, _) in control_basis.items() if v is Re) solutions = {dx_A + r*x_A - r*x_B, dx_B - r*x_A + r*x_B} relations = set(a_to_b.constitutive_relations) assert not solutions ^ relations
def test_ported_series_resistor(): Se = new("Se") r1 = new("R", value=1) r2 = new("R", value=2) kvl = new('1') ss = new("SS") model = new() model.add(Se, r1, r2, kvl, ss) expose(ss) connect(Se, kvl.non_inverting) connect(kvl.inverting, r1) connect(kvl.inverting, r2) connect(kvl.inverting, ss) assert len(model.ports) == 1 assert model.constitutive_relations == [sympy.sympify("e_0 - 3*f_0 - u_0")]
def test_rlc(): c = new("C", value=1) se = new("Se") r = new("R", value=1) l = new("I", value=1) kvl = new("0") bg = new() bg.add([c, se, kvl, r, l]) connect(c, kvl) connect(r, kvl) connect(se, kvl) connect(l, kvl) _ = simulate( bg, timespan=[0, 10], x0=[1, 0], control_vars=[1] )
def test_cv_relations(): c = bgt.new("C", value=1) se = bgt.new("Se") r = bgt.new("R", value=1) kcl = bgt.new("1") bg = bgt.new() bg.add([c, se, kcl, r]) connect(c, (kcl, kcl.non_inverting)) connect(r, (kcl, kcl.non_inverting)) connect(se, (kcl, kcl.non_inverting)) assert bg.constitutive_relations == [sympy.sympify("dx_0 + u_0 + x_0")]
def test_a_to_b_model(): A = bgt.new("Ce", library="BioChem", value=[1, 1, 1]) B = bgt.new("Ce", library="BioChem", value=[1, 1, 1]) Re = bgt.new("Re", library="BioChem", value={'r': 1, "R": 1, "T": 1}) Y_A = bgt.new('1') Y_B = bgt.new('1') a_to_b = bgt.new() a_to_b.add(A, Re, B, Y_A, Y_B) connect(A, Y_A.non_inverting) connect(B, Y_B.non_inverting) connect((Re, 0), Y_A.inverting) connect((Re, 1), Y_B.inverting) eqns = {sympy.sympify("dx_0 + x_0 -x_1"), sympy.sympify("dx_1 + x_1 -x_0")} for relation in a_to_b.constitutive_relations: assert relation in eqns
def test_parallel_crv_relations(): c = bgt.new("C", value=1) se = bgt.new("Se") r = bgt.new("R", value=1) kcl = bgt.new("0") bg = bgt.new() bg.add([c, se, kcl, r]) connect(c, kcl) connect(se, kcl) connect(r, kcl) assert bg.constitutive_relations == [sympy.sympify("dx_0 - du_0"), sympy.sympify("x_0 - u_0")]
def test_cv_subs_state_func(): c = bgt.new("C", value=1) se = bgt.new("Se") r = bgt.new("R", value=1) kcl = bgt.new("1") bg = bgt.new() bg.add([c, se, kcl, r]) connect(c, (kcl, kcl.non_inverting)) connect(r, (kcl, kcl.non_inverting)) connect(se, (kcl, kcl.non_inverting)) cv_s = {'u_0': ' -exp(-x_0)'} subs = [(sympy.Symbol('u_0'), sympy.sympify('-exp(-x_0)'))] mappings, coords = inverse_coord_maps(*bg.basis_vectors) assert _generate_cv_substitutions(cv_s, mappings, coords) == subs
def test_zero_junction_relations(): r = bgt.new("R", value=sympy.symbols('r')) l = bgt.new("I", value=sympy.symbols('l')) c = bgt.new("C", value=sympy.symbols('c')) kvl = bgt.new("0", name="kvl") rlc = bgt.new() rlc.add([c, l, kvl, r]) connect(r, kvl) connect(l, kvl) connect(c, kvl) rels = kvl.constitutive_relations assert sympy.sympify("e_1 - e_2") in rels assert sympy.sympify("e_0 - e_2") in rels assert sympy.sympify("f_0 + f_1 + f_2") in rels
def test_c_se_sum_switch(): c = new("C", value=1) se = new("Se") r = new("R", value=1) kcl = new("1") bg = new() bg.add([c, se, kcl, r]) connect(c, (kcl, kcl.non_inverting)) connect(r, (kcl, kcl.non_inverting)) connect(se, (kcl, kcl.non_inverting)) def bang_bang(t, x, dx): return 1.5 if x >= 1 else -2.0 t, x = simulate( bg, timespan=[0, 10], x0=[0], dx0=[1], control_vars=[bang_bang]) assert (x[0, -1] - 1) < 0.001
def test_make_a_to_b(): A = bgt.new("Ce", library="BioChem", value=[1, 1, 1]) B = bgt.new("Ce", library="BioChem", value=[1, 1, 1]) Re = bgt.new("Re", library="BioChem", value={"R": 1, "T": 1}) a_to_b = bgt.new() a_to_b.add(A, Re, B) connect(A, (Re, 0)) connect(B, (Re, 1)) with pytest.raises(InvalidPortException): connect(A, Re) assert Re.control_vars == ['r'] assert list(a_to_b.state_vars.keys()) == ['x_0', 'x_1'] assert list(a_to_b.control_vars.keys()) == ['u_0'] assert not a_to_b.ports
def test_nlin_se(): rn = Reaction_Network(name="A+B to C", reactions="A+B=C") system = rn.as_network_model(normalised=True) for param in system.params: system.set_param(param, 1) Ce_A = system / "A" Ce_B = system / "B" Ce_C = system / "C" assert Ce_A is not Ce_B Y = system / "AB" bgt.disconnect(Ce_A, Y) J_A = bgt.new("0", name="Ce_A") Se_A = bgt.new('Se', value=1, name='e=1') system.add(J_A), system.add(Se_A) connect(J_A, Y) connect(Ce_A, J_A) connect(Se_A, J_A) assert len(system.state_vars) == 3 state_basis, _, _ = system.basis_vectors (x0, dx0), = (k for k, (v, _) in state_basis.items() if v is Ce_A) (x1, dx1), = (k for k, (v, _) in state_basis.items() if v is Ce_B) (x2, dx2), = (k for k, (v, _) in state_basis.items() if v is Ce_C) E = sympy.S("E") solutions = {dx1 + E * x1 - x2, dx2 - E * x1 + x2, x0 - E, dx0} relations = set(system.constitutive_relations) assert not solutions ^ relations