Code Monkey home page Code Monkey logo

wombat's People

Contributors

dmulas avatar gbarter avatar pre-commit-ci[bot] avatar rhammond2 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

wombat's Issues

Swap Pandas out for Polars for simulation-specific tasks

Pandas 2.0 has greatly decreased the runtime performance of WOMBAT due to significantly slower indexing and search. Initial tests confirm that Polars is significantly faster at the exact operations required in the simulation, and so it'd be beneficial to convert the weather dataframe, specifically. Below is an example of extracting a single row from the weather profile in both pandas and polars.

image

Event log file does not have headers or column names

I was running the how_to jupyter notebook (see the code that I ran below) and encounter the following errors. I think the issue is that the code expects the first column of the event log file to have the column names. I can resolve this issue by setting the read_option to be ReadOptions(autogenerate_column_names=True), but then another error popped up as the code is expecting the some fixed column names such as date_time.

Code

from time import perf_counter
from wombat import Simulation
from wombat.core.library import load_yaml, DINWOODIE

library_path = DINWOODIE
config = load_yaml(library_path / "project/config", "base.yaml")
sim = Simulation.from_config(config)
sim.env.cleanup_log_files()

start = perf_counter()
sim.run()
end = perf_counter()
timing = end - start
print(f"Run time: {timing / 60:,.2f} minutes")

Error Message

ValueError                                Traceback (most recent call last)
Cell In[2], line 2
      1 start = perf_counter()
----> 2 sim.run()
      3 end = perf_counter()
      4 timing = end - start

File ~/miniconda3/envs/wisdem/lib/python3.10/site-packages/wombat/core/simulation_api.py:326, in Simulation.run(self, until, create_metrics, save_metrics_inputs)
    324     self.save_metrics_inputs()
    325 if create_metrics:
--> 326     self.initialize_metrics()

File ~/miniconda3/envs/wisdem/lib/python3.10/site-packages/wombat/core/simulation_api.py:330, in Simulation.initialize_metrics(self)
    328 def initialize_metrics(self) -> None:
    329     """Instantiates the ``metrics`` attribute after the simulation is run."""
--> 330     events = self.env.load_events_log_dataframe()
    331     operations = self.env.load_operations_log_dataframe()
    332     power_potential, power_production = self.env.power_production_potential_to_csv(
    333         windfarm=self.windfarm, operations=operations, return_df=True
    334     )

File ~/miniconda3/envs/wisdem/lib/python3.10/site-packages/wombat/core/environment.py:679, in WombatEnvironment.load_events_log_dataframe(self)
    671 convert_options = pa.csv.ConvertOptions(
    672     timestamp_parsers=["%Y-%m-%d %H:%M:%S.%f", "%Y-%m-%d %H:%M:%S"]
    673 )
    674 parse_options = pa.csv.ParseOptions(delimiter="|")
    675 log_df = pa.csv.read_csv(
    676     self.events_log_fname,
    677     convert_options=convert_options,
    678     parse_options=parse_options,
--> 679 ).to_pandas()
    680 if not pd.api.types.is_datetime64_any_dtype(log_df.datetime):
    681     log_df.datetime = pd.to_datetime(
    682         log_df.datetime, yearfirst=True, format="mixed"
    683     )

File ~/miniconda3/envs/wisdem/lib/python3.10/site-packages/pyarrow/array.pxi:837, in pyarrow.lib._PandasConvertible.to_pandas()

File ~/miniconda3/envs/wisdem/lib/python3.10/site-packages/pyarrow/table.pxi:4114, in pyarrow.lib.Table._to_pandas()

File ~/miniconda3/envs/wisdem/lib/python3.10/site-packages/pyarrow/pandas_compat.py:819, in table_to_blockmanager(options, table, categories, ignore_metadata, types_mapper)
    816     ext_columns_dtypes = _get_extension_dtypes(table, [], types_mapper)
    818 _check_data_column_metadata_consistency(all_columns)
--> 819 columns = _deserialize_column_index(table, all_columns, column_indexes)
    820 blocks = _table_to_blocks(options, table, categories, ext_columns_dtypes)
    822 axes = [columns, index]

File ~/miniconda3/envs/wisdem/lib/python3.10/site-packages/pyarrow/pandas_compat.py:938, in _deserialize_column_index(block_table, all_columns, column_indexes)
    935     columns = _reconstruct_columns_from_metadata(columns, column_indexes)
    937 # ARROW-1751: flatten a single level column MultiIndex for pandas 0.21.0
--> 938 columns = _flatten_single_level_multiindex(columns)
    940 return columns

