Example #1
0
    def test_constructor(self):
        with pytest.raises(KeyError) as excinfo:
            xs.Model({"init_profile": InitProfile})
        assert "Process class 'Profile' missing" in str(excinfo.value)

        # test empty model
        assert len(xs.Model({})) == 0
Example #2
0
    def test_context_manager(self):
        m1 = xs.Model({})
        m2 = xs.Model({})

        with pytest.raises(ValueError, match=r"There is already a model object.*"):
            with m1, m2:
                pass
Example #3
0
def test_global_variable():
    @xs.process
    class Foo:
        var = xs.variable(global_name="global_var")
        idx = xs.index(dims="x", global_name="global_idx")
        obj = xs.any_object(global_name="global_obj")

        def initialize(self):
            self.idx = np.array([1, 1])
            self.obj = 2

    @xs.process
    class Bar:
        var = xs.global_ref("global_var")
        idx = xs.global_ref("global_idx")
        obj = xs.global_ref("global_obj")

        actual = xs.variable(intent="out")

        def initialize(self):
            self.actual = self.var + self.obj * np.sum(self.idx)

    @xs.process
    class Baz:
        # foreign pointing to global reference Bar.var
        # --> must pass through and actually points to Foo.var
        var = xs.foreign(Bar, "var", intent="out")

        def initialize(self):
            self.var = 1

    model = xs.Model({"foo": Foo, "bar": Bar, "baz": Baz})
    model.execute("initialize", {})

    assert model.state[("foo", "var")] == 1
    assert model.state[("bar", "actual")] == 5

    # -- test errors
    @xs.process
    class NotFound:
        var = xs.global_ref("missing")

    with pytest.raises(KeyError,
                       match="No variable with global name 'missing' found.*"):
        xs.Model({"foo": Foo, "not_found": NotFound})

    @xs.process
    class Duplicate:
        var = xs.variable(global_name="global_var")

    with pytest.raises(ValueError,
                       match="Found multiple variables with global name.*"):
        xs.Model({"foo": Foo, "bar": Bar, "dup": Duplicate})
def test_process_executor():
    @xs.process
    class P:
        in_var = xs.variable()
        out_var = xs.variable(intent="out")
        od_var = xs.on_demand()

        def run_step(self):
            self.out_var = self.in_var * 2
            return xs.RuntimeSignal.BREAK

        @od_var.compute
        def _dummy(self):
            return None

    m = xs.Model({"p": P})
    executor = m.p.__xsimlab_executor__
    state = {("p", "in_var"): 1}

    state_out, signal_out = executor.execute(m.p,
                                             SimulationStage.RUN_STEP, {},
                                             state=state)
    assert state_out == {("p", "out_var"): 2}
    assert signal_out == xs.RuntimeSignal.BREAK

    state_out, signal_out = executor.execute(m.p,
                                             SimulationStage.INITIALIZE, {},
                                             state=state)
    assert state_out == {}
    assert signal_out == xs.RuntimeSignal.NONE
Example #5
0
def test_group_dict_variable():
    @xs.process
    class Foo:
        a = xs.variable(groups="g", intent="out")

        def initialize(self):
            self.a = 1

    @xs.process
    class Bar:
        b = xs.variable(groups="g", intent="out")

        def initialize(self):
            self.b = 2

    @xs.process
    class Baz:
        c = xs.group_dict("g")
        actual = xs.variable(intent="out")

        def initialize(self):
            self.actual = self.c

    model = xs.Model({"foo": Foo, "bar": Bar, "baz": Baz})
    model.execute("initialize", {})

    assert model.state[("baz", "actual")] == Frozen({
        ("foo", "a"): 1,
        ("bar", "b"): 2
    })
Example #6
0
def model():
    return xs.Model({
        'roll': Roll,
        'add': AddOnDemand,
        'profile': Profile,
        'init_profile': InitProfile
    })
