Domain: Physics — Condensed Matter Physics

Problem:
A stationary 3D fiber system is modeled by a Poisson–Boolean set of straight circular cylinders with constant radius \(r\), mean length \(\bar\ell\), fiber number intensity \(\lambda_F\) (mean fibers per unit volume), and a non-uniform axisymmetric orientation distribution given by a two-component Schladitz mixture. The expected contacts per fiber follow Toll’s estimate

\[ \lambda_{cF}\approx 4\lambda_F r \bar\ell \big[\bar\ell f_\psi + \pi r (g_\psi + 1)\big] \]

with

\[ f_\psi=\iint_{S^2\times S^2}\lvert p\times p'\rvert \psi(p)\psi(p')\,\mathrm{d}p\,\mathrm{d}p' \qquad g_\psi=\iint_{S^2\times S^2}\lvert p\cdot p'\rvert \psi(p)\psi(p')\,\mathrm{d}p\,\mathrm{d}p' . \]

Orientation model. For unit axis \(a\in S^2\) and anisotropy parameter \(\beta>0\), the Schladitz density on \(S^2\) (w.r.t. area measure \(\mathrm{d}p\)) is

\[ \psi_{\beta,a}(p)=\frac{1}{4\pi}\frac{\beta}{\big(1+(\beta^2-1)(a\cdot p)^2\big)^{3/2}} . \]

Let \(a_1=(0,0,1)\). Let \(a_2=R_0 a_1\), where \(R_0\) is the right-hand rotation by \(\theta_0=27^\circ\) about the \(x\)-axis,

\[ R_0=\begin{pmatrix} 1 & 0 & 0\\ 0 & \cos\theta_0 & -\sin\theta_0\\ 0 & \sin\theta_0 & \cos\theta_0 \end{pmatrix}. \]

Define the mixture

\[ \psi(p)=w \psi_{\beta_1,a_1}(p)+(1-w) \psi_{\beta_2,a_2}(p), \]

with parameters \(w=0.37\), \(\beta_1=0.58\), \(\beta_2=2.20\).

Numerical estimation of \((f_\psi,g_\psi)\) by deterministic, measure-weighted pairing on \(S^2\times S^2\).

1.  Generate \(N=300000\) spherical Fibonacci nodes \(\{q_i\}_{i=1}^N\subset S^2\) (deterministic lattice).

2.  Draw a single Haar-uniform rotation \(R\in\mathrm{SO}(3)\) from a PCG64 RNG seeded with \(195015\) using the unit-quaternion (Shoemake) construction: generate \(u_1,u_2,u_3\sim\mathrm{Unif}(0,1)\), set
   
\[ q_0=\sqrt{1-u_1},\quad q_1=\sqrt{u_1}, \]
 
\[ \mathbf{h}=(\sin 2\pi u_2,\cos 2\pi u_2,\sin 2\pi u_3,\cos 2\pi u_3), \]

\[ \text{quaternion }(x,y,z,w)=\big(q_1 h_1,\ q_1 h_2,\ q_0 h_3,\ q_0 h_4\big), \]

then convert to \(R\) (no additional random draws). Rotate nodes: \(p_i=R q_i\).

3.  Using the same RNG instance, create an independent random permutation \(\pi\) of \(\{1,\dots,N\}\) and set \(p'_i=p_{\pi(i)}\).

4.  Importance weights for the mixture density (since the nodes sample the uniform density \(1/(4\pi)\)):
    \(w_i=4\pi \psi(p_i)\), \(w'_i=4\pi \psi(p'_i)\).

5.  Compute

\[ \widehat f_\psi=\frac{\sum_{i=1}^N w_i w'_i \lvert p_i\times p'_i\rvert}{\sum_{i=1}^N w_i w'_i}, \qquad \widehat g_\psi=\frac{\sum_{i=1}^N w_i w'_i \lvert p_i\cdot p'_i\rvert}{\sum_{i=1}^N w_i w'_i}. \]

