Beispiel #1
0
def test_dual_processors(env, geometry_a):
    # move content from two different limited containers to an unlimited container at the same time
    limited_container_1 = BasicStorageUnit(env=env,
                                           geometry=geometry_a,
                                           capacity=1000,
                                           level=0,
                                           nr_resources=1)
    limited_container_2 = BasicStorageUnit(env=env,
                                           geometry=geometry_a,
                                           capacity=1000,
                                           level=0,
                                           nr_resources=1)
    unlimited_container = BasicStorageUnit(env=env,
                                           geometry=geometry_a,
                                           capacity=2000,
                                           level=1000,
                                           nr_resources=100)

    processor1 = Processor(
        env=env,
        name="Processor 1",
        loading_func=model.get_loading_func(2),
        unloading_func=model.get_unloading_func(2),
        geometry=geometry_a,
    )
    processor2 = Processor(
        env=env,
        name="Processor 2",
        loading_func=model.get_loading_func(1),
        unloading_func=model.get_unloading_func(1),
        geometry=geometry_a,
    )

    processor1.ActivityID = "Test activity"
    processor2.ActivityID = "Test activity"

    env.process(
        processor1.process(limited_container_1, 400, unlimited_container))
    env.process(
        processor2.process(limited_container_2, 400, unlimited_container))
    env.run()

    np.testing.assert_almost_equal(env.now, env.epoch + 400)
    assert unlimited_container.container.level == 200
    assert limited_container_1.container.level == 400
    assert limited_container_2.container.level == 400

    env.process(
        processor1.process(limited_container_1, 100, unlimited_container))
    env.process(
        processor2.process(limited_container_2, 300, unlimited_container))
    start = env.now
    env.run()
    time_spent = env.now - start

    np.testing.assert_almost_equal(time_spent, 150)
    assert unlimited_container.container.level == 600
    assert limited_container_1.container.level == 100
    assert limited_container_2.container.level == 300
Beispiel #2
0
def test_container_transfer_hub(env, geometry_a, Location, TransportProcessingResource):
    from_location = Location(
        env=env, name="From", geometry=geometry_a, capacity=1000, level=1000
    )
    transfer_location = Location(
        env=env, name="Transfer", geometry=geometry_a, capacity=500, level=0
    )
    to_location = Location(
        env=env, name="To", geometry=geometry_a, capacity=1000, level=0
    )

    delivery_vessel = TransportProcessingResource(
        env=env,
        name="Delivery",
        geometry=geometry_a,
        loading_func=model.get_loading_func(1),
        unloading_func=model.get_unloading_func(1),
        capacity=100,
        compute_v=(lambda x: 1),
    )

    collection_vessel = TransportProcessingResource(
        env=env,
        name="Collection",
        geometry=geometry_a,
        loading_func=model.get_loading_func(2),
        unloading_func=model.get_unloading_func(2),
        capacity=100,
        compute_v=(lambda x: 1),
    )

    model.Activity(
        env=env,
        name="Delivery Activity",
        origin=from_location,
        destination=transfer_location,
        loader=delivery_vessel,
        mover=delivery_vessel,
        unloader=delivery_vessel,
        stop_event=env.timeout(3000),
    )
    model.Activity(
        env=env,
        name="Collection Activity",
        origin=transfer_location,
        destination=to_location,
        loader=collection_vessel,
        mover=collection_vessel,
        unloader=collection_vessel,
        stop_event=env.timeout(3000),
    )

    env.run()
    assert from_location.container.level == 0
    assert transfer_location.container.level == 0
    assert to_location.container.level == 1000
Beispiel #3
0
def test_basic_processor(env, geometry_a):
    # move content from one container to another, then move some of it back again
    source = BasicStorageUnit(
        env=env, geometry=geometry_a, capacity=1000, level=1000, nr_resources=1
    )
    dest = BasicStorageUnit(
        env=env, geometry=geometry_a, capacity=1000, level=0, nr_resources=1
    )

    processor = Processor(
        env=env,
        loading_func=model.get_loading_func(2),
        unloading_func=model.get_unloading_func(2),
        geometry=geometry_a,
    )

    processor.ActivityID = "Test activity"

    env.process(processor.process(source, 400, dest))
    env.run()
    np.testing.assert_almost_equal(env.now, env.epoch + 300)
    assert source.container.level == 400
    assert dest.container.level == 600

    env.process(processor.process(dest, 300, source))
    start = env.now
    env.run()
    time_spent = env.now - start
    np.testing.assert_almost_equal(time_spent, 150)
    assert source.container.level == 700
    assert dest.container.level == 300
