29 #include <boost/random.hpp>
30 #include <core/common/exceptions/WPreconditionNotMet.h>
32 #include "WTuringPatternCreator.h"
35 : m_numThreads( numThreads ),
36 m_numIterations( 100 ),
37 m_spotIrregularity( 0.1 ),
39 m_progress( progress )
41 WPrecond( numThreads > 0,
"" );
50 WPrecond( iter > 0,
"Invalid number of iterations!" );
57 WPrecond( irr >= 0.0f && irr <= 1.0f,
"Spot irregularity must be in [0,1]!" );
64 WPrecond( size >= 0.0f && size <= 1.0f,
"Spot size must be in [0,1]!" );
72 float const spotFactor = ( 0.02f + 0.58f * ( 1.0f -
m_spotSize ) ) / 15.0f;
73 float const d1 = 0.125f;
74 float const d2 = 0.03125f;
75 float const speed = 1.0f;
77 std::shared_ptr< std::vector< float > > concentration1(
new std::vector< float >( sizeX * sizeY * sizeZ, 4.0f ) );
78 std::vector< float > concentration2( sizeX * sizeY * sizeZ, 4.0f );
79 std::vector< float > delta1( sizeX * sizeY * sizeZ, 0.0f );
80 std::vector< float > delta2( sizeX * sizeY * sizeZ, 0.0f );
81 std::vector< float > noise( sizeX * sizeY * sizeZ );
83 boost::mt19937 generator( std::time( 0 ) );
87 boost::uniform_real< float > dist( 12.0f - noiseRange, 12.0f + noiseRange );
88 boost::variate_generator< boost::mt19937&, boost::uniform_real< float > > rand( generator, dist );
91 for( std::size_t k = 0; k < sizeX * sizeY * sizeZ; ++k )
97 std::shared_ptr< WConditionSet > continueCondition(
new WConditionSet() );
98 continueCondition->setResetable(
true,
true );
101 std::shared_ptr< WConditionSet > waitCondition(
new WConditionSet() );
102 continueCondition->setResetable(
true,
true );
107 std::vector< std::shared_ptr< PatternThread > > threads;
111 threads.push_back( std::shared_ptr< PatternThread >(
new PatternThread( k,
m_numThreads, continueCondition, waitCondition, &counter ) ) );
112 threads[ k ]->setDomainSize( sizeX, sizeY, sizeZ );
113 threads[ k ]->setSpotFactor( spotFactor );
114 threads[ k ]->setDiffusionConstants( d1, d2 );
115 threads[ k ]->setBufferPointers( concentration1.get(), &concentration2, &noise, &delta1, &delta2 );
120 boost::this_thread::sleep( boost::posix_time::seconds( 1 ) );
124 std::size_t currentStep = 0;
130 waitCondition->notify();
131 continueCondition->wait();
134 for( std::size_t k = 0; k < sizeX * sizeY * sizeZ; ++k )
136 ( *concentration1 )[ k ] += speed * delta1[ k ];
137 concentration2[ k ] += speed * delta2[ k ];
141 std::size_t newStep =
static_cast< std::size_t
>( iter * stepsPerIteration ) + 1;
142 m_progress->increment( newStep - currentStep );
143 currentStep = newStep;
148 threads[ k ]->finish();
150 waitCondition->notify();
153 boost::this_thread::sleep( boost::posix_time::seconds( 1 ) );
155 return concentration1;
159 std::shared_ptr< WCondition >
const mainThreadContinueCondition,
160 std::shared_ptr< WCondition >
const waitForMainThreadCondition,
169 m_diffusionConstant1( 0.5 ),
170 m_diffusionConstant2( 0.5 ),
171 m_mainThreadContinueCondition( mainThreadContinueCondition ),
172 m_waitForMainThreadCondition( waitForMainThreadCondition ),
173 m_counter( counter ),
184 WPrecond( d1 >= 0.0 && d1 <= 1.0,
"" );
185 WPrecond( d2 >= 0.0 && d2 <= 1.0,
"" );
187 m_diffusionConstant1 = d1;
188 m_diffusionConstant2 = d2;
193 WPrecond( spotFactor > 0.0,
"" );
195 m_spotFactor = spotFactor;
200 WPrecond( sizeX > 0,
"" );
201 WPrecond( sizeY > 0,
"" );
202 WPrecond( sizeZ > 0,
"" );
211 WPrecond( m_concentration1 != 0,
"Invalid pointer!" );
212 WPrecond( m_concentration2 != 0,
"Invalid pointer!" );
213 WPrecond( m_noise != 0,
"Invalid pointer!" );
214 WPrecond( m_delta1 != 0,
"Invalid pointer!" );
215 WPrecond( m_delta2 != 0,
"Invalid pointer!" );
217 std::size_t
const numVoxels = m_sizeX * m_sizeY * m_sizeZ;
220 std::size_t start = m_id * ( numVoxels / m_maxThreads );
221 std::size_t end = ( m_id + 1 ) * ( numVoxels / m_maxThreads );
224 if( m_id == m_maxThreads - 1 )
232 m_waitForMainThreadCondition->wait();
238 for( std::size_t idx = start; idx < end; ++idx )
240 std::size_t i = idx % m_sizeX;
241 std::size_t j = ( idx / m_sizeX ) % m_sizeY;
242 std::size_t k = ( idx / m_sizeX ) / m_sizeY;
244 std::size_t iNext = ( i + 1 ) % m_sizeX;
245 std::size_t iPrev = ( i + m_sizeX - 1 ) % m_sizeX;
247 std::size_t jNext = ( j + 1 ) % m_sizeY;
248 std::size_t jPrev = ( j + m_sizeY - 1 ) % m_sizeY;
250 std::size_t kNext = ( k + 1 ) % m_sizeZ;
251 std::size_t kPrev = ( k + m_sizeZ - 1 ) % m_sizeZ;
255 dc1 += ( *m_concentration1 )[ iPrev + j * m_sizeX + k * m_sizeX * m_sizeY ];
256 dc1 += ( *m_concentration1 )[ iNext + j * m_sizeX + k * m_sizeX * m_sizeY ];
257 dc1 += ( *m_concentration1 )[ i + jPrev * m_sizeX + k * m_sizeX * m_sizeY ];
258 dc1 += ( *m_concentration1 )[ i + jNext * m_sizeX + k * m_sizeX * m_sizeY ];
259 dc1 += ( *m_concentration1 )[ i + j * m_sizeX + kPrev * m_sizeX * m_sizeY ];
260 dc1 += ( *m_concentration1 )[ i + j * m_sizeX + kNext * m_sizeX * m_sizeY ];
261 dc1 -= 6.0f * ( *m_concentration1 )[ idx ];
264 dc2 += ( *m_concentration2 )[ iPrev + j * m_sizeX + k * m_sizeX * m_sizeY ];
265 dc2 += ( *m_concentration2 )[ iNext + j * m_sizeX + k * m_sizeX * m_sizeY ];
266 dc2 += ( *m_concentration2 )[ i + jPrev * m_sizeX + k * m_sizeX * m_sizeY ];
267 dc2 += ( *m_concentration2 )[ i + jNext * m_sizeX + k * m_sizeX * m_sizeY ];
268 dc2 += ( *m_concentration2 )[ i + j * m_sizeX + kPrev * m_sizeX * m_sizeY ];
269 dc2 += ( *m_concentration2 )[ i + j * m_sizeX + kNext * m_sizeX * m_sizeY ];
270 dc2 -= 6.0f * ( *m_concentration2 )[ idx ];
273 ( *m_delta1 )[ idx ] = m_spotFactor * ( 16.0f - ( *m_concentration1 )[ idx ] * ( *m_concentration2 )[ idx ] )
274 + m_diffusionConstant1 * dc1;
275 ( *m_delta2 )[ idx ] = m_spotFactor * ( ( *m_concentration1 )[ idx ] * ( *m_concentration2 )[ idx ]
276 - ( *m_concentration2 )[ idx ] - ( *m_noise )[ idx ] ) + m_diffusionConstant2 * dc2;
281 if(
static_cast< std::size_t
>( ++( *m_counter ) ) == m_maxThreads )
283 m_mainThreadContinueCondition->notify();
290 std::vector< float >
const* noise, std::vector< float >* delta1,
291 std::vector< float >* delta2 )
293 WPrecond( concentration1 != 0,
"Invalid pointer!" );
294 WPrecond( concentration2 != 0,
"Invalid pointer!" );
295 WPrecond( noise != 0,
"Invalid pointer!" );
296 WPrecond( delta1 != 0,
"Invalid pointer!" );
297 WPrecond( delta2 != 0,
"Invalid pointer!" );
299 m_concentration1 = concentration1;
300 m_concentration2 = concentration2;
Class allowing multiple conditions to be used for one waiting cycle.
This is a simple but thread-safe counter.
Base class for all classes needing to be executed in a separate thread.
A thread calculating the reaction for a certain part of the domain.
void setDomainSize(std::size_t sizeX, std::size_t sizeY, std::size_t sizeZ)
Set the domain size.
void setDiffusionConstants(float d1, float d2)
Set the diffusion constants.
PatternThread(std::size_t id, std::size_t max, std::shared_ptr< WCondition > const mainThreadContinueCondition, std::shared_ptr< WCondition > const waitForMainThreadCondition, WCounter *const counter)
Constructor.
void setBufferPointers(std::vector< float > const *concentration1, std::vector< float > const *concentration2, std::vector< float > const *noise, std::vector< float > *delta1, std::vector< float > *delta2)
Set the pointers to the buffer all threads share.
void setSpotFactor(float spotFactor)
Set the spot factor.
void finish()
Tells the thread to finish.
virtual void threadMain()
The entry point for the thread.
~PatternThread()
Destructor.
std::shared_ptr< std::vector< float > > create(std::size_t sizeX, std::size_t sizeY, std::size_t sizeZ)
Creates the 3D pattern and writes it into a vector of floats.
void setSpotIrregularity(float irr)
Sets the spot irregularity parameter.
float m_spotSize
The spot size parameter.
void setSpotSize(float size)
Sets the spotsize parameter.
float m_spotIrregularity
The spot irregularity parameter.
~WTuringPatternCreator()
Destructor.
void setNumIterations(std::size_t iter)
Sets the number of iterations for the chemical simulation that creates the pattern.
WTuringPatternCreator(std::shared_ptr< WProgress > const progress, std::size_t numThreads=boost::thread::hardware_concurrency())
Constructor.
float m_numIterations
The number of iterations for the simulation.
std::size_t m_numThreads
The number of threads to use.
std::shared_ptr< WProgress > m_progress
The progress to increment.