UT-SIM
  • Home
  • Architecture
    • Communication
    • Integration Modules
    • Substructure Modules
  • Users
    • Get Started with UT-SIM >
      • OpenSees
      • Abaqus
      • S-Frame
      • VecTor Suite
      • NICON-NIO
      • NICON-AIO
    • Download
  • Developers
    • Source Code
    • Communication Examples >
      • C/C++
      • Fortran
      • Matlab
      • Python
    • Download
  • Hybrid Simulation
  • Numerical Simulation
  • Application Examples
  • Workshop
  • News
  • Collaborators
  • Contact
  • References

Source code
(dataexchange library)

sourcecode

The DataExchange library includes the UTNP data exchange format and the communication protocol as described here(link to communication page). It also includes the functions to ease establishing connection and sending/receiving the formatted data packets. The library is compiled as a dynamic shared library such that it can be loaded into memory when a program is launched and binding occurs at run time. Depending on the operating system on which the analysis program is executed, the DataExchange library can be compiled as a dynamic link library (DataExchange.dll) for windows operating systems or an object file (DataExchange.out) for UNIX-link systems.

The DataExchange library is written in C++ with a header file (DataExchange.h) and a cpp file (DataExchange.cpp). Only the DLL version of the library is presented here.

DataExchange.h¶

The source code of the header files of DataExchange.dll are shown below

// ==============================================================================
// 
// Data exchange format for UT-SIM framework (www.ut-sim.ca)
// 
// Developed by Dr. Xu Huang
//              @ University of Toronto
// Version: 2.0.0 (Messageheader->version == 2)
// Last updated on Dec. 12, 2021
// Note: UDP is implemented in this version
// - function name change: updatesubtype -> updatedatatype
//                         getformat -> printheader
//
//==============================================================================

/*#include <stdint.h>*/
#include <winsock2.h>

// define data types
typedef signed char int8_t;
typedef short int16_t;
typedef int int32_t;

typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
typedef unsigned int uint32_t;


#ifndef dll_h
#define dll_h

#ifdef __cplusplus
extern "C" {
#endif

#ifdef _WIN32
#ifdef EXPORT_FCNS
#define FUNCSDLL_API __declspec(dllexport)
#else
#define FUNCSDLL_API __declspec(dllimport)
#endif
#else
#define FUNCSDLL_API
#endif


        FUNCSDLL_API void updatemessageheader (uint8_t version, uint8_t command, uint8_t testtype, 
                               uint8_t subtype, uint8_t precision, uint16_t numdofs);

        FUNCSDLL_API int setupconnection(int port, SOCKET* ClientSocket, int flag, char* machineInetAddr, int protocol); // either client or server
        FUNCSDLL_API int initialization (SOCKET ClientSocket, int flag, int protocol); // 
        FUNCSDLL_API uint8_t command(SOCKET ClientSocket, int flag, int protocol);
        FUNCSDLL_API int senddata (SOCKET ClientSocket, double* sdata, int len, int protocol);
        FUNCSDLL_API int recvdata (SOCKET ClientSocket, double* response, int len, int protocol);
        FUNCSDLL_API int terminate(SOCKET* ClientSocket);

        FUNCSDLL_API uint16_t getnumdof (void);
        FUNCSDLL_API uint16_t getnumstep (void);
        FUNCSDLL_API void updatecommand (uint8_t command);
        FUNCSDLL_API void updatenumstep (uint16_t step);
        FUNCSDLL_API uint8_t getsubtype (void);
        FUNCSDLL_API void updatedatatype (int disp, int vel, int accel, int force, int stiff, int mass, int temp);
        FUNCSDLL_API void updatenumdofs (uint16_t ndfs);
        FUNCSDLL_API int indicator (void);
        FUNCSDLL_API void printheader (void);

#ifdef  __cplusplus
}
#endif

#endif

DataExchange.cpp¶

The DataExchange cpp file is shown below