Beispiel #4
0
def test_processor(env, geometry_a, energy_use_sailing, energy_use_loading,
                   energy_use_unloading):

    source = BasicStorageUnit(env=env,
                              geometry=geometry_a,
                              capacity=1000,
                              level=1000,
                              nr_resources=1)
    dest = BasicStorageUnit(env=env,
                            geometry=geometry_a,
                            capacity=1000,
                            level=0,
                            nr_resources=1)

    processor = type(
        "processor",
        (core.Processor, core.EnergyUse, core.Locatable, core.Log), {})

    data_processor = {
        "env": env,
        "unloading_func": model.get_unloading_func(2),
        "loading_func": model.get_loading_func(2),
        "geometry": geometry_a,
        "energy_use_sailing": energy_use_sailing,
        "energy_use_loading": energy_use_loading,
        "energy_use_unloading": energy_use_unloading,
    }

    processor = processor(**data_processor)
    processor.ActivityID = "Test activity"

    # Log fuel use of the processor in step 1
    start = env.now
    env.process(processor.process(source, 400, dest))
    env.run()

    np.testing.assert_almost_equal(processor.log["Value"][-1],
                                   (env.now - start) * 4)

    # Log fuel use of the processor in step 2
    start = env.now
    env.process(processor.process(dest, 300, source))
    env.run()

    np.testing.assert_almost_equal(processor.log["Value"][-1],
                                   (env.now - start) * 4)
Beispiel #5
0
def test_sequential_activities(
    env, geometry_a, geometry_b, Location, TransportProcessingResource
):
    """ Test if activities only start after another one is finished. """

    amount = 10_000

    # Initialize from site with correct parameters
    data_from_location = {
        "env": env,  # The simpy environment
        "name": "Location A",  # The name of the "from location"
        "geometry": geometry_a,  # The coordinates of the "from location"
        "capacity": amount,  # The capacity of the "from location"
        "level": amount,
    }  # The actual volume of the "from location"
    data_to_location = {
        "env": env,  # The simpy environment
        "name": "Location B",  # The name of the "to location"
        "geometry": geometry_b,  # The coordinates of the "to location"
        "capacity": amount / 2,  # The capacity of the "to location"
        "level": 0,
    }  # The actual volume of the "to location"

    from_location = Location(**data_from_location)
    to_location_1 = Location(**data_to_location)
    to_location_2 = Location(**data_to_location)

    # make the vessel
    data_vessel = {
        "env": env,  # The simpy environment
        "name": "Vessel",
        "geometry": geometry_a,  # It is located at the "from location"
        "unloading_func": model.get_unloading_func(
            1
        ),  # Unloading production is 1 amount / s
        "loading_func": model.get_loading_func(1),  # Loading production is 1 amount / s
        "capacity": 1_000,  # Capacity of the vessel
        "compute_v": (lambda x: 1),
    }  # Speed is always 1 m / s
