/[escript]/trunk/weipa/src/VisItControl.cpp
ViewVC logotype

Contents of /trunk/weipa/src/VisItControl.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3096 - (show annotations)
Thu Aug 19 01:40:52 2010 UTC (9 years, 2 months ago) by caltinay
File size: 8537 byte(s)
-New VisIt simulation control interface in weipa (uses VisIt's simv2)
-Rewrote restarts.py to be a more generic data manager for restarts and exports
-Removed weipa python file since the functionality is now handled by restarts.py

1
2 /*******************************************************
3 *
4 * Copyright (c) 2003-2010 by University of Queensland
5 * Earth Systems Science Computational Center (ESSCC)
6 * http://www.uq.edu.au/esscc
7 *
8 * Primary Business: Queensland, Australia
9 * Licensed under the Open Software License version 3.0
10 * http://www.opensource.org/licenses/osl-3.0.php
11 *
12 *******************************************************/
13
14 #include <weipa/VisItControl.h>
15
16 #ifdef USE_VISIT
17 #include <weipa/VisItData.h>
18
19 #include <VisItControlInterface_V2.h>
20
21 #include <cstring>
22 #include <iostream>
23 #ifdef PASO_MPI
24 #include <mpi.h>
25 #endif
26
27 #define VISIT_COMMAND_PROCESS 0
28 #define VISIT_COMMAND_SUCCESS 1
29 #define VISIT_COMMAND_FAILURE 2
30 #endif
31
32 namespace weipa {
33
34 namespace VisItControl {
35
36 #ifdef USE_VISIT
37
38 weipa::VisItData_ptr visitData(new VisItData());
39 int mpiRank = 0;
40 int mpiSize = 1;
41 bool runFlag = true;
42 bool connected = false;
43
44 // Helper function for processVisItCommand()
45 static void broadcastSlaveCommand(int* command)
46 {
47 #ifdef PASO_MPI
48 MPI_Bcast(command, 1, MPI_INT, 0, MPI_COMM_WORLD);
49 #endif
50 }
51
52 // Processes commands from the VisIt viewer on all processors
53 static int processVisItCommand()
54 {
55 if (mpiRank == 0) {
56 int success = VisItProcessEngineCommand();
57 int command;
58
59 if (success) {
60 command = VISIT_COMMAND_SUCCESS;
61 broadcastSlaveCommand(&command);
62 return 1;
63 } else {
64 command = VISIT_COMMAND_FAILURE;
65 broadcastSlaveCommand(&command);
66 return 0;
67 }
68 } else {
69 // Note: Only through the SlaveProcessCallback() function
70 // can rank 0 send VISIT_COMMAND_PROCESS to non-zero ranks
71 while (1) {
72 int command=VISIT_COMMAND_SUCCESS;
73 broadcastSlaveCommand(&command);
74 switch (command) {
75 case VISIT_COMMAND_PROCESS:
76 VisItProcessEngineCommand();
77 break;
78 case VISIT_COMMAND_SUCCESS:
79 return 1;
80 case VISIT_COMMAND_FAILURE:
81 return 0;
82 }
83 }
84 }
85 }
86
87 // Callback involved in command communication
88 static void slaveProcessCallback()
89 {
90 int command = VISIT_COMMAND_PROCESS;
91 broadcastSlaveCommand(&command);
92 }
93
94 #ifdef PASO_MPI
95 static int broadcastIntCallback(int* value, int sender)
96 {
97 return MPI_Bcast(value, 1, MPI_INT, sender, MPI_COMM_WORLD);
98 }
99
100 static int broadcastStringCallback(char* str, int len, int sender)
101 {
102 return MPI_Bcast(str, len, MPI_CHAR, sender, MPI_COMM_WORLD);
103 }
104 #endif
105
106 // Processes a control command
107 static void controlCommandCallback(const char* cmd, const char* sdata,
108 void* cb_data)
109 {
110 std::cout << "Control Command: " << cmd << std::endl;
111
112 if (strstr(cmd, "pause")) {
113 runFlag = !runFlag;
114 } else if (strstr(cmd, "update_plots")) {
115 VisItUpdatePlots();
116 }
117 }
118
119 // Callback that returns metadata for this dataset
120 visit_handle VisItGetMetaData(void* cbdata)
121 {
122 std::cout << "VisItGetMetaData()" << std::endl;
123 return visitData->getSimMetaData();
124 }
125
126 // Callback that returns the domain list for this dataset
127 visit_handle VisItGetDomainList(const char* name, void* cbdata)
128 {
129 std::cout << "VisItGetDomainList(" << name << ")" << std::endl;
130 return visitData->getDomainList();
131 }
132
133 // Callback that returns mesh data
134 visit_handle VisItGetMesh(int domain, const char* name, void* cbdata)
135 {
136 std::cout << "VisItGetMesh(" << domain << ", '" << name << "')" << std::endl;
137 if (mpiRank != domain) {
138 std::cout << "I don't have data for domain " << domain << std::endl;
139 return VISIT_INVALID_HANDLE;
140 }
141 return visitData->getMesh(name);
142 }
143
144 // Callback that returns variable data
145 visit_handle VisItGetVariable(int domain, const char* name, void* cbdata)
146 {
147 std::cout << "VisItGetVariable(" << domain << ", '" << name << "')" << std::endl;
148 if (mpiRank != domain) {
149 std::cout << "I don't have data for domain " << domain << std::endl;
150 }
151 return visitData->getVariable(name);
152 }
153
154 #endif // USE_VISIT
155
156 /****************************************************************************/
157
158 // Initializes libsim and the communication to VisIt
159 bool initialize(const std::string& simFile, const std::string& comment)
160 {
161 bool initialized = false;
162
163 #ifdef USE_VISIT
164 if (connected) {
165 VisItDisconnect();
166 connected = false;
167 std::cout << "Disconnected." << std::endl;
168 }
169
170 //VisItOpenTraceFile("/tmp/simV2trace.txt");
171 if (!VisItSetupEnvironment()) {
172 std::cerr << "Error setting up VisIt environment" << std::endl;
173 } else {
174 #ifdef PASO_MPI
175 MPI_Comm_rank(MPI_COMM_WORLD, &mpiRank);
176 MPI_Comm_size(MPI_COMM_WORLD, &mpiSize);
177
178 // Install callback functions for global communication
179 VisItSetBroadcastIntFunction(broadcastIntCallback);
180 VisItSetBroadcastStringFunction(broadcastStringCallback);
181
182 // Tell libsim whether the simulation is parallel
183 VisItSetParallel(mpiSize > 1);
184 VisItSetParallelRank(mpiRank);
185 #endif
186 if (mpiRank == 0) {
187 std::string filename(simFile);
188 if (filename.rfind(".sim2") != filename.length()-5) {
189 filename += ".sim2";
190 }
191 VisItInitializeSocketAndDumpSimFile("escript", comment.c_str(),
192 NULL, NULL, NULL, filename.c_str());
193 }
194 std::vector<std::string> cmdNames;
195 cmdNames.push_back("pause");
196 cmdNames.push_back("update_plots");
197 visitData->setCommandNames(cmdNames);
198 initialized = true;
199 }
200 #endif // USE_VISIT
201 return initialized;
202 }
203
204 // Main entry point that checks for client input and publishes new data
205 void publishData(int cycle, double time, escript::Domain_ptr domain,
206 const boost::python::dict& datavars)
207 {
208 #ifdef USE_VISIT
209 int visitState = 0, err = 0;
210
211 if (connected) {
212 visitData->publishData(domain, datavars);
213 visitData->setSimulationStatus(runFlag, time, cycle);
214 VisItTimeStepChanged();
215 }
216
217 do {
218 // Get input from VisIt or timeout so the simulation can continue
219 if (mpiRank == 0) {
220 int blocking = (connected && !runFlag) ? 1 : 0;
221 visitState = VisItDetectInput(blocking, -1);
222 }
223
224 #ifdef PASO_MPI
225 MPI_Bcast(&visitState, 1, MPI_INT, 0, domain->getMPIComm());
226 #endif
227
228 // visitState values:
229 // 0: there was no input from VisIt so nothing to do
230 // 1: VisIt is trying to connect
231 // 2: VisIt sent a command which should be processed
232 // < 0: an unrecoverable error occurred
233 if (visitState < 0) {
234 std::cerr << "VisItControl: Can't recover from error! State="
235 << visitState << std::endl; fflush(stderr);
236 err = 1;
237 } else if (visitState == 1) {
238 if (VisItAttemptToCompleteConnection() == VISIT_OKAY) {
239 std::cout << "Client connected!" << std::endl;
240 // publish latest data
241 visitData->publishData(domain, datavars);
242 visitData->setSimulationStatus(runFlag, time, cycle);
243 void* cbdata = NULL;
244 VisItSetCommandCallback(controlCommandCallback, cbdata);
245 VisItSetSlaveProcessCallback(slaveProcessCallback);
246
247 VisItSetGetMetaData(VisItGetMetaData, cbdata);
248 VisItSetGetMesh(VisItGetMesh, cbdata);
249 VisItSetGetVariable(VisItGetVariable, cbdata);
250 VisItSetGetDomainList(VisItGetDomainList, cbdata);
251 VisItTimeStepChanged();
252 connected = true;
253 } else {
254 char *errorString = VisItGetLastError();
255 if (mpiRank == 0) {
256 if (strlen(errorString) > 0) {
257 std::cerr << errorString << std::endl;
258 } else {
259 std::cerr << "VisIt failed to connect successfully"
260 << std::endl;
261 }
262 }
263 free(errorString);
264 }
265 } else if (visitState == 2) {
266 if (!processVisItCommand()) {
267 VisItDisconnect();
268 connected = false;
269 std::cout << "Disconnected." << std::endl;
270 }
271 }
272 } while (visitState != 0);
273 #endif // USE_VISIT
274 }
275
276 } // namespace VisItControl
277
278 } // namespace weipa
279

  ViewVC Help
Powered by ViewVC 1.1.26