Skip to content

Commit 42d64e3

Browse files
authored
Merge pull request #189 from markcoletti/main
Bringing over current ensemble code from forked repo
2 parents 6f02737 + 5a4e5d1 commit 42d64e3

File tree

10 files changed

+587
-148
lines changed

10 files changed

+587
-148
lines changed

.gitignore

Lines changed: 84 additions & 132 deletions
Original file line numberDiff line numberDiff line change
@@ -1,138 +1,90 @@
1-
# Byte-compiled / optimized / DLL files
2-
__pycache__/
3-
*.py[cod]
4-
*$py.class
5-
6-
# C extensions
7-
*.so
8-
9-
# Distribution / packaging
10-
.Python
11-
build/
12-
develop-eggs/
13-
dist/
14-
downloads/
15-
eggs/
16-
.eggs/
17-
lib/
18-
lib64/
19-
parts/
20-
sdist/
21-
var/
22-
wheels/
23-
share/python-wheels/
24-
*.egg-info/
25-
.installed.cfg
26-
*.egg
27-
MANIFEST
28-
29-
# PyInstaller
30-
# Usually these files are written by a python script from a template
31-
# before PyInstaller builds the exe, so as to inject date/other infos into it.
32-
*.manifest
33-
*.spec
34-
35-
# Installer logs
36-
pip-log.txt
37-
pip-delete-this-directory.txt
38-
39-
# Unit test / coverage reports
40-
htmlcov/
41-
.tox/
42-
.nox/
43-
.coverage
44-
.coverage.*
45-
.cache
46-
nosetests.xml
47-
coverage.xml
48-
*.cover
49-
*.py,cover
50-
.hypothesis/
51-
.pytest_cache/
52-
cover/
53-
54-
# Translations
55-
*.mo
56-
*.pot
57-
58-
# Django stuff:
1+
/tmp.*
2+
/local
593
*.log
60-
local_settings.py
61-
db.sqlite3
62-
db.sqlite3-journal
63-
64-
# Flask stuff:
65-
instance/
66-
.webassets-cache
67-
68-
# Scrapy stuff:
69-
.scrapy
70-
71-
# Sphinx documentation
72-
doc/_build/
73-
74-
# PyBuilder
75-
.pybuilder/
76-
target/
77-
78-
# Jupyter Notebook
79-
.ipynb_checkpoints
80-
81-
# IPython
82-
profile_default/
83-
ipython_config.py
84-
85-
# pyenv
86-
# For a library or package, you might want to ignore these files since the code is
87-
# intended to run in multiple environments; otherwise, check them in:
88-
# .python-version
89-
90-
# pipenv
91-
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
92-
# However, in case of collaboration, if having platform-specific dependencies or dependencies
93-
# having no cross-platform support, pipenv may install dependencies that don't work, or not
94-
# install all needed dependencies.
95-
#Pipfile.lock
96-
97-
# PEP 582; used by e.g. github.com/David-OConnor/pyflow
98-
__pypackages__/
99-
100-
# Celery stuff
101-
celerybeat-schedule
102-
celerybeat.pid
103-
104-
# SageMath parsed files
105-
*.sage.py
106-
107-
# Environments
108-
.env
109-
.venv
110-
env/
4+
*.pyc
5+
__pycache__
6+
docker-nom/build/
7+
\#*\#
8+
.\#*
1119
venv/
112-
ENV/
113-
env.bak/
114-
venv.bak/
115-
116-
# Spyder project settings
117-
.spyderproject
118-
.spyproject
119-
120-
# Rope project settings
121-
.ropeproject
122-
123-
# mkdocs documentation
124-
/site
10+
*.egg-info/
11+
docs/build/
12+
.coverage*
13+
htmlcov/
14+
.ipynb_checkpoints/
15+
.pytest_cache
16+
build/
17+
dist/
12518

126-
# mypy
127-
.mypy_cache/
128-
.dmypy.json
129-
dmypy.json
19+
# Subversion
20+
.svn
13021

131-
# Pyre type checker
132-
.pyre/
13322