// ==============================================================================
// Data exchange format for SubStructure element and NICA 
// 
// Developed by Dr. Xu Huang
//              @ University of Toronto
// Version: 2.0.0 (Messageheader->version == 2)
// Last updated on April. 24, 2015
// Change log:
// - function name change: updatesubtype -> updatedatatype
//                         getformat -> printheader
// - 
//
//==============================================================================
#define EXPORT_FCNS
#include "DataExchange.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <winsock2.h>
#include <windows.h>
#include <inaddr.h>
#include <stdint.h>
#include <iostream>
#include <fstream>


#define MAX_UDP_DATAGRAM 9126

using namespace std;

// Need to link with Ws2_32.lib, Mswsock.lib, and Advapi32.lib
#pragma comment (lib, "Ws2_32.lib")


union MA {
    struct sockaddr    addr;
    struct sockaddr_in addr_in;
} ;

union MA myaddr;                                  // Server address struct
union MA otheraddr;                               // Client address struct
int AddLength;                                    // address length


//communication data format
// 
/* version 2.0.0
//Command 
#define RemoteTest_setTrialResponse  3            // send trial displacement
#define RemoteTest_setMass           4            // receive mass (no use anymore)
#define RemoteTest_getForce         10            // receive restoring force
#define RemoteTest_getInitialStiff  12            // receive initial stiffness (no use anymore)
#define RemoteTest_DIE              99            // terminate analysis

//substructure types
#define OpenSees                     1            
#define Zeus_NL                      2
#define Abaqus                       3
#define VecTor2                      4   
#define Cyrus                        5
#define S-Frame                      6
#define NICON                        7
#define VecTor4                      8

//test type
#define Ramp_hold                    1
#define Continuous                   2
#define Real_time                    3
#define Software_only                4            // component-level
#define Software_only2               5            // system-level 

//Communication precision
#define Single_precision             1
#define Double_precision             2            // default

*/

struct messageheader {
    uint8_t Version;
    uint8_t Command;
    uint8_t Test_type;
    uint8_t Sub_type;
    uint8_t Precision;
    struct Data_type {
        uint8_t disp:1;
        uint8_t vel:1;
        uint8_t accel:1;
        uint8_t force:1;
        uint8_t stiff:1;
        uint8_t mass:1;                            // add mass indicator
        uint8_t temper:1;
        uint8_t resvd:1;
    }datatype;
    uint16_t Num_DOFs;
    uint16_t Step_num;
    uint16_t Reserved;
    uint32_t Time_stamp;
} ;

struct messageheader *MessageHeader;

//variables for communication
char* recvbuf;
char* sendbuf;
double* rData;
double* sData;

// convert message from host to net
void 
htonDataheader (struct messageheader* h, char buffer[])
{
    uint16_t snum;
    uint16_t numdofs;
    uint16_t re;
    uint32_t timest;

    snum = htons(h->Step_num);
    numdofs = htons(h->Num_DOFs);
    re = htons(h->Reserved);
    timest = htonl(h->Time_stamp);

    memcpy(buffer+0, &(h->Version), 1);
    memcpy(buffer+1, &(h->Command), 1);
    memcpy(buffer+2, &(h->Test_type), 1);
    memcpy(buffer+3, &(h->Sub_type), 1);
    memcpy(buffer+4, &(h->Precision), 1);
    memcpy(buffer+5, &(h->datatype), 1);
    memcpy(buffer+6, &numdofs, 2);
    memcpy(buffer+8, &snum, 2);
    memcpy(buffer+10, &re, 2);
    memcpy(buffer+12, &timest, 4);

    // debugging
    //printf("Version in Send() is =%d\n", h->Version);
    //printf("Command in Send() is =%d\n", h->Command);
    //printf("Test_type in Send() is =%d\n", h->Test_type);
    //printf("Sub_type in Send() is =%d\n", h->Sub_type);
    //printf("Precision in Send() is =%d\n", h->Precision);
    //printf("Num_DOFs in Send() is =%d\n", h->Num_DOFs);
}


