Sophie

Sophie

distrib > Fedora > 18 > x86_64 > media > updates > by-pkgid > 45a94e45036b4f2592a7e2c3922f90c7 > files > 347

adevs-doc-2.6-4.fc18.noarch.rpm

#include "adevs.h"
#include <iostream>
using namespace std;
using namespace adevs;

/**
 * This is the circuit example from "Building Software for Simulation". It
 * prints the trajectory of the model to stdout; if this is captured in a file,
 * then the gnuplot command file 'plot' can be used to plot the voltage and
 * diode and switch states.
 */
class Circuit: public ode_system<bool>
{
	public:
		Circuit():
			ode_system<bool>(1,1), // one state variable and event function
			s(1),d(0), // diode and switch states
			vs(1.0),C(1.0),Rs(1.0),Rl(1.0), // device parameters
			vop(0.5),vcl(0.25){} 
		void init(double* q) { q[0] = 0.0; } // vc = 0
		void der_func(const double* q, double *dq)
		{
			// ODE form of the differential equations
			if (!s && !d) dq[0] = 0.0; 
			else if (!s && d) dq[0] = -q[0]/(C*Rl);
			else if (s && !d) dq[0] = (vs-q[0])/(C*Rs);
			else dq[0] = ((vs-q[0])/Rs-q[0]/Rl)/C;
		}
		void state_event_func(const double *q, double* z) 
		{
			// This model uses the implicit form of the diode event
			if (d==0) z[0] = q[0]-vop; 
			else z[0] = q[0]-vcl;
		}
		// As written here, this model does not have any time events
		double time_event_func(const double* q) { return DBL_MAX; }
		void internal_event(double* q, const bool* events)
		{
			assert(events[0]); // only one event type; make sure it fired
			d = !d;
		}
		void external_event(double*,double,const Bag<bool>& xb)
		{
			s = *(xb.begin());
		}
		void confluent_event(double* q,const bool* events,
				const Bag<bool>& xb)
		{
			internal_event(q,events);
			external_event(q,0.0,xb);
		}
		void output_func(const double* q, const bool* events,
				Bag<bool>& yb)
		{
			assert(events[0]);
			yb.insert(!d);
		}
		void gc_output(Bag<bool>&){}
		bool getDiode() const { return d; }
		bool getSwitch() const { return s; }
	private:
		bool s, d;
		const double vs, C, Rs, Rl, vop, vcl;
};

class StateListener: public EventListener<bool>
{
	public:
		StateListener(Hybrid<bool>* c1, Circuit* c2):c1(c1),c2(c2){}
		void stateChange(Atomic<bool>*,double t)
		{
			cout << t << " " << c1->getState(0) << " " << 
				c2->getSwitch() << " " << c2->getDiode() << endl;
		}
		void outputEvent(Event<bool>,double){}
	private:
		Hybrid<bool>* c1; Circuit* c2;
};

int main()
{
	// Create the model
	Circuit* circuit = new Circuit();
	Hybrid<bool>* hybrid_model = new Hybrid<bool>(
			circuit,new corrected_euler<bool>(circuit,1E-5,0.01),
			new linear_event_locator<bool>(circuit,1E-5));
	// Create the simulator
	Simulator<bool>* sim = new Simulator<bool>(hybrid_model);
	sim->addEventListener(new StateListener(hybrid_model,circuit));
	// Simulate until the switch opens
	while (sim->nextEventTime() <= 1.0) sim->execNextEvent();
	// Open the switch
	Bag<Event<bool> > xb; xb.insert(Event<bool>(hybrid_model,0));
	sim->computeNextState(xb,1.0);
	// Simulate for another second
	while (sim->nextEventTime() <= 4.0) sim->execNextEvent();
	delete sim; delete hybrid_model;
	return 0;
}