File ~/miniconda3/envs/wisdem/lib/python3.10/site-packages/pyarrow/pandas_compat.py:1184, in _flatten_single_level_multiindex(index)
   1182     # Cheaply check that we do not somehow have duplicate column names
   1183     if not index.is_unique:
-> 1184         raise ValueError('Found non-unique column index')
   1186     return pd.Index(
   1187         [levels[_label] if _label != -1 else None for _label in labels],
   1188         dtype=dtype,
   1189         name=index.names[0]
   1190     )
   1191 return index

ValueError: Found non-unique column index

First 4 lines of the event log file (note no column names)

2023-06-20 21:56:06.625773|2003-01-01 00:00:00|0|S00T1|subassemblies created: ['turbine']|windfarm initialization|initialization|S00T1|S00T1|||1.0|1|0|0|na|na|0|0|0|0|0|0
2023-06-20 21:56:06.657014|2003-01-01 00:00:00|0|S00T2|subassemblies created: ['turbine']|windfarm initialization|initialization|S00T2|S00T2|||1.0|1|0|0|na|na|0|0|0|0|0|0
2023-06-20 21:56:06.685828|2003-01-01 00:00:00|0|S00T3|subassemblies created: ['turbine']|windfarm initialization|initialization|S00T3|S00T3|||1.0|1|0|0|na|na|0|0|0|0|0|0

Support for weather profiles with many columns

Weather profiles that have more columns than ["datetime", "windspeed", "wave_height"] will cause an error here: https://github.com/WISDEM/WOMBAT/blob/main/wombat/core/environment.py#L520.

A simple fix such as the following could allow for more robust workflows using WOMBAT:

  1. reordering the columns to be in the expected order when setting up the weather data
  2. when getting the weather forecast in-code, use the following:
    wind, wave, hour, *_ = self.weather.values[start:end].T

Double counting weather delays

If CTVs are always on site, the total duration of all activities should be equal to the simulation period. This isn't the case. Comparing the cumulative CTV activity duration and the env_time, it looks like the CTV is allowing 2x each weather delay to elapse before it tries to do anything. This also appears to be true for vessels that are not always on site.

Windfarm/Turbine Losses Model

A model to post-hoc apply aggregate model losses (wake, electrical, etc.) would be ideal to better translate between the power production model and what is typically seen in operational analyses.

Date-Based Maintenance

Potentially consider providing date, or set of dates for when to trigger a timeout instead of a fixed time frequency. This allows maintenance to be scheduled in particular times of year.

Additional Weather Constraint Support

Enable the ability to model sea surface icing or turbine icing for crew accessibility/safety constraints. This would require humidity, temperature, and visibility constraints (helicopter access).

Random seed not respected when specified in configuration file that is loaded automatically given a library path and configuration file name

I seem to have found a small bug in which the random seed I set in my configuration file is not being used in the simulation.

I created my simulation using Simulation() rather than the Simulation.from_config(). Unlike when using the from_config function, when using the default class initialization my random seed loads correctly as part of the Simulation.config attribute but is not applied to the Simulation.random_seed attribute directly. When Simulation._setup_simulation() calls, it passes only the random_seed attribute on the simulation object, not the version from the config attribute, when it instantiates the WombatEnvironment class. As a result, the environment detects no random seed.

Apologies if I have misunderstood something, but it seems like this is probably not the desired behaviour. Everything works fine if I pass the random seed directly as a parameter into the Simulation() function, or if I load using from_config(), so it seems to just be this one case which has the problem.

I am using WOMBAT v0.9.3.

Multi-Crew Handoff

Functionality to enable multiple service crews in one servicing equipment, particularly for offshore wind scenarios would enable more realistic crew transfer vessel functionality

Monte Carlo Simulation Methodoloy

To better understand the effect of model uncertainty, it would be great to have the ability to model a probability distribution surrounding the failure rates in the model.

More sensible repair time starts

It would be great if any operations at site wouldn't start until the next shift if less than an hour or two of work will be done on that task in the current shift.

Alternatively, it could make sense for shifts to be continuous with a rotating crew for x number of days until a vessel refresh is required, with a default of a single shift to maintain compatibility with land-based servicing regimes.

Tow-to-Port Repair Logic

A major innovation in offshore wind will be tow-to-port repairs, and should be considered for the next batch of model updates.

Tow-to-Port Costing Improvements

After some external review it would be best to revamp the tow-to-port model now that it works and does pretty well overall compare to other models.

  • Swap out the monthly fee for an annual lease fee
  • Include port usage fees
  • Include tugboat mobilization costs
  • Tugboats should attempt to find a suitable weather window prior to beginning the travel out to site, reducing the overall weather delays associated with tugboats

distance_km is NaN for CTVs

