Added continuation for stopped simulation

This commit is contained in:
Kenneth Jao 2021-10-18 19:57:47 -04:00
parent 0d65aa5366
commit b4d6b5dbd8
6 changed files with 60 additions and 80 deletions

View File

@ -1,23 +0,0 @@
from pathlib import Path
import numpy as np, pickle, sys
from squish import Simulation
def main():
n = int(sys.argv[1])
all_widths = set(np.round(np.arange(3, 10.05, 0.05), 2))
for file in Path(f"squish_output/Radial[T]Search - N{n} - 500").iterdir():
sim, frames = Simulation.load(file / 'data.squish')
if sim.domain.n == n:
try:
all_widths.remove(next(frames)["domain"][1])
except StopIteration:
pass
remain_widths = sorted(list(all_widths))[::-1]
print("Remaining:", remain_widths)
if __name__ == "__main__":
main()

View File

@ -1,6 +1,6 @@
[metadata]
name = squish
version = 0.1.3
version = 0.1.4
author = Kenneth Jao
author_email = ksjdragon@gmail.com
description = squish is Python program which perform simulations for the flow of 'soft' or 'compressible' objects under some energy in a periodic domain.

View File

@ -6,7 +6,6 @@ from pathlib import Path
from ._squish import VoronoiContainer, AreaEnergy, RadialALEnergy, RadialTEnergy
OUTPUT_DIR = Path("squish_output")
OUTPUT_DIR.mkdir(exist_ok=True)
STR_TO_ENERGY = {
"area": AreaEnergy,
@ -17,7 +16,7 @@ STR_TO_ENERGY = {
def generate_filepath(sim: SimulationMode, fol: Union[str, Path], prec: int = 2) -> Path:
energy = sim.energy.title_str
width, height = round(sim.domain.w, 2), round(sim.domain.h, 2)
width, height = round(sim.domain.w, prec), round(sim.domain.h, prec)
base_path = f"{fol}/{energy}{sim.title_str} - " + \
f"N{sim.domain.n} - {width:.{prec}f}x{height:.{prec}f}"

View File

@ -6,7 +6,7 @@ from matplotlib.ticker import MaxNLocator, FormatStrFormatter
from scipy.spatial import Voronoi, voronoi_plot_2d
from multiprocessing import Pool, cpu_count
from .common import DomainParams
from .common import DomainParams, OUTPUT_DIR
SYMM = np.array([[0,0], [1,0], [1,1], [0,1], [-1,1], [-1,0], [-1,-1], [0,-1], [1,-1]])
@ -302,6 +302,8 @@ class Diagram:
def render_frames(self, frames: List[int], fol: str = 'frames') -> None:
OUTPUT_DIR.mkdir(exist_ok=True)
self.sim.path.mkdir(exist_ok=True)
(self.sim.path / fol).mkdir(exist_ok=True)
combo_list = []
for i in range(cpu_count()):

View File

@ -5,6 +5,7 @@ import pickle, numpy as np
from math import log10
from scipy.linalg import null_space
from timeit import default_timer as timer
from pathlib import Path
from .common import DomainParams, Energy, generate_filepath, OUTPUT_DIR
@ -46,7 +47,7 @@ class Simulation:
return len(self.frames)
def add_frame(self, points: Optional[numpy.ndarray]) -> None:
def add_frame(self, points: Optional[numpy.ndarray] = None) -> None:
if points is None:
points = np.random.random_sample((self.domain.n, 2)) * self.domain.dim
else:
@ -91,6 +92,7 @@ class Simulation:
def save(self, info: Dict, overwrite: bool = False) -> None:
OUTPUT_DIR.mkdir(exist_ok=True)
self.path.mkdir(exist_ok=True)
path = self.path / 'data.squish'
@ -117,8 +119,9 @@ class Simulation:
@staticmethod
def load(path: str) -> Tuple[Simulation, Generator]:
path = Path(path)
def frames() -> Dict:
with open(path, 'rb') as infile:
with open(path / 'data.squish', 'rb') as infile:
first = True
while True:
try:
@ -130,16 +133,26 @@ class Simulation:
except EOFError:
break
with open(path, 'rb') as infile:
with open(path / 'data.squish', 'rb') as infile:
sim_info = pickle.load(infile)
domain = DomainParams(*sim_info["domain"])
energy = Energy(sim_info["energy"])
sim = STR_TO_SIM[sim_info["mode"]](domain, energy, *list(sim_info.values())[3:])
sim.path = path
return sim, frames()
@staticmethod
def from_file(path: str) -> Simulation:
sim, frames = Simulation.load(path)
for frame in frames:
sim.frames.append(sim.energy.mode(*frame["domain"], frame["arr"]))
return sim
class Flow(Simulation):
"""Finds an equilibrium from initial sites.
@ -177,12 +190,13 @@ class Flow(Simulation):
return info
def run(self, save: bool, log: bool, log_steps: int) -> None:
def run(self, save: bool, log: bool, log_steps: int,
new_sites: Optional[numpy.ndarray] = None) -> None:
if log: print(f"Find - {self.domain}", flush=True)
if save: self.save(self.initial_data, True)
if len(self) == 0: self.add_frame()
if save and len(self) == 0: self.save(self.initial_data, True)
if len(self) == 0: self.add_frame(new_sites)
i, stop = 0, False
i, stop = len(self)-1, False
while not stop: # Get to threshold.
if save:
@ -262,17 +276,12 @@ class Search(Simulation):
return info
def run(self, save: bool, log: bool, log_steps: int) -> None:
def run(self, save: bool, log: bool, log_steps: int,
new_sites: Optional[numpy.ndarray] = None) -> None:
if log: print(f'Travel - {self.domain}', flush=True)
if save: self.save(self.initial_data, True)
if save and len(self) == 0: self.save(self.initial_data, True)
if len(self) != 0:
new_sites = self[0].site_arr
self.frames = []
else:
new_sites = None
for i in range(self.count):
for i in range(len(self), self.count):
# Get to equilibrium.
sim = Flow(self.domain, self.energy, self.step_size, self.thres, self.adaptive)
sim.add_frame(new_sites)
@ -298,7 +307,6 @@ class Search(Simulation):
new_sites = self.frames[i].add_sites(self.kernel_step*vec)
class Shrink(Simulation):
"""Shrinks width and finds nearest equilibrium.
@ -343,17 +351,12 @@ class Shrink(Simulation):
return info
def run(self, save: bool, log: bool, log_steps: int) -> None:
def run(self, save: bool, log: bool, log_steps: int,
new_sites: Optional[numpy.ndarray] = None) -> None:
if log: print(f'Shrink - {self.domain}', flush=True)
if save: self.save(self.initial_data, True)
if save and len(self) == 0: self.save(self.initial_data, True)
if len(self) != 0:
new_sites = self[0].site_arr
self.frames = []
else:
new_sites = None
width = self.domain.w
width = self.domain.w if len(self.frames) == 0 else self.frames[-1].w
i = 0
while width >= self.stop_width:
# Get to equilibrium.
@ -371,6 +374,7 @@ class Shrink(Simulation):
width -= self.delta
i += 1
STR_TO_SIM = {
"flow": Flow,
"search": Search,

View File

@ -5,7 +5,7 @@ from shutil import which
from pathlib import Path
from .common import DomainParams, Energy
from .simulation import Flow, Search, Shrink
from .simulation import Simulation, Flow, Search, Shrink
from .diagram import Diagram
dia_presets = {
@ -45,13 +45,15 @@ def check_params(container: Dict, needed: List[str], valid: Dict) -> None:
def main():
# Loading configuration and settings.
parser = argparse.ArgumentParser("PackSim")
parser = argparse.ArgumentParser("Squish")
parser.add_argument('sim_conf', metavar='/path/to/config.json',
help="configuration file for a simulation")
parser.add_argument('-q', '--quiet', dest='quiet', action='store_true', default=False,
help="suppress all normal output")
parser.add_argument('-l', '--log', dest='log_steps', default=50, type=int,
help="number of iterations before logging")
parser.add_argument('-i', dest='input_file', metavar='/path/to/sim',
help="folder that contains outputted simulation files.", default=None)
parser.add_argument('--n_objects', dest='n', type=int, help="objects in domain")
parser.add_argument('--width', dest='w', type=float, help="width of domain")
@ -60,17 +62,14 @@ def main():
parser.add_argument('--energy', dest='energy', help="energy type of system")
args = parser.parse_args()
config_sim(args)
# if args.input_file is None:
# config_sim(args)
# else:
# loaded_sim(args)
do_sim(args, args.input_file)
def config_sim(args):
def do_sim(args, file):
with open(args.sim_conf) as f:
params = json.load(f)
check_params(params, ["domain", "simulation"], {})
dmn_params, sim_params = params["domain"], params["simulation"]
@ -105,20 +104,23 @@ def config_sim(args):
name = sim_params.get("name")
if mode == "flow":
sim = Flow(domain, energy, step, thres, adaptive, name=name)
elif mode == "search":
check_params(sim_params, ["manifold_step_size", "eq_stop_count"], {
"manifold_step_size": "positive", "eq_stop_count": "positive"
})
sim = Search(domain, energy, step, thres, adaptive, sim_params["manifold_step_size"],
sim_params["eq_stop_count"], name=name)
elif mode == "shrink":
check_params(sim_params, ["width_change", "width_stop"], {
"width_change": "positive", "width_stop": "positive"
})
sim = Shrink(domain, energy, step, thres, adaptive, sim_params["width_change"],
sim_params["width_stop"], name=name)
if file is None:
if mode == "flow":
sim = Flow(domain, energy, step, thres, adaptive, name=name)
elif mode == "search":
check_params(sim_params, ["manifold_step_size", "eq_stop_count"], {
"manifold_step_size": "positive", "eq_stop_count": "positive"
})
sim = Search(domain, energy, step, thres, adaptive, sim_params["manifold_step_size"],
sim_params["eq_stop_count"], name=name)
elif mode == "shrink":
check_params(sim_params, ["width_change", "width_stop"], {
"width_change": "positive", "width_stop": "positive"
})
sim = Shrink(domain, energy, step, thres, adaptive, sim_params["width_change"],
sim_params["width_stop"], name=name)
else:
sim = Simulation.from_file(file)
save_diagram = False
if "diagram" in params:
@ -139,8 +141,7 @@ def config_sim(args):
if "time" not in dia_params:
dia_params["time"] = 30
sim.add_frame(points)
sim.run(save_sim, not args.quiet, args.log_steps)
sim.run(save_sim, not args.quiet, args.log_steps, points)
if save_diagram:
diagram = Diagram(sim, dia_params["figures"])
@ -153,9 +154,6 @@ def config_sim(args):
diagram.render_video(dia_params["time"], "use_all")
def loaded_sim(args):
pass
def pre():
os.environ["QT_LOGGING_RULES"] = "*=false"
try: