Because a single Python process cannot run more than one Comsol session, you must use the multiprocessing module to achieve parallel execution. This allows you to run multiple Python processes, each managing its own mph.start() session, to perform tasks like parameter sweeps across multiple CPU cores.
Implementation Pattern
- Define a Worker Function: The function should call
mph.start(cores=1) inside the process to initialize a local Comsol session. It should pull tasks from a multiprocessing.Queue (jobs), perform the simulation, and push results to another multiprocessing.Queue (results). - Initialize Queues: Create a
multiprocessing.Queue() for jobs and an empty one for results. - Spawn Processes: Use
multiprocessing.Process to start multiple workers. It is recommended to keep references to these process objects in a list to prevent garbage collection from terminating them prematurely. - Collect Results: In the main process, iterate through the results queue to retrieve the completed data. Note that because processes run asynchronously, results may not be returned in the same order they were submitted.
This approach provides more programmatic control than Comsol's internal 'parametric sweep', making it suitable for iterative optimization algorithms like genetic algorithms.
import mph
import multiprocessing
import queue
# 1. Define the worker
def worker(jobs, results):
client = mph.start(cores=1)
model = client.load('capacitor.mph')
while True:
try:
d = jobs.get(block=False)
except queue.Empty:
break
model.parameter('d', f'{d} [mm]')
model.solve('static')
C = model.evaluate('2*es.intWe/U^2', 'pF')
results.put((d, C))
# 2. Setup data and queues
values = [0.5, 1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, 5.0]
jobs = multiprocessing.Queue()
for d in values:
jobs.put(d)
results = multiprocessing.Queue()
# 3. Start workers
processes = []
for _ in range(4):
process = multiprocessing.Process(target=worker, args=(jobs, results))
process.start()
processes.append(process)
# 4. Collect results
for _ in values:
(d, C) = results.get()
print(f"Distance: {d}, Capacitance: {C}")