Skip to content

Commit

Permalink
Merge pull request #2 from simphony/v2.4.0-dev
Browse files Browse the repository at this point in the history
v2.4.0 dev
  • Loading branch information
pablo-de-andres committed Aug 28, 2020
2 parents bb7f91d + 8635b1c commit 2e44194
Show file tree
Hide file tree
Showing 13 changed files with 295 additions and 33 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ __pycache__/
build/
dist/
*~*
*.egg-info
.mypy_cache/
coverage.xml
.coverage
Expand Down
13 changes: 13 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
BSD 3-Clause
Copyright 2020 SimPhoNy OSP-core developers

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.

3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
9 changes: 6 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Wrapper Development
*Version*: 2.3.0
*Version*: 2.4.0

The aim of this project is simplify as much as possible the development of a new Wrapper for __SimPhoNy v3__.
For this, the general folder and file structure of a wrapper is simulated here, and notes on what to do are provided.
Expand All @@ -14,13 +14,16 @@ Material Informatics team, Fraunhofer IWM.

## Compatibility

The following table describes the version compatibility between the [OSP core](https://gitlab.cc-asp.fraunhofer.de/simphony/osp-core) package and this project.
The following table describes the version compatibility between the [OSP core](https://github.com/simphony/osp-core/) package and this project.

| __Wrapper development__ | __OSP core__ |
|:-----------------------:|:------------:|
| 2.4.0 | 3.5.0-beta |
| 2.3.0 | 3.3.5-beta |
| 2.2.0 | 3.3.0-beta |
| 2.1.0 | 3.2.x-beta |
| 2.0.0 | 3.1.x-beta |

The releases of OSP core are available [here](https://github.com/simphony/osp-core/releases).
The releases of OSP core are available [here](https://github.com/simphony/osp-core/releases).

In `osp/wrappers/simple_simulation` you will find a minimalistic wrapper with the required elements implemented.
28 changes: 28 additions & 0 deletions examples/simple_example.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# This code runs on the wrapper under ../osp/wrappers/simple_simulation

from osp.core.namespaces import simple_ontology
from osp.wrappers.simple_simulation import SimpleSimulationSession
from osp.core.utils import pretty_print
import numpy as np

m = simple_ontology.Material()
for i in range(3):
a = m.add(simple_ontology.Atom())
a.add(
simple_ontology.Position(value=[i, i, i], unit="m"),
simple_ontology.Velocity(value=np.random.random(3), unit="m/s")
)

# Run a simulation
with SimpleSimulationSession() as session:
w = simple_ontology.Wrapper(session=session)
m = w.add(m)
w.session.run()

pretty_print(m)

for atom in m.get(rel=simple_ontology.hasPart):
atom.get(oclass=simple_ontology.Velocity)[0].value = [0, 0, 0]
w.session.run()

pretty_print(m)
2 changes: 2 additions & 0 deletions osp/wrappers/simple_simulation/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
from osp.wrappers.simple_simulation.simulation_engine import SimulationEngine
from osp.wrappers.simple_simulation.simple_simulation_session import SimpleSimulationSession
80 changes: 80 additions & 0 deletions osp/wrappers/simple_simulation/simple_ontology.ontology.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
---
version: 0.0.2
author: Me
namespace: simple_ontology

ontology:

Atom:
subclass_of:
- cuba.Class
- simple_ontology.hasPart:
cardinality: some
exclusive: false
range: simple_ontology.Position
- simple_ontology.hasPart:
cardinality: some
exclusive: false
range: simple_ontology.Velocity

Material:
subclass_of:
- cuba.Class
- simple_ontology.hasPart:
cardinality: some
exclusive: true
range: simple_ontology.Atom

PhysicalQuantity:
attributes:
simple_ontology.unit: null
simple_ontology.value: null
subclass_of:
- cuba.Class

Position:
subclass_of:
- simple_ontology.PhysicalQuantity

Velocity:
subclass_of:
- simple_ontology.PhysicalQuantity

Wrapper:
subclass_of:
- cuba.Wrapper
- simple_ontology.hasPart:
cardinality: some
exclusive: true
range: simple_ontology.Material

encloses:
inverse: simple_ontology.isEnclosedBy
subclass_of:
- cuba.activeRelationship

hasPart:
default_rel: true
inverse: simple_ontology.isPartOf
subclass_of:
- simple_ontology.encloses

isEnclosedBy:
inverse: simple_ontology.encloses
subclass_of:
- cuba.passiveRelationship

isPartOf:
inverse: simple_ontology.hasPart
subclass_of:
- simple_ontology.isEnclosedBy

unit:
datatype: STRING
subclass_of:
- cuba.attribute

value:
datatype: VECTOR:3
subclass_of:
- cuba.attribute
75 changes: 75 additions & 0 deletions osp/wrappers/simple_simulation/simple_simulation_session.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
from osp.core.session import SimWrapperSession
from osp.wrappers.simple_simulation import SimulationEngine
from osp.core.namespaces import simple_ontology


class SimpleSimulationSession(SimWrapperSession):
"""
Session class for some engine.
"""

def __init__(self, engine=None, **kwargs):
super().__init__(engine or SimulationEngine(), **kwargs)
self.mapper = dict() # maps uuid to index in the backend

def __str__(self):
return "Simple sample Wrapper Session"

# OVERRIDE
def _apply_added(self, root_obj, buffer):
"""Adds the added cuds to the engine."""
for obj in buffer.values():
if obj.is_a(simple_ontology.Atom):
self.mapper[obj.uid] = len(self.mapper)
pos = obj.get(oclass=simple_ontology.Position)[0].value
vel = obj.get(oclass=simple_ontology.Velocity)[0].value
self._engine.add_atom(pos, vel)

# OVERRIDE
def _apply_updated(self, root_obj, buffer):
"""Updates the updated cuds in the engine."""
for obj in buffer.values():

# case 1: we change the velocity
if obj.is_a(simple_ontology.Velocity):
atom = obj.get(rel=simple_ontology.isPartOf)[0]
idx = self.mapper[atom.uid]
self._engine.update_velocity(idx, obj.value)

# case 2: we change the position
elif obj.is_a(simple_ontology.Position):
atom = obj.get(rel=simple_ontology.isPartOf)[0]
idx = self.mapper[atom.uid]
self._engine.update_position(idx, obj.value)

# OVERRIDE
def _apply_deleted(self, root_obj, buffer):
"""Deletes the deleted cuds from the engine."""

# OVERRIDE
def _load_from_backend(self, uids, expired=None):
"""Loads the cuds object from the simulation engine"""
for uid in uids:
if uid in self._registry:
obj = self._registry.get(uid)

# check whether user wants to load a position
if obj.is_a(simple_ontology.Position):
atom = obj.get(rel=simple_ontology.isPartOf)[0]
idx = self.mapper[atom.uid]
pos = self._engine.get_position(idx)
obj.value = pos

# check whether user wants to load a velocity
elif obj.is_a(simple_ontology.Velocity):
atom = obj.get(rel=simple_ontology.isPartOf)[0]
idx = self.mapper[atom.uid]
vel = self._engine.get_velocity(idx)
obj.value = vel

yield obj

# OVERRIDE
def _run(self, root_cuds_object):
"""Call the run command of the engine."""
self._engine.run()
82 changes: 82 additions & 0 deletions osp/wrappers/simple_simulation/simulation_engine.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
# This file contains simple code to emulate communication with an engine.
# It acts like a dummy syntactic layer.

class Atom():

def __init__(self, position, velocity):
self.position = position
self.velocity = velocity


class SimulationEngine:
"""
Simple engine sample code.
"""

def __init__(self):
self.atoms = list()
print("Engine instantiated!")

def __str__(self):
return "Some Engine Connection"

def run(self, timesteps=1):
"""Call the run command of the engine."""
print("Now the engine is running")
for atom in self.atoms:
atom.position += atom.velocity * timesteps

def add_atom(self, position, velocity):
"""Add an atom to the engine.
Args:
position (array): A 3D array for the position of the atom.
velocity (array): A 3D array for the velocity of the atom.
"""
print("Add atom %s with position %s and velocity %s"
% (len(self.atoms), position, velocity))
self.atoms.append(Atom(position, velocity))

def update_position(self, idx, position):
"""Update the position of the atom
Args:
idx (int): The index of the atom to update
position (array): The new position.
"""
print("Update atom %s. Setting position to %s"
% (idx, position))
self.atoms[idx].position = position

def update_velocity(self, idx, velocity):
"""Update the velocity of an atom.
Args:
idx (int): The index of the atom
velocity (array): The new velocity.
"""
print("Update atom %s. Setting velocity to %s"
% (idx, velocity))
self.atoms[idx].velocity = velocity

def get_velocity(self, idx):
"""Get the velocity of an atom.
Args:
idx (int): The index of the atom.
Returns:
array: The velocity of the atom.
"""
return self.atoms[idx].velocity

def get_position(self, idx):
"""Get the position of the atom.
Args:
idx (int): The index of the atom.
Returns:
array: The position of the atom.
"""
return self.atoms[idx].position
16 changes: 2 additions & 14 deletions osp/wrappers/some_database_session.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,4 @@
# Copyright (c) 2014-2019, Adham Hashibon, Materials Informatics Team,
# Fraunhofer IWM.
# All rights reserved.
# Redistribution and use are limited to the scope agreed with the end user.
# No parts of this software may be used outside of this context.
# No redistribution is allowed without explicit written permission.

# TODO: Import the python connection to the DB

from osp.core.session import DbWrapperSession


Expand Down Expand Up @@ -81,11 +73,7 @@ def _load_first_level(self):
# that are direct neighbors of the wrapper
pass

# OVERRIDE
def _load_from_backend(self, uids, expired=None):
# TODO load cuds objects from the backend
print("WARNING: please override _load_from_backend method of your session")
for uid in uids:
if uid in self._registry:
yield self._registry[uid]
else:
yield None
pass
3 changes: 0 additions & 3 deletions osp/wrappers/some_simulation_session.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
# Maybe some copyright stuff goes here

# TODO: Import the python connection to the engine

from osp.core.session import SimWrapperSession
Expand All @@ -26,7 +24,6 @@ def _run(self, root_cuds_object):
# OVERRIDE
def _load_from_backend(self, uids, expired=None):
"""Loads the cuds object from the simulation engine"""
print("WARNING: please override _load_from_backend method of your session")
for uid in uids:
if uid in self._registry:
yield self._registry[uid]
Expand Down
7 changes: 0 additions & 7 deletions osp/wrappers/some_sql_database_session.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,3 @@
# Copyright (c) 2014-2019, Adham Hashibon, Materials Informatics Team,
# Fraunhofer IWM.
# All rights reserved.
# Redistribution and use are limited to the scope agreed with the end user.
# No parts of this software may be used outside of this context.
# No redistribution is allowed without explicit written permission.

# TODO: Import the python connection to the DB

from osp.core.session import SqlWrapperSession
Expand Down
4 changes: 2 additions & 2 deletions packageinfo.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
NAME = "simphony_wrapper_for_something"
VERSION = "0.0.1"
# These are used for the compatibility in the Docker and CI images
OSP_CORE_MIN = "3.3.5"
OSP_CORE_MAX = "3.4.0"
OSP_CORE_MIN = "3.5.0"
OSP_CORE_MAX = "3.6.0"

0 comments on commit 2e44194

Please sign in to comment.