import functools
import numpy as np
from worldhistory.world import World, neighbours_from_ids
DEFAULTS = dict(ocean=False, elevation_m=100.0, T_mean=15.0, P_ann=1000.0, holdridge=20, landform=1, river=False,
strahler=0, lake=False, ice=0, coal_potential=False, iron_potential=False, vent_potential=0.0,
seabed_type=0, lithology=1, ground=0, gravity_g=1.0, o2_fraction=0.21, pressure_bar=1.0,
bottom_temp_c=2.0, plate=0)
def fields(n, **over):
out = {}
for k, v in {**DEFAULTS, **over}.items():
a = np.asarray(v)
out[k] = np.broadcast_to(a, (n,)).copy() if a.ndim == 0 else a.copy()
return out
def line_world(n, spacing_km=100.0, radius_km=6371.0, **over):
"""Cells on the equator in a row, each linked to the next: 1-D worlds with hand-checkable answers."""
lon = np.arange(n) * np.degrees(spacing_km / radius_km)
lat = np.zeros(n)
xyz = np.stack([np.cos(np.radians(lon)), np.sin(np.radians(lon)), np.zeros(n)], 1)
nb = np.full((n, 6), -1, np.int64)
nb[1:, 0] = np.arange(n - 1)
nb[:-1, 1] = np.arange(1, n)
return World(nb=nb, lat=lat, lon=lon, xyz=xyz, area=np.full(n, spacing_km ** 2), radius_km=radius_km,
base=fields(n, **over))
@functools.lru_cache(maxsize=4)
def _h3_grid(res):
import h3.api.basic_int as h3
ids = sorted(c for r0 in h3.get_res0_cells() for c in h3.cell_to_children(r0, res))
ll = np.array([h3.cell_to_latlng(c) for c in ids])
area = np.array([h3.cell_area(c, unit="rads^2") for c in ids])
return np.array(ids, np.uint64), ll, area
def globe_world(res=1, radius_km=6371.0):
"""A whole H3 globe (res 1 = 842 cells) with default fields; tests edit world.base afterwards."""
ids, ll, area = _h3_grid(res)
lat, lon = ll[:, 0].copy(), ll[:, 1].copy()
la, lo = np.radians(lat), np.radians(lon)
xyz = np.stack([np.cos(la) * np.cos(lo), np.cos(la) * np.sin(lo), np.sin(la)], 1)
return World(nb=neighbours_from_ids(ids), lat=lat, lon=lon, xyz=xyz, area=area * radius_km ** 2,
radius_km=radius_km, base=fields(len(ids)))
from worldhistory.config import parse_history, parse_race
def make_race(id="a", **over):
"""A land race with density 1/km² at q=1, growth 0.1/step, no Allee, founder 1, no mobility; sections override."""
d = {"id": id,
"demography": {"density": 1.0, "growth": 0.1, "allee": 0.0, "founder": 1.0, "mobility": 0.0},
"habitat": {"realm": "land", "terms": [{"p": "land", "w": 1.0}]}}
for k, v in over.items():
d[k] = {**d.get(k, {}), **v} if isinstance(v, dict) and isinstance(d.get(k), dict) else v
return parse_race(d, f"test:{id}")
def make_history(**over):
d = {"run": {"years": 100, "step": 10, "snapshot_every": 50, "seed": 1}}
d.update(over)
return parse_history(d, "test:history")