Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add tubes for rendering streamlines #1239

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
4556bfe
tubes might not be the answer. play with adding constant field
nicolemarsaglia Dec 12, 2023
7ef0074
using line renderer and addconstantpointfield
nicolemarsaglia Dec 13, 2023
f95a2bc
add optional tubes to streamline filter with optional params
nicolemarsaglia Dec 15, 2023
ab50c66
streamlines basically done, now to do warpx
nicolemarsaglia Dec 16, 2023
4319649
change default naming
nicolemarsaglia Dec 19, 2023
8f8f93a
Merge branch 'develop' into task/2023_12_vtkm_add_tubes_for_particle_…
nicolemarsaglia Dec 19, 2023
92240df
unclear if this will work with warpx
nicolemarsaglia Dec 20, 2023
aa911ad
it works, but is it correct? I dont' think so. But i also don't think…
nicolemarsaglia Dec 20, 2023
4ec69ec
update docs
nicolemarsaglia Dec 20, 2023
80cc765
add to changelog, but the log looks old?
nicolemarsaglia Dec 20, 2023
996c964
turn tubes off by default for warpx streamlines
nicolemarsaglia Dec 21, 2023
20c5af4
disable rendering in warpx test.
nicolemarsaglia Dec 21, 2023
f079724
serial and par test
nicolemarsaglia Dec 21, 2023
4ff813b
no ranks for you
nicolemarsaglia Dec 21, 2023
fbde873
Merge branch 'develop' into task/2023_12_vtkm_add_tubes_for_particle_…
nicolemarsaglia Jan 8, 2024
b41d784
gotta set field name, defaults are in ascent runtime rather than vtkh…
nicolemarsaglia Jan 9, 2024
a257e74
Update CHANGELOG.md
nicolemarsaglia Jan 10, 2024
1872856
add default radius based on bounds
nicolemarsaglia Jan 13, 2024
20c0646
Merge branch 'task/2023_12_vtkm_add_tubes_for_particle_advec_renderin…
nicolemarsaglia Jan 13, 2024
8add1d6
update docs
nicolemarsaglia Jan 13, 2024
636379c
add baseline image, check for it; change reg streamline tubes default…
nicolemarsaglia Jan 19, 2024
d4b58cc
try to get some output
nicolemarsaglia Jan 20, 2024
994e269
not seeing a difference, reduce num seeds
nicolemarsaglia Jan 22, 2024
a3f368e
actually, more seeds, more print out seeds
nicolemarsaglia Jan 22, 2024
aeb0b66
reduce num seeds a lil
nicolemarsaglia Jan 22, 2024
47117ce
keep output file coming
nicolemarsaglia Jan 22, 2024
0bcb396
python off
nicolemarsaglia Jan 22, 2024
6d41572
I want 30 particles again
nicolemarsaglia Jan 23, 2024
6a2a436
remove unneeded images
nicolemarsaglia Jan 24, 2024
ab7844d
add linear point field as a function option. todo: make param
nicolemarsaglia Feb 14, 2024
fdebf15
add gyre vector field
nicolemarsaglia Feb 14, 2024
f5a576f
Merge branch 'develop' into task/2023_12_vtkm_add_tubes_for_particle_…
nicolemarsaglia Apr 10, 2024
35011a0
revamp verify params with new settings
nicolemarsaglia Apr 10, 2024
486a3f5
add point and point_list seed types
nicolemarsaglia Apr 11, 2024
c780f7d
add line and tmp tests. forgot out sample space param
nicolemarsaglia Apr 12, 2024
76be2d3
skeleton of box
nicolemarsaglia Apr 15, 2024
40da3da
interior box
nicolemarsaglia Apr 16, 2024
633ab92
add boundary random and uniform
nicolemarsaglia Apr 17, 2024
f255eda
Merge branch 'develop' into task/2023_12_vtkm_add_tubes_for_particle_…
cyrush Apr 19, 2024
2d38fb8
don't need epsilon
nicolemarsaglia Apr 23, 2024
8217351
Merge branch 'task/2023_12_vtkm_add_tubes_for_particle_advec_renderin…
nicolemarsaglia Apr 23, 2024
a0d64e2
add unit test as point_list. add baseline. remove print stmts.
nicolemarsaglia Apr 23, 2024
7fdfd0e
revert windows ci build output
nicolemarsaglia Apr 23, 2024
238add7
docs and changelog
nicolemarsaglia Apr 23, 2024
6bc206a
add docs. add fixed point unit tests
nicolemarsaglia Apr 24, 2024
3739089
doc fixes
nicolemarsaglia Apr 26, 2024
51635f4
make bullet points
nicolemarsaglia Apr 26, 2024
8aa6dbf
needs spaces?
nicolemarsaglia Apr 26, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,12 @@ and this project aspires to adhere to [Semantic Versioning](https://semver.org/s
- Added parameters to control HDF5 compression options to the Relay Extract.
- Added check to make sure all domain IDs are unique
- Added a `vtk` extract that saves each mesh domain to a legacy vtk file grouped, with all domain data grouped by a `.visit` file.
- Added WarpX Streamline filter that uses charged particles.
- Added seed population options for particle advection: point, point list, line, and box

### Changed
- Changed the Data Binning filter to accept a `reduction_field` parameter (instead of `var`), and similarly the axis parameters to take `field` (instead of `var`). The `var` style parameters are still accepted, but deprecated and will be removed in a future release.
- Changed the Streamline and WarpXStreamline filters to apply the VTK-m Tube filter to their outputs, allowing for the results to be rendered.

## [0.9.2] - Released 2023-06-30
### Preferred dependency versions for [email protected]
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
// Copyright (c) Lawrence Livermore National Security, LLC and other Ascent
// Project developers. See top-level LICENSE AND COPYRIGHT files for dates and
// other details. No copyright assignment is required to contribute to Ascent.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//

//-----------------------------------------------------------------------------
///
/// file: ascent_tutorial_cpp_utils.hpp
///
//-----------------------------------------------------------------------------

#ifndef ASCENT_TUTORIAL_CPP_UTILS_H
#define ASCENT_TUTORIAL_CPP_UTILS_H

#include <iostream>
#include "conduit_blueprint.hpp"

#include <math.h>

using namespace conduit;

const float64 PI_VALUE = 3.14159265359;

// --------------------------------------------------------------------------//
void
tutorial_tets_example(Node &mesh)
{
mesh.reset();

//
// (create example tet mesh from blueprint example 2)
//
// Create a 3D mesh defined on an explicit set of points,
// composed of two tets, with two element associated fields
// (`var1` and `var2`)
//

// create an explicit coordinate set
double X[5] = { -1.0, 0.0, 0.0, 0.0, 1.0 };
double Y[5] = { 0.0, -1.0, 0.0, 1.0, 0.0 };
double Z[5] = { 0.0, 0.0, 1.0, 0.0, 0.0 };
mesh["coordsets/coords/type"] = "explicit";
mesh["coordsets/coords/values/x"].set(X, 5);
mesh["coordsets/coords/values/y"].set(Y, 5);
mesh["coordsets/coords/values/z"].set(Z, 5);


// add an unstructured topology
mesh["topologies/mesh/type"] = "unstructured";
// reference the coordinate set by name
mesh["topologies/mesh/coordset"] = "coords";
// set topology shape type
mesh["topologies/mesh/elements/shape"] = "tet";
// add a connectivity array for the tets
int64 connectivity[8] = { 0, 1, 3, 2, 4, 3, 1, 2 };
mesh["topologies/mesh/elements/connectivity"].set(connectivity, 8);

const int num_elements = 2;
float var1_vals[num_elements] = { 0, 1 };
float var2_vals[num_elements] = { 1, 0 };

// create a field named var1
mesh["fields/var1/association"] = "element";
mesh["fields/var1/topology"] = "mesh";
mesh["fields/var1/values"].set(var1_vals, 2);

// create a field named var2
mesh["fields/var2/association"] = "element";
mesh["fields/var2/topology"] = "mesh";
mesh["fields/var2/values"].set(var2_vals, 2);

// make sure the mesh we created conforms to the blueprint
Node verify_info;
if(!blueprint::mesh::verify(mesh, verify_info))
{
std::cout << "Mesh Verify failed!" << std::endl;
std::cout << verify_info.to_yaml() << std::endl;
}
}

// --------------------------------------------------------------------------//
void
tutorial_gyre_example(float64 time_value, Node &mesh)
{
mesh.reset();
int xy_dims = 40;
int z_dims = 2;

conduit::blueprint::mesh::examples::braid("hexs",
xy_dims,
xy_dims,
z_dims,
mesh);

mesh["state/time"] = time_value;
Node &field = mesh["fields/gyre"];
field["association"] = "vertex";
field["topology"] = "mesh";
field["values"].set(DataType::float64(xy_dims*xy_dims*z_dims));

Node &vec_field = mesh["fields/gyre_vel"];
vec_field["association"] = "vertex";
vec_field["topology"] = "mesh";
vec_field["values/u"].set(DataType::float64(xy_dims*xy_dims*z_dims));
vec_field["values/v"].set(DataType::float64(xy_dims*xy_dims*z_dims));
vec_field["values/w"].set(DataType::float64(xy_dims*xy_dims*z_dims));

float64 *values_ptr = field["values"].value();
float64 *u_values_ptr = vec_field["values/u"].value();
float64 *v_values_ptr = vec_field["values/v"].value();
float64 *w_values_ptr = vec_field["values/w"].value();

float64 e = 0.25;
float64 A = 0.1;
float64 w = (2.0 * PI_VALUE) / 10.0;
float64 a_t = e * sin(w * time_value);
float64 b_t = 1.0 - 2 * e * sin(w * time_value);
// print("e: " + str(e) + " A " + str(A) + " w " + str(w) + " a_t " + str(a_t) + " b_t " + str(b_t))
// print(b_t)
// print(w)
int idx = 0;
for (int z=0; z < z_dims; z++)
{
for (int y=0; y < xy_dims; y++)
{
// scale y to 0-1
float64 y_n = float64(y)/float64(xy_dims);
float64 y_t = sin(PI_VALUE * y_n);
for (int x=0; x < xy_dims; x++)
{
// scale x to 0-1
float64 x_f = float(x)/ (float(xy_dims) * .5);
float64 f_t = a_t * x_f * x_f + b_t * x_f;
// print(f_t)
float64 value = A * sin(PI_VALUE * f_t) * y_t;
float64 u = -PI_VALUE * A * sin(PI_VALUE * f_t) * cos(PI_VALUE * y_n);
float64 df_dx = 2.0 * a_t + b_t;
// print("df_dx " + str(df_dx))
float64 v = PI_VALUE * A * cos(PI_VALUE * f_t) * sin(PI_VALUE * y_n) * df_dx;
values_ptr[idx] = sqrt(u * u + v * v);
u_values_ptr[idx] = u;
v_values_ptr[idx] = v;
w_values_ptr[idx] = 0;
// values[idx] = u * u + v * v
// values[idx] = value
// print("u " + str(u) + " v " + str(v) + " mag " + str(math.sqrt(u * u + v * v)))
idx++;
}
}
}

//print(values)
}

#endif
23 changes: 23 additions & 0 deletions src/docs/sphinx/Actions/Examples.rst
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,17 @@ Resulting image:

.. image:: examples/tout_trigger_extract_inline100.png

An example of the streamline filter using point list seed placement
--------------------------------------------------------------------

YAML actions:

.. literalinclude:: examples/tout_streamline_point_list100.yaml

Resulting image:

.. image:: examples/tout_streamline_point_list100.png

An example of the interconnecting pipelines.
---------------------------------------------

Expand Down Expand Up @@ -755,6 +766,18 @@ Resulting image:

.. image:: examples/tout_cell_gradient_mag_radial100.png

An example of using the streamline filter and associated tube parameters to produce a rendering.
--------------------------------------------------------------------------------------------------

YAML actions:

.. literalinclude:: examples/tout_streamline_render100.yaml

Resulting image:

.. image:: examples/tout_streamline_render100.png


An example of using the xray extract.
--------------------------------------

Expand Down
186 changes: 186 additions & 0 deletions src/docs/sphinx/Actions/Pipelines.rst
Original file line number Diff line number Diff line change
Expand Up @@ -607,6 +607,192 @@ values are removed from the data set.

An example of creating a iso-volume of values between 5.0 and 10.0.

Particle Advection
~~~~~~~~~~~~~~~~
The particle advection filter distributes some number of weightless particles over a user-specified vector field (``field``) and, given some advection distance (``step_size``), advects them for some number of advection steps (``num_steps``).

.. code-block:: c++

conduit::Node pipelines;
// pipeline 1
pipelines["pl1/f1/type"] = "particle_advection";
//required params
conduit::Node &params = pipelines["pl1/f1/params"];
params["field"] = "vel"; // name of the vector field
params["step_size"] = 0.01; // advection step size
params["num_steps"] = 100; // number of advection steps

Users also need to specify how to generate seed placements (``seeds``).
The seed placements can be an individual point (``point``), a list of points (``point_list``), a line (``line``), or a box (``box``).
The seed placement type will determine the necessary parameters:

- ``point`` requires a ``location`` as an [x,y,z] list of doubles.
- ``point_list`` requires a ``location`` as an [x0,y0,z0,...,xn,yn,zn] list of doubles.
- ``line`` requires a ``start`` and ``end`` as [x,y,z] lists of doubles, the number of seeds (``num_seeds``) to place on the line as well as defining the spacing between seeds (``sampling_type``) as either ``uniform`` or ``random``.
- ``box`` requires the sampling space (``sampling_space``) to be defined (``boundary`` or ``interior``), the sampling type (``sampling_type``) to be defined (``random`` or ``uniform``). By default the boundary of the entire dataset is used, but user can define a new boundary (``x_extents``, ``y_extents``, and ``z_extents``).


At this time, Ascent can only save the output of the particle advection filter as an extract. For rendering, consider using the streamline filter.

Streamlines
~~~~~~~~~~~~
The streamline filter behaves similarly to the particle advection filter, but as the particles are advected, the path of the particle is is collected as a streamline that can be rendered or saved as an extract.
The streamlines are rendered using tubes, which transform the streamline data into a 3D surface.
Tubes are on by default but they can be disabled, though this would also disable rendering capabilities.

.. code-block:: c++

conduit::Node pipelines;
// pipeline 1
pipelines["pl1/f1/type"] = "streamline";
// filter knobs (all these are optional)
conduit::Node &params = pipelines["pl1/f1/params"];
params["field"] = "vel"; // name of the vector field
params["num_steps"] = 1; // number of advection steps
params["step_size"] = 0.01; // advection step size
params["seeds/type"] = "point";
params["seeds/location"] = [-0.826997,-5.62082,3.52779];
//all tubing params are optional
params["enable_tubes"] = "true"; //default: true
params["tube_size"] = 0.4; //default: based on bounds
params["tube_sides"] = 4; //default: 3
params["tube_val"] = 1.0; //default: 0.0
params["tube_capping"] = "true"; //default: true
params["output_field"] = "lines"; //name of streamline tubes for rendering
//default: "field" + "_streamlines"
//e.g "vel_streamlines"

.. figure:: ../images/tout_render_streamlines_point100.png
:scale: 50 %
:align: center

An example of creating a pseudocolor plot of streamline seed placements using ``point``.

.. code-block:: c++

conduit::Node pipelines;
// pipeline 1
pipelines["pl1/f1/type"] = "streamline";
// filter knobs (all these are optional)
conduit::Node &params = pipelines["pl1/f1/params"];
params["field"] = "vel"; // name of the vector field
params["num_steps"] = 1; // number of advection steps
params["step_size"] = 0.01; // advection step size
params["seeds/type"] = "point_list";
params["seeds/location"] = [-9,-9,-9,1,1,1]; // two points
//all tubing params are optional
params["enable_tubes"] = "true"; //default: true
params["tube_size"] = 0.4; //default: based on bounds
params["tube_sides"] = 4; //default: 3
params["tube_val"] = 1.0; //default: 0.0
params["tube_capping"] = "true"; //default: true
params["output_field"] = "lines"; //name of streamline tubes for rendering
//default: "field" + "_streamlines"
//e.g "vel_streamlines"

.. figure:: ../images/tout_render_streamlines_point_list100.png
:scale: 50 %
:align: center

An example of creating a pseudocolor plot of streamline seed placements using ``point_list``.
.. code-block:: c++

conduit::Node pipelines;
// pipeline 1
pipelines["pl1/f1/type"] = "streamline";
// filter knobs (all these are optional)
conduit::Node &params = pipelines["pl1/f1/params"];
params["field"] = "vel"; // name of the vector field
params["num_steps"] = 1; // number of advection steps
params["step_size"] = 0.01; // advection step size
params["seeds/type"] = "line";
//required: how to space the seeds on the line
params["seeds/sampling_type"] = "uniform"; //or "random"
params["seeds/start"] = [-9,-9,-9]; // required: start of line
params["seeds/end"] = [9,9,9]; // required: end of line
params["seeds/num_seeds"] = 10; // required: number of seeds
//all tubing params are optional
params["enable_tubes"] = "true"; //default: true
params["tube_size"] = 0.1; //default: based on bounds
params["tube_sides"] = 4; //default: 3
params["tube_val"] = 1.0; //default: 0.0
params["tube_capping"] = "true"; //default: true
params["output_field"] = "lines"; //name of streamline tubes for rendering
//default: "field" + "_streamlines"
//e.g "vel_streamlines"

.. figure:: ../images/tout_render_streamlines_line100.png
:scale: 50 %
:align: center

An example of creating a pseudocolor plot of streamline seed placements using ``line``.

.. code-block:: c++

conduit::Node pipelines;
// pipeline 1
pipelines["pl1/f1/type"] = "streamline";
// filter knobs (all these are optional)
conduit::Node &params = pipelines["pl1/f1/params"];
params["field"] = "vel"; // name of the vector field
params["step_size"] = 0.01; // advection step size
params["num_steps"] = 1; // number of advection steps
//seed parameters
params["seeds/type"] = "box";
params["seeds/sampling_type"] = "uniform"; //or "random"
params["seeds/sampling_space"] = "interior"; //or "boundary"
//default is using the boundary of the entire dataset
params["seeds/x_extents"] = [-9,9]; //optional: define the boundary
params["seeds/y_extents"] = [-9,9]; //for the distribution
params["seeds/z_extents"] = [-9,9]; //of the particles
//all tubing params are optional
params["enable_tubes"] = "true"; //default: true
params["tube_size"] = 0.1; //default: based on bounds
params["tube_sides"] = 4; //default: 3
params["tube_val"] = 1.0; //default: 0.0
params["tube_capping"] = "true"; //default: true
params["output_field"] = "lines"; //name of streamline tubes for rendering
//default: "field" + "_streamlines"
//e.g "vel_streamlines"

.. figure:: ../images/tout_render_streamlines_box100.png
:scale: 50 %
:align: center

An example of creating a pseudocolor plot of streamline seed placements using ``box``.

Streamlines with Charged Particles (WarpX)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The streamlines with charged particles filter behaves similarly to the streamline filter, but instead utilizes charged particles, which are particles with physical attributes (``charge``, ``mass``, ``momentum``, ``weighting``), that are advected using magnetic (``b_field``) and electric (``e_field``) vector fields.
The resulting streamlines are rendered using tubes, which transform the streamline data into a 3D surface.
Note: the tube functionality is not behaving correctly, currently this functionality is OFF by default.
Otherwise, the resulting streamlines can be saved via an extract.

.. code-block:: c++

conduit::Node pipelines;
// pipeline 1
pipelines["pl1/f1/type"] = "warpx_streamline";
// filter knobs (all these are optional)
conduit::Node &params = pipelines["pl1/f1/params"];
//vector fields
params["b_field"] = "magnetic_field"; //default: B
params["e_field"] = "electric_field"; //default: E
//charged particle params
params["charge_field"] = "charge_field"; //default: Charge
params["mass_field"] = "mass_field"; //default: Mass
params["momentum_field"] = "momentum_field"; //default: Momentum
params["weighting_field"] = "weighting_field"; //default: Weighting
//tubing params
params["enable_tubes"] = "true"; //default: false
params["tube_size"] = 0.2; //default: based on bounds
params["tube_sides"] = 4; //default: 3
params["tube_val"] = 1.0; //default: 0.0
params["tube_capping"] = "true"; //default: true
params["output_field"] = "lines"; //name of streamline tubes for rendering
//default: "b_field" + "e_field" + "_streamlines"
//e.g "B_E_streamlines"

Vector Magnitude
~~~~~~~~~~~~~~~~
Vector magnitude creates a new field on the data set representing the magitude
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Loading