With the latest update, the distance_km output metric is reporting NaN for CTVs (and sometimes DSVs but not always). Nothing is obviously wrong with the CTV distances in the events log
image

Weather Model

To better understand the tradeoffs in weather conditions, it would be ideal to have a probabilistic weather model, as opposed to a fixed weather model. In addition, it would enable more robust model comparison for various global regions with some predefined inputs to be used for weather profile generation instead of creating/downloading and modifying unique weather profiles.

Corewind - Tow to port config not working [WTG is not in list]

Hi

Trying to reproduce the corewind tow to port case. Before starting my own simulations.
When running it I get a simulation failed message as below.

Is this something that has been experienced before?

Regards
Filip

library_path =  Path(r."WOMBAT\library\corewind")
config = load_yaml("corewind/project/config", "morro_bay_tow_to_port.yaml")
sim = Simulation(library_path=library_path, config=config, random_seed=2023)
sim.run()
Simulation failed at hour 118,560.500503, simulation time: 2015-07-12 00:30:02
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
File [~\OneDrive](http://localhost:8888/lab/tree/~/OneDrive) [Deducted] - \wombat\core\repair_management.py:264, in RepairManager._run_equipment_requests(self, request)
    263     return
--> 264 self.invalidate_system(system, tow=True)
    265 yield self.env.process(self.port.run_tow_to_port(request))

File [~\OneDrive](http://localhost:8888/lab/tree/~/OneDrive) - [Deducted] \wombat\core\repair_management.py:532, in RepairManager.invalidate_system(self, system, tow)
    530 self.systems_in_tow.append(system.id)
    531 _ = self.systems_waiting_for_tow.pop(
--> 532     self.systems_waiting_for_tow.index(system.id)
    533 )

ValueError: 'WTG_0607' is not in list

The above exception was the direct cause of the following exception:

ValueError                                Traceback (most recent call last)
Cell In[35], line 4
      1 # Timing for a demonstration of performance
      2 start = perf_counter()
----> 4 sim.run()
      6 end = perf_counter()
      8 timing = end - start

File [~\OneDrive](http://localhost:8888/lab/tree/~/OneDrive [Deducted] wombat\core\simulation_api.py:348, in Simulation.run(self, until, create_metrics, save_metrics_inputs)
    325 def run(
    326     self,
    327     until: int | float | Event | None = None,
    328     create_metrics: bool = True,
    329     save_metrics_inputs: bool = True,
    330 ):
    331     """Calls ``WombatEnvironment.run()`` and gathers the results for
    332     post-processing. See ``wombat.simulation.WombatEnvironment.run`` or
    333     ``simpy.Environment.run`` for more details.
   (...)
    346         False, the data will not be saved, by default True.
    347     """
--> 348     self.env.run(until=until)
    349     if save_metrics_inputs:
    350         self.save_metrics_inputs()

File [~\OneDrive](http://localhost:8888/lab/tree/~/OneDrive [Deducted]/wombat\core\environment.py:247, in WombatEnvironment.run(self, until)
    242     self._operations_csv.close()
    243     print(
    244         f"Simulation failed at hour {self.now:,.6f},"
    245         f" simulation time: {self.simulation_time}"
    246     )
--> 247     raise e
    249 # Ensure all logged events make it to their target file
    250 self._events_writer.writerows(self._events_buffer)

File [~\OneDrive](http://localhost:8888/lab/tree/~/OneDrive [Deducted] wombat\core\environment.py:234, in WombatEnvironment.run(self, until)
    232     until = self.max_run_time
    233 try:
--> 234     super().run(until=until)
    235 except BaseException as e:
    236     # Flush the logs to so the simulation up to the point of failure is logged
    237     self._events_writer.writerows(self._events_buffer)

File [~\miniconda3\envs\wombat39\lib\site-packages\simpy\core.py:246](http://localhost:8888/lab/tree/~/miniconda3/envs/wombat39/lib/site-packages/simpy/core.py#line=245), in Environment.run(self, until)
    244 try:
    245     while True:
--> 246         self.step()
    247 except StopSimulation as exc:
    248     return exc.args[0]  # == until.value

File [~\miniconda3\envs\wombat39\lib\site-packages\simpy\core.py:204](http://localhost:8888/lab/tree/~/miniconda3/envs/wombat39/lib/site-packages/simpy/core.py#line=203), in Environment.step(self)
    202 exc = type(event._value)(*event._value.args)
    203 exc.__cause__ = event._value
--> 204 raise exc

ValueError: 'WTG_0607' is not in list

Strings with a fork don't resolve correctly

When an array cable string splits into two diverging upstream paths, the upstream cable/turbine connections don't resolve correctly. Likely a customized graph model is required for this scenario instead of a sequentially defined, CSV-based model.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.