Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
25 changes: 25 additions & 0 deletions test/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,10 @@
import importlib
import os
import pathlib
import random
from collections import defaultdict

import numpy as np
import pytest
import torch

Expand Down Expand Up @@ -171,3 +173,26 @@ def requires_module(names):
def device(request):
"""Device fixture that automatically skips CUDA tests when not available."""
return request.param


@pytest.fixture(autouse=True, scope="function")
def seed_random_state():
"""Reset all random number generators to a fixed seed before each test.

This ensures test reproducibility and isolation - each test starts with
identical RNG state regardless of test execution order or subset.

Tests that need a specific seed can still call torch.manual_seed() etc.
explicitly, which will override this fixture's seeding.
"""
SEED = 95051

random.seed(SEED)
np.random.seed(SEED)
torch.manual_seed(SEED)

# CUDA seeding (no-op if CUDA unavailable)
if torch.cuda.is_available():
torch.cuda.manual_seed_all(SEED)

yield
5 changes: 0 additions & 5 deletions test/mesh/io/io_pyvista/test_data_array_shapes.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ class TestDataArrayShapes:

def test_scalar_data(self):
"""Test scalar data (1D array per point/cell)."""
np.random.seed(0)
pv_mesh = pv.Sphere(radius=1.0, theta_resolution=10, phi_resolution=10)

# Add scalar data
Expand All @@ -53,7 +52,6 @@ def test_scalar_data(self):

def test_vector_data(self):
"""Test vector data (Nx3 arrays)."""
np.random.seed(0)
pv_mesh = pv.Sphere(radius=1.0, theta_resolution=10, phi_resolution=10)

# Add vector data
Expand Down Expand Up @@ -81,7 +79,6 @@ def test_matrix_data(self):
For higher-dimensional data like 3x3 stress tensors, you must
flatten them to (n, 9) before adding to PyVista.
"""
np.random.seed(0)
pv_mesh = pv.Sphere(radius=1.0, theta_resolution=10, phi_resolution=10)

# For tensor data, must be pre-flattened to 2D
Expand Down Expand Up @@ -113,7 +110,6 @@ def test_large_2d_array_data(self):
NOTE: PyVista only accepts arrays with dimensionality ≤ 2.
Higher-order tensors must be pre-flattened before adding to PyVista.
"""
np.random.seed(0)
pv_mesh = pv.Sphere(radius=1.0, theta_resolution=10, phi_resolution=10)

# For higher-dimensional data, flatten to 2D before adding to PyVista
Expand All @@ -137,7 +133,6 @@ def test_large_2d_array_data(self):

def test_mixed_data_types(self):
"""Test mesh with multiple data arrays of different shapes and types."""
np.random.seed(0)
pv_mesh = pv.Sphere(radius=1.0, theta_resolution=10, phi_resolution=10)

# Clear default data to have a clean slate
Expand Down
3 changes: 0 additions & 3 deletions test/mesh/io/io_pyvista/test_data_preservation.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ class TestDataPreservation:

def test_point_data_preserved(self):
"""Test that point_data is preserved during conversion."""
np.random.seed(0)
pv_mesh = pv.Sphere()

# Explicitly create point data
Expand Down Expand Up @@ -78,7 +77,6 @@ def test_point_data_preserved(self):

def test_cell_data_preserved(self):
"""Test that cell_data is preserved as cell_data."""
np.random.seed(0)
pv_mesh = pv.Sphere()

# Explicitly create cell data
Expand Down Expand Up @@ -161,7 +159,6 @@ class TestDataPreservationParametrized:

