Пример #1
0
/*
 * 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;
}
Пример #2
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;
}
Пример #3
0
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;
    }
}
Пример #4
0
/**************************************************************************
 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;
}
Пример #5
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;
}