@@ -155,7 +155,7 @@ def libE(
155155 exit_criteria : ExitCriteria ,
156156 persis_info : dict = {},
157157 alloc_specs : AllocSpecs = AllocSpecs (),
158- libE_specs : LibeSpecs = {},
158+ libE_specs : LibeSpecs | dict = {},
159159 H0 = None ,
160160) -> (np .ndarray , dict , int ):
161161 """
@@ -242,11 +242,16 @@ def libE(
242242 ]
243243 exit_criteria = specs_dump (ensemble .exit_criteria , by_alias = True , exclude_none = True )
244244
245- # Restore objects that don't survive serialization via model_dump
246- if hasattr (ensemble .gen_specs , "generator" ) and ensemble .gen_specs .generator is not None :
247- gen_specs ["generator" ] = ensemble .gen_specs .generator
248- if hasattr (ensemble .gen_specs , "vocs" ) and ensemble .gen_specs .vocs is not None :
249- gen_specs ["vocs" ] = ensemble .gen_specs .vocs
245+ if hasattr (ensemble .sim_specs , "simulator" ) and ensemble .sim_specs .simulator is not None :
246+ sim_specs ["simulator" ] = ensemble .sim_specs .simulator
247+ if hasattr (ensemble .sim_specs , "vocs" ) and ensemble .sim_specs .vocs is not None :
248+ sim_specs ["vocs" ] = ensemble .sim_specs .vocs
249+
250+ if ensemble .gen_specs is not None :
251+ if hasattr (ensemble .gen_specs , "generator" ) and ensemble .gen_specs .generator is not None :
252+ gen_specs ["generator" ] = ensemble .gen_specs .generator
253+ if hasattr (ensemble .gen_specs , "vocs" ) and ensemble .gen_specs .vocs is not None :
254+ gen_specs ["vocs" ] = ensemble .gen_specs .vocs
250255
251256 # Extract platform info from settings or environment
252257 platform_info = get_platform (libE_specs )
@@ -358,7 +363,7 @@ def libE_mpi(sim_specs, gen_specs, exit_criteria, persis_info, alloc_specs, libE
358363 logger .manager_warning ("*WARNING* libEnsemble detected a NULL communicator" )
359364 return [], persis_info , 3 # Process not in mpi_comm
360365
361- assert libE_specs ["mpi_comm" ].Get_size () > 1 , "Manager only - must be at least one worker (2 MPI tasks) "
366+ assert libE_specs ["mpi_comm" ].Get_size () >= 1 , "Manager only - must be at least one MPI task "
362367
363368 with DupComm (libE_specs ["mpi_comm" ]) as mpi_comm :
364369 is_manager = mpi_comm .Get_rank () == 0
@@ -368,7 +373,6 @@ def libE_mpi(sim_specs, gen_specs, exit_criteria, persis_info, alloc_specs, libE
368373 local_host = socket .gethostname ()
369374 libE_nodes = list (set (mpi_comm .allgather (local_host )))
370375 resources .add_comm_info (libE_nodes = libE_nodes )
371- nworkers = mpi_comm .Get_size () - 1
372376
373377 exctr = Executor .executor
374378 if exctr is not None :
@@ -379,7 +383,8 @@ def libE_mpi(sim_specs, gen_specs, exit_criteria, persis_info, alloc_specs, libE
379383 # Run manager or worker code, depending
380384 if is_manager :
381385 if resources is not None :
382- resources .set_resource_manager (nworkers )
386+ n_resource_workers = mpi_comm .Get_size ()
387+ resources .set_resource_manager (n_resource_workers )
383388 return libE_mpi_manager (
384389 mpi_comm , sim_specs , gen_specs , exit_criteria , persis_info , alloc_specs , libE_specs , H0
385390 )
@@ -497,7 +502,8 @@ def libE_local(sim_specs, gen_specs, exit_criteria, persis_info, alloc_specs, li
497502
498503 # Set manager resources after the forkpoint.
499504 if resources is not None :
500- resources .set_resource_manager (libE_specs ["nworkers" ])
505+ n_resource_workers = libE_specs ["nworkers" ] + (not libE_specs .get ("gen_on_worker" , False ))
506+ resources .set_resource_manager (n_resource_workers )
501507
502508 if not libE_specs ["disable_log_files" ]:
503509 exit_logger = manager_logging_config (specs = libE_specs )
0 commit comments