Beispiel #6
0
        "v": 1,  # Speed always 1 m/s
        "compute_draught": compute_draught(4.0, 7.0),  # Variable draught
        "waves": [0.5, 1],  # Waves with specific ukc
        "ukc": [0.75, 1],  # UKC corresponding to the waves
        "filling": None,
    }  # The filling degree

    mover = Mover(**data)
    mover.ActivityID = "Test activity"

    data = {
        "env": env,  # The simpy environment
        "name": "Quay Crane",  # Name
        "geometry": geometry_a,  # It starts at the "from site"
        "loading_func": model.get_loading_func(1.0),  # Loading rate
        "unloading_func": model.get_unloading_func(1.0),
    }  # Unloading rate

    crane = Processor(**data)
    crane.rate = crane.loading_func
    crane.ActivityID = "Test activity"

    # Initialize the LocationWeather
    data = {
        "env": env,  # The simpy environment defined in the first cel
        "name": "Limited Location",  # The name of the site
        "geometry": geometry_a,  # Location
        "capacity": 500_000,  # The capacity of the site
        "level": 500_000,  # The actual volume of the site
        "dataframe": weather_data,  # The dataframe containing the weather data
        "bed": -7,
Beispiel #7
0
    data_to_site = {
        "env": env,  # The simpy environment
        "name": "Location B",  # The name of the "to location"
        "geometry": location,  # The coordinates of the "to location"
        "capacity": 1_000,  # The capacity of the "to location"
        "level": 0,
    }  # The actual volume of the "to location"

    to_site = Location(**data_to_site)

    # make the processor with source terms
    data_processor = {
        "env": env,  # The simpy environment
        "geometry": location,  # The coordinates of the "processore"
        "unloading_func": model.get_unloading_func(
            1
        ),  # Unloading production is 1 amount / s
        "loading_func": model.get_loading_func(1),
    }  # Loading production is 1 amount / s

    processor = Processor(**data_processor)
    processor.ActivityID = "Test activity"

    # Log fuel use of the processor in step 1
    env.process(processor.process(from_site, 0, to_site))
    env.run()
    assert "fines released" in processor.log["Message"]
    fines = [
        processor.log["Value"][i]
        for i in range(len(processor.log["Value"]))
        if processor.log["Message"][i] == "fines released"
Beispiel #8
0
def test_Processor_ContainerDependentMovable(
    env,
    geometry_a,
    geometry_b,
    locatable_a,
    locatable_b,
    energy_use_sailing,
    energy_use_loading,
    energy_use_unloading,
):

    source = BasicStorageUnit(env=env,
                              geometry=geometry_a,
                              capacity=1000,
                              level=1000,
                              nr_resources=1)
    dest = BasicStorageUnit(env=env,
                            geometry=geometry_b,
                            capacity=1000,
                            level=0,
                            nr_resources=1)

    # The generic class for an object that can process (a quay crane for example)
    ProcessingResource = type(
        "ProcessingResource",
        (
            core.Identifiable,  # Give it a name
            core.Locatable,  # Allow logging of location
            core.Log,  # Allow logging of all discrete events
            core.Processor,  # Allow for loading and unloading
            core.HasResource,  # Add information on serving equipment
            core.EnergyUse,
        ),  # Add information on fuel
        {},
    )

    processor_1 = {
        "env": env,  # The simpy environment
        "name": "Processor 1",  # Name
        "geometry": geometry_a,  # It is located at location A
        "unloading_func": model.get_unloading_func(1),  # Unloading rate
        "loading_func": model.get_loading_func(2),  # Loading rate
        "energy_use_loading": energy_use_loading,  # Variable fuel use
        "energy_use_sailing": energy_use_sailing,  # Variable fuel use
        "energy_use_unloading": energy_use_loading,
    }  # Variable fuel use
    processor_2 = {
        "env": env,  # The simpy environment
        "name": "Processor 2",  # Name
        "geometry": geometry_b,  # It is located at location B
        "unloading_func": model.get_unloading_func(1),  # Unloading rate
        "loading_func": model.get_loading_func(2),  # Loading rate
        "energy_use_loading": energy_use_unloading,  # Variable fuel use
        "energy_use_sailing": energy_use_sailing,  # Variable fuel use
        "energy_use_unloading": energy_use_unloading,
    }  # Variable fuel use

    # The generic class for an object that can move an amount (a containervessel)
    mover = type(
        "Mover",
        (core.ContainerDependentMovable, core.EnergyUse, core.HasResource,
         core.Log),
        {},
    )

    data_mover = {
        "compute_v": lambda x: 1,
        "geometry": geometry_a,
        "env": env,
        "capacity": 1000,
        "energy_use_sailing": energy_use_sailing,
        "energy_use_loading": energy_use_loading,
        "energy_use_unloading": energy_use_unloading,
    }

    # The simulation objects
    processor_1 = ProcessingResource(**processor_1)
    processor_2 = ProcessingResource(**processor_2)
    containervessel = mover(**data_mover)

    processor_1.ActivityID = "Test activity"
    processor_2.ActivityID = "Test activity"
    containervessel.ActivityID = "Test activity"

    # Simulation starts with loading
    start = env.now
    env.process(processor_1.process(containervessel, 500, source))
    env.run()

    np.testing.assert_almost_equal(processor_1.log["Value"][-1],
                                   (env.now - start) * 4)

    # Simulation continues with moving from A to B
    start = env.now
    env.process(containervessel.move(locatable_b))
    env.run()

    np.testing.assert_almost_equal(containervessel.log["Value"][-2],
                                   (env.now - start) * 2.5,
                                   decimal=5)

    # Simulation ends with unloading
    start = env.now
    env.process(processor_2.process(containervessel, 0, dest))
    env.run()

    np.testing.assert_almost_equal(processor_2.log["Value"][-1],
                                   (env.now - start) * 3)
Beispiel #9
0
def test_TransportProcessingResource(
    env,
    geometry_a,
    geometry_b,
    locatable_a,
    locatable_b,
    energy_use_sailing,
    energy_use_loading,
    energy_use_unloading,
):

    source = BasicStorageUnit(env=env,
                              geometry=geometry_a,
                              capacity=1000,
                              level=1000,
                              nr_resources=1)
    dest = BasicStorageUnit(env=env,
                            geometry=geometry_b,
                            capacity=1000,
                            level=0,
                            nr_resources=1)

    # The generic class for an object that can move and transport (a TSHD for example)
    TransportProcessingResource = type(
        "TransportProcessingResource",
        (
            core.Identifiable,  # Give it a name
            core.Log,  # Allow logging of all discrete events
            core.
            ContainerDependentMovable,  # A moving container, so capacity and location
            core.Processor,  # Allow for loading and unloading
            core.HasResource,  # Allow queueing
            core.EnergyUse,
        ),  # Allow logging energy use
        {},
    )

    # TSHD variables
    data_hopper = {
        "env": env,  # The simpy environment
        "name": "Hopper",  # Name
        "geometry": geometry_b,  # It starts at the "to site"
        "unloading_func": model.get_unloading_func(1),  # Unloading rate
        "loading_func": model.get_loading_func(2),  # Loading rate
        "capacity": 500,  # Capacity of the hopper
        "compute_v": lambda x: 1,  # Variable speed
        "energy_use_loading": energy_use_loading,  # Variable fuel use
        "energy_use_sailing": energy_use_sailing,  # Variable fuel use
        "energy_use_unloading": energy_use_unloading,
    }  # Variable fuel use

    # The simulation object
    hopper = TransportProcessingResource(**data_hopper)
    hopper.ActivityID = "Test activity"

    # Simulation starts with moving to A
    start = env.now
    env.process(hopper.move(source))
    env.run()

    # moving empty to energy use is 2 per second
    np.testing.assert_almost_equal(hopper.log["Value"][-2],
                                   (env.now - start) * 2,
                                   decimal=5)

    # Simulation continues with loading
    start = env.now
    env.process(hopper.process(hopper, 500, source))
    env.run()

    # Duration should be amount / 2
    # Energy use duration * 4
    np.testing.assert_almost_equal(hopper.log["Value"][-2],
                                   (env.now - start) * 4)

    # Simulation continues with moving from A to B
    start = env.now
    env.process(hopper.move(locatable_b))
    env.run()

    # moving full so energy use is 3 per second
    np.testing.assert_almost_equal(hopper.log["Value"][-2],
                                   (env.now - start) * 3,
                                   decimal=5)

    # Simulation ends with unloading
    hopper.rate = hopper.unloading_func
    start = env.now
    env.process(hopper.process(hopper, 0, dest))
    env.run()

    np.testing.assert_almost_equal(hopper.log["Value"][-2],
                                   (env.now - start) * 3)
Beispiel #10
0
def available_equipment(env):
    # should be read from database
    equipment_data = [
        {
            "id": "EGG123",
            "type": "Side stone dumping vessel",
            "speed loaded": 6.5,
            "tonnage": 2601,
            "lat": 52.94239823421129,
            "lon": 5.019298185633251,
            "tags": ["mover"],
        },
        {
            "id": "Boaty McBoatStone",
            "type": "Multi purpose support vessel",
            "speed loaded": 7.0,
            "tonnage": 1824,
            "capacity": 10.3,
            "lat": 52.94239823421129,
            "lon": 5.019298185633251,
            "tags": ["loader", "mover"],
        },
        {
            "id": "Loady McLoader",
            "type": "Simple Loading Crane",
            "lat": 52.94239823421129,
            "lon": 5.019298185633251,
            "capacity": 13.2,
        },
        {
            "id": "Unloady McUnloader",
            "type": "Simple Loading Crane",
            "lat": 52.94042293840172,
            "lon": 5.054676856441372,
            "capacity": 12.1,
        },
    ]

    type_to_mixins_mapping = {
        "Side stone dumping vessel": (
            core.Identifiable,
            core.Log,
            core.ContainerDependentMovable,
            core.HasResource,
            core.Locatable,
        ),
        "Multi purpose support vessel": (
            core.Identifiable,
            core.Log,
            core.ContainerDependentMovable,
            core.Processor,
            core.HasResource,
            core.Locatable,
        ),
        "Simple Loading Crane": (
            core.Identifiable,
            core.Log,
            core.Processor,
            core.HasResource,
            core.Locatable,
        ),
    }

    ship_mixins = {}
    for data in equipment_data:
        ship_type = data["type"]
        mixin_classes = type_to_mixins_mapping[ship_type]
        klass = type(type_to_class_name(ship_type), mixin_classes, {})
        ureg = pint.UnitRegistry()
        kwargs = dict(env=env, name=data["id"])
        if issubclass(klass, core.Processor):
            processing_speed = (
                data["capacity"] * ureg.ton / ureg.minute
            ).to_base_units()
            kwargs["loading_func"] = model.get_loading_func(processing_speed.magnitude)
            kwargs["unloading_func"] = model.get_unloading_func(
                processing_speed.magnitude
            )
        if issubclass(klass, core.HasResource):
            kwargs["nr_resources"] = 1
        if issubclass(klass, core.HasContainer):
            tonnage = (data["tonnage"] * ureg.metric_ton).to_base_units()
            kwargs["capacity"] = tonnage.magnitude
        if issubclass(klass, core.Locatable):
            # todo change this to something read from the database
            kwargs["geometry"] = shapely.geometry.Point(data["lon"], data["lat"])
        if issubclass(klass, core.Movable):
            speed_loaded = (data["speed loaded"] * ureg.knot).to_base_units().magnitude
            if issubclass(klass, core.ContainerDependentMovable):
                kwargs["compute_v"] = compute_v_linear(speed_loaded * 2, speed_loaded)
            else:
                kwargs["v"] = speed_loaded

        ship = klass(**kwargs)
        ship_mixins[data["id"]] = ship
    return ship_mixins
Beispiel #11
0
def test_dual_processors_with_limit(env, geometry_a):
    # move content into a limited container, have two process wait for each other to finish
    unlimited_container_1 = BasicStorageUnit(env=env,
                                             geometry=geometry_a,
                                             capacity=1000,
                                             level=1000,
                                             nr_resources=100)
    unlimited_container_2 = BasicStorageUnit(env=env,
                                             geometry=geometry_a,
                                             capacity=1000,
                                             level=1000,
                                             nr_resources=100)
    unlimited_container_3 = BasicStorageUnit(env=env,
                                             geometry=geometry_a,
                                             capacity=2000,
                                             level=0,
                                             nr_resources=100)
    limited_container = BasicStorageUnit(env=env,
                                         geometry=geometry_a,
                                         capacity=2000,
                                         level=0,
                                         nr_resources=1)

    processor1 = Processor(
        env=env,
        name="Processor 1",
        loading_func=model.get_loading_func(1),
        unloading_func=model.get_unloading_func(1),
        geometry=geometry_a,
    )
    processor2 = Processor(
        env=env,
        name="Processor 2",
        loading_func=model.get_loading_func(1),
        unloading_func=model.get_unloading_func(1),
        geometry=geometry_a,
    )

    processor1.ActivityID = "Test activity"
    processor2.ActivityID = "Test activity"

    env.process(
        model.single_run_process(
            processor1,
            env,
            unlimited_container_1,
            limited_container,
            processor1,
            unlimited_container_3,
            processor1,
        ))
    env.process(
        model.single_run_process(
            processor2,
            env,
            unlimited_container_2,
            limited_container,
            processor2,
            unlimited_container_3,
            processor2,
        ))
    env.run()

    # Simultaneous accessing limited_container, so waiting event of 1000 seconds
    np.testing.assert_almost_equal(env.now, env.epoch + 3000)
    assert limited_container.container.level == 2000
    assert unlimited_container_1.container.level == 0
    assert unlimited_container_2.container.level == 0