// convert message from net to host
void
ntohDataheader(char buffer[], struct messageheader *h) 
{
    uint16_t snum = 0;
    uint16_t numdofs = 0;
    uint16_t re = 0;
    uint32_t timest = 0;

    memcpy(&(h->Version), buffer+0, 1);
    memcpy(&(h->Command), buffer+1,  1);
    memcpy(&(h->Test_type), buffer+2,  1);
    memcpy(&(h->Sub_type), buffer+3,  1);
    memcpy(&(h->Precision), buffer+4, 1);
    memcpy(&(h->datatype), buffer+5, 1);
    memcpy(&(numdofs), buffer+6, 2);
    memcpy(&(snum), buffer+8, 2);
    memcpy(&(re), buffer+10, 2);
    memcpy(&(timest), buffer+12, 4);

    h->Step_num = ntohs(snum);
    h->Num_DOFs = ntohs(numdofs);
    h->Reserved = ntohs(re);
    h->Time_stamp = ntohl(timest);

    // debugging
    //printf("Version in Recv() is =%d\n", h->Version);
    //printf("Command in Recv() is =%d\n", h->Command);
    //printf("Test_type in Recv() is =%d\n", h->Test_type);
    //printf("Sub_type in Recv() is =%d\n", h->Sub_type);
    //printf("Precision in Recv() is =%d\n", h->Precision);
    //printf("Num_DOFs in Recv() is =%d\n", h->Num_DOFs);

}

// function to calculate data size appended to the data exchange format
int
indicator (void)
{
    int nd = 0;
    if (MessageHeader->datatype.disp == 1) 
        nd = nd + MessageHeader->Num_DOFs;
    if (MessageHeader->datatype.vel == 1) 
        nd = nd + MessageHeader->Num_DOFs;
    if (MessageHeader->datatype.accel == 1)
        nd = nd + MessageHeader->Num_DOFs;
    if (MessageHeader->datatype.force == 1)
        nd = nd + MessageHeader->Num_DOFs;

    if (MessageHeader->datatype.stiff == 1) {
            nd = nd + MessageHeader->Num_DOFs * MessageHeader->Num_DOFs;
    }

    if (MessageHeader->datatype.mass == 1)
        nd = nd + MessageHeader->Num_DOFs * MessageHeader->Num_DOFs;

    if (MessageHeader->datatype.temper == 1) {  
        nd = nd + MessageHeader->Num_DOFs;
    } 
    if (MessageHeader->datatype.resvd) {
        // do nothing
    }

    return nd;
}

void
    printheader (void)
{
    printf("Version      =%d\n", MessageHeader->Version);
    printf("Command      =%d\n", MessageHeader->Command);
    printf("Test_type    =%d\n", MessageHeader->Test_type);
    printf("Sub_type     =%d\n", MessageHeader->Sub_type);
    printf("Precision    =%d\n", MessageHeader->Precision);
    printf("Num_DOFs     =%d\n", MessageHeader->Num_DOFs);

}


// TCP send method
int
TCP_Send(char* sbuf, int dsize, double *sd, SOCKET sockfd)
{

    if (MessageHeader->Precision == 1) {// single precision

        float* sdata = new float [dsize];
        if (sd !=0) {
            for (int i=0; i<dsize; i++) {
                sdata[i] = (float) sd[i];
            }
        }

        int nwrite;
        char* Msg = sbuf;
        int nleft = dsize*sizeof(float)+16;

        htonDataheader(MessageHeader, sbuf);
        if (nleft-16 > 0) {
        memcpy (sbuf+16, sdata, nleft-16);
        }

        while (nleft > 0) {
            nwrite = send(sockfd,Msg,nleft,0);  
            if (nwrite < 0) {
                closesocket(sockfd);
                WSACleanup();
                return -1;
            }
            else if (nwrite == 0) {}
            else {
            nleft -= nwrite;
            Msg += nwrite;
            }
        }

        delete[] sdata;

    } else if (MessageHeader->Precision == 2) {//double precision

        int nwrite;
        char* Msg = sbuf;
        int nleft = dsize*sizeof(double)+16;

        htonDataheader(MessageHeader, sbuf);

        if (nleft-16 > 0) {
        memcpy (sbuf+16, sd, nleft-16);
        }

        while (nleft > 0) {
            nwrite = send(sockfd,Msg,nleft,0);
            if (nwrite < 0) {
                closesocket(sockfd);
                WSACleanup();
                return -1;
            }
            else if (nwrite == 0) {}
            else {
            nleft -= nwrite;
            Msg += nwrite;
            }
        }

    } else {
        printf("The defined precision %d in TCP_Send() is not accepted\n", MessageHeader->Precision);
    }




    return 0;
}


