Add one predeclared mass-four paired VIV exploration
This commit is contained in:
1 parent
516975ef64
commit
73d3f6214e
3 files changed
+154
-9
No files matched your search
@@ -22,6 +22,7 @@ from research.steady_pinball.run import Structure, config, scaled_points, CENTRE
|
||||
BIAS = np.array([0., -4., 4.])
|
||||
MODEL_SHA = '148240c1dcb8b11d8e5a0a9e991f6874c4e799c9744707bf0fb32a8efeb0468d'
|
||||
NORM_SHA = '534fda818c030a56960e95d0f3ac1e350d887d03db7f80f1d6453195a502b7f0'
|
||||
RELEASE_SOURCE = '516975ef6482f983ace347cb10de7450d2fbd680'
|
||||
STEP_COLUMNS = (*COLUMNS, 'omega_F', 'omega_U', 'omega_L')
|
||||
|
||||
|
||||
@@ -161,12 +162,12 @@ def precursor(cfgpath, scale, warm, si, targets, out, start, cap):
|
||||
return seed, force
|
||||
|
||||
|
||||
def run_arm(name, cfgpath, scale, si, intervals, seed, initial_force, model, norm, out, start, cap):
|
||||
def run_arm(name, cfgpath, scale, si, intervals, seed, initial_force, model, norm, out, start, cap, *, mass_ratio=2.):
|
||||
from CelerisLab import Simulation
|
||||
from CelerisLab.body.motion import MovingTables
|
||||
cols = {k:i for i, k in enumerate(MovingTables.DIAG)}
|
||||
diameter = 20.*scale
|
||||
structure = Structure(2., 1.e-4/scale**2, 0., diameter)
|
||||
structure = Structure(mass_ratio, 1.e-4/scale**2, 0., diameter)
|
||||
arm = out/name
|
||||
arm.mkdir()
|
||||
rows = np.lib.format.open_memmap(arm/'steps.npy', mode='w+', dtype=np.float64,
|
||||
@@ -244,16 +245,45 @@ def run_arm(name, cfgpath, scale, si, intervals, seed, initial_force, model, nor
|
||||
(arm/'report.json').write_text(json.dumps(report,indent=2)+'\n')
|
||||
|
||||
|
||||
def saved_release(directory):
|
||||
"""Read the retained m*=2 static release; not a moving-state restart."""
|
||||
case = json.loads((directory/'case.json').read_text())
|
||||
expected = dict(source=RELEASE_SOURCE, model_sha256=MODEL_SHA, norm_sha256=NORM_SHA,
|
||||
smoke=False, D=40, U=.005, nu=.004, warmup_each=2048000,
|
||||
target_intervals=150, SI=3200)
|
||||
if any(case.get(k) != v for k, v in expected.items()):
|
||||
raise ValueError('saved release case does not match the frozen precursor')
|
||||
if json.loads((directory/'config.json').read_text()) != config(40):
|
||||
raise ValueError('saved release config differs')
|
||||
with np.load(directory/'release.npz') as data:
|
||||
seed = (data['current'], data['spare'], data['flags'], int(data['clock']))
|
||||
force = float(data['force'])
|
||||
transfer = json.loads((directory/'zero/report.json').read_text())['release_transfer']
|
||||
if seed[3] != transfer['clock'] or seed[3] != 4576000 or not np.isfinite(force):
|
||||
raise ValueError('saved release clock/force differs')
|
||||
if [array_sha(a) for a in seed[:3]] != [transfer[k] for k in ('current','spare','flags')]:
|
||||
raise ValueError('saved release buffer/flags hash differs')
|
||||
target = np.load(directory/'target.npy')
|
||||
if target.shape != (150,6) or not np.isfinite(target).all():
|
||||
raise ValueError('saved target is incomplete or nonfinite')
|
||||
return seed, force
|
||||
|
||||
|
||||
def main():
|
||||
ap = argparse.ArgumentParser(description=__doc__)
|
||||
ap.add_argument('--model', type=Path, required=True)
|
||||
ap.add_argument('--norm', type=Path, required=True)
|
||||
ap.add_argument('--out', type=Path, required=True)
|
||||
ap.add_argument('--smoke', action='store_true', help='short plumbing only; no physical conclusion')
|
||||
ap.add_argument('--mass-ratio', type=float, choices=(2.,4.), default=2.,
|
||||
help='4 is the single declared exploratory candidate; fn and damping unchanged')
|
||||
ap.add_argument('--release-dir', type=Path, help='retained m*=2 precursor; skip warmup')
|
||||
ap.add_argument('--wall-seconds', type=float, default=14400.)
|
||||
args = ap.parse_args()
|
||||
if not np.isfinite(args.wall_seconds) or args.wall_seconds<=0:
|
||||
ap.error('positive finite wall cap required')
|
||||
if args.release_dir is not None and args.smoke:
|
||||
ap.error('saved physical release cannot be used for the plumbing smoke')
|
||||
if sha(args.model)!=MODEL_SHA or sha(args.norm)!=NORM_SHA:
|
||||
ap.error('model/normalizer must match frozen provenance')
|
||||
out = args.out.resolve()
|
||||
@@ -272,14 +302,24 @@ def main():
|
||||
response_steps=si*intervals,response_tU_D=si*intervals*.005/40,
|
||||
rhs='previous native step sum CME_y+Wen_y; policy uses interval packed CME',
|
||||
probe_frame='lab-fixed; fine area mean * 2 * trained 78 cells',
|
||||
ema_native_alpha=.9**.25, structural_damping=0., columns=STEP_COLUMNS)
|
||||
ema_native_alpha=.9**.25, structural_damping=0., mass_ratio=args.mass_ratio,
|
||||
exploratory=args.mass_ratio==4., columns=STEP_COLUMNS)
|
||||
loaded = None
|
||||
if args.release_dir is not None:
|
||||
loaded = saved_release(args.release_dir)
|
||||
cfgpath.write_bytes((args.release_dir/'config.json').read_bytes())
|
||||
(out/'target.npy').write_bytes((args.release_dir/'target.npy').read_bytes())
|
||||
receipt.update(release_dir=str(args.release_dir.resolve()), release_source=RELEASE_SOURCE,
|
||||
release_sha256=sha(args.release_dir/'release.npz'),
|
||||
warmup_executed=0, target_sha256=sha(out/'target.npy'))
|
||||
(out/'case.json').write_text(json.dumps(receipt,indent=2)+'\n')
|
||||
start = time.monotonic()
|
||||
status = 'running'
|
||||
try:
|
||||
seed, force = precursor(cfgpath,scale,warm,si,targets,out,start,args.wall_seconds)
|
||||
seed, force = loaded if loaded is not None else precursor(cfgpath,scale,warm,si,targets,out,start,args.wall_seconds)
|
||||
for name in ('zero','controlled'):
|
||||
run_arm(name,cfgpath,scale,si,intervals,seed,force,model,norm,out,start,args.wall_seconds)
|
||||
run_arm(name,cfgpath,scale,si,intervals,seed,force,model,norm,out,start,args.wall_seconds,
|
||||
mass_ratio=args.mass_ratio)
|
||||
status = 'smoke_completed' if args.smoke else 'pair_completed_not_qualified'
|
||||
except BaseException as exc:
|
||||
status = f'error: {type(exc).__name__}: {exc}'
|
||||
|
||||
Reference in new issue
Block a user