1 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
2 // Copyright (c) Lawrence Livermore National Security, LLC and other Ascent
3 // Project developers. See top-level LICENSE AND COPYRIGHT files for dates and
4 // other details. No copyright assignment is required to contribute to Ascent.
5 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
6 //-----------------------------------------------------------------------------
7 ///
8 /// file: t_ascent_cinema_a.cpp
9 ///
10 //-----------------------------------------------------------------------------
11 
12 #include "gtest/gtest.h"
13 
14 #include <ascent.hpp>
15 
16 #include <iostream>
17 #include <math.h>
18 
19 #include <conduit_blueprint.hpp>
20 
21 #include "t_config.hpp"
22 #include "t_utils.hpp"
23 
24 
25 
26 using namespace std;
27 using namespace conduit;
28 using namespace ascent;
29 
30 index_t EXAMPLE_MESH_SIDE_DIM = 32;
31 
32 //-----------------------------------------------------------------------------
TEST(ascent_triggers,simple_rick)33 TEST(ascent_triggers, simple_rick)
34 {
35     // the vtkm runtime is currently our only rendering runtime
36     Node n;
37     ascent::about(n);
38 
39     //
40     // Create example mesh.
41     //
42     Node data, verify_info;
43     conduit::blueprint::mesh::examples::braid("hexs",
44                                                EXAMPLE_MESH_SIDE_DIM,
45                                                EXAMPLE_MESH_SIDE_DIM,
46                                                EXAMPLE_MESH_SIDE_DIM,
47                                                data);
48 
49     EXPECT_TRUE(conduit::blueprint::mesh::verify(data,verify_info));
50 
51     string output_path = prepare_output_dir();
52     string trigger_file = conduit::utils::join_file_path(output_path,"simple_trigger_actions");
53     string output_file = conduit::utils::join_file_path(output_path,"tout_simple_trigger_actions");
54     // remove old file
55     if(conduit::utils::is_file(trigger_file))
56     {
57         conduit::utils::remove_file(trigger_file);
58     }
59 
60 
61     //
62     // Create trigger actions.
63     //
64     Node trigger_actions;
65 
66     conduit::Node extracts;
67 
68     extracts["e1/type"]  = "relay";
69     extracts["e1/params/path"] = output_file;
70     extracts["e1/params/protocol"] = "blueprint/mesh/hdf5";
71 
72     conduit::Node &add_ext= trigger_actions.append();
73     add_ext["action"] = "add_extracts";
74     add_ext["extracts"] = extracts;
75 
76     trigger_actions.save(trigger_file, "json");
77 
78     //
79     // Create the actions.
80     //
81     Node actions;
82 
83     std::string condition = "1 == 1";
84     conduit::Node triggers;
85     triggers["t1/params/condition"] = condition;
86     triggers["t1/params/actions_file"] = trigger_file;
87 
88     conduit::Node &add_triggers= actions.append();
89     add_triggers["action"] = "add_triggers";
90     add_triggers["triggers"] = triggers;
91     actions.print();
92 
93     //
94     // Run Ascent
95     //
96 
97     Ascent ascent;
98     Node ascent_opts;
99     // default is now ascent
100     ascent_opts["runtime/type"] = "ascent";
101     ascent.open(ascent_opts);
102     ascent.publish(data);
103     ascent.execute(actions);
104 
105     conduit::Node info;
106     ascent.info(info);
107     std::string path = "expressions/" + condition + "/100/value";
108     info["expressions"].print();
109     EXPECT_TRUE(info[path].to_int32() == 1);
110     std::string msg = "A simple example of triggering actions based on a boolean"
111                       " expression.";
112     ASCENT_ACTIONS_DUMP(actions, std::string("basic_trigger"), msg);
113 
114     ascent.close();
115 
116 }
117 
118 //-----------------------------------------------------------------------------
TEST(ascent_triggers,complex_trigger)119 TEST(ascent_triggers, complex_trigger)
120 {
121     // the vtkm runtime is currently our only rendering runtime
122     Node n;
123     ascent::about(n);
124     // only run this test if ascent was built with vtkm support
125     if(n["runtimes/ascent/vtkm/status"].as_string() == "disabled")
126     {
127         ASCENT_INFO("Ascent support disabled, skipping test");
128         return;
129     }
130 
131     //
132     // Create example mesh.
133     //
134     Node data, verify_info;
135     conduit::blueprint::mesh::examples::braid("hexs",
136                                                EXAMPLE_MESH_SIDE_DIM,
137                                                EXAMPLE_MESH_SIDE_DIM,
138                                                EXAMPLE_MESH_SIDE_DIM,
139                                                data);
140 
141     EXPECT_TRUE(conduit::blueprint::mesh::verify(data,verify_info));
142 
143     string output_path = prepare_output_dir();
144     string trigger_file = conduit::utils::join_file_path(output_path,"complex_trigger_actions");
145     string output_file = conduit::utils::join_file_path(output_path,"tout_complex_trigger_actions");
146     // remove old files
147     if(conduit::utils::is_file(trigger_file))
148     {
149       conduit::utils::remove_file(trigger_file);
150     }
151     if(conduit::utils::is_file(output_file))
152     {
153       conduit::utils::remove_file(output_file);
154     }
155 
156     //
157     // Create trigger actions.
158     //
159     Node trigger_actions;
160 
161     conduit::Node scenes;
162     scenes["s1/plots/p1/type"]  = "pseudocolor";
163     scenes["s1/plots/p1/field"] = "radial";
164     scenes["s1/image_prefix"]   = output_file;
165 
166     conduit::Node &add_scenes= trigger_actions.append();
167     add_scenes["action"] = "add_scenes";
168     add_scenes["scenes"] = scenes;
169 
170     trigger_actions.save(trigger_file, "json");
171 
172     //
173     // Create the actions.
174     //
175     Node actions;
176     // this should always be true
177     std::string condition = "magnitude(max(field('braid')).position - vector(0,0,0)) > 0";
178     conduit::Node triggers;
179     triggers["t1/params/condition"] = condition;
180     triggers["t1/params/actions_file"] = trigger_file;
181 
182     conduit::Node &add_triggers= actions.append();
183     add_triggers["action"] = "add_triggers";
184     add_triggers["triggers"] = triggers;
185     actions.print();
186 
187     //
188     // Run Ascent
189     //
190 
191     Ascent ascent;
192     Node ascent_opts;
193     // default is now ascent
194     ascent_opts["runtime/type"] = "ascent";
195     ascent.open(ascent_opts);
196     ascent.publish(data);
197     ascent.execute(actions);
198 
199     conduit::Node info;
200     ascent.info(info);
201     std::string path = "expressions/" + condition + "/100/value";
202     EXPECT_TRUE(info[path].to_uint8() == 1);
203 
204     ascent.close();
205 
206     // check that we created an image from the trigger
207     EXPECT_TRUE(check_test_image(output_file));
208     std::string msg = "A more complex trigger example using several functions"
209                       " that evaluate positons on the mesh.";
210     ASCENT_ACTIONS_DUMP(actions,output_file,msg);
211 }
212 
213 //-----------------------------------------------------------------------------
TEST(ascent_triggers,trigger_extract)214 TEST(ascent_triggers, trigger_extract)
215 {
216     // the vtkm runtime is currently our only rendering runtime
217     Node n;
218     ascent::about(n);
219     // only run this test if ascent was built with vtkm support
220     if(n["runtimes/ascent/vtkm/status"].as_string() == "disabled")
221     {
222         ASCENT_INFO("Ascent support disabled, skipping test");
223         return;
224     }
225 
226     //
227     // Create example mesh.
228     //
229     Node data, verify_info;
230     conduit::blueprint::mesh::examples::braid("hexs",
231                                                EXAMPLE_MESH_SIDE_DIM,
232                                                EXAMPLE_MESH_SIDE_DIM,
233                                                EXAMPLE_MESH_SIDE_DIM,
234                                                data);
235 
236     EXPECT_TRUE(conduit::blueprint::mesh::verify(data,verify_info));
237 
238     string output_path = prepare_output_dir();
239     string trigger_file = conduit::utils::join_file_path(output_path,"trigger_extract_actions");
240     string output_file = conduit::utils::join_file_path(output_path,"tout_trigger_extract");
241     string output_root_file = output_file + ".cycle_000100.root";
242 
243     // remove old files
244     if(conduit::utils::is_file(trigger_file))
245     {
246       conduit::utils::remove_file(trigger_file);
247     }
248 
249     if(conduit::utils::is_file(output_root_file))
250     {
251       conduit::utils::remove_file(output_root_file);
252     }
253 
254     //
255     // Create trigger actions.
256     //
257     Node trigger_actions;
258 
259     conduit::Node extracts;
260 
261     extracts["e1/type"]  = "relay";
262     extracts["e1/params/path"] = output_file;
263     extracts["e1/params/protocol"] = "blueprint/mesh/hdf5";
264 
265     conduit::Node &add_ext= trigger_actions.append();
266     add_ext["action"] = "add_extracts";
267     add_ext["extracts"] = extracts;
268 
269     trigger_actions.save(trigger_file, "json");
270 
271     //
272     // Create the actions.
273     //
274     Node actions;
275     // this should always be true
276     std::string condition = "magnitude(max(field('braid')).position - vector(0,0,0)) > 0";
277     conduit::Node triggers;
278     triggers["t1/params/condition"] = condition;
279     triggers["t1/params/actions_file"] = trigger_file;
280 
281     conduit::Node &add_triggers= actions.append();
282     add_triggers["action"] = "add_triggers";
283     add_triggers["triggers"] = triggers;
284     actions.print();
285 
286     //
287     // Run Ascent
288     //
289 
290     Ascent ascent;
291     Node ascent_opts;
292     // default is now ascent
293     ascent_opts["runtime/type"] = "ascent";
294     ascent.open(ascent_opts);
295     ascent.publish(data);
296     ascent.execute(actions);
297     ascent.close();
298 
299     // check that we created an image from the trigger
300     EXPECT_TRUE(conduit::utils::is_file(output_root_file));
301     std::string msg = "A more complex trigger example using several functions"
302                       " that evaluate positons on the mesh.";
303     ASCENT_ACTIONS_DUMP(actions,output_file,msg);
304 }
305 
306 //-----------------------------------------------------------------------------
TEST(ascent_triggers,trigger_extract_inline_actions)307 TEST(ascent_triggers, trigger_extract_inline_actions)
308 {
309     // the vtkm runtime is currently our only rendering runtime
310     Node n;
311     ascent::about(n);
312     // only run this test if ascent was built with vtkm support
313     if(n["runtimes/ascent/vtkm/status"].as_string() == "disabled")
314     {
315         ASCENT_INFO("Ascent support disabled, skipping test");
316         return;
317     }
318 
319     //
320     // Create example mesh.
321     //
322     Node data, verify_info;
323     conduit::blueprint::mesh::examples::braid("hexs",
324                                                EXAMPLE_MESH_SIDE_DIM,
325                                                EXAMPLE_MESH_SIDE_DIM,
326                                                EXAMPLE_MESH_SIDE_DIM,
327                                                data);
328 
329     EXPECT_TRUE(conduit::blueprint::mesh::verify(data,verify_info));
330 
331     string output_path = prepare_output_dir();
332     string output_file = conduit::utils::join_file_path(output_path,"tout_trigger_extract_inline");
333     // remove old images before rendering
334     remove_test_image(output_file);
335 
336 
337     //
338     // Create the trigger actions.
339     //
340     conduit::Node trigger_scenes;
341     trigger_scenes["s1/plots/p1/type"] = "pseudocolor";
342     trigger_scenes["s1/plots/p1/field"] = "braid";
343     trigger_scenes["s1/image_prefix"] = output_file;
344 
345     conduit::Node trigger_actions;
346     // add the scenes
347     conduit::Node &add_scenes= trigger_actions.append();
348     add_scenes["action"] = "add_scenes";
349     add_scenes["scenes"] = trigger_scenes;
350 
351     //
352     // Create the actions.
353     //
354     Node actions;
355     // this should always be true
356     std::string condition = "magnitude(max(field('braid')).position - vector(0,0,0)) > 0";
357     conduit::Node triggers;
358     triggers["t1/params/condition"] = condition;
359     triggers["t1/params/actions"] = trigger_actions;
360 
361     conduit::Node &add_triggers= actions.append();
362     add_triggers["action"] = "add_triggers";
363     add_triggers["triggers"] = triggers;
364     actions.print();
365 
366     //
367     // Run Ascent
368     //
369 
370     Ascent ascent;
371     Node ascent_opts;
372     // default is now ascent
373     ascent_opts["runtime/type"] = "ascent";
374     ascent.open(ascent_opts);
375     ascent.publish(data);
376     ascent.execute(actions);
377     ascent.close();
378 
379     // check that we created an image from the trigger
380     EXPECT_TRUE(check_test_image(output_file));
381     std::string msg = "An example of specifying trigger actions without a trigger "
382                       "trigger actions file.";
383     ASCENT_ACTIONS_DUMP(actions,output_file,msg);
384 }
385 
386 
387 
388 //-----------------------------------------------------------------------------
main(int argc,char * argv[])389 int main(int argc, char* argv[])
390 {
391     int result = 0;
392 
393     ::testing::InitGoogleTest(&argc, argv);
394 
395     // allow override of the data size via the command line
396     if(argc == 2)
397     {
398         EXAMPLE_MESH_SIDE_DIM = atoi(argv[1]);
399     }
400 
401     result = RUN_ALL_TESTS();
402     return result;
403 }
404 
405 
406