Template for CPU executables
- forces_simple.forces_simf.run_forces(H, persis_info, sim_specs, libE_info)
Runs the forces MPI application.
By default assigns the number of MPI ranks to the number of cores available to this worker.
To assign a different number give e.g., num_procs=4 to
exctr.submit.
forces_simf.py
1import numpy as np
2
3# Optional status codes to display in libE_stats.txt for each gen or sim
4from libensemble.message_numbers import TASK_FAILED, WORKER_DONE
5
6
7def run_forces(H, persis_info, sim_specs, libE_info):
8 """Runs the forces MPI application.
9
10 By default assigns the number of MPI ranks to the number
11 of cores available to this worker.
12
13 To assign a different number give e.g., `num_procs=4` to
14 ``exctr.submit``.
15 """
16
17 calc_status = 0
18
19 # Parse out num particles, from generator function
20 particles = str(int(H["x"][0][0]))
21
22 # app arguments: num particles, timesteps, also using num particles as seed
23 args = particles + " " + str(10) + " " + particles
24
25 # Retrieve our MPI Executor
26 exctr = libE_info["executor"]
27
28 # Submit our forces app for execution.
29 task = exctr.submit(app_name="forces", app_args=args)
30
31 # Block until the task finishes
32 task.wait()
33
34 # Try loading final energy reading, set the sim's status
35 statfile = "forces.stat"
36 try:
37 data = np.loadtxt(statfile)
38 final_energy = data[-1]
39 calc_status = WORKER_DONE
40 except Exception:
41 final_energy = np.nan
42 calc_status = TASK_FAILED
43
44 # Define our output array, populate with energy reading
45 output = np.zeros(1, dtype=sim_specs["out"])
46 output["energy"] = final_energy
47
48 # Return final information to worker, for reporting to manager
49 return output, persis_info, calc_status
Example usage
1#!/usr/bin/env python
2import os
3import sys
4
5import numpy as np
6from forces_simf import run_forces # Sim func from current dir
7
8from libensemble import Ensemble
9from libensemble.alloc_funcs.start_only_persistent import only_persistent_gens as alloc_f
10from libensemble.executors import MPIExecutor
11from libensemble.gen_funcs.persistent_sampling import persistent_uniform as gen_f
12from libensemble.specs import AllocSpecs, ExitCriteria, GenSpecs, LibeSpecs, SimSpecs
13
14if __name__ == "__main__":
15 # Initialize MPI Executor
16 exctr = MPIExecutor()
17
18 # Register simulation executable with executor
19 sim_app = os.path.join(os.getcwd(), "../forces_app/forces.x")
20
21 if not os.path.isfile(sim_app):
22 sys.exit("forces.x not found - please build first in ../forces_app dir")
23
24 exctr.register_app(full_path=sim_app, app_name="forces")
25
26 # Parse number of workers, comms type, etc. from arguments
27 ensemble = Ensemble(parse_args=True, executor=exctr)
28 nsim_workers = ensemble.nworkers - 1 # One worker is for persistent generator
29
30 # Persistent gen does not need resources
31 ensemble.libE_specs = LibeSpecs(
32 num_resource_sets=nsim_workers,
33 sim_dirs_make=True,
34 )
35
36 ensemble.sim_specs = SimSpecs(
37 sim_f=run_forces,
38 inputs=["x"],
39 outputs=[("energy", float)],
40 )
41
42 ensemble.gen_specs = GenSpecs(
43 gen_f=gen_f,
44 inputs=[], # No input when start persistent generator
45 persis_in=["sim_id"], # Return sim_ids of evaluated points to generator
46 outputs=[("x", float, (1,))],
47 user={
48 "initial_batch_size": nsim_workers,
49 "lb": np.array([1000]), # min particles
50 "ub": np.array([3000]), # max particles
51 },
52 )
53
54 # Starts one persistent generator. Simulated values are returned in batch.
55 ensemble.alloc_specs = AllocSpecs(
56 alloc_f=alloc_f,
57 user={
58 "async_return": False, # False causes batch returns
59 },
60 )
61
62 # Instruct libEnsemble to exit after this many simulations
63 ensemble.exit_criteria = ExitCriteria(sim_max=8)
64
65 # Seed random streams for each worker, particularly for gen_f
66 ensemble.add_random_streams()
67
68 # Run ensemble
69 ensemble.run()
70
71 if ensemble.is_manager:
72 # Note, this will change if changing sim_max, nworkers, lb, ub, etc.
73 print(f'Final energy checksum: {np.sum(ensemble.H["energy"])}')
Also see the Forces tutorial.