updateplots.c 23.4 KB
Newer Older
hrchilds's avatar
hrchilds committed
1
2
/*****************************************************************************
*
whitlocb's avatar
whitlocb committed
3
* Copyright (c) 2000 - 2010, The Regents of the University of California
hrchilds's avatar
hrchilds committed
4
* Produced at the Lawrence Livermore National Laboratory
brugger's avatar
   
brugger committed
5
* LLNL-CODE-400142
hrchilds's avatar
hrchilds committed
6
7
* All rights reserved.
*
brugger's avatar
   
brugger committed
8
* This file is  part of VisIt. For  details, see https://visit.llnl.gov/.  The
hrchilds's avatar
hrchilds committed
9
10
11
12
13
14
15
16
17
18
* full copyright notice is contained in the file COPYRIGHT located at the root
* of the VisIt distribution or at http://www.llnl.gov/visit/copyright.html.
*
* Redistribution  and  use  in  source  and  binary  forms,  with  or  without
* modification, are permitted provided that the following conditions are met:
*
*  - Redistributions of  source code must  retain the above  copyright notice,
*    this list of conditions and the disclaimer below.
*  - Redistributions in binary form must reproduce the above copyright notice,
*    this  list of  conditions  and  the  disclaimer (as noted below)  in  the
brugger's avatar
   
brugger committed
19
20
21
*    documentation and/or other materials provided with the distribution.
*  - Neither the name of  the LLNS/LLNL nor the names of  its contributors may
*    be used to endorse or promote products derived from this software without
hrchilds's avatar
hrchilds committed
22
23
24
25
26
*    specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT  HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR  IMPLIED WARRANTIES, INCLUDING,  BUT NOT  LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND  FITNESS FOR A PARTICULAR  PURPOSE
brugger's avatar
   
brugger committed
27
28
29
* ARE  DISCLAIMED. IN  NO EVENT  SHALL LAWRENCE  LIVERMORE NATIONAL  SECURITY,
* LLC, THE  U.S.  DEPARTMENT OF  ENERGY  OR  CONTRIBUTORS BE  LIABLE  FOR  ANY
* DIRECT,  INDIRECT,   INCIDENTAL,   SPECIAL,   EXEMPLARY,  OR   CONSEQUENTIAL
hrchilds's avatar
hrchilds committed
30
31
32
33
34
35
36
37
38
39
* DAMAGES (INCLUDING, BUT NOT  LIMITED TO, PROCUREMENT OF  SUBSTITUTE GOODS OR
* SERVICES; LOSS OF  USE, DATA, OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER
* CAUSED  AND  ON  ANY  THEORY  OF  LIABILITY,  WHETHER  IN  CONTRACT,  STRICT
* LIABILITY, OR TORT  (INCLUDING NEGLIGENCE OR OTHERWISE)  ARISING IN ANY  WAY
* OUT OF THE  USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*
*****************************************************************************/

/* SIMPLE SIMULATION SKELETON */
whitlocb's avatar
whitlocb committed
40
41
42
#include <VisItControlInterface_V2.h>
#include <VisItDataInterface_V2.h>

hrchilds's avatar
hrchilds committed
43
44
#include <stdio.h>
#include <string.h>
whitlocb's avatar
whitlocb committed
45
#include <stdlib.h>
hrchilds's avatar
hrchilds committed
46
47
48
49
50
#include <math.h>
#ifdef PARALLEL
#include <mpi.h>
#endif

51
52
#include "SimulationExample.h"

hrchilds's avatar
hrchilds committed
53
54
55
56
#define VISIT_COMMAND_PROCESS 0
#define VISIT_COMMAND_SUCCESS 1
#define VISIT_COMMAND_FAILURE 2

whitlocb's avatar
whitlocb committed
57
58
void read_input_deck(void) { }
/* Data Access Function prototypes */
59
visit_handle SimGetMetaData(void *);
whitlocb's avatar
whitlocb committed
60
visit_handle SimGetMesh(int, const char *, void *);
61
visit_handle SimGetCurve(const char *name, void *);
whitlocb's avatar
whitlocb committed
62
visit_handle SimGetVariable(int, const char *, void *);
63
visit_handle SimGetDomainList(const char *, void *);
whitlocb's avatar
whitlocb committed
64
65
66
67

/******************************************************************************
 * Simulation data and functions
 ******************************************************************************/