Example #7
0
def model():
    return xs.Model({
        "roll": Roll,
        "add": AddOnDemand,
        "profile": Profile,
        "init_profile": InitProfile,
    })
    def test_write_global_vars(self):
        # ensure that variable metadata (dims, etc.) is properly accessed for global references

        @xs.process
        class Foo:
            var = xs.variable(dims="x", global_name="global_var", intent="out")

        @xs.process
        class Bar:
            var = xs.global_ref("global_var")

        model = xs.Model({"foo": Foo, "bar": Bar})

        in_ds = xs.create_setup(
            model=model,
            clocks={"clock": [0, 1]},
            output_vars={"bar__var": None},
        )

        store = ZarrSimulationStore(in_ds, model)

        model.state[("foo", "var")] = np.array([1, 2, 3])
        store.write_output_vars(-1, -1)

        ztest = zarr.open_group(store.zgroup.store, mode="r")
        np.testing.assert_array_equal(ztest.bar__var, np.array([1, 2, 3]))
    def test_encoding(self):
        @xs.process
        class P:
            v1 = xs.variable(dims="x",
                             intent="out",
                             encoding={"dtype": np.int32})
            v2 = xs.on_demand(dims="x", encoding={"fill_value": 0})
            v3 = xs.index(dims="x")
            v4 = xs.variable(
                dims="x",
                intent="out",
                encoding={
                    "dtype": object,
                    "object_codec": zarr.codecs.Pickle()
                },
            )

            @v2.compute
            def _get_v2(self):
                return [0]

        model = xs.Model({"p": P})

        in_ds = xs.create_setup(
            model=model,
            clocks={"clock": [0]},
            output_vars={
                "p__v1": None,
                "p__v2": None,
                "p__v3": None,
                "p__v4": None
            },
        )

        store = ZarrSimulationStore(
            in_ds,
            model,
            encoding={
                "p__v2": {
                    "fill_value": -1
                },
                "p__v3": {
                    "chunks": (10, )
                }
            },
        )

        model.state[("p", "v1")] = [0]
        model.state[("p", "v3")] = [0]
        model.state[("p", "v4")] = [{"foo": "bar"}]
        store.write_output_vars(-1, -1)

        ztest = zarr.open_group(store.zgroup.store, mode="r")

        assert ztest.p__v1.dtype == np.int32
        # test encoding precedence ZarrSimulationStore > model variable
        assert ztest.p__v2.fill_value == -1
        assert ztest.p__v3.chunks == (10, )
        assert ztest.p__v4[0] == {"foo": "bar"}
Example #10
0
    def test_object_variable(self):
        @xs.process
        class P:
            obj = xs.any_object()

        m = xs.Model({"p": P})

        assert m.p.__xsimlab_state_keys__["obj"] == ("p", "obj")
Example #11
0
    def test_set_output_object_vars(self):
        @xs.process
        class P:
            obj = xs.any_object()

        m = xs.Model({"p": P})
        ds = xr.Dataset()

        with pytest.raises(ValueError,
                           match=r"Object variables can't be set.*"):
            ds.xsimlab._set_output_vars(m, {("p", "obj"): None})
Example #12
0
    def test_set_output_object_or_group_vars(self, field):
        @xs.process
        class P:
            var = field

        m = xs.Model({"p": P})
        ds = xr.Dataset()

        with pytest.raises(ValueError,
                           match=r"Object or group variables can't be set.*"):
            ds.xsimlab._set_output_vars(m, {("p", "var"): None})
Example #13
0
    def test_sort_processes_cycle(self, model):
        @xs.process
        class Foo:
            in_var = xs.variable()
            out_var = xs.variable(intent="out")

        @xs.process
        class Bar:
            in_foreign = xs.foreign(Foo, "out_var")
            out_foreign = xs.foreign(Foo, "in_var", intent="out")

        with pytest.raises(RuntimeError, match=r"Cycle detected.*"):
            xs.Model({"foo": Foo, "bar": Bar})
Example #14
0
    def test_multiple_groups(self):
        @xs.process
        class A:
            v = xs.variable(groups=["g1", "g2"])

        @xs.process
        class B:
            g1 = xs.group("g1")
            g2 = xs.group("g2")

        m = xs.Model({"a": A, "b": B})

        assert m.b.__xsimlab_state_keys__["g1"] == [("a", "v")]
        assert m.b.__xsimlab_state_keys__["g2"] == [("a", "v")]
