Skip to content

Commit d5b0cd1

Browse files
committed
documentation and fixed data visualizer
1 parent 3c64ac8 commit d5b0cd1

File tree

6 files changed

+126
-83
lines changed

6 files changed

+126
-83
lines changed

docs/source/files/assignments/project.rst

Lines changed: 23 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,42 +2,47 @@
22
10. Project Phase
33
###################
44

5-
In the project phase we decided to implement a userfriendly Gui. The aim is to make the usage of our Tsunami solver
5+
In the project phase we decided to implement a user-friendly Gui. The aim was to make the usage of our Tsunami solver
66
as easy and interactive as possible.
77

88
*********************
9-
GUI (Client-side)
9+
Preface
1010
*********************
1111

12-
.. image:: ../../_static/assets/task-10-Gui_help.png
13-
14-
For the layout we chose to use multiple tabs, in order to make the use more clear.
15-
The first page gives general informations about the project and refers to our website.
16-
17-
.. image:: ../../_static/assets/task-10-Gui_connectivity.png
12+
While we tried to stick to our plan as best as we could, we decided to do some things a little different.
13+
The biggest difference being a Client-Server approach although we explicitly mentioned we would not realize this.
14+
The original triggering point for this were all kinds of loading times and issues with concurrency:
15+
for any GUI application, one of the key features is its responsiveness to user input. Be it numerical input or just clicking and moving things around - the GUI should react as fast as possible.
16+
Integrating a GUI directly into the solver application while maintaining this responsiveness meant that the GUI and every other task the actual solver does, need to be separated in different threads
17+
to assure that the GUI thread has always time for the user.
1818