hrchilds's avatar
hrchilds committed
68

whitlocb's avatar
whitlocb committed
69
70
#define SIM_STOPPED       0
#define SIM_RUNNING       1
hrchilds's avatar
hrchilds committed
71

whitlocb's avatar
whitlocb committed
72
73
74
75
76
77
78
79
80
81
82
typedef struct
{
    int     par_rank;
    int     par_size;
    int     cycle;
    double  time;
    int     runMode;
    int     done;
    int     savingFiles;
    int     saveCounter;
} simulation_data;
hrchilds's avatar
hrchilds committed
83

whitlocb's avatar
whitlocb committed
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
void
simulation_data_ctor(simulation_data *sim)
{
    sim->par_rank = 0;
    sim->par_size = 1;
    sim->cycle = 0;
    sim->time = 0.;
    sim->runMode = SIM_STOPPED;
    sim->done = 0;
    sim->savingFiles = 0;
    sim->saveCounter = 0;
}

void
simulation_data_dtor(simulation_data *sim)
{
}
hrchilds's avatar
hrchilds committed
101

102
103
const char *cmd_names[] = {"halt", "step", "run", "addplot"};

hrchilds's avatar
hrchilds committed
104
105
106
107
108
109
110
111
/******************************************************************************
 ******************************************************************************
 ***
 *** EVENT PROCESSING FUNCTIONS
 ***
 ******************************************************************************
 *****************************************************************************/

whitlocb's avatar
whitlocb committed
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
/******************************************************************************
 *
 * Purpose: This function simulates one time step
 *
 * Programmer: Brad Whitlock
 * Date:       Fri Jan 12 13:37:17 PST 2007
 *
 * Modifications:
 *   Brad Whitlock, Tue Jun 17 16:09:51 PDT 2008
 *   Call VisItTimeStepChanged on all processors to prevent a "merge"
 *   exception in the engine.
 *
 *****************************************************************************/
void simulate_one_timestep(simulation_data *sim)
{
    ++sim->cycle;
    sim->time += (M_PI / 10.);

    if(sim->par_rank == 0)
        printf("Simulating time step: cycle=%d, time=%lg\n", sim->cycle, sim->time);

    VisItTimeStepChanged();
    VisItUpdatePlots();

    if(sim->savingFiles)
    {
        char filename[100];
        sprintf(filename, "updateplots%04d.jpg", sim->saveCounter);
        if(VisItSaveWindow(filename, 800, 800, VISIT_IMAGEFORMAT_JPEG) == VISIT_OKAY)
        {
            sim->saveCounter++;
            if(sim->par_rank == 0)
                printf("Saved %s\n", filename);
        }
        else if(sim->par_rank == 0)
            printf("The image could not be saved to %s\n", filename);
    }
}

hrchilds's avatar
hrchilds committed
151
152
153
154
/* Callback function for control commands, which are the buttons in the 
 * GUI's Simulation window. This type of command is handled automatically
 * provided that you have registered a command callback such as this.
 */
whitlocb's avatar
whitlocb committed
155
void ControlCommandCallback(const char *cmd, const char *args, void *cbdata)
hrchilds's avatar
hrchilds committed
156
{
whitlocb's avatar
whitlocb committed
157
158
    simulation_data *sim = (simulation_data *)cbdata;

hrchilds's avatar
hrchilds committed
159
    if(strcmp(cmd, "halt") == 0)
whitlocb's avatar
whitlocb committed
160
        sim->runMode = SIM_STOPPED;
hrchilds's avatar
hrchilds committed
161
    else if(strcmp(cmd, "step") == 0)
whitlocb's avatar
whitlocb committed
162
        simulate_one_timestep(sim);
hrchilds's avatar
hrchilds committed
163
    else if(strcmp(cmd, "run") == 0)
whitlocb's avatar
whitlocb committed
164
165
166
167
168
169
        sim->runMode = SIM_RUNNING;
    else if(strcmp(cmd, "addplot") == 0)
    {
        VisItExecuteCommand("AddPlot(\"Pseudocolor\", \"zonal\")\n");
        VisItExecuteCommand("DrawPlots()\n");
    }
hrchilds's avatar
hrchilds committed
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
}

/* CHANGE 1 */
#ifdef PARALLEL
static int visit_broadcast_int_callback(int *value, int sender)
{
    return MPI_Bcast(value, 1, MPI_INT, sender, MPI_COMM_WORLD);
}

