From 38b5b223e4b75ea6cde0edef4aa0bb8873facba7 Mon Sep 17 00:00:00 2001 From: Jan Nikl Date: Fri, 2 May 2025 13:09:49 -0700 Subject: [PATCH 01/56] Fixed the order of source files in Makefile. --- makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/makefile b/makefile index 17548919..44fb9f92 100644 --- a/makefile +++ b/makefile @@ -254,7 +254,7 @@ ALL_SOURCE_FILES = \ lib/gl/shader.cpp lib/gl/types.cpp lib/aux_js.cpp lib/aux_vis.cpp \ lib/coll_reader.cpp lib/data_state.cpp lib/file_reader.cpp \ lib/font.cpp lib/gl2ps.c lib/gltf.cpp lib/material.cpp \ - lib/openglvis.cpp lib/palettes.cpp lib/palettes_base.cpp lib/sdl.cpp \ + lib/openglvis.cpp lib/palettes_base.cpp lib/palettes.cpp lib/sdl.cpp \ lib/sdl_helper.cpp lib/sdl_main.cpp lib/sdl_windows.cpp \ lib/sdl_x11.cpp lib/stream_reader.cpp lib/threads.cpp lib/vsdata.cpp \ lib/vssolution.cpp lib/vssolution3d.cpp lib/vsvector.cpp \ @@ -275,8 +275,8 @@ HEADER_FILES = \ lib/gl/types.hpp lib/aux_vis.hpp lib/coll_reader.hpp \ lib/data_state.hpp lib/file_reader.hpp lib/font.hpp \ lib/geom_utils.hpp lib/gl2ps.h lib/gltf.hpp lib/logo.hpp \ - lib/material.hpp lib/openglvis.hpp lib/palettes.hpp \ - lib/palettes_base.hpp lib/sdl.hpp lib/sdl_helper.hpp lib/sdl_mac.hpp \ + lib/material.hpp lib/openglvis.hpp lib/palettes_base.hpp \ + lib/palettes.hpp lib/sdl_helper.hpp lib/sdl.hpp lib/sdl_mac.hpp \ lib/sdl_main.hpp lib/sdl_windows.hpp lib/sdl_x11.hpp \ lib/stream_reader.hpp lib/threads.hpp lib/visual.hpp lib/vsdata.hpp \ lib/vssolution.hpp lib/vssolution3d.hpp lib/vsvector.hpp \ From 360ca25217f77062addb8c8519dee0980d97f39c Mon Sep 17 00:00:00 2001 From: Jan Nikl Date: Fri, 2 May 2025 13:20:05 -0700 Subject: [PATCH 02/56] Separated script control functions. --- glvis.cpp | 846 +----------------------------------- lib/CMakeLists.txt | 2 + lib/script_controller.cpp | 878 ++++++++++++++++++++++++++++++++++++++ lib/script_controller.hpp | 19 + makefile | 18 +- 5 files changed, 909 insertions(+), 854 deletions(-) create mode 100644 lib/script_controller.cpp create mode 100644 lib/script_controller.hpp diff --git a/glvis.cpp b/glvis.cpp index 8c5721d3..f526fd02 100644 --- a/glvis.cpp +++ b/glvis.cpp @@ -34,6 +34,7 @@ #include "mfem.hpp" #include "lib/palettes.hpp" #include "lib/visual.hpp" +#include "lib/script_controller.hpp" #include "lib/stream_reader.hpp" #include "lib/file_reader.hpp" #include "lib/coll_reader.hpp" @@ -91,14 +92,6 @@ const char *window_titles[] = { "GLVis [mesh]", "GLVis [scalar data]", "GLVis [vector data]", }; -istream *script = NULL; -int scr_running = 0; -int scr_level = 0; -Vector *init_nodes = NULL; -double scr_min_val, scr_max_val; - -extern char **environ; - void PrintSampleUsage(ostream &out); @@ -282,843 +275,6 @@ void GLVisStartVis() cout << "GLVis window closed." << endl; } -int ScriptReadSolution(istream &scr, DataState& state) -{ - int err_read; - string mword,sword; - - cout << "Script: solution: " << flush; - // read the mesh - scr >> ws >> mword; // mesh filename (can't contain spaces) - cout << "mesh: " << mword << "; " << flush; - named_ifgzstream imesh(mword.c_str()); - if (!imesh) - { - cout << "Can not open mesh file: " << mword << endl; - return 1; - } - state.SetMesh(new Mesh(imesh, 1, 0, state.fix_elem_orient)); - - // read the solution (GridFunction) - scr >> ws >> sword; - cout << "solution: " << sword << endl; - - FileReader reader(state); - err_read = reader.ReadSerial(FileReader::FileType::GRID_FUNC, mword.c_str(), - sword.c_str()); - - return err_read; -} - -int ScriptReadQuadrature(istream &scr, DataState& state) -{ - int err_read; - string mword,sword; - - cout << "Script: quadrature: " << flush; - // read the mesh - scr >> ws >> mword; // mesh filename (can't contain spaces) - cout << "mesh: " << mword << "; " << flush; - named_ifgzstream imesh(mword.c_str()); - if (!imesh) - { - cout << "Can not open mesh file: " << mword << endl; - return 1; - } - state.SetMesh(new Mesh(imesh, 1, 0, state.fix_elem_orient)); - - // read the quadrature (QuadratureFunction) - scr >> ws >> sword; - cout << "quadrature: " << sword << endl; - - FileReader reader(state); - err_read = reader.ReadSerial(FileReader::FileType::QUAD_FUNC, mword.c_str(), - sword.c_str()); - - return err_read; -} - -int ScriptReadParSolution(istream &scr, DataState& state) -{ - int np, scr_keep_attr, err_read; - string mesh_prefix, sol_prefix; - - cout << "Script: psolution: " << flush; - // read number of processors - scr >> np; - cout << "# processors: " << np << "; " << flush; - // read the mesh prefix - scr >> ws >> mesh_prefix; // mesh prefix (can't contain spaces) - cout << "mesh prefix: " << mesh_prefix << "; " << flush; - scr >> ws >> scr_keep_attr; - if (scr_keep_attr) - { - cout << "(real attributes); " << flush; - } - else - { - cout << "(processor attributes); " << flush; - } - // read the solution prefix - scr >> ws >> sol_prefix; - cout << "solution prefix: " << sol_prefix << endl; - - FileReader reader(state); - err_read = reader.ReadParallel(np, FileReader::FileType::GRID_FUNC, - mesh_prefix.c_str(), sol_prefix.c_str()); - return err_read; -} - -int ScriptReadParQuadrature(istream &scr, DataState& state) -{ - int np, scr_keep_attr, err_read; - string mesh_prefix, quad_prefix; - - cout << "Script: pquadrature: " << flush; - // read number of processors - scr >> np; - cout << "# processors: " << np << "; " << flush; - // read the mesh prefix - scr >> ws >> mesh_prefix; // mesh prefix (can't contain spaces) - cout << "mesh prefix: " << mesh_prefix << "; " << flush; - scr >> ws >> scr_keep_attr; - if (scr_keep_attr) - { - cout << "(real attributes); " << flush; - } - else - { - cout << "(processor attributes); " << flush; - } - // read the quadrature prefix - scr >> ws >> quad_prefix; - cout << "quadrature prefix: " << quad_prefix << endl; - - FileReader reader(state); - err_read = reader.ReadParallel(np, FileReader::FileType::QUAD_FUNC, - mesh_prefix.c_str(), quad_prefix.c_str()); - return err_read; -} - -int ScriptReadDisplMesh(istream &scr, DataState& state) -{ - DataState meshstate; - string word; - - cout << "Script: mesh: " << flush; - scr >> ws >> word; - { - named_ifgzstream imesh(word.c_str()); - if (!imesh) - { - cout << "Can not open mesh file: " << word << endl; - return 1; - } - cout << word << endl; - meshstate.SetMesh(new Mesh(imesh, 1, 0, state.fix_elem_orient)); - } - meshstate.ExtrudeMeshAndSolution(); - Mesh* const m = meshstate.mesh.get(); - if (init_nodes == NULL) - { - init_nodes = new Vector; - meshstate.mesh->GetNodes(*init_nodes); - state.SetMesh(NULL); - state.SetGridFunction(NULL); - } - else - { - FiniteElementCollection *vfec = NULL; - FiniteElementSpace *vfes; - vfes = (FiniteElementSpace *)m->GetNodalFESpace(); - if (vfes == NULL) - { - vfec = new LinearFECollection; - vfes = new FiniteElementSpace(m, vfec, m->SpaceDimension()); - } - - meshstate.SetGridFunction(new GridFunction(vfes)); - GridFunction * const g = meshstate.grid_f.get(); - if (vfec) - { - g->MakeOwner(vfec); - } - m->GetNodes(*g); - if (g->Size() == init_nodes->Size()) - { - subtract(*init_nodes, *g, *g); - } - else - { - cout << "Script: incompatible meshes!" << endl; - *g = 0.0; - } - - state = std::move(meshstate); - } - - return 0; -} - -int ScriptReadDataColl(istream &scr, DataState &state, bool mesh_only = true, - bool quad = false) -{ - int err_read; - int type; - string cword, fword; - - cout << "Script: data_collection: " << flush; - // read the collection - scr >> ws >> type; // collection type - cout << "type: " << type << "; " << flush; - scr >> ws >> cword; // collection filename (can't contain spaces) - cout << "collection: " << cword << "; " << flush; - - if (!mesh_only) - { - // read the field - scr >> ws >> fword; - cout << "field: " << fword << endl; - } - - DataCollectionReader reader(state); - if (dc_protocol != string_default) - { - reader.SetProtocol(dc_protocol.c_str()); - } - - if (mesh_only) - err_read = reader.ReadSerial((DataCollectionReader::CollType)type, - cword.c_str(), dc_cycle); - else - err_read = reader.ReadSerial((DataCollectionReader::CollType)type, - cword.c_str(), dc_cycle, fword.c_str(), quad); - - return err_read; -} - -void ExecuteScriptCommand() -{ - if (!script) - { - cout << "No script stream defined! (Bug?)" << endl; - return; - } - - istream &scr = *script; - string word; - int done_one_command = 0; - while (!done_one_command) - { - scr >> ws; - if (!scr.good()) - { - cout << "End of script." << endl; - scr_level = 0; - return; - } - if (scr.peek() == '#') - { - getline(scr, word); - continue; - } - scr >> word; - if (word == "{") - { - scr_level++; - } - else if (word == "}") - { - scr_level--; - if (scr_level < 0) - { - scr_level = 0; - } - } - else if (word == "data_coll_cycle") - { - scr >> dc_cycle; - } - else if (word == "data_coll_protocol") - { - scr >> dc_protocol; - } - else if (word == "solution" || word == "mesh" || word == "psolution" - || word == "quadrature" || word == "pquadrature" || word == "data_coll_mesh" - || word == "data_coll_field" || word == "data_coll_quad") - { - DataState new_state; - - if (word == "solution") - { - if (ScriptReadSolution(scr, new_state)) - { - done_one_command = 1; - continue; - } - } - else if (word == "quadrature") - { - if (ScriptReadQuadrature(scr, new_state)) - { - done_one_command = 1; - continue; - } - } - else if (word == "mesh") - { - if (ScriptReadDisplMesh(scr, new_state)) - { - done_one_command = 1; - continue; - } - if (new_state.mesh == NULL) - { - cout << "Script: unexpected 'mesh' command!" << endl; - done_one_command = 1; - continue; - } - } - else if (word == "psolution") - { - if (ScriptReadParSolution(scr, new_state)) - { - done_one_command = 1; - continue; - } - } - else if (word == "pquadrature") - { - if (ScriptReadParQuadrature(scr, new_state)) - { - done_one_command = 1; - continue; - } - } - else if (word == "data_coll_mesh") - { - if (ScriptReadDataColl(scr, new_state)) - { - done_one_command = 1; - continue; - } - } - else if (word == "data_coll_field") - { - if (ScriptReadDataColl(scr, new_state, false)) - { - done_one_command = 1; - continue; - } - } - else if (word == "data_coll_quad") - { - if (ScriptReadDataColl(scr, new_state, false, true)) - { - done_one_command = 1; - continue; - } - } - - if (stream_state.SetNewMeshAndSolution(std::move(new_state), vs)) - { - MyExpose(); - } - else - { - cout << "Different type of mesh / solution." << endl; - } - } - else if (word == "screenshot") - { - scr >> ws >> word; - - cout << "Script: screenshot: " << flush; - - if (Screenshot(word.c_str(), true)) - { - cout << "Screenshot(" << word << ") failed." << endl; - done_one_command = 1; - continue; - } - cout << "-> " << word << endl; - - if (scr_min_val > vs->GetMinV()) - { - scr_min_val = vs->GetMinV(); - } - if (scr_max_val < vs->GetMaxV()) - { - scr_max_val = vs->GetMaxV(); - } - } - else if (word == "viewcenter") - { - scr >> vs->ViewCenterX >> vs->ViewCenterY; - cout << "Script: viewcenter: " - << vs->ViewCenterX << ' ' << vs->ViewCenterY << endl; - MyExpose(); - } - else if (word == "perspective") - { - scr >> ws >> word; - cout << "Script: perspective: " << word; - if (word == "off") - { - vs->OrthogonalProjection = 1; - } - else if (word == "on") - { - vs->OrthogonalProjection = 0; - } - else - { - cout << '?'; - } - cout << endl; - MyExpose(); - } - else if (word == "light") - { - scr >> ws >> word; - cout << "Script: light: " << word; - if (word == "off") - { - vs->SetLight(false); - } - else if (word == "on") - { - vs->SetLight(true); - } - else - { - cout << '?'; - } - cout << endl; - MyExpose(); - } - else if (word == "view") - { - double theta, phi; - scr >> theta >> phi; - cout << "Script: view: " << theta << ' ' << phi << endl; - vs->SetView(theta, phi); - MyExpose(); - } - else if (word == "zoom") - { - double factor; - scr >> factor; - cout << "Script: zoom: " << factor << endl; - vs->Zoom(factor); - MyExpose(); - } - else if (word == "shading") - { - scr >> ws >> word; - cout << "Script: shading: " << flush; - VisualizationSceneScalarData::Shading s = - VisualizationSceneScalarData::Shading::Invalid; - if (word == "flat") - { - s = VisualizationSceneScalarData::Shading::Flat; - } - else if (word == "smooth") - { - s = VisualizationSceneScalarData::Shading::Smooth; - } - else if (word == "cool") - { - s = VisualizationSceneScalarData::Shading::Noncomforming; - } - if (s != VisualizationSceneScalarData::Shading::Invalid) - { - vs->SetShading(s, false); - cout << word << endl; - MyExpose(); - } - else - { - cout << word << " ?" << endl; - } - } - else if (word == "subdivisions") - { - int t, b; - scr >> t >> b; - cout << "Script: subdivisions: " << flush; - vs->SetRefineFactors(t, b); - cout << t << ' ' << b << endl; - MyExpose(); - } - else if (word == "valuerange") - { - double min, max; - scr >> min >> max; - cout << "Script: valuerange: " << flush; - vs->SetValueRange(min, max); - cout << min << ' ' << max << endl; - MyExpose(); - } - else if (word == "autoscale") - { - scr >> ws >> word; - cout << "Script: autoscale: " << word; - if (word == "off") - { - vs->SetAutoscale(0); - } - else if (word == "on") - { - vs->SetAutoscale(1); - } - else if (word == "value") - { - vs->SetAutoscale(2); - } - else if (word == "mesh") - { - vs->SetAutoscale(3); - } - else - { - cout << '?'; - } - cout << endl; - } - else if (word == "levellines") - { - double min, max; - int num; - scr >> min >> max >> num; - cout << "Script: levellines: " << flush; - vs->SetLevelLines(min, max, num); - vs->UpdateLevelLines(); - cout << min << ' ' << max << ' ' << num << endl; - MyExpose(); - } - else if (word == "axis_numberformat") - { - char delim; - string axis_formatting; - scr >> ws >> delim; - getline(scr, axis_formatting, delim); - cout << "Script: axis_numberformat: " << flush; - vs->SetAxisNumberFormat(axis_formatting); - cout << axis_formatting << endl; - MyExpose(); - } - else if (word == "colorbar_numberformat") - { - char delim; - string colorbar_formatting; - scr >> ws >> delim; - getline(scr, colorbar_formatting, delim); - cout << "Script: colorbar_numberformat: " << flush; - vs->SetColorbarNumberFormat(colorbar_formatting); - cout << colorbar_formatting << endl; - MyExpose(); - } - else if (word == "window") - { - scr >> window_x >> window_y >> window_w >> window_h; - cout << "Script: window: " << window_x << ' ' << window_y - << ' ' << window_w << ' ' << window_h << endl; - MoveResizeWindow(window_x, window_y, window_w, window_h); - MyExpose(); - } - else if (word == "keys") - { - scr >> stream_state.keys; - cout << "Script: keys: '" << stream_state.keys << "'" << endl; - // SendKeySequence(keys.c_str()); - CallKeySequence(stream_state.keys.c_str()); - MyExpose(); - } - else if (word == "palette") - { - int pal; - scr >> pal; - cout << "Script: palette: " << pal << endl; - vs->palette.SetIndex(pal-1); - MyExpose(); - } - else if (word == "palette_repeat") - { - int rpt_times; - scr >> rpt_times; - cout << "Script: palette_repeat: " << rpt_times << endl; - vs->palette.SetRepeatTimes(rpt_times); - vs->palette.GenerateTextures(); - MyExpose(); - } - else if (word == "toggle_attributes") - { - Array attr_list; - cout << "Script: toggle_attributes:"; - for (scr >> ws; scr.peek() != ';'; scr >> ws) - { - attr_list.Append(0); - scr >> attr_list.Last(); - if (attr_list.Size() <= 256) - { - cout << ' ' << attr_list.Last(); - } - else if (attr_list.Size() == 257) - { - cout << " ... " << flush; - } - } - scr.get(); // read the end symbol: ';' - cout << endl; - vs->ToggleAttributes(attr_list); - MyExpose(); - } - else if (word == "rotmat") - { - cout << "Script: rotmat:"; - for (int i = 0; i < 16; i++) - { - scr >> vs->rotmat[i/4][i%4]; - cout << ' ' << vs->rotmat[i/4][i%4]; - } - cout << endl; - MyExpose(); - } - else if (word == "camera") - { - double cam[9]; - cout << "Script: camera:"; - for (int i = 0; i < 9; i++) - { - scr >> cam[i]; - cout << ' ' << cam[i]; - } - cout << endl; - vs->cam.Set(cam); - MyExpose(); - } - else if (word == "scale") - { - double scale; - cout << "Script: scale:"; - scr >> scale; - cout << ' ' << scale; - cout << endl; - vs->Scale(scale); - MyExpose(); - } - else if (word == "translate") - { - double x, y, z; - cout << "Script: translate:"; - scr >> x >> y >> z; - cout << ' ' << x << ' ' << y << ' ' << z; - cout << endl; - vs->Translate(x, y, z); - MyExpose(); - } - else if (word == "plot_caption") - { - char delim; - scr >> ws >> delim; - getline(scr, plot_caption, delim); - vs->PrepareCaption(); // turn on or off the caption - MyExpose(); - } - else - { - cout << "Unknown command in script: " << word << endl; - } - - done_one_command = 1; - } -} - -void ScriptControl(); - -void ScriptIdleFunc() -{ - ExecuteScriptCommand(); - if (scr_level == 0) - { - ScriptControl(); - } -} - -void ScriptControl() -{ - if (scr_running) - { - scr_running = 0; - RemoveIdleFunc(ScriptIdleFunc); - } - else - { - scr_running = 1; - AddIdleFunc(ScriptIdleFunc); - } -} - -void PlayScript(istream &scr) -{ - string word; - - scr_min_val = numeric_limits::infinity(); - scr_max_val = -scr_min_val; - - // read initializing commands - while (1) - { - scr >> ws; - if (!scr.good()) - { - cout << "Error in script" << endl; - return; - } - if (scr.peek() == '#') - { - getline(scr, word); - continue; - } - scr >> word; - if (word == "window") - { - scr >> window_x >> window_y >> window_w >> window_h; - } - else if (word == "data_coll_cycle") - { - scr >> dc_cycle; - } - else if (word == "data_coll_protocol") - { - scr >> dc_protocol; - } - else if (word == "solution") - { - if (ScriptReadSolution(scr, stream_state)) - { - return; - } - - // start the visualization - break; - } - else if (word == "quadrature") - { - if (ScriptReadQuadrature(scr, stream_state)) - { - return; - } - - // start the visualization - break; - } - else if (word == "psolution") - { - if (ScriptReadParSolution(scr, stream_state)) - { - return; - } - - // start the visualization - break; - } - else if (word == "pquadrature") - { - if (ScriptReadParQuadrature(scr, stream_state)) - { - return; - } - - // start the visualization - break; - } - else if (word == "mesh") - { - if (ScriptReadDisplMesh(scr, stream_state)) - { - return; - } - if (stream_state.mesh) - { - break; - } - } - else if (word == "data_coll_mesh") - { - if (ScriptReadDataColl(scr, stream_state)) - { - return; - } - - // start the visualization - break; - } - else if (word == "data_coll_field") - { - if (ScriptReadDataColl(scr, stream_state, false)) - { - return; - } - - // start the visualization - break; - } - else if (word == "data_coll_quad") - { - if (ScriptReadDataColl(scr, stream_state, false, true)) - { - return; - } - - // start the visualization - break; - } - else - { - cout << "Unknown command in script: " << word << endl; - } - } - - scr_level = scr_running = 0; - script = &scr; - stream_state.keys.clear(); - - // Make sure the singleton object returned by GetMainThread() is - // initialized from the main thread. - GetMainThread(); - - std::thread worker_thread - { - [&](DataState local_state) - { - // set the thread-local DataState - stream_state = std::move(local_state); - if (c_plot_caption != string_none) - { - plot_caption = c_plot_caption; - } - if (GLVisInitVis({})) - { - GetAppWindow()->setOnKeyDown(SDLK_SPACE, ScriptControl); - GLVisStartVis(); - } - }, - std::move(stream_state) - }; - - SDLMainLoop(); - worker_thread.join(); - - delete init_nodes; init_nodes = NULL; - - cout << "Script: min_val = " << scr_min_val - << ", max_val = " << scr_max_val << endl; - - script = NULL; -} - class Session { StreamCollection input_streams; diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index a3e65200..5654f430 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -24,6 +24,7 @@ list(APPEND SOURCES openglvis.cpp palettes.cpp palettes_base.cpp + script_controller.cpp sdl.cpp sdl_helper.cpp sdl_main.cpp @@ -53,6 +54,7 @@ list(APPEND HEADERS openglvis.hpp palettes.hpp palettes_base.hpp + script_controller.hpp sdl.hpp sdl_helper.hpp sdl_main.hpp diff --git a/lib/script_controller.cpp b/lib/script_controller.cpp new file mode 100644 index 00000000..55b166ea --- /dev/null +++ b/lib/script_controller.cpp @@ -0,0 +1,878 @@ +// Copyright (c) 2010-2025, Lawrence Livermore National Security, LLC. Produced +// at the Lawrence Livermore National Laboratory. All Rights reserved. See files +// LICENSE and NOTICE for details. LLNL-CODE-443271. +// +// This file is part of the GLVis visualization tool and library. For more +// information and source code availability see https://glvis.org. +// +// GLVis is free software; you can redistribute it and/or modify it under the +// terms of the BSD-3 license. We welcome feedback and contributions, see file +// CONTRIBUTING.md for details. + +#include "file_reader.hpp" +#include "coll_reader.hpp" +#include "stream_reader.hpp" +#include "visual.hpp" + +using namespace std; +using namespace mfem; + +extern const char *string_none; +extern const char *string_default; + +extern string dc_protocol; +extern int dc_cycle; +extern int window_x; +extern int window_y; +extern int window_w; +extern int window_h; +extern const char *c_plot_caption; + +extern thread_local DataState stream_state; +extern thread_local VisualizationSceneScalarData *vs; + +istream *script = NULL; +int scr_running = 0; +int scr_level = 0; +Vector *init_nodes = NULL; +double scr_min_val, scr_max_val; + +bool GLVisInitVis(StreamCollection input_streams); +void GLVisStartVis(); + +int ScriptReadSolution(istream &scr, DataState& state) +{ + int err_read; + string mword,sword; + + cout << "Script: solution: " << flush; + // read the mesh + scr >> ws >> mword; // mesh filename (can't contain spaces) + cout << "mesh: " << mword << "; " << flush; + named_ifgzstream imesh(mword.c_str()); + if (!imesh) + { + cout << "Can not open mesh file: " << mword << endl; + return 1; + } + state.SetMesh(new Mesh(imesh, 1, 0, state.fix_elem_orient)); + + // read the solution (GridFunction) + scr >> ws >> sword; + cout << "solution: " << sword << endl; + + FileReader reader(state); + err_read = reader.ReadSerial(FileReader::FileType::GRID_FUNC, mword.c_str(), + sword.c_str()); + + return err_read; +} + +int ScriptReadQuadrature(istream &scr, DataState& state) +{ + int err_read; + string mword,sword; + + cout << "Script: quadrature: " << flush; + // read the mesh + scr >> ws >> mword; // mesh filename (can't contain spaces) + cout << "mesh: " << mword << "; " << flush; + named_ifgzstream imesh(mword.c_str()); + if (!imesh) + { + cout << "Can not open mesh file: " << mword << endl; + return 1; + } + state.SetMesh(new Mesh(imesh, 1, 0, state.fix_elem_orient)); + + // read the quadrature (QuadratureFunction) + scr >> ws >> sword; + cout << "quadrature: " << sword << endl; + + FileReader reader(state); + err_read = reader.ReadSerial(FileReader::FileType::QUAD_FUNC, mword.c_str(), + sword.c_str()); + + return err_read; +} + +int ScriptReadParSolution(istream &scr, DataState& state) +{ + int np, scr_keep_attr, err_read; + string mesh_prefix, sol_prefix; + + cout << "Script: psolution: " << flush; + // read number of processors + scr >> np; + cout << "# processors: " << np << "; " << flush; + // read the mesh prefix + scr >> ws >> mesh_prefix; // mesh prefix (can't contain spaces) + cout << "mesh prefix: " << mesh_prefix << "; " << flush; + scr >> ws >> scr_keep_attr; + if (scr_keep_attr) + { + cout << "(real attributes); " << flush; + } + else + { + cout << "(processor attributes); " << flush; + } + // read the solution prefix + scr >> ws >> sol_prefix; + cout << "solution prefix: " << sol_prefix << endl; + + FileReader reader(state); + err_read = reader.ReadParallel(np, FileReader::FileType::GRID_FUNC, + mesh_prefix.c_str(), sol_prefix.c_str()); + return err_read; +} + +int ScriptReadParQuadrature(istream &scr, DataState& state) +{ + int np, scr_keep_attr, err_read; + string mesh_prefix, quad_prefix; + + cout << "Script: pquadrature: " << flush; + // read number of processors + scr >> np; + cout << "# processors: " << np << "; " << flush; + // read the mesh prefix + scr >> ws >> mesh_prefix; // mesh prefix (can't contain spaces) + cout << "mesh prefix: " << mesh_prefix << "; " << flush; + scr >> ws >> scr_keep_attr; + if (scr_keep_attr) + { + cout << "(real attributes); " << flush; + } + else + { + cout << "(processor attributes); " << flush; + } + // read the quadrature prefix + scr >> ws >> quad_prefix; + cout << "quadrature prefix: " << quad_prefix << endl; + + FileReader reader(state); + err_read = reader.ReadParallel(np, FileReader::FileType::QUAD_FUNC, + mesh_prefix.c_str(), quad_prefix.c_str()); + return err_read; +} + +int ScriptReadDisplMesh(istream &scr, DataState& state) +{ + DataState meshstate; + string word; + + cout << "Script: mesh: " << flush; + scr >> ws >> word; + { + named_ifgzstream imesh(word.c_str()); + if (!imesh) + { + cout << "Can not open mesh file: " << word << endl; + return 1; + } + cout << word << endl; + meshstate.SetMesh(new Mesh(imesh, 1, 0, state.fix_elem_orient)); + } + meshstate.ExtrudeMeshAndSolution(); + Mesh* const m = meshstate.mesh.get(); + if (init_nodes == NULL) + { + init_nodes = new Vector; + meshstate.mesh->GetNodes(*init_nodes); + state.SetMesh(NULL); + state.SetGridFunction(NULL); + } + else + { + FiniteElementCollection *vfec = NULL; + FiniteElementSpace *vfes; + vfes = (FiniteElementSpace *)m->GetNodalFESpace(); + if (vfes == NULL) + { + vfec = new LinearFECollection; + vfes = new FiniteElementSpace(m, vfec, m->SpaceDimension()); + } + + meshstate.SetGridFunction(new GridFunction(vfes)); + GridFunction * const g = meshstate.grid_f.get(); + if (vfec) + { + g->MakeOwner(vfec); + } + m->GetNodes(*g); + if (g->Size() == init_nodes->Size()) + { + subtract(*init_nodes, *g, *g); + } + else + { + cout << "Script: incompatible meshes!" << endl; + *g = 0.0; + } + + state = std::move(meshstate); + } + + return 0; +} + +int ScriptReadDataColl(istream &scr, DataState &state, bool mesh_only = true, + bool quad = false) +{ + int err_read; + int type; + string cword, fword; + + cout << "Script: data_collection: " << flush; + // read the collection + scr >> ws >> type; // collection type + cout << "type: " << type << "; " << flush; + scr >> ws >> cword; // collection filename (can't contain spaces) + cout << "collection: " << cword << "; " << flush; + + if (!mesh_only) + { + // read the field + scr >> ws >> fword; + cout << "field: " << fword << endl; + } + + DataCollectionReader reader(state); + if (dc_protocol != string_default) + { + reader.SetProtocol(dc_protocol.c_str()); + } + + if (mesh_only) + err_read = reader.ReadSerial((DataCollectionReader::CollType)type, + cword.c_str(), dc_cycle); + else + err_read = reader.ReadSerial((DataCollectionReader::CollType)type, + cword.c_str(), dc_cycle, fword.c_str(), quad); + + return err_read; +} + +void ExecuteScriptCommand() +{ + if (!script) + { + cout << "No script stream defined! (Bug?)" << endl; + return; + } + + istream &scr = *script; + string word; + int done_one_command = 0; + while (!done_one_command) + { + scr >> ws; + if (!scr.good()) + { + cout << "End of script." << endl; + scr_level = 0; + return; + } + if (scr.peek() == '#') + { + getline(scr, word); + continue; + } + scr >> word; + if (word == "{") + { + scr_level++; + } + else if (word == "}") + { + scr_level--; + if (scr_level < 0) + { + scr_level = 0; + } + } + else if (word == "data_coll_cycle") + { + scr >> dc_cycle; + } + else if (word == "data_coll_protocol") + { + scr >> dc_protocol; + } + else if (word == "solution" || word == "mesh" || word == "psolution" + || word == "quadrature" || word == "pquadrature" || word == "data_coll_mesh" + || word == "data_coll_field" || word == "data_coll_quad") + { + DataState new_state; + + if (word == "solution") + { + if (ScriptReadSolution(scr, new_state)) + { + done_one_command = 1; + continue; + } + } + else if (word == "quadrature") + { + if (ScriptReadQuadrature(scr, new_state)) + { + done_one_command = 1; + continue; + } + } + else if (word == "mesh") + { + if (ScriptReadDisplMesh(scr, new_state)) + { + done_one_command = 1; + continue; + } + if (new_state.mesh == NULL) + { + cout << "Script: unexpected 'mesh' command!" << endl; + done_one_command = 1; + continue; + } + } + else if (word == "psolution") + { + if (ScriptReadParSolution(scr, new_state)) + { + done_one_command = 1; + continue; + } + } + else if (word == "pquadrature") + { + if (ScriptReadParQuadrature(scr, new_state)) + { + done_one_command = 1; + continue; + } + } + else if (word == "data_coll_mesh") + { + if (ScriptReadDataColl(scr, new_state)) + { + done_one_command = 1; + continue; + } + } + else if (word == "data_coll_field") + { + if (ScriptReadDataColl(scr, new_state, false)) + { + done_one_command = 1; + continue; + } + } + else if (word == "data_coll_quad") + { + if (ScriptReadDataColl(scr, new_state, false, true)) + { + done_one_command = 1; + continue; + } + } + + if (stream_state.SetNewMeshAndSolution(std::move(new_state), vs)) + { + MyExpose(); + } + else + { + cout << "Different type of mesh / solution." << endl; + } + } + else if (word == "screenshot") + { + scr >> ws >> word; + + cout << "Script: screenshot: " << flush; + + if (Screenshot(word.c_str(), true)) + { + cout << "Screenshot(" << word << ") failed." << endl; + done_one_command = 1; + continue; + } + cout << "-> " << word << endl; + + if (scr_min_val > vs->GetMinV()) + { + scr_min_val = vs->GetMinV(); + } + if (scr_max_val < vs->GetMaxV()) + { + scr_max_val = vs->GetMaxV(); + } + } + else if (word == "viewcenter") + { + scr >> vs->ViewCenterX >> vs->ViewCenterY; + cout << "Script: viewcenter: " + << vs->ViewCenterX << ' ' << vs->ViewCenterY << endl; + MyExpose(); + } + else if (word == "perspective") + { + scr >> ws >> word; + cout << "Script: perspective: " << word; + if (word == "off") + { + vs->OrthogonalProjection = 1; + } + else if (word == "on") + { + vs->OrthogonalProjection = 0; + } + else + { + cout << '?'; + } + cout << endl; + MyExpose(); + } + else if (word == "light") + { + scr >> ws >> word; + cout << "Script: light: " << word; + if (word == "off") + { + vs->SetLight(false); + } + else if (word == "on") + { + vs->SetLight(true); + } + else + { + cout << '?'; + } + cout << endl; + MyExpose(); + } + else if (word == "view") + { + double theta, phi; + scr >> theta >> phi; + cout << "Script: view: " << theta << ' ' << phi << endl; + vs->SetView(theta, phi); + MyExpose(); + } + else if (word == "zoom") + { + double factor; + scr >> factor; + cout << "Script: zoom: " << factor << endl; + vs->Zoom(factor); + MyExpose(); + } + else if (word == "shading") + { + scr >> ws >> word; + cout << "Script: shading: " << flush; + VisualizationSceneScalarData::Shading s = + VisualizationSceneScalarData::Shading::Invalid; + if (word == "flat") + { + s = VisualizationSceneScalarData::Shading::Flat; + } + else if (word == "smooth") + { + s = VisualizationSceneScalarData::Shading::Smooth; + } + else if (word == "cool") + { + s = VisualizationSceneScalarData::Shading::Noncomforming; + } + if (s != VisualizationSceneScalarData::Shading::Invalid) + { + vs->SetShading(s, false); + cout << word << endl; + MyExpose(); + } + else + { + cout << word << " ?" << endl; + } + } + else if (word == "subdivisions") + { + int t, b; + scr >> t >> b; + cout << "Script: subdivisions: " << flush; + vs->SetRefineFactors(t, b); + cout << t << ' ' << b << endl; + MyExpose(); + } + else if (word == "valuerange") + { + double min, max; + scr >> min >> max; + cout << "Script: valuerange: " << flush; + vs->SetValueRange(min, max); + cout << min << ' ' << max << endl; + MyExpose(); + } + else if (word == "autoscale") + { + scr >> ws >> word; + cout << "Script: autoscale: " << word; + if (word == "off") + { + vs->SetAutoscale(0); + } + else if (word == "on") + { + vs->SetAutoscale(1); + } + else if (word == "value") + { + vs->SetAutoscale(2); + } + else if (word == "mesh") + { + vs->SetAutoscale(3); + } + else + { + cout << '?'; + } + cout << endl; + } + else if (word == "levellines") + { + double min, max; + int num; + scr >> min >> max >> num; + cout << "Script: levellines: " << flush; + vs->SetLevelLines(min, max, num); + vs->UpdateLevelLines(); + cout << min << ' ' << max << ' ' << num << endl; + MyExpose(); + } + else if (word == "axis_numberformat") + { + char delim; + string axis_formatting; + scr >> ws >> delim; + getline(scr, axis_formatting, delim); + cout << "Script: axis_numberformat: " << flush; + vs->SetAxisNumberFormat(axis_formatting); + cout << axis_formatting << endl; + MyExpose(); + } + else if (word == "colorbar_numberformat") + { + char delim; + string colorbar_formatting; + scr >> ws >> delim; + getline(scr, colorbar_formatting, delim); + cout << "Script: colorbar_numberformat: " << flush; + vs->SetColorbarNumberFormat(colorbar_formatting); + cout << colorbar_formatting << endl; + MyExpose(); + } + else if (word == "window") + { + scr >> window_x >> window_y >> window_w >> window_h; + cout << "Script: window: " << window_x << ' ' << window_y + << ' ' << window_w << ' ' << window_h << endl; + MoveResizeWindow(window_x, window_y, window_w, window_h); + MyExpose(); + } + else if (word == "keys") + { + scr >> stream_state.keys; + cout << "Script: keys: '" << stream_state.keys << "'" << endl; + // SendKeySequence(keys.c_str()); + CallKeySequence(stream_state.keys.c_str()); + MyExpose(); + } + else if (word == "palette") + { + int pal; + scr >> pal; + cout << "Script: palette: " << pal << endl; + vs->palette.SetIndex(pal-1); + MyExpose(); + } + else if (word == "palette_repeat") + { + int rpt_times; + scr >> rpt_times; + cout << "Script: palette_repeat: " << rpt_times << endl; + vs->palette.SetRepeatTimes(rpt_times); + vs->palette.GenerateTextures(); + MyExpose(); + } + else if (word == "toggle_attributes") + { + Array attr_list; + cout << "Script: toggle_attributes:"; + for (scr >> ws; scr.peek() != ';'; scr >> ws) + { + attr_list.Append(0); + scr >> attr_list.Last(); + if (attr_list.Size() <= 256) + { + cout << ' ' << attr_list.Last(); + } + else if (attr_list.Size() == 257) + { + cout << " ... " << flush; + } + } + scr.get(); // read the end symbol: ';' + cout << endl; + vs->ToggleAttributes(attr_list); + MyExpose(); + } + else if (word == "rotmat") + { + cout << "Script: rotmat:"; + for (int i = 0; i < 16; i++) + { + scr >> vs->rotmat[i/4][i%4]; + cout << ' ' << vs->rotmat[i/4][i%4]; + } + cout << endl; + MyExpose(); + } + else if (word == "camera") + { + double cam[9]; + cout << "Script: camera:"; + for (int i = 0; i < 9; i++) + { + scr >> cam[i]; + cout << ' ' << cam[i]; + } + cout << endl; + vs->cam.Set(cam); + MyExpose(); + } + else if (word == "scale") + { + double scale; + cout << "Script: scale:"; + scr >> scale; + cout << ' ' << scale; + cout << endl; + vs->Scale(scale); + MyExpose(); + } + else if (word == "translate") + { + double x, y, z; + cout << "Script: translate:"; + scr >> x >> y >> z; + cout << ' ' << x << ' ' << y << ' ' << z; + cout << endl; + vs->Translate(x, y, z); + MyExpose(); + } + else if (word == "plot_caption") + { + char delim; + scr >> ws >> delim; + getline(scr, plot_caption, delim); + vs->PrepareCaption(); // turn on or off the caption + MyExpose(); + } + else + { + cout << "Unknown command in script: " << word << endl; + } + + done_one_command = 1; + } +} + +void ScriptControl(); + +void ScriptIdleFunc() +{ + ExecuteScriptCommand(); + if (scr_level == 0) + { + ScriptControl(); + } +} + +void ScriptControl() +{ + if (scr_running) + { + scr_running = 0; + RemoveIdleFunc(ScriptIdleFunc); + } + else + { + scr_running = 1; + AddIdleFunc(ScriptIdleFunc); + } +} + +void PlayScript(istream &scr) +{ + string word; + + scr_min_val = numeric_limits::infinity(); + scr_max_val = -scr_min_val; + + // read initializing commands + while (1) + { + scr >> ws; + if (!scr.good()) + { + cout << "Error in script" << endl; + return; + } + if (scr.peek() == '#') + { + getline(scr, word); + continue; + } + scr >> word; + if (word == "window") + { + scr >> window_x >> window_y >> window_w >> window_h; + } + else if (word == "data_coll_cycle") + { + scr >> dc_cycle; + } + else if (word == "data_coll_protocol") + { + scr >> dc_protocol; + } + else if (word == "solution") + { + if (ScriptReadSolution(scr, stream_state)) + { + return; + } + + // start the visualization + break; + } + else if (word == "quadrature") + { + if (ScriptReadQuadrature(scr, stream_state)) + { + return; + } + + // start the visualization + break; + } + else if (word == "psolution") + { + if (ScriptReadParSolution(scr, stream_state)) + { + return; + } + + // start the visualization + break; + } + else if (word == "pquadrature") + { + if (ScriptReadParQuadrature(scr, stream_state)) + { + return; + } + + // start the visualization + break; + } + else if (word == "mesh") + { + if (ScriptReadDisplMesh(scr, stream_state)) + { + return; + } + if (stream_state.mesh) + { + break; + } + } + else if (word == "data_coll_mesh") + { + if (ScriptReadDataColl(scr, stream_state)) + { + return; + } + + // start the visualization + break; + } + else if (word == "data_coll_field") + { + if (ScriptReadDataColl(scr, stream_state, false)) + { + return; + } + + // start the visualization + break; + } + else if (word == "data_coll_quad") + { + if (ScriptReadDataColl(scr, stream_state, false, true)) + { + return; + } + + // start the visualization + break; + } + else + { + cout << "Unknown command in script: " << word << endl; + } + } + + scr_level = scr_running = 0; + script = &scr; + stream_state.keys.clear(); + + // Make sure the singleton object returned by GetMainThread() is + // initialized from the main thread. + GetMainThread(); + + std::thread worker_thread + { + [&](DataState local_state) + { + // set the thread-local DataState + stream_state = std::move(local_state); + if (c_plot_caption != string_none) + { + plot_caption = c_plot_caption; + } + if (GLVisInitVis({})) + { + GetAppWindow()->setOnKeyDown(SDLK_SPACE, ScriptControl); + GLVisStartVis(); + } + }, + std::move(stream_state) + }; + + SDLMainLoop(); + worker_thread.join(); + + delete init_nodes; init_nodes = NULL; + + cout << "Script: min_val = " << scr_min_val + << ", max_val = " << scr_max_val << endl; + + script = NULL; +} diff --git a/lib/script_controller.hpp b/lib/script_controller.hpp new file mode 100644 index 00000000..b9ecf838 --- /dev/null +++ b/lib/script_controller.hpp @@ -0,0 +1,19 @@ +// Copyright (c) 2010-2025, Lawrence Livermore National Security, LLC. Produced +// at the Lawrence Livermore National Laboratory. All Rights reserved. See files +// LICENSE and NOTICE for details. LLNL-CODE-443271. +// +// This file is part of the GLVis visualization tool and library. For more +// information and source code availability see https://glvis.org. +// +// GLVis is free software; you can redistribute it and/or modify it under the +// terms of the BSD-3 license. We welcome feedback and contributions, see file +// CONTRIBUTING.md for details. + +#ifndef GLVIS_SCRIPT_CONTROLLER_HPP +#define GLVIS_SCRIPT_CONTROLLER_HPP + +#include + +void PlayScript(std::istream &scr); + +#endif // GLVIS_SCRIPT_CONTROLLER_HPP diff --git a/makefile b/makefile index 44fb9f92..80833500 100644 --- a/makefile +++ b/makefile @@ -255,10 +255,10 @@ ALL_SOURCE_FILES = \ lib/coll_reader.cpp lib/data_state.cpp lib/file_reader.cpp \ lib/font.cpp lib/gl2ps.c lib/gltf.cpp lib/material.cpp \ lib/openglvis.cpp lib/palettes_base.cpp lib/palettes.cpp lib/sdl.cpp \ - lib/sdl_helper.cpp lib/sdl_main.cpp lib/sdl_windows.cpp \ - lib/sdl_x11.cpp lib/stream_reader.cpp lib/threads.cpp lib/vsdata.cpp \ - lib/vssolution.cpp lib/vssolution3d.cpp lib/vsvector.cpp \ - lib/vsvector3d.cpp + lib/script_controller.cpp lib/sdl_helper.cpp lib/sdl_main.cpp \ + lib/sdl_windows.cpp lib/sdl_x11.cpp lib/stream_reader.cpp \ + lib/threads.cpp lib/vsdata.cpp lib/vssolution.cpp lib/vssolution3d.cpp \ + lib/vsvector.cpp lib/vsvector3d.cpp OBJC_SOURCE_FILES = $(if $(NOTMAC),,lib/sdl_mac.mm) DESKTOP_ONLY_SOURCE_FILES = \ lib/gl/renderer_ff.cpp lib/threads.cpp lib/gl2ps.c lib/sdl_x11.cpp @@ -276,11 +276,11 @@ HEADER_FILES = \ lib/data_state.hpp lib/file_reader.hpp lib/font.hpp \ lib/geom_utils.hpp lib/gl2ps.h lib/gltf.hpp lib/logo.hpp \ lib/material.hpp lib/openglvis.hpp lib/palettes_base.hpp \ - lib/palettes.hpp lib/sdl_helper.hpp lib/sdl.hpp lib/sdl_mac.hpp \ - lib/sdl_main.hpp lib/sdl_windows.hpp lib/sdl_x11.hpp \ - lib/stream_reader.hpp lib/threads.hpp lib/visual.hpp lib/vsdata.hpp \ - lib/vssolution.hpp lib/vssolution3d.hpp lib/vsvector.hpp \ - lib/vsvector3d.hpp + lib/palettes.hpp lib/script_controller.hpp lib/sdl_helper.hpp \ + lib/sdl.hpp lib/sdl_mac.hpp lib/sdl_main.hpp lib/sdl_windows.hpp \ + lib/sdl_x11.hpp lib/stream_reader.hpp lib/threads.hpp lib/visual.hpp \ + lib/vsdata.hpp lib/vssolution.hpp lib/vssolution3d.hpp \ + lib/vsvector.hpp lib/vsvector3d.hpp DESKTOP_SOURCE_FILES = $(COMMON_SOURCE_FILES) $(DESKTOP_ONLY_SOURCE_FILES) $(LOGO_FILE_CPP) WEB_SOURCE_FILES = $(COMMON_SOURCE_FILES) $(WEB_ONLY_SOURCE_FILES) From a7b9c58203e3de8e91c8f297e248db47ddafe17e Mon Sep 17 00:00:00 2001 From: Jan Nikl Date: Fri, 2 May 2025 14:03:44 -0700 Subject: [PATCH 03/56] Introduced Window structure. --- glvis.cpp | 142 +++++++++++++++++++------------------- lib/CMakeLists.txt | 3 +- lib/script_controller.cpp | 106 ++++++++++++++-------------- lib/threads.cpp | 2 +- lib/vsdata.cpp | 10 +-- lib/vsdata.hpp | 6 +- lib/vssolution.cpp | 4 +- lib/vsvector.cpp | 4 +- lib/vsvector3d.cpp | 2 +- lib/window.hpp | 29 ++++++++ makefile | 2 +- 11 files changed, 171 insertions(+), 139 deletions(-) create mode 100644 lib/window.hpp diff --git a/glvis.cpp b/glvis.cpp index f526fd02..5a1df8c1 100644 --- a/glvis.cpp +++ b/glvis.cpp @@ -34,6 +34,7 @@ #include "mfem.hpp" #include "lib/palettes.hpp" #include "lib/visual.hpp" +#include "lib/window.hpp" #include "lib/script_controller.hpp" #include "lib/stream_reader.hpp" #include "lib/file_reader.hpp" @@ -63,8 +64,6 @@ int window_w = 400; int window_h = 350; const char *window_title = string_default; const char *c_plot_caption = string_none; -thread_local string plot_caption; -thread_local string extra_caption; bool secure = socketstream::secure_default; // Global variables @@ -81,8 +80,8 @@ enum InputOptions INPUT_PARALLEL = 1 << 8, }; int input = INPUT_SERVER_MODE; -thread_local DataState stream_state; -thread_local VisualizationSceneScalarData *vs = NULL; + +thread_local Window win; extern thread_local GLVisCommand* glvis_command; thread_local communication_thread *comm_thread = NULL; @@ -101,7 +100,7 @@ void SwitchQuadSolution(); // Visualize the data in the global variables mesh, sol/grid_f, etc bool GLVisInitVis(StreamCollection input_streams) { - DataState::FieldType field_type = stream_state.GetType(); + DataState::FieldType field_type = win.data_state.GetType(); if (field_type <= DataState::FieldType::MIN || field_type >= DataState::FieldType::MAX) @@ -121,11 +120,11 @@ bool GLVisInitVis(StreamCollection input_streams) if (input_streams.size() > 0) { GetAppWindow()->setOnKeyDown(SDLK_SPACE, ThreadsPauseFunc); - glvis_command = new GLVisCommand(&vs, stream_state); + glvis_command = new GLVisCommand(&win.vs, win.data_state); comm_thread = new communication_thread(std::move(input_streams), glvis_command); } - if (stream_state.quad_f) + if (win.data_state.quad_f) { GetAppWindow()->setOnKeyDown('Q', SwitchQuadSolution); } @@ -134,49 +133,51 @@ bool GLVisInitVis(StreamCollection input_streams) if (field_type == DataState::FieldType::SCALAR || field_type == DataState::FieldType::MESH) { - if (stream_state.grid_f) + if (win.data_state.grid_f) { - stream_state.grid_f->GetNodalValues(stream_state.sol); + win.data_state.grid_f->GetNodalValues(win.data_state.sol); } - if (stream_state.mesh->SpaceDimension() == 2) + if (win.data_state.mesh->SpaceDimension() == 2) { VisualizationSceneSolution * vss; - if (stream_state.normals.Size() > 0) + if (win.data_state.normals.Size() > 0) { - vs = vss = new VisualizationSceneSolution(*stream_state.mesh, stream_state.sol, - stream_state.mesh_quad.get(), &stream_state.normals); + win.vs = vss = new VisualizationSceneSolution(*win.data_state.mesh, + win.data_state.sol, + win.data_state.mesh_quad.get(), &win.data_state.normals); } else { - vs = vss = new VisualizationSceneSolution(*stream_state.mesh, stream_state.sol, - stream_state.mesh_quad.get()); + win.vs = vss = new VisualizationSceneSolution(*win.data_state.mesh, + win.data_state.sol, + win.data_state.mesh_quad.get()); } - if (stream_state.grid_f) + if (win.data_state.grid_f) { - vss->SetGridFunction(*stream_state.grid_f); + vss->SetGridFunction(*win.data_state.grid_f); } if (field_type == DataState::FieldType::MESH) { - vs->OrthogonalProjection = 1; - vs->SetLight(false); - vs->Zoom(1.8); + win.vs->OrthogonalProjection = 1; + win.vs->SetLight(false); + win.vs->Zoom(1.8); // Use the 'bone' palette when visualizing a 2D mesh only (otherwise // the 'jet-like' palette is used in 2D, see vssolution.cpp). - vs->palette.SetIndex(4); + win.vs->palette.SetIndex(4); } } - else if (stream_state.mesh->SpaceDimension() == 3) + else if (win.data_state.mesh->SpaceDimension() == 3) { VisualizationSceneSolution3d * vss; - vs = vss = new VisualizationSceneSolution3d(*stream_state.mesh, - stream_state.sol, stream_state.mesh_quad.get()); - if (stream_state.grid_f) + win.vs = vss = new VisualizationSceneSolution3d(*win.data_state.mesh, + win.data_state.sol, win.data_state.mesh_quad.get()); + if (win.data_state.grid_f) { - vss->SetGridFunction(stream_state.grid_f.get()); + vss->SetGridFunction(win.data_state.grid_f.get()); } if (field_type == DataState::FieldType::MESH) { - if (stream_state.mesh->Dimension() == 3) + if (win.data_state.mesh->Dimension() == 3) { // Use the 'white' palette when visualizing a 3D volume mesh only vss->palette.SetIndex(11); @@ -194,68 +195,69 @@ bool GLVisInitVis(StreamCollection input_streams) } if (field_type == DataState::FieldType::MESH) { - if (stream_state.grid_f) + if (win.data_state.grid_f) { - mesh_range = stream_state.grid_f->Max() + 1.0; + mesh_range = win.data_state.grid_f->Max() + 1.0; } else { - mesh_range = stream_state.sol.Max() + 1.0; + mesh_range = win.data_state.sol.Max() + 1.0; } } } else if (field_type == DataState::FieldType::VECTOR) { - if (stream_state.mesh->SpaceDimension() == 2) + if (win.data_state.mesh->SpaceDimension() == 2) { - if (stream_state.grid_f) + if (win.data_state.grid_f) { - vs = new VisualizationSceneVector(*stream_state.grid_f); + win.vs = new VisualizationSceneVector(*win.data_state.grid_f); } else { - vs = new VisualizationSceneVector(*stream_state.mesh, stream_state.solu, - stream_state.solv, stream_state.mesh_quad.get()); + win.vs = new VisualizationSceneVector(*win.data_state.mesh, win.data_state.solu, + win.data_state.solv, win.data_state.mesh_quad.get()); } } - else if (stream_state.mesh->SpaceDimension() == 3) + else if (win.data_state.mesh->SpaceDimension() == 3) { - if (stream_state.grid_f) + if (win.data_state.grid_f) { - stream_state.ProjectVectorFEGridFunction(); - vs = new VisualizationSceneVector3d(*stream_state.grid_f, - stream_state.mesh_quad.get()); + win.data_state.ProjectVectorFEGridFunction(); + win.vs = new VisualizationSceneVector3d(*win.data_state.grid_f, + win.data_state.mesh_quad.get()); } else { - vs = new VisualizationSceneVector3d(*stream_state.mesh, stream_state.solu, - stream_state.solv, stream_state.solw, - stream_state.mesh_quad.get()); + win.vs = new VisualizationSceneVector3d(*win.data_state.mesh, + win.data_state.solu, + win.data_state.solv, win.data_state.solw, + win.data_state.mesh_quad.get()); } } } - if (vs) + if (win.vs) { // increase the refinement factors if visualizing a GridFunction - if (stream_state.grid_f) + if (win.data_state.grid_f) { - vs->AutoRefine(); - vs->SetShading(VisualizationSceneScalarData::Shading::Noncomforming, true); + win.vs->AutoRefine(); + win.vs->SetShading(VisualizationSceneScalarData::Shading::Noncomforming, true); } if (mesh_range > 0.0) { - vs->SetValueRange(-mesh_range, mesh_range); - vs->SetAutoscale(0); + win.vs->SetValueRange(-mesh_range, mesh_range); + win.vs->SetAutoscale(0); } - if (stream_state.mesh->SpaceDimension() == 2 + if (win.data_state.mesh->SpaceDimension() == 2 && field_type == DataState::FieldType::MESH) { - SetVisualizationScene(vs, 2, stream_state.keys.c_str()); + SetVisualizationScene(win.vs, 2, win.data_state.keys.c_str()); } else { - SetVisualizationScene(vs, 3, stream_state.keys.c_str()); + SetVisualizationScene(win.vs, 3, win.data_state.keys.c_str()); } } return true; @@ -263,8 +265,8 @@ bool GLVisInitVis(StreamCollection input_streams) void GLVisStartVis() { - RunVisualization(); // deletes vs - vs = NULL; + RunVisualization(); // deletes win.vs + win.vs = NULL; if (glvis_command) { glvis_command->Terminate(); @@ -306,10 +308,10 @@ class Session auto funcThread = [](DataState thread_state, StreamCollection is) { // Set thread-local stream state - stream_state = std::move(thread_state); + win.data_state = std::move(thread_state); if (c_plot_caption != string_none) { - plot_caption = c_plot_caption; + win.plot_caption = c_plot_caption; } if (GLVisInitVis(std::move(is))) @@ -628,17 +630,17 @@ int main (int argc, char *argv[]) "Palette file."); args.AddOption(&arg_keys, "-k", "--keys", "Execute key shortcut commands in the GLVis window."); - args.AddOption(&stream_state.fix_elem_orient, "-fo", "--fix-orientations", + args.AddOption(&win.data_state.fix_elem_orient, "-fo", "--fix-orientations", "-no-fo", "--dont-fix-orientations", "Attempt to fix the orientations of inverted elements."); - args.AddOption(&stream_state.keep_attr, "-a", "--real-attributes", + args.AddOption(&win.data_state.keep_attr, "-a", "--real-attributes", "-ap", "--processor-attributes", "When opening a parallel mesh, use the real mesh attributes" " or replace them with the processor rank."); args.AddOption(&geom_ref_type, "-grt", "--geometry-refiner-type", "Set of points to use when refining geometry:" " 3 = uniform, 1 = Gauss-Lobatto, (see mfem::Quadrature1D)."); - args.AddOption(&stream_state.save_coloring, "-sc", "--save-coloring", + args.AddOption(&win.data_state.save_coloring, "-sc", "--save-coloring", "-no-sc", "--dont-save-coloring", "Save the mesh coloring generated when opening only a mesh."); args.AddOption(&portnum, "-p", "--listen-port", @@ -749,7 +751,7 @@ int main (int argc, char *argv[]) } if (arg_keys != string_none) { - stream_state.keys = arg_keys; + win.data_state.keys = arg_keys; } if (font_name != string_default) { @@ -769,7 +771,7 @@ int main (int argc, char *argv[]) } if (c_plot_caption != string_none) { - plot_caption = c_plot_caption; + win.plot_caption = c_plot_caption; } if (legacy_gl_ctx == true) { @@ -794,8 +796,8 @@ int main (int argc, char *argv[]) // initialized from the main thread. GetMainThread(); - Session stream_session(stream_state.fix_elem_orient, - stream_state.save_coloring); + Session stream_session(win.data_state.fix_elem_orient, + win.data_state.save_coloring); if (!stream_session.StartSavedSession(stream_file)) { @@ -862,8 +864,8 @@ int main (int argc, char *argv[]) // Run server in new thread std::thread serverThread{GLVisServer, portnum, save_stream, - stream_state.fix_elem_orient, - stream_state.save_coloring}; + win.data_state.fix_elem_orient, + win.data_state.save_coloring}; // Start SDL in main thread SDLMainLoop(true); @@ -904,7 +906,7 @@ int main (int argc, char *argv[]) return 1; } - FileReader reader(stream_state, pad_digits); + FileReader reader(win.data_state, pad_digits); int ierr; if (input & INPUT_PARALLEL) { @@ -953,7 +955,7 @@ int main (int argc, char *argv[]) mesh_only = true; } - DataCollectionReader reader(stream_state); + DataCollectionReader reader(win.data_state); reader.SetPadDigits(pad_digits); if (dc_protocol != string_default) { @@ -977,7 +979,7 @@ int main (int argc, char *argv[]) // initialized from the main thread. GetMainThread(); - Session single_session(std::move(stream_state)); + Session single_session(std::move(win.data_state)); single_session.StartSession(); SDLMainLoop(); @@ -1009,8 +1011,8 @@ void PrintSampleUsage(ostream &os) void SwitchQuadSolution() { - int iqs = ((int)stream_state.GetQuadSolution()+1) + int iqs = ((int)win.data_state.GetQuadSolution()+1) % ((int)DataState::QuadSolution::MAX); - stream_state.SwitchQuadSolution((DataState::QuadSolution)iqs, vs); + win.data_state.SwitchQuadSolution((DataState::QuadSolution)iqs, win.vs); SendExposeEvent(); } diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 5654f430..89d963d5 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -65,7 +65,8 @@ list(APPEND HEADERS vssolution.hpp vssolution3d.hpp vsvector.hpp - vsvector3d.hpp) + vsvector3d.hpp + window.hpp) if(EMSCRIPTEN) # Emscripten build target diff --git a/lib/script_controller.cpp b/lib/script_controller.cpp index 55b166ea..4337593c 100644 --- a/lib/script_controller.cpp +++ b/lib/script_controller.cpp @@ -9,6 +9,7 @@ // terms of the BSD-3 license. We welcome feedback and contributions, see file // CONTRIBUTING.md for details. +#include "window.hpp" #include "file_reader.hpp" #include "coll_reader.hpp" #include "stream_reader.hpp" @@ -28,8 +29,7 @@ extern int window_w; extern int window_h; extern const char *c_plot_caption; -extern thread_local DataState stream_state; -extern thread_local VisualizationSceneScalarData *vs; +extern thread_local Window win; istream *script = NULL; int scr_running = 0; @@ -378,7 +378,7 @@ void ExecuteScriptCommand() } } - if (stream_state.SetNewMeshAndSolution(std::move(new_state), vs)) + if (win.data_state.SetNewMeshAndSolution(std::move(new_state), win.vs)) { MyExpose(); } @@ -401,20 +401,20 @@ void ExecuteScriptCommand() } cout << "-> " << word << endl; - if (scr_min_val > vs->GetMinV()) + if (scr_min_val > win.vs->GetMinV()) { - scr_min_val = vs->GetMinV(); + scr_min_val = win.vs->GetMinV(); } - if (scr_max_val < vs->GetMaxV()) + if (scr_max_val < win.vs->GetMaxV()) { - scr_max_val = vs->GetMaxV(); + scr_max_val = win.vs->GetMaxV(); } } else if (word == "viewcenter") { - scr >> vs->ViewCenterX >> vs->ViewCenterY; + scr >> win.vs->ViewCenterX >> win.vs->ViewCenterY; cout << "Script: viewcenter: " - << vs->ViewCenterX << ' ' << vs->ViewCenterY << endl; + << win.vs->ViewCenterX << ' ' << win.vs->ViewCenterY << endl; MyExpose(); } else if (word == "perspective") @@ -423,11 +423,11 @@ void ExecuteScriptCommand() cout << "Script: perspective: " << word; if (word == "off") { - vs->OrthogonalProjection = 1; + win.vs->OrthogonalProjection = 1; } else if (word == "on") { - vs->OrthogonalProjection = 0; + win.vs->OrthogonalProjection = 0; } else { @@ -442,11 +442,11 @@ void ExecuteScriptCommand() cout << "Script: light: " << word; if (word == "off") { - vs->SetLight(false); + win.vs->SetLight(false); } else if (word == "on") { - vs->SetLight(true); + win.vs->SetLight(true); } else { @@ -460,7 +460,7 @@ void ExecuteScriptCommand() double theta, phi; scr >> theta >> phi; cout << "Script: view: " << theta << ' ' << phi << endl; - vs->SetView(theta, phi); + win.vs->SetView(theta, phi); MyExpose(); } else if (word == "zoom") @@ -468,7 +468,7 @@ void ExecuteScriptCommand() double factor; scr >> factor; cout << "Script: zoom: " << factor << endl; - vs->Zoom(factor); + win.vs->Zoom(factor); MyExpose(); } else if (word == "shading") @@ -491,7 +491,7 @@ void ExecuteScriptCommand() } if (s != VisualizationSceneScalarData::Shading::Invalid) { - vs->SetShading(s, false); + win.vs->SetShading(s, false); cout << word << endl; MyExpose(); } @@ -505,7 +505,7 @@ void ExecuteScriptCommand() int t, b; scr >> t >> b; cout << "Script: subdivisions: " << flush; - vs->SetRefineFactors(t, b); + win.vs->SetRefineFactors(t, b); cout << t << ' ' << b << endl; MyExpose(); } @@ -514,7 +514,7 @@ void ExecuteScriptCommand() double min, max; scr >> min >> max; cout << "Script: valuerange: " << flush; - vs->SetValueRange(min, max); + win.vs->SetValueRange(min, max); cout << min << ' ' << max << endl; MyExpose(); } @@ -524,19 +524,19 @@ void ExecuteScriptCommand() cout << "Script: autoscale: " << word; if (word == "off") { - vs->SetAutoscale(0); + win.vs->SetAutoscale(0); } else if (word == "on") { - vs->SetAutoscale(1); + win.vs->SetAutoscale(1); } else if (word == "value") { - vs->SetAutoscale(2); + win.vs->SetAutoscale(2); } else if (word == "mesh") { - vs->SetAutoscale(3); + win.vs->SetAutoscale(3); } else { @@ -550,8 +550,8 @@ void ExecuteScriptCommand() int num; scr >> min >> max >> num; cout << "Script: levellines: " << flush; - vs->SetLevelLines(min, max, num); - vs->UpdateLevelLines(); + win.vs->SetLevelLines(min, max, num); + win.vs->UpdateLevelLines(); cout << min << ' ' << max << ' ' << num << endl; MyExpose(); } @@ -562,7 +562,7 @@ void ExecuteScriptCommand() scr >> ws >> delim; getline(scr, axis_formatting, delim); cout << "Script: axis_numberformat: " << flush; - vs->SetAxisNumberFormat(axis_formatting); + win.vs->SetAxisNumberFormat(axis_formatting); cout << axis_formatting << endl; MyExpose(); } @@ -573,7 +573,7 @@ void ExecuteScriptCommand() scr >> ws >> delim; getline(scr, colorbar_formatting, delim); cout << "Script: colorbar_numberformat: " << flush; - vs->SetColorbarNumberFormat(colorbar_formatting); + win.vs->SetColorbarNumberFormat(colorbar_formatting); cout << colorbar_formatting << endl; MyExpose(); } @@ -587,10 +587,10 @@ void ExecuteScriptCommand() } else if (word == "keys") { - scr >> stream_state.keys; - cout << "Script: keys: '" << stream_state.keys << "'" << endl; + scr >> win.data_state.keys; + cout << "Script: keys: '" << win.data_state.keys << "'" << endl; // SendKeySequence(keys.c_str()); - CallKeySequence(stream_state.keys.c_str()); + CallKeySequence(win.data_state.keys.c_str()); MyExpose(); } else if (word == "palette") @@ -598,7 +598,7 @@ void ExecuteScriptCommand() int pal; scr >> pal; cout << "Script: palette: " << pal << endl; - vs->palette.SetIndex(pal-1); + win.vs->palette.SetIndex(pal-1); MyExpose(); } else if (word == "palette_repeat") @@ -606,8 +606,8 @@ void ExecuteScriptCommand() int rpt_times; scr >> rpt_times; cout << "Script: palette_repeat: " << rpt_times << endl; - vs->palette.SetRepeatTimes(rpt_times); - vs->palette.GenerateTextures(); + win.vs->palette.SetRepeatTimes(rpt_times); + win.vs->palette.GenerateTextures(); MyExpose(); } else if (word == "toggle_attributes") @@ -629,7 +629,7 @@ void ExecuteScriptCommand() } scr.get(); // read the end symbol: ';' cout << endl; - vs->ToggleAttributes(attr_list); + win.vs->ToggleAttributes(attr_list); MyExpose(); } else if (word == "rotmat") @@ -637,8 +637,8 @@ void ExecuteScriptCommand() cout << "Script: rotmat:"; for (int i = 0; i < 16; i++) { - scr >> vs->rotmat[i/4][i%4]; - cout << ' ' << vs->rotmat[i/4][i%4]; + scr >> win.vs->rotmat[i/4][i%4]; + cout << ' ' << win.vs->rotmat[i/4][i%4]; } cout << endl; MyExpose(); @@ -653,7 +653,7 @@ void ExecuteScriptCommand() cout << ' ' << cam[i]; } cout << endl; - vs->cam.Set(cam); + win.vs->cam.Set(cam); MyExpose(); } else if (word == "scale") @@ -663,7 +663,7 @@ void ExecuteScriptCommand() scr >> scale; cout << ' ' << scale; cout << endl; - vs->Scale(scale); + win.vs->Scale(scale); MyExpose(); } else if (word == "translate") @@ -673,15 +673,15 @@ void ExecuteScriptCommand() scr >> x >> y >> z; cout << ' ' << x << ' ' << y << ' ' << z; cout << endl; - vs->Translate(x, y, z); + win.vs->Translate(x, y, z); MyExpose(); } else if (word == "plot_caption") { char delim; scr >> ws >> delim; - getline(scr, plot_caption, delim); - vs->PrepareCaption(); // turn on or off the caption + getline(scr, win.plot_caption, delim); + win.vs->PrepareCaption(); // turn on or off the caption MyExpose(); } else @@ -754,7 +754,7 @@ void PlayScript(istream &scr) } else if (word == "solution") { - if (ScriptReadSolution(scr, stream_state)) + if (ScriptReadSolution(scr, win.data_state)) { return; } @@ -764,7 +764,7 @@ void PlayScript(istream &scr) } else if (word == "quadrature") { - if (ScriptReadQuadrature(scr, stream_state)) + if (ScriptReadQuadrature(scr, win.data_state)) { return; } @@ -774,7 +774,7 @@ void PlayScript(istream &scr) } else if (word == "psolution") { - if (ScriptReadParSolution(scr, stream_state)) + if (ScriptReadParSolution(scr, win.data_state)) { return; } @@ -784,7 +784,7 @@ void PlayScript(istream &scr) } else if (word == "pquadrature") { - if (ScriptReadParQuadrature(scr, stream_state)) + if (ScriptReadParQuadrature(scr, win.data_state)) { return; } @@ -794,18 +794,18 @@ void PlayScript(istream &scr) } else if (word == "mesh") { - if (ScriptReadDisplMesh(scr, stream_state)) + if (ScriptReadDisplMesh(scr, win.data_state)) { return; } - if (stream_state.mesh) + if (win.data_state.mesh) { break; } } else if (word == "data_coll_mesh") { - if (ScriptReadDataColl(scr, stream_state)) + if (ScriptReadDataColl(scr, win.data_state)) { return; } @@ -815,7 +815,7 @@ void PlayScript(istream &scr) } else if (word == "data_coll_field") { - if (ScriptReadDataColl(scr, stream_state, false)) + if (ScriptReadDataColl(scr, win.data_state, false)) { return; } @@ -825,7 +825,7 @@ void PlayScript(istream &scr) } else if (word == "data_coll_quad") { - if (ScriptReadDataColl(scr, stream_state, false, true)) + if (ScriptReadDataColl(scr, win.data_state, false, true)) { return; } @@ -841,7 +841,7 @@ void PlayScript(istream &scr) scr_level = scr_running = 0; script = &scr; - stream_state.keys.clear(); + win.data_state.keys.clear(); // Make sure the singleton object returned by GetMainThread() is // initialized from the main thread. @@ -852,10 +852,10 @@ void PlayScript(istream &scr) [&](DataState local_state) { // set the thread-local DataState - stream_state = std::move(local_state); + win.data_state = std::move(local_state); if (c_plot_caption != string_none) { - plot_caption = c_plot_caption; + win.plot_caption = c_plot_caption; } if (GLVisInitVis({})) { @@ -863,7 +863,7 @@ void PlayScript(istream &scr) GLVisStartVis(); } }, - std::move(stream_state) + std::move(win.data_state) }; SDLMainLoop(); diff --git a/lib/threads.cpp b/lib/threads.cpp index 5c2cb678..9e547d3b 100644 --- a/lib/threads.cpp +++ b/lib/threads.cpp @@ -539,7 +539,7 @@ int GLVisCommand::Execute() case PLOT_CAPTION: { cout << "Command: plot_caption: " << plot_caption << endl; - ::plot_caption = plot_caption; + win.plot_caption = plot_caption; (*vs)->PrepareCaption(); // turn on or off the caption MyExpose(); break; diff --git a/lib/vsdata.cpp b/lib/vsdata.cpp index dd19091b..17884eb9 100644 --- a/lib/vsdata.cpp +++ b/lib/vsdata.cpp @@ -596,13 +596,13 @@ void VisualizationSceneScalarData::PrepareColorBar (double minval, // Draw a centered caption at the top (visible with the colorbar) void VisualizationSceneScalarData::PrepareCaption() { - bool empty = plot_caption.empty(); + bool empty = win.plot_caption.empty(); colorbar = (colorbar ? empty+1 : !empty); - string caption(plot_caption); - if (!extra_caption.empty()) + string caption(win.plot_caption); + if (!win.extra_caption.empty()) { - caption += " (" + extra_caption + ")"; + caption += " (" + win.extra_caption + ")"; } caption_buf.clear(); @@ -643,7 +643,7 @@ void KeycPressed(GLenum state) void KeyCPressed() { cout << "Enter new caption: " << flush; - std::getline(cin, plot_caption); + std::getline(cin, win.plot_caption); vsdata->PrepareCaption(); // turn on or off the caption SendExposeEvent(); } diff --git a/lib/vsdata.hpp b/lib/vsdata.hpp index ed09eca6..60b61fe5 100644 --- a/lib/vsdata.hpp +++ b/lib/vsdata.hpp @@ -17,11 +17,11 @@ #include "mfem.hpp" #include "openglvis.hpp" #include "aux_vis.hpp" +#include "window.hpp" using namespace mfem; -extern thread_local std::string plot_caption; // defined in glvis.cpp -extern thread_local std::string extra_caption; // defined in glvis.cpp +extern thread_local Window win; // defined in glvis.cpp class Plane { @@ -272,7 +272,7 @@ class VisualizationSceneScalarData : public VisualizationScene // colorbar states are: 0) no colorbar, no caption; 1) colorbar with // caption; 2) colorbar without caption. static const int next[2][3] = { { 1, 2, 0 }, { 2, 0, 0 } }; - colorbar = next[plot_caption.empty()][colorbar]; + colorbar = next[win.plot_caption.empty()][colorbar]; } // Turn on or off the caption diff --git a/lib/vssolution.cpp b/lib/vssolution.cpp index 246f88c0..0033e512 100644 --- a/lib/vssolution.cpp +++ b/lib/vssolution.cpp @@ -549,11 +549,11 @@ void VisualizationSceneSolution::ToggleDrawElems() if (drawelems < 2) { - extra_caption.clear(); + win.extra_caption.clear(); } else { - extra_caption = modes[drawelems]; + win.extra_caption = modes[drawelems]; } if (drawelems == 0) diff --git a/lib/vsvector.cpp b/lib/vsvector.cpp index 2b5efda4..926e9c8a 100644 --- a/lib/vsvector.cpp +++ b/lib/vsvector.cpp @@ -381,7 +381,7 @@ void VisualizationSceneVector::CycleVec2Scalar(int print) } Vec2Scalar = Vec2ScalarFunctions[i]; - extra_caption = Vec2ScalarNames[i]; + win.extra_caption = Vec2ScalarNames[i]; for (i = 0; i < mesh->GetNV(); i++) { @@ -488,7 +488,7 @@ void VisualizationSceneVector::Init() ArrowScale = 1.0; RefineFactor = 1; Vec2Scalar = VecLength; - extra_caption = Vec2ScalarNames[0]; + win.extra_caption = Vec2ScalarNames[0]; for (int i = 0; i < mesh->GetNV(); i++) { diff --git a/lib/vsvector3d.cpp b/lib/vsvector3d.cpp index d66059f2..308eb8b4 100644 --- a/lib/vsvector3d.cpp +++ b/lib/vsvector3d.cpp @@ -330,7 +330,7 @@ void VisualizationSceneVector3d::SetScalarFunction() } break; } - extra_caption = scal_func_name[scal_func]; + win.extra_caption = scal_func_name[scal_func]; } void VisualizationSceneVector3d::ToggleScalarFunction() diff --git a/lib/window.hpp b/lib/window.hpp new file mode 100644 index 00000000..8f880177 --- /dev/null +++ b/lib/window.hpp @@ -0,0 +1,29 @@ +// Copyright (c) 2010-2025, Lawrence Livermore National Security, LLC. Produced +// at the Lawrence Livermore National Laboratory. All Rights reserved. See files +// LICENSE and NOTICE for details. LLNL-CODE-443271. +// +// This file is part of the GLVis visualization tool and library. For more +// information and source code availability see https://glvis.org. +// +// GLVis is free software; you can redistribute it and/or modify it under the +// terms of the BSD-3 license. We welcome feedback and contributions, see file +// CONTRIBUTING.md for details. + +#ifndef GLVIS_WINDOW_HPP +#define GLVIS_WINDOW_HPP + +#include + +#include "data_state.hpp" + +class VisualizationSceneScalarData; + +struct Window +{ + DataState data_state; + VisualizationSceneScalarData *vs = NULL; + std::string plot_caption; + std::string extra_caption; +}; + +#endif // GLVIS_WINDOW_HPP diff --git a/makefile b/makefile index 80833500..5f7f538b 100644 --- a/makefile +++ b/makefile @@ -280,7 +280,7 @@ HEADER_FILES = \ lib/sdl.hpp lib/sdl_mac.hpp lib/sdl_main.hpp lib/sdl_windows.hpp \ lib/sdl_x11.hpp lib/stream_reader.hpp lib/threads.hpp lib/visual.hpp \ lib/vsdata.hpp lib/vssolution.hpp lib/vssolution3d.hpp \ - lib/vsvector.hpp lib/vsvector3d.hpp + lib/vsvector.hpp lib/vsvector3d.hpp lib/window.hpp DESKTOP_SOURCE_FILES = $(COMMON_SOURCE_FILES) $(DESKTOP_ONLY_SOURCE_FILES) $(LOGO_FILE_CPP) WEB_SOURCE_FILES = $(COMMON_SOURCE_FILES) $(WEB_ONLY_SOURCE_FILES) From 8b9a8b7c5035dc54a06120c352ff685783b7597d Mon Sep 17 00:00:00 2001 From: Jan Nikl Date: Fri, 2 May 2025 17:01:39 -0700 Subject: [PATCH 04/56] Removed shared Window structure from visualization scenes. --- glvis.cpp | 51 +++++-------------------------- lib/threads.cpp | 60 ++++++++++++++++++------------------ lib/threads.hpp | 15 ++++----- lib/vsdata.cpp | 20 +++++++----- lib/vsdata.hpp | 10 +++--- lib/vssolution.cpp | 24 ++++++++------- lib/vssolution.hpp | 6 ++-- lib/vssolution3d.cpp | 22 +++++++------- lib/vssolution3d.hpp | 5 ++- lib/vsvector.cpp | 72 ++++++++++++++++++++------------------------ lib/vsvector.hpp | 5 ++- lib/vsvector3d.cpp | 59 +++++++++++++++--------------------- lib/vsvector3d.hpp | 8 ++--- 13 files changed, 149 insertions(+), 208 deletions(-) diff --git a/glvis.cpp b/glvis.cpp index 5a1df8c1..29c019e2 100644 --- a/glvis.cpp +++ b/glvis.cpp @@ -120,7 +120,7 @@ bool GLVisInitVis(StreamCollection input_streams) if (input_streams.size() > 0) { GetAppWindow()->setOnKeyDown(SDLK_SPACE, ThreadsPauseFunc); - glvis_command = new GLVisCommand(&win.vs, win.data_state); + glvis_command = new GLVisCommand(win); comm_thread = new communication_thread(std::move(input_streams), glvis_command); } @@ -139,23 +139,8 @@ bool GLVisInitVis(StreamCollection input_streams) } if (win.data_state.mesh->SpaceDimension() == 2) { - VisualizationSceneSolution * vss; - if (win.data_state.normals.Size() > 0) - { - win.vs = vss = new VisualizationSceneSolution(*win.data_state.mesh, - win.data_state.sol, - win.data_state.mesh_quad.get(), &win.data_state.normals); - } - else - { - win.vs = vss = new VisualizationSceneSolution(*win.data_state.mesh, - win.data_state.sol, - win.data_state.mesh_quad.get()); - } - if (win.data_state.grid_f) - { - vss->SetGridFunction(*win.data_state.grid_f); - } + win.vs = new VisualizationSceneSolution(win); + if (field_type == DataState::FieldType::MESH) { win.vs->OrthogonalProjection = 1; @@ -168,13 +153,9 @@ bool GLVisInitVis(StreamCollection input_streams) } else if (win.data_state.mesh->SpaceDimension() == 3) { - VisualizationSceneSolution3d * vss; - win.vs = vss = new VisualizationSceneSolution3d(*win.data_state.mesh, - win.data_state.sol, win.data_state.mesh_quad.get()); - if (win.data_state.grid_f) - { - vss->SetGridFunction(win.data_state.grid_f.get()); - } + VisualizationSceneSolution3d *vss; + win.vs = vss = new VisualizationSceneSolution3d(win); + if (field_type == DataState::FieldType::MESH) { if (win.data_state.mesh->Dimension() == 3) @@ -209,31 +190,15 @@ bool GLVisInitVis(StreamCollection input_streams) { if (win.data_state.mesh->SpaceDimension() == 2) { - if (win.data_state.grid_f) - { - win.vs = new VisualizationSceneVector(*win.data_state.grid_f); - } - else - { - win.vs = new VisualizationSceneVector(*win.data_state.mesh, win.data_state.solu, - win.data_state.solv, win.data_state.mesh_quad.get()); - } + win.vs = new VisualizationSceneVector(win); } else if (win.data_state.mesh->SpaceDimension() == 3) { if (win.data_state.grid_f) { win.data_state.ProjectVectorFEGridFunction(); - win.vs = new VisualizationSceneVector3d(*win.data_state.grid_f, - win.data_state.mesh_quad.get()); - } - else - { - win.vs = new VisualizationSceneVector3d(*win.data_state.mesh, - win.data_state.solu, - win.data_state.solv, win.data_state.solw, - win.data_state.mesh_quad.get()); } + win.vs = new VisualizationSceneVector3d(win); } } diff --git a/lib/threads.cpp b/lib/threads.cpp index 9e547d3b..08107e3a 100644 --- a/lib/threads.cpp +++ b/lib/threads.cpp @@ -18,11 +18,9 @@ using namespace std; extern const char *strings_off_on[]; // defined in vsdata.cpp -GLVisCommand::GLVisCommand( - VisualizationSceneScalarData **_vs, DataState& state) - : curr_state(state) +GLVisCommand::GLVisCommand(Window &win_) + : win(win_) { - vs = _vs; // should be set in this thread by a call to InitVisualization() thread_wnd = GetAppWindow(); @@ -463,7 +461,7 @@ int GLVisCommand::Execute() } else { - auto qs = curr_state.GetQuadSolution(); + auto qs = win.data_state.GetQuadSolution(); if (qs != DataState::QuadSolution::NONE) { new_state.SetQuadSolution(qs); @@ -475,11 +473,11 @@ int GLVisCommand::Execute() new_state.ExtrudeMeshAndSolution(); } } - if (curr_state.SetNewMeshAndSolution(std::move(new_state), *vs)) + if (win.data_state.SetNewMeshAndSolution(std::move(new_state), win.vs)) { if (mesh_range > 0.0) { - (*vs)->SetValueRange(-mesh_range, mesh_range); + win.vs->SetValueRange(-mesh_range, mesh_range); } MyExpose(); } @@ -540,7 +538,7 @@ int GLVisCommand::Execute() { cout << "Command: plot_caption: " << plot_caption << endl; win.plot_caption = plot_caption; - (*vs)->PrepareCaption(); // turn on or off the caption + win.vs->PrepareCaption(); // turn on or off the caption MyExpose(); break; } @@ -549,8 +547,8 @@ int GLVisCommand::Execute() { cout << "Command: axis_labels: '" << axis_label_x << "' '" << axis_label_y << "' '" << axis_label_z << "'" << endl; - (*vs)->SetAxisLabels(axis_label_x.c_str(), axis_label_y.c_str(), - axis_label_z.c_str()); + win.vs->SetAxisLabels(axis_label_x.c_str(), axis_label_y.c_str(), + axis_label_z.c_str()); MyExpose(); break; } @@ -559,7 +557,7 @@ int GLVisCommand::Execute() { cout << "Command: axis_numberformat: '" << axis_formatting << "'" << endl; - (*vs)->SetAxisNumberFormat(axis_formatting); + win.vs->SetAxisNumberFormat(axis_formatting); MyExpose(); break; } @@ -568,7 +566,7 @@ int GLVisCommand::Execute() { cout << "Command: colorbar_numberformat: '" << colorbar_formatting << "'" << endl; - (*vs)->SetColorbarNumberFormat(colorbar_formatting); + win.vs->SetColorbarNumberFormat(colorbar_formatting); MyExpose(); break; } @@ -584,7 +582,7 @@ int GLVisCommand::Execute() { cout << "Command: view: " << view_ang_theta << ' ' << view_ang_phi << endl; - (*vs)->SetView(view_ang_theta, view_ang_phi); + win.vs->SetView(view_ang_theta, view_ang_phi); MyExpose(); break; } @@ -592,7 +590,7 @@ int GLVisCommand::Execute() case ZOOM: { cout << "Command: zoom: " << zoom_factor << endl; - (*vs)->Zoom(zoom_factor); + win.vs->Zoom(zoom_factor); MyExpose(); break; } @@ -600,7 +598,7 @@ int GLVisCommand::Execute() case SUBDIVISIONS: { cout << "Command: subdivisions: " << flush; - (*vs)->SetRefineFactors(subdiv_tot, subdiv_bdr); + win.vs->SetRefineFactors(subdiv_tot, subdiv_bdr); cout << subdiv_tot << ' ' << subdiv_bdr << endl; MyExpose(); break; @@ -609,7 +607,7 @@ int GLVisCommand::Execute() case VALUE_RANGE: { cout << "Command: valuerange: " << flush; - (*vs)->SetValueRange(val_min, val_max); + win.vs->SetValueRange(val_min, val_max); cout << val_min << ' ' << val_max << endl; MyExpose(); break; @@ -618,8 +616,8 @@ int GLVisCommand::Execute() case LEVELLINES: { cout << "Command: levellines: " << flush; - (*vs)->SetLevelLines(lvl_min, lvl_max, lvl_num); - (*vs)->UpdateLevelLines(); + win.vs->SetLevelLines(lvl_min, lvl_max, lvl_num); + win.vs->UpdateLevelLines(); cout << lvl_min << ' ' << lvl_max << ' ' << lvl_num << endl; MyExpose(); break; @@ -644,7 +642,7 @@ int GLVisCommand::Execute() } if (s != VisualizationSceneScalarData::Shading::Invalid) { - (*vs)->SetShading(s, false); + win.vs->SetShading(s, false); cout << shading << endl; MyExpose(); } @@ -659,8 +657,8 @@ int GLVisCommand::Execute() { cout << "Command: viewcenter: " << view_center_x << ' ' << view_center_y << endl; - (*vs)->ViewCenterX = view_center_x; - (*vs)->ViewCenterY = view_center_y; + win.vs->ViewCenterX = view_center_x; + win.vs->ViewCenterY = view_center_y; MyExpose(); break; } @@ -670,19 +668,19 @@ int GLVisCommand::Execute() cout << "Command: autoscale: " << autoscale_mode; if (autoscale_mode == "off") { - (*vs)->SetAutoscale(0); + win.vs->SetAutoscale(0); } else if (autoscale_mode == "on") { - (*vs)->SetAutoscale(1); + win.vs->SetAutoscale(1); } else if (autoscale_mode == "value") { - (*vs)->SetAutoscale(2); + win.vs->SetAutoscale(2); } else if (autoscale_mode == "mesh") { - (*vs)->SetAutoscale(3); + win.vs->SetAutoscale(3); } else { @@ -695,10 +693,10 @@ int GLVisCommand::Execute() case PALETTE: { cout << "Command: palette: " << palette << endl; - (*vs)->palette.SetIndex(palette-1); + win.vs->palette.SetIndex(palette-1); if (!GetUseTexture()) { - (*vs)->EventUpdateColors(); + win.vs->EventUpdateColors(); } MyExpose(); break; @@ -707,12 +705,12 @@ int GLVisCommand::Execute() case PALETTE_REPEAT: { cout << "Command: palette_repeat: " << palette_repeat << endl; - (*vs)->palette.SetRepeatTimes(palette_repeat); - (*vs)->palette.GenerateTextures(); + win.vs->palette.SetRepeatTimes(palette_repeat); + win.vs->palette.GenerateTextures(); if (!GetUseTexture()) { - (*vs)->EventUpdateColors(); + win.vs->EventUpdateColors(); } MyExpose(); break; @@ -726,7 +724,7 @@ int GLVisCommand::Execute() cout << ' ' << camera[i]; } cout << endl; - (*vs)->cam.Set(camera); + win.vs->cam.Set(camera); MyExpose(); break; } diff --git a/lib/threads.hpp b/lib/threads.hpp index 1a48aa95..78c1649d 100644 --- a/lib/threads.hpp +++ b/lib/threads.hpp @@ -12,8 +12,7 @@ #ifndef GLVIS_THREADS_HPP #define GLVIS_THREADS_HPP -#include "vsdata.hpp" -#include "data_state.hpp" +#include "window.hpp" #include #include #include @@ -23,9 +22,8 @@ class GLVisCommand { private: // Pointers to global GLVis data - VisualizationSceneScalarData **vs; - DataState& curr_state; - SdlWindow *thread_wnd; + Window &win; + SdlWindow *thread_wnd; std::mutex glvis_mutex; std::condition_variable glvis_cond; @@ -101,12 +99,11 @@ class GLVisCommand public: // called by the main execution thread - GLVisCommand(VisualizationSceneScalarData **_vs, - DataState& thread_state); + GLVisCommand(Window &win); // to be used by worker threads - bool KeepAttrib() { return curr_state.keep_attr; } // may need to sync this - bool FixElementOrientations() { return curr_state.fix_elem_orient; } + bool KeepAttrib() { return win.data_state.keep_attr; } // may need to sync this + bool FixElementOrientations() { return win.data_state.fix_elem_orient; } // called by worker threads int NewMeshAndSolution(DataState &&ss); diff --git a/lib/vsdata.cpp b/lib/vsdata.cpp index 17884eb9..fdd1ffc0 100644 --- a/lib/vsdata.cpp +++ b/lib/vsdata.cpp @@ -611,7 +611,8 @@ void VisualizationSceneScalarData::PrepareCaption() GetFont()->getObjectSize(caption, caption_w, caption_h); } -thread_local VisualizationSceneScalarData * vsdata; +static thread_local VisualizationSceneScalarData * vsdata; +static thread_local Window *window; extern thread_local VisualizationScene * locscene; void KeycPressed(GLenum state) @@ -643,7 +644,7 @@ void KeycPressed(GLenum state) void KeyCPressed() { cout << "Enter new caption: " << flush; - std::getline(cin, win.plot_caption); + std::getline(cin, window->plot_caption); vsdata->PrepareCaption(); // turn on or off the caption SendExposeEvent(); } @@ -1354,19 +1355,22 @@ void VisualizationSceneScalarData::SetAutoscale(int _autoscale) } VisualizationSceneScalarData::VisualizationSceneScalarData( - Mesh & m, Vector & s, Mesh *mc) - : a_label_x("x"), a_label_y("y"), a_label_z("z") + Window &win_, bool init) : win(win_) { - mesh = &m; - mesh_coarse = mc; - sol = &s; + mesh = win.data_state.mesh.get(); + mesh_coarse = win.data_state.mesh_quad.get(); + sol = &win.data_state.sol; - Init(); + if (init) + { + Init(); + } } void VisualizationSceneScalarData::Init() { vsdata = this; + window = &win; wnd = GetAppWindow(); arrow_type = arrow_scaling_type = 0; diff --git a/lib/vsdata.hpp b/lib/vsdata.hpp index 60b61fe5..0020abc1 100644 --- a/lib/vsdata.hpp +++ b/lib/vsdata.hpp @@ -21,8 +21,6 @@ using namespace mfem; -extern thread_local Window win; // defined in glvis.cpp - class Plane { private: @@ -72,9 +70,11 @@ class VisualizationSceneScalarData : public VisualizationScene Mesh *mesh{}, *mesh_coarse{}; Vector *sol{}; + Window &win; + double minv, maxv; - std::string a_label_x, a_label_y, a_label_z; + std::string a_label_x{"x"}, a_label_y{"y"}, a_label_z{"z"}; int scaling, colorbar, drawaxes; Shading shading; @@ -158,9 +158,7 @@ class VisualizationSceneScalarData : public VisualizationScene /// Shrink factor with respect to the element (material) attributes centers double shrinkmat; - VisualizationSceneScalarData() - : a_label_x("x"), a_label_y("y"), a_label_z("z") {} - VisualizationSceneScalarData (Mesh & m, Vector & s, Mesh *mc = NULL); + VisualizationSceneScalarData(Window &win, bool init = true); virtual ~VisualizationSceneScalarData(); diff --git a/lib/vssolution.cpp b/lib/vssolution.cpp index 0033e512..7ec44f61 100644 --- a/lib/vssolution.cpp +++ b/lib/vssolution.cpp @@ -419,20 +419,22 @@ static void KeyF12Pressed() } } -VisualizationSceneSolution::VisualizationSceneSolution() -{ - v_normals = NULL; -} - VisualizationSceneSolution::VisualizationSceneSolution( - Mesh &m, Vector &s, Mesh *mc, Vector *normals) + Window &win_, bool init) : VisualizationSceneScalarData(win_, false) { - mesh = &m; - mesh_coarse = mc; - sol = &s; - v_normals = normals; + if (win.data_state.normals.Size() > 0) + { + v_normals = &win.data_state.normals; + } - Init(); + if (init) + { + Init(); + if (win.data_state.grid_f) + { + SetGridFunction(*win.data_state.grid_f); + } + } } void VisualizationSceneSolution::Init() diff --git a/lib/vssolution.hpp b/lib/vssolution.hpp index 86b848ca..b41be912 100644 --- a/lib/vssolution.hpp +++ b/lib/vssolution.hpp @@ -26,7 +26,7 @@ using namespace mfem; class VisualizationSceneSolution : public VisualizationSceneScalarData { protected: - Vector *v_normals; + Vector *v_normals{}; GridFunction *rsol; int drawmesh, drawelems, drawnums, draworder; @@ -86,9 +86,7 @@ class VisualizationSceneSolution : public VisualizationSceneScalarData int attr_to_show, bdr_attr_to_show; Array el_attr_to_show, bdr_el_attr_to_show; - VisualizationSceneSolution(); - VisualizationSceneSolution(Mesh &m, Vector &s, Mesh *mc = NULL, - Vector *normals = NULL); + VisualizationSceneSolution(Window &win, bool init = true); virtual ~VisualizationSceneSolution(); diff --git a/lib/vssolution3d.cpp b/lib/vssolution3d.cpp index 4d927da8..d9e2c1c3 100644 --- a/lib/vssolution3d.cpp +++ b/lib/vssolution3d.cpp @@ -687,18 +687,18 @@ static void KeyF10Pressed() SendExposeEvent(); } -VisualizationSceneSolution3d::VisualizationSceneSolution3d() -{} - -VisualizationSceneSolution3d::VisualizationSceneSolution3d(Mesh &m, Vector &s, - Mesh *mc) +VisualizationSceneSolution3d::VisualizationSceneSolution3d(Window &win_, + bool init) + : VisualizationSceneScalarData(win_, false) { - mesh = &m; - mesh_coarse = mc; - sol = &s; - GridF = NULL; - - Init(); + if (init) + { + Init(); + if (win.data_state.grid_f) + { + SetGridFunction(win.data_state.grid_f.get()); + } + } } diff --git a/lib/vssolution3d.hpp b/lib/vssolution3d.hpp index 0448e128..30ad530e 100644 --- a/lib/vssolution3d.hpp +++ b/lib/vssolution3d.hpp @@ -43,7 +43,7 @@ class VisualizationSceneSolution3d : public VisualizationSceneScalarData int nlevels; Array levels; - GridFunction *GridF; + GridFunction *GridF{}; void Init(); @@ -119,8 +119,7 @@ class VisualizationSceneSolution3d : public VisualizationSceneScalarData Array bdr_attr_to_show; - VisualizationSceneSolution3d(); - VisualizationSceneSolution3d(Mesh & m, Vector & s, Mesh *mc); + VisualizationSceneSolution3d(Window &win, bool init = true); void SetGridFunction (GridFunction *gf) { GridF = gf; } diff --git a/lib/vsvector.cpp b/lib/vsvector.cpp index 926e9c8a..16283540 100644 --- a/lib/vsvector.cpp +++ b/lib/vsvector.cpp @@ -256,56 +256,50 @@ const char *Vec2ScalarNames[7] = "curl", "anisotropy" }; -VisualizationSceneVector::VisualizationSceneVector(Mesh & m, - Vector & sx, Vector & sy, Mesh *mc) +VisualizationSceneVector::VisualizationSceneVector(Window &win_) + : VisualizationSceneSolution(win_, false) { - mesh = &m; - mesh_coarse = mc; - solx = &sx; - soly = &sy; - - sol = new Vector(mesh -> GetNV()); + if (win.data_state.grid_f) + { + FiniteElementSpace *fes = win.data_state.grid_f->FESpace(); + if (fes == NULL || win.data_state.grid_f->VectorDim() != 2) + { + cout << "VisualizationSceneVector::VisualizationSceneVector" << endl; + exit(1); + } - VecGridF = NULL; + VecGridF = win.data_state.grid_f.get(); - Init(); -} + solx = new Vector(mesh -> GetNV()); + soly = new Vector(mesh -> GetNV()); -VisualizationSceneVector::VisualizationSceneVector(GridFunction &vgf) -{ - FiniteElementSpace *fes = vgf.FESpace(); - if (fes == NULL || vgf.VectorDim() != 2) + VecGridF->GetNodalValues(*solx, 1); + VecGridF->GetNodalValues(*soly, 2); + } + else { - cout << "VisualizationSceneVector::VisualizationSceneVector" << endl; - exit(1); + solx = &win.data_state.solu; + soly = &win.data_state.solv; } - VecGridF = &vgf; - - mesh = fes->GetMesh(); - - solx = new Vector(mesh -> GetNV()); - soly = new Vector(mesh -> GetNV()); - - vgf.GetNodalValues (*solx, 1); - vgf.GetNodalValues (*soly, 2); + sol = new Vector(mesh -> GetNV()); - sol = new Vector(mesh -> GetNV()); + Init(); - // VisualizationSceneSolution::Init() sets rsol = NULL ! + if (VecGridF) { - Init(); - SetGridFunction(vgf); - } + // VisualizationSceneSolution::Init() sets rsol = NULL ! + SetGridFunction(*VecGridF); - mesh->GetNodes(vc0); - if (vc0.Size() != vgf.Size()) - { - vc0.Destroy(); - } - else - { - vc0 += vgf; + mesh->GetNodes(vc0); + if (vc0.Size() != VecGridF->Size()) + { + vc0.Destroy(); + } + else + { + vc0 += *VecGridF; + } } } diff --git a/lib/vsvector.hpp b/lib/vsvector.hpp index c7453bd2..b8c53601 100644 --- a/lib/vsvector.hpp +++ b/lib/vsvector.hpp @@ -26,7 +26,7 @@ class VisualizationSceneVector : public VisualizationSceneSolution gl3::GlDrawable vector_buf; gl3::GlDrawable displine_buf; - GridFunction *VecGridF; + GridFunction *VecGridF{}; void Init(); @@ -48,8 +48,7 @@ class VisualizationSceneVector : public VisualizationSceneSolution int GetFunctionAutoRefineFactor() override; public: - VisualizationSceneVector(Mesh &m, Vector &sx, Vector &sy, Mesh *mc = NULL); - VisualizationSceneVector(GridFunction &vgf); + VisualizationSceneVector(Window &win_); void NewMeshAndSolution(GridFunction &vgf, Mesh *mc = NULL); diff --git a/lib/vsvector3d.cpp b/lib/vsvector3d.cpp index 308eb8b4..0df11e77 100644 --- a/lib/vsvector3d.cpp +++ b/lib/vsvector3d.cpp @@ -341,49 +341,38 @@ void VisualizationSceneVector3d::ToggleScalarFunction() FindNewValueRange(true); } -VisualizationSceneVector3d::VisualizationSceneVector3d(Mesh &m, Vector &sx, - Vector &sy, Vector &sz, Mesh *mc) +VisualizationSceneVector3d::VisualizationSceneVector3d(Window &win_) + : VisualizationSceneSolution3d(win_, false) { - mesh = &m; - mesh_coarse = mc; - solx = &sx; - soly = &sy; - solz = &sz; + if (win.data_state.grid_f) + { + FiniteElementSpace *fes = win.data_state.grid_f->FESpace(); + if (fes == NULL || fes->GetVDim() != 3) + { + cout << "VisualizationSceneVector3d::VisualizationSceneVector3d" << endl; + exit(1); + } - sol = new Vector(mesh->GetNV()); + VecGridF = win.data_state.grid_f.get(); - sfes = NULL; - VecGridF = NULL; + sfes = new FiniteElementSpace(mesh, fes->FEColl(), 1, fes->GetOrdering()); + GridF = new GridFunction(sfes); - Init(); -} + solx = new Vector(mesh->GetNV()); + soly = new Vector(mesh->GetNV()); + solz = new Vector(mesh->GetNV()); -VisualizationSceneVector3d::VisualizationSceneVector3d(GridFunction &vgf, - Mesh *mc) -{ - FiniteElementSpace *fes = vgf.FESpace(); - if (fes == NULL || fes->GetVDim() != 3) + VecGridF->GetNodalValues(*solx, 1); + VecGridF->GetNodalValues(*soly, 2); + VecGridF->GetNodalValues(*solz, 3); + } + else { - cout << "VisualizationSceneVector3d::VisualizationSceneVector3d" << endl; - exit(1); + solx = &win.data_state.solu; + soly = &win.data_state.solv; + solz = &win.data_state.solw; } - VecGridF = &vgf; - - mesh = fes->GetMesh(); - mesh_coarse = mc; - - sfes = new FiniteElementSpace(mesh, fes->FEColl(), 1, fes->GetOrdering()); - GridF = new GridFunction(sfes); - - solx = new Vector(mesh->GetNV()); - soly = new Vector(mesh->GetNV()); - solz = new Vector(mesh->GetNV()); - - vgf.GetNodalValues(*solx, 1); - vgf.GetNodalValues(*soly, 2); - vgf.GetNodalValues(*solz, 3); - sol = new Vector(mesh->GetNV()); Init(); diff --git a/lib/vsvector3d.hpp b/lib/vsvector3d.hpp index b32fe3ea..e15a89b9 100644 --- a/lib/vsvector3d.hpp +++ b/lib/vsvector3d.hpp @@ -26,8 +26,8 @@ class VisualizationSceneVector3d : public VisualizationSceneSolution3d gl3::GlDrawable vector_buf; gl3::GlDrawable displine_buf; - GridFunction *VecGridF; - FiniteElementSpace *sfes; + GridFunction *VecGridF{}; + FiniteElementSpace *sfes{}; void Init(); @@ -39,9 +39,7 @@ class VisualizationSceneVector3d : public VisualizationSceneSolution3d public: int ianim, ianimd, ianimmax, drawdisp; - VisualizationSceneVector3d(Mesh & m, Vector & sx, Vector & sy, Vector & sz, - Mesh *mc = NULL); - VisualizationSceneVector3d (GridFunction &vgf, Mesh *mc = NULL); + VisualizationSceneVector3d(Window &win); void NewMeshAndSolution(Mesh *new_m, Mesh *new_mc, GridFunction *new_v); From a0e70ad3d495cf80dd7ea85dd53c78ae91d02a6c Mon Sep 17 00:00:00 2001 From: Jan Nikl Date: Fri, 2 May 2025 18:04:25 -0700 Subject: [PATCH 05/56] Moved script functions to ScriptController making Window static. --- glvis.cpp | 5 +++-- lib/script_controller.cpp | 45 +++++++++++++++++---------------------- lib/script_controller.hpp | 32 +++++++++++++++++++++++++++- 3 files changed, 53 insertions(+), 29 deletions(-) diff --git a/glvis.cpp b/glvis.cpp index 29c019e2..72d98734 100644 --- a/glvis.cpp +++ b/glvis.cpp @@ -81,7 +81,7 @@ enum InputOptions }; int input = INPUT_SERVER_MODE; -thread_local Window win; +static thread_local Window win; extern thread_local GLVisCommand* glvis_command; thread_local communication_thread *comm_thread = NULL; @@ -784,7 +784,8 @@ int main (int argc, char *argv[]) } cout << "Running script from file: " << script_file << endl; cout << "You may need to press to execute the script steps." << endl; - PlayScript(scr); + ScriptController script(win); + script.PlayScript(scr); return 0; } diff --git a/lib/script_controller.cpp b/lib/script_controller.cpp index 4337593c..d4390e86 100644 --- a/lib/script_controller.cpp +++ b/lib/script_controller.cpp @@ -9,7 +9,7 @@ // terms of the BSD-3 license. We welcome feedback and contributions, see file // CONTRIBUTING.md for details. -#include "window.hpp" +#include "script_controller.hpp" #include "file_reader.hpp" #include "coll_reader.hpp" #include "stream_reader.hpp" @@ -29,18 +29,10 @@ extern int window_w; extern int window_h; extern const char *c_plot_caption; -extern thread_local Window win; - -istream *script = NULL; -int scr_running = 0; -int scr_level = 0; -Vector *init_nodes = NULL; -double scr_min_val, scr_max_val; - bool GLVisInitVis(StreamCollection input_streams); void GLVisStartVis(); -int ScriptReadSolution(istream &scr, DataState& state) +int ScriptController::ScriptReadSolution(istream &scr, DataState &state) { int err_read; string mword,sword; @@ -68,7 +60,7 @@ int ScriptReadSolution(istream &scr, DataState& state) return err_read; } -int ScriptReadQuadrature(istream &scr, DataState& state) +int ScriptController::ScriptReadQuadrature(istream &scr, DataState &state) { int err_read; string mword,sword; @@ -96,7 +88,7 @@ int ScriptReadQuadrature(istream &scr, DataState& state) return err_read; } -int ScriptReadParSolution(istream &scr, DataState& state) +int ScriptController::ScriptReadParSolution(istream &scr, DataState &state) { int np, scr_keep_attr, err_read; string mesh_prefix, sol_prefix; @@ -127,7 +119,7 @@ int ScriptReadParSolution(istream &scr, DataState& state) return err_read; } -int ScriptReadParQuadrature(istream &scr, DataState& state) +int ScriptController::ScriptReadParQuadrature(istream &scr, DataState &state) { int np, scr_keep_attr, err_read; string mesh_prefix, quad_prefix; @@ -158,7 +150,7 @@ int ScriptReadParQuadrature(istream &scr, DataState& state) return err_read; } -int ScriptReadDisplMesh(istream &scr, DataState& state) +int ScriptController::ScriptReadDisplMesh(istream &scr, DataState &state) { DataState meshstate; string word; @@ -218,8 +210,8 @@ int ScriptReadDisplMesh(istream &scr, DataState& state) return 0; } -int ScriptReadDataColl(istream &scr, DataState &state, bool mesh_only = true, - bool quad = false) +int ScriptController::ScriptReadDataColl(istream &scr, DataState &state, + bool mesh_only, bool quad) { int err_read; int type; @@ -255,7 +247,7 @@ int ScriptReadDataColl(istream &scr, DataState &state, bool mesh_only = true, return err_read; } -void ExecuteScriptCommand() +void ScriptController::ExecuteScriptCommand() { if (!script) { @@ -693,32 +685,32 @@ void ExecuteScriptCommand() } } -void ScriptControl(); +thread_local ScriptController *ScriptController::script_ctrl = NULL; -void ScriptIdleFunc() +void ScriptController::ScriptIdleFunc() { - ExecuteScriptCommand(); - if (scr_level == 0) + script_ctrl->ExecuteScriptCommand(); + if (script_ctrl->scr_level == 0) { ScriptControl(); } } -void ScriptControl() +void ScriptController::ScriptControl() { - if (scr_running) + if (script_ctrl->scr_running) { - scr_running = 0; + script_ctrl->scr_running = 0; RemoveIdleFunc(ScriptIdleFunc); } else { - scr_running = 1; + script_ctrl->scr_running = 1; AddIdleFunc(ScriptIdleFunc); } } -void PlayScript(istream &scr) +void ScriptController::PlayScript(istream &scr) { string word; @@ -841,6 +833,7 @@ void PlayScript(istream &scr) scr_level = scr_running = 0; script = &scr; + script_ctrl = this; win.data_state.keys.clear(); // Make sure the singleton object returned by GetMainThread() is diff --git a/lib/script_controller.hpp b/lib/script_controller.hpp index b9ecf838..201aa024 100644 --- a/lib/script_controller.hpp +++ b/lib/script_controller.hpp @@ -14,6 +14,36 @@ #include -void PlayScript(std::istream &scr); +#include "window.hpp" + +class ScriptController +{ + Window &win; + + istream *script = NULL; + int scr_running = 0; + int scr_level = 0; + mfem::Vector *init_nodes = NULL; + double scr_min_val, scr_max_val; + + static int ScriptReadSolution(istream &scr, DataState &state); + static int ScriptReadQuadrature(istream &scr, DataState &state); + static int ScriptReadParSolution(istream &scr, DataState &state); + static int ScriptReadParQuadrature(istream &scr, DataState &state); + int ScriptReadDisplMesh(istream &scr, DataState &state); + int ScriptReadDataColl(istream &scr, DataState &state, bool mesh_only = true, + bool quad = false); + + //key handlers using thread-local singleton + static thread_local ScriptController *script_ctrl; + static void ScriptIdleFunc(); + static void ScriptControl(); + void ExecuteScriptCommand(); + +public: + ScriptController(Window &win_) : win(win_) { } + + void PlayScript(std::istream &scr); +}; #endif // GLVIS_SCRIPT_CONTROLLER_HPP From 8ed454a42dacf3fbf6259c1e1a5b8e04b5d06f2b Mon Sep 17 00:00:00 2001 From: Jan Nikl Date: Mon, 5 May 2025 09:59:13 -0700 Subject: [PATCH 06/56] Moved visualization routines to Window and eliminated global cmd-line options. --- glvis.cpp | 258 +++++++------------------------------- lib/CMakeLists.txt | 3 +- lib/script_controller.cpp | 35 ++---- lib/script_controller.hpp | 6 + lib/window.cpp | 177 ++++++++++++++++++++++++++ lib/window.hpp | 23 ++++ makefile | 2 +- 7 files changed, 261 insertions(+), 243 deletions(-) create mode 100644 lib/window.cpp diff --git a/glvis.cpp b/glvis.cpp index 72d98734..675ae403 100644 --- a/glvis.cpp +++ b/glvis.cpp @@ -46,26 +46,6 @@ using namespace mfem; const char *string_none = "(none)"; const char *string_default = "(default)"; -// Global variables for command line arguments -const char *mesh_file = string_none; -const char *sol_file = string_none; -const char *vec_sol_file = string_none; -const char *gfunc_file = string_none; -const char *qfunc_file = string_none; -string dc_protocol = string_default; -int dc_cycle = 0; -const char *arg_keys = string_none; -int pad_digits = 6; -int gf_component = -1; -int qf_component = -1; -int window_x = 0; // not a command line option -int window_y = 0; // not a command line option -int window_w = 400; -int window_h = 350; -const char *window_title = string_default; -const char *c_plot_caption = string_none; -bool secure = socketstream::secure_default; - // Global variables enum InputOptions { @@ -81,183 +61,28 @@ enum InputOptions }; int input = INPUT_SERVER_MODE; -static thread_local Window win; -extern thread_local GLVisCommand* glvis_command; -thread_local communication_thread *comm_thread = NULL; - thread_local GeometryRefiner GLVisGeometryRefiner; -const char *window_titles[] = { "GLVis [mesh]", - "GLVis [scalar data]", - "GLVis [vector data]", - }; - void PrintSampleUsage(ostream &out); -// switch representation of the quadrature function -void SwitchQuadSolution(); - -// Visualize the data in the global variables mesh, sol/grid_f, etc -bool GLVisInitVis(StreamCollection input_streams) -{ - DataState::FieldType field_type = win.data_state.GetType(); - - if (field_type <= DataState::FieldType::MIN - || field_type >= DataState::FieldType::MAX) - { - return false; - } - - const char *win_title = (window_title == string_default) ? - window_titles[(int)field_type] : window_title; - - if (InitVisualization(win_title, window_x, window_y, window_w, window_h)) - { - cerr << "Initializing the visualization failed." << endl; - return false; - } - - if (input_streams.size() > 0) - { - GetAppWindow()->setOnKeyDown(SDLK_SPACE, ThreadsPauseFunc); - glvis_command = new GLVisCommand(win); - comm_thread = new communication_thread(std::move(input_streams), glvis_command); - } - - if (win.data_state.quad_f) - { - GetAppWindow()->setOnKeyDown('Q', SwitchQuadSolution); - } - - double mesh_range = -1.0; - if (field_type == DataState::FieldType::SCALAR - || field_type == DataState::FieldType::MESH) - { - if (win.data_state.grid_f) - { - win.data_state.grid_f->GetNodalValues(win.data_state.sol); - } - if (win.data_state.mesh->SpaceDimension() == 2) - { - win.vs = new VisualizationSceneSolution(win); - - if (field_type == DataState::FieldType::MESH) - { - win.vs->OrthogonalProjection = 1; - win.vs->SetLight(false); - win.vs->Zoom(1.8); - // Use the 'bone' palette when visualizing a 2D mesh only (otherwise - // the 'jet-like' palette is used in 2D, see vssolution.cpp). - win.vs->palette.SetIndex(4); - } - } - else if (win.data_state.mesh->SpaceDimension() == 3) - { - VisualizationSceneSolution3d *vss; - win.vs = vss = new VisualizationSceneSolution3d(win); - - if (field_type == DataState::FieldType::MESH) - { - if (win.data_state.mesh->Dimension() == 3) - { - // Use the 'white' palette when visualizing a 3D volume mesh only - vss->palette.SetIndex(11); - vss->SetLightMatIdx(4); - } - else - { - // Use the 'bone' palette when visualizing a surface mesh only - vss->palette.SetIndex(4); - } - // Otherwise, the 'vivid' palette is used in 3D see vssolution3d.cpp - vss->ToggleDrawAxes(); - vss->ToggleDrawMesh(); - } - } - if (field_type == DataState::FieldType::MESH) - { - if (win.data_state.grid_f) - { - mesh_range = win.data_state.grid_f->Max() + 1.0; - } - else - { - mesh_range = win.data_state.sol.Max() + 1.0; - } - } - } - else if (field_type == DataState::FieldType::VECTOR) - { - if (win.data_state.mesh->SpaceDimension() == 2) - { - win.vs = new VisualizationSceneVector(win); - } - else if (win.data_state.mesh->SpaceDimension() == 3) - { - if (win.data_state.grid_f) - { - win.data_state.ProjectVectorFEGridFunction(); - } - win.vs = new VisualizationSceneVector3d(win); - } - } - - if (win.vs) - { - // increase the refinement factors if visualizing a GridFunction - if (win.data_state.grid_f) - { - win.vs->AutoRefine(); - win.vs->SetShading(VisualizationSceneScalarData::Shading::Noncomforming, true); - } - if (mesh_range > 0.0) - { - win.vs->SetValueRange(-mesh_range, mesh_range); - win.vs->SetAutoscale(0); - } - if (win.data_state.mesh->SpaceDimension() == 2 - && field_type == DataState::FieldType::MESH) - { - SetVisualizationScene(win.vs, 2, win.data_state.keys.c_str()); - } - else - { - SetVisualizationScene(win.vs, 3, win.data_state.keys.c_str()); - } - } - return true; -} - -void GLVisStartVis() -{ - RunVisualization(); // deletes win.vs - win.vs = NULL; - if (glvis_command) - { - glvis_command->Terminate(); - delete comm_thread; - delete glvis_command; - glvis_command = NULL; - } - cout << "GLVis window closed." << endl; -} - class Session { StreamCollection input_streams; - DataState state; + Window win; std::thread handler; public: Session(bool fix_elem_orient, - bool save_coloring) + bool save_coloring, + string plot_caption) { - state.fix_elem_orient = fix_elem_orient; - state.save_coloring = save_coloring; + win.data_state.fix_elem_orient = fix_elem_orient; + win.data_state.save_coloring = save_coloring; + win.plot_caption = plot_caption; } - Session(DataState other_state) - : state(std::move(other_state)) + Session(Window other_win) + : win(std::move(other_win)) { } ~Session() = default; @@ -265,27 +90,20 @@ class Session Session(Session&& from) = default; Session& operator= (Session&& from) = default; - inline DataState& GetState() { return state; } - inline const DataState& GetState() const { return state; } + inline DataState& GetState() { return win.data_state; } + inline const DataState& GetState() const { return win.data_state; } void StartSession() { - auto funcThread = [](DataState thread_state, StreamCollection is) + auto funcThread = [](Window w, StreamCollection is) { - // Set thread-local stream state - win.data_state = std::move(thread_state); - if (c_plot_caption != string_none) - { - win.plot_caption = c_plot_caption; - } - - if (GLVisInitVis(std::move(is))) + if (w.GLVisInitVis(std::move(is))) { - GLVisStartVis(); + w.GLVisStartVis(); } }; handler = std::thread {funcThread, - std::move(state), std::move(input_streams)}; + std::move(win), std::move(input_streams)}; handler.detach(); } @@ -299,7 +117,7 @@ class Session } string data_type; *ifs >> data_type >> ws; - StreamReader reader(state); + StreamReader reader(win.data_state); reader.ReadStream(*ifs, data_type); input_streams.emplace_back(std::move(ifs)); @@ -310,7 +128,7 @@ class Session int StartStreamSession(std::unique_ptr &&stream, const std::string &data_type) { - StreamReader reader(state); + StreamReader reader(win.data_state); int ierr = reader.ReadStream(*stream, data_type); if (ierr) { return ierr; } input_streams.emplace_back(std::move(stream)); @@ -321,7 +139,7 @@ class Session int StartStreamSession(StreamCollection &&streams) { - StreamReader reader(state); + StreamReader reader(win.data_state); int ierr = reader.ReadStreams(streams); if (ierr) { return ierr; } input_streams = std::move(streams); @@ -333,7 +151,7 @@ class Session }; void GLVisServer(int portnum, bool save_stream, bool fix_elem_orient, - bool save_coloring) + bool save_coloring, string plot_caption) { std::vector current_sessions; string data_type; @@ -483,7 +301,7 @@ void GLVisServer(int portnum, bool save_stream, bool fix_elem_orient, while (1); } - Session new_session(fix_elem_orient, save_coloring); + Session new_session(fix_elem_orient, save_coloring, plot_caption); constexpr int tmp_filename_size = 50; char tmp_file[tmp_filename_size]; @@ -530,7 +348,23 @@ int main (int argc, char *argv[]) // SDL_main(). SDL_SetMainReady(); #endif + // main Window structure + Window win; + // variables for command line arguments + const char *mesh_file = string_none; + const char *sol_file = string_none; + const char *vec_sol_file = string_none; + const char *gfunc_file = string_none; + const char *qfunc_file = string_none; + string dc_protocol = string_default; + int dc_cycle = 0; + const char *arg_keys = string_none; + int pad_digits = 6; + int gf_component = -1; + int qf_component = -1; + const char *c_plot_caption = string_none; + bool secure = socketstream::secure_default; const char *visit_coll = string_none; const char *sidre_coll = string_none; const char *fms_coll = string_none; @@ -619,11 +453,11 @@ int main (int argc, char *argv[]) " visualization."); args.AddOption(&stream_file, "-saved", "--saved-stream", "Load a GLVis stream saved to a file."); - args.AddOption(&window_w, "-ww", "--window-width", + args.AddOption(&win.window_w, "-ww", "--window-width", "Set the window width."); - args.AddOption(&window_h, "-wh", "--window-height", + args.AddOption(&win.window_h, "-wh", "--window-height", "Set the window height."); - args.AddOption(&window_title, "-wt", "--window-title", + args.AddOption(&win.window_title, "-wt", "--window-title", "Set the window title."); args.AddOption(&c_plot_caption, "-c", "--plot-caption", "Set the plot caption (visible when colorbar is visible)."); @@ -762,7 +596,8 @@ int main (int argc, char *argv[]) GetMainThread(); Session stream_session(win.data_state.fix_elem_orient, - win.data_state.save_coloring); + win.data_state.save_coloring, + win.plot_caption); if (!stream_session.StartSavedSession(stream_file)) { @@ -831,7 +666,8 @@ int main (int argc, char *argv[]) // Run server in new thread std::thread serverThread{GLVisServer, portnum, save_stream, win.data_state.fix_elem_orient, - win.data_state.save_coloring}; + win.data_state.save_coloring, + win.plot_caption}; // Start SDL in main thread SDLMainLoop(true); @@ -945,7 +781,7 @@ int main (int argc, char *argv[]) // initialized from the main thread. GetMainThread(); - Session single_session(std::move(win.data_state)); + Session single_session(std::move(win)); single_session.StartSession(); SDLMainLoop(); @@ -974,11 +810,3 @@ void PrintSampleUsage(ostream &os) " glvis -np <#proc> -m [-q ]\n\n" "All Options:\n"; } - -void SwitchQuadSolution() -{ - int iqs = ((int)win.data_state.GetQuadSolution()+1) - % ((int)DataState::QuadSolution::MAX); - win.data_state.SwitchQuadSolution((DataState::QuadSolution)iqs, win.vs); - SendExposeEvent(); -} diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 89d963d5..4f63a6c0 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -33,7 +33,8 @@ list(APPEND SOURCES vssolution.cpp vssolution3d.cpp vsvector.cpp - vsvector3d.cpp) + vsvector3d.cpp + window.cpp) list(APPEND HEADERS gl/attr_traits.hpp diff --git a/lib/script_controller.cpp b/lib/script_controller.cpp index d4390e86..a56039c1 100644 --- a/lib/script_controller.cpp +++ b/lib/script_controller.cpp @@ -21,17 +21,6 @@ using namespace mfem; extern const char *string_none; extern const char *string_default; -extern string dc_protocol; -extern int dc_cycle; -extern int window_x; -extern int window_y; -extern int window_w; -extern int window_h; -extern const char *c_plot_caption; - -bool GLVisInitVis(StreamCollection input_streams); -void GLVisStartVis(); - int ScriptController::ScriptReadSolution(istream &scr, DataState &state) { int err_read; @@ -571,10 +560,10 @@ void ScriptController::ExecuteScriptCommand() } else if (word == "window") { - scr >> window_x >> window_y >> window_w >> window_h; - cout << "Script: window: " << window_x << ' ' << window_y - << ' ' << window_w << ' ' << window_h << endl; - MoveResizeWindow(window_x, window_y, window_w, window_h); + scr >> win.window_x >> win.window_y >> win.window_w >> win.window_h; + cout << "Script: window: " << win.window_x << ' ' << win.window_y + << ' ' << win.window_w << ' ' << win.window_h << endl; + MoveResizeWindow(win.window_x, win.window_y, win.window_w, win.window_h); MyExpose(); } else if (word == "keys") @@ -734,7 +723,7 @@ void ScriptController::PlayScript(istream &scr) scr >> word; if (word == "window") { - scr >> window_x >> window_y >> window_w >> window_h; + scr >> win.window_x >> win.window_y >> win.window_w >> win.window_h; } else if (word == "data_coll_cycle") { @@ -842,21 +831,15 @@ void ScriptController::PlayScript(istream &scr) std::thread worker_thread { - [&](DataState local_state) + [&](Window local_win) { - // set the thread-local DataState - win.data_state = std::move(local_state); - if (c_plot_caption != string_none) - { - win.plot_caption = c_plot_caption; - } - if (GLVisInitVis({})) + if (local_win.GLVisInitVis({})) { GetAppWindow()->setOnKeyDown(SDLK_SPACE, ScriptControl); - GLVisStartVis(); + local_win.GLVisStartVis(); } }, - std::move(win.data_state) + std::move(win) }; SDLMainLoop(); diff --git a/lib/script_controller.hpp b/lib/script_controller.hpp index 201aa024..ab6d1573 100644 --- a/lib/script_controller.hpp +++ b/lib/script_controller.hpp @@ -16,10 +16,16 @@ #include "window.hpp" +extern const char *string_none; +extern const char *string_default; + class ScriptController { Window &win; + string dc_protocol = string_default; + int dc_cycle = 0; + istream *script = NULL; int scr_running = 0; int scr_level = 0; diff --git a/lib/window.cpp b/lib/window.cpp new file mode 100644 index 00000000..e5cc9d83 --- /dev/null +++ b/lib/window.cpp @@ -0,0 +1,177 @@ +// Copyright (c) 2010-2025, Lawrence Livermore National Security, LLC. Produced +// at the Lawrence Livermore National Laboratory. All Rights reserved. See files +// LICENSE and NOTICE for details. LLNL-CODE-443271. +// +// This file is part of the GLVis visualization tool and library. For more +// information and source code availability see https://glvis.org. +// +// GLVis is free software; you can redistribute it and/or modify it under the +// terms of the BSD-3 license. We welcome feedback and contributions, see file +// CONTRIBUTING.md for details. + +#include "window.hpp" +#include "visual.hpp" + +extern thread_local GLVisCommand* glvis_command; + +// Visualize the data in the global variables mesh, sol/grid_f, etc +bool Window::GLVisInitVis(StreamCollection input_streams) +{ + DataState::FieldType field_type = data_state.GetType(); + + if (field_type <= DataState::FieldType::MIN + || field_type >= DataState::FieldType::MAX) + { + return false; + } + + static const char *window_titles[] = { "GLVis [mesh]", + "GLVis [scalar data]", + "GLVis [vector data]", + }; + + const char *win_title = (window_title == string_default) ? + window_titles[(int)field_type] : window_title; + + if (InitVisualization(win_title, window_x, window_y, window_w, window_h)) + { + cerr << "Initializing the visualization failed." << endl; + return false; + } + + if (input_streams.size() > 0) + { + GetAppWindow()->setOnKeyDown(SDLK_SPACE, ThreadsPauseFunc); + glvis_command = new GLVisCommand(*this); + comm_thread = new communication_thread(std::move(input_streams), glvis_command); + } + + locwin = this; + + if (data_state.quad_f) + { + GetAppWindow()->setOnKeyDown('Q', SwitchQuadSolution); + } + + double mesh_range = -1.0; + if (field_type == DataState::FieldType::SCALAR + || field_type == DataState::FieldType::MESH) + { + if (data_state.grid_f) + { + data_state.grid_f->GetNodalValues(data_state.sol); + } + if (data_state.mesh->SpaceDimension() == 2) + { + vs = new VisualizationSceneSolution(*this); + + if (field_type == DataState::FieldType::MESH) + { + vs->OrthogonalProjection = 1; + vs->SetLight(false); + vs->Zoom(1.8); + // Use the 'bone' palette when visualizing a 2D mesh only (otherwise + // the 'jet-like' palette is used in 2D, see vssolution.cpp). + vs->palette.SetIndex(4); + } + } + else if (data_state.mesh->SpaceDimension() == 3) + { + VisualizationSceneSolution3d *vss; + vs = vss = new VisualizationSceneSolution3d(*this); + + if (field_type == DataState::FieldType::MESH) + { + if (data_state.mesh->Dimension() == 3) + { + // Use the 'white' palette when visualizing a 3D volume mesh only + vss->palette.SetIndex(11); + vss->SetLightMatIdx(4); + } + else + { + // Use the 'bone' palette when visualizing a surface mesh only + vss->palette.SetIndex(4); + } + // Otherwise, the 'vivid' palette is used in 3D see vssolution3d.cpp + vss->ToggleDrawAxes(); + vss->ToggleDrawMesh(); + } + } + if (field_type == DataState::FieldType::MESH) + { + if (data_state.grid_f) + { + mesh_range = data_state.grid_f->Max() + 1.0; + } + else + { + mesh_range = data_state.sol.Max() + 1.0; + } + } + } + else if (field_type == DataState::FieldType::VECTOR) + { + if (data_state.mesh->SpaceDimension() == 2) + { + vs = new VisualizationSceneVector(*this); + } + else if (data_state.mesh->SpaceDimension() == 3) + { + if (data_state.grid_f) + { + data_state.ProjectVectorFEGridFunction(); + } + vs = new VisualizationSceneVector3d(*this); + } + } + + if (vs) + { + // increase the refinement factors if visualizing a GridFunction + if (data_state.grid_f) + { + vs->AutoRefine(); + vs->SetShading(VisualizationSceneScalarData::Shading::Noncomforming, true); + } + if (mesh_range > 0.0) + { + vs->SetValueRange(-mesh_range, mesh_range); + vs->SetAutoscale(0); + } + if (data_state.mesh->SpaceDimension() == 2 + && field_type == DataState::FieldType::MESH) + { + SetVisualizationScene(vs, 2, data_state.keys.c_str()); + } + else + { + SetVisualizationScene(vs, 3, data_state.keys.c_str()); + } + } + return true; +} + +void Window::GLVisStartVis() +{ + RunVisualization(); // deletes vs + vs = NULL; + if (glvis_command) + { + glvis_command->Terminate(); + delete comm_thread; + delete glvis_command; + glvis_command = NULL; + } + cout << "GLVis window closed." << endl; +} + +thread_local Window *Window::locwin = NULL; + +void Window::SwitchQuadSolution() +{ + int iqs = ((int)locwin->data_state.GetQuadSolution()+1) + % ((int)DataState::QuadSolution::MAX); + locwin->data_state.SwitchQuadSolution((DataState::QuadSolution)iqs, locwin->vs); + SendExposeEvent(); +} diff --git a/lib/window.hpp b/lib/window.hpp index 8f880177..0ec15a88 100644 --- a/lib/window.hpp +++ b/lib/window.hpp @@ -15,15 +15,38 @@ #include #include "data_state.hpp" +#include "stream_reader.hpp" class VisualizationSceneScalarData; +class communication_thread; + +extern const char *string_none; +extern const char *string_default; struct Window { DataState data_state; VisualizationSceneScalarData *vs = NULL; + communication_thread *comm_thread = NULL; + + int window_x = 0; // not a command line option + int window_y = 0; // not a command line option + int window_w = 400; + int window_h = 350; + const char *window_title = string_default; std::string plot_caption; std::string extra_caption; + + /// Visualize the data in the global variables mesh, sol/grid_f, etc + bool GLVisInitVis(StreamCollection input_streams); + void GLVisStartVis(); + +private: + /// Thread-local singleton for key handlers + static thread_local Window *locwin; + + /// Switch representation of the quadrature function + static void SwitchQuadSolution(); }; #endif // GLVIS_WINDOW_HPP diff --git a/makefile b/makefile index 5f7f538b..3f53000a 100644 --- a/makefile +++ b/makefile @@ -258,7 +258,7 @@ ALL_SOURCE_FILES = \ lib/script_controller.cpp lib/sdl_helper.cpp lib/sdl_main.cpp \ lib/sdl_windows.cpp lib/sdl_x11.cpp lib/stream_reader.cpp \ lib/threads.cpp lib/vsdata.cpp lib/vssolution.cpp lib/vssolution3d.cpp \ - lib/vsvector.cpp lib/vsvector3d.cpp + lib/vsvector.cpp lib/vsvector3d.cpp lib/window.cpp OBJC_SOURCE_FILES = $(if $(NOTMAC),,lib/sdl_mac.mm) DESKTOP_ONLY_SOURCE_FILES = \ lib/gl/renderer_ff.cpp lib/threads.cpp lib/gl2ps.c lib/sdl_x11.cpp From 791cb7d09acd75f8aee4fa8d1b4c436fe8b99c93 Mon Sep 17 00:00:00 2001 From: Jan Nikl Date: Mon, 5 May 2025 10:30:05 -0700 Subject: [PATCH 07/56] Moved scene updating methods to Window. --- lib/data_state.cpp | 66 +-------------------------------------- lib/data_state.hpp | 20 ++---------- lib/script_controller.cpp | 2 +- lib/threads.cpp | 2 +- lib/window.cpp | 66 ++++++++++++++++++++++++++++++++++++++- lib/window.hpp | 17 ++++++++++ 6 files changed, 87 insertions(+), 86 deletions(-) diff --git a/lib/data_state.cpp b/lib/data_state.cpp index c678a851..461f233b 100644 --- a/lib/data_state.cpp +++ b/lib/data_state.cpp @@ -10,7 +10,6 @@ // CONTRIBUTING.md for details. #include "data_state.hpp" -#include "visual.hpp" #include @@ -523,8 +522,7 @@ void DataState::SetQuadSolution(QuadSolution quad_type) quad_sol = quad_type; } -void DataState::SwitchQuadSolution(QuadSolution quad_type, - VisualizationScene *vs) +void DataState::SwitchQuadSolution(QuadSolution quad_type) { unique_ptr old_mesh; // we must backup the refined mesh to prevent its deleting @@ -535,7 +533,6 @@ void DataState::SwitchQuadSolution(QuadSolution quad_type, } SetQuadSolution(quad_type); ExtrudeMeshAndSolution(); - ResetMeshAndSolution(*this, vs); } // Replace a given VectorFiniteElement-based grid function (e.g. from a Nedelec @@ -564,67 +561,6 @@ DataState::ProjectVectorFEGridFunction(std::unique_ptr gf) return gf; } -bool DataState::SetNewMeshAndSolution(DataState new_state, - VisualizationScene* vs) -{ - if (new_state.mesh->SpaceDimension() == mesh->SpaceDimension() && - new_state.grid_f->VectorDim() == grid_f->VectorDim()) - { - ResetMeshAndSolution(new_state, vs); - - internal.grid_f = std::move(new_state.internal.grid_f); - internal.mesh = std::move(new_state.internal.mesh); - internal.quad_f = std::move(new_state.internal.quad_f); - internal.mesh_quad = std::move(new_state.internal.mesh_quad); - - return true; - } - else - { - return false; - } -} - -void DataState::ResetMeshAndSolution(DataState &ss, VisualizationScene* vs) -{ - if (ss.mesh->SpaceDimension() == 2) - { - if (ss.grid_f->VectorDim() == 1) - { - VisualizationSceneSolution *vss = - dynamic_cast(vs); - ss.grid_f->GetNodalValues(ss.sol); - vss->NewMeshAndSolution(ss.mesh.get(), ss.mesh_quad.get(), &ss.sol, - ss.grid_f.get()); - } - else - { - VisualizationSceneVector *vsv = - dynamic_cast(vs); - vsv->NewMeshAndSolution(*ss.grid_f, ss.mesh_quad.get()); - } - } - else - { - if (ss.grid_f->VectorDim() == 1) - { - VisualizationSceneSolution3d *vss = - dynamic_cast(vs); - ss.grid_f->GetNodalValues(ss.sol); - vss->NewMeshAndSolution(ss.mesh.get(), ss.mesh_quad.get(), &ss.sol, - ss.grid_f.get()); - } - else - { - ss.ProjectVectorFEGridFunction(); - - VisualizationSceneVector3d *vss = - dynamic_cast(vs); - vss->NewMeshAndSolution(ss.mesh.get(), ss.mesh_quad.get(), ss.grid_f.get()); - } - } -} - void ::VectorExtrudeCoefficient::Eval(Vector &v, ElementTransformation &T, const IntegrationPoint &ip) { diff --git a/lib/data_state.hpp b/lib/data_state.hpp index 47fdc639..3ee65235 100644 --- a/lib/data_state.hpp +++ b/lib/data_state.hpp @@ -144,8 +144,8 @@ struct DataState /// Set the quadrature function representation producing a proxy grid function void SetQuadSolution(QuadSolution type = QuadSolution::LOR_ClosedGL); - /// Switch the quadrature function representation and update the visualization - void SwitchQuadSolution(QuadSolution type, VisualizationScene* vs); + /// Switch the quadrature function representation + void SwitchQuadSolution(QuadSolution type); /// Get the current representation of quadrature solution inline QuadSolution GetQuadSolution() const { return quad_sol; } @@ -158,22 +158,6 @@ struct DataState void ProjectVectorFEGridFunction() { internal.grid_f = ProjectVectorFEGridFunction(std::move(internal.grid_f)); } - - /// Sets a new mesh and solution from another DataState object, and - /// updates the given VisualizationScene pointer with the new data. - /// - /// Mesh space and grid function dimensions must both match the original - /// dimensions of the current DataState. If there is a mismatch in either - /// value, the function will return false, and the mesh/solution will not be - /// updated. - bool SetNewMeshAndSolution(DataState new_state, - VisualizationScene* vs); - - /// Updates the given VisualizationScene pointer with the new data - /// of the given DataState object. - /// @note: Use with caution when the update is compatible - /// @see SetNewMeshAndSolution() - static void ResetMeshAndSolution(DataState &ss, VisualizationScene* vs); }; #endif // GLVIS_DATA_STATE_HPP diff --git a/lib/script_controller.cpp b/lib/script_controller.cpp index a56039c1..3575280f 100644 --- a/lib/script_controller.cpp +++ b/lib/script_controller.cpp @@ -359,7 +359,7 @@ void ScriptController::ExecuteScriptCommand() } } - if (win.data_state.SetNewMeshAndSolution(std::move(new_state), win.vs)) + if (win.SetNewMeshAndSolution(std::move(new_state))) { MyExpose(); } diff --git a/lib/threads.cpp b/lib/threads.cpp index 08107e3a..47ef5f8d 100644 --- a/lib/threads.cpp +++ b/lib/threads.cpp @@ -473,7 +473,7 @@ int GLVisCommand::Execute() new_state.ExtrudeMeshAndSolution(); } } - if (win.data_state.SetNewMeshAndSolution(std::move(new_state), win.vs)) + if (win.SetNewMeshAndSolution(std::move(new_state))) { if (mesh_range > 0.0) { diff --git a/lib/window.cpp b/lib/window.cpp index e5cc9d83..7f319be7 100644 --- a/lib/window.cpp +++ b/lib/window.cpp @@ -166,12 +166,76 @@ void Window::GLVisStartVis() cout << "GLVis window closed." << endl; } +void Window::SwitchQuadSolution(DataState::QuadSolution quad_type) +{ + data_state.SwitchQuadSolution(quad_type); + ResetMeshAndSolution(data_state); +} + +bool Window::SetNewMeshAndSolution(DataState new_state) +{ + if (new_state.mesh->SpaceDimension() == data_state.mesh->SpaceDimension() && + new_state.grid_f->VectorDim() == data_state.grid_f->VectorDim()) + { + ResetMeshAndSolution(new_state); + + data_state = std::move(new_state); + + return true; + } + else + { + return false; + } +} + +void Window::ResetMeshAndSolution(DataState &ss) +{ + if (ss.mesh->SpaceDimension() == 2) + { + if (ss.grid_f->VectorDim() == 1) + { + VisualizationSceneSolution *vss = + dynamic_cast(vs); + ss.grid_f->GetNodalValues(ss.sol); + vss->NewMeshAndSolution(ss.mesh.get(), ss.mesh_quad.get(), &ss.sol, + ss.grid_f.get()); + } + else + { + VisualizationSceneVector *vsv = + dynamic_cast(vs); + vsv->NewMeshAndSolution(*ss.grid_f, ss.mesh_quad.get()); + } + } + else + { + if (ss.grid_f->VectorDim() == 1) + { + VisualizationSceneSolution3d *vss = + dynamic_cast(vs); + ss.grid_f->GetNodalValues(ss.sol); + vss->NewMeshAndSolution(ss.mesh.get(), ss.mesh_quad.get(), &ss.sol, + ss.grid_f.get()); + } + else + { + ss.ProjectVectorFEGridFunction(); + + VisualizationSceneVector3d *vss = + dynamic_cast(vs); + vss->NewMeshAndSolution(ss.mesh.get(), ss.mesh_quad.get(), ss.grid_f.get()); + } + } +} + + thread_local Window *Window::locwin = NULL; void Window::SwitchQuadSolution() { int iqs = ((int)locwin->data_state.GetQuadSolution()+1) % ((int)DataState::QuadSolution::MAX); - locwin->data_state.SwitchQuadSolution((DataState::QuadSolution)iqs, locwin->vs); + locwin->SwitchQuadSolution((DataState::QuadSolution)iqs); SendExposeEvent(); } diff --git a/lib/window.hpp b/lib/window.hpp index 0ec15a88..befde0de 100644 --- a/lib/window.hpp +++ b/lib/window.hpp @@ -41,6 +41,23 @@ struct Window bool GLVisInitVis(StreamCollection input_streams); void GLVisStartVis(); + /// Switch the quadrature function representation and update the visualization + void SwitchQuadSolution(DataState::QuadSolution type); + + /// Sets a new mesh and solution from another DataState object, and + /// updates the VisualizationScene with the new data. + /// + /// Mesh space and grid function dimensions must both match the original + /// dimensions of the current DataState. If there is a mismatch in either + /// value, the function will return false, and the mesh/solution will not be + /// updated. + bool SetNewMeshAndSolution(DataState new_state); + + /// Updates the VisualizationScene with the new data of the given DataState object. + /// @note: Use with caution when the update is compatible + /// @see SetNewMeshAndSolution() + void ResetMeshAndSolution(DataState &ss); + private: /// Thread-local singleton for key handlers static thread_local Window *locwin; From 473d146316f5232d35199880c48e972addcb21da Mon Sep 17 00:00:00 2001 From: Jan Nikl Date: Mon, 5 May 2025 11:03:29 -0700 Subject: [PATCH 08/56] Updated aux_js.cpp. --- lib/aux_js.cpp | 131 ++++++++++++++++++------------------------------- 1 file changed, 48 insertions(+), 83 deletions(-) diff --git a/lib/aux_js.cpp b/lib/aux_js.cpp index 7fad3f3b..cad5eacf 100644 --- a/lib/aux_js.cpp +++ b/lib/aux_js.cpp @@ -24,16 +24,12 @@ #include // used in extern context -thread_local std::string plot_caption; -thread_local std::string extra_caption; thread_local mfem::GeometryRefiner GLVisGeometryRefiner; -static VisualizationSceneScalarData * vs = nullptr; - // either bitmap data or png bytes std::vector * screen_state = nullptr; -DataState stream_state; +static Window win; int last_stream_nproc = 1; @@ -60,7 +56,7 @@ void display(std::stringstream & commands, const int w, const int h) if (word == "keys") { std::cout << "parsing 'keys'" << std::endl; - commands >> stream_state.keys; + commands >> win.data_state.keys; } else if (word == "valuerange") { @@ -73,7 +69,7 @@ void display(std::stringstream & commands, const int w, const int h) } } - DataState::FieldType field_type = stream_state.GetType(); + DataState::FieldType field_type = win.data_state.GetType(); if (field_type <= DataState::FieldType::MIN || field_type >= DataState::FieldType::MAX) @@ -86,10 +82,10 @@ void display(std::stringstream & commands, const int w, const int h) return; } - delete vs; - vs = nullptr; + delete win.vs; + win.vs = nullptr; - if (stream_state.quad_f) + if (win.data_state.quad_f) { GetAppWindow()->setOnKeyDown('Q', SwitchQuadSolution); } @@ -98,58 +94,41 @@ void display(std::stringstream & commands, const int w, const int h) if (field_type == DataState::FieldType::SCALAR || field_type == DataState::FieldType::MESH) { - if (stream_state.grid_f) + if (win.data_state.grid_f) { - stream_state.grid_f->GetNodalValues(stream_state.sol); + win.data_state.grid_f->GetNodalValues(win.data_state.sol); } - if (stream_state.mesh->SpaceDimension() == 2) + if (win.data_state.mesh->SpaceDimension() == 2) { - VisualizationSceneSolution * vss; - if (stream_state.normals.Size() > 0) - { - vs = vss = new VisualizationSceneSolution(*stream_state.mesh, stream_state.sol, - stream_state.mesh_quad.get(), &stream_state.normals); - } - else - { - vs = vss = new VisualizationSceneSolution(*stream_state.mesh, stream_state.sol, - stream_state.mesh_quad.get()); - } - if (stream_state.grid_f) - { - vss->SetGridFunction(*stream_state.grid_f); - } + win.vs = new VisualizationSceneSolution(win); + if (field_type == DataState::FieldType::MESH) { - vs->OrthogonalProjection = 1; - vs->SetLight(0); - vs->Zoom(1.8); + win.vs->OrthogonalProjection = 1; + win.vs->SetLight(0); + win.vs->Zoom(1.8); // Use the 'bone' palette when visualizing a 2D mesh only (otherwise // the 'jet-like' palette is used in 2D, see vssolution.cpp). - vs->palette.SetIndex(4); + win.vs->palette.SetIndex(4); } } - else if (stream_state.mesh->SpaceDimension() == 3) + else if (win.data_state.mesh->SpaceDimension() == 3) { VisualizationSceneSolution3d * vss; - vs = vss = new VisualizationSceneSolution3d(*stream_state.mesh, - stream_state.sol, stream_state.mesh_quad.get()); - if (stream_state.grid_f) - { - vss->SetGridFunction(stream_state.grid_f.get()); - } + win.vs = vss = new VisualizationSceneSolution3d(win); + if (field_type == DataState::FieldType::MESH) { - if (stream_state.mesh->Dimension() == 3) + if (win.data_state.mesh->Dimension() == 3) { // Use the 'white' palette when visualizing a 3D volume mesh only - vs->palette.SetIndex(11); + win.vs->palette.SetIndex(11); vss->SetLightMatIdx(4); } else { // Use the 'bone' palette when visualizing a surface mesh only - vs->palette.SetIndex(4); + win.vs->palette.SetIndex(4); } // Otherwise, the 'vivid' palette is used in 3D see vssolution3d.cpp @@ -159,76 +138,62 @@ void display(std::stringstream & commands, const int w, const int h) } if (field_type == DataState::FieldType::MESH) { - if (stream_state.grid_f) + if (win.data_state.grid_f) { - mesh_range = stream_state.grid_f->Max() + 1.0; + mesh_range = win.data_state.grid_f->Max() + 1.0; } else { - mesh_range = stream_state.sol.Max() + 1.0; + mesh_range = win.data_state.sol.Max() + 1.0; } } } else if (field_type == DataState::FieldType::VECTOR) { - if (stream_state.mesh->SpaceDimension() == 2) + if (win.data_state.mesh->SpaceDimension() == 2) { - if (stream_state.grid_f) - { - vs = new VisualizationSceneVector(*stream_state.grid_f); - } - else - { - vs = new VisualizationSceneVector(*stream_state.mesh, stream_state.solu, - stream_state.solv, stream_state.mesh_quad.get()); - } + win.vs = new VisualizationSceneVector(win); } - else if (stream_state.mesh->SpaceDimension() == 3) + else if (win.data_state.mesh->SpaceDimension() == 3) { - if (stream_state.grid_f) + if (win.data_state.grid_f) { - stream_state.ProjectVectorFEGridFunction(); - vs = new VisualizationSceneVector3d(*stream_state.grid_f, - stream_state.mesh_quad.get()); - } - else - { - vs = new VisualizationSceneVector3d(*stream_state.mesh, stream_state.solu, - stream_state.solv, stream_state.solw, - stream_state.mesh_quad.get()); + win.data_state.ProjectVectorFEGridFunction(); } + + win.vs = new VisualizationSceneVector3d(win); } } - if (vs) + if (win.vs) { // increase the refinement factors if visualizing a GridFunction - if (stream_state.grid_f) + if (win.data_state.grid_f) { - vs->AutoRefine(); - vs->SetShading(VisualizationSceneScalarData::Shading::Noncomforming, true); + win.vs->AutoRefine(); + win.vs->SetShading(VisualizationSceneScalarData::Shading::Noncomforming, true); } if (mesh_range > 0.0) { - vs->SetValueRange(-mesh_range, mesh_range); - vs->SetAutoscale(0); + win.vs->SetValueRange(-mesh_range, mesh_range); + win.vs->SetAutoscale(0); } - if (stream_state.mesh->SpaceDimension() == 2 && + if (win.data_state.mesh->SpaceDimension() == 2 && field_type == DataState::FieldType::MESH) { - SetVisualizationScene(vs, 2); + SetVisualizationScene(win.vs, 2); } else { - SetVisualizationScene(vs, 3); + SetVisualizationScene(win.vs, 3); } } - CallKeySequence(stream_state.keys.c_str()); + CallKeySequence(win.data_state.keys.c_str()); if (minv || maxv) { - vs->SetValueRange(minv, maxv); + win.vs->SetValueRange(minv, maxv); } SendExposeEvent(); @@ -282,7 +247,7 @@ void displayParallelStreams(const StringArray & streams, const int w, const int h) { std::stringstream commands(streams[0]); - processParallelStreams(stream_state, streams, &commands); + processParallelStreams(win.data_state, streams, &commands); display(commands, w, h); } @@ -293,7 +258,7 @@ void displayStream(const std::string & stream, const int w, const int h) std::string data_type; ss >> data_type; - StreamReader reader(stream_state); + StreamReader reader(win.data_state); reader.ReadStream(ss, data_type); display(ss, w, h); @@ -306,11 +271,11 @@ int update(DataState & new_state) { double mesh_range = -1.0; - if (stream_state.SetNewMeshAndSolution(std::move(new_state), vs)) + if (win.SetNewMeshAndSolution(std::move(new_state))) { if (mesh_range > 0.0) { - vs->SetValueRange(-mesh_range, mesh_range); + win.vs->SetValueRange(-mesh_range, mesh_range); } SendExposeEvent(); @@ -465,9 +430,9 @@ em::val getScreenBuffer(bool flip_y=false) void SwitchQuadSolution() { - int iqs = ((int)stream_state.GetQuadSolution()+1) + int iqs = ((int)win.data_state.GetQuadSolution()+1) % ((int)DataState::QuadSolution::MAX); - stream_state.SwitchQuadSolution((DataState::QuadSolution)iqs, vs); + win.SwitchQuadSolution((DataState::QuadSolution)iqs); SendExposeEvent(); } From f2286e38cefdd149fda77444a4eba04e7b062896 Mon Sep 17 00:00:00 2001 From: Jan Nikl Date: Mon, 5 May 2025 11:18:08 -0700 Subject: [PATCH 09/56] Unified GLVisInitVis() and aux_js. --- lib/aux_js.cpp | 135 +++---------------------------------------------- 1 file changed, 6 insertions(+), 129 deletions(-) diff --git a/lib/aux_js.cpp b/lib/aux_js.cpp index cad5eacf..e3a14f56 100644 --- a/lib/aux_js.cpp +++ b/lib/aux_js.cpp @@ -40,9 +40,6 @@ namespace js using namespace mfem; -/// Switch representation of the quadrature function -void SwitchQuadSolution(); - /// Display a new stream void display(std::stringstream & commands, const int w, const int h) { @@ -69,125 +66,13 @@ void display(std::stringstream & commands, const int w, const int h) } } - DataState::FieldType field_type = win.data_state.GetType(); - - if (field_type <= DataState::FieldType::MIN - || field_type >= DataState::FieldType::MAX) - { - return; - } - - if (InitVisualization("glvis", 0, 0, w, h)) - { - return; - } - - delete win.vs; - win.vs = nullptr; - - if (win.data_state.quad_f) - { - GetAppWindow()->setOnKeyDown('Q', SwitchQuadSolution); - } - - double mesh_range = -1.0; - if (field_type == DataState::FieldType::SCALAR - || field_type == DataState::FieldType::MESH) - { - if (win.data_state.grid_f) - { - win.data_state.grid_f->GetNodalValues(win.data_state.sol); - } - if (win.data_state.mesh->SpaceDimension() == 2) - { - win.vs = new VisualizationSceneSolution(win); + win.window_title = "glvis"; + win.window_x = 0.; + win.window_y = 0.; + win.window_w = w; + win.window_h = h; - if (field_type == DataState::FieldType::MESH) - { - win.vs->OrthogonalProjection = 1; - win.vs->SetLight(0); - win.vs->Zoom(1.8); - // Use the 'bone' palette when visualizing a 2D mesh only (otherwise - // the 'jet-like' palette is used in 2D, see vssolution.cpp). - win.vs->palette.SetIndex(4); - } - } - else if (win.data_state.mesh->SpaceDimension() == 3) - { - VisualizationSceneSolution3d * vss; - win.vs = vss = new VisualizationSceneSolution3d(win); - - if (field_type == DataState::FieldType::MESH) - { - if (win.data_state.mesh->Dimension() == 3) - { - // Use the 'white' palette when visualizing a 3D volume mesh only - win.vs->palette.SetIndex(11); - vss->SetLightMatIdx(4); - } - else - { - // Use the 'bone' palette when visualizing a surface mesh only - win.vs->palette.SetIndex(4); - } - // Otherwise, the 'vivid' palette is used in 3D see vssolution3d.cpp - - vss->ToggleDrawAxes(); - vss->ToggleDrawMesh(); - } - } - if (field_type == DataState::FieldType::MESH) - { - if (win.data_state.grid_f) - { - mesh_range = win.data_state.grid_f->Max() + 1.0; - } - else - { - mesh_range = win.data_state.sol.Max() + 1.0; - } - } - } - else if (field_type == DataState::FieldType::VECTOR) - { - if (win.data_state.mesh->SpaceDimension() == 2) - { - win.vs = new VisualizationSceneVector(win); - } - else if (win.data_state.mesh->SpaceDimension() == 3) - { - if (win.data_state.grid_f) - { - win.data_state.ProjectVectorFEGridFunction(); - } - - win.vs = new VisualizationSceneVector3d(win); - } - } - - if (win.vs) - { - // increase the refinement factors if visualizing a GridFunction - if (win.data_state.grid_f) - { - win.vs->AutoRefine(); - win.vs->SetShading(VisualizationSceneScalarData::Shading::Noncomforming, true); - } - if (mesh_range > 0.0) - { - win.vs->SetValueRange(-mesh_range, mesh_range); - win.vs->SetAutoscale(0); - } - if (win.data_state.mesh->SpaceDimension() == 2 && - field_type == DataState::FieldType::MESH) - { - SetVisualizationScene(win.vs, 2); - } - else - { - SetVisualizationScene(win.vs, 3); - } - } + win.GLVisInitVis({}); CallKeySequence(win.data_state.keys.c_str()); @@ -428,14 +313,6 @@ em::val getScreenBuffer(bool flip_y=false) screen_state->data())); } -void SwitchQuadSolution() -{ - int iqs = ((int)win.data_state.GetQuadSolution()+1) - % ((int)DataState::QuadSolution::MAX); - win.SwitchQuadSolution((DataState::QuadSolution)iqs); - SendExposeEvent(); -} - #ifdef GLVIS_USE_LIBPNG em::val getPNGByteArray() { From 503039b4dcdaabd20387c84a4deb7d99f4ecd58e Mon Sep 17 00:00:00 2001 From: Jan Nikl Date: Mon, 5 May 2025 11:52:27 -0700 Subject: [PATCH 10/56] Changed plain pointers to std unique in Window. --- lib/vsdata.cpp | 1 + lib/window.cpp | 45 ++++++++++++++++++++++++++++++++------------- lib/window.hpp | 16 ++++++++++++++-- 3 files changed, 47 insertions(+), 15 deletions(-) diff --git a/lib/vsdata.cpp b/lib/vsdata.cpp index fdd1ffc0..a14c52ab 100644 --- a/lib/vsdata.cpp +++ b/lib/vsdata.cpp @@ -23,6 +23,7 @@ using namespace std; #include "aux_vis.hpp" #include "material.hpp" #include "palettes.hpp" +#include "threads.hpp" #include "gl2ps.h" diff --git a/lib/window.cpp b/lib/window.cpp index 7f319be7..989d428a 100644 --- a/lib/window.cpp +++ b/lib/window.cpp @@ -14,6 +14,23 @@ extern thread_local GLVisCommand* glvis_command; +Window &Window::operator=(Window &&w) +{ + internal = std::move(w.internal); + + data_state = std::move(w.data_state); + + window_x = w.window_x; + window_y = w.window_y; + window_w = w.window_w; + window_h = w.window_h; + window_title = w.window_title; + plot_caption = std::move(w.plot_caption); + extra_caption = std::move(w.extra_caption); + + return *this; +} + // Visualize the data in the global variables mesh, sol/grid_f, etc bool Window::GLVisInitVis(StreamCollection input_streams) { @@ -43,7 +60,8 @@ bool Window::GLVisInitVis(StreamCollection input_streams) { GetAppWindow()->setOnKeyDown(SDLK_SPACE, ThreadsPauseFunc); glvis_command = new GLVisCommand(*this); - comm_thread = new communication_thread(std::move(input_streams), glvis_command); + internal.comm_thread.reset(new communication_thread(std::move(input_streams), + glvis_command)); } locwin = this; @@ -63,7 +81,7 @@ bool Window::GLVisInitVis(StreamCollection input_streams) } if (data_state.mesh->SpaceDimension() == 2) { - vs = new VisualizationSceneSolution(*this); + internal.vs.reset(new VisualizationSceneSolution(*this)); if (field_type == DataState::FieldType::MESH) { @@ -78,7 +96,8 @@ bool Window::GLVisInitVis(StreamCollection input_streams) else if (data_state.mesh->SpaceDimension() == 3) { VisualizationSceneSolution3d *vss; - vs = vss = new VisualizationSceneSolution3d(*this); + vss = new VisualizationSceneSolution3d(*this); + internal.vs.reset(vss); if (field_type == DataState::FieldType::MESH) { @@ -114,7 +133,7 @@ bool Window::GLVisInitVis(StreamCollection input_streams) { if (data_state.mesh->SpaceDimension() == 2) { - vs = new VisualizationSceneVector(*this); + internal.vs.reset(new VisualizationSceneVector(*this)); } else if (data_state.mesh->SpaceDimension() == 3) { @@ -122,7 +141,7 @@ bool Window::GLVisInitVis(StreamCollection input_streams) { data_state.ProjectVectorFEGridFunction(); } - vs = new VisualizationSceneVector3d(*this); + internal.vs.reset(new VisualizationSceneVector3d(*this)); } } @@ -142,11 +161,11 @@ bool Window::GLVisInitVis(StreamCollection input_streams) if (data_state.mesh->SpaceDimension() == 2 && field_type == DataState::FieldType::MESH) { - SetVisualizationScene(vs, 2, data_state.keys.c_str()); + SetVisualizationScene(vs.get(), 2, data_state.keys.c_str()); } else { - SetVisualizationScene(vs, 3, data_state.keys.c_str()); + SetVisualizationScene(vs.get(), 3, data_state.keys.c_str()); } } return true; @@ -155,11 +174,11 @@ bool Window::GLVisInitVis(StreamCollection input_streams) void Window::GLVisStartVis() { RunVisualization(); // deletes vs - vs = NULL; + internal.vs.reset(); if (glvis_command) { glvis_command->Terminate(); - delete comm_thread; + internal.comm_thread.reset(); delete glvis_command; glvis_command = NULL; } @@ -196,7 +215,7 @@ void Window::ResetMeshAndSolution(DataState &ss) if (ss.grid_f->VectorDim() == 1) { VisualizationSceneSolution *vss = - dynamic_cast(vs); + dynamic_cast(internal.vs.get()); ss.grid_f->GetNodalValues(ss.sol); vss->NewMeshAndSolution(ss.mesh.get(), ss.mesh_quad.get(), &ss.sol, ss.grid_f.get()); @@ -204,7 +223,7 @@ void Window::ResetMeshAndSolution(DataState &ss) else { VisualizationSceneVector *vsv = - dynamic_cast(vs); + dynamic_cast(internal.vs.get()); vsv->NewMeshAndSolution(*ss.grid_f, ss.mesh_quad.get()); } } @@ -213,7 +232,7 @@ void Window::ResetMeshAndSolution(DataState &ss) if (ss.grid_f->VectorDim() == 1) { VisualizationSceneSolution3d *vss = - dynamic_cast(vs); + dynamic_cast(internal.vs.get()); ss.grid_f->GetNodalValues(ss.sol); vss->NewMeshAndSolution(ss.mesh.get(), ss.mesh_quad.get(), &ss.sol, ss.grid_f.get()); @@ -223,7 +242,7 @@ void Window::ResetMeshAndSolution(DataState &ss) ss.ProjectVectorFEGridFunction(); VisualizationSceneVector3d *vss = - dynamic_cast(vs); + dynamic_cast(internal.vs.get()); vss->NewMeshAndSolution(ss.mesh.get(), ss.mesh_quad.get(), ss.grid_f.get()); } } diff --git a/lib/window.hpp b/lib/window.hpp index befde0de..b4f18b47 100644 --- a/lib/window.hpp +++ b/lib/window.hpp @@ -25,9 +25,17 @@ extern const char *string_default; struct Window { +private: + struct + { + std::unique_ptr vs; + std::unique_ptr comm_thread; + } internal; + +public: DataState data_state; - VisualizationSceneScalarData *vs = NULL; - communication_thread *comm_thread = NULL; + const std::unique_ptr &vs{internal.vs}; + const std::unique_ptr &comm_thread{internal.comm_thread}; int window_x = 0; // not a command line option int window_y = 0; // not a command line option @@ -37,6 +45,10 @@ struct Window std::string plot_caption; std::string extra_caption; + Window() = default; + Window(Window &&w) { *this = std::move(w); } + Window& operator=(Window &&w); + /// Visualize the data in the global variables mesh, sol/grid_f, etc bool GLVisInitVis(StreamCollection input_streams); void GLVisStartVis(); From c9df9fb7dea546de3c2933e4bcc477ad1892ffe3 Mon Sep 17 00:00:00 2001 From: Jan Nikl Date: Mon, 5 May 2025 12:25:36 -0700 Subject: [PATCH 11/56] Included GLVisCommand in Window and made static a few other variables in aux_vis.cpp. --- lib/aux_vis.cpp | 20 +++++++++++++------- lib/aux_vis.hpp | 3 +++ lib/window.cpp | 10 ++++------ lib/window.hpp | 3 +++ 4 files changed, 23 insertions(+), 13 deletions(-) diff --git a/lib/aux_vis.cpp b/lib/aux_vis.cpp index d7e4b282..54e16025 100644 --- a/lib/aux_vis.cpp +++ b/lib/aux_vis.cpp @@ -35,9 +35,9 @@ using namespace mfem; -thread_local int visualize = 0; +static thread_local int visualize = 0; thread_local VisualizationScene * locscene; -thread_local GLVisCommand *glvis_command = NULL; +static thread_local GLVisCommand *glvis_command = NULL; #ifdef GLVIS_MULTISAMPLE static int glvis_multisample = GLVIS_MULTISAMPLE; @@ -45,17 +45,23 @@ static int glvis_multisample = GLVIS_MULTISAMPLE; static int glvis_multisample = -1; #endif -float line_w = 1.f; -float line_w_aa = gl3::LINE_WIDTH_AA; +static float line_w = 1.f; +static float line_w_aa = gl3::LINE_WIDTH_AA; + +static thread_local SdlWindow * wnd = nullptr; +static bool wndLegacyGl = false; +bool wndUseHiDPI = true; // shared with sdl_main.cpp -thread_local SdlWindow * wnd = nullptr; -bool wndLegacyGl = false; -bool wndUseHiDPI = true; void SDLMainLoop(bool server_mode) { SdlWindow::StartSDL(server_mode); } +void SetGLVisCommand(GLVisCommand *cmd) +{ + glvis_command = cmd; +} + SdlWindow * GetAppWindow() { return wnd; diff --git a/lib/aux_vis.hpp b/lib/aux_vis.hpp index 9929639b..4f412247 100644 --- a/lib/aux_vis.hpp +++ b/lib/aux_vis.hpp @@ -23,6 +23,9 @@ void SDLMainLoop(bool server_mode = false); +class GLVisCommand; +void SetGLVisCommand(GLVisCommand *cmd); + /// Initializes the visualization and some keys. int InitVisualization(const char name[], int x, int y, int w, int h); diff --git a/lib/window.cpp b/lib/window.cpp index 989d428a..96b9e7a8 100644 --- a/lib/window.cpp +++ b/lib/window.cpp @@ -12,8 +12,6 @@ #include "window.hpp" #include "visual.hpp" -extern thread_local GLVisCommand* glvis_command; - Window &Window::operator=(Window &&w) { internal = std::move(w.internal); @@ -59,9 +57,10 @@ bool Window::GLVisInitVis(StreamCollection input_streams) if (input_streams.size() > 0) { GetAppWindow()->setOnKeyDown(SDLK_SPACE, ThreadsPauseFunc); - glvis_command = new GLVisCommand(*this); + internal.glvis_command.reset(new GLVisCommand(*this)); + SetGLVisCommand(glvis_command.get()); internal.comm_thread.reset(new communication_thread(std::move(input_streams), - glvis_command)); + glvis_command.get())); } locwin = this; @@ -179,8 +178,7 @@ void Window::GLVisStartVis() { glvis_command->Terminate(); internal.comm_thread.reset(); - delete glvis_command; - glvis_command = NULL; + internal.glvis_command.reset(); } cout << "GLVis window closed." << endl; } diff --git a/lib/window.hpp b/lib/window.hpp index b4f18b47..b9f794cd 100644 --- a/lib/window.hpp +++ b/lib/window.hpp @@ -19,6 +19,7 @@ class VisualizationSceneScalarData; class communication_thread; +class GLVisCommand; extern const char *string_none; extern const char *string_default; @@ -30,12 +31,14 @@ struct Window { std::unique_ptr vs; std::unique_ptr comm_thread; + std::unique_ptr glvis_command; } internal; public: DataState data_state; const std::unique_ptr &vs{internal.vs}; const std::unique_ptr &comm_thread{internal.comm_thread}; + const std::unique_ptr &glvis_command{internal.glvis_command}; int window_x = 0; // not a command line option int window_y = 0; // not a command line option From e2e01bbb3e3c4f3cc80aee3e9c6b79977aa2c096 Mon Sep 17 00:00:00 2001 From: Jan Nikl Date: Mon, 5 May 2025 12:37:27 -0700 Subject: [PATCH 12/56] Made locscene local. --- lib/aux_vis.cpp | 2 +- lib/vsdata.cpp | 51 +++++++++++++++++++++++----------------------- lib/vssolution.cpp | 1 - lib/vsvector.cpp | 1 - lib/vsvector3d.cpp | 16 ++++++++------- 5 files changed, 35 insertions(+), 36 deletions(-) diff --git a/lib/aux_vis.cpp b/lib/aux_vis.cpp index 54e16025..16efccb7 100644 --- a/lib/aux_vis.cpp +++ b/lib/aux_vis.cpp @@ -36,7 +36,7 @@ using namespace mfem; static thread_local int visualize = 0; -thread_local VisualizationScene * locscene; +static thread_local VisualizationScene *locscene = NULL; static thread_local GLVisCommand *glvis_command = NULL; #ifdef GLVIS_MULTISAMPLE diff --git a/lib/vsdata.cpp b/lib/vsdata.cpp index a14c52ab..d80e6fab 100644 --- a/lib/vsdata.cpp +++ b/lib/vsdata.cpp @@ -612,9 +612,8 @@ void VisualizationSceneScalarData::PrepareCaption() GetFont()->getObjectSize(caption, caption_w, caption_h); } -static thread_local VisualizationSceneScalarData * vsdata; +static thread_local VisualizationSceneScalarData *vsdata; static thread_local Window *window; -extern thread_local VisualizationScene * locscene; void KeycPressed(GLenum state) { @@ -717,22 +716,22 @@ void KeyLPressed() void KeyrPressed() { - locscene -> spinning = 0; + window->vs -> spinning = 0; RemoveIdleFunc(MainLoop); vsdata -> CenterObject(); - locscene -> ViewAngle = 45.0; - locscene -> ViewScale = 1.0; - locscene -> ViewCenterX = 0.0; - locscene -> ViewCenterY = 0.0; - locscene->cam.Reset(); + window->vs -> ViewAngle = 45.0; + window->vs -> ViewScale = 1.0; + window->vs -> ViewCenterX = 0.0; + window->vs -> ViewCenterY = 0.0; + window->vs->cam.Reset(); vsdata -> key_r_state = 0; SendExposeEvent(); } void KeyRPressed() { - locscene->spinning = 0; + window->vs->spinning = 0; RemoveIdleFunc(MainLoop); vsdata->Toggle2DView(); SendExposeEvent(); @@ -746,14 +745,14 @@ void KeypPressed(GLenum state) } else { - locscene->palette.NextIndex(); + window->vs->palette.NextIndex(); SendExposeEvent(); } } void KeyPPressed() { - locscene->palette.PrevIndex(); + window->vs->palette.PrevIndex(); SendExposeEvent(); } @@ -912,23 +911,23 @@ void KeyF2Pressed() void KeykPressed() { - locscene->matAlpha -= 0.05; - if (locscene->matAlpha < 0.0) + window->vs->matAlpha -= 0.05; + if (window->vs->matAlpha < 0.0) { - locscene->matAlpha = 0.0; + window->vs->matAlpha = 0.0; } - locscene->GenerateAlphaTexture(); + window->vs->GenerateAlphaTexture(); SendExposeEvent(); } void KeyKPressed() { - locscene->matAlpha += 0.05; - if (locscene->matAlpha > 1.0) + window->vs->matAlpha += 0.05; + if (window->vs->matAlpha > 1.0) { - locscene->matAlpha = 1.0; + window->vs->matAlpha = 1.0; } - locscene->GenerateAlphaTexture(); + window->vs->GenerateAlphaTexture(); SendExposeEvent(); } @@ -946,23 +945,23 @@ void KeyAPressed() void KeyCommaPressed() { - locscene->matAlphaCenter -= 0.25; + window->vs->matAlphaCenter -= 0.25; // vsdata -> EventUpdateColors(); - locscene->GenerateAlphaTexture(); + window->vs->GenerateAlphaTexture(); SendExposeEvent(); #ifdef GLVIS_DEBUG - cout << "MatAlphaCenter = " << locscene->matAlphaCenter << endl; + cout << "MatAlphaCenter = " << window->vs->matAlphaCenter << endl; #endif } void KeyLessPressed() { - locscene->matAlphaCenter += 0.25; + window->vs->matAlphaCenter += 0.25; // vsdata -> EventUpdateColors(); - locscene->GenerateAlphaTexture(); + window->vs->GenerateAlphaTexture(); SendExposeEvent(); #ifdef GLVIS_DEBUG - cout << "MatAlphaCenter = " << locscene->matAlphaCenter << endl; + cout << "MatAlphaCenter = " << window->vs->matAlphaCenter << endl; #endif } @@ -1162,7 +1161,7 @@ void VisualizationSceneScalarData::Toggle2DView() break; } - // if (locscene -> view != 2) // make 'R' work the same in 2D and 3D + // if (window->vs -> view != 2) // make 'R' work the same in 2D and 3D key_r_state = (key_r_state+1)%6; rotmat = newrot.mtx; diff --git a/lib/vssolution.cpp b/lib/vssolution.cpp index 7ec44f61..44638f00 100644 --- a/lib/vssolution.cpp +++ b/lib/vssolution.cpp @@ -26,7 +26,6 @@ using namespace std; thread_local VisualizationSceneSolution *vssol; -extern thread_local VisualizationScene *locscene; extern thread_local GeometryRefiner GLVisGeometryRefiner; #ifdef GLVIS_ISFINITE diff --git a/lib/vsvector.cpp b/lib/vsvector.cpp index 16283540..62345069 100644 --- a/lib/vsvector.cpp +++ b/lib/vsvector.cpp @@ -103,7 +103,6 @@ std::string VisualizationSceneVector::GetHelpString() const } thread_local VisualizationSceneVector * vsvector; -extern thread_local VisualizationScene * locscene; extern thread_local VisualizationSceneSolution * vssol; extern thread_local GeometryRefiner GLVisGeometryRefiner; diff --git a/lib/vsvector3d.cpp b/lib/vsvector3d.cpp index 0df11e77..ea725a3c 100644 --- a/lib/vsvector3d.cpp +++ b/lib/vsvector3d.cpp @@ -115,7 +115,7 @@ std::string VisualizationSceneVector3d::GetHelpString() const } thread_local VisualizationSceneVector3d *vsvector3d; -extern thread_local VisualizationScene *locscene; +static thread_local Window *window; extern thread_local GeometryRefiner GLVisGeometryRefiner; static void KeyDPressed() @@ -150,13 +150,13 @@ static void KeyBPressed() static void KeyrPressed() { - locscene -> spinning = 0; + window->vs -> spinning = 0; RemoveIdleFunc(MainLoop); vsvector3d -> CenterObject(); - locscene -> ViewAngle = 45.0; - locscene -> ViewScale = 1.0; - locscene -> ViewCenterX = 0.0; - locscene -> ViewCenterY = 0.0; + window->vs -> ViewAngle = 45.0; + window->vs -> ViewScale = 1.0; + window->vs -> ViewCenterX = 0.0; + window->vs -> ViewCenterY = 0.0; vsvector3d -> ianim = vsvector3d -> ianimd = 0; vsvector3d -> Prepare(); vsvector3d -> PrepareLines(); @@ -167,7 +167,7 @@ static void KeyrPressed() static void KeyRPressed() { - locscene->spinning = 0; + window->vs->spinning = 0; RemoveIdleFunc(MainLoop); vsvector3d -> ianim = vsvector3d -> ianimd = 0; vsvector3d -> Prepare(); @@ -380,6 +380,8 @@ VisualizationSceneVector3d::VisualizationSceneVector3d(Window &win_) void VisualizationSceneVector3d::Init() { + window = &win; + key_r_state = 0; drawdisp = 0; From 456eb3d21f4f248011991959ad5021c5e8155698 Mon Sep 17 00:00:00 2001 From: Jan Nikl Date: Mon, 5 May 2025 12:44:30 -0700 Subject: [PATCH 13/56] Made a few thread-local vis scenes local. --- lib/vssolution3d.cpp | 2 +- lib/vsvector.cpp | 3 +-- lib/vsvector3d.cpp | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/lib/vssolution3d.cpp b/lib/vssolution3d.cpp index d9e2c1c3..ada41aec 100644 --- a/lib/vssolution3d.cpp +++ b/lib/vssolution3d.cpp @@ -21,7 +21,7 @@ using namespace mfem; using namespace std; -thread_local VisualizationSceneSolution3d *vssol3d; +static thread_local VisualizationSceneSolution3d *vssol3d; extern thread_local GeometryRefiner GLVisGeometryRefiner; // Reference geometries with a cut in the middle, based on subdivision of diff --git a/lib/vsvector.cpp b/lib/vsvector.cpp index 62345069..206f47fd 100644 --- a/lib/vsvector.cpp +++ b/lib/vsvector.cpp @@ -102,8 +102,7 @@ std::string VisualizationSceneVector::GetHelpString() const return os.str(); } -thread_local VisualizationSceneVector * vsvector; -extern thread_local VisualizationSceneSolution * vssol; +static thread_local VisualizationSceneVector * vsvector; extern thread_local GeometryRefiner GLVisGeometryRefiner; thread_local int ianim = 0; diff --git a/lib/vsvector3d.cpp b/lib/vsvector3d.cpp index ea725a3c..c9f99f90 100644 --- a/lib/vsvector3d.cpp +++ b/lib/vsvector3d.cpp @@ -114,7 +114,7 @@ std::string VisualizationSceneVector3d::GetHelpString() const return os.str(); } -thread_local VisualizationSceneVector3d *vsvector3d; +static thread_local VisualizationSceneVector3d *vsvector3d; static thread_local Window *window; extern thread_local GeometryRefiner GLVisGeometryRefiner; From 4b1ff381485bb4b270994f6bbb6115b014203de8 Mon Sep 17 00:00:00 2001 From: Jan Nikl Date: Mon, 5 May 2025 15:18:10 -0700 Subject: [PATCH 14/56] Fixed setting of attributes from script commands. --- lib/script_controller.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/script_controller.cpp b/lib/script_controller.cpp index 3575280f..a3b40369 100644 --- a/lib/script_controller.cpp +++ b/lib/script_controller.cpp @@ -98,6 +98,8 @@ int ScriptController::ScriptReadParSolution(istream &scr, DataState &state) { cout << "(processor attributes); " << flush; } + state.keep_attr = scr_keep_attr; + // read the solution prefix scr >> ws >> sol_prefix; cout << "solution prefix: " << sol_prefix << endl; @@ -129,6 +131,8 @@ int ScriptController::ScriptReadParQuadrature(istream &scr, DataState &state) { cout << "(processor attributes); " << flush; } + state.keep_attr = scr_keep_attr; + // read the quadrature prefix scr >> ws >> quad_prefix; cout << "quadrature prefix: " << quad_prefix << endl; From 44f214fb67f0aa7b834227cc0130fdb59416b1ed Mon Sep 17 00:00:00 2001 From: Jan Nikl Date: Mon, 5 May 2025 17:42:25 -0700 Subject: [PATCH 15/56] Fixed default number padding digits. --- lib/coll_reader.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/coll_reader.hpp b/lib/coll_reader.hpp index a0c6f86c..68a5eb20 100644 --- a/lib/coll_reader.hpp +++ b/lib/coll_reader.hpp @@ -19,7 +19,7 @@ class DataCollectionReader { DataState &data; - int pad_digits; + int pad_digits = 6; std::string protocol; public: From 8f743503755ba5958dd6a264db08bbe747a701ce Mon Sep 17 00:00:00 2001 From: Jan Nikl Date: Mon, 5 May 2025 17:57:26 -0700 Subject: [PATCH 16/56] Reworked script commands adding console help. --- lib/script_controller.cpp | 967 +++++++++++++++++++++----------------- lib/script_controller.hpp | 5 +- 2 files changed, 551 insertions(+), 421 deletions(-) diff --git a/lib/script_controller.cpp b/lib/script_controller.cpp index a3b40369..bf11e529 100644 --- a/lib/script_controller.cpp +++ b/lib/script_controller.cpp @@ -15,11 +15,61 @@ #include "stream_reader.hpp" #include "visual.hpp" +#include +#include + using namespace std; using namespace mfem; -extern const char *string_none; -extern const char *string_default; +enum class Command +{ + Mesh, + Solution, + ParSolution, + Quadrature, + ParQuadrature, + DataCollMesh, + DataCollField, + DataCollQuad, + DataCollCycle, + DataCollProto, + Screenshot, + Viewcenter, + Perspective, + Light, + View, + Zoom, + Shading, + Subdivisions, + Valuerange, + Autoscale, + Levellines, + AxisNumberFormat, + ColorbarNumberFormat, + Window, + Keys, + Palette, + PaletteRepeat, + ToggleAttributes, + Rotmat, + Camera, + Scale, + Translate, + PlotCaption, + //---------- + Max +}; + +struct CmdItem +{ + const char *keyword; + const char *params; + const char *desc; + + bool operator==(const string &key) const { return key == keyword; } +}; + +static vector commands; int ScriptController::ScriptReadSolution(istream &scr, DataState &state) { @@ -240,6 +290,55 @@ int ScriptController::ScriptReadDataColl(istream &scr, DataState &state, return err_read; } +void ScriptController::InitCommands() +{ + commands.resize((size_t)Command::Max); + + commands[(size_t)Command::Mesh] = {"mesh", "", "Visualize the mesh."}; + commands[(size_t)Command::Solution] = {"solution", " ", "Visualize the solution."}; + commands[(size_t)Command::ParSolution] = {"psolution", " ", "Visualize the distributed solution."}; + commands[(size_t)Command::Quadrature] = {"quadrature", " ", "Visualize the quadrature."}; + commands[(size_t)Command::ParQuadrature] = {"pquadrature", " ", "Visualize the distributed quadrature."}; + commands[(size_t)Command::DataCollMesh] = {"data_coll_mesh", " ", "Visualize the mesh from data collection."}; + commands[(size_t)Command::DataCollField] = {"data_coll_field", " ", "Visualize the field from data collection."}; + commands[(size_t)Command::DataCollQuad] = {"data_coll_quad", " ", "Visualize the Q-field from data collection."}; + commands[(size_t)Command::DataCollCycle] = {"data_coll_cycle", "", "Preset the cycle of the data collection."}; + commands[(size_t)Command::DataCollProto] = {"data_coll_protocol", "", "Preset the protocol of the data collection."}; + commands[(size_t)Command::Screenshot] = {"screenshot", "", "Take a screenshot, saving it to the file."}; + commands[(size_t)Command::Viewcenter] = {"viewcenter", " ", "Change the viewcenter."}; + commands[(size_t)Command::Perspective] = {"perspective", "", "Turn on or off perspective projection."}; + commands[(size_t)Command::Light] = {"light", "", "Turn on or off light."}; + commands[(size_t)Command::View] = {"view", " ", "Change the solid angle of view."}; + commands[(size_t)Command::Zoom] = {"zoom", "", "Change the zoom factor."}; + commands[(size_t)Command::Shading] = {"shading", "", "Change the shading algorithm."}; + commands[(size_t)Command::Subdivisions] = {"subdivisions", " ", "Change the refinement level."}; + commands[(size_t)Command::Valuerange] = {"valuerange", " ", "Change the value range."}; + commands[(size_t)Command::Autoscale] = {"autoscale", "", "Change the autoscale algorithm."}; + commands[(size_t)Command::Levellines] = {"levellines", " ", "Set the level lines."}; + commands[(size_t)Command::AxisNumberFormat] = {"axis_numberformat", "''", "Set the axis number format."}; + commands[(size_t)Command::ColorbarNumberFormat] = {"colorbar_numberformat", "''", "Set the colorbar number format."}; + commands[(size_t)Command::Window] = {"window", " ", "Set the position and size of the window."}; + commands[(size_t)Command::Keys] = {"keys", "", "Send the control key sequence."}; + commands[(size_t)Command::Palette] = {"palette", "", "Set the palette index."}; + commands[(size_t)Command::PaletteRepeat] = {"palette_repeat", "", "Set the repetition of the palette."}; + commands[(size_t)Command::ToggleAttributes] = {"toggle_attributes", "<1/0> [[<1/0>] ...];", "Toggle visibility of the attributes."}; + commands[(size_t)Command::Rotmat] = {"rotmat", "<[0,0]> <[1,0]> ... <[3,3]>", "Set the rotation matrix."}; + commands[(size_t)Command::Camera] = {"camera", " ... ... ... ", "Set the camera position, direction and upward vector."}; + commands[(size_t)Command::Scale] = {"scale", "", "Set the scaling factor."}; + commands[(size_t)Command::Translate] = {"translate", " ", "Set the translation coordinates."}; + commands[(size_t)Command::PlotCaption] = {"plot_caption", "''", "Set the plot caption."}; +} + +void ScriptController::PrintCommands() +{ + cout << "Available commands are:" << endl; + + for (const CmdItem &ci : commands) + { + cout << "\t" << ci.keyword << " " << ci.params << " - " << ci.desc << endl; + } +} + void ScriptController::ExecuteScriptCommand() { if (!script) @@ -269,6 +368,7 @@ void ScriptController::ExecuteScriptCommand() if (word == "{") { scr_level++; + continue; } else if (word == "}") { @@ -277,401 +377,435 @@ void ScriptController::ExecuteScriptCommand() { scr_level = 0; } + continue; } - else if (word == "data_coll_cycle") - { - scr >> dc_cycle; - } - else if (word == "data_coll_protocol") + + auto it = find(commands.begin(), commands.end(), word); + if (it == commands.end()) { - scr >> dc_protocol; + cout << "Unknown command in script: " << word << endl; + PrintCommands(); + break; } - else if (word == "solution" || word == "mesh" || word == "psolution" - || word == "quadrature" || word == "pquadrature" || word == "data_coll_mesh" - || word == "data_coll_field" || word == "data_coll_quad") - { - DataState new_state; - if (word == "solution") + const Command cmd = (Command)(it - commands.begin()); + switch (cmd) + { + case Command::Mesh: + case Command::Solution: + case Command::ParSolution: + case Command::Quadrature: + case Command::ParQuadrature: + case Command::DataCollField: + case Command::DataCollQuad: { - if (ScriptReadSolution(scr, new_state)) + DataState new_state; + + switch (cmd) { - done_one_command = 1; - continue; + case Command::Solution: + if (ScriptReadSolution(scr, new_state)) + { + done_one_command = 1; + continue; + } + break; + case Command::Quadrature: + if (ScriptReadQuadrature(scr, new_state)) + { + done_one_command = 1; + continue; + } + break; + case Command::Mesh: + if (ScriptReadDisplMesh(scr, new_state)) + { + done_one_command = 1; + continue; + } + if (new_state.mesh == NULL) + { + cout << "Script: unexpected 'mesh' command!" << endl; + done_one_command = 1; + continue; + } + break; + case Command::ParSolution: + if (ScriptReadParSolution(scr, new_state)) + { + done_one_command = 1; + continue; + } + break; + case Command::ParQuadrature: + if (ScriptReadParQuadrature(scr, new_state)) + { + done_one_command = 1; + continue; + } + break; + case Command::DataCollMesh: + if (ScriptReadDataColl(scr, new_state)) + { + done_one_command = 1; + continue; + } + break; + case Command::DataCollField: + if (ScriptReadDataColl(scr, new_state, false)) + { + done_one_command = 1; + continue; + } + break; + case Command::DataCollQuad: + if (ScriptReadDataColl(scr, new_state, false, true)) + { + done_one_command = 1; + continue; + } + break; + default: + break; } - } - else if (word == "quadrature") - { - if (ScriptReadQuadrature(scr, new_state)) + + if (win.SetNewMeshAndSolution(std::move(new_state))) { - done_one_command = 1; - continue; + MyExpose(); + } + else + { + cout << "Different type of mesh / solution." << endl; } } - else if (word == "mesh") + break; + case Command::DataCollCycle: + scr >> dc_cycle; + break; + case Command::DataCollProto: + scr >> dc_protocol; + break; + case Command::Screenshot: { - if (ScriptReadDisplMesh(scr, new_state)) + scr >> ws >> word; + + cout << "Script: screenshot: " << flush; + + if (Screenshot(word.c_str(), true)) { + cout << "Screenshot(" << word << ") failed." << endl; done_one_command = 1; continue; } - if (new_state.mesh == NULL) + cout << "-> " << word << endl; + + if (scr_min_val > win.vs->GetMinV()) { - cout << "Script: unexpected 'mesh' command!" << endl; - done_one_command = 1; - continue; + scr_min_val = win.vs->GetMinV(); } - } - else if (word == "psolution") - { - if (ScriptReadParSolution(scr, new_state)) + if (scr_max_val < win.vs->GetMaxV()) { - done_one_command = 1; - continue; + scr_max_val = win.vs->GetMaxV(); } } - else if (word == "pquadrature") + break; + case Command::Viewcenter: { - if (ScriptReadParQuadrature(scr, new_state)) - { - done_one_command = 1; - continue; - } + scr >> win.vs->ViewCenterX >> win.vs->ViewCenterY; + cout << "Script: viewcenter: " + << win.vs->ViewCenterX << ' ' << win.vs->ViewCenterY << endl; + MyExpose(); } - else if (word == "data_coll_mesh") + break; + case Command::Perspective: { - if (ScriptReadDataColl(scr, new_state)) + scr >> ws >> word; + cout << "Script: perspective: " << word; + if (word == "off") { - done_one_command = 1; - continue; + win.vs->OrthogonalProjection = 1; } - } - else if (word == "data_coll_field") - { - if (ScriptReadDataColl(scr, new_state, false)) + else if (word == "on") { - done_one_command = 1; - continue; + win.vs->OrthogonalProjection = 0; } - } - else if (word == "data_coll_quad") - { - if (ScriptReadDataColl(scr, new_state, false, true)) + else { - done_one_command = 1; - continue; + cout << '?'; } - } - - if (win.SetNewMeshAndSolution(std::move(new_state))) - { + cout << endl; MyExpose(); } - else - { - cout << "Different type of mesh / solution." << endl; - } - } - else if (word == "screenshot") - { - scr >> ws >> word; - - cout << "Script: screenshot: " << flush; - - if (Screenshot(word.c_str(), true)) - { - cout << "Screenshot(" << word << ") failed." << endl; - done_one_command = 1; - continue; - } - cout << "-> " << word << endl; - - if (scr_min_val > win.vs->GetMinV()) - { - scr_min_val = win.vs->GetMinV(); - } - if (scr_max_val < win.vs->GetMaxV()) - { - scr_max_val = win.vs->GetMaxV(); - } - } - else if (word == "viewcenter") - { - scr >> win.vs->ViewCenterX >> win.vs->ViewCenterY; - cout << "Script: viewcenter: " - << win.vs->ViewCenterX << ' ' << win.vs->ViewCenterY << endl; - MyExpose(); - } - else if (word == "perspective") - { - scr >> ws >> word; - cout << "Script: perspective: " << word; - if (word == "off") - { - win.vs->OrthogonalProjection = 1; - } - else if (word == "on") + break; + case Command::Light: { - win.vs->OrthogonalProjection = 0; + scr >> ws >> word; + cout << "Script: light: " << word; + if (word == "off") + { + win.vs->SetLight(false); + } + else if (word == "on") + { + win.vs->SetLight(true); + } + else + { + cout << '?'; + } + cout << endl; + MyExpose(); } - else + break; + case Command::View: { - cout << '?'; + double theta, phi; + scr >> theta >> phi; + cout << "Script: view: " << theta << ' ' << phi << endl; + win.vs->SetView(theta, phi); + MyExpose(); } - cout << endl; - MyExpose(); - } - else if (word == "light") - { - scr >> ws >> word; - cout << "Script: light: " << word; - if (word == "off") + break; + case Command::Zoom: { - win.vs->SetLight(false); + double factor; + scr >> factor; + cout << "Script: zoom: " << factor << endl; + win.vs->Zoom(factor); + MyExpose(); } - else if (word == "on") + break; + case Command::Shading: { - win.vs->SetLight(true); + scr >> ws >> word; + cout << "Script: shading: " << flush; + VisualizationSceneScalarData::Shading s = + VisualizationSceneScalarData::Shading::Invalid; + if (word == "flat") + { + s = VisualizationSceneScalarData::Shading::Flat; + } + else if (word == "smooth") + { + s = VisualizationSceneScalarData::Shading::Smooth; + } + else if (word == "cool") + { + s = VisualizationSceneScalarData::Shading::Noncomforming; + } + if (s != VisualizationSceneScalarData::Shading::Invalid) + { + win.vs->SetShading(s, false); + cout << word << endl; + MyExpose(); + } + else + { + cout << word << " ?" << endl; + } } - else + break; + case Command::Subdivisions: { - cout << '?'; + int t, b; + scr >> t >> b; + cout << "Script: subdivisions: " << flush; + win.vs->SetRefineFactors(t, b); + cout << t << ' ' << b << endl; + MyExpose(); } - cout << endl; - MyExpose(); - } - else if (word == "view") - { - double theta, phi; - scr >> theta >> phi; - cout << "Script: view: " << theta << ' ' << phi << endl; - win.vs->SetView(theta, phi); - MyExpose(); - } - else if (word == "zoom") - { - double factor; - scr >> factor; - cout << "Script: zoom: " << factor << endl; - win.vs->Zoom(factor); - MyExpose(); - } - else if (word == "shading") - { - scr >> ws >> word; - cout << "Script: shading: " << flush; - VisualizationSceneScalarData::Shading s = - VisualizationSceneScalarData::Shading::Invalid; - if (word == "flat") + break; + case Command::Valuerange: { - s = VisualizationSceneScalarData::Shading::Flat; + double min, max; + scr >> min >> max; + cout << "Script: valuerange: " << flush; + win.vs->SetValueRange(min, max); + cout << min << ' ' << max << endl; + MyExpose(); } - else if (word == "smooth") + break; + case Command::Autoscale: { - s = VisualizationSceneScalarData::Shading::Smooth; + scr >> ws >> word; + cout << "Script: autoscale: " << word; + if (word == "off") + { + win.vs->SetAutoscale(0); + } + else if (word == "on") + { + win.vs->SetAutoscale(1); + } + else if (word == "value") + { + win.vs->SetAutoscale(2); + } + else if (word == "mesh") + { + win.vs->SetAutoscale(3); + } + else + { + cout << '?'; + } + cout << endl; } - else if (word == "cool") - { - s = VisualizationSceneScalarData::Shading::Noncomforming; + break; + case Command::Levellines: + { + double min, max; + int num; + scr >> min >> max >> num; + cout << "Script: levellines: " << flush; + win.vs->SetLevelLines(min, max, num); + win.vs->UpdateLevelLines(); + cout << min << ' ' << max << ' ' << num << endl; + MyExpose(); } - if (s != VisualizationSceneScalarData::Shading::Invalid) - { - win.vs->SetShading(s, false); - cout << word << endl; + break; + case Command::AxisNumberFormat: + { + char delim; + string axis_formatting; + scr >> ws >> delim; + getline(scr, axis_formatting, delim); + cout << "Script: axis_numberformat: " << flush; + win.vs->SetAxisNumberFormat(axis_formatting); + cout << axis_formatting << endl; MyExpose(); } - else - { - cout << word << " ?" << endl; + break; + case Command::ColorbarNumberFormat: + { + char delim; + string colorbar_formatting; + scr >> ws >> delim; + getline(scr, colorbar_formatting, delim); + cout << "Script: colorbar_numberformat: " << flush; + win.vs->SetColorbarNumberFormat(colorbar_formatting); + cout << colorbar_formatting << endl; + MyExpose(); } - } - else if (word == "subdivisions") - { - int t, b; - scr >> t >> b; - cout << "Script: subdivisions: " << flush; - win.vs->SetRefineFactors(t, b); - cout << t << ' ' << b << endl; - MyExpose(); - } - else if (word == "valuerange") - { - double min, max; - scr >> min >> max; - cout << "Script: valuerange: " << flush; - win.vs->SetValueRange(min, max); - cout << min << ' ' << max << endl; - MyExpose(); - } - else if (word == "autoscale") - { - scr >> ws >> word; - cout << "Script: autoscale: " << word; - if (word == "off") + break; + case Command::Window: { - win.vs->SetAutoscale(0); + scr >> win.window_x >> win.window_y >> win.window_w >> win.window_h; + cout << "Script: window: " << win.window_x << ' ' << win.window_y + << ' ' << win.window_w << ' ' << win.window_h << endl; + MoveResizeWindow(win.window_x, win.window_y, win.window_w, win.window_h); + MyExpose(); } - else if (word == "on") + break; + case Command::Keys: { - win.vs->SetAutoscale(1); + scr >> win.data_state.keys; + cout << "Script: keys: '" << win.data_state.keys << "'" << endl; + // SendKeySequence(keys.c_str()); + CallKeySequence(win.data_state.keys.c_str()); + MyExpose(); } - else if (word == "value") + break; + case Command::Palette: { - win.vs->SetAutoscale(2); + int pal; + scr >> pal; + cout << "Script: palette: " << pal << endl; + win.vs->palette.SetIndex(pal-1); + MyExpose(); } - else if (word == "mesh") + case Command::PaletteRepeat: { - win.vs->SetAutoscale(3); + int rpt_times; + scr >> rpt_times; + cout << "Script: palette_repeat: " << rpt_times << endl; + win.vs->palette.SetRepeatTimes(rpt_times); + win.vs->palette.GenerateTextures(); + MyExpose(); } - else + break; + case Command::ToggleAttributes: { - cout << '?'; + Array attr_list; + cout << "Script: toggle_attributes:"; + for (scr >> ws; scr.peek() != ';'; scr >> ws) + { + attr_list.Append(0); + scr >> attr_list.Last(); + if (attr_list.Size() <= 256) + { + cout << ' ' << attr_list.Last(); + } + else if (attr_list.Size() == 257) + { + cout << " ... " << flush; + } + } + scr.get(); // read the end symbol: ';' + cout << endl; + win.vs->ToggleAttributes(attr_list); + MyExpose(); } - cout << endl; - } - else if (word == "levellines") - { - double min, max; - int num; - scr >> min >> max >> num; - cout << "Script: levellines: " << flush; - win.vs->SetLevelLines(min, max, num); - win.vs->UpdateLevelLines(); - cout << min << ' ' << max << ' ' << num << endl; - MyExpose(); - } - else if (word == "axis_numberformat") - { - char delim; - string axis_formatting; - scr >> ws >> delim; - getline(scr, axis_formatting, delim); - cout << "Script: axis_numberformat: " << flush; - win.vs->SetAxisNumberFormat(axis_formatting); - cout << axis_formatting << endl; - MyExpose(); - } - else if (word == "colorbar_numberformat") - { - char delim; - string colorbar_formatting; - scr >> ws >> delim; - getline(scr, colorbar_formatting, delim); - cout << "Script: colorbar_numberformat: " << flush; - win.vs->SetColorbarNumberFormat(colorbar_formatting); - cout << colorbar_formatting << endl; - MyExpose(); - } - else if (word == "window") - { - scr >> win.window_x >> win.window_y >> win.window_w >> win.window_h; - cout << "Script: window: " << win.window_x << ' ' << win.window_y - << ' ' << win.window_w << ' ' << win.window_h << endl; - MoveResizeWindow(win.window_x, win.window_y, win.window_w, win.window_h); - MyExpose(); - } - else if (word == "keys") - { - scr >> win.data_state.keys; - cout << "Script: keys: '" << win.data_state.keys << "'" << endl; - // SendKeySequence(keys.c_str()); - CallKeySequence(win.data_state.keys.c_str()); - MyExpose(); - } - else if (word == "palette") - { - int pal; - scr >> pal; - cout << "Script: palette: " << pal << endl; - win.vs->palette.SetIndex(pal-1); - MyExpose(); - } - else if (word == "palette_repeat") - { - int rpt_times; - scr >> rpt_times; - cout << "Script: palette_repeat: " << rpt_times << endl; - win.vs->palette.SetRepeatTimes(rpt_times); - win.vs->palette.GenerateTextures(); - MyExpose(); - } - else if (word == "toggle_attributes") - { - Array attr_list; - cout << "Script: toggle_attributes:"; - for (scr >> ws; scr.peek() != ';'; scr >> ws) + break; + case Command::Rotmat: { - attr_list.Append(0); - scr >> attr_list.Last(); - if (attr_list.Size() <= 256) + cout << "Script: rotmat:"; + for (int i = 0; i < 16; i++) { - cout << ' ' << attr_list.Last(); + scr >> win.vs->rotmat[i/4][i%4]; + cout << ' ' << win.vs->rotmat[i/4][i%4]; } - else if (attr_list.Size() == 257) + cout << endl; + MyExpose(); + } + break; + case Command::Camera: + { + double cam[9]; + cout << "Script: camera:"; + for (int i = 0; i < 9; i++) { - cout << " ... " << flush; + scr >> cam[i]; + cout << ' ' << cam[i]; } + cout << endl; + win.vs->cam.Set(cam); + MyExpose(); } - scr.get(); // read the end symbol: ';' - cout << endl; - win.vs->ToggleAttributes(attr_list); - MyExpose(); - } - else if (word == "rotmat") - { - cout << "Script: rotmat:"; - for (int i = 0; i < 16; i++) - { - scr >> win.vs->rotmat[i/4][i%4]; - cout << ' ' << win.vs->rotmat[i/4][i%4]; + break; + case Command::Scale: + { + double scale; + cout << "Script: scale:"; + scr >> scale; + cout << ' ' << scale; + cout << endl; + win.vs->Scale(scale); + MyExpose(); } - cout << endl; - MyExpose(); - } - else if (word == "camera") - { - double cam[9]; - cout << "Script: camera:"; - for (int i = 0; i < 9; i++) + break; + case Command::Translate: + { + double x, y, z; + cout << "Script: translate:"; + scr >> x >> y >> z; + cout << ' ' << x << ' ' << y << ' ' << z; + cout << endl; + win.vs->Translate(x, y, z); + MyExpose(); + } + break; + case Command::PlotCaption: { - scr >> cam[i]; - cout << ' ' << cam[i]; + char delim; + scr >> ws >> delim; + getline(scr, win.plot_caption, delim); + win.vs->PrepareCaption(); // turn on or off the caption + MyExpose(); } - cout << endl; - win.vs->cam.Set(cam); - MyExpose(); - } - else if (word == "scale") - { - double scale; - cout << "Script: scale:"; - scr >> scale; - cout << ' ' << scale; - cout << endl; - win.vs->Scale(scale); - MyExpose(); - } - else if (word == "translate") - { - double x, y, z; - cout << "Script: translate:"; - scr >> x >> y >> z; - cout << ' ' << x << ' ' << y << ' ' << z; - cout << endl; - win.vs->Translate(x, y, z); - MyExpose(); - } - else if (word == "plot_caption") - { - char delim; - scr >> ws >> delim; - getline(scr, win.plot_caption, delim); - win.vs->PrepareCaption(); // turn on or off the caption - MyExpose(); - } - else - { - cout << "Unknown command in script: " << word << endl; + break; + default: + break; } done_one_command = 1; @@ -703,15 +837,25 @@ void ScriptController::ScriptControl() } } +ScriptController::ScriptController(Window &win_) + : win(win_) +{ + if (commands.empty()) + { + InitCommands(); + } +} + void ScriptController::PlayScript(istream &scr) { string word; + bool done = false; scr_min_val = numeric_limits::infinity(); scr_max_val = -scr_min_val; // read initializing commands - while (1) + while (!done) { scr >> ws; if (!scr.good()) @@ -725,102 +869,85 @@ void ScriptController::PlayScript(istream &scr) continue; } scr >> word; - if (word == "window") - { - scr >> win.window_x >> win.window_y >> win.window_w >> win.window_h; - } - else if (word == "data_coll_cycle") - { - scr >> dc_cycle; - } - else if (word == "data_coll_protocol") - { - scr >> dc_protocol; - } - else if (word == "solution") - { - if (ScriptReadSolution(scr, win.data_state)) - { - return; - } - // start the visualization - break; - } - else if (word == "quadrature") + auto it = find(commands.begin(), commands.end(), word); + if (it == commands.end()) { - if (ScriptReadQuadrature(scr, win.data_state)) - { - return; - } - - // start the visualization - break; - } - else if (word == "psolution") - { - if (ScriptReadParSolution(scr, win.data_state)) - { - return; - } - - // start the visualization - break; + cout << "Unknown command in script: " << word << endl; + PrintCommands(); + return; } - else if (word == "pquadrature") - { - if (ScriptReadParQuadrature(scr, win.data_state)) - { - return; - } - // start the visualization - break; - } - else if (word == "mesh") + const Command cmd = (Command)(it - commands.begin()); + switch (cmd) { - if (ScriptReadDisplMesh(scr, win.data_state)) - { - return; - } - if (win.data_state.mesh) - { + case Command::Window: + scr >> win.window_x >> win.window_y >> win.window_w >> win.window_h; + break; + case Command::DataCollCycle: + scr >> dc_cycle; + break; + case Command::DataCollProto: + scr >> dc_protocol; + break; + case Command::Solution: + if (ScriptReadSolution(scr, win.data_state)) + { + return; + } + done = true; // start the visualization + break; + case Command::Quadrature: + if (ScriptReadQuadrature(scr, win.data_state)) + { + return; + } + done = true; // start the visualization + break; + case Command::ParSolution: + if (ScriptReadParSolution(scr, win.data_state)) + { + return; + } + done = true; // start the visualization + break; + case Command::ParQuadrature: + if (ScriptReadParQuadrature(scr, win.data_state)) + { + return; + } + done = true; // start the visualization + break; + case Command::Mesh: + if (ScriptReadDisplMesh(scr, win.data_state)) + { + return; + } + done = win.data_state.mesh != nullptr; + break; + case Command::DataCollMesh: + if (ScriptReadDataColl(scr, win.data_state)) + { + return; + } + done = true; // start the visualization + break; + case Command::DataCollField: + if (ScriptReadDataColl(scr, win.data_state, false)) + { + return; + } + done = true; // start the visualization + break; + case Command::DataCollQuad: + if (ScriptReadDataColl(scr, win.data_state, false, true)) + { + return; + } + done = true; // start the visualization + break; + default: break; - } - } - else if (word == "data_coll_mesh") - { - if (ScriptReadDataColl(scr, win.data_state)) - { - return; - } - - // start the visualization - break; - } - else if (word == "data_coll_field") - { - if (ScriptReadDataColl(scr, win.data_state, false)) - { - return; - } - - // start the visualization - break; - } - else if (word == "data_coll_quad") - { - if (ScriptReadDataColl(scr, win.data_state, false, true)) - { - return; - } - - // start the visualization - break; - } - else - { - cout << "Unknown command in script: " << word << endl; } } diff --git a/lib/script_controller.hpp b/lib/script_controller.hpp index ab6d1573..44304ab1 100644 --- a/lib/script_controller.hpp +++ b/lib/script_controller.hpp @@ -44,10 +44,13 @@ class ScriptController static thread_local ScriptController *script_ctrl; static void ScriptIdleFunc(); static void ScriptControl(); + + static void InitCommands(); + static void PrintCommands(); void ExecuteScriptCommand(); public: - ScriptController(Window &win_) : win(win_) { } + ScriptController(Window &win_); void PlayScript(std::istream &scr); }; From b021552af7a335d078ba05d6822c5940a672252e Mon Sep 17 00:00:00 2001 From: Jan Nikl Date: Mon, 5 May 2025 22:43:15 -0700 Subject: [PATCH 17/56] Fixed double free. --- lib/aux_vis.cpp | 1 - lib/window.cpp | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/aux_vis.cpp b/lib/aux_vis.cpp index 16efccb7..015f55ca 100644 --- a/lib/aux_vis.cpp +++ b/lib/aux_vis.cpp @@ -369,7 +369,6 @@ void RunVisualization() wnd->mainLoop(); #endif InitIdleFuncs(); - delete locscene; delete wnd; wnd = nullptr; } diff --git a/lib/window.cpp b/lib/window.cpp index 96b9e7a8..1966069d 100644 --- a/lib/window.cpp +++ b/lib/window.cpp @@ -172,7 +172,7 @@ bool Window::GLVisInitVis(StreamCollection input_streams) void Window::GLVisStartVis() { - RunVisualization(); // deletes vs + RunVisualization(); internal.vs.reset(); if (glvis_command) { From 7323f0281e4c4219c0c6ca52c8448cf120fc4031 Mon Sep 17 00:00:00 2001 From: Jan Nikl Date: Tue, 6 May 2025 01:23:22 -0700 Subject: [PATCH 18/56] Changed streams to commands list. --- lib/script_controller.cpp | 2 +- lib/threads.cpp | 1048 +++++++++++++++++++++---------------- lib/threads.hpp | 2 + 3 files changed, 598 insertions(+), 454 deletions(-) diff --git a/lib/script_controller.cpp b/lib/script_controller.cpp index bf11e529..56e60a76 100644 --- a/lib/script_controller.cpp +++ b/lib/script_controller.cpp @@ -318,7 +318,7 @@ void ScriptController::InitCommands() commands[(size_t)Command::AxisNumberFormat] = {"axis_numberformat", "''", "Set the axis number format."}; commands[(size_t)Command::ColorbarNumberFormat] = {"colorbar_numberformat", "''", "Set the colorbar number format."}; commands[(size_t)Command::Window] = {"window", " ", "Set the position and size of the window."}; - commands[(size_t)Command::Keys] = {"keys", "", "Send the control key sequence."}; + commands[(size_t)Command::Keys] = {"keys", "", "Send the control key sequence."}; commands[(size_t)Command::Palette] = {"palette", "", "Set the palette index."}; commands[(size_t)Command::PaletteRepeat] = {"palette_repeat", "", "Set the repetition of the palette."}; commands[(size_t)Command::ToggleAttributes] = {"toggle_attributes", "<1/0> [[<1/0>] ...];", "Toggle visibility of the attributes."}; diff --git a/lib/threads.cpp b/lib/threads.cpp index 47ef5f8d..fdad95fe 100644 --- a/lib/threads.cpp +++ b/lib/threads.cpp @@ -12,6 +12,7 @@ #include "visual.hpp" #include "palettes.hpp" #include +#include using namespace std; @@ -796,6 +797,49 @@ GLVisCommand::~GLVisCommand() } } +enum class Command +{ + Mesh, + Solution, + Quadrature, + Parallel, + Screenshot, + Viewcenter, + View, + Zoom, + Shading, + Subdivisions, + Valuerange, + Autoscale, + Levellines, + AxisNumberFormat, + ColorbarNumberFormat, + WindowSize, + WindowGeometry, + WindowTitle, + Keys, + Palette, + PaletteRepeat, + Camera, + PlotCaption, + AxisLabels, + Pause, + Autopause, + //---------- + Max +}; + +struct CmdItem +{ + const char *keyword; + const char *params; + const char *desc; + + bool operator==(const string &key) const { return key == keyword; } +}; + +static vector commands; + communication_thread::communication_thread(StreamCollection _is, GLVisCommand* cmd) : is(std::move(_is)), glvis_command(cmd) @@ -803,6 +847,11 @@ communication_thread::communication_thread(StreamCollection _is, new_m = NULL; new_g = NULL; + if (commands.empty()) + { + init_commands(); + } + if (is.size() > 0) { tid = std::thread(&communication_thread::execute, this); @@ -818,6 +867,48 @@ communication_thread::~communication_thread() } } +void communication_thread::init_commands() +{ + commands.resize((size_t)Command::Max); + + commands[(size_t)Command::Mesh] = {"mesh", "", "Visualize the mesh."}; + commands[(size_t)Command::Solution] = {"solution", " ", "Visualize the solution."}; + commands[(size_t)Command::Quadrature] = {"quadrature", " ", "Visualize the quadrature."}; + commands[(size_t)Command::Parallel] = {"parallel", " ", "Prefix for distributed mesh/solution/quadrature."}; + commands[(size_t)Command::Screenshot] = {"screenshot", "", "Take a screenshot, saving it to the file."}; + commands[(size_t)Command::Viewcenter] = {"viewcenter", " ", "Change the viewcenter."}; + commands[(size_t)Command::View] = {"view", " ", "Change the solid angle of view."}; + commands[(size_t)Command::Zoom] = {"zoom", "", "Change the zoom factor."}; + commands[(size_t)Command::Shading] = {"shading", "", "Change the shading algorithm."}; + commands[(size_t)Command::Subdivisions] = {"subdivisions", " ", "Change the refinement level."}; + commands[(size_t)Command::Valuerange] = {"valuerange", " ", "Change the value range."}; + commands[(size_t)Command::Autoscale] = {"autoscale", "", "Change the autoscale algorithm."}; + commands[(size_t)Command::Levellines] = {"levellines", " ", "Set the level lines."}; + commands[(size_t)Command::AxisNumberFormat] = {"axis_numberformat", "''", "Set the axis number format."}; + commands[(size_t)Command::ColorbarNumberFormat] = {"colorbar_numberformat", "''", "Set the colorbar number format."}; + commands[(size_t)Command::WindowSize] = {"window_size", " ", "Set the size of the window."}; + commands[(size_t)Command::WindowGeometry] = {"window_geometry", " ", "Set the position and size of the window."}; + commands[(size_t)Command::WindowTitle] = {"window_title", "''", "Set title of the window."}; + commands[(size_t)Command::Keys] = {"keys", "<keys>", "Send the control key sequence."}; + commands[(size_t)Command::Palette] = {"palette", "<index>", "Set the palette index."}; + commands[(size_t)Command::PaletteRepeat] = {"palette_repeat", "<times>", "Set the repetition of the palette."}; + commands[(size_t)Command::Camera] = {"camera", "<cam[0]> ... <cam[2]> <dir[0]> ... <dir[2]> <up[0]> ... <up[2]>", "Set the camera position, direction and upward vector."}; + commands[(size_t)Command::PlotCaption] = {"plot_caption", "'<caption>'", "Set the plot caption."}; + commands[(size_t)Command::AxisLabels] = {"axis_labels", "'<x label>' '<y label>' '<z label>'", "Set labels of the axes."}; + commands[(size_t)Command::Pause] = {"pause", "", "Stop the stream until space is pressed."}; + commands[(size_t)Command::Autopause] = {"autopause", "<0/off/1/on>", "Turns off or on autopause."}; +} + +void communication_thread::print_commands() +{ + cout << "Available commands are:" << endl; + + for (const CmdItem &ci : commands) + { + cout << "\t" << ci.keyword << " " << ci.params << " - " << ci.desc << endl; + } +} + void communication_thread::execute() { while (1) @@ -832,571 +923,622 @@ void communication_thread::execute() break; } - if (ident == "mesh" || ident == "solution" || - ident == "quadrature" || ident == "parallel") + auto it = find(commands.begin(), commands.end(), ident); + if (it == commands.end()) { - bool fix_elem_orient = glvis_command->FixElementOrientations(); - DataState tmp; - if (ident == "mesh") - { - tmp.SetMesh(new Mesh(*is[0], 1, 0, fix_elem_orient)); - if (!(*is[0])) - { - break; - } - tmp.SetGridFunction(NULL); - } - else if (ident == "solution") - { - tmp.SetMesh(new Mesh(*is[0], 1, 0, fix_elem_orient)); - if (!(*is[0])) - { - break; - } - tmp.SetGridFunction(new GridFunction(tmp.mesh.get(), *is[0])); - if (!(*is[0])) - { - break; - } - } - else if (ident == "quadrature") - { - tmp.SetMesh(new Mesh(*is[0], 1, 0, fix_elem_orient)); - if (!(*is[0])) - { - break; - } - tmp.SetQuadFunction(new QuadratureFunction(tmp.mesh.get(), *is[0])); - if (!(*is[0])) + cout << "Stream: unknown command: " << ident << endl; + print_commands(); + goto comm_terminate; + } + + const Command cmd = (Command)(it - commands.begin()); + switch (cmd) + { + case Command::Mesh: + case Command::Solution: + case Command::Quadrature: + case Command::Parallel: + { + bool fix_elem_orient = glvis_command->FixElementOrientations(); + bool done = false; + DataState tmp; + switch (cmd) { + case Command::Mesh: + { + tmp.SetMesh(new Mesh(*is[0], 1, 0, fix_elem_orient)); + if (!(*is[0])) + { + done = true; + break; + } + tmp.SetGridFunction(NULL); + } break; - } - } - else if (ident == "parallel") - { - std::vector<Mesh*> mesh_array; - std::vector<GridFunction*> gf_array; - std::vector<QuadratureFunction*> qf_array; - int proc, nproc, np = 0; - bool keep_attr = glvis_command->KeepAttrib(); - do - { - istream &isock = *is[np]; - isock >> nproc >> proc >> ws; -#ifdef GLVIS_DEBUG - cout << "connection[" << np << "]: parallel " << nproc << ' ' - << proc << endl; -#endif - isock >> ident >> ws; - mesh_array.resize(nproc); - mesh_array[proc] = new Mesh(isock, 1, 0, fix_elem_orient); - if (!keep_attr) + case Command::Solution: { - // set element and boundary attributes to proc+1 - for (int i = 0; i < mesh_array[proc]->GetNE(); i++) + tmp.SetMesh(new Mesh(*is[0], 1, 0, fix_elem_orient)); + if (!(*is[0])) { - mesh_array[proc]->GetElement(i)->SetAttribute(proc+1); + done = true; + break; } - for (int i = 0; i < mesh_array[proc]->GetNBE(); i++) + tmp.SetGridFunction(new GridFunction(tmp.mesh.get(), *is[0])); + if (!(*is[0])) { - mesh_array[proc]->GetBdrElement(i)->SetAttribute(proc+1); + done = true; + break; } } - if (ident == "solution") - { - gf_array.resize(nproc); - gf_array[proc] = new GridFunction(mesh_array[proc], isock); - } - else if (ident == "quadrature") + break; + case Command::Quadrature: { - qf_array.resize(nproc); - qf_array[proc] = new QuadratureFunction(mesh_array[proc], isock); + tmp.SetMesh(new Mesh(*is[0], 1, 0, fix_elem_orient)); + if (!(*is[0])) + { + done = true; + break; + } + tmp.SetQuadFunction(new QuadratureFunction(tmp.mesh.get(), *is[0])); + if (!(*is[0])) + { + done = true; + break; + } } - else + break; + case Command::Parallel: { - cout << "Stream: unknown command: " << ident << endl; + std::vector<Mesh*> mesh_array; + std::vector<GridFunction*> gf_array; + std::vector<QuadratureFunction*> qf_array; + int proc, nproc, np = 0; + bool keep_attr = glvis_command->KeepAttrib(); + do + { + istream &isock = *is[np]; + isock >> nproc >> proc >> ws; +#ifdef GLVIS_DEBUG + cout << "connection[" << np << "]: parallel " << nproc << ' ' + << proc << endl; +#endif + isock >> ident >> ws; + mesh_array.resize(nproc); + mesh_array[proc] = new Mesh(isock, 1, 0, fix_elem_orient); + if (!keep_attr) + { + // set element and boundary attributes to proc+1 + for (int i = 0; i < mesh_array[proc]->GetNE(); i++) + { + mesh_array[proc]->GetElement(i)->SetAttribute(proc+1); + } + for (int i = 0; i < mesh_array[proc]->GetNBE(); i++) + { + mesh_array[proc]->GetBdrElement(i)->SetAttribute(proc+1); + } + } + if (ident == "solution") + { + gf_array.resize(nproc); + gf_array[proc] = new GridFunction(mesh_array[proc], isock); + } + else if (ident == "quadrature") + { + qf_array.resize(nproc); + qf_array[proc] = new QuadratureFunction(mesh_array[proc], isock); + } + else + { + cout << "Stream: unknown command: " << ident << endl; + } + np++; + if (np == nproc) + { + break; + } + *is[np] >> ident >> ws; // "parallel" + } + while (1); + + tmp.SetMesh(new Mesh(mesh_array.data(), nproc)); + if (gf_array.size() > 0) + { + tmp.SetGridFunction(new GridFunction(tmp.mesh.get(), gf_array.data(), nproc)); + } + else if (qf_array.size() > 0) + { + tmp.SetQuadFunction(qf_array); + } + + for (int p = 0; p < nproc; p++) + { + if (gf_array.size() > 0) + { + delete gf_array[nproc-1-p]; + } + if (qf_array.size() > 0) + { + delete qf_array[nproc-1-p]; + } + delete mesh_array[nproc-1-p]; + } + gf_array.clear(); + qf_array.clear(); + mesh_array.clear(); } - np++; - if (np == nproc) - { + break; + default: break; - } - *is[np] >> ident >> ws; // "parallel" } - while (1); + if (done) { break; } - tmp.SetMesh(new Mesh(mesh_array.data(), nproc)); - if (gf_array.size() > 0) + // cout << "Stream: new solution" << endl; + + tmp.ExtrudeMeshAndSolution(); + + if (glvis_command->NewMeshAndSolution(std::move(tmp))) { - tmp.SetGridFunction(new GridFunction(tmp.mesh.get(), gf_array.data(), nproc)); + goto comm_terminate; } - else if (qf_array.size() > 0) + } + break; + case Command::Screenshot: + { + string filename; + + *is[0] >> ws >> filename; + + // all processors sent the screenshot command + for (size_t i = 1; i < is.size(); i++) { - tmp.SetQuadFunction(qf_array); + *is[i] >> ws >> ident; // 'screenshot' + *is[i] >> ws >> ident; // filename } - for (int p = 0; p < nproc; p++) + if (glvis_command->Screenshot(filename.c_str())) { - if (gf_array.size() > 0) - { - delete gf_array[nproc-1-p]; - } - if (qf_array.size() > 0) - { - delete qf_array[nproc-1-p]; - } - delete mesh_array[nproc-1-p]; + goto comm_terminate; } - gf_array.clear(); - qf_array.clear(); - mesh_array.clear(); } + break; + case Command::Keys: + { + string keys; - // cout << "Stream: new solution" << endl; + *is[0] >> ws >> keys; - tmp.ExtrudeMeshAndSolution(); + // all processors sent the command + for (size_t i = 1; i < is.size(); i++) + { + *is[i] >> ws >> ident; // 'keys' + *is[i] >> ws >> ident; // keys + } - if (glvis_command->NewMeshAndSolution(std::move(tmp))) - { - goto comm_terminate; + if (glvis_command->KeyCommands(keys.c_str())) + { + goto comm_terminate; + } } - } - else if (ident == "screenshot") - { - string filename; - - *is[0] >> ws >> filename; - - // all processors sent the screenshot command - for (size_t i = 1; i < is.size(); i++) + break; + case Command::WindowSize: { - *is[i] >> ws >> ident; // 'screenshot' - *is[i] >> ws >> ident; // filename - } + int w, h, t; - if (glvis_command->Screenshot(filename.c_str())) - { - goto comm_terminate; - } - } - else if (ident == "keys") - { - string keys; + *is[0] >> w >> h; - *is[0] >> ws >> keys; + // all processors sent the command + for (size_t i = 1; i < is.size(); i++) + { + *is[i] >> ws >> ident; // 'window_size' + *is[i] >> t >> t; + } - // all processors sent the command - for (size_t i = 1; i < is.size(); i++) - { - *is[i] >> ws >> ident; // 'keys' - *is[i] >> ws >> ident; // keys + if (glvis_command->WindowSize(w, h)) + { + goto comm_terminate; + } } - - if (glvis_command->KeyCommands(keys.c_str())) + break; + case Command::WindowGeometry: { - goto comm_terminate; - } - } - else if (ident == "window_size") - { - int w, h, t; + int x, y, w, h, t; - *is[0] >> w >> h; + *is[0] >> x >> y >> w >> h; - // all processors sent the command - for (size_t i = 1; i < is.size(); i++) - { - *is[i] >> ws >> ident; // 'window_size' - *is[i] >> t >> t; - } + // all processors sent the command + for (size_t i = 1; i < is.size(); i++) + { + *is[i] >> ws >> ident; // 'window_geometry' + *is[i] >> t >> t >> t >> t; + } - if (glvis_command->WindowSize(w, h)) - { - goto comm_terminate; + if (glvis_command->WindowGeometry(x, y, w, h)) + { + goto comm_terminate; + } } - } - else if (ident == "window_geometry") - { - int x, y, w, h, t; - - *is[0] >> x >> y >> w >> h; - - // all processors sent the command - for (size_t i = 1; i < is.size(); i++) + break; + case Command::WindowTitle: { - *is[i] >> ws >> ident; // 'window_geometry' - *is[i] >> t >> t >> t >> t; - } + char c; + string title; - if (glvis_command->WindowGeometry(x, y, w, h)) - { - goto comm_terminate; - } - } - else if (ident == "window_title") - { - char c; - string title; + // read the opening char + *is[0] >> ws >> c; + // use the opening char as termination as well + getline(*is[0], title, c); - // read the opening char - *is[0] >> ws >> c; - // use the opening char as termination as well - getline(*is[0], title, c); + // all processors sent the command + for (size_t i = 1; i < is.size(); i++) + { + *is[i] >> ws >> ident; // 'window_title' + *is[i] >> ws >> c; + getline(*is[i], ident, c); + } - // all processors sent the command - for (size_t i = 1; i < is.size(); i++) - { - *is[i] >> ws >> ident; // 'window_title' - *is[i] >> ws >> c; - getline(*is[i], ident, c); + if (glvis_command->WindowTitle(title.c_str())) + { + goto comm_terminate; + } } - - if (glvis_command->WindowTitle(title.c_str())) + break; + case Command::PlotCaption: { - goto comm_terminate; - } - } - else if (ident == "plot_caption") - { - char c; - string caption; + char c; + string caption; - // read the opening char - *is[0] >> ws >> c; - // use the opening char as termination as well - getline(*is[0], caption, c); + // read the opening char + *is[0] >> ws >> c; + // use the opening char as termination as well + getline(*is[0], caption, c); - // all processors sent the command - for (size_t i = 1; i < is.size(); i++) - { - *is[i] >> ws >> ident; // 'plot_caption' - *is[i] >> ws >> c; - getline(*is[i], ident, c); + // all processors sent the command + for (size_t i = 1; i < is.size(); i++) + { + *is[i] >> ws >> ident; // 'plot_caption' + *is[i] >> ws >> c; + getline(*is[i], ident, c); + } + + if (glvis_command->PlotCaption(caption.c_str())) + { + goto comm_terminate; + } } + break; + case Command::AxisLabels: + { + char c; + string label_x, label_y, label_z; + + // read the opening char + *is[0] >> ws >> c; + // use the opening char as termination as well + getline(*is[0], label_x, c); + *is[0] >> ws >> c; + getline(*is[0], label_y, c); + *is[0] >> ws >> c; + getline(*is[0], label_z, c); + + // all processors sent the command + for (size_t i = 1; i < is.size(); i++) + { + *is[i] >> ws >> ident; // 'axis_label' + *is[i] >> ws >> c; + getline(*is[i], ident, c); + *is[i] >> ws >> c; + getline(*is[i], ident, c); + *is[i] >> ws >> c; + getline(*is[i], ident, c); + } - if (glvis_command->PlotCaption(caption.c_str())) - { - goto comm_terminate; + if (glvis_command->AxisLabels(label_x.c_str(), + label_y.c_str(), + label_z.c_str())) + { + goto comm_terminate; + } } - } - else if (ident == "axis_labels") - { - char c; - string label_x, label_y, label_z; - - // read the opening char - *is[0] >> ws >> c; - // use the opening char as termination as well - getline(*is[0], label_x, c); - *is[0] >> ws >> c; - getline(*is[0], label_y, c); - *is[0] >> ws >> c; - getline(*is[0], label_z, c); - - // all processors sent the command - for (size_t i = 1; i < is.size(); i++) + break; + case Command::Pause: { - *is[i] >> ws >> ident; // 'axis_label' - *is[i] >> ws >> c; - getline(*is[i], ident, c); - *is[i] >> ws >> c; - getline(*is[i], ident, c); - *is[i] >> ws >> c; - getline(*is[i], ident, c); - } + // all processors sent the command + for (size_t i = 1; i < is.size(); i++) + { + *is[i] >> ws >> ident; // 'pause' + } - if (glvis_command->AxisLabels(label_x.c_str(), - label_y.c_str(), - label_z.c_str())) - { - goto comm_terminate; + if (glvis_command->Pause()) + { + goto comm_terminate; + } } - } - else if (ident == "pause") - { - // all processors sent the command - for (size_t i = 1; i < is.size(); i++) + break; + case Command::View: { - *is[i] >> ws >> ident; // 'pause' - } + double theta, phi, a; - if (glvis_command->Pause()) - { - goto comm_terminate; - } - } - else if (ident == "view") - { - double theta, phi, a; + *is[0] >> theta >> phi; - *is[0] >> theta >> phi; + // all processors sent the command + for (size_t i = 1; i < is.size(); i++) + { + *is[i] >> ws >> ident; // 'view' + *is[i] >> a >> a; + } - // all processors sent the command - for (size_t i = 1; i < is.size(); i++) - { - *is[i] >> ws >> ident; // 'view' - *is[i] >> a >> a; + if (glvis_command->ViewAngles(theta, phi)) + { + goto comm_terminate; + } } - - if (glvis_command->ViewAngles(theta, phi)) + break; + case Command::Zoom: { - goto comm_terminate; - } - } - else if (ident == "zoom") - { - double factor, a; + double factor, a; - *is[0] >> factor; + *is[0] >> factor; - // all processors sent the command - for (size_t i = 1; i < is.size(); i++) - { - *is[i] >> ws >> ident; // 'zoom' - *is[i] >> a; - } + // all processors sent the command + for (size_t i = 1; i < is.size(); i++) + { + *is[i] >> ws >> ident; // 'zoom' + *is[i] >> a; + } - if (glvis_command->Zoom(factor)) - { - goto comm_terminate; + if (glvis_command->Zoom(factor)) + { + goto comm_terminate; + } } - } - else if (ident == "subdivisions") - { - int tot, bdr, a; - - *is[0] >> tot >> bdr; - - // all processors sent the command - for (size_t i = 1; i < is.size(); i++) + break; + case Command::Subdivisions: { - *is[i] >> ws >> ident; // 'subdivisions' - *is[i] >> a >> a; - } + int tot, bdr, a; - if (glvis_command->Subdivisions(tot, bdr)) - { - goto comm_terminate; - } - } - else if (ident == "valuerange") - { - double minv, maxv, a; + *is[0] >> tot >> bdr; - *is[0] >> minv >> maxv; + // all processors sent the command + for (size_t i = 1; i < is.size(); i++) + { + *is[i] >> ws >> ident; // 'subdivisions' + *is[i] >> a >> a; + } - // all processors sent the command - for (size_t i = 1; i < is.size(); i++) - { - *is[i] >> ws >> ident; // 'valuerange' - *is[i] >> a >> a; + if (glvis_command->Subdivisions(tot, bdr)) + { + goto comm_terminate; + } } - - if (glvis_command->ValueRange(minv, maxv)) + break; + case Command::Valuerange: { - goto comm_terminate; - } - } - else if (ident == "levellines") - { - double minv, maxv, a; - int num, b; + double minv, maxv, a; - *is[0] >> minv >> maxv >> num; + *is[0] >> minv >> maxv; - // all processors sent the command - for (size_t i = 1; i < is.size(); i++) - { - *is[i] >> ws >> ident; // 'levellines' - *is[i] >> a >> a >> b; - } + // all processors sent the command + for (size_t i = 1; i < is.size(); i++) + { + *is[i] >> ws >> ident; // 'valuerange' + *is[i] >> a >> a; + } - if (glvis_command->Levellines(minv, maxv, num)) - { - goto comm_terminate; + if (glvis_command->ValueRange(minv, maxv)) + { + goto comm_terminate; + } } - } - else if (ident == "axis_numberformat") - { - char c; - string formatting; + break; + case Command::Levellines: + { + double minv, maxv, a; + int num, b; - // read the opening char - *is[0] >> ws >> c; - // read formatting string & use c for termination - getline(*is[0], formatting, c); + *is[0] >> minv >> maxv >> num; - // all processors sent the command - for (size_t i = 1; i < is.size(); i++) - { - *is[i] >> ws >> ident; // 'axis_numberformat' - *is[i] >> ws >> c; - getline(*is[i], ident, c); - } + // all processors sent the command + for (size_t i = 1; i < is.size(); i++) + { + *is[i] >> ws >> ident; // 'levellines' + *is[i] >> a >> a >> b; + } - if (glvis_command->AxisNumberFormat(formatting)) - { - goto comm_terminate; + if (glvis_command->Levellines(minv, maxv, num)) + { + goto comm_terminate; + } } - } - else if (ident == "colorbar_numberformat") - { - char c; - string formatting; + break; + case Command::AxisNumberFormat: + { + char c; + string formatting; - // read the opening char - *is[0] >> ws >> c; - // read formatting string & use c for termination - getline(*is[0], formatting, c); + // read the opening char + *is[0] >> ws >> c; + // read formatting string & use c for termination + getline(*is[0], formatting, c); - // all processors sent the command - for (size_t i = 1; i < is.size(); i++) - { - *is[i] >> ws >> ident; // 'colorbar_numberformat' - *is[i] >> ws >> c; - getline(*is[i], ident, c); - } + // all processors sent the command + for (size_t i = 1; i < is.size(); i++) + { + *is[i] >> ws >> ident; // 'axis_numberformat' + *is[i] >> ws >> c; + getline(*is[i], ident, c); + } - if (glvis_command->ColorbarNumberFormat(formatting)) - { - goto comm_terminate; + if (glvis_command->AxisNumberFormat(formatting)) + { + goto comm_terminate; + } } - } - else if (ident == "shading") - { - string shd; + break; + case Command::ColorbarNumberFormat: + { + char c; + string formatting; - *is[0] >> ws >> shd; + // read the opening char + *is[0] >> ws >> c; + // read formatting string & use c for termination + getline(*is[0], formatting, c); - // all processors sent the command - for (size_t i = 1; i < is.size(); i++) - { - *is[i] >> ws >> ident; // 'shading' - *is[i] >> ws >> ident; - } + // all processors sent the command + for (size_t i = 1; i < is.size(); i++) + { + *is[i] >> ws >> ident; // 'colorbar_numberformat' + *is[i] >> ws >> c; + getline(*is[i], ident, c); + } - if (glvis_command->SetShading(shd.c_str())) - { - goto comm_terminate; + if (glvis_command->ColorbarNumberFormat(formatting)) + { + goto comm_terminate; + } } - } - else if (ident == "viewcenter") - { - double x, y, a; + break; + case Command::Shading: + { + string shd; - *is[0] >> x >> y; + *is[0] >> ws >> shd; - // all processors sent the command - for (size_t i = 1; i < is.size(); i++) - { - *is[i] >> ws >> ident; // 'viewcenter' - *is[i] >> a >> a; - } + // all processors sent the command + for (size_t i = 1; i < is.size(); i++) + { + *is[i] >> ws >> ident; // 'shading' + *is[i] >> ws >> ident; + } - if (glvis_command->ViewCenter(x, y)) - { - goto comm_terminate; + if (glvis_command->SetShading(shd.c_str())) + { + goto comm_terminate; + } } - } - else if (ident == "autoscale") - { - string mode; + break; + case Command::Viewcenter: + { + double x, y, a; - *is[0] >> ws >> mode; + *is[0] >> x >> y; - // all processors sent the command - for (size_t i = 1; i < is.size(); i++) - { - *is[i] >> ws >> ident; // 'autoscale' - *is[i] >> ws >> ident; - } + // all processors sent the command + for (size_t i = 1; i < is.size(); i++) + { + *is[i] >> ws >> ident; // 'viewcenter' + *is[i] >> a >> a; + } - if (glvis_command->Autoscale(mode.c_str())) - { - goto comm_terminate; + if (glvis_command->ViewCenter(x, y)) + { + goto comm_terminate; + } } - } - else if (ident == "palette") - { - int pal, a; + break; + case Command::Autoscale: + { + string mode; - *is[0] >> pal; + *is[0] >> ws >> mode; - // all processors sent the command - for (size_t i = 1; i < is.size(); i++) - { - *is[i] >> ws >> ident; // 'palette' - *is[i] >> a; - } + // all processors sent the command + for (size_t i = 1; i < is.size(); i++) + { + *is[i] >> ws >> ident; // 'autoscale' + *is[i] >> ws >> ident; + } - if (glvis_command->Palette(pal)) - { - goto comm_terminate; + if (glvis_command->Autoscale(mode.c_str())) + { + goto comm_terminate; + } } - } - else if (ident == "palette_repeat") - { - int n, a; + break; + case Command::Palette: + { + int pal, a; - *is[0] >> n; + *is[0] >> pal; - // all processors sent the command - for (size_t i = 1; i < is.size(); i++) - { - *is[i] >> ws >> ident; // 'palette_repeat' - *is[i] >> a; - } + // all processors sent the command + for (size_t i = 1; i < is.size(); i++) + { + *is[i] >> ws >> ident; // 'palette' + *is[i] >> a; + } - if (glvis_command->PaletteRepeat(n)) - { - goto comm_terminate; + if (glvis_command->Palette(pal)) + { + goto comm_terminate; + } } - } - else if (ident == "camera") - { - double cam[9], a; - - for (int i = 0; i < 9; i++) + break; + case Command::PaletteRepeat: { - *is[0] >> cam[i]; - } + int n, a; - // all processors sent the command - for (size_t i = 1; i < is.size(); i++) - { - *is[i] >> ws >> ident; // 'camera' - for (int j = 0; j < 9; j++) + *is[0] >> n; + + // all processors sent the command + for (size_t i = 1; i < is.size(); i++) { + *is[i] >> ws >> ident; // 'palette_repeat' *is[i] >> a; } - } - if (glvis_command->Camera(cam)) - { - goto comm_terminate; + if (glvis_command->PaletteRepeat(n)) + { + goto comm_terminate; + } } - } - else if (ident == "autopause") - { - string mode; + break; + case Command::Camera: + { + double cam[9], a; - *is[0] >> ws >> mode; + for (int i = 0; i < 9; i++) + { + *is[0] >> cam[i]; + } - // all processors sent the command - for (size_t i = 1; i < is.size(); i++) - { - *is[i] >> ws >> ident; // 'autopause' - *is[i] >> ws >> ident; - } + // all processors sent the command + for (size_t i = 1; i < is.size(); i++) + { + *is[i] >> ws >> ident; // 'camera' + for (int j = 0; j < 9; j++) + { + *is[i] >> a; + } + } - if (glvis_command->Autopause(mode.c_str())) + if (glvis_command->Camera(cam)) + { + goto comm_terminate; + } + } + break; + case Command::Autopause: { - goto comm_terminate; + string mode; + + *is[0] >> ws >> mode; + + // all processors sent the command + for (size_t i = 1; i < is.size(); i++) + { + *is[i] >> ws >> ident; // 'autopause' + *is[i] >> ws >> ident; + } + + if (glvis_command->Autopause(mode.c_str())) + { + goto comm_terminate; + } } - } - else - { - cout << "Stream: unknown command: " << ident << endl; + break; + default: + break; } } diff --git a/lib/threads.hpp b/lib/threads.hpp index 78c1649d..6d31d11b 100644 --- a/lib/threads.hpp +++ b/lib/threads.hpp @@ -163,6 +163,8 @@ class communication_thread // signal for thread cancellation std::atomic<bool> terminate_thread {false}; + static void init_commands(); + static void print_commands(); void execute(); public: From 3d658d8f3092313b66e60f4643180ff2e46a91e7 Mon Sep 17 00:00:00 2001 From: Jan Nikl <nikl1@llnl.gov> Date: Tue, 6 May 2025 02:16:04 -0700 Subject: [PATCH 19/56] Fixed confused fix_elem_orient and save_coloring in stream_reader. --- lib/stream_reader.cpp | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/lib/stream_reader.cpp b/lib/stream_reader.cpp index 9fa45538..d73785b3 100644 --- a/lib/stream_reader.cpp +++ b/lib/stream_reader.cpp @@ -23,13 +23,13 @@ int StreamReader::ReadStream( if (data_type == "fem2d_data") { data.type = DataState::FieldType::SCALAR; - data.SetMesh(new Mesh(is, 0, 0, data.save_coloring)); + data.SetMesh(new Mesh(is, 0, 0, data.fix_elem_orient)); data.sol.Load(is, data.mesh->GetNV()); } else if (data_type == "vfem2d_data" || data_type == "vfem2d_data_keys") { data.type = DataState::FieldType::VECTOR; - data.SetMesh(new Mesh(is, 0, 0, data.save_coloring)); + data.SetMesh(new Mesh(is, 0, 0, data.fix_elem_orient)); data.solu.Load(is, data.mesh->GetNV()); data.solv.Load(is, data.mesh->GetNV()); if (data_type == "vfem2d_data_keys") @@ -40,13 +40,13 @@ int StreamReader::ReadStream( else if (data_type == "fem3d_data") { data.type = DataState::FieldType::SCALAR; - data.SetMesh(new Mesh(is, 0, 0, data.save_coloring)); + data.SetMesh(new Mesh(is, 0, 0, data.fix_elem_orient)); data.sol.Load(is, data.mesh->GetNV()); } else if (data_type == "vfem3d_data" || data_type == "vfem3d_data_keys") { data.type = DataState::FieldType::VECTOR; - data.SetMesh(new Mesh(is, 0, 0, data.save_coloring)); + data.SetMesh(new Mesh(is, 0, 0, data.fix_elem_orient)); data.solu.Load(is, data.mesh->GetNV()); data.solv.Load(is, data.mesh->GetNV()); data.solw.Load(is, data.mesh->GetNV()); @@ -57,7 +57,7 @@ int StreamReader::ReadStream( } else if (data_type == "fem2d_gf_data" || data_type == "fem2d_gf_data_keys") { - data.SetMesh(new Mesh(is, 1, 0, data.save_coloring)); + data.SetMesh(new Mesh(is, 1, 0, data.fix_elem_orient)); data.SetGridFunction(new GridFunction(data.mesh.get(), is)); if (data_type == "fem2d_gf_data_keys") { @@ -66,7 +66,7 @@ int StreamReader::ReadStream( } else if (data_type == "vfem2d_gf_data" || data_type == "vfem2d_gf_data_keys") { - data.SetMesh(new Mesh(is, 1, 0, data.save_coloring)); + data.SetMesh(new Mesh(is, 1, 0, data.fix_elem_orient)); data.SetGridFunction(new GridFunction(data.mesh.get(), is)); if (data_type == "vfem2d_gf_data_keys") { @@ -75,7 +75,7 @@ int StreamReader::ReadStream( } else if (data_type == "fem3d_gf_data" || data_type == "fem3d_gf_data_keys") { - data.SetMesh(new Mesh(is, 1, 0, data.save_coloring)); + data.SetMesh(new Mesh(is, 1, 0, data.fix_elem_orient)); data.SetGridFunction(new GridFunction(data.mesh.get(), is)); if (data_type == "fem3d_gf_data_keys") { @@ -84,7 +84,7 @@ int StreamReader::ReadStream( } else if (data_type == "vfem3d_gf_data" || data_type == "vfem3d_gf_data_keys") { - data.SetMesh(new Mesh(is, 1, 0, data.save_coloring)); + data.SetMesh(new Mesh(is, 1, 0, data.fix_elem_orient)); data.SetGridFunction(new GridFunction(data.mesh.get(), is)); if (data_type == "vfem3d_gf_data_keys") { @@ -93,18 +93,18 @@ int StreamReader::ReadStream( } else if (data_type == "solution") { - data.SetMesh(new Mesh(is, 1, 0, data.save_coloring)); + data.SetMesh(new Mesh(is, 1, 0, data.fix_elem_orient)); data.SetGridFunction(new GridFunction(data.mesh.get(), is)); } else if (data_type == "quadrature") { - data.SetMesh(new Mesh(is, 1, 0, data.save_coloring)); + data.SetMesh(new Mesh(is, 1, 0, data.fix_elem_orient)); data.SetQuadFunction(new QuadratureFunction(data.mesh.get(), is)); data.SetQuadSolution(); } else if (data_type == "mesh") { - data.SetMesh(new Mesh(is, 1, 0, data.save_coloring)); + data.SetMesh(new Mesh(is, 1, 0, data.fix_elem_orient)); data.SetMeshSolution(); } else if (data_type == "raw_scalar_2d") @@ -200,11 +200,11 @@ int StreamReader::ReadStream( if (mesh_type == 1) { - data.mesh->FinalizeTriMesh(1, 0, data.save_coloring); + data.mesh->FinalizeTriMesh(1, 0, data.fix_elem_orient); } else if (mesh_type == 2) { - data.mesh->FinalizeQuadMesh(1, 0, data.save_coloring); + data.mesh->FinalizeQuadMesh(1, 0, data.fix_elem_orient); } else { @@ -256,7 +256,7 @@ int StreamReader::ReadStreams(const StreamCollection &input_streams) #ifdef GLVIS_DEBUG cout << " type " << data_type << " ... " << flush; #endif - mesh_array[p] = new Mesh(isock, 1, 0, data.save_coloring); + mesh_array[p] = new Mesh(isock, 1, 0, data.fix_elem_orient); if (!data.keep_attr) { // set element and boundary attributes to proc+1 From 25bccc965485f02134851f596adbbab2c90b3efb Mon Sep 17 00:00:00 2001 From: Jan Nikl <nikl1@llnl.gov> Date: Tue, 6 May 2025 03:27:03 -0700 Subject: [PATCH 20/56] Unified loading of solutions from stream. --- lib/threads.cpp | 110 +++++++++--------------------------------------- 1 file changed, 20 insertions(+), 90 deletions(-) diff --git a/lib/threads.cpp b/lib/threads.cpp index fdad95fe..4071adde 100644 --- a/lib/threads.cpp +++ b/lib/threads.cpp @@ -939,47 +939,18 @@ void communication_thread::execute() case Command::Quadrature: case Command::Parallel: { - bool fix_elem_orient = glvis_command->FixElementOrientations(); bool done = false; DataState tmp; + tmp.fix_elem_orient = glvis_command->FixElementOrientations(); + tmp.keep_attr = glvis_command->KeepAttrib(); + StreamReader reader(tmp); switch (cmd) { case Command::Mesh: - { - tmp.SetMesh(new Mesh(*is[0], 1, 0, fix_elem_orient)); - if (!(*is[0])) - { - done = true; - break; - } - tmp.SetGridFunction(NULL); - } - break; case Command::Solution: - { - tmp.SetMesh(new Mesh(*is[0], 1, 0, fix_elem_orient)); - if (!(*is[0])) - { - done = true; - break; - } - tmp.SetGridFunction(new GridFunction(tmp.mesh.get(), *is[0])); - if (!(*is[0])) - { - done = true; - break; - } - } - break; case Command::Quadrature: { - tmp.SetMesh(new Mesh(*is[0], 1, 0, fix_elem_orient)); - if (!(*is[0])) - { - done = true; - break; - } - tmp.SetQuadFunction(new QuadratureFunction(tmp.mesh.get(), *is[0])); + reader.ReadStream(*is[0], ident); if (!(*is[0])) { done = true; @@ -989,11 +960,7 @@ void communication_thread::execute() break; case Command::Parallel: { - std::vector<Mesh*> mesh_array; - std::vector<GridFunction*> gf_array; - std::vector<QuadratureFunction*> qf_array; - int proc, nproc, np = 0; - bool keep_attr = glvis_command->KeepAttrib(); + unsigned int proc, nproc, np = 0; do { istream &isock = *is[np]; @@ -1002,34 +969,17 @@ void communication_thread::execute() cout << "connection[" << np << "]: parallel " << nproc << ' ' << proc << endl; #endif - isock >> ident >> ws; - mesh_array.resize(nproc); - mesh_array[proc] = new Mesh(isock, 1, 0, fix_elem_orient); - if (!keep_attr) - { - // set element and boundary attributes to proc+1 - for (int i = 0; i < mesh_array[proc]->GetNE(); i++) - { - mesh_array[proc]->GetElement(i)->SetAttribute(proc+1); - } - for (int i = 0; i < mesh_array[proc]->GetNBE(); i++) - { - mesh_array[proc]->GetBdrElement(i)->SetAttribute(proc+1); - } - } - if (ident == "solution") + if (nproc != is.size()) { - gf_array.resize(nproc); - gf_array[proc] = new GridFunction(mesh_array[proc], isock); + cout << "Unexpected number of processors: " << nproc + << ", expected: " << is.size() << endl; + mfem_error(); } - else if (ident == "quadrature") + if (proc >= nproc) { - qf_array.resize(nproc); - qf_array[proc] = new QuadratureFunction(mesh_array[proc], isock); - } - else - { - cout << "Stream: unknown command: " << ident << endl; + cout << "Invalid processor rank: " << proc + << ", number of processors: " << nproc << endl; + mfem_error(); } np++; if (np == nproc) @@ -1037,34 +987,16 @@ void communication_thread::execute() break; } *is[np] >> ident >> ws; // "parallel" - } - while (1); - - tmp.SetMesh(new Mesh(mesh_array.data(), nproc)); - if (gf_array.size() > 0) - { - tmp.SetGridFunction(new GridFunction(tmp.mesh.get(), gf_array.data(), nproc)); - } - else if (qf_array.size() > 0) - { - tmp.SetQuadFunction(qf_array); - } - - for (int p = 0; p < nproc; p++) - { - if (gf_array.size() > 0) + if (ident != "parallel") { - delete gf_array[nproc-1-p]; + cout << "Expected keyword \"parallel\", got \"" << ident + << '"' << endl; + mfem_error(); } - if (qf_array.size() > 0) - { - delete qf_array[nproc-1-p]; - } - delete mesh_array[nproc-1-p]; } - gf_array.clear(); - qf_array.clear(); - mesh_array.clear(); + while (1); + + reader.ReadStreams(is); } break; default: @@ -1074,8 +1006,6 @@ void communication_thread::execute() // cout << "Stream: new solution" << endl; - tmp.ExtrudeMeshAndSolution(); - if (glvis_command->NewMeshAndSolution(std::move(tmp))) { goto comm_terminate; From 451066337af2b4cc1d7cbccc1c9cc09a67a98e3d Mon Sep 17 00:00:00 2001 From: Jan Nikl <nikl1@llnl.gov> Date: Tue, 6 May 2025 04:41:23 -0700 Subject: [PATCH 21/56] Changed StreamReader to commands list. --- lib/stream_reader.cpp | 426 ++++++++++++++++++++++++------------------ lib/stream_reader.hpp | 5 +- 2 files changed, 244 insertions(+), 187 deletions(-) diff --git a/lib/stream_reader.cpp b/lib/stream_reader.cpp index d73785b3..4a6416d5 100644 --- a/lib/stream_reader.cpp +++ b/lib/stream_reader.cpp @@ -11,222 +11,276 @@ #include "stream_reader.hpp" +#include <vector> +#include <algorithm> + using namespace std; using namespace mfem; -int StreamReader::ReadStream( - istream &is, const string &data_type) +enum class Command { - data.SetMesh(NULL); - data.keys.clear(); + Mesh, + Solution, + Quadrature, + Fem2D, + VFem2D, + VFem2D_keys, + Fem3D, + VFem3D, + VFem3D_keys, + Fem2D_GF, + Fem2D_GF_keys, + VFem2D_GF, + VFem2D_GF_keys, + Fem3D_GF, + Fem3D_GF_keys, + VFem3D_GF, + VFem3D_GF_keys, + RawScalar2D, + //---------- + Max +}; - if (data_type == "fem2d_data") - { - data.type = DataState::FieldType::SCALAR; - data.SetMesh(new Mesh(is, 0, 0, data.fix_elem_orient)); - data.sol.Load(is, data.mesh->GetNV()); - } - else if (data_type == "vfem2d_data" || data_type == "vfem2d_data_keys") - { - data.type = DataState::FieldType::VECTOR; - data.SetMesh(new Mesh(is, 0, 0, data.fix_elem_orient)); - data.solu.Load(is, data.mesh->GetNV()); - data.solv.Load(is, data.mesh->GetNV()); - if (data_type == "vfem2d_data_keys") - { - is >> data.keys; - } - } - else if (data_type == "fem3d_data") - { - data.type = DataState::FieldType::SCALAR; - data.SetMesh(new Mesh(is, 0, 0, data.fix_elem_orient)); - data.sol.Load(is, data.mesh->GetNV()); - } - else if (data_type == "vfem3d_data" || data_type == "vfem3d_data_keys") - { - data.type = DataState::FieldType::VECTOR; - data.SetMesh(new Mesh(is, 0, 0, data.fix_elem_orient)); - data.solu.Load(is, data.mesh->GetNV()); - data.solv.Load(is, data.mesh->GetNV()); - data.solw.Load(is, data.mesh->GetNV()); - if (data_type == "vfem3d_data_keys") - { - is >> data.keys; - } - } - else if (data_type == "fem2d_gf_data" || data_type == "fem2d_gf_data_keys") - { - data.SetMesh(new Mesh(is, 1, 0, data.fix_elem_orient)); - data.SetGridFunction(new GridFunction(data.mesh.get(), is)); - if (data_type == "fem2d_gf_data_keys") - { - is >> data.keys; - } - } - else if (data_type == "vfem2d_gf_data" || data_type == "vfem2d_gf_data_keys") - { - data.SetMesh(new Mesh(is, 1, 0, data.fix_elem_orient)); - data.SetGridFunction(new GridFunction(data.mesh.get(), is)); - if (data_type == "vfem2d_gf_data_keys") - { - is >> data.keys; - } - } - else if (data_type == "fem3d_gf_data" || data_type == "fem3d_gf_data_keys") - { - data.SetMesh(new Mesh(is, 1, 0, data.fix_elem_orient)); - data.SetGridFunction(new GridFunction(data.mesh.get(), is)); - if (data_type == "fem3d_gf_data_keys") - { - is >> data.keys; - } - } - else if (data_type == "vfem3d_gf_data" || data_type == "vfem3d_gf_data_keys") - { - data.SetMesh(new Mesh(is, 1, 0, data.fix_elem_orient)); - data.SetGridFunction(new GridFunction(data.mesh.get(), is)); - if (data_type == "vfem3d_gf_data_keys") - { - is >> data.keys; - } - } - else if (data_type == "solution") +struct CmdItem +{ + const char *keyword; + bool keys; + const char *params; + const char *desc; + + bool operator==(const string &key) const { return key == keyword; } +}; + +static vector<CmdItem> commands; + +StreamReader::StreamReader(DataState &data_) + : data(data_) +{ + if (commands.empty()) { - data.SetMesh(new Mesh(is, 1, 0, data.fix_elem_orient)); - data.SetGridFunction(new GridFunction(data.mesh.get(), is)); + InitCommands(); } - else if (data_type == "quadrature") +} + +void StreamReader::InitCommands() +{ + commands.resize((size_t)Command::Max); + + commands[(size_t)Command::Mesh] = {"mesh", false, "<mesh>", "Visualize the mesh."}; + commands[(size_t)Command::Solution] = {"solution", false, "<mesh> <solution>", "Visualize the solution."}; + commands[(size_t)Command::Quadrature] = {"quadrature", false, "<mesh> <quadrature>", "Visualize the quadrature."}; + commands[(size_t)Command::Fem2D] = {"fem2d_data", false, "<mesh> <data>", "Visualize the 2D scalar data."}; + commands[(size_t)Command::VFem2D] = {"vfem2d_data", false, "<mesh> <data_x> <data_y>", "Visualize the 2D vector data."}; + commands[(size_t)Command::VFem2D_keys] = {"vfem2d_data_keys", true, "<mesh> <data_x> <data_y> <keys>", "Visualize the 2D vector data and apply control keys."}; + commands[(size_t)Command::Fem3D] = {"fem3d_data", false, "<mesh> <data>", "Visualize the 3D scalar data."}; + commands[(size_t)Command::VFem3D] = {"vfem3d_data", false, "<mesh> <data_x> <data_y> <data_z>", "Visualize the 3D vector data."}; + commands[(size_t)Command::VFem3D_keys] = {"vfem3d_data_keys", true, "<mesh> <data_x> <data_y> <data_z> <keys>", "Visualize the 3D vector data and apply control keys."}; + commands[(size_t)Command::Fem2D_GF] = {"fem2d_gf_data", false, "<mesh> <solution>", "Visualize the 2D scalar grid function."}; + commands[(size_t)Command::Fem2D_GF_keys] = {"fem2d_gf_data_keys", true, "<mesh> <solution> <keys>", "Visualize the 2D scalar grid function and apply control keys."}; + commands[(size_t)Command::VFem2D_GF] = {"vfem2d_gf_data", false, "<mesh> <solution>", "Visualize the 2D vector grid function."}; + commands[(size_t)Command::VFem2D_GF_keys] = {"vfem2d_gf_data_keys", true, "<mesh> <solution> <keys>", "Visualize the 2D vector grid function and apply control keys."}; + commands[(size_t)Command::Fem3D_GF] = {"fem3d_gf_data", false, "<mesh> <solution>", "Visualize the 3D scalar grid function."}; + commands[(size_t)Command::Fem3D_GF_keys] = {"fem3d_gf_data_keys", true, "<mesh> <solution> <keys>", "Visualize the 3D scalar grid function and apply control keys."}; + commands[(size_t)Command::VFem3D_GF] = {"vfem3d_gf_data", false, "<mesh> <solution>", "Visualize the 3D vector grid function."}; + commands[(size_t)Command::VFem3D_GF_keys] = {"vfem3d_gf_data_keys", true, "<mesh> <solution> <keys>", "Visualize the 3D vector grid function and apply control keys."}; + commands[(size_t)Command::RawScalar2D] = {"raw_scalar_2d", false, "<data>", "Visualize the 2D scalar data (see stream_reader.cpp)."}; +} + +void StreamReader::PrintCommands() +{ + cout << "Available commands are:" << endl; + + for (const CmdItem &ci : commands) { - data.SetMesh(new Mesh(is, 1, 0, data.fix_elem_orient)); - data.SetQuadFunction(new QuadratureFunction(data.mesh.get(), is)); - data.SetQuadSolution(); + cout << "\t" << ci.keyword << " " << ci.params << " - " << ci.desc << endl; } - else if (data_type == "mesh") +} + +int StreamReader::ReadStream( + istream &is, const string &data_type) +{ + data.SetMesh(NULL); + data.keys.clear(); + + auto it = find(commands.begin(), commands.end(), data_type); + if (it == commands.end()) { - data.SetMesh(new Mesh(is, 1, 0, data.fix_elem_orient)); - data.SetMeshSolution(); + cerr << "Unknown data format " << data_type << endl; + PrintCommands(); + return 1; } - else if (data_type == "raw_scalar_2d") + + Command cmd = (Command)(it - commands.begin()); + switch (cmd) { - Array<Array<double> *> vertices; - Array<Array<int> *> elements; - Array<int> elem_types; - string ident; - int num_patches, num_vert, num_elem, n; - is >> ws >> ident; // 'patches' - is >> num_patches; - // cout << ident << ' ' << num_patches << endl; - vertices.SetSize(num_patches); - vertices = NULL; - elements.SetSize(num_patches); - elements = NULL; - elem_types.SetSize(num_patches); - elem_types = 0; - int tot_num_vert = 0; - int tot_num_elem = 0; - int mesh_type = 0; - for (int i = 0; i < num_patches; i++) + case Command::Fem2D: + data.type = DataState::FieldType::SCALAR; + data.SetMesh(new Mesh(is, 0, 0, data.fix_elem_orient)); + data.sol.Load(is, data.mesh->GetNV()); + break; + case Command::VFem2D: + case Command::VFem2D_keys: + data.type = DataState::FieldType::VECTOR; + data.SetMesh(new Mesh(is, 0, 0, data.fix_elem_orient)); + data.solu.Load(is, data.mesh->GetNV()); + data.solv.Load(is, data.mesh->GetNV()); + break; + case Command::Fem3D: + data.type = DataState::FieldType::SCALAR; + data.SetMesh(new Mesh(is, 0, 0, data.fix_elem_orient)); + data.sol.Load(is, data.mesh->GetNV()); + break; + case Command::VFem3D: + case Command::VFem3D_keys: + data.type = DataState::FieldType::VECTOR; + data.SetMesh(new Mesh(is, 0, 0, data.fix_elem_orient)); + data.solu.Load(is, data.mesh->GetNV()); + data.solv.Load(is, data.mesh->GetNV()); + data.solw.Load(is, data.mesh->GetNV()); + break; + case Command::Fem2D_GF: + case Command::Fem2D_GF_keys: + case Command::VFem2D_GF: + case Command::VFem2D_GF_keys: + case Command::Fem3D_GF: + case Command::Fem3D_GF_keys: + case Command::VFem3D_GF: + case Command::VFem3D_GF_keys: + case Command::Solution: + data.SetMesh(new Mesh(is, 1, 0, data.fix_elem_orient)); + data.SetGridFunction(new GridFunction(data.mesh.get(), is)); + break; + case Command::Quadrature: + data.SetMesh(new Mesh(is, 1, 0, data.fix_elem_orient)); + data.SetQuadFunction(new QuadratureFunction(data.mesh.get(), is)); + break; + case Command::Mesh: + data.SetMesh(new Mesh(is, 1, 0, data.fix_elem_orient)); + data.SetMeshSolution(); + break; + case Command::RawScalar2D: { - is >> ws >> ident; // 'vertices' - is >> num_vert; - // cout << '\n' << ident << ' ' << num_vert << endl; - // read vertices in the format: x y z nx ny nz - vertices[i] = new Array<double>(6*num_vert); - Array<double> &verts = *vertices[i]; - for (int j = 0; j < verts.Size(); j++) + Array<Array<double> *> vertices; + Array<Array<int> *> elements; + Array<int> elem_types; + string ident; + int num_patches, num_vert, num_elem, n; + is >> ws >> ident; // 'patches' + is >> num_patches; + // cout << ident << ' ' << num_patches << endl; + vertices.SetSize(num_patches); + vertices = NULL; + elements.SetSize(num_patches); + elements = NULL; + elem_types.SetSize(num_patches); + elem_types = 0; + int tot_num_vert = 0; + int tot_num_elem = 0; + int mesh_type = 0; + for (int i = 0; i < num_patches; i++) { - is >> verts[j]; + is >> ws >> ident; // 'vertices' + is >> num_vert; + // cout << '\n' << ident << ' ' << num_vert << endl; + // read vertices in the format: x y z nx ny nz + vertices[i] = new Array<double>(6*num_vert); + Array<double> &verts = *vertices[i]; + for (int j = 0; j < verts.Size(); j++) + { + is >> verts[j]; + } + + is >> ws >> ident; // 'triangles' or 'quads' + if (ident == "triangles") + { + n = 3, mesh_type |= 1; + } + else + { + n = 4, mesh_type |= 2; + } + elem_types[i] = n; + is >> num_elem; + // cout << ident << ' ' << num_elem << endl; + elements[i] = new Array<int>(n*num_elem); + Array<int> &elems = *elements[i]; + for (int j = 0; j < elems.Size(); j++) + { + is >> elems[j]; + elems[j] += tot_num_vert; + } + tot_num_vert += num_vert; + tot_num_elem += num_elem; } - is >> ws >> ident; // 'triangles' or 'quads' - if (ident == "triangles") + data.SetMesh(new Mesh(2, tot_num_vert, tot_num_elem, 0)); + data.sol.SetSize(tot_num_vert); + data.normals.SetSize(3*tot_num_vert); + + int v_off = 0; + for (int i = 0; i < num_patches; i++) { - n = 3, mesh_type |= 1; + Array<double> &verts = *vertices[i]; + num_vert = verts.Size()/6; + for (int j = 0; j < num_vert; j++) + { + data.mesh->AddVertex(&verts[6*j]); + data.sol(v_off) = verts[6*j+2]; + data.normals(3*v_off+0) = verts[6*j+3]; + data.normals(3*v_off+1) = verts[6*j+4]; + data.normals(3*v_off+2) = verts[6*j+5]; + v_off++; + } + + n = elem_types[i]; + Array<int> &elems = *elements[i]; + num_elem = elems.Size()/n; + // int attr = 1; + int attr = i + 1; + if (n == 3) + for (int j = 0; j < num_elem; j++) + { + data.mesh->AddTriangle(&elems[3*j], attr); + } + else + for (int j = 0; j < num_elem; j++) + { + data.mesh->AddQuad(&elems[4*j], attr); + } } - else + + if (mesh_type == 1) { - n = 4, mesh_type |= 2; + data.mesh->FinalizeTriMesh(1, 0, data.fix_elem_orient); } - elem_types[i] = n; - is >> num_elem; - // cout << ident << ' ' << num_elem << endl; - elements[i] = new Array<int>(n*num_elem); - Array<int> &elems = *elements[i]; - for (int j = 0; j < elems.Size(); j++) + else if (mesh_type == 2) { - is >> elems[j]; - elems[j] += tot_num_vert; + data.mesh->FinalizeQuadMesh(1, 0, data.fix_elem_orient); } - tot_num_vert += num_vert; - tot_num_elem += num_elem; - } - - data.SetMesh(new Mesh(2, tot_num_vert, tot_num_elem, 0)); - data.sol.SetSize(tot_num_vert); - data.normals.SetSize(3*tot_num_vert); - - int v_off = 0; - for (int i = 0; i < num_patches; i++) - { - Array<double> &verts = *vertices[i]; - num_vert = verts.Size()/6; - for (int j = 0; j < num_vert; j++) + else { - data.mesh->AddVertex(&verts[6*j]); - data.sol(v_off) = verts[6*j+2]; - data.normals(3*v_off+0) = verts[6*j+3]; - data.normals(3*v_off+1) = verts[6*j+4]; - data.normals(3*v_off+2) = verts[6*j+5]; - v_off++; + mfem_error("Input data contains mixture of triangles and quads!"); } - n = elem_types[i]; - Array<int> &elems = *elements[i]; - num_elem = elems.Size()/n; - // int attr = 1; - int attr = i + 1; - if (n == 3) - for (int j = 0; j < num_elem; j++) - { - data.mesh->AddTriangle(&elems[3*j], attr); - } - else - for (int j = 0; j < num_elem; j++) - { - data.mesh->AddQuad(&elems[4*j], attr); - } - } - - if (mesh_type == 1) - { - data.mesh->FinalizeTriMesh(1, 0, data.fix_elem_orient); - } - else if (mesh_type == 2) - { - data.mesh->FinalizeQuadMesh(1, 0, data.fix_elem_orient); - } - else - { - mfem_error("Input data contains mixture of triangles and quads!"); - } + data.mesh->GenerateBoundaryElements(); - data.mesh->GenerateBoundaryElements(); + for (int i = num_patches; i > 0; ) + { + i--; + delete elements[i]; + delete vertices[i]; + } - for (int i = num_patches; i > 0; ) - { - i--; - delete elements[i]; - delete vertices[i]; + data.type = DataState::FieldType::SCALAR; } - - data.type = DataState::FieldType::SCALAR; + break; + default: + break; } - else + + if (commands[(size_t)cmd].keys) { - cerr << "Unknown data format" << endl; - cerr << data_type << endl; - return 1; + is >> data.keys; } data.ExtrudeMeshAndSolution(); diff --git a/lib/stream_reader.hpp b/lib/stream_reader.hpp index eb9606f0..847c268d 100644 --- a/lib/stream_reader.hpp +++ b/lib/stream_reader.hpp @@ -25,8 +25,11 @@ class StreamReader { DataState &data; + static void InitCommands(); + static void PrintCommands(); + public: - StreamReader(DataState &data_) : data(data_) { } + StreamReader(DataState &data_); /// Read the content of an input stream (e.g. from socket/file) int ReadStream(std::istream &is, const std::string &data_type); From 2df9cc9a5b9e83285479bd2dfc1b60645dd55e38 Mon Sep 17 00:00:00 2001 From: Jan Nikl <nikl1@llnl.gov> Date: Tue, 6 May 2025 04:49:25 -0700 Subject: [PATCH 22/56] Fixed script handling of data coll meshes and improved code safety for commands enums. --- lib/script_controller.cpp | 3 ++- lib/stream_reader.cpp | 2 +- lib/threads.cpp | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/script_controller.cpp b/lib/script_controller.cpp index 56e60a76..0decf3d8 100644 --- a/lib/script_controller.cpp +++ b/lib/script_controller.cpp @@ -396,6 +396,7 @@ void ScriptController::ExecuteScriptCommand() case Command::ParSolution: case Command::Quadrature: case Command::ParQuadrature: + case Command::DataCollMesh: case Command::DataCollField: case Command::DataCollQuad: { @@ -804,7 +805,7 @@ void ScriptController::ExecuteScriptCommand() MyExpose(); } break; - default: + case Command::Max: //dummy break; } diff --git a/lib/stream_reader.cpp b/lib/stream_reader.cpp index 4a6416d5..0dc60f4a 100644 --- a/lib/stream_reader.cpp +++ b/lib/stream_reader.cpp @@ -274,7 +274,7 @@ int StreamReader::ReadStream( data.type = DataState::FieldType::SCALAR; } break; - default: + case Command::Max: //dummy break; } diff --git a/lib/threads.cpp b/lib/threads.cpp index 4071adde..8f9f32e4 100644 --- a/lib/threads.cpp +++ b/lib/threads.cpp @@ -1467,7 +1467,7 @@ void communication_thread::execute() } } break; - default: + case Command::Max: //dummy break; } } From 94add8b5c9e3f018986688fc4f23290a86412ac9 Mon Sep 17 00:00:00 2001 From: Jan Nikl <nikl1@llnl.gov> Date: Tue, 6 May 2025 05:18:57 -0700 Subject: [PATCH 23/56] Unified handling of solutions in streams. --- lib/stream_reader.cpp | 11 ++++ lib/stream_reader.hpp | 8 ++- lib/threads.cpp | 123 +++++++++++++++++++----------------------- 3 files changed, 74 insertions(+), 68 deletions(-) diff --git a/lib/stream_reader.cpp b/lib/stream_reader.cpp index 0dc60f4a..2b528c21 100644 --- a/lib/stream_reader.cpp +++ b/lib/stream_reader.cpp @@ -96,6 +96,17 @@ void StreamReader::PrintCommands() } } +bool StreamReader::SupportsDataType(const string &data_type) +{ + if (commands.empty()) + { + InitCommands(); + } + + auto it = find(commands.begin(), commands.end(), data_type); + return it != commands.end(); +} + int StreamReader::ReadStream( istream &is, const string &data_type) { diff --git a/lib/stream_reader.hpp b/lib/stream_reader.hpp index 847c268d..2fdecaab 100644 --- a/lib/stream_reader.hpp +++ b/lib/stream_reader.hpp @@ -26,11 +26,17 @@ class StreamReader DataState &data; static void InitCommands(); - static void PrintCommands(); public: + StreamReader(DataState &data_); + /// Prints available commands + static void PrintCommands(); + + /// Tests if the data type is supported + static bool SupportsDataType(const std::string &data_type); + /// Read the content of an input stream (e.g. from socket/file) int ReadStream(std::istream &is, const std::string &data_type); diff --git a/lib/threads.cpp b/lib/threads.cpp index 8f9f32e4..e27ab24a 100644 --- a/lib/threads.cpp +++ b/lib/threads.cpp @@ -799,9 +799,6 @@ GLVisCommand::~GLVisCommand() enum class Command { - Mesh, - Solution, - Quadrature, Parallel, Screenshot, Viewcenter, @@ -871,9 +868,6 @@ void communication_thread::init_commands() { commands.resize((size_t)Command::Max); - commands[(size_t)Command::Mesh] = {"mesh", "<mesh>", "Visualize the mesh."}; - commands[(size_t)Command::Solution] = {"solution", "<mesh> <solution>", "Visualize the solution."}; - commands[(size_t)Command::Quadrature] = {"quadrature", "<mesh> <quadrature>", "Visualize the quadrature."}; commands[(size_t)Command::Parallel] = {"parallel", "<num proc> <proc>", "Prefix for distributed mesh/solution/quadrature."}; commands[(size_t)Command::Screenshot] = {"screenshot", "<file>", "Take a screenshot, saving it to the file."}; commands[(size_t)Command::Viewcenter] = {"viewcenter", "<x> <y>", "Change the viewcenter."}; @@ -901,7 +895,7 @@ void communication_thread::init_commands() void communication_thread::print_commands() { - cout << "Available commands are:" << endl; + StreamReader::PrintCommands(); for (const CmdItem &ci : commands) { @@ -923,6 +917,27 @@ void communication_thread::execute() break; } + // new solution handled by StreamReader + if (StreamReader::SupportsDataType(ident)) + { + DataState tmp; + tmp.fix_elem_orient = glvis_command->FixElementOrientations(); + StreamReader reader(tmp); + reader.ReadStream(*is[0], ident); + if (!(*is[0])) + { + break; + } + + // cout << "Stream: new solution" << endl; + + if (glvis_command->NewMeshAndSolution(std::move(tmp))) + { + goto comm_terminate; + } + continue; + } + auto it = find(commands.begin(), commands.end(), ident); if (it == commands.end()) { @@ -934,75 +949,49 @@ void communication_thread::execute() const Command cmd = (Command)(it - commands.begin()); switch (cmd) { - case Command::Mesh: - case Command::Solution: - case Command::Quadrature: case Command::Parallel: { - bool done = false; - DataState tmp; - tmp.fix_elem_orient = glvis_command->FixElementOrientations(); - tmp.keep_attr = glvis_command->KeepAttrib(); - StreamReader reader(tmp); - switch (cmd) + unsigned int proc, nproc, np = 0; + do { - case Command::Mesh: - case Command::Solution: - case Command::Quadrature: + istream &isock = *is[np]; + isock >> nproc >> proc >> ws; +#ifdef GLVIS_DEBUG + cout << "connection[" << np << "]: parallel " << nproc << ' ' + << proc << endl; +#endif + if (nproc != is.size()) { - reader.ReadStream(*is[0], ident); - if (!(*is[0])) - { - done = true; - break; - } + cout << "Unexpected number of processors: " << nproc + << ", expected: " << is.size() << endl; + mfem_error(); } - break; - case Command::Parallel: + if (proc >= nproc) { - unsigned int proc, nproc, np = 0; - do - { - istream &isock = *is[np]; - isock >> nproc >> proc >> ws; -#ifdef GLVIS_DEBUG - cout << "connection[" << np << "]: parallel " << nproc << ' ' - << proc << endl; -#endif - if (nproc != is.size()) - { - cout << "Unexpected number of processors: " << nproc - << ", expected: " << is.size() << endl; - mfem_error(); - } - if (proc >= nproc) - { - cout << "Invalid processor rank: " << proc - << ", number of processors: " << nproc << endl; - mfem_error(); - } - np++; - if (np == nproc) - { - break; - } - *is[np] >> ident >> ws; // "parallel" - if (ident != "parallel") - { - cout << "Expected keyword \"parallel\", got \"" << ident - << '"' << endl; - mfem_error(); - } - } - while (1); - - reader.ReadStreams(is); + cout << "Invalid processor rank: " << proc + << ", number of processors: " << nproc << endl; + mfem_error(); } - break; - default: + np++; + if (np == nproc) + { break; + } + *is[np] >> ident >> ws; // "parallel" + if (ident != "parallel") + { + cout << "Expected keyword \"parallel\", got \"" << ident + << '"' << endl; + mfem_error(); + } } - if (done) { break; } + while (1); + + DataState tmp; + tmp.fix_elem_orient = glvis_command->FixElementOrientations(); + tmp.keep_attr = glvis_command->KeepAttrib(); + StreamReader reader(tmp); + reader.ReadStreams(is); // cout << "Stream: new solution" << endl; From b2ffa5a12488d4298bf487e9d504a1216a063ffc Mon Sep 17 00:00:00 2001 From: Jan Nikl <nikl1@llnl.gov> Date: Tue, 6 May 2025 05:45:13 -0700 Subject: [PATCH 24/56] Added handling of keys if bundled with data. --- lib/threads.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/lib/threads.cpp b/lib/threads.cpp index e27ab24a..f8abec59 100644 --- a/lib/threads.cpp +++ b/lib/threads.cpp @@ -935,6 +935,13 @@ void communication_thread::execute() { goto comm_terminate; } + if (!tmp.keys.empty()) + { + if (glvis_command->KeyCommands(tmp.keys.c_str())) + { + goto comm_terminate; + } + } continue; } From 9f9502d4c70b8966d24c1e9ac5c1308a0830f52e Mon Sep 17 00:00:00 2001 From: Jan Nikl <nikl1@llnl.gov> Date: Tue, 6 May 2025 07:12:53 -0700 Subject: [PATCH 25/56] Made command lists thread-safe. --- lib/script_controller.cpp | 111 +++++++++++++++++++------------------- lib/script_controller.hpp | 3 +- lib/stream_reader.cpp | 48 ++++++++--------- lib/stream_reader.hpp | 4 +- lib/threads.cpp | 80 ++++++++++++++------------- lib/threads.hpp | 1 - 6 files changed, 120 insertions(+), 127 deletions(-) diff --git a/lib/script_controller.cpp b/lib/script_controller.cpp index 0decf3d8..2a238fd5 100644 --- a/lib/script_controller.cpp +++ b/lib/script_controller.cpp @@ -15,7 +15,7 @@ #include "stream_reader.hpp" #include "visual.hpp" -#include <vector> +#include <array> #include <algorithm> using namespace std; @@ -60,16 +60,63 @@ enum class Command Max }; -struct CmdItem +class ScriptCommands { - const char *keyword; - const char *params; - const char *desc; + struct CmdItem + { + const char *keyword; + const char *params; + const char *desc; + + bool operator==(const string &key) const { return key == keyword; } + }; + array<CmdItem,(size_t)Command::Max> commands; - bool operator==(const string &key) const { return key == keyword; } +public: + ScriptCommands(); + + array<CmdItem,(size_t)Command::Max>::const_iterator begin() const { return commands.begin(); } + array<CmdItem,(size_t)Command::Max>::const_iterator end() const { return commands.end(); } + const CmdItem& operator[](Command cmd) const { return commands[(size_t)cmd]; } }; +static const ScriptCommands commands; -static vector<CmdItem> commands; +ScriptCommands::ScriptCommands() +{ + commands[(size_t)Command::Mesh] = {"mesh", "<file>", "Visualize the mesh."}; + commands[(size_t)Command::Solution] = {"solution", "<mesh> <solution>", "Visualize the solution."}; + commands[(size_t)Command::ParSolution] = {"psolution", "<np> <mesh prefix> <keep attributes> <solution prefix>", "Visualize the distributed solution."}; + commands[(size_t)Command::Quadrature] = {"quadrature", "<mesh> <quadrature>", "Visualize the quadrature."}; + commands[(size_t)Command::ParQuadrature] = {"pquadrature", "<np> <mesh prefix> <keep attributes> <quadrature prefix>", "Visualize the distributed quadrature."}; + commands[(size_t)Command::DataCollMesh] = {"data_coll_mesh", "<type> <data coll>", "Visualize the mesh from data collection."}; + commands[(size_t)Command::DataCollField] = {"data_coll_field", "<type> <data coll> <field>", "Visualize the field from data collection."}; + commands[(size_t)Command::DataCollQuad] = {"data_coll_quad", "<type> <data coll> <quad>", "Visualize the Q-field from data collection."}; + commands[(size_t)Command::DataCollCycle] = {"data_coll_cycle", "<cycle>", "Preset the cycle of the data collection."}; + commands[(size_t)Command::DataCollProto] = {"data_coll_protocol", "<protocol>", "Preset the protocol of the data collection."}; + commands[(size_t)Command::Screenshot] = {"screenshot", "<file>", "Take a screenshot, saving it to the file."}; + commands[(size_t)Command::Viewcenter] = {"viewcenter", "<x> <y>", "Change the viewcenter."}; + commands[(size_t)Command::Perspective] = {"perspective", "<on/off>", "Turn on or off perspective projection."}; + commands[(size_t)Command::Light] = {"light", "<on/off>", "Turn on or off light."}; + commands[(size_t)Command::View] = {"view", "<theta> <phi>", "Change the solid angle of view."}; + commands[(size_t)Command::Zoom] = {"zoom", "<zoom>", "Change the zoom factor."}; + commands[(size_t)Command::Shading] = {"shading", "<flat/smooth/cool>", "Change the shading algorithm."}; + commands[(size_t)Command::Subdivisions] = {"subdivisions", "<times> <dummy>", "Change the refinement level."}; + commands[(size_t)Command::Valuerange] = {"valuerange", "<min> <max>", "Change the value range."}; + commands[(size_t)Command::Autoscale] = {"autoscale", "<off/on/value/mesh>", "Change the autoscale algorithm."}; + commands[(size_t)Command::Levellines] = {"levellines", "<min> <max> <num>", "Set the level lines."}; + commands[(size_t)Command::AxisNumberFormat] = {"axis_numberformat", "'<format>'", "Set the axis number format."}; + commands[(size_t)Command::ColorbarNumberFormat] = {"colorbar_numberformat", "'<format>'", "Set the colorbar number format."}; + commands[(size_t)Command::Window] = {"window", "<x> <y> <w> <h>", "Set the position and size of the window."}; + commands[(size_t)Command::Keys] = {"keys", "<keys>", "Send the control key sequence."}; + commands[(size_t)Command::Palette] = {"palette", "<index>", "Set the palette index."}; + commands[(size_t)Command::PaletteRepeat] = {"palette_repeat", "<times>", "Set the repetition of the palette."}; + commands[(size_t)Command::ToggleAttributes] = {"toggle_attributes", "<1/0> [[<1/0>] ...];", "Toggle visibility of the attributes."}; + commands[(size_t)Command::Rotmat] = {"rotmat", "<[0,0]> <[1,0]> ... <[3,3]>", "Set the rotation matrix."}; + commands[(size_t)Command::Camera] = {"camera", "<cam[0]> ... <cam[2]> <dir[0]> ... <dir[2]> <up[0]> ... <up[2]>", "Set the camera position, direction and upward vector."}; + commands[(size_t)Command::Scale] = {"scale", "<scale>", "Set the scaling factor."}; + commands[(size_t)Command::Translate] = {"translate", "<x> <y> <z>", "Set the translation coordinates."}; + commands[(size_t)Command::PlotCaption] = {"plot_caption", "'<caption>'", "Set the plot caption."}; +} int ScriptController::ScriptReadSolution(istream &scr, DataState &state) { @@ -290,50 +337,11 @@ int ScriptController::ScriptReadDataColl(istream &scr, DataState &state, return err_read; } -void ScriptController::InitCommands() -{ - commands.resize((size_t)Command::Max); - - commands[(size_t)Command::Mesh] = {"mesh", "<file>", "Visualize the mesh."}; - commands[(size_t)Command::Solution] = {"solution", "<mesh> <solution>", "Visualize the solution."}; - commands[(size_t)Command::ParSolution] = {"psolution", "<np> <mesh prefix> <keep attributes> <solution prefix>", "Visualize the distributed solution."}; - commands[(size_t)Command::Quadrature] = {"quadrature", "<mesh> <quadrature>", "Visualize the quadrature."}; - commands[(size_t)Command::ParQuadrature] = {"pquadrature", "<np> <mesh prefix> <keep attributes> <quadrature prefix>", "Visualize the distributed quadrature."}; - commands[(size_t)Command::DataCollMesh] = {"data_coll_mesh", "<type> <data coll>", "Visualize the mesh from data collection."}; - commands[(size_t)Command::DataCollField] = {"data_coll_field", "<type> <data coll> <field>", "Visualize the field from data collection."}; - commands[(size_t)Command::DataCollQuad] = {"data_coll_quad", "<type> <data coll> <quad>", "Visualize the Q-field from data collection."}; - commands[(size_t)Command::DataCollCycle] = {"data_coll_cycle", "<cycle>", "Preset the cycle of the data collection."}; - commands[(size_t)Command::DataCollProto] = {"data_coll_protocol", "<protocol>", "Preset the protocol of the data collection."}; - commands[(size_t)Command::Screenshot] = {"screenshot", "<file>", "Take a screenshot, saving it to the file."}; - commands[(size_t)Command::Viewcenter] = {"viewcenter", "<x> <y>", "Change the viewcenter."}; - commands[(size_t)Command::Perspective] = {"perspective", "<on/off>", "Turn on or off perspective projection."}; - commands[(size_t)Command::Light] = {"light", "<on/off>", "Turn on or off light."}; - commands[(size_t)Command::View] = {"view", "<theta> <phi>", "Change the solid angle of view."}; - commands[(size_t)Command::Zoom] = {"zoom", "<zoom>", "Change the zoom factor."}; - commands[(size_t)Command::Shading] = {"shading", "<flat/smooth/cool>", "Change the shading algorithm."}; - commands[(size_t)Command::Subdivisions] = {"subdivisions", "<times> <dummy>", "Change the refinement level."}; - commands[(size_t)Command::Valuerange] = {"valuerange", "<min> <max>", "Change the value range."}; - commands[(size_t)Command::Autoscale] = {"autoscale", "<off/on/value/mesh>", "Change the autoscale algorithm."}; - commands[(size_t)Command::Levellines] = {"levellines", "<min> <max> <num>", "Set the level lines."}; - commands[(size_t)Command::AxisNumberFormat] = {"axis_numberformat", "'<format>'", "Set the axis number format."}; - commands[(size_t)Command::ColorbarNumberFormat] = {"colorbar_numberformat", "'<format>'", "Set the colorbar number format."}; - commands[(size_t)Command::Window] = {"window", "<x> <y> <w> <h>", "Set the position and size of the window."}; - commands[(size_t)Command::Keys] = {"keys", "<keys>", "Send the control key sequence."}; - commands[(size_t)Command::Palette] = {"palette", "<index>", "Set the palette index."}; - commands[(size_t)Command::PaletteRepeat] = {"palette_repeat", "<times>", "Set the repetition of the palette."}; - commands[(size_t)Command::ToggleAttributes] = {"toggle_attributes", "<1/0> [[<1/0>] ...];", "Toggle visibility of the attributes."}; - commands[(size_t)Command::Rotmat] = {"rotmat", "<[0,0]> <[1,0]> ... <[3,3]>", "Set the rotation matrix."}; - commands[(size_t)Command::Camera] = {"camera", "<cam[0]> ... <cam[2]> <dir[0]> ... <dir[2]> <up[0]> ... <up[2]>", "Set the camera position, direction and upward vector."}; - commands[(size_t)Command::Scale] = {"scale", "<scale>", "Set the scaling factor."}; - commands[(size_t)Command::Translate] = {"translate", "<x> <y> <z>", "Set the translation coordinates."}; - commands[(size_t)Command::PlotCaption] = {"plot_caption", "'<caption>'", "Set the plot caption."}; -} - void ScriptController::PrintCommands() { cout << "Available commands are:" << endl; - for (const CmdItem &ci : commands) + for (const auto &ci : commands) { cout << "\t" << ci.keyword << " " << ci.params << " - " << ci.desc << endl; } @@ -838,15 +846,6 @@ void ScriptController::ScriptControl() } } -ScriptController::ScriptController(Window &win_) - : win(win_) -{ - if (commands.empty()) - { - InitCommands(); - } -} - void ScriptController::PlayScript(istream &scr) { string word; diff --git a/lib/script_controller.hpp b/lib/script_controller.hpp index 44304ab1..d24f506d 100644 --- a/lib/script_controller.hpp +++ b/lib/script_controller.hpp @@ -45,12 +45,11 @@ class ScriptController static void ScriptIdleFunc(); static void ScriptControl(); - static void InitCommands(); static void PrintCommands(); void ExecuteScriptCommand(); public: - ScriptController(Window &win_); + ScriptController(Window &win_) : win(win_) { } void PlayScript(std::istream &scr); }; diff --git a/lib/stream_reader.cpp b/lib/stream_reader.cpp index 2b528c21..f49c5e06 100644 --- a/lib/stream_reader.cpp +++ b/lib/stream_reader.cpp @@ -11,7 +11,7 @@ #include "stream_reader.hpp" -#include <vector> +#include <array> #include <algorithm> using namespace std; @@ -41,31 +41,30 @@ enum class Command Max }; -struct CmdItem +class StreamCommands { - const char *keyword; - bool keys; - const char *params; - const char *desc; + struct CmdItem + { + const char *keyword; + bool keys; + const char *params; + const char *desc; - bool operator==(const string &key) const { return key == keyword; } -}; + bool operator==(const string &key) const { return key == keyword; } + }; + array<CmdItem,(size_t)Command::Max> commands; -static vector<CmdItem> commands; +public: + StreamCommands(); -StreamReader::StreamReader(DataState &data_) - : data(data_) -{ - if (commands.empty()) - { - InitCommands(); - } -} + array<CmdItem,(size_t)Command::Max>::const_iterator begin() const { return commands.begin(); } + array<CmdItem,(size_t)Command::Max>::const_iterator end() const { return commands.end(); } + const CmdItem& operator[](Command cmd) const { return commands[(size_t)cmd]; } +}; +static const StreamCommands commands; -void StreamReader::InitCommands() +StreamCommands::StreamCommands() { - commands.resize((size_t)Command::Max); - commands[(size_t)Command::Mesh] = {"mesh", false, "<mesh>", "Visualize the mesh."}; commands[(size_t)Command::Solution] = {"solution", false, "<mesh> <solution>", "Visualize the solution."}; commands[(size_t)Command::Quadrature] = {"quadrature", false, "<mesh> <quadrature>", "Visualize the quadrature."}; @@ -90,7 +89,7 @@ void StreamReader::PrintCommands() { cout << "Available commands are:" << endl; - for (const CmdItem &ci : commands) + for (const auto &ci : commands) { cout << "\t" << ci.keyword << " " << ci.params << " - " << ci.desc << endl; } @@ -98,11 +97,6 @@ void StreamReader::PrintCommands() bool StreamReader::SupportsDataType(const string &data_type) { - if (commands.empty()) - { - InitCommands(); - } - auto it = find(commands.begin(), commands.end(), data_type); return it != commands.end(); } @@ -289,7 +283,7 @@ int StreamReader::ReadStream( break; } - if (commands[(size_t)cmd].keys) + if (commands[cmd].keys) { is >> data.keys; } diff --git a/lib/stream_reader.hpp b/lib/stream_reader.hpp index 2fdecaab..5801d362 100644 --- a/lib/stream_reader.hpp +++ b/lib/stream_reader.hpp @@ -25,11 +25,9 @@ class StreamReader { DataState &data; - static void InitCommands(); - public: - StreamReader(DataState &data_); + StreamReader(DataState &data_): data(data_) { } /// Prints available commands static void PrintCommands(); diff --git a/lib/threads.cpp b/lib/threads.cpp index f8abec59..94976d2c 100644 --- a/lib/threads.cpp +++ b/lib/threads.cpp @@ -11,7 +11,8 @@ #include "visual.hpp" #include "palettes.hpp" -#include <vector> + +#include <array> #include <algorithm> using namespace std; @@ -826,48 +827,29 @@ enum class Command Max }; -struct CmdItem +class ThreadCommands { - const char *keyword; - const char *params; - const char *desc; - - bool operator==(const string &key) const { return key == keyword; } -}; - -static vector<CmdItem> commands; - -communication_thread::communication_thread(StreamCollection _is, - GLVisCommand* cmd) - : is(std::move(_is)), glvis_command(cmd) -{ - new_m = NULL; - new_g = NULL; - - if (commands.empty()) + struct CmdItem { - init_commands(); - } + const char *keyword; + const char *params; + const char *desc; - if (is.size() > 0) - { - tid = std::thread(&communication_thread::execute, this); - } -} + bool operator==(const string &key) const { return key == keyword; } + }; + array<CmdItem,(size_t)Command::Max> commands; -communication_thread::~communication_thread() -{ - if (is.size() > 0) - { - terminate_thread = true; - tid.join(); - } -} +public: + ThreadCommands(); -void communication_thread::init_commands() -{ - commands.resize((size_t)Command::Max); + array<CmdItem,(size_t)Command::Max>::const_iterator begin() const { return commands.begin(); } + array<CmdItem,(size_t)Command::Max>::const_iterator end() const { return commands.end(); } + const CmdItem& operator[](Command cmd) const { return commands[(size_t)cmd]; } +}; +static const ThreadCommands commands; +ThreadCommands::ThreadCommands() +{ commands[(size_t)Command::Parallel] = {"parallel", "<num proc> <proc>", "Prefix for distributed mesh/solution/quadrature."}; commands[(size_t)Command::Screenshot] = {"screenshot", "<file>", "Take a screenshot, saving it to the file."}; commands[(size_t)Command::Viewcenter] = {"viewcenter", "<x> <y>", "Change the viewcenter."}; @@ -893,11 +875,33 @@ void communication_thread::init_commands() commands[(size_t)Command::Autopause] = {"autopause", "<0/off/1/on>", "Turns off or on autopause."}; } +communication_thread::communication_thread(StreamCollection _is, + GLVisCommand* cmd) + : is(std::move(_is)), glvis_command(cmd) +{ + new_m = NULL; + new_g = NULL; + + if (is.size() > 0) + { + tid = std::thread(&communication_thread::execute, this); + } +} + +communication_thread::~communication_thread() +{ + if (is.size() > 0) + { + terminate_thread = true; + tid.join(); + } +} + void communication_thread::print_commands() { StreamReader::PrintCommands(); - for (const CmdItem &ci : commands) + for (const auto &ci : commands) { cout << "\t" << ci.keyword << " " << ci.params << " - " << ci.desc << endl; } diff --git a/lib/threads.hpp b/lib/threads.hpp index 6d31d11b..c63e3e82 100644 --- a/lib/threads.hpp +++ b/lib/threads.hpp @@ -163,7 +163,6 @@ class communication_thread // signal for thread cancellation std::atomic<bool> terminate_thread {false}; - static void init_commands(); static void print_commands(); void execute(); From 6c568f3253c9976021e90f9355f5a50cc95a0f46 Mon Sep 17 00:00:00 2001 From: Jan Nikl <nikl1@llnl.gov> Date: Tue, 6 May 2025 07:26:50 -0700 Subject: [PATCH 26/56] Cosmetic change of command lists. --- lib/script_controller.cpp | 4 ++-- lib/stream_reader.cpp | 4 ++-- lib/threads.cpp | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/script_controller.cpp b/lib/script_controller.cpp index 2a238fd5..9245701f 100644 --- a/lib/script_controller.cpp +++ b/lib/script_controller.cpp @@ -75,8 +75,8 @@ class ScriptCommands public: ScriptCommands(); - array<CmdItem,(size_t)Command::Max>::const_iterator begin() const { return commands.begin(); } - array<CmdItem,(size_t)Command::Max>::const_iterator end() const { return commands.end(); } + decltype(commands)::const_iterator begin() const { return commands.begin(); } + decltype(commands)::const_iterator end() const { return commands.end(); } const CmdItem& operator[](Command cmd) const { return commands[(size_t)cmd]; } }; static const ScriptCommands commands; diff --git a/lib/stream_reader.cpp b/lib/stream_reader.cpp index f49c5e06..5b65cea5 100644 --- a/lib/stream_reader.cpp +++ b/lib/stream_reader.cpp @@ -57,8 +57,8 @@ class StreamCommands public: StreamCommands(); - array<CmdItem,(size_t)Command::Max>::const_iterator begin() const { return commands.begin(); } - array<CmdItem,(size_t)Command::Max>::const_iterator end() const { return commands.end(); } + decltype(commands)::const_iterator begin() const { return commands.begin(); } + decltype(commands)::const_iterator end() const { return commands.end(); } const CmdItem& operator[](Command cmd) const { return commands[(size_t)cmd]; } }; static const StreamCommands commands; diff --git a/lib/threads.cpp b/lib/threads.cpp index 94976d2c..52064a31 100644 --- a/lib/threads.cpp +++ b/lib/threads.cpp @@ -842,8 +842,8 @@ class ThreadCommands public: ThreadCommands(); - array<CmdItem,(size_t)Command::Max>::const_iterator begin() const { return commands.begin(); } - array<CmdItem,(size_t)Command::Max>::const_iterator end() const { return commands.end(); } + decltype(commands)::const_iterator begin() const { return commands.begin(); } + decltype(commands)::const_iterator end() const { return commands.end(); } const CmdItem& operator[](Command cmd) const { return commands[(size_t)cmd]; } }; static const ThreadCommands commands; From b880ffcdac6f3b8f89dff9bfb8fbd1f82038b270 Mon Sep 17 00:00:00 2001 From: Jan Nikl <nikl1@llnl.gov> Date: Wed, 7 May 2025 09:45:52 -0700 Subject: [PATCH 27/56] Minor debugging log change. --- lib/stream_reader.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/stream_reader.cpp b/lib/stream_reader.cpp index 5b65cea5..b8547263 100644 --- a/lib/stream_reader.cpp +++ b/lib/stream_reader.cpp @@ -307,7 +307,7 @@ int StreamReader::ReadStreams(const StreamCollection &input_streams) for (int p = 0; p < nproc; p++) { #ifdef GLVIS_DEBUG - cout << "connection[" << p << "]: reading initial data ... " << flush; + cout << "connection[" << p << "]: reading data ... " << flush; #endif istream &isock = *input_streams[p]; // assuming the "parallel nproc p" part of the stream has been read From ced295ed9d06592e6346e80ebc6c72fc155b56ce Mon Sep 17 00:00:00 2001 From: Jan Nikl <nikl1@llnl.gov> Date: Wed, 7 May 2025 10:45:15 -0700 Subject: [PATCH 28/56] Changed init_nodes to unique_ptr. --- lib/script_controller.cpp | 4 +--- lib/script_controller.hpp | 3 ++- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/lib/script_controller.cpp b/lib/script_controller.cpp index 9245701f..a9e30cfc 100644 --- a/lib/script_controller.cpp +++ b/lib/script_controller.cpp @@ -261,7 +261,7 @@ int ScriptController::ScriptReadDisplMesh(istream &scr, DataState &state) Mesh* const m = meshstate.mesh.get(); if (init_nodes == NULL) { - init_nodes = new Vector; + init_nodes.reset(new Vector); meshstate.mesh->GetNodes(*init_nodes); state.SetMesh(NULL); state.SetGridFunction(NULL); @@ -976,8 +976,6 @@ void ScriptController::PlayScript(istream &scr) SDLMainLoop(); worker_thread.join(); - delete init_nodes; init_nodes = NULL; - cout << "Script: min_val = " << scr_min_val << ", max_val = " << scr_max_val << endl; diff --git a/lib/script_controller.hpp b/lib/script_controller.hpp index d24f506d..2f227e82 100644 --- a/lib/script_controller.hpp +++ b/lib/script_controller.hpp @@ -13,6 +13,7 @@ #define GLVIS_SCRIPT_CONTROLLER_HPP #include <iostream> +#include <memory> #include "window.hpp" @@ -29,7 +30,7 @@ class ScriptController istream *script = NULL; int scr_running = 0; int scr_level = 0; - mfem::Vector *init_nodes = NULL; + std::unique_ptr<mfem::Vector> init_nodes; double scr_min_val, scr_max_val; static int ScriptReadSolution(istream &scr, DataState &state); From 8687102153147a231f25c8127e0d041b96446109 Mon Sep 17 00:00:00 2001 From: Jan Nikl <nikl1@llnl.gov> Date: Wed, 7 May 2025 10:52:49 -0700 Subject: [PATCH 29/56] Fixed thread-locality of the script controller. --- glvis.cpp | 3 +-- lib/script_controller.cpp | 54 +++++++++++++++++++-------------------- lib/script_controller.hpp | 6 ++--- 3 files changed, 30 insertions(+), 33 deletions(-) diff --git a/glvis.cpp b/glvis.cpp index 675ae403..7ef13259 100644 --- a/glvis.cpp +++ b/glvis.cpp @@ -619,8 +619,7 @@ int main (int argc, char *argv[]) } cout << "Running script from file: " << script_file << endl; cout << "You may need to press <space> to execute the script steps." << endl; - ScriptController script(win); - script.PlayScript(scr); + ScriptController::PlayScript(std::move(win), scr); return 0; } diff --git a/lib/script_controller.cpp b/lib/script_controller.cpp index a9e30cfc..081590d1 100644 --- a/lib/script_controller.cpp +++ b/lib/script_controller.cpp @@ -846,13 +846,15 @@ void ScriptController::ScriptControl() } } -void ScriptController::PlayScript(istream &scr) +void ScriptController::PlayScript(Window win, istream &scr) { string word; bool done = false; - scr_min_val = numeric_limits<double>::infinity(); - scr_max_val = -scr_min_val; + ScriptController script(std::move(win)); + + script.scr_min_val = numeric_limits<double>::infinity(); + script.scr_max_val = -script.scr_min_val; // read initializing commands while (!done) @@ -882,65 +884,66 @@ void ScriptController::PlayScript(istream &scr) switch (cmd) { case Command::Window: - scr >> win.window_x >> win.window_y >> win.window_w >> win.window_h; + scr >> script.win.window_x >> script.win.window_y >> script.win.window_w >> + script.win.window_h; break; case Command::DataCollCycle: - scr >> dc_cycle; + scr >> script.dc_cycle; break; case Command::DataCollProto: - scr >> dc_protocol; + scr >> script.dc_protocol; break; case Command::Solution: - if (ScriptReadSolution(scr, win.data_state)) + if (ScriptReadSolution(scr, script.win.data_state)) { return; } done = true; // start the visualization break; case Command::Quadrature: - if (ScriptReadQuadrature(scr, win.data_state)) + if (ScriptReadQuadrature(scr, script.win.data_state)) { return; } done = true; // start the visualization break; case Command::ParSolution: - if (ScriptReadParSolution(scr, win.data_state)) + if (ScriptReadParSolution(scr, script.win.data_state)) { return; } done = true; // start the visualization break; case Command::ParQuadrature: - if (ScriptReadParQuadrature(scr, win.data_state)) + if (ScriptReadParQuadrature(scr, script.win.data_state)) { return; } done = true; // start the visualization break; case Command::Mesh: - if (ScriptReadDisplMesh(scr, win.data_state)) + if (script.ScriptReadDisplMesh(scr, script.win.data_state)) { return; } - done = win.data_state.mesh != nullptr; + done = script.win.data_state.mesh != nullptr; break; case Command::DataCollMesh: - if (ScriptReadDataColl(scr, win.data_state)) + if (script.ScriptReadDataColl(scr, script.win.data_state)) { return; } done = true; // start the visualization break; case Command::DataCollField: - if (ScriptReadDataColl(scr, win.data_state, false)) + if (script.ScriptReadDataColl(scr, script.win.data_state, false)) { return; } done = true; // start the visualization break; case Command::DataCollQuad: - if (ScriptReadDataColl(scr, win.data_state, false, true)) + if (script.ScriptReadDataColl(scr, script.win.data_state, false, true)) { return; } @@ -951,10 +954,9 @@ void ScriptController::PlayScript(istream &scr) } } - scr_level = scr_running = 0; - script = &scr; - script_ctrl = this; - win.data_state.keys.clear(); + script.scr_level = script.scr_running = 0; + script.script = &scr; + script.win.data_state.keys.clear(); // Make sure the singleton object returned by GetMainThread() is // initialized from the main thread. @@ -962,22 +964,18 @@ void ScriptController::PlayScript(istream &scr) std::thread worker_thread { - [&](Window local_win) + [&](ScriptController local_script) { - if (local_win.GLVisInitVis({})) + script_ctrl = &local_script; + if (local_script.win.GLVisInitVis({})) { GetAppWindow()->setOnKeyDown(SDLK_SPACE, ScriptControl); - local_win.GLVisStartVis(); + local_script.win.GLVisStartVis(); } }, - std::move(win) + std::move(script) }; SDLMainLoop(); worker_thread.join(); - - cout << "Script: min_val = " << scr_min_val - << ", max_val = " << scr_max_val << endl; - - script = NULL; } diff --git a/lib/script_controller.hpp b/lib/script_controller.hpp index 2f227e82..99b173a5 100644 --- a/lib/script_controller.hpp +++ b/lib/script_controller.hpp @@ -22,7 +22,7 @@ extern const char *string_default; class ScriptController { - Window &win; + Window win; string dc_protocol = string_default; int dc_cycle = 0; @@ -50,9 +50,9 @@ class ScriptController void ExecuteScriptCommand(); public: - ScriptController(Window &win_) : win(win_) { } + ScriptController(Window win_) : win(std::move(win_)) { } - void PlayScript(std::istream &scr); + static void PlayScript(Window win, std::istream &scr); }; #endif // GLVIS_SCRIPT_CONTROLLER_HPP From eebcea9e18b52553454970993c7802dfc25efaac Mon Sep 17 00:00:00 2001 From: Jan Nikl <nikl1@llnl.gov> Date: Thu, 8 May 2025 13:21:21 -0700 Subject: [PATCH 30/56] Cosmetic change of commands initialization. --- lib/script_controller.cpp | 67 ++++++++++++++++++++------------------- lib/stream_reader.cpp | 37 ++++++++++----------- lib/threads.cpp | 47 +++++++++++++-------------- 3 files changed, 77 insertions(+), 74 deletions(-) diff --git a/lib/script_controller.cpp b/lib/script_controller.cpp index 081590d1..d89a228d 100644 --- a/lib/script_controller.cpp +++ b/lib/script_controller.cpp @@ -77,45 +77,46 @@ class ScriptCommands decltype(commands)::const_iterator begin() const { return commands.begin(); } decltype(commands)::const_iterator end() const { return commands.end(); } + CmdItem& operator[](Command cmd) { return commands[(size_t)cmd]; } const CmdItem& operator[](Command cmd) const { return commands[(size_t)cmd]; } }; static const ScriptCommands commands; ScriptCommands::ScriptCommands() { - commands[(size_t)Command::Mesh] = {"mesh", "<file>", "Visualize the mesh."}; - commands[(size_t)Command::Solution] = {"solution", "<mesh> <solution>", "Visualize the solution."}; - commands[(size_t)Command::ParSolution] = {"psolution", "<np> <mesh prefix> <keep attributes> <solution prefix>", "Visualize the distributed solution."}; - commands[(size_t)Command::Quadrature] = {"quadrature", "<mesh> <quadrature>", "Visualize the quadrature."}; - commands[(size_t)Command::ParQuadrature] = {"pquadrature", "<np> <mesh prefix> <keep attributes> <quadrature prefix>", "Visualize the distributed quadrature."}; - commands[(size_t)Command::DataCollMesh] = {"data_coll_mesh", "<type> <data coll>", "Visualize the mesh from data collection."}; - commands[(size_t)Command::DataCollField] = {"data_coll_field", "<type> <data coll> <field>", "Visualize the field from data collection."}; - commands[(size_t)Command::DataCollQuad] = {"data_coll_quad", "<type> <data coll> <quad>", "Visualize the Q-field from data collection."}; - commands[(size_t)Command::DataCollCycle] = {"data_coll_cycle", "<cycle>", "Preset the cycle of the data collection."}; - commands[(size_t)Command::DataCollProto] = {"data_coll_protocol", "<protocol>", "Preset the protocol of the data collection."}; - commands[(size_t)Command::Screenshot] = {"screenshot", "<file>", "Take a screenshot, saving it to the file."}; - commands[(size_t)Command::Viewcenter] = {"viewcenter", "<x> <y>", "Change the viewcenter."}; - commands[(size_t)Command::Perspective] = {"perspective", "<on/off>", "Turn on or off perspective projection."}; - commands[(size_t)Command::Light] = {"light", "<on/off>", "Turn on or off light."}; - commands[(size_t)Command::View] = {"view", "<theta> <phi>", "Change the solid angle of view."}; - commands[(size_t)Command::Zoom] = {"zoom", "<zoom>", "Change the zoom factor."}; - commands[(size_t)Command::Shading] = {"shading", "<flat/smooth/cool>", "Change the shading algorithm."}; - commands[(size_t)Command::Subdivisions] = {"subdivisions", "<times> <dummy>", "Change the refinement level."}; - commands[(size_t)Command::Valuerange] = {"valuerange", "<min> <max>", "Change the value range."}; - commands[(size_t)Command::Autoscale] = {"autoscale", "<off/on/value/mesh>", "Change the autoscale algorithm."}; - commands[(size_t)Command::Levellines] = {"levellines", "<min> <max> <num>", "Set the level lines."}; - commands[(size_t)Command::AxisNumberFormat] = {"axis_numberformat", "'<format>'", "Set the axis number format."}; - commands[(size_t)Command::ColorbarNumberFormat] = {"colorbar_numberformat", "'<format>'", "Set the colorbar number format."}; - commands[(size_t)Command::Window] = {"window", "<x> <y> <w> <h>", "Set the position and size of the window."}; - commands[(size_t)Command::Keys] = {"keys", "<keys>", "Send the control key sequence."}; - commands[(size_t)Command::Palette] = {"palette", "<index>", "Set the palette index."}; - commands[(size_t)Command::PaletteRepeat] = {"palette_repeat", "<times>", "Set the repetition of the palette."}; - commands[(size_t)Command::ToggleAttributes] = {"toggle_attributes", "<1/0> [[<1/0>] ...];", "Toggle visibility of the attributes."}; - commands[(size_t)Command::Rotmat] = {"rotmat", "<[0,0]> <[1,0]> ... <[3,3]>", "Set the rotation matrix."}; - commands[(size_t)Command::Camera] = {"camera", "<cam[0]> ... <cam[2]> <dir[0]> ... <dir[2]> <up[0]> ... <up[2]>", "Set the camera position, direction and upward vector."}; - commands[(size_t)Command::Scale] = {"scale", "<scale>", "Set the scaling factor."}; - commands[(size_t)Command::Translate] = {"translate", "<x> <y> <z>", "Set the translation coordinates."}; - commands[(size_t)Command::PlotCaption] = {"plot_caption", "'<caption>'", "Set the plot caption."}; + (*this)[Command::Mesh] = {"mesh", "<file>", "Visualize the mesh."}; + (*this)[Command::Solution] = {"solution", "<mesh> <solution>", "Visualize the solution."}; + (*this)[Command::ParSolution] = {"psolution", "<np> <mesh prefix> <keep attributes> <solution prefix>", "Visualize the distributed solution."}; + (*this)[Command::Quadrature] = {"quadrature", "<mesh> <quadrature>", "Visualize the quadrature."}; + (*this)[Command::ParQuadrature] = {"pquadrature", "<np> <mesh prefix> <keep attributes> <quadrature prefix>", "Visualize the distributed quadrature."}; + (*this)[Command::DataCollMesh] = {"data_coll_mesh", "<type> <data coll>", "Visualize the mesh from data collection."}; + (*this)[Command::DataCollField] = {"data_coll_field", "<type> <data coll> <field>", "Visualize the field from data collection."}; + (*this)[Command::DataCollQuad] = {"data_coll_quad", "<type> <data coll> <quad>", "Visualize the Q-field from data collection."}; + (*this)[Command::DataCollCycle] = {"data_coll_cycle", "<cycle>", "Preset the cycle of the data collection."}; + (*this)[Command::DataCollProto] = {"data_coll_protocol", "<protocol>", "Preset the protocol of the data collection."}; + (*this)[Command::Screenshot] = {"screenshot", "<file>", "Take a screenshot, saving it to the file."}; + (*this)[Command::Viewcenter] = {"viewcenter", "<x> <y>", "Change the viewcenter."}; + (*this)[Command::Perspective] = {"perspective", "<on/off>", "Turn on or off perspective projection."}; + (*this)[Command::Light] = {"light", "<on/off>", "Turn on or off light."}; + (*this)[Command::View] = {"view", "<theta> <phi>", "Change the solid angle of view."}; + (*this)[Command::Zoom] = {"zoom", "<zoom>", "Change the zoom factor."}; + (*this)[Command::Shading] = {"shading", "<flat/smooth/cool>", "Change the shading algorithm."}; + (*this)[Command::Subdivisions] = {"subdivisions", "<times> <dummy>", "Change the refinement level."}; + (*this)[Command::Valuerange] = {"valuerange", "<min> <max>", "Change the value range."}; + (*this)[Command::Autoscale] = {"autoscale", "<off/on/value/mesh>", "Change the autoscale algorithm."}; + (*this)[Command::Levellines] = {"levellines", "<min> <max> <num>", "Set the level lines."}; + (*this)[Command::AxisNumberFormat] = {"axis_numberformat", "'<format>'", "Set the axis number format."}; + (*this)[Command::ColorbarNumberFormat] = {"colorbar_numberformat", "'<format>'", "Set the colorbar number format."}; + (*this)[Command::Window] = {"window", "<x> <y> <w> <h>", "Set the position and size of the window."}; + (*this)[Command::Keys] = {"keys", "<keys>", "Send the control key sequence."}; + (*this)[Command::Palette] = {"palette", "<index>", "Set the palette index."}; + (*this)[Command::PaletteRepeat] = {"palette_repeat", "<times>", "Set the repetition of the palette."}; + (*this)[Command::ToggleAttributes] = {"toggle_attributes", "<1/0> [[<1/0>] ...];", "Toggle visibility of the attributes."}; + (*this)[Command::Rotmat] = {"rotmat", "<[0,0]> <[1,0]> ... <[3,3]>", "Set the rotation matrix."}; + (*this)[Command::Camera] = {"camera", "<cam[0]> ... <cam[2]> <dir[0]> ... <dir[2]> <up[0]> ... <up[2]>", "Set the camera position, direction and upward vector."}; + (*this)[Command::Scale] = {"scale", "<scale>", "Set the scaling factor."}; + (*this)[Command::Translate] = {"translate", "<x> <y> <z>", "Set the translation coordinates."}; + (*this)[Command::PlotCaption] = {"plot_caption", "'<caption>'", "Set the plot caption."}; } int ScriptController::ScriptReadSolution(istream &scr, DataState &state) diff --git a/lib/stream_reader.cpp b/lib/stream_reader.cpp index b8547263..24b40d85 100644 --- a/lib/stream_reader.cpp +++ b/lib/stream_reader.cpp @@ -59,30 +59,31 @@ class StreamCommands decltype(commands)::const_iterator begin() const { return commands.begin(); } decltype(commands)::const_iterator end() const { return commands.end(); } + CmdItem& operator[](Command cmd) { return commands[(size_t)cmd]; } const CmdItem& operator[](Command cmd) const { return commands[(size_t)cmd]; } }; static const StreamCommands commands; StreamCommands::StreamCommands() { - commands[(size_t)Command::Mesh] = {"mesh", false, "<mesh>", "Visualize the mesh."}; - commands[(size_t)Command::Solution] = {"solution", false, "<mesh> <solution>", "Visualize the solution."}; - commands[(size_t)Command::Quadrature] = {"quadrature", false, "<mesh> <quadrature>", "Visualize the quadrature."}; - commands[(size_t)Command::Fem2D] = {"fem2d_data", false, "<mesh> <data>", "Visualize the 2D scalar data."}; - commands[(size_t)Command::VFem2D] = {"vfem2d_data", false, "<mesh> <data_x> <data_y>", "Visualize the 2D vector data."}; - commands[(size_t)Command::VFem2D_keys] = {"vfem2d_data_keys", true, "<mesh> <data_x> <data_y> <keys>", "Visualize the 2D vector data and apply control keys."}; - commands[(size_t)Command::Fem3D] = {"fem3d_data", false, "<mesh> <data>", "Visualize the 3D scalar data."}; - commands[(size_t)Command::VFem3D] = {"vfem3d_data", false, "<mesh> <data_x> <data_y> <data_z>", "Visualize the 3D vector data."}; - commands[(size_t)Command::VFem3D_keys] = {"vfem3d_data_keys", true, "<mesh> <data_x> <data_y> <data_z> <keys>", "Visualize the 3D vector data and apply control keys."}; - commands[(size_t)Command::Fem2D_GF] = {"fem2d_gf_data", false, "<mesh> <solution>", "Visualize the 2D scalar grid function."}; - commands[(size_t)Command::Fem2D_GF_keys] = {"fem2d_gf_data_keys", true, "<mesh> <solution> <keys>", "Visualize the 2D scalar grid function and apply control keys."}; - commands[(size_t)Command::VFem2D_GF] = {"vfem2d_gf_data", false, "<mesh> <solution>", "Visualize the 2D vector grid function."}; - commands[(size_t)Command::VFem2D_GF_keys] = {"vfem2d_gf_data_keys", true, "<mesh> <solution> <keys>", "Visualize the 2D vector grid function and apply control keys."}; - commands[(size_t)Command::Fem3D_GF] = {"fem3d_gf_data", false, "<mesh> <solution>", "Visualize the 3D scalar grid function."}; - commands[(size_t)Command::Fem3D_GF_keys] = {"fem3d_gf_data_keys", true, "<mesh> <solution> <keys>", "Visualize the 3D scalar grid function and apply control keys."}; - commands[(size_t)Command::VFem3D_GF] = {"vfem3d_gf_data", false, "<mesh> <solution>", "Visualize the 3D vector grid function."}; - commands[(size_t)Command::VFem3D_GF_keys] = {"vfem3d_gf_data_keys", true, "<mesh> <solution> <keys>", "Visualize the 3D vector grid function and apply control keys."}; - commands[(size_t)Command::RawScalar2D] = {"raw_scalar_2d", false, "<data>", "Visualize the 2D scalar data (see stream_reader.cpp)."}; + (*this)[Command::Mesh] = {"mesh", false, "<mesh>", "Visualize the mesh."}; + (*this)[Command::Solution] = {"solution", false, "<mesh> <solution>", "Visualize the solution."}; + (*this)[Command::Quadrature] = {"quadrature", false, "<mesh> <quadrature>", "Visualize the quadrature."}; + (*this)[Command::Fem2D] = {"fem2d_data", false, "<mesh> <data>", "Visualize the 2D scalar data."}; + (*this)[Command::VFem2D] = {"vfem2d_data", false, "<mesh> <data_x> <data_y>", "Visualize the 2D vector data."}; + (*this)[Command::VFem2D_keys] = {"vfem2d_data_keys", true, "<mesh> <data_x> <data_y> <keys>", "Visualize the 2D vector data and apply control keys."}; + (*this)[Command::Fem3D] = {"fem3d_data", false, "<mesh> <data>", "Visualize the 3D scalar data."}; + (*this)[Command::VFem3D] = {"vfem3d_data", false, "<mesh> <data_x> <data_y> <data_z>", "Visualize the 3D vector data."}; + (*this)[Command::VFem3D_keys] = {"vfem3d_data_keys", true, "<mesh> <data_x> <data_y> <data_z> <keys>", "Visualize the 3D vector data and apply control keys."}; + (*this)[Command::Fem2D_GF] = {"fem2d_gf_data", false, "<mesh> <solution>", "Visualize the 2D scalar grid function."}; + (*this)[Command::Fem2D_GF_keys] = {"fem2d_gf_data_keys", true, "<mesh> <solution> <keys>", "Visualize the 2D scalar grid function and apply control keys."}; + (*this)[Command::VFem2D_GF] = {"vfem2d_gf_data", false, "<mesh> <solution>", "Visualize the 2D vector grid function."}; + (*this)[Command::VFem2D_GF_keys] = {"vfem2d_gf_data_keys", true, "<mesh> <solution> <keys>", "Visualize the 2D vector grid function and apply control keys."}; + (*this)[Command::Fem3D_GF] = {"fem3d_gf_data", false, "<mesh> <solution>", "Visualize the 3D scalar grid function."}; + (*this)[Command::Fem3D_GF_keys] = {"fem3d_gf_data_keys", true, "<mesh> <solution> <keys>", "Visualize the 3D scalar grid function and apply control keys."}; + (*this)[Command::VFem3D_GF] = {"vfem3d_gf_data", false, "<mesh> <solution>", "Visualize the 3D vector grid function."}; + (*this)[Command::VFem3D_GF_keys] = {"vfem3d_gf_data_keys", true, "<mesh> <solution> <keys>", "Visualize the 3D vector grid function and apply control keys."}; + (*this)[Command::RawScalar2D] = {"raw_scalar_2d", false, "<data>", "Visualize the 2D scalar data (see stream_reader.cpp)."}; } void StreamReader::PrintCommands() diff --git a/lib/threads.cpp b/lib/threads.cpp index 52064a31..0d55180e 100644 --- a/lib/threads.cpp +++ b/lib/threads.cpp @@ -844,35 +844,36 @@ class ThreadCommands decltype(commands)::const_iterator begin() const { return commands.begin(); } decltype(commands)::const_iterator end() const { return commands.end(); } + CmdItem& operator[](Command cmd) { return commands[(size_t)cmd]; } const CmdItem& operator[](Command cmd) const { return commands[(size_t)cmd]; } }; static const ThreadCommands commands; ThreadCommands::ThreadCommands() { - commands[(size_t)Command::Parallel] = {"parallel", "<num proc> <proc>", "Prefix for distributed mesh/solution/quadrature."}; - commands[(size_t)Command::Screenshot] = {"screenshot", "<file>", "Take a screenshot, saving it to the file."}; - commands[(size_t)Command::Viewcenter] = {"viewcenter", "<x> <y>", "Change the viewcenter."}; - commands[(size_t)Command::View] = {"view", "<theta> <phi>", "Change the solid angle of view."}; - commands[(size_t)Command::Zoom] = {"zoom", "<zoom>", "Change the zoom factor."}; - commands[(size_t)Command::Shading] = {"shading", "<flat/smooth/cool>", "Change the shading algorithm."}; - commands[(size_t)Command::Subdivisions] = {"subdivisions", "<times> <dummy>", "Change the refinement level."}; - commands[(size_t)Command::Valuerange] = {"valuerange", "<min> <max>", "Change the value range."}; - commands[(size_t)Command::Autoscale] = {"autoscale", "<off/on/value/mesh>", "Change the autoscale algorithm."}; - commands[(size_t)Command::Levellines] = {"levellines", "<min> <max> <num>", "Set the level lines."}; - commands[(size_t)Command::AxisNumberFormat] = {"axis_numberformat", "'<format>'", "Set the axis number format."}; - commands[(size_t)Command::ColorbarNumberFormat] = {"colorbar_numberformat", "'<format>'", "Set the colorbar number format."}; - commands[(size_t)Command::WindowSize] = {"window_size", "<w> <h>", "Set the size of the window."}; - commands[(size_t)Command::WindowGeometry] = {"window_geometry", "<x> <y> <w> <h>", "Set the position and size of the window."}; - commands[(size_t)Command::WindowTitle] = {"window_title", "'<title>'", "Set title of the window."}; - commands[(size_t)Command::Keys] = {"keys", "<keys>", "Send the control key sequence."}; - commands[(size_t)Command::Palette] = {"palette", "<index>", "Set the palette index."}; - commands[(size_t)Command::PaletteRepeat] = {"palette_repeat", "<times>", "Set the repetition of the palette."}; - commands[(size_t)Command::Camera] = {"camera", "<cam[0]> ... <cam[2]> <dir[0]> ... <dir[2]> <up[0]> ... <up[2]>", "Set the camera position, direction and upward vector."}; - commands[(size_t)Command::PlotCaption] = {"plot_caption", "'<caption>'", "Set the plot caption."}; - commands[(size_t)Command::AxisLabels] = {"axis_labels", "'<x label>' '<y label>' '<z label>'", "Set labels of the axes."}; - commands[(size_t)Command::Pause] = {"pause", "", "Stop the stream until space is pressed."}; - commands[(size_t)Command::Autopause] = {"autopause", "<0/off/1/on>", "Turns off or on autopause."}; + (*this)[Command::Parallel] = {"parallel", "<num proc> <proc>", "Prefix for distributed mesh/solution/quadrature."}; + (*this)[Command::Screenshot] = {"screenshot", "<file>", "Take a screenshot, saving it to the file."}; + (*this)[Command::Viewcenter] = {"viewcenter", "<x> <y>", "Change the viewcenter."}; + (*this)[Command::View] = {"view", "<theta> <phi>", "Change the solid angle of view."}; + (*this)[Command::Zoom] = {"zoom", "<zoom>", "Change the zoom factor."}; + (*this)[Command::Shading] = {"shading", "<flat/smooth/cool>", "Change the shading algorithm."}; + (*this)[Command::Subdivisions] = {"subdivisions", "<times> <dummy>", "Change the refinement level."}; + (*this)[Command::Valuerange] = {"valuerange", "<min> <max>", "Change the value range."}; + (*this)[Command::Autoscale] = {"autoscale", "<off/on/value/mesh>", "Change the autoscale algorithm."}; + (*this)[Command::Levellines] = {"levellines", "<min> <max> <num>", "Set the level lines."}; + (*this)[Command::AxisNumberFormat] = {"axis_numberformat", "'<format>'", "Set the axis number format."}; + (*this)[Command::ColorbarNumberFormat] = {"colorbar_numberformat", "'<format>'", "Set the colorbar number format."}; + (*this)[Command::WindowSize] = {"window_size", "<w> <h>", "Set the size of the window."}; + (*this)[Command::WindowGeometry] = {"window_geometry", "<x> <y> <w> <h>", "Set the position and size of the window."}; + (*this)[Command::WindowTitle] = {"window_title", "'<title>'", "Set title of the window."}; + (*this)[Command::Keys] = {"keys", "<keys>", "Send the control key sequence."}; + (*this)[Command::Palette] = {"palette", "<index>", "Set the palette index."}; + (*this)[Command::PaletteRepeat] = {"palette_repeat", "<times>", "Set the repetition of the palette."}; + (*this)[Command::Camera] = {"camera", "<cam[0]> ... <cam[2]> <dir[0]> ... <dir[2]> <up[0]> ... <up[2]>", "Set the camera position, direction and upward vector."}; + (*this)[Command::PlotCaption] = {"plot_caption", "'<caption>'", "Set the plot caption."}; + (*this)[Command::AxisLabels] = {"axis_labels", "'<x label>' '<y label>' '<z label>'", "Set labels of the axes."}; + (*this)[Command::Pause] = {"pause", "", "Stop the stream until space is pressed."}; + (*this)[Command::Autopause] = {"autopause", "<0/off/1/on>", "Turns off or on autopause."}; } communication_thread::communication_thread(StreamCollection _is, From 78d568fe6c7b8592c4120cd426b0e65ba8864903 Mon Sep 17 00:00:00 2001 From: Jan Nikl <nikl1@llnl.gov> Date: Thu, 8 May 2025 13:43:00 -0700 Subject: [PATCH 31/56] Minor script debugging print out. --- lib/script_controller.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/script_controller.cpp b/lib/script_controller.cpp index d89a228d..27cf8785 100644 --- a/lib/script_controller.cpp +++ b/lib/script_controller.cpp @@ -951,6 +951,7 @@ void ScriptController::PlayScript(Window win, istream &scr) done = true; // start the visualization break; default: + cout << "Command not supported at this level: " << word << endl; break; } } From 69499093624e5eeed59fe78f750195f9751374d2 Mon Sep 17 00:00:00 2001 From: Jan Nikl <nikl1@llnl.gov> Date: Mon, 12 May 2025 09:50:46 -0700 Subject: [PATCH 32/56] Fixed the order of deletion for cleaner cleanup. --- lib/aux_vis.cpp | 5 +++++ lib/aux_vis.hpp | 3 +++ lib/window.cpp | 1 + 3 files changed, 9 insertions(+) diff --git a/lib/aux_vis.cpp b/lib/aux_vis.cpp index 015f55ca..dbd48b0c 100644 --- a/lib/aux_vis.cpp +++ b/lib/aux_vis.cpp @@ -369,6 +369,11 @@ void RunVisualization() wnd->mainLoop(); #endif InitIdleFuncs(); +} + +void EndVisualization() +{ + visualize = 0; delete wnd; wnd = nullptr; } diff --git a/lib/aux_vis.hpp b/lib/aux_vis.hpp index 4f412247..4c03b48d 100644 --- a/lib/aux_vis.hpp +++ b/lib/aux_vis.hpp @@ -35,6 +35,9 @@ void SetVisualizationScene(VisualizationScene * scene, /// Start the infinite visualization loop. void RunVisualization(); +/// End the visualization and destroy the window. +void EndVisualization(); + /// Send expose event. In our case MyReshape is executed and Draw after it. void SendExposeEvent(); diff --git a/lib/window.cpp b/lib/window.cpp index 1966069d..c5573ddc 100644 --- a/lib/window.cpp +++ b/lib/window.cpp @@ -174,6 +174,7 @@ void Window::GLVisStartVis() { RunVisualization(); internal.vs.reset(); + EndVisualization(); if (glvis_command) { glvis_command->Terminate(); From bcd8fcb32d47e75ada71d725977daf3085e5f9bf Mon Sep 17 00:00:00 2001 From: Jan Nikl <nikl1@llnl.gov> Date: Tue, 13 May 2025 22:07:07 -0700 Subject: [PATCH 33/56] Moved ownership of SdlWindow to Window and removed GetAppWindow() uses. --- lib/aux_js.cpp | 12 ++++++------ lib/aux_vis.cpp | 11 +++-------- lib/aux_vis.hpp | 5 +---- lib/openglvis.cpp | 4 ++-- lib/script_controller.cpp | 2 +- lib/threads.cpp | 4 ++-- lib/vsdata.cpp | 8 ++++---- lib/window.cpp | 10 ++++++---- lib/window.hpp | 3 +++ 9 files changed, 28 insertions(+), 31 deletions(-) diff --git a/lib/aux_js.cpp b/lib/aux_js.cpp index e3a14f56..49a34fac 100644 --- a/lib/aux_js.cpp +++ b/lib/aux_js.cpp @@ -44,7 +44,7 @@ using namespace mfem; void display(std::stringstream & commands, const int w, const int h) { // reset antialiasing - GetAppWindow()->getRenderer().setAntialiasing(0); + win.wnd->getRenderer().setAntialiasing(0); std::string word; double minv = 0.0, maxv = 0.0; @@ -207,13 +207,13 @@ int updateParallelStreams(const StringArray & streams) // void iterVisualization() { - GetAppWindow()->mainIter(); + win.wnd->mainIter(); } void setCanvasId(const std::string & id) { std::cout << "glvis: setting canvas id to " << id << std::endl; - GetAppWindow()->setCanvasId(id); + win.wnd->setCanvasId(id); } void disableKeyHandling() @@ -244,7 +244,7 @@ void processKey(int sym, bool ctrl=false, bool shift=false, bool alt=false) mod |= ctrl ? KMOD_CTRL : 0; mod |= shift ? KMOD_SHIFT : 0; mod |= alt ? KMOD_ALT : 0; - GetAppWindow()->callKeyDown(sym, mod); + win.wnd->callKeyDown(sym, mod); } void setupResizeEventCallback(const std::string & id) @@ -274,7 +274,7 @@ std::string getHelpString() em::val getScreenBuffer(bool flip_y=false) { MyExpose(); - auto * wnd = GetAppWindow(); + auto * wnd = win.wnd; int w, h; wnd->getGLDrawSize(w, h); @@ -317,7 +317,7 @@ em::val getScreenBuffer(bool flip_y=false) em::val getPNGByteArray() { constexpr const char * filename = "im.png"; - auto * wnd = GetAppWindow(); + auto * wnd = win.wnd; int w, h; wnd->getGLDrawSize(w, h); diff --git a/lib/aux_vis.cpp b/lib/aux_vis.cpp index dbd48b0c..716e7a72 100644 --- a/lib/aux_vis.cpp +++ b/lib/aux_vis.cpp @@ -85,7 +85,7 @@ void SetUseHiDPI(bool status) void MyExpose(GLsizei w, GLsizei h); void MyExpose(); -int InitVisualization (const char name[], int x, int y, int w, int h) +SdlWindow* InitVisualization(const char name[], int x, int y, int w, int h) { #ifdef GLVIS_DEBUG @@ -96,7 +96,7 @@ int InitVisualization (const char name[], int x, int y, int w, int h) wnd = new SdlWindow(); if (!wnd->createWindow(name, x, y, w, h, wndLegacyGl)) { - return 1; + return NULL; } } else @@ -199,7 +199,7 @@ int InitVisualization (const char name[], int x, int y, int w, int h) #endif locscene = nullptr; - return 0; + return wnd; } void SendKeySequence(const char *seq) @@ -369,12 +369,7 @@ void RunVisualization() wnd->mainLoop(); #endif InitIdleFuncs(); -} - -void EndVisualization() -{ visualize = 0; - delete wnd; wnd = nullptr; } diff --git a/lib/aux_vis.hpp b/lib/aux_vis.hpp index 4c03b48d..97286abf 100644 --- a/lib/aux_vis.hpp +++ b/lib/aux_vis.hpp @@ -27,7 +27,7 @@ class GLVisCommand; void SetGLVisCommand(GLVisCommand *cmd); /// Initializes the visualization and some keys. -int InitVisualization(const char name[], int x, int y, int w, int h); +SdlWindow* InitVisualization(const char name[], int x, int y, int w, int h); void SetVisualizationScene(VisualizationScene * scene, int view = 3, const char *keys = NULL); @@ -35,9 +35,6 @@ void SetVisualizationScene(VisualizationScene * scene, /// Start the infinite visualization loop. void RunVisualization(); -/// End the visualization and destroy the window. -void EndVisualization(); - /// Send expose event. In our case MyReshape is executed and Draw after it. void SendExposeEvent(); diff --git a/lib/openglvis.cpp b/lib/openglvis.cpp index c5981a75..7b54361e 100644 --- a/lib/openglvis.cpp +++ b/lib/openglvis.cpp @@ -1068,12 +1068,12 @@ void VisualizationScene::ToggleBackground() if (background == BG_BLK) { background = BG_WHITE; - GetAppWindow()->getRenderer().setClearColor(1.f, 1.f, 1.f, 1.f); + wnd->getRenderer().setClearColor(1.f, 1.f, 1.f, 1.f); } else { background = BG_BLK; - GetAppWindow()->getRenderer().setClearColor(0.f, 0.f, 0.f, 1.f); + wnd->getRenderer().setClearColor(0.f, 0.f, 0.f, 1.f); } } diff --git a/lib/script_controller.cpp b/lib/script_controller.cpp index 27cf8785..25c3d57a 100644 --- a/lib/script_controller.cpp +++ b/lib/script_controller.cpp @@ -971,7 +971,7 @@ void ScriptController::PlayScript(Window win, istream &scr) script_ctrl = &local_script; if (local_script.win.GLVisInitVis({})) { - GetAppWindow()->setOnKeyDown(SDLK_SPACE, ScriptControl); + local_script.win.wnd->setOnKeyDown(SDLK_SPACE, ScriptControl); local_script.win.GLVisStartVis(); } }, diff --git a/lib/threads.cpp b/lib/threads.cpp index 0d55180e..d4a725db 100644 --- a/lib/threads.cpp +++ b/lib/threads.cpp @@ -24,7 +24,7 @@ GLVisCommand::GLVisCommand(Window &win_) : win(win_) { // should be set in this thread by a call to InitVisualization() - thread_wnd = GetAppWindow(); + thread_wnd = win.wnd.get(); num_waiting = 0; terminating = false; @@ -500,7 +500,7 @@ int GLVisCommand::Execute() cout << "Command: screenshot -> " << screenshot_filename << endl; // Allow SdlWindow to handle the expose and screenshot action, in case // any actions need to be taken before MyExpose(). - GetAppWindow()->screenshot(screenshot_filename, true); + thread_wnd->screenshot(screenshot_filename, true); break; } diff --git a/lib/vsdata.cpp b/lib/vsdata.cpp index d80e6fab..e3ee16f9 100644 --- a/lib/vsdata.cpp +++ b/lib/vsdata.cpp @@ -933,8 +933,8 @@ void KeyKPressed() void KeyAPressed() { - bool curr_aa = GetAppWindow()->getRenderer().getAntialiasing(); - GetAppWindow()->getRenderer().setAntialiasing(!curr_aa); + bool curr_aa = window->wnd->getRenderer().getAntialiasing(); + window->wnd->getRenderer().setAntialiasing(!curr_aa); cout << "Multisampling/Antialiasing: " << strings_off_on[!curr_aa ? 1 : 0] << endl; @@ -1371,7 +1371,7 @@ void VisualizationSceneScalarData::Init() { vsdata = this; window = &win; - wnd = GetAppWindow(); + wnd = win.wnd.get(); arrow_type = arrow_scaling_type = 0; scaling = 0; @@ -1753,7 +1753,7 @@ void VisualizationSceneScalarData::SetLevelLines ( void VisualizationSceneScalarData::PrintState() { - cout << "\nkeys: " << GetAppWindow()->getSavedKeys() << "\n" + cout << "\nkeys: " << wnd->getSavedKeys() << "\n" << "\nlight " << strings_off_on[use_light ? 1 : 0] << "\nperspective " << strings_off_on[OrthogonalProjection ? 0 : 1] << "\nviewcenter " << ViewCenterX << ' ' << ViewCenterY diff --git a/lib/window.cpp b/lib/window.cpp index c5573ddc..2b3c5a17 100644 --- a/lib/window.cpp +++ b/lib/window.cpp @@ -48,7 +48,9 @@ bool Window::GLVisInitVis(StreamCollection input_streams) const char *win_title = (window_title == string_default) ? window_titles[(int)field_type] : window_title; - if (InitVisualization(win_title, window_x, window_y, window_w, window_h)) + internal.wnd.reset(InitVisualization(win_title, window_x, window_y, window_w, + window_h)); + if (!wnd) { cerr << "Initializing the visualization failed." << endl; return false; @@ -56,7 +58,7 @@ bool Window::GLVisInitVis(StreamCollection input_streams) if (input_streams.size() > 0) { - GetAppWindow()->setOnKeyDown(SDLK_SPACE, ThreadsPauseFunc); + wnd->setOnKeyDown(SDLK_SPACE, ThreadsPauseFunc); internal.glvis_command.reset(new GLVisCommand(*this)); SetGLVisCommand(glvis_command.get()); internal.comm_thread.reset(new communication_thread(std::move(input_streams), @@ -67,7 +69,7 @@ bool Window::GLVisInitVis(StreamCollection input_streams) if (data_state.quad_f) { - GetAppWindow()->setOnKeyDown('Q', SwitchQuadSolution); + wnd->setOnKeyDown('Q', SwitchQuadSolution); } double mesh_range = -1.0; @@ -174,7 +176,7 @@ void Window::GLVisStartVis() { RunVisualization(); internal.vs.reset(); - EndVisualization(); + internal.wnd.reset(); if (glvis_command) { glvis_command->Terminate(); diff --git a/lib/window.hpp b/lib/window.hpp index b9f794cd..28f8df5c 100644 --- a/lib/window.hpp +++ b/lib/window.hpp @@ -17,6 +17,7 @@ #include "data_state.hpp" #include "stream_reader.hpp" +class SdlWindow; class VisualizationSceneScalarData; class communication_thread; class GLVisCommand; @@ -29,6 +30,7 @@ struct Window private: struct { + std::unique_ptr<SdlWindow> wnd; std::unique_ptr<VisualizationSceneScalarData> vs; std::unique_ptr<communication_thread> comm_thread; std::unique_ptr<GLVisCommand> glvis_command; @@ -36,6 +38,7 @@ struct Window public: DataState data_state; + const std::unique_ptr<SdlWindow> &wnd{internal.wnd}; const std::unique_ptr<VisualizationSceneScalarData> &vs{internal.vs}; const std::unique_ptr<communication_thread> &comm_thread{internal.comm_thread}; const std::unique_ptr<GLVisCommand> &glvis_command{internal.glvis_command}; From 3b91045192e3c8545742fe7859ead2cb69b084a2 Mon Sep 17 00:00:00 2001 From: Jan Nikl <nikl1@llnl.gov> Date: Tue, 13 May 2025 22:14:09 -0700 Subject: [PATCH 34/56] Moved assignment of SdlWindow in VisualizationScene from Init to constructor. --- lib/openglvis.cpp | 6 ++++-- lib/openglvis.hpp | 2 +- lib/vsdata.cpp | 3 +-- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/lib/openglvis.cpp b/lib/openglvis.cpp index 7b54361e..6d131896 100644 --- a/lib/openglvis.cpp +++ b/lib/openglvis.cpp @@ -112,8 +112,10 @@ void Camera::Print() << std::endl; } -VisualizationScene::VisualizationScene() +VisualizationScene::VisualizationScene(SdlWindow &wnd_) { + wnd = &wnd_; + translmat = glm::mat4(1.0); rotmat = glm::mat4(1.0); rotmat = glm::rotate(rotmat, glm::radians(-60.f), glm::vec3(1.f, 0.f, 0.f)); @@ -130,7 +132,7 @@ VisualizationScene::VisualizationScene() cut_updated = false; background = BG_WHITE; - GetAppWindow()->getRenderer().setClearColor(1.f, 1.f, 1.f, 1.f); + wnd->getRenderer().setClearColor(1.f, 1.f, 1.f, 1.f); _use_cust_l0_pos = false; light_mat_idx = 3; use_light = true; diff --git a/lib/openglvis.hpp b/lib/openglvis.hpp index 1455242d..9cbb3899 100644 --- a/lib/openglvis.hpp +++ b/lib/openglvis.hpp @@ -171,7 +171,7 @@ class VisualizationScene const gl3::GlDrawable &gl_drawable); public: - VisualizationScene(); + VisualizationScene(SdlWindow &wnd); virtual ~VisualizationScene(); int spinning, OrthogonalProjection, print, movie; diff --git a/lib/vsdata.cpp b/lib/vsdata.cpp index e3ee16f9..d7dbb5d2 100644 --- a/lib/vsdata.cpp +++ b/lib/vsdata.cpp @@ -1355,7 +1355,7 @@ void VisualizationSceneScalarData::SetAutoscale(int _autoscale) } VisualizationSceneScalarData::VisualizationSceneScalarData( - Window &win_, bool init) : win(win_) + Window &win_, bool init) : VisualizationScene(*win_.wnd), win(win_) { mesh = win.data_state.mesh.get(); mesh_coarse = win.data_state.mesh_quad.get(); @@ -1371,7 +1371,6 @@ void VisualizationSceneScalarData::Init() { vsdata = this; window = &win; - wnd = win.wnd.get(); arrow_type = arrow_scaling_type = 0; scaling = 0; From 21ab52098eee039738fb219662a6f40166c15813 Mon Sep 17 00:00:00 2001 From: Jan Nikl <nikl1@llnl.gov> Date: Tue, 13 May 2025 22:26:10 -0700 Subject: [PATCH 35/56] Fix of handling failed window creation. --- lib/aux_vis.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/aux_vis.cpp b/lib/aux_vis.cpp index 716e7a72..238562ee 100644 --- a/lib/aux_vis.cpp +++ b/lib/aux_vis.cpp @@ -96,6 +96,8 @@ SdlWindow* InitVisualization(const char name[], int x, int y, int w, int h) wnd = new SdlWindow(); if (!wnd->createWindow(name, x, y, w, h, wndLegacyGl)) { + delete wnd; + wnd = nullptr; return NULL; } } From 20ec3f8d1322c2850b8457a06fed6ff9e2ab0b48 Mon Sep 17 00:00:00 2001 From: Jan Nikl <nikl1@llnl.gov> Date: Tue, 27 May 2025 10:45:40 -0700 Subject: [PATCH 36/56] Fixed canvas id in sdl.cpp. --- lib/sdl.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/sdl.cpp b/lib/sdl.cpp index 3131d757..471a431a 100644 --- a/lib/sdl.cpp +++ b/lib/sdl.cpp @@ -549,13 +549,13 @@ void SdlWindow::getWindowSize(int& w, int& h) if (handle.isInitialized()) { #ifdef __EMSCRIPTEN__ - if (canvas_id_.empty()) + if (canvas_id.empty()) { - std::cerr << "error: id is undefined: " << canvas_id_ << std::endl; + std::cerr << "error: id is undefined: " << canvas_id << std::endl; return; } double dw, dh; - auto err = emscripten_get_element_css_size(canvas_id_.c_str(), &dw, &dh); + auto err = emscripten_get_element_css_size(canvas_id.c_str(), &dw, &dh); w = int(dw); h = int(dh); if (err != EMSCRIPTEN_RESULT_SUCCESS) From 2a02262fca431aadd16dc0f5cdbb1e131f142289 Mon Sep 17 00:00:00 2001 From: Jan Nikl <nikl1@llnl.gov> Date: Tue, 27 May 2025 10:55:32 -0700 Subject: [PATCH 37/56] Fixed definition of GLWindow in aux_js. --- lib/aux_js.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/aux_js.cpp b/lib/aux_js.cpp index 49a34fac..5016c959 100644 --- a/lib/aux_js.cpp +++ b/lib/aux_js.cpp @@ -13,6 +13,7 @@ #include "palettes.hpp" #include "stream_reader.hpp" #include "visual.hpp" +#include "glwindow.hpp" #ifdef GLVIS_USE_LIBPNG #include <png.h> From cf1bb1e0a21bf6145ab4f7844ba0a51e995d66d9 Mon Sep 17 00:00:00 2001 From: Jan Nikl <nikl1@llnl.gov> Date: Tue, 27 May 2025 11:07:02 -0700 Subject: [PATCH 38/56] Fixed dereferencing of window in aux_js. --- lib/aux_js.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/lib/aux_js.cpp b/lib/aux_js.cpp index 5016c959..0f9677ee 100644 --- a/lib/aux_js.cpp +++ b/lib/aux_js.cpp @@ -275,9 +275,8 @@ std::string getHelpString() em::val getScreenBuffer(bool flip_y=false) { MyExpose(); - auto * wnd = win.wnd; int w, h; - wnd->getGLDrawSize(w, h); + win.wnd->getGLDrawSize(w, h); // 4 bytes for rgba const size_t buffer_size = w*h*4; @@ -318,13 +317,12 @@ em::val getScreenBuffer(bool flip_y=false) em::val getPNGByteArray() { constexpr const char * filename = "im.png"; - auto * wnd = win.wnd; int w, h; - wnd->getGLDrawSize(w, h); + win.wnd->getGLDrawSize(w, h); MyExpose(); // save to in-memory file - int status = SaveAsPNG(filename, w, h, wnd->isHighDpi(), true); + int status = SaveAsPNG(filename, w, h, win.wnd->isHighDpi(), true); if (status != 0) { fprintf(stderr, "unable to generate png\n"); From 171ed0fe6c97d140c194e6a144e307b75a465732 Mon Sep 17 00:00:00 2001 From: Jan Nikl <nikl1@llnl.gov> Date: Wed, 28 May 2025 12:25:22 -0700 Subject: [PATCH 39/56] Revert "Fixed canvas id in sdl.cpp." This reverts commit 20ec3f8d1322c2850b8457a06fed6ff9e2ab0b48. --- lib/sdl.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/sdl.cpp b/lib/sdl.cpp index 471a431a..3131d757 100644 --- a/lib/sdl.cpp +++ b/lib/sdl.cpp @@ -549,13 +549,13 @@ void SdlWindow::getWindowSize(int& w, int& h) if (handle.isInitialized()) { #ifdef __EMSCRIPTEN__ - if (canvas_id.empty()) + if (canvas_id_.empty()) { - std::cerr << "error: id is undefined: " << canvas_id << std::endl; + std::cerr << "error: id is undefined: " << canvas_id_ << std::endl; return; } double dw, dh; - auto err = emscripten_get_element_css_size(canvas_id.c_str(), &dw, &dh); + auto err = emscripten_get_element_css_size(canvas_id_.c_str(), &dw, &dh); w = int(dw); h = int(dh); if (err != EMSCRIPTEN_RESULT_SUCCESS) From 54df563a804157d1770112e525f01ba9346bd2b3 Mon Sep 17 00:00:00 2001 From: Jan Nikl <nikl1@llnl.gov> Date: Wed, 28 May 2025 12:37:02 -0700 Subject: [PATCH 40/56] Revert "Fixed definition of GLWindow in aux_js." This reverts commit 2a02262fca431aadd16dc0f5cdbb1e131f142289. --- lib/aux_js.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/aux_js.cpp b/lib/aux_js.cpp index 0f9677ee..401af562 100644 --- a/lib/aux_js.cpp +++ b/lib/aux_js.cpp @@ -13,7 +13,6 @@ #include "palettes.hpp" #include "stream_reader.hpp" #include "visual.hpp" -#include "glwindow.hpp" #ifdef GLVIS_USE_LIBPNG #include <png.h> From b9e80d167c973e05740fc5a362a379235ab5372d Mon Sep 17 00:00:00 2001 From: Jan Nikl <nikl1@llnl.gov> Date: Wed, 28 May 2025 14:02:51 -0700 Subject: [PATCH 41/56] Fixed typo in NOTICE. --- NOTICE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NOTICE b/NOTICE index 799bac34..e548fdff 100644 --- a/NOTICE +++ b/NOTICE @@ -25,6 +25,6 @@ This project distributes the sources of several external software products with their own respective licenses which can be found in their code and attached license files. These software products and their licenses are as follows: -* GL2PS (linalg/gl2ps.{h,c}) -- Custom 1-clause license +* GL2PS (lib/gl2ps.{h,c}) -- Custom 1-clause license * Additional color palettes (share/palettes-crameri.txt) -- MIT license * Additional color palettes (share/palettes-cet.txt) -- CC BY 4.0 license From 6919572123cf4ca4d7d9e46f1a4876c8e7324dd3 Mon Sep 17 00:00:00 2001 From: Jan Nikl <nikl1@llnl.gov> Date: Wed, 28 May 2025 14:20:41 -0700 Subject: [PATCH 42/56] Guarded GL2PS for emscripten. --- lib/aux_vis.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/aux_vis.cpp b/lib/aux_vis.cpp index 238562ee..9e85bac5 100644 --- a/lib/aux_vis.cpp +++ b/lib/aux_vis.cpp @@ -20,7 +20,9 @@ #include "sdl.hpp" #include "palettes.hpp" #include "visual.hpp" +#ifndef __EMSCRIPTEN__ #include "gl2ps.h" +#endif #if defined(GLVIS_USE_LIBTIFF) #include "tiffio.h" @@ -1176,6 +1178,7 @@ void KeyS() SendExposeEvent(); } +#ifndef __EMSCRIPTEN__ inline GL2PSvertex CreatePrintVtx(gl3::FeedbackVertex v) { return @@ -1218,6 +1221,7 @@ void PrintCaptureBuffer(gl3::CaptureBuffer& cbuf) gl2psText(entry.text.c_str(), "Times", 12); } } +#endif void KeyCtrlP() { From 818b538770e69fbd0eb02a7360d77f090aa7b58f Mon Sep 17 00:00:00 2001 From: Jan Nikl <nikl1@llnl.gov> Date: Wed, 28 May 2025 14:26:30 -0700 Subject: [PATCH 43/56] Guarded threads for emscripten. --- lib/aux_vis.cpp | 2 ++ lib/visual.hpp | 2 ++ lib/vsdata.cpp | 4 ++-- lib/window.cpp | 2 ++ lib/window.hpp | 4 ++++ 5 files changed, 12 insertions(+), 2 deletions(-) diff --git a/lib/aux_vis.cpp b/lib/aux_vis.cpp index 9e85bac5..d64e9c67 100644 --- a/lib/aux_vis.cpp +++ b/lib/aux_vis.cpp @@ -460,6 +460,7 @@ void InitIdleFuncs() } } +#ifndef __EMSCRIPTEN__ bool CommunicationIdleFunc() { int status = glvis_command->Execute(); @@ -475,6 +476,7 @@ bool CommunicationIdleFunc() } return false; } +#endif bool MainIdleFunc() { diff --git a/lib/visual.hpp b/lib/visual.hpp index 8c5e5dfa..9507294b 100644 --- a/lib/visual.hpp +++ b/lib/visual.hpp @@ -22,7 +22,9 @@ #include "vssolution3d.hpp" #include "vsvector.hpp" #include "vsvector3d.hpp" +#ifndef __EMSCRIPTEN__ #include "threads.hpp" +#endif #include "gl/types.hpp" #endif diff --git a/lib/vsdata.cpp b/lib/vsdata.cpp index d7dbb5d2..03e1eba1 100644 --- a/lib/vsdata.cpp +++ b/lib/vsdata.cpp @@ -23,9 +23,9 @@ using namespace std; #include "aux_vis.hpp" #include "material.hpp" #include "palettes.hpp" +#ifndef __EMSCRIPTEN__ #include "threads.hpp" - -#include "gl2ps.h" +#endif const char *strings_off_on[] = { "off", "on" }; diff --git a/lib/window.cpp b/lib/window.cpp index 2b3c5a17..f4e72b23 100644 --- a/lib/window.cpp +++ b/lib/window.cpp @@ -56,6 +56,7 @@ bool Window::GLVisInitVis(StreamCollection input_streams) return false; } +#ifndef __EMSCRIPTEN__ if (input_streams.size() > 0) { wnd->setOnKeyDown(SDLK_SPACE, ThreadsPauseFunc); @@ -64,6 +65,7 @@ bool Window::GLVisInitVis(StreamCollection input_streams) internal.comm_thread.reset(new communication_thread(std::move(input_streams), glvis_command.get())); } +#endif locwin = this; diff --git a/lib/window.hpp b/lib/window.hpp index 28f8df5c..f44f6d1e 100644 --- a/lib/window.hpp +++ b/lib/window.hpp @@ -32,16 +32,20 @@ struct Window { std::unique_ptr<SdlWindow> wnd; std::unique_ptr<VisualizationSceneScalarData> vs; +#ifndef __EMSCRIPTEN__ std::unique_ptr<communication_thread> comm_thread; std::unique_ptr<GLVisCommand> glvis_command; +#endif } internal; public: DataState data_state; const std::unique_ptr<SdlWindow> &wnd{internal.wnd}; const std::unique_ptr<VisualizationSceneScalarData> &vs{internal.vs}; +#ifndef __EMSCRIPTEN__ const std::unique_ptr<communication_thread> &comm_thread{internal.comm_thread}; const std::unique_ptr<GLVisCommand> &glvis_command{internal.glvis_command}; +#endif int window_x = 0; // not a command line option int window_y = 0; // not a command line option From a44d2afb2e03b049884dcccac7d1925d4c29c60b Mon Sep 17 00:00:00 2001 From: Jan Nikl <nikl1@llnl.gov> Date: Wed, 28 May 2025 15:10:07 -0700 Subject: [PATCH 44/56] Fixed aux_vis for emscripten. --- lib/aux_vis.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/aux_vis.cpp b/lib/aux_vis.cpp index d64e9c67..fda13994 100644 --- a/lib/aux_vis.cpp +++ b/lib/aux_vis.cpp @@ -15,6 +15,7 @@ #include <cmath> #include <chrono> #include <regex> +#include <thread> #include "mfem.hpp" #include "sdl.hpp" @@ -1286,7 +1287,9 @@ void ThreadsPauseFunc(GLenum state) { if (state & KMOD_CTRL) { +#ifndef __EMSCRIPTEN__ glvis_command->ToggleAutopause(); +#endif } else { From 130c59bc96f97286cf206bba87410da080d77937 Mon Sep 17 00:00:00 2001 From: Jan Nikl <nikl1@llnl.gov> Date: Wed, 28 May 2025 15:22:15 -0700 Subject: [PATCH 45/56] Fixed include in script controller. --- lib/script_controller.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/script_controller.cpp b/lib/script_controller.cpp index 25c3d57a..d7097907 100644 --- a/lib/script_controller.cpp +++ b/lib/script_controller.cpp @@ -17,6 +17,7 @@ #include <array> #include <algorithm> +#include <thread> using namespace std; using namespace mfem; From 01fa33ae4edbd61c396dc6c470602db9d9363004 Mon Sep 17 00:00:00 2001 From: Jan Nikl <nikl1@llnl.gov> Date: Wed, 28 May 2025 15:31:00 -0700 Subject: [PATCH 46/56] Fixed window for emscripten. --- lib/window.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/window.cpp b/lib/window.cpp index f4e72b23..9f6189bc 100644 --- a/lib/window.cpp +++ b/lib/window.cpp @@ -179,12 +179,14 @@ void Window::GLVisStartVis() RunVisualization(); internal.vs.reset(); internal.wnd.reset(); +#ifndef __EMSCRIPTEN__ if (glvis_command) { glvis_command->Terminate(); internal.comm_thread.reset(); internal.glvis_command.reset(); } +#endif cout << "GLVis window closed." << endl; } From caa662abdc380a6e15186785b1132c288db8d231 Mon Sep 17 00:00:00 2001 From: Jan Nikl <nikl1@llnl.gov> Date: Wed, 28 May 2025 16:10:21 -0700 Subject: [PATCH 47/56] Removed script controller from glvis-js compilation. --- makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/makefile b/makefile index 3f53000a..18e33226 100644 --- a/makefile +++ b/makefile @@ -261,7 +261,8 @@ ALL_SOURCE_FILES = \ lib/vsvector.cpp lib/vsvector3d.cpp lib/window.cpp OBJC_SOURCE_FILES = $(if $(NOTMAC),,lib/sdl_mac.mm) DESKTOP_ONLY_SOURCE_FILES = \ - lib/gl/renderer_ff.cpp lib/threads.cpp lib/gl2ps.c lib/sdl_x11.cpp + lib/gl/renderer_ff.cpp lib/threads.cpp lib/gl2ps.c \ + lib/script_controller.cpp lib/sdl_x11.cpp WEB_ONLY_SOURCE_FILES = lib/aux_js.cpp LOGO_FILE = share/logo.rgba LOGO_FILE_CPP = $(LOGO_FILE).bin.cpp From c30e83687e776513aaa33c867fdd2a691748c186 Mon Sep 17 00:00:00 2001 From: Jan Nikl <nikl1@llnl.gov> Date: Wed, 28 May 2025 16:48:42 -0700 Subject: [PATCH 48/56] Fixed window title default value. --- glvis.cpp | 7 ++++++- lib/window.cpp | 2 +- lib/window.hpp | 7 ++----- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/glvis.cpp b/glvis.cpp index 7ef13259..90d39ff0 100644 --- a/glvis.cpp +++ b/glvis.cpp @@ -374,6 +374,7 @@ int main (int argc, char *argv[]) const char *stream_file = string_none; const char *script_file = string_none; const char *palette_file = string_none; + const char *window_title = string_default; const char *font_name = string_default; int portnum = 19916; int multisample = GetMultisample(); @@ -457,7 +458,7 @@ int main (int argc, char *argv[]) "Set the window width."); args.AddOption(&win.window_h, "-wh", "--window-height", "Set the window height."); - args.AddOption(&win.window_title, "-wt", "--window-title", + args.AddOption(&window_title, "-wt", "--window-title", "Set the window title."); args.AddOption(&c_plot_caption, "-c", "--plot-caption", "Set the plot caption (visible when colorbar is visible)."); @@ -552,6 +553,10 @@ int main (int argc, char *argv[]) { win.data_state.keys = arg_keys; } + if (window_title != string_default) + { + win.window_title = window_title; + } if (font_name != string_default) { SetFont(font_name); diff --git a/lib/window.cpp b/lib/window.cpp index 9f6189bc..34056d8d 100644 --- a/lib/window.cpp +++ b/lib/window.cpp @@ -45,7 +45,7 @@ bool Window::GLVisInitVis(StreamCollection input_streams) "GLVis [vector data]", }; - const char *win_title = (window_title == string_default) ? + const char *win_title = (window_title == nullptr) ? window_titles[(int)field_type] : window_title; internal.wnd.reset(InitVisualization(win_title, window_x, window_y, window_w, diff --git a/lib/window.hpp b/lib/window.hpp index f44f6d1e..1c2bc8e1 100644 --- a/lib/window.hpp +++ b/lib/window.hpp @@ -22,9 +22,6 @@ class VisualizationSceneScalarData; class communication_thread; class GLVisCommand; -extern const char *string_none; -extern const char *string_default; - struct Window { private: @@ -43,7 +40,7 @@ struct Window const std::unique_ptr<SdlWindow> &wnd{internal.wnd}; const std::unique_ptr<VisualizationSceneScalarData> &vs{internal.vs}; #ifndef __EMSCRIPTEN__ - const std::unique_ptr<communication_thread> &comm_thread{internal.comm_thread}; + const std::unique_ptr<communication_thread> &comm_thread {internal.comm_thread}; const std::unique_ptr<GLVisCommand> &glvis_command{internal.glvis_command}; #endif @@ -51,7 +48,7 @@ struct Window int window_y = 0; // not a command line option int window_w = 400; int window_h = 350; - const char *window_title = string_default; + const char *window_title = nullptr; std::string plot_caption; std::string extra_caption; From 9a307369a8bf57011289ab24a1038b38fb5c03d3 Mon Sep 17 00:00:00 2001 From: Justin Laughlin <laughlin6@llnl.gov> Date: Thu, 29 May 2025 16:51:05 -0700 Subject: [PATCH 49/56] Trying to update display --- lib/aux_js.cpp | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ lib/window.cpp | 4 ---- lib/window.hpp | 4 ---- 3 files changed, 48 insertions(+), 8 deletions(-) diff --git a/lib/aux_js.cpp b/lib/aux_js.cpp index 401af562..74174000 100644 --- a/lib/aux_js.cpp +++ b/lib/aux_js.cpp @@ -13,6 +13,8 @@ #include "palettes.hpp" #include "stream_reader.hpp" #include "visual.hpp" +// #include "window.hpp" +// #include <thread> #ifdef GLVIS_USE_LIBPNG #include <png.h> @@ -30,6 +32,9 @@ thread_local mfem::GeometryRefiner GLVisGeometryRefiner; std::vector<unsigned char> * screen_state = nullptr; static Window win; +// using StreamCollection = std::vector<std::unique_ptr<std::istream>>; +// static StreamCollection input_streams; +// static std::thread handler; int last_stream_nproc = 1; @@ -84,6 +89,33 @@ void display(std::stringstream & commands, const int w, const int h) SendExposeEvent(); } +// void display2(const int w, const int h) +// { +// // reset antialiasing +// win.wnd->getRenderer().setAntialiasing(0); + +// win.window_title = "glvis"; +// win.window_x = 0.; +// win.window_y = 0.; +// win.window_w = w; +// win.window_h = h; + +// auto funcThread = [](Window w, StreamCollection is) +// { +// if (w.GLVisInitVis(std::move(is))) +// { +// w.GLVisStartVis(); +// } +// }; +// handler = std::thread {funcThread, +// std::move(win), std::move(input_streams)}; +// handler.detach(); + +// // win.GLVisInitVis({}); +// // CallKeySequence(win.data_state.keys.c_str()); +// // SendExposeEvent(); +// } + // // StreamReader::ReadStream requires a list of unique_ptr to istream and since // we cannot directly pass a list of string we need to repack the strings into @@ -149,6 +181,22 @@ void displayStream(const std::string & stream, const int w, const int h) display(ss, w, h); } +// void displayStream(const std::string & stream, const int w, const int h) +// { +// std::stringstream ss(stream); +// std::string data_type; +// ss >> data_type >> ws; + +// StreamReader reader(win.data_state); +// reader.ReadStream(ss, data_type); +// input_streams.emplace_back(std::move(&ss)); + +// // display(ss, w, h); +// display2(w, h); +// } + + + // // update the existing stream // diff --git a/lib/window.cpp b/lib/window.cpp index 34056d8d..f46b8687 100644 --- a/lib/window.cpp +++ b/lib/window.cpp @@ -56,7 +56,6 @@ bool Window::GLVisInitVis(StreamCollection input_streams) return false; } -#ifndef __EMSCRIPTEN__ if (input_streams.size() > 0) { wnd->setOnKeyDown(SDLK_SPACE, ThreadsPauseFunc); @@ -65,7 +64,6 @@ bool Window::GLVisInitVis(StreamCollection input_streams) internal.comm_thread.reset(new communication_thread(std::move(input_streams), glvis_command.get())); } -#endif locwin = this; @@ -179,14 +177,12 @@ void Window::GLVisStartVis() RunVisualization(); internal.vs.reset(); internal.wnd.reset(); -#ifndef __EMSCRIPTEN__ if (glvis_command) { glvis_command->Terminate(); internal.comm_thread.reset(); internal.glvis_command.reset(); } -#endif cout << "GLVis window closed." << endl; } diff --git a/lib/window.hpp b/lib/window.hpp index 1c2bc8e1..a0746a98 100644 --- a/lib/window.hpp +++ b/lib/window.hpp @@ -29,20 +29,16 @@ struct Window { std::unique_ptr<SdlWindow> wnd; std::unique_ptr<VisualizationSceneScalarData> vs; -#ifndef __EMSCRIPTEN__ std::unique_ptr<communication_thread> comm_thread; std::unique_ptr<GLVisCommand> glvis_command; -#endif } internal; public: DataState data_state; const std::unique_ptr<SdlWindow> &wnd{internal.wnd}; const std::unique_ptr<VisualizationSceneScalarData> &vs{internal.vs}; -#ifndef __EMSCRIPTEN__ const std::unique_ptr<communication_thread> &comm_thread {internal.comm_thread}; const std::unique_ptr<GLVisCommand> &glvis_command{internal.glvis_command}; -#endif int window_x = 0; // not a command line option int window_y = 0; // not a command line option From dba04e9885a15bca0cc806b55b5f967c554b8b67 Mon Sep 17 00:00:00 2001 From: Jan Nikl <nikl1@llnl.gov> Date: Thu, 29 May 2025 17:26:13 -0700 Subject: [PATCH 50/56] Enabled compilation threads.cpp. --- lib/aux_vis.cpp | 19 ++----------------- lib/visual.hpp | 2 -- lib/vsdata.cpp | 2 -- makefile | 4 ++-- 4 files changed, 4 insertions(+), 23 deletions(-) diff --git a/lib/aux_vis.cpp b/lib/aux_vis.cpp index fda13994..82b37174 100644 --- a/lib/aux_vis.cpp +++ b/lib/aux_vis.cpp @@ -461,7 +461,6 @@ void InitIdleFuncs() } } -#ifndef __EMSCRIPTEN__ bool CommunicationIdleFunc() { int status = glvis_command->Execute(); @@ -477,12 +476,11 @@ bool CommunicationIdleFunc() } return false; } -#endif bool MainIdleFunc() { bool sleep = true; -#ifndef __EMSCRIPTEN__ + if (glvis_command && visualize == 1 && !(IdleFuncs.Size() > 0 && use_idle)) { @@ -505,18 +503,7 @@ bool MainIdleFunc() sleep = false; } use_idle = !use_idle; -#else - if (IdleFuncs.Size() > 0) - { - LastIdleFunc = (LastIdleFunc + 1) % IdleFuncs.Size(); - if (IdleFuncs[LastIdleFunc]) - { - (*IdleFuncs[LastIdleFunc])(); - } - // Continue executing idle functions - sleep = false; - } -#endif + return sleep; LastIdleFunc = (LastIdleFunc + 1) % IdleFuncs.Size(); if (IdleFuncs[LastIdleFunc]) @@ -1287,9 +1274,7 @@ void ThreadsPauseFunc(GLenum state) { if (state & KMOD_CTRL) { -#ifndef __EMSCRIPTEN__ glvis_command->ToggleAutopause(); -#endif } else { diff --git a/lib/visual.hpp b/lib/visual.hpp index 9507294b..8c5e5dfa 100644 --- a/lib/visual.hpp +++ b/lib/visual.hpp @@ -22,9 +22,7 @@ #include "vssolution3d.hpp" #include "vsvector.hpp" #include "vsvector3d.hpp" -#ifndef __EMSCRIPTEN__ #include "threads.hpp" -#endif #include "gl/types.hpp" #endif diff --git a/lib/vsdata.cpp b/lib/vsdata.cpp index 03e1eba1..8c255dac 100644 --- a/lib/vsdata.cpp +++ b/lib/vsdata.cpp @@ -23,9 +23,7 @@ using namespace std; #include "aux_vis.hpp" #include "material.hpp" #include "palettes.hpp" -#ifndef __EMSCRIPTEN__ #include "threads.hpp" -#endif const char *strings_off_on[] = { "off", "on" }; diff --git a/makefile b/makefile index 18e33226..50d6f5b4 100644 --- a/makefile +++ b/makefile @@ -261,8 +261,8 @@ ALL_SOURCE_FILES = \ lib/vsvector.cpp lib/vsvector3d.cpp lib/window.cpp OBJC_SOURCE_FILES = $(if $(NOTMAC),,lib/sdl_mac.mm) DESKTOP_ONLY_SOURCE_FILES = \ - lib/gl/renderer_ff.cpp lib/threads.cpp lib/gl2ps.c \ - lib/script_controller.cpp lib/sdl_x11.cpp + lib/gl/renderer_ff.cpp lib/gl2ps.c lib/script_controller.cpp \ + lib/sdl_x11.cpp WEB_ONLY_SOURCE_FILES = lib/aux_js.cpp LOGO_FILE = share/logo.rgba LOGO_FILE_CPP = $(LOGO_FILE).bin.cpp From e08c703785d885b1dc2abb3fcc93918e264b2f0d Mon Sep 17 00:00:00 2001 From: Jan Nikl <nikl1@llnl.gov> Date: Thu, 29 May 2025 17:32:52 -0700 Subject: [PATCH 51/56] Removed unreachable code. --- lib/aux_vis.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/lib/aux_vis.cpp b/lib/aux_vis.cpp index 82b37174..8f82e971 100644 --- a/lib/aux_vis.cpp +++ b/lib/aux_vis.cpp @@ -505,11 +505,6 @@ bool MainIdleFunc() use_idle = !use_idle; return sleep; - LastIdleFunc = (LastIdleFunc + 1) % IdleFuncs.Size(); - if (IdleFuncs[LastIdleFunc]) - { - (*IdleFuncs[LastIdleFunc])(); - } } void AddIdleFunc(void (*Func)(void)) From 2d2c6fcfd29a101a187fecb87107f5c88bd5c4eb Mon Sep 17 00:00:00 2001 From: Jan Nikl <nikl1@llnl.gov> Date: Thu, 29 May 2025 19:59:50 -0700 Subject: [PATCH 52/56] Refactored communication_thread. --- lib/threads.cpp | 909 ++++++++++++++++++++++++------------------------ lib/threads.hpp | 6 +- 2 files changed, 458 insertions(+), 457 deletions(-) diff --git a/lib/threads.cpp b/lib/threads.cpp index d4a725db..6f9c9336 100644 --- a/lib/threads.cpp +++ b/lib/threads.cpp @@ -880,9 +880,6 @@ communication_thread::communication_thread(StreamCollection _is, GLVisCommand* cmd) : is(std::move(_is)), glvis_command(cmd) { - new_m = NULL; - new_g = NULL; - if (is.size() > 0) { tid = std::thread(&communication_thread::execute, this); @@ -908,574 +905,582 @@ void communication_thread::print_commands() } } -void communication_thread::execute() +bool communication_thread::execute_one(std::string ident) { - while (1) + // new solution handled by StreamReader + if (StreamReader::SupportsDataType(ident)) { - *is[0] >> ws; - // thread cancellation point - if (terminate_thread) { break; } + DataState tmp; + tmp.fix_elem_orient = glvis_command->FixElementOrientations(); + StreamReader reader(tmp); + reader.ReadStream(*is[0], ident); - *is[0] >> ident; - if (!(*is[0])) + // cout << "Stream: new solution" << endl; + + if (glvis_command->NewMeshAndSolution(std::move(tmp))) { - break; + return false; } - - // new solution handled by StreamReader - if (StreamReader::SupportsDataType(ident)) + if (!tmp.keys.empty()) { - DataState tmp; - tmp.fix_elem_orient = glvis_command->FixElementOrientations(); - StreamReader reader(tmp); - reader.ReadStream(*is[0], ident); - if (!(*is[0])) - { - break; - } - - // cout << "Stream: new solution" << endl; - - if (glvis_command->NewMeshAndSolution(std::move(tmp))) + if (glvis_command->KeyCommands(tmp.keys.c_str())) { - goto comm_terminate; + return false; } - if (!tmp.keys.empty()) - { - if (glvis_command->KeyCommands(tmp.keys.c_str())) - { - goto comm_terminate; - } - } - continue; } + return true; + } - auto it = find(commands.begin(), commands.end(), ident); - if (it == commands.end()) - { - cout << "Stream: unknown command: " << ident << endl; - print_commands(); - goto comm_terminate; - } + auto it = find(commands.begin(), commands.end(), ident); + if (it == commands.end()) + { + cout << "Stream: unknown command: " << ident << endl; + print_commands(); + return false; + } - const Command cmd = (Command)(it - commands.begin()); - switch (cmd) + const Command cmd = (Command)(it - commands.begin()); + switch (cmd) + { + case Command::Parallel: { - case Command::Parallel: + unsigned int proc, nproc, np = 0; + do { - unsigned int proc, nproc, np = 0; - do - { - istream &isock = *is[np]; - isock >> nproc >> proc >> ws; + istream &isock = *is[np]; + isock >> nproc >> proc >> ws; #ifdef GLVIS_DEBUG - cout << "connection[" << np << "]: parallel " << nproc << ' ' - << proc << endl; + cout << "connection[" << np << "]: parallel " << nproc << ' ' + << proc << endl; #endif - if (nproc != is.size()) - { - cout << "Unexpected number of processors: " << nproc - << ", expected: " << is.size() << endl; - mfem_error(); - } - if (proc >= nproc) - { - cout << "Invalid processor rank: " << proc - << ", number of processors: " << nproc << endl; - mfem_error(); - } - np++; - if (np == nproc) - { - break; - } - *is[np] >> ident >> ws; // "parallel" - if (ident != "parallel") - { - cout << "Expected keyword \"parallel\", got \"" << ident - << '"' << endl; - mfem_error(); - } + if (nproc != is.size()) + { + cout << "Unexpected number of processors: " << nproc + << ", expected: " << is.size() << endl; + mfem_error(); } - while (1); - - DataState tmp; - tmp.fix_elem_orient = glvis_command->FixElementOrientations(); - tmp.keep_attr = glvis_command->KeepAttrib(); - StreamReader reader(tmp); - reader.ReadStreams(is); - - // cout << "Stream: new solution" << endl; - - if (glvis_command->NewMeshAndSolution(std::move(tmp))) + if (proc >= nproc) { - goto comm_terminate; + cout << "Invalid processor rank: " << proc + << ", number of processors: " << nproc << endl; + mfem_error(); } - } - break; - case Command::Screenshot: - { - string filename; - - *is[0] >> ws >> filename; - - // all processors sent the screenshot command - for (size_t i = 1; i < is.size(); i++) + np++; + if (np == nproc) { - *is[i] >> ws >> ident; // 'screenshot' - *is[i] >> ws >> ident; // filename + break; } - - if (glvis_command->Screenshot(filename.c_str())) + *is[np] >> ident >> ws; // "parallel" + if (ident != "parallel") { - goto comm_terminate; + cout << "Expected keyword \"parallel\", got \"" << ident + << '"' << endl; + mfem_error(); } } - break; - case Command::Keys: - { - string keys; + while (1); - *is[0] >> ws >> keys; + DataState tmp; + tmp.fix_elem_orient = glvis_command->FixElementOrientations(); + tmp.keep_attr = glvis_command->KeepAttrib(); + StreamReader reader(tmp); + reader.ReadStreams(is); - // all processors sent the command - for (size_t i = 1; i < is.size(); i++) - { - *is[i] >> ws >> ident; // 'keys' - *is[i] >> ws >> ident; // keys - } + // cout << "Stream: new solution" << endl; - if (glvis_command->KeyCommands(keys.c_str())) - { - goto comm_terminate; - } - } - break; - case Command::WindowSize: + if (glvis_command->NewMeshAndSolution(std::move(tmp))) { - int w, h, t; + return false; + } + } + break; + case Command::Screenshot: + { + string filename; - *is[0] >> w >> h; + *is[0] >> ws >> filename; - // all processors sent the command - for (size_t i = 1; i < is.size(); i++) - { - *is[i] >> ws >> ident; // 'window_size' - *is[i] >> t >> t; - } + // all processors sent the screenshot command + for (size_t i = 1; i < is.size(); i++) + { + *is[i] >> ws >> ident; // 'screenshot' + *is[i] >> ws >> ident; // filename + } - if (glvis_command->WindowSize(w, h)) - { - goto comm_terminate; - } + if (glvis_command->Screenshot(filename.c_str())) + { + return false; } - break; - case Command::WindowGeometry: + } + break; + case Command::Keys: + { + string keys; + + *is[0] >> ws >> keys; + + // all processors sent the command + for (size_t i = 1; i < is.size(); i++) { - int x, y, w, h, t; + *is[i] >> ws >> ident; // 'keys' + *is[i] >> ws >> ident; // keys + } - *is[0] >> x >> y >> w >> h; + if (glvis_command->KeyCommands(keys.c_str())) + { + return false; + } + } + break; + case Command::WindowSize: + { + int w, h, t; - // all processors sent the command - for (size_t i = 1; i < is.size(); i++) - { - *is[i] >> ws >> ident; // 'window_geometry' - *is[i] >> t >> t >> t >> t; - } + *is[0] >> w >> h; - if (glvis_command->WindowGeometry(x, y, w, h)) - { - goto comm_terminate; - } + // all processors sent the command + for (size_t i = 1; i < is.size(); i++) + { + *is[i] >> ws >> ident; // 'window_size' + *is[i] >> t >> t; } - break; - case Command::WindowTitle: + + if (glvis_command->WindowSize(w, h)) { - char c; - string title; + return false; + } + } + break; + case Command::WindowGeometry: + { + int x, y, w, h, t; - // read the opening char - *is[0] >> ws >> c; - // use the opening char as termination as well - getline(*is[0], title, c); + *is[0] >> x >> y >> w >> h; - // all processors sent the command - for (size_t i = 1; i < is.size(); i++) - { - *is[i] >> ws >> ident; // 'window_title' - *is[i] >> ws >> c; - getline(*is[i], ident, c); - } + // all processors sent the command + for (size_t i = 1; i < is.size(); i++) + { + *is[i] >> ws >> ident; // 'window_geometry' + *is[i] >> t >> t >> t >> t; + } - if (glvis_command->WindowTitle(title.c_str())) - { - goto comm_terminate; - } + if (glvis_command->WindowGeometry(x, y, w, h)) + { + return false; } - break; - case Command::PlotCaption: + } + break; + case Command::WindowTitle: + { + char c; + string title; + + // read the opening char + *is[0] >> ws >> c; + // use the opening char as termination as well + getline(*is[0], title, c); + + // all processors sent the command + for (size_t i = 1; i < is.size(); i++) { - char c; - string caption; + *is[i] >> ws >> ident; // 'window_title' + *is[i] >> ws >> c; + getline(*is[i], ident, c); + } - // read the opening char - *is[0] >> ws >> c; - // use the opening char as termination as well - getline(*is[0], caption, c); + if (glvis_command->WindowTitle(title.c_str())) + { + return false; + } + } + break; + case Command::PlotCaption: + { + char c; + string caption; - // all processors sent the command - for (size_t i = 1; i < is.size(); i++) - { - *is[i] >> ws >> ident; // 'plot_caption' - *is[i] >> ws >> c; - getline(*is[i], ident, c); - } + // read the opening char + *is[0] >> ws >> c; + // use the opening char as termination as well + getline(*is[0], caption, c); - if (glvis_command->PlotCaption(caption.c_str())) - { - goto comm_terminate; - } + // all processors sent the command + for (size_t i = 1; i < is.size(); i++) + { + *is[i] >> ws >> ident; // 'plot_caption' + *is[i] >> ws >> c; + getline(*is[i], ident, c); } - break; - case Command::AxisLabels: - { - char c; - string label_x, label_y, label_z; - - // read the opening char - *is[0] >> ws >> c; - // use the opening char as termination as well - getline(*is[0], label_x, c); - *is[0] >> ws >> c; - getline(*is[0], label_y, c); - *is[0] >> ws >> c; - getline(*is[0], label_z, c); - - // all processors sent the command - for (size_t i = 1; i < is.size(); i++) - { - *is[i] >> ws >> ident; // 'axis_label' - *is[i] >> ws >> c; - getline(*is[i], ident, c); - *is[i] >> ws >> c; - getline(*is[i], ident, c); - *is[i] >> ws >> c; - getline(*is[i], ident, c); - } - if (glvis_command->AxisLabels(label_x.c_str(), - label_y.c_str(), - label_z.c_str())) - { - goto comm_terminate; - } + if (glvis_command->PlotCaption(caption.c_str())) + { + return false; } - break; - case Command::Pause: + } + break; + case Command::AxisLabels: + { + char c; + string label_x, label_y, label_z; + + // read the opening char + *is[0] >> ws >> c; + // use the opening char as termination as well + getline(*is[0], label_x, c); + *is[0] >> ws >> c; + getline(*is[0], label_y, c); + *is[0] >> ws >> c; + getline(*is[0], label_z, c); + + // all processors sent the command + for (size_t i = 1; i < is.size(); i++) { - // all processors sent the command - for (size_t i = 1; i < is.size(); i++) - { - *is[i] >> ws >> ident; // 'pause' - } + *is[i] >> ws >> ident; // 'axis_label' + *is[i] >> ws >> c; + getline(*is[i], ident, c); + *is[i] >> ws >> c; + getline(*is[i], ident, c); + *is[i] >> ws >> c; + getline(*is[i], ident, c); + } - if (glvis_command->Pause()) - { - goto comm_terminate; - } + if (glvis_command->AxisLabels(label_x.c_str(), + label_y.c_str(), + label_z.c_str())) + { + return false; } - break; - case Command::View: + } + break; + case Command::Pause: + { + // all processors sent the command + for (size_t i = 1; i < is.size(); i++) { - double theta, phi, a; + *is[i] >> ws >> ident; // 'pause' + } - *is[0] >> theta >> phi; + if (glvis_command->Pause()) + { + return false; + } + } + break; + case Command::View: + { + double theta, phi, a; - // all processors sent the command - for (size_t i = 1; i < is.size(); i++) - { - *is[i] >> ws >> ident; // 'view' - *is[i] >> a >> a; - } + *is[0] >> theta >> phi; - if (glvis_command->ViewAngles(theta, phi)) - { - goto comm_terminate; - } - } - break; - case Command::Zoom: + // all processors sent the command + for (size_t i = 1; i < is.size(); i++) { - double factor, a; + *is[i] >> ws >> ident; // 'view' + *is[i] >> a >> a; + } - *is[0] >> factor; + if (glvis_command->ViewAngles(theta, phi)) + { + return false; + } + } + break; + case Command::Zoom: + { + double factor, a; - // all processors sent the command - for (size_t i = 1; i < is.size(); i++) - { - *is[i] >> ws >> ident; // 'zoom' - *is[i] >> a; - } + *is[0] >> factor; - if (glvis_command->Zoom(factor)) - { - goto comm_terminate; - } - } - break; - case Command::Subdivisions: + // all processors sent the command + for (size_t i = 1; i < is.size(); i++) { - int tot, bdr, a; + *is[i] >> ws >> ident; // 'zoom' + *is[i] >> a; + } - *is[0] >> tot >> bdr; + if (glvis_command->Zoom(factor)) + { + return false; + } + } + break; + case Command::Subdivisions: + { + int tot, bdr, a; - // all processors sent the command - for (size_t i = 1; i < is.size(); i++) - { - *is[i] >> ws >> ident; // 'subdivisions' - *is[i] >> a >> a; - } + *is[0] >> tot >> bdr; - if (glvis_command->Subdivisions(tot, bdr)) - { - goto comm_terminate; - } - } - break; - case Command::Valuerange: + // all processors sent the command + for (size_t i = 1; i < is.size(); i++) { - double minv, maxv, a; + *is[i] >> ws >> ident; // 'subdivisions' + *is[i] >> a >> a; + } - *is[0] >> minv >> maxv; + if (glvis_command->Subdivisions(tot, bdr)) + { + return false; + } + } + break; + case Command::Valuerange: + { + double minv, maxv, a; - // all processors sent the command - for (size_t i = 1; i < is.size(); i++) - { - *is[i] >> ws >> ident; // 'valuerange' - *is[i] >> a >> a; - } + *is[0] >> minv >> maxv; - if (glvis_command->ValueRange(minv, maxv)) - { - goto comm_terminate; - } - } - break; - case Command::Levellines: + // all processors sent the command + for (size_t i = 1; i < is.size(); i++) { - double minv, maxv, a; - int num, b; + *is[i] >> ws >> ident; // 'valuerange' + *is[i] >> a >> a; + } - *is[0] >> minv >> maxv >> num; + if (glvis_command->ValueRange(minv, maxv)) + { + return false; + } + } + break; + case Command::Levellines: + { + double minv, maxv, a; + int num, b; - // all processors sent the command - for (size_t i = 1; i < is.size(); i++) - { - *is[i] >> ws >> ident; // 'levellines' - *is[i] >> a >> a >> b; - } + *is[0] >> minv >> maxv >> num; - if (glvis_command->Levellines(minv, maxv, num)) - { - goto comm_terminate; - } + // all processors sent the command + for (size_t i = 1; i < is.size(); i++) + { + *is[i] >> ws >> ident; // 'levellines' + *is[i] >> a >> a >> b; } - break; - case Command::AxisNumberFormat: + + if (glvis_command->Levellines(minv, maxv, num)) { - char c; - string formatting; + return false; + } + } + break; + case Command::AxisNumberFormat: + { + char c; + string formatting; - // read the opening char - *is[0] >> ws >> c; - // read formatting string & use c for termination - getline(*is[0], formatting, c); + // read the opening char + *is[0] >> ws >> c; + // read formatting string & use c for termination + getline(*is[0], formatting, c); - // all processors sent the command - for (size_t i = 1; i < is.size(); i++) - { - *is[i] >> ws >> ident; // 'axis_numberformat' - *is[i] >> ws >> c; - getline(*is[i], ident, c); - } - - if (glvis_command->AxisNumberFormat(formatting)) - { - goto comm_terminate; - } + // all processors sent the command + for (size_t i = 1; i < is.size(); i++) + { + *is[i] >> ws >> ident; // 'axis_numberformat' + *is[i] >> ws >> c; + getline(*is[i], ident, c); } - break; - case Command::ColorbarNumberFormat: + + if (glvis_command->AxisNumberFormat(formatting)) { - char c; - string formatting; + return false; + } + } + break; + case Command::ColorbarNumberFormat: + { + char c; + string formatting; - // read the opening char - *is[0] >> ws >> c; - // read formatting string & use c for termination - getline(*is[0], formatting, c); + // read the opening char + *is[0] >> ws >> c; + // read formatting string & use c for termination + getline(*is[0], formatting, c); - // all processors sent the command - for (size_t i = 1; i < is.size(); i++) - { - *is[i] >> ws >> ident; // 'colorbar_numberformat' - *is[i] >> ws >> c; - getline(*is[i], ident, c); - } - - if (glvis_command->ColorbarNumberFormat(formatting)) - { - goto comm_terminate; - } - } - break; - case Command::Shading: + // all processors sent the command + for (size_t i = 1; i < is.size(); i++) { - string shd; + *is[i] >> ws >> ident; // 'colorbar_numberformat' + *is[i] >> ws >> c; + getline(*is[i], ident, c); + } - *is[0] >> ws >> shd; + if (glvis_command->ColorbarNumberFormat(formatting)) + { + return false; + } + } + break; + case Command::Shading: + { + string shd; - // all processors sent the command - for (size_t i = 1; i < is.size(); i++) - { - *is[i] >> ws >> ident; // 'shading' - *is[i] >> ws >> ident; - } + *is[0] >> ws >> shd; - if (glvis_command->SetShading(shd.c_str())) - { - goto comm_terminate; - } - } - break; - case Command::Viewcenter: + // all processors sent the command + for (size_t i = 1; i < is.size(); i++) { - double x, y, a; + *is[i] >> ws >> ident; // 'shading' + *is[i] >> ws >> ident; + } - *is[0] >> x >> y; + if (glvis_command->SetShading(shd.c_str())) + { + return false; + } + } + break; + case Command::Viewcenter: + { + double x, y, a; - // all processors sent the command - for (size_t i = 1; i < is.size(); i++) - { - *is[i] >> ws >> ident; // 'viewcenter' - *is[i] >> a >> a; - } + *is[0] >> x >> y; - if (glvis_command->ViewCenter(x, y)) - { - goto comm_terminate; - } + // all processors sent the command + for (size_t i = 1; i < is.size(); i++) + { + *is[i] >> ws >> ident; // 'viewcenter' + *is[i] >> a >> a; } - break; - case Command::Autoscale: + + if (glvis_command->ViewCenter(x, y)) { - string mode; + return false; + } + } + break; + case Command::Autoscale: + { + string mode; - *is[0] >> ws >> mode; + *is[0] >> ws >> mode; - // all processors sent the command - for (size_t i = 1; i < is.size(); i++) - { - *is[i] >> ws >> ident; // 'autoscale' - *is[i] >> ws >> ident; - } + // all processors sent the command + for (size_t i = 1; i < is.size(); i++) + { + *is[i] >> ws >> ident; // 'autoscale' + *is[i] >> ws >> ident; + } - if (glvis_command->Autoscale(mode.c_str())) - { - goto comm_terminate; - } + if (glvis_command->Autoscale(mode.c_str())) + { + return false; } - break; - case Command::Palette: + } + break; + case Command::Palette: + { + int pal, a; + + *is[0] >> pal; + + // all processors sent the command + for (size_t i = 1; i < is.size(); i++) { - int pal, a; + *is[i] >> ws >> ident; // 'palette' + *is[i] >> a; + } - *is[0] >> pal; + if (glvis_command->Palette(pal)) + { + return false; + } + } + break; + case Command::PaletteRepeat: + { + int n, a; - // all processors sent the command - for (size_t i = 1; i < is.size(); i++) - { - *is[i] >> ws >> ident; // 'palette' - *is[i] >> a; - } + *is[0] >> n; - if (glvis_command->Palette(pal)) - { - goto comm_terminate; - } + // all processors sent the command + for (size_t i = 1; i < is.size(); i++) + { + *is[i] >> ws >> ident; // 'palette_repeat' + *is[i] >> a; } - break; - case Command::PaletteRepeat: + + if (glvis_command->PaletteRepeat(n)) { - int n, a; + return false; + } + } + break; + case Command::Camera: + { + double cam[9], a; - *is[0] >> n; + for (int i = 0; i < 9; i++) + { + *is[0] >> cam[i]; + } - // all processors sent the command - for (size_t i = 1; i < is.size(); i++) + // all processors sent the command + for (size_t i = 1; i < is.size(); i++) + { + *is[i] >> ws >> ident; // 'camera' + for (int j = 0; j < 9; j++) { - *is[i] >> ws >> ident; // 'palette_repeat' *is[i] >> a; } - - if (glvis_command->PaletteRepeat(n)) - { - goto comm_terminate; - } } - break; - case Command::Camera: + + if (glvis_command->Camera(cam)) { - double cam[9], a; + return false; + } + } + break; + case Command::Autopause: + { + string mode; - for (int i = 0; i < 9; i++) - { - *is[0] >> cam[i]; - } + *is[0] >> ws >> mode; - // all processors sent the command - for (size_t i = 1; i < is.size(); i++) - { - *is[i] >> ws >> ident; // 'camera' - for (int j = 0; j < 9; j++) - { - *is[i] >> a; - } - } + // all processors sent the command + for (size_t i = 1; i < is.size(); i++) + { + *is[i] >> ws >> ident; // 'autopause' + *is[i] >> ws >> ident; + } - if (glvis_command->Camera(cam)) - { - goto comm_terminate; - } + if (glvis_command->Autopause(mode.c_str())) + { + return false; } + } + break; + case Command::Max: //dummy break; - case Command::Autopause: - { - string mode; + } - *is[0] >> ws >> mode; + return true; +} - // all processors sent the command - for (size_t i = 1; i < is.size(); i++) - { - *is[i] >> ws >> ident; // 'autopause' - *is[i] >> ws >> ident; - } +void communication_thread::execute() +{ + std::string ident; + bool status = true; - if (glvis_command->Autopause(mode.c_str())) - { - goto comm_terminate; - } - } + while (status) + { + *is[0] >> ws; + // thread cancellation point + if (terminate_thread) { break; } + + *is[0] >> ident; + if (!(*is[0])) + { break; - case Command::Max: //dummy - break; } + + status = execute_one(ident); } - cout << "Stream: end of input." << endl; + if (status) + { + cout << "Stream: end of input." << endl; + } -comm_terminate: for (size_t i = 0; i < is.size(); i++) { socketstream *isock = dynamic_cast<socketstream *>(is[i].get()); diff --git a/lib/threads.hpp b/lib/threads.hpp index c63e3e82..8e428bf3 100644 --- a/lib/threads.hpp +++ b/lib/threads.hpp @@ -153,17 +153,13 @@ class communication_thread GLVisCommand* glvis_command; - // data that may be dynamically allocated by the thread - std::unique_ptr<Mesh> new_m; - std::unique_ptr<GridFunction> new_g; - std::string ident; - // thread object std::thread tid; // signal for thread cancellation std::atomic<bool> terminate_thread {false}; static void print_commands(); + bool execute_one(std::string word); void execute(); public: From 337c27ae38ae7d393fa28b1ee9e45739e89c7bd2 Mon Sep 17 00:00:00 2001 From: Jan Nikl <nikl1@llnl.gov> Date: Thu, 29 May 2025 20:56:49 -0700 Subject: [PATCH 53/56] Added non-multithreaded stream commands execution for JS. --- lib/aux_js.cpp | 31 ++----------------------------- lib/sdl.cpp | 5 ++++- lib/threads.cpp | 16 ++++++++++++---- lib/threads.hpp | 6 +++++- lib/window.cpp | 10 +++++++++- 5 files changed, 32 insertions(+), 36 deletions(-) diff --git a/lib/aux_js.cpp b/lib/aux_js.cpp index 74174000..12ad9285 100644 --- a/lib/aux_js.cpp +++ b/lib/aux_js.cpp @@ -51,42 +51,15 @@ void display(std::stringstream & commands, const int w, const int h) // reset antialiasing win.wnd->getRenderer().setAntialiasing(0); - std::string word; - double minv = 0.0, maxv = 0.0; - while (commands >> word) - { - if (word == "keys") - { - std::cout << "parsing 'keys'" << std::endl; - commands >> win.data_state.keys; - } - else if (word == "valuerange") - { - std::cout << "parsing 'valuerange'" << std::endl; - commands >> minv >> maxv; - } - else - { - std::cout << "unknown command '" << word << "'" << std::endl; - } - } - win.window_title = "glvis"; win.window_x = 0.; win.window_y = 0.; win.window_w = w; win.window_h = h; - win.GLVisInitVis({}); - - CallKeySequence(win.data_state.keys.c_str()); - - if (minv || maxv) - { - win.vs->SetValueRange(minv, maxv); - } + win.GLVisInitVis({commands}); - SendExposeEvent(); + win.comm_thread->process_one(); } // void display2(const int w, const int h) diff --git a/lib/sdl.cpp b/lib/sdl.cpp index 3131d757..7636dac1 100644 --- a/lib/sdl.cpp +++ b/lib/sdl.cpp @@ -539,7 +539,10 @@ void SdlWindow::signalLoop() lock_guard<mutex> evt_guard{event_mutex}; call_idle_func = true; } - events_available.notify_all(); + if (is_multithreaded) + { + events_available.notify_all(); + } } void SdlWindow::getWindowSize(int& w, int& h) diff --git a/lib/threads.cpp b/lib/threads.cpp index 6f9c9336..fbc3a71b 100644 --- a/lib/threads.cpp +++ b/lib/threads.cpp @@ -877,18 +877,26 @@ ThreadCommands::ThreadCommands() } communication_thread::communication_thread(StreamCollection _is, - GLVisCommand* cmd) - : is(std::move(_is)), glvis_command(cmd) + GLVisCommand* cmd, bool multithread) + : is(std::move(_is)), glvis_command(cmd), is_multithread(multithread) { - if (is.size() > 0) + if (is_multithread && is.size() > 0) { tid = std::thread(&communication_thread::execute, this); } } +bool communication_thread::process_one() +{ + std::string word; + *is[0] >> ws; + *is[0] >> word; + return execute_one(word); +} + communication_thread::~communication_thread() { - if (is.size() > 0) + if (is_multithread && is.size() > 0) { terminate_thread = true; tid.join(); diff --git a/lib/threads.hpp b/lib/threads.hpp index 8e428bf3..3ec65d81 100644 --- a/lib/threads.hpp +++ b/lib/threads.hpp @@ -152,6 +152,7 @@ class communication_thread StreamCollection is; GLVisCommand* glvis_command; + bool is_multithread; // thread object std::thread tid; @@ -163,7 +164,10 @@ class communication_thread void execute(); public: - communication_thread(StreamCollection _is, GLVisCommand* cmd); + communication_thread(StreamCollection _is, GLVisCommand* cmd, + bool mulithread = true); + + bool process_one(); ~communication_thread(); }; diff --git a/lib/window.cpp b/lib/window.cpp index f46b8687..6ae30459 100644 --- a/lib/window.cpp +++ b/lib/window.cpp @@ -58,11 +58,19 @@ bool Window::GLVisInitVis(StreamCollection input_streams) if (input_streams.size() > 0) { +#ifndef __EMSCRIPTEN__ wnd->setOnKeyDown(SDLK_SPACE, ThreadsPauseFunc); +#endif internal.glvis_command.reset(new GLVisCommand(*this)); SetGLVisCommand(glvis_command.get()); +#ifndef __EMSCRIPTEN__ + constexpr bool multithreaded = true; +#else + constexpr bool multithreaded = false; +#endif internal.comm_thread.reset(new communication_thread(std::move(input_streams), - glvis_command.get())); + glvis_command.get(), + multithreaded)); } locwin = this; From 2de3292759f11e93f2d42c423bee73c76909cc56 Mon Sep 17 00:00:00 2001 From: Jan Nikl <nikl1@llnl.gov> Date: Thu, 29 May 2025 22:01:19 -0700 Subject: [PATCH 54/56] Fixed stream collection construction. --- lib/aux_js.cpp | 44 +++++++++++++++----------------------------- 1 file changed, 15 insertions(+), 29 deletions(-) diff --git a/lib/aux_js.cpp b/lib/aux_js.cpp index 12ad9285..a2083b36 100644 --- a/lib/aux_js.cpp +++ b/lib/aux_js.cpp @@ -46,7 +46,7 @@ namespace js using namespace mfem; /// Display a new stream -void display(std::stringstream & commands, const int w, const int h) +void display(StreamCollection streams, const int w, const int h) { // reset antialiasing win.wnd->getRenderer().setAntialiasing(0); @@ -57,7 +57,7 @@ void display(std::stringstream & commands, const int w, const int h) win.window_w = w; win.window_h = h; - win.GLVisInitVis({commands}); + win.GLVisInitVis(std::move(streams)); win.comm_thread->process_one(); } @@ -97,61 +97,47 @@ void display(std::stringstream & commands, const int w, const int h) // each string in streams must start with `parallel <nproc> <rank>' // using StringArray = std::vector<std::string>; -void processParallelStreams(DataState & state, - const StringArray & streams, - std::stringstream * commands = nullptr) +StreamCollection processParallelStreams(DataState & state, + const StringArray & streams) { // std::cerr << "got " << streams.size() << " streams" << std::endl; - // HACK: match unique_ptr<istream> interface for ReadStreams: - std::vector<std::stringstream> sstreams(streams.size()); StreamCollection istreams(streams.size()); for (int i = 0; i < streams.size(); ++i) { - sstreams[i] = std::stringstream(streams[i]); + istreams[i] = std::unique_ptr<std::istream>(new std::stringstream(streams[i])); // pull off the first list std::string word; int nproc, rank; - sstreams[i] >> word >> nproc >> rank; - // std::cerr << "packing " << rank+1 << "/" << nproc << std::endl; - istreams[i] = std::unique_ptr<std::istream>(&sstreams[i]); + *istreams[i] >> word >> nproc >> rank; } StreamReader reader(state); reader.ReadStreams(istreams); - if (commands) - { - commands->seekg(istreams[0]->tellg()); - } - - // HACK: don't let unique_ptr free the data - for (int i = 0; i < streams.size(); ++i) - { - istreams[i].release(); - } - last_stream_nproc = streams.size(); + + return istreams; } void displayParallelStreams(const StringArray & streams, const int w, const int h) { - std::stringstream commands(streams[0]); - processParallelStreams(win.data_state, streams, &commands); + StreamCollection sc = processParallelStreams(win.data_state, streams); - display(commands, w, h); + display(std::move(sc), w, h); } void displayStream(const std::string & stream, const int w, const int h) { - std::stringstream ss(stream); + std::unique_ptr<std::istream> ss(new std::istringstream(stream)); std::string data_type; - ss >> data_type; + *ss >> data_type; StreamReader reader(win.data_state); - reader.ReadStream(ss, data_type); + reader.ReadStream(*ss, data_type); - display(ss, w, h); + StreamCollection sc({std::move(ss)}); + display(std::move(sc), w, h); } // void displayStream(const std::string & stream, const int w, const int h) From 3df9a8df331283b01b425c70b1a3eb00444791e9 Mon Sep 17 00:00:00 2001 From: Jan Nikl <nikl1@llnl.gov> Date: Thu, 29 May 2025 22:15:17 -0700 Subject: [PATCH 55/56] A try to fix stream collection constructor. --- lib/aux_js.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/aux_js.cpp b/lib/aux_js.cpp index a2083b36..666ed0a5 100644 --- a/lib/aux_js.cpp +++ b/lib/aux_js.cpp @@ -136,7 +136,7 @@ void displayStream(const std::string & stream, const int w, const int h) StreamReader reader(win.data_state); reader.ReadStream(*ss, data_type); - StreamCollection sc({std::move(ss)}); + StreamCollection sc{std::move(ss)}; display(std::move(sc), w, h); } From d73bf98adde81438d5bd8272a4e48301f229724f Mon Sep 17 00:00:00 2001 From: Jan Nikl <nikl1@llnl.gov> Date: Thu, 29 May 2025 22:24:31 -0700 Subject: [PATCH 56/56] Fixed stream collection construction. --- lib/aux_js.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/aux_js.cpp b/lib/aux_js.cpp index 666ed0a5..0433001b 100644 --- a/lib/aux_js.cpp +++ b/lib/aux_js.cpp @@ -136,7 +136,8 @@ void displayStream(const std::string & stream, const int w, const int h) StreamReader reader(win.data_state); reader.ReadStream(*ss, data_type); - StreamCollection sc{std::move(ss)}; + StreamCollection sc; + sc.emplace_back(std::move(ss)); display(std::move(sc), w, h); }