def test_data_preservation_with_device_transfer(self, device):
"""Test that data is preserved when transferring to different device."""
np.random.seed(42)
pv_mesh = pv.Sphere(theta_resolution=5, phi_resolution=5)
pv_mesh.point_data["temp"] = np.random.rand(pv_mesh.n_points).astype(np.float32)
pv_mesh.cell_data["pressure"] = np.random.rand(pv_mesh.n_cells).astype(
Expand Down
3 changes: 0 additions & 3 deletions test/mesh/io/io_pyvista/test_from_pyvista_0d.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ class TestFromPyvista0D:

def test_pointset_auto_detection(self):
"""Test automatic detection of 0D manifold from PointSet."""
np.random.seed(0)
points = np.random.rand(100, 3).astype(np.float32)
pv_mesh = pv.PointSet(points)

Expand All @@ -50,7 +49,6 @@ def test_pointset_auto_detection(self):

def test_pointset_explicit_dim(self):
"""Test explicit manifold_dim specification for point cloud."""
np.random.seed(0)
points = np.random.rand(50, 3).astype(np.float32)
pv_mesh = pv.PointSet(points)

Expand All @@ -65,7 +63,6 @@ def test_polydata_points_only(self):

PolyData can represent point clouds using vertex cells.
"""
np.random.seed(0)
points = np.random.rand(25, 3).astype(np.float32)
pv_mesh = pv.PolyData(points)

Expand Down
1 change: 0 additions & 1 deletion test/mesh/io/io_pyvista/test_from_pyvista_1d.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,6 @@ def test_spline_constructed(self):

Create a spline through specific points and verify it converts correctly.
"""
np.random.seed(0)
# Create control points for the spline
control_points = np.array(
[
Expand Down
3 changes: 0 additions & 3 deletions test/mesh/io/io_pyvista/test_round_trip.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,6 @@ def test_round_trip_1d_spline(self):

def test_round_trip_0d_pointset(self):
"""Test round-trip conversion for 0D mesh."""
np.random.seed(0)
points_orig = np.random.rand(25, 3).astype(np.float32)
pv_original = pv.PointSet(points_orig)

Expand All @@ -108,7 +107,6 @@ def test_round_trip_0d_pointset(self):

def test_round_trip_with_data(self):
"""Test round-trip conversion preserves data arrays."""
np.random.seed(0)
pv_original = pv.Sphere(theta_resolution=10, phi_resolution=10)
pv_original.clear_data()

Expand Down Expand Up @@ -225,7 +223,6 @@ def test_round_trip_spline_device_parametrized(self, device):

def test_device_transfer_preserves_data(self, device):
"""Test that device transfer preserves all data."""
np.random.seed(42)
# Create mesh with data
pv_mesh = pv.Sphere(theta_resolution=5, phi_resolution=5)
pv_mesh.point_data["temp"] = np.random.rand(pv_mesh.n_points).astype(np.float32)
Expand Down
4 changes: 0 additions & 4 deletions test/mesh/io/io_pyvista/test_to_pyvista.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,6 @@ def test_1d_mesh_to_polydata(self):

def test_0d_mesh_to_pointset(self):
"""Test converting 0D mesh to PointSet."""
np.random.seed(0)
points = torch.from_numpy(np.random.rand(50, 3).astype(np.float32))
cells = torch.empty((0, 1), dtype=torch.long)

Expand All @@ -116,9 +115,6 @@ def test_0d_mesh_to_pointset(self):

def test_data_preservation_to_pyvista(self):
"""Test that point_data, cell_data, and global_data are preserved."""
np.random.seed(0)
torch.manual_seed(42)

# Create a mesh with data
points = torch.rand(10, 3)
cells = torch.tensor([[0, 1, 2], [2, 3, 4]], dtype=torch.long)
Expand Down
17 changes: 0 additions & 17 deletions test/mesh/visualization/test_visualization.py
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,6 @@ def test_pyvista_points_padded_to_3d():

def test_unsupported_spatial_dims():
"""Test that meshes with >3 spatial dimensions raise error."""
torch.manual_seed(42)
# Create a 4D mesh
points = torch.randn(10, 4)
cells = torch.randint(0, 10, (5, 2))
Expand All @@ -241,7 +240,6 @@ def test_no_scalars():

def test_point_scalars_tensor():
"""Test point scalars with direct tensor."""
torch.manual_seed(42)
mesh = create_2d_triangle_mesh()
point_scalars = torch.rand(mesh.n_points)
ax = mesh.draw(show=False, backend="matplotlib", point_scalars=point_scalars)
Expand All @@ -251,7 +249,6 @@ def test_point_scalars_tensor():

def test_cell_scalars_tensor():
"""Test cell scalars with direct tensor."""
torch.manual_seed(42)
mesh = create_2d_triangle_mesh()
cell_scalars = torch.rand(mesh.n_cells)
ax = mesh.draw(show=False, backend="matplotlib", cell_scalars=cell_scalars)
Expand All @@ -261,7 +258,6 @@ def test_cell_scalars_tensor():

def test_point_scalars_key():
"""Test point scalars with key lookup."""
torch.manual_seed(42)
mesh = create_2d_triangle_mesh()
mesh.point_data["temperature"] = torch.rand(mesh.n_points)
ax = mesh.draw(show=False, backend="matplotlib", point_scalars="temperature")
Expand All @@ -271,7 +267,6 @@ def test_point_scalars_key():

def test_cell_scalars_key():
"""Test cell scalars with key lookup."""
torch.manual_seed(42)
mesh = create_2d_triangle_mesh()
mesh.cell_data["pressure"] = torch.rand(mesh.n_cells)
ax = mesh.draw(show=False, backend="matplotlib", cell_scalars="pressure")
Expand All @@ -283,7 +278,6 @@ def test_nested_tensordict_key():
"""Test scalar lookup with nested TensorDict key."""
from tensordict import TensorDict

torch.manual_seed(42)
mesh = create_2d_triangle_mesh()

# Create nested structure
Expand All @@ -300,7 +294,6 @@ def test_nested_tensordict_key():

def test_multidimensional_scalars_norm():
"""Test that multidimensional scalars are L2-normed."""
torch.manual_seed(42)
mesh = create_2d_triangle_mesh()

# Create 3D vector field
Expand All @@ -313,7 +306,6 @@ def test_multidimensional_scalars_norm():

def test_mutual_exclusivity():
"""Test that point_scalars and cell_scalars are mutually exclusive."""
torch.manual_seed(42)
mesh = create_2d_triangle_mesh()

with pytest.raises(ValueError, match="mutually exclusive"):
Expand All @@ -326,7 +318,6 @@ def test_mutual_exclusivity():

def test_scalar_wrong_shape():
"""Test that scalars with wrong shape raise error."""
torch.manual_seed(42)
mesh = create_2d_triangle_mesh()

with pytest.raises(ValueError, match="wrong first dimension"):
Expand All @@ -350,7 +341,6 @@ def test_scalar_key_not_found():

def test_colormap():
"""Test custom colormap."""
torch.manual_seed(42)
mesh = create_2d_triangle_mesh()
mesh.cell_data["data"] = torch.rand(mesh.n_cells)

Expand All @@ -361,7 +351,6 @@ def test_colormap():

def test_vmin_vmax():
"""Test colormap range specification."""
torch.manual_seed(42)
mesh = create_2d_triangle_mesh()
mesh.cell_data["data"] = torch.rand(mesh.n_cells)

Expand Down Expand Up @@ -447,7 +436,6 @@ def test_draw_1d_in_2d():

def test_draw_empty_mesh():
"""Test drawing mesh with no cells."""
torch.manual_seed(42)
points = torch.randn(10, 2)
cells = torch.empty((0, 3), dtype=torch.long)
mesh = Mesh(points=points, cells=cells)
Expand All @@ -459,7 +447,6 @@ def test_draw_empty_mesh():

def test_pyvista_with_scalars():
"""Test PyVista backend with scalar coloring."""
torch.manual_seed(42)
mesh = create_3d_surface_mesh()
mesh.cell_data["pressure"] = torch.rand(mesh.n_cells)

Expand All @@ -472,7 +459,6 @@ def test_pyvista_with_scalars():

def test_pyvista_with_point_scalars():
"""Test PyVista backend with point scalar coloring."""
torch.manual_seed(42)
mesh = create_3d_surface_mesh()
mesh.point_data["temperature"] = torch.rand(mesh.n_points)

Expand All @@ -488,7 +474,6 @@ def test_pyvista_with_point_scalars():

def test_full_workflow_matplotlib():
"""Test complete workflow with matplotlib backend."""
torch.manual_seed(42)
mesh = create_2d_triangle_mesh()

# Add some data
Expand All @@ -512,7 +497,6 @@ def test_full_workflow_matplotlib():

def test_full_workflow_pyvista():
"""Test complete workflow with PyVista backend."""
torch.manual_seed(42)
mesh = create_3d_surface_mesh()

# Add some data
Expand Down Expand Up @@ -608,7 +592,6 @@ def test_basic_visualization_parametrized(
@pytest.mark.parametrize("backend", ["matplotlib", "pyvista"])
def test_visualization_with_scalars_parametrized(self, backend):
"""Test visualization with scalar data across backends."""
torch.manual_seed(42)
if backend == "pyvista":
# Use 3D mesh for PyVista
points = torch.tensor([[0.0, 0.0, 0.0], [1.0, 0.0, 0.0], [0.0, 1.0, 0.0]])
Expand Down
8 changes: 0 additions & 8 deletions test/models/domino/test_domino_encodings.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,6 @@ def test_fourier_mlp(device, fourier_features, num_modes):
"""Test FourierMLP with various configurations"""
from physicsnemo.nn import FourierMLP

torch.manual_seed(0)

model = FourierMLP(
input_features=3,
base_layer=64,
Expand All @@ -48,8 +46,6 @@ def test_fourier_encode_vectorized(device):
"""Test fourier encoding function"""
from physicsnemo.nn import fourier_encode

torch.manual_seed(0)

coords = torch.randn(4, 20, 3).to(device)
freqs = torch.exp(torch.linspace(0, math.pi, 5)).to(device)

Expand All @@ -66,8 +62,6 @@ def test_local_geometry_encoding(device):

BATCH_SIZE = 1

torch.manual_seed(0)

N_ENCODING_CHANNELS = 3
N_NEIGHBORS = 32
N_MESH_POINTS = 50
Expand Down Expand Up @@ -99,8 +93,6 @@ def test_multi_geometry_encoding(device, geo_encoding_type):
from physicsnemo.models.domino.encodings import MultiGeometryEncoding
from physicsnemo.models.domino.model import get_activation

torch.manual_seed(0)

BATCH_SIZE = 1
N_MESH_POINTS = 50
GRID_RESOLUTION = (32, 32, 32)
Expand Down
6 changes: 0 additions & 6 deletions test/models/domino/test_domino_geometry_rep.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,6 @@ def test_geo_conv_out(device, act, fourier_features):
"""Test GeoConvOut layer"""
from physicsnemo.models.domino.geometry_rep import GeoConvOut

torch.manual_seed(0)

@dataclass
class TestParams:
base_neurons: int = 32
Expand Down Expand Up @@ -71,8 +69,6 @@ def test_geo_processor(device, act):
"""Test GeoProcessor CNN"""
from physicsnemo.models.domino.geometry_rep import GeoProcessor

torch.manual_seed(0)

@dataclass
class TestParams:
base_filters: int = 8
Expand All @@ -98,8 +94,6 @@ def test_geometry_rep(
"""Test GeometryRep module with different configurations"""
from physicsnemo.models.domino.geometry_rep import GeometryRep

torch.manual_seed(0)

# Modify params for this test
params = base_model_params()
params.geometry_encoding_type = geometry_encoding_type
Expand Down
4 changes: 0 additions & 4 deletions test/models/domino/test_domino_mlps.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,6 @@ def test_aggregation_model(device, activation):
from physicsnemo.models.domino.mlps import AggregationModel
from physicsnemo.models.domino.model import get_activation

torch.manual_seed(0)

model = AggregationModel(
input_features=100,
output_features=1,
Expand All @@ -47,8 +45,6 @@ def test_local_point_conv(device, activation):
from physicsnemo.models.domino.mlps import LocalPointConv
from physicsnemo.models.domino.model import get_activation

torch.manual_seed(0)

model = LocalPointConv(
input_features=50,
base_layer=128,
Expand Down
Loading