static int visit_broadcast_string_callback(char *str, int len, int sender)
{
    return MPI_Bcast(str, len, MPI_CHAR, sender, MPI_COMM_WORLD);
}
#endif


/* Helper function for ProcessVisItCommand */
static void BroadcastSlaveCommand(int *command)
{
#ifdef PARALLEL
    MPI_Bcast(command, 1, MPI_INT, 0, MPI_COMM_WORLD);
#endif
}

/* Callback involved in command communication. */
void SlaveProcessCallback()
{
   int command = VISIT_COMMAND_PROCESS;
   BroadcastSlaveCommand(&command);
}

/* Process commands from viewer on all processors. */
whitlocb's avatar
whitlocb committed
202
int ProcessVisItCommand(simulation_data *sim)
hrchilds's avatar
hrchilds committed
203
204
{
    int command;
whitlocb's avatar
whitlocb committed
205
    if (sim->par_rank==0)
hrchilds's avatar
hrchilds committed
206
207
208
    {  
        int success = VisItProcessEngineCommand();

209
        if (success == VISIT_OKAY)
hrchilds's avatar
hrchilds committed
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
        {
            command = VISIT_COMMAND_SUCCESS;
            BroadcastSlaveCommand(&command);
            return 1;
        }
        else
        {
            command = VISIT_COMMAND_FAILURE;
            BroadcastSlaveCommand(&command);
            return 0;
        }
    }
    else
    {
        /* Note: only through the SlaveProcessCallback callback
         * above can the rank 0 process send a VISIT_COMMAND_PROCESS
         * instruction to the non-rank 0 processes. */
        while (1)
        {
            BroadcastSlaveCommand(&command);
            switch (command)
            {
            case VISIT_COMMAND_PROCESS:
                VisItProcessEngineCommand();
                break;
            case VISIT_COMMAND_SUCCESS:
                return 1;
            case VISIT_COMMAND_FAILURE:
                return 0;
            }
        }
    }
}

/* Called to handle case 3 from VisItDetectInput where we have console
 * input that needs to be processed in order to accomplish an action.
 */
void
whitlocb's avatar
whitlocb committed
248
ProcessConsoleCommand(simulation_data *sim)
hrchilds's avatar
hrchilds committed
249
250
{
    /* Read A Command */
whitlocb's avatar
whitlocb committed
251
    char cmd[1000];
hrchilds's avatar
hrchilds committed
252

whitlocb's avatar
whitlocb committed
253
    if (sim->par_rank == 0)
hrchilds's avatar
hrchilds committed
254
    {
whitlocb's avatar
whitlocb committed
255
        int iseof = (fgets(cmd, 1000, stdin) == NULL);
hrchilds's avatar
hrchilds committed
256
257
        if (iseof)
        {
whitlocb's avatar
whitlocb committed
258
            sprintf(cmd, "quit");
hrchilds's avatar
hrchilds committed
259
260
261
            printf("quit\n");
        }

whitlocb's avatar
whitlocb committed
262
263
        if (strlen(cmd)>0 && cmd[strlen(cmd)-1] == '\n')
            cmd[strlen(cmd)-1] = '\0';
hrchilds's avatar
hrchilds committed
264
265
266
267
    }

#ifdef PARALLEL
    /* Broadcast the command to all processors. */
whitlocb's avatar
whitlocb committed
268
    MPI_Bcast(cmd, 1000, MPI_CHAR, 0, MPI_COMM_WORLD);
hrchilds's avatar
hrchilds committed
269
270
#endif

whitlocb's avatar
whitlocb committed
271
272
273
274
275
276
277
278
279
    if(strcmp(cmd, "quit") == 0)
        sim->done = 1;
    else if(strcmp(cmd, "halt") == 0)
        sim->runMode = SIM_STOPPED;
    else if(strcmp(cmd, "step") == 0)
        simulate_one_timestep(sim);
    else if(strcmp(cmd, "run") == 0)
        sim->runMode = SIM_RUNNING;
    else if(strcmp(cmd, "update") == 0)
hrchilds's avatar
hrchilds committed
280
    {
whitlocb's avatar
whitlocb committed
281
282
        VisItTimeStepChanged();
        VisItUpdatePlots();
hrchilds's avatar
hrchilds committed
283
    }
whitlocb's avatar
whitlocb committed
284
285
286
287
288
    else if(strcmp(cmd, "saveon") == 0)
        sim->savingFiles = 1;
    else if(strcmp(cmd, "saveoff") == 0)
        sim->savingFiles = 0;
    else if(strcmp(cmd, "addplot") == 0)
289
290
291
292
    {
        VisItExecuteCommand("AddPlot(\"Pseudocolor\", \"zonal\")\n");
        VisItExecuteCommand("DrawPlots()\n");
    }
hrchilds's avatar
hrchilds committed
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
}