134-
# pytype static type analyzer
135-
.pytype/
23+
# Vim (and some others)
24+
*~
25+
*.swp
13626

137-
# Cython debug symbols
138-
cython_debug/
27+
# Eclipse
28+
.cache
29+
.classpath
30+
.project
31+
.settings
32+
build-eclipse
33+
34+
# Gradle
35+
.gradle
36+
gradle-app.setting
37+
38+
# Sublime Text
39+
*.sublime-workspace
40+
41+
# NetBeans
42+
.netbeans
43+
catalog.xml
44+
generated
45+
nb-configuration.xml
46+
47+
# Mac OS
48+
.DS_Store
49+
__MACOSX
50+
51+
# Intellij
52+
.idea/
53+
.idea/workspace.xml
54+
.idea/libraries
55+
.idea/kotlinc.xml
56+
.idea/tasks.xml
57+
.idea/dictionaries
58+
.idea/scopes
59+
.idea/artifacts
60+
.idea/uiDesigner.xml
61+
.idea/dataSources.local.xml
62+
.idea/dataSources.local.xml
63+
.idea/dataSources.ids
64+
.idea/dataSources.xml
65+
.idea/dataSources
66+
.idea/kotlinc.xml
67+
.idea/sonar*
68+
*.iws
69+
*.iml
70+
.idea/compiler.xml
71+
.idea/kotlinc.xml
72+
.idea/inspectionProfiles/profiles_settings.xml
73+
.idea/misc.xml
74+
.idea/modules.xml
75+
76+
# vscode
77+
.vscode
78+
79+
# dask
80+
dask-worker-space/
81+
82+
# Generated data
83+
*.csv
84+
*.png
85+
86+
# Project specific
87+
simulation_log/
88+
simulation_setup/
89+
run.log
90+
resource_usage

doc/examples/ensembles/a_sim_comp.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#!/usr/bin/env python3
2+
""" Component wrapper for the ensemble example for `a_sim`. """
3+
from ipsframework import Component
4+
5+
6+
class a_sim_comp(Component):
7+
def __init__(self, services, config):
8+
super().__init__(services, config)
9+
print('Created %s' % (self.__class__))
10+
11+
def step(self, timestamp=0.0):
12+
# TODO echo parameters for this run
13+
print('Hello from a_sim_comp')
14+
15+
# Echo the parameters we're expecting, A, B, and C
16+
print(f'a_sim_comp parameters: A={self.A}, B={self.B}, C={self.C}')
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#!/usr/bin/env python3
2+
""" Component wrapper for the ensemble example for `another_sim`. """
3+
from ipsframework import Component
4+
5+
6+
class another_sim_comp(Component):
7+
def __init__(self, services, config):
8+
super().__init__(services, config)
9+
print('Created %s' % (self.__class__))
10+
11+
def step(self, timestamp=0.0):
12+
# TODO echo parameters for this run
13+
print('Hello from another_sim_comp')
14+
15+
# Echo the parameters we're expecting, D, B, and F
16+
print(f'another_sim_comp parameters: D={self.D}, B={self.B}, F={self.F}')

doc/examples/ensembles/driver.config

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# Example configuration file for ensemble support
2+
3+
SIM_ROOT = $PWD
4+
SIM_NAME = ensemble_example
5+
ENSEMBLE_DIR = /tmp/ensembles
6+
ENSEMBLE_PREFIX = MY_INSTANCE_
7+
LOG_FILE = run.log
8+
LOG_LEVEL = INFO
9+
SIMULATION_MODE = NORMAL
10+
11+
[PORTS]
12+
NAMES = DRIVER
13+
14+
[[DRIVER]]
15+
IMPLEMENTATION = driver
16+
17+
[driver]
18+
# SRC_DIR specified in platform config
19+
BIN_PATH = $SRC_DIR/IPS-framework/doc/examples/ensembles/
20+
CLASS = driver
21+
SUB_CLASS =
22+
NAME = ensemble_driver
23+
SCRIPT = ${BIN_PATH}/driver.py
24+
TEMPLATE = ${BIN_PATH}/template.config
25+
PLATFORM_CONFIG_FILE = ${BIN_PATH}/mac135909.config
26+
NPROC = 1
27+
INPUT_FILES =
28+
OUTPUT_FILES =
29+
RESTART_FILES =
30+
31+

