Skip to content

Commit

Permalink
Merge pull request #164 from eve-le-guillou/mpiExample
Browse files Browse the repository at this point in the history
[MPI] Add example of use for MPI
  • Loading branch information
julien-tierny authored Sep 17, 2024
2 parents aa4f967 + 71b01b2 commit b03bb77
Show file tree
Hide file tree
Showing 4 changed files with 14,304 additions and 0 deletions.
2 changes: 2 additions & 0 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -115,3 +115,5 @@ If you have any questions regarding these examples, please let us know by sendin
| [Manifold checks](manifoldCheck/) | ![ExampleImage](https://topology-tool-kit.github.io/img/gallery/manifoldCheck.jpg) |
| [Cinema IO](cinemaIO/) | <iframe width="100%" height="420" src="https://www.youtube.com/embed/yKyiRzPbs0U" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe> |
| [Compact Triangulation](compactTriangulation/) | <iframe width="100%" height="420" src="https://www.youtube.com/embed/vDQRh_tuUSA" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe> |
| [MPI Example](mpiExample) | ![ExampleImage](https://topology-tool-kit.github.io/img/gallery/mpiExample.jpg) |

85 changes: 85 additions & 0 deletions docs/mpiExample.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
# MPI Example

![MPI example Image](https://topology-tool-kit.github.io/img/gallery/mpiExample.jpg)

This toy example illustrates the usage of TTK in a distributed-memory context with MPI. For this example, the original data set is small. Thus, the pipeline first resamples it to $256^3$ but this dimension can be changed to fit the capabilities of your distributed system.

For more information about how to run a pipeline in parallel in ParaView with MPI, please refer to the [ParaView documentation](https://docs.paraview.org/en/latest/ReferenceManual/parallelDataVisualization.html).

Please note both ParaView and TTK need to be compiled with MPI to allow for parallel execution in a distributed context. For that we refer the reader to the ParaView and TTK installation instructions, but, in short, this can be done by setting the following CMake flags `PARAVIEW_USE_MPI=ON` and `TTK_ENABLE_MPI=ON` for ParaView and TTK respectively. Also, for processing large-scale datasets (typically beyond $1024^3$), we recommend to build TTK with 64 bit identifiers (by setting the CMake flag `TTK_ENABLE_64BIT_IDS=ON`).

## Pipeline description

The produced visualization captures the covalent and hydrogen bonds within the Adenine-Thymine molecular complex. It also shows where the electronic density experiences rapid changes, indicating transition points occurring within the bond.

First, the magnitude of the scalar field is computed and the data set is resampled to $256^3$. This dimension can be changed
(see the corresponding [Python script below](#python-code)).

Then, both the scalar field and its magnitude are smoothed via [ScalarFieldSmoother](https://topology-tool-kit.github.io/doc/html/classttkScalarFieldSmoother.html) and normalized via [ScalarFieldNormalizer](https://topology-tool-kit.github.io/doc/html/classttkScalarFieldNormalizer.html).

Next, the critical points of the scalar field are computed via [ScalarFieldCriticalPoints](https://topology-tool-kit.github.io/doc/html/classttkScalarFieldCriticalPoints.html) and used as seeds of the [IntegralLines](https://topology-tool-kit.github.io/doc/html/classttkIntegralLines.html).

Next, the geometry of the integral lines is smoothed using the [GeometrySmoother](https://topology-tool-kit.github.io/doc/html/classttkGeometrySmoother.html).

Finally, the critical points of the magnitude are computed on the smoothed geometry of the integral lines.

## ParaView
To reproduce the above screenshot on 4 processes and 2 threads, go to your [ttk-data](https://github.com/topology-tool-kit/ttk-data) directory and enter the following command:

``` bash
OMP_NUM_THREADS=2 mpirun -n 4 pvserver
```
In another command line enter the following command:
``` bash
paraview
```
Now, follow the procedure described in paragraph $7.2.2$ of the following [ParaView documentation](https://docs.paraview.org/en/latest/ReferenceManual/parallelDataVisualization.html#configuring-a-server-connection) to connect your ParaView server to your client. Once that is done, you can open the state file `states/mpiExample.pvsm` in the ParaView GUI through `File` > `Load State`.


## Python code

``` python linenums="1"
--8<-- "python/mpiExample.py"
```

To run the above Python script using 2 threads and 4 processes, go to your [ttk-data](https://github.com/topology-tool-kit/ttk-data) directory and enter the following command:
``` bash
OMP_NUM_THREADS=2 mpirun -n 4 pvbatch python/mpiExample.py
```

By default, the dataset is resampled to $256^3$. To resample to a higher dimension, for example $2048^3$, enter the following command:

```bash
OMP_NUM_THREADS=2 mpirun -n 4 pvbatch python/mpiExample.py 2048
```
Be aware that this will require a lot of memory to execute and will most likely not be possible on a regular laptop.



## Inputs
- [at.vti](https://github.com/topology-tool-kit/ttk-data/raw/dev/at.vti): A molecular dataset: a three-dimensional regular grid with one scalar field, the electronic density for the Adenine Thymine complex.

## Outputs
- `integralLines.pvtu`: the geometry of the smoothed integral lines capturing the covalent and hydrogen bonds of the molecule, as extracted by the analysis pipeline.
- `criticalPoints.pvtp`: the critical points computed on the geometry of the integral lines, showing the rapid changes in the bonds.

## C++/Python API

[ArrayPreconditioning](https://topology-tool-kit.github.io/doc/html/classttkArrayPreconditioning.html)

[GeometrySmoother](https://topology-tool-kit.github.io/doc/html/classttkGeometrySmoother.html)

[IntegralLines](https://topology-tool-kit.github.io/doc/html/classttkIntegralLines.html)

[PointDataSelector](https://topology-tool-kit.github.io/doc/html/classttkPointDataSelector.html)

[ScalarFieldCriticalPoints](https://topology-tool-kit.github.io/doc/html/classttkScalarFieldCriticalPoints.html)

[ScalarFieldNormalizer](https://topology-tool-kit.github.io/doc/html/classttkScalarFieldNormalizer.html)

[ScalarFieldSmoother](https://topology-tool-kit.github.io/doc/html/classttkScalarFieldSmoother.html)





126 changes: 126 additions & 0 deletions python/mpiExample.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
#### import the simple module from the paraview
from paraview.simple import *

# ----------------------------------------------------------------
# Choose the resampling dimension for the example
# ----------------------------------------------------------------

if len(sys.argv) == 2:
dim = int(sys.argv[1])
else:
dim = 256

# create a new 'XML Image Data Reader'
atvti = XMLImageDataReader(FileName=["at.vti"])
atvti.PointArrayStatus = ["density"]

calculator1 = Calculator(Input=atvti)
calculator1.ResultArrayType = "Float"
calculator1.ResultArrayName = "density"
calculator1.Function = "density"

# create a new 'Compute Derivatives'
computeDerivatives1 = ComputeDerivatives(Input=calculator1)
computeDerivatives1.Scalars = ["POINTS", "density"]
computeDerivatives1.Vectors = ["POINTS", "1"]

# create a new 'Calculator'
calculator2 = Calculator(Input=computeDerivatives1)
calculator2.AttributeType = "Cell Data"
calculator2.ResultArrayName = "gradientMagnitude"
calculator2.Function = "mag(ScalarGradient)"
calculator2.ResultArrayType = "Float"


# create a new 'Cell Data to Point Data'
cellDatatoPointData1 = CellDatatoPointData(Input=calculator2)
cellDatatoPointData1.CellDataArraytoprocess = ["gradientMagnitude"]

# create a new 'TTK PointDataSelector'
tTKPointDataSelector1 = TTKPointDataSelector(Input=cellDatatoPointData1)
tTKPointDataSelector1.ScalarFields = ["density", "gradientMagnitude"]
tTKPointDataSelector1.RangeId = [0, 2]

# create a new 'Cell Data to Point Data'
cellDatatoPointData2 = CellDatatoPointData(Input=tTKPointDataSelector1)
cellDatatoPointData2.CellDataArraytoprocess = ["ScalarGradient", "gradientMagnitude"]

# create a new 'Resample To Image'
resampleToImage1 = ResampleToImage(Input=cellDatatoPointData2)
resampleToImage1.SamplingDimensions = [dim, dim, dim]
resampleToImage1.SamplingBounds = [0.0, 176.0, 0.0, 94.0, 0.0, 47.0]

# create a new 'TTK ScalarFieldSmoother'
tTKScalarFieldSmoother1 = TTKScalarFieldSmoother(Input=resampleToImage1)
tTKScalarFieldSmoother1.ScalarField = ["POINTS", "density"]
tTKScalarFieldSmoother1.IterationNumber = 1

# create a new 'TTK ScalarFieldSmoother'
tTKScalarFieldSmoother2 = TTKScalarFieldSmoother(Input=tTKScalarFieldSmoother1)
tTKScalarFieldSmoother2.ScalarField = ["POINTS", "gradientMagnitude"]
tTKScalarFieldSmoother2.IterationNumber = 10

# create a new 'TTK ScalarFieldNormalizer'
tTKScalarFieldNormalizer2 = TTKScalarFieldNormalizer(Input=tTKScalarFieldSmoother2)
tTKScalarFieldNormalizer2.ScalarField = ["POINTS", "density"]

# create a new 'TTK ArrayPreconditioning'
tTKArrayPreconditioning1 = TTKArrayPreconditioning(Input=tTKScalarFieldNormalizer2)
tTKArrayPreconditioning1.PointDataArrays = ["density"]

# create a new 'TTK ScalarFieldCriticalPoints'
tTKScalarFieldCriticalPoints2 = TTKScalarFieldCriticalPoints(
Input=tTKArrayPreconditioning1
)
tTKScalarFieldCriticalPoints2.ScalarField = ["POINTS", "density"]
tTKScalarFieldCriticalPoints2.Backend = "Default generic backend"

# create a new 'Mask Points'
maskPoints2 = MaskPoints(Input=tTKScalarFieldCriticalPoints2)
maskPoints2.OnRatio = 1
maskPoints2.MaximumNumberofPoints = 99999999
maskPoints2.ProportionallyDistributeMaximumNumberOfPoints = 1
maskPoints2.RandomSampling = 1
maskPoints2.RandomSamplingMode = "Random Sampling"
maskPoints2.GenerateVertices = 1
maskPoints2.SingleVertexPerCell = 1

# create a new 'Threshold'
threshold1 = Threshold(Input=maskPoints2)
threshold1.Scalars = ["POINTS", "CriticalType"]
threshold1.LowerThreshold = 1.0
threshold1.UpperThreshold = 1.0

# create a new 'Threshold'
threshold4 = Threshold(Input=threshold1)
threshold4.Scalars = ["POINTS", "IsOnBoundary"]

# create a new 'TTK IntegralLines'
tTKIntegralLines1 = TTKIntegralLines(Domain=tTKArrayPreconditioning1, Seeds=threshold4)
tTKIntegralLines1.ScalarField = ["POINTS", "density"]
tTKIntegralLines1.Direction = "Backward"
tTKIntegralLines1.Vertexidentifierfield = ["POINTS", "CriticalType"]
tTKIntegralLines1.EnableForking = 1

# create a new 'Clean to Grid'
cleantoGrid1 = CleantoGrid(Input=tTKIntegralLines1)

# create a new 'TTK GeometrySmoother'
tTKGeometrySmoother2 = TTKGeometrySmoother(Input=cleantoGrid1)
tTKGeometrySmoother2.IterationNumber = 200

# create a new 'Resample With Dataset'
resampleWithDataset1 = ResampleWithDataset(
SourceDataArrays=cellDatatoPointData1, DestinationMesh=tTKGeometrySmoother2
)
resampleWithDataset1.CellLocator = "Static Cell Locator"
resampleWithDataset1.PassCellArrays = 1
resampleWithDataset1.PassPointArrays = 1

# create a new 'TTK ScalarFieldCriticalPoints'
tTKScalarFieldCriticalPoints1 = TTKScalarFieldCriticalPoints(Input=resampleWithDataset1)
tTKScalarFieldCriticalPoints1.ScalarField = ["POINTS", "gradientMagnitude"]
tTKScalarFieldCriticalPoints1.Backend = "Default generic backend"

SaveData("integralLines.pvtu", tTKGeometrySmoother2)
SaveData("criticalPoints.pvtp", tTKScalarFieldCriticalPoints1)
Loading

0 comments on commit b03bb77

Please sign in to comment.