/******************************************************************************
 *
 * Function: mainloop
 *
 * Purpose: Handles the program's main event loop and dispatches events to 
 *          other functions for processing.
 *
 * Programmer: Brad Whitlock
 * Date:       Thu Nov 2 17:26:08 PST 2006
 *
 * Modifications:
 *
 *****************************************************************************/

whitlocb's avatar
whitlocb committed
309
void mainloop(simulation_data *sim)
hrchilds's avatar
hrchilds committed
310
311
312
{
    int blocking, visitstate, err = 0;

whitlocb's avatar
whitlocb committed
313
314
315
316
317
318
319
    /* If we're not running by default then simulate once there's something
     * once VisIt connects.
     */
    if(sim->runMode == SIM_STOPPED)
        simulate_one_timestep(sim);

    if (sim->par_rank == 0)
hrchilds's avatar
hrchilds committed
320
321
322
323
324
325
326
    {
        fprintf(stderr, "command> ");
        fflush(stderr);
    }

    do
    {
whitlocb's avatar
whitlocb committed
327
        blocking = (sim->runMode == SIM_RUNNING) ? 0 : 1;
hrchilds's avatar
hrchilds committed
328
        /* Get input from VisIt or timeout so the simulation can run. */
whitlocb's avatar
whitlocb committed
329
        if(sim->par_rank == 0)
hrchilds's avatar
hrchilds committed
330
331
332
333
334
335
336
337
338
339
340
341
        {
            visitstate = VisItDetectInput(blocking, fileno(stdin));
        }
#ifdef PARALLEL
        /* Broadcast the return value of VisItDetectInput to all procs. */
        MPI_Bcast(&visitstate, 1, MPI_INT, 0, MPI_COMM_WORLD);
#endif
        /* Do different things depending on the output from VisItDetectInput. */
        switch(visitstate)
        {
        case 0:
            /* There was no input from VisIt, return control to sim. */
whitlocb's avatar
whitlocb committed
342
            simulate_one_timestep(sim);
hrchilds's avatar
hrchilds committed
343
344
345
            break;
        case 1:
            /* VisIt is trying to connect to sim. */
346
            if(VisItAttemptToCompleteConnection() == VISIT_OKAY)
hrchilds's avatar
hrchilds committed
347
348
            {
                fprintf(stderr, "VisIt connected\n");
whitlocb's avatar
whitlocb committed
349
                VisItSetCommandCallback(ControlCommandCallback, (void*)sim);
hrchilds's avatar
hrchilds committed
350
                VisItSetSlaveProcessCallback(SlaveProcessCallback);
whitlocb's avatar
whitlocb committed
351
352
353
354
355
356

                VisItSetGetMetaData(SimGetMetaData, (void*)sim);
                VisItSetGetMesh(SimGetMesh, (void*)sim);
                VisItSetGetCurve(SimGetCurve, (void*)sim);
                VisItSetGetVariable(SimGetVariable, (void*)sim);
                VisItSetGetDomainList(SimGetDomainList, (void*)sim);
hrchilds's avatar
hrchilds committed
357
            }
whitlocb's avatar
whitlocb committed
358
359
360
361
362
363
364
            else 
            {
                /* Print the error message */
                char *err = VisItGetLastError();
                fprintf(stderr, "VisIt did not connect: %s\n", err);
                free(err);
            }
hrchilds's avatar
hrchilds committed
365
366
367
            break;
        case 2:
            /* VisIt wants to tell the engine something. */
whitlocb's avatar
whitlocb committed
368
            if(!ProcessVisItCommand(sim))
hrchilds's avatar
hrchilds committed
369
370
371
372
            {
                /* Disconnect on an error or closed connection. */
                VisItDisconnect();
                /* Start running again if VisIt closes. */
373
                /*sim->runMode = SIM_RUNNING;*/
hrchilds's avatar
hrchilds committed
374
375
376
377
378
379
380
            }
            break;
        case 3:
            /* VisItDetectInput detected console input - do something with it.
             * NOTE: you can't get here unless you pass a file descriptor to
             * VisItDetectInput instead of -1.
             */
whitlocb's avatar
whitlocb committed
381
382
            ProcessConsoleCommand(sim);
            if (sim->par_rank == 0)
hrchilds's avatar
hrchilds committed
383
384
385
386
387
388
389
390
391
392
            {
                fprintf(stderr, "command> ");
                fflush(stderr);
            }
            break;
        default:
            fprintf(stderr, "Can't recover from error %d!\n", visitstate);
            err = 1;
            break;
        }
whitlocb's avatar
whitlocb committed
393
    } while(!sim->done && err == 0);
hrchilds's avatar
hrchilds committed
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
}

