Skip to content

Commit 96004a0

Browse files
authored
Merge pull request #178 from StochSS/tspan-fix
Timespan Fix
2 parents b755f28 + dd00c5a commit 96004a0

File tree

8 files changed

+50
-42
lines changed

8 files changed

+50
-42
lines changed

spatialpy/Model.py

Lines changed: 24 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ def __init__(self, name="spatialpy"):
9595

9696
######################
9797
self.tspan = None
98-
self.timestep_size = 1e-5
98+
self.timestep_size = None
9999
self.num_timesteps = None
100100
self.output_freq = None
101101

@@ -188,51 +188,50 @@ def __check_if_complete(self):
188188

189189
def set_timesteps(self, output_interval, num_steps, timestep_size=None):
190190
"""" Set the simlation time span parameters
191-
Args:
192-
:param output_interval: size of each output timestep in seconds
193-
:type output_interval: float
194-
:param num_steps: total number of steps to take. Note: the number of output times will be num_steps+1 as the first
195-
output will be at time zero.
196-
:type num_steps: int
197-
:param step_size: Size of each timestep in seconds
198-
:type step_size: float
199-
:param num_steps: Total number of steps to take
200-
:type num_steps: int
201-
191+
:param output_interval: size of each output timestep in seconds
192+
:type output_interval: float
193+
:param num_steps: total number of steps to take. Note: the number of output times will be num_steps+1 as the first
194+
output will be at time zero.
195+
:type num_steps: int
196+
:param timestep_size: Size of each timestep in seconds
197+
:type timestep_size: float
202198
"""
203199
if timestep_size is not None:
204200
self.timestep_size = timestep_size
205201
if self.timestep_size is None:
206-
raise ModelError("timestep_size is not set")
207-
208-
self.output_freq = math.ceil(output_interval/self.timestep_size)
202+
self.timestep_size = output_interval
203+
204+
self.output_freq = output_interval/self.timestep_size
205+
if self.output_freq < self.timestep_size:
206+
raise ModelError("Timestep size exceeds output frequency.")
209207

210208
self.num_timesteps = math.ceil(num_steps * self.output_freq)
211-
# array of step numbers corresponding to the simulation times in the timespan
212-
self.timespan_steps = numpy.linspace(0,self.num_timesteps,
213-
num=math.ceil(self.num_timesteps/self.output_freq)+1, dtype=int)
214-
215-
self.tspan = numpy.linspace(0,self.num_timesteps*self.timestep_size,self.num_timesteps)
216209

210+
# array of step numbers corresponding to the simulation times in the timespan
211+
output_steps = numpy.arange(0, self.num_timesteps + self.timestep_size, self.output_freq)
212+
self.output_steps = numpy.unique(numpy.round(output_steps).astype(int))
213+
sim_steps = numpy.arange(0, self.num_timesteps + self.timestep_size, self.timestep_size)
214+
self.tspan = numpy.zeros((self.output_steps.size), dtype=float)
215+
for i, step in enumerate(self.output_steps):
216+
self.tspan[i] = sim_steps[step]
217+
217218
def timespan(self, time_span, timestep_size=None):
218219
"""
219220
Set the time span of simulation. The SSA-SDPD engine does not support
220221
non-uniform timespans.
221222
222223
:param tspan: Evenly-spaced list of times at which to sample the species populations during the simulation.
223224
:type tspan: numpy.ndarray
225+
:param timestep_size: Size of each timestep in seconds
226+
:type timestep_size: float
224227
"""
225228

226-
self.tspan = time_span
227-
if timestep_size is not None:
228-
self.timestep_size = timestep_size
229-
230229
items_diff = numpy.diff(time_span)
231230
items = map(lambda x: round(x, 10), items_diff)
232231
isuniform = (len(set(items)) == 1)
233232

234233
if isuniform:
235-
self.set_timesteps( items_diff[0], len(items_diff) )
234+
self.set_timesteps(items_diff[0], len(items_diff), timestep_size=timestep_size)
236235
else:
237236
raise ModelError("Only uniform timespans are supported")
238237

spatialpy/Result.py

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -193,10 +193,7 @@ def read_step(self, step_num, debug=False):
193193

194194
if debug:
195195
print("read_step({0}) ".format(step_num), end='')
196-
#num = int(step_num * self.model.output_freq)
197-
#num = int(step_num / self.model.timestep_size)
198-
num = self.model.timespan_steps[step_num]
199-
filename = os.path.join(self.result_dir, "output{0}.vtk".format(num))
196+
filename = os.path.join(self.result_dir, "output{0}.vtk".format(step_num))
200197

201198
if debug:
202199
print("opening '{0}'".format(filename))
@@ -238,8 +235,7 @@ def get_timespan(self):
238235
239236
"""
240237

241-
self.tspan = numpy.linspace(0,self.model.num_timesteps,
242-
num=math.ceil(self.model.num_timesteps/self.model.output_freq)+1) * self.model.timestep_size
238+
self.tspan = self.model.tspan
243239
return self.tspan
244240

245241
def get_species(self, species, timepoints=None, concentration=False, deterministic=False, debug=False):
@@ -278,13 +274,9 @@ def get_species(self, species, timepoints=None, concentration=False, determinist
278274
if spec_name not in self.model.listOfSpecies.keys():
279275
raise ResultError("Species '{0}' not found".format(spec_name))
280276

281-
#t_index_arr = numpy.linspace(0,self.model.num_timesteps,
282-
# num=self.model.num_timesteps+1, dtype=int)
283-
#t_index_arr = numpy.linspace(0,self.model.num_timesteps,
284-
# num=math.ceil(self.model.num_timesteps/self.model.output_freq)+1)
285277
lt=len(self.get_timespan())-1
286278
t_index_arr = numpy.linspace(0,lt,num=lt+1,dtype=int)
287-
279+
288280
if timepoints is not None:
289281
if isinstance(timepoints,float):
290282
raise ResultError("timepoints argument must be an integer, the index of time timespan")
@@ -572,8 +564,9 @@ def get_property(self, property_name, timepoints=None):
572564
:rtype: numpy.ndarray
573565
"""
574566

