
function rxn_grp = runsim(cmpd_info, plot_info, run_info, dir_info, rxn_grp, run_id)

output_filename = dir_info.output_filename;
output_dir = dir_info.output_dir;

num_cmpds = cmpd_info.num_cmpds;
comp_name = cmpd_info.cmpd_name;
orig_cmpd_vals = cmpd_info.orig_cmpd_vals;

monitor_cmpds = plot_info.monitor_cmpds;
plot_cmpds = plot_info.plot_cmpds;
monitor_cmpds_gid = plot_info.monitor_cmpds_gid;
plot_organize = plot_info.organize;
eventlog_flag = plot_info.eventlog_flag;
eventlog_maxelements = plot_info.eventlog_maxelements;
eventlog_arraysize = plot_info.eventlog_arraysize;
snapshot_interval = plot_info.snapshot_interval;
plot_interval = plot_info.plot_interval;
mpi_save_param = plot_info.mpi_save_param;

volume = run_info.volume;
monitor_interval = run_info.monitor_interval;
time_start = run_info.time_start;
time_end = run_info.time_end;
num_runs = run_info.num_runs;
stoch_algor = run_info.stoch_algor;
randseed = run_info.randseed;
use_randseed = run_info.use_randseed;
param_sets = run_info.param_sets;

snap_file = fullfile(output_dir, [output_filename '_data_' num2str(run_id)]);
fid_snap = fopen(snap_file,'wt');
if (fid_snap == -1)
      errordlg('Cannot open output file','Open File Error!')
    return
end

global_time = time_start;
if monitor_interval < (time_end - time_start)
    if monitor_interval < snapshot_interval
        monitor_interval = snapshot_interval;
        timestep = snapshot_interval;
    else
        n_snap = floor(monitor_interval/snapshot_interval);
        timestep = n_snap * snapshot_interval;
    end
else
    timestep = time_end - time_start;
end
timestep_max = monitor_interval;

cmpd_vals = orig_cmpd_vals;

data_time = [];
data_cmpds = [];
perm_event_log = [];
agr_event_log = []; 
datafile_num = 0;
ev_log_num = 0;
timestep_iteration = 0;

num_grps = length(rxn_grp);

for i = 1:num_grps
    [rxn_grp{i}, ssdata, aglog] = init_rxn_grp(rxn_grp{i}, global_time, cmpd_info, run_info, eventlog_arraysize, snapshot_interval, use_randseed);
end

if ~isempty(ssdata)
    data_time = [data_time; ssdata(:,1)];
    data_cmpds = [data_cmpds; ssdata(:,2:end)];
end
if ~isempty(aglog)
    agr_event_log = [agr_event_log; aglog(:,1:end)];
end

time_multiple = 0;
[make_plot_now,time_multiple] = decide_if_make_plots(plot_interval, global_time, time_multiple);
if make_plot_now
    make_plots(data_time, data_cmpds, 0, 0, plot_organize);
end

while global_time < time_end
    
    good_timestep = 0;
    
    timestep_iteration = timestep_iteration + 1;
%    data_row = data_row + 1;

    while ~good_timestep
        
        prev_timestep = timestep;
        
        %official numbers stored into local reaction groups
        for i = 1:num_grps
            rxn_grp{i} = assign_official_data_to_reaction_group(rxn_grp{i}, cmpd_vals, stoch_algor);   
        end

        % the key loop
        for i = 1:num_grps
            [rxn_grp{i}, times_rxns_executed{i}, temp_event_log{i}, ssdata, aglog] = coordinate_erg(rxn_grp{i},global_time,timestep, run_info, 0, eventlog_arraysize, snapshot_interval);
        end
  
%        collect proposed new compound numbers
        for i = 1:num_grps
            cmpd_vals = tally_changes_in_cmpd_numbers(rxn_grp{i}.global_comp_gid, rxn_grp{i}.cmpd_nums, cmpd_vals);
        end
        
        [good_timestep, timestep, cmpd_vals] = check_last_timestep(num_cmpds, cmpd_vals, timestep, timestep_max, num_grps);
        
    end
    
    % was a good timestep, so...
    % make putative numbers official
    
    cmpd_vals = make_compound_numbers_official(num_cmpds, cmpd_vals);
    

    global_time = global_time + prev_timestep;
    if (global_time + timestep) > time_end
        timestep = time_end - global_time;
    end

    % need values of compound numbers at monitor intervals, in case not all
    % events were logged (due to insufficient memory)
%    mon_cnums(timestep_iteration).vals = cmpd_vals(:,1);
%    mon_cnums(timestep_iteration).time = global_time;
 
    for i = 1:num_grps
        
        if num_grps ~= 1

        %       recalculate reaction probabilities and times since they may have changed due to tally_changes.
            [rxn_grp{i}, tmp1, tmp2, tmp3, tmp4] = coordinate_erg(rxn_grp{i},global_time,timestep, run_info, 1, eventlog_arraysize, snapshot_interval);
            
        end
        
        rxn_grp{i} = save_rxngrp_data(rxn_grp{i}, times_rxns_executed{i}, stoch_algor);

        if eventlog_flag == 1
            if ~isempty(temp_event_log{i})
                if num_grps ~= 1
                    temp_event_log{i}(:,3) = i;
                end
                perm_event_log = [perm_event_log; temp_event_log{i}];
            end
        end
            agr_event_log = [agr_event_log; aglog(:,1:end)];    
    end

% collect the snapshot data
    if ~isempty(ssdata)
        data_time = [data_time; ssdata(:,1)];
        data_cmpds = [data_cmpds; ssdata(:,2:end)];
    end
	
    [make_plot_now,time_multiple] = decide_if_make_plots(plot_interval, global_time, time_multiple);
	if make_plot_now
        make_plots(data_time, data_cmpds, 0, 0, plot_organize);
    end


% monitor size of snapshot data file
    if  (length(data_time) * length(monitor_cmpds_gid))> eventlog_maxelements
        warning('Size of snapshot data file has become too large.  Oldest half of snapshot data will now be deleted.  Increase eventlog_maxelements in storing_and_plotting.m to store more.')
        num_half = floor(length(data_time)/2);
        data_time = data_time(num_half:end);
        data_cmpds = data_cmpds(num_half:end,:);
    end

% monitor size of eventlog data file, and save a chunk to disk if it's too big
    if mpi_save_param == 0 | mpi_save_param == 1
        if size(perm_event_log,1) >= eventlog_maxelements
            ev_log_num = ev_log_num + 1;
            save_logdata(output_dir, output_filename, 'eventlog', run_id, ev_log_num, perm_event_log);
            perm_event_log = [];
        end
    end

    
end
core_time = toc;

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% save to disk section
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

if mpi_save_param == 0 | mpi_save_param == 1    % until we figure it out, only let single processor and master processor save to disk

% save snapshot data to disk
%       save_mat(output_dir, output_filename, 'data', run_id, 0, data_time, 'data_time', data_cmpds, 'data_cmpds');
        save_snapshot(fid_snap, run_id, data_time, data_cmpds, agr_event_log); 
        data_cmpds = [];
        mon_cnums = [];
        agr_event_log = []; 
        data_time = [];
% Else save latest eventlog data to disk
    if ~isempty(perm_event_log)
        ev_log_num = ev_log_num + 1;
        save_logdata(output_dir, output_filename, 'eventlog', run_id, ev_log_num, perm_event_log);
        perm_event_log = [];
    end

end
    fclose(fid_snap);

