|
|
|
Table of Contents
This is an example of solving a one-compartment dilution problem using the ODE solving tools in OmeChron.
We assume a single, continuously mixed compartment through which a fluid is flowing at a constant rate. The compartment volume V = 10 liters and the flow rate F = 2 liters/min. At time t0, 3 moles of tracer are injected into the compartment. The differential equation for the tracer concentration as a function of time C(t) is:
dC/dt = -F/V * C(t)
This is easily solved in closed-form as:
C(t) = C(0) * e( -F/V * t ) [1]
We will solve it numerically and use the closed-form solution to check our answers.
We'll create the model as an OmeChron Plugin Library. Implementing our one-compartment
model in OmeChron requires that we create a C++ class derived from the built-in
class SimOdeModel. The usual OmeChron boiler plate
and attribute handling code has been deleted so we can focus on the parts related
to solving DE's. The following functions are called by the simulation executive
at different stages of a simulation run. The function deriv()
is called to compute the derivative at time t given the current state vector. The
function initialize_self() is called at the beginning
of the first simulation run and the function reset_self()
is called at the beginning of each simulation run. [2]
class CompartmentModel : public SimOdeModel
{
public:
//
void deriv( double t, sim::StateVec const& x, sim::StateVec& dx );
//
void initialize_self();
//
void reset_self();
};// end class CompartmentModel
Note the following key features.
|
Derive your model class from |
|
|
Override |
|
|
Override |
|
|
Override |
The implementation of these functions follows.
void CompartmentModel::initialize_self()
{
// Every SimOdeModel has system of ODE's called a "block".
// We have to add our state, its derivative, and an optional label...
block()->push_back( &x(0), &xdt(0), "C" );
// Activate calling 'sample_self()' at time intervals suitable
// for printing the states...
activate_sampling( 1.0 );
}// end initialize_self
void CompartmentModel::reset_self()
{
x(0) = a_I0 / a_V; // C(0) in moles/liter.
xdt(0) = 0.0; // The initial value for dC/dt
}// end reset_self
void CompartmentModel::deriv( double t,
sim::StateVec const& x,
sim::StateVec& dx )
{
dx[0] = -a_F/a_V * x[0]; // dC/dt = -F/V * C(t)
}// end update
The following qmake
.pro file will generate makefile to create an OmeChron plugin library
for the the one-compartment model. To build the plugin type:
qmake
then:
make
CONFIG += ome_plugin TEMPLATE = lib TARGET = one_compartmentVERSION = DESTDIR = $(OMECHRON)/bin/plugins OBJECTS_DIR = ./obj HEADERS = CompartmentModel.h
SOURCES = CompartmentModel.cpp
include( $(OMECHRON)/oplot/oplot.pri )
include( $(OMECHRON)/config/omechron.conf )
Note the following features that are specific to each OmeChron plugin model build file.
|
Define the plugin library name. |
|
|
List the model C++ header files here. |
|
|
List the model C++ source files here. |
|
|
Include the OmeChron plotting classes in this plugin project. |
![]() |
Note |
|---|---|
|
You can use this qmake file as template for building other model plugins. |
Start OmeChron and load your plugin model using the library manager. Drag and drop
an instance of the OmeCompartmentModel onto the pallet.
Also add a strip chart so we can plot the results as the model runs. Your pallet
should appears as shown in
Figure 1
Configure the one-compartment model parameters and initial conditions as shown in Figure 2
Configure the stripchart parameters as shown in Figure 3
The expected exponent decay in the tracer concentration appears in the plotted output in Figure 4