// TCP receive method
int 
TCP_Recv(char* rbuf, int dsize, double *rd , SOCKET sockfd)
{

    if (MessageHeader->Precision == 1) {//single precision

    int nread = 0;
    char* Msg = rbuf;

    int nleft = dsize*sizeof(float)+16;

    while (nleft > 0) {
        nread = recv(sockfd,Msg,nleft,0);
        if (nread < 0) {
            closesocket(sockfd);
            WSACleanup();
            return -1;
        }
        else if (nread == 0) {}
        else {
            nleft -= nread;
            Msg += nread;
        }
    }

    ntohDataheader(rbuf, MessageHeader);

    float* rdata = new float [dsize];

    memcpy (rdata, rbuf+16, dsize*sizeof(float));   
    for (int i=0; i<dsize; i++) {
        rd[i] = (double) rdata[i];
    }

    delete[] rdata;

    } else if (MessageHeader->Precision == 2) {//double precision


        int nread = 0;
        char* Msg = rbuf;

        int nleft = dsize*sizeof(double)+16;

        while (nleft > 0) {
            nread = recv(sockfd,Msg,nleft,0);
            if (nread < 0) {
                closesocket(sockfd);
                WSACleanup();
                return -1;
            }
            else if (nread == 0) {}
            else {
                nleft -= nread;
                Msg += nread;
            }
        }


        ntohDataheader(rbuf, MessageHeader);

        memcpy (rd, rbuf+16, dsize*sizeof(double)); 

    } else {
        printf("The defined precision %d in TCP_Recv() is not accepted\n", MessageHeader->Precision);
    }

    return 0;
}





// TCP send method
int
UDP_Send(char* sbuf, int dsize, double *sd, SOCKET sockfd)
{

    if (MessageHeader->Precision == 1) {// single precision

        float* sdata = new float [dsize];
        if (sd !=0) {
            for (int i=0; i<dsize; i++) {
                sdata[i] = (float) sd[i];
            }
        }

        char* Msg = sbuf;
        int nleft = dsize*sizeof(float)+16;

        htonDataheader(MessageHeader, sbuf);
        if (nleft-16 > 0) {
        memcpy (sbuf+16, sdata, nleft-16);
        }

        while (nleft > 0) {
            if (nleft <= MAX_UDP_DATAGRAM) {
                sendto(sockfd, Msg, nleft, 0, &otheraddr.addr, AddLength);
                nleft =0;
            }
            else {
                sendto(sockfd, Msg, MAX_UDP_DATAGRAM, 0, &otheraddr.addr, AddLength);
                Msg += MAX_UDP_DATAGRAM;
                nleft -= MAX_UDP_DATAGRAM;
            }
        }


        delete[] sdata;

    } else if (MessageHeader->Precision == 2) {//double precision

        char* Msg = sbuf;
        int nleft = dsize*sizeof(double)+16;

        htonDataheader(MessageHeader, sbuf);

        if (nleft-16 > 0) {
        memcpy (sbuf+16, sd, nleft-16);
        }

        while (nleft > 0) {
            if (nleft <= MAX_UDP_DATAGRAM) {
                sendto(sockfd, Msg, nleft, 0, &otheraddr.addr, AddLength);
                nleft =0;
            }
            else {
                sendto(sockfd, Msg, MAX_UDP_DATAGRAM, 0, &otheraddr.addr, AddLength);
                Msg += MAX_UDP_DATAGRAM;
                nleft -= MAX_UDP_DATAGRAM;
            }
        }

    }

    return 0;
}


