Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Jan 15, 2026

Implements Boussinesq point load solution for elastic half-space, parallel to existing Brazil test in disk.py. Generates synthetic stress fields and RGB polarized images for elastic contact problems.

Implementation

  • photoelastimetry/elastic.py: Core module with analytical Boussinesq solution

    • boussinesq_stress_cartesian(): Computes σ_xx, σ_yy, τ_xy for point load P on semi-infinite half-space
    • generate_synthetic_boussinesq(): Produces synthetic photoelastic images via Mueller matrix formalism
    • post_process_synthetic_data(): 16-panel visualization (stress components, fringes, polarimetry)
    • Enforces boundary condition (zero stress above surface y < 0)
  • json/elastic.json5: Configuration with material properties (C, thickness, wavelengths, Poisson's ratio)

  • tests/test_elastic.py: 9 tests covering stress computation, boundary conditions, synthetic image generation, parameter validation

Usage

from photoelastimetry.elastic import boussinesq_stress_cartesian

# Compute stress field for 100N point load
sigma_xx, sigma_yy, tau_xy = boussinesq_stress_cartesian(X, Y, P=100.0, nu_poisson=0.3)

Or run as script to generate TIFF outputs:

python -m photoelastimetry.elastic
# Creates images/elastic/boussinesq_synthetic_{stress,images}.tiff

Technical notes

  • Uses classical Boussinesq elasticity solution with singularity handling at load point
  • Consistent with disk.py architecture: analytical solution → stress field → Mueller matrices → polarized intensities
  • Supports configurable Poisson's ratio and multi-wavelength RGB imaging
Original prompt

add a new elastic.py file that will operate similarly to disk
pt, but for elastic solutions, let's start with the boussinesq point load on an elastic half space. when you run the file it should generate tiff files with synthetic images of the stress field and RGB polarised images.


💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.

Copilot AI and others added 3 commits January 15, 2026 20:35
Co-authored-by: benjym <3380296+benjym@users.noreply.github.com>
Co-authored-by: benjym <3380296+benjym@users.noreply.github.com>
Co-authored-by: benjym <3380296+benjym@users.noreply.github.com>
Copilot AI changed the title [WIP] Add elastic.py for Boussinesq point load on elastic half space Add elastic.py with Boussinesq point load solution for photoelastic simulations Jan 15, 2026
Copilot AI requested a review from benjym January 15, 2026 20:42
@benjym benjym marked this pull request as ready for review January 15, 2026 21:52
Copilot AI review requested due to automatic review settings January 15, 2026 21:52
@benjym benjym merged commit b4c398c into main Jan 15, 2026
5 of 12 checks passed
@benjym benjym deleted the copilot/add-elastic-py-file branch January 15, 2026 21:53
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds a new elastic.py module implementing the Boussinesq point load solution for elastic half-space photoelastic simulations, parallel to the existing Brazil test in disk.py. The implementation includes analytical stress field computation, synthetic image generation via Mueller matrix formalism, and comprehensive visualization tools.

Changes:

  • New analytical elastic solution module with Boussinesq stress computation
  • Configuration file for elastic simulation parameters
  • Comprehensive test suite with 9 test cases covering stress computation, boundary conditions, and parameter validation

Reviewed changes

Copilot reviewed 3 out of 4 changed files in this pull request and generated 4 comments.

File Description
photoelastimetry/elastic.py Core module implementing Boussinesq analytical solution, synthetic image generation, and 16-panel visualization
json/elastic.json5 Configuration file with material properties and simulation parameters
tests/test_elastic.py Test suite covering stress field computation, boundary conditions, and synthetic data generation
.gitignore Adds patterns for generated output files and images directory

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

def test_parameters():
"""Fixture providing standard test parameters."""
return {
"wavelengths_nm": np.array([650e-9, 550e-9, 450e-9]), # R, G, B wavelengths in meters
Copy link

Copilot AI Jan 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The variable name wavelengths_nm suggests nanometers, but the values are in meters (650e-9, 550e-9, 450e-9) and the comment confirms "in meters". This is inconsistent with the equivalent fixture in test_disk.py line 23 which correctly uses nanometer values (650, 550, 450) with the same variable name. The variable should either be renamed to wavelengths_m or the values should be changed to [650, 550, 450] to match the naming convention and be consistent with test_disk.py.

Copilot uses AI. Check for mistakes.
S_i_hat : [1.0, 0.0, 0.0], // Incoming polarization state
binning: 8,
wavelengths : [650, 550, 450], // R, G, B wavelengths (nm)
C : [3e-9, 3e-9, 3e-9], // stress-optic coefficient for each wavelength (1/Pa)
Copy link

Copilot AI Jan 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The stress-optic coefficient values [3e-9, 3e-9, 3e-9] are identical for all three wavelengths (R, G, B), which differs from the pattern in test fixtures and other JSON files that use wavelength-dependent values like [2e-12, 2.2e-12, 2.5e-12] in test_disk.py or json/test.json5. While this may be intentional, using identical C values removes the wavelength-dependent behavior that is typically expected in photoelastic simulations. Consider using wavelength-dependent values like [3e-9, 3.3e-9, 3.75e-9] to better represent realistic material dispersion, or add a comment explaining why identical values are appropriate for this elastic simulation.

Suggested change
C : [3e-9, 3e-9, 3e-9], // stress-optic coefficient for each wavelength (1/Pa)
C : [3e-9, 3.3e-9, 3.75e-9], // stress-optic coefficient for each wavelength (1/Pa)

Copilot uses AI. Check for mistakes.
height, width = sigma_xx.shape
n_wavelengths = len(wavelengths_nm)

synthetic_images = np.empty((height, width, n_wavelengths, 4)) # wavelengths, 4 polarizer angles
Copy link

Copilot AI Jan 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment says "wavelengths, 4 polarizer angles" but according to line 170 the hardcoded shape is (height, width, 3, 4) in disk.py, while here it dynamically uses n_wavelengths. The comment should be more explicit about the array dimensions, like "# (height, width, n_wavelengths, 4 polarizer angles)" to match the actual shape tuple for clarity.

Suggested change
synthetic_images = np.empty((height, width, n_wavelengths, 4)) # wavelengths, 4 polarizer angles
synthetic_images = np.empty((height, width, n_wavelengths, 4)) # (height, width, n_wavelengths, 4 polarizer angles)

Copilot uses AI. Check for mistakes.
height, width = sigma_xx.shape
n_wavelengths = len(wavelengths_nm)

synthetic_images = np.empty((height, width, n_wavelengths, 4)) # wavelengths, 4 polarizer angles
Copy link

Copilot AI Jan 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The array is initialized with np.empty() which leaves uninitialized memory. While this is immediately populated in the loop below, using np.zeros() would be safer and make debugging easier if the loop fails to populate all values. This is consistent with defensive programming practices, especially for arrays that will be saved to files.

Suggested change
synthetic_images = np.empty((height, width, n_wavelengths, 4)) # wavelengths, 4 polarizer angles
synthetic_images = np.zeros((height, width, n_wavelengths, 4)) # wavelengths, 4 polarizer angles

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants