opendrift icon indicating copy to clipboard operation
opendrift copied to clipboard

OpenDrift simulation should consist of separate steps

Open gauteh opened this issue 3 years ago • 2 comments

  • Data integrity: reduce chance of aliasing
    • Less chance of confusion
    • Can reuse init object, since it is not mutated by simulation
    • Since it can be reused it can be used for parallelization
  • Methods can only be run on a simulation that is in a valid state:
    • Plot is only meaningful on result (at least as it is)
  • Easier to separate data from functionality:
    • Result should (hopefully) have a single data member (xarray dataset?), with some convenience methods
  • Generic Analysis package can work on this data member, and thus be non-opendrift specific.
  • Less coupled code: maintenance should be easier and more fun!

gauteh avatar Oct 05 '22 08:10 gauteh

import xarray as xr

class OcenaDriftState:
    pass

class Init(OcenaDriftState):

    config = { }

    def seed(..):
        pass

    def set_config(..):
        pass

    def serialize(..):
        pass

    def deserialize_from(something):
        pass

class Simulation(OcenaDriftState):
    def __init__(self, init):
        self.init = init

    adve

class Result(OcenaDriftState):
    data: xr.Dataset

    def __init__(self, simu):
        pass

    @property
    def elements(self):
        return self.data.history[:].values

    def plot(self):
        pass

    def to_netcdf(self, fname):
        pass

class ChemResult(Result):
    def metavars():

    def _extra_vars_(self):
        return [ xr.DataArray ]

class NewModel:
    class Init:
        pass

    class Simulation:
        pass

    class Result:
        pass

class OceanDrift:
    state: OcenaDriftState

    def __init__(self):
        self.state = Init()

    def seed(self, lat, lon):
        # ..
        return self

    def run(self):
        assert isinstance(self.state, Init), "Wrong state"

        self.state = Simulation(self.state)
        self.state = Result(self.state.run()) # ... long time
        return self.state

    def __getattr__(self, attr):
        """
        Forward all other method calls and attributes to reader.
        """
        return getattr(self.state, attr)

    def plot(self, *args, **kwargs):
        match self.state:
            case Result:
                return self.state.plot()
            case Init:
                return self.state.plot(..)
            case Simulation:
                raise NotImplemented()



OceanDrift().seed(3, 4).run().plot()

OceanDrift().set_x_wind

f = OceanDrift() \
        .seed(3, 5) \
        .seed(4, 6) \
        .run() \
        .plot()


o = OceanDrift()
o.seed(..)
o.seed(..)

gauteh avatar Oct 05 '22 12:10 gauteh

o = OceanDrift().set_config()
o.add_readers(..)

ii = o.split(8)

with ThreadPoolExecutor as ex:
    i1 = o.seed(1)
    i2 = o.seed(2)

    r1 = ex.map(i1, run)
    r2 = ex.map(i2, run)

opendrift.CombinedResult([r1, r2])

gauteh avatar Oct 05 '22 12:10 gauteh