// TCP receive method
int 
UDP_Recv(char* rbuf, int dsize, double *rd , SOCKET sockfd)
{

    if (MessageHeader->Precision == 1) {//single precision

    int nread = 0;
    char* Msg = rbuf;

    int nleft = dsize*sizeof(float)+16;

    while (nleft > 0) {
        if (nleft <= MAX_UDP_DATAGRAM) {
            recvfrom(sockfd, Msg, nleft, 0, &otheraddr.addr, &AddLength);
            nleft =0;
        }
        else {
            recvfrom(sockfd, Msg, MAX_UDP_DATAGRAM, 0, &otheraddr.addr, &AddLength);
            Msg += MAX_UDP_DATAGRAM;
            nleft -= MAX_UDP_DATAGRAM;
        }
    }

    ntohDataheader(rbuf, MessageHeader);

    float* rdata = new float [dsize];

    memcpy (rdata, rbuf+16, dsize*sizeof(float));   
    for (int i=0; i<dsize; i++) {
        rd[i] = (double) rdata[i];
    }

    delete[] rdata;

    } else if (MessageHeader->Precision == 2) {//double precision
        int nread = 0;
        char* Msg = rbuf;

        int nleft = dsize*sizeof(double)+16;

        while (nleft > 0) {
            if (nleft <= MAX_UDP_DATAGRAM) {
                recvfrom(sockfd, Msg, nleft, 0, &otheraddr.addr, &AddLength);
                nleft =0;
            }
            else {
                recvfrom(sockfd, Msg, MAX_UDP_DATAGRAM, 0, &otheraddr.addr, &AddLength);
                Msg += MAX_UDP_DATAGRAM;
                nleft -= MAX_UDP_DATAGRAM;
            }
        }

        ntohDataheader(rbuf, MessageHeader);

        memcpy (rd, rbuf+16, dsize*sizeof(double)); 

    }

    return 0;
}


