Skip to content

Commit 9d1e554

Browse files
committed
[Iter 96] Code modification in PDE_D.py
[Automated commit by Claude]
1 parent 0a9bc98 commit 9d1e554

1 file changed

Lines changed: 61 additions & 1 deletion

File tree

src/ParticleGraph/generators/PDE_D.py

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@ class PDE_D(pyg.nn.MessagePassing):
2929
{"index": 2, "name": "A", "description": "Brusselator param A (used by mesh model)", "typical_range": [0.5, 5.0]},
3030
{"index": 3, "name": "B", "description": "Brusselator param B (used by mesh model)", "typical_range": [1.0, 10.0]},
3131
{"index": 4, "name": "mu", "description": "Morphological parameter (used by mesh model)", "typical_range": [0.01, 0.1]},
32-
{"index": 5, "name": "M1", "description": "Mobility coefficient for C1 gradients", "typical_range": [-16, 16]}
32+
{"index": 5, "name": "M1", "description": "Mobility coefficient for C1 gradients", "typical_range": [-16, 16]},
33+
{"index": 6, "name": "fdm_alpha", "description": "Field-dependent mobility strength (0=off, >0=faster at peaks, <0=slower at peaks)", "typical_range": [-2.0, 2.0]}
3334
]
3435
},
3536
{
@@ -202,6 +203,37 @@ def __init__(self, aggr_type='mean', p=None, particle_params=None, bc_dpos=None,
202203
else:
203204
self.alignment_strength = 0.0
204205

206+
# Block 13 code change: Field-dependent mobility (FDM)
207+
# p[0, 6] controls fdm_alpha (field-dependent mobility strength):
208+
# 0.0 = constant mobility (backward compatible, default)
209+
# >0 = M_eff = M * (1 + fdm_alpha * clamp((C1-A)^2/A^2, max=4.0))
210+
# Particles move FASTER at field peaks/troughs (far from steady state)
211+
# and SLOWER near the Brusselator steady state (C1 ≈ A)
212+
# <0 = M_eff = M / (1 + |fdm_alpha| * clamp((C1-A)^2/A^2, max=4.0))
213+
# Particles move SLOWER at field peaks/troughs and FASTER near steady state
214+
# Literature: Hillen & Painter (2009) J Math Biol 58:183-217
215+
# "A user's guide to PDE models for chemotaxis" — concentration-dependent
216+
# chemotactic sensitivity chi(C) is standard in Keller-Segel family models.
217+
# Also: Painter & Hillen (2002) Can Appl Math Q 10:501-543 — volume-filling
218+
# chemotaxis where cells move slower in crowded (high-concentration) regions.
219+
# Rationale: The 7/10 ceiling (96 iterations, Blocks 1-12) is a COUPLING
220+
# bottleneck: particles respond uniformly to gradients. FDM creates nonlinear
221+
# coupling where accumulation dynamics depend on local field state, enabling
222+
# multi-scale organization (tight clusters at peaks, dispersed at boundaries).
223+
# Effect: With positive alpha, particles accumulate more strongly at Turing peaks
224+
# (where C1 >> A) because their mobility is amplified there. This creates
225+
# positive feedback: peaks attract particles faster → particles consume C1 →
226+
# pattern reorganizes. With negative alpha, particles are more mobile near
227+
# steady state and immobilized at peaks → smeared distributions.
228+
if p.shape[1] > 6:
229+
self.fdm_alpha = p[0, 6]
230+
else:
231+
self.fdm_alpha = 0.0
232+
233+
# Brusselator parameter A for FDM normalization
234+
# Stored from mesh params row 0, index 2
235+
self.A_ref = p[0, 2]
236+
205237
# Report configuration
206238
print(f"initialized PDE_D with parameters:")
207239
print(f"mobility: M₁={self.M1.item()}, M₂={self.M2.item()}")
@@ -255,6 +287,12 @@ def __init__(self, aggr_type='mean', p=None, particle_params=None, bc_dpos=None,
255287
print(f"velocity alignment (Vicsek): strength={align_val:.3f} (f_align = alpha*(v_j-v_i)*w(d), Vicsek 1995)")
256288
else:
257289
print(f"velocity alignment: off (strength=0)")
290+
if hasattr(self, 'fdm_alpha'):
291+
fdm_val = self.fdm_alpha.item() if hasattr(self.fdm_alpha, 'item') else self.fdm_alpha
292+
if fdm_val != 0:
293+
print(f"field-dependent mobility (FDM): alpha={fdm_val:.3f} (M_eff = M*(1+alpha*clamp((C1-A)^2/A^2,max=4)), Hillen & Painter 2009)")
294+
else:
295+
print(f"field-dependent mobility: off (alpha=0)")
258296
if particle_params is not None:
259297
print(f"multi-type support: {particle_params.shape[0]} particle types")
260298
print(f"per-type params: [M1, M2, consumption, production, ar_p1, ar_p2, ar_p3, ar_p4]")
@@ -451,6 +489,28 @@ def message(self, edge_index_i, edge_index_j, x_i, x_j, mode=None, parameters_i=
451489
v_perp[:, 1] = velocity_raw[:, 0] # +vx
452490
velocity_raw = velocity_raw + self.chirality * v_perp
453491

492+
# Block 13: Field-dependent mobility (FDM)
493+
# Hillen & Painter (2009): concentration-dependent chemotactic sensitivity
494+
# M_eff depends on local C1 value relative to Brusselator steady state A.
495+
# Positive alpha: particles move faster at peaks/troughs (far from A)
496+
# Negative alpha: particles move slower at peaks/troughs (immobilized at features)
497+
# Uses (C1 - A)^2 / A^2 as dimensionless deviation, clamped for stability.
498+
if hasattr(self, 'fdm_alpha') and self.fdm_alpha != 0:
499+
C1_local = fields_i[:, 0:1] # Local C1 at particle position
500+
A_ref = self.A_ref
501+
# Dimensionless squared deviation from steady state
502+
deviation_sq = (C1_local - A_ref) ** 2 / (A_ref ** 2 + 1e-6)
503+
deviation_sq = torch.clamp(deviation_sq, max=4.0)
504+
505+
if self.fdm_alpha > 0:
506+
# Positive: amplify mobility at peaks/troughs
507+
fdm_factor = 1.0 + self.fdm_alpha * deviation_sq
508+
else:
509+
# Negative: suppress mobility at peaks/troughs
510+
fdm_factor = 1.0 / (1.0 + torch.abs(self.fdm_alpha) * deviation_sq)
511+
512+
velocity_raw = velocity_raw * fdm_factor
513+
454514
velocities = velocity_raw
455515

456516
return velocities

0 commit comments

Comments
 (0)