/******************************************************************************
 *
 * Purpose: This is the main function for the program.
 *
 * Programmer: Brad Whitlock
 * Date:       Fri Jan 12 13:36:17 PST 2007
 *
 * Input Arguments:
 *   argc : The number of command line arguments.
 *   argv : The command line arguments.
 *
 * Modifications:
 *
 *****************************************************************************/

int main(int argc, char **argv)
{
413
414
415
    simulation_data sim;
    simulation_data_ctor(&sim);

416
417
418
419
    /* Initialize environment variables. */
    SimulationArguments(argc, argv);
    VisItSetupEnvironment();

hrchilds's avatar
hrchilds committed
420
421
422
#ifdef PARALLEL
    /* Initialize MPI */
    MPI_Init(&argc, &argv);
whitlocb's avatar
whitlocb committed
423
424
    MPI_Comm_rank (MPI_COMM_WORLD, &sim.par_rank);
    MPI_Comm_size (MPI_COMM_WORLD, &sim.par_size);
hrchilds's avatar
hrchilds committed
425
426
427
428
429

    /* Install callback functions for global communication. */
    VisItSetBroadcastIntFunction(visit_broadcast_int_callback);
    VisItSetBroadcastStringFunction(visit_broadcast_string_callback);
    /* Tell VSIL whether the simulation is parallel. */
whitlocb's avatar
whitlocb committed
430
431
    VisItSetParallel(sim.par_size > 1);
    VisItSetParallelRank(sim.par_rank);
hrchilds's avatar
hrchilds committed
432
433
434
435
436
437
#endif

    /* Write out .sim file that VisIt uses to connect. Only do it
     * on processor 0.
     */
    /* CHANGE 3 */
whitlocb's avatar
whitlocb committed
438
    if(sim.par_rank == 0)
hrchilds's avatar
hrchilds committed
439
440
    {
        /* Write out .sim file that VisIt uses to connect. */
441
442
443
444
445
446
        VisItInitializeSocketAndDumpSimFile(
#ifdef PARALLEL
            "updateplots_par",
#else
            "updateplots",
#endif
hrchilds's avatar
hrchilds committed
447
448
            "Demonstrates VisItUpdatePlots function",
            "/path/to/where/sim/was/started",
449
            NULL, NULL, NULL);
hrchilds's avatar
hrchilds committed
450
451
452
453
454
455
    }

    /* Read input problem setup, geometry, data.*/
    read_input_deck();

    /* Call the main loop. */
whitlocb's avatar
whitlocb committed
456
    mainloop(&sim);
hrchilds's avatar
hrchilds committed
457

whitlocb's avatar
whitlocb committed
458
    simulation_data_dtor(&sim);
hrchilds's avatar
hrchilds committed
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
#ifdef PARALLEL
    MPI_Finalize();
#endif

    return 0;
}

/* DATA ACCESS FUNCTIONS */

/******************************************************************************
 *
 * Purpose: This callback function returns simulation metadata.
 *
 * Programmer: Brad Whitlock
 * Date:       Fri Jan 12 13:37:17 PST 2007
 *
 * Modifications:
 *
 *****************************************************************************/