575-
t_index_arr = numpy.linspace(0,self.model.num_timesteps,
576-
num=self.model.num_timesteps+1, dtype=int)
567+
lt=len(self.get_timespan())-1
568+
t_index_arr = numpy.linspace(0,lt,num=lt+1,dtype=int)
569+
577570
num_voxel = self.model.domain.get_num_voxels()
578571

579572
if timepoints is not None:

spatialpy/Solver.py

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,11 @@ def compile(self, debug=False, profile=False):
119119
:type profile: bool
120120
"""
121121

122+
if self.model.timestep_size is None:
123+
self.model.timestep_size = 1e-5
124+
if self.model.output_freq < self.model.timestep_size:
125+
raise ModelError("Timestep size exceeds output frequency.")
126+
122127
# Create the models expression utility
123128
self.model.get_expression_utility()
124129

@@ -580,7 +585,6 @@ def __create_propensity_file(self, file_name=None):
580585

581586
system_config += "system->dt = {0};\n".format(self.model.timestep_size)
582587
system_config += "system->nt = {0};\n".format(self.model.num_timesteps)
583-
system_config += "system->output_freq = {0};\n".format(self.model.output_freq)
584588
if self.h is None:
585589
self.h = self.model.domain.find_h()
586590
if self.h == 0.0:
@@ -625,6 +629,15 @@ def __create_propensity_file(self, file_name=None):
625629
init_bc += bc.expression()
626630
propfilestr = propfilestr.replace("__BOUNDARY_CONDITIONS__", init_bc)
627631

632+
output_step = "unsigned int get_next_output(ParticleSystem* system)\n{\n"
633+
output_step += "static int index = 0;\n"
634+
output_step += "const std::vector<unsigned int> output_steps = {"
635+
output_step += f"{', '.join(self.model.output_steps.astype(str).tolist())}"
636+
output_step += "};\nunsigned int next_step = output_steps[index];\n"
637+
output_step += "index++;\n"
638+
output_step += "return next_step;\n}\n"
639+
propfilestr = propfilestr.replace("__DEFINE_GET_NEXT_OUTPUT__", output_step)
640+
628641
#### Write the data to the file ####
629642
propfile.write(propfilestr)
630643
propfile.close()

spatialpy/ssa_sdpd-c-simulation-engine/include/particle_system.hpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,6 @@ namespace Spatialpy{
6161
double dt;
6262
unsigned int nt;
6363
unsigned int current_step;
64-
unsigned int output_freq;
6564
double xlo, xhi, ylo, yhi, zlo, zhi;
6665
double h;
6766
double c0;

spatialpy/ssa_sdpd-c-simulation-engine/include/propensities.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ namespace Spatialpy{
3636
/* Global variable that can be used to pass parameters to the propensity functions. */
3737
extern double *parameters;
3838

39+
unsigned int get_next_output(ParticleSystem* system);
3940
/* Definition of the propensity function. */
4041
// double rfun(const int *x, double t, const double vol, const double *data, int sd, int voxel, int *xx, const size_t *irK, const size_t *jcK, const double *prK)
4142
//typedef double (*PropensityFun)(const int *, double, double, const double *, int, int, int *, const size_t *, const size_t *, const double *);

spatialpy/ssa_sdpd-c-simulation-engine/propensity_file_template.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ namespace Spatialpy{
4141
__DEFINE_REACTIONS__
4242
/* Deterministic RHS definitions */
4343
__DEFINE_CHEM_FUNS__
44+
/* Definition for get next output step */
45+
__DEFINE_GET_NEXT_OUTPUT__
4446

4547
PropensityFun *ALLOC_propensities(void)
4648
{

spatialpy/ssa_sdpd-c-simulation-engine/src/output.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ namespace Spatialpy{
106106
int i;
107107
char filename[256];
108108
int np = output_buffer_current_num_particles;
109+
static unsigned int output_index = 0;
109110
if(output_buffer_current_step == 0){
110111
sprintf(filename, "output0_boundingBox.vtk");
111112
if(debug_flag){printf("Writing file '%s'\n", filename);}
@@ -125,7 +126,7 @@ namespace Spatialpy{
125126
fprintf(fp, "%lf %lf\n", system->zlo, system->zhi);
126127
fclose(fp);
127128
}
128-
sprintf(filename,"output%u.vtk",output_buffer_current_step);
129+
sprintf(filename,"output%u.vtk", output_index++);
129130
if(debug_flag){printf("Writing file '%s'\n", filename);}
130131
if((fp = fopen(filename,"w+"))==NULL){
131132
perror("Can't write output vtk file");exit(1);

spatialpy/ssa_sdpd-c-simulation-engine/src/simulate_threads.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,7 @@ namespace Spatialpy{
239239
// Release output thread
240240
if(debug_flag) printf("[%i] Starting the Output threads\n",system->current_step);
241241
pthread_barrier_wait(&begin_output_barrier);
242-
next_output_step += system->output_freq;
242+
next_output_step = get_next_output(system);
243243
// Wait until output threads are done
244244
pthread_barrier_wait(&end_output_barrier);
245245
if(debug_flag) printf("[%i] Output threads finished\n",system->current_step);

0 commit comments

Comments
 (0)