Ejemplo n.º 1
0
/*************************************************************************
 mcell_generate_range:
    Generate a num_expr_list containing the numeric values from start to end,
    incrementing by step.

 In:  state: the simulation state
      list:  destination to receive list of values
      start: start of range
      end:   end of range
      step:  increment
 Out: 0 on success, 1 on failure.  On success, list is filled in.
*************************************************************************/
MCELL_STATUS mcell_generate_range(struct num_expr_list_head *list, double start,
                                  double end, double step) {
  list->value_head = NULL;
  list->value_tail = NULL;
  list->value_count = 0;
  list->shared = 0;

  if (step > 0) {
    /* JW 2008-03-31: In the guard on the loop below, it seems to me that
     * the third condition is redundant with the second.
     */
    for (double tmp_dbl = start;
         tmp_dbl < end || !distinguishable(tmp_dbl, end, EPS_C) ||
             fabs(end - tmp_dbl) <= EPS_C;
         tmp_dbl += step) {
      if (advance_range(list, tmp_dbl))
        return MCELL_FAIL;
    }
  } else /* if (step < 0) */
  {
    /* JW 2008-03-31: In the guard on the loop below, it seems to me that
     * the third condition is redundant with the second.
     */
    for (double tmp_dbl = start;
         tmp_dbl > end || !distinguishable(tmp_dbl, end, EPS_C) ||
             fabs(end - tmp_dbl) <= EPS_C;
         tmp_dbl += step) {
      if (advance_range(list, tmp_dbl))
        return MCELL_FAIL;
    }
  }
  return MCELL_SUCCESS;
}
Ejemplo n.º 2
0
/*************************************************************************
timeof_unimolecular:
  In: the reaction we're testing
  Out: double containing the number of timesteps until the reaction occurs
*************************************************************************/
double timeof_unimolecular(struct rxn *rx, struct abstract_molecule *a,
                           struct rng_state *rng) {
  double k_tot = rx->max_fixed_p;
  double p = rng_dbl(rng);

  if ((k_tot <= 0) || (!distinguishable(p, 0, EPS_C)))
    return FOREVER;
  return -log(p) / k_tot;
}
Ejemplo n.º 3
0
/*************************************************************************
eval_oexpr_tree:
   In: root of an output_expression tree
       flag indicating whether to recalculate values marked CONST
   Out: no return value.  The value member variable of each
        output_expression in the tree is updated to be accurate given
        current leaf values.
*************************************************************************/
void eval_oexpr_tree(struct output_expression *root, int skip_const) {
  double lval = 0.0;
  double rval = 0.0;

  if ((root->expr_flags & OEXPR_TYPE_CONST) && skip_const)
    return;
  if (root->left != NULL) {
    if ((root->expr_flags & OEXPR_LEFT_MASK) == OEXPR_LEFT_INT)
      lval = (double)*((int *)root->left);
    else if ((root->expr_flags & OEXPR_LEFT_MASK) == OEXPR_LEFT_DBL)
      lval = *((double *)root->left);
    else if ((root->expr_flags & OEXPR_LEFT_MASK) == OEXPR_LEFT_OEXPR) {
      eval_oexpr_tree((struct output_expression *)root->left, skip_const);
      lval = ((struct output_expression *)root->left)->value;
    }
  }
  if (root->right != NULL) {
    if ((root->expr_flags & OEXPR_RIGHT_MASK) == OEXPR_RIGHT_INT)
      rval = (double)*((int *)root->right);
    else if ((root->expr_flags & OEXPR_RIGHT_MASK) == OEXPR_RIGHT_DBL)
      rval = *((double *)root->right);
    else if ((root->expr_flags & OEXPR_RIGHT_MASK) == OEXPR_RIGHT_OEXPR) {
      eval_oexpr_tree((struct output_expression *)root->right, skip_const);
      rval = ((struct output_expression *)root->right)->value;
    }
  }
  switch (root->oper) {
  case '=':
    break;
  case '(':
  case '#':
  case '@':
    if (root->right != NULL)
      root->value = lval + rval;
    else
      root->value = lval;
    break;
  case '_':
    root->value = -lval;
    break;
  case '+':
    root->value = lval + rval;
    break;
  case '-':
    root->value = lval - rval;
    break;
  case '*':
    root->value = lval * rval;
    break;
  case '/':
    root->value = (!distinguishable(rval, 0, EPS_C)) ? 0 : lval / rval;
    break;
  default:
    break;
  }
}
Ejemplo n.º 4
0
/*************************************************************************
timeof_unimolecular:
  In: the reaction we're testing
  Out: double containing the number of timesteps until the reaction occurs
*************************************************************************/
double timeof_unimolecular(struct rxn *rx, struct abstract_molecule *a,
                           struct rng_state *rng) {
  double k_tot = rx->max_fixed_p;
  if (rx->rates) {
    for (int path_idx = rx->n_pathways; path_idx-- != 0;) {
      if (!rx->rates[path_idx])
        break;

      k_tot += macro_lookup_rate(rx->rates[path_idx], a, rx->pb_factor);
    }
  }

  double p = rng_dbl(rng);

  if ((k_tot <= 0) || (!distinguishable(p, 0, EPS_C)))
    return FOREVER;
  return -log(p) / k_tot;
}
Ejemplo n.º 5
0
void totypesRec(node e) {
     int i, j;
     /* 
	e is a list of TYPEs to be defined recursively

        The recursion is handled through the type fields of the symbols
	involved, which are assumed to be already set, or through TYPEs.
	TYPEs have no POSITIONs in them.
	Any type which turns out to be equivalent to a prior one has the
	address of the prior one inserted into its value field.
     	We assume that the value fields have been run through ExpandType,
	so that each value field is an expression constructed from other
	TYPEs.

	This routine probably has bugs, with the result that the order of
	declarations makes a difference.

        */
     numnewtypes = length(e);
     newtypeslist = newarray(node,numnewtypes);
     ttable = newarray(struct DISTIN *, numnewtypes);
     /* we could perform some hashing first */
     for (i=0; i<numnewtypes; i++) {
	  node t = nth(e,i+1);
	  assert(istype(t));
	  newtypeslist[i] = t;
	  assert(t->tag == type_tag);
	  assert(!(t->body.type.flags & deferred_F));
	  t->body.type.seqno = i + numtypes;
	  ttable[i] = newarray(struct DISTIN,numtypes+numnewtypes);
	  for (j=0; j<numtypes+numnewtypes; j++) {
	       ttable[i][j].listp = NULL;
	       ttable[i][j].distinguishable = FALSE;
	       }
	  }
     for (i=numtypes; i<numnewtypes+numtypes; i++) {
	  for (j=0; j<i; j++) {
	       struct DISTIN *dd = table(i,j);
	       node t = thetype(i), u = thetype(j), tval, uval, th, uh;
	       assertpos(istype(t),t);
	       assertpos(istype(u),u);
	       if ((t->body.type.flags & basic_type_F) || (u->body.type.flags & basic_type_F)) {
		    assert(t != u);
		    differ: mark(i,j);
		    continue;
		    }
	       tval = t -> body.type.definition;
	       uval = u -> body.type.definition;
	       assertpos(tval != NULL,t);
	       assertpos(uval != NULL,u);
	       if (equal(tval,uval)) continue;
	       assertpos(iscons(tval),t);
	       assertpos(iscons(uval),u);
	       assert(! dd->distinguishable );
	       th = car(tval);
	       uh = car(uval);
	       tval = cdr(tval);
	       uval = cdr(uval);
	       if (th != uh) goto differ;
	       if (th == or_K) {
		    for (;tval != NULL && uval != NULL;
			 tval = cdr(tval), uval = cdr(uval)) {
			 node ti = typeforward(car(tval));
			 node tj = typeforward(car(uval));
			 int ii = typeseqno(ti);
			 int jj = typeseqno(tj);
			 if (ti == tj) continue;
			 if (ii == -1 || jj == -1) goto differ;	/* not defined yet... */
			 if (distinguishable(ii,jj)) goto differ;
			 appendlt(ii,jj,i,j);			 
			 }
		    if (tval != NULL || uval != NULL) goto differ;
		    }
	       else if (th == object__K || th == tagged_object_K) {
		    for (;tval != NULL && uval != NULL;
			 tval = cdr(tval), uval = cdr(uval)) {
			 node tmem = car(tval);
			 node umem = car(uval);
			 int ii, jj;
			 node tt, uu;
			 if (car(tmem) != car(umem)) goto differ;
			 ii = typeseqno(tt=typeforward(cadr(tmem)));
			 jj = typeseqno(uu=typeforward(cadr(umem)));
			 if (tt==uu) continue;
			 if (ii == -1 || jj == -1) goto differ;	/* not defined yet... */
			 if (distinguishable(ii,jj)) goto differ;
			 appendlt(ii,jj,i,j);
			 }
		    if (tval != NULL || uval != NULL) goto differ;
		    }
	       else if (th == array_K || th == tarray_K) {
		    node tt,uu;
		    int ii = typeseqno(tt=typeforward(car(tval)));
		    int jj = typeseqno(uu=typeforward(car(uval)));
		    if (tt!=uu) {
		    	 if (ii == -1 || jj == -1) goto differ;	/* not defined yet... */
		    	 else if (distinguishable(ii,jj)) goto differ;
		    	 else if (!equal(cdr(tval),cdr(uval))) goto differ;
		    	 else appendlt(ii,jj,i,j);
			 }
		    else {
		         if (!equal(cdr(tval),cdr(uval))) goto differ;
		         }
		    }
	       else if (th == function_S) {
		    node ttt,uuu;
		    node targs = car(tval);
		    node uargs = car(uval);
		    int iii = typeseqno(ttt=typeforward(cadr(tval)));
		    int jjj = typeseqno(uuu=typeforward(cadr(uval)));
		    if (ttt!=uuu) {
		    	 if (iii == -1 || jjj == -1) goto differ;	/* not defined yet... */
		    	 if (distinguishable(iii,jjj)) goto differ;
			 }
		    for (;targs != NULL && uargs != NULL;
			 targs = cdr(targs), uargs = cdr(uargs)) {
			 node tt,uu;
			 int ii = typeseqno(tt=typeforward(car(targs)));
			 int jj = typeseqno(uu=typeforward(car(uargs)));
			 if (tt==uu) continue;
		    	 if (ii == -1 || jj == -1) goto differ;	/* not defined yet... */
			 if (distinguishable(ii,jj)) goto differ;
			 }
		    if (targs != NULL || uargs != NULL) goto differ;
		    }
	       else {
		    assert(FALSE); return;
		    }
	       }
	  }
     for (i=0; i<numnewtypes; i++) {
	  for (j=0;j<i+numtypes;j++) {
	       if (!distinguishable(i+numtypes,j)) {
		    /* indistinguishable types are identified here */
		    node t = newtypeslist[i];
		    node n = t->body.type.name;
		    if (n != NULL) {
			 assert(n->tag == symbol_tag);
			 n->body.symbol.value = thetype(j);
			 }
		    t->body.type.forward = thetype(j);
		    t->body.type.flags = identified_F;
		    newtypeslist[i] = NULL;
		    break;
		    }
	       }
	  }
     for (i=0; i<numnewtypes; i++) {
	  if (newtypeslist[i] != NULL) {
	       node t = newtypeslist[i];
	       interntype(t);
	       }
	  }
     }
Ejemplo n.º 6
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;
}