Hi everyone,
I’m developing several EDEM API plugins to study melting of DRI particles in an electric furnace. The model is EDEM-only (no CFD): buoyancy, drag, convection, conduction, shrinkage and removal are implemented via plugins.
Functionally the plugins work, but I hit a multi-threading problem:
- In single-thread runs everything is stable, but slow.
 - In multi-thread runs I can insert a handful of particles, but when I spawn a larger bed (e.g., 1000–5000 particles at t = 0 with a static factory) EDEM crashes. Also with less particle but longer simulations EDEM tends to crash.
 
From debugging, I believe two plugins are not MT-safe and result in a race condition. I’d really appreciate guidance how to make EDEM API plugins MT-safe. I am a novice C++ programmer so this is new for me. After some days of fiddling around I have not succeeded myself.  The plugins that give me trouble are:
1. CTemperatureUpdateV2:
I need each particle’s initial mass for my energy balance, but particles shrink, so I can’t reuse particle.mass. I currently cache the initial mass in a global unordered_map keyed by particle ID:
    
        
            
    
    
        
            
    
This works in single-thread mode but likely races in multi-thread mode when many particles are created/processed simultaneously and my EDEM crashes silently with the following crashdump.
    
        
            
    
I feel like the main issue is that I declare isThreadSafe but that the script is not multi-thread safe and therefore upon generation of many particles in the first time step immediately crashes. 
    
        
            
    
2. CSurfaceTrackingV2 
I have the same problem in this plugin I think. 
This plugin identifies surface particles of the feed pile so only those feel convection. A screenshot of how this looks is provided below. The script tags the outside particles.
    
        
            
    
To realise this, I discretize the domain into voxels (cells). This looks as follows:
    
        
            
    
 Each timestep I:
- compute each particle’s voxel location and add it to 
m_currentVoxelSet - compare 
m_currentVoxelSet to m_previousVoxelSet to find surface voxels/particles. (looking at empty neighbour cells) - swap/clear the sets for the next step
 
The relevant code:
    
        
            
    
    
        
            
    
    
        
            
    
    
        
            
    
    
        
            
    
Because externalForce() is run in parallel, the shared m_currentVoxelSet is written concurrently. That likely explains the crash when many particles are inserted/processed at the same time
Now, I am quite a novice programmer to C++ and I have never had to make anything MT-safe. Also, I can not find any API examples that uses similar logic to my plugins and is MT-safe. 
My question
Can anyone explain to me what it would take to preserve the logic of both plugins but make the scripts MT-safe for the usage in EDEM. 
- CTemperatureUpdateV2:
What is the correct, simple way to store each particle’s initial mass so it’s safe in multi-thread runs?
(Right now I use one global container and it crashes.)
Please show the small code change I should make. - CSurfaceTrackingV2:
I currently insert voxels into one shared set inside externalForce(int threadID, …) and swap/clear sets when time changes inside externalForce.What is the EDEM-2025 best way to do this MT-safe
Is the correct pattern:
1. in starting(..., numThreads): allocate per-thread voxel sets,
2. in externalForce(threadID, …): write only to threadID’s set,
3. in the single-threaded end-of-step callback (please confirm the exact name in EDEM 2025): merge per-thread sets, then swap/clear?
A 10–20 line sketch showing allocate → collect → merge/swap would be perfect. 
If someone can share a tiny code sketch (10–20 lines) for both cases, or give me some guidance on how to best preserve the logic of both plugins but make it MT-safe that would be perfect. Right now I dont know where to start after trying several things.
Kind regards,
Jan-Thijn Wijnker
The full code of both plugins: