//==================================================== file = stop_csim.c =====
//=  A CSIM simulation of an M/M/1 with automatic run-length control          =
//=============================================================================
//=  Notes: 1) Values for lambda and mu are set in the main program           =
//=         2) Values for CI and ACCURACY are set as #defines                 =
//=         3) Converges on response time                                     =
//=         4) Computes theoretical results for comparison                    =
//=---------------------------------------------------------------------------=
//= Example execution:                                                        =
//=                                                                           =
//=   *** BEGIN SIMULATION ***                                                =
//=   =============================================================           =
//=   ==     *** CSIM M/M/1 queueing system simulation ***       ==           =
//=   =============================================================           =
//=   = Lambda   =   0.900 cust/sec                                           =
//=   = Mu       =   1.000 cust/sec                                           =
//=   = CI level =  95.000 %                                                  =
//=   = Accuracy =   1.000 %                                                  =
//=   =============================================================           =
//=   = Total CPU time     = 38.786 sec                                       =
//=   = Total sim time     = 11473862.555 sec                                 =
//=   = Total completions  = 10321601 cust                                    =
//=   =------------------------------------------------------------           =
//=   = >>> Simulation results                                    -           =
//=   =------------------------------------------------------------           =
//=   = Utilization        = 89.956 %                                         =
//=   = Mean num in system =  8.937 cust                                      =
//=   = Mean response time =  9.935 +/-  0.098 sec                            =
//=   = Mean service time  =  1.000 sec                                       =
//=   = Mean throughput    =  0.900 cust/sec                                  =
//=   =------------------------------------------------------------           =
//=   = >>> Theoretical results                                   -           =
//=   =------------------------------------------------------------           =
//=   = Utilization        = 90.000 %                                         =
//=   = Mean num in system =  9.000 cust                                      =
//=   = Mean response time = 10.000 sec                                       =
//=   = Mean service time  =  1.000 sec                                       =
//=   = Mean throughput    =  0.900 cust/sec                                  =
//=   =============================================================           =
//=   *** END SIMULATION ***                                                  =
//=---------------------------------------------------------------------------=
//=  Build: standard CSIM build                                               =
//=---------------------------------------------------------------------------=
//=  Execute: stop_csim                                                       =
//=---------------------------------------------------------------------------=
//=  Author: Ken Christensen                                                  =
//=          University of South Florida                                      =
//=          WWW: http://www.csee.usf.edu/~christen                           =
//=          Email: christen@csee.usf.edu                                     =
//=---------------------------------------------------------------------------=
//=  History: KJC (01/27/04) - Genesis (from mm1_csim.c)                      =
//=============================================================================
//----- Includes --------------------------------------------------------------
#include <stdio.h>      // Needed for printf()
#include "csim.h"       // Needed for CSIM18 stuff

//----- Defines ---------------------------------------------------------------
#define MAX_TIME  1.0e2 // Maximum simulation CPU time in seconds
#define CI_LEVEL  0.95  // Confidence interval level
#define ACCURACY  0.01  // Target accuracy

//----- Globals ---------------------------------------------------------------
FACILITY Server;        // Declaration of CSIM Server facility
TABLE    Delay_table;   // Declaration of CSIM table of delay values

//----- Prototypes ------------------------------------------------------------
void generate(double lambda, double mu);             // Customer generator
void queue1(double service_time, double org_time);   // Single server queue

//=============================================================================
//==  Main program                                                           ==
//=============================================================================
void sim(void)
{
  double   lambda;      // Mean arrival rate (cust/sec)
  double   mu;          // Mean service rate (cust/sec)
  double   rho;         // Theoretical utilization

  // Create the simulation
  create("sim");

  // CSIM initializations
  Server = facility("Server");
  Delay_table = table("Customer delay table");
  table_confidence(Delay_table);
  table_run_length(Delay_table, ACCURACY, CI_LEVEL, MAX_TIME);

  // Parameter initializations
  lambda = 0.90;
  mu = 1.00;

  // Output begin-of-simulation banner
  printf("*** BEGIN SIMULATION *** \n");

  // Initiate generate function and wait for convergence to CI
  generate(lambda, mu);
  wait(converged);

  // Compute theoretical utilization
  rho = lambda / mu;

  // Output results
  printf("============================================================= \n");
  printf("==     *** CSIM M/M/1 queueing system simulation ***       == \n");
  printf("============================================================= \n");
  printf("= Lambda   = %7.3f cust/sec   \n", lambda);
  printf("= Mu       = %7.3f cust/sec   \n", mu);
  printf("= CI level = %7.3f %%         \n", 100.0 * CI_LEVEL);
  printf("= Accuracy = %7.3f %%         \n", 100.0 * ACCURACY);
  printf("============================================================= \n");
  printf("= Total CPU time     = %6.3f sec      \n", cputime());
  printf("= Total sim time     = %6.3f sec      \n", clock);
  printf("= Total completions  = %ld cust       \n", completions(Server));
  printf("=------------------------------------------------------------ \n");
  printf("= >>> Simulation results                                    - \n");
  printf("=------------------------------------------------------------ \n");
  printf("= Utilization        = %6.3f %%       \n", 100.0 * util(Server));
  printf("= Mean num in system = %6.3f cust     \n", qlen(Server));
  printf("= Mean response time = %6.3f +/- %6.3f sec \n",
    table_conf_mean(Delay_table), table_conf_halfwidth(Delay_table, CI_LEVEL));
  printf("= Mean service time  = %6.3f sec      \n", serv(Server));
  printf("= Mean throughput    = %6.3f cust/sec \n", tput(Server));
  printf("=------------------------------------------------------------ \n");
  printf("= >>> Theoretical results                                   - \n");
  printf("=------------------------------------------------------------ \n");
  printf("= Utilization        = %6.3f %%       \n", 100.0 * rho);
  printf("= Mean num in system = %6.3f cust     \n", rho / (1.0 - rho));
  printf("= Mean response time = %6.3f sec      \n", (1.0 / mu) / (1.0 - rho));
  printf("= Mean service time  = %6.3f sec      \n", (1.0 / mu));
  printf("= Mean throughput    = %6.3f cust/sec \n", lambda);
  printf("============================================================= \n");

  // Output end-of-simulation banner
  printf("*** END SIMULATION *** \n");
}

//=============================================================================
//==  Function to generate Poisson customers                                 ==
//=============================================================================
void generate(double lambda, double mu)
{
  double   interarrival_time;    // Interarrival time to next send
  double   service_time;         // Service time for this customer

  create("generate");

  // Loop forever to create customers
  while(1)
  {
    // Pull an interarrival time and hold for it
    interarrival_time = exponential(1.0 / lambda);
    hold(interarrival_time);

    // Pull a service time and then send the customer to the queue
    service_time = exponential(1.0 / mu);
    queue1(service_time, clock);
  }
}

//=============================================================================
//==  Function for single server queue                                       ==
//=============================================================================
void queue1(double service_time, double org_time)
{
  create("queue1");

  // Reserve, hold, and release server
  reserve(Server);
  hold(service_time);
  release(Server);

  // Record customer delay in table for convergence test
  record((clock - org_time), Delay_table);
}