Example #15
0
    def test_sort_processes_cycle(self, model):
        @xs.process
        class Foo(object):
            in_var = xs.variable()
            out_var = xs.variable(intent='out')

        @xs.process
        class Bar(object):
            in_foreign = xs.foreign(Foo, 'out_var')
            out_foreign = xs.foreign(Foo, 'in_var', intent='out')

        with pytest.raises(RuntimeError) as excinfo:
            xs.Model({'foo': Foo, 'bar': Bar})
        assert "Cycle detected" in str(excinfo.value)
Example #16
0
def test_on_demand_cache():
    @xs.process
    class P1:
        var = xs.on_demand(dims="x")
        cached_var = xs.on_demand(dims="x")

        @var.compute
        def _compute_var(self):
            return np.random.rand(10)

        @cached_var.compute(cache=True)
        def _compute_cached_var(self):
            return np.random.rand(10)

    @xs.process
    class P2:
        var = xs.foreign(P1, "var")
        cached_var = xs.foreign(P1, "cached_var")
        view = xs.variable(dims="x", intent="out")
        cached_view = xs.variable(dims="x", intent="out")

        def run_step(self):
            self.view = self.var
            self.cached_view = self.cached_var

    @xs.process
    class P3:
        p1_view = xs.foreign(P1, "var")
        p1_cached_view = xs.foreign(P1, "cached_var")
        p2_view = xs.foreign(P2, "view")
        p2_cached_view = xs.foreign(P2, "cached_view")

        def initialize(self):
            self._p1_cached_view_init = self.p1_cached_view

        def run_step(self):
            # P1.var's compute method called twice
            assert not np.all(self.p1_view == self.p2_view)
            # P1.cached_var's compute method called once
            assert self.p1_cached_view is self.p2_cached_view
            # check cache cleared between simulation stages
            assert not np.all(self.p1_cached_view == self._p1_cached_view_init)

    model = xs.Model({"p1": P1, "p2": P2, "p3": P3})
    model.execute("initialize", {})
    model.execute("run_step", {})
Example #17
0
    def test_run_decoding(self, decoding, expected):
        @xs.process
        class P:
            var = xs.variable(dims="x",
                              intent="out",
                              encoding={"fill_value": -1})

            def initialize(self):
                self.var = [-1, -1]

        m = xs.Model({"p": P})

        in_ds = xs.create_setup(
            model=m,
            clocks={"clock": [0, 1]},
            output_vars={"p__var": None},
        )

        out_ds = in_ds.xsimlab.run(model=m, decoding=decoding)

        np.testing.assert_array_equal(out_ds.p__var, expected)
Example #18
0
def test_signal_process_level(step, trigger, signal, break_bar, expected_v1,
                              expected_v2, parallel):
    @xs.process
    class Foo:
        v1 = xs.variable(intent="out")
        v2 = xs.variable()

        def initialize(self):
            self.v1 = 0

        def run_step(self):
            self.v1 = 1

    @xs.process
    class Bar:
        v2 = xs.foreign(Foo, "v2", intent="out")

        def initialize(self):
            self.v2 = 0

        def run_step(self):
            self.v2 = 2

            if break_bar:
                return xs.RuntimeSignal.BREAK

    def hook_func(model, context, state):
        if context["step"] == 1:
            return signal

    hook_dict = {SimulationStage.RUN_STEP: {"process": {trigger: [hook_func]}}}

    model = xs.Model({"foo": Foo, "bar": Bar})
    model.execute("initialize", {})
    model.execute("run_step", {"step": step},
                  hooks=hook_dict,
                  parallel=parallel)

    assert model.state[("foo", "v1")] == expected_v1
    assert model.state[("foo", "v2")] == expected_v2
    def test_fill_values(self):
        @xs.process
        class Foo:
            v_int64 = xs.variable(dims="x", intent="out")
            v_float64 = xs.variable(dims="x", intent="out")
            v_uint8 = xs.variable(dims="x",
                                  intent="out",
                                  encoding={"dtype": np.uint8})
            v_string = xs.variable(dims="x", intent="out")
            v_bool = xs.variable(dims="x", intent="out")

            def initialize(self):
                self.v_int64 = [0, np.iinfo("int64").max]
                self.v_float64 = [0.0, np.nan]
                self.v_uint8 = [0, 255]
                self.v_string = ["hello", ""]
                self.v_bool = [True, False]

        model = xs.Model({"foo": Foo})
        in_ds = xs.create_setup(
            model=model,
            clocks={"clock": [0, 1]},
            output_vars={
                "foo__v_int64": None,
                "foo__v_float64": None,
                "foo__v_uint8": None,
                "foo__v_string": None,
                "foo__v_bool": None,
            },
        )
        out_ds = in_ds.xsimlab.run(model=model)
        np.testing.assert_equal(out_ds["foo__v_int64"].data, [0, np.nan])
        np.testing.assert_equal(out_ds["foo__v_float64"].data, [0.0, np.nan])
        np.testing.assert_equal(out_ds["foo__v_uint8"].data, [0, np.nan])
        # np.testing.assert_equal does not work for "object" dtypes, so test each value explicitly:
        assert out_ds["foo__v_string"].data[0] == "hello"
        assert np.isnan(out_ds["foo__v_string"].data[1])
        assert out_ds["foo__v_bool"].data[0] == True
        assert np.isnan(out_ds["foo__v_bool"].data[1])
