This section describes an example that illustrates how to link a simulation program to the BCVTB in such a way that they exchange data at a fixed time step through a BSD socket connection. We will consider a system with two rooms. Each room has a heater that is controlled by a proportional controller. We will implement the simulation program for the two rooms in a C program, and we will link it to a controller that is implemented in Ptolemy II.
Let denote equally spaced time steps and let denote the number of the room. For the -th time step and the room number , let denote the room temperature and let denote the control signal for the heater. The room temperature is governed by
with initial conditions where is the time interval, is the room thermal capacity, is the room heat loss coefficient, is the outside temperature, is the nominal capacity of the heater and is the initial temperature. In these equations, we assumed that the communication time step is small enough to be used as the integration time step. If this is not the case, we could use a different integration time step and synchronize the integration time step with the communication time step.
The governing equation for the control signal is where is the proportional gain, is the set point temperature and the and functions limit the control signal between and .
Figure 6.1 shows a source code snippet of the implemented client. This source code can be found in the directory bcvtb/examples/c-room
. A similar implementation in Fortran 90 can be found in the directory bcvtb/examples/f90-room
.
Figure 6.1. Source code for a model of two rooms that is implemented in the C language.
1 // Establish the client socket const int sockfd = establishclientsocket("socket.cfg"); if (sockfd < 0){ fprintf(stderr,"Error: Failed to obtain socket file descriptor.\n"); 5 exit((sockfd)+100); } // Simulation loop while(1){ // assign values to be exchanged for(i=0; i < nDblWri; i++) dblValWri[i]=TRoo[i]; 10 // Exchange values retVal = exchangedoubleswithsocket(&sockfd, &flaWri, &flaRea, &nDblWri, &nDblRea, &simTimWri, dblValWri, &simTimRea, dblValRea); 15 ///////////////////////////////////////////////////////////// // Check flags if (retVal < 0){ sendclientmessage(&sockfd, &cliErrFla); printf("Simulator received value %d from socket.\n", retVal); 20 closeipc(&sockfd); exit((retVal)+100); } if (flaRea == 1){ printf("Simulator received end of simulation signal.\n"); closeipc(&sockfd); exit(0); } if (flaRea != 0){ 25 printf("Simulator received flag = %d. Exit simulation.\n", flaRea); closeipc(&sockfd); exit(1); } ///////////////////////////////////////////////////////////// // No flags found that require the simulation to terminate. // Assign exchanged variables 30 for(i=0; i < nRoo; i++) u[i] = dblValRea[i]; ///////////////////////////////////////////////////////////// // Having obtained u_k, we compute the new state x_k+1 = f(u_k). // This is the actual simulation time step of the client 35 for(i=0; i < nRoo; i++) TRoo[i] = TRoo[i] + delTim/C[i] * ( UA * (TOut-TRoo[i] ) + Q0Hea * u[i] ); simTimWri += delTim; // advance simulation time } // end of simulation loop
There are three functions that interface the client with the BCVTB: The function call
establishclientsocket
establishes the socket connection from the client to the middleware. The return value is an integer that references the socket. This descriptor is then used on line 11 as an argument to the function call exchangedoubleswithsocket
. This function writes data to the socket and reads data from the socket. Its arguments are the socket file descriptor, a flag to send a signal to the middleware (a non-zero value means that the client will stop its simulation) and a flag received from the middleware (a non-zero value indicates that no further values will be written to or read from the socket by the client). The remaining arguments are the array lengths and the array data to be written to and read from the middleware. After the call to
exchangedoubleswithsocket
follows error handling.
The test retVal < 0
checks for errors during the communication.
If there was an error, then a message is sent to the server to indicate that the client will terminate the co-simulation. Finally, the socket connection is closed by calling closeipc
.
To compile the source code, type on a command shell
cd bcvtb/examples/c-room ant all
This will invoke the ant build system, which calls the file bcvtb/examples/c-room/build.xml
that contains the compiler and linker commands.
To simulate this example, we implemented the controller directly in the middleware, using actors from the Ptolemy II library. However, the controller could as well be implemented in Modelica, MATLAB, Simulink or in a user written program that communicates through a BSD socket similarly to the C client above. Figure 6.2 shows the system diagram with the actor for the controller and the actor that interfaces the simulation program.