doc/examples/ensembles/driver.py

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
#!/usr/bin/env python3
2+
"""
3+
Example driver for the ensembles example.
4+
5+
Please note that run_ensemble can be run from any IPS component, not
6+
just a driver. The driver is used here for simplicity.
7+
"""
8+
from pathlib import Path
9+
10+
from ipsframework import Component
11+
12+
13+
class ensemble_driver(Component):
14+
15+
def __init__(self, services, config):
16+
super().__init__(services, config)
17+
print('Creating driver')
18+
19+
def init(self, timeStamp=0.0):
20+
return
21+
22+
def step(self, timestamp=0.0, **keywords):
23+
""" set up and run the ensemble
24+
"""
25+
# ENSEMBLE_DIR is an arbitrary variable denoting where we want to run
26+
# all the ensembles. You don't have to use ENSEMBLE_DIR. You can
27+
# even hardcode the path here. Whatever.
28+
run_dir = Path(self.services.get_config_param('ENSEMBLE_DIR'))
29+
self.services.info(f'Running ensemble in {run_dir}')
30+
31+
# ENSEMBLE_PREFIX is an optional config variable for specifying
32+
# a string to prepend to the ensemble run directories and generated
33+
# files. If not specified, the default is 'INSTANCE_n' where n is
34+
# is the arbitrary instance ID.
35+
prefix = self.services.get_config_param('ENSEMBLE_PREFIX',
36+
silent=True)
37+
if not prefix or prefix == '' or prefix == {}:
38+
self.services.info('No ensemble instance prefix specified. Using '
39+
'default of INSTANCE_.')
40+
prefix = "INSTANCE_"
41+
else:
42+
self.services.info(f'Using ensemble instance prefix {prefix}')
43+
44+
if not run_dir.exists():
45+
self.services.info(f'Creating {run_dir}')
46+
run_dir.mkdir(parents=True)
47+
48+
template = Path(self.config['TEMPLATE'])
49+
self.services.info(f'Using template config file {template}')
50+
51+
if not template.exists():
52+
raise RuntimeError(f'{template} config template file does not exist')
53+
54+
# PLATFORM_CONFIG_FILE is a variable that points to the platform
55+
# config file used by the ensembles. This could be the same
56+
# platform config file used for this driver, but it doesn't have to be.
57+
platform_config = self.config['PLATFORM_CONFIG_FILE']
58+
self.services.info(f'Using platform config file {platform_config}')
59+
60+
# Specifies different sets of variable values for concurrent ensemble
61+
# runs for two different components, 'a_sim_comp' and
62+
# 'another_sim_comp', that correspond to two different coupled
63+
# simulations. We chose two components to demonstrate that the same
64+
# variable, in this case 'B', can have different values for different
65+
# components. 'a_sim_comp' and 'another_sim_comp' are the names of
66+
# the config sections in the template file so we know where to look
67+
# for variable substitutions.
68+
variables = {'a_sim_comp': {'A': [3, 2, 4],
69+
'B': [2.34, 5.82, 0.1],
70+
'C': ['bar', 'baz', 'quux']},
71+
'another_sim_comp': {'D': [7, 5, 9],
72+
'B': [0.775, 0.080, 29.2],
73+
'F': ['xyzzy', 'plud', 'thud']}}
74+
75+
# Spins up N tasks, in this case three, each with a different set of
76+
# variable values. `mapping` is a data struct that associates the
77+
# specific simulation to a given run directory so that the user can
78+
# easily find output for a specific run.
79+
mapping = self.services.run_ensemble(template,
80+
variables,
81+
run_dir,
82+
platform_config,
83+
prefix)
84+
85+
self.services.info(f'Mapping of dirs to parameters: {mapping!s}')
86+
87+
88+
def finalize(self, timeStamp=0.0):
89+
return
90+

0 commit comments

Comments
 (0)