Example #20
0
    def test_run_check_dims(self):
        @xs.process
        class P:
            var = xs.variable(dims=["x", ("x", "y")])

        m = xs.Model({"p": P})

        arr = np.array([[1, 2], [3, 4]])

        in_ds = xs.create_setup(
            model=m,
            clocks={"clock": [1, 2]},
            input_vars={"p__var": (("y", "x"), arr)},
            output_vars={"p__var": None},
        )

        out_ds = in_ds.xsimlab.run(model=m, check_dims=None)
        actual = out_ds.p__var.values
        np.testing.assert_array_equal(actual, arr)

        with pytest.raises(ValueError, match=r"Invalid dimension.*"):
            in_ds.xsimlab.run(model=m, check_dims="strict")

        out_ds = in_ds.xsimlab.run(model=m,
                                   check_dims="transpose",
                                   safe_mode=False)
        actual = out_ds.p__var.values
        np.testing.assert_array_equal(actual, arr)
        np.testing.assert_array_equal(m.p.var, arr.transpose())

        in_ds2 = in_ds.xsimlab.update_vars(model=m,
                                           output_vars={"p__var": "clock"})
        # TODO: fix update output vars time-independet -> dependent
        # currently need the workaround below
        in_ds2.attrs = {}

        out_ds = in_ds2.xsimlab.run(model=m, check_dims="transpose")
        actual = out_ds.p__var.isel(clock=-1).values
        np.testing.assert_array_equal(actual, arr)
def test_finalize_always_called():
    @xs.process
    class P:
        var = xs.variable(intent="out")

        def initialize(self):
            self.var = "initialized"
            raise RuntimeError()

        def finalize(self):
            self.var = "finalized"

    model = xs.Model({"p": P})
    in_dataset = xs.create_setup(model=model, clocks={"clock": [0, 1]})
    driver = XarraySimulationDriver(in_dataset, model)

    try:
        driver.run_model()
    except RuntimeError:
        pass

    assert model.state[("p", "var")] == "finalized"
Example #22
0
def test_signal_model_level(trigger, signal, expected):
    @xs.process
    class Foo:
        v = xs.variable(intent="out")
        vv = xs.variable(intent="out")

        def initialize(self):
            self.v = 0.0
            self.vv = 10.0

        def run_step(self):
            self.v += 1.0

        def finalize_step(self):
            self.v += 1.0

    @xs.runtime_hook("run_step", level="model", trigger=trigger)
    def hook_func(model, context, state):
        if context["step"] == 1:
            return signal

    model = xs.Model({"foo": Foo})
    ds_in = xs.create_setup(
        model=model,
        clocks={"clock": range(4)},
        output_vars={
            "foo__v": "clock",
            "foo__vv": None
        },
    )
    ds_out = ds_in.xsimlab.run(model=model, hooks=[hook_func])

    np.testing.assert_equal(ds_out.foo__v.values, expected)

    # ensure that clock-independent output variables are properly
    # saved even when the simulation stops early
    assert ds_out.foo__vv == 10.0