479
480
visit_handle
SimGetMetaData(void *cbdata)
hrchilds's avatar
hrchilds committed
481
{
482
    visit_handle md = VISIT_INVALID_HANDLE;
whitlocb's avatar
whitlocb committed
483
    simulation_data *sim = (simulation_data *)cbdata;
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553

    /* Create metadata. */
    if(VisIt_SimulationMetaData_alloc(&md) == VISIT_OKAY)
    {
        int i;
        visit_handle mmd = VISIT_INVALID_HANDLE;
        visit_handle vmd = VISIT_INVALID_HANDLE;
        visit_handle cmd = VISIT_INVALID_HANDLE;
        visit_handle emd = VISIT_INVALID_HANDLE;

        /* Set the simulation state. */
        VisIt_SimulationMetaData_setMode(md, (sim->runMode == SIM_STOPPED) ?
            VISIT_SIMMODE_STOPPED : VISIT_SIMMODE_RUNNING);
        VisIt_SimulationMetaData_setCycleTime(md, sim->cycle, sim->time);

        /* Add mesh metadata. */
        if(VisIt_MeshMetaData_alloc(&mmd) == VISIT_OKAY)
        {
            /* Set the mesh's properties.*/
            VisIt_MeshMetaData_setName(mmd, "mesh2d");
            VisIt_MeshMetaData_setMeshType(mmd, VISIT_MESHTYPE_RECTILINEAR);
            VisIt_MeshMetaData_setTopologicalDimension(mmd, 2);
            VisIt_MeshMetaData_setSpatialDimension(mmd, 2);
            VisIt_MeshMetaData_setNumDomains(mmd, sim->par_size);
            VisIt_MeshMetaData_setDomainTitle(mmd, "Domains");
            VisIt_MeshMetaData_setDomainPieceName(mmd, "domain");
            VisIt_MeshMetaData_setNumGroups(mmd, 0);
            VisIt_MeshMetaData_setXUnits(mmd, "cm");
            VisIt_MeshMetaData_setYUnits(mmd, "cm");
            VisIt_MeshMetaData_setZUnits(mmd, "cm");
            VisIt_MeshMetaData_setXLabel(mmd, "Width");
            VisIt_MeshMetaData_setYLabel(mmd, "Height");
            VisIt_MeshMetaData_setZLabel(mmd, "Depth");

            VisIt_SimulationMetaData_addMesh(md, mmd);
        }

        /* Add a variable. */
        if(VisIt_VariableMetaData_alloc(&vmd) == VISIT_OKAY)
        {
            VisIt_VariableMetaData_setName(vmd, "zonal");
            VisIt_VariableMetaData_setMeshName(vmd, "mesh2d");
            VisIt_VariableMetaData_setType(vmd, VISIT_VARTYPE_SCALAR);
            VisIt_VariableMetaData_setCentering(vmd, VISIT_VARCENTERING_ZONE);

            VisIt_SimulationMetaData_addVariable(md, vmd);
        }

        /* Add a curve variable. */
        if(VisIt_CurveMetaData_alloc(&cmd) == VISIT_OKAY)
        {
            VisIt_CurveMetaData_setName(cmd, "sine");
            VisIt_CurveMetaData_setXLabel(cmd, "Angle");
            VisIt_CurveMetaData_setXUnits(cmd, "radians");
            VisIt_CurveMetaData_setYLabel(cmd, "Amplitude");
            VisIt_CurveMetaData_setYUnits(cmd, "");

            VisIt_SimulationMetaData_addCurve(md, cmd);
        }

        /* Add an expression. */
        if(VisIt_ExpressionMetaData_alloc(&emd) == VISIT_OKAY)
        {
            VisIt_ExpressionMetaData_setName(emd, "zvec");
            VisIt_ExpressionMetaData_setDefinition(emd, "{zonal, zonal}");
            VisIt_ExpressionMetaData_setType(emd, VISIT_VARTYPE_VECTOR);

            VisIt_SimulationMetaData_addExpression(md, emd);
        }
            
554
        /* Add some commands. */
555
556
557
558
559
560
561
562
563
564
565
566
        for(i = 0; i < sizeof(cmd_names)/sizeof(const char *); ++i)
        {
            visit_handle cmd = VISIT_INVALID_HANDLE;
            if(VisIt_CommandMetaData_alloc(&cmd) == VISIT_OKAY)
            {
                VisIt_CommandMetaData_setName(cmd, cmd_names[i]);
                VisIt_SimulationMetaData_addGenericCommand(md, cmd);
            }
        }
    }

    return md;
hrchilds's avatar
hrchilds committed
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
}