Parameters (dimensionless): \(r=1.000\), \(\bar\ell=1.000\), \(\lambda_F=1.00\times 10^{-2}\).

Using double precision and the exact steps above, compute \(\lambda_{cF}\) by plugging \((\widehat f_\psi,\widehat g_\psi)\) into Toll’s expression. Print a single number, the final \(\lambda_{cF}\), rounded to three decimals.

Answer: \(0.221\)

Solution code:
import numpy as np
from numpy.random import Generator, PCG64

# Parameters
N = 300000
w = 0.37
beta1 = 0.58
beta2 = 2.20
theta0 = np.deg2rad(27)
r = 1.0
ell_bar = 1.0
lambda_F = 0.01

# Define axes
a1 = np.array([0.0, 0.0, 1.0])
R0 = np.array([[1, 0, 0],
               [0, np.cos(theta0), -np.sin(theta0)],
               [0, np.sin(theta0), np.cos(theta0)]])
a2 = R0 @ a1

# Step 1: Generate spherical Fibonacci nodes
i = np.arange(N) + 0.5
theta = np.arccos(1 - 2*i/N)
phi = np.pi * (1 + np.sqrt(5)) * i
q = np.column_stack([np.sin(theta)*np.cos(phi), 
                     np.sin(theta)*np.sin(phi), 
                     np.cos(theta)])

# Step 2: Generate random rotation with seed 195015
rng = Generator(PCG64(195015))
u1, u2, u3 = rng.uniform(0, 1, 3)

# Quaternion construction
q0 = np.sqrt(1 - u1)
q1 = np.sqrt(u1)
h = [np.sin(2*np.pi*u2), np.cos(2*np.pi*u2),
     np.sin(2*np.pi*u3), np.cos(2*np.pi*u3)]

# Quaternion components (x, y, z, w)
qx = q1 * h[0]
qy = q1 * h[1]
qz = q0 * h[2]
qw = q0 * h[3]

# Convert to rotation matrix
R = np.array([[1-2*(qy**2+qz**2), 2*(qx*qy-qz*qw), 2*(qx*qz+qy*qw)],
              [2*(qx*qy+qz*qw), 1-2*(qx**2+qz**2), 2*(qy*qz-qx*qw)],
              [2*(qx*qz-qy*qw), 2*(qy*qz+qx*qw), 1-2*(qx**2+qy**2)]])

# Rotate nodes
p = (R @ q.T).T

# Step 3: Create random permutation
perm = rng.permutation(N)
p_prime = p[perm]

# Step 4: Calculate importance weights
def schladitz_density(points, beta, a):
    dot_prod = points @ a
    denom = (1 + (beta**2 - 1) * dot_prod**2)**1.5
    return beta / (4 * np.pi * denom)

# Mixture density values
psi_vals = w * schladitz_density(p, beta1, a1) + (1-w) * schladitz_density(p, beta2, a2)
psi_prime_vals = w * schladitz_density(p_prime, beta1, a1) + (1-w) * schladitz_density(p_prime, beta2, a2)

# Importance weights
w_i = 4 * np.pi * psi_vals
w_i_prime = 4 * np.pi * psi_prime_vals

# Step 5: Compute estimates
cross_norms = np.linalg.norm(np.cross(p, p_prime), axis=1)
abs_dots = np.abs(np.sum(p * p_prime, axis=1))

combined_weights = w_i * w_i_prime
weight_sum = np.sum(combined_weights)

f_psi_hat = np.sum(combined_weights * cross_norms) / weight_sum
g_psi_hat = np.sum(combined_weights * abs_dots) / weight_sum

# Calculate lambda_cF using Toll's formula
lambda_cF = 4 * lambda_F * r * ell_bar * (ell_bar * f_psi_hat + np.pi * r * (g_psi_hat + 1))
print(lambda_cF)