19-
Tab number two handles the the connection to thhe server. The properties for interacting with the server are getting set here.
20-
Furthermore, the connection can also be disconnected here.
19+
We started off with this directly integrated and threaded approach and quickly realized that handling correct communication between two or more asynchronous running threads was getting closer and closer to just having two separate applications communicating over an API.
20+
Knowing that this approach meant we would have to invest a lot more effort and work overtime, we decided on taking this path nontheless as it would come with a lot of other benefits as well.
21+
Now, using the Server-Client model we have a GUI that can just send commands to the server without needing to wait for a response (most of the time, unless you're specifically asking for data such as water/bathymetry data).
2122

22-
.. image:: ../../_static/assets/task-10-Gui_windows.png
23+
It can also be used in scenarios when using a more powerful machine (e.g. HPC-Cluster) without display access. Just start the program as a server on the remote machine and control it from home via laptop - its that easy.
2324

24-
On the next page the user can find all options of configuration for the simulation. The simulation parameters like cell amount, size and offset can be set here.
25-
In Addition to that, compiler and run time options can be found here. These contain differetn modes, compiler options, flags and usage choices.
26-
After selecting the simulation has to be recompiled with the according button below.
25+
*********************
26+
GUI (Client-side)
27+
*********************
2728

28-
.. image:: ../../_static/assets/task-10-Gui_select.png
29+
*********************
30+
Server-side
31+
*********************
2932

30-
The last tab contains further actions to interact with the simulation. First, the simulation can be started or killed here.
31-
Also files for the bathymetry and displacement can be chosen. As an addition, the user can get data like the heigth from the simulation.
33+
The first thing we did was to modularize our main ``tsunami_lab`` program. The original ``main.cpp`` had one main function that executed the whole program loop.
3234

3335
*********************
34-
Server-side
36+
Build process
3537
*********************
3638

3739
*********************
3840
Libraries
3941
*********************
4042

43+
To keep the main code clean, we decided to export most of the code associated with communication to external libraries:
44+
the Communicator and the API.
45+
4146
Communicator
4247
=====================
4348

lib/xlpmg/Communicator.hpp

Lines changed: 57 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,11 @@ namespace xlpmg
2727
class Communicator
2828
{
2929
private:
30-
// Timeout value for socket operations in seconds
31-
int TIMEOUT = 20;
3230
// Log data for storing communication logs
3331
std::string logData = "";
34-
// Socket related variables
32+
// Client socket related variables
3533
int sockStatus, sockValread, sockClient_fd = -1;
36-
// Socket related variables
34+
// Server socket related variables
3735
int server_fd, new_socket;
3836

3937
/**
@@ -113,25 +111,60 @@ namespace xlpmg
113111
}
114112
}
115113

114+
/**
115+
* Sets the send timeout for a socket.
116+
* @param socket The socket to set the send timeout for.
117+
* @param timeout The timeout value in seconds.
118+
*/
119+
void setSendTimeout(int socket, long timeout){
120+
struct timeval tv;
121+
tv.tv_sec = timeout;
122+
tv.tv_usec = 0;
123+
setsockopt(socket, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(struct timeval));
124+
}
125+
126+
/**
127+
* Sets the receive timeout for a socket.
128+
* @param socket The socket to set the receive timeout for.
129+
* @param timeout The timeout value in seconds.
130+
*/
131+
void setRecvTimeout(int socket, long timeout){
132+
struct timeval tv;
133+
tv.tv_sec = timeout;
134+
tv.tv_usec = 0;
135+
setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(struct timeval));
136+
}
137+
116138
public:
139+
// Timeout value for normal socket operations in seconds
140+
static const long TIMEOUT = 2;
117141
//! default size of the reading buffer
118-
const unsigned int BUFF_SIZE_READ_DEFAULT = 8096;
142+
unsigned int BUFF_SIZE_READ_DEFAULT = 8096;
119143
//! actual size of the reading buffer
120144
unsigned int BUFF_SIZE_READ = BUFF_SIZE_READ_DEFAULT;
121-
122145
//! default size of the sending buffer
123-
const unsigned int BUFF_SIZE_SEND_DEFAULT = 8096;
146+
unsigned int BUFF_SIZE_SEND_DEFAULT = 8096;
124147
//! actual size of the sending buffer
125148
unsigned int BUFF_SIZE_SEND = BUFF_SIZE_SEND_DEFAULT;
126149

127150
//! true if there is a connection
128151
bool isConnected = false;
129152

153+
/**
154+
* @brief Sets the read buffer size.
155+
*
156+
* @param newSize The new size of the read buffer.
157+
*/
130158
void setReadBufferSize(unsigned int newSize)
131159
{
132160
BUFF_SIZE_READ = newSize;
133161
}
134162

163+
/**
164+
* @brief Sets the send buffer size.
165+
*
166+
* @param newSize The new size of the send buffer.
167+
*/
135168
void setSendBufferSize(unsigned int newSize)
136169
{
137170
BUFF_SIZE_SEND = newSize;
@@ -149,9 +182,6 @@ namespace xlpmg
149182
int startClient(char *IPADDRESS, int PORT)
150183
{
151184
struct sockaddr_in serv_addr;
152-
struct timeval tv;
153-
tv.tv_sec = TIMEOUT;
154-
tv.tv_usec = 0;
155185

156186
if ((sockClient_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
157187
{
@@ -161,8 +191,8 @@ namespace xlpmg
161191
}
162192
logEvent("Socket created.", INFO, true);
163193

164-
setsockopt(sockClient_fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(struct timeval));
165-
setsockopt(sockClient_fd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(struct timeval));
194+
setSendTimeout(sockClient_fd, TIMEOUT);
195+
setRecvTimeout(sockClient_fd, TIMEOUT);
166196

167197
serv_addr.sin_family = AF_INET;
168198
serv_addr.sin_port = htons(PORT);
@@ -191,7 +221,7 @@ namespace xlpmg
191221

192222
/**
193223
* @brief Stops all connections of the client socket.
194-
*/
224+
*/
195225
void stopClient()
196226
{
197227
// closing the connected socket
@@ -202,9 +232,10 @@ namespace xlpmg
202232
/**
203233
* @brief Receives a message from the server.
204234
* @return Message as string.
235+
* @param timeout Timeout for the operation in seconds.
205236
* @param log Whether the message should be logged or not.
206237
*/
207-
std::string receiveFromServer(bool log = true)
238+
std::string receiveFromServer(long timeout = TIMEOUT, bool log = true)
208239
{
209240
if (sockClient_fd < 0)
210241
{
@@ -217,6 +248,8 @@ namespace xlpmg
217248
bool finished = false;
218249
unsigned long totalBytes = 0;
219250

251+
setRecvTimeout(sockClient_fd, timeout);
252+
220253
logEvent(std::to_string(totalBytes) + " Bytes (" + std::to_string(totalBytes / 1000000) + " MB) received ", DEBUG, log);
221254

222255
while (!finished)
@@ -255,33 +288,29 @@ namespace xlpmg
255288
finished = true;
256289
}
257290
}
291+
setRecvTimeout(sockClient_fd, TIMEOUT);
258292
isConnected = true;
259293
return message;
260294
}
261295

262-
/**
263-
* @brief Checks if the server is reachable.
264-
* @return true if server responded.
265-
*/
266-
bool checkServerResponse()
267-
{
268-
269-
}
270-
271296
/**
272297
* @brief Sends a message to the server.
273298
* @param message String to send.
299+
* @param timeout Timeout for the operation in seconds.
274300
* @param log Whether the message should be logged or not.
275301
* @return 0 if successful, 1 otherwise.
276302
*/
277-
int sendToServer(std::string message, bool log = true)
303+
int sendToServer(std::string message, long timeout = TIMEOUT, bool log = true)
278304
{
279305
if (sockClient_fd < 0)
280306
{
281307
logEvent("Sending failed: Socket not initialized.", ERROR, log);
282308
isConnected = false;
283309
return 1;
284310
}
311+
312+
setSendTimeout(sockClient_fd, timeout);
313+
285314
// terminator
286315
message.append("#!");
287316

@@ -317,6 +346,7 @@ namespace xlpmg
317346
logEvent(bytesSentStr.c_str(), DEBUG, log, true);
318347
}
319348
}
349+
setSendTimeout(sockClient_fd, TIMEOUT);
320350
isConnected = true;
321351
return 0;
322352
}
@@ -370,10 +400,13 @@ namespace xlpmg
370400
isConnected = false;
371401
exit(EXIT_FAILURE);
372402
}
403+
373404
address.sin_family = AF_INET;
374405
address.sin_addr.s_addr = INADDR_ANY;
375406
address.sin_port = htons(PORT);
376407

408+
setSendTimeout(new_socket, TIMEOUT);
409+
377410
// Forcefully attaching socket to the port 8080
378411
if (bind(server_fd, (struct sockaddr *)&address,
379412
sizeof(address)) < 0)

lib/xlpmg/communicator_api.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -194,9 +194,9 @@ namespace xlpmg
194194
// HIGH
195195

196196
//! Tells the server to start sending height data. (buffered)
197-
inline const Message GET_HEIGHT_DATA = {MessageExpectation::EXPECT_RESPONSE, MessageUrgency::MEDIUM, "get_height_data"};
197+
inline const Message GET_HEIGHT_DATA = {MessageExpectation::EXPECT_RESPONSE, MessageUrgency::HIGH, "get_height_data"};
198198
//! Tells the server to start sending bathymetry data. (buffered)
199-
inline const Message GET_BATHYMETRY_DATA = {MessageExpectation::EXPECT_RESPONSE, MessageUrgency::MEDIUM, "get_bathymetry_data"};
199+
inline const Message GET_BATHYMETRY_DATA = {MessageExpectation::EXPECT_RESPONSE, MessageUrgency::HIGH, "get_bathymetry_data"};
200200

201201
// MEDIUM
202202

src/Server.cpp

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,11 @@ std::thread m_updateThread;
1616
std::atomic<bool> m_stopUpdating = false;
1717
bool m_isSimulationRunning = false;
1818

19-
// updating
19+
// last update time point
2020
std::chrono::time_point m_lastDataUpdate = std::chrono::high_resolution_clock::now();
21+
// data update frequency in ms
2122
int m_dataUpdateFrequency = 10;
2223

23-
// temp files
24-
std::string m_bathTempFile = "bathymetry_temp.nc";
25-
std::string m_displTempFile = "displacement_temp.nc";
26-
2724
// system info
2825
tsunami_lab::systeminfo::SystemInfo l_systemInfo;
2926
double l_usedRAM = 0;
@@ -143,6 +140,12 @@ int main(int i_argc, char *i_argv[])
143140
{
144141
exitSimulationThread();
145142
}
143+
else if (l_key == xlpmg::WRITE_CHECKPOINT.key)
144+
{
145+
std::cout << "Writing checkpoint" << std::endl;
146+
simulator->writeCheckpoint();
147+
}
148+
146149
else if (l_key == xlpmg::PAUSE_SIMULATION.key)
147150
{
148151
std::cout << "Pause simulation" << std::endl;
@@ -160,7 +163,7 @@ int main(int i_argc, char *i_argv[])
160163
{
161164
if (l_key == xlpmg::CHECK.key)
162165
{
163-
l_communicator.sendToClient("OK");
166+
std::cout << "A client requested a check." << std::endl;
164167
}
165168
else if (l_key == xlpmg::START_SIMULATION.key)
166169
{
@@ -417,26 +420,25 @@ int main(int i_argc, char *i_argv[])
417420
xlpmg::Message l_heightDataMsg = xlpmg::SERVER_RESPONSE;
418421
l_heightDataMsg.key = "height_data";
419422
json l_data;
420-
421423
// get data from simulation
422424
if (simulator->getWaveProp() != nullptr)
423425
{
424426
tsunami_lab::patches::WavePropagation *l_waveprop = simulator->getWaveProp();
425427
const tsunami_lab::t_real *l_heightData = l_waveprop->getHeight();
426-
const tsunami_lab::t_real *l_bathymetryData = l_waveprop->getBathymetry();
427428
// calculate array size
428429
tsunami_lab::t_idx l_ncellsX, l_ncellsY;
429430
simulator->getCellAmount(l_ncellsX, l_ncellsY);
430431
for (tsunami_lab::t_idx y = 0; y < l_ncellsY; y++)
431432
{
432433
for (tsunami_lab::t_idx x = 0; x < l_ncellsX; x++)
433434
{
434-
l_data.push_back(l_heightData[x + l_waveprop->getStride() * y] + l_bathymetryData[x + l_waveprop->getStride() * y]);
435+
l_data.push_back(l_heightData[x + l_waveprop->getStride() * y]);
435436
}
436437
}
437438
}
438439
l_heightDataMsg.args = l_data;
439440
l_communicator.sendToClient(xlpmg::messageToJsonString(l_heightDataMsg));
441+
440442
}
441443
else if (l_key == xlpmg::GET_BATHYMETRY_DATA.key)
442444
{
@@ -513,8 +515,6 @@ int main(int i_argc, char *i_argv[])
513515
{
514516
m_updateThread.join();
515517
}
516-
std::remove(m_bathTempFile.c_str());
517-
std::remove(m_displTempFile.c_str());
518518
}
519519
//------------------------------------------//
520520
//--------------STANDARD MODE---------------//

0 commit comments

Comments
 (0)