/* Rectilinear mesh */
#define RNX 50
#define RNY 50
int   rmesh_dims[] = {RNX, RNY, 1};
int   rmesh_ndims = 2;

/******************************************************************************
 *
 * Purpose: This callback function returns meshes.
 *
 * Programmer: Brad Whitlock
 * Date:       Fri Jan 12 13:37:17 PST 2007
 *
 * Modifications:
 *
 *****************************************************************************/

whitlocb's avatar
whitlocb committed
586
587
visit_handle
SimGetMesh(int domain, const char *name, void *cbdata)
hrchilds's avatar
hrchilds committed
588
{
whitlocb's avatar
whitlocb committed
589
    visit_handle h = VISIT_INVALID_HANDLE;
hrchilds's avatar
hrchilds committed
590
591
592

    if(strcmp(name, "mesh2d") == 0)
    {
whitlocb's avatar
whitlocb committed
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
        if(VisIt_RectilinearMesh_alloc(&h) != VISIT_ERROR)
        {
            int i, minRealIndex[3]={0,0,0}, maxRealIndex[3]={0,0,0};
            float *rmesh_x, *rmesh_y;
            visit_handle hx, hy;

            maxRealIndex[0] = rmesh_dims[0]-1;
            maxRealIndex[1] = rmesh_dims[1]-1;
            maxRealIndex[2] = rmesh_dims[2]-1;

            rmesh_x = (float *)malloc(sizeof(float) * RNX);
            for(i = 0; i < RNX; ++i)
                rmesh_x[i] = ((float)i / (float)(RNX-1)) * 5. - 2.5 + 5 * domain;
            rmesh_y = (float *)malloc(sizeof(float) * RNY);
            for(i = 0; i < RNY; ++i)
                rmesh_y[i] = ((float)i / (float)(RNY-1)) * 5. - 2.5;

            VisIt_VariableData_alloc(&hx);
            VisIt_VariableData_alloc(&hy);
            VisIt_VariableData_setDataF(hx, VISIT_OWNER_VISIT, 1, RNX, rmesh_x);
            VisIt_VariableData_setDataF(hy, VISIT_OWNER_VISIT, 1, RNY, rmesh_y);
            VisIt_RectilinearMesh_setCoordsXY(h, hx, hy);
            VisIt_RectilinearMesh_setRealIndices(h, minRealIndex, maxRealIndex);
        }
hrchilds's avatar
hrchilds committed
617
618
    }

whitlocb's avatar
whitlocb committed
619
    return h;
hrchilds's avatar
hrchilds committed
620
621
622
623
624
625
626
627
628
629
630
631
632
}

/******************************************************************************
 *
 * Purpose: This callback function returns scalars.
 *
 * Programmer: Brad Whitlock
 * Date:       Fri Jan 12 13:37:17 PST 2007
 *
 * Modifications:
 *
 *****************************************************************************/

whitlocb's avatar
whitlocb committed
633
634
visit_handle
SimGetVariable(int domain, const char *name, void *cbdata)
hrchilds's avatar
hrchilds committed
635
{
whitlocb's avatar
whitlocb committed
636
    visit_handle h = VISIT_INVALID_HANDLE;
whitlocb's avatar
whitlocb committed
637
    simulation_data *sim = (simulation_data *)cbdata;
hrchilds's avatar
hrchilds committed
638
639
640
641
642

    if(strcmp(name, "zonal") == 0)
    {
        float angle, xpos, ypos, cellX, cellY, dX, dY, tx, ty, *zoneptr;
        float sx, ex, sy, ey, *rmesh_zonal;
643
        int i, j, nTuples;
hrchilds's avatar
hrchilds committed
644
645
646
647
648
649
650
651
652

        sx = -2.5  + domain * 5.;
        ex = sx + 5.;
        sy = -2.5;
        ey = sy + 5.;

        /* Calculate a zonal variable that moves around. */
        rmesh_zonal = (float*)malloc(sizeof(float) * (RNX-1) * (RNY-1));
        zoneptr = rmesh_zonal;
whitlocb's avatar
whitlocb committed
653
        angle = sim->time;
hrchilds's avatar
hrchilds committed
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
        xpos = 2.5 * cos(angle);
        ypos = 2.5 * sin(angle);
        for(j = 0; j < rmesh_dims[1]-1; ++j)
        {
            ty = (float)j / (float)(rmesh_dims[1]-1-1);
            cellY = (1.-ty)*sy + ey*ty;
            dY = cellY - ypos;
            for(i = 0; i < rmesh_dims[0]-1; ++i)
            {
                tx = (float)i / (float)(rmesh_dims[0]-1-1);
                cellX = (1.-tx)*sx + ex*tx;
                dX = cellX - xpos;
                *zoneptr++ = sqrt(dX * dX + dY * dY);
            }
        }

670
        nTuples = (rmesh_dims[0]-1) * (rmesh_dims[1]-1);
whitlocb's avatar
whitlocb committed
671
672
        VisIt_VariableData_alloc(&h);
        VisIt_VariableData_setDataF(h, VISIT_OWNER_VISIT, 1,
673
            nTuples, rmesh_zonal);
hrchilds's avatar
hrchilds committed
674
675
    }

whitlocb's avatar
whitlocb committed
676
    return h;
hrchilds's avatar
hrchilds committed
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
}

