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] [metadata]
name = squish name = squish
version = 0.1.3 version = 0.1.4
author = Kenneth Jao author = Kenneth Jao
author_email = ksjdragon@gmail.com 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. 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 from ._squish import VoronoiContainer, AreaEnergy, RadialALEnergy, RadialTEnergy
OUTPUT_DIR = Path("squish_output") OUTPUT_DIR = Path("squish_output")
OUTPUT_DIR.mkdir(exist_ok=True)
STR_TO_ENERGY = { STR_TO_ENERGY = {
"area": AreaEnergy, "area": AreaEnergy,
@ -17,7 +16,7 @@ STR_TO_ENERGY = {
def generate_filepath(sim: SimulationMode, fol: Union[str, Path], prec: int = 2) -> Path: def generate_filepath(sim: SimulationMode, fol: Union[str, Path], prec: int = 2) -> Path:
energy = sim.energy.title_str 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} - " + \ base_path = f"{fol}/{energy}{sim.title_str} - " + \
f"N{sim.domain.n} - {width:.{prec}f}x{height:.{prec}f}" 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 scipy.spatial import Voronoi, voronoi_plot_2d
from multiprocessing import Pool, cpu_count 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]]) 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: 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) (self.sim.path / fol).mkdir(exist_ok=True)
combo_list = [] combo_list = []
for i in range(cpu_count()): for i in range(cpu_count()):

View File

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

View File

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