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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3096 - (hide annotations)
Thu Aug 19 01:40:52 2010 UTC (9 years 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 caltinay 3096
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