diff --git a/.gitignore b/.gitignore
index dc0373c6..8ee8084c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -29,6 +29,7 @@ eggs/
.eggs/
lib/
lib64/
+.vscode/
parts/
sdist/
var/
@@ -71,6 +72,7 @@ docs/_build/
_build/*
_build
+
# PyBuilder
target/
diff --git a/CITATION.cff b/CITATION.cff
index e34df189..c4fa576e 100644
--- a/CITATION.cff
+++ b/CITATION.cff
@@ -2,8 +2,8 @@ cff-version: 1.2.0
message: If you use this software, please cite it using the metadata from this file.
type: software
title: 'pycopancore: Reference implementation of the copan:CORE World-Earth modelling framework'
-version: 0.7.0
-date-released: '2024-07-04'
+version: 0.8.0
+date-released: '2025-01-28'
abstract: The pycopancore package is a python implementation of the copan:CORE
modeling framework as described in this paper. The framework is designed to
allow an easy implementation of World-Earth (i.e., global social-ecological)
@@ -14,6 +14,18 @@ abstract: The pycopancore package is a python implementation of the copan:CORE
stochastic and deterministic events and therefore allows to compare different
model and component types and implementations.
authors:
+- family-names: Breier
+ given-names: Jannes
+ email: jannesbr@pik-potsdam.de
+ orcid: 0000-0002-9055-6904
+- family-names: Schwarz
+ given-names: Luana
+ email: lschwarz@pik-potsdam.de
+ orcid: 0000-0003-1726-1509
+- family-names: Hotz
+ given-names: Ronja
+ email: ronja.hotz@kit.edu
+ orcid: 0000-0003-3425-268X
- family-names: Bechthold
given-names: Max
email: maxbecht@pik-potsdam.de
diff --git a/docs/Makefile b/docs/Makefile
index c8653f9b..3c94a46a 100644
--- a/docs/Makefile
+++ b/docs/Makefile
@@ -6,6 +6,7 @@ SPHINXOPTS = -E -a
SPHINXBUILD = sphinx-build
PYREVERSE = pyreverse
APIDOC = sphinx-apidoc
+APIDOCOPTS = -l -d 2 -e -P -M -f -o ./docs/_api
SPHINX_APIDOC_OPTIONS=members,undoc-members,private-members,special-members,inherited-members,show-inheritance
DOT = dot
PAPER =
@@ -61,7 +62,7 @@ clean:
.PHONY: html
html:
@echo "Creating auto-generated documentation from source"
- cd ..; $(APIDOC) --implicit-namespaces -f -o ./docs/_api ./pycopancore/ ./pycopancore/model_components/base/__init__.py ./pycopancore/model_components/seven_dwarfs/__init__.py
+ cd ..; $(APIDOC) $(APIDOCOPTS) --implicit-namespaces ./pycopancore/ #./pycopancore/model_components/base/__init__.py ./pycopancore/model_components/seven_dwarfs/__init__.py
@echo
@echo "Sphinx-apidoc is done, building directories"
$(SPHINXBUILD) -b html -v $(ALLSPHINXOPTS) $(BUILDDIR)/html
@@ -71,7 +72,7 @@ html:
.PHONY: api
api:
@echo
- cd ..; $(APIDOC) -f -o ./docs/_api ./pycopancore/
+ cd ..; $(APIDOC) $(APIDOCOPTS) ./docs/_api ./pycopancore/
.PHONY : uml
uml:
diff --git a/docs/conf.py b/docs/conf.py
index d80fad29..8b65a5c4 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -44,7 +44,7 @@
# Napoleon settings
napoleon_numpy_docstring = True
-napoleon_google_docstring = False
+napoleon_google_docstring = True
napoleon_include_special_with_doc = True
# more info at http://www.sphinx-doc.org/en/stable/ext/
# napoleon.html#module-sphinx.ext.napoleon
@@ -54,14 +54,15 @@
# The suffix(es) of source filenames.
# You can specify multiple suffix as a list of string:
-# source_suffix = ['.rst', '.md']
-source_suffix = '.rst'
+source_suffix = ['.rst', '.md']
+#source_suffix = '.rst'
# The encoding of source files.
#source_encoding = 'utf-8-sig'
# The master toctree document.
master_doc = 'index'
+root_doc = 'index'
# General information about the project.
project = u'pycopancore'
@@ -100,15 +101,15 @@
#default_role = None
# If true, '()' will be appended to :func: etc. cross-reference text.
-#add_function_parentheses = True
+add_function_parentheses = True
# If true, the current module name will be prepended to all description
# unit titles (such as .. function::).
-#add_module_names = True
+add_module_names = False
# If true, sectionauthor and moduleauthor directives will be shown in the
# output. They are ignored by default.
-#show_authors = False
+show_authors = True
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx'
@@ -185,19 +186,19 @@
html_domain_indices = True
# If false, no index is generated.
-#html_use_index = True
+html_use_index = True
# If true, the index is split into individual pages for each letter.
-#html_split_index = False
+html_split_index = True
# If true, links to the reST sources are added to the pages.
-#html_show_sourcelink = True
+html_show_sourcelink = True
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
-#html_show_sphinx = True
+html_show_sphinx = True
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
-#html_show_copyright = True
+html_show_copyright = True
# If true, an OpenSearch description file will be output, and all pages will
# contain a tag referring to it. The value of this option must be the
diff --git a/docs/index.rst b/docs/index.rst
index 097325af..60ae29a1 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -18,7 +18,7 @@ Contents:
.. TODO: move introduction to inside this page so that it is more immediately available for reading?
.. toctree::
- :maxdepth: 1
+ :maxdepth: 3
:titlesonly:
introduction
diff --git a/examples/__init__.py b/examples/__init__.py
deleted file mode 100644
index 46890d1d..00000000
--- a/examples/__init__.py
+++ /dev/null
@@ -1,8 +0,0 @@
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
diff --git a/pycopancore/__init__.py b/pycopancore/__init__.py
index 3aba1e22..e2672f34 100644
--- a/pycopancore/__init__.py
+++ b/pycopancore/__init__.py
@@ -9,14 +9,4 @@
#
# URL:
# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-from .data_model import *
-from .process_types import *
-from .runners import *
-from .util import *
-
-from .model_components import base
-
-__url__ = "http://www.pik-potsdam.de/copan/software"
-__version__ = "0.1.0"
+# License: BSD 2-clause license
\ No newline at end of file
diff --git a/pycopancore/data_model/__init__.py b/pycopancore/data_model/__init__.py
index d640954e..cfbe98f7 100644
--- a/pycopancore/data_model/__init__.py
+++ b/pycopancore/data_model/__init__.py
@@ -1,3 +1,73 @@
+"""
+==========
+Data model
+==========
+
+**************************
+Variable naming convention
+**************************
+
+We suggest to use rather descriptive variable names that make the relevant
+dimension clear in the following fashion:
+
+* Variables that represent integer cardinalities should be called **numbers**
+ (possibly abbreviated as `n`, `no`, or `num`) or **counts**.
+
+* Extensive variables of simple physical dimension should be called **stocks**,
+ e.g. `atmospheric_carbon_stock` of dimension `carbon` and default unit `GtC`,
+ or `physical_capital_stock` of dimension `monetary_value` and default unit `dollars`.
+
+* Intensive variables of simple physical dimension should *not* be called 'stocks'
+ to distinguish them from extensive variables. E.g. `surface_air_temperature`
+ of dimension `temperature` and default unit `kelvins`.
+
+* Variables that represent a stock per surface area, volume, or mass should be
+ called **densities**, e.g., `vegetation_carbon_density` in `GtC/m2` or
+ `energy_density_of_wood` in `MJ/kg`.
+
+* Variables that represent (changes of) stocks per time or time derivatives of stocks
+ should be called **flows**, e.g. `photosynthesis_carbon_flow` of dimension
+ `carbon/time` and default unit `GtC/yr`, or `income_flow` of dimension `money/time`
+ and default unit `dollars/yr`.
+
+* Variables that represent flows per surface area should be called **fluxes**,
+ e.g. `sensible_heat_flux` of dimension `energy/time/area` and default unit
+ `W/m^2`.
+
+* Variables of dimension `time` that represent specific unique time points
+ should be called **time_points** or **dates**, e.g., `net_zero_date`.
+
+* Variables of dimension `time` that represent amounts of time *between*
+ time points should be called **delays**, **intervals**, **durations**,
+ **periods**, **ages**, etc., or sometimes just **times**.
+ e.g. `business_cycle_period` or `Individual.age`.
+
+* Variables of dimension `1/time` referring to periodic occurrences should be
+ called **frequencies**, i.e., `voting_frequency`.
+
+* Other variables of dimension `1/time` should be called **rates**, e.g.
+ `equilibration_rate`, `discount_rate`, `depreciation_rate`, `diffusion_rate`.
+ Variables of other dimension than `1/time`, in particular fractions or ratios,
+ should *not* be called 'rates'.
+
+* Dimensionless variables between 0 and 1 that represent parts of a whole
+ should be called **fractions** or **shares**, e.g. `dirty_fraction` or
+ `fossil_energy_share`.
+
+* Dimensionless variables that represent the relative size of one quantity as
+ compared to another quantity of the same dimension should be called **ratios**,
+ e.g., `cost_benefit_ratio`.
+
+* Variables representing the derivative of one quantity w.r.t. another quantity
+ (other than time) should be called **sensitivities**, e.g.
+ `temperature_sensitivity_of_photosynthesis`.
+
+* Variables representing the derivative of the *logarithm* of one quantity w.r.t.
+ the logarithm of another quantity should be called **elasticities**, e.g.
+ `labor_elasticity_of_fossil_energy_production`.
+"""
+
+
# This file is part of pycopancore.
#
# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
diff --git a/pycopancore/data_model/dimensional_quantity.py b/pycopancore/data_model/dimensional_quantity.py
index 90ccd2d3..017e3942 100644
--- a/pycopancore/data_model/dimensional_quantity.py
+++ b/pycopancore/data_model/dimensional_quantity.py
@@ -9,8 +9,8 @@
# Contact: core@pik-potsdam.de
# License: BSD 2-clause license
-from . import dimension
-from . import unit as U
+from pycopancore.data_model import dimension
+from pycopancore.data_model import unit as U
class DimensionalQuantity(object):
diff --git a/pycopancore/data_model/master_data_model/__init__.py b/pycopancore/data_model/master_data_model/__init__.py
index f962b122..cb94d9d2 100644
--- a/pycopancore/data_model/master_data_model/__init__.py
+++ b/pycopancore/data_model/master_data_model/__init__.py
@@ -41,4 +41,3 @@
from .group import Group as group
from .group import Group
-from .. import unity
diff --git a/pycopancore/data_model/master_data_model/cell.py b/pycopancore/data_model/master_data_model/cell.py
index ce5ddd66..c0779546 100644
--- a/pycopancore/data_model/master_data_model/cell.py
+++ b/pycopancore/data_model/master_data_model/cell.py
@@ -9,8 +9,12 @@
# Contact: core@pik-potsdam.de
# License: BSD 2-clause license
-from . import ENV, MET
-from . import square_kilometers
+from pycopancore.data_model.master_data_model.environment \
+ import Environment as ENV
+from pycopancore.data_model.master_data_model.metabolism \
+ import Metabolism as MET
+from pycopancore.data_model.master_data_model.dimensions_and_units \
+ import DimensionsAndUnits as DAU
class Cell:
@@ -18,7 +22,7 @@ class Cell:
# natural:
land_area = ENV.land_area.copy()
- land_area.default = 1 * square_kilometers
+ land_area.default = 1 * DAU.km2
atmospheric_carbon = ENV.atmospheric_carbon.copy()
surface_air_temperature = ENV.surface_air_temperature.copy()
ocean_carbon = ENV.ocean_carbon.copy()
diff --git a/pycopancore/data_model/master_data_model/culture.py b/pycopancore/data_model/master_data_model/culture.py
index d89d2c82..2917e680 100644
--- a/pycopancore/data_model/master_data_model/culture.py
+++ b/pycopancore/data_model/master_data_model/culture.py
@@ -9,11 +9,10 @@
# Contact: core@pik-potsdam.de
# License: BSD 2-clause license
-from .. import Variable
-
from networkx import DiGraph, Graph
-from .. import unity
+from pycopancore.data_model.variable import Variable
+from pycopancore.data_model.unit import unity
class Culture:
diff --git a/pycopancore/data_model/master_data_model/dimensions_and_units.py b/pycopancore/data_model/master_data_model/dimensions_and_units.py
index c5072bb9..11575438 100644
--- a/pycopancore/data_model/master_data_model/dimensions_and_units.py
+++ b/pycopancore/data_model/master_data_model/dimensions_and_units.py
@@ -9,8 +9,8 @@
# Contact: core@pik-potsdam.de
# License: BSD 2-clause license
-from .. import Dimension
-from .. import Unit, unity
+from pycopancore.data_model.dimension import Dimension
+from pycopancore.data_model.unit import Unit, unity
class DimensionsAndUnits:
@@ -24,14 +24,15 @@ class DimensionsAndUnits:
decimeters = (meters / 10).named("decimeters", symbol="dm")
time = Dimension("time", "time")
- time.default_unit = a = yr = years = Unit("years", "years", symbol="a")
+ time.default_unit = a = yr = years = Unit("years", "years", symbol="yr")
s = seconds = (years / 31556952).named("seconds", symbol="s")
minutes = (seconds * 60).named("minutes", symbol="min")
h = hours = (minutes * 60).named("hours", symbol="h")
days = (hours * 24).named("days", symbol="d")
+ doy = (hours * 24).named("day of the year", symbol="doy")
weeks = (days * 7).named("weeks")
months = (years / 12).named("months")
-
+
mass = Dimension("mass",
"mass (only use for matter changing its type, otherwise use specific mass dimension, e.g. 'carbon')")
mass.default_unit = t = tonnes = \
@@ -40,7 +41,8 @@ class DimensionsAndUnits:
symbol="t")
Gt = gigatonnes = (tonnes * 1e9).named("gigatonnes", symbol="Gt")
kg = kilograms = (tonnes * 1e-3).named("kilograms", symbol="kg")
-
+ g = grams = (tonnes * 1e-6).named("grams", symbol="g")
+
absolute_temperature = Dimension("absolute temperature",
"absolute temperature")
absolute_temperature.default_unit = K = kelvins = \
@@ -49,10 +51,9 @@ class DimensionsAndUnits:
# other base dimensions and units:
- # TODO: maybe rename to monetary monetary_value:
- monetary_value = \
- Dimension("monetary_value",
- "inflation-adjusted monetary monetary_value of goods, services etc.")
+ money = monetary_value = \
+ Dimension("money or monetary value",
+ "inflation-adjusted money or monetary value of goods, services etc.")
monetary_value.default_unit = dollars = US_dollars_2005 = \
Unit("dollars",
"inflation-adjusted 2005 US dollars", symbol="$")
@@ -71,7 +72,10 @@ class DimensionsAndUnits:
symbol="tC")
GtC = gigatonnes_carbon = (tonnes_carbon * 1e9).named("gigatonnes carbon",
symbol="GtC")
-
+ kgC = kilograms_carbon = (tonnes_carbon * 1e-3).named("kilograms carbon",
+ symbol="kgC")
+ gC = grams_carbon = (tonnes_carbon * 1e-6).named("grams carbon",
+ symbol="gC")
humans = Dimension("humans", "cardinality of a set of human beings")
humans.default_unit = H = people = persons = \
Unit("people", "number of human beings", symbol="H")
@@ -80,7 +84,7 @@ class DimensionsAndUnits:
#energy = (mass * velocity**2).named("energy")
#joules = kilograms * meters**2 / seconds**2
# but:
- energy = Dimension("energy", "(not convertible to mass velocity²)")
+ heat = energy = Dimension("energy", "(not convertible to mass velocity²)")
J = joules = Unit("joules", "(not convertible to kg m²/s²)",
symbol="J", dimension=energy)
energy.default_unit = GJ = gigajoules = \
@@ -94,28 +98,37 @@ class DimensionsAndUnits:
).named("gigacalories (thermochemical)",
symbol="Gcalth")
- # derived flow dimensions:
+ # derived flow dimensions and units:
value_flow = (monetary_value / time).named("monetary_value flow")
carbon_flow = (carbon / time).named("carbon flow")
human_flow = (humans / time).named("human flow")
-
+
GW = gigawatts = (GWh / h).named("gigawatts", symbol="GW")
-
+
# other derived dimensions and units:
-
+
percent = pct = (unity / 100).named("per cent", symbol="%")
-
+
area = (length**2).named("area", "2D spatial dimension")
- square_kilometers = (kilometers**2).named("square kilometers", symbol="km²")
- hectares = (meters**2 * 1e4).named("hectares", symbol="ha")
-
+ km2 = square_kilometers = (kilometers**2).named("square kilometers",
+ symbol="km²")
+ ha = hectares = (meters**2 * 1e4).named("hectares", symbol="ha")
+ m2 = square_meters = (meters**2).named("square meters", symbol="m²")
+
volume = (length**3).named("volume", "3D spatial dimension")
- litres = (decimeters**3).named("litres", symbol="l")
-
+ litres = (decimeters**3).named("litres", symbol="l")
+
velocity = (length / time).named("velocity")
-
acceleration = (velocity / time).named("acceleration")
+ tC_per_ha = (t/ha).named("tonnes carbon per hectare",
+ symbol="tC/ha")
+ kgC_per_m2 = (kgC/m2).named("kilograms carbon per square meter",
+ symbol="kgC/m²")
+ gC_per_m2 = (gC/m2).named("grams carbon per square meter",
+ symbol="gC/m²")
+
person_hours = (people * hours).named("person hours")
person_months = (people * months).named("person months")
+
diff --git a/pycopancore/data_model/master_data_model/environment.py b/pycopancore/data_model/master_data_model/environment.py
index eb33a8cc..9bae2ccb 100644
--- a/pycopancore/data_model/master_data_model/environment.py
+++ b/pycopancore/data_model/master_data_model/environment.py
@@ -2,25 +2,28 @@
"""Master data model for environment."""
-from .. import Variable
-from . import gigatonnes_carbon, kelvins, years, square_kilometers
-from .. import unity
+from pycopancore.data_model.variable import Variable
+from pycopancore.data_model.master_data_model.dimensions_and_units import \
+ DimensionsAndUnits as DAU
+from pycopancore.data_model.unit import unity
-from networkx import DiGraph, Graph
+from networkx import Graph
class Environment:
# Geography:
- land_area = Variable("land area", "", unit=square_kilometers,
+ land_area = Variable("land area",
+ "",
+ unit=DAU.square_kilometers,
strict_lower_bound=0)
# Atmosphere:
atmospheric_carbon = Variable("atmospheric carbon stock",
"(mass of C in any chemical compound)",
- unit=gigatonnes_carbon,
+ unit=DAU.gigatonnes_carbon,
is_extensive=True, lower_bound=0, default=0)
# Note: this is NOT the same as the CF var. atmosphere_mass_of_carbon_dioxide
@@ -29,7 +32,7 @@ class Environment:
"""(in the meaning used in climate policy debates,
i.e., at 2m above surface, averaged over the day)""",
AMIP="tas", # CF="air_temperature"?
- unit=kelvins,
+ unit=DAU.kelvins,
is_intensive=True, lower_bound=0, default=287)
# TODO: higher layers as a vector by (geopotential) hight?
@@ -38,7 +41,7 @@ class Environment:
ocean_carbon = Variable("ocean carbon stock",
"(mass of C in any chemical compound)",
- unit=gigatonnes_carbon,
+ unit=DAU.gigatonnes_carbon,
is_extensive=True, lower_bound=0, default=0)
# Note: when using the following, include
@@ -46,12 +49,12 @@ class Environment:
upper_ocean_carbon = \
Variable("upper ocean carbon stock",
"(that which interacts relatively much/fast with atmosphere)",
- unit=gigatonnes_carbon,
+ unit=DAU.gigatonnes_carbon,
is_extensive=True, lower_bound=0, default=0)
deep_ocean_carbon = \
Variable("deep ocean carbon stock",
"(that which interacts relatively little/slow with atmosphere)",
- unit=gigatonnes_carbon,
+ unit=DAU.gigatonnes_carbon,
is_extensive=True, lower_bound=0, default=0)
# Note: there are no corresponding CF vars. yet
@@ -61,19 +64,19 @@ class Environment:
terrestrial_carbon = Variable("terrestrial carbon stock",
"(mass of C in any chemical compound)",
- unit=gigatonnes_carbon,
+ unit=DAU.gigatonnes_carbon,
is_extensive=True, lower_bound=0, default=0)
# Note: when using the following, include
# Implicit(terrestrial_carbon == soil_carbon + biomass_carbon)
soil_carbon = Variable("soil carbon stock",
"(mass of C in any chemical compound)",
- unit=gigatonnes_carbon,
+ unit=DAU.gigatonnes_carbon,
is_extensive=True, lower_bound=0, default=0)
# Note: has to do with CF var. soil_carbon_content
biomass_carbon = Variable("biomass/plant carbon stock",
"(mass of C in any chemical compound)",
- unit=gigatonnes_carbon,
+ unit=DAU.gigatonnes_carbon,
is_extensive=True, lower_bound=0, default=0)
# Note: when using the following, include
@@ -82,12 +85,12 @@ class Environment:
Variable("harvestable biomass carbon stock",
"""(that which can be accessed easily for direct harvesting,
in particular agricultural biomass)""",
- unit=gigatonnes_carbon,
+ unit=DAU.gigatonnes_carbon,
is_extensive=True, lower_bound=0, default=0)
other_biomass_carbon = \
Variable("other (non-harvestable) biomass carbon stock",
"(that which cannot be accessed easily for direct harvesting)",
- unit=gigatonnes_carbon,
+ unit=DAU.gigatonnes_carbon,
is_extensive=True, lower_bound=0, default=0)
# Note: there are no corresponding CF vars. yet
@@ -99,7 +102,7 @@ class Environment:
"""(mass of C in any chemical compound,
potentially accessible for human extraction
and combustion)""",
- unit=gigatonnes_carbon,
+ unit=DAU.gigatonnes_carbon,
is_extensive=True, lower_bound=0, default=0)
# Note: when using the following, include
@@ -107,19 +110,21 @@ class Environment:
discovered_fossil_reserves = \
Variable("discovered fossil reserves carbon stock",
"""(that which can currently be accessed for extraction)""",
- unit=gigatonnes_carbon,
+ unit=DAU.gigatonnes_carbon,
is_extensive=True, lower_bound=0, default=0)
undiscovered_fossil_reserves = \
Variable("undiscovered fossil reserves carbon stock",
"(that which cannot currently be accessed for extraction)",
- unit=gigatonnes_carbon,
+ unit=DAU.gigatonnes_carbon,
is_extensive=True, lower_bound=0, default=0)
# For ocean-atmosphere interactions:
ocean_atmosphere_diffusion_coefficient = \
Variable("ocean-atmosphere diffusion coefficient", "",
- unit=years**-1, lower_bound=0, default=0.016)
+ unit=DAU.years**-1,
+ lower_bound=0,
+ default=0.016)
carbon_solubility_in_sea_water = \
Variable("carbon solubility in sea water",
"(in the sense of Nitzbon et al. 2017, not in g/L but unitless!)",
@@ -130,11 +135,11 @@ class Environment:
photosynthesis_carbon_flow = \
Variable("photosynthesis carbon flow", "",
ref="https://en.wikipedia.org/wiki/Photosynthesis",
- unit = gigatonnes_carbon / years,
+ unit = DAU.gigatonnes_carbon / DAU.years,
is_extensive=True, lower_bound=0, default=0)
terrestrial_respiration_carbon_flow = \
Variable("plant and soil respiration carbon flow", "",
- unit = gigatonnes_carbon / years,
+ unit = DAU.gigatonnes_carbon / DAU.years,
is_extensive=True, lower_bound=0, default=0)
# Note: when using the following, include
@@ -143,12 +148,12 @@ class Environment:
plant_respiration_carbon_flow = \
Variable("plant respiration carbon flow", "",
ref="https://en.wikipedia.org/wiki/Cellular_respiration",
- unit = gigatonnes_carbon / years,
+ unit = DAU.gigatonnes_carbon / DAU.years,
is_extensive=True, lower_bound=0, default=0)
soil_respiration_carbon_flow = \
Variable("soil respiration carbon flow", "",
ref="https://en.wikipedia.org/wiki/Soil_respiration",
- unit = gigatonnes_carbon / years,
+ unit = DAU.gigatonnes_carbon / DAU.years,
is_extensive=True, lower_bound=0, default=0)
# Note: there are no corresponding CF vars. yet
diff --git a/pycopancore/data_model/master_data_model/group.py b/pycopancore/data_model/master_data_model/group.py
index a114e4d9..1d8504da 100644
--- a/pycopancore/data_model/master_data_model/group.py
+++ b/pycopancore/data_model/master_data_model/group.py
@@ -1,6 +1,6 @@
"""Master data model for group."""
-from .. import Variable
+from pycopancore.data_model.variable import Variable
from networkx import Graph
diff --git a/pycopancore/data_model/master_data_model/metabolism.py b/pycopancore/data_model/master_data_model/metabolism.py
index a13ca902..2f30812c 100644
--- a/pycopancore/data_model/master_data_model/metabolism.py
+++ b/pycopancore/data_model/master_data_model/metabolism.py
@@ -9,9 +9,10 @@
# Contact: core@pik-potsdam.de
# License: BSD 2-clause license
-from .. import Variable
-from . import gigajoules, dollars, gigatonnes_carbon, years, utils, people, kelvins
-from .. import unity
+from pycopancore.data_model.variable import Variable
+from pycopancore.data_model.master_data_model.dimensions_and_units import \
+ DimensionsAndUnits as DAU
+from pycopancore.data_model.unit import unity
class Metabolism:
@@ -21,7 +22,7 @@ class Metabolism:
population = Variable("human population", "",
IAMC="Population",
CETS="SP.POP",
- unit=people,
+ unit=DAU.people,
is_extensive=True, lower_bound=0, default=0)
# Note: when using the following, include
@@ -30,70 +31,70 @@ class Metabolism:
"(in years from 0 to 99+)",
IAMC="Population",
CETS="SP.POP",
- unit=people,
+ unit=DAU.people,
is_extensive=True, lower_bound=0,
array_shape=(100,)) # 1d-array
migrant_population = Variable("first-generation migrant population", "",
- unit=people,
+ unit=DAU.people,
is_extensive=True, lower_bound=0, default=0)
fertility = Variable("current human fertility rate", "",
- unit=years**-1,
+ unit=DAU.years**-1,
lower_bound=0, is_intensive=True,
default=0.02)
min_fertility = Variable("minimum human fertility rate", "",
- unit=years**-1,
+ unit=DAU.years**-1,
lower_bound=0, is_intensive=True,
default=0.008)
max_fertility = Variable("maximum human fertility rate", "",
- unit=years**-1,
+ unit=DAU.years**-1,
lower_bound=0, is_intensive=True,
default=0.05)
mortality = Variable("current human mortility rate", "",
- unit=years**-1,
+ unit=DAU.years**-1,
lower_bound=0, is_intensive=True,
default=0.01)
mortality_temperature_sensitivity = \
Variable("mortality temperature sensitivity", "",
- unit = years**-1 / kelvins,
+ unit=DAU.years**-1 / DAU.kelvins,
lower_bound=0, is_intensive=True,
- default = 5e-5/years / kelvins
+ default=5e-5/DAU.years / DAU.kelvins
)
mortality_reference_temperature = \
Variable("reference temperature for relationship with mortality",
"default: pre-industrial value",
- unit=kelvins, lower_bound=0,
+ unit=DAU.kelvins, lower_bound=0,
default=287) # TODO: verify!
births = Variable("births per time", "",
- unit = people / years,
+ unit=DAU.people / DAU.years,
lower_bound=0, is_extensive=True, default=0)
deaths = Variable("deaths per time", "",
- unit = people / years,
+ unit=DAU.people / DAU.years,
lower_bound=0, is_extensive=True, default=0)
-
+
immigration = Variable("immigrants per time", "",
- unit = people / years,
+ unit=DAU.people / DAU.years,
lower_bound=0, is_extensive=True, default=0)
emigration = Variable("emigrants per time", "",
- unit = people / years,
+ unit=DAU.people / DAU.years,
lower_bound=0, is_extensive=True, default=0)
-
-
+
+
# Resource extraction and waste:
-
+
biomass_harvest_flow = Variable("biomass harvest flow", "",
- unit = gigatonnes_carbon / years, # leave whitespace as it is, for g*ds sake!!!!
+ unit=DAU.gigatonnes_carbon / DAU.years, # leave whitespace as it is, for g*ds sake!!!!
lower_bound=0, is_extensive=True, default=0)
-
+
fossil_extraction_flow = Variable("fossil extraction flow", "",
- unit = gigatonnes_carbon / years,
+ unit=DAU.gigatonnes_carbon / DAU.years,
lower_bound=0, is_extensive=True, default=0)
carbon_emission_flow = Variable("carbon emission flow", "",
- unit = gigatonnes_carbon / years,
+ unit=DAU.gigatonnes_carbon / DAU.years,
IAMC="Emissions|CO2",
lower_bound=0, is_extensive=True, default=0)
@@ -107,14 +108,14 @@ class Metabolism:
# stocks:
physical_capital = \
- Variable("physical capital", "(in value units)", unit=dollars,
+ Variable("physical capital", "(in value units)", unit=DAU.dollars,
lower_bound=0, is_extensive=True, default=0)
renewable_energy_knowledge = \
Variable("renewable energy production knowledge stock",
"= non-depreciated cumulative energy produced in the past. "
"Interpreted as in Wright's law",
- unit=gigajoules,
+ unit=DAU.gigajoules,
lower_bound=0, is_extensive=True, default=0)
# flows:
@@ -124,52 +125,52 @@ class Metabolism:
Variable("biomass input flow",
"(in carbon units)",
IAMC="Primary Energy|Biomass",
- unit = gigatonnes_carbon / years,
+ unit=DAU.gigatonnes_carbon / DAU.years,
lower_bound=0, is_extensive=True, default=0)
fossil_fuel_input_flow = \
Variable("fossil fuels input flow",
"(in carbon units)",
IAMC="Primary Energy|Fossil",
- unit = gigatonnes_carbon / years,
+ unit=DAU.gigatonnes_carbon / DAU.years,
lower_bound=0, is_extensive=True, default=0)
renewable_energy_input_flow = \
Variable("non-biomass renewable energy input flow",
"",
IAMC="Primary Energy|Non-Biomass Renewables",
- unit = gigajoules / years,
+ unit=DAU.gigajoules / DAU.years,
lower_bound=0, is_extensive=True, default=0)
secondary_energy_flow = \
Variable("secondary energy flow",
"(all sources)",
IAMC="Secondary Energy",
- unit = gigajoules / years,
+ unit=DAU.gigajoules / DAU.years,
lower_bound=0, is_extensive=True, default=0)
total_energy_intensity = \
Variable("total energy intensity", "",
- unit = gigajoules / dollars,
- lower_bound=0, is_intensive=True, default = 1/147)
+ unit=DAU.gigajoules / DAU.dollars,
+ lower_bound=0, is_intensive=True, default=1/147)
economic_output_flow = \
Variable("total economic output flow",
"(in value units)",
IAMC="GDP|PPP", # or GDP|MER?
- unit = dollars / years,
+ unit=DAU.dollars / DAU.years,
lower_bound=0, is_extensive=True, default=0)
consumption_flow = \
Variable("consumption flow", """(in value units)""",
IAMC="Consumption",
- unit = dollars / years,
+ unit=DAU.dollars / DAU.years,
lower_bound=0, is_extensive=True, default=0)
investment_flow = \
Variable("flow of total investment into physical capital", "",
# IAMC="Investment",
- unit = dollars / years,
+ unit=DAU.dollars / DAU.years,
lower_bound=0, is_extensive=True, default=0)
# per-capita quantities:
@@ -178,25 +179,25 @@ class Metabolism:
Variable("cardinal social welfare flow 'per capita'",
"Note that 'per capita' here does not imply that the value is "
"an average, but only that it is an intensive quantity",
- unit = utils / people / years,
+ unit=DAU.utils / DAU.people / DAU.years,
is_intensive=True, default=0)
wellbeing = \
Variable("well-being", "(in utility flow units)",
- unit = utils / people / years,
+ unit=DAU.utils / DAU.people / DAU.years,
is_intensive=True, default=0)
# productivities, efficiencies etc.
- biomass_energy_density = Variable("biomass energy density",
+ biomass_energy_density = Variable("biomass energy density",
"(default from Nitzbon 2016)",
- unit = gigajoules / gigatonnes_carbon,
+ unit=DAU.gigajoules / DAU.gigatonnes_carbon,
lower_bound=0, is_intensive=True,
default=40e9)
- fossil_energy_density = Variable("fossil energy density",
+ fossil_energy_density = Variable("fossil energy density",
"(default from Nitzbon 2016)",
- unit = gigajoules / gigatonnes_carbon,
+ unit=DAU.gigajoules / DAU.gigatonnes_carbon,
lower_bound=0, is_intensive=True,
default=47e9)
@@ -207,13 +208,13 @@ class Metabolism:
Variable("protected stock of terrestrial carbon",
"""what stock of the current terrestrial carbon will be treated
as protected and thus not harvested at each point in time""",
- unit=gigatonnes_carbon, lower_bound=0,
+ unit=DAU.gigatonnes_carbon, lower_bound=0,
default=0) # may be increased by cultural components
protected_fossil_carbon = \
Variable("protected stock of fossil carbon",
"""what stock of the current fossil carbon will be treated
as protected and thus not extracted at each point in time""",
- unit=gigatonnes_carbon, lower_bound=0,
+ unit=DAU.gigatonnes_carbon, lower_bound=0,
default=0) # may be increased by cultural components
protected_terrestrial_carbon_share = \
Variable("protected share of terrestrial carbon",
@@ -233,19 +234,19 @@ class Metabolism:
physical_capital_depreciation_rate = \
Variable("physical capital depreciation rate", "",
- unit = years**-1,
+ unit=DAU.years**-1,
lower_bound=0, is_intensive=True,
default=0.1)
basic_physical_capital_depreciation_rate = \
Variable("basic physical capital depreciation rate", "",
- unit = years**-1,
+ unit=DAU.years**-1,
lower_bound=0, is_intensive=True,
default=0.1)
physical_capital_depreciation_rate_temperature_sensitivity = \
Variable("physical capital depreciation rate temperature sensitivity", "",
- unit = years**-1 / kelvins,
+ unit=DAU.years**-1 / DAU.kelvins,
lower_bound=0, is_intensive=True,
- default = 0.05/years / kelvins
+ default=0.05/DAU.years / DAU.kelvins
# the following gives much too large sensitivity:
# (40e9 * dollars / years) / (6e13 * dollars)
# / ((1.5*kelvins) / (1000*gigatonnes_carbon))
@@ -253,12 +254,12 @@ class Metabolism:
physical_capital_depreciation_rate_reference_temperature = \
Variable("reference temperature for relationship with capital depreciation",
"default: pre-industrial value",
- unit=kelvins, lower_bound=0,
+ unit=DAU.kelvins, lower_bound=0,
default=287) # TODO: verify!
renewable_energy_knowledge_depreciation_rate = \
Variable("renewable energy production knowledge depreciation rate", "",
- unit = years**-1,
+ unit=DAU.years**-1,
lower_bound=0, is_intensive=True,
default=0.02)
diff --git a/pycopancore/data_model/master_data_model/social_system.py b/pycopancore/data_model/master_data_model/social_system.py
index fe638196..24c82292 100644
--- a/pycopancore/data_model/master_data_model/social_system.py
+++ b/pycopancore/data_model/master_data_model/social_system.py
@@ -1,8 +1,10 @@
"""Master data model for social_system."""
-from . import MET
-from .. import Variable
-from . import dollars, gigatonnes_carbon, gigajoules
+from pycopancore.data_model.master_data_model.metabolism \
+ import Metabolism as MET
+from pycopancore.data_model.variable import Variable
+from pycopancore.data_model.master_data_model.dimensions_and_units import \
+ DimensionsAndUnits as DAU
class SocialSystem:
@@ -84,10 +86,10 @@ class SocialSystem:
emissions_tax_level = \
Variable("emissions tax level",
"level of emissions tax when introduced",
- unit = dollars / gigatonnes_carbon,
+ unit=DAU.dollars / DAU.gigatonnes_carbon,
lower_bound=0, default=100e9*3.5)
renewable_subsidy_level = \
Variable("renewable subsidy level",
"level of renewable subsidy when introduced",
- unit = dollars / gigajoules,
- lower_bound=0, default=50) # FIXME: check plausibility!
+ unit=DAU.dollars / DAU.gigajoules,
+ lower_bound=0, default=50) # FIXME: check plausibility!
diff --git a/pycopancore/data_model/master_data_model/world.py b/pycopancore/data_model/master_data_model/world.py
index 9fe60a2b..d2904e53 100644
--- a/pycopancore/data_model/master_data_model/world.py
+++ b/pycopancore/data_model/master_data_model/world.py
@@ -9,27 +9,31 @@
# Contact: core@pik-potsdam.de
# License: BSD 2-clause license
-from . import ENV, MET
-from . import gigatonnes_carbon as GtC
-from . import square_kilometers as km2
+from pycopancore.data_model.master_data_model.environment \
+ import Environment as ENV
+from pycopancore.data_model.master_data_model.metabolism \
+ import Metabolism as MET
+
+from pycopancore.data_model.master_data_model.dimensions_and_units \
+ import DimensionsAndUnits as DAU
class World:
# natural:
- land_area = ENV.land_area.copy(default=1.5e8*km2)
- atmospheric_carbon = ENV.atmospheric_carbon.copy(default=589*GtC)
+ land_area = ENV.land_area.copy(default=1.5e8*DAU.km2)
+ atmospheric_carbon = ENV.atmospheric_carbon.copy(default=589*DAU.GtC)
surface_air_temperature = ENV.surface_air_temperature.copy()
- ocean_carbon = ENV.ocean_carbon.copy(default=38000*GtC)
- upper_ocean_carbon = ENV.upper_ocean_carbon.copy(default=900*GtC)
- deep_ocean_carbon = ENV.deep_ocean_carbon.copy(default=37100*GtC)
- terrestrial_carbon = ENV.terrestrial_carbon.copy(default=2550*GtC)
- soil_carbon = ENV.soil_carbon.copy(default=2000*GtC)
- biomass_carbon = ENV.biomass_carbon.copy(default=550*GtC)
+ ocean_carbon = ENV.ocean_carbon.copy(default=38000*DAU.GtC)
+ upper_ocean_carbon = ENV.upper_ocean_carbon.copy(default=900*DAU.GtC)
+ deep_ocean_carbon = ENV.deep_ocean_carbon.copy(default=37100*DAU.GtC)
+ terrestrial_carbon = ENV.terrestrial_carbon.copy(default=2550*DAU.GtC)
+ soil_carbon = ENV.soil_carbon.copy(default=2000*DAU.GtC)
+ biomass_carbon = ENV.biomass_carbon.copy(default=550*DAU.GtC)
harvestable_biomass_carbon = ENV.harvestable_biomass_carbon.copy()
other_biomass_carbon = ENV.other_biomass_carbon.copy()
- fossil_carbon = ENV.fossil_carbon.copy(default=1500*GtC)
+ fossil_carbon = ENV.fossil_carbon.copy(default=1500*DAU.GtC)
discovered_fossil_reserves = ENV.discovered_fossil_reserves.copy()
undiscovered_fossil_reserves = ENV.undiscovered_fossil_reserves.copy()
diff --git a/pycopancore/data_model/ordered_set.py b/pycopancore/data_model/ordered_set.py
index 49eddc0d..e47b99e2 100644
--- a/pycopancore/data_model/ordered_set.py
+++ b/pycopancore/data_model/ordered_set.py
@@ -12,11 +12,14 @@
# python recipe at https://code.activestate.com/recipes/576694/
# plus __add__, __iadd__
-import collections
+try:
+ from collections import MutableSet
+except:
+ from collections.abc import MutableSet
# TODO: docstrings
-class OrderedSet(collections.MutableSet):
+class OrderedSet(MutableSet):
"""Ordered Set."""
def __init__(self, iterable=None):
diff --git a/pycopancore/data_model/reference_variable.py b/pycopancore/data_model/reference_variable.py
index 21471444..312dd504 100644
--- a/pycopancore/data_model/reference_variable.py
+++ b/pycopancore/data_model/reference_variable.py
@@ -9,8 +9,8 @@
# Contact: core@pik-potsdam.de
# License: BSD 2-clause license
-from . import Variable
-from ..private import _DotConstruct
+from pycopancore.data_model.variable import Variable
+from pycopancore.private._expressions import _DotConstruct
# TODO: complete logics, set other Variable attributes, validate etc.
diff --git a/pycopancore/data_model/set_variable.py b/pycopancore/data_model/set_variable.py
index ec9358b2..7e31e285 100644
--- a/pycopancore/data_model/set_variable.py
+++ b/pycopancore/data_model/set_variable.py
@@ -9,8 +9,9 @@
# Contact: core@pik-potsdam.de
# License: BSD 2-clause license
-from . import Variable
-from ..private import _DotConstruct, unknown
+from pycopancore.data_model.variable import Variable
+from pycopancore.private._expressions import _DotConstruct
+from pycopancore.private._simple_expressions import unknown
# TODO: complete logics, set other Variable attributes, validate etc.
diff --git a/pycopancore/data_model/unit.py b/pycopancore/data_model/unit.py
index b83bc14c..4cc04052 100644
--- a/pycopancore/data_model/unit.py
+++ b/pycopancore/data_model/unit.py
@@ -13,7 +13,8 @@
import operator
from numpy import log10
-from . import dimension, dimensional_quantity, nondim
+from pycopancore.data_model.dimension import nondim
+from pycopancore.data_model import dimensional_quantity
class Unit (object):
@@ -49,7 +50,7 @@ def dimension(self):
return reduce(operator.mul,
[unit.dimension**ex
for unit, ex in self.exponents.items()],
- dimension.nondim)
+ nondim)
def __init__(self,
name="",
@@ -112,7 +113,7 @@ def __init__(self,
assert dimension is None, \
"dimension of non-base unit is derived automatically"
- def named(self, name, desc=None, *, symbol=None):
+ def named(self, name, *, desc=None, symbol=None):
return Unit(is_base=self.is_base, name=name,
symbol=self.symbol if symbol is None else symbol,
desc=self.desc if desc is None else desc,
diff --git a/pycopancore/data_model/variable.py b/pycopancore/data_model/variable.py
index 0ec83a9a..a548e2aa 100644
--- a/pycopancore/data_model/variable.py
+++ b/pycopancore/data_model/variable.py
@@ -16,8 +16,9 @@
import random
from sympy import Symbol
-from . import DimensionalQuantity, Unit
-from .. import private
+from pycopancore.data_model.dimensional_quantity import DimensionalQuantity
+from pycopancore.data_model.unit import Unit
+from pycopancore.private._simple_expressions import unset, unknown
EPS = 1e-10
@@ -44,7 +45,7 @@ class Variable(Symbol):
readonly = None
"""whether variable is read-only, e.g. holding redundant information"""
- default = private.unset # can't use None since None is a possible default value
+ default = unset # can't use None since None is a possible default value
"""default initial value"""
uninformed_prior = None
"""random value generator (probability distribution)
@@ -141,7 +142,7 @@ def __init__(self,
ref=None,
scale="ratio",
readonly=False,
- default=private.unset,
+ default=unset,
uninformed_prior=None,
CF=None,
AMIP=None,
@@ -204,10 +205,10 @@ def __init__(self,
self.levels = levels
if readonly:
- assert default is private.unset
+ assert default is unset
assert uninformed_prior is None
self.allow_none = True
- self.default = private.unknown
+ self.default = unknown
else:
self.allow_none = allow_none
self.default = default
@@ -247,7 +248,7 @@ def default(self):
@default.setter
def default(self, value):
- if value is not private.unset:
+ if value is not unset:
self.assert_valid(value)
self._default = value
@@ -312,7 +313,7 @@ def __repr__(self):
r += ", shape=" + str(self.array_shape)
# FIXME: the following was commented out as a dirty fix of the AttributeError
# in run_example1.py:
-# if self.default is not private.unset:
+# if self.default is not unset:
# r += ", default=" + str(self.default)
return r # + " (uid=" + str(self._uid) + ")"
@@ -321,7 +322,7 @@ def __repr__(self):
def _check_valid(self, v):
"""check validity of candidate value"""
- assert v is not private.unset, str(self) + " has no value set"
+ assert v is not unset, str(self) + " has no value set"
if self.array_shape is not None:
if not v.shape == self.array_shape:
@@ -430,6 +431,10 @@ def convert_to_standard_units(
self.set_value(i, v) # does the conversion
def _get_instances(self, instances):
+ from pycopancore.private._abstract_entity_mixin import \
+ _AbstractEntityMixin
+ from pycopancore.private._abstract_process_taxon_mixin import \
+ _AbstractProcessTaxonMixin
"""converts argument into a set of instances
(entities or process taxa)"""
if instances is None: # use all that have this variable
@@ -440,8 +445,8 @@ def _get_instances(self, instances):
instances.update(self._get_instances(k))
instances.update(self._get_instances(i))
elif isinstance(instances,
- (private._AbstractEntityMixin,
- private._AbstractProcessTaxonMixin)):
+ (_AbstractEntityMixin,
+ _AbstractProcessTaxonMixin)):
instances = set([instances])
else:
instances = set(instances)
@@ -451,7 +456,7 @@ def set_to_default(
self,
instances=None): # if None: all entities/taxa
"""Set values in selected entities to default if a default was given"""
- if self.default is private.unset:
+ if self.default is unset:
return
instances = self._get_instances(instances)
if instances: # Maybe variables owning class has no instances!
diff --git a/pycopancore/model_components/abstract/cell.py b/pycopancore/model_components/abstract/cell.py
index 298000cc..cab731f0 100644
--- a/pycopancore/model_components/abstract/cell.py
+++ b/pycopancore/model_components/abstract/cell.py
@@ -9,8 +9,8 @@
# Contact: core@pik-potsdam.de
# License: BSD 2-clause license
-from ...private import _AbstractEntityMixin
-from ...data_model import OrderedSet
+from pycopancore.private._abstract_entity_mixin import _AbstractEntityMixin
+from pycopancore.data_model.ordered_set import OrderedSet
class Cell (_AbstractEntityMixin):
diff --git a/pycopancore/model_components/abstract/culture.py b/pycopancore/model_components/abstract/culture.py
index ee88c3b5..8ae28d78 100644
--- a/pycopancore/model_components/abstract/culture.py
+++ b/pycopancore/model_components/abstract/culture.py
@@ -8,9 +8,9 @@
# URL:
# Contact: core@pik-potsdam.de
# License: BSD 2-clause license
-
-from ...private import _AbstractProcessTaxonMixin
-from ...data_model import OrderedSet
+from pycopancore.private._abstract_process_taxon_mixin import \
+ _AbstractProcessTaxonMixin
+from pycopancore.data_model.ordered_set import OrderedSet
class Culture (_AbstractProcessTaxonMixin):
diff --git a/pycopancore/model_components/abstract/environment.py b/pycopancore/model_components/abstract/environment.py
index d7af1c38..39a12861 100644
--- a/pycopancore/model_components/abstract/environment.py
+++ b/pycopancore/model_components/abstract/environment.py
@@ -8,8 +8,9 @@
# URL:
# License: MIT license
-from ...private import _AbstractProcessTaxonMixin
-from ...data_model import OrderedSet
+from pycopancore.private._abstract_process_taxon_mixin import \
+ _AbstractProcessTaxonMixin
+from pycopancore.data_model.ordered_set import OrderedSet
class Environment (_AbstractProcessTaxonMixin):
diff --git a/pycopancore/model_components/abstract/group.py b/pycopancore/model_components/abstract/group.py
index f919b38e..ad14d30d 100644
--- a/pycopancore/model_components/abstract/group.py
+++ b/pycopancore/model_components/abstract/group.py
@@ -9,8 +9,8 @@
# Contact: core@pik-potsdam.de
# License: BSD 2-clause license
-from ...private import _AbstractEntityMixin
-from ...data_model import OrderedSet
+from pycopancore.private._abstract_entity_mixin import _AbstractEntityMixin
+from pycopancore.data_model.ordered_set import OrderedSet
class Group (_AbstractEntityMixin):
diff --git a/pycopancore/model_components/abstract/individual.py b/pycopancore/model_components/abstract/individual.py
index 8b8e8a8a..c538c2af 100644
--- a/pycopancore/model_components/abstract/individual.py
+++ b/pycopancore/model_components/abstract/individual.py
@@ -9,8 +9,8 @@
# Contact: core@pik-potsdam.de
# License: BSD 2-clause license
-from ...private import _AbstractEntityMixin
-from ...data_model import OrderedSet
+from pycopancore.private._abstract_entity_mixin import _AbstractEntityMixin
+from pycopancore.data_model.ordered_set import OrderedSet
class Individual (_AbstractEntityMixin):
diff --git a/pycopancore/model_components/abstract/metabolism.py b/pycopancore/model_components/abstract/metabolism.py
index d158464e..4f30a9ac 100644
--- a/pycopancore/model_components/abstract/metabolism.py
+++ b/pycopancore/model_components/abstract/metabolism.py
@@ -12,8 +12,9 @@
# Contact: core@pik-potsdam.de
# License: BSD 2-clause license
-from ...private import _AbstractProcessTaxonMixin
-from ...data_model import OrderedSet
+from pycopancore.private._abstract_process_taxon_mixin import \
+ _AbstractProcessTaxonMixin
+from pycopancore.data_model.ordered_set import OrderedSet
class Metabolism (_AbstractProcessTaxonMixin):
diff --git a/pycopancore/model_components/abstract/social_system.py b/pycopancore/model_components/abstract/social_system.py
index 7540d1d5..ecc8d752 100644
--- a/pycopancore/model_components/abstract/social_system.py
+++ b/pycopancore/model_components/abstract/social_system.py
@@ -8,8 +8,8 @@
# URL:
# License: MIT license
-from ...private import _AbstractEntityMixin
-from ...data_model import OrderedSet
+from pycopancore.private._abstract_entity_mixin import _AbstractEntityMixin
+from pycopancore.data_model.ordered_set import OrderedSet
class SocialSystem (_AbstractEntityMixin):
diff --git a/pycopancore/model_components/abstract/world.py b/pycopancore/model_components/abstract/world.py
index 051c1143..4f1ef8a2 100644
--- a/pycopancore/model_components/abstract/world.py
+++ b/pycopancore/model_components/abstract/world.py
@@ -9,8 +9,8 @@
# Contact: core@pik-potsdam.de
# License: BSD 2-clause license
-from ...private import _AbstractEntityMixin
-from ...data_model import OrderedSet
+from pycopancore.private._abstract_entity_mixin import _AbstractEntityMixin
+from pycopancore.data_model.ordered_set import OrderedSet
class World (_AbstractEntityMixin):
diff --git a/pycopancore/model_components/adaptive_voter_opinion_formation/__init__.py b/pycopancore/model_components/adaptive_voter_opinion_formation/__init__.py
deleted file mode 100644
index 6852092c..00000000
--- a/pycopancore/model_components/adaptive_voter_opinion_formation/__init__.py
+++ /dev/null
@@ -1,26 +0,0 @@
-"""
-Model component package template.
-
-TODO:
-Copy this folder, rename it to the name of your model component,
-then adjust or fill in code and documentation in all modules wherever marked by "TODO:",
-finally remove these instructions.
-See the model component development tutorial for details.
-"""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-from . import interface
-
-# export all implementation classes:
-from .implementation import *
-
-# export model component mixin class:
-from .model import Model
diff --git a/pycopancore/model_components/adaptive_voter_opinion_formation/implementation/__init__.py b/pycopancore/model_components/adaptive_voter_opinion_formation/implementation/__init__.py
deleted file mode 100644
index 30d00d4d..00000000
--- a/pycopancore/model_components/adaptive_voter_opinion_formation/implementation/__init__.py
+++ /dev/null
@@ -1,20 +0,0 @@
-"""
-Model component implementation subpackage template.
-"""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-# TODO: adjust the following lists to your needs:
-
-# export all provided entity type implementation mixin classes:
-from .individual import Individual
-
-# export all provided process taxon implementation mixin classes:
-from .culture import Culture
diff --git a/pycopancore/model_components/adaptive_voter_opinion_formation/implementation/culture.py b/pycopancore/model_components/adaptive_voter_opinion_formation/implementation/culture.py
deleted file mode 100644
index 6e02a436..00000000
--- a/pycopancore/model_components/adaptive_voter_opinion_formation/implementation/culture.py
+++ /dev/null
@@ -1,298 +0,0 @@
-"""Culture process taxon mixing class template.
-
-TODO: adjust or fill in code and documentation wherever marked by "TODO:",
-then remove these instructions
-"""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-from .. import interface as I
-#from .... import master_data_model as D
-from .... import Step
-
-from ....runners import Hooks
-
-from blist import sortedlist # more performant for large list modifications
-import datetime as dt
-from enum import Enum, unique
-import random
-from time import time
-
-
-class Culture (I.Culture):
- """Culture process taxon mixin implementation class."""
-
- # standard methods:
-
- __nodes_by_opinion = None
- __nodes = None
-
- def __filter_by_opinion(opinion, input_list): return list(
- filter(lambda ind: ind.opinion == opinion, input_list))
-
- def __remove_by_opinion(opinion, input_list): return list(
- filter(lambda ind: ind.opinion != opinion, input_list))
-
- __update_function = None
-
- __configuration = dict( # keeps the configuration status, whether the updates are done basic or fast, and clusteredd or non-clustered
- configured=False,
- process_type=None,
- update_mode=None,
- synchronous_updates=None
- )
- """configuration status"""
- @unique
- class update_modes(Enum):
- """update modes for the adaptive voter model: basic or fast"""
- basic = 0
- fast = 1
-
- def __init__(self,
- *,
- rewiring,
- opinion_change=1.0,
- timestep=0.1,
- possible_opinions={0, 1},
- active_neighbor_only=True,
- **kwargs):
- """Initialize the unique instance of Culture.
-
- Parameters
- ----------
- rewiring : float or function
- if float: probability of rewiring
- if function: decide whether the link between the two individuals is separated and a link to a new individual is created
- takes: active_individual, active_individuals_neighbor
-
- opinion_change: float or function, optional, default: 1
- if float: probability of opinion adaption if there was no rewiring
- if function: decide whether the opinion of the neighbor should be adopted
- takes: active_individual, active_individuals_neighbor
-
- timestep : float, optional, default: 0.1
- interval between opinion updates
-
- possible_opinions : set-like, optional, default: {0, 1}
- set of possible options the individuals can take
-
- active_neighbor_only : bool, optional, default: True
- if False: any neighbor of the active individual is chosen randomly
- if True: only neighbors with different opinions are chosen randomly (if there is at least one, else nothing is done)
- """
- super().__init__(**kwargs)
-
- # TODO: ask Jobst, whether this should get the network as input so it
- # could be applied to different networks... seems sensible too me but
- # might contradict the frameworks idea
-
- _rewiring = rewiring
- if not callable(rewiring):
- if rewiring == 1:
- def _rewiring(x, y): return True
- else:
- assert 0 < rewiring < 1, "rewiring_probability should be a float between 0 and 1 or a function"
-
- def _rewiring(x, y): return random.random() < rewiring
- self.rewiring = _rewiring
-
- if not callable(opinion_change):
- if opinion_change == 1:
- def opinion_change(x, y): return True
- else:
- _opinion_change = opinion_change
-
- def opinion_change(
- x, y): return random.random() < _opinion_change
- self.opinion_change = opinion_change
-
- self.possible_opinions = possible_opinions
- self.active_neighbor_only = active_neighbor_only
-
- self.next_update_time = 0
- self.timestep = timestep
-
- # process-related methods:
-
- def analyze_graph(self, t):
- """analyze the graph so speed-ups can be used later"""
- # TODO: test whether sortedlist or sets are faster for large numbers of
- # entries
- assert t == 0, "This function should be run as a pre-hook of the runner!"
- print(" analyzing the graph ... ", end="", flush=True)
- start = time()
-
- self.__nodes = sortedlist(self.acquaintance_network.nodes()) # FIXME: why do you assume entities allow sorting?
- self.__nodes_by_opinion = {opinion: sortedlist()
- for opinion in self.possible_opinions}
- for node in self.acquaintance_network:
- self.__nodes_by_opinion[node.opinion].add(node)
-
- print("done ({})".format(dt.timedelta(seconds=(time() - start))))
-
- def clear_graph_analysis(self, t):
- """clear everything that was created during analyze_graph"""
- print(" deleting lists from graph analysis")
- del self.__nodes
- del self.__nodes_by_opinion
-
- def opinion_update_basic(self, t):
- """update the aquaintance network following the adaptive voter model prescription by (Holme, Newman - 2006)"""
- # this code is currently only precisely following the model prescription
- # without any additional speed-ups
-
- nodes = list(self.acquaintance_network.nodes())
-
- active_individual = random.choice(nodes)
- neighbors = self.acquaintance_network.neighbors(active_individual)
- if self.active_neighbor_only:
- active_neighbors = Culture.__remove_by_opinion(
- active_individual.opinion, neighbors)
- if not active_neighbors:
- return # nothing to be done
- active_neighbor = random.choice(active_neighbors)
- else:
- active_neighbor = random.choice(neighbors)
-
- # decide whether to rewire or to adopt the opinion
- if self.rewiring(active_individual, active_neighbor):
- # rewire
- possible_new_neighbors = Culture.__filter_by_opinion(
- active_individual.opinion, nodes)
- if not possible_new_neighbors:
- return # can't find a new one, active_individual is the last one
- new_neighbor = random.choice(possible_new_neighbors)
- # new_neighbor = random.choice(list(filter(lambda x: x.opinion == active_individual.opinion, self.acquaintance_network.nodes())))
- self.acquaintance_network.remove_edge(
- active_individual, active_neighbor)
- self.acquaintance_network.add_edge(active_individual, new_neighbor)
- elif self.opinion_change(active_individual, active_neighbor):
- # adopt opinion
- active_individual.opinion = active_neighbor.opinion
-
- def opinion_update_fast(self, t):
- """update the aquaintance network following the adaptive voter model prescription by (Holme, Newman - 2006)"""
- # TODO: there are some intuitive speed-ups:
- # 1) (done) use a list with references to nodes of the differing opinions so the statement with filter can be avoided
- # 2) cluster the updates instead of making every update separately
- # ... this should probably be done as a separate function calling one of the opinion_update_basic/fast functions
- # ... make sure that the rest of the model works on longer time scales if you do that
- # ... introduce a time scale for that
-
- # choose only between the active nodes, which are the keys of this
- # sortedset
- active_individual = random.choice(self.__nodes)
- neighbors = self.acquaintance_network.neighbors(active_individual)
- if self.active_neighbor_only:
- active_neighbors = Culture.__remove_by_opinion(
- active_individual.opinion, neighbors)
- if not active_neighbors:
- return # nothing to be done
- active_neighbor = random.choice(active_neighbors)
- else:
- active_neighbor = random.choice(neighbors)
-
- # decide whether to rewire or to adopt the opinion
- if self.rewiring(active_individual, active_neighbor):
- # rewire
-
- # find new neighbor with same opinion
- if not self.__nodes_by_opinion[active_individual.opinion]:
- return # active_individual is the last one with this opinion and cannot connect to a new one
- new_neighbor = random.choice(
- self.__nodes_by_opinion[active_individual.opinion])
- # remove old link
- self.acquaintance_network.remove_edge(
- active_individual, active_neighbor)
- # add new link
- self.acquaintance_network.add_edge(active_individual, new_neighbor)
- elif self.opinion_change(active_individual, active_neighbor):
- # adopt opinion
-
- # move the active individual to the new opinion list
- self.__nodes_by_opinion[active_individual.opinion].remove(
- active_individual)
- self.__nodes_by_opinion[active_neighbor.opinion].add(
- active_individual)
- # set the new opinion
- # TODO: ask Jobst, whether this is okai within his framework!
- active_individual.opinion = active_neighbor.opinion
-
- # test, update opinion for n individuals at the same time
- def opinion_update_multiple(self, t):
- for i in range(self.multiple_updates):
- self.__update_function(t)
-
- def next_update_time(self, t):
- self.next_update_time += self.timestep
- return self.next_update_time
-
- @classmethod
- def configure(cls, *, update_mode, synchronous_updates=1):
- """configure the adaptive voter opinion formation model component
-
- Parameters
- ----------
-
- update_mode : element of Enum Cultur.update_modes
- chooses between the basic and the fast update mode. The fast update mode is preferred but needs the nodes of the acquaintance_network to stay the same
-
- synchronous_updates : (optional) positive int
- how many opinion updates should be done at once
- """
-
- synchronous_updates = int(synchronous_updates)
- assert synchronous_updates >= 1, "can't do a non-positive number of synchronous updates"
-
- assert update_mode in Culture.update_modes, "choose an update mode from Culture.update_modes Enum"
-
- cls.multiple_updates = synchronous_updates
-
- process_type = Step
- process_name = "opinion update"
- process_variables = [
- I.Culture.acquaintance_network, I.Individual.opinion]
- process_time = cls.next_update_time
- process_func = cls.opinion_update_multiple
-
- # unregister everything
- Hooks.unregister_hook(Hooks.Types.pre, cls.analyze_graph,
- I.Culture, error_if_not_registered=False)
- Hooks.unregister_hook(Hooks.Types.post, cls.clear_graph_analysis,
- I.Culture, error_if_not_registered=False)
-
- if update_mode is Culture.update_modes.basic:
- cls.__update_function = cls.opinion_update_basic
- elif update_mode is Culture.update_modes.fast:
- cls.__update_function = cls.opinion_update_fast
- # register necessary hooks
- Hooks.register_hook(Hooks.Types.pre, cls.analyze_graph, I.Culture)
- Hooks.register_hook(
- Hooks.Types.post, cls.clear_graph_analysis, I.Culture)
- else:
- raise ValueError("unknown update_mode '{}'".format(update_mode))
-
- # set the configuration dictionary
- cls.__configuration["configured"] = True
- cls.__configuration["process_type"] = process_type
- cls.__configuration["update_mode"] = update_mode
- cls.__configuration["synchronous_updates"] = synchronous_updates
-
- cls.processes = [
- process_type(
- process_name,
- process_variables,
- [process_time, process_func]
- )
- ]
-
-
-# set the default configuration of the model component
-Culture.configure(update_mode=Culture.update_modes.fast)
diff --git a/pycopancore/model_components/adaptive_voter_opinion_formation/implementation/individual.py b/pycopancore/model_components/adaptive_voter_opinion_formation/implementation/individual.py
deleted file mode 100644
index 3e0b0123..00000000
--- a/pycopancore/model_components/adaptive_voter_opinion_formation/implementation/individual.py
+++ /dev/null
@@ -1,56 +0,0 @@
-"""Individual entity type class template.
-
-TODO: adjust or fill in code and documentation wherever marked by "TODO:",
-then remove these instructions
-"""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-from .. import interface as I
-#from .... import master_data_model as D
-
-import random
-
-
-class Individual (I.Individual):
- """Individual entity type mixin implementation class."""
-
- # standard methods:
-
- def __init__(self,
- *,
- initial_opinion,
- **kwargs):
- """Initialize an instance of Individual."""
- super().__init__(**kwargs) # must be the first line
- self.opinion = initial_opinion
- pass
-
- def __lt__(self, other):
- """make objects sortable, so big sorted lists can be used for quick look-ups"""
- return self._uid < other._uid
-
- def deactivate(self):
- """Deactivate an individual."""
- # TODO: add custom code here:
- pass
- super().deactivate() # must be the last line
-
- def reactivate(self):
- """Reactivate an individual."""
- super().reactivate() # must be the first line
- # TODO: add custom code here:
- pass
-
- # process-related methods:
-
- # TODO: add some if needed...
-
- processes = [] # TODO: instantiate and list process objects here
diff --git a/pycopancore/model_components/adaptive_voter_opinion_formation/interface.py b/pycopancore/model_components/adaptive_voter_opinion_formation/interface.py
deleted file mode 100644
index 8a15754a..00000000
--- a/pycopancore/model_components/adaptive_voter_opinion_formation/interface.py
+++ /dev/null
@@ -1,82 +0,0 @@
-"""model component Interface template.
-
-TODO: adjust or fill in code and documentation wherever marked by "TODO:", then
-remove these instructions.
-"""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-# TODO: use variables from the master data model wherever possible:
-from ... import master_data_model as D
-# TODO: uncomment and adjust of you need further variables from another
-# model component:
-# import ..BBB.interface as BBB
-# TODO: uncomment and adjust only if you really need other variables:
-from ... import Variable # used for opinion here, maybe that should be included in the master data model? But I wouldn't know how? something like discrete opinion
-from ..base import interface as baseI
-
-
-class Model (object):
- """Interface for Model mixin."""
-
- # metadata:
- name = "adaptive voter model"
- """a unique name for the model component"""
- description = "..."
- """see (Holme, Newman - 2006)"""
- requires = []
- """list of other model components required for this model component to
- make sense"""
-
- # Notes:
- # - Model does NOT define variables or parameters, only entity types
- # and process taxons do!
- # - implementation.Model lists these entity-types and process taxons
-
-
-# entity types:
-
-class Culture (object):
- """Interface for Culture process taxon mixin."""
-
- # endogenous variables:
- acquaintance_network = D.CUL.acquaintance_network
- # TODO: give possible_opinions a type, wait for Wolf's choice stuff in the
- # master data model
- possible_opinions = Variable(
- "possible opinions",
- "possible opinions of an individual in the sense of the adaptive voter model"
- )
-
- opinion_change = Variable("probability to adopt another opinion", "")
-
- multiple_updates = Variable(
- "number of updates", "number of updates that are done at the same time")
-
- # exogenous variables / parameters:
-
-
-class Individual (object):
- """Interface for Individual entity type mixin."""
-
- # endogenous variables:
- opinion = Variable(
- "opinion",
- "opinion of an individual in the sense of the adaptive voter model"
- )
- """Interface for Culture process taxon mixin."""
-
- # endogenous variables:
- rewiring_probability = Variable(
- "rewiring probability",
- "rewiring probability phi in the sense of the adaptive voter model by (Holme, Newman - 2006)"
- )
-
- # exogenous variables / parameters:
diff --git a/pycopancore/model_components/adaptive_voter_opinion_formation/model.py b/pycopancore/model_components/adaptive_voter_opinion_formation/model.py
deleted file mode 100644
index b561dc02..00000000
--- a/pycopancore/model_components/adaptive_voter_opinion_formation/model.py
+++ /dev/null
@@ -1,31 +0,0 @@
-"""Model mixing class template.
-
-TODO: adjust or fill in code and documentation wherever marked by "TODO:",
-then remove these instructions
-"""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-from . import interface as I
-# import all needed entity type implementation classes:
-from .implementation import Individual
-# import all needed process taxon implementation classes:
-from .implementation import Culture
-
-
-class Model (I.Model):
- """Model mixin class"""
-
- # mixins provided by this model component:
-
- entity_types = [Individual]
- """list of entity types augmented by this component"""
- process_taxa = [Culture]
- """list of process taxa augmented by this component"""
diff --git a/pycopancore/model_components/anderies_carbon_cycle/__init__.py b/pycopancore/model_components/anderies_carbon_cycle/__init__.py
deleted file mode 100644
index d9f2b43c..00000000
--- a/pycopancore/model_components/anderies_carbon_cycle/__init__.py
+++ /dev/null
@@ -1,20 +0,0 @@
-
-"""
-copan_global_like_carbon_cycle model component
-"""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-from . import interface
-
-from .implementation import *
-
-# export model component mixin class:
-from .model import Model
diff --git a/pycopancore/model_components/anderies_carbon_cycle/implementation/__init__.py b/pycopancore/model_components/anderies_carbon_cycle/implementation/__init__.py
deleted file mode 100644
index d6e283c7..00000000
--- a/pycopancore/model_components/anderies_carbon_cycle/implementation/__init__.py
+++ /dev/null
@@ -1,19 +0,0 @@
-"""
-This is the copan_global_like_carbon_cycle model-component implementation subpackage
-"""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-
-from .world import World
-from .cell import Cell
-from .social_system import SocialSystem
-
-from .environment import Environment
diff --git a/pycopancore/model_components/anderies_carbon_cycle/implementation/cell.py b/pycopancore/model_components/anderies_carbon_cycle/implementation/cell.py
deleted file mode 100644
index 45299863..00000000
--- a/pycopancore/model_components/anderies_carbon_cycle/implementation/cell.py
+++ /dev/null
@@ -1,114 +0,0 @@
-"""Jobst: write docstring."""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-from .... import Explicit, ODE
-from .... import master_data_model as D
-from ...base import interface as B
-
-from .. import interface as I
-
-import numpy as np
-import sympy as sp
-
-
-class Cell (I.Cell):
- """Jobst: write docstring."""
-
- # standard methods:
-
- def __init__(self,
- *,
- terrestrial_carbon=1 * D.gigatonnes_carbon,
- fossil_carbon=1 * D.gigatonnes_carbon,
- **kwargs
- ):
- """Initialize a cell"""
- super().__init__(**kwargs)
- # initial values:
- self.terrestrial_carbon = terrestrial_carbon
- self.fossil_carbon = fossil_carbon
-
- # abbreviations:
-
- balance = I.Cell.net_ecosystem_production - I.Cell.human_offtake
-
- processes = [ # using symbolic expressions for performance reasons:
-
- Explicit("net ecosystem production",
- [I.Cell.net_ecosystem_production],
- [B.Cell.environment.ecosystem_dependent_conversion_factor
- * I.Cell.terrestrial_carbon * (1 - (I.Cell.terrestrial_carbon
- / B.Cell.environment.terrestrial_carbon_carrying_capacity))
- * (I.World.photosynthesis_rate - I.World.respiration_rate)
- ]),
-
-
- # capacity per area?
- # Explicit("net ecosystem production",
- # [I.Cell.net_ecosystem_production],
- # [B.Cell.environment.ecosystem_dependent_conversion_factor
- # * I.Cell.terrestrial_carbon * (1 - (I.Cell.terrestrial_carbon
- # / (B.Cell.environment.terrestrial_carbon_capacity_per_area
- # * B.Cell.land_area)))
- # * (I.World.photosynthesis_rate - I.World.respiration_rate)
- # ]),
-
- Explicit("human offtake", # Interface
- [I.Cell.human_offtake],
- [I.SocialSystem.harvest_rate * I.Cell.terrestrial_carbon
- ]),
-
- ODE("effect of photosynthesis and respiration",
- [I.Cell.terrestrial_carbon, B.Cell.world.atmospheric_carbon],
- [balance, -balance]),
-
- ]
-
-# instead of:
-#
-# def do_photosynthesis(self, unused_t):
-# """compute and store rhs of ODE photosynthesis"""
-#
-# # abbreviations:
-# L = self.terrestrial_carbon
-# Sigma = self.land_area
-#
-# self.photosynthesis_carbon_flow = \
-# ((self.environment.basic_photosynthesis_productivity
-# - self.environment.photosynthesis_sensitivity_on_atmospheric_carbon
-# * self.world.atmospheric_carbon)
-# * np.sqrt(self.world.atmospheric_carbon / Sigma)
-# * (1 - L / (self.environment.terrestrial_carbon_capacity_per_area
-# * Sigma))) \
-# * L
-#
-# self.world.d_atmospheric_carbon -= self.photosynthesis_carbon_flow
-# self.d_terrestrial_carbon += self.photosynthesis_carbon_flow
-#
-# def do_respiration(self, unused_t):
-# """compute and store rhs of ODE respiration"""
-#
-# self.terrestrial_respiration_carbon_flow = \
-# (self.environment.basic_respiration_rate
-# + self.environment.respiration_sensitivity_on_atmospheric_carbon
-# * self.world.atmospheric_carbon) \
-# * self.terrestrial_carbon
-#
-# self.d_terrestrial_carbon -= self.terrestrial_respiration_carbon_flow
-# self.world.d_atmospheric_carbon += self.terrestrial_respiration_carbon_flow
-#
-# processes = [
-# ODE("photosynthesis", [I.Cell.terrestrial_carbon,
-# B.Cell.world.atmospheric_carbon],
-# do_photosynthesis),
-# ODE("respiration", [I.Cell.terrestrial_carbon, I.World.atmospheric_carbon],
-# do_respiration),
-# ]
diff --git a/pycopancore/model_components/anderies_carbon_cycle/implementation/environment.py b/pycopancore/model_components/anderies_carbon_cycle/implementation/environment.py
deleted file mode 100644
index a7dcf2b0..00000000
--- a/pycopancore/model_components/anderies_carbon_cycle/implementation/environment.py
+++ /dev/null
@@ -1,98 +0,0 @@
-"""Environment process taxon mixing class.
-"""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-from .. import interface as I
-from ....data_model.master_data_model.dimensions_and_units import \
- gigatonnes_carbon, years, square_kilometers, kelvins
-
-
-class Environment (I.Environment):
- """Environment process taxon mixin implementation class."""
-
- # standard methods:
-
- def __init__(self,
- *, # TODO: uncomment when adding named args behind here
- ocean_atmosphere_diffusion_coefficient=0.05 / years, # Anderies
- carbon_solubility_in_sea_water=1, # Anderies
- basic_photosynthesis_productivity=26.4 / years / \
- (gigatonnes_carbon /
- square_kilometers)**.5, # see Nitzbon 2016
- photosynthesis_sensitivity_on_atmospheric_carbon=0 \
- # 1.1e6 \
- / years / (gigatonnes_carbon / square_kilometers)**.5
- / kelvins, # see Nitzbon 2016
- terrestrial_carbon_capacity_per_area=5000 / 1.5e8 * \
- gigatonnes_carbon / square_kilometers, # ca. 2 times current value
- basic_respiration_rate=0.0298 / years, # see Nitzbon 2016
- respiration_sensitivity_on_atmospheric_carbon=0 \
- # 3200 \
- / years / (gigatonnes_carbon / square_kilometers), # see Nitzbon 2016
- temperature_offset=0.2 * kelvins, # Anderies
- temperature_sensitivity_on_atmospheric_carbon=0.8 * \
- kelvins / gigatonnes_carbon, # Anderies
- scaling_factor_temperature_respiration=110, # Anderies
- exponent_for_increase_in_respiration_low_T=4, # Anderies
- exponent_for_increase_in_respiration_high_T=5, # Anderies
- strength_of_fertilization_effect=1.5, # Anderies
- rapidity_of_fertilization_saturation=0.3, # Anderies
- scaling_factor_temperature_photosynthesis=220, # Anderies
- exponent_for_increase_in_photosynthesis_low_T=3, # Anderies
- exponent_for_increase_in_photosynthesis_high_T=7, # Anderies
- ecosystem_dependent_conversion_factor=2.5,
- terrestrial_carbon_carrying_capacity=0.7,
- **kwargs):
- """Initialize the unique instance of Environment."""
- super().__init__(**kwargs) # must be the first line
-
- self.ocean_atmosphere_diffusion_coefficient = \
- ocean_atmosphere_diffusion_coefficient
- self.carbon_solubility_in_sea_water = carbon_solubility_in_sea_water
- self.basic_photosynthesis_productivity = \
- basic_photosynthesis_productivity
- self.photosynthesis_sensitivity_on_atmospheric_carbon = \
- photosynthesis_sensitivity_on_atmospheric_carbon
- self.terrestrial_carbon_capacity_per_area = \
- terrestrial_carbon_capacity_per_area
- self.basic_respiration_rate = basic_respiration_rate
- self.respiration_sensitivity_on_atmospheric_carbon = \
- respiration_sensitivity_on_atmospheric_carbon
- self.temperature_offset = temperature_offset
- self.temperature_sensitivity_on_atmospheric_carbon = \
- temperature_sensitivity_on_atmospheric_carbon
-# Anderies:
- self.scaling_factor_temperature_respiration = \
- scaling_factor_temperature_respiration
- self.exponent_for_increase_in_respiration_low_T = \
- exponent_for_increase_in_respiration_low_T
- self.exponent_for_increase_in_respiration_high_T = \
- exponent_for_increase_in_respiration_high_T
- self.strength_of_fertilization_effect = \
- strength_of_fertilization_effect
- self.rapidity_of_fertilization_saturation = \
- rapidity_of_fertilization_saturation
- self.scaling_factor_temperature_photosynthesis = \
- scaling_factor_temperature_photosynthesis
- self.exponent_for_increase_in_photosynthesis_low_T = \
- exponent_for_increase_in_photosynthesis_low_T
- self.exponent_for_increase_in_photosynthesis_high_T = \
- exponent_for_increase_in_photosynthesis_high_T
- self.ecosystem_dependent_conversion_factor = \
- ecosystem_dependent_conversion_factor
- self.terrestrial_carbon_carrying_capacity = \
- terrestrial_carbon_carrying_capacity
-
- # process-related methods:
-
- # TODO: add some if needed...
-
- processes = [] # TODO: instantiate and list process objects here
diff --git a/pycopancore/model_components/anderies_carbon_cycle/implementation/social_system.py b/pycopancore/model_components/anderies_carbon_cycle/implementation/social_system.py
deleted file mode 100644
index 442abcde..00000000
--- a/pycopancore/model_components/anderies_carbon_cycle/implementation/social_system.py
+++ /dev/null
@@ -1,50 +0,0 @@
-"""SocialSystem entity type mixing class template.
-
-TODO: adjust or fill in code and documentation wherever marked by "TODO:",
-then remove these instructions
-"""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-from .. import interface as I
-#from .... import master_data_model as D
-
-
-class SocialSystem (I.SocialSystem):
- """SocialSystem entity type mixin implementation class."""
-
- # standard methods:
-
- def __init__(self,
- *,
- harvest_rate=0.5,
- **kwargs):
- """Initialize an instance of SocialSystem."""
- super().__init__(**kwargs) # must be the first line
-
- self.harvest_rate = harvest_rate
-
- def deactivate(self):
- """Deactivate a social_system."""
- # TODO: add custom code here:
- pass
- super().deactivate() # must be the last line
-
- def reactivate(self):
- """Reactivate a social_system."""
- super().reactivate() # must be the first line
- # TODO: add custom code here:
- pass
-
- # process-related methods:
-
- # TODO: add some if needed...
-
- processes = [] # TODO: instantiate and list process objects here
diff --git a/pycopancore/model_components/anderies_carbon_cycle/implementation/world.py b/pycopancore/model_components/anderies_carbon_cycle/implementation/world.py
deleted file mode 100644
index d6f750fe..00000000
--- a/pycopancore/model_components/anderies_carbon_cycle/implementation/world.py
+++ /dev/null
@@ -1,82 +0,0 @@
-"""Jobst: write docstring."""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-from .... import Explicit, ODE
-from .. import interface as I
-from ...base import interface as B
-from .... import master_data_model as D
-
-import sympy as sp
-
-
-class World (I.World):
- """Jobst: write docstring."""
-
- # standard methods:
-
- def __init__(self,
- *,
- atmospheric_carbon=1 * D.gigatonnes_carbon,
- ocean_carbon=1 * D.gigatonnes_carbon,
- surface_air_temperature=1 * D.kelvins,
- **kwargs
- ):
- """Initialize an (typically the unique) instance of World."""
- super().__init__(**kwargs)
- # initial values:
- self.atmospheric_carbon = atmospheric_carbon
- self.ocean_carbon = ocean_carbon
- self.surface_air_temperature = surface_air_temperature
-
- # process-related methods:
-
- def convert_temperature(self, unused_t):
- """(see Anderies et al. 2013)"""
- self.surface_air_temperature = self.environment.temperature_offset \
- + self.environment.temperature_sensitivity_on_atmospheric_carbon \
- * self.atmospheric_carbon
-
- def ocean_atmosphere_diffusion(self, unused_t):
- """(see Anderies et al. 2013)"""
- flow = self.environment.ocean_atmosphere_diffusion_coefficient * (
- self.environment.carbon_solubility_in_sea_water * self.ocean_carbon
- - self.atmospheric_carbon)
- self.d_ocean_carbon -= flow
- self.d_atmospheric_carbon += flow
-
- processes = [
- Explicit("convert temperature",
- [I.World.surface_air_temperature],
- convert_temperature),
- ODE("ocean-atmosphere diffusion",
- [I.World.ocean_carbon, I.World.atmospheric_carbon],
- ocean_atmosphere_diffusion),
-
- Explicit("respiration rate",
- [I.World.respiration_rate],
- [(B.World.environment.scaling_factor_temperature_respiration
- * I.World.surface_air_temperature ** B.World.environment.exponent_for_increase_in_respiration_low_T
- * sp.exp(-B.World.environment.exponent_for_increase_in_respiration_high_T
- * B.Cell.world.surface_air_temperature))]),
-
- Explicit("fertilization",
- [I.World.fertilization],
- [B.World.environment.strength_of_fertilization_effect * I.World.atmospheric_carbon
- ** B.World.environment.rapidity_of_fertilization_saturation]),
-
- Explicit("photosynthesis rate",
- [I.World.photosynthesis_rate],
- [I.World.fertilization
- * B.World.environment.scaling_factor_temperature_photosynthesis * I.World.surface_air_temperature
- ** B.World.environment.exponent_for_increase_in_photosynthesis_low_T
- * sp.exp(-B.World.environment.exponent_for_increase_in_photosynthesis_high_T
- * I.World.surface_air_temperature)])
- ]
diff --git a/pycopancore/model_components/anderies_carbon_cycle/interface.py b/pycopancore/model_components/anderies_carbon_cycle/interface.py
deleted file mode 100644
index b0a232c5..00000000
--- a/pycopancore/model_components/anderies_carbon_cycle/interface.py
+++ /dev/null
@@ -1,103 +0,0 @@
-"""copan_global_like_carbon_cycle model component Interface
-"""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-from ... import master_data_model as D
-from ...data_model.master_data_model import ENV, MET, CUL, W, S, C, I
-from ... import Variable
-
-
-class Model (object):
- """Interface for Model mixin"""
-
- # metadata:
- name = "Anderies carbon cycle"
- """a unique name for the model component"""
- description = "see Anderies 2013"
- """some longer description"""
- requires = []
- """list of other model components required for this model component to
- make sense"""
-
-
-# entity types:
-
-
-class World (object):
- """Interface for World mixin"""
-
- # variables:
- atmospheric_carbon = W.atmospheric_carbon
- ocean_carbon = W.ocean_carbon
- surface_air_temperature = W.surface_air_temperature
- respiration_rate = Variable("respiration rate", "") # unit
- fertilization = Variable("fertilization", "") # unit
- photosynthesis_rate = Variable("photosynthesis rate", "") # unit
-
-
-class Cell (object):
- """Interface for Cell mixin"""
-
- # variables:
- terrestrial_carbon = C.terrestrial_carbon
- photosynthesis_carbon_flow = C.photosynthesis_carbon_flow
- terrestrial_respiration_carbon_flow = \
- C.terrestrial_respiration_carbon_flow
- human_offtake = Variable("human offtake", "") # unit
- net_ecosystem_production = Variable(
- "net ecosystem production", "") # unit
-
-
-class SocialSystem (object):
-
- # variables:
- harvest_rate = Variable("harvest rate", "") # unit
-
-
-# process taxa:
-
-
-class Environment (object):
- """Interface for Environment mixin"""
-
- # parameters / exogenous veriables:
- ocean_atmosphere_diffusion_coefficient = \
- ENV.ocean_atmosphere_diffusion_coefficient
- carbon_solubility_in_sea_water = ENV.carbon_solubility_in_sea_water
-
- basic_photosynthesis_productivity = \
- Variable("basic photosynthesis productivity", "",
- unit=D.years**-1
- / (D.gigatonnes_carbon / D.square_kilometers)**.5,
- lower_bound=0)
- photosynthesis_sensitivity_on_atmospheric_carbon = \
- Variable("sensitivity of photosynthesis productivity on atmospheric carbon", "",
- unit=D.years**-1
- / (D.gigatonnes_carbon / D.square_kilometers)**.5
- / D.kelvins)
- terrestrial_carbon_capacity_per_area = \
- Variable("per-area capacity of terrestrial carbon", "",
- unit=D.gigatonnes_carbon / D.square_kilometers,
- lower_bound=0)
-
- basic_respiration_rate = Variable("basic respiration rate", "",
- unit=D.years**-1)
- respiration_sensitivity_on_atmospheric_carbon = \
- Variable("sensitivity of respiration rate on atmospheric carbon", "",
- unit=D.years**-1
- / (D.gigatonnes_carbon / D.square_kilometers))
-
- temperature_offset = \
- Variable("offset of temperature for zero atmospheric carbon", "",
- unit=D.kelvins, lower_bound=0)
- temperature_sensitivity_on_atmospheric_carbon = \
- Variable("sensitivity of temperature on atmospheric carbon", "",
- unit=D.kelvins / D.gigatonnes_carbon, lower_bound=0)
diff --git a/pycopancore/model_components/anderies_carbon_cycle/model.py b/pycopancore/model_components/anderies_carbon_cycle/model.py
deleted file mode 100644
index 9d622461..00000000
--- a/pycopancore/model_components/anderies_carbon_cycle/model.py
+++ /dev/null
@@ -1,26 +0,0 @@
-"""copan_global_like_carbon_cycle model mixing class
-"""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-from . import interface as I
-# import all needed entity type implementation classes:
-from .implementation import World, Cell, SocialSystem
-# import all needed process taxon implementation classes:
-from .implementation import Environment
-
-
-class Model (I.Model):
- """Model component mixin class"""
-
- # mixins provided by this model component:
-
- entity_types = [World, Cell, SocialSystem]
- process_taxa = [Environment]
diff --git a/pycopancore/model_components/base/implementation/cell.py b/pycopancore/model_components/base/implementation/cell.py
index f34a961c..035521b4 100644
--- a/pycopancore/model_components/base/implementation/cell.py
+++ b/pycopancore/model_components/base/implementation/cell.py
@@ -10,12 +10,11 @@
# License: BSD 2-clause license
# only used in this component, not in others:
-from ... import abstract
-from ....private import unknown
+from pycopancore.model_components import abstract
+from pycopancore.private._simple_expressions import unknown
# typical imports for implementation classes:
from .. import interface as I
-from .... import master_data_model as D
class Cell (I.Cell, abstract.Cell):
diff --git a/pycopancore/model_components/base/implementation/culture.py b/pycopancore/model_components/base/implementation/culture.py
index 1d2239af..81d42c40 100644
--- a/pycopancore/model_components/base/implementation/culture.py
+++ b/pycopancore/model_components/base/implementation/culture.py
@@ -9,8 +9,11 @@
# Contact: core@pik-potsdam.de
# License: BSD 2-clause license
+from networkx import Graph
+
# only used in this component, not in others:
-from ... import abstract
+from pycopancore.model_components import abstract
+from pycopancore.private._simple_expressions import unknown
from .. import interface as I
@@ -64,6 +67,44 @@ def worlds(self):
"""Get the set of all Worlds this Culture acts in."""
return self._worlds
+ _individuals = unknown
+ """cache, depends on self.worlds, world.individuals"""
+ @property # read-only
+ def individuals(self):
+ """Get and set the set of Individuals governed by this Culture."""
+ if self._individuals is unknown:
+ # aggregate from worlds:
+ self._individuals = set()
+ for w in self.worlds:
+ self._individuals.update(w.individuals)
+ return self._individuals
+
+ @individuals.setter
+ def individuals(self, u):
+ assert u == unknown, "setter can only be used to reset cache"
+ self._individuals = unknown
+ # reset dependent caches:
+ pass
+
+ _social_systems = unknown
+ """cache, depends on self.worlds, world.social_systems"""
+ @property # read-only
+ def social_systems(self):
+ """Get and set the set of SocialSystems governed by this Culture."""
+ if self._social_systems is unknown:
+ # aggregate from worlds:
+ self._social_systems = set()
+ for w in self.worlds:
+ self._social_systems.update(w.social_systems)
+ return self._social_systems
+
+ @social_systems.setter
+ def social_systems(self, u):
+ assert u == unknown, "setter can only be used to reset cache"
+ self._social_systems = unknown
+ # reset dependent caches:
+ pass
+
@property # read-only
def groups(self):
"""Get the set of all Groups in this Culture."""
diff --git a/pycopancore/model_components/base/implementation/group.py b/pycopancore/model_components/base/implementation/group.py
index e28a71e0..74854faf 100644
--- a/pycopancore/model_components/base/implementation/group.py
+++ b/pycopancore/model_components/base/implementation/group.py
@@ -10,10 +10,7 @@
# License: BSD 2-clause license
# only used in this component, not in others:
-from ... import abstract
-from .... import master_data_model as D
-from ....private import unknown
-
+from pycopancore.model_components import abstract
from .. import interface as I
diff --git a/pycopancore/model_components/base/implementation/individual.py b/pycopancore/model_components/base/implementation/individual.py
index dcaa0ffb..f910da7e 100644
--- a/pycopancore/model_components/base/implementation/individual.py
+++ b/pycopancore/model_components/base/implementation/individual.py
@@ -10,12 +10,13 @@
# License: BSD 2-clause license
# only used in this component, not in others
-from ... import abstract
+from pycopancore.model_components import abstract
# from .... import master_data_model as D
-from ....private import unknown
+from pycopancore.private._simple_expressions import unknown
from .. import interface as I
+
class Individual (I.Individual, abstract.Individual):
"""Individual entity type mixin implementation class.
diff --git a/pycopancore/model_components/base/implementation/social_system.py b/pycopancore/model_components/base/implementation/social_system.py
index b8dac8e3..bbaed494 100644
--- a/pycopancore/model_components/base/implementation/social_system.py
+++ b/pycopancore/model_components/base/implementation/social_system.py
@@ -10,9 +10,8 @@
# License: BSD 2-clause license
# only used in this component, not in others:
-from ... import abstract
-from .... import master_data_model as D
-from ....private import unknown
+from pycopancore.model_components import abstract
+from pycopancore.private._simple_expressions import unknown
from .. import interface as I
diff --git a/pycopancore/model_components/base/implementation/world.py b/pycopancore/model_components/base/implementation/world.py
index fa6851bb..6f14feaa 100644
--- a/pycopancore/model_components/base/implementation/world.py
+++ b/pycopancore/model_components/base/implementation/world.py
@@ -10,13 +10,16 @@
# License: BSD 2-clause license
# only used in this component, not in others:
-from ... import abstract
-from .... import master_data_model as D
-from ....private import unknown
+from pycopancore.private._abstract_process_taxon_mixin import \
+ _AbstractProcessTaxonMixin
+from pycopancore.data_model.ordered_set import OrderedSet
+
+from pycopancore.model_components import abstract
+from pycopancore.private._simple_expressions import unknown
from .. import interface as I
-from .... import Explicit
+from pycopancore.process_types import Explicit
class World (I.World, abstract.World):
@@ -32,7 +35,6 @@ def __init__(self,
*,
environment=None,
metabolism=None,
- culture=None,
**kwargs
):
"""Instantiate (typically the only) instance of World.
@@ -43,8 +45,6 @@ def __init__(self,
Environment acting on this World.
metabolism : obj
Metabolism acting on this World.
- culture : obj
- Culture acting on this World.
**kwargs
keyword arguments passed to super()
@@ -55,8 +55,6 @@ def __init__(self,
self.environment = environment
self._metabolism = None
self.metabolism = metabolism
- self._culture = None
- self.culture = culture
self._social_systems = set()
self._cells = set()
self._groups = set()
@@ -98,37 +96,6 @@ def metabolism(self, m):
m._worlds.add(self)
self._metabolism = m
- @property
- def culture(self):
- """Get world's culture."""
- return self._culture
-
- @culture.setter
- def culture(self, c):
- """Set world's culture."""
- if self._culture is not None:
- # first deregister from previous culture's list of worlds:
- self._culture.worlds.remove(self)
- if c is not None:
- assert isinstance(c, I.Culture), \
- "Culture must be taxon type Culture"
- c._worlds.add(self)
- self._culture = c
-
- @property
- def culture(self):
- """Get the Culture acting in this World."""
- return self._culture
-
- @culture.setter
- def culture(self, c):
- """Set the World the SocialSystem is part of."""
- if self._culture is not None:
- self._culture._worlds.remove(self)
- assert isinstance(c, I.Culture), "culture must be of taxon type Culture"
- c._worlds.add(self)
- self._culture = c
-
@property # read-only
def social_systems(self):
"""Get the set of all SocialSystems on this World."""
diff --git a/pycopancore/model_components/base/interface.py b/pycopancore/model_components/base/interface.py
index e2fb0de1..a1f1c593 100644
--- a/pycopancore/model_components/base/interface.py
+++ b/pycopancore/model_components/base/interface.py
@@ -13,13 +13,27 @@
# Contact: core@pik-potsdam.de
# License: BSD 2-clause license
-from ...private import _MixinType, unknown
-from ... import Variable, ReferenceVariable, SetVariable
-from ... import master_data_model as D
-from ...data_model.master_data_model import ENV, CUL, W, S, C
+from pycopancore.private._mixin import _MixinType
+from pycopancore.data_model.variable import Variable
+from pycopancore.data_model.reference_variable import ReferenceVariable
+from pycopancore.data_model.set_variable import SetVariable
-# model component:
+from pycopancore.data_model.unit import unity
+
+from pycopancore.data_model.master_data_model.dimensions_and_units \
+ import DimensionsAndUnits as DAU
+
+from pycopancore.data_model.master_data_model.environment \
+ import Environment as ENV
+from pycopancore.data_model.master_data_model.culture \
+ import Culture as CUL
+from pycopancore.data_model.master_data_model.world \
+ import World as W
+from pycopancore.data_model.master_data_model.social_system \
+ import SocialSystem as S
+from pycopancore.data_model.master_data_model.cell \
+ import Cell as C
class Model (object):
@@ -71,10 +85,12 @@ class Culture (object):
group_membership_network = CUL.group_membership_network
- # read-only attributes storing redundant information:
- worlds = SetVariable("worlds",
- "Set of Worlds governed by this Culture",
- readonly=True)
+ social_systems = SetVariable("social systems",
+ "Set of all SocialSystems governed by this Culture",
+ readonly=True)
+ individuals = SetVariable("individuals",
+ "Set of Individuals governed by this Culture",
+ readonly=True)
# entity types:
@@ -190,6 +206,7 @@ class SocialSystem (object, metaclass=_MixinType):
SocialSystem.higher_social_systems.type = SocialSystem
SocialSystem.next_lower_social_systems.type = SocialSystem
SocialSystem.lower_social_systems.type = SocialSystem
+Culture.social_systems.type = SocialSystem
World.social_systems.type = SocialSystem
World.top_level_social_systems.type = SocialSystem
@@ -252,7 +269,7 @@ class Individual (object, metaclass=_MixinType):
"relative representation weight for social_system's population, "
"to be used in determining how many people this individual "
"represents",
- unit=D.unity, lower_bound=0, default=1)
+ unit=unity, lower_bound=0, default=1)
# attributes storing redundant information:
world = ReferenceVariable("world", "", type=World,
@@ -288,12 +305,13 @@ class Individual (object, metaclass=_MixinType):
"represented population",
"absolute population represented by this individual",
readonly=True,
- unit=D.people,
+ unit=DAU.people,
is_extensive=True)
# specified only now to avoid recursion:
World.individuals.type = Individual
+Culture.individuals.type = Individual
SocialSystem.direct_individuals.type = Individual
SocialSystem.individuals.type = Individual
Cell.individuals.type = Individual
diff --git a/pycopancore/model_components/base/model_logics.py b/pycopancore/model_components/base/model_logics.py
index a9434aa8..fb1275c0 100644
--- a/pycopancore/model_components/base/model_logics.py
+++ b/pycopancore/model_components/base/model_logics.py
@@ -15,11 +15,18 @@
# Contact: core@pik-potsdam.de
# License: BSD 2-clause license
-from .. import abstract
-from ... import Variable, ReferenceVariable, SetVariable, \
- ODE, Explicit, Step, Event, OrderedSet
-from ...private import _AbstractProcess, unknown, _expressions, \
- _AbstractEntityMixin, _AbstractProcessTaxonMixin
+from pycopancore.model_components import abstract
+from pycopancore.data_model import Variable, ReferenceVariable, SetVariable, \
+ OrderedSet
+from pycopancore.process_types import ODE, Explicit, Step, Event
+
+from pycopancore.private._abstract_process import _AbstractProcess
+from pycopancore.private._abstract_entity_mixin import _AbstractEntityMixin
+from pycopancore.private._abstract_process_taxon_mixin \
+ import _AbstractProcessTaxonMixin
+
+from pycopancore.private._simple_expressions import unknown
+from pycopancore.private._expressions import get_vars
import gc
import inspect
import re
@@ -163,6 +170,13 @@ def configure(cls, reconfigure=False, **kwargs):
])
# iterate through all model components:
for component in cls.components:
+
+ if "entity_types" not in component.__dict__:
+ component.entity_types = []
+
+ if "process_taxa" not in component.__dict__:
+ component.process_taxa = []
+
component_interface = component.__bases__[0] # the first base class of an impl. cl. is its interface
print("Model component ", component_interface.name, "(", component,
")...")
@@ -194,6 +208,9 @@ def configure(cls, reconfigure=False, **kwargs):
"different codename."
# find and register all processes defined directly in this
# mixin's "process" attribute:
+ if "processes" not in mixin_interface.__dict__:
+ mixin.processes = []
+
for p in mixin.processes:
assert isinstance(p, _AbstractProcess), \
"The 'processes' attribute of an implementation " \
@@ -310,7 +327,7 @@ def new__init__(inst, **kwargs):
+ str(target.owning_class) \
+ str(composed_class)
if isinstance(p.specification, list):
- deps = _expressions.get_vars(p.specification[i])
+ deps = get_vars(p.specification[i])
print(" Derivative of",
target.target_variable,
"directly depends on", deps)
@@ -353,7 +370,7 @@ def new__init__(inst, **kwargs):
"reference starts at a wrong " \
"entity-type/taxon:"
if isinstance(p.specification, list):
- deps = _expressions.get_vars(p.specification[i])
+ deps = get_vars(p.specification[i])
print(" Target var.",
target.target_variable,
"directly depends on", deps)
diff --git a/pycopancore/model_components/carbon_voters/__init__.py b/pycopancore/model_components/carbon_voters/__init__.py
deleted file mode 100644
index 6852092c..00000000
--- a/pycopancore/model_components/carbon_voters/__init__.py
+++ /dev/null
@@ -1,26 +0,0 @@
-"""
-Model component package template.
-
-TODO:
-Copy this folder, rename it to the name of your model component,
-then adjust or fill in code and documentation in all modules wherever marked by "TODO:",
-finally remove these instructions.
-See the model component development tutorial for details.
-"""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-from . import interface
-
-# export all implementation classes:
-from .implementation import *
-
-# export model component mixin class:
-from .model import Model
diff --git a/pycopancore/model_components/carbon_voters/implementation/__init__.py b/pycopancore/model_components/carbon_voters/implementation/__init__.py
deleted file mode 100644
index 24d7babf..00000000
--- a/pycopancore/model_components/carbon_voters/implementation/__init__.py
+++ /dev/null
@@ -1,21 +0,0 @@
-"""
-Model component implementation subpackage template.
-"""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-# TODO: adjust the following lists to your needs:
-
-# export all provided entity type implementation mixin classes:
-from .world import World
-from .social_system import SocialSystem
-from .culture import Culture
-
-# export all provided process taxon implementation mixin classes:
diff --git a/pycopancore/model_components/carbon_voters/implementation/culture.py b/pycopancore/model_components/carbon_voters/implementation/culture.py
deleted file mode 100644
index e209ab95..00000000
--- a/pycopancore/model_components/carbon_voters/implementation/culture.py
+++ /dev/null
@@ -1,69 +0,0 @@
-"""Culture process taxon mixing class template.
-
-TODO: adjust or fill in code and documentation wherever marked by "TODO:",
-then remove these instructions
-"""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-from .. import interface as I
-# from .... import master_data_model as D
-from .... import Explicit
-import sympy as sp
-import random
-
-
-class Culture (I.Culture):
- """Culture process taxon mixin implementation class."""
-
- # standard methods:
-
- def __init__(self,
- *,
- impact_scaling_factor=5,
- no_impact_atmospheric_carbon_level=0.15,
- no_impact_opinion_change=0.5,
- **kwargs):
- """Initialize the unique instance of Culture."""
- super().__init__(**kwargs) # must be the first line
-
- self.impact_scaling_factor = impact_scaling_factor
- self.no_impact_atmospheric_carbon_level = no_impact_atmospheric_carbon_level
- self.no_impact_opinion_change = no_impact_opinion_change
-
- # process-related methods:
- def opinion_change_function(self, x, y):
- if self.impact > 0:
- _opinion_change_to_awareness = self.no_impact_opinion_change + (1 - self.no_impact_opinion_change) \
- * (1 - sp.exp(- self.impact))
- if x.opinion == 0 and y.opinion == 1:
- return random.random() < _opinion_change_to_awareness
- elif x.opinion == 1 and y.opinion == 0:
- return random.random() < (1 - _opinion_change_to_awareness)
- else:
- return random.random() < self.no_impact_opinion_change
-
- def set_opinion_change(self, t):
- self.opinion_change = \
- self.opinion_change_function
-
- processes = [
-
- Explicit(
- "atmospheric carbon impact",
- [I.Culture.impact],
- [I.Culture.impact_scaling_factor
- * (I.World.atmospheric_carbon - I.Culture.no_impact_atmospheric_carbon_level)]
- ),
-
- Explicit("set probability of opinion adoption",
- [I.Culture.opinion_change],
- set_opinion_change)
- ] # TODO: instantiate and list process objects here
diff --git a/pycopancore/model_components/carbon_voters/implementation/social_system.py b/pycopancore/model_components/carbon_voters/implementation/social_system.py
deleted file mode 100644
index 0eeeb06c..00000000
--- a/pycopancore/model_components/carbon_voters/implementation/social_system.py
+++ /dev/null
@@ -1,63 +0,0 @@
-"""SocialSystem entity type mixing class template.
-
-TODO: adjust or fill in code and documentation wherever marked by "TODO:",
-then remove these instructions
-"""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-from .. import interface as I
-from ...base import interface as B
-# from .... import master_data_model as D
-from .... import Explicit
-import sympy as sp
-
-
-class SocialSystem (I.SocialSystem):
- """SocialSystem entity type mixin implementation class."""
-
- # standard methods:
-
- def __init__(self,
- # *, # TODO: uncomment when adding named args behind here
- **kwargs):
- """Initialize an instance of SocialSystem."""
- super().__init__(**kwargs) # must be the first line
- # TODO: add custom code here:
- pass
-
- def deactivate(self):
- """Deactivate a social_system."""
- # TODO: add custom code here:
- pass
- super().deactivate() # must be the last line
-
- def reactivate(self):
- """Reactivate a social_system."""
- super().reactivate() # must be the first line
- # TODO: add custom code here:
- pass
-
- # process-related methods:
-
- def set_harvest_rate(self, t):
- if self.opinion == 0: # indifferent
- self.harvest_rate = 0.5
- else: # opinion == 1
- self.harvest_rate = 0.25
-
- processes = [
- Explicit(
- "harvest rate decision",
- [I.SocialSystem.harvest_rate],
- set_harvest_rate
- ),
-
- ] # TODO: instantiate and list process objects here
diff --git a/pycopancore/model_components/carbon_voters/implementation/world.py b/pycopancore/model_components/carbon_voters/implementation/world.py
deleted file mode 100644
index b4cd66e8..00000000
--- a/pycopancore/model_components/carbon_voters/implementation/world.py
+++ /dev/null
@@ -1,49 +0,0 @@
-"""World entity type mixing class template.
-
-TODO: adjust or fill in code and documentation wherever marked by "TODO:",
-then remove these instructions
-"""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-from .. import interface as I
-# from .... import master_data_model as D
-
-
-class World (I.World):
- """World entity type mixin implementation class."""
-
- # standard methods:
-
- def __init__(self,
- # *, # TODO: uncomment when adding named args behind here
- **kwargs):
- """Initialize an instance of World."""
- super().__init__(**kwargs) # must be the first line
- # TODO: add custom code here:
- pass
-
- def deactivate(self):
- """Deactivate a world."""
- # TODO: add custom code here:
- pass
- super().deactivate() # must be the last line
-
- def reactivate(self):
- """Reactivate a world."""
- super().reactivate() # must be the first line
- # TODO: add custom code here:
- pass
-
- # process-related methods:
-
- # TODO: add some if needed...
-
- processes = [] # TODO: instantiate and list process objects here
diff --git a/pycopancore/model_components/carbon_voters/interface.py b/pycopancore/model_components/carbon_voters/interface.py
deleted file mode 100644
index 8855de4d..00000000
--- a/pycopancore/model_components/carbon_voters/interface.py
+++ /dev/null
@@ -1,130 +0,0 @@
-"""model component Interface template.
-
-TODO: adjust or fill in code and documentation wherever marked by "TODO:", then
-remove these instructions.
-"""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-# TODO: use variables from the master data model wherever possible:
-from ... import master_data_model as D
-# TODO: uncomment and adjust of you need further variables from another
-# model component:
-# import ..BBB.interface as BBB
-from .. import adaptive_voter_opinion_formation as avof
-from .. import majority_decision as md
-from .. import anderies_carbon_cycle as cc
-# TODO: uncomment and adjust only if you really need other variables:
-from ... import Variable
-
-
-class Model (object):
- """Interface for Model mixin."""
-
- # metadata:
- name = "carbon voters"
- """a unique name for the model component"""
- description = "sets the harvest rate by majority decision and " \
- "the probability of awareness opinion adoption is dependent on atmospheric carbon"
- """some longer description"""
- requires = [avof, md, cc]
- """list of other model components required for this model component to
- make sense"""
-
- # Notes:
- # - Model does NOT define variables or parameters, only entity types
- # and process taxons do!
- # - implementation.Model lists these entity-types and process taxons
-
-# entity types:
-
-
-class World (object):
- """Interface for World mixin."""
-
- # endogenous variables:
- # TODO: use variables from the master data model wherever possible
- # wherever possible!:
- # X = D.X
- # TODO: uncomment and adjust of you need further variables from another
- atmospheric_carbon = cc.World.atmospheric_carbon
- # TODO: uncomment and adjust only if you really need other variables:
- # W = Variable("name", "desc", unit=..., ...)
-
- # exogenous variables / parameters:
- # surface_air_temperature = D.world.surface_air_temperature
-
-
-class SocialSystem (object):
- """Interface for SocialSystem entity type mixin."""
-
- # endogenous variables:
-
- # exogenous variables / parameters:
-
- opinion = md.SocialSystem.opinion
-
- harvest_rate = cc.SocialSystem.harvest_rate
-
-
-# class Cell (object):
-# """Interface for Cell entity type mixin."""
-#
-# # endogenous variables:
-#
-# # exogenous variables / parameters:
-
-
-# class Individual (object):
-# """Interface for Individual entity type mixin."""
-#
-# # endogenous variables:
-#
-# # exogenous variables / parameters:
-
-
-# process taxa:
-
-
-# class Environment (object):
-# """Interface for Environment process taxon mixin."""
-#
-# # endogenous variables:
-#
-# # exogenous variables / parameters:
-
-
-# class Metabolism (object):
-# """Interface for Metabolism process taxon mixin."""
-#
-# # endogenous variables:
-#
-# # exogenous variables / parameters:
-
-
-class Culture (object):
- """Interface for Culture process taxon mixin."""
-
- # endogenous variables:
-
- # exogenous variables / parameters:
- #
- opinion_change = avof.Culture.opinion_change
-
- impact_scaling_factor = Variable("scaling factor", "")
-
- no_impact_atmospheric_carbon_level = Variable("", "level of atmospheric carbon that doesn't change peoples "
- "probability of opinion change to awareness")
-
- no_impact_opinion_change = Variable("", "basic probability of opinion change to awareness in "
- "avof without climate impact effects") # take adaptive voter model opinion_change?
-
- impact = Variable("impact of atmospheric carbon / temperature on social_system",
- "based on atmospheric carbon level")
diff --git a/pycopancore/model_components/carbon_voters/model.py b/pycopancore/model_components/carbon_voters/model.py
deleted file mode 100644
index d582c286..00000000
--- a/pycopancore/model_components/carbon_voters/model.py
+++ /dev/null
@@ -1,31 +0,0 @@
-"""Model mixing class template.
-
-TODO: adjust or fill in code and documentation wherever marked by "TODO:",
-then remove these instructions
-"""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-from . import interface as I
-# import all needed entity type implementation classes:
-from .implementation import World, SocialSystem, Culture
-# import all needed process taxon implementation classes:
-# from .implementation import Environment, Metabolism, Culture
-
-
-class Model (I.Model):
- """Model mixin class."""
-
- # mixins provided by this model component:
-
- entity_types = [World, SocialSystem]
- """list of entity types augmented by this component"""
- process_taxa = [Culture]
- """list of process taxa augmented by this component"""
diff --git a/pycopancore/model_components/copan_global_like_carbon_cycle/__init__.py b/pycopancore/model_components/copan_global_like_carbon_cycle/__init__.py
deleted file mode 100644
index a8a236ad..00000000
--- a/pycopancore/model_components/copan_global_like_carbon_cycle/__init__.py
+++ /dev/null
@@ -1,19 +0,0 @@
-"""
-copan_global_like_carbon_cycle model component
-"""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-from . import interface
-
-from .implementation import *
-
-# export model component mixin class:
-from .model import Model
diff --git a/pycopancore/model_components/copan_global_like_carbon_cycle/implementation/__init__.py b/pycopancore/model_components/copan_global_like_carbon_cycle/implementation/__init__.py
deleted file mode 100644
index 15c21fe9..00000000
--- a/pycopancore/model_components/copan_global_like_carbon_cycle/implementation/__init__.py
+++ /dev/null
@@ -1,18 +0,0 @@
-"""
-This is the copan_global_like_carbon_cycle model-component implementation subpackage
-"""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-
-from .world import World
-from .cell import Cell
-
-from .environment import Environment
diff --git a/pycopancore/model_components/copan_global_like_carbon_cycle/implementation/cell.py b/pycopancore/model_components/copan_global_like_carbon_cycle/implementation/cell.py
deleted file mode 100644
index 699ad554..00000000
--- a/pycopancore/model_components/copan_global_like_carbon_cycle/implementation/cell.py
+++ /dev/null
@@ -1,103 +0,0 @@
-"""provides this model component's Cell mixin class"""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-
-from .... import Explicit, ODE
-from ...base import interface as B
-
-from .. import interface as I
-
-import sympy as sp # to be able to use sp.sqrt
-
-
-class Cell (I.Cell):
- """Jobst: write docstring."""
-
- # abbreviation:
-
- balance = (I.Cell.photosynthesis_carbon_flow
- - I.Cell.terrestrial_respiration_carbon_flow)
- atmospheric_carbon_density = sp.Max(0, B.Cell.world.atmospheric_carbon
- / B.Cell.world.sum.cells.land_area)
-
- processes = [ # using symbolic expressions for performance and legibility:
-
- Explicit("photosynthesis flow",
- [I.Cell.photosynthesis_carbon_flow],
- [((B.Cell.environment.basic_photosynthesis_productivity
- - B.Cell.environment.photosynthesis_sensitivity_on_atmospheric_carbon
- * atmospheric_carbon_density)
- * sp.sqrt(atmospheric_carbon_density)
- * (1 - I.Cell.terrestrial_carbon
- / (B.Cell.environment.terrestrial_carbon_capacity_per_area
- * B.Cell.land_area))
- )
- * I.Cell.terrestrial_carbon
- ]),
-
- Explicit("respiration flow",
- [I.Cell.terrestrial_respiration_carbon_flow],
- [(B.Cell.world.environment.basic_respiration_rate
- + B.Cell.world.environment.respiration_sensitivity_on_atmospheric_carbon
- * atmospheric_carbon_density)
- * I.Cell.terrestrial_carbon
- ]),
-
- ODE("effect of photosynthesis and respiration",
- [I.Cell.terrestrial_carbon,
- B.Cell.world.atmospheric_carbon],
- [balance,
- -balance]),
-
- ]
-
-# instead of:
-#
-# def do_photosynthesis(self, unused_t):
-# """compute and store rhs of ODE photosynthesis"""
-#
-# # abbreviations:
-# L = self.terrestrial_carbon
-# Sigma = self.land_area
-#
-# self.photosynthesis_carbon_flow = \
-# ((self.environment.basic_photosynthesis_productivity
-# - self.environment.photosynthesis_sensitivity_on_atmospheric_carbon
-# * self.world.atmospheric_carbon)
-# * np.sqrt(self.world.atmospheric_carbon / Sigma)
-# * (1 - L / (self.environment.terrestrial_carbon_capacity_per_area
-# * Sigma))) \
-# * L
-#
-# self.world.d_atmospheric_carbon -= self.photosynthesis_carbon_flow
-# self.d_terrestrial_carbon += self.photosynthesis_carbon_flow
-#
-# def do_respiration(self, unused_t):
-# """compute and store rhs of ODE respiration"""
-#
-# self.terrestrial_respiration_carbon_flow = \
-# (self.environment.basic_respiration_rate
-# + self.environment.respiration_sensitivity_on_atmospheric_carbon
-# * self.world.atmospheric_carbon) \
-# * self.terrestrial_carbon
-#
-# self.d_terrestrial_carbon -= self.terrestrial_respiration_carbon_flow
-# self.world.d_atmospheric_carbon += (self
-# .terrestrial_respiration_carbon_flow)
-#
-# processes = [
-# ODE("photosynthesis", [I.Cell.terrestrial_carbon,
-# B.Cell.world.atmospheric_carbon],
-# do_photosynthesis),
-# ODE("respiration", [I.Cell.terrestrial_carbon,
-# B.Cell.world.atmospheric_carbon],
-# do_respiration),
-# ]
diff --git a/pycopancore/model_components/copan_global_like_carbon_cycle/implementation/environment.py b/pycopancore/model_components/copan_global_like_carbon_cycle/implementation/environment.py
deleted file mode 100644
index e681dbd9..00000000
--- a/pycopancore/model_components/copan_global_like_carbon_cycle/implementation/environment.py
+++ /dev/null
@@ -1,17 +0,0 @@
-"""provides this model component's Environment mixin class"""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# License: MIT license
-
-from .. import interface as I
-
-
-class Environment (I.Environment):
- """Environment process taxon mixin implementation class."""
-
- processes = []
diff --git a/pycopancore/model_components/copan_global_like_carbon_cycle/implementation/world.py b/pycopancore/model_components/copan_global_like_carbon_cycle/implementation/world.py
deleted file mode 100644
index 5db56dd5..00000000
--- a/pycopancore/model_components/copan_global_like_carbon_cycle/implementation/world.py
+++ /dev/null
@@ -1,44 +0,0 @@
-"""provides this model component's World mixin class"""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-from .... import Explicit, ODE
-from .. import interface as I
-from ...base import interface as B
-from .... import master_data_model as D
-
-
-class World (I.World):
- """World with ocean-atmosphere diffusion
- and linear relationship between temperature and atmospheric carbon
- """
-
- # abbreviation:
- diffusion_flow = (B.World.environment.ocean_atmosphere_diffusion_coefficient
- * (I.World.upper_ocean_carbon
- - B.World.environment.carbon_solubility_in_sea_water
- * I.World.atmospheric_carbon))
- """(See Nitzbon et al. 2017)."""
-
- processes = [
-
- Explicit("immediate greenhouse effect",
- [I.World.surface_air_temperature],
- [B.World.environment.reference_temperature
- + B.World.environment.temperature_sensitivity_on_atmospheric_carbon
- * (I.World.atmospheric_carbon
- - B.World.environment.reference_atmospheric_carbon)]),
-
- ODE("ocean-atmosphere diffusion",
- [I.World.upper_ocean_carbon, I.World.atmospheric_carbon],
- [-diffusion_flow, diffusion_flow]
- )
-
- ]
diff --git a/pycopancore/model_components/copan_global_like_carbon_cycle/interface.py b/pycopancore/model_components/copan_global_like_carbon_cycle/interface.py
deleted file mode 100644
index 3cf7a570..00000000
--- a/pycopancore/model_components/copan_global_like_carbon_cycle/interface.py
+++ /dev/null
@@ -1,110 +0,0 @@
-"""copan_global_like_carbon_cycle model component Interface."""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-from ... import master_data_model as D
-from ...data_model.master_data_model import ENV, W, C
-from ... import Variable
-
-
-class Model (object):
- """Interface for Model mixin."""
-
- # metadata:
- name = "copan:GLOBAL-like carbon cycle"
- """a unique name for the model component"""
- description = "Simple carbon cycle as in copan:GLOBAL, " \
- "but with cell-based terrestrial and fossil carbon"
- """some longer description"""
- requires = []
- """list of other model components required for this model component to
- make sense"""
-
-
-# entity types:
-
-
-class World (object):
- """Interface for World mixin."""
-
- # variables:
- atmospheric_carbon = W.atmospheric_carbon
- upper_ocean_carbon = W.upper_ocean_carbon
- surface_air_temperature = W.surface_air_temperature
-
-
-class Cell (object):
- """Interface for Cell mixin."""
-
- # variables:
-
- land_area = C.land_area
- land_area.default = 1 * D.square_kilometers
-
- terrestrial_carbon = C.terrestrial_carbon
- terrestrial_carbon.default = 1 * D.gigatonnes_carbon
-
- photosynthesis_carbon_flow = C.photosynthesis_carbon_flow
- terrestrial_respiration_carbon_flow = \
- C.terrestrial_respiration_carbon_flow
-
-# process taxa:
-
-
-class Environment (object):
- """Interface for Environment mixin."""
-
- # parameters / exogenous variables / read-only:
-
- ocean_atmosphere_diffusion_coefficient = \
- ENV.ocean_atmosphere_diffusion_coefficient
- carbon_solubility_in_sea_water = ENV.carbon_solubility_in_sea_water
-
- basic_photosynthesis_productivity = \
- Variable("basic photosynthesis productivity", "",
- unit = D.years**-1
- / (D.gigatonnes_carbon / D.square_kilometers)**0.5,
- lower_bound=0,
- default=34) # higher than 26.4 due to non-infinity capacity
- photosynthesis_sensitivity_on_atmospheric_carbon = \
- Variable("sensitivity of photosynthesis productivity on atmospheric "
- "carbon density", "",
- unit = D.years**-1
- / (D.gigatonnes_carbon / D.square_kilometers)**0.5
- / (D.gigatonnes_carbon / D.square_kilometers),
- default=1.1e6)
- terrestrial_carbon_capacity_per_area = \
- Variable("per-area capacity of terrestrial carbon", "",
- unit = D.gigatonnes_carbon / D.square_kilometers,
- lower_bound=0, default = 10 * 2500 / 1.5e8)
- # ca. 10 times current value. TODO: improve default
-
- basic_respiration_rate = Variable("basic respiration rate", "",
- unit=D.years**-1, default=.0298)
- respiration_sensitivity_on_atmospheric_carbon = \
- Variable("sensitivity of respiration rate on atmospheric carbon", "",
- unit = D.years**-1
- / (D.gigatonnes_carbon / D.square_kilometers),
- default=3.2e3)
-
- reference_temperature = \
- Variable("reference temperature for relationship with atmospheric carbon",
- "default: pre-industrial value",
- unit=D.kelvins, lower_bound=0,
- default=287) # TODO: verify!
- reference_atmospheric_carbon = \
- Variable("reference atmospheric carbon for relationship with temperature",
- "default: pre-industrial value",
- unit=D.gigatonnes_carbon, lower_bound=0,
- default=589)
- temperature_sensitivity_on_atmospheric_carbon = \
- Variable("sensitivity of temperature on atmospheric carbon", "",
- unit = D.kelvins / D.gigatonnes_carbon, lower_bound=0,
- default = 1.5 / 1000)
diff --git a/pycopancore/model_components/copan_global_like_carbon_cycle/model.py b/pycopancore/model_components/copan_global_like_carbon_cycle/model.py
deleted file mode 100644
index 4f1e7395..00000000
--- a/pycopancore/model_components/copan_global_like_carbon_cycle/model.py
+++ /dev/null
@@ -1,25 +0,0 @@
-"""copan_global_like_carbon_cycle model mixing class."""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-from . import interface as I
-# import all needed entity type implementation classes:
-from .implementation import World, Cell
-# import all needed process taxon implementation classes:
-from .implementation import Environment
-
-
-class Model (I.Model):
- """Model component mixin class."""
-
- # mixins provided by this model component:
-
- entity_types = [World, Cell]
- process_taxa = [Environment]
diff --git a/pycopancore/model_components/copan_global_like_economic_growth/__init__.py b/pycopancore/model_components/copan_global_like_economic_growth/__init__.py
deleted file mode 100644
index c59080ec..00000000
--- a/pycopancore/model_components/copan_global_like_economic_growth/__init__.py
+++ /dev/null
@@ -1,20 +0,0 @@
-"""
-copan_global_like_economic_growth model component package.
-"""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-from . import interface
-
-# export all implementation classes:
-from .implementation import *
-
-# export model component mixin class:
-from .model import Model
diff --git a/pycopancore/model_components/copan_global_like_economic_growth/implementation/__init__.py b/pycopancore/model_components/copan_global_like_economic_growth/implementation/__init__.py
deleted file mode 100644
index 5f05fc41..00000000
--- a/pycopancore/model_components/copan_global_like_economic_growth/implementation/__init__.py
+++ /dev/null
@@ -1,18 +0,0 @@
-"""
-Model component implementation subpackage.
-"""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-from .metabolism import Metabolism
-
-# export all provided entity type implementation mixin classes:
-from .social_system import SocialSystem
-from .world import World
diff --git a/pycopancore/model_components/copan_global_like_economic_growth/implementation/metabolism.py b/pycopancore/model_components/copan_global_like_economic_growth/implementation/metabolism.py
deleted file mode 100644
index de4443f3..00000000
--- a/pycopancore/model_components/copan_global_like_economic_growth/implementation/metabolism.py
+++ /dev/null
@@ -1,18 +0,0 @@
-"""provides this model component' Metabolism mixin class"""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-from .. import interface as I
-
-
-class Metabolism (I.Metabolism):
- """Metabolism process taxon mixin implementation class."""
-
- processes = []
diff --git a/pycopancore/model_components/copan_global_like_economic_growth/implementation/social_system.py b/pycopancore/model_components/copan_global_like_economic_growth/implementation/social_system.py
deleted file mode 100644
index 97cd419f..00000000
--- a/pycopancore/model_components/copan_global_like_economic_growth/implementation/social_system.py
+++ /dev/null
@@ -1,50 +0,0 @@
-"""provides this model component's SocialSystem mixin class"""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-from .. import interface as I
-from .... import Explicit, ODE
-from ...base import interface as B
-
-
-class SocialSystem (I.SocialSystem):
- """SocialSystem entity type mixin implementation class."""
-
- processes = [
-
- Explicit("investment",
- [I.SocialSystem.investment_flow,
- I.SocialSystem.consumption_flow],
- [I.SocialSystem.savings_rate * I.SocialSystem.economic_output_flow,
- (1 - I.SocialSystem.savings_rate) * I.SocialSystem.economic_output_flow]
- ),
-
- Explicit("capital depreciation rate",
- [I.SocialSystem.physical_capital_depreciation_rate],
- [I.SocialSystem.basic_physical_capital_depreciation_rate
- + I.SocialSystem.physical_capital_depreciation_rate_temperature_sensitivity
- * (B.SocialSystem.world.surface_air_temperature
- - I.SocialSystem.physical_capital_depreciation_rate_reference_temperature)]
- ),
-
- ODE("growth, spillovers, depreciation",
- [I.SocialSystem.physical_capital,
- I.SocialSystem.renewable_energy_knowledge],
- [I.SocialSystem.investment_flow
- - I.SocialSystem.physical_capital_depreciation_rate
- * I.SocialSystem.physical_capital,
- I.SocialSystem.renewable_energy_input_flow
- + B.SocialSystem.metabolism.renewable_energy_knowledge_spillover_fraction
- * (B.SocialSystem.world.renewable_energy_input_flow
- - I.SocialSystem.renewable_energy_input_flow)
- - I.SocialSystem.renewable_energy_knowledge_depreciation_rate
- * I.SocialSystem.renewable_energy_knowledge])
-
- ]
diff --git a/pycopancore/model_components/copan_global_like_economic_growth/implementation/world.py b/pycopancore/model_components/copan_global_like_economic_growth/implementation/world.py
deleted file mode 100644
index 8161a9f0..00000000
--- a/pycopancore/model_components/copan_global_like_economic_growth/implementation/world.py
+++ /dev/null
@@ -1,26 +0,0 @@
-"""provides this model component's World mixin class"""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-from .... import Explicit
-from .. import interface as I
-from ...base import interface as B
-
-
-class World (I.World):
- """
- """
-
- processes = [
-
- Explicit("aggregate flows",
- [I.World.renewable_energy_input_flow],
- [B.World.sum.social_systems.renewable_energy_input_flow]),
- ]
diff --git a/pycopancore/model_components/copan_global_like_economic_growth/interface.py b/pycopancore/model_components/copan_global_like_economic_growth/interface.py
deleted file mode 100644
index c5d495d2..00000000
--- a/pycopancore/model_components/copan_global_like_economic_growth/interface.py
+++ /dev/null
@@ -1,83 +0,0 @@
-"""model component Interface."""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-from ... import master_data_model as D
-from ...data_model.master_data_model import MET, S, W
-
-
-class Model (object):
- """Interface for Model mixin."""
-
- # metadata:
- name = "copan:GLOBAL-like economic growth"
- """a unique name for the model component"""
- description = """capital investments at fixed savings rate,
- learning-by-doing in renewable energy sector"""
- """some longer description"""
- requires = []
- """list of other model components required for this model component to
- make sense"""
-
- # Notes:
- # - Model does NOT define variables or parameters, only entity types
- # and process taxons do!
- # - implementation.Model lists these entity-types and process taxons
-
-
-class Metabolism (object):
- """Interface for Metabolism process taxon mixin."""
-
- renewable_energy_knowledge_spillover_fraction = \
- MET.renewable_energy_knowledge_spillover_fraction
-
-
-# entity types:
-
-
-class World (object):
- """Interface for World entity type mixin."""
-
- renewable_energy_input_flow = W.renewable_energy_input_flow
-
-
-class SocialSystem (object):
- """Interface for SocialSystem entity type mixin."""
-
- # endogenous variables:
-
- physical_capital = S.physical_capital
- physical_capital.default = 1 * D.dollars
-
- renewable_energy_knowledge = S.renewable_energy_knowledge
- renewable_energy_knowledge.default = 1 * D.gigajoules
-
- physical_capital_depreciation_rate = S.physical_capital_depreciation_rate
-
- # output-only variables:
-
- investment_flow = S.investment_flow
- consumption_flow = S.consumption_flow
-
- # exogenous variables / parameters:
-
- economic_output_flow = S.economic_output_flow
- renewable_energy_input_flow = S.renewable_energy_input_flow
-
- savings_rate = S.savings_rate
- basic_physical_capital_depreciation_rate = \
- S.basic_physical_capital_depreciation_rate
- physical_capital_depreciation_rate_temperature_sensitivity = \
- S.physical_capital_depreciation_rate_temperature_sensitivity
- physical_capital_depreciation_rate_reference_temperature = \
- S.physical_capital_depreciation_rate_reference_temperature
- renewable_energy_knowledge_depreciation_rate = \
- S.renewable_energy_knowledge_depreciation_rate
-
\ No newline at end of file
diff --git a/pycopancore/model_components/copan_global_like_economic_growth/model.py b/pycopancore/model_components/copan_global_like_economic_growth/model.py
deleted file mode 100644
index ae46394b..00000000
--- a/pycopancore/model_components/copan_global_like_economic_growth/model.py
+++ /dev/null
@@ -1,23 +0,0 @@
-"""Model mixing class."""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-from . import interface as I
-# import all needed entity type implementation classes:
-from .implementation import Metabolism, SocialSystem, World
-
-
-class Model (I.Model):
- """Model mixin class."""
-
- # mixins provided by this model component:
-
- entity_types = [SocialSystem, World]
- process_taxa = [Metabolism]
diff --git a/pycopancore/model_components/copan_global_like_population_growth/__init__.py b/pycopancore/model_components/copan_global_like_population_growth/__init__.py
deleted file mode 100644
index 6852092c..00000000
--- a/pycopancore/model_components/copan_global_like_population_growth/__init__.py
+++ /dev/null
@@ -1,26 +0,0 @@
-"""
-Model component package template.
-
-TODO:
-Copy this folder, rename it to the name of your model component,
-then adjust or fill in code and documentation in all modules wherever marked by "TODO:",
-finally remove these instructions.
-See the model component development tutorial for details.
-"""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-from . import interface
-
-# export all implementation classes:
-from .implementation import *
-
-# export model component mixin class:
-from .model import Model
diff --git a/pycopancore/model_components/copan_global_like_population_growth/implementation/__init__.py b/pycopancore/model_components/copan_global_like_population_growth/implementation/__init__.py
deleted file mode 100644
index b7d4aa4c..00000000
--- a/pycopancore/model_components/copan_global_like_population_growth/implementation/__init__.py
+++ /dev/null
@@ -1,20 +0,0 @@
-"""
-Model component implementation subpackage template.
-"""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-# TODO: adjust the following lists to your needs:
-
-# export all provided entity type implementation mixin classes:
-from .social_system import SocialSystem
-
-# export all provided process taxon implementation mixin classes:
-from .metabolism import Metabolism
diff --git a/pycopancore/model_components/copan_global_like_population_growth/implementation/metabolism.py b/pycopancore/model_components/copan_global_like_population_growth/implementation/metabolism.py
deleted file mode 100644
index de4443f3..00000000
--- a/pycopancore/model_components/copan_global_like_population_growth/implementation/metabolism.py
+++ /dev/null
@@ -1,18 +0,0 @@
-"""provides this model component' Metabolism mixin class"""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-from .. import interface as I
-
-
-class Metabolism (I.Metabolism):
- """Metabolism process taxon mixin implementation class."""
-
- processes = []
diff --git a/pycopancore/model_components/copan_global_like_population_growth/implementation/social_system.py b/pycopancore/model_components/copan_global_like_population_growth/implementation/social_system.py
deleted file mode 100644
index 8f4ee6b1..00000000
--- a/pycopancore/model_components/copan_global_like_population_growth/implementation/social_system.py
+++ /dev/null
@@ -1,87 +0,0 @@
-"""SocialSystem entity type mixing class template.
-
-TODO: adjust or fill in code and documentation wherever marked by "TODO:",
-then remove these instructions
-"""
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-from .... import Explicit, ODE
-from ...base import interface as B
-from .... import master_data_model as D
-
-from .. import interface as I
-
-import sympy as sp # to be able to use sp.sqrt
-
-
-# TODO: move this to a suitable place (like pycopancore.util?):
-def sqrtorzero(expr):
- """square root if positive, zero otherwise.
- needed since ODE solver may pass negative values in Jacobian estimation"""
- return sp.sqrt(sp.Max(0, expr))
-
-
-class SocialSystem (I.SocialSystem):
- """SocialSystem entity type mixin implementation class."""
-
- # abbreviations:
- land_area = B.SocialSystem.sum.cells.land_area
- terrestrial_carbon = B.SocialSystem.sum.cells.terrestrial_carbon
- min_fert = B.SocialSystem.metabolism.min_fertility
- fert_exp = B.SocialSystem.metabolism.fertility_decay_exponent
-
- pop = I.SocialSystem.population
-
- fert = (min_fert
- + 2 * (B.SocialSystem.metabolism.max_fertility - min_fert)
- * I.SocialSystem.wellbeing
- * B.SocialSystem.metabolism.fertility_maximizing_wellbeing
- ** fert_exp
- / (I.SocialSystem.wellbeing ** (1 + fert_exp)
- + B.SocialSystem.metabolism.fertility_maximizing_wellbeing
- ** (1 + fert_exp)
- )
- )
-
- mort = (B.SocialSystem.metabolism.characteristic_mortality
- / (I.SocialSystem.wellbeing
- / B.SocialSystem.metabolism.fertility_maximizing_wellbeing)
- ** B.SocialSystem.metabolism.mortality_decay_exponent
- + I.SocialSystem.mortality_temperature_sensitivity
- * (B.SocialSystem.world.surface_air_temperature
- - I.SocialSystem.mortality_reference_temperature)
- + B.SocialSystem.metabolism.population_spatial_competition_coefficient
- * (I.SocialSystem.population / land_area)
- / sp.sqrt(I.SocialSystem.physical_capital))
-
- processes = [
-
- Explicit("wellbeing, fertility, mortality, births, deaths",
- [I.SocialSystem.wellbeing,
- I.SocialSystem.fertility,
- I.SocialSystem.mortality,
- I.SocialSystem.births,
- I.SocialSystem.deaths],
- [B.SocialSystem.metabolism.wellbeing_sensitivity_to_consumption
- * I.SocialSystem.consumption_flow / pop
- + B.SocialSystem.metabolism.wellbeing_sensitivity_to_terrestrial_carbon
- * terrestrial_carbon / land_area,
- fert,
- mort,
- pop * fert,
- pop * mort]),
-
- ODE("population dynamics",
- [pop,
- I.SocialSystem.migrant_population],
- [I.SocialSystem.births - I.SocialSystem.deaths,
- - I.SocialSystem.deaths * I.SocialSystem.migrant_population / pop])
-
- ]
diff --git a/pycopancore/model_components/copan_global_like_population_growth/interface.py b/pycopancore/model_components/copan_global_like_population_growth/interface.py
deleted file mode 100644
index 14a35cbb..00000000
--- a/pycopancore/model_components/copan_global_like_population_growth/interface.py
+++ /dev/null
@@ -1,121 +0,0 @@
-"""model component Interface template.
-"""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-# TODO: use variables from the master data model wherever possible:
-from ... import master_data_model as D
-from ...data_model.master_data_model import MET, S
-from ... import Variable
-
-
-class Model (object):
- """Interface for Model mixin."""
-
- # metadata:
- name = "copan:GLOBAL-like population growth"
- """a unique name for the model component"""
- description = "fertility and mortality act on SocialSystem level and depend on well-being"
- """some longer description"""
- requires = []
- """list of other model components required for this model component to
- make sense"""
-
- # Notes:
- # - Model does NOT define variables or parameters, only entity types
- # and process taxons do!
- # - implementation.Model lists these entity-types and process taxons
-
-
-# entity types:
-
-
-class SocialSystem (object):
- """Interface for SocialSystem entity type mixin."""
-
- # endogenous variables:
-
- population = S.population
- population.default = 1 * D.people
-
- migrant_population = S.migrant_population
-
- wellbeing = S.wellbeing
- wellbeing.default = 1 * D.utils / D.people / D.years
-
- fertility = S.fertility
- mortality = S.mortality
- mortality_temperature_sensitivity = S.mortality_temperature_sensitivity
- mortality_reference_temperature = S.mortality_reference_temperature
-
- births = S.births
- deaths = S.deaths
-
- # exogenous variables / parameters:
-
- physical_capital = S.physical_capital
- consumption_flow = S.consumption_flow
-
-
-# process taxa:
-
-
-class Metabolism (object):
- """Interface for Metabolism process taxon mixin."""
-
- # endogenous variables:
-
- # exogenous variables / parameters:
- min_fertility = MET.min_fertility
- max_fertility = MET.max_fertility
- fertility_maximizing_wellbeing = Variable(
- "fertility-maximizing value of well-being",
- "",
- unit = D.utils / D.people / D.years,
- lower_bound=0, is_intensive=True,
- default=2000)
- fertility_decay_exponent = Variable(
- "exponent of power-law shaped asymptotic decay of fertility "
- "for large wellbeing", "",
- unit = D.unity,
- strict_lower_bound=0, is_intensive=True,
- default=1/2)
- characteristic_mortality = Variable(
- "characteristic mortality rate",
- "mortality rate at fertility-maximizing value of well-being",
- unit = D.years**-1,
- lower_bound=0, is_intensive=True,
- default=0.02)
- mortality_decay_exponent = Variable(
- "exponent of power-law shaped asymptotic decay of mortality "
- "for large wellbeing", "",
- unit = D.unity,
- strict_lower_bound=0, is_intensive=True,
- default=1/12)
-# renewable_energy_knowledge_depreciation_rate = \
-# MET.renewable_energy_knowledge_depreciation_rate
- population_spatial_competition_coefficient = Variable(
- "coeff. of spatial competition in population dynamics",
- "causes a capital- and well-being-dependent per-area population limit",
- unit = D.dollars**0.5 / (D.people / D.square_kilometers) / D.years,
- lower_bound=0, is_intensive=True,
- default=0 # TODO: set properly
- )
- wellbeing_sensitivity_to_consumption = Variable(
- "sensitivity of wellbeing to per capita consumption flow", "",
- is_intensive=True, allow_None=False,
- default = 1 * D.utils / D.dollars)
- wellbeing_sensitivity_to_terrestrial_carbon = Variable(
- "sensitivity of wellbeing to terrestrial carbon density", "",
- unit = (D.utils/D.people/D.years)
- / (D.gigatonnes_carbon/D.square_kilometers),
- is_intensive=True, allow_None=False,
- default = 1e-8 * (2000*D.utils / D.people / D.years)
- / (5500*D.gigatonnes_carbon / (1.5e8*D.square_kilometers)))
diff --git a/pycopancore/model_components/copan_global_like_population_growth/model.py b/pycopancore/model_components/copan_global_like_population_growth/model.py
deleted file mode 100644
index 8b28535f..00000000
--- a/pycopancore/model_components/copan_global_like_population_growth/model.py
+++ /dev/null
@@ -1,31 +0,0 @@
-"""Model mixing class template.
-
-TODO: adjust or fill in code and documentation wherever marked by "TODO:",
-then remove these instructions
-"""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-from . import interface as I
-# import all needed entity type implementation classes:
-from .implementation import SocialSystem
-# import all needed process taxon implementation classes:
-from .implementation import Metabolism
-
-
-class Model (I.Model):
- """Model mixin class."""
-
- # mixins provided by this model component:
-
- entity_types = [SocialSystem]
- """list of entity types augmented by this component"""
- process_taxa = [Metabolism]
- """list of process taxa augmented by this component"""
diff --git a/pycopancore/model_components/copan_global_like_production/__init__.py b/pycopancore/model_components/copan_global_like_production/__init__.py
deleted file mode 100644
index 80076629..00000000
--- a/pycopancore/model_components/copan_global_like_production/__init__.py
+++ /dev/null
@@ -1,20 +0,0 @@
-"""
-copan_global_like_economy model component
-"""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-from . import interface
-
-# export all implementation classes:
-from .implementation import *
-
-# export model component mixin class:
-from .model import Model
diff --git a/pycopancore/model_components/copan_global_like_production/implementation/__init__.py b/pycopancore/model_components/copan_global_like_production/implementation/__init__.py
deleted file mode 100644
index aad5cd43..00000000
--- a/pycopancore/model_components/copan_global_like_production/implementation/__init__.py
+++ /dev/null
@@ -1,22 +0,0 @@
-"""
-Model component implementation subpackage template.
-"""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-# TODO: adjust the following lists to your needs:
-
-# export all provided entity type implementation mixin classes:
-from .world import World
-from .social_system import SocialSystem
-from .cell import Cell
-
-# export all provided process taxon implementation mixin classes:
-from .metabolism import Metabolism
diff --git a/pycopancore/model_components/copan_global_like_production/implementation/cell.py b/pycopancore/model_components/copan_global_like_production/implementation/cell.py
deleted file mode 100644
index 261ecc8b..00000000
--- a/pycopancore/model_components/copan_global_like_production/implementation/cell.py
+++ /dev/null
@@ -1,86 +0,0 @@
-"""Cell entity type mixing class template."""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-from .... import Explicit, ITE
-from .... import master_data_model as D
-from .. import interface as I
-from ...base import interface as B
-from sympy import Min, Max
-
-
-# import numpy as np
-
-
-class Cell (I.Cell):
- """Cell entity type mixin implementation class."""
-
- # TODO: allocate protected stock more adequately than this:
- quotient = (B.Cell.social_system.protected_terrestrial_carbon
- / B.Cell.social_system.sum.cells.terrestrial_carbon)
-
- unprotected_terrestrial_carbon_squared = ITE(quotient < 1,
- (I.Cell.terrestrial_carbon * (1 - quotient))**2,
- 0) #Min(1, quotient)
-
- processes = [
-
- Explicit("sectoral relative productivities",
- [I.Cell.biomass_relative_productivity,
- I.Cell.fossil_relative_productivity,
- I.Cell.renewable_relative_productivity],
- [
- I.Cell.biomass_sector_productivity
- # TODO: verify the following:
- * ITE(B.Cell.social_system.has_emissions_tax > 0,
- # FIXME: clarify why it does not work without the "> 0" above
- ITE(quotient < 1,
- (I.Cell.terrestrial_carbon * (1 - quotient))**2
- * (1
- - B.Cell.social_system.emissions_tax_level
- * I.Cell.total_energy_intensity
- / B.Cell.metabolism.biomass_energy_density),
- 0),
- unprotected_terrestrial_carbon_squared),
- ITE(B.Cell.social_system.has_fossil_ban > 0,
- 0,
- I.Cell.fossil_sector_productivity
- # TODO: verify the following:
- * ITE(B.Cell.social_system.has_emissions_tax > 0,
- (I.Cell.fossil_carbon
- * (1 - B.Cell.social_system.protected_fossil_carbon_share)
- )**2 * (
- 1
- - B.Cell.social_system.emissions_tax_level
- * I.Cell.total_energy_intensity
- / B.Cell.metabolism.fossil_energy_density),
- (I.Cell.fossil_carbon
- * (1 - B.Cell.social_system.protected_fossil_carbon_share)
- )**2)
- ),
- I.Cell.renewable_sector_productivity
- # TODO: verify the following:
- * ITE(B.Cell.social_system.has_renewable_subsidy > 0,
- (B.Cell.social_system.renewable_energy_knowledge)**2 * (
- 1
- + B.Cell.social_system.renewable_subsidy_level
- * I.Cell.total_energy_intensity),
- (B.Cell.social_system.renewable_energy_knowledge)**2)
- ]),
-
- Explicit("total relative productivity",
- [I.Cell.total_relative_productivity],
- [
- Max(0, I.Cell.biomass_relative_productivity)
- + Max(0, I.Cell.fossil_relative_productivity)
- + Max(0, I.Cell.renewable_relative_productivity)
- ])
-
- ]
diff --git a/pycopancore/model_components/copan_global_like_production/implementation/metabolism.py b/pycopancore/model_components/copan_global_like_production/implementation/metabolism.py
deleted file mode 100644
index 14a41271..00000000
--- a/pycopancore/model_components/copan_global_like_production/implementation/metabolism.py
+++ /dev/null
@@ -1,20 +0,0 @@
-"""Metabolism process taxon mixin class."""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-from .. import interface as I
-
-
-class Metabolism (I.Metabolism):
- """Metabolism process taxon mixin implementation class."""
-
- # standard methods:
-
- processes = []
diff --git a/pycopancore/model_components/copan_global_like_production/implementation/social_system.py b/pycopancore/model_components/copan_global_like_production/implementation/social_system.py
deleted file mode 100644
index fee3a191..00000000
--- a/pycopancore/model_components/copan_global_like_production/implementation/social_system.py
+++ /dev/null
@@ -1,177 +0,0 @@
-"""SocialSystem entity type mixing class template.
-
-TODO: adjust or fill in code and documentation wherever marked by "TODO:",
-then remove these instructions
-"""
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-from .... import Explicit, ODE
-from .. import interface as I
-from ...base import interface as B
-
-import numpy as np
-
-
-class SocialSystem (I.SocialSystem):
- """SocialSystem entity type mixin implementation class."""
-
-
- # process-related methods:
-
- def do_economic_production(self, unused_t):
- """Do something.
-
- It needs to be described so other people want to use it.
- Parameters
- ----------
- unused_t
- """
- # list of cells in some fixed order, so that we can use arrays below:
- C = list(self.cells)
- # collect cellwise input for energy subsectors:
- intensity = np.array([c.total_energy_intensity for c in C])
- # use the copan:GLOBAL Leontieff/Cobb-Douglas nested production
- # function:
- relative_productivity = np.array([c.total_relative_productivity
- for c in C])
- """an aggregate, production-function specific indicator"""
- # distribute population and capital to cells so that wages and rents
- # are equal across cells (efficient allocation):
- if np.any(relative_productivity == np.inf):
- # give equal prod. to those with inf relative prod.:
- wh = np.where(relative_productivity < np.inf)[0]
- relative_productivity[:] = 1
- relative_productivity[wh] = 0
- relative_weight = relative_productivity
- total_relative_weight = sum(relative_weight)
- else:
- relative_weight = relative_productivity
- total_relative_weight = sum(relative_weight)
- if total_relative_weight == 0:
- # unimportant since relative_weight == 0, just to avoid division error:
- total_relative_weight = 1
- weight = relative_weight / total_relative_weight
- P = weight * self.population
- K = weight * self.physical_capital
- # resulting cell-wise harvest, extraction and production:
- denom = relative_productivity**0.8
- # unimportant since numerator is then 0, just to avoid division error:
- denom[np.where(denom == 0)] = 1
- fac = (P * K)**0.4 / denom
- if any(np.isnan(fac)):
- w = np.where(np.isnan(fac))[0]
-# print("fac",self.physical_capital,P[w],K[w],weight[w],relative_productivity[w],intensity[w])
- exit()
- eB = self.metabolism.biomass_energy_density
- eF = self.metabolism.fossil_energy_density
- # TODO: FIX occurrence of intensity:
- B = np.array([max(0, c.biomass_relative_productivity) for c in C]) * fac / eB
- F = np.array([max(0, c.fossil_relative_productivity) for c in C]) * fac / eF
- R = np.array([max(0, c.renewable_relative_productivity) for c in C]) * fac
- E = eB * B + eF * F + R
- Y = E / intensity
- if any(Y < 0):
- w = np.where(np.isnan(fac))[0]
-# print("Y",P[w],K[w],weight[w],relative_productivity[w],intensity[w],E[w])
- exit()
-
- # tell cells what their harvest and extraction is:
- for i in range(len(C)):
- C[i].biomass_harvest_flow = B[i]
- C[i].fossil_extraction_flow = F[i]
- # store social_systems' total harvest and extraction, emissions,
- # and production:
- self.biomass_input_flow = sum(B)
- self.fossil_fuel_input_flow = sum(F)
- self.renewable_energy_input_flow = sum(R)
- self.secondary_energy_flow = sum(E)
- self.economic_output_flow = sum(Y)
- self.carbon_emission_flow = \
- self.biomass_input_flow + self.fossil_fuel_input_flow
-
- def do_harvest_extraction_emissions(self, unused_t):
- """Add carbon emission flow to world's athmospheric carbon.
-
- Parameters
- ----------
- unused_t
- """
- # this is an example of a process that is owned by SocialSystem
- # but affects its cells and the world:
- for c in self.cells:
- c.d_terrestrial_carbon -= c.biomass_harvest_flow
- c.d_fossil_carbon -= c.fossil_extraction_flow
- self.world.d_atmospheric_carbon += self.carbon_emission_flow
-
-
- # abbreviations:
-
- this = I.SocialSystem
- met = B.SocialSystem.metabolism
- cs = B.SocialSystem.cells
- # distribute population and capital to cells so that wages and rents
- # are equal across cells (efficient allocation):
- relative_weight = cs.total_relative_productivity
- total_relative_weight = B.SocialSystem.sum(relative_weight)
- weight = relative_weight / total_relative_weight
- P = weight * this.population
- K = weight * this.physical_capital
- # resulting cell-wise harvest, extraction and production:
- intensity = cs.total_energy_intensity
- denom = (cs.total_relative_productivity * intensity)**0.8
- fac = (P * K)**0.4 / denom
- eB = met.biomass_energy_density
- eF = met.fossil_energy_density
- Bcell = cs.biomass_relative_productivity * fac / eB
- Fcell = cs.fossil_relative_productivity * fac / eF
- Rcell = cs.renewable_relative_productivity * fac
- Ecell = eB * Bcell + eF * Fcell + Rcell
- Ycell = Ecell / intensity
- # societal aggregates:
- Bsoc = B.SocialSystem.sum(Bcell)
- Fsoc = B.SocialSystem.sum(Fcell)
- Rsoc = B.SocialSystem.sum(Rcell)
- Esoc = B.SocialSystem.sum(Ecell)
- Ysoc = B.SocialSystem.sum(Ycell)
- emissions = Bsoc + Fsoc
-
- processes = [
-
- Explicit("economic production",
- [B.SocialSystem.cells.biomass_harvest_flow,
- B.SocialSystem.cells.fossil_extraction_flow,
- I.SocialSystem.biomass_input_flow,
- I.SocialSystem.fossil_fuel_input_flow,
- I.SocialSystem.renewable_energy_input_flow,
- I.SocialSystem.secondary_energy_flow,
- I.SocialSystem.economic_output_flow,
- I.SocialSystem.carbon_emission_flow],
-# [Bcell,
-# Fcell,
-# Bsoc,
-# Fsoc,
-# Rsoc,
-# Esoc,
-# Ysoc,
-# emissions
-# ]),
- do_economic_production),
-
- ODE("harvest, extraction, emissions",
- [B.SocialSystem.cells.terrestrial_carbon,
- B.SocialSystem.cells.fossil_carbon,
- B.SocialSystem.world.atmospheric_carbon],
-# [-Bcell,
-# -Fcell,
-# emissions
-# ])
- do_harvest_extraction_emissions)
-
- ]
diff --git a/pycopancore/model_components/copan_global_like_production/implementation/world.py b/pycopancore/model_components/copan_global_like_production/implementation/world.py
deleted file mode 100644
index 7960a530..00000000
--- a/pycopancore/model_components/copan_global_like_production/implementation/world.py
+++ /dev/null
@@ -1,21 +0,0 @@
-"""World entity type mixing class template.
-
-TODO: adjust or fill in code and documentation wherever marked by "TODO:",
-then remove these instructions
-"""
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-from .. import interface as I
-
-
-class World (I.World):
- """World entity type mixin implementation class."""
-
- processes = []
\ No newline at end of file
diff --git a/pycopancore/model_components/copan_global_like_production/interface.py b/pycopancore/model_components/copan_global_like_production/interface.py
deleted file mode 100644
index 7aa69952..00000000
--- a/pycopancore/model_components/copan_global_like_production/interface.py
+++ /dev/null
@@ -1,146 +0,0 @@
-"""copan_global_like_production model component Interface."""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-from ... import master_data_model as D
-from ...data_model.master_data_model import MET, W, S, C
-from ... import Variable
-
-
-class Model (object):
- """Interface for Model mixin."""
-
- # metadata:
- name = "copan:GLOBAL-like economic production"
- """a unique name for the model component"""
- description = """Simple four-sector (three energy, one final) economy
- as in copan:GLOBAL, but with cell-based harvesting of terrestrial
- and extraction of fossil carbon and perfect allocation between cells.
- Restriction: cannot deal with nested social_systems yet."""
- """some longer description"""
- requires = []
- """list of other model components required for this model component to
- make sense"""
-
-
-# entity types:
-
-
-class World (object):
- """Interface for World mixin."""
-
- # endogenous variables:
-
- atmospheric_carbon = W.atmospheric_carbon
-
- # exogenous variables / parameters:
-
-
-class SocialSystem (object):
- """Interface for SocialSystem entity type mixin."""
-
- # pure output variables:
-
- biomass_input_flow = S.biomass_input_flow
- fossil_fuel_input_flow = S.fossil_fuel_input_flow
- renewable_energy_input_flow = S.renewable_energy_input_flow
- secondary_energy_flow = S.secondary_energy_flow
- carbon_emission_flow = S.carbon_emission_flow
- economic_output_flow = S.economic_output_flow
-
- # exogenous variables / parameters:
-
- population = S.population
- physical_capital = S.physical_capital
- renewable_energy_knowledge = S.renewable_energy_knowledge
-
- protected_terrestrial_carbon = S.protected_terrestrial_carbon
- protected_fossil_carbon = S.protected_fossil_carbon
- protected_terrestrial_carbon_share = S.protected_terrestrial_carbon_share
- protected_fossil_carbon_share = S.protected_fossil_carbon_share
-
- has_renewable_subsidy = S.has_renewable_subsidy
- has_emissions_tax = S.has_emissions_tax
- has_fossil_ban = S.has_fossil_ban
- emissions_tax_level = S.emissions_tax_level
- renewable_subsidy_level = S.renewable_subsidy_level
-
-
-class Cell (object):
- """Interface for Cell entity type mixin."""
-
- # endogenous variables:
-
- terrestrial_carbon = C.terrestrial_carbon
- fossil_carbon = C.fossil_carbon
-
- # pure output variables:
-
- biomass_relative_productivity = \
- Variable("biomass relative productivity",
- "used to determine energy input",
- unit=D.unity,
- lower_bound=0, default=1)
-
- fossil_relative_productivity = \
- Variable("fossil relative productivity",
- "used to determine energy input",
- unit=D.unity,
- lower_bound=0, default=1)
-
- renewable_relative_productivity = \
- Variable("renewable relative productivity",
- "used to determine energy input",
- unit=D.unity,
- lower_bound=0, default=1)
-
- total_relative_productivity = \
- Variable("total relative productivity",
- "used as weights in allocation of labour and capital",
- unit=D.unity,
- lower_bound=0, default=3)
-
- biomass_harvest_flow = C.biomass_harvest_flow
- fossil_extraction_flow = C.fossil_extraction_flow
-
- # exogenous variables / parameters:
-
- biomass_sector_productivity = \
- Variable("biomass sector productivity",
- "(Parameter aB in Nitzbon et al. 2017)",
- unit = (D.gigajoules / D.years)**5
- / (D.gigatonnes_carbon * D.dollars * D.people)**2,
- lower_bound=0, is_intensive=True, default=3e5)
- fossil_sector_productivity = \
- Variable("fossil sector productivity",
- "(Parameter aF in Nitzbon et al. 2017)",
- unit = (D.gigajoules / D.years)**5
- / (D.gigatonnes_carbon * D.dollars * D.people)**2,
- lower_bound=0, is_intensive=True, default=5e6)
- renewable_sector_productivity = \
- Variable("renewable sector productivity", "",
- unit = D.gigajoules**3 / D.years**5
- / (D.dollars * D.people)**2,
- lower_bound=0, is_intensive=True, default=7e-18)
- total_energy_intensity = C.total_energy_intensity
-
-
-# process taxa:
-
-
-class Metabolism (object):
- """Interface for Metabolism process taxon mixin."""
-
- # endogenous variables:
-
- biomass_energy_density = MET.biomass_energy_density
- fossil_energy_density = MET.fossil_energy_density
-
- # exogenous variables / parameters:
diff --git a/pycopancore/model_components/copan_global_like_production/model.py b/pycopancore/model_components/copan_global_like_production/model.py
deleted file mode 100644
index 547812ea..00000000
--- a/pycopancore/model_components/copan_global_like_production/model.py
+++ /dev/null
@@ -1,25 +0,0 @@
-"""copan_global_like_economy model mixing class."""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-from . import interface as I
-# import all needed entity type implementation classes:
-from .implementation import World, SocialSystem, Cell
-# import all needed process taxon implementation classes:
-from .implementation import Metabolism
-
-
-class Model (I.Model):
- """Model mixin class."""
-
- # mixins provided by this model component:
-
- entity_types = [World, SocialSystem, Cell]
- process_taxa = [Metabolism]
diff --git a/pycopancore/model_components/environmental_awareness/__init__.py b/pycopancore/model_components/environmental_awareness/__init__.py
deleted file mode 100644
index c429726b..00000000
--- a/pycopancore/model_components/environmental_awareness/__init__.py
+++ /dev/null
@@ -1,20 +0,0 @@
-"""
-Model component package template.
-"""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-from . import interface
-
-# export all implementation classes:
-from .implementation import *
-
-# export model component mixin class:
-from .model import Model
diff --git a/pycopancore/model_components/environmental_awareness/implementation/__init__.py b/pycopancore/model_components/environmental_awareness/implementation/__init__.py
deleted file mode 100644
index c09e5c02..00000000
--- a/pycopancore/model_components/environmental_awareness/implementation/__init__.py
+++ /dev/null
@@ -1,22 +0,0 @@
-"""
-Model component implementation subpackage template.
-"""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-# TODO: adjust the following lists to your needs:
-
-# export all provided entity type implementation mixin classes:
-from .social_system import SocialSystem
-from .individual import Individual
-from .cell import Cell
-
-# export all provided process taxon implementation mixin classes:
-from .culture import Culture
diff --git a/pycopancore/model_components/environmental_awareness/implementation/cell.py b/pycopancore/model_components/environmental_awareness/implementation/cell.py
deleted file mode 100644
index e461b725..00000000
--- a/pycopancore/model_components/environmental_awareness/implementation/cell.py
+++ /dev/null
@@ -1,36 +0,0 @@
-"""Cell entity type mixing class template.
-
-TODO: adjust or fill in code and documentation wherever marked by "TODO:",
-then remove these instructions
-"""
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-from .... import Explicit, ODE, ITE
-from .. import interface as I
-from ...base import interface as B
-
-class Cell (I.Cell):
- """Cell entity type mixin implementation class."""
-
- processes = [
- ODE("exponentially discounted running mean of carbon",
- [I.Cell.mean_past_terrestrial_carbon],
- [ITE(B.Cell.world.culture.terrestrial_carbon_averaging_time > 0,
- (I.Cell.terrestrial_carbon - I.Cell.mean_past_terrestrial_carbon)
- / B.Cell.world.culture.terrestrial_carbon_averaging_time,
- 0) # if zero, then the Explicit process governs this variable
- ]),
- Explicit("infinitely fast discounted running mean of carbon",
- [I.Cell.mean_past_terrestrial_carbon],
- [ITE(B.Cell.world.culture.terrestrial_carbon_averaging_time > 0,
- I.Cell.mean_past_terrestrial_carbon, # if nonzero, then the ODE process governs this variable
- I.Cell.terrestrial_carbon)
- ])
- ]
diff --git a/pycopancore/model_components/environmental_awareness/implementation/culture.py b/pycopancore/model_components/environmental_awareness/implementation/culture.py
deleted file mode 100644
index feb9fbfe..00000000
--- a/pycopancore/model_components/environmental_awareness/implementation/culture.py
+++ /dev/null
@@ -1,42 +0,0 @@
-"""Culture process taxon mixing class template.
-"""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-from .... import Event
-from .. import interface as I
-from ...base import interface as B
-from numpy import inf
-from numpy.random import exponential, uniform
-
-
-class Culture (I.Culture):
- """Culture process taxon mixin implementation class."""
-
- # process-related methods:
-
- def next_awareness_update_time(self, t):
- """time of next awareness update"""
- return (inf if self.awareness_update_rate == 0
- else t + exponential(1. / self.awareness_update_rate))
-
- def update_individuals_awareness(self, t):
- """let some individuals update their awareness"""
- for w in self.worlds:
- for i in w.individuals:
- if uniform() < self.awareness_update_fraction:
- i.update_awareness(t)
-
- processes = [
- Event("update individuals' awareness",
- [B.Culture.worlds.individuals.is_environmentally_friendly],
- ["time",
- next_awareness_update_time,
- update_individuals_awareness])
- ]
diff --git a/pycopancore/model_components/environmental_awareness/implementation/individual.py b/pycopancore/model_components/environmental_awareness/implementation/individual.py
deleted file mode 100644
index cd0357d4..00000000
--- a/pycopancore/model_components/environmental_awareness/implementation/individual.py
+++ /dev/null
@@ -1,34 +0,0 @@
-"""Individual entity type class template.
-
-TODO: adjust or fill in code and documentation wherever marked by "TODO:",
-then remove these instructions
-"""
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-from .. import interface as I
-from numpy.random import exponential
-
-class Individual (I.Individual):
- """Individual entity type mixin implementation class."""
-
- def update_awareness(self, unused_t):
- """stochastically change awareness status depending on
- terrestrial carbon density.
-
- This method is called by Culture's awareness updating process
- """
- r = exponential()
- density = self.cell.mean_past_terrestrial_carbon / self.cell.land_area
- if r * self.culture.awareness_lower_carbon_density > density:
- self.is_environmentally_friendly = True
- elif r * self.culture.awareness_upper_carbon_density < density:
- self.is_environmentally_friendly = False
-
- processes = []
diff --git a/pycopancore/model_components/environmental_awareness/implementation/social_system.py b/pycopancore/model_components/environmental_awareness/implementation/social_system.py
deleted file mode 100644
index 084b4613..00000000
--- a/pycopancore/model_components/environmental_awareness/implementation/social_system.py
+++ /dev/null
@@ -1,38 +0,0 @@
-"""SocialSystem entity type mixing class template.
-
-TODO: adjust or fill in code and documentation wherever marked by "TODO:",
-then remove these instructions
-"""
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-from .... import Explicit, ITE
-from .. import interface as I
-from ...base import interface as B
-
-# from .... import master_data_model as D
-
-
-class SocialSystem (I.SocialSystem):
- """SocialSystem entity type mixin implementation class."""
-
- processes = [
- Explicit("biomass protection due to awareness",
-# [I.SocialSystem.protected_terrestrial_carbon_share],
-# [B.SocialSystem.culture.max_protected_terrestrial_carbon_share
-# * B.SocialSystem.sum(
-# ITE(B.SocialSystem.individuals.is_environmentally_friendly,
-# B.SocialSystem.individuals.population_share, 0.0))]
- [I.SocialSystem.protected_terrestrial_carbon],
- [I.SocialSystem.max_protected_terrestrial_carbon
- * B.SocialSystem.sum(
- ITE(B.SocialSystem.individuals.is_environmentally_friendly,
- B.SocialSystem.individuals.population_share, 0.0))]
- )
- ]
diff --git a/pycopancore/model_components/environmental_awareness/interface.py b/pycopancore/model_components/environmental_awareness/interface.py
deleted file mode 100644
index b61cbb58..00000000
--- a/pycopancore/model_components/environmental_awareness/interface.py
+++ /dev/null
@@ -1,114 +0,0 @@
-"""model component Interface template.
-"""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-# TODO: use variables from the master data model wherever possible:
-from ... import master_data_model as D
-from ...data_model.master_data_model import CUL, I, S, C
-from ... import Variable
-
-
-class Model (object):
- """Interface for Model mixin."""
-
- # metadata:
- name = "environmental awareness"
- """a unique name for the model component"""
- description = "Declining/growing terrestrial carbon increases likelihood" \
- "of individuals becoming environmentally friendly/careless"
- """some longer description"""
- requires = []
- """list of other model components required for this model component to
- make sense"""
-
-
-# entity types:
-
-
-class SocialSystem (object):
- """Interface for Individual entity type mixin."""
-
- # endogenous variables:
- protected_terrestrial_carbon = S.protected_terrestrial_carbon
- protected_terrestrial_carbon_share = S.protected_terrestrial_carbon_share
-
- # exogenous variables / parameters:
- max_protected_terrestrial_carbon = \
- Variable("maximal protected stock of terrestrial carbon",
- """what stock of the current terrestrial carbon would be treated
- as protected if population is environmentally friendly""",
- unit=D.gigatonnes_carbon, lower_bound=0,
- default=0)
-
-
-class Individual (object):
- """Interface for Individual entity type mixin."""
-
- # endogenous variables:
- is_environmentally_friendly = I.is_environmentally_friendly
-
- # exogenous variables / parameters:
-
-
-# process taxa:
-
-class Culture (object):
- """Interface for Culture process taxon mixin."""
-
- # endogenous variables:
-
- # exogenous variables / parameters:
- awareness_update_rate = \
- Variable("awareness update rate",
- "rate at which a fraction of individuals update their " \
- "awareness",
- unit=D.years**-1, lower_bound=0, default=1)
- awareness_update_fraction = \
- Variable("awareness update fraction",
- "fraction of individuals updating their awareness" \
- "simultaneously",
- unit=D.unity, lower_bound=0, upper_bound=1, default=0.1)
- awareness_lower_carbon_density = \
- Variable("awareness lower carbon density",
- "characteristic value of terrestrial carbon density below which " \
- "individuals get more likely to become environmentally aware",
- unit = D.gigatonnes_carbon / D.square_kilometers,
- lower_bound=0,
- default=1e-5) # ca. 2e-5 is the current global mean
- awareness_upper_carbon_density = \
- Variable("awareness upper carbon density",
- "characteristic value of terrestrial carbon density above which " \
- "individuals get more likely to become environmentally unaware",
- unit = D.gigatonnes_carbon / D.square_kilometers,
- lower_bound=0,
- default=2e-5) # ca. 2e-5 is the current global mean
- max_protected_terrestrial_carbon_share = \
- Variable("maximal protected share of terrestrial carbon",
- """what share of the current terrestrial carbon would be treated
- as protected if population is environmentally friendly""",
- unit=D.unity, lower_bound=0, upper_bound=1,
- default=0.5) # TODO: a plausible value?
-
- terrestrial_carbon_averaging_time = \
- Variable("terrestrial carbon averaging time",
- """characteristic time for time-averaging of terrestrial carbon""",
- unit=D.years, lower_bound=0,
- default=0 # for backwards compatibility
- )
-
-class Cell (object):
-
- terrestrial_carbon = C.terrestrial_carbon
- mean_past_terrestrial_carbon = \
- Variable("mean past terrestrial carbon",
- "running exponentially discounted mean over 50 years",
- unit=D.gigatonnes_carbon)
-
\ No newline at end of file
diff --git a/pycopancore/model_components/environmental_awareness/model.py b/pycopancore/model_components/environmental_awareness/model.py
deleted file mode 100644
index aa37131f..00000000
--- a/pycopancore/model_components/environmental_awareness/model.py
+++ /dev/null
@@ -1,28 +0,0 @@
-"""Model mixing class template.
-"""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-from . import interface as I
-# import all needed entity type implementation classes:
-from .implementation import SocialSystem, Individual, Cell
-# import all needed process taxon implementation classes:
-from .implementation import Culture
-
-
-class Model (I.Model):
- """Model mixin class."""
-
- # mixins provided by this model component:
-
- entity_types = [SocialSystem, Individual, Cell]
- """list of entity types augmented by this component"""
- process_taxa = [Culture]
- """list of process taxa augmented by this component"""
diff --git a/pycopancore/model_components/exodus/__init__.py b/pycopancore/model_components/exodus/__init__.py
deleted file mode 100644
index 6852092c..00000000
--- a/pycopancore/model_components/exodus/__init__.py
+++ /dev/null
@@ -1,26 +0,0 @@
-"""
-Model component package template.
-
-TODO:
-Copy this folder, rename it to the name of your model component,
-then adjust or fill in code and documentation in all modules wherever marked by "TODO:",
-finally remove these instructions.
-See the model component development tutorial for details.
-"""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-from . import interface
-
-# export all implementation classes:
-from .implementation import *
-
-# export model component mixin class:
-from .model import Model
diff --git a/pycopancore/model_components/exodus/implementation/__init__.py b/pycopancore/model_components/exodus/implementation/__init__.py
deleted file mode 100644
index 42d65a79..00000000
--- a/pycopancore/model_components/exodus/implementation/__init__.py
+++ /dev/null
@@ -1,24 +0,0 @@
-"""
-Model component implementation subpackage template.
-"""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-# TODO: adjust the following lists to your needs:
-
-# export all provided entity type implementation mixin classes:
-from .world import World
-from .social_system import SocialSystem
-from .cell import Cell
-from .individual import Individual
-
-# export all provided process taxon implementation mixin classes:
-from .metabolism import Metabolism
-from .culture import Culture
diff --git a/pycopancore/model_components/exodus/implementation/cell.py b/pycopancore/model_components/exodus/implementation/cell.py
deleted file mode 100644
index 4392798c..00000000
--- a/pycopancore/model_components/exodus/implementation/cell.py
+++ /dev/null
@@ -1,47 +0,0 @@
-"""Cell entity type mixing class template.
-
-TODO: adjust or fill in code and documentation wherever marked by "TODO:",
-then remove these instructions
-"""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-from .. import interface as I
-# from .... import master_data_model as D
-
-
-class Cell (I.Cell):
- """Cell entity type mixin implementation class."""
-
- # standard methods:
-
- def __init__(self,
- *,
- characteristic=None,
- average_precipitation=None,
- **kwargs):
- """Initialize an instance of Cell."""
- super().__init__(**kwargs) # must be the first line
- self.characteristic = characteristic
- self.average_precipitation = average_precipitation
-
- self.assert_valid()
-
- # assert that farmland is owned by county and city by municipality:
- if self.characteristic == 'farmland':
- assert self.social_system.municipality_like is False
- if self.characteristic == 'city':
- assert self.social_system.municipality_like is True
-
- # process-related methods:
-
- # TODO: add some if needed...
-
- processes = [] # TODO: instantiate and list process objects here
diff --git a/pycopancore/model_components/exodus/implementation/culture.py b/pycopancore/model_components/exodus/implementation/culture.py
deleted file mode 100644
index c13b9f57..00000000
--- a/pycopancore/model_components/exodus/implementation/culture.py
+++ /dev/null
@@ -1,103 +0,0 @@
-"""Culture process taxon mixing class template.
-
-TODO: adjust or fill in code and documentation wherever marked by "TODO:",
-then remove these instructions
-"""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-from .. import interface as I
-from pycopancore.model_components.base import interface as B
-# from .... import master_data_model as D
-from pycopancore import Explicit, Step
-import networkx as nx
-import community
-
-
-class Culture (I.Culture):
- """Culture process taxon mixin implementation class."""
-
- def __init__(self,
- *,
- network_clustering=0, # this is stupid but necessary, plotting failes otherwise
- fully_connected_network=True, # static network
- **kwargs):
- """Initialize the unique instance of Metabolism."""
- super().__init__(**kwargs) # must be the first line
-
- self.network_clustering = network_clustering
- self.fully_connected_network = fully_connected_network
-
- def calculate_av_clustering(self, unused_t):
- """Calculate clustering wih networkx."""
- # only if not fully connected:
- if not self.fully_connected_network:
- self.network_clustering = nx.average_clustering(
- self.acquaintance_network)
-
- def calculate_partition(self, graph):
- """Calculate the partition of the Graph using Louvain algo."""
- partition = community.best_partition(graph)
- return partition
-
- def calculate_modularity(self, unused_t):
- """Calculate modularity from partition."""
- # only if not fully connected:
- if not self.fully_connected_network:
- shallow_network = nx.from_scipy_sparse_matrix(
- nx.adjacency_matrix(self.acquaintance_network))
- partition = self.calculate_partition(shallow_network)
- self.modularity = community.modularity(
- partition,
- shallow_network)
- # print('modularity: ', self.modularity)
-
- def modularity_timing(self, t):
- """Timing for step process to calculate modularity."""
- # only if not fully connected:
- if not self.fully_connected_network:
- return t + 1
- else:
- return t + 1000 # just a high number, so it doesnt happen...
-
- def calculate_transitivity(self, unused_t):
- """Calculate the transitivity of the network"""
- # only if not fully connected:
- if not self.fully_connected_network:
- self.transitivity = nx.transitivity(self.acquaintance_network)
-
- def check_for_split(self):
- """Check if network has split into to groups."""
- # Iterate through all individuals and see if they know someone from
- # another profession:
- connection = False
- for ind in self.acquaintance_network:
- for acq in ind.acquaintances:
- if ind.profession != acq.profession:
- # if one has another profession, the split has not
- # taken place:
- connection = True
- break
- self.split = False
- if connection is False:
- self.split = True
- return self.split
-
- processes = [
- Explicit("calculate average clustering",
- [I.Culture.network_clustering],
- calculate_av_clustering),
- Step("Calculate Modularity",
- [I.Culture.modularity],
- [modularity_timing, calculate_modularity]),
- Step("Calculate Transitivity",
- [I.Culture.transitivity],
- [modularity_timing, calculate_transitivity])
- ] # TODO: instantiate and list process objects here
diff --git a/pycopancore/model_components/exodus/implementation/individual.py b/pycopancore/model_components/exodus/implementation/individual.py
deleted file mode 100644
index 231f66c2..00000000
--- a/pycopancore/model_components/exodus/implementation/individual.py
+++ /dev/null
@@ -1,349 +0,0 @@
-"""Individual entity type class template.
-
-TODO: adjust or fill in code and documentation wherever marked by "TODO:",
-then remove these instructions
-"""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-from .. import interface as I
-from pycopancore.model_components.base import interface as B
-from pycopancore import Event, Explicit
-import math
-import random
-import numpy as np
-from scipy import stats
-
-
-class Individual (I.Individual):
- """Individual entity type mixin implementation class."""
-
- # standard methods:
-
- def __init__(self,
- *,
- profession=None,
- nutrition_need=1240,
- liquidity=None,
- nutrition=None,
- second_degree_rewire_prob=0.3,
- outspokenness=None,
- random_rewire=0.05,
- farm_size=None,
- gross_income=None,
- **kwargs):
- """Initialize an instance of Cell."""
- super().__init__(**kwargs) # must be the first line
- self.profession = profession
- self.nutrition_need = nutrition_need
- self.second_degree_rewire_prob = second_degree_rewire_prob
- self.outspokenness = outspokenness
- self.random_rewire = random_rewire
- self.gross_income = gross_income
- self.farm_size = farm_size
- self.liquidity = liquidity
- self.nutrition = nutrition
-
- if self.profession == 'farmer':
- assert self.cell.characteristic == 'farmland'
- if self.profession == 'townsman':
- assert self.cell.characteristic == 'city'
-
- def calc_farm_size(self):
- """Get the farm size."""
- # Check, if not already been calculated:
- if self.farm_size is None:
- # If townsman, individual has no farm:
- if self.social_system.municipality_like is True:
- self.farm_size = 0
- # If farmer, distribute farm size:
- if self.social_system.municipality_like is False:
- # Let social_system distribute farm size
- self.farm_size = self.social_system.calc_gross_income_or_farmsize()
- # return self.farm_size
-
- def calc_gross_income(self):
- """Get the gross income."""
- # Check if not already been calculated:
- if self.gross_income is None:
- # Check if farmer or townsman:
- if self.social_system.municipality_like is True:
- # Let social_system distribute income:
- self.gross_income = self.social_system.calc_gross_income_or_farmsize()
- # If not townsman, income = 0
- if self.social_system.municipality_like is False:
- self.gross_income = 0
- # return self.gross_income
-
- # process-related methods:
- def social_update_timer(self, t):
- """Calculate when a social update takes place"""
- return t + np.random.exponential(self.outspokenness)
- # outspokenness = 1 means in average once a year, 0.1 = 10 times a year,
- # 10 means once every 10 years in average.
-
- def social_update(self, unused_t):
- """Do social update.
-
- Either migration or de- and re-friending takes place.
- In case of a fully connected network only migration takes place.
- """
- # Set Flag to prevent agents from migrating twice when continuos
- # exploration is True:
- migrated = False
- # First: determine if fully connected network:
- if self.culture.fully_connected_network:
- # First check if continuos exploration is turned on:
- if self.social_system.continuous_exploration:
- # define threshold for noise:
- if random.random() < 0.05:
- # Do exploration -> Move to any cell/social system
- ss = random.sample(self.world.social_systems, 1)[0]
- # Get the social systems cell (cells is a set)
- print(ss)
- for cell in ss.cells:
- new_cell = cell
- # If social system is idle/deactivated:
- if ss.__class__.idle_entities and \
- ss in ss.__class__.idle_entities:
- # reactivate it:
- ss.reactivate()
- self.migrate(new_cell)
- migrated = True
-
- # Network is fully connected:
- chosen_one = random.choice(self.culture.acquaintance_network.nodes())
- # Add event to social systems migration counter:
- self.social_system.migration_counter[0] += 1
- self.social_system.migration_counter[1].append(
- chosen_one.social_system)
- if self.decide_migration(chosen_one) and not migrated:
- # in case of preferential migration, checks are done
- if self.preferential_migration:
- # Add successful event to migration counter:
- self.social_system.migration_counter[2].append(
- chosen_one.social_system)
- self.preferential_migrate(chosen_one.cell)
- else:
- # Add successful event to migration counter:
- self.social_system.migration_counter[2].append(
- chosen_one.social_system)
- # Migrate
- self.migrate(chosen_one.cell)
-
- else: # Not fully connected:
- # Chose Acquaintance, if existent:
- if self.acquaintances:
- chosen_one = random.choice(self.acquaintances)
- # Get the Chosen One's Profession:
- chosen_profession = chosen_one.profession
- # Check, whether same profession, therefore define
- # if migration or rewiring takes place or nothing
- if chosen_profession != self.profession:
- # Compare utility and decide if migration takes place:
- if self.decide_migration(chosen_one):
- # Migrate
- self.migrate(chosen_one.cell)
- else:
- self.rewire(chosen_one)
- if (chosen_profession == self.profession
- and random.random() <= self.random_rewire):
- # Noise: Rewire to a random individual
- random_guy = random.choice(tuple(self.world.individuals))
- if (random_guy not in self.acquaintances):
- # Add edge:
- self.culture.acquaintance_network.add_edge(self, random_guy)
- # remove old edge:
- self.culture.acquaintance_network.remove_edge(self,
- chosen_one)
-
- def decide_migration(self, neighbour):
- """Decide, if rewire or migration takes place.
-
- Parameters
- ----------
- neighbour: exodus.individual
- Object of type individual that has different profession than the
- self object.
-
- Returns
- -------
- bool:
- True if migration takes place
- """
- # If last one standing is active, check if there are more than one
- # agent in the social system:
- if self.social_system.last_one_standing:
- if self.social_system.population == 1:
- return False
- # Difference in utility:
- delta_utility = neighbour.utility - self.utility
- # print('delta util', delta_utility)
- # Tanh function:
- tanh = 0.5 * (1 + math.tanh(delta_utility / 2))
- if random.random() <= tanh:
- # Migrate if enough liquidity
- if self.liquidity > neighbour.social_system.migration_cost:
- # Next line is causing liquidities to drop below 0 if the
- # social_system update takes place:
- # self.liquidity -= neighbour.social_system.migration_cost
- return True
- else:
- # Not enough money to migrate
- return False
- else:
- # Rewire
- return False
-
- def rewire(self, neighbour):
- """Do rewiring.
-
- Detaches from neighbour and rewires to a neighbour of degree n.
- This process is only used, if the network is not static!
- Parameters.
- ----------
- neighbour: exodus.individual
- neighbour from which to detach
- """
- # Remove edge:
- self.culture.acquaintance_network.remove_edge(self, neighbour)
- # Chose another random neighbour
- # Check if individuals has acquaintances:
- if not self.acquaintances:
- # If so, connect to random one in model:
- random_one = random.choice(tuple(self.world.individuals))
- self.culture.acquaintance_network.add_edge(self, random_one)
- random_neighbour = random.choice(self.acquaintances)
- third_degree_neighbors = []
- break_cond = False
- # Iterate through second degree neighbours of random neighbour:
- for n in random_neighbour.acquaintances:
- # Attach with second_degree_rewire_prob, if not already connected
- # or if not just detached:
- if (random.random() < self.second_degree_rewire_prob
- and n != neighbour
- and n not in self.acquaintances):
- self.culture.acquaintance_network.add_edge(self, n)
- break_cond = True
- break
- # If rewiring did not take place, add his neighbours to third
- # degree neighbour list:
- if (n != neighbour
- and n not in self.acquaintances):
- for nn in n.acquaintances:
- third_degree_neighbors.append(nn)
- # Iterate through 3 degree neighbours, if ne neighbour was not found:
- if break_cond is False:
- for n in third_degree_neighbors:
- # Attach with second_degree_rewire_prob^2, if not already
- # connected or if not just detached:
- if (random.random() < (self.second_degree_rewire_prob**2)
- and n != neighbour
- and n not in self.acquaintances):
- self.culture.acquaintance_network.add_edge(self, n)
- break_cond = True
- break
- # if nobody has connected yet, chose any random individual:
- if break_cond is False:
- # tuple is necessary since self.world.individuals is a set,
- # therefore random.choice alone does not work!
- random_guy = random.choice(tuple(self.world.individuals))
- if (random_guy != neighbour
- and random_guy not in self.acquaintances):
- self.culture.acquaintance_network.add_edge(self, random_guy)
- else:
- print('this is very unlikely, nobody has been found, '
- 'individual loses a connection.')
-
- def preferential_migrate(self, cell):
- """Calls migragte in case of preferential migration."""
- # 3 cases: city-city, farmland-farmland, city-farmland/vice versa
- # first, check city-city
- if (self.cell.social_system.municipality_like and
- cell.social_system.municipality_like):
- if random.random() < 0.2: # need of number that makes sense
- self.migrate(cell)
- # second, check farmlad farmland
- elif (not self.cell.social_system.municipality_like and
- not cell.social_system.municipality_like):
- if random.random() < 0.2: # need of number that makes sense
- self.migrate(cell)
- # third: check city-farmland/farmland-city
- else:
- # check if neighbours
- if ((cell.location[0] ^ self.cell.location[0])
- ^ (cell.location[1] ^ self.cell.location[1])):
- # cells are neighbouring
- if random.random() < 1:
- self.migrate(cell)
-
- def migrate(self, cell):
- """Migrate to Cell.
-
- Parameters
- ----------
- cell: exodus.cell
- cell to migrate to.
- """
- # Change cell and social_system (done in base.individual):
- self.cell = cell
- # Change Profession:
- if cell.social_system.municipality_like is False:
- self.profession = 'farmer'
- elif cell.social_system.municipality_like is True:
- self.profession = 'townsman'
- else:
- raise TypeError('Neither Municipality nor County!')
- # Set Values to None, so they can be recalculated:
- self.farm_size = None
- self.gross_income = None
- self.calc_gross_income()
- self.calc_farm_size()
-
- def calculate_harvest(self, unused_t):
- """Calculate the harvest of an Individual."""
- self.harvest = self.farm_size * self.cell.average_precipitation * 1000000
-
- def calculate_utility(self, unused_t):
- """Calculate utility if an Individual."""
- try:
- self.utility = math.sqrt(
- self.liquidity * self.nutrition
- / self.social_system.average_liquidity / 1240)
- # 1240 m^3 is the annual need, maybe need to incorporate it
- # The folloeing should not happen but do so on the cluster:
- except ValueError:
- print('liquidity could not be calculated! Setting it to 0')
- print(self.liquidity, self.nutrition,
- self.social_system.average_liquidity)
- self.utility = 0
- except TypeError:
- print('liquidity could not be calculated! Setting it to 0')
- print(self.liquidity, self.nutrition,
- self.social_system.average_liquidity)
- self.utility = 0
-
- processes = [
- Event("social update",
- [B.Individual.social_system,
- # B.Individual.culture.acquaintance_network TOO BIG TO SAVE!
- I.Individual.farm_size,
- I.Individual.gross_income,
- I.Individual.liquidity,
- B.Individual.social_system.migration_counter
- ],
- ["time", social_update_timer, social_update]),
- Explicit("Calculate harvest",
- [I.Individual.harvest],
- calculate_harvest),
- Explicit("Calculate Utility",
- [I.Individual.utility],
- calculate_utility)
- ] # TODO: instantiate and list process objects here
diff --git a/pycopancore/model_components/exodus/implementation/metabolism.py b/pycopancore/model_components/exodus/implementation/metabolism.py
deleted file mode 100644
index e6dfc59f..00000000
--- a/pycopancore/model_components/exodus/implementation/metabolism.py
+++ /dev/null
@@ -1,108 +0,0 @@
-"""Metabolism process taxon mixin class template.
-
-TODO: adjust or fill in code and documentation wherever marked by "TODO:",
-then remove these instructions
-"""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-from .. import interface as I
-from pycopancore.model_components.base import interface as B
-from pycopancore import Step, Explicit
-
-from scipy import optimize
-import numpy as np
-import math
-
-
-class Metabolism (I.Metabolism):
- """Metabolism process taxon mixin implementation class."""
-
- # standard methods:
-
- def __init__(self,
- *,
- market_frequency=1,
- **kwargs):
- """Initialize the unique instance of Metabolism."""
- super().__init__(**kwargs) # must be the first line
-
- self.market_frequency = market_frequency
-
- # At last, check for validity of all variables that have been
- # initialized and given a value:
-
- # Following method is defined in abstract_process_taxon_mixin which is
- # inherited only by mixing in the model:
- self.assert_valid()
-
- @property
- def total_gross_income(self):
- """Get the total gross income."""
- # Chose a world as world. When having several, this must be changed!
- for w in self.worlds:
- world = w
- break
- tgi = 0
- for individual in world.individuals:
- tgi += individual.gross_income
- return tgi
-
- # process-related methods:
-
- def do_market_clearing(self, unused_t):
- """Calculate water price and market movements."""
- print('market clearing takes place at time', unused_t)
- # Iterate through worlds
- for w in self.worlds:
- world = w
- w.calc_total_harvest(unused_t)
- w.calc_total_gross_income(unused_t)
- price = world.water_price = w.total_gross_income / w.total_harvest
- for ind in w.individuals:
- ind.nutrition = (ind.gross_income + price * ind.harvest) / (
- 2 * price)
- ind.liquidity = (ind.gross_income + price * ind.harvest) / 2
- w.calc_total_nutrition(unused_t)
- w.calc_total_liquidity(unused_t)
- tgi = world.total_gross_income
- th = world.total_harvest
- tn = world.total_nutrition
- tl = world.total_liquidity
- print('market clearing is done at time', unused_t,
- 'price is now at', world.water_price)
- # Break condition if suppy and demand are not equal:
- if round(tn) != round(th):
- print('Market clearing failed')
- print('nutrition - harvest', tn - th,
- 'income - liquidity', tgi-tl)
- self.non_equilibrium_checker = True
-
- def market_timing(self, t):
- """Define how often market clearing takes place."""
- return t + 1 / self.market_frequency
-
- def check_for_market_equilibrium(self):
- """Check if the market equilibrium is still in order."""
- if self.non_equilibrium_checker is True:
- return self.non_equilibrium_checker
- else:
- return False
-
- processes = [
- Step("market clearing",
- [B.Metabolism.worlds.individuals.liquidity,
- B.Metabolism.worlds.water_price,
- B.Metabolism.worlds.individuals.nutrition
- ],
- [market_timing,
- do_market_clearing]
- )
- ] # TODO: instantiate and list process objects here
diff --git a/pycopancore/model_components/exodus/implementation/social_system.py b/pycopancore/model_components/exodus/implementation/social_system.py
deleted file mode 100644
index 88500bb1..00000000
--- a/pycopancore/model_components/exodus/implementation/social_system.py
+++ /dev/null
@@ -1,282 +0,0 @@
-"""SocialSystem entity type mixing class template.
-
-TODO: adjust or fill in code and documentation wherever marked by "TODO:",
-then remove these instructions
-"""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-from .. import interface as I
-from pycopancore.model_components.base import interface as B
-from pycopancore import Explicit, Step
-# from .... import master_data_model as D
-
-from scipy import stats
-import numpy as np
-import math
-import random
-
-
-class SocialSystem (I.SocialSystem):
- """SocialSystem entity type mixin implementation class."""
-
- # standard methods:
-
- def __init__(self,
- *,
- municipality_like=False,
- base_mean_income=1000,
- pdf_sigma=0.34, # 0.34 taken from Clementi, Gallegati 2005 for income distribution
- scaling_parameter=1.12, # taken from Bettencourt paper
- migration_cost=1000,
- last_one_standing=False, # measures to ensure ergodicity
- continuous_exploration=False, # kind of a noise term
- **kwargs):
- """Initialize an instance of SocialSystem."""
- super().__init__(**kwargs) # must be the first line
-
- self.municipality_like = municipality_like
- self.base_mean_income = base_mean_income
- self.pdf_sigma = pdf_sigma
- self.scaling_parameter = scaling_parameter
- self.migration_cost = migration_cost
- self.migration_counter = [0, [], []]
- self.last_one_standing = last_one_standing
- self.continuous_exploration = continuous_exploration
- # Initializing self.migration_rates list with length of number of
- # social systems not possibble here, since not all social systems
- # are initialized yet.
-
- def calc_gross_income_or_farmsize(self):
- "Get random income or farm size distributed log-normal."
-
- # Use log-normal
- number = random.random()
- sigma = self.pdf_sigma
- # calculate ´median from mean:
- median = (self.mean_income_or_farmsize / np.exp(sigma**2 / 2))
- lognormal_random = stats.lognorm.ppf(number, s=sigma, scale=median)
- return lognormal_random
-
- def calc_population(self, unused_t):
- """Calculate the social_systems population explicitly.
-
- Parameters
- ----------
- unused_t
- """
- if len(self.individuals) == 0:
- self.deactivate()
- print(f'social_system {self} died out at time {unused_t}')
- # to prevent division by zero:
- self.population = 1
- else:
- self.population = len(self.individuals)
-
- def update_incomes(self):
- """Update incomes to adjust to population in some manner."""
- # first: Check if really a municipaity:
- if self.municipality_like is not True:
- raise SocialSystemTypeError('SocialSystem not a municipality')
- # Define factor how fast adjusting takes place
- factor = 0.5
- sum = 0
- for ind in self.individuals:
- sum += ind.gross_income
- # Now divide by number of individuals to get mean:
- real_mean = sum / self.population
- adaption_rate = self.mean_income_or_farmsize / real_mean
- adaption = adaption_rate + (1 - adaption_rate) * factor
- for ind in self.individuals:
- ind.gross_income *= adaption
-
- def update_farmsizes(self):
- """Update farmsizes to adjust to population."""
- # first: Check if really a county:
- if self.municipality_like is not False:
- raise SocialSystemTypeError('SocialSystem not a county')
- # Define factor how fast adjusting takes place
- factor = 0.5
- sum = 0
- for ind in self.individuals:
- sum += ind.farm_size
- # Now divide by number of individuals to get mean:
- real_mean = sum / self.population
- adaption_rate = self.mean_income_or_farmsize / real_mean
- adaption = adaption_rate + (1 - adaption_rate) * factor
- for ind in self.individuals:
- ind.farm_size *= adaption
-
- def update_timing(self, t):
- """Decide how often income and farm size are adjusted."""
- return t + 1
-
- def do_update(self, unused_t):
- """Do the adjustment of income or farmsize"""
- if self.is_active:
- if self.municipality_like is True:
- self.update_incomes()
- print('incomes updated of social_system', self)
- elif self.municipality_like is False:
- self.update_farmsizes()
- print('farmsizes updated of social_system', self)
- else:
- raise SocialSystemTypeError('Neither County nor Municipality!')
-
- def calculate_mean_income_or_farmsize(self, unused_t):
- """Calculate mean income (if municipality) or farm size (county)."""
- if self.is_active:
- if self.municipality_like:
- # in case of municipality
- total_income = self.base_mean_income * (
- self.population**self.scaling_parameter)
- self.mean_income_or_farmsize = total_income / self.population
- if not self.municipality_like:
- # in case of county
- for c in self.direct_cells:
- # mean farm size:
- self.mean_income_or_farmsize = c.land_area / self.population
-
- def calculate_average_liquidity(self, unused_t):
- """Calculate average liquidity of social_system."""
- if self.is_active:
- sum = 0
- for ind in self.individuals:
- sum += ind.liquidity
- self.average_liquidity = sum / self.population
- else:
- # This should not happen, but apparently does nevertheless...
- self.average_liquidity = 1
-
- def calculate_average_utility(self, unused_t):
- """Calculate the average utility in this social_system."""
- if self.is_active:
- summe = 0
- for ind in self.individuals:
- summe += ind.utility
- self.average_utility = summe / self.population
-
- def calculate_gini(self, unused_t):
- """Calculate the gini coefficient of the utility.
-
- This is using the Relative mean absolute difference:
- https://en.wikipedia.org/wiki/Mean_absolute_difference#Relative_mean_absolute_difference
- """
- # Mean absolute difference
- if self.is_active:
- utilities = []
- for ind in self.individuals:
- utilities.append(ind.utility)
- mad = np.abs(np.subtract.outer(utilities, utilities)).mean()
- # Relative mean absolute difference
- rmad = mad / np.mean(utilities)
- # Gini coefficient
- self.gini_coefficient = 0.5 * rmad
-
- def calculate_migration_rate(self, unused_t):
- """Calculate migration rates"""
- # First time this is called, a list of length of number of social
- # systems is generated:
- if self.migration_rates is None:
- self.migration_rates = [0] * len(self.world.social_systems)
-
- # Every time this is called, this list needs to be reset:
- for i in range(len(self.migration_rates)):
- self.migration_rates[i] = 0
- # The two above steps are not performed as one, since some social
- # systems might be deactivated during run, resulting in a new length
- # for the list.
-
- # Now copy this list for theoretical migration rates:
- self.theoretical_mig_rate = list(self.migration_rates)
- if self.is_active:
- # print(self.migration_counter)
- tot_tries = self.migration_counter[0] # total number of tries
- mig_attempts = self.migration_counter[1] # list of social systems where attempted
- mig_moves = self.migration_counter[2] # list of social system where success
-
- # for the following to work, it is important, that we know the
- # smallest uid of the social systems and all other social systems
- # have following uids!
- min_uid = min(ss._uid for ss in self.world.social_systems)
- # attempted moves:
- attempt_list = self.migration_rates.copy()
- for element in mig_attempts:
- for i, soc in enumerate(attempt_list):
- # since uids start with min_uid, we need to add it:
- if str(element).endswith(str(i+min_uid)+']'):
- attempt_list[i] += 1
-
- # successful moves:
- for element in mig_moves:
- for i, soc in enumerate(self.migration_rates):
- # print(i)
- # since uids start with min_uid, we need to add it:
- if element._uid == i+min_uid:
- self.migration_rates[i] += 1
- # Now divide success by attempts
- for i, el in enumerate(self.migration_rates):
- try:
- self.migration_rates[i] = self.migration_rates[i]
- # If probability is needed, following is needed:
- # self.migration_rates[i] = (self.migration_rates[i]
- # / attempt_list[i])
- except ZeroDivisionError:
- # Both entries 0
- self.migration_rates[i] = 0
-
- # Theoretical Calculation:
- for ss in self.world.social_systems:
- # Put in values according to the uids. Since uids start with
- # min_uid, we have to account for that by subtracting it:
- self.theoretical_mig_rate[(ss._uid-min_uid)] = (1/2 + (
- math.sqrt(ss.average_liquidity)
- - math.sqrt(self.average_liquidity))/(4 * math.sqrt(
- self.world.water_price * 1240))) * attempt_list[(ss._uid-min_uid)]
- # if probability is wanted, leave out * attempt_list[(ss._uid-min_uid)]
- # 1240 is the water need, also set in Individual.calculate_utility
- # print(self.migration_rates, self.theoretical_mig_rate)
- # reset migration counter for next step:
- self.migration_counter = [0, [], []]
- #print(self.migration_counter)
-
- processes = [
- Explicit('calculate population',
- [B.SocialSystem.population,
- # Following is only done to determine if soc is a city or
- # not afterwards, since this is not saved otherwise:
- I.SocialSystem.municipality_like],
- calc_population),
- Explicit('calculate mean income or farmsize',
- [I.SocialSystem.mean_income_or_farmsize],
- calculate_mean_income_or_farmsize),
- Explicit("Calculate average liquidities",
- [I.SocialSystem.average_liquidity],
- calculate_average_liquidity),
- Explicit("Calculate average utilities",
- [I.SocialSystem.average_utility],
- calculate_average_utility),
- Explicit("Calculate gini",
- [I.SocialSystem.gini_coefficient],
- calculate_gini),
- Step("Calculate Migration Rates",
- [I.SocialSystem.migration_rates,
- I.SocialSystem.theoretical_mig_rate],
- [update_timing, calculate_migration_rate]),
- Step("Update incomes/farmsizes",
- [B.SocialSystem.individuals.farm_size,
- B.SocialSystem.individuals.gross_income],
- [update_timing, do_update])
- ]
-
-
-class SocialSystemTypeError(Exception):
- """Error Class if wrong type of social_system."""
- pass
diff --git a/pycopancore/model_components/exodus/implementation/world.py b/pycopancore/model_components/exodus/implementation/world.py
deleted file mode 100644
index 5d1e31b7..00000000
--- a/pycopancore/model_components/exodus/implementation/world.py
+++ /dev/null
@@ -1,102 +0,0 @@
-"""World entity type mixing class template.
-
-TODO: adjust or fill in code and documentation wherever marked by "TODO:",
-then remove these instructions
-"""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-from .. import interface as I
-from pycopancore.model_components.base import interface as B
-import numpy
-from pycopancore import Explicit
-# from .... import master_data_model as D
-
-
-class World (I.World):
- """World entity type mixin implementation class."""
-
- # standard methods:
-
- def __init__(self,
- *,
- water_price,
- **kwargs):
- """Initialize an instance of World."""
- super().__init__(**kwargs) # must be the first line
-
- self.water_price = water_price
- # At last, check for validity of all variables that have been
- # initialized and given a value:
-
- # Following method is defined in abstract_entity_mixin which is
- # inherited only by mixing in the model:
- self.assert_valid()
-
- def calc_total_gross_income(self, unused_t):
- """Calculate total gross income explicitly."""
- tgi = 0
- for individual in self.individuals:
- tgi += individual.gross_income
- self.total_gross_income = tgi
-
- def calc_total_harvest(self, unused_t):
- """Calculate total harves exlicitly"""
- th = 0
- for individual in self.individuals:
- th += individual.harvest
- self.total_harvest = th
-
- def calc_total_nutrition(self, unused_t):
- """Calculate total nutrition explicitly."""
- """Get the total nutrition."""
- tn = 0
- for individual in self.individuals:
- # print(individual.nutrition)
- tn += individual.nutrition
- if numpy.isnan(tn):
- self.exception_checker = True
- # raise BaseException('some individuals nutrition is nan!')
- print('some individuals nutrition is nan!')
- self.total_nutrition = tn
-
- def calc_total_liquidity(self, unused_t):
- """Calculate total liquidity explicitly."""
- tl = 0
- for individual in self.individuals:
- # print(individual.liquidity)
- tl += individual.liquidity
- if numpy.isnan(tl):
- self.exception_checker = True
- # raise BaseException('some individuals liquidity is nan!')
- print('some individuals nutrition is nan!')
- self.total_liquidity = tl
-
- def check_for_exceptions(self):
- """Check if the market equilibrium is still in order."""
- if self.exception_checker is True:
- return self.exception_checker
- else:
- return False
-
- processes = [
- Explicit('calculate total gross income',
- [I.World.total_gross_income],
- calc_total_gross_income),
- Explicit('calculate total harvest',
- [I.World.total_harvest],
- calc_total_harvest),
- Explicit('calculate total nutrition',
- [I.World.total_nutrition],
- calc_total_nutrition),
- Explicit('calculate total liquidity',
- [I.World.total_liquidity],
- calc_total_liquidity)
- ]
diff --git a/pycopancore/model_components/exodus/interface.py b/pycopancore/model_components/exodus/interface.py
deleted file mode 100644
index 1aabc778..00000000
--- a/pycopancore/model_components/exodus/interface.py
+++ /dev/null
@@ -1,260 +0,0 @@
-"""model component Interface template.
-
-TODO: adjust or fill in code and documentation wherever marked by "TODO:", then
-remove these instructions.
-"""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-from ... import master_data_model as D
-from ... import Variable
-
-
-class Model (object):
- """Interface for Model mixin."""
-
- # metadata:
- name = "Exodus"
- description = "..."
- """A migration model in the urban rural space."""
- requires = []
- """list of other model components required for this model component to
- make sense"""
-
- # Notes:
- # - Model does NOT define variables or parameters, only entity types
- # and process taxons do!
- # - implementation.Model lists these entity-types and process taxons
-
-
-# entity types:
-
-
-class World (object):
- """Interface for World mixin."""
-
- total_gross_income = Variable("total gross income",
- "Total income generated in the world.",
- lower_bound=0,
- unit=D.dollars)
- total_harvest = Variable("total harvest",
- "All water that has been harvested in the world",
- lower_bound=0,
- dimension=D.volume * D.time,
- unit=D.meters ** 3 / D.years)
- total_nutrition = Variable("total nutrition",
- "All water that is being consumed in the world",
- lower_bound=0,
- dimension=D.volume * D.time,
- unit=D.meters ** 3 / D.years)
- total_liquidity = Variable("total liquidity",
- "All the liquidity in the world, shall be equal"
- "to the total gross income",
- lower_bound=0,
- unit=D.dollars)
- water_price = Variable("water price",
- "price of water that is calculated by market "
- "clearing",
- lower_bound=0,
- unit=D.dollars,
- default=1)
- exception_checker = Variable("Exception checker",
- "Check for exceptions to terminate run",
- default=False)
-
-
-class SocialSystem (object):
- """Interface for SocialSystem entity type mixin."""
-
- # endogenous variables:
- municipality_like = Variable("municipality like",
- "If true, social_system is a Municipality, "
- "otherwise a county",
- datatype=bool)
- base_mean_income = Variable("base income",
- "Base of scaling mean income dependend on "
- "population, only important for municipality",
- default=1000)
- mean_income_or_farmsize = Variable("Mean income or farmsize",
- "Mean income or farm size dependend on "
- "population and base_mean_income",
- default=0)
- average_liquidity = Variable("Average Liquidity",
- "Average over all liquidities in social_system",
- lower_bound=0,
- unit=D.dollars)
- average_utility = Variable("Average Utility",
- "Average Utility in a social_system")
- gini_coefficient = Variable("Gini Coefficient",
- "Gini coefficient of utilities")
- scaling_parameter = Variable("Scaling Parameter",
- "Parameter that scales income as in "
- "Total_income = base_inc ** parameter, "
- "default from bettencourt paper",
- default=1.12)
- migration_cost = Variable("Migration Cost",
- "Cost to migrate to this social_system",
- default=1000)
- migration_counter = Variable("Migration Counter",
- "List of: "
- "-number of events that could lead to "
- "migration,"
- "-list of social systems uids of possible "
- "taget social systems,"
- "-list of social system and uids "
- "of target SocialSystems",
- datatype=list)
- migration_rates = Variable("Migration Rates",
- "List with migration rates to all other "
- "social systems",
- datatype=list,
- allow_none=True,
- default=None)
- theoretical_mig_rate = Variable("Theoretical Migration Rate",
- "Analytical approximation of rates",
- datatype=list,
- allow_none=True,
- default=None)
- last_one_standing = Variable("Last one standing",
- "Bool that if True prohibits the last agent "
- "in a social system from migrating",
- datatype=bool,
- default=False)
- continuous_exploration = Variable("Continuos Exploration",
- "Bool, that if True leads to a noise in"
- "migration",
- datatype=bool,
- default=False)
-
- # exogenous variables / parameters:
-
-
-class Cell (object):
- """Interface for Cell entity type mixin."""
-
- # endogenous variables:
-
- characteristic = Variable("characteristic",
- "sort of cell, e.g 'farmland' or 'city' ")
- average_precipitation = Variable("average precipitation",
- "average precipitation per square meter "
- "of cell's area and year",
- lower_bound=0,
- dimension=D.volume / (D.area * D.time),
- unit=D.meters/D.years)
-
- # exogenous variables / parameters:
-
-
-class Individual (object):
- """Interface for Individual entity type mixin."""
-
- # endogenous variables:
- profession = Variable("profession",
- "profession of an Individual, eg. 'farmer' or "
- " 'townsman' ")
- farm_size = Variable("farm size",
- "Size of the farm of an individual, if his "
- "profession is farmer",
- lower_bound=0,
- unit=D.square_kilometers,
- allow_none=True) # farm size is None until distributed by social system
- gross_income = Variable("gross income",
- "Income before trade, distributed by social_system if "
- "social_system is a municipality",
- lower_bound=0,
- unit=D.dollars,
- allow_none=True) # incomes are none until distributed by social system
- harvest = Variable("harvest",
- "Water harvested before trade, calculated by farm size "
- "and average farmland precipitation",
- lower_bound=0,
- dimension=D.volume*D.time,
- unit=D.meters**3 / D.years,
- default=0)
- liquidity = Variable("liquidity",
- "income after trade",
- lower_bound=0,
- unit=D.dollars)
- nutrition = Variable("nutrition",
- "water after trade. Since it is virtual water, "
- "it can be subsumed into nutrition.",
- lower_bound=0,
- dimension=D.volume / D.time)
- nutrition_need = Variable("nutrition need",
- "need of nutrition per time",
- dimension=D.volume / D.time,
- unit=D.meters**3 / D.years)
- utility = Variable("utility",
- "Utility of an agent, calculated by any useful "
- "function",
- lower_bound=0,
- upper_bound=1)
- second_degree_rewire_prob = Variable("second degree rewire probability",
- "Probability to rewire to a neighbour "
- "of degree 2.",
- default=0.3)
- outspokenness = Variable("outspokenness",
- "Describes how often per year an individual does "
- "social updates in average",
- default=1)
- random_rewire = Variable("Random rewire",
- "Probability to rewire to a random individual"
- "and cutiing a connection with a known one.",
- default=0.05)
- preferential_migration = Variable("preferential migration",
- "Define if migration is hindered in some "
- "direction",
- datatype=bool,
- default=False)
-
- # exogenous variables / parameters:
-
-
-# process taxa:
-
-
-class Metabolism (object):
- """Interface for Metabolism process taxon mixin."""
-
- # endogenous variables:
- market_frequency = Variable("market frequency",
- "Defines how often per year the market "
- "clearing is calculated",
- default=1)
-
- non_equilibrium_checker = Variable("Nonequilibrium Checker",
- "Is set true, if market is not in "
- "equilibrium anymore",
- default=False)
-
-
-class Culture (object):
- """Interface for Culture process taxon mixin."""
-
- # endogenous variables:
- network_clustering = Variable("network clustering",
- "Average clustering of network, values from"
- "networkx.average_clustering",
- default=0)
- modularity = Variable("Modularity",
- "Modularity of a partition of the network",
- default=0)
- transitivity = Variable("Transitivity",
- "Transitivity of the network")
- split = Variable("Split",
- "Shows if network has split",
- default=False)
- fully_connected_network = Variable("Fully connected Network",
- "This var is set true when the "
- "acquaintance network is fully "
- "connected",
- default=False,
- datatype=bool)
diff --git a/pycopancore/model_components/exodus/model.py b/pycopancore/model_components/exodus/model.py
deleted file mode 100644
index f93ee5db..00000000
--- a/pycopancore/model_components/exodus/model.py
+++ /dev/null
@@ -1,31 +0,0 @@
-"""Model mixing class template.
-
-TODO: adjust or fill in code and documentation wherever marked by "TODO:",
-then remove these instructions
-"""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-from . import interface as I
-# import all needed entity type implementation classes:
-from .implementation import World, SocialSystem, Cell, Individual
-# import all needed process taxon implementation classes:
-from .implementation import Metabolism, Culture
-
-
-class Model (I.Model):
- """Model mixin class."""
-
- # mixins provided by this model component:
-
- entity_types = [World, SocialSystem, Cell, Individual]
- """list of entity types augmented by this component"""
- process_taxa = [Metabolism, Culture]
- """list of process taxa augmented by this component"""
diff --git a/pycopancore/model_components/exploit_social_learning/__init__.py b/pycopancore/model_components/exploit_social_learning/__init__.py
deleted file mode 100644
index 1e1226a7..00000000
--- a/pycopancore/model_components/exploit_social_learning/__init__.py
+++ /dev/null
@@ -1,18 +0,0 @@
-"""Model component package simple_extraction."""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-from . import interface
-
-# export all implementation classes:
-from .implementation import *
-
-# export model component mixin class:
-from .model import Model
diff --git a/pycopancore/model_components/exploit_social_learning/implementation/__init__.py b/pycopancore/model_components/exploit_social_learning/implementation/__init__.py
deleted file mode 100644
index f990b981..00000000
--- a/pycopancore/model_components/exploit_social_learning/implementation/__init__.py
+++ /dev/null
@@ -1,22 +0,0 @@
-"""
-Model component implementation subpackage exploit_social_learning.
-"""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-# TODO: adjust the following lists to your needs:
-
-# export all provided entity type implementation mixin classes:
-from .world import World
-from .individual import Individual
-
-# export all provided process taxon implementation mixin classes:
-
-from .culture import Culture
diff --git a/pycopancore/model_components/exploit_social_learning/implementation/culture.py b/pycopancore/model_components/exploit_social_learning/implementation/culture.py
deleted file mode 100644
index 734b0ccf..00000000
--- a/pycopancore/model_components/exploit_social_learning/implementation/culture.py
+++ /dev/null
@@ -1,211 +0,0 @@
-"""Culture process taxon mixing class exploit_social_learning."""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-from pycopancore.model_components.base import interface as B
-from .. import interface as I
-from .... import Step
-
-import numpy as np
-import networkx as nx
-
-
-class Culture (I.Culture):
- """Culture process taxon mixin for exploit_social_learning."""
-
- # process-related methods:
-
- def social_update(self, t):
- """Execute the social update.
-
- Parameters
- ----------
- t : float
- time
-
- Returns
- -------
-
- """
- self.last_execution_time = t
- agent_i = self.get_update_agent()
-
- # Step (1)
- if self.acquaintance_network.neighbors(agent_i):
- agent_j = np.random.choice(
- list(self.acquaintance_network.neighbors(agent_i)))
- # Step (2): Compare strategies of i and j:
- # If they are the same, do nothing. Else change i's strategy.
- if agent_i.strategy != agent_j.strategy:
- # Step (2.1)
- if np.random.random() < agent_i.rewiring_prob:
- self.reconnect(agent_i, agent_j)
- # Step (2.2)
- else:
- self.change_strategy(agent_i, agent_j)
- # Step (3)
- self.set_new_update_time(agent_i)
-
- if self.check_for_consensus():
- print('Consensus! time ', t)
-
- def reconnect(self, agent_i, agent_j):
- """Reconnect agent_i from agent_j and connect it to k.
-
- Disconnect agent_i from agent_j and connect agent_i
- to a randomly chosen agent_k with the same strategy,
- agent_i.strategy == agent_k.strategy.
-
- Parameters
- ----------
- agent_i : Agent (Individual or SocialSystem)
- agent_j : Agent (Individual or SocialSystem)
-
- Returns
- -------
-
- """
- # Find a random stranger agent_k with same strategy as agent_i
- all_non_neighbors = \
- list(set(self.acquaintance_network.nodes())
- - set(self.acquaintance_network.neighbors(agent_i)))
- strategy_i = agent_i.strategy
- for stranger in all_non_neighbors:
- if stranger.strategy != strategy_i:
- all_non_neighbors.remove(stranger)
- if not all_non_neighbors:
- print('No possible neighbors with different strategy.')
- else:
- # Disconnect agent_i and agent_j
- self.acquaintance_network.remove_edge(agent_i, agent_j)
- # Connect agent_i and agent_k
- agent_k = np.random.choice(all_non_neighbors)
- self.acquaintance_network.add_edge(agent_i, agent_k)
-
- def change_strategy(self, agent_i, agent_j):
- """Change strategy of agent_i to agent_j's.
-
- Change the strategy of agent_i to the strategy of agent_j
- depending on their respective harvest rates and the imitation tendency
- according to a sigmoidal function.
-
- Parameters
- ----------
- agent_i : Agent (Individual or SocialSystem)
- Agent i whose strategy is to be changed to agent j's strategy
- agent_j : Agent (Individual or SocialSystem)
- Agent j whose strategy is imitated
- Returns
- -------
-
- """
- probability = 0.5 * np.tanh(agent_i.imitation_tendency *
- (agent_j.get_harvest_rate() -
- agent_i.get_harvest_rate()) + 1)
- if np.random.random() < probability:
- agent_i.strategy = agent_j.strategy
-
- def get_update_agent(self):
- """Return the agent with the closest waiting time.
-
- Choose from all agents the one with the smallest update_time.
- Returns
- -------
-
- """
- next_agent = list(self.acquaintance_network.nodes())[0]
- for agent in self.acquaintance_network:
- if agent.update_time < next_agent.update_time:
- next_agent = agent
- return next_agent
-
- def set_new_update_time(self, agent):
- """Set next time step when agent is to be called again.
-
- Set the attribute update_time of agent to
- old_update_time + new_update_time, where new_update_time is again
- drawn from an exponential distribution.
-
- Parameters
- ----------
- agent : Agent (Individual or SocialSystem)
- The agent whose new update_time should be drawn and set.
-
- Returns
- -------
-
- """
- # print('old_update_time: ',individual.update_time)
- new_update_time = np.random.exponential(agent.average_waiting_time)
- agent.update_time += new_update_time
-
- def check_for_consensus(self):
- """Check if the model has run into a consensus state.
-
- The model is in a consensus state if in each connected component
- all agents use the same strategy. In this case, there will be no more
- change of strategies since the agents are only connected to agents
- with the same strategy.
-
- Returns
- -------
- consensus : bool
- True if model is into consensus state, otherwise False
- """
- cc = nx.connected_components(self.acquaintance_network)
- # iterate through all connected components
- for component in cc:
- # iterate through all agents in this component
- stratlist = []
- for j in component:
- # check if all agents of component have the same strategy
- stratlist.append(j.strategy)
- if stratlist.count(stratlist[0]) != len(stratlist):
- self.consensus = False
- return self.consensus
-
- # If in each component, all agents have the same strategy, then a
- # consensus state is reached
- self.consensus = True
- return self.consensus
-
- def step_timing(self,
- t):
- """Return the next time step is to be called.
-
- This function is used to get to know when the step function is
- to be called.
- Parameters
- ----------
- t : float
- time
-
- Returns
- -------
-
- """
- if isinstance(self.last_execution_time, type(None)):
- self.last_execution_time = 0
- if t < self.last_execution_time:
- print('last execution time after t!')
-
- next_time = list(self.acquaintance_network.nodes())[0].update_time
- for agent in self.acquaintance_network:
- if agent.update_time < next_time:
- next_time = agent.update_time
- if t > next_time:
- print('next update time before t!')
- return next_time
-
- processes = [Step('Social Update is a step function',
- [I.Culture.acquaintance_network,
- B.Culture.worlds.individuals.strategy, B.Culture.worlds.individuals.update_time,
- I.Culture.consensus],
- [step_timing, social_update])]
diff --git a/pycopancore/model_components/exploit_social_learning/implementation/individual.py b/pycopancore/model_components/exploit_social_learning/implementation/individual.py
deleted file mode 100644
index 54ff2f60..00000000
--- a/pycopancore/model_components/exploit_social_learning/implementation/individual.py
+++ /dev/null
@@ -1,65 +0,0 @@
-"""Individual entity type of the component exploit_social_learning."""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-from .. import interface as I
-import numpy as np
-
-
-class Individual(I.Individual):
- """Define properties of exploit_social_learning individual."""
-
- # standard methods:
-
- def __init__(self,
- *,
- strategy=0,
- imitation_tendency=1,
- rewiring_prob=0,
- average_waiting_time=1,
- **kwargs
- ):
- """Initialize an instance of Individual."""
- super().__init__(**kwargs) # must be the first line
- self.strategy = strategy
- self.imitation_tendency = imitation_tendency
- self.rewiring_prob = rewiring_prob
- self.average_waiting_time = average_waiting_time
- self.update_time = np.random.exponential(self.average_waiting_time)
-
- pass
-
- def __lt__(self, other):
- """Make objects sortable."""
- return self._uid < other._uid
-
- def deactivate(self):
- """Deactivate an individual."""
- # TODO: add custom code here:
- pass
- super().deactivate() # must be the last line
-
- def reactivate(self):
- """Reactivate an individual."""
- super().reactivate() # must be the first line
- # TODO: add custom code here:
- pass
-
- # process-related methods:
-
- def get_harvest_rate(self):
- """Compute a random harvest rate of individual.
-
- This method should be overwritten with a method of the class
- simple_extraction.individual.
- """
- return np.random.rand()
-
- processes = []
diff --git a/pycopancore/model_components/exploit_social_learning/implementation/world.py b/pycopancore/model_components/exploit_social_learning/implementation/world.py
deleted file mode 100644
index 2b19b9bf..00000000
--- a/pycopancore/model_components/exploit_social_learning/implementation/world.py
+++ /dev/null
@@ -1,131 +0,0 @@
-"""The exploit_social_learning.world class.
-
-In this module the exploit_social_learning World mixing class inherits from
-World_ in that basic variables and parameters are defined.
-"""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-import numpy as np
-from pycopancore.model_components import abstract
-from pycopancore.model_components.exploit_social_learning import interface as I
-
-
-class World (I.World, abstract.World):
- """Define properties of exploit_social_learning.world.
-
- Inherits from I.World as the interface with all necessary variables
- and parameters.
- """
-
- def __init__(self,
- *,
- contact_network=None,
- agent_list=[],
- **kwargs
- ):
- """Initialize an instance of World.
-
- Parameters
- ----------
- agent_list
- """
- super(World, self).__init__(**kwargs)
-
- self.contact_network = contact_network
- self.agent_list = agent_list
- # assert isinstance(self.contact_network, np.ndarray),\
- # 'Given network is not an numpy.ndarray.'
- # assert (len(self.agent_list) == len(self.contact_network[:, 0]) and
- # len(self.agent_list) == len(self.contact_network[0, :])),\
- # 'agent_list and contact_network do not have suitable dimensions.'
- # # Make sure that all diagonal entries are zero.
- # np.fill_diagonal(self.contact_network, 0)
-
- processes = []
-
- def has_neighbor(self, agent):
- """Return True if agent has a neighbor and False if not.
-
- Parameters
- ----------
- agent Agent: Individual or SocialSystem
-
- Return
- ------
- boolean
- """
- assert agent in self.agent_list, 'agent is not in agent_list'
- index = self.agent_list.index(agent)
- isolated = True
- i = 0
- n = self.contact_network[0].size
-
- while isolated and i < n:
- if self.contact_network[index, i] != 0:
- isolated = False
- i += 1
- return not isolated
-
- def get_random_neighbor(self, agent):
- """Return a random neighbor of agent.
-
- Parameters
- ----------
- agent Agent: Individual or SocialSystem
-
- Return
- ------
- neighbor Agent
- """
- assert agent in self.agent_list, 'agent is not in agent_list'
- neighbors = self.get_neighbors(agent)
- neighbor = np.random.choice(neighbors)
- return neighbor
-
- def get_neighbors(self, agent):
- """Return a list of the neighbors of agent.
-
- Parameters
- ----------
- agent Agent: Individual or SocialSystem
-
- Returns
- -------
- neighbors: A list of all neighbors of agent
- """
- assert agent in self.agent_list, 'agent is not in agent_list'
- index = self.agent_list.index(agent)
- n = self.contact_network[0].size
- neighbors = []
- for i in range(n):
- if self.contact_network[index, i] != 0:
- neighbors.append(self.agent_list[i])
- return neighbors
-
- def get_non_neighbors(self, agent):
- """Return a list of all agents that are not connected to agent.
-
- Parameters
- ----------
- agent Agent: Individual or SocialSystem
-
- Returns
- -------
- non_neighbors: A list of all agents that are no neighbors of agent
- """
- assert agent in self.agent_list, 'agent is not in agent_list'
- index = self.agent_list.index(agent)
- n = self.contact_network[0].size
- non_neighbors = []
- for i in range(n):
- if index != i and self.contact_network[index, i] == 0:
- non_neighbors.append(self.agent_list[i])
- return non_neighbors
diff --git a/pycopancore/model_components/exploit_social_learning/interface.py b/pycopancore/model_components/exploit_social_learning/interface.py
deleted file mode 100644
index 1f7f28fe..00000000
--- a/pycopancore/model_components/exploit_social_learning/interface.py
+++ /dev/null
@@ -1,67 +0,0 @@
-"""model component Interface exploit_social_learning."""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-# TODO: use variables from the master data model wherever possible:
-from ... import master_data_model as D
-# TODO: uncomment and adjust of you need further variables from another
-# model component:
-# import ..BBB.interface as BBB
-# TODO: uncomment and adjust only if you really need other variables:
-from ... import Variable
-
-
-class Model(object):
- """Interface for Model mixin."""
-
- # metadata:
- name = "..."
- """Exploit Social Learning"""
- description = "..."
- """The Exploit social learning dynamics including reward based imitation
- behaviour"""
- requires = []
- """list of other model components required for this model component to
- make sense"""
-
-
-# entity types:
-class World(object):
- """Define Interface for World."""
-
- agent_list = Variable('list of all agents', 'all agents in network')
-
-
-class Individual(object):
- """Interface for Individual."""
-
- strategy = Variable('harvesting strategy', 'harvesting strategy indiv.')
- imitation_tendency = Variable('imitation tendency', 'former rationality')
- rewiring_prob = Variable('rewiring probability', 'rew. prob.')
- average_waiting_time = Variable('estimated waiting time tau', 'tau')
- update_time = Variable('next update time', 'next time for update')
-
-
-class Cell(object):
- """Interface for Cell."""
-
- stock = Variable('current stock', 'current stock of resource')
- growth_rate = Variable('growth rate', 'growth rate of resource')
-
-
-class Culture(object):
- """Define Interface for Culture."""
-
- acquaintance_network = D.CUL.acquaintance_network
- last_execution_time = Variable('last exec.time',
- 'last time a step was executed',
- default=-1)
- consensus = Variable('consensus state', 'indicating if consensus is there',
- default=False)
diff --git a/pycopancore/model_components/exploit_social_learning/model.py b/pycopancore/model_components/exploit_social_learning/model.py
deleted file mode 100644
index ab4fcaa5..00000000
--- a/pycopancore/model_components/exploit_social_learning/model.py
+++ /dev/null
@@ -1,30 +0,0 @@
-"""Model mixing class exploit_social_learning.
-
-It includes reward based imitation behaviour.
-"""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-from . import interface as I
-# import all needed entity type implementation classes:
-from .implementation import World, Individual, Culture
-# import all needed process taxon implementation classes:
-# none needed
-
-
-class Model (I.Model):
- """Model mixin class."""
-
- # mixins provided by this model component:
-
- entity_types = [World, Individual]
- """list of entity types augmented by this component"""
- process_taxa = [Culture]
- """list of process taxa augmented by this component"""
diff --git a/pycopancore/model_components/majority_decision/__init__.py b/pycopancore/model_components/majority_decision/__init__.py
deleted file mode 100644
index 6852092c..00000000
--- a/pycopancore/model_components/majority_decision/__init__.py
+++ /dev/null
@@ -1,26 +0,0 @@
-"""
-Model component package template.
-
-TODO:
-Copy this folder, rename it to the name of your model component,
-then adjust or fill in code and documentation in all modules wherever marked by "TODO:",
-finally remove these instructions.
-See the model component development tutorial for details.
-"""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-from . import interface
-
-# export all implementation classes:
-from .implementation import *
-
-# export model component mixin class:
-from .model import Model
diff --git a/pycopancore/model_components/majority_decision/implementation/__init__.py b/pycopancore/model_components/majority_decision/implementation/__init__.py
deleted file mode 100644
index 89786d7c..00000000
--- a/pycopancore/model_components/majority_decision/implementation/__init__.py
+++ /dev/null
@@ -1,20 +0,0 @@
-"""
-Model component implementation subpackage template.
-"""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-# TODO: adjust the following lists to your needs:
-
-# export all provided entity type implementation mixin classes:
-from .social_system import SocialSystem
-from .individual import Individual
-
-from .culture import Culture
diff --git a/pycopancore/model_components/majority_decision/implementation/culture.py b/pycopancore/model_components/majority_decision/implementation/culture.py
deleted file mode 100644
index b4981741..00000000
--- a/pycopancore/model_components/majority_decision/implementation/culture.py
+++ /dev/null
@@ -1,37 +0,0 @@
-"""Culture process taxon mixing class template.
-
-TODO: adjust or fill in code and documentation wherever marked by "TODO:",
-then remove these instructions
-"""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-from .. import interface as I
-# from .... import master_data_model as D
-
-
-class Culture (I.Culture):
- """Culture process taxon mixin implementation class."""
-
- # standard methods:
-
- def __init__(self,
- # *, # TODO: uncomment when adding named args behind here
- **kwargs):
- """Initialize the unique instance of Culture."""
- super().__init__(**kwargs) # must be the first line
- # TODO: add custom code here:
- pass
-
- # process-related methods:
-
- # TODO: add some if needed...
-
- processes = [] # TODO: instantiate and list process objects here
diff --git a/pycopancore/model_components/majority_decision/implementation/individual.py b/pycopancore/model_components/majority_decision/implementation/individual.py
deleted file mode 100644
index b5e385a9..00000000
--- a/pycopancore/model_components/majority_decision/implementation/individual.py
+++ /dev/null
@@ -1,49 +0,0 @@
-"""Individual entity type class template.
-
-TODO: adjust or fill in code and documentation wherever marked by "TODO:",
-then remove these instructions
-"""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-from .. import interface as I
-# from .... import master_data_model as D
-
-
-class Individual (I.Individual):
- """Individual entity type mixin implementation class."""
-
- # standard methods:
-
- def __init__(self,
- # *, # TODO: uncomment when adding named args behind here
- **kwargs):
- """Initialize an instance of Individual."""
- super().__init__(**kwargs) # must be the first line
- # TODO: add custom code here:
- pass
-
- def deactivate(self):
- """Deactivate an individual."""
- # TODO: add custom code here:
- pass
- super().deactivate() # must be the last line
-
- def reactivate(self):
- """Reactivate an individual."""
- super().reactivate() # must be the first line
- # TODO: add custom code here:
- pass
-
- # process-related methods:
-
- # TODO: add some if needed...
-
- processes = [] # TODO: instantiate and list process objects here
diff --git a/pycopancore/model_components/majority_decision/implementation/social_system.py b/pycopancore/model_components/majority_decision/implementation/social_system.py
deleted file mode 100644
index 35ee0aef..00000000
--- a/pycopancore/model_components/majority_decision/implementation/social_system.py
+++ /dev/null
@@ -1,66 +0,0 @@
-"""SocialSystem entity type mixing class template.
-
-TODO: adjust or fill in code and documentation wherever marked by "TODO:",
-then remove these instructions
-"""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-from .. import interface as I
-# from .... import master_data_model as D
-
-from .... import Explicit
-
-import operator
-
-
-class SocialSystem (I.SocialSystem):
- """SocialSystem entity type mixin implementation class."""
-
- # standard methods:
-
- def __init__(self,
- # *, # TODO: uncomment when adding named args behind here
- **kwargs):
- """Initialize an instance of SocialSystem."""
- super().__init__(**kwargs) # must be the first line
- # TODO: add custom code here:
- pass
-
- def deactivate(self):
- """Deactivate a social_system."""
- # TODO: add custom code here:
- pass
- super().deactivate() # must be the last line
-
- def reactivate(self):
- """Reactivate a social_system."""
- super().reactivate() # must be the first line
- # TODO: add custom code here:
- pass
-
- # process-related methods:
-
- def get_majority_opinion(self, t):
- opinion_count = {}
- for op in self.culture.possible_opinions:
- opinion_count[op] = sum(1 for _ in filter(
- lambda ind: ind.opinion == op, self.individuals))
-
- self.opinion = max(opinion_count.items(),
- key=operator.itemgetter(1))[0]
-
- processes = [
- Explicit(
- "identification of majority opinion",
- [I.SocialSystem.opinion],
- get_majority_opinion
- )
- ]
diff --git a/pycopancore/model_components/majority_decision/interface.py b/pycopancore/model_components/majority_decision/interface.py
deleted file mode 100644
index d295f6c5..00000000
--- a/pycopancore/model_components/majority_decision/interface.py
+++ /dev/null
@@ -1,73 +0,0 @@
-"""model component Interface template.
-
-TODO: adjust or fill in code and documentation wherever marked by "TODO:", then
-remove these instructions.
-"""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-# TODO: use variables from the master data model wherever possible:
-from ... import master_data_model as D
-# TODO: uncomment and adjust of you need further variables from another
-# model component:
-# import ..BBB.interface as BBB
-from .. import adaptive_voter_opinion_formation as avof
-# TODO: uncomment and adjust only if you really need other variables:
-from ... import Variable
-
-
-class Model (object):
- """Interface for Model mixin."""
-
- # metadata:
- name = "majority decision"
- """a unique name for the model component"""
- description = "find the opinion the most represented in a social_system"
- """some longer description"""
- requires = [avof]
- """list of other model components required for this model component to
- make sense"""
-
- # Notes:
- # - Model does NOT define variables or parameters, only entity types
- # and process taxons do!
- # - implementation.Model lists these entity-types and process taxons
-
-
-# entity types:
-
-
-class SocialSystem (object):
- """Interface for SocialSystem entity type mixin."""
-
- # endogenous variables:
-
- opinion = avof.Individual.opinion.copy()
-
- # exogenous variables / parameters:
-
-
-class Individual (object):
- """Interface for Individual entity type mixin."""
-
- # endogenous variables:
-
- opinion = avof.Individual.opinion
-
- # exogenous variables / parameters:
-
-
-class Culture (object):
- """Interface for Culture process taxon mixin."""
-
- # endogenous variables:
- acquaintance_network = D.CUL.acquaintance_network
-
- # exogenous variables / parameters:
diff --git a/pycopancore/model_components/majority_decision/model.py b/pycopancore/model_components/majority_decision/model.py
deleted file mode 100644
index ed844312..00000000
--- a/pycopancore/model_components/majority_decision/model.py
+++ /dev/null
@@ -1,31 +0,0 @@
-"""Model mixing class template.
-
-TODO: adjust or fill in code and documentation wherever marked by "TODO:",
-then remove these instructions
-"""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-from . import interface as I
-# import all needed entity type implementation classes:
-from .implementation import SocialSystem, Individual
-# import all needed process taxon implementation classes:
-from .implementation import Culture
-
-
-class Model (I.Model):
- """Model mixin class."""
-
- # mixins provided by this model component:
-
- entity_types = [SocialSystem, Individual]
- """list of entity types augmented by this component"""
- process_taxa = [Culture]
- """list of process taxa augmented by this component"""
diff --git a/pycopancore/model_components/maxploit_individual_layer/__init__.py b/pycopancore/model_components/maxploit_individual_layer/__init__.py
deleted file mode 100644
index 1e1226a7..00000000
--- a/pycopancore/model_components/maxploit_individual_layer/__init__.py
+++ /dev/null
@@ -1,18 +0,0 @@
-"""Model component package simple_extraction."""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-from . import interface
-
-# export all implementation classes:
-from .implementation import *
-
-# export model component mixin class:
-from .model import Model
diff --git a/pycopancore/model_components/maxploit_individual_layer/implementation/__init__.py b/pycopancore/model_components/maxploit_individual_layer/implementation/__init__.py
deleted file mode 100644
index f990b981..00000000
--- a/pycopancore/model_components/maxploit_individual_layer/implementation/__init__.py
+++ /dev/null
@@ -1,22 +0,0 @@
-"""
-Model component implementation subpackage exploit_social_learning.
-"""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-# TODO: adjust the following lists to your needs:
-
-# export all provided entity type implementation mixin classes:
-from .world import World
-from .individual import Individual
-
-# export all provided process taxon implementation mixin classes:
-
-from .culture import Culture
diff --git a/pycopancore/model_components/maxploit_social_norms/__init__.py b/pycopancore/model_components/maxploit_social_norms/__init__.py
deleted file mode 100644
index 1e1226a7..00000000
--- a/pycopancore/model_components/maxploit_social_norms/__init__.py
+++ /dev/null
@@ -1,18 +0,0 @@
-"""Model component package simple_extraction."""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-from . import interface
-
-# export all implementation classes:
-from .implementation import *
-
-# export model component mixin class:
-from .model import Model
diff --git a/pycopancore/model_components/maxploit_social_norms/implementation/__init__.py b/pycopancore/model_components/maxploit_social_norms/implementation/__init__.py
deleted file mode 100644
index 3c7f3304..00000000
--- a/pycopancore/model_components/maxploit_social_norms/implementation/__init__.py
+++ /dev/null
@@ -1,22 +0,0 @@
-"""
-Model component implementation subpackage exploit_social_learning.
-"""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-# TODO: adjust the following lists to your needs:
-
-# export all provided entity type implementation mixin classes:
-from .individual import Individual
-from .group import Group
-
-# export all provided process taxon implementation mixin classes:
-
-from .culture import Culture
diff --git a/pycopancore/model_components/most_simple_vegetation/__init__.py b/pycopancore/model_components/most_simple_vegetation/__init__.py
deleted file mode 100644
index 20c2fade..00000000
--- a/pycopancore/model_components/most_simple_vegetation/__init__.py
+++ /dev/null
@@ -1,18 +0,0 @@
-"""Model component package most_simple_vegetation."""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-from . import interface
-
-# export all implementation classes:
-from .implementation import *
-
-# export model component mixin class:
-from .model import Model
diff --git a/pycopancore/model_components/most_simple_vegetation/implementation/__init__.py b/pycopancore/model_components/most_simple_vegetation/implementation/__init__.py
deleted file mode 100644
index 542f6aa4..00000000
--- a/pycopancore/model_components/most_simple_vegetation/implementation/__init__.py
+++ /dev/null
@@ -1,19 +0,0 @@
-"""
-Model component implementation subpackage most_simple_vegetation.
-"""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-# TODO: adjust the following lists to your needs:
-
-# export all provided entity type implementation mixin classes:
-from .cell import Cell
-
-# export all provided process taxon implementation mixin classes:
diff --git a/pycopancore/model_components/most_simple_vegetation/implementation/cell.py b/pycopancore/model_components/most_simple_vegetation/implementation/cell.py
deleted file mode 100644
index 5b8a538a..00000000
--- a/pycopancore/model_components/most_simple_vegetation/implementation/cell.py
+++ /dev/null
@@ -1,74 +0,0 @@
-"""Cell entity type mixing of class most_simple_vegetation."""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-from pycopancore import ODE
-from pycopancore.model_components.simple_extraction import interface as I
-
-
-class Cell(I.Cell):
- """Cell entity type mixin implementation class."""
-
- # standard methods:
-
- def __init__(self,
- *,
- stock=1,
- capacity=1,
- growth_rate=1,
- **kwargs
- ):
- """Initialize an instance of Cell."""
- super().__init__(**kwargs)
-
- self.stock = stock
- self.capacity = capacity
- self.growth_rate = growth_rate
-
- pass
-
- def deactivate(self):
- """Deactivate a cell."""
- # TODO: add custom code here:
- pass
- super().deactivate() # must be the last line
-
- def reactivate(self):
- """Reactivate a cell."""
- super().reactivate() # must be the first line
- # TODO: add custom code here:
- pass
-
- # process-related methods:
-
- def logistic_growth(self, t):
- """Compute the biophysical logistic growth function of cell's stock.
-
- Parameters
- ----------
- t : float
- time
-
- Returns
- -------
-
- """
- g = self.growth_rate
- s = self.stock
- smax = self.capacity
- self.d_stock += g * (1 - s / smax) * s
-
- # processes:
-
- processes = [
- ODE('logistic_growth_function',
- [I.Cell.stock],
- logistic_growth)
- ]
diff --git a/pycopancore/model_components/most_simple_vegetation/interface.py b/pycopancore/model_components/most_simple_vegetation/interface.py
deleted file mode 100644
index 74269869..00000000
--- a/pycopancore/model_components/most_simple_vegetation/interface.py
+++ /dev/null
@@ -1,41 +0,0 @@
-"""model component Interface most_simple_vegetation."""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-# TODO: use variables from the master data model wherever possible:
-# from ... import master_data_model as D
-# TODO: uncomment and adjust of you need further variables from another
-# model component:
-# import ..BBB.interface as BBB
-# TODO: uncomment and adjust only if you really need other variables:
-from ... import Variable
-
-
-class Model(object):
- """Interface for Model mixin."""
-
- # metadata:
- name = "..."
- """most simple vegetation"""
- description = "..."
- """A most simple vegetation growth model"""
- requires = []
- """list of other model components required for this model component to
- make sense"""
-
-
-# entity types:
-
-class Cell(object):
- """Interface for Cell."""
-
- stock = Variable('current stock', 'current stock of resource')
- capacity = Variable('capacity', 'capacity of resource')
- growth_rate = Variable('growth rate', 'growth rate of resource')
diff --git a/pycopancore/model_components/most_simple_vegetation/model.py b/pycopancore/model_components/most_simple_vegetation/model.py
deleted file mode 100644
index eaa3b0e6..00000000
--- a/pycopancore/model_components/most_simple_vegetation/model.py
+++ /dev/null
@@ -1,27 +0,0 @@
-"""Model mixing class most_simple_vegetation."""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-from . import interface as I
-# import all needed entity type implementation classes:
-from .implementation import Cell
-# import all needed process taxon implementation classes:
-# none needed
-
-
-class Model (I.Model):
- """Model mixin class."""
-
- # mixins provided by this model component:
-
- entity_types = [Cell]
- """list of entity types augmented by this component"""
- process_taxa = []
- """list of process taxa augmented by this component"""
diff --git a/pycopancore/model_components/seven_dwarfs/implementation/cell.py b/pycopancore/model_components/seven_dwarfs/implementation/cell.py
index 1372c6c2..a15e74d1 100644
--- a/pycopancore/model_components/seven_dwarfs/implementation/cell.py
+++ b/pycopancore/model_components/seven_dwarfs/implementation/cell.py
@@ -14,7 +14,7 @@
# License: BSD 2-clause license
from .. import interface as I
-from pycopancore import Event
+from pycopancore.process_types import Event
import numpy as np
# from .... import master_data_model as D
diff --git a/pycopancore/model_components/seven_dwarfs/implementation/group.py b/pycopancore/model_components/seven_dwarfs/implementation/group.py
index 4da3f6b7..7217a51b 100644
--- a/pycopancore/model_components/seven_dwarfs/implementation/group.py
+++ b/pycopancore/model_components/seven_dwarfs/implementation/group.py
@@ -13,14 +13,11 @@
# Contact: core@pik-potsdam.de
# License: BSD 2-clause license
-from .. import interface as I
-# from .... import master_data_model as D
+# TODO: import those process types you need:
+from pycopancore.process_types import Explicit
-# TODO: uncomment this if you need ref. variables such as B.Individual.cell:
-from ...base import interface as B
+from .. import interface as I
-# TODO: import those process types you need:
-from .... import Explicit
class Group (I.Group):
"""Group entity type mixin implementation class."""
diff --git a/pycopancore/model_components/seven_dwarfs/implementation/individual.py b/pycopancore/model_components/seven_dwarfs/implementation/individual.py
index c48d947c..11415c8a 100644
--- a/pycopancore/model_components/seven_dwarfs/implementation/individual.py
+++ b/pycopancore/model_components/seven_dwarfs/implementation/individual.py
@@ -16,7 +16,7 @@
from .. import interface as I
from pycopancore.model_components.base import interface as B
# from .... import master_data_model as D
-from pycopancore import ODE, Step, Explicit, Event
+from pycopancore.process_types import ODE, Step, Explicit, Event
import numpy as np
diff --git a/pycopancore/model_components/seven_dwarfs/implementation/social_system.py b/pycopancore/model_components/seven_dwarfs/implementation/social_system.py
index b0762c5e..97810bde 100644
--- a/pycopancore/model_components/seven_dwarfs/implementation/social_system.py
+++ b/pycopancore/model_components/seven_dwarfs/implementation/social_system.py
@@ -15,7 +15,7 @@
from .. import interface as I
from pycopancore.model_components.base import interface as B
# from .... import master_data_model as D
-from pycopancore import ODE, Step, Explicit, Event
+from pycopancore.process_types import ODE, Step, Explicit, Event
import numpy as np
diff --git a/pycopancore/model_components/seven_dwarfs/interface.py b/pycopancore/model_components/seven_dwarfs/interface.py
index 7176b1a8..f39da64f 100644
--- a/pycopancore/model_components/seven_dwarfs/interface.py
+++ b/pycopancore/model_components/seven_dwarfs/interface.py
@@ -19,10 +19,9 @@
# model component:
# import ..BBB.interface as BBB
# TODO: uncomment and adjust only if you really need other variables:
-from ... import Variable
-from ... import master_data_model as D
-from ...data_model.master_data_model import CUL
-
+from pycopancore.data_model import Variable
+from pycopancore.data_model import master_data_model as D
+from pycopancore.data_model.master_data_model import CUL
class Model (object):
diff --git a/pycopancore/model_components/simple_extraction/__init__.py b/pycopancore/model_components/simple_extraction/__init__.py
deleted file mode 100644
index 1e1226a7..00000000
--- a/pycopancore/model_components/simple_extraction/__init__.py
+++ /dev/null
@@ -1,18 +0,0 @@
-"""Model component package simple_extraction."""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-from . import interface
-
-# export all implementation classes:
-from .implementation import *
-
-# export model component mixin class:
-from .model import Model
diff --git a/pycopancore/model_components/simple_extraction/implementation/__init__.py b/pycopancore/model_components/simple_extraction/implementation/__init__.py
deleted file mode 100644
index bdf1b499..00000000
--- a/pycopancore/model_components/simple_extraction/implementation/__init__.py
+++ /dev/null
@@ -1,20 +0,0 @@
-"""
-Model component implementation subpackage simple_extraction.
-"""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-# TODO: adjust the following lists to your needs:
-
-# export all provided entity type implementation mixin classes:
-from .cell import Cell
-from .individual import Individual
-
-# export all provided process taxon implementation mixin classes:
diff --git a/pycopancore/model_components/simple_extraction/implementation/cell.py b/pycopancore/model_components/simple_extraction/implementation/cell.py
deleted file mode 100644
index 9ad1f45e..00000000
--- a/pycopancore/model_components/simple_extraction/implementation/cell.py
+++ /dev/null
@@ -1,61 +0,0 @@
-"""Cell entity type mixing of class simple_extraction."""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-from pycopancore import ODE
-from pycopancore.model_components.simple_extraction import interface as I
-
-
-class Cell(I.Cell):
- """Cell entity type mixin implementation class."""
-
- # standard methods:
-
- def __init__(self,
- *,
- stock=1,
- growth_rate=1,
- **kwargs
- ):
- """Initialize an instance of Cell."""
- super().__init__(**kwargs)
-
- self.stock = stock
- self.growth_rate = growth_rate
-
-
- def deactivate(self):
- """Deactivate a cell."""
- # TODO: add custom code here:
-
- super().deactivate() # must be the last line
-
- def reactivate(self):
- """Reactivate a cell."""
- super().reactivate() # must be the first line
- # TODO: add custom code here:
-
- # process-related methods:
-
- def harvest(self, t):
- """Compute the harvesting dynamics.
-
- Parameters
- ----------
- t : float
- time
-
- Returns
- -------
-
- """
- self.d_stock -= self.individual.get_harvest_rate()
-
- processes = [ODE('harvesting function', [I.Cell.stock], harvest)]
diff --git a/pycopancore/model_components/simple_extraction/implementation/individual.py b/pycopancore/model_components/simple_extraction/implementation/individual.py
deleted file mode 100644
index b66b4822..00000000
--- a/pycopancore/model_components/simple_extraction/implementation/individual.py
+++ /dev/null
@@ -1,59 +0,0 @@
-"""Individual entity type of the component simple_extraction."""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-from .. import interface as I
-
-
-class Individual(I.Individual):
- """Define properties of simple_extraction individual."""
-
- # standard methods:
-
- def __init__(self,
- *,
- strategy=0,
- **kwargs
- ):
- """Initialize an instance of Individual."""
- super().__init__(**kwargs) # must be the first line
- self.strategy = strategy
-
-
- def __lt__(self, other):
- """Make objects sortable."""
- return self._uid < other._uid
-
- def deactivate(self):
- """Deactivate an individual."""
- # TODO: add custom code here:
-
- super().deactivate() # must be the last line
-
- def reactivate(self):
- """Reactivate an individual."""
- super().reactivate() # must be the first line
- # TODO: add custom code here:
-
-
- # process-related methods:
-
- def get_harvest_rate(self):
- """Compute the harvest rate of the individual on its cell.
-
- Returns
- -------
- harvest : float
- """
- effort = 0.5 * self.cell.growth_rate * (3 - 2 * self.strategy)
- harvest = effort * self.cell.stock
- return harvest
-
- processes = []
diff --git a/pycopancore/model_components/simple_extraction/interface.py b/pycopancore/model_components/simple_extraction/interface.py
deleted file mode 100644
index ffb8d3c3..00000000
--- a/pycopancore/model_components/simple_extraction/interface.py
+++ /dev/null
@@ -1,46 +0,0 @@
-"""model component Interface simple_extraction."""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-# TODO: use variables from the master data model wherever possible:
-# from ... import master_data_model as D
-# TODO: uncomment and adjust of you need further variables from another
-# model component:
-from ..exploit_social_learning import Individual as ESLIndividual
-# TODO: uncomment and adjust only if you really need other variables:
-from ... import Variable
-
-
-class Model(object):
- """Interface for Model mixin."""
-
- # metadata:
- name = "..."
- """simple extraction"""
- description = "..."
- """A simple extraction model"""
- requires = []
- """list of other model components required for this model component to
- make sense"""
-
-
-# entity types:
-
-class Individual(object):
- """Interface for Individual."""
-
- strategy = ESLIndividual.strategy
-
-
-class Cell(object):
- """Interface for Cell."""
-
- stock = Variable('current stock', 'current stock of resource')
- growth_rate = Variable('growth rate', 'growth rate of resource')
diff --git a/pycopancore/model_components/simple_extraction/model.py b/pycopancore/model_components/simple_extraction/model.py
deleted file mode 100644
index b6a77118..00000000
--- a/pycopancore/model_components/simple_extraction/model.py
+++ /dev/null
@@ -1,27 +0,0 @@
-"""Model mixing class simple_extraction."""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-from . import interface as I
-# import all needed entity type implementation classes:
-from .implementation import Cell, Individual
-# import all needed process taxon implementation classes:
-# none needed
-
-
-class Model(I.Model):
- """Model mixin class."""
-
- # mixins provided by this model component:
-
- entity_types = [Cell, Individual]
- """list of entity types augmented by this component"""
- process_taxa = []
- """list of process taxa augmented by this component"""
diff --git a/pycopancore/model_components/snowwhite/__init__.py b/pycopancore/model_components/snowwhite/__init__.py
deleted file mode 100644
index ffe9fe83..00000000
--- a/pycopancore/model_components/snowwhite/__init__.py
+++ /dev/null
@@ -1,24 +0,0 @@
-"""
-Model component package template.
-
-TODO:
-Copy this folder, rename it to the name of your model component,
-then adjust or fill in code and documentation in all modules wherever marked by "TODO:",
-finally remove these instructions.
-See the model component development tutorial for details.
-"""
-# This file is part of pycopancore.
-#
-# Copyright (C) 2017 by COPAN team at Potsdam Institute for Climate Impact
-# Research
-#
-# URL:
-# License: MIT license
-
-from . import interface
-
-# export all implementation classes:
-from .implementation import *
-
-# export model component mixin class:
-from .model import Model
diff --git a/pycopancore/model_components/snowwhite/implementation/__init__.py b/pycopancore/model_components/snowwhite/implementation/__init__.py
deleted file mode 100644
index 8cce37d2..00000000
--- a/pycopancore/model_components/snowwhite/implementation/__init__.py
+++ /dev/null
@@ -1,13 +0,0 @@
-"""
-Model component implementation subpackage template.
-"""
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016 by COPAN team at Potsdam Institute for Climate Impact
-# Research
-#
-# URL:
-# License: MIT license
-
-# export all provided entity type implementation mixin classes:
-from .cell import Cell
diff --git a/pycopancore/model_components/snowwhite/implementation/cell.py b/pycopancore/model_components/snowwhite/implementation/cell.py
deleted file mode 100644
index 8ed5cb94..00000000
--- a/pycopancore/model_components/snowwhite/implementation/cell.py
+++ /dev/null
@@ -1,40 +0,0 @@
-"""Cell entity type mixing class template.
-
-TODO: adjust or fill in code and documentation wherever marked by "TODO:",
-then remove these instructions
-"""
-# This file is part of pycopancore.
-#
-# Copyright (C) 2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# License: MIT license
-
-from .. import interface as I
-from pycopancore import Event
-import numpy as np
-
-# from .... import master_data_model as D
-
-
-class Cell (I.Cell):
- """Cell entity type mixin implementation class."""
-
- # standard methods:
-
- def snow_white_arrival(self, t):
- """Calculate snow white's arrival."""
- return t + np.random.exponential(14.)
-
- def snow_white_eating(self, unused_t):
- """Party hard."""
- print('Snow white arrives and has the munchies.')
- self.eating_stock = self.eating_stock / 2.
-
- processes = [
- Event("snow_white",
- [I.Cell.eating_stock],
- ["time", snow_white_arrival, snow_white_eating]
- )
- ]
diff --git a/pycopancore/model_components/snowwhite/interface.py b/pycopancore/model_components/snowwhite/interface.py
deleted file mode 100644
index c1de8ddd..00000000
--- a/pycopancore/model_components/snowwhite/interface.py
+++ /dev/null
@@ -1,48 +0,0 @@
-"""model component Interface template.
-
-TODO: adjust or fill in code and documentation wherever marked by "TODO:", then
-remove these instructions.
-"""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# License: MIT license
-
-# TODO: use variables from the master data model wherever possible:
-# from ... import master_data_model as D
-# TODO: uncomment and adjust of you need further variables from another
-# model component:
-# import ..BBB.interface as BBB
-# TODO: uncomment and adjust only if you really need other variables:
-from ... import Variable
-from ... import master_data_model as D
-from ..seven_dwarfs.interface import Cell as C
-
-
-class Model (object):
- """Interface for Model mixin."""
-
- # metadata:
- name = "Snwow White Component"
- description = "Snow White arrives at the Dwarf's cave."
- requires = []
- """list of other model components required for this model component to
- make sense"""
-
- # Notes:
- # - Model does NOT define variables or parameters, only entity types
- # and process taxons do!
- # - implementation.Model lists these entity-types and process taxons
-
-
-# entity types:
-
-class Cell (object):
- """Interface for Cell entity type mixin."""
-
- # endogenous variables:
- eating_stock = C.eating_stock # exogenous variables / parameters:
diff --git a/pycopancore/model_components/snowwhite/model.py b/pycopancore/model_components/snowwhite/model.py
deleted file mode 100644
index 85ba683d..00000000
--- a/pycopancore/model_components/snowwhite/model.py
+++ /dev/null
@@ -1,30 +0,0 @@
-"""Model mixing class template.
-
-TODO: adjust or fill in code and documentation wherever marked by "TODO:",
-then remove these instructions
-"""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# License: MIT license
-
-from . import interface as I
-# import all needed entity type implementation classes:
-from .implementation import Cell # TODO: adjust!
-# import all needed process taxon implementation classes:
-#from .implementation import Environment, Metabolism, Culture # TODO: adjust!
-
-
-class Model(I.Model):
- """Model mixin class."""
-
- # mixins provided by this model component:
-
- entity_types = [Cell] # TODO: adjust!
- """list of entity types augmented by this component"""
- process_taxa = [] # TODO: adjust!
- """list of process taxa augmented by this component"""
diff --git a/pycopancore/model_components/social_learning_of_environmental_friendliness/__init__.py b/pycopancore/model_components/social_learning_of_environmental_friendliness/__init__.py
deleted file mode 100644
index 6852092c..00000000
--- a/pycopancore/model_components/social_learning_of_environmental_friendliness/__init__.py
+++ /dev/null
@@ -1,26 +0,0 @@
-"""
-Model component package template.
-
-TODO:
-Copy this folder, rename it to the name of your model component,
-then adjust or fill in code and documentation in all modules wherever marked by "TODO:",
-finally remove these instructions.
-See the model component development tutorial for details.
-"""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-from . import interface
-
-# export all implementation classes:
-from .implementation import *
-
-# export model component mixin class:
-from .model import Model
diff --git a/pycopancore/model_components/social_learning_of_environmental_friendliness/implementation/__init__.py b/pycopancore/model_components/social_learning_of_environmental_friendliness/implementation/__init__.py
deleted file mode 100644
index 91998faf..00000000
--- a/pycopancore/model_components/social_learning_of_environmental_friendliness/implementation/__init__.py
+++ /dev/null
@@ -1,18 +0,0 @@
-"""
-Model component implementation subpackage template.
-"""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-# export all provided entity type implementation mixin classes:
-from .individual import Individual
-
-# export all provided process taxon implementation mixin classes:
-from .culture import Culture
diff --git a/pycopancore/model_components/social_learning_of_environmental_friendliness/implementation/culture.py b/pycopancore/model_components/social_learning_of_environmental_friendliness/implementation/culture.py
deleted file mode 100644
index d294d5fa..00000000
--- a/pycopancore/model_components/social_learning_of_environmental_friendliness/implementation/culture.py
+++ /dev/null
@@ -1,43 +0,0 @@
-"""Culture process taxon mixing class template.
-"""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-from .... import Event
-from .. import interface as I
-from ...base import interface as B
-from numpy import inf
-from numpy.random import exponential, uniform
-
-
-class Culture (I.Culture):
- """Culture process taxon mixin implementation class."""
-
- # process-related methods:
-
- def next_learning_time(self, t):
- """time of next awareness update"""
- return (inf if self.environmental_friendliness_learning_rate == 0
- else t + exponential(1. / self.environmental_friendliness_learning_rate))
-
- def let_individuals_learn(self, t):
- """let some individuals learn environmental (un)friendliness"""
- for w in self.worlds:
- for i in w.individuals:
- if uniform() < self.environmental_friendliness_learning_fraction:
- i.learn_environmental_friendliness(t)
-
- processes = [
- Event("learn environmental (un)friendliness",
- [B.Culture.worlds.individuals.is_environmentally_friendly],
- ["time",
- next_learning_time,
- let_individuals_learn])
- ]
diff --git a/pycopancore/model_components/social_learning_of_environmental_friendliness/implementation/individual.py b/pycopancore/model_components/social_learning_of_environmental_friendliness/implementation/individual.py
deleted file mode 100644
index df7a7fed..00000000
--- a/pycopancore/model_components/social_learning_of_environmental_friendliness/implementation/individual.py
+++ /dev/null
@@ -1,47 +0,0 @@
-"""Individual entity type class template.
-"""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-from .. import interface as I
-from numpy import arctan, log, pi, random
-
-class Individual (I.Individual):
- """Individual entity type mixin implementation class."""
-
- def learn_environmental_friendliness(self, unused_t):
- """stochastically change environmental friendliness status depending on
- acquaintances' environmental friendliness.
-
- This method is called by Culture's learning process
- """
- # choose random acquaintance if there are any:
- neighbors = list(self.culture.acquaintance_network.neighbors(self))
- if len(neighbors) == 0:
- return
- other = random.choice(neighbors)
- # consider imitating her if your traits differ:
- othertrait = other.is_environmentally_friendly
- if othertrait == self.is_environmentally_friendly:
- return
- # compute quotient of respective terrestrial carbon densities:
- here = self.cell
- there = other.cell
- cul = self.culture
- slope = cul.environmental_friendliness_learning_probability_characteristic_slope
- offset = cul.environmental_friendliness_learning_density_quotient_offset
- quotient = ((there.terrestrial_carbon / there.land_area) /
- (here.terrestrial_carbon / here.land_area))
- # imitate other with probability = sigmoid-shaped function of quotient:
- if random.uniform() < (1/2
- + 1/pi * arctan(pi * slope * log(quotient / offset))):
- self.is_environmentally_friendly = othertrait
-
- processes = []
diff --git a/pycopancore/model_components/social_learning_of_environmental_friendliness/interface.py b/pycopancore/model_components/social_learning_of_environmental_friendliness/interface.py
deleted file mode 100644
index e34fd35c..00000000
--- a/pycopancore/model_components/social_learning_of_environmental_friendliness/interface.py
+++ /dev/null
@@ -1,71 +0,0 @@
-"""model component Interface template.
-
-TODO: adjust or fill in code and documentation wherever marked by "TODO:", then
-remove these instructions.
-"""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-from ... import master_data_model as D
-from ...data_model.master_data_model import CUL, I
-from ... import Variable
-
-
-class Model (object):
- """Interface for Model mixin."""
-
- # metadata:
- name = "social learning of environmental friendliness"
- """a unique name for the model component"""
- description = "a certain fraction of individuals imitates a random " \
- "acquaintance's env. friendliness with a probability depending on " \
- "their surrounding terrestrial carbon density "
- """some longer description"""
- requires = []
- """list of other model components required for this model component to
- make sense"""
-
-
-# entity types:
-
-
-class Individual (object):
- """Interface for Individual entity type mixin."""
-
- # endogenous variables:
- is_environmentally_friendly = I.is_environmentally_friendly
-
-
-# process taxa:
-
-
-class Culture (object):
- """Interface for Culture process taxon mixin."""
-
- # exogenous variables / parameters:
- environmental_friendliness_learning_rate = \
- Variable("environmental friendliness learning rate",
- "rate at which a fraction of individuals learn " \
- "environmental (un)friendliness from neighbours",
- unit=D.years**-1, lower_bound=0, default=1)
- environmental_friendliness_learning_fraction = \
- Variable("awareness update fraction",
- "fraction of individuals learning environmental " \
- "(un)friendliness simultaneously",
- unit=D.unity, lower_bound=0, upper_bound=1, default=0.1)
- environmental_friendliness_learning_density_quotient_offset = Variable(
- "environmental friendliness learning density quotient offset",
- "terrestrial carbon density quotient at which imitation probability "
- "has its point of inflection",
- unit=D.unity, is_intensive=True, default=1)
- environmental_friendliness_learning_probability_characteristic_slope = Variable(
- "environmental friendliness imitation probability's characteristic slope",
- "slope of the normalized sigmoid function at its point of inflection",
- unit=D.unity, is_intensive=True, default=1)
diff --git a/pycopancore/model_components/social_learning_of_environmental_friendliness/model.py b/pycopancore/model_components/social_learning_of_environmental_friendliness/model.py
deleted file mode 100644
index 66509619..00000000
--- a/pycopancore/model_components/social_learning_of_environmental_friendliness/model.py
+++ /dev/null
@@ -1,29 +0,0 @@
-"""Model mixing class template.
-"""
-
-# This file is part of pycopancore.
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-from . import interface as I
-# import all needed entity type implementation classes:
-from .implementation import Individual
-# import all needed process taxon implementation classes:
-from .implementation import Culture
-
-
-class Model (I.Model):
- """Model mixin class."""
-
- # mixins provided by this model component:
-
- entity_types = [Individual]
- """list of entity types augmented by this component"""
- process_taxa = [Culture]
- """list of process taxa augmented by this component"""
diff --git a/pycopancore/model_components/voting_on_climate_policy/__init__.py b/pycopancore/model_components/voting_on_climate_policy/__init__.py
deleted file mode 100644
index 6852092c..00000000
--- a/pycopancore/model_components/voting_on_climate_policy/__init__.py
+++ /dev/null
@@ -1,26 +0,0 @@
-"""
-Model component package template.
-
-TODO:
-Copy this folder, rename it to the name of your model component,
-then adjust or fill in code and documentation in all modules wherever marked by "TODO:",
-finally remove these instructions.
-See the model component development tutorial for details.
-"""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-from . import interface
-
-# export all implementation classes:
-from .implementation import *
-
-# export model component mixin class:
-from .model import Model
diff --git a/pycopancore/model_components/voting_on_climate_policy/implementation/__init__.py b/pycopancore/model_components/voting_on_climate_policy/implementation/__init__.py
deleted file mode 100644
index 4927cda2..00000000
--- a/pycopancore/model_components/voting_on_climate_policy/implementation/__init__.py
+++ /dev/null
@@ -1,17 +0,0 @@
-"""
-Model component implementation subpackage template.
-"""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-# export all provided entity type implementation mixin classes:
-from .social_system import SocialSystem
-
-# export all provided process taxon implementation mixin classes:
diff --git a/pycopancore/model_components/voting_on_climate_policy/implementation/social_system.py b/pycopancore/model_components/voting_on_climate_policy/implementation/social_system.py
deleted file mode 100644
index 24086b00..00000000
--- a/pycopancore/model_components/voting_on_climate_policy/implementation/social_system.py
+++ /dev/null
@@ -1,57 +0,0 @@
-"""SocialSystem entity type mixing class template.
-
-TODO: adjust or fill in code and documentation wherever marked by "TODO:",
-then remove these instructions
-"""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-from .. import interface as I
-# from .... import master_data_model as D
-from .... import Event
-from numpy import array
-from numpy.random import uniform
-
-class SocialSystem (I.SocialSystem):
- """SocialSystem entity type mixin implementation class."""
-
- voting_time_offset = None
-
- def next_voting_time(self, t):
- if not self.voting_time_offset:
- self.voting_time_offset = uniform() * self.time_between_votes
- return (self.voting_time_offset
- + self.time_between_votes
- * ((t - self.voting_time_offset + 1e-10) // self.time_between_votes
- + 1))
-
- def take_a_vote(self, unused_t):
- share = sum([i.population_share for i in self.individuals
- if i.is_environmentally_friendly])
- self.has_renewable_subsidy = (
- (share > self.renewable_subsidy_intro_threshold)
- if not self.has_renewable_subsidy
- else (share > self.renewable_subsidy_keeping_threshold))
- self.has_emissions_tax = (
- (share > self.emissions_tax_intro_threshold)
- if not self.has_emissions_tax
- else (share > self.emissions_tax_keeping_threshold))
- self.has_fossil_ban = (
- (share > self.fossil_ban_intro_threshold)
- if not self.has_fossil_ban
- else (share > self.fossil_ban_keeping_threshold))
-
- processes = [
- Event("voting",
- [I.SocialSystem.has_renewable_subsidy,
- I.SocialSystem.has_emissions_tax,
- I.SocialSystem.has_fossil_ban],
- ["time", next_voting_time, take_a_vote])
- ]
diff --git a/pycopancore/model_components/voting_on_climate_policy/interface.py b/pycopancore/model_components/voting_on_climate_policy/interface.py
deleted file mode 100644
index cba5775a..00000000
--- a/pycopancore/model_components/voting_on_climate_policy/interface.py
+++ /dev/null
@@ -1,96 +0,0 @@
-"""model component Interface template.
-
-TODO: adjust or fill in code and documentation wherever marked by "TODO:", then
-remove these instructions.
-"""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-# TODO: use variables from the master data model wherever possible:
-from ... import master_data_model as D
-from ...data_model.master_data_model import S
-# TODO: uncomment and adjust of you need further variables from another
-# model component:
-# import ..BBB.interface as BBB
-# TODO: uncomment and adjust only if you really need other variables:
-from ... import Variable
-
-
-class Model (object):
- """Interface for Model mixin."""
-
- # metadata:
- name = "voting on climate policy"
- """a unique name for the model component"""
- description = "individuals vote on different climate policy measures" \
- "based on their environmental friendliness"
- """some longer description"""
- requires = []
- """list of other model components required for this model component to
- make sense"""
-
-
-# entity types:
-
-
-class SocialSystem (object):
- """Interface for SocialSystem entity type mixin."""
-
- # endogenous variables:
-
- has_renewable_subsidy = S.has_renewable_subsidy
- has_emissions_tax = S.has_emissions_tax
- has_fossil_ban = S.has_fossil_ban
-
- # exogenous variables / parameters:
-
- emissions_tax_level = S.emissions_tax_level
- renewable_subsidy_level = S.renewable_subsidy_level
-
- time_between_votes = \
- Variable("time between votes",
- "every how many years votes are taken",
- unit=D.years, strict_lower_bound=0, default=4)
-
- renewable_subsidy_intro_threshold = \
- Variable("renewable subsidy introduction threshold",
- "share of environmentally friendly voters needed to introduce"
- "a subsidy for renewables",
- unit=D.unity, lower_bound=0, upper_bound=1, default=1/2)
-
- emissions_tax_intro_threshold = \
- Variable("emissions tax introduction threshold",
- "share of environmentally friendly voters needed to introduce"
- "an emissions tax",
- unit=D.unity, lower_bound=0, upper_bound=1, default=2/3)
-
- fossil_ban_intro_threshold = \
- Variable("fossil ban introduction threshold",
- "share of environmentally friendly voters needed to ban"
- "fossil fuels",
- unit=D.unity, lower_bound=0, upper_bound=1, default=3/4)
-
- renewable_subsidy_keeping_threshold = \
- Variable("renewable subsidy keeping threshold",
- "share of environmentally friendly voters needed to keep "
- "a subsidy for renewables",
- unit=D.unity, lower_bound=0, upper_bound=1, default=1/3)
-
- emissions_tax_keeping_threshold = \
- Variable("emissions tax keeping threshold",
- "share of environmentally friendly voters needed to keep "
- "an emissions tax",
- unit=D.unity, lower_bound=0, upper_bound=1, default=1/2)
-
- fossil_ban_keeping_threshold = \
- Variable("fossil ban keeping threshold",
- "share of environmentally friendly voters needed to keep "
- "a ban on fossil fuels",
- unit=D.unity, lower_bound=0, upper_bound=1, default=2/3)
diff --git a/pycopancore/model_components/voting_on_climate_policy/model.py b/pycopancore/model_components/voting_on_climate_policy/model.py
deleted file mode 100644
index 8c21529e..00000000
--- a/pycopancore/model_components/voting_on_climate_policy/model.py
+++ /dev/null
@@ -1,31 +0,0 @@
-"""Model mixing class template.
-
-TODO: adjust or fill in code and documentation wherever marked by "TODO:",
-then remove these instructions
-"""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-from . import interface as I
-# import all needed entity type implementation classes:
-from .implementation import SocialSystem
-# import all needed process taxon implementation classes:
-#from .implementation import ...
-
-
-class Model (I.Model):
- """Model mixin class."""
-
- # mixins provided by this model component:
-
- entity_types = [SocialSystem]
- """list of entity types augmented by this component"""
- process_taxa = []
- """list of process taxa augmented by this component"""
diff --git a/pycopancore/model_components/wellbeing_driven_migration/__init__.py b/pycopancore/model_components/wellbeing_driven_migration/__init__.py
deleted file mode 100644
index 6852092c..00000000
--- a/pycopancore/model_components/wellbeing_driven_migration/__init__.py
+++ /dev/null
@@ -1,26 +0,0 @@
-"""
-Model component package template.
-
-TODO:
-Copy this folder, rename it to the name of your model component,
-then adjust or fill in code and documentation in all modules wherever marked by "TODO:",
-finally remove these instructions.
-See the model component development tutorial for details.
-"""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-from . import interface
-
-# export all implementation classes:
-from .implementation import *
-
-# export model component mixin class:
-from .model import Model
diff --git a/pycopancore/model_components/wellbeing_driven_migration/implementation/__init__.py b/pycopancore/model_components/wellbeing_driven_migration/implementation/__init__.py
deleted file mode 100644
index b7d4aa4c..00000000
--- a/pycopancore/model_components/wellbeing_driven_migration/implementation/__init__.py
+++ /dev/null
@@ -1,20 +0,0 @@
-"""
-Model component implementation subpackage template.
-"""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-# TODO: adjust the following lists to your needs:
-
-# export all provided entity type implementation mixin classes:
-from .social_system import SocialSystem
-
-# export all provided process taxon implementation mixin classes:
-from .metabolism import Metabolism
diff --git a/pycopancore/model_components/wellbeing_driven_migration/implementation/metabolism.py b/pycopancore/model_components/wellbeing_driven_migration/implementation/metabolism.py
deleted file mode 100644
index de4443f3..00000000
--- a/pycopancore/model_components/wellbeing_driven_migration/implementation/metabolism.py
+++ /dev/null
@@ -1,18 +0,0 @@
-"""provides this model component' Metabolism mixin class"""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-from .. import interface as I
-
-
-class Metabolism (I.Metabolism):
- """Metabolism process taxon mixin implementation class."""
-
- processes = []
diff --git a/pycopancore/model_components/wellbeing_driven_migration/implementation/social_system.py b/pycopancore/model_components/wellbeing_driven_migration/implementation/social_system.py
deleted file mode 100644
index cb246b0f..00000000
--- a/pycopancore/model_components/wellbeing_driven_migration/implementation/social_system.py
+++ /dev/null
@@ -1,78 +0,0 @@
-"""SocialSystem entity type mixing class template.
-"""
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-from .... import Explicit, ODE
-from ...base import interface as B
-
-from .. import interface as I
-
-import sympy as sp # to be able to use symbolic constants and functions
-
-
-class SocialSystem (I.SocialSystem):
- """SocialSystem entity type mixin implementation class."""
-
- # abbreviations:
- basic_rate = B.SocialSystem.metabolism.basic_emigration_probability_rate
- slope = B.SocialSystem.metabolism.emigration_probability_characteristic_slope
- offset = B.SocialSystem.metabolism.emigration_wellbeing_quotient_offset
-
- # for pairwise migration formula:
- this_social_system = I.SocialSystem
- other_social_system = B.SocialSystem.world.social_systems # we will sum about all those!
-
- processes = [
-
- Explicit("emigration",
- [this_social_system.emigration],
- [basic_rate
- * this_social_system.population
- * B.SocialSystem.world.sum( # here is the summation
- other_social_system.population
- * (1/2 + 1/sp.pi * sp.atan(
- sp.pi
- * slope
- * sp.log(other_social_system.wellbeing
- / this_social_system.wellbeing
- / offset)
- )
- )
- )
- ]),
-
- Explicit("immigration",
- [this_social_system.immigration],
- [basic_rate
- * this_social_system.population
- * B.SocialSystem.world.sum( # here is the summation again
- other_social_system.population
- * (1/2 + 1/sp.pi * sp.atan(
- sp.pi
- * slope
- * sp.log(this_social_system.wellbeing
- / other_social_system.wellbeing
- / offset)
- )
- )
- )
- ]),
-
- ODE("effect of migration",
- [I.SocialSystem.population,
- I.SocialSystem.migrant_population],
- [I.SocialSystem.immigration
- - I.SocialSystem.emigration,
- I.SocialSystem.immigration
- # assuming an equal emigration probability among migrants:
- - I.SocialSystem.emigration * I.SocialSystem.migrant_population
- / I.SocialSystem.population])
-
- ]
diff --git a/pycopancore/model_components/wellbeing_driven_migration/interface.py b/pycopancore/model_components/wellbeing_driven_migration/interface.py
deleted file mode 100644
index bab50399..00000000
--- a/pycopancore/model_components/wellbeing_driven_migration/interface.py
+++ /dev/null
@@ -1,80 +0,0 @@
-"""model component Interface template.
-"""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-# TODO: use variables from the master data model wherever possible:
-from ... import master_data_model as D
-from ...data_model.master_data_model import MET, S
-from ... import Variable
-
-
-class Model (object):
- """Interface for Model mixin."""
-
- # metadata:
- name = "wellbeing-driven migration"
- """a unique name for the model component"""
- description = "migration flow between social_systems is proportional to a " \
- "sigmoid function of wellbeing difference and product of populations"
- """some longer description"""
- requires = []
- """list of other model components required for this model component to
- make sense"""
-
-
-# entity types:
-
-
-class SocialSystem (object):
- """Interface for SocialSystem entity type mixin."""
-
- # endogenous variables:
-
- immigration = S.immigration
- emigration = S.emigration
-
- migrant_population = S.migrant_population
-
- # exogenous variables / parameters:
-
- population = S.population
- wellbeing = S.wellbeing
-
-
-# process taxa:
-
-
-class Metabolism (object):
- """Interface for Metabolism process taxon mixin."""
-
- # endogenous variables:
-
- # exogenous variables / parameters:
- emigration_wellbeing_quotient_offset = Variable(
- "emigration wellbeing quotient offset",
- "wellbeing quotient at which emigration probability has its point "
- "of inflection",
- unit = D.unity,
- is_intensive=True,
- default=3) # 1
- emigration_probability_characteristic_slope = Variable(
- "emigration probability's characteristic slope",
- "slope of the normalized sigmoid function at its point of inflection",
- unit = D.unity,
- is_intensive=True,
- default=1)
- basic_emigration_probability_rate = Variable(
- "basic emigration probability rate",
- "absolute value of emigration probability rate at its point of inflection",
- unit = D.years**-1 / D.people**2,
- lower_bound=0, is_intensive=True,
- default = 8e-13) # 3e-13
-
\ No newline at end of file
diff --git a/pycopancore/model_components/wellbeing_driven_migration/model.py b/pycopancore/model_components/wellbeing_driven_migration/model.py
deleted file mode 100644
index add78cd2..00000000
--- a/pycopancore/model_components/wellbeing_driven_migration/model.py
+++ /dev/null
@@ -1,28 +0,0 @@
-"""Model mixing class template.
-"""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-from . import interface as I
-# import all needed entity type implementation classes:
-from .implementation import SocialSystem
-# import all needed process taxon implementation classes:
-from .implementation import Metabolism
-
-
-class Model (I.Model):
- """Model mixin class."""
-
- # mixins provided by this model component:
-
- entity_types = [SocialSystem]
- """list of entity types augmented by this component"""
- process_taxa = [Metabolism]
- """list of process taxa augmented by this component"""
diff --git a/pycopancore/models/_testing/__init__.py b/pycopancore/models/_testing/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/pycopancore/models/_testing/generic_imitation/like_example1.py b/pycopancore/models/_testing/generic_imitation/like_example1.py
new file mode 100644
index 00000000..1f894c7f
--- /dev/null
+++ b/pycopancore/models/_testing/generic_imitation/like_example1.py
@@ -0,0 +1,139 @@
+"""jobsts_prototype_1 model adapted to test generic_imitation component."""
+
+# This file is part of pycopancore.
+#
+# Copyright (C) 2016-2021 by COPAN team at Potsdam Institute for Climate
+# Impact Research
+#
+# URL:
+# Contact: core@pik-potsdam.de
+# License: BSD 2-clause license
+
+#
+# Imports
+#
+
+import numpy as np
+
+from .... import base # all models must use the base component
+
+from ....model_components import copan_global_like_carbon_cycle \
+ as cc
+from ....model_components import copan_global_like_production \
+ as prod
+from ....model_components import copan_global_like_economic_growth \
+ as growth
+from ....model_components import copan_global_like_population_growth \
+ as pop
+from ....model_components import wellbeing_driven_migration \
+ as mig
+from ....model_components import environmental_awareness \
+ as aware
+#from ...model_components import social_learning_of_environmental_friendliness \
+# as learn
+from ....model_components import voting_on_climate_policy \
+ as vote
+
+from ....model_components import config
+config.generic_imitation = {'variables': [base.interface.Culture.individuals.is_environmentally_friendly,
+ base.interface.Culture.social_systems.has_emissions_tax,
+ base.interface.Culture.social_systems.emissions_tax_level]}
+
+from ....model_components import generic_imitation as imi
+
+
+# entity types:
+
+class World(cc.World,
+ prod.World,
+ growth.World,
+ base.World):
+ """World entity type."""
+ pass
+
+
+class SocialSystem(prod.SocialSystem,
+ growth.SocialSystem,
+ pop.SocialSystem,
+ mig.SocialSystem,
+ aware.SocialSystem,
+ vote.SocialSystem,
+ base.SocialSystem):
+ """SocialSystem entity type."""
+ pass
+
+
+class Cell(cc.Cell,
+ prod.Cell,
+ aware.Cell,
+ base.Cell):
+ """Cell entity type."""
+ pass
+
+
+class Individual(aware.Individual,
+# learn.Individual,
+ base.Individual):
+ """Individual entity type."""
+
+ def imi_p_imitate_env(self, own_trait=None, other_trait=None):
+ return 1 / (1 + np.exp(self.relative_weight))
+
+ def imi_imitate_env(self, variables=None, values=None):
+ for index, var in enumerate(variables):
+ var.set_value(self, values[index])
+
+# process taxa:
+
+
+class Environment(cc.Environment,
+ base.Environment):
+ """Environment process taxon."""
+ pass
+
+
+class Metabolism(prod.Metabolism,
+ growth.Metabolism,
+ pop.Metabolism,
+ mig.Metabolism,
+ base.Metabolism):
+ """Metabolism process taxon."""
+ pass
+
+
+class Culture (aware.Culture,
+# learn.Culture,
+ imi.Culture,
+ base.Culture):
+ """Culture process taxon"""
+
+ imi.Culture.imi_traits.default = {
+ 'env': (aware.Individual.is_environmentally_friendly,),
+ 'tax': (prod.SocialSystem.has_emissions_tax, prod.SocialSystem.emissions_tax_level)
+ }
+
+
+# Model class:
+
+
+class Model(cc.Model,
+ prod.Model,
+ growth.Model,
+ pop.Model,
+ mig.Model,
+ aware.Model,
+# learn.Model,
+ imi.Model,
+ vote.Model,
+ base.Model):
+ """Class representing the whole model."""
+
+ name = "Jobst's prototype 1"
+ """Name of the model"""
+ description = "(as presented internally at PIK in fall 2016)"
+ """Longer description"""
+
+ entity_types = [World, SocialSystem, Cell, Individual]
+ """List of entity types used in the model"""
+ process_taxa = [Environment, Metabolism, Culture]
+ """List of process taxa used in the model"""
diff --git a/pycopancore/models/_testing/generic_imitation/other_component.py b/pycopancore/models/_testing/generic_imitation/other_component.py
new file mode 100644
index 00000000..b83a59ce
--- /dev/null
+++ b/pycopancore/models/_testing/generic_imitation/other_component.py
@@ -0,0 +1,48 @@
+from .... import master_data_model as D
+from .... import Variable
+
+# INTERFACE:
+
+class ISocialSystem (object):
+ is_active = Variable(
+ "a boolean variable", "", scale='nominal', datatype=bool)
+
+class ICell (object):
+ an_ordinal_var = Variable(
+ "an ordinal variable", "e.g., a Likert scale", scale='ordinal', datatype=int,
+ levels=[1, 2, 3, 4, 5])
+
+class IIndividual (object):
+ a_nominal_var = Variable(
+ "a nominal (categorical) variable", "", scale='nominal', datatype=str,
+ levels=['a', 'b', 'c'])
+ a_dimensional_var = Variable(
+ "a dimensional variable", "", unit=D.dollars)
+ a_criterion = Variable(
+ "a fitness criterion", "e.g. income")
+
+class IModel (object):
+ name = "other component"
+ description = "only for testing generic_imitation"
+ requires = []
+
+class interface:
+ SocialSystem = ISocialSystem
+ Cell = ICell
+ Individual = IIndividual
+ Model = IModel
+
+# IMPLEMENTATION:
+
+class SocialSystem (ISocialSystem):
+ processes = []
+
+class Cell (ICell):
+ processes = []
+
+class Individual (IIndividual):
+ processes = []
+
+class Model (IModel):
+ entity_types = [SocialSystem, Cell, Individual]
+ process_taxa = []
diff --git a/pycopancore/models/_testing/generic_imitation/simple.py b/pycopancore/models/_testing/generic_imitation/simple.py
new file mode 100755
index 00000000..8643e4fb
--- /dev/null
+++ b/pycopancore/models/_testing/generic_imitation/simple.py
@@ -0,0 +1,44 @@
+import numpy as np
+
+from .... import base # all models must use the base component
+
+from . import other_component as other
+
+from ....model_components import config
+config.generic_imitation = {'variables': [base.interface.Culture.social_systems.is_active,
+ base.interface.Culture.social_systems.cells.an_ordinal_var,
+ base.interface.Culture.individuals.a_nominal_var,
+ base.interface.Culture.individuals.a_dimensional_var]}
+
+from ....model_components import generic_imitation as imi
+
+
+class World(base.World):
+ pass
+
+class SocialSystem(other.SocialSystem, base.SocialSystem):
+ pass
+
+class Cell(other.Cell, base.Cell):
+ def imi_p_imitate_ord(self, own_trait=None, other_trait=None):
+ return 1.0 if np.abs(other_trait[0] - own_trait[0]) <= 2 else 0.0
+
+class Individual(other.Individual, base.Individual):
+ def imi_evaluate_pair(self, other=None):
+ return other.a_criterion
+
+
+class Culture (imi.Culture, base.Culture):
+
+ imi.Culture.imi_traits.default = {
+ 'bool': (other.SocialSystem.is_active,),
+ 'ord': (other.Cell.an_ordinal_var,),
+ 'pair': (other.Individual.a_nominal_var, other.Individual.a_dimensional_var)
+ }
+
+
+class Model(other.Model, imi.Model, base.Model):
+ name = "Simple test of generic_imitation component"
+ description = "uses only one other component"
+ entity_types = [World, SocialSystem, Cell, Individual]
+ process_taxa = [Culture]
diff --git a/pycopancore/models/adaptive_voter_model.py b/pycopancore/models/adaptive_voter_model.py
deleted file mode 100644
index 3af4ed68..00000000
--- a/pycopancore/models/adaptive_voter_model.py
+++ /dev/null
@@ -1,108 +0,0 @@
-"""
-Model class adaptive_voter_model.
-"""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-#
-# Imports
-#
-
-from .. import base # all models must use the base component
-
-from ..model_components import adaptive_voter_opinion_formation as avof
-from ..model_components import majority_decision as md
-
-
-# entity types:
-
-# NEED TO: compose all needed entity type implementation classes
-# by mixing the above model components' mixin classes of the same name.
-# Only compose those entity types and process taxons that the model needs,
-# delete the templates for the unneeded ones, and add those for missing ones:
-
-# NEED TO: list all mixin classes needed:
-class World(base.World):
- """World entity type."""
-
- pass
-
-
-# NEED TO: list all mixin classes needed:
-class SocialSystem(md.SocialSystem,
- base.SocialSystem):
- """SocialSystem entity type."""
-
- pass
-
-
-# NEED TO: list all mixin classes needed:
-class Cell(base.Cell):
- """Cell entity type."""
-
- pass
-
-
-# NEED TO: list all mixin classes needed:
-class Individual(avof.Individual,
- md.Individual,
- base.Individual):
- """Individual entity type."""
-
- pass
-
-
-# process taxa:
-
-# NEED TO: do the same for process taxa:
-
-
-# NEED TO: list all mixin classes needed:
-# class Environment (
-# base.Environment):
-# """Environment process taxon."""
-#
-# pass
-
-
-# NEED TO: list all mixin classes needed:
-# class Metabolism (
-# base.Metabolism):
-# """Metabolism process taxon."""
-#
-# pass
-
-
-# NEED TO: list all mixin classes needed:
-class Culture(avof.Culture, md.Culture,
- base.Culture):
- """Culture process taxon."""
-
- pass
-
-
-# Model class:
-
-# NEED TO: list all used model components:
-class Model(avof.Model, md.Model,
- base.Model):
- """Class representing the whole model."""
-
- name = "..."
- """Name of the model"""
- description = "..."
- """Longer description"""
-
- # NEED TO: list all entity types you composed above:
- entity_types = [World, SocialSystem, Individual]
- """List of entity types used in the model"""
- # NEED TO: list all entity types you composed above:
- process_taxa = [Culture]
- """List of process taxa used in the model"""
diff --git a/pycopancore/models/base_and_dummy.py b/pycopancore/models/base_and_dummy.py
deleted file mode 100644
index 466f09f7..00000000
--- a/pycopancore/models/base_and_dummy.py
+++ /dev/null
@@ -1,80 +0,0 @@
-"""Dummy model to create model modules."""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-#
-# Imports
-#
-
-import pycopancore.model_components.base as base
-import pycopancore.model_components.dummy as dummy
-
-#
-# Entity Types
-#
-
-
-class World(base.World):
- """Class to mix all World_mixins to create World clas."""
-
- pass
-
-
-class Cell(dummy.Cell, base.Cell):
- """Class to mix all Cell_mixins to create Cell class."""
-
- pass
-
-
-class Individual(base.Individual):
- """Class to mix all Individual_mixins to create Individual class."""
-
- pass
-
-
-class SocialSystem(base.SocialSystem):
- """Class to mix all SocialSystem_mixins to create SocialSystem class."""
-
- pass
-
-#
-# Dynamics
-#
-
-
-class Culture(base.Culture):
- """Class to mix all Culture_mixins to create Culture class."""
-
- pass
-
-
-class Metabolism(base.Metabolism):
- """Class to mix all Metabolism_mixins to create Metabolism class."""
-
- pass
-
-
-class Environment(base.Environment):
- """Class to mix all Environment_mixins to create Environment class."""
-
- pass
-
-#
-# Models
-#
-
-
-class Model(dummy.Model, base.Model):
- """Class to mix all Model_mixins to create Model class."""
-
- name = "This model's name"
- description = "Description of the model"
- entity_types = [Cell, Individual, SocialSystem, World]
- process_taxa = [Culture, Metabolism, Environment]
diff --git a/pycopancore/models/carbon_voters_anderies_model.py b/pycopancore/models/carbon_voters_anderies_model.py
deleted file mode 100644
index ba27f6ad..00000000
--- a/pycopancore/models/carbon_voters_anderies_model.py
+++ /dev/null
@@ -1,114 +0,0 @@
-"""Model class carbon_voters_anderies_model."""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-#
-# Imports
-#
-
-from .. import base # all models must use the base component
-
-from ..model_components import adaptive_voter_opinion_formation as avof
-from ..model_components import majority_decision as md
-from ..model_components import anderies_carbon_cycle as cc
-from ..model_components import carbon_voters as cv
-
-
-# entity types:
-
-# NEED TO: compose all needed entity type implementation classes
-# by mixing the above model components' mixin classes of the same name.
-# Only compose those entity types and process taxons that the model needs,
-# delete the templates for the unneeded ones, and add those for missing ones:
-
-# NEED TO: list all mixin classes needed:
-class World(cc.World,
- cv.World,
- base.World):
- """World entity type."""
-
- pass
-
-
-# NEED TO: list all mixin classes needed:
-class SocialSystem(md.SocialSystem,
- cv.SocialSystem,
- cc.SocialSystem,
- base.SocialSystem):
- """SocialSystem entity type."""
-
- pass
-
-
-# NEED TO: list all mixin classes needed:
-class Cell(cc.Cell,
- base.Cell):
- """Cell entity type."""
-
- pass
-
-
-# NEED TO: list all mixin classes needed:
-class Individual(avof.Individual,
- md.Individual,
- base.Individual):
- """Individual entity type."""
-
- pass
-
-
-# process taxa:
-
-# NEED TO: do the same for process taxa:
-
-
-# NEED TO: list all mixin classes needed:
-class Environment(cc.Environment,
- base.Environment):
- """Environment process taxon."""
-
-
-# NEED TO: list all mixin classes needed:
-class Metabolism(base.Metabolism):
- """Metabolism process taxon."""
-
- pass
-
-
-# NEED TO: list all mixin classes needed:
-class Culture(avof.Culture,
- cv.Culture,
- base.Culture):
- """Culture process taxon."""
-
- pass
-
-
-# Model class:
-
-# NEED TO: list all used model components:
-class Model(avof.Model,
- md.Model,
- cc.Model,
- cv.Model,
- base.Model):
- """Class representing the whole model."""
-
- name = "..."
- """Name of the model"""
- description = "..."
- """Longer description"""
-
- # NEED TO: list all entity types you composed above:
- entity_types = [World, SocialSystem, Individual, Cell]
- """List of entity types used in the model"""
- # NEED TO: list all entity types you composed above:
- process_taxa = [Culture, Environment]
- """List of process taxa used in the model"""
diff --git a/pycopancore/models/coccon/carboncycle.py b/pycopancore/models/coccon/carboncycle.py
deleted file mode 100644
index ba9ff796..00000000
--- a/pycopancore/models/coccon/carboncycle.py
+++ /dev/null
@@ -1,80 +0,0 @@
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-from ... import base # all models must use the base component
-
-from ...model_components import copan_global_like_carbon_cycle \
- as cc
-
-
-# entity types:
-
-
-class World(cc.World,
- base.World):
- """World entity type."""
-
- pass
-
-
-class SocialSystem(base.SocialSystem):
- """SocialSystem entity type."""
-
- pass
-
-
-class Cell(cc.Cell,
- base.Cell):
- """Cell entity type."""
-
- pass
-
-
-class Individual(base.Individual):
- """Individual entity type."""
- pass
-
-
-# process taxa:
-
-
-class Environment(cc.Environment,
- base.Environment):
- """Environment process taxon."""
-
- pass
-
-
-class Metabolism(base.Metabolism):
- """Metabolism process taxon."""
-
- pass
-
-
-class Culture (base.Culture):
- """Culture process taxon"""
- pass
-
-
-# Model class:
-
-
-class Model(cc.Model,
- base.Model):
- """Class representing the whole model."""
-
- name = "CoCCoN tutorial model, only carbon cycle"
- """Name of the model"""
- description = "(as presented at PIK in fall 2017)"
- """Longer description"""
-
- entity_types = [World, SocialSystem, Cell, Individual]
- """List of entity types used in the model"""
- process_taxa = [Environment, Metabolism, Culture]
- """List of process taxa used in the model"""
diff --git a/pycopancore/models/coccon/full.py b/pycopancore/models/coccon/full.py
deleted file mode 100644
index e2e3db6f..00000000
--- a/pycopancore/models/coccon/full.py
+++ /dev/null
@@ -1,122 +0,0 @@
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-from ... import base # all models must use the base component
-
-from ...model_components import copan_global_like_carbon_cycle \
- as cc
-from ...model_components import copan_global_like_production \
- as prod
-from ...model_components import copan_global_like_economic_growth \
- as growth
-from ...model_components import copan_global_like_population_growth \
- as pop
-from ...model_components import wellbeing_driven_migration \
- as mig
-from ...model_components import environmental_awareness \
- as aware
-from ...model_components import social_learning_of_environmental_friendliness \
- as learn
-from ...model_components import voting_on_climate_policy \
- as vote
-
-
-# entity types:
-
-
-class World(cc.World,
- prod.World,
- growth.World,
- base.World):
- """World entity type."""
-
- pass
-
-
-class SocialSystem(
- prod.SocialSystem,
- growth.SocialSystem,
- pop.SocialSystem,
- mig.SocialSystem,
- aware.SocialSystem,
- vote.SocialSystem,
- base.SocialSystem):
- """SocialSystem entity type."""
-
- pass
-
-
-class Cell(cc.Cell,
- prod.Cell,
- base.Cell):
- """Cell entity type."""
-
- pass
-
-
-class Individual(
- aware.Individual,
- learn.Individual,
- base.Individual):
- """Individual entity type."""
- pass
-
-
-# process taxa:
-
-
-class Environment(cc.Environment,
- base.Environment):
- """Environment process taxon."""
-
- pass
-
-
-class Metabolism(
- prod.Metabolism,
- growth.Metabolism,
- pop.Metabolism,
- mig.Metabolism,
- base.Metabolism):
- """Metabolism process taxon."""
-
- pass
-
-
-class Culture (
- aware.Culture,
- learn.Culture,
- base.Culture):
- """Culture process taxon"""
- pass
-
-
-# Model class:
-
-
-class Model(cc.Model,
- prod.Model,
- growth.Model,
- pop.Model,
- mig.Model,
- aware.Model,
- learn.Model,
- vote.Model,
- base.Model):
- """Class representing the whole model."""
-
- name = "CoCCoN tutorial model"
- """Name of the model"""
- description = "(as presented at PIK in fall 2017)"
- """Longer description"""
-
- entity_types = [World, SocialSystem, Cell, Individual]
- """List of entity types used in the model"""
- process_taxa = [Environment, Metabolism, Culture]
- """List of process taxa used in the model"""
diff --git a/pycopancore/models/example1.py b/pycopancore/models/example1.py
deleted file mode 100644
index eba53869..00000000
--- a/pycopancore/models/example1.py
+++ /dev/null
@@ -1,126 +0,0 @@
-"""jobsts_prototype_1 model."""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-#
-# Imports
-#
-
-from .. import base # all models must use the base component
-
-from ..model_components import copan_global_like_carbon_cycle \
- as cc
-from ..model_components import copan_global_like_production \
- as prod
-from ..model_components import copan_global_like_economic_growth \
- as growth
-from ..model_components import copan_global_like_population_growth \
- as pop
-from ..model_components import wellbeing_driven_migration \
- as mig
-from ..model_components import environmental_awareness \
- as aware
-from ..model_components import social_learning_of_environmental_friendliness \
- as learn
-from ..model_components import voting_on_climate_policy \
- as vote
-
-# entity types:
-
-
-class World(cc.World,
- prod.World,
- growth.World,
- base.World):
- """World entity type."""
-
- pass
-
-
-class SocialSystem(
- prod.SocialSystem,
- growth.SocialSystem,
- pop.SocialSystem,
- mig.SocialSystem,
- aware.SocialSystem,
- vote.SocialSystem,
- base.SocialSystem):
- """SocialSystem entity type."""
-
- pass
-
-
-class Cell(cc.Cell,
- prod.Cell,
- aware.Cell,
- base.Cell):
- """Cell entity type."""
-
- pass
-
-
-class Individual(aware.Individual,
- learn.Individual,
- base.Individual):
- """Individual entity type."""
- pass
-
-
-# process taxa:
-
-
-class Environment(cc.Environment,
- base.Environment):
- """Environment process taxon."""
-
- pass
-
-
-class Metabolism(
- prod.Metabolism,
- growth.Metabolism,
- pop.Metabolism,
- mig.Metabolism,
- base.Metabolism):
- """Metabolism process taxon."""
-
- pass
-
-
-class Culture (aware.Culture,
- learn.Culture,
- base.Culture):
- """Culture process taxon"""
- pass
-
-
-# Model class:
-
-
-class Model(cc.Model,
- prod.Model,
- growth.Model,
- pop.Model,
- mig.Model,
- aware.Model,
- learn.Model,
- vote.Model,
- base.Model):
- """Class representing the whole model."""
-
- name = "Jobst's prototype 1"
- """Name of the model"""
- description = "(as presented internally at PIK in fall 2016)"
- """Longer description"""
-
- entity_types = [World, SocialSystem, Cell, Individual]
- """List of entity types used in the model"""
- process_taxa = [Environment, Metabolism, Culture]
- """List of process taxa used in the model"""
diff --git a/pycopancore/models/example2.py b/pycopancore/models/example2.py
deleted file mode 100644
index 61cf6850..00000000
--- a/pycopancore/models/example2.py
+++ /dev/null
@@ -1,114 +0,0 @@
-"""jobsts_prototype_2 model."""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-#
-# Imports
-#
-
-from .. import base # all models must use the base component
-
-from ..model_components import copan_global_like_carbon_cycle \
- as cc
-from ..model_components import copan_global_like_production \
- as prod
-from ..model_components import copan_global_like_economic_growth \
- as growth
-from ..model_components import environmental_awareness \
- as aware
-from ..model_components import social_learning_of_environmental_friendliness \
- as learn
-from ..model_components import voting_on_climate_policy \
- as vote
-
-
-# entity types:
-
-class World(cc.World,
- prod.World,
- growth.World,
- base.World):
- """World entity type."""
-
- pass
-
-
-class SocialSystem(prod.SocialSystem,
- growth.SocialSystem,
- aware.SocialSystem,
- vote.SocialSystem,
- base.SocialSystem):
- """SocialSystem entity type."""
-
- pass
-
-
-class Cell(cc.Cell,
- prod.Cell,
- aware.Cell,
- base.Cell):
- """Cell entity type."""
-
- pass
-
-
-class Individual(aware.Individual,
- learn.Individual,
- base.Individual):
- """Individual entity type."""
- pass
-
-
-# process taxa:
-
-
-class Environment(cc.Environment,
- base.Environment):
- """Environment process taxon."""
-
- pass
-
-
-class Metabolism(prod.Metabolism,
- growth.Metabolism,
- base.Metabolism):
- """Metabolism process taxon."""
-
- pass
-
-
-class Culture (aware.Culture,
- learn.Culture,
- base.Culture):
- """Culture process taxon"""
- pass
-
-
-# Model class:
-
-
-class Model(cc.Model,
- prod.Model,
- growth.Model,
- aware.Model,
- learn.Model,
- vote.Model,
- base.Model):
- """Class representing the whole model."""
-
- name = "Jobst's prototype 2"
- """Name of the model"""
- description = "(as suggested in the paper revision plan)"
- """Longer description"""
-
- entity_types = [World, SocialSystem, Cell, Individual]
- """List of entity types used in the model"""
- process_taxa = [Environment, Metabolism, Culture]
- """List of process taxa used in the model"""
diff --git a/pycopancore/models/exodus.py b/pycopancore/models/exodus.py
deleted file mode 100644
index 29486b7d..00000000
--- a/pycopancore/models/exodus.py
+++ /dev/null
@@ -1,72 +0,0 @@
-"""Model class of model Exodus."""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-from .. import base # all models must use the base component
-from ..model_components import exodus as ex
-
-
-class World(ex.World,
- base.World):
- """World entity type."""
-
- pass
-
-
-class SocialSystem(ex.SocialSystem,
- base.SocialSystem):
- """SocialSystem entity type."""
-
- pass
-
-
-class Cell(ex.Cell,
- base.Cell):
- """Cell entity type."""
-
- pass
-
-
-class Individual(ex.Individual,
- base.Individual):
- """Individual entity type."""
-
- pass
-
-
-# process taxa:
-class Metabolism(ex.Metabolism,
- base.Metabolism):
- """Metabolism process taxon."""
-
- pass
-
-
-class Culture(ex.Culture,
- base.Culture):
- """Culture process taxon."""
-
- pass
-
-
-# Model class:
-
-# NEED TO: list all used model components:
-class Model(ex.Model,
- base.Model):
- """Class representing the whole model."""
-
- name = "Exodus"
- description = "Model describing rural-urban migration."
-
- entity_types = [World, SocialSystem, Cell, Individual]
- """List of entity types used in the model"""
- process_taxa = [Metabolism, Culture]
- """List of process taxa used in the model"""
diff --git a/pycopancore/models/exploit.py b/pycopancore/models/exploit.py
deleted file mode 100644
index 118b641f..00000000
--- a/pycopancore/models/exploit.py
+++ /dev/null
@@ -1,90 +0,0 @@
-"""
-Exploit model.
-
-The exploit model is including the modules base,
-most_simple_vegetation, simple_extraction
-and exploit_simple_learning.
-It is based on the cython implementation cyexploit
-(see https://github.com/wbarfuss/cyexploit )
-"""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-#
-# Imports
-#
-
-import pycopancore.model_components.base as base
-import pycopancore.model_components.most_simple_vegetation as vegetation
-import pycopancore.model_components.simple_extraction as extraction
-import pycopancore.model_components.exploit_social_learning as social_learning
-
-#
-# Entity Types
-#
-
-
-class World(social_learning.World,
- base.World):
- """Class to mix all World_mixins to create World class."""
-
- pass
-
-
-class SocialSystem(base.SocialSystem):
- """Class to mix all SocialSystem_mixins to create SocialSystem class."""
-
- pass
-
-
-class Cell(vegetation.Cell,
- extraction.Cell,
- base.Cell):
- """Class to mix all Cell_mixins to create Cell class."""
-
- pass
-
-
-# Order is important: extraction.Individual before social_learning.Individual
-# because of the get_harvest_rate() method that should be overwritten.
-class Individual(extraction.Individual,
- social_learning.Individual,
- base.Individual):
- """Class to mix all Individual_mixins to create Individual class."""
-
- pass
-
-#
-# Dynamics
-#
-
-
-class Culture(social_learning.Culture,
- base.Culture):
- """Class to mix all Culture_mixins to create Culture class."""
-
- pass
-
-#
-# Models
-#
-
-
-class Model(vegetation.Model,
- extraction.Model,
- social_learning.Model,
- base.Model):
- """Class to mix all Model_mixins to create Model class."""
-
- name = "Exploit model"
- description = "COPAN:Exploit model"
-
- entity_types = [World, SocialSystem, Cell, Individual]
- process_taxa = [Culture]
diff --git a/pycopancore/models/groups_seven_dwarfs.py b/pycopancore/models/groups_seven_dwarfs.py
deleted file mode 100644
index 6c823150..00000000
--- a/pycopancore/models/groups_seven_dwarfs.py
+++ /dev/null
@@ -1,90 +0,0 @@
-"""Model class seven_dwarfs."""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-#
-# Imports
-#
-
-from .. import base # all models must use the base component
-
-from ..model_components import seven_dwarfs as sd
-from ..model_components import snowwhite as sw
-
-# entity types:
-
-# by mixing the above model components' mixin classes of the same name.
-# Only compose those entity types and process taxons that the model needs,
-# delete the templates for the unneeded ones, and add those for missing ones:
-
-
-class World(sd.World,
- base.World):
- """World entity type."""
-
- pass
-
-
-class SocialSystem(base.SocialSystem):
- """SocialSystem entity type."""
-
- pass
-
-
-class Cell(sd.Cell,
- sw.Cell,
- base.Cell):
- """Cell entity type."""
-
- pass
-
-
-class Individual(sd.Individual,
- base.Individual):
- """Individual entity type."""
-
- pass
-
-
-class SocialSystem(sd.SocialSystem,
- base.SocialSystem):
- """SocialSystem entity type."""
-
- pass
-
-class Group(sd.Group,
- base.Group):
- """Groups entity type"""
-
-# process taxa:
-
-class Culture(sd.Culture,
- base.Culture):
- """Culture process taxon."""
-
- pass
-
-
-# Model class:
-
-class Model(sd.Model,
- sw.Model,
- base.Model):
- """Class representing the whole model."""
-
- name = "Seven dwarfs"
- """Name of the model"""
- description = "Tutorial model"
- """Longer description"""
-
- entity_types = [World, SocialSystem, Cell, Individual, Group]
- """List of entity types used in the model"""
- process_taxa = [Culture]
- """List of process taxa used in the model"""
diff --git a/pycopancore/models/only_copan_global_like_carbon_cycle.py b/pycopancore/models/only_copan_global_like_carbon_cycle.py
deleted file mode 100644
index cd7dcfb0..00000000
--- a/pycopancore/models/only_copan_global_like_carbon_cycle.py
+++ /dev/null
@@ -1,102 +0,0 @@
-"""jobsts_prototype_1 model, reduced to carbon cycle only."""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-#
-# Imports
-#
-
-from .. import base # all models must use the base component
-
-from ..model_components import copan_global_like_carbon_cycle \
- as cc
-# from ..model_components import copan_global_like_production \
-# as prod
-# from ..model_components import copan_global_like_economic_growth \
-# as growth
-# from ..model_components import copan_global_like_population_growth \
-# as population
-# from ..model_components import ...migration \
-# as migration
-
-
-# entity types:
-
-
-class World(cc.World,
- # prod.World,
- base.World):
- """World entity type."""
-
- pass
-
-
-class SocialSystem(base.SocialSystem):
- # prod.SocialSystem,
- # growth.SocialSystem):
- """SocialSystem entity type."""
-
- pass
-
-
-class Cell(cc.Cell,
- # prod.Cell,
- base.Cell):
- """Cell entity type."""
-
- pass
-
-# class Individual (ABBR1.Individual, ABBR2.Individual,
-# base.Individual):
-# """Individual entity type."""
-# pass
-
-
-# process taxa:
-
-
-class Environment(cc.Environment,
- base.Environment):
- """Environment process taxon."""
-
- pass
-
-
-class Metabolism(base.Metabolism):
- # , prod.Metabolism):
- """Metabolism process taxon."""
-
- pass
-
-# class Culture (ABBR1.Culture, ABBR2.Culture,
-# base.Culture):
-# """Culture process taxon."""
-
-# pass
-
-
-# Model class:
-
-
-class Model(cc.Model,
- # prod.Model,
- # growth.Model,
- base.Model):
- """Class representing the whole model."""
-
- name = "Jobst's prototype 1, only CC"
- """Name of the model"""
- description = "(as presented internally at PIK in fall 2016)"
- """Longer description"""
-
- entity_types = [World, SocialSystem, Cell]
- """List of entity types used in the model"""
- process_taxa = [Environment, Metabolism]
- """List of process taxa used in the model"""
diff --git a/pycopancore/models/our_model.py b/pycopancore/models/our_model.py
deleted file mode 100644
index 72bea62b..00000000
--- a/pycopancore/models/our_model.py
+++ /dev/null
@@ -1,105 +0,0 @@
-"""Model class our_model."""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-#
-# Imports
-#
-
-from .. import base # all models must use the base component
-# from ..model_components import copan_global_like_carbon_cycle \
-# as cc
-from ..model_components import anderies_carbon_cycle \
- as cc
-
-# from ..model_components import COMPONENT1 as ABBR1
-
-
-# entity types:
-
-# by mixing the above model components' mixin classes of the same name.
-# Only compose those entity types and process taxons that the model needs,
-# delete the templates for the unneeded ones, and add those for missing ones:
-
-
-class World(cc.World,
- base.World):
- """World entity type."""
-
- pass
-
-
-class SocialSystem(cc.SocialSystem,
- base.SocialSystem):
- """SocialSystem entity type."""
-
- pass
-
-
-class Cell(cc.Cell,
- base.Cell):
- """Cell entity type."""
-
- pass
-
-
-class Individual(base.Individual):
- """Individual entity type."""
-
- pass
-
-
-# process taxa:
-
-class Environment(cc.Environment,
- base.Environment):
- """Environment process taxon."""
-
- pass
-
-
-class Metabolism(base.Metabolism):
- """Metabolism process taxon."""
-
- pass
-
-
-class Culture(base.Culture):
- """Culture process taxon."""
-
- pass
-
-
-# Model class:
-
-class Model(cc.Model,
- base.Model):
- """Class representing the whole model."""
-
- name = "..."
- """our model"""
-
- description = "..."
- """Longer description"""
-
- entity_types = [
- World,
- SocialSystem,
- Cell,
- # Individual,
- ]
- """List of entity types used in the model"""
-
- process_taxa = [
- Environment,
- # Metabolism,
- # Culture,
- ]
- """List of process taxa used in the model"""
diff --git a/pycopancore/models/seven_dwarfs.py b/pycopancore/models/seven_dwarfs.py
index fd7bacc6..c96989b1 100644
--- a/pycopancore/models/seven_dwarfs.py
+++ b/pycopancore/models/seven_dwarfs.py
@@ -13,10 +13,11 @@
# Imports
#
-from .. import base # all models must use the base component
+# all models must use the base component
+from pycopancore.model_components import base
-from ..model_components import seven_dwarfs as sd
-from ..model_components import snowwhite as sw
+from pycopancore.model_components import seven_dwarfs as sd
+from pycopancore.model_components import snowwhite as sw
# entity types:
diff --git a/pycopancore/private/__init__.py b/pycopancore/private/__init__.py
index 677cd94b..31595449 100644
--- a/pycopancore/private/__init__.py
+++ b/pycopancore/private/__init__.py
@@ -9,10 +9,11 @@
"""
"""
-from ._mixin import _Mixin, _MixinType
-from ._abstract_process import _AbstractProcess
-from ._abstract_process_taxon_mixin import _AbstractProcessTaxonMixin
-from ._abstract_entity_mixin import _AbstractEntityMixin
-from ._abstract_runner import _AbstractRunner
-from ._expressions import _DotConstruct, eval, unknown, unset
-from ._trajectory_dictionary import _TrajectoryDictionary
+# from ._mixin import _Mixin, _MixinType
+# from ._abstract_process import _AbstractProcess
+# from ._abstract_process_taxon_mixin import _AbstractProcessTaxonMixin
+# from ._abstract_entity_mixin import _AbstractEntityMixin
+# from ._abstract_runner import _AbstractRunner
+# from ._expressions import _DotConstruct, eval
+# from ._simple_expressions import unset, unknown
+# from ._trajectory_dictionary import _TrajectoryDictionary
diff --git a/pycopancore/private/_abstract_entity_mixin.py b/pycopancore/private/_abstract_entity_mixin.py
index de8b3cf4..657c39b4 100644
--- a/pycopancore/private/_abstract_entity_mixin.py
+++ b/pycopancore/private/_abstract_entity_mixin.py
@@ -18,7 +18,7 @@
# - in __init__, add logics that sets all variables to either their specified
# values or their default values as given in Variable.
-from . import _Mixin
+from pycopancore.private._mixin import _Mixin
class _AbstractEntityMixin(_Mixin):
diff --git a/pycopancore/private/_abstract_process_taxon_mixin.py b/pycopancore/private/_abstract_process_taxon_mixin.py
index 2b7dd3eb..c2ff3d10 100644
--- a/pycopancore/private/_abstract_process_taxon_mixin.py
+++ b/pycopancore/private/_abstract_process_taxon_mixin.py
@@ -13,7 +13,7 @@
# License: BSD 2-clause license
-from . import _Mixin
+from pycopancore.private._mixin import _Mixin
class _AbstractProcessTaxonMixin(_Mixin):
diff --git a/pycopancore/private/_expressions.py b/pycopancore/private/_expressions.py
index c5b5a63f..a8912cea 100644
--- a/pycopancore/private/_expressions.py
+++ b/pycopancore/private/_expressions.py
@@ -19,27 +19,8 @@
from sympy.functions.elementary.piecewise import ExprCondPair
import scipy.special
-from .. import data_model as D
-from .. import private
-
-from numba import njit
-
-
-class _Unknown(object):
- def __str__(self):
- return "unknown"
- def update(self, *args):
- return self
-
-unknown = _Unknown()
-
-class _Unset(object):
- def __str__(self):
- return "unset"
- def update(self, *args):
- return self
-
-unset = _Unset()
+from ._simple_expressions import unknown
+from pycopancore import data_model as D
# hierarchical aggregation functions:
@@ -49,7 +30,6 @@ def aggregation(npfunc):
# TODO: add docstring to function
- @njit
def func(values, lens):
"""Dummy docstring"""
@@ -65,6 +45,7 @@ def func(values, lens):
return func
+
name2numpy = {
"all": np.all,
"any": np.any,
@@ -83,7 +64,6 @@ def func(values, lens):
# hierarchical broadcasting:
-@njit
def _broadcast(values, lens):
"""Dummy docstring"""
# TODO: add docstring to function
diff --git a/pycopancore/private/_mixin.py b/pycopancore/private/_mixin.py
index 7cd22e9d..bec055bd 100644
--- a/pycopancore/private/_mixin.py
+++ b/pycopancore/private/_mixin.py
@@ -18,9 +18,8 @@
# - in __init__, add logics that sets all variables to either their specified
# values or their default values as given in Variable.
-from ..data_model import variable
-from ..private._expressions import _DotConstruct, aggregation_names
-from ..data_model import OrderedSet
+from pycopancore.data_model.variable import Variable
+from pycopancore.private._expressions import _DotConstruct, aggregation_names
import inspect
@@ -58,7 +57,7 @@ def __getattribute__(cls, name):
for c in inspect.getmro(cls)[1:]:
try:
res = c.__getattribute__(c, name)
- if isinstance(res, variable.Variable):
+ if isinstance(res, Variable):
return res
except BaseException:
pass
@@ -121,22 +120,23 @@ def __init__(self, **kwargs):
for key, val in kwargs.items():
if hasattr(self.__class__, key):
clsattr = getattr(self.__class__, key)
- if isinstance(clsattr, variable.Variable):
+ if isinstance(clsattr, Variable):
varvals[clsattr] = val
continue
- print("unexpected (misspelled?) keyword argument",key,"=",val)
+
nonvarkwargs[key] = val
+
# pass other kwargs to super:
super().__init__(**nonvarkwargs)
# assign Variable values:
for var, val in varvals.items():
var.set_value(self, val)
-
+
def complete_values(self):
"""assign default values to all unset Variables"""
for var in self.variables:
if (not hasattr(self, var.codename) # this happens for unset properties
- or isinstance(getattr(self, var.codename), variable.Variable)):
+ or isinstance(getattr(self, var.codename), Variable)):
# class attribute was returned by getattr,
# hence object attribute has not been assigned a value yet.
try:
@@ -151,7 +151,7 @@ def complete_values(self):
def set_value(self, var, value):
"""Dummy docstring"""
# TODO: add docstring to method
- assert isinstance(var, variable.Variable), \
+ assert isinstance(var, Variable), \
"variable must be a Variable object"
var.set_value(self, value)
diff --git a/pycopancore/private/_simple_expressions.py b/pycopancore/private/_simple_expressions.py
new file mode 100644
index 00000000..e318f220
--- /dev/null
+++ b/pycopancore/private/_simple_expressions.py
@@ -0,0 +1,39 @@
+"""Created on Mar 20, 2017.
+
+@author: heitzig
+"""
+
+# This file is part of pycopancore.
+#
+# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
+# Impact Research
+#
+# URL:
+# Contact: core@pik-potsdam.de
+# License: BSD 2-clause license
+
+# defines logics to deal with symbolic expressions and their evaluation
+
+
+class _Unknown(object):
+
+ def __str__(self):
+ return "unknown"
+
+ def update(self, *args):
+ return self
+
+
+unknown = _Unknown()
+
+
+class _Unset(object):
+
+ def __str__(self):
+ return "unset"
+
+ def update(self, *args):
+ return self
+
+
+unset = _Unset()
diff --git a/pycopancore/private/_trajectory_dictionary.py b/pycopancore/private/_trajectory_dictionary.py
index bef03f44..e624f02d 100644
--- a/pycopancore/private/_trajectory_dictionary.py
+++ b/pycopancore/private/_trajectory_dictionary.py
@@ -16,7 +16,8 @@
import pickle, json
import networkx as nx
-from . import _AbstractEntityMixin, _AbstractProcessTaxonMixin
+from ._abstract_entity_mixin import _AbstractEntityMixin
+from ._abstract_process_taxon_mixin import _AbstractProcessTaxonMixin
class _TrajectoryDictionary(dict):
diff --git a/pycopancore/process_types/ODE.py b/pycopancore/process_types/ODE.py
index c777a68a..97f5039a 100644
--- a/pycopancore/process_types/ODE.py
+++ b/pycopancore/process_types/ODE.py
@@ -23,7 +23,7 @@
# Definition of class ODE
#
-from ..private import _AbstractProcess
+from pycopancore.private._abstract_process import _AbstractProcess
class ODE(_AbstractProcess):
diff --git a/pycopancore/process_types/event.py b/pycopancore/process_types/event.py
index 99b5b1cf..bb773534 100644
--- a/pycopancore/process_types/event.py
+++ b/pycopancore/process_types/event.py
@@ -22,7 +22,7 @@
# Definition of class Event
#
-from ..private import _AbstractProcess
+from pycopancore.private._abstract_process import _AbstractProcess
class Event(_AbstractProcess):
diff --git a/pycopancore/process_types/explicit.py b/pycopancore/process_types/explicit.py
index 27a15ef7..e565e388 100644
--- a/pycopancore/process_types/explicit.py
+++ b/pycopancore/process_types/explicit.py
@@ -22,7 +22,7 @@
# Definition of class Event
#
-from ..private import _AbstractProcess
+from pycopancore.private._abstract_process import _AbstractProcess
class Explicit(_AbstractProcess):
diff --git a/pycopancore/process_types/implicit.py b/pycopancore/process_types/implicit.py
index 73ff57cc..810f77d7 100644
--- a/pycopancore/process_types/implicit.py
+++ b/pycopancore/process_types/implicit.py
@@ -21,7 +21,7 @@
# Definition of class Event
#
-from ..private import _AbstractProcess
+from pycopancore.private._abstract_process import _AbstractProcess
class Implicit(_AbstractProcess):
diff --git a/pycopancore/process_types/step.py b/pycopancore/process_types/step.py
index ffedd703..41e075f2 100644
--- a/pycopancore/process_types/step.py
+++ b/pycopancore/process_types/step.py
@@ -23,7 +23,7 @@
# Definition of class Event
#
-from ..private import _AbstractProcess
+from pycopancore.private._abstract_process import _AbstractProcess
class Step(_AbstractProcess):
diff --git a/pycopancore/runners/runner.py b/pycopancore/runners/runner.py
index 1da1f055..799e736d 100644
--- a/pycopancore/runners/runner.py
+++ b/pycopancore/runners/runner.py
@@ -14,11 +14,15 @@
# - rename to ScipyODERunner
# - enable verbosity level, use proper logger
-from .. import Event, Step, Variable
-from ..private import _AbstractRunner, _DotConstruct, eval, unknown, \
- _AbstractEntityMixin, _TrajectoryDictionary, _AbstractProcessTaxonMixin
+from pycopancore.process_types import Event, Step
+from pycopancore.data_model import Variable
+from pycopancore.private._abstract_runner import _AbstractRunner
+from pycopancore.private._expressions import eval
+from pycopancore.private._simple_expressions import unknown
+from pycopancore.private._abstract_entity_mixin import _AbstractEntityMixin
+from pycopancore.private._trajectory_dictionary import _TrajectoryDictionary
# TODO: discuss whether this makes sense or leads to problems:
-from .hooks import Hooks
+from pycopancore.runners.hooks import Hooks
from scipy import integrate
import numpy as np
diff --git a/pycopancore/util/__init__.py b/pycopancore/util/__init__.py
index e9fe8eb7..869d2a54 100644
--- a/pycopancore/util/__init__.py
+++ b/pycopancore/util/__init__.py
@@ -1,2 +1,26 @@
+from .. import config
+
from .functions import *
-from .seeding import *
\ No newline at end of file
+from .seeding import *
+
+# profiling:
+
+try:
+ from line_profiler import LineProfiler
+ class _Profile (object):
+ def __init__(self):
+ self.profile = LineProfiler()
+ def __call__(self, f):
+ return self.profile(f) if config.profile else f
+ def __getattr__(self, key):
+ return getattr(self.profile, key)
+except:
+ class _Profile (object):
+ def __call__(self, f):
+ if config.profile:
+ print("INFO: line_profiler not available")
+ return f
+ def __getattr__(self, key):
+ print("INFO: line_profiler not available")
+ return None
+profile = _Profile()
diff --git a/setup.py b/setup.py
index 94d7930c..af4dae23 100644
--- a/setup.py
+++ b/setup.py
@@ -16,7 +16,7 @@
# This creates a link insteaed of copying the files, so modifications in this directory are modifications in the installed package.
setup(name="pycopancore",
- version="0.7.1",
+ version="0.8.0",
description="Reference implementation of the copan:CORE World-Earth modelling framework",
url="https://github.com/pik-copan/pycopancore",
author="COPAN team @ PIK",
@@ -27,10 +27,10 @@
"numpy>=1.11.0",
"scipy>=0.17.0",
"sympy>=1.0",
- "blist>=1.3.6",
+ # "blist>=1.3.6",
"python-louvain>=0.9",
"profilehooks",
- "pytest",
+ "pytest>=4.6",
"pylama",
"pylint",
"pytest-cov>=2.5.1",
diff --git a/studies/.gitignore b/studies/.gitignore
deleted file mode 100755
index bb4dfe9d..00000000
--- a/studies/.gitignore
+++ /dev/null
@@ -1,3 +0,0 @@
-/fort.1
-/*.html
-/*.png
diff --git a/studies/coccon_tutorial.py b/studies/coccon_tutorial.py
deleted file mode 100755
index 7fcf0d9a..00000000
--- a/studies/coccon_tutorial.py
+++ /dev/null
@@ -1,180 +0,0 @@
-"""Run script for CoCCoN tutorial model."""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-from time import time
-from numpy import random, array, average, exp
-from pylab import show, subplots
-
-from pycopancore import master_data_model as D
-from pycopancore.runners import Runner
-
-import pycopancore.models.coccon.full as M
-
-# first thing: set seed so that each execution must return same thing:
-
-random.seed(1)
-
-# parameters:
-
-nworlds = 1 # no. worlds
-nsocs = 5 #2 # no. social_systems
-ncells = 50 #20 # no. cells
-ninds = 500 #200 # no. individuals
-years = 100 # time to simulate
-
-# instantiate model and process taxa:
-
-model = M.Model()
-environment = M.Environment()
-metabolism = M.Metabolism(
- renewable_energy_knowledge_spillover_fraction = 0,
-# renewable_energy_knowledge_spillover_fraction = .5,
- basic_emigration_probability_rate = 0,
-# basic_emigration_probability_rate = 1e-13,
- )
-culture = M.Culture(
- awareness_lower_carbon_density=1e-4,
- awareness_upper_carbon_density=2e-4,
- awareness_update_rate=0,
-# awareness_update_rate=.5,
- environmental_friendliness_learning_rate=0,
-# environmental_friendliness_learning_rate=1,
- )
-
-# generate entities and plug them together at random:
-
-world = M.World(environment=environment, metabolism=metabolism, culture=culture,
- atmospheric_carbon = 830 * D.gigatonnes_carbon,
- upper_ocean_carbon = (5500 - 830 - 2480 - 1125) * D.gigatonnes_carbon
- )
-social_systems = [M.SocialSystem(world=world,
- has_renewable_subsidy = random.choice([False, True], p=[3/4, 1/4]),
- has_emissions_tax = random.choice([False, True], p=[4/5, 1/5]),
- has_fossil_ban = False,
- time_between_votes = 1e100,
-# time_between_votes = 4,
- )
- for s in range(nsocs)]
-cells = [M.Cell(social_system=random.choice(social_systems),
- renewable_sector_productivity = 2 * random.rand() * M.Cell.renewable_sector_productivity.default
- )
- for c in range(ncells)]
-individuals = [M.Individual(cell=random.choice(cells),
- is_environmentally_friendly = random.choice([False, True], p=[.7, .3]),
- )
- for i in range(ninds)]
-
-# initialize block model acquaintance network:
-
-target_degree = 20
-target_degree_samecell = 0.5 * target_degree
-target_degree_samesoc = 0.35 * target_degree
-target_degree_other = 0.15 * target_degree
-p_samecell = target_degree_samecell / (ninds/ncells - 1)
-p_samesoc = target_degree_samesoc / (ninds/nsocs - ninds/ncells - 1)
-p_other = target_degree_other / (ninds - ninds/nsocs - 1)
-for index, i in enumerate(individuals):
- for j in individuals[:index]:
- if random.uniform() < (
- p_samecell if i.cell == j.cell
- else p_samesoc if i.social_system == j.social_system \
- else p_other):
- culture.acquaintance_network.add_edge(i, j)
-
-# distribute global aggregate quantities to cells and social_systems:
-
-r = random.uniform(size=ncells)
-Sigma0 = 1.5e8 * D.square_kilometers * r / sum(r)
-M.Cell.land_area.set_values(cells, Sigma0)
-
-r += random.uniform(size=ncells)
-L0 = 2480 * D.gigatonnes_carbon * r / sum(r) # 2480 is yr 2000
-M.Cell.terrestrial_carbon.set_values(cells, L0)
-
-r = exp(random.normal(size=ncells))
-G0 = 1125 * D.gigatonnes_carbon * r / sum(r) # 1125 is yr 2000
-M.Cell.fossil_carbon.set_values(cells, G0)
-
-r = random.uniform(size=nsocs)
-P0 = 6e9 * D.people * r / sum(r) # 500e9 is middle ages, 6e9 would be yr 2000
-M.SocialSystem.population.set_values(social_systems, P0)
-M.SocialSystem.migrant_population.set_values(social_systems, P0 * 250e6/6e9)
-for s in social_systems:
- s.max_protected_terrestrial_carbon = 0.90 * sum(c.terrestrial_carbon for c in s.cells)
-
-r = random.uniform(size=nsocs)
-K0 = sum(P0) * 1e4 * D.dollars/D.people * r / sum(r)
-M.SocialSystem.physical_capital.set_values(social_systems, K0)
-
-r = random.uniform(size=nsocs)
-S0 = 1e12 * D.gigajoules * r / r.mean()
-M.SocialSystem.renewable_energy_knowledge.set_values(social_systems, S0)
-
-# print initial global state:
-
-for v in culture.variables:
- if v.unit: print(v, v.get_quantity(culture))
-for v in environment.variables:
- if v.unit: print(v, v.get_quantity(environment))
-for v in metabolism.variables:
- if v.unit: print(v, v.get_quantity(metabolism))
-for v in world.variables:
- if v.unit: print(v, v.get_quantity(world))
-
-# run simulation:
-
-runner = Runner(model=model)
-starttime = time()
-traj = runner.run(t_0=2000, t_1=2000+years, dt=1,
- add_to_output=[M.Individual.represented_population])
-
-# plots:
-
-t = array(traj['t'])
-
-fig, (ax1,ax2,ax3) = subplots(3, sharex=True)
-
-ax1.plot(t[3:], 100*average(array([traj[M.Individual.is_environmentally_friendly][i][3:] for i in individuals]),
- weights=[traj[M.Individual.represented_population][i][0] for i in individuals],
- axis=0),
- "--", color="green", lw=1, label="env. friendly individuals")
-ax1.plot(t[3:], 100*average(array([traj[M.SocialSystem.has_renewable_subsidy][s][3:] for s in social_systems]), axis=0),
- color="orange", lw=2, label="social_systems with renewable subsidy")
-ax1.plot(t[3:], 100*average(array([traj[M.SocialSystem.has_emissions_tax][s][3:] for s in social_systems]), axis=0),
- color="blue", lw=2, label="social_systems with emissions tax")
-ax1.plot(t[3:], 100*average(array([traj[M.SocialSystem.has_fossil_ban][s][3:] for s in social_systems]), axis=0),
- color="black", lw=2, label="social_systems with fossil ban")
-ax1.set_ylabel('percent')
-ax1.legend()
-
-for i, s in enumerate(social_systems):
- ax2.semilogy(t[3:], traj[M.SocialSystem.population][s][3:], color="yellow", lw=2, label="population [humans]" if i==0 else None)
- ax2.semilogy(t[3:], traj[M.SocialSystem.physical_capital][s][3:], color="black", lw=2, label="physical capital [$]" if i==0 else None)
- ax2.semilogy(t[3:], traj[M.SocialSystem.renewable_energy_knowledge][s][3:], color="orange", lw=2, label="renewable energy knowledge [GJ]" if i==0 else None)
-ax2.set_ylabel('(mixed units)')
-ax2.legend()
-
-ax3.plot(t[3:], traj[M.World.atmospheric_carbon][world][3:], color="cyan", lw=3, label="atmospheric carbon")
-ax3.plot(t[3:], traj[M.World.upper_ocean_carbon][world][3:], color="blue", lw=3, label="upper ocean carbon")
-ax3.plot(t[3:], traj[M.World.terrestrial_carbon][world][3:], color="green", lw=3, label="terrestrial carbon")
-ax3.plot(t[3:], traj[M.World.fossil_carbon][world][3:], color="gray", lw=3, label="fossil carbon")
-ax3.set_ylabel('global GtC')
-ax3.legend()
-ax3b = ax3.twinx()
-for c in cells:
- ax3b.plot(t[3:], traj[M.Cell.terrestrial_carbon][c][3:], color="green", lw=1, alpha=0.2)
-ax3b.set_ylabel("cells' GtC")
-
-print(time()-starttime, " seconds")
-
-show()
-
-
diff --git a/studies/esd_description_paper_example/README.md b/studies/esd_description_paper_example/README.md
index f0d9f8f8..01be1ef0 100755
--- a/studies/esd_description_paper_example/README.md
+++ b/studies/esd_description_paper_example/README.md
@@ -10,53 +10,4 @@ Run the following code:
python run_esd_example.py -p 0.25 -s 0
python run_esd_example.py -p 0.4 -s 0 -u 12 --with-social
python plot_figure5.py
-```
-
-# Plot figure 6
-As of now this only works properly on the High Performance Cluster at the
-Potsdam Institute for Climate Impact Research.
-
-Follow these steps to reproduce the figure:
-1. Create a temporary output directory for the results of the model
- simulations. On PIK's high performace cluster this should be somewhere under
- `/p/tmp/YOURUSERNAME/`. We call this directory `OUTPUTPATH` from here on.
-
-2. Set the correct path `OUTPUTPATH` in line 9 of
- `submit_jobarray.sh`.
-
-3. Make sure the `pycopancore` repository is located in your home folder such
- that `$HOME/pycopancore/studies/esd_description_paper_example/` is a
- valid path. If `pycopancore` is located elsewhere make sure to set the
- correct paths in `submit_single_runs.py` and `submit_jobarray.sh`.
-
-4. Use `sbatch submit_jobarray.sh` to submit the simulations to the cluster.
-
-5. Use `collect_results.py -t OUTPUTPATH` to collect the simulation data and
- store them in a single file called `results_ensemble.p` for later
- processing.
-
-6. Use `plot_figure6.py` to plot the results of the bifurcation analysis. The
- scripts loads `results_ensemble.p` and the simulation data without social
- processes that was created using `python run_esd_example.py -p 0.25 -s 0`
- above.
-
-# Some further information on the files in this directory
-
-## run_esd_example.py
-Runs one simulation for a specified learning rate. As this script is intended
-to run on a cluster it must be called with a `task-id` (that corresponds to the
-id of the job array entry) which is then translated into a corresponding
-learning rate. Secondly a seed must be specified as input argument. This script
-produces large output, so it should only be used on a cluster with large
-storage capacity. Use `collect_results.py` after running this script to get
-data of manageable size.
-
-## submit_jobarray.sh
-Submit the simulation to the cluster. Adjust as needed.
-
-## submit_single_runs.py
-Helper scripts that calls `run_esd_example.py` 50 times in a row for the same
-task id, i.e., learning rate, and different seeds. This is needed to circumvent
-the limit of a maximum of 3600 single jobs per job array on PIKs high
-performance cluster and the fact that a model can only be instantiated once
-when using `pycopancore`.
+```
\ No newline at end of file
diff --git a/studies/esd_description_paper_example/collect_results.py b/studies/esd_description_paper_example/collect_results.py
deleted file mode 100755
index 37092aa2..00000000
--- a/studies/esd_description_paper_example/collect_results.py
+++ /dev/null
@@ -1,60 +0,0 @@
-import os
-import argparse
-import pickle
-import glob
-import numpy as np
-
-def main():
-
- parser = argparse.ArgumentParser()
- parser.add_argument('-t', '--tmp-dir', required=True)
- parser.add_argument('--overwrite', action='store_const', const=True,
- default=False)
- args = vars(parser.parse_args())
-
- load(input_dir=args["tmp_dir"], overwrite=args["overwrite"])
-
-
-def load(input_dir, overwrite):
-
- if input_dir[-1] != "/":
- input_dir += "/"
-
- files = glob.glob(input_dir+"*.p")
-
- if os.path.exists("results_ensemble.p") and not overwrite:
- results = np.load("results_ensemble.p")
- print("Loading results from disk")
- else:
- results = {"succesful_files": []}
- print("Creating new results file")
-
- files = [f for f in files if f not in results["succesful_files"]]
- print(len(files))
- for i, datafile in enumerate(files):
-
- print(i, datafile, end="\r")
-
- updaterate = float(datafile.split("_")[6])
-
- if updaterate not in results.keys():
- results[updaterate] = {"terr": [], "atmo": [], "foss": [], "ocea": [],
- "gmt": [], "econ": []}
-
- data = np.load(datafile)
-
- world = list(data["World.surface_air_temperature"].keys())[0]
-
- results[updaterate]["terr"].append(data["World.terrestrial_carbon"][world][-1])
- results[updaterate]["atmo"].append(data["World.atmospheric_carbon"][world][-1])
- results[updaterate]["foss"].append(data["World.fossil_carbon"][world][-1])
- results[updaterate]["ocea"].append(data["World.upper_ocean_carbon"][world][-1])
- results[updaterate]["gmt"].append(data["World.surface_air_temperature"][world][-1])
-
- social_systems = list(data["SocialSystem.has_emissions_tax"].keys())
- econ = [data["SocialSystem.economic_output_flow"][s][-1] for s in social_systems]
- results[updaterate]["econ"].append(econ)
-
- results["succesful_files"].append(datafile)
-
- pickle.dump(results, open("results_ensemble.p", "wb"))
diff --git a/studies/esd_description_paper_example/esd_example_without_social_seed_0.p b/studies/esd_description_paper_example/esd_example_without_social_seed_0.p
deleted file mode 100644
index 3942b7ae..00000000
Binary files a/studies/esd_description_paper_example/esd_example_without_social_seed_0.p and /dev/null differ
diff --git a/studies/esd_description_paper_example/plot_figure6.py b/studies/esd_description_paper_example/plot_figure6.py
deleted file mode 100755
index 6b8f69cc..00000000
--- a/studies/esd_description_paper_example/plot_figure6.py
+++ /dev/null
@@ -1,89 +0,0 @@
-#!/usr/bin/env python
-# coding: utf-8
-import numpy as np
-from matplotlib import pyplot as plt
-
-AX1_PLOTS = (("terr", "g", "Terrestrial carbon"),
- ("atmo", "c", "Atmospheric carbon"),
- ("ocea", "b", "Ocean carbon"))
-
-def main():
-
- _, (ax1, ax2) = plt.subplots(2, 1, sharex=True, figsize=(6, 8))
- ax3 = ax2.twinx()
-
- results = np.load("results_ensemble.p", allow_pickle=True)
- baseline = np.load("esd_example_without_social_seed_0.p", allow_pickle=True)
-
- keys = [k for k in results.keys() if isinstance(k, float)]
- keys.sort()
-
- for shortlabel, color, label in AX1_PLOTS:
- _y = np.zeros((len(keys), 2))
- for i, key in enumerate(keys):
- _y[i, 0] = np.mean(results[key][shortlabel])
- _y[i, 1] = np.std(results[key][shortlabel])
- ax1.errorbar(keys, _y[:, 0], yerr=_y[:, 1], fmt='o', c=color,
- alpha=0.5, label=label)
-
-
- gmt = np.zeros((len(keys), 2))
- econ = np.zeros((len(keys), 4))
- for i, key in enumerate(keys):
- gmt[i, 0] = np.mean(results[key]["gmt"])
- gmt[i, 1] = np.std(results[key]["gmt"])
- econ[i, 0:2] = np.mean(results[key]["econ"], axis=0)
- econ[i, 2:] = np.std(results[key]["econ"], axis=0)
-
- econ[:, 0::2] /= 0.25 * 6e9
- econ[:, 1::2] /= 0.75 * 6e9
-
- ax2.errorbar(keys, econ[:, 0], yerr=econ[:, 2], fmt='o', c="r",
- alpha=0.5, label="North")
- ax2.errorbar(keys, econ[:, 1], yerr=econ[:, 3], fmt='d', c="r",
- alpha=0.5, label="South")
-
- ax3.errorbar(keys, gmt[:, 0], yerr=gmt[:, 1], fmt='o', c="k",
- alpha=0.5, label="Global Mean Temperature")
-
- world = list(baseline["World.surface_air_temperature"].keys())[0]
-
- _y = baseline["World.terrestrial_carbon"][world][-1]
- ax1.axhline(_y, c="g", ls="--", lw=2)
-
- _y = baseline["World.atmospheric_carbon"][world][-1]
- ax1.axhline(_y, c="c", ls="--", lw=2)
-
- _y = baseline["World.upper_ocean_carbon"][world][-1]
- ax1.axhline(_y, c="b", ls="--", lw=2)
-
- social_systems = list(baseline["SocialSystem.has_emissions_tax"].keys())
- _y = [baseline["SocialSystem.economic_output_flow"][s][-1] for s in social_systems]
- ax2.axhline(_y[0] / 0.25 / 6e9, ls="--", lw=2, c="r")
- ax2.axhline(_y[1] / 0.75 / 6e9, ls="--", lw=2, c="r")
-
- _y = baseline["World.surface_air_temperature"][world][-1]
- ax3.axhline(_y, c="k", ls="--", lw=2)
-
- ax1.legend()
- ax2.legend(loc="center left")
- ax3.legend(loc="upper left")
-
- ax2.set_xlabel("Learning rate [$yr^{-1}$]")
-
- ax1.set_ylabel("Gigatonnes Carbon in 2120")
- ax2.set_ylabel("GDP/capita in 2120 [$/yr]")
- ax3.set_ylabel("Global mean temperature in 2120 [K]")
-
- ax2.semilogx()
- ax2.semilogy()
- ax2.set_xlim(min(keys), max(keys))
-
- ax3.set_ylim(287.5, 290)
-
- plt.tight_layout()
- plt.savefig("figure6.pdf")
-
-
-if __name__ == "__main__":
- main()
diff --git a/studies/esd_description_paper_example/submit_jobarray.sh b/studies/esd_description_paper_example/submit_jobarray.sh
deleted file mode 100755
index 7569fa05..00000000
--- a/studies/esd_description_paper_example/submit_jobarray.sh
+++ /dev/null
@@ -1,11 +0,0 @@
-#!/bin/bash
-
-#SBATCH --qos=short
-#SBATCH --job-name=core_mult_runs
-#SBATCH --array=0-49
-#SBATCH --output=core-%A_%a.out
-#SBATCH --error=core-%A_%a.err
-#SBATCH --account=copan
-#SBATCH --workdir=
-
-python3 $HOME/pycopancore/studies/esd_description_paper_example/submit_single_runs.py
diff --git a/studies/esd_description_paper_example/submit_single_runs.py b/studies/esd_description_paper_example/submit_single_runs.py
deleted file mode 100755
index ee21232c..00000000
--- a/studies/esd_description_paper_example/submit_single_runs.py
+++ /dev/null
@@ -1,15 +0,0 @@
-import os
-
-try:
- TASK = os.environ['SLURM_ARRAY_TASK_ID']
-except KeyError:
- print("Not running with SLURM job arrays")
- TASK = 0
-
-HOME = os.path.expanduser("~")
-PATH = HOME + "/pycopancore/studies/esd_description_paper_example/"\
- "run_esd_example.py"
-
-for seed in range(50):
- cmd = f"python {PATH} -s {seed} -i {TASK} -p 0.25 --with-social"
- os.system(cmd)
diff --git a/studies/heitzig_sandbox/fit_parameters_example1.py b/studies/heitzig_sandbox/fit_parameters_example1.py
deleted file mode 100755
index 7673b8f2..00000000
--- a/studies/heitzig_sandbox/fit_parameters_example1.py
+++ /dev/null
@@ -1,283 +0,0 @@
-"""Script to run example1 model."""
-
-from time import time
-from numpy import random, array
-import numpy as np
-
-import pycopancore.models.example1 as M
-from pycopancore import master_data_model as D
-from pycopancore.runners import Runner
-
-from pylab import plot, gca, show, figure, subplot, gca, semilogy, legend
-
-from numba.errors import NumbaDeprecationWarning, NumbaPendingDeprecationWarning
-import warnings
-warnings.simplefilter('ignore', category=NumbaDeprecationWarning)
-warnings.simplefilter('ignore', category=NumbaPendingDeprecationWarning)
-
-# first thing: set seed so that each execution must return same thing:
-random.seed(10)
-
-# parameters:
-
-nworlds = 1 # no. worlds
-nsocs = 5 # no. social_systems
-ncells = 100 # no. cells
-ninds = 1000 # no. individuals
-
-t_1 = 2000.01
-
-# choose one of two scenarios:
-with_social = 0 # 0 or 1
-
-# directory to store results:
-dir = "/tmp/";
-
-if with_social:
- filename = dir + "with_social.pickle"
- with_migration = 0
- with_awareness = 1
- with_learning = 1
- with_voting = 1
-else:
- filename = dir + "without_social.pickle"
- with_migration = 0
- with_awareness = 0
- with_learning = 0
- with_voting = 0
-with_spillovers = 1
-
-print("Using model as defined in file", M.__file__)
-model = M.Model()
-runner = Runner(model=model)
-
-# instantiate process taxa:
-environment = M.Environment()
-metabolism = M.Metabolism(
- renewable_energy_knowledge_spillover_fraction =
- .1 if with_spillovers else 0,
- basic_emigration_probability_rate =
- 16e-13 if with_migration else 0, # leads to ca. 5mio. at 5 socs, (real)
- )
-culture = M.Culture(
- awareness_lower_carbon_density=1e-4,
- awareness_upper_carbon_density=2e-4,
- awareness_update_rate = 10 if with_awareness else 0,
- environmental_friendliness_learning_rate = 1 if with_learning else 0,
- max_protected_terrestrial_carbon_share=0,
- terrestrial_carbon_averaging_time=10,
- )
-
-# generate entities and plug them together at random:
-worlds = [M.World(environment=environment,
- metabolism=metabolism,
- culture=culture,
- atmospheric_carbon = 830 * D.gigatonnes_carbon,
- upper_ocean_carbon = (5500 - 830 - 2480 - 1125) * D.GtC
- ) for w in range(nworlds)]
-social_systems = [M.SocialSystem(
- world=random.choice(worlds),
- has_renewable_subsidy = random.choice([False, True],
- p=[3/4, 1/4]),
- has_emissions_tax = random.choice([False, True],
- p=[4/5, 1/5]),
- has_fossil_ban = False,
- time_between_votes = 4 if with_voting else 1e100,
- ) for s in range(nsocs)]
-cells = [M.Cell(social_system=random.choice(social_systems))
- for c in range(ncells)]
-individuals = [M.Individual(
- cell=random.choice(cells),
- is_environmentally_friendly =
- random.choice([False, True], p=[.7, .3]),
- )
- for i in range(ninds)]
-
-# initialize block model acquaintance network:
-target_degree = 150
-target_degree_samecell = 0.5 * target_degree
-target_degree_samesoc = 0.35 * target_degree
-target_degree_other = 0.15 * target_degree
-p_samecell = target_degree_samecell / (ninds/ncells - 1)
-p_samesoc = target_degree_samesoc / (ninds/nsocs - ninds/ncells - 1)
-p_other = target_degree_other / (ninds - ninds/nsocs - 1)
-for index, i in enumerate(individuals):
- for j in individuals[:index]:
- if random.uniform() < (
- p_samecell if i.cell == j.cell
- else p_samesoc if i.social_system == j.social_system \
- else p_other):
- culture.acquaintance_network.add_edge(i, j)
-
-# set renewable sector productivities randomly:
-rel_prod = 2 * random.uniform(size=ncells)
-M.Cell.renewable_sector_productivity.set_values(cells, rel_prod * M.Cell.renewable_sector_productivity.default)
-
-# distribute area and vegetation randomly but correlatedly:
-r = random.uniform(size=ncells)
-Sigma0 = 1.5e8 * D.square_kilometers * r / sum(r)
-M.Cell.land_area.set_values(cells, Sigma0)
-
-r += random.uniform(size=ncells)
-L0 = 2480 * D.gigatonnes_carbon * r / sum(r) # 2480 is yr 2000
-M.Cell.terrestrial_carbon.set_values(cells, L0)
-M.Cell.mean_past_terrestrial_carbon.set_values(cells, L0)
-
-r = np.exp(random.normal(size=ncells))
-G0 = 1125 * D.gigatonnes_carbon * r / sum(r) # 1125 is yr 2000
-M.Cell.fossil_carbon.set_values(cells, G0)
-
-r = random.uniform(size=nsocs)
-P0 = 6e9 * D.people * r / sum(r) # 6e9 is yr 2000
-M.SocialSystem.population.set_values(social_systems, P0)
-M.SocialSystem.migrant_population.set_values(social_systems, P0 * 250e6 / 6e9)
-for s in social_systems:
- s.max_protected_terrestrial_carbon = \
- 0.90 * sum(c.terrestrial_carbon for c in s.cells)
-
-r = random.uniform(size=nsocs)
-K0 = sum(P0) * 1e4 * D.dollars/D.people * r / sum(r) # ?
-M.SocialSystem.physical_capital.set_values(social_systems, K0)
-
-# for renewables, do NOT divide by number of socs:
-r = random.uniform(size=nsocs)
-S0 = 1e12 * D.gigajoules * r / r.mean()
-M.SocialSystem.renewable_energy_knowledge.set_values(social_systems, S0)
-
-w = worlds[0]
-s = social_systems[0]
-c = cells[0]
-for v in environment.variables: print(v,v.get_value(environment))
-for v in metabolism.variables: print(v,v.get_value(metabolism))
-for v in w.variables: print(v,v.get_value(w))
-for v in s.variables: print(v,v.get_value(s))
-for v in c.variables: print(v,v.get_value(c))
-
-
-def get_initial_state():
- return {
- etpt: {
- v: {
- i: v.get_value(i)
- for i in etpt.instances }
- for v in etpt.variables }
- for etpt in [M.Cell, M.Culture, M.Environment, M.Individual, M.Metabolism, M.SocialSystem, M.World] }
-
-def set_initial_state(x0):
- for etpt, vardict in x0.items():
- for v, instancedict in vardict.items():
- if not v.readonly:
- v.set_values(list(instancedict.keys()), list(instancedict.values()))
-
-x0 = get_initial_state()
-
-
-from scipy.optimize import fmin
-
-
-# set sector productivities that roughly match real-world energy production:
-
-print("\n\n\nFITTING SECTOR PRODUCTIVITIES...")
-
-Rtarget = 100 * D.gigawatts / (D.gigajoules / D.years)
-
-def target(productivities):
- print("\n\nTRYING PRODUCTIVITIES",productivities,":\n")
- set_initial_state(x0)
- M.Cell.biomass_sector_productivity.set_values(cells, np.ones(ncells) * productivities[0])
- M.Cell.fossil_sector_productivity.set_values(cells, np.ones(ncells) * productivities[1])
- M.Cell.renewable_sector_productivity.set_values(cells, rel_prod * productivities[2])
- traj = runner.run(t_0=2000, t_1=2000.001, dt=1)
- Bglobal = sum(traj[M.SocialSystem.biomass_input_flow][s][1] for s in social_systems)
- Fglobal = sum(traj[M.SocialSystem.fossil_fuel_input_flow][s][1] for s in social_systems)
- Rglobal = sum(traj[M.SocialSystem.renewable_energy_input_flow][s][1] for s in social_systems) # D.gigajoules / D.years
- err = ((Bglobal - 3)/3)**2 + ((Fglobal - 11)/11)**2 + ((Rglobal - Rtarget)/Rtarget)**2
- print("\nERROR:", err)
- return err
-
-productivities0 = np.array([3e5, 5e6, 7e-18])
-print("START:",productivities0)
-productivities = fmin(target, productivities0)
-print("OPTIMAL:",productivities)
-set_initial_state(x0)
-M.Cell.biomass_sector_productivity.set_values(cells, np.ones(ncells) * productivities[0])
-M.Cell.fossil_sector_productivity.set_values(cells, np.ones(ncells) * productivities[1])
-M.Cell.renewable_sector_productivity.set_values(cells, rel_prod * productivities[2])
-
-
-# set initial capital values that roughly match a certain GDP distribution:
-
-print("\n\n\nFITTING INITIAL CAPITAL...")
-
-GWP_2000 = 33.57e12 # gross world product in 2000 in USD
-
-# for illustration, use a random GDP distribution (later use real-world data):
-r = random.uniform(size=nsocs)
-Ytargets = GWP_2000 * r / r.sum()
-weights = Ytargets**(5/2) / P0
-capitals0 = sum(P0) * 1e4 * weights/sum(weights)
-
-def target2(logcapitals):
- capitals = np.exp(logcapitals)
- print("\n\nTRYING CAPITALS",capitals,":\n")
- set_initial_state(x0)
- M.SocialSystem.physical_capital.set_values(social_systems, capitals)
- traj = runner.run(t_0=2000, t_1=2000.001, dt=1)
- err = ((np.array(M.SocialSystem.economic_output_flow.get_values(social_systems)) - Ytargets)**2).sum()
- print("\nERROR:", err)
- return err
-
-#capitals0 = np.array(M.SocialSystem.physical_capital.get_values(social_systems))
-capitals = np.exp(fmin(target2, np.log(capitals0)))
-print("START:",capitals0)
-print("OPTIMAL:",capitals)
-set_initial_state(x0)
-M.SocialSystem.physical_capital.set_values(social_systems, capitals)
-
-
-exit()
-
-# do simulation:
-start = time()
-traj = runner.run(t_0=2000, t_1=t_1, dt=1,
- add_to_output=[M.Individual.represented_population,
- M.Cell.mean_past_terrestrial_carbon])
-
-for v in environment.variables: print(v,v.get_value(environment))
-for v in metabolism.variables: print(v,v.get_value(metabolism))
-for v in w.variables: print(v,v.get_value(w))
-for v in s.variables: print(v,v.get_value(s))
-for v in c.variables: print(v,v.get_value(c))
-
-
-from pickle import dump
-tosave = {
- v.owning_class.__name__ + "."
- + v.codename: {str(e): traj[v][e]
- for e in traj[v].keys()
- }
- for v in traj.keys() if v is not "t"
- }
-tosave["t"] = traj["t"]
-dump(tosave, open(filename,"wb"))
-print(time()-start, " seconds")
-
-t = np.array(traj['t'])
-print("max. time step", (t[1:]-t[:-1]).max())
-
-
-
-exit()
-
-# POSSIBLY TRY FITTING THESE VALUES AS WELL:
-
-print("\nYr 2000 values (real):")
-print("emigration (5e6):",sum(traj[M.SocialSystem.emigration][s][5]
- for s in social_systems)) # TODO: fit via changing basic_emigration_probability_rate
-print("photo (123):",sum(traj[M.Cell.photosynthesis_carbon_flow][c][5]
- for c in cells)) # TODO: fit via changing cell's basic photosynthesis rate
-print("resp (118):",sum(traj[M.Cell.terrestrial_respiration_carbon_flow][c][5]
- for c in cells)) # TODO: fit via changing cell's basic respiration rate
-print("temp. at begin:", traj[M.World.surface_air_temperature][worlds[0]][5])
-
-
diff --git a/studies/jobst2leander.py b/studies/jobst2leander.py
deleted file mode 100644
index 7ebf5d60..00000000
--- a/studies/jobst2leander.py
+++ /dev/null
@@ -1,215 +0,0 @@
-"""Script to run example2 model, plus comments for possible use by Leander."""
-
-# @Leander: siehe Kommentare mit TODO
-
-from time import time
-from numpy import random, array
-import numpy as np
-
-import pycopancore.models.example2 as M
-from pycopancore import master_data_model as D
-from pycopancore.runners import Runner
-
-from pylab import plot, gca, show, figure, subplot, gca, semilogy, legend
-
-# first thing: set seed so that each execution must return same thing:
-random.seed(10)
-
-# parameters:
-
-nworlds = 1 # no. worlds
-nsocs = 2 # no. social_systems # TODO: zunächst Anzahl Länder in Nils' Daten. Später auf Ländercluster aus Sophie Spilles Arbeit reduzieren.
-ncells = 4 # no. cells # TODO: zunächst = nsocs, also eine pro Land. Später mit Luana abstimmen wegen LPJ. Alternativ: Zellen aus Sophie Spilles Arbeit verwenden.
-ninds = 400 # no. individuals # TODO: 10000 wie bei Nils
-
-t_1 = 2120
-
-filename = "/home/heitzig/work/with.pickle"
-
-with_awareness = 1
-with_learning = 1
-with_voting = 1
-
-model = M.Model()
-
-# instantiate process taxa:
-
-environment = M.Environment()
-
-metabolism = M.Metabolism(
- renewable_energy_knowledge_spillover_fraction = 0
- )
-
-culture = M.Culture(
- awareness_lower_carbon_density=1e-4,
- awareness_upper_carbon_density=2e-4,
- awareness_update_rate = 1 if with_awareness else 0,
- environmental_friendliness_learning_rate = 1 if with_learning else 0,
- )
-
-# generate entities and plug them together:
-
-(world, ) = worlds = [M.World(
- environment = environment,
- metabolism = metabolism,
- culture = culture,
- atmospheric_carbon = 830 * D.gigatonnes_carbon,
- upper_ocean_carbon = (5500 - 830 - 2480 - 1125) * D.GtC
- ) for w in range(nworlds)]
-
-# TODO: statt des folgenden ein SocialSystem pro Land:
-(north, south) = social_systems = [M.SocialSystem(
- world = world,
- has_renewable_subsidy = False,
- has_emissions_tax = False,
- has_fossil_ban = False,
- emissions_tax_intro_threshold = 0.5, # disabled
- renewable_subsidy_intro_threshold = 1, # disabled
- fossil_ban_intro_threshold = 1, # disabled
- emissions_tax_level = 30 * 200e9, # see Wikipedia social cost of carbon. 100e9*3.5,
- time_between_votes = 4 if with_voting else 1e100,
- ) for s in range(nsocs)]
-
-# TODO: statt des folgenden eine Zelle pro Land:
-(boreal, temperate, subtropical, tropical) = cells = [M.Cell(
- social_system = social_systems[c//2],
- renewable_sector_productivity = [.7, .9, 1.1, 1.3][c]
- * 2000 * M.Cell.renewable_sector_productivity.default,
- # represents dependency of solar energy on solar insolation angle
- fossil_sector_productivity = M.Cell.fossil_sector_productivity.default * 7,
- biomass_sector_productivity = M.Cell.biomass_sector_productivity.default * 5
- # these values result in realistic total energy production for the year 2000, see below # TODO: anpassen, so dass die Gesamtenergieprod. wieder stimmt, s.u.
- ) for c in range(ncells)]
-
-# TODO: hier die Variable is_environmentally_friendly stattdessen gemäß Nils' "certainly active" nodes ersetzen:
-individuals = [M.Individual(
- cell = cells[i%4],
- is_environmentally_friendly =
- random.choice([False, True], p=[.8, .2]), # represents the "20% suffice" assumption
- )
- for i in range(ninds)]
-
-# TODO: statt des folgenden das von Nils Skript GenerateNetwork.py erzeugte Netzwerk einlesen und verwenden:
-# initialize block model acquaintance network:
-target_degree = 10 # = 2.5% of all agents. Dunbar's number would be too large
-target_degree_samecell = 0.5 * target_degree
-target_degree_samesoc = 0.35 * target_degree
-target_degree_other = 0.15 * target_degree
-p_samecell = target_degree_samecell / (ninds/ncells - 1)
-p_samesoc = target_degree_samesoc / (ninds/nsocs - ninds/ncells - 1)
-p_other = target_degree_other / (ninds - ninds/nsocs - 1)
-for index, i in enumerate(individuals):
- for j in individuals[:index]:
- if random.uniform() < (
- p_samecell if i.cell == j.cell
- else p_samesoc if i.social_system == j.social_system \
- else p_other):
- culture.acquaintance_network.add_edge(i, j)
-
-# TODO: statt des folgenden die echten Landflächen der Länder verwenden
-# und dann die Gesamtvegetation von 2480 GtC und die Fossilen Ressourcen von 1125 GtC proportional zur Landfläche der Länder verteilen:
-
-# distribute area and vegetation uniformly since it seems there are no real differences between the actual zones:
-Sigma0 = 1.5e8 * D.square_kilometers * array([0.25, 0.25, .25, .36])
-M.Cell.land_area.set_values(cells, Sigma0)
-
-L0 = 2480 * D.gigatonnes_carbon * array([0.25, 0.25, .25, .25]) # 2480 is yr 2000
-M.Cell.terrestrial_carbon.set_values(cells, L0)
-
-# distribute fossils linearly from north to south:
-G0 = 1125 * D.gigatonnes_carbon * array([.4, .3, .2, .1]) # 1125 is yr 2000
-M.Cell.fossil_carbon.set_values(cells, G0)
-
-# TODO: statt des folgenden die reale Bevölkerung der Länder gemäß Nils' Inputdaten verwenden:
-# distribute population 1:3 between north and south, and 2:3 within each:
-r = random.uniform(size=nsocs)
-P0 = 6e9 * D.people * array([0.1, 0.15, 0.3, 0.45]) # 6e9 is yr 2000
-M.SocialSystem.population.set_values(social_systems, P0)
-
-# TODO: statt des folgenden zunächst ein Kapital von 1e4 $ * Bevölkerung des Landes annehmen:
-# distribute capital 2:1:
-K0 = sum(P0) * 1e4 * D.dollars/D.people * array([2/3, 1/3])
-M.SocialSystem.physical_capital.set_values(social_systems, K0)
-
-# TODO: dies so lassen (alle wissen genau gleich viel zu erneuerbaren Energien):
-S0 = 1e12 * D.gigajoules * array([1, 1])
-M.SocialSystem.renewable_energy_knowledge.set_values(social_systems, S0)
-
-w = worlds[0]
-s = social_systems[0]
-c = cells[0]
-for v in environment.variables: print(v,v.get_value(environment))
-for v in metabolism.variables: print(v,v.get_value(metabolism))
-for v in w.variables: print(v,v.get_value(w))
-for v in s.variables: print(v,v.get_value(s))
-for v in c.variables: print(v,v.get_value(c))
-
-
-# do simulation:
-runner = Runner(model=model)
-start = time()
-traj = runner.run(t_0=2000, t_1=t_1, dt=1,
- add_to_output=[
- M.Individual.represented_population,
- M.SocialSystem.population
- ])
-
-
-for v in environment.variables: print(v,v.get_value(environment))
-for v in metabolism.variables: print(v,v.get_value(metabolism))
-for v in w.variables: print(v,v.get_value(w))
-for v in s.variables: print(v,v.get_value(s))
-for v in c.variables: print(v,v.get_value(c))
-
-
-from pickle import dump
-tosave = {
- v.owning_class.__name__ + "."
- + v.codename: {str(e): traj[v][e]
- for e in traj[v].keys()
- }
- for v in traj.keys() if v is not "t"
- }
-tosave["t"] = traj["t"]
-dump(tosave, open(filename,"wb"))
-print(time()-start, " seconds")
-
-t = np.array(traj['t'])
-print("max. time step", (t[1:]-t[:-1]).max())
-
-print("\nyr 2000 values (real):")
-print("photo (123):",sum(traj[M.Cell.photosynthesis_carbon_flow][c][5]
- for c in cells))
-print("resp (118):",sum(traj[M.Cell.terrestrial_respiration_carbon_flow][c][5]
- for c in cells))
-print("GWP (4e13):",sum(traj[M.SocialSystem.economic_output_flow][s][5]
- for s in social_systems))
-B0 = sum(traj[M.SocialSystem.biomass_input_flow][s][5]
- for s in social_systems)
-Bglobal = B0 * D.gigatonnes_carbon / D.years
-Fglobal = sum(traj[M.SocialSystem.fossil_fuel_input_flow][s][5]
- for s in social_systems) * D.gigatonnes_carbon / D.years
-Rglobal = sum(traj[M.SocialSystem.renewable_energy_input_flow][s][5]
- for s in social_systems) * D.gigajoules / D.years
-Eglobal = sum(traj[M.SocialSystem.secondary_energy_flow][s][5]
- for s in social_systems) * D.gigajoules / D.years
-
-# TODO: oben in Z.79/80 die Faktoren so wählen, dass hier ungef. B=3, F=11 und R=100 herauskommt:
-print("B, F, R:",
- Bglobal, Bglobal.tostr(unit=D.gigatonnes_carbon/D.years),
- Fglobal, Fglobal.tostr(unit=D.gigatonnes_carbon/D.years),
- Rglobal, Rglobal.tostr(unit=D.gigawatts),
- )
-print("cap. deprec. at begin (0.1?):",
- np.mean([traj[M.SocialSystem.physical_capital_depreciation_rate][s][5]
- for s in social_systems]))
-print("cap. deprec. at end (0.1?):",
- np.mean([traj[M.SocialSystem.physical_capital_depreciation_rate][s][-1]
- for s in social_systems]))
-print("temp. at begin:", traj[M.World.surface_air_temperature][worlds[0]][5])
-print("temp. at end:", traj[M.World.surface_air_temperature][worlds[0]][-1])
-print("has emissions tax at begin", traj[M.SocialSystem.has_emissions_tax][north][5])
-print("has emissions tax at end", traj[M.SocialSystem.has_emissions_tax][north][-1])
-print("biomass prod. at begin", traj[M.Cell.biomass_relative_productivity][boreal][5] / traj[M.Cell.terrestrial_carbon][boreal][5]**2)
-print("biomass prod. at end", traj[M.Cell.biomass_relative_productivity][boreal][-1] / traj[M.Cell.terrestrial_carbon][boreal][-1]**2)
-
diff --git a/studies/plot_example1.py b/studies/plot_example1.py
deleted file mode 100755
index d5aad72e..00000000
--- a/studies/plot_example1.py
+++ /dev/null
@@ -1,130 +0,0 @@
-"""Script to plot example1 model results."""
-
-#dir = "/home/heitzig/work/pycopancore/";
-dir = "/tmp/";
-
-import numpy as np
-from numpy import array, average, mean
-from pylab import plot, gca, show, figure, subplots, gca, semilogy, legend, \
- tight_layout, NullLocator
-from pickle import load
-
-f, ((ax11, ax12), (ax21, ax22), (ax31, ax32)) = \
- subplots(nrows=3, ncols=2, sharex=True, sharey=False, figsize=(12, 12))
-lws = 1
-al = 0.5
-
-# LEFT: without policy
-
-ax11.title.set_text('example run without socio-cultural processes')
-
-traj = load(open(dir + "without_social.pickle","rb"))
-worlds = list(traj["World.atmospheric_carbon"].keys())
-social_systems = list(traj["SocialSystem.population"].keys())
-cells = list(traj["Cell.fossil_carbon"].keys())
-individuals = list(traj["Individual.is_environmentally_friendly"].keys())
-t = np.array(traj['t'])
-
-# cultural
-ax11.plot(t[3:], 100*average([array(traj["Individual.is_environmentally_friendly"][i][3:]*1) for i in individuals], axis=0,
- weights=[array(traj["Individual.represented_population"][i][3:]*1) for i in individuals]),
- color="green",lw=2, label="env. friendly individuals")
-ax11.plot(t[3:], 100*mean([array(traj["SocialSystem.has_renewable_subsidy"][s][3:]*1) for s in social_systems], axis=0),
- color="darkorange",lw=2, label="regions w/ renewable subsidy")
-ax11.plot(t[3:], 1 + 100*mean([array(traj["SocialSystem.has_emissions_tax"][s][3:]*1) for s in social_systems], axis=0),
- color="cyan",lw=2, label="regions w/ emissions tax")
-ax11.plot(t[3:], 100*mean([array(traj["SocialSystem.has_fossil_ban"][s][3:]*1) for s in social_systems], axis=0),
- color="gray",lw=2, label="regions w/ fossil ban")
-ax11.set_ylabel('CUL:\nglobal opinions & policies\n(percent)')
-ax11.set_ylim(-5,105)
-# ax11.legend(title='CUL: opinions & policies')
-ax11.legend(loc=7)
-
-# metabolic
-for i, s in enumerate(social_systems):
- Es = array(traj["SocialSystem.secondary_energy_flow"][s][3:])
- ax21.plot(t[3:], 100*array(traj["SocialSystem.biomass_input_flow"][s][3:]) * 40e9 / Es,
- color="green", lw=lws, alpha=al, label=None if i else "biomass (5 regions)")
- ax21.plot(t[3:], 100*array(traj["SocialSystem.fossil_fuel_input_flow"][s][3:]) * 47e9 / Es,
- color="gray", lw=lws, alpha=al, label=None if i else "fossils (5 regions)")
- ax21.plot(t[3:], 100*array(traj["SocialSystem.renewable_energy_input_flow"][s][3:]) / Es,
- color="darkorange", lw=lws, alpha=al, label=None if i else "renewables (5 regions)")
-ax21.set_ylabel('MET:\nregional energy shares\n(percent)')
-ax21.set_ylim(-5,105)
-#ax21.legend(title='MET: regional energy shares')
-ax21.legend(loc=7)
-
-# environmental
-ax31.plot(t[3:], traj["World.atmospheric_carbon"][worlds[0]][3:],
- color="cyan", lw=2, label="atmosphere")
-ax31.plot(t[3:], traj["World.upper_ocean_carbon"][worlds[0]][3:],
- color="blue", lw=2, label="upper oceans")
-ax31.plot(t[3:], sum(array(traj["Cell.terrestrial_carbon"][c][3:]) for c in cells),
- color="green", lw=2, label="plants & soils")
-ax31.plot(t[3:], sum(array(traj["Cell.fossil_carbon"][c][3:]) for c in cells),
- color="gray", lw=2, label="fossils")
-ax31.set_ylabel('ENV:\nglobal carbon stocks\n(gigatonnes carbon)')
-ax31.set_ylim(-100,3100)
-#ax31.legend(title='ENV: global carbon stocks')
-ax31.legend(loc=7)
-
-ax31.set_xlabel('year')
-ax31.set_xlim(1990,2110)
-
-# RIGHT: with policy
-
-ax12.title.set_text('example run with socio-cultural processes')
-
-traj = load(open(dir + "with_social.pickle","rb"))
-worlds = list(traj["World.atmospheric_carbon"].keys())
-social_systems = list(traj["SocialSystem.population"].keys())
-cells = list(traj["Cell.fossil_carbon"].keys())
-individuals = list(traj["Individual.is_environmentally_friendly"].keys())
-t = np.array(traj['t'])
-
-# cultural
-ax12.plot(t[3:], 100*average([array(traj["Individual.is_environmentally_friendly"][i][3:]*1) for i in individuals], axis=0,
- weights=[array(traj["Individual.represented_population"][i][3:]*1) for i in individuals]),
- color="green",lw=2, label="env. friendly individuals")
-ax12.plot(t[3:], 100*mean([array(traj["SocialSystem.has_renewable_subsidy"][s][3:]*1) for s in social_systems], axis=0),
- color="darkorange",lw=2, label="regions w/ renewable subsidy")
-ax12.plot(t[3:], 100*mean([array(traj["SocialSystem.has_emissions_tax"][s][3:]*1) for s in social_systems], axis=0),
- color="cyan",lw=2, label="regions w/ emissions tax")
-ax12.plot(t[3:], 100*mean([array(traj["SocialSystem.has_fossil_ban"][s][3:]*1) for s in social_systems], axis=0),
- color="gray",lw=2, label="regions w/ fossil ban")
-ax12.set_ylim(-5,105)
-ax12.yaxis.set_major_locator(NullLocator())
-ax12.legend(loc=7)
-
-# metabolic
-for i, s in enumerate(social_systems):
- Es = array(traj["SocialSystem.secondary_energy_flow"][s][3:])
- ax22.plot(t[3:], 100*array(traj["SocialSystem.biomass_input_flow"][s][3:]) * 40e9 / Es,
- color="green", lw=lws, alpha=al, label=None if i else "biomass (5 regions)")
- ax22.plot(t[3:], 100*array(traj["SocialSystem.fossil_fuel_input_flow"][s][3:]) * 47e9 / Es,
- color="gray", lw=lws, alpha=al, label=None if i else "fossils (5 regions)")
- ax22.plot(t[3:], 100*array(traj["SocialSystem.renewable_energy_input_flow"][s][3:]) / Es,
- color="darkorange", lw=lws, alpha=al, label=None if i else "renewables (5 regions)")
-ax22.set_ylim(-5,105)
-ax22.yaxis.set_major_locator(NullLocator())
-ax22.legend(loc=7)
-
-# environmental
-ax32.plot(t[3:], traj["World.atmospheric_carbon"][worlds[0]][3:],
- color="cyan", lw=2, label="atmosphere")
-ax32.plot(t[3:], traj["World.upper_ocean_carbon"][worlds[0]][3:],
- color="blue", lw=2, label="upper oceans")
-ax32.plot(t[3:], sum(array(traj["Cell.terrestrial_carbon"][c][3:]) for c in cells),
- color="green", lw=2, label="plants & soils")
-ax32.plot(t[3:], sum(array(traj["Cell.fossil_carbon"][c][3:]) for c in cells),
- color="gray", lw=2, label="fossils")
-ax32.yaxis.set_major_locator(NullLocator())
-ax32.set_ylim(-100,3100)
-
-ax32.set_xlabel('year')
-ax32.set_xlim(1990,2110)
-ax32.legend(loc=7)
-
-f.subplots_adjust(hspace=0, wspace=0)
-show()
-
diff --git a/studies/plot_example2.py b/studies/plot_example2.py
deleted file mode 100755
index d2cd69ec..00000000
--- a/studies/plot_example2.py
+++ /dev/null
@@ -1,158 +0,0 @@
-"""Script to plot example2 model results."""
-
-import numpy as np
-from numpy import array, average, mean
-from pylab import plot, gca, show, figure, subplots, gca, semilogy, legend, \
- tight_layout, NullLocator
-from pickle import load
-
-f, ((ax11, ax12), (ax21, ax22), (ax2b1, ax2b2), (ax31, ax32)) = \
- subplots(nrows=4, ncols=2, sharex=True, sharey=False, figsize=(12, 12))
-lws = 1
-al = 0.5
-lss = ['-','--']
-
-
-# LEFT: without policy
-
-ax11.title.set_text('example run without socio-cultural processes')
-
-traj = load(open("/home/jobst/work/without.pickle","rb"))
-worlds = list(traj["World.atmospheric_carbon"].keys())
-social_systems = list(traj["SocialSystem.has_emissions_tax"].keys())
-cells = list(traj["Cell.fossil_carbon"].keys())
-individuals = list(traj["Individual.is_environmentally_friendly"].keys())
-t = np.array(traj['t'])
-
-print(social_systems, cells)
-
-# cultural
-for i, s in enumerate(social_systems):
- ax11.plot(t[3:], 100*average([array(traj["Individual.is_environmentally_friendly"][ii][3:]*1) for j, ii in enumerate(individuals) if (j%4)//2 == i], axis=0,
- weights=[array(traj["Individual.represented_population"][ii][3:]*1) for j, ii in enumerate(individuals) if (j%4)//2 == i]),
- color="green",lw=1, linestyle=lss[i], label=None if i else "env. friendly individuals")
-ax11.plot(t[3:], 1 + 100*mean([array(traj["SocialSystem.has_emissions_tax"][s][3:]*1) for s in social_systems], axis=0),
- color="cyan",lw=2, label="regions w/ emissions tax")
-ax11.set_ylabel('CUL:\nregional opinions & policies\n(percent)')
-ax11.set_ylim(-5,105)
-# ax11.legend(title='CUL: opinions & policies')
-#ax11.legend(loc=7)
-
-# metabolic
-for i, s in enumerate(social_systems):
- Es = array(traj["SocialSystem.secondary_energy_flow"][s][3:])
- ax21.plot(t[3:], 100*array(traj["SocialSystem.biomass_input_flow"][s][3:]) * 40e9 / Es,
- color="green", lw=lws, alpha=al, linestyle=lss[i], label=None if i else "biomass")
- ax21.plot(t[3:], 100*array(traj["SocialSystem.fossil_fuel_input_flow"][s][3:]) * 47e9 / Es,
- color="gray", lw=lws, alpha=al, linestyle=lss[i], label=None if i else "fossils")
- ax21.plot(t[3:], 100*array(traj["SocialSystem.renewable_energy_input_flow"][s][3:]) / Es,
- color="darkorange", lw=lws, linestyle=lss[i], alpha=al, label=None if i else "renewables")
- ax2b1.semilogy(t[3:], array(traj["SocialSystem.economic_output_flow"][s][3:])
- / array(traj["SocialSystem.population"][s][3:]),
- color="magenta", lw=lws, alpha=al, linestyle=lss[i], label=None if i else "GDP per capita [USD/yr]")
- ax2b1.semilogy(t[3:], 1e-9 * array(traj["SocialSystem.physical_capital"][s][3:]),
- color="black", lw=lws, alpha=al, linestyle=lss[i], label=None if i else "physical capital [bln. USD]")
-ax21.set_ylabel('MET:\nregional energy shares\n(percent)')
-ax21.set_ylim(-5,105)
-ax2b1.set_ylim(.9e4,1.1e6)
-#ax21.legend(title='MET: regional energy shares')
-#ax21.legend(loc=7)
-
-ax2b1.set_ylabel('MET:\neconomic production\n(log-scale)')
-#ax2b1.set_ylim(-5,105)
-#ax21.legend(title='MET: regional energy shares')
-#ax2b1.legend(loc=7)
-
-# environmental
-ax31.plot(t[3:], traj["World.atmospheric_carbon"][worlds[0]][3:],
- color="cyan", lw=2, label="atmosphere (global)")
-ax31.plot(t[3:], traj["World.upper_ocean_carbon"][worlds[0]][3:],
- color="blue", lw=2, label="upper oceans (global)")
-#ax31.plot(t[3:], sum(array(traj["Cell.terrestrial_carbon"][c][3:]) for c in cells),
-# color="green", lw=2, label="plants & soils")
-#ax31.plot(t[3:], sum(array(traj["Cell.fossil_carbon"][c][3:]) for c in cells),
-# color="gray", lw=2, label="fossils")
-for i, c in enumerate(cells):
- ax31.plot(t[3:], array(traj["Cell.terrestrial_carbon"][c][3:]),
- color="green", lw=1, linestyle=lss[i//2], label=None if i else "plants & soils (per cell)")
- ax31.plot(t[3:], array(traj["Cell.fossil_carbon"][c][3:]),
- color="gray", lw=1, linestyle=lss[i//2], label=None if i else "fossils (per cell)")
-ax31.set_ylabel('ENV:\ncarbon stocks\n(gigatonnes carbon)')
-ax31.set_ylim(-100,1300) #3100)
-#ax31.legend(title='ENV: global carbon stocks')
-#ax31.legend(loc=7)
-
-ax31.set_xlabel('year')
-ax31.set_xlim(1990,2110)
-
-
-# RIGHT: with policy
-
-ax12.title.set_text('example run with socio-cultural processes')
-
-traj = load(open("/home/jobst/work/with.pickle","rb"))
-worlds = list(traj["World.atmospheric_carbon"].keys())
-social_systems = list(traj["SocialSystem.has_emissions_tax"].keys())
-cells = list(traj["Cell.fossil_carbon"].keys())
-individuals = list(traj["Individual.is_environmentally_friendly"].keys())
-t = np.array(traj['t'])
-
-print((s,traj["SocialSystem.has_emissions_tax"][s]) for s in social_systems)
-
-# cultural
-for i, s in enumerate(social_systems):
- ax12.plot(t[3:], 100*average([array(traj["Individual.is_environmentally_friendly"][ii][3:]*1) for j, ii in enumerate(individuals) if (j%4)//2 == i], axis=0,
- weights=[array(traj["Individual.represented_population"][ii][3:]*1) for j, ii in enumerate(individuals) if (j%4)//2 == i]),
- color="green",lw=1, linestyle=lss[i], label=None if i else "env. friendly individuals")
-ax12.plot(t[3:], 100*mean([array(traj["SocialSystem.has_emissions_tax"][s][3:]*1) for s in social_systems], axis=0),
- color="cyan",lw=2, label="regions w/ emissions tax")
-ax12.set_ylim(-5,105)
-ax12.yaxis.set_major_locator(NullLocator())
-ax12.legend(loc=7)
-
-# metabolic
-for i, s in enumerate(social_systems):
- Es = array(traj["SocialSystem.secondary_energy_flow"][s][3:])
- ax22.plot(t[3:], 100*array(traj["SocialSystem.biomass_input_flow"][s][3:]) * 40e9 / Es,
- color="green", lw=lws, alpha=al, linestyle=lss[i], label=None if i else "biomass")
- ax22.plot(t[3:], 100*array(traj["SocialSystem.fossil_fuel_input_flow"][s][3:]) * 47e9 / Es,
- color="gray", lw=lws, alpha=al, linestyle=lss[i], label=None if i else "fossils")
- ax22.plot(t[3:], 100*array(traj["SocialSystem.renewable_energy_input_flow"][s][3:]) / Es,
- color="darkorange", lw=lws, alpha=al, linestyle=lss[i], label=None if i else "renewables")
- ax2b2.semilogy(t[3:], array(traj["SocialSystem.economic_output_flow"][s][3:])
- / array(traj["SocialSystem.population"][s][3:]),
- color="magenta", lw=lws, alpha=al, linestyle=lss[i], label=None if i else "GDP per capita [USD/yr]")
- ax2b2.semilogy(t[3:], 1e-9 * array(traj["SocialSystem.physical_capital"][s][3:]),
- color="black", lw=lws, alpha=al, linestyle=lss[i], label=None if i else "physical capital [bln. USD]")
-ax22.set_ylim(-5,105)
-ax2b2.set_ylim(.9e4,1.1e6)
-ax22.yaxis.set_major_locator(NullLocator())
-ax2b2.yaxis.set_major_locator(NullLocator())
-ax22.legend(loc=7)
-ax2b2.legend(loc=8)
-
-# environmental
-ax32.plot(t[3:], traj["World.atmospheric_carbon"][worlds[0]][3:],
- color="cyan", lw=2, label="atmosphere")
-ax32.plot(t[3:], traj["World.upper_ocean_carbon"][worlds[0]][3:],
- color="blue", lw=2, label="upper oceans")
-#ax32.plot(t[3:], sum(array(traj["Cell.terrestrial_carbon"][c][3:]) for c in cells),
-# color="green", lw=2, label="plants & soils")
-#ax32.plot(t[3:], sum(array(traj["Cell.fossil_carbon"][c][3:]) for c in cells),
-# color="gray", lw=2, label="fossils")
-for i, c in enumerate(cells):
- ax32.plot(t[3:], array(traj["Cell.terrestrial_carbon"][c][3:]),
- color="green", lw=1, linestyle=lss[i//2], label=None if i else "plants & soils (per cell)")
- ax32.plot(t[3:], array(traj["Cell.fossil_carbon"][c][3:]),
- color="gray", lw=1, linestyle=lss[i//2], label=None if i else "fossils (per cell)")
-
-ax32.yaxis.set_major_locator(NullLocator())
-ax32.set_ylim(-100,1300) #3100)
-
-ax32.set_xlabel('year')
-ax32.set_xlim(1990,2110)
-ax32.legend(loc=8)
-
-f.subplots_adjust(hspace=0, wspace=0)
-show()
-
diff --git a/studies/plot_example2_mw.py b/studies/plot_example2_mw.py
deleted file mode 100755
index c5f18765..00000000
--- a/studies/plot_example2_mw.py
+++ /dev/null
@@ -1,168 +0,0 @@
-"""Script to plot example2 model results."""
-import matplotlib
-matplotlib.use("Agg")
-import numpy as np
-from numpy import array, average, mean
-from pylab import plot, gca, show, figure, subplots, gca, semilogy, legend, \
- tight_layout, NullLocator, savefig, setp
-from pickle import load
-
-with_file = "core_with_social_p_0.9.p"
-wo_file ="core_without_social_p_0.4.p"
-
-
-f, ((ax11, ax12), (ax21, ax22), (ax31, ax32)) = \
- subplots(nrows=3, ncols=2, sharey=False, figsize=(12, 12))
-lws = 1
-al = 0.5
-
-# LEFT: without policy
-
-ax11.title.set_text('example run without socio-cultural processes')
-
-traj = load(open(wo_file,"rb"))
-worlds = list(traj["World.atmospheric_carbon"].keys())
-social_systems = list(traj["SocialSystem.has_fossil_ban"].keys())
-cells = list(traj["Cell.fossil_carbon"].keys())
-individuals = list(traj["Individual.is_environmentally_friendly"].keys())
-t = np.array(traj['t'])
-
-print(t)
-print(social_systems, cells)
-
-# cultural
-ax11.plot(t[3:], 100*average([array(traj["Individual.is_environmentally_friendly"][i][3:]*1) for i in individuals], axis=0,
- weights=[array(traj["Individual.represented_population"][i][3:]*1) for i in individuals]),
- color="green",lw=2, label="env. friendly individuals")
-ax11.plot(t[3:], 1 + 100*mean([array(traj["SocialSystem.has_fossil_ban"][s][3:]*1) for s in social_systems], axis=0),
- color="cyan",lw=2, label="regions w/ subsidy and fossil ban")
-ax11.set_ylabel('CUL:\nglobal opinions & policies\n(percent)')
-ax11.set_ylim(-5,105)
-# ax11.legend(title='CUL: opinions & policies')
-ax11.legend(loc=7)
-
-# metabolic
-for i, s in enumerate(social_systems):
- Es = array(traj["SocialSystem.secondary_energy_flow"][s][3:])
- ax21.plot(t[3:], 100*array(traj["SocialSystem.biomass_input_flow"][s][3:]) * 40e9 / Es,
- color="green", lw=lws, alpha=al, label=None if i else "biomass")
- ax21.plot(t[3:], 100*array(traj["SocialSystem.fossil_fuel_input_flow"][s][3:]) * 47e9 / Es,
- color="gray", lw=lws, alpha=al, label=None if i else "fossils")
- ax21.plot(t[3:], 100*array(traj["SocialSystem.renewable_energy_input_flow"][s][3:]) / Es,
- color="darkorange", lw=lws, alpha=al, label=None if i else "renewables")
-ax21.set_ylabel('MET:\nregional energy shares\n(percent)')
-ax21.set_ylim(-5,105)
-#ax21.legend(title='MET: regional energy shares')
-ax21.legend(loc=7)
-
-# environmental
-atmos_carb = traj["World.atmospheric_carbon"][worlds[0]][3:]
-ocean_carb = traj["World.upper_ocean_carbon"][worlds[0]][3:]
-terre_carb = sum(array(traj["Cell.terrestrial_carbon"][c][3:]) for c in cells)
-fossi_carb = sum(array(traj["Cell.fossil_carbon"][c][3:]) for c in cells)
-photosynth = 10 * sum(array(traj["Cell.photosynthesis_carbon_flow"][c][3:]) for c in cells)
-
-print((atmos_carb+terre_carb+ocean_carb)[-1])
-ax31.plot(t[3:], atmos_carb,
- color="cyan", lw=2, label="atmosphere")
-ax31.plot(t[3:], ocean_carb,
- color="blue", lw=2, label="upper oceans")
-ax31.plot(t[3:], terre_carb,
- color="green", lw=2, label="plants & soils")
-ax31.plot(t[3:], fossi_carb,
- color="gray", lw=2, label="fossils")
-ax31.plot(t[3:], photosynth,
- color="yellow", lw=2, label="photo")
-
-ax31.plot(t[3:], (fossi_carb+atmos_carb+ocean_carb+terre_carb)/4,
- color="gray", lw=2, ls=":", label="average")
-
-ax31a = ax31.twinx()
-ax31a.plot(t[3:],
- np.array(traj["World.surface_air_temperature"][worlds[0]][3:]) -
- 273,
- color="black", lw=2, label="GMT")
-ax31a.legend()
-ax31a.set_ylim(13,18)
-setp(ax31a.get_yticklabels(), visible=False)
-
-ax31.set_ylabel('ENV:\nglobal carbon stocks\n(gigatonnes carbon)')
-ax31.set_ylim(-100,4100)
-#ax31.legend(title='ENV: global carbon stocks')
-ax31.legend(loc="upper left")
-
-ax31.set_xlabel('year')
-ax31.set_xlim(1990,2110)
-
-# RIGHT: with policy
-
-ax12.title.set_text('example run with socio-cultural processes')
-
-traj = load(open(with_file,"rb"))
-worlds = list(traj["World.atmospheric_carbon"].keys())
-social_systems = list(traj["SocialSystem.has_fossil_ban"].keys())
-cells = list(traj["Cell.fossil_carbon"].keys())
-individuals = list(traj["Individual.is_environmentally_friendly"].keys())
-t = np.array(traj['t'])
-
-print((s,traj["SocialSystem.has_fossil_ban"][s]) for s in social_systems)
-
-# cultural
-ax12.plot(t[3:], 100*average([array(traj["Individual.is_environmentally_friendly"][i][3:]*1) for i in individuals], axis=0,
- weights=[array(traj["Individual.represented_population"][i][3:]*1) for i in individuals]),
- color="green",lw=2, label="env. friendly individuals")
-ax12.plot(t[3:], 100*mean([array(traj["SocialSystem.has_fossil_ban"][s][3:]*1) for s in social_systems], axis=0),
- color="cyan",lw=2, label="regions w/ subsidy and fossil ban")
-ax12.set_ylim(-5,105)
-ax12.yaxis.set_major_locator(NullLocator())
-ax12.legend(loc=7)
-
-# metabolic
-for i, s in enumerate(social_systems):
- Es = array(traj["SocialSystem.secondary_energy_flow"][s][3:])
- ax22.plot(t[3:], 100*array(traj["SocialSystem.biomass_input_flow"][s][3:]) * 40e9 / Es,
- color="green", lw=lws, alpha=al, label=None if i else "biomass")
- ax22.plot(t[3:], 100*array(traj["SocialSystem.fossil_fuel_input_flow"][s][3:]) * 47e9 / Es,
- color="gray", lw=lws, alpha=al, label=None if i else "fossils")
- ax22.plot(t[3:], 100*array(traj["SocialSystem.renewable_energy_input_flow"][s][3:]) / Es,
- color="darkorange", lw=lws, alpha=al, label=None if i else "renewables")
-ax22.set_ylim(-5,105)
-ax22.yaxis.set_major_locator(NullLocator())
-ax22.legend(loc=7)
-
-# environmental
-atmos_carb = traj["World.atmospheric_carbon"][worlds[0]][3:]
-ocean_carb = traj["World.upper_ocean_carbon"][worlds[0]][3:]
-terre_carb = sum(array(traj["Cell.terrestrial_carbon"][c][3:]) for c in cells)
-fossi_carb = sum(array(traj["Cell.fossil_carbon"][c][3:]) for c in cells)
-
-print((atmos_carb+terre_carb+ocean_carb)[-1])
-ax32.plot(t[3:], atmos_carb,
- color="cyan", lw=2, label="atmosphere")
-ax32.plot(t[3:], ocean_carb,
- color="blue", lw=2, label="upper oceans")
-ax32.plot(t[3:], terre_carb,
- color="green", lw=2, label="plants & soils")
-ax32.plot(t[3:], fossi_carb,
- color="gray", lw=2, label="fossils")
-ax32.plot(t[3:], (fossi_carb+atmos_carb+ocean_carb+terre_carb)/4,
- color="gray", lw=2, ls=":", label="average")
-
-
-ax32a = ax32.twinx()
-ax32a.set_ylabel("Global mean temperature [Celcius]")
-ax32a.plot(t[3:],
- np.array(traj["World.surface_air_temperature"][worlds[0]][3:]) -
- 273,
- color="black", lw=2, label="GMT")
-ax32a.set_ylim(13,18)
-ax32a.legend()
-ax32.yaxis.set_major_locator(NullLocator())
-ax32.set_ylim(-100,4100)
-
-ax32.set_xlabel('year')
-ax32.set_xlim(1990,2110)
-ax32.legend(loc="upper left")
-
-f.subplots_adjust(hspace=0, wspace=0)
-savefig(with_file+"df")
diff --git a/studies/plot_figure5.py b/studies/plot_figure5.py
deleted file mode 100644
index f278489f..00000000
--- a/studies/plot_figure5.py
+++ /dev/null
@@ -1,163 +0,0 @@
-"""Script to plot example2 model results."""
-import matplotlib
-matplotlib.use("Agg")
-import numpy as np
-from numpy import array, average, mean
-from pylab import plot, gca, show, figure, subplots, gca, semilogy, legend, \
- tight_layout, NullLocator, savefig, setp, tight_layout
-from pickle import load
-
-with_file = "with_social_learning_rate_4.p"
-wo_file ="without_social.p"
-
-f, ((ax11, ax12), (ax21, ax22), (ax21a, ax22a), (ax31, ax32)) = \
- subplots(nrows=4, ncols=2, sharex=True, figsize=(12, 14))
-lws = 2
-al = 1.
-
-# LEFT: without policy
-
-ax11.title.set_text('example run without socio-cultural processes')
-
-traj = load(open(wo_file,"rb"))
-worlds = list(traj["World.atmospheric_carbon"].keys())
-social_systems = list(traj["SocialSystem.has_fossil_ban"].keys())
-cells = list(traj["Cell.fossil_carbon"].keys())
-individuals = list(traj["Individual.is_environmentally_friendly"].keys())
-t = np.array(traj['t']) - 2000 # to have model years
-
-print(t)
-print(social_systems, cells)
-
-# cultural
-ax11.plot(t[3:], 100*average([array(traj["Individual.is_environmentally_friendly"][i][3:]*1) for i in individuals], axis=0,
- weights=[array(traj["Individual.represented_population"][i][3:]*1) for i in individuals]),
- color="green",lw=2, label="env. friendly individuals")
-ax11.plot(t[3:], 1 + 100*mean([array(traj["SocialSystem.has_fossil_ban"][s][3:]*1) for s in social_systems], axis=0),
- color="cyan",lw=2, label="regions w/ subsidy and fossil ban")
-ax11.set_ylabel('CUL:\nglobal opinions & policies\n(percent)')
-ax11.set_ylim(-5,105)
-# ax11.legend(title='CUL: opinions & policies')
-ax11.legend(loc=7)
-
-# metabolic
-ls = ["-", ":"]
-#ax21a = ax21.twinx()
-
-for i, s in enumerate(social_systems):
- Es = array(traj["SocialSystem.secondary_energy_flow"][s][3:])
- ax21.plot(t[3:], 100*array(traj["SocialSystem.biomass_input_flow"][s][3:]) * 40e9 / Es,
- color="green", ls=ls[i], lw=lws, alpha=al, label=None if i else "biomass")
- ax21.plot(t[3:], 100*array(traj["SocialSystem.fossil_fuel_input_flow"][s][3:]) * 47e9 / Es,
- color="gray", ls=ls[i], lw=lws, alpha=al, label=None if i else "fossils")
- ax21.plot(t[3:], 100*array(traj["SocialSystem.renewable_energy_input_flow"][s][3:]) / Es,
- color="darkorange", ls=ls[i], lw=lws, alpha=al, label=None if i else "renewables")
- ax21a.plot(t[3:],
- 100*array(traj["SocialSystem.economic_output_flow"][s][3:]) /
- [0.25, 0.75][i] / 6e9,
- color="red", ls=ls[i], lw=lws, alpha=al, label=None if i else "GDP")
-
-ax21a.semilogy()
-ax21.set_ylabel('MET:\nregional energy shares\n(percent)')
-ax21.set_ylim(-5,105)
-#ax21.legend(title='MET: regional energy shares')
-ax21.legend()
-
-ax21a.set_ylabel('MET:\nGDP/capita ($/yr)')
-
-# environmental
-atmos_carb = traj["World.atmospheric_carbon"][worlds[0]][3:]
-ocean_carb = traj["World.upper_ocean_carbon"][worlds[0]][3:]
-terre_carb = sum(array(traj["Cell.terrestrial_carbon"][c][3:]) for c in cells)
-fossi_carb = sum(array(traj["Cell.fossil_carbon"][c][3:]) for c in cells)
-photosynth = 10 * sum(array(traj["Cell.photosynthesis_carbon_flow"][c][3:]) for c in cells)
-
-print((atmos_carb+terre_carb+ocean_carb)[-1])
-ax31.plot(t[3:], atmos_carb,
- color="cyan", lw=2, label="atmosphere")
-ax31.plot(t[3:], ocean_carb,
- color="blue", lw=2, label="upper oceans")
-ax31.plot(t[3:], terre_carb,
- color="green", lw=2, label="plants & soils")
-ax31.plot(t[3:], fossi_carb,
- color="gray", lw=2, label="fossils")
-
-setp(ax12.get_yticklabels(), visible=False)
-setp(ax22.get_yticklabels(), visible=False)
-setp(ax32.get_yticklabels(), visible=False)
-setp(ax22a.get_yticklabels(), visible=False)
-
-ax31.set_ylabel('ENV:\nglobal carbon stocks\n(gigatonnes carbon)')
-ax31.set_ylim(-100,3500)
-ax31.legend(loc="upper left")
-
-ax31.set_xlabel('model year') # if we subtract 2000 above
-ax31.set_xlim(0,120) # (1990,2110)
-
-# RIGHT: with policy
-
-ax12.title.set_text('example run with socio-cultural processes')
-
-traj = load(open(with_file,"rb"))
-worlds = list(traj["World.atmospheric_carbon"].keys())
-social_systems = list(traj["SocialSystem.has_fossil_ban"].keys())
-cells = list(traj["Cell.fossil_carbon"].keys())
-individuals = list(traj["Individual.is_environmentally_friendly"].keys())
-t = np.array(traj['t']) - 2000 # to have model years
-
-print((s,traj["SocialSystem.has_fossil_ban"][s]) for s in social_systems)
-
-# cultural
-ax12.plot(t[3:], 100*average([array(traj["Individual.is_environmentally_friendly"][i][3:]*1) for i in individuals], axis=0,
- weights=[array(traj["Individual.represented_population"][i][3:]*1) for i in individuals]),
- color="green",lw=2, label="env. friendly individuals")
-ax12.plot(t[3:], 100*mean([array(traj["SocialSystem.has_fossil_ban"][s][3:]*1) for s in social_systems], axis=0),
- color="cyan",lw=2, label="regions w/ subsidy and fossil ban")
-ax12.set_ylim(-5,105)
-#ax12.yaxis.set_major_locator(NullLocator())
-#ax12.legend(loc=7)
-
-# metabolic
-#ax22a = ax22.twinx()
-for i, s in enumerate(social_systems):
- Es = array(traj["SocialSystem.secondary_energy_flow"][s][3:])
- ax22.plot(t[3:], 100*array(traj["SocialSystem.biomass_input_flow"][s][3:]) * 40e9 / Es,
- color="green", ls=ls[i], lw=lws, alpha=al, label=None if i else "biomass")
- ax22.plot(t[3:], 100*array(traj["SocialSystem.fossil_fuel_input_flow"][s][3:]) * 47e9 / Es,
- color="gray", ls=ls[i], lw=lws, alpha=al, label=None if i else "fossils")
- ax22.plot(t[3:], 100*array(traj["SocialSystem.renewable_energy_input_flow"][s][3:]) / Es,
- color="darkorange", ls=ls[i], lw=lws, alpha=al, label=None if i else "renewables")
- ax22a.plot(t[3:],
- 100*array(traj["SocialSystem.economic_output_flow"][s][3:]) /
- [0.25, 0.75][i] / 6e9,
- color="red", ls=ls[i], lw=lws, alpha=al, label=None if i else "GDP")
-
-ax22a.semilogy()
-#äax22a.legend()
-ax22.set_ylim(-5,105)
-#ax22.yaxis.set_major_locator(NullLocator())
-#ax22.legend(loc=7)
-
-# environmental
-atmos_carb = traj["World.atmospheric_carbon"][worlds[0]][3:]
-ocean_carb = traj["World.upper_ocean_carbon"][worlds[0]][3:]
-terre_carb = sum(array(traj["Cell.terrestrial_carbon"][c][3:]) for c in cells)
-fossi_carb = sum(array(traj["Cell.fossil_carbon"][c][3:]) for c in cells)
-
-print((atmos_carb+terre_carb+ocean_carb)[-1])
-ax32.plot(t[3:], atmos_carb,
- color="cyan", lw=2, label="atmosphere")
-ax32.plot(t[3:], ocean_carb,
- color="blue", lw=2, label="upper oceans")
-ax32.plot(t[3:], terre_carb,
- color="green", lw=2, label="plants & soils")
-ax32.plot(t[3:], fossi_carb,
- color="gray", lw=2, label="fossils")
-ax32.set_ylim(0,3500)
-
-ax32.set_xlabel('model year')
-ax32.set_xlim(0,120) #(1990,2110)
-#ax32.set_xlim(t.min(), t.max())
-f.subplots_adjust(hspace=0, wspace=0.05)
-tight_layout()
-savefig("figure5.pdf")
diff --git a/studies/plot_jobsts_prototype_1.py b/studies/plot_jobsts_prototype_1.py
deleted file mode 100755
index 80921a7e..00000000
--- a/studies/plot_jobsts_prototype_1.py
+++ /dev/null
@@ -1,123 +0,0 @@
-"""Skript to plot Jobsts prototype model results."""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-import numpy as np
-from numpy import array, average, mean
-from pylab import plot, gca, show, figure, subplots, gca, semilogy, legend, tight_layout, NullLocator
-from pickle import load
-
-f, ((ax11, ax12), (ax21, ax22), (ax31, ax32)) = subplots(nrows=3, ncols=2, sharex=True, sharey=False)
-lws = 1
-al = 0.5
-
-# LEFT: without policy
-
-traj = load(open("/home/jobst/work/without.pickle","rb"))
-worlds = list(traj["World.atmospheric_carbon"].keys())
-social_systems = list(traj["SocialSystem.population"].keys())
-cells = list(traj["Cell.fossil_carbon"].keys())
-individuals = list(traj["Individual.is_environmentally_friendly"].keys())
-t = np.array(traj['t'])
-
-print(sum(array(traj["SocialSystem.protected_terrestrial_carbon"][s]) for s in social_systems)
- / sum(array(traj["Cell.terrestrial_carbon"][c]) for c in cells))
-quit()
-
-# cultural
-ax11.plot(t[3:], 100*average([array(traj["Individual.is_environmentally_friendly"][i][3:]*1) for i in individuals], axis=0,
-# weights=[array(traj["Individual.represented_population"][i][3:]*1) for i in individuals]
- ),color="green",lw=lws, label="env. friendly individuals")
-ax11.plot(t[3:], 100*mean([array(traj["SocialSystem.has_renewable_subsidy"][s][3:]*1) for s in social_systems], axis=0),color="darkorange",lw=lws, label="regions w/ renewable subsidy")
-ax11.plot(t[3:], 100*mean([array(traj["SocialSystem.has_emissions_tax"][s][3:]*1) for s in social_systems], axis=0),color="blue",lw=lws, label="regions w/ emissions tax")
-ax11.plot(t[3:], 100*mean([array(traj["SocialSystem.has_fossil_ban"][s][3:]*1) for s in social_systems], axis=0),color="gray",lw=lws, label="regions w/ fossil ban")
-ax11.set_ylabel('percent')
-ax11.set_ylim(-5,105)
-
-# metabolic
-for i, s in enumerate(social_systems):
- Es = array(traj["SocialSystem.secondary_energy_flow"][s][3:])
- ax21.plot(t[3:], 100*array(traj["SocialSystem.biomass_input_flow"][s][3:]) * 40e9 / Es, color="green", lw=lws, alpha=al, label=None if i else "biomass")
- ax21.plot(t[3:], 100*array(traj["SocialSystem.fossil_fuel_input_flow"][s][3:]) * 47e9 / Es, color="gray", lw=lws, alpha=al, label=None if i else "fossils")
- ax21.plot(t[3:], 100*array(traj["SocialSystem.renewable_energy_input_flow"][s][3:]) / Es, color="darkorange", lw=lws, alpha=al, label=None if i else "renewables")
-#plot(t[3:], 100*average([array(traj["biomass_input_flow"][s][3:]) for s in social_systems], axis=0,
-# weights=[array(traj["population"][s][3:]) for s in social_systems]) * 40e9 / Es, color="green", lw=3, label="global share of biomass energy")
-#plot(t[3:], 100*average([array(traj["fossil_fuel_input_flow"][s][3:]) for s in social_systems], axis=0,
-# weights=[array(traj["population"][s][3:]) for s in social_systems]) * 47e9 / Es, color="gray", lw=3, label="global share of fossil energy")
-#plot(t[3:], 100*average([array(traj["renewable_energy_input_flow"][s][3:]) for s in social_systems], axis=0,
-# weights=[array(traj["population"][s][3:]) for s in social_systems]) / Es, color="darkorange", lw=3, label="global share of renewables")
-ax21.set_ylabel('percent')
-ax21.set_ylim(-5,105)
-
-# natural
-ax31.plot(t[3:], traj["World.atmospheric_carbon"][worlds[0]][3:], color="cyan", lw=2, label="atmosphere")
-ax31.plot(t[3:], traj["World.upper_ocean_carbon"][worlds[0]][3:], color="blue", lw=2, label="upper oceans")
-ax31.plot(t[3:], sum(array(traj["Cell.terrestrial_carbon"][c][3:]) for c in cells), color="green", lw=2, label="plants & soils")
-ax31.plot(t[3:], sum(array(traj["Cell.fossil_carbon"][c][3:]) for c in cells), color="gray", lw=2, label="fossils")
-#for i, s in enumerate(social_systems):
-# plot(t[3:], traj["protected_terrestrial_carbon"][s][3:],color="green",lw=lws, label=None if i else "protected biomass")
-ax31.set_ylabel('gigatonnes carbon')
-
-# RIGHT: with policy
-
-traj = load(open("/home/jobst/work/with.pickle","rb"))
-worlds = list(traj["World.atmospheric_carbon"].keys())
-social_systems = list(traj["SocialSystem.population"].keys())
-cells = list(traj["Cell.fossil_carbon"].keys())
-individuals = list(traj["Individual.is_environmentally_friendly"].keys())
-t = np.array(traj['t'])
-
-# cultural
-ax12.plot(t[3:], 100*average([array(traj["Individual.is_environmentally_friendly"][i][3:]*1) for i in individuals], axis=0,
- weights=[array(traj["Individual.represented_population"][i][3:]*1) for i in individuals]
- ),color="green",lw=lws, label="env. friendly individuals")
-ax12.plot(t[3:], 100*mean([array(traj["SocialSystem.has_renewable_subsidy"][s][3:]*1) for s in social_systems], axis=0),color="darkorange",lw=lws, label="regions w/ renewable subsidy")
-ax12.plot(t[3:], 100*mean([array(traj["SocialSystem.has_emissions_tax"][s][3:]*1) for s in social_systems], axis=0),color="blue",lw=lws, label="regions w/ emissions tax")
-ax12.plot(t[3:], 100*mean([array(traj["SocialSystem.has_fossil_ban"][s][3:]*1) for s in social_systems], axis=0),color="gray",lw=lws, label="regions w/ fossil ban")
-ax12.set_ylim(-5,105)
-ax12.yaxis.set_major_locator(NullLocator())
-ax12.legend()
-
-# metabolic
-for i, s in enumerate(social_systems):
- Es = array(traj["SocialSystem.secondary_energy_flow"][s][3:])
- ax22.plot(t[3:], 100*array(traj["SocialSystem.biomass_input_flow"][s][3:]) * 40e9 / Es, color="green", lw=lws, alpha=al, label=None if i else "biomass")
- ax22.plot(t[3:], 100*array(traj["SocialSystem.fossil_fuel_input_flow"][s][3:]) * 47e9 / Es, color="gray", lw=lws, alpha=al, label=None if i else "fossils")
- ax22.plot(t[3:], 100*array(traj["SocialSystem.renewable_energy_input_flow"][s][3:]) / Es, color="darkorange", lw=lws, alpha=al, label=None if i else "renewables")
-#plot(t[3:], 100*average([array(traj["biomass_input_flow"][s][3:]) for s in social_systems], axis=0,
-# weights=[array(traj["population"][s][3:]) for s in social_systems]) * 40e9 / Es, color="green", lw=3, label="global share of biomass energy")
-#plot(t[3:], 100*average([array(traj["fossil_fuel_input_flow"][s][3:]) for s in social_systems], axis=0,
-# weights=[array(traj["population"][s][3:]) for s in social_systems]) * 47e9 / Es, color="gray", lw=3, label="global share of fossil energy")
-#plot(t[3:], 100*average([array(traj["renewable_energy_input_flow"][s][3:]) for s in social_systems], axis=0,
-# weights=[array(traj["population"][s][3:]) for s in social_systems]) / Es, color="darkorange", lw=3, label="global share of renewables")
-ax22.set_ylim(-5,105)
-ax22.yaxis.set_major_locator(NullLocator())
-ax22.legend()
-
-# natural
-ax32.plot(t[3:], traj["World.atmospheric_carbon"][worlds[0]][3:], color="cyan", lw=2, label="atmosphere")
-ax32.plot(t[3:], traj["World.upper_ocean_carbon"][worlds[0]][3:], color="blue", lw=2, label="upper oceans")
-ax32.plot(t[3:], sum(array(traj["Cell.terrestrial_carbon"][c][3:]) for c in cells), color="green", lw=2, label="plants & soils")
-ax32.plot(t[3:], sum(array(traj["Cell.fossil_carbon"][c][3:]) for c in cells), color="gray", lw=2, label="fossils")
-#for i, s in enumerate(social_systems):
-# plot(t[3:], traj["protected_terrestrial_carbon"][s][3:],color="green",lw=lws, label=None if i else "protected biomass")
-#ax32.yaxis.set_major_locator(NullLocator())
-ax32.legend()
-
-f.subplots_adjust(hspace=0, wspace=0)
-show()
-
-# TODO:
-# policy shares, env. friendly shares
-# transparancy, means
-# wellb. abs., renew., pop. log
-# total protected
-# horiz.
-# save dump with codename,uid as key
\ No newline at end of file
diff --git a/studies/run_adaptive_voter_model.py b/studies/run_adaptive_voter_model.py
deleted file mode 100755
index c271908d..00000000
--- a/studies/run_adaptive_voter_model.py
+++ /dev/null
@@ -1,134 +0,0 @@
-"""Skript to run the model."""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-from time import time
-import datetime as dt
-# from numpy import random
-import random
-# import networkx as nx
-import numpy as np
-# import sys
-import pycopancore.models.adaptive_voter_model as M
-# import pycopancore.models.only_copan_global_like_carbon_cycle as M
-# from pycopancore import master_data_model as D
-from pycopancore.runners import Runner
-
-# import plotly.plotly as py
-import plotly.offline as py
-import plotly.graph_objs as go
-
-# first thing: set seed so that each execution must return same thing:
-random.seed(1)
-# TODO: figure out why it doesn't seem to work here ...
-
-# parameters:
-timeinterval = 100
-timestep = 0.1
-expected_degree = 10
-nindividuals = 4000
-rewiring_probability = 0.1
-possible_opinions = list(range(2))
-p_initial = 0.7 # probability of initial opinion 0 (over opinion 1)
-
-# instantiate model
-model = M.Model()
-
-# instantiate process taxa:
-culture = M.Culture(rewiring=rewiring_probability)
-
-# generate entities and distribute opinions uniformly randomly:
-world = M.World(culture=culture)
-social_system = M.SocialSystem(world=world, culture=culture)
-cell = M.Cell(world=world, social_system=social_system)
-individuals = [M.Individual(cell=cell,
- initial_opinion=int(random.random() < p_initial))
- for _ in range(nindividuals)]
-
-
-def erdosrenyify(graph, p=0.5):
- """Create a ErdosRenzi graph from networkx graph.
-
- Take a a networkx.Graph with nodes and distribute the edges following the
- erdos-renyi graph procedure.
- """
- assert not graph.edges(), "your graph has already edges"
- nodes = list(graph.nodes())
- for i, n1 in enumerate(nodes[:-1]):
- for n2 in nodes[i+1:]:
- if random.random() < p:
- graph.add_edge(n1, n2)
-
-
-# set the initial graph structure to be an erdos-renyi graph
-print("erdosrenyifying the graph ... ", end="", flush=True)
-start = time()
-erdosrenyify(culture.acquaintance_network, p=expected_degree / nindividuals)
-print("done ({})".format(dt.timedelta(seconds=(time() - start))))
-
-runner = Runner(model=model)
-
-start = time()
-traj = runner.run(t_1=timeinterval, dt=timestep)
-runtime = dt.timedelta(seconds=(time() - start))
-print("runtime: {runtime}".format(**locals()))
-
-
-t = np.array(traj['t'])
-print("max. time step", (t[1:]-t[:-1]).max())
-
-individuals_opinions = np.array([traj[M.Individual.opinion][ind]
- for ind in individuals])
-
-nopinion1_list = np.sum(individuals_opinions, axis=0) / nindividuals
-nopinion0_list = 1 - nopinion1_list
-
-# everything below is just plotting commands for plotly
-
-data_opinion0 = go.Scatter(
- x=t,
- y=nopinion0_list,
- mode="lines",
- name="relative amount opinion 0",
- line=dict(
- color="lightblue",
- width=2
- )
-)
-data_opinion1 = go.Scatter(
- x=t,
- y=nopinion1_list,
- mode="lines",
- name="relative amount opinion 1",
- line=dict(
- color="orange",
- width=2
- )
-)
-data_majority_opinion = go.Scatter(
- x=t,
- y=traj[M.SocialSystem.opinion][social_system],
- mode="lines+markers",
- name="majority opinion",
- line=dict(
- color="red",
- width=2
- ),
- marker=dict(
- color="red",
- size=4
- )
-)
-
-layout = dict(title='Adaptive Voter Model',
- xaxis=dict(title='time'),
- )
-
-fig = dict(data=[data_opinion0, data_opinion1, data_majority_opinion], layout=layout)
-py.plot(fig, filename="adaptive-voter-model.html")
diff --git a/studies/run_carbon_voters_anderies.py b/studies/run_carbon_voters_anderies.py
deleted file mode 100755
index 96d5c60e..00000000
--- a/studies/run_carbon_voters_anderies.py
+++ /dev/null
@@ -1,211 +0,0 @@
-"""Skript to run Carbon Voters model."""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-from time import time
-import datetime as dt
-# from numpy import random
-import random
-# import networkx as nx
-import numpy as np
-# import sys
-import pycopancore.models.carbon_voters_anderies_model as M
-# import pycopancore.models.only_copan_global_like_carbon_cycle as M
-from pycopancore import master_data_model as D
-from pycopancore.runners import Runner
-
-# import plotly.plotly as py
-import plotly.offline as py
-import plotly.graph_objs as go
-
-# first thing: set seed so that each execution must return same thing:
-random.seed(1)
-# TODO: figure out why it doesn't seem to work here ...
-
-# parameters:
-timeinterval = 60
-timestep = 1
-expected_degree = 10
-nindividuals = 400
-rewiring_probability = 0.1
-possible_opinions = list(range(2))
-impact_scaling_factor=20
-no_impact_opinion_change=0.5
-no_impact_atmospheric_carbon_level=0.2
-
-# use fast method and with multple updates
-M.avof.Culture.configure(
- update_mode=M.avof.Culture.update_modes.fast,
- synchronous_updates=100
-)
-
-# instantiate model
-model = M.Model()
-
-
-# instantiate process taxa:
-culture = M.Culture(
- timestep=timestep,
- rewiring=rewiring_probability, impact_scaling_factor=impact_scaling_factor,
- no_impact_opinion_change=no_impact_opinion_change,
- no_impact_atmospheric_carbon_level=no_impact_atmospheric_carbon_level
-)
-environment = M.Environment()
-
-# generate entities and distribute opinions uniformly randomly:
-world = M.World(culture=culture, environment=environment,
- atmospheric_carbon=0.2 * D.gigatonnes_carbon,
- ocean_carbon=0.6 * D.gigatonnes_carbon
- )
-social_system = M.SocialSystem(world=world)
-cell = M.Cell(world=world, social_system=social_system)
-individuals = [M.Individual(cell=cell,
- initial_opinion=float(np.random.choice(possible_opinions, 1, p=[0.6,0.4])))
- for _ in range(nindividuals)] # individual opinion 0 with prob. p1, 1(aware) with prob. p2
-
-# set initial values
-Sigma0 = 1.5e8 * D.square_kilometers
-cell.land_area = Sigma0
-# print(M.Cell.land_area.get_values(cells))
-
-L0 = 0.2 * D.gigatonnes_carbon # 2480 is yr 2000
-cell.terrestrial_carbon = L0
-# print(M.Cell.terrestrial_carbon.get_values(cells))
-
-G0 = 0.5 * D.gigatonnes_carbon # 1125 is yr 2000
-cell.fossil_carbon = G0
-
-# TODO: ask Jobst, why are all individuals already in the network?
-
-
-def erdosrenyify(graph, p=0.5):
- """Create a ErdosRenzi graph from networkx graph.
-
- Take a a networkx.Graph with nodes and distribute the edges following the
- erdos-renyi graph procedure.
- """
- assert not graph.edges(), "your graph has already edges"
- nodes = list(graph.nodes())
- for i, n1 in enumerate(nodes[:-1]):
- for n2 in nodes[i+1:]:
- if random.random() < p:
- graph.add_edge(n1, n2)
-
-
-# set the initial graph structure to be an erdos-renyi graph
-print("erdosrenyifying the graph ... ", end="", flush=True)
-start = time()
-erdosrenyify(culture.acquaintance_network, p=expected_degree / nindividuals)
-print("done ({})".format(dt.timedelta(seconds=(time() - start))))
-
-runner = Runner(model=model)
-
-start = time()
-traj = runner.run(t_1=timeinterval, dt=timestep)
-runtime = dt.timedelta(seconds=(time() - start))
-print("runtime: {runtime}".format(**locals()))
-
-
-t = np.array(traj['t'])
-print("max. time step", (t[1:]-t[:-1]).max())
-
-individuals_opinions = np.array([traj[M.Individual.opinion][ind]
- for ind in individuals])
-
-nopinion1_list = np.sum(individuals_opinions, axis=0) / nindividuals
-nopinion0_list = 1 - nopinion1_list
-
-# everything below is just plotting commands for plotly
-
-data_opinion0 = go.Scatter(
- x=t,
- y=nopinion0_list,
- mode="lines",
- name="relative amount opinion 0",
- line=dict(
- color="lightblue",
- width=2
- )
-)
-data_opinion1 = go.Scatter(
- x=t,
- y=nopinion1_list,
- mode="lines",
- name="relative amount opinion 1",
- line=dict(
- color="orange",
- width=2
- )
-)
-# majority opinion
-data_majority_opinion = go.Scatter(
- x=t,
- y=traj[M.SocialSystem.opinion][social_system],
- mode="lines+markers",
- name="majority opinion",
- line=dict(
- color="red",
- width=2
- ),
- marker=dict(
- color="red",
- size=4
- )
-)
-# carbon
-data_ca = go.Scatter(
- x=t,
- y=traj[M.World.atmospheric_carbon][world],
- mode="lines",
- name="atmospheric carbon",
- line=dict(
- color="lightblue",
- width=4
- )
-)
-data_ct = go.Scatter(
- x=t,
- y=traj[M.World.terrestrial_carbon][world],
- mode="lines",
- name="terrestrial carbon",
- line=dict(
- color="green",
- width=4
- )
-)
-data_cm = go.Scatter(
- x=t,
- y=traj[M.World.ocean_carbon][world],
- mode="lines",
- name="maritime carbon",
- line=dict(
- color="blue",
- width=4
- )
-)
-data_cf = go.Scatter(
- x=t,
- y=traj[M.World.fossil_carbon][world],
- mode="lines",
- name="fossil carbon",
- line=dict(
- color="gray",
- width=4
- )
-)
-
-layout = dict(title='Adaptive Voter Model and Anderies Carbon Cycle',
- xaxis=dict(title='time'),
- yaxis=dict(title='relative opinion and carbon amounts'),
- )
-
-fig = dict(data=[data_opinion0, data_opinion1, data_majority_opinion,
- data_ca, data_cf, data_cm, data_ct], layout=layout)
-py.plot(fig, filename="adaptive-voter-model.html")
diff --git a/studies/run_example1.py b/studies/run_example1.py
deleted file mode 100755
index 1b3b4316..00000000
--- a/studies/run_example1.py
+++ /dev/null
@@ -1,231 +0,0 @@
-"""Script to run example1 model."""
-
-from time import time
-from numpy import random, array
-import numpy as np
-
-import pycopancore.models.example1 as M
-from pycopancore import master_data_model as D
-from pycopancore.runners import Runner
-import pycopancore as pcc
-
-from pylab import plot, gca, show, figure, subplot, gca, semilogy, legend
-
-from numba.errors import NumbaDeprecationWarning, NumbaPendingDeprecationWarning
-import warnings
-warnings.simplefilter('ignore', category=NumbaDeprecationWarning)
-warnings.simplefilter('ignore', category=NumbaPendingDeprecationWarning)
-
-# first thing: set seed so that each execution must return same thing:
-pcc.set_seed(10)
-
-# parameters:
-
-nworlds = 1 # no. worlds
-nsocs = 5 # no. social_systems
-ncells = 100 # no. cells
-ninds = 1000 # no. individuals
-
-t_1 = 2120
-
-# choose one of two scenarios:
-with_social = 1 # 0 or 1
-
-# directory to store results:
-dir = "/tmp/";
-
-if with_social:
- filename = dir + "with_social.pickle"
- with_migration = 1
- with_awareness = 1
- with_learning = 1
- with_voting = 1
-else:
- filename = dir + "without_social.pickle"
- with_migration = 0
- with_awareness = 0
- with_learning = 0
- with_voting = 0
-with_spillovers = 1
-
-print("Using model as defined in file", M.__file__)
-model = M.Model()
-runner = Runner(model=model)
-
-# instantiate process taxa:
-environment = M.Environment()
-metabolism = M.Metabolism(
- renewable_energy_knowledge_spillover_fraction =
- .1 if with_spillovers else 0,
- basic_emigration_probability_rate =
- 16e-13 if with_migration else 0, # leads to ca. 5mio. at 5 socs, (real)
- )
-culture = M.Culture(
- awareness_lower_carbon_density=1e-4,
- awareness_upper_carbon_density=2e-4,
- awareness_update_rate = 10 if with_awareness else 0,
- environmental_friendliness_learning_rate = 1 if with_learning else 0,
- max_protected_terrestrial_carbon_share=0,
- terrestrial_carbon_averaging_time=10,
- )
-
-# generate entities and plug them together at random:
-worlds = [M.World(environment=environment,
- metabolism=metabolism,
- culture=culture,
- atmospheric_carbon = 830 * D.gigatonnes_carbon,
- upper_ocean_carbon = (5500 - 830 - 2480 - 1125) * D.GtC
- ) for w in range(nworlds)]
-social_systems = [M.SocialSystem(
- world=random.choice(worlds),
- has_renewable_subsidy = random.choice([False, True],
- p=[3/4, 1/4]),
- has_emissions_tax = random.choice([False, True],
- p=[4/5, 1/5]),
- has_fossil_ban = False,
- time_between_votes = 4 if with_voting else 1e100,
- ) for s in range(nsocs)]
-cells = [M.Cell(social_system=random.choice(social_systems))
- for c in range(ncells)]
-individuals = [M.Individual(
- cell=random.choice(cells),
- is_environmentally_friendly =
- random.choice([False, True], p=[.7, .3]),
- )
- for i in range(ninds)]
-
-# initialize block model acquaintance network:
-target_degree = 150
-target_degree_samecell = 0.5 * target_degree
-target_degree_samesoc = 0.35 * target_degree
-target_degree_other = 0.15 * target_degree
-p_samecell = target_degree_samecell / (ninds/ncells - 1)
-p_samesoc = target_degree_samesoc / (ninds/nsocs - ninds/ncells - 1)
-p_other = target_degree_other / (ninds - ninds/nsocs - 1)
-for index, i in enumerate(individuals):
- for j in individuals[:index]:
- if random.uniform() < (
- p_samecell if i.cell == j.cell
- else p_samesoc if i.social_system == j.social_system \
- else p_other):
- culture.acquaintance_network.add_edge(i, j)
-
-# set renewable sector productivities randomly:
-rel_prod = 2 * random.uniform(size=ncells)
-M.Cell.renewable_sector_productivity.set_values(cells, rel_prod * M.Cell.renewable_sector_productivity.default)
-
-# distribute area and vegetation randomly but correlatedly:
-r = random.uniform(size=ncells)
-Sigma0 = 1.5e8 * D.square_kilometers * r / sum(r)
-M.Cell.land_area.set_values(cells, Sigma0)
-
-r += random.uniform(size=ncells)
-L0 = 2480 * D.gigatonnes_carbon * r / sum(r) # 2480 is yr 2000
-M.Cell.terrestrial_carbon.set_values(cells, L0)
-M.Cell.mean_past_terrestrial_carbon.set_values(cells, L0)
-
-r = np.exp(random.normal(size=ncells))
-G0 = 1125 * D.gigatonnes_carbon * r / sum(r) # 1125 is yr 2000
-M.Cell.fossil_carbon.set_values(cells, G0)
-
-r = random.uniform(size=nsocs)
-P0 = 6e9 * D.people * r / sum(r) # 6e9 is yr 2000
-M.SocialSystem.population.set_values(social_systems, P0)
-M.SocialSystem.migrant_population.set_values(social_systems, P0 * 250e6 / 6e9)
-for s in social_systems:
- s.max_protected_terrestrial_carbon = \
- 0.90 * sum(c.terrestrial_carbon for c in s.cells)
-
-r = random.uniform(size=nsocs)
-K0 = sum(P0) * 1e4 * D.dollars/D.people * r / sum(r) # ?
-M.SocialSystem.physical_capital.set_values(social_systems, K0)
-
-# for renewables, do NOT divide by number of socs:
-r = random.uniform(size=nsocs)
-S0 = 1e12 * D.gigajoules * r / r.mean()
-M.SocialSystem.renewable_energy_knowledge.set_values(social_systems, S0)
-
-w = worlds[0]
-s = social_systems[0]
-c = cells[0]
-for v in environment.variables: print(v,v.get_value(environment))
-for v in metabolism.variables: print(v,v.get_value(metabolism))
-for v in w.variables: print(v,v.get_value(w))
-for v in s.variables: print(v,v.get_value(s))
-for v in c.variables: print(v,v.get_value(c))
-
-# do simulation:
-start = time()
-traj = runner.run(t_0=2000, t_1=t_1, dt=1,
- add_to_output=[M.Individual.represented_population,
- M.Cell.mean_past_terrestrial_carbon])
-
-for v in environment.variables: print(v,v.get_value(environment))
-for v in metabolism.variables: print(v,v.get_value(metabolism))
-for v in w.variables: print(v,v.get_value(w))
-for v in s.variables: print(v,v.get_value(s))
-for v in c.variables: print(v,v.get_value(c))
-
-
-from pickle import dump
-tosave = {
- v.owning_class.__name__ + "."
- + v.codename: {str(e): traj[v][e]
- for e in traj[v].keys()
- }
- for v in traj.keys() if v is not "t"
- }
-tosave["t"] = traj["t"]
-dump(tosave, open(filename,"wb"))
-print(time()-start, " seconds")
-
-t = np.array(traj['t'])
-print("max. time step", (t[1:]-t[:-1]).max())
-
-exit()
-
-print("\nYr 2000 values (real):")
-print("emigration (5e6):",sum(traj[M.SocialSystem.emigration][s][5]
- for s in social_systems))
-print("photo (123):",sum(traj[M.Cell.photosynthesis_carbon_flow][c][5]
- for c in cells))
-print("resp (118):",sum(traj[M.Cell.terrestrial_respiration_carbon_flow][c][5]
- for c in cells))
-print("GWP (4e13):",sum(traj[M.SocialSystem.economic_output_flow][s][5]
- for s in social_systems))
-B0 = sum(traj[M.SocialSystem.biomass_input_flow][s][5]
- for s in social_systems)
-Bglobal = B0 * D.gigatonnes_carbon / D.years
-Fglobal = sum(traj[M.SocialSystem.fossil_fuel_input_flow][s][5]
- for s in social_systems) * D.gigatonnes_carbon / D.years
-Rglobal = sum(traj[M.SocialSystem.renewable_energy_input_flow][s][5]
- for s in social_systems) * D.gigajoules / D.years
-Eglobal = sum(traj[M.SocialSystem.secondary_energy_flow][s][5]
- for s in social_systems) * D.gigajoules / D.years
-print("B (3), F (11), R(100):",
- Bglobal, Bglobal.tostr(unit=D.gigatonnes_carbon/D.years),
- Fglobal, Fglobal.tostr(unit=D.gigatonnes_carbon/D.years),
- Rglobal, Rglobal.tostr(unit=D.gigawatts),
- )
-print("life exp. at end:", 1/np.mean([traj[M.SocialSystem.mortality][s][-1]
- for s in social_systems]))
-print("cap. deprec. at begin (0.1?):",
- np.mean([traj[M.SocialSystem.physical_capital_depreciation_rate][s][5]
- for s in social_systems]))
-print("cap. deprec. at end (0.1?):",
- np.mean([traj[M.SocialSystem.physical_capital_depreciation_rate][s][-1]
- for s in social_systems]))
-print("deaths at begin (>250000?):", sum(traj[M.SocialSystem.deaths][s][5]
- for s in social_systems))
-print("deaths at end (>250000?):", sum(traj[M.SocialSystem.deaths][s][-1]
- for s in social_systems))
-print("temp. at begin:", traj[M.World.surface_air_temperature][worlds[0]][5])
-print("temp. at end:", traj[M.World.surface_air_temperature][worlds[0]][-1])
-print("prot. carbon share:",
- [traj[M.SocialSystem.protected_terrestrial_carbon][s][-1]
- / sum(traj[M.Cell.terrestrial_carbon][c][-1]
- for c in s.cells) for s in social_systems])
-print(traj[M.World.terrestrial_carbon][worlds[0]][-1],
- sum(traj[M.Cell.terrestrial_carbon][c][-1] for c in worlds[0].cells))
-
-
diff --git a/studies/run_example2.py b/studies/run_example2.py
deleted file mode 100755
index af0219cd..00000000
--- a/studies/run_example2.py
+++ /dev/null
@@ -1,211 +0,0 @@
-"""Script to run example2 model."""
-
-from time import time
-from numpy import random, array
-import numpy as np
-
-import pycopancore.models.example2 as M
-from pycopancore import master_data_model as D
-from pycopancore.runners import Runner
-
-from pylab import plot, gca, show, figure, subplot, gca, semilogy, legend
-
-# first thing: set seed so that each execution must return same thing:
-random.seed(10)
-
-# parameters:
-
-nworlds = 1 # no. worlds
-nsocs = 2 # no. social_systems
-ncells = 4 # no. cells
-ninds = 400 # no. individuals
-
-t_1 = 2100
-dir = "/tmp/"
-# choose one of two scenarios:
-filename = "with.pickle"
-#filename = "without.pickle"
-# (these files will be read by plot_example1.py)
-
-if filename == "with.pickle":
- with_awareness = 1
- with_learning = 1
- with_voting = 1
-else:
- with_awareness = 0
- with_learning = 0
- with_voting = 0
-
-model = M.Model()
-
-# instantiate process taxa:
-
-environment = M.Environment()
-
-metabolism = M.Metabolism(
- renewable_energy_knowledge_spillover_fraction = 0
- )
-
-culture = M.Culture(
- awareness_lower_carbon_density=1e-5,
- awareness_upper_carbon_density=4e-5,
- awareness_update_rate = 1 if with_awareness else 0,
- environmental_friendliness_learning_rate = 1 if with_learning else 0,
- )
-
-# generate entities and plug them together:
-
-(world, ) = worlds = [M.World(
- environment = environment,
- metabolism = metabolism,
- culture = culture,
- atmospheric_carbon = 830 * D.gigatonnes_carbon,
- upper_ocean_carbon = (5500 - 830 - 2480 - 1125) * D.GtC
- ) for w in range(nworlds)]
-
-(north, south) = social_systems = [M.SocialSystem(
- world = world,
- has_renewable_subsidy = False,
- has_emissions_tax = False,
- has_fossil_ban = False,
- emissions_tax_intro_threshold = 0.5, # disabled
- renewable_subsidy_intro_threshold = 1, # disabled
- fossil_ban_intro_threshold = 1, # disabled
- emissions_tax_level = 30 * 200e9, # see Wikipedia social cost of carbon. 100e9*3.5,
- time_between_votes = 4 if with_voting else 1e100,
- ) for s in range(nsocs)]
-
-(boreal, temperate, subtropical, tropical) = cells = [M.Cell(
- social_system = social_systems[c//2],
- renewable_sector_productivity = [.7, .9, 1.1, 1.3][c]
- * 2000 * M.Cell.renewable_sector_productivity.default,
- # represents dependency of solar energy on solar insolation angle
- fossil_sector_productivity = M.Cell.fossil_sector_productivity.default * 7,
- biomass_sector_productivity = M.Cell.biomass_sector_productivity.default * 5
- # these values result in realistic total energy production for the year 2000, see below
- ) for c in range(ncells)]
-
-individuals = [M.Individual(
- cell = cells[i%4],
- is_environmentally_friendly =
- random.choice([False, True], p=[.8, .2]), # represents the "20% suffice" assumption
- )
- for i in range(ninds)]
-
-# initialize block model acquaintance network:
-target_degree = 10 # = 2.5% of all agents. Dunbar's number would be too large
-target_degree_samecell = 0.5 * target_degree
-target_degree_samesoc = 0.35 * target_degree
-target_degree_other = 0.15 * target_degree
-p_samecell = target_degree_samecell / (ninds/ncells - 1)
-p_samesoc = target_degree_samesoc / (ninds/nsocs - ninds/ncells - 1)
-p_other = target_degree_other / (ninds - ninds/nsocs - 1)
-for index, i in enumerate(individuals):
- for j in individuals[:index]:
- if random.uniform() < (
- p_samecell if i.cell == j.cell
- else p_samesoc if i.social_system == j.social_system \
- else p_other):
- culture.acquaintance_network.add_edge(i, j)
-
-# distribute area and vegetation uniformly since it seems there are no real differences between the actual zones:
-Sigma0 = 1.5e8 * D.square_kilometers * array([0.25, 0.25, .25, .36])
-M.Cell.land_area.set_values(cells, Sigma0)
-
-L0 = 2480 * D.gigatonnes_carbon * array([0.25, 0.25, .25, .25]) # 2480 is yr 2000
-M.Cell.terrestrial_carbon.set_values(cells, L0)
-M.Cell.mean_past_terrestrial_carbon.set_values(cells, L0)
-
-# distribute fossils linearly from north to south:
-G0 = 1125 * D.gigatonnes_carbon * array([.4, .3, .2, .1]) # 1125 is yr 2000
-M.Cell.fossil_carbon.set_values(cells, G0)
-
-# distribute population 1:3 between north and south, and 2:3 within each:
-r = random.uniform(size=nsocs)
-P0 = 6e9 * D.people * array([0.1, 0.15, 0.3, 0.45]) # 6e9 is yr 2000
-M.SocialSystem.population.set_values(social_systems, P0)
-
-# distribute capital 2:1:
-K0 = sum(P0) * 1e4 * D.dollars/D.people * array([2/3, 1/3])
-M.SocialSystem.physical_capital.set_values(social_systems, K0)
-
-S0 = 1e12 * D.gigajoules * array([1, 1])
-M.SocialSystem.renewable_energy_knowledge.set_values(social_systems, S0)
-
-w = worlds[0]
-s = social_systems[0]
-c = cells[0]
-for v in environment.variables: print(v,v.get_value(environment))
-for v in metabolism.variables: print(v,v.get_value(metabolism))
-for v in w.variables: print(v,v.get_value(w))
-for v in s.variables: print(v,v.get_value(s))
-for v in c.variables: print(v,v.get_value(c))
-
-
-# do simulation:
-runner = Runner(model=model)
-start = time()
-traj = runner.run(t_0=2000, t_1=t_1, dt=1,
- add_to_output=[
- M.Individual.represented_population,
- M.Cell.mean_past_terrestrial_carbon,
- M.SocialSystem.population
- ])
-
-
-for v in environment.variables: print(v,v.get_value(environment))
-for v in metabolism.variables: print(v,v.get_value(metabolism))
-for v in w.variables: print(v,v.get_value(w))
-for v in s.variables: print(v,v.get_value(s))
-for v in c.variables: print(v,v.get_value(c))
-
-
-from pickle import dump
-tosave = {
- v.owning_class.__name__ + "."
- + v.codename: {str(e): traj[v][e]
- for e in traj[v].keys()
- }
- for v in traj.keys() if v is not "t"
- }
-tosave["t"] = traj["t"]
-dump(tosave, open(dir+filename,"wb"))
-print(time()-start, " seconds")
-
-t = np.array(traj['t'])
-print("max. time step", (t[1:]-t[:-1]).max())
-
-print("\nyr 2000 values (real):")
-print("photo (123):",sum(traj[M.Cell.photosynthesis_carbon_flow][c][5]
- for c in cells))
-print("resp (118):",sum(traj[M.Cell.terrestrial_respiration_carbon_flow][c][5]
- for c in cells))
-print("GWP (4e13):",sum(traj[M.SocialSystem.economic_output_flow][s][5]
- for s in social_systems))
-B0 = sum(traj[M.SocialSystem.biomass_input_flow][s][5]
- for s in social_systems)
-Bglobal = B0 * D.gigatonnes_carbon / D.years
-Fglobal = sum(traj[M.SocialSystem.fossil_fuel_input_flow][s][5]
- for s in social_systems) * D.gigatonnes_carbon / D.years
-Rglobal = sum(traj[M.SocialSystem.renewable_energy_input_flow][s][5]
- for s in social_systems) * D.gigajoules / D.years
-Eglobal = sum(traj[M.SocialSystem.secondary_energy_flow][s][5]
- for s in social_systems) * D.gigajoules / D.years
-print("B (3), F (11), R(100):",
- Bglobal, Bglobal.tostr(unit=D.gigatonnes_carbon/D.years),
- Fglobal, Fglobal.tostr(unit=D.gigatonnes_carbon/D.years),
- Rglobal, Rglobal.tostr(unit=D.gigawatts),
- )
-print("cap. deprec. at begin (0.1?):",
- np.mean([traj[M.SocialSystem.physical_capital_depreciation_rate][s][5]
- for s in social_systems]))
-print("cap. deprec. at end (0.1?):",
- np.mean([traj[M.SocialSystem.physical_capital_depreciation_rate][s][-1]
- for s in social_systems]))
-print("temp. at begin:", traj[M.World.surface_air_temperature][worlds[0]][5])
-print("temp. at end:", traj[M.World.surface_air_temperature][worlds[0]][-1])
-print("has emissions tax at begin", traj[M.SocialSystem.has_emissions_tax][north][5])
-print("has emissions tax at end", traj[M.SocialSystem.has_emissions_tax][north][-1])
-print("biomass prod. at begin", traj[M.Cell.biomass_relative_productivity][boreal][5] / traj[M.Cell.terrestrial_carbon][boreal][5]**2)
-print("biomass prod. at end", traj[M.Cell.biomass_relative_productivity][boreal][-1] / traj[M.Cell.terrestrial_carbon][boreal][-1]**2)
-
diff --git a/studies/run_example2_mw.py b/studies/run_example2_mw.py
deleted file mode 100755
index a5c2dd2e..00000000
--- a/studies/run_example2_mw.py
+++ /dev/null
@@ -1,229 +0,0 @@
-"""Script to run example2 model."""
-
-from time import time
-from numpy import random, array
-import numpy as np
-
-import pycopancore.models.example2 as M
-from pycopancore import master_data_model as D
-from pycopancore.runners import Runner
-
-from pylab import plot, gca, show, figure, subplot, gca, semilogy, legend
-
-# first thing: set seed so that each execution must return same thing:
-random.seed(10)
-
-# parameters:
-
-p_env_friendly = 0.9
-with_social = True
-
-nworlds = 1 # no. worlds
-nsocs = 2 # no. social_systems
-ncells = 4 # no. cells
-ninds = 400 # no. individuals
-
-t_1 = 2120
-
-# choose one of two scenarios:
-#filename = "/home/jobst/work/without.pickle"
-# (these files will be read by plot_example1.py)
-
-if with_social:
- filename = "core_with_social_p_{0}.p".format(p_env_friendly)
- with_awareness = 1
- with_learning = 1
- with_voting = 1
-else:
- filename = "core_without_social_p_{0}.p".format(p_env_friendly)
- with_awareness = 0
- with_learning = 0
- with_voting = 0
-
-model = M.Model()
-
-# instantiate process taxa:
-
-environment = M.Environment()
-
-metabolism = M.Metabolism(
- renewable_energy_knowledge_spillover_fraction = 0
- )
-
-culture = M.Culture(
- awareness_lower_carbon_density=1e-5,
- awareness_upper_carbon_density=4e-5,
- awareness_update_rate = 1 if with_awareness else 0,
- environmental_friendliness_learning_rate = 1 if with_learning else 0,
- )
-
-# generate entities and plug them together:
-
-(world, ) = worlds = [M.World(
- environment = environment,
- metabolism = metabolism,
- culture = culture,
- atmospheric_carbon = 830 * D.gigatonnes_carbon,
- upper_ocean_carbon = (5500 - 830 - 2480 - 1125) * D.GtC
- ) for w in range(nworlds)]
-
-(north, south) = social_systems = [M.SocialSystem(
- world = world,
- has_renewable_subsidy = False,
- has_emissions_tax = False,
- has_fossil_ban = False,
- emissions_tax_intro_threshold = 1, # disabled
- renewable_subsidy_intro_threshold = 0.5, # disabled
- fossil_ban_intro_threshold = 0.5, # disabled
- emissions_tax_level = 20 * 200e9, # see Wikipedia social cost of carbon. 100e9*3.5,
- time_between_votes = 4 if with_voting else 1e100,
- ) for s in range(nsocs)]
-
-(boreal, temperate, subtropical, tropical) = cells = [M.Cell(
- social_system = social_systems[c//2],
- renewable_sector_productivity = [.7, .9, 1.1, 1.3][c]
- * 100000 * M.Cell.renewable_sector_productivity.default,
- # represents dependency of solar energy on solar insolation angle
- fossil_sector_productivity = M.Cell.fossil_sector_productivity.default *280,
- #biomass_sector_productivity = M.Cell.biomass_sector_productivity.default * 5
- biomass_sector_productivity=3e5*10**(0.4)*900,
- # these values result in realistic total energy production for the year 2000, see below
- ) for c in range(ncells)]
-
-individuals = [M.Individual(
- cell = cells[i%4],
- is_environmentally_friendly =
- random.choice([False, True], p=[1-p_env_friendly,
- p_env_friendly]), # represents the "20% suffice" assumption
- )
- for i in range(ninds)]
-
-# initialize block model acquaintance network:
-target_degree = 10 # = 2.5% of all agents. Dunbar's number would be too large
-target_degree_samecell = 0.5 * target_degree
-target_degree_samesoc = 0.35 * target_degree
-target_degree_other = 0.15 * target_degree
-p_samecell = target_degree_samecell / (ninds/ncells - 1)
-p_samesoc = target_degree_samesoc / (ninds/nsocs - ninds/ncells - 1)
-p_other = target_degree_other / (ninds - ninds/nsocs - 1)
-for index, i in enumerate(individuals):
- for j in individuals[:index]:
- if random.uniform() < (
- p_samecell if i.cell == j.cell
- else p_samesoc if i.social_system == j.social_system \
- else p_other):
- culture.acquaintance_network.add_edge(i, j)
-
-# distribute area and vegetation uniformly since it seems there are no real differences between the actual zones:
-Sigma0 = 1.5e8 * D.square_kilometers * array([0.25, 0.25, .25, .36])
-M.Cell.land_area.set_values(cells, Sigma0)
-
-L0 = 2480 * D.gigatonnes_carbon * array([0.25, 0.25, .25, .25]) # 2480 is yr 2000
-M.Cell.terrestrial_carbon.set_values(cells, L0)
-
-# distribute fossils linearly from north to south:
-G0 = 1125 * D.gigatonnes_carbon * array([.4, .3, .2, .1]) # 1125 is yr 2000
-M.Cell.fossil_carbon.set_values(cells, G0)
-
-# distribute population 1:3 between north and south, and 2:3 within each:
-r = random.uniform(size=nsocs)
-P0 = 6e9 * D.people * array([0.1, 0.15, 0.3, 0.45]) # 6e9 is yr 2000
-M.SocialSystem.population.set_values(social_systems, P0)
-
-# distribute capital 2:1:
-K0 = sum(P0) * 1e4 * D.dollars/D.people * array([2/3, 1/3])
-M.SocialSystem.physical_capital.set_values(social_systems, K0)
-
-S0 = 1e12 * D.gigajoules * array([1, 1])
-M.SocialSystem.renewable_energy_knowledge.set_values(social_systems, S0)
-
-w = worlds[0]
-s = social_systems[0]
-c = cells[0]
-for v in environment.variables: print(v,v.get_value(environment))
-for v in metabolism.variables: print(v,v.get_value(metabolism))
-for v in w.variables: print(v,v.get_value(w))
-for v in s.variables: print(v,v.get_value(s))
-for v in c.variables: print(v,v.get_value(c))
-
-
-# do simulation:
-runner = Runner(model=model)
-start = time()
-traj = runner.run(t_0=2000, t_1=t_1, dt=1,
- add_to_output=[M.Individual.represented_population])
-
-
-for v in environment.variables: print(v,v.get_value(environment))
-for v in metabolism.variables: print(v,v.get_value(metabolism))
-for v in w.variables: print(v,v.get_value(w))
-for v in s.variables: print(v,v.get_value(s))
-for v in c.variables: print(v,v.get_value(c))
-
-
-from pickle import dump
-tosave = {
- v.owning_class.__name__ + "."
- + v.codename: {str(e): traj[v][e]
- for e in traj[v].keys()
- }
- for v in traj.keys() if v is not "t"
- }
-tosave["t"] = traj["t"]
-dump(tosave, open(filename,"wb"))
-print(time()-start, " seconds")
-
-t = np.array(traj['t'])
-print("max. time step", (t[1:]-t[:-1]).max())
-
-print("\nyr 2000 values (real):")
-print("photo (123):",sum(traj[M.Cell.photosynthesis_carbon_flow][c][5]
- for c in cells))
-print("resp (118):",sum(traj[M.Cell.terrestrial_respiration_carbon_flow][c][5]
- for c in cells))
-print("GWP (4e13):",sum(traj[M.SocialSystem.economic_output_flow][s][5]
- for s in social_systems))
-B0 = sum(traj[M.SocialSystem.biomass_input_flow][s][5]
- for s in social_systems)
-Bglobal = B0 * D.gigatonnes_carbon / D.years
-Fglobal = sum(traj[M.SocialSystem.fossil_fuel_input_flow][s][5]
- for s in social_systems) * D.gigatonnes_carbon / D.years
-Rglobal = sum(traj[M.SocialSystem.renewable_energy_input_flow][s][5]
- for s in social_systems) * D.gigajoules / D.years
-Eglobal = sum(traj[M.SocialSystem.secondary_energy_flow][s][5]
- for s in social_systems) * D.gigajoules / D.years
-print("B (3), F (11), R(100):",
- Bglobal, Bglobal.tostr(unit=D.gigatonnes_carbon/D.years),
- Fglobal, Fglobal.tostr(unit=D.gigatonnes_carbon/D.years),
- Rglobal, Rglobal.tostr(unit=D.gigawatts),
- )
-
-B0 = sum(traj[M.SocialSystem.biomass_input_flow][s][-1]
- for s in social_systems)
-Bglobal = B0 * D.gigatonnes_carbon / D.years
-Fglobal = sum(traj[M.SocialSystem.fossil_fuel_input_flow][s][-1]
- for s in social_systems) * D.gigatonnes_carbon / D.years
-Rglobal = sum(traj[M.SocialSystem.renewable_energy_input_flow][s][-1]
- for s in social_systems) * D.gigajoules / D.years
-Eglobal = sum(traj[M.SocialSystem.secondary_energy_flow][s][-1]
- for s in social_systems) * D.gigajoules / D.years
-print("B (3), F (11), R(100):",
- Bglobal, Bglobal.tostr(unit=D.gigatonnes_carbon/D.years),
- Fglobal, Fglobal.tostr(unit=D.gigatonnes_carbon/D.years),
- Rglobal, Rglobal.tostr(unit=D.gigawatts),
- )
-
-
-print("cap. deprec. at begin (0.1?):",
- np.mean([traj[M.SocialSystem.physical_capital_depreciation_rate][s][5]
- for s in social_systems]))
-print("cap. deprec. at end (0.1?):",
- np.mean([traj[M.SocialSystem.physical_capital_depreciation_rate][s][-1]
- for s in social_systems]))
-print("temp. at begin:", traj[M.World.surface_air_temperature][worlds[0]][5])
-print("temp. at end:", traj[M.World.surface_air_temperature][worlds[0]][-1])
-print("has emissions tax at begin", traj[M.SocialSystem.has_emissions_tax][north][5])
-print("has emissions tax at end", traj[M.SocialSystem.has_emissions_tax][north][-1])
-print("biomass prod. at begin", traj[M.Cell.biomass_relative_productivity][boreal][5] / traj[M.Cell.terrestrial_carbon][boreal][5]**2)
-print("biomass prod. at end", traj[M.Cell.biomass_relative_productivity][boreal][-1] / traj[M.Cell.terrestrial_carbon][boreal][-1]**2)
-
diff --git a/studies/run_example2_varying_learning_rate.py b/studies/run_example2_varying_learning_rate.py
deleted file mode 100644
index 98425186..00000000
--- a/studies/run_example2_varying_learning_rate.py
+++ /dev/null
@@ -1,258 +0,0 @@
-"""Script to run example2 model."""
-
-from time import time
-from numpy import random, array
-import numpy as np
-
-import pycopancore.models.example2 as M
-from pycopancore import master_data_model as D
-from pycopancore.runners import Runner
-
-from pylab import plot, gca, show, figure, subplot, gca, semilogy, legend
-import argparse
-import os
-
-parser = argparse.ArgumentParser()
-parser.add_argument('-i','--task-id', required=True, type=int)
-parser.add_argument('-s','--seed', required=True, type=int)
-args = vars(parser.parse_args())
-
-seed = args["seed"]
-task = args["task_id"]
-
-random.seed(seed)
-
-p_env_friendly = 0.40 #0.25
-updates = np.logspace(np.log10(1/50), np.log10(12), 50)[task]
-with_social = True
-t_1 = 2120
-
-# parameters:
-
-#This is going in the right direction
-#S0 = 2e11 * D.gigajoules * array([1, 1])
-#renewable_scaling = 2500000
-
-#1e12 collapse
-#5e11 collapse
-#2.5e11 almost collapse
-#4e11 scaling 600000, 98 W collapse
-#3e11 scaling 1100000 101.91 GW almost collapse
-S0 = 2e11 * D.gigajoules * array([1, 1])
-renewable_scaling = 2500000
-
-
-nworlds = 1 # no. worlds
-nsocs = 2 # no. social_systems
-ncells = 4 # no. cells
-ninds = 400 # no. individuals
-
-
-# choose one of two scenarios:
-#filename = "/home/jobst/work/without.pickle"
-# (these files will be read by plot_example1.py)
-
-if with_social:
- filename = "core_with_social_u_{0}_loweredS0_{1}.p".format(updates,seed)
- with_awareness = 1
- with_learning = 1
- with_voting = 1
-else:
- filename = "core_without_social_u_{0}_loweredS0_{1}.p".format(updates, seed)
- with_awareness = 0
- with_learning = 0
- with_voting = 0
-
-model = M.Model()
-
-# instantiate process taxa:
-
-environment = M.Environment()
-
-metabolism = M.Metabolism(
- renewable_energy_knowledge_spillover_fraction = 0
- )
-
-culture = M.Culture(
- awareness_lower_carbon_density=1e-5,
- awareness_upper_carbon_density=4e-5,
- awareness_update_rate = updates if with_awareness else 0,
- environmental_friendliness_learning_rate = updates if with_learning else 0,
- )
-
-# generate entities and plug them together:
-
-(world, ) = worlds = [M.World(
- environment = environment,
- metabolism = metabolism,
- culture = culture,
- atmospheric_carbon = 830 * D.gigatonnes_carbon,
- upper_ocean_carbon = (5500 - 830 - 2480 - 1125) * D.GtC
- ) for w in range(nworlds)]
-
-(north, south) = social_systems = [M.SocialSystem(
- world = world,
- has_renewable_subsidy = False,
- has_emissions_tax = False,
- has_fossil_ban = False,
- emissions_tax_intro_threshold = 1, # disabled
- renewable_subsidy_intro_threshold = 0.5, # disabled
- fossil_ban_intro_threshold = 0.5, # disabled
- renewable_subsidy_keeping_threshold = 0.5,
- fossil_ban_keeping_threshold = 0.5,
- emissions_tax_level = 20 * 200e9, # see Wikipedia social cost of carbon. 100e9*3.5,
- time_between_votes = 4 if with_voting else 1e100,
- ) for s in range(nsocs)]
-
-# renewable_scaling = 100000
-(boreal, temperate, subtropical, tropical) = cells = [M.Cell(
- social_system = social_systems[c//2],
- renewable_sector_productivity = [.7, .9, 1.1, 1.3][c]
- * renewable_scaling * M.Cell.renewable_sector_productivity.default,
- # represents dependency of solar energy on solar insolation angle
- fossil_sector_productivity = M.Cell.fossil_sector_productivity.default *280,
- #biomass_sector_productivity = M.Cell.biomass_sector_productivity.default * 5
- biomass_sector_productivity=3e5*10**(0.4)*900,
- # these values result in realistic total energy production for the year 2000, see below
- ) for c in range(ncells)]
-
-individuals = [M.Individual(
- cell = cells[i%4],
- is_environmentally_friendly =
- random.choice([False, True], p=[1-p_env_friendly,
- p_env_friendly]), # represents the "20% suffice" assumption
- )
- for i in range(ninds)]
-
-# initialize block model acquaintance network:
-target_degree = 10 # = 2.5% of all agents. Dunbar's number would be too large
-target_degree_samecell = 0.5 * target_degree
-target_degree_samesoc = 0.35 * target_degree
-target_degree_other = 0.15 * target_degree
-p_samecell = target_degree_samecell / (ninds/ncells - 1)
-p_samesoc = target_degree_samesoc / (ninds/nsocs - ninds/ncells - 1)
-p_other = target_degree_other / (ninds - ninds/nsocs - 1)
-for index, i in enumerate(individuals):
- for j in individuals[:index]:
- if random.uniform() < (
- p_samecell if i.cell == j.cell
- else p_samesoc if i.social_system == j.social_system \
- else p_other):
- culture.acquaintance_network.add_edge(i, j)
-
-# distribute area and vegetation uniformly since it seems there are no real differences between the actual zones:
-Sigma0 = 1.5e8 * D.square_kilometers * array([0.25, 0.25, .25, .25])
-M.Cell.land_area.set_values(cells, Sigma0)
-
-L0 = 2480 * D.gigatonnes_carbon * array([0.25, 0.25, .25, .25]) # 2480 is yr 2000
-M.Cell.terrestrial_carbon.set_values(cells, L0)
-
-# distribute fossils linearly from north to south:
-G0 = 1125 * D.gigatonnes_carbon * array([.4, .3, .2, .1]) # 1125 is yr 2000
-M.Cell.fossil_carbon.set_values(cells, G0)
-
-# distribute population 1:3 between north and south, and 2:3 within each:
-r = random.uniform(size=nsocs)
-#P0 = 6e9 * D.people * array([0.1, 0.15, 0.3, 0.45]) # 6e9 is yr 2000
-P0 = 6e9 * D.people * array([0.25, 0.75]) # 6e9 is yr 2000
-
-M.SocialSystem.population.set_values(social_systems, P0)
-
-# distribute capital 2:1:
-K0 = sum(P0) * 1e4 * D.dollars/D.people * array([2/3, 1/3])
-M.SocialSystem.physical_capital.set_values(social_systems, K0)
-
-#S0 = 1e12 * D.gigajoules * array([1, 1])
-#S0 = 1e12 * D.gigajoules * array([1, 1])
-M.SocialSystem.renewable_energy_knowledge.set_values(social_systems, S0)
-
-w = worlds[0]
-s = social_systems[0]
-c = cells[0]
-for v in environment.variables: print(v,v.get_value(environment))
-for v in metabolism.variables: print(v,v.get_value(metabolism))
-for v in w.variables: print(v,v.get_value(w))
-for v in s.variables: print(v,v.get_value(s))
-for v in c.variables: print(v,v.get_value(c))
-
-
-# do simulation:
-runner = Runner(model=model)
-start = time()
-traj = runner.run(t_0=2000, t_1=t_1, dt=1,
- add_to_output=[M.Individual.represented_population])
-
-
-for v in environment.variables: print(v,v.get_value(environment))
-for v in metabolism.variables: print(v,v.get_value(metabolism))
-for v in w.variables: print(v,v.get_value(w))
-for v in s.variables: print(v,v.get_value(s))
-for v in c.variables: print(v,v.get_value(c))
-
-
-from pickle import dump
-tosave = {
- v.owning_class.__name__ + "."
- + v.codename: {str(e): traj[v][e]
- for e in traj[v].keys()
- }
- for v in traj.keys() if v is not "t"
- }
-tosave["t"] = traj["t"]
-dump(tosave, open(filename,"wb"))
-print(time()-start, " seconds")
-
-t = np.array(traj['t'])
-print("max. time step", (t[1:]-t[:-1]).max())
-
-print("\nyr 2000 values (real):")
-print("photo (123):",sum(traj[M.Cell.photosynthesis_carbon_flow][c][5]
- for c in cells))
-print("resp (118):",sum(traj[M.Cell.terrestrial_respiration_carbon_flow][c][5]
- for c in cells))
-print("GWP (4e13):",sum(traj[M.SocialSystem.economic_output_flow][s][5]
- for s in social_systems))
-B0 = sum(traj[M.SocialSystem.biomass_input_flow][s][5]
- for s in social_systems)
-Bglobal = B0 * D.gigatonnes_carbon / D.years
-Fglobal = sum(traj[M.SocialSystem.fossil_fuel_input_flow][s][5]
- for s in social_systems) * D.gigatonnes_carbon / D.years
-Rglobal = sum(traj[M.SocialSystem.renewable_energy_input_flow][s][5]
- for s in social_systems) * D.gigajoules / D.years
-Eglobal = sum(traj[M.SocialSystem.secondary_energy_flow][s][5]
- for s in social_systems) * D.gigajoules / D.years
-print("B (3), F (11), R(100):",
- Bglobal, Bglobal.tostr(unit=D.gigatonnes_carbon/D.years),
- Fglobal, Fglobal.tostr(unit=D.gigatonnes_carbon/D.years),
- Rglobal, Rglobal.tostr(unit=D.gigawatts),
- )
-
-B0 = sum(traj[M.SocialSystem.biomass_input_flow][s][-1]
- for s in social_systems)
-Bglobal = B0 * D.gigatonnes_carbon / D.years
-Fglobal = sum(traj[M.SocialSystem.fossil_fuel_input_flow][s][-1]
- for s in social_systems) * D.gigatonnes_carbon / D.years
-Rglobal = sum(traj[M.SocialSystem.renewable_energy_input_flow][s][-1]
- for s in social_systems) * D.gigajoules / D.years
-Eglobal = sum(traj[M.SocialSystem.secondary_energy_flow][s][-1]
- for s in social_systems) * D.gigajoules / D.years
-print("B (3), F (11), R(100):",
- Bglobal, Bglobal.tostr(unit=D.gigatonnes_carbon/D.years),
- Fglobal, Fglobal.tostr(unit=D.gigatonnes_carbon/D.years),
- Rglobal, Rglobal.tostr(unit=D.gigawatts),
- )
-
-
-print("cap. deprec. at begin (0.1?):",
- np.mean([traj[M.SocialSystem.physical_capital_depreciation_rate][s][5]
- for s in social_systems]))
-print("cap. deprec. at end (0.1?):",
- np.mean([traj[M.SocialSystem.physical_capital_depreciation_rate][s][-1]
- for s in social_systems]))
-print("temp. at begin:", traj[M.World.surface_air_temperature][worlds[0]][5])
-print("temp. at end:", traj[M.World.surface_air_temperature][worlds[0]][-1])
-print("has emissions tax at begin", traj[M.SocialSystem.has_emissions_tax][north][5])
-print("has emissions tax at end", traj[M.SocialSystem.has_emissions_tax][north][-1])
-print("biomass prod. at begin", traj[M.Cell.biomass_relative_productivity][boreal][5] / traj[M.Cell.terrestrial_carbon][boreal][5]**2)
-print("biomass prod. at end", traj[M.Cell.biomass_relative_productivity][boreal][-1] / traj[M.Cell.terrestrial_carbon][boreal][-1]**2)
-
diff --git a/studies/run_exodus.py b/studies/run_exodus.py
deleted file mode 100755
index 387a39cf..00000000
--- a/studies/run_exodus.py
+++ /dev/null
@@ -1,199 +0,0 @@
-"""This is the test exodus model.
-
-In this version only the Step-process 'aging' of entitytype 'Individual' is
-implemented, such that the only relevant attributes of 'Individual' are 'age'
-and 'cell'.
-"""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-import random
-from scipy import stats
-from time import time
-import datetime as dt
-import numpy as np
-import networkx as nx
-import pickle, json
-
-#import plotly.offline as py
-#import plotly.graph_objs as go
-from matplotlib.pyplot import plot, gca, show, savefig
-
-import pycopancore.models.exodus as M
-from pycopancore.runners.runner import Runner
-
-
-# setting timeinterval for run method 'Runner.run()'
-timeinterval = 200
-# setting time step to hand to 'Runner.run()'
-timestep = .1
-
-nm = 1 # number of municipalities, also cities
-nc = 1 # number of counties, also farmland_cells
-na = 200 # number of agents
-pf = .5 # percentage of farmers
-nf = int(na * pf) # number of farmers
-nt = int(na - nf) # number of townsmen
-
-
-model = M.Model()
-
-# instantiate process taxa culture:
-# In this certain case we need 'M.Culture()' for the acquaintance network.
-culture = M.Culture(fully_connected_network=True) # fully connected -> static network
-metabolism = M.Metabolism(market_frequency=1)
-
-# instantiate world:
-world = M.World(culture=culture, metabolism=metabolism,
- water_price=.1)
-# Instantiate SocialSystems:
-municipalities = [M.SocialSystem(world=world,
- municipality_like=True,
- base_mean_income=6130,
- scaling_parameter=1.12,
- migration_cost=0,
- last_one_standing=False,
- continuous_exploration=False)
- for m in range(nm)
- ]
-
-counties = [M.SocialSystem(world=world,
- municipality_like=False,
- migration_cost=0,
- last_one_standing=False,
- continuous_exploration=False)
- for c in range(nc)
- ]
-# Instantiate farmland cells:
-farmland_cells = []
-county_allocation = list(counties)
-for fc in range(nc):
- # chose county:
- county = random.choice(county_allocation)
- county_allocation.remove(county)
- farmland_cells.append(M.Cell(world=world,
- social_system=county,
- characteristic='farmland',
- land_area=0.0025 * (nf + nt) / nc, # in square kilometers
- average_precipitation=0.75))
-# Instantiate city cells:
-city_cells = []
-municipality_allocation = list(municipalities)
-
-for cc in range(nm):
- # chose county:
- municipality = random.choice(municipality_allocation)
- municipality_allocation.remove(municipality)
- city_cells.append(M.Cell(world=world,
- social_system=municipality,
- characteristic='city',
- average_precipitation=0))
-
-# Instantiate farmers:
-farmers = []
-for f in range(nf):
- # Chose cell
- farmland = random.choice(farmland_cells)
- # determine liquidity before first market:
- liq = stats.lognorm.rvs(scale=300, s=0.34, loc=0)
- farmers.append(M.Individual(cell=farmland,
- profession='farmer',
- outspokenness=3,
- liquidity=liq,
- nutrition=1000))
-# Instantiate townsmen:
-townsmen = []
-for t in range(nt):
- # Chose cell
- city = random.choice(city_cells)
- # determine liquidity before first market:
- liq = stats.lognorm.rvs(scale=700, s=0.34, loc=0)
- townsmen.append(M.Individual(cell=city,
- profession='townsman',
- outspokenness=3,
- liquidity=liq,
- nutrition=100))
-
-start = time()
-# Calculate social_systems variables before run:
-print('calculating social_system attributes before run:')
-for soc in M.SocialSystem.instances:
- soc.calc_population(0)
- soc.calculate_mean_income_or_farmsize(0)
- soc.calculate_average_liquidity(0)
-# Calculate other stuff:
-for ind in M.Individual.instances:
- ind.calc_farm_size()
- ind.calc_gross_income()
- ind.calculate_harvest(0)
- ind.calculate_utility(0)
-for soc in M.SocialSystem.instances:
- soc.calculate_average_utility(0)
- soc.calculate_gini(0)
- soc.calculate_migration_rate(0)
-
-world.calc_total_gross_income(0)
-world.calc_total_harvest(0)
-world.calc_total_nutrition(0)
-world.calc_total_liquidity(0)
-
-# Run market clearing once:
-metabolism.do_market_clearing(0)
-
-print("done ({})".format(dt.timedelta(seconds=(time() - start))))
-
-termination_conditions = [[M.Metabolism.check_for_market_equilibrium, metabolism],
- [M.World.check_for_exceptions, world]]
-
-print('\n runner starting')
-# Runner is instantiated
-r = Runner(model=model, termination_calls=termination_conditions
- )
-
-start = time()
-# run the Runner and saving the return dict in traj
-traj = r.run(t_1=timeinterval,
- dt=timestep,
- max_resolution=True
- )
-runtime = dt.timedelta(seconds=(time() - start))
-print('runtime: {runtime}'.format(**locals()))
-
-
-# Saving:
-print('saving:')
-#traj.save(filename='data')
-print('...is done')
-
-# Plotting:
-t = np.array(traj['t'])
-# for key, val in traj.items():
-# print('key', key,)
-plot(t, traj[M.World.water_price][world], "b", lw=3)
-#plot(t, traj[M.World.total_gross_income][world], "m:", lw=3)
-#plot(t, traj[M.World.total_harvest][world], "m--", lw=3)
-# plot(t, traj[M.Culture.network_clustering][culture], "r--", lw=3)
-# plot(t, traj[M.Culture.modularity][culture], "r:", lw=3)
-
-for soc in municipalities:
- plot(t, traj[M.SocialSystem.population][soc], "r", lw=3)
- #plot(t, traj[M.SocialSystem.average_utility][soc], "r:", lw=3)
- #plot(t, traj[M.SocialSystem.gini_coefficient][soc], "r--", lw=3)
-for soc in counties:
- plot(t, traj[M.SocialSystem.population][soc], "k", lw=3)
- #plot(t, traj[M.SocialSystem.average_utility][soc], "k:", lw=3)
- #plot(t, traj[M.SocialSystem.gini_coefficient][soc], "k--", lw=3)
-
-# for ind in M.Individual.instances:
-# plot(t, traj[M.Individual.utility][ind], "y", lw=0.5)
-gca().set_yscale('symlog')
-
-# savefig('20_ag_4_soc.png', dpi=150)
-show()
diff --git a/studies/run_exodus_oscillations.py b/studies/run_exodus_oscillations.py
deleted file mode 100755
index b5defcb1..00000000
--- a/studies/run_exodus_oscillations.py
+++ /dev/null
@@ -1,218 +0,0 @@
-"""This is the test script for the seven dwarfs step by step tutorial.
-
-In this version only the Step-process 'aging' of entitytype 'Individual' is
-implemented, such that the only relevant attributes of 'Individual' are 'age'
-and 'cell'.
-"""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-import random
-from scipy import stats
-from time import time
-import datetime as dt
-import numpy as np
-import networkx as nx
-import pickle, json
-
-import plotly.offline as py
-import plotly.graph_objs as go
-from matplotlib.pyplot import plot, gca, show, savefig
-
-import pycopancore.models.exodus as M
-from pycopancore.runners.runner import Runner
-
-
-# setting timeinterval for run method 'Runner.run()'
-timeinterval = 10
-# setting time step to hand to 'Runner.run()'
-timestep = .1
-
-# Since this is a special model, only 2 of each type of cells are allowed.
-nm = 2 # number of municipalities, also cities
-nc = 2 # number of counties, also farmland_cells
-na = 100 # number of agents
-pf = .5 # percentage of farmers
-nf = int(na * pf) # number of farmers
-nt = int(na - nf) # number of townsmen
-
-
-model = M.Model()
-
-# instantiate process taxa culture:
-# In this certain case we need 'M.Culture()' for the acquaintance network.
-culture = M.Culture(fully_connected_network=True)
-metabolism = M.Metabolism(market_frequency=1)
-
-# instantiate world:
-world = M.World(culture=culture, metabolism=metabolism,
- water_price=.1)
-# Instantiate Social Systems:
-municipalities = [M.SocialSystem(world=world,
- municipality_like=True,
- base_mean_income=1000,
- scaling_parameter=1.12,
- migration_cost=0)
- for m in range(nm)
- ]
-
-counties = [M.SocialSystem(world=world,
- municipality_like=False,
- migration_cost=0)
- for c in range(nc)
- ]
-# Instantiate farmland cells:
-farmland_cells = []
-farmland_cells.append(M.Cell(world=world,
- social_system=counties[0],
- characteristic='farmland',
- land_area=0.01 * (nf + nt) / nc,
- average_precipitation=0.75,
- location=(0, 0)))
-farmland_cells.append(M.Cell(world=world,
- social_system=counties[1],
- characteristic='farmland',
- land_area=0.01 * (nf + nt) / nc,
- average_precipitation=0.75,
- location=(0, 1)))
-# Instantiate city cells:
-city_cells = []
-city_cells.append(M.Cell(world=world,
- social_system=municipalities[0],
- characteristic='city',
- average_precipitation=0,
- location=(1, 1)))
-city_cells.append(M.Cell(world=world,
- social_system=municipalities[1],
- characteristic='city',
- average_precipitation=0,
- location=(1, 0)))
-
-# Instantiate farmers:
-farmers = []
-for f in range(nf):
- # Chose cell
- farmland = random.choice(farmland_cells)
- # determine liquidity before first market:
- liq = stats.lognorm.rvs(scale=300, s=0.34, loc=0)
- farmers.append(M.Individual(cell=farmland,
- profession='farmer',
- outspokenness=.1,
- liquidity=liq,
- nutrition=1000,
- preferential_migration=True))
-# Instantiate townsmen:
-townsmen = []
-for t in range(nt):
- # Chose cell
- city = random.choice(city_cells)
- # determine liquidity before first market:
- liq = stats.lognorm.rvs(scale=700, s=0.34, loc=0)
- townsmen.append(M.Individual(cell=city,
- profession='townsman',
- outspokenness=.1,
- liquidity=liq,
- nutrition=100,
- preferential_migration=True))
-
-start = time()
-# Calculate social_systems variables before run:
-print('calculating social_system attributes before run:')
-for soc in M.SocialSystem.instances:
- soc.calc_population(0)
- soc.calculate_mean_income_or_farmsize(0)
- soc.calculate_average_liquidity(0)
-# Calculate other stuff:
-for ind in M.Individual.instances:
- ind.calc_farm_size()
- ind.calc_gross_income()
- ind.calculate_harvest(0)
- ind.calculate_utility(0)
-for soc in M.SocialSystem.instances:
- soc.calculate_average_utility(0)
- soc.calculate_gini(0)
-
-world.calc_total_gross_income(0)
-world.calc_total_harvest(0)
-world.calc_total_nutrition(0)
-world.calc_total_liquidity(0)
-
-# Run market clearing once:
-metabolism.do_market_clearing(0)
-# In case of a erdos renyi network:
-# culture.calculate_modularity(0)
-# culture.calculate_transitivity(0)
-print("done ({})".format(dt.timedelta(seconds=(time() - start))))
-
-termination_conditions = [[M.Metabolism.check_for_market_equilibrium, metabolism],
- [M.World.check_for_exceptions, world]]
-
-print('\n runner starting')
-# Runner is instantiated
-r = Runner(model=model, termination_calls=termination_conditions
- )
-
-start = time()
-# run the Runner and saving the return dict in traj
-traj = r.run(t_1=timeinterval, dt=timestep, max_resolution=True)
-runtime = dt.timedelta(seconds=(time() - start))
-print('runtime: {runtime}'.format(**locals()))
-
-
-# Saving:
-print('saving:')
-traj.save(filename='data')
-print('...is done')
-
-# Plotting:
-t = np.array(traj['t'])
-# for key, val in traj.items():
-# print('key', key,)
-plot(t, traj[M.World.water_price][world], "b", lw=3)
-plot(t, traj[M.World.total_gross_income][world], "m:", lw=3)
-plot(t, traj[M.World.total_harvest][world], "m--", lw=3)
-# plot(t, traj[M.Culture.network_clustering][culture], "r--", lw=3)
-# plot(t, traj[M.Culture.modularity][culture], "r:", lw=3)
-
-for soc in municipalities:
- plot(t, traj[M.SocialSystem.population][soc], "r", lw=3)
- #plot(t, traj[M.SocialSystem.average_utility][soc], "r:", lw=3)
- #plot(t, traj[M.SocialSystem.gini_coefficient][soc], "r--", lw=3)
-for soc in counties:
- plot(t, traj[M.SocialSystem.population][soc], "k", lw=3)
- #plot(t, traj[M.SocialSystem.average_utility][soc], "k:", lw=3)
- #plot(t, traj[M.SocialSystem.gini_coefficient][soc], "k--", lw=3)
-
-# for ind in M.Individual.instances:
-# plot(t, traj[M.Individual.utility][ind], "y", lw=0.5)
-gca().set_yscale('symlog')
-
-# savefig('20_ag_4_soc.png', dpi=150)
-show()
-
-# network_data = traj[M.Culture.acquaintance_network][culture]
-# G = network_data[-1]
-
-# Make list to have colors according to profession:
-# professions = {}
-# for ind in M.Individual.instances:
-# if ind.profession == 'farmer':
-# professions[ind] = 'yellow'
-# else:
-# professions[ind] = 'red'
-# colors = [professions.get(node) for node in list(G.nodes())]
-# # Make second list to have labels according to social_system:
-# social_systems = {}
-# for ind in M.Individual.instances:
-# social_systems[ind] = str(ind.social_system._uid)
-# nx.draw(G, node_color=colors,
-# labels=social_systems,
-# pos=nx.spring_layout(G))
-# show()
diff --git a/studies/run_exploit.py b/studies/run_exploit.py
deleted file mode 100755
index 23ab8837..00000000
--- a/studies/run_exploit.py
+++ /dev/null
@@ -1,137 +0,0 @@
-"""Test Study for the exploit model.
-
-A study to test the runner with the exploit model.
-It includes the module components exploit_social_learning,
-most_simple_vegetation and simple_extraction.
-"""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-import numpy as np
-from time import time
-import datetime as dt
-from numpy import random
-import argparse
-
-import plotly.offline as py
-import plotly.graph_objs as go
-
-import pycopancore.models.exploit as M
-from pycopancore.runners.runner import Runner
-
-#parameters:
-timeinterval = 100
-timestep = 0.1
-ni_sust = 50 # number of agents with sustainable strategy 1
-ni_nonsust = 50 # number of agents with unsustainable strategy 0
-nindividuals = ni_sust + ni_nonsust
-nc = nindividuals # number of cells
-p = 0.4 # link density
-
-# New Order of instantiating things !!!!!
-# instantiate model
-model = M.Model()
-
-# instantiate process taxa culture:
-culture = M.Culture()
-
-# generate entitites:
-world = M.World(culture=culture)
-social_system = M.SocialSystem(world=world)
-cells = [M.Cell(stock=1, capacity=1, growth_rate=1, social_system=social_system)
- for c in range(nc)]
-individuals = [M.Individual(strategy=0, imitation_tendency=0,
- rewiring_prob=0.5,
- cell=cells[i]) for i in range(ni_nonsust)]\
- + [M.Individual(strategy=1, imitation_tendency=0,
- rewiring_prob=0.5,
- cell=cells[i+ni_nonsust])
- for i in range(ni_sust)]
-
-for (i, c) in enumerate(cells):
- c.individual = individuals[i]
-
-
-def erdosrenyify(graph, p=0.5):
- """Create a ErdosRenzi graph from networkx graph.
-
- Take a a networkx.Graph with nodes and distribute the edges following the
- erdos-renyi graph procedure.
- """
- assert not graph.edges(), "your graph has already edges"
- nodes = list(graph.nodes())
- for i, n1 in enumerate(nodes[:-1]):
- for n2 in nodes[i+1:]:
- if random.random() < p:
- graph.add_edge(n1, n2)
-
-# set the initial graph structure to be an erdos-renyi graph
-print("erdosrenyifying the graph ... ", end="", flush=True)
-start = time()
-erdosrenyify(culture.acquaintance_network, p=p)
-print("done ({})".format(dt.timedelta(seconds=(time() - start))))
-
-print('\n runner starting')
-
-# Define termination signals as list [ signal_method, object_method_works_on ]
-signal_consensus = [M.Culture.check_for_consensus,
- culture]
-# Define termination_callables as list of all signals
-termination_callables = [signal_consensus]
-print('termination_callables: ', termination_callables)
-
-r = Runner(model=model, termination_calls=termination_callables)
-start = time()
-traj = r.run(t_1=timeinterval, dt=timestep)
-runtime = dt.timedelta(seconds=(time() - start))
-print('runtime: {runtime}'.format(**locals()))
-
-t = np.array(traj['t'])
-print("max. time step", (t[1:]-t[:-1]).max())
-# print('keys:', np.array(traj.keys()))
-# print('completeDict: ', traj)
-
-individuals_strategies = np.array([traj[M.Individual.strategy][ind]
- for ind in individuals])
-
-nopinion1_list = np.sum(individuals_strategies, axis=0) / nindividuals
-nopinion0_list = 1 - nopinion1_list
-
-# everything below is just plotting commands for plotly
-
-data_opinion0 = go.Scatter(
- x=t,
- y=nopinion0_list,
- mode="lines",
- name="relative amount strategy 0",
- line=dict(
- color="lightblue",
- width=2
- )
-)
-data_opinion1 = go.Scatter(
- x=t,
- y=nopinion1_list,
- mode="lines",
- name="relative amount strategy 1",
- line=dict(
- color="orange",
- width=2
- )
-)
-
-layout = dict(title='Exploit Model',
- xaxis=dict(title='time'),
- yaxis=dict(title='relative strategy amounts'),
- )
-
-fig = dict(data=[data_opinion0, data_opinion1], layout=layout)
-py.plot(fig, filename="exlpoit_model.html")
-
diff --git a/studies/run_groups_illustration.py b/studies/run_groups_illustration.py
deleted file mode 100644
index c17fb1d6..00000000
--- a/studies/run_groups_illustration.py
+++ /dev/null
@@ -1,173 +0,0 @@
-"""This is an illustration script for some of the features that come with the group entity based on the seven dwarfs model.
-"""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-import numpy as np
-from numpy.random import uniform
-from time import time
-import datetime as dt
-
-import networkx as nx
-from networkx.algorithms import bipartite
-import matplotlib.pyplot as plt
-
-import plotly.offline as py
-import plotly.graph_objs as go
-
-import pycopancore.models.groups_seven_dwarfs as M
-from pycopancore.runners.runner import Runner
-
-# from studies import plot_multilayer as pm
-# from mpl_toolkits.mplot3d import Axes3D
-# from mpl_toolkits.mplot3d.art3d import Line3DCollection
-
-
-# setting timeinterval for run method 'Runner.run()'
-timeinterval = 10
-# setting time step to hand to 'Runner.run()'
-timestep = .1
-nc = 1 # number of caves
-dwarfs = 10 # number of dwarfs
-
-# instantiate model M (needs to be done in the beginning of each script).
-# This configures the model M through 'ModelLogics' in module
-# 'base.model_logics' such that initialisation of attributes and entities gets
-# possible
-model = M.Model()
-
-# instantiate process taxa culture:
-# In this certain case we need 'M.Culture()' for the acquaintance network.
-culture = M.Culture()
-
-# instantiate world:
-world = M.World(culture=culture)
-
-# instantiate one social system:
-social_system = M.SocialSystem(world=world)
-
-# instantiate cells (the caves):
-cells = [M.Cell(social_system=social_system,
- eating_stock=100
- )
- for c in range(nc)
- ]
-
-# instantiate dwarfs and assigning initial conditions
-individuals = [M.Individual(cell=cells[0],
- age=0,
- beard_length=0,
- beard_growth_parameter=0.5,
- eating_parameter=.1
- ) for i in range(dwarfs)
- ]
-
-print("\n The individuals:")
-print(individuals)
-print("\n \n")
-
-# assigning individuals to cell is not necessary since it is done by
-# initializing the individuals in 'base.Individuals' with the 'cell' method
-
-# instantiate groups
-ng = 10 #number of groups
-groups = [M.Group(culture=culture, world=world) for i in range (ng)]
-
-print("\n The groups:")
-print(groups)
-print("\n \n")
-
-start = time()
-
-print("done ({})".format(dt.timedelta(seconds=(time() - start))))
-
-print('\n runner starting')
-
-# first test for group network
-#nx.draw(culture.group_membership_network)
-#plt.show()
-
-
-# initialize the network:
-for i in individuals:
- for g in groups:
- culture.group_membership_network.add_edge(i, g)
-
-print("\n Individual 1 Group Memberships:")
-print(list(individuals[0].group_memberships))
-print("\n")
-
-print("\n Group Members:")
-print(list(groups[0].group_members))
-print("\n")
-
-#draw network of one group
-# nx.draw(individuals[0].culture.group_membership_network)
-# plt.show()
-
-GM = culture.group_membership_network
-
-print("\n The data structure in gm network:")
-print(GM.nodes.data())
-print("\n")
-
-# How networkx would classicaly plot the network
-nx.draw(culture.group_membership_network)
-plt.show()
-
-# How to plot more intuitively using the type and color information
-color_map = []
-shape_map = []
-for node in list(GM.nodes):
- print(node)
- print(GM.nodes[node])
- color_map.append(GM.nodes[node]["color"])
-
- if GM.nodes[node]["type"] == "Group":
- shape_map.append("o")
- else:
- shape_map.append("^")
-top_nodes = {n for n, d in GM.nodes(data=True) if d["type"] == "Group"}
-bottom_nodes = set(GM) - top_nodes
-nx.draw(GM, node_color=color_map, with_labels=False,
- pos=nx.bipartite_layout(GM, bottom_nodes, align="horizontal", aspect_ratio=4/1))
-plt.show()
-
-# Define termination signals as list [ signal_method, object_method_works_on ]
-# the termination method 'check_for_extinction' must return a boolean
-termination_signal = [M.Culture.check_for_extinction,
- culture]
-
-# Define termination_callables as list of all signals
-termination_callables = [termination_signal]
-
-# nx.draw(culture.acquaintance_network)
-# plt.show()
-
-# Runner is instantiated
-r = Runner(model=model,
- termination_calls=termination_callables
- )
-
-start = time()
-# run the Runner and saving the return dict in traj
-traj = r.run(t_1=timeinterval, dt=timestep, add_to_output=[M.Culture.acquaintance_network])
-runtime = dt.timedelta(seconds=(time() - start))
-print('runtime: {runtime}'.format(**locals()))
-
-# saving time values to t
-t = np.array(traj['t'])
-print("max. time step", (t[1:]-t[:-1]).max())
-
-# save and print membership
-
-membercheck = traj[M.Group.having_members]
-plt.plot(t, membercheck[groups[0]]) # plot if dwarf 0 was member of group 0
-plt.show()
diff --git a/studies/run_seven_dwarfs.py b/studies/seven_dwarfs/run_seven_dwarfs.py
similarity index 100%
rename from studies/run_seven_dwarfs.py
rename to studies/seven_dwarfs/run_seven_dwarfs.py
diff --git a/studies/test_jobsts_prototype_1.py b/studies/test_jobsts_prototype_1.py
deleted file mode 100755
index 15a51a38..00000000
--- a/studies/test_jobsts_prototype_1.py
+++ /dev/null
@@ -1,259 +0,0 @@
-"""Skript to run Jobsts prototype model."""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-from time import time
-from numpy import random, array
-import numpy as np
-import pycopancore.models.jobsts_prototype_1 as M
-# import pycopancore.models.only_copan_global_like_carbon_cycle as M
-from pycopancore import master_data_model as D
-from pycopancore.runners import Runner
-
-from pylab import plot, gca, show, figure, subplot, gca, semilogy, legend
-
-# first thing: set seed so that each execution must return same thing:
-random.seed(10) # 10
-
-# parameters:
-
-nworlds = 1 # no. worlds
-nsocs = 5 # no. social_systems #10
-ncells = 100 # no. cells #100
-ninds = 1000 # no. individuals
-
-model = M.Model()
-
-# instantiate process taxa:
-environment = M.Environment()
-metabolism = M.Metabolism(
- renewable_energy_knowledge_spillover_fraction = .1, #.1, #.1,
- # 1 w/o protection: success but desertification
- # .75 w protection: success (even w/o or w much migration)
- # .1 w protection: success but desertification
- # 0 w/o protection: very slow success but desertification
- # ?: oscillations
- basic_emigration_probability_rate = 16e-13, # 5e-13 leads to ca. 5mio. at 10 socs, (real)
- )
-culture = M.Culture(
- awareness_lower_carbon_density=1e-4, #1e100, # 1e-6?
- awareness_upper_carbon_density=2e-4, #1e100, # 2e-6?
- awareness_update_rate=0, #1:SUCCESS, #1e-10
- environmental_friendliness_learning_rate=0, #1:SUCCESS
- max_protected_terrestrial_carbon_share=0,
- )
-
-# generate entities and plug them together at random:
-worlds = [M.World(environment=environment, metabolism=metabolism, culture=culture,
- atmospheric_carbon = 830 * D.gigatonnes_carbon,
- upper_ocean_carbon = (5500 - 830 - 2480 - 1125) * D.gigatonnes_carbon
- ) for w in range(nworlds)]
-social_systems = [M.SocialSystem(world=random.choice(worlds),
- has_renewable_subsidy = random.choice([False, True], p=[3/4, 1/4]), #True, #False,
- has_emissions_tax = random.choice([False, True], p=[4/5, 1/5]), #True, #False,
- has_fossil_ban = False, #True, #False,
- time_between_votes = 1e100, #4, #1e100, # 4
- ) for s in range(nsocs)]
-cells = [M.Cell(social_system=random.choice(social_systems),
- renewable_sector_productivity = 2 * random.rand()
- * M.Cell.renewable_sector_productivity.default)
- for c in range(ncells)]
-individuals = [M.Individual(
- cell=random.choice(cells),
- is_environmentally_friendly =
- random.choice([False, True], p=[.7, .3]), #True, #False,
- )
- for i in range(ninds)]
-
-# initialize block model acquaintance network:
-target_degree = 150
-target_degree_samecell = 0.5 * target_degree
-target_degree_samesoc = 0.35 * target_degree
-target_degree_other = 0.15 * target_degree
-p_samecell = target_degree_samecell / (ninds/ncells - 1)
-p_samesoc = target_degree_samesoc / (ninds/nsocs - ninds/ncells - 1)
-p_other = target_degree_other / (ninds - ninds/nsocs - 1)
-for index, i in enumerate(individuals):
- for j in individuals[:index]:
- if random.uniform() < (
- p_samecell if i.cell == j.cell
- else p_samesoc if i.social_system == j.social_system \
- else p_other):
- culture.acquaintance_network.add_edge(i, j)
-#print("degrees:",culture.acquaintance_network.degree())
-
-# distribute area and vegetation randomly but correlatedly:
-r = random.uniform(size=ncells)
-Sigma0 = 1.5e8 * D.square_kilometers * r / sum(r)
-M.Cell.land_area.set_values(cells, Sigma0)
-# print(M.Cell.land_area.get_values(cells))
-
-r += random.uniform(size=ncells)
-L0 = 2480 * D.gigatonnes_carbon * r / sum(r) # 2480 is yr 2000
-M.Cell.terrestrial_carbon.set_values(cells, L0)
-# print(M.Cell.terrestrial_carbon.get_values(cells))
-
-r = np.exp(random.normal(size=ncells))
-G0 = 1125 * D.gigatonnes_carbon * r / sum(r) # 1125 is yr 2000
-M.Cell.fossil_carbon.set_values(cells, G0)
-# print(M.Cell.fossil_carbon.get_values(cells))
-
-r = random.uniform(size=nsocs)
-P0 = 6e9 * D.people * r / sum(r) # 500e9 is middle ages, 6e9 would be yr 2000
-M.SocialSystem.population.set_values(social_systems, P0)
-M.SocialSystem.migrant_population.set_values(social_systems, P0 * 250e6/6e9)
-for s in social_systems:
- s.max_protected_terrestrial_carbon = 0.90 * sum(c.terrestrial_carbon for c in s.cells)
-
-# print(M.SocialSystem.population.get_values(social_systems))
-
-r = random.uniform(size=nsocs)
-K0 = sum(P0) * 1e4 * D.dollars/D.people * r / sum(r) # ?
-M.SocialSystem.physical_capital.set_values(social_systems, K0)
-# print(M.SocialSystem.physical_capital.get_values(social_systems))
-
-# for renewables, do NOT divide by number of socs:
-r = random.uniform(size=nsocs)
-# in AWS paper: 1e12 (alternatively: 1e13):
-S0 = 1e12 * D.gigajoules * r / r.mean()
-M.SocialSystem.renewable_energy_knowledge.set_values(social_systems, S0)
-# print(M.SocialSystem.renewable_energy_knowledge.get_values(social_systems))
-
-# TODO: add noise to parameters
-
-w = worlds[0]
-s = social_systems[0]
-c = cells[0]
-for v in environment.variables: print(v,v.get_value(environment))
-for v in metabolism.variables: print(v,v.get_value(metabolism))
-for v in w.variables: print(v,v.get_value(w))
-for v in s.variables: print(v,v.get_value(s))
-for v in c.variables: print(v,v.get_value(c))
-
-# from pycopancore.private._expressions import eval
-# import pycopancore.model_components.base.interface as B
-# import sympy as sp
-
-runner = Runner(model=model)
-
-start = time()
-traj = runner.run(t_0=2000, t_1=2000+100, dt=1, add_to_output=[M.Individual.represented_population])
-
-
-for v in environment.variables: print(v,v.get_value(environment))
-for v in metabolism.variables: print(v,v.get_value(metabolism))
-for v in w.variables: print(v,v.get_value(w))
-for v in s.variables: print(v,v.get_value(s))
-for v in c.variables: print(v,v.get_value(c))
-
-
-from pickle import dump
-tosave = {
- v.owning_class.__name__ + "."
- + v.codename: {str(e): traj[v][e]
- for e in traj[v].keys()
- }
- for v in traj.keys() if v is not "t"
- }
-tosave["t"] = traj["t"]
-dump(tosave, open("/home/jobst/work/without.pickle","wb"))
-print(time()-start, " seconds")
-
-t = np.array(traj['t'])
-print("max. time step", (t[1:]-t[:-1]).max())
-
-figure()
-lws = 1
-
-subplot(511) # cultural
-for i, s in enumerate(social_systems):
-# plot(t[3:], traj[M.SocialSystem.protected_terrestrial_carbon_share][s][3:],color="green",lw=lws, label=None if i else "share of protected biomass")
- plot(t[3:], traj[M.SocialSystem.has_renewable_subsidy][s][3:]*1,color="darkorange",lw=lws, label=None if i else "renewable subsidy in place?")
- plot(t[3:], traj[M.SocialSystem.has_emissions_tax][s][3:]*1,color="blue",lw=lws, label=None if i else "emissions tax in place?")
- plot(t[3:], traj[M.SocialSystem.has_fossil_ban][s][3:]*1,color="gray",lw=lws, label=None if i else "fossil ban in place?")
-legend()
-
-subplot(512) # metabolic, logscale: capital, knowledge, production, wellbeing
-for i, s in enumerate(social_systems):
- semilogy(t[3:], array(traj[M.SocialSystem.physical_capital][s][3:])/1e6, color="black", lw=lws, label=None if i else "physical capital [mio. $]")
- semilogy(t[3:], array(traj[M.SocialSystem.renewable_energy_knowledge][s][3:])/1e6, color="darkorange", lw=lws, label=None if i else "renewable energy knowledge [PJ]")
- semilogy(t[3:], array(traj[M.SocialSystem.economic_output_flow][s][3:])/1e6, color="blue", lw=lws, label=None if i else "GDP [mio. $ per year]")
- semilogy(t[3:], array(traj[M.SocialSystem.wellbeing][s][3:]), color="magenta",lw=lws, label=None if i else "wellbeing [$ per year and person]")
-legend()
-
-subplot(513) # metabolic: population (left), migration (right)
-ax1 = gca()
-#ax1.set_xlabel('years')
-# Make the y-axis label, ticks and tick labels match the line color.
-ax1.set_ylabel('humans')
-ax1.tick_params('y')
-ax2 = ax1.twinx()
-ax2.set_ylabel('humans per year', color='gray')
-ax2.tick_params('y', colors='gray')
-for i, s in enumerate(social_systems):
- ax1.plot(t[3:], traj[M.SocialSystem.population][s][3:],color="black",lw=lws, label=None if i else "population")
- ax1.plot(t[3:], traj[M.SocialSystem.migrant_population][s][3:],"-.",color="black",lw=lws, label=None if i else "migrant population")
- ax2.plot(t[3:], traj[M.SocialSystem.immigration][s][3:],"--",color="gray",lw=lws, label=None if i else "immigration flow")
- ax2.plot(t[3:], traj[M.SocialSystem.emigration][s][3:],":",color="gray",lw=lws, label=None if i else "emigration flow")
-ax1.legend(loc=2)
-ax2.legend(loc=1)
-
-subplot(514) # metabolic: energy mix
-for i, s in enumerate(social_systems):
- Es = array(traj[M.SocialSystem.secondary_energy_flow][s][3:])
- plot(t[3:], array(traj[M.SocialSystem.biomass_input_flow][s][3:]) * metabolism.biomass_energy_density / Es, color="green", lw=lws, label=None if i else "share of biomass")
- plot(t[3:], array(traj[M.SocialSystem.fossil_fuel_input_flow][s][3:]) * metabolism.fossil_energy_density / Es, color="gray", lw=lws, label=None if i else "share of fossils")
- plot(t[3:], array(traj[M.SocialSystem.renewable_energy_input_flow][s][3:]) / Es, color="darkorange", lw=lws, label=None if i else "share of renewables")
-legend()
-
-subplot(515) # natural
-plot(t[3:], traj[M.World.atmospheric_carbon][worlds[0]][3:], color="cyan", lw=3, label="atmospheric carbon")
-plot(t[3:], traj[M.World.upper_ocean_carbon][worlds[0]][3:], color="blue", lw=3, label="upper ocean carbon")
-plot(t[3:], traj[M.World.terrestrial_carbon][worlds[0]][3:], color="green", lw=3, label="terrestrial carbon")
-plot(t[3:], traj[M.World.fossil_carbon][worlds[0]][3:], color="gray", lw=3, label="fossil carbon")
-for i, s in enumerate(social_systems):
- plot(t[3:], traj[M.SocialSystem.protected_terrestrial_carbon][s][3:],color="green",lw=lws, label=None if i else "protected biomass")
-gca().set_ylabel('gigatonnes carbon')
-legend()
-
-print("\nyr 2000 values (real):")
-print("emigration (5e6):",sum(traj[M.SocialSystem.emigration][s][5] for s in social_systems)) # should be ca. 5e6
-print("photo (123):",sum(traj[M.Cell.photosynthesis_carbon_flow][c][5] for c in cells))
-print("resp (118):",sum(traj[M.Cell.terrestrial_respiration_carbon_flow][c][5] for c in cells))
-print("GWP (4e13):",sum(traj[M.SocialSystem.economic_output_flow][s][5] for s in social_systems)) # should be ca. 4e13
-Bglobal = sum(traj[M.SocialSystem.biomass_input_flow][s][5] for s in social_systems) * D.gigatonnes_carbon / D.years
-Fglobal = sum(traj[M.SocialSystem.fossil_fuel_input_flow][s][5] for s in social_systems) * D.gigatonnes_carbon / D.years
-Rglobal = sum(traj[M.SocialSystem.renewable_energy_input_flow][s][5] for s in social_systems) * D.gigajoules / D.years
-print("B (3), F (11), R(100):",
- Bglobal.tostr(unit=D.gigatonnes_carbon/D.years), # should be ca. 3
- Fglobal.tostr(unit=D.gigatonnes_carbon/D.years), # should be ca. 11
- Rglobal.tostr(unit=D.gigawatts)) # last should be ca. 100
-#print((Bglobal * metabolism.biomass_energy_density * D.gigajoules/D.gigatonnes_carbon).tostr(unit=D.gigawatts),
-# (Fglobal * metabolism.fossil_energy_density * D.gigajoules/D.gigatonnes_carbon).tostr(unit=D.gigawatts),
-# Rglobal.tostr(unit=D.gigawatts), "(100)") # last should be ca. 100
-print("life exp. at end:",1/np.mean([traj[M.SocialSystem.mortality][s][-1] for s in social_systems]))
-print("cap. deprec. at begin (0.1?):",np.mean([traj[M.SocialSystem.physical_capital_depreciation_rate][s][5] for s in social_systems]))
-print("cap. deprec. at end (0.1?):",np.mean([traj[M.SocialSystem.physical_capital_depreciation_rate][s][-1] for s in social_systems]))
-print("deaths at begin (>250000?):",sum(traj[M.SocialSystem.deaths][s][5] for s in social_systems))
-print("deaths at end (>250000?):",sum(traj[M.SocialSystem.deaths][s][-1] for s in social_systems))
-print("temp. at begin:",traj[M.World.surface_air_temperature][worlds[0]][5])
-print("temp. at end:",traj[M.World.surface_air_temperature][worlds[0]][-1])
-print("prot. carbon share:",[traj[M.SocialSystem.protected_terrestrial_carbon][s][-1]/sum(traj[M.Cell.terrestrial_carbon][c][-1]for c in s.cells) for s in social_systems])
-print(traj[M.World.terrestrial_carbon][worlds[0]][-1],sum(traj[M.Cell.terrestrial_carbon][c][-1] for c in worlds[0].cells))
-
-show()
-
-# TODO:
-# policy shares, env. friendly shares
-# transparancy, means
-# wellb. abs., renew., pop. log
-# total protected
-# horiz.
-# save dump with codename,uid as key
\ No newline at end of file
diff --git a/studies/test_our_model.py b/studies/test_our_model.py
deleted file mode 100755
index 91d46a3e..00000000
--- a/studies/test_our_model.py
+++ /dev/null
@@ -1,137 +0,0 @@
-"""Skript to run Anderies carbon cycle."""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-from time import time
-from numpy import random
-import numpy as np
-import pycopancore.models.our_model as M
-# import pycopancore.models.only_copan_global_like_carbon_cycle as M
-from pycopancore import master_data_model as D
-from pycopancore.runners import Runner
-
-# import plotly.plotly as py
-import plotly.offline as py
-import plotly.graph_objs as go
-from pylab import plot, gca, show
-
-
-
-# first thing: set seed so that each execution must return same thing:
-random.seed(1)
-
-# parameters:
-
-model = M.Model()
-
-# instantiate process taxa:
-environment = M.Environment()
-# metabolism = M.Metabolism()
-
-# generate entities and plug them together at random:
-world = M.World(environment=environment, #metabolism=metabolism,
- atmospheric_carbon = 0.2 * D.gigatonnes_carbon, #relative values
- ocean_carbon = 0.6 * D.gigatonnes_carbon
- )
-social_system = M.SocialSystem(world=world)
-cell = M.Cell(social_system=social_system)
-
-# set initial values # only one cell so far
-Sigma0 = 1.5e8 * D.square_kilometers
-cell.land_area = Sigma0
-# print(M.Cell.land_area.get_values(cells))
-
-L0 = 0.2 * D.gigatonnes_carbon # 2480 is yr 2000
-cell.terrestrial_carbon = L0
-# print(M.Cell.terrestrial_carbon.get_values(cells))
-
-G0 = 0.5 * D.gigatonnes_carbon # 1125 is yr 2000
-cell.fossil_carbon = G0
-# print(M.Cell.fossil_carbon.get_values(cells))
-
-# r = random.uniform(size=nsocs)
-# P0 = 6e9 * D.people * r / sum(r) # 500e9 is middle ages, 6e9 would be yr 2000
-# M.SocialSystem.population.set_values(social_systems, P0)
-# print(M.SocialSystem.population.get_values(social_systems))
-
-# r = random.uniform(size=nsocs)
-# in AWS paper: 1e12 (alternatively: 1e13):
-# S0 = 1e13 * D.gigajoules * r / sum(r)
-# M.SocialSystem.renewable_energy_knowledge.set_values(social_systems, S0)
-# print(M.SocialSystem.renewable_energy_knowledge.get_values(social_systems))
-
-# r = random.uniform(size=nsocs)
-# K0 = sum(P0) * 1e4 * D.dollars/D.people * r / sum(r) # ?
-# M.SocialSystem.physical_capital.set_values(social_systems, K0)
-# print(M.SocialSystem.physical_capital.get_values(social_systems))
-
-# TODO: add noise to parameters
-
-# from pycopancore.private._expressions import eval
-# import pycopancore.model_components.base.interface as B
-# import sympy as sp
-
-runner = Runner(model=model)
-
-start = time()
-traj = runner.run(t_1=100, dt=.1)
-print(time()-start, " seconds")
-
-t = np.array(traj['t'])
-print("max. time step", (t[1:]-t[:-1]).max())
-
-data_ca = go.Scatter(
- x=t,
- y=traj[M.World.atmospheric_carbon][world],
- mode="lines",
- name="atmospheric carbon",
- line=dict(
- color="lightblue",
- width=4
- )
-)
-data_ct = go.Scatter(
- x=t,
- y=traj[M.World.terrestrial_carbon][world],
- mode="lines",
- name="terrestrial carbon",
- line=dict(
- color="green",
- width=4
- )
-)
-data_cm = go.Scatter(
- x=t,
- y=traj[M.World.ocean_carbon][world],
- mode="lines",
- name="maritime carbon",
- line=dict(
- color="blue",
- width=4
- )
-)
-data_cf = go.Scatter(
- x=t,
- y=traj[M.World.fossil_carbon][world],
- mode="lines",
- name="fossil carbon",
- line=dict(
- color="gray",
- width=4
- )
-)
-layout = dict(title = 'Our model (Anderies Carbon Cycle)',
- xaxis = dict(title = 'time [yr]'),
- yaxis = dict(title = 'Carbon [GtC]'),
- )
-
-fig = dict(data=[data_ca, data_ct, data_cm, data_cf], layout=layout)
-py.plot(fig, filename="our-model-result.html")
-
diff --git a/tests/test_simple_extraction_individual.py b/tests/test_simple_extraction_individual.py
deleted file mode 100644
index d60ca152..00000000
--- a/tests/test_simple_extraction_individual.py
+++ /dev/null
@@ -1,66 +0,0 @@
-"""Test file for the simple extraction module."""
-
-# This file is part of pycopancore.
-#
-# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
-# Impact Research
-#
-# URL:
-# Contact: core@pik-potsdam.de
-# License: BSD 2-clause license
-
-
-import pycopancore.models.exploit as M
-
-import numpy as np
-import unittest
-
-###################################################################
-# Example from https://docs.python.org/3/library/unittest.html
-###################################################################
-# class TestStringMethods(unittest.TestCase):
-#
-# def test_upper(self):
-# self.assertEqual('foo'.upper(), 'FOO')
-#
-# def test_isupper(self):
-# self.assertTrue('FOO'.isupper())
-# self.assertFalse('Foo'.isupper())
-# # self.assertTrue('Foo'.isupper(), "This test is failing on purpose.") #
-#
-# def test_split(self):
-# s = 'hello world'
-# self.assertEqual(s.split(), ['hello', 'world'])
-# # check that s.split fails when the separator is not a string
-# with self.assertRaises(TypeError):
-# s.split(2)
-
-
-class TestSimpleExtraction(unittest.TestCase):
-
- def setUp(self):
- """called before any of the tests in this test case"""
-
- self.stock = np.random.random()
- self.growth_rate = np.random.random()
- self.strategy = np.random.random()
-
- self.culture = M.Culture()
- self.world = M.World(culture=self.culture)
- self.cell = M.Cell(stock=self.stock, capacity=1, growth_rate=self.growth_rate, world=self.world)
- self.individual = M.Individual(
- strategy=self.strategy,
- imitation_tendency=0,
- cell=self.cell
- )
-
- def test_simple_extractiont(self):
- """Check the whole component."""
- #######################################################
- # Put all tests in one method, else you might get
- # annoying problems because we have a global list
- # of instances for most classes.
- #######################################################
- # self.assertTrue(False, "This is definitely wrong")
- solution = 0.5 * self.growth_rate * (3 - 2 * self.strategy) * self.stock
- self.assertEqual(self.individual.get_harvest_rate(), solution)
\ No newline at end of file