/* * Reschedule a volume output item, if necessary. */ static int reschedule_volume_output_item(struct volume *wrld, struct volume_output_item *vo) { /* Find the next time */ if (vo->timer_type == OUTPUT_BY_STEP) vo->t += (vo->step_time / wrld->time_unit); else { double time_scale = 0.0; /* Check if we're done */ if (vo->next_time == vo->times + vo->num_times) { free(vo->filename_prefix); free(vo->molecules); free(vo->times); free(vo); return 0; } /* Compute the next time and advance the next_time ptr */ if (vo->timer_type == OUTPUT_BY_ITERATION_LIST) time_scale = 1.0; else time_scale = 1.0 / wrld->time_unit; vo->t = (*vo->next_time++) * time_scale; } switch (wrld->notify->volume_output_report) { case NOTIFY_NONE: case NOTIFY_BRIEF: break; case NOTIFY_FULL: mcell_log(" Next output scheduled for time %.15g.", vo->t * wrld->time_unit); break; default: UNHANDLED_CASE(wrld->notify->volume_output_report); } /* Add to the schedule */ if (schedule_add(wrld->volume_output_scheduler, vo)) mcell_allocfailed("Failed to add volume output request to scheduler."); return 0; }
/* * Output a block of volume data as requested by the 'vo' object. */ int update_volume_output(struct volume *wrld, struct volume_output_item *vo) { int failure = 0; char *filename; switch (wrld->notify->volume_output_report) { case NOTIFY_NONE: break; case NOTIFY_BRIEF: case NOTIFY_FULL: mcell_log("Updating volume output '%s' scheduled at time %.15g on " "iteration %lld.", vo->filename_prefix, vo->t, wrld->current_iterations); break; default: UNHANDLED_CASE(wrld->notify->volume_output_report); } /* build the filename */ filename = CHECKED_SPRINTF("%s.%lld.dat", vo->filename_prefix, wrld->current_iterations); /* Try to make the directory if it doesn't exist */ if (make_parent_dir(filename)) { free(filename); return 1; } /* Output the volume item */ failure = output_volume_output_item(wrld, filename, vo); free(filename); /* Reschedule this volume item, if appropriate */ if (!failure) failure = reschedule_volume_output_item(wrld, vo); /* Should we return failure if we can't create the file? Doing so will bring * down the entire sim... */ return failure; }
void iUniStream::SafeCast(T& c) { USBits mask(0, US_MASK_BIT_SIZE); *this >> mask; switch (mask.bits) { case US_MASK_UINT_8: { unsigned char cC = 0; Receive8(cC); c = (T)cC; } break; case US_MASK_SINT_8: { unsigned char cC = 0; Receive8(cC); signed char cSigned = reinterpret_cast<signed char&>(cC); c = (T)cSigned; } break; case US_MASK_UINT_16: { unsigned short cC = 0; Receive16(cC); c = (T)cC; } break; case US_MASK_SINT_16: { unsigned short cC = 0; Receive16(cC); signed short cSigned = reinterpret_cast<signed short&>(cC); c = (T)cSigned; } break; case US_MASK_UINT_32: { unsigned long cC = 0; Receive32(cC); c = (T)cC; } break; case US_MASK_SINT_32: { unsigned long cC = 0; Receive32(cC); signed long cSigned = reinterpret_cast<signed long&>(cC); c = (T)cSigned; } break; case US_MASK_UINT_64: { unsigned long long cC = 0; Receive64(cC); c = (T)cC; } break; case US_MASK_SINT_64: { unsigned long long cC = 0; Receive64(cC); signed long long cSigned = reinterpret_cast<signed long long&>(cC); c = (T)cSigned; } break; case US_MASK_CHAR_16: { unsigned short cC = 0; Receive16(cC); if (sizeof(char16_t) == 2) { usUint16_t tmp = (usUint16_t)(cC); char16_t ch = reinterpret_cast<char16_t&>(tmp); c = (T)ch; } else if(sizeof(char16_t) == 4) { usUint32_t tmp = (usUint32_t)(cC); char32_t ch = reinterpret_cast<char32_t&>(tmp); c = (T)ch; } else { UNHANDLED_CASE(); } } break; case US_MASK_CHAR_32: { unsigned long cC = 0; Receive32(cC); if(sizeof(char32_t) == 4) { usUint32_t tmp = (usUint32_t)(cC); char32_t ch = reinterpret_cast<char32_t&>(tmp); c = (T)ch; } else if (sizeof(char32_t) == 8) { usUint64_t tmp = (usUint64_t)(cC); char32_t ch = reinterpret_cast<char32_t&>(tmp); c = (T)ch; } else { UNHANDLED_CASE(); } } break; case US_MASK_FLOAT_32: { unsigned long cC = 0; CopyNum32(cC); if (sizeof(float) == 4) { usUint32_t tmp = (usUint32_t)(cC); float ch = reinterpret_cast<float&>(tmp); c = (T)ch; } else { UNHANDLED_CASE(); } } break; case US_MASK_DOUBLE_64: { unsigned long long cC = 0; CopyNum64(cC); if (sizeof(long long) == 8) { usUint64_t tmp = (usUint64_t)(cC); double ch = reinterpret_cast<double&>(tmp); c = (T)ch; } else { UNHANDLED_CASE(); } } break; case US_MASK_BOOL_1: { USBits boolMask(1, 1); GetStreamData(boolMask); bool val = (boolMask.bits == 1); c = (T)val; } break; default: UNHANDLED_CASE(); break; } }
/************************************************************************** check_reaction_output_file: Check that the reaction output file is writable within the policy set by the user. Creates and/or truncates the file to 0 bytes, as appropriate. Note that for SUBSTITUTE, the truncation is done later on, during initialization. In: parse_state: parser state os: output set containing file details Out: 0 if file preparation is successful, 1 if not. The file named will be created and emptied or truncated as requested. **************************************************************************/ int check_reaction_output_file(struct output_set *os) { FILE *f; char *name; struct stat fs; int i; name = os->outfile_name; if (make_parent_dir(name)) { // mdlerror_fmt(parse_state, // "Directory for %s does not exist and could not be // created.", // name); return 1; } switch (os->file_flags) { case FILE_OVERWRITE: f = fopen(name, "w"); if (!f) { switch (errno) { case EACCES: // mdlerror_fmt(parse_state, "Access to %s denied.", name); return 1; case ENOENT: // mdlerror_fmt(parse_state, "Directory for %s does not exist", // name); return 1; case EISDIR: // mdlerror_fmt(parse_state, "%s already exists and is a // directory", name); return 1; default: // mdlerror_fmt(parse_state, "Unable to open %s for writing", // name); return 1; } } fclose(f); break; case FILE_SUBSTITUTE: f = fopen(name, "a+"); if (!f) { switch (errno) { case EACCES: // mdlerror_fmt(parse_state, "Access to %s denied.", name); return 1; case ENOENT: // mdlerror_fmt(parse_state, "Directory for %s does not exist", // name); return 1; case EISDIR: // mdlerror_fmt(parse_state, "%s already exists and is a // directory", name); return 1; default: // mdlerror_fmt(parse_state, "Unable to open %s for writing", // name); return 1; } } i = fstat(fileno(f), &fs); if (!i && fs.st_size == 0) os->file_flags = FILE_OVERWRITE; fclose(f); break; case FILE_APPEND: case FILE_APPEND_HEADER: f = fopen(name, "a"); if (!f) { switch (errno) { case EACCES: // mdlerror_fmt(parse_state, "Access to %s denied.", name); return 1; case ENOENT: // mdlerror_fmt(parse_state, "Directory for %s does not exist", // name); return 1; case EISDIR: // mdlerror_fmt(parse_state, "%s already exists and is a // directory", name); return 1; default: // mdlerror_fmt(parse_state, "Unable to open %s for writing", // name); return 1; } } i = fstat(fileno(f), &fs); if (!i && fs.st_size == 0) os->file_flags = FILE_APPEND_HEADER; fclose(f); break; case FILE_CREATE: i = access(name, F_OK); if (!i) { i = stat(name, &fs); if (!i && fs.st_size > 0) { // mdlerror_fmt(parse_state, // "Cannot create new file %s: it already exists", // name); return 1; } } f = fopen(name, "w"); if (f == NULL) { switch (errno) { case EEXIST: // mdlerror_fmt(parse_state, "Cannot create %s because it already // exists", // name); return 1; case EACCES: // mdlerror_fmt(parse_state, "Access to %s denied.", name); return 1; case ENOENT: // mdlerror_fmt(parse_state, "Directory for %s does not exist", // name); return 1; case EISDIR: // mdlerror_fmt(parse_state, "%s already exists and is a // directory", name); return 1; default: // mdlerror_fmt(parse_state, "Unable to open %s for writing", // name); return 1; } } fclose(f); break; default: UNHANDLED_CASE(os->file_flags); } return 0; }
/************************************************************************** update_reaction_output: In: the output_block we want to update Out: 0 on success, 1 on failure. The counters in this block are updated, and the block is rescheduled for the next output time. The counters are saved to an internal buffer, and written out when full. **************************************************************************/ int update_reaction_output(struct volume *world, struct output_block *block) { int report_as_non_trigger = 1; int i = block->buf_index; if (block->data_set_head != NULL && block->data_set_head->column_head != NULL && block->data_set_head->column_head->buffer[i].data_type == COUNT_TRIG_STRUCT) report_as_non_trigger = 0; if (report_as_non_trigger) { switch (world->notify->reaction_output_report) { case NOTIFY_NONE: break; case NOTIFY_BRIEF: mcell_log( "Updating reaction output scheduled at time %.15g on iteration %lld.", block->t, world->current_iterations); break; case NOTIFY_FULL: mcell_log("Updating reaction output scheduled at time %.15g on iteration" " %lld.\n Buffer fill level is at %u/%u.", block->t, world->current_iterations, block->buf_index, block->buffersize); break; default: UNHANDLED_CASE(world->notify->reaction_output_report); } } /* update all counters */ block->t /= (1. + EPS_C); if (world->chkpt_seq_num == 1) { if (block->timer_type == OUTPUT_BY_ITERATION_LIST) block->time_array[i] = block->t; else block->time_array[i] = block->t * world->time_unit; } else { if (block->timer_type == OUTPUT_BY_ITERATION_LIST) { block->time_array[i] = block->t; } else if (block->timer_type == OUTPUT_BY_TIME_LIST) { if (block->time_now == NULL) { return 0; } else { block->time_array[i] = block->time_now->value; } } else { /* OUTPUT_BY_STEP */ block->time_array[i] = convert_iterations_to_seconds( world->start_iterations, world->time_unit, world->simulation_start_seconds, block->t); } } struct output_set *set; struct output_column *column; // Each file for (set = block->data_set_head; set != NULL; set = set->next) { if (report_as_non_trigger) { if (world->notify->reaction_output_report == NOTIFY_FULL) mcell_log(" Processing reaction output file '%s'.", set->outfile_name); } // Each column for (column = set->column_head; column != NULL; column = column->next) { if (column->buffer[i].data_type != COUNT_TRIG_STRUCT) { eval_oexpr_tree(column->expr, 1); switch (column->buffer[i].data_type) { case COUNT_INT: column->buffer[i].val.ival = (int)column->expr->value; break; case COUNT_DBL: column->buffer[i].val.dval = (double)column->expr->value; break; case COUNT_UNSET: column->buffer[i].val.cval = 'X'; break; case COUNT_TRIG_STRUCT: default: UNHANDLED_CASE(column->buffer[i].data_type); } } } } block->buf_index++; int final_chunk_flag = 0; // flag signaling an end to the scheduled // reaction outputs. Takes values {0,1}. // 0 - end not reached yet, // 1 - end reached. /* Pick time of next output, if any */ if (block->timer_type == OUTPUT_BY_STEP) block->t += block->step_time / world->time_unit; else if (block->time_now != NULL) { block->time_now = block->time_now->next; if (block->time_now == NULL) final_chunk_flag = 1; else { if (block->timer_type == OUTPUT_BY_ITERATION_LIST) block->t = block->time_now->value; else { /* OUTPUT_BY_TIME_LIST */ if (world->chkpt_seq_num == 1) { block->t = block->time_now->value / world->time_unit; } else { block->t = world->start_iterations + (block->time_now->value - world->simulation_start_seconds) / world->time_unit; } } } } else final_chunk_flag = 1; /* Schedule next output event--even if we're at the end, since triggers may * not yet be written */ double actual_t; if (final_chunk_flag == 1) { actual_t = block->t; block->t = FOREVER; } else actual_t = -1; block->t *= (1. + EPS_C); if (schedule_add(world->count_scheduler, block)) { mcell_allocfailed_nodie("Failed to add count to scheduler."); return 1; } if (distinguishable(actual_t, -1, EPS_C)) block->t = actual_t; /* Fix time for output */ if (report_as_non_trigger && world->notify->reaction_output_report == NOTIFY_FULL) { mcell_log(" Next output for this block scheduled at time %.15g.", block->t); } if (block->t >= world->iterations + 1) final_chunk_flag = 1; /* write data to outfile */ if (block->buf_index == block->buffersize || final_chunk_flag) { for (set = block->data_set_head; set != NULL; set = set->next) { if (set->column_head->buffer[i].data_type == COUNT_TRIG_STRUCT) continue; if (write_reaction_output(world, set)) { mcell_error_nodie("Failed to write reaction output to file '%s'.", set->outfile_name); return 1; } } block->buf_index = 0; no_printf("Done updating reaction output\n"); } if (distinguishable(actual_t, -1, EPS_C)) block->t = FOREVER; /* Back to infinity if we're done */ return 0; }