Example #23
0
    def test_run_batch_dim(self, dims, data, clock, parallel, scheduler):
        @xs.process
        class P:
            in_var = xs.variable(dims=[(), "x"])
            out_var = xs.variable(dims=[(), "x"], intent="out")
            idx_var = xs.index(dims="x")

            def initialize(self):
                self.idx_var = [0, 1]

            def run_step(self):
                self.out_var = self.in_var * 2

        m = xs.Model({"p": P})

        in_ds = xs.create_setup(
            model=m,
            clocks={"clock": [0, 1, 2]},
            input_vars={"p__in_var": (dims, data)},
            output_vars={"p__out_var": clock},
        )

        out_ds = in_ds.xsimlab.run(
            model=m,
            batch_dim="batch",
            parallel=parallel,
            scheduler=scheduler,
            store=zarr.TempStore(),
        )

        if clock is None:
            coords = {}
        else:
            coords = {"clock": in_ds["clock"]}

        expected = xr.DataArray(data, dims=dims, coords=coords) * 2
        xr.testing.assert_equal(out_ds["p__out_var"], expected)
Example #24
0
def test_process_executor():
    @xs.process
    class P:
        in_var = xs.variable()
        out_var = xs.variable(intent="out")
        od_var = xs.on_demand()

        def run_step(self):
            self.out_var = self.in_var * 2

        @od_var.compute
        def _dummy(self):
            return None

    m = xs.Model({"p": P})
    executor = m.p.__xsimlab_executor__
    state = {("p", "in_var"): 1}

    expected = {("p", "out_var"): 2}
    actual = executor.execute(m.p, SimulationStage.RUN_STEP, {}, state=state)
    assert actual == expected

    assert executor.execute(m.p, SimulationStage.INITIALIZE, {},
                            state=state) == {}
    def test_resize_zarr_dataset(self):
        @xs.process
        class P:
            arr = xs.variable(dims="x", intent="out")

        model = xs.Model({"p": P})

        in_ds = xs.create_setup(
            model=model,
            clocks={"clock": [0, 1, 2]},
            output_vars={"p__arr": "clock"},
        )

        store = ZarrSimulationStore(in_ds, model)

        for step, size in zip([0, 1, 2], [1, 3, 2]):
            model.state[("p", "arr")] = np.ones(size)
            store.write_output_vars(-1, step)

        ztest = zarr.open_group(store.zgroup.store, mode="r")

        expected = np.array([[1.0, np.nan, np.nan], [1.0, 1.0, 1.0],
                             [1.0, 1.0, np.nan]])
        np.testing.assert_array_equal(ztest.p__arr, expected)
def test_model_repr(simple_model, simple_model_repr):
    assert repr_model(simple_model) == simple_model_repr

    expected = "<xsimlab.Model (0 processes, 0 inputs)>\n"
    assert repr(xs.Model({})) == expected
Example #27
0
import xsimlab as xs

import phydra
from phydra.components.main import Backend



# ``Bootstrap model`` has the minimal set of components required to
# simulate a

Bootstrap_model = xs.Model({
    'Grid': Backend
})


# ``NPZD Slab model`` has the minimal set of components required to
# simulate a

ZeroD_NPZD_Slab_model = xs.Model({
    'Grid': Backend
})


# ``ZeroD NPxZx Chemostat model`` has the minimal set of components required to
# simulate a

ZeroD_NPxZx_Chemostat_model = xs.Model({
    'Grid': Backend
})

Example #28
0
def no_init_model():
    return xs.Model({"roll": Roll, "add": Add, "profile": Profile})
Example #29
0
def simple_model():
    return xs.Model({"roll": Roll, "profile": Profile})
    def initialize(self):
        self.x = np.arange(0, self.length, self.spacing)
        self.u = np.exp(-1 / self.scale ** 2 * (self.x - self.loc) ** 2)

    @xs.runtime(args="step_delta")
    def run_step(self, dt):
        factor = (self.v * dt) / (2 * self.spacing)
        u_left = np.roll(self.u, 1)
        u_right = np.roll(self.u, -1)
        self.u1 = 0.5 * (u_right + u_left) - factor * (u_right - u_left)

    def finalize_step(self):
        self.u = self.u1


advect_model_raw = xs.Model({"advect": AdvectionLax1D})


@xs.process
class UniformGrid1D:
    """Create a 1-dimensional, equally spaced grid."""

    spacing = xs.variable(description="uniform spacing", static=True)
    length = xs.variable(description="total length", static=True)
    x = xs.index(dims="x")

    def initialize(self):
        self.x = np.arange(0, self.length, self.spacing)


@xs.process