/******************************************************************************
 *
 * Purpose: This callback function returns a curve.
 *
 * Programmer: Brad Whitlock
 * Date:       Fri Jan 12 13:37:17 PST 2007
 *
 * Modifications:
 *   Brad Whitlock, Thu Jan 25 15:46:19 PST 2007
 *   Added simtime into the angle so the plot will animate.
 *
 *****************************************************************************/

692
693
visit_handle
SimGetCurve(const char *name, void *cbdata)
hrchilds's avatar
hrchilds committed
694
{
695
    int h = VISIT_INVALID_HANDLE;
whitlocb's avatar
whitlocb committed
696
    simulation_data *sim = (simulation_data *)cbdata;
hrchilds's avatar
hrchilds committed
697
698
699

    if(strcmp(name, "sine") == 0)
    {
700
        if(VisIt_CurveData_alloc(&h) != VISIT_ERROR)
hrchilds's avatar
hrchilds committed
701
        {
702
            visit_handle hxc, hyc;
703
704
705
706
707
708
709
710
711
712
713
            int i;
            float *x = NULL, *y = NULL;
            x = (float*)malloc(200 * sizeof(float));
            y = (float*)malloc(200 * sizeof(float));
        
            for(i = 0; i < 200; ++i)
            {
                float angle = sim->time + ((float)i / (float)(200-1)) * 4. * M_PI;
                x[i] = angle;
                y[i] = sin(x[i]);
            }
whitlocb's avatar
whitlocb committed
714

715
            /* Give the arrays to VisIt. VisIt will free them. */
716
717
718
719
720
            VisIt_VariableData_alloc(&hxc);
            VisIt_VariableData_alloc(&hyc);
            VisIt_VariableData_setDataF(hxc, VISIT_OWNER_VISIT, 1, 200, x);
            VisIt_VariableData_setDataF(hyc, VISIT_OWNER_VISIT, 1, 200, y);
            VisIt_CurveData_setCoordsXY(h, hxc, hyc);
721
        }
hrchilds's avatar
hrchilds committed
722
723
    }

724
    return h;
hrchilds's avatar
hrchilds committed
725
726
727
728
729
730
731
732
733
734
735
736
737
}

/******************************************************************************
 *
 * Purpose: This callback function returns a domain list.
 *
 * Programmer: Brad Whitlock
 * Date:       Fri Jan 12 13:37:17 PST 2007
 *
 * Modifications:
 *
 *****************************************************************************/

738
739
visit_handle
SimGetDomainList(const char *name, void *cbdata)
hrchilds's avatar
hrchilds committed
740
{
741
742
743
744
745
746
    visit_handle h = VISIT_INVALID_HANDLE;
    if(VisIt_DomainList_alloc(&h) != VISIT_ERROR)
    {
        visit_handle hdl;
        int i, *iptr = NULL;
        simulation_data *sim = (simulation_data *)cbdata;
hrchilds's avatar
hrchilds committed
747

748
749
        iptr = (int *)malloc(sizeof(int));
        *iptr = sim->par_rank;
hrchilds's avatar
hrchilds committed
750

751
752
753
754
755
        VisIt_VariableData_alloc(&hdl);
        VisIt_VariableData_setDataI(hdl, VISIT_OWNER_VISIT, 1, 1, iptr);
        VisIt_DomainList_setDomains(h, sim->par_size, hdl);
    }
    return h;
hrchilds's avatar
hrchilds committed
756
}