// 
int setupconnection(int port, SOCKET* ClientSocket, int flag, char* machineInetAddr, int protocol)
{

    // variables for network communication 

    WSADATA wsaData;
    SOCKET ListenSocket = INVALID_SOCKET;           // listen socket

    int iResult;


    if (flag == 1) {                                // Client
        // set remote address
        memset((char *) &otheraddr, 0, sizeof(otheraddr));
        otheraddr.addr_in.sin_family = AF_INET;
        otheraddr.addr_in.sin_port = htons(port);
        otheraddr.addr_in.sin_addr.S_un.S_addr = inet_addr(machineInetAddr);

        // set local address
        memset((char *) &myaddr, 0, sizeof(myaddr));
        myaddr.addr_in.sin_family = AF_INET;
        myaddr.addr_in.sin_port = htons(0);
        myaddr.addr_in.sin_addr.S_un.S_addr = htonl(INADDR_ANY);

        printf("before WSAStartup: %d\n", *ClientSocket);

        // Initialize Winsock
        iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
        if (iResult != 0) {
            printf("WSAStartup failed with error: %d\n", iResult);
            return -1;
        }

        // open a socket
        if (protocol == 1) {
        printf("before socket: %d\n", *ClientSocket);
            if ((*ClientSocket = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
                fprintf(stderr, "setupconnection() - could not open socket\n");
                WSACleanup();
                return -2;
            }
        } else {
            if ((*ClientSocket = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
                fprintf(stderr, "setupconnection() - could not open socket\n");
                WSACleanup();
                return -3;
            }
        }

        // bind local address to it
                printf("before bind: %d\n", *ClientSocket);

        if (bind(*ClientSocket, &myaddr.addr, sizeof(myaddr.addr)) < 0) {
            fprintf(stderr,"setupconnection() - could not bind local address\n");
            closesocket(*ClientSocket);
            WSACleanup();
            return -4;
        }


        if (protocol == 1) {
                    printf("before ClientSocket: %d\n", *ClientSocket);

            // try to connect to socket with remote address.
            if (connect(*ClientSocket, &otheraddr.addr, sizeof(otheraddr.addr))< 0) {
                fprintf(stderr, "setupconnection() - could not connect\n");
                return *ClientSocket;
            }
                    return 0;

        } else {

            AddLength = sizeof(myaddr.addr);
            // send a message to address
            char data = 'a';
            sendto(*ClientSocket, &data, 1, 0, &otheraddr.addr, AddLength);

            // receive a message from other
            recvfrom(*ClientSocket, &data, 1, 0, &otheraddr.addr, &AddLength);    
            if (data != 'b') {
                fprintf(stderr, "setupconnection() - could not connect\n");
                return -1;
            }
        }

        return 0;

    } else if (flag == 2) {                         // server
        // Initialize Winsock
        iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
           if (iResult != 0) {
               printf("WSAStartup failed with error: %d\n", iResult);
               return 1;
           }

           // set up my_Addr.addr_in with address given by port and internet address of
           // machine on which the process that uses this routine is running.

           memset((char *) &myaddr, 0, sizeof(myaddr));
           myaddr.addr_in.sin_family = AF_INET;
           myaddr.addr_in.sin_port = htons(port);
           myaddr.addr_in.sin_addr.S_un.S_addr = htonl(INADDR_ANY);

           // setup connection
           // wait for other process to contact me & set up connection  
           // open a socket 
           if (protocol == 1) {
               if ((ListenSocket = socket(AF_INET, SOCK_STREAM, 0)) < 0) {  
               fprintf(stderr, "setupconnection() - could not open socket\n");
               return -1;   
               }
           } else {
               if ((ListenSocket = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {   
               fprintf(stderr, "setupconnection() - could not open socket\n");
               return -1;   
               }
           }

           // bind local address to it
           if (bind(ListenSocket, &myaddr.addr, sizeof(myaddr.addr)) < 0) {
            fprintf(stderr, "setupconnection() - could not bind local address\n");
              return -1;
           }    

           AddLength = sizeof(myaddr. addr);

           if (protocol == 1) {
               listen(ListenSocket, 1);    
               fprintf(stderr, "setupconnection() - waiting for connection\n");
               *ClientSocket = accept(ListenSocket, &otheraddr.addr, &AddLength);

               if (*ClientSocket < 0) {
                   fprintf(stderr, "setupconnection() - could not accept connection\n");
                   return -1;
               } else {
                   fprintf(stderr, "setupconnection() - accept connection\n");
                                  // No longer need server socket
               closesocket(ListenSocket);
                return 0;
               }

           } else {
               *ClientSocket = ListenSocket;
               // handshake by receiving a character from client
               char data;
               recvfrom(*ClientSocket, &data, 1, 0, &otheraddr.addr, &AddLength); 
               if (data == 'a') {    
                fprintf(stderr, "setupconnection() - accept connection\n");
                               // then send a message back
               data = 'b';
               sendto(*ClientSocket, &data, 1, 0, &otheraddr.addr, AddLength);        
               return 0;
               } 
               else 
                   return -1;


           }


    }       

}

// Function to define and intialize the data exchange format
void updatemessageheader (uint8_t version, uint8_t command, uint8_t testtype, uint8_t subtype, uint8_t precision, uint16_t numdofs)
{

    // create and update *MessageHeader 
    if (MessageHeader == NULL)
        MessageHeader = (struct messageheader*) malloc (sizeof(struct messageheader));

    MessageHeader->Version = version;
    MessageHeader->Command = command;
    MessageHeader->Test_type = testtype;
    MessageHeader->Sub_type = subtype;
    MessageHeader->Precision = precision;

    MessageHeader->datatype.disp = 0;   
    MessageHeader->datatype.vel = 0;
    MessageHeader->datatype.accel = 0;
    MessageHeader->datatype.force = 0;
    MessageHeader->datatype.stiff = 0;
    MessageHeader->datatype.mass = 0;
    MessageHeader->datatype.temper = 0;
    MessageHeader->datatype.resvd = 0;

    MessageHeader->Num_DOFs = numdofs;
    MessageHeader->Step_num = 1;   
    MessageHeader->Reserved = 0;
    MessageHeader->Time_stamp = 0;

}

// Function to define command value in exchange format
void updatecommand (uint8_t command)
{
    MessageHeader->Command = command;

}

// Function to record step number
void updatenumstep (uint16_t step)
{
    MessageHeader->Step_num = step;
}

void updatenumdofs (uint16_t ndfs)
{
    MessageHeader->Num_DOFs = ndfs;
}

// Function to return substructure type
uint8_t getsubtype (void)
{
    return MessageHeader->Sub_type;
}

// Function to update data type
void updatedatatype (int disp, int vel, int accel, int force, int stiff, int mass, int temp)
{
    if (disp == 1)
        MessageHeader->datatype.disp = 1;
    else
        MessageHeader->datatype.disp = 0;

    if (vel == 1)
        MessageHeader->datatype.vel = 1;
    else
        MessageHeader->datatype.vel = 0;

    if (accel == 1)
        MessageHeader->datatype.accel = 1;
    else
        MessageHeader->datatype.accel = 0;

    if (force == 1)
        MessageHeader->datatype.force = 1;
    else
        MessageHeader->datatype.force = 0;

    if (stiff == 1)
        MessageHeader->datatype.stiff = 1;
    else
        MessageHeader->datatype.stiff = 0;

    if (mass == 1)
        MessageHeader->datatype.mass = 1;
    else
        MessageHeader->datatype.mass = 0;

    if (temp == 1)
        MessageHeader->datatype.temper = 1;
    else
        MessageHeader->datatype.temper =  0;

}

// Function to initalize the data exchange format in the other side
int initialization (SOCKET ClientSocket, int flag, int protocol)
{
    int iResult;
    if (flag == 1) {
        sendbuf = new char[16];
        sData = NULL;
        if (protocol == 1) 
            iResult = TCP_Send(sendbuf, 0, sData, ClientSocket);
        else
            iResult = UDP_Send(sendbuf, 0, sData, ClientSocket);

        //cleanup temporary memory
        sData = NULL;
        delete[] sendbuf;
        sendbuf = NULL;

    } else if (flag == 2) {
        recvbuf = new char[16];
        rData = NULL;
        if (protocol == 1)
            iResult = TCP_Recv (recvbuf, 0, rData, ClientSocket);
        else
            iResult = UDP_Recv (recvbuf, 0, rData, ClientSocket);

        //cleanup temporary memory
        rData = NULL;
        delete[] recvbuf;
        recvbuf = NULL;

    } 

    if (iResult < 0) {      
        fprintf(stderr, "Initialization() - failed\n");
        return -1;
    }

    return 0;
}

// Function to send command
uint8_t command(SOCKET ClientSocket, int flag, int protocol)
{

    int iResult;
    if (flag ==1) {
        sendbuf = new char [16];
        sData = NULL;
        if (protocol == 1)
            iResult = TCP_Send (sendbuf, 0, sData, ClientSocket);
        else if (protocol == 2)
            iResult = UDP_Send (sendbuf, 0, sData, ClientSocket);
        else
            fprintf(stderr, "command() - wrong protocol\n");

        // cleanup temporary memory
        delete[] sendbuf;
        sendbuf =NULL;
        sData = NULL;

    } 
    else if (flag ==2 ) {
        recvbuf = new char [16];
        rData = NULL;   

        if (protocol == 1)
            iResult = TCP_Recv (recvbuf, 0, rData, ClientSocket);
        else if (protocol == 2)
            iResult = UDP_Recv (recvbuf, 0, rData, ClientSocket);
        else
            fprintf(stderr, "command() - wrong protocol\n");

        // cleanup temporary memory 
        delete[] recvbuf;
        recvbuf =NULL;
        rData = NULL;
    }

    if (iResult < 0) {
        fprintf(stderr, "RecvData() - failed\n");
        return 1;
    }

    return MessageHeader->Command;


}

// Function to receive data
int recvdata (SOCKET ClientSocket, double* response, int len, int protocol)
{
    int iResult;
    //nd = indicator (MessageHeader);
    rData = new double [len];
    if (MessageHeader->Precision == 1) {
         recvbuf = new char[16+len*sizeof(float)];
         if (protocol == 1)
             iResult = TCP_Recv(recvbuf, len, rData, ClientSocket);
         else if (protocol == 2)
             iResult = UDP_Recv(recvbuf, len, rData, ClientSocket);
         else
             fprintf(stderr, "RecvData() - wrong protocol\n");

    } else if (MessageHeader->Precision == 2) {
         recvbuf = new char[16+len*sizeof(double)];
         if (protocol == 1)
             iResult = TCP_Recv(recvbuf, len, rData, ClientSocket);
         else if (protocol == 2)
             iResult = UDP_Recv(recvbuf, len, rData, ClientSocket);
         else
             fprintf(stderr, "RecvData() - wrong protocol\n");
    } else {
        fprintf(stderr, "RecvData() - wrong precision\n");

    }


    if (iResult < 0) {
        fprintf(stderr, "RecvData() - failed\n");
        return -1;
    }

    for (int i = 0; i<len; i++) {
        response[i] = rData[i];
    }

    // cleanup temporary memory
    delete[] recvbuf;
    recvbuf = NULL;
    delete[] rData;
    rData =NULL;

    return 0;
}

// Function to get number of DOFs
uint16_t getnumdof (void)
{
    return MessageHeader->Num_DOFs;

}

// Function to get step number
uint16_t getnumstep (void)
{
    return MessageHeader->Step_num;
}

// Function to send data
int senddata (SOCKET ClientSocket, double* sdata, int len, int protocol)
{
    int iSendResult;
    //nd = indicator(MessageHeader);

    if (sData == NULL)
        sData = new double [len];

    for (int i = 0; i<len; i++) {
        sData[i] = sdata[i];
    }

    // send resisting force to Client
    if (MessageHeader->Precision == 1) {
        sendbuf = new char[16+len*sizeof(float)];
        if (protocol == 1)
            iSendResult = TCP_Send(sendbuf, len, sData, ClientSocket);
        else if (protocol == 2)
            iSendResult = UDP_Send(sendbuf, len, sData, ClientSocket);
        else
             fprintf(stderr, "SendData() - wrong protocol\n");
    } else if (MessageHeader->Precision == 2) {
         sendbuf = new char[16+len*sizeof(double)];
         if (protocol == 1)
             iSendResult = TCP_Send(sendbuf, len, sData, ClientSocket);
         else if (protocol == 2)
             iSendResult = UDP_Send(sendbuf, len, sData, ClientSocket);
         else
             fprintf(stderr, "SendData() - wrong protocol\n");
    } else {
        fprintf(stderr, "SendData() - wrong precision\n");
    }

    if (iSendResult < 0) {
        fprintf(stderr, "SendData() - failed\n");
        return -1;
    }

    // cleanup temporary memory
    delete[] sendbuf;            
    sendbuf = NULL;
    delete[] sData;
    sData = NULL;

    return 0;
}


// Function to shut down connection and close socket
int terminate(SOCKET* ClientSocket)
{

    // Shutdown the network connection 
    int iResult = shutdown(*ClientSocket, SD_SEND);

    if (iResult == SOCKET_ERROR) {
        printf("shutdown failed with error: %d\n", WSAGetLastError());
        closesocket(*ClientSocket);
        WSACleanup();
        return -1;
    }
    else {
        closesocket(*ClientSocket);
        WSACleanup();
    }

    delete sData;
//  delete MessageHeader;

    return 0;
}

Compile library¶

The steps to compile the DataExchange.dll using Visual Studio are listed below:

  1. Download the header and cpp files from the UT-SIM website (link).
  2. Open Visual Studio and open a new project for Win32 Console Application
    • FILE -> NEW -> Project -> Win32 Console Application
    • Name the project as DataExchange and click "Ok" button to proceed
    • From the Win32 Application Wizard window as shown below, click "Next" to open the
      Drawing
    • On the Application Setting window, select DLL type, check Empty project, and click "Finish" button. Drawing
  3. From the Solution Explorer, add the DataExchange header file and cpp file to the "Header Files" folder and "Source Files" folder, respectively, as shown below Drawing
  4. Build the project (BUILD -> BUILD SOLUTION)

It should be noted that the library should be compiled in Release mode. In addition, the library can be compiled in 32-bit or 64-bit depending on the simulation program to be linked with. For example, 64-bit DataExchange.dll must be used for 64-bit OpenSees modules in the current development.

Proudly powered by Weebly
  • Home
  • Architecture
    • Communication
    • Integration Modules
    • Substructure Modules
  • Users
    • Get Started with UT-SIM >
      • OpenSees
      • Abaqus
      • S-Frame
      • VecTor Suite
      • NICON-NIO
      • NICON-AIO
    • Download
  • Developers
    • Source Code
    • Communication Examples >
      • C/C++
      • Fortran
      • Matlab
      • Python
    • Download
  • Hybrid Simulation
  • Numerical Simulation
  • Application Examples
  • Workshop
  • News
  • Collaborators
  • Contact
  • References