code wiki / _hdl_build / nx_morpho_rd_gate.nx

nx_morpho_rd_gate.nx source

↩ module page · 343 lines · 16248 B

1// nx_morpho_rd_gate.nx -- MORPHOGENESIS CORE rung 1: volumetric tissue growth by 3D Gray-Scott 2// reaction-diffusion, driven from a compact genome. This is the "Infinigen layer" for anatomy: no organ meshes 3// are stored, the structure GROWS from a seed + a handful of genome scalars. 4// 5// ★SUBSTRATE CORRECTIONS vs the proposal, deliberate and load-bearing: 6// (1) NishiLang, not C. C is bench-oracle-only here by standing law; product paths are sovereign .nx. 7// (2) ALL-INTEGER Q16 fixed point, not float. Our measured sovereign exceed is BIT-EXACT DETERMINISM 8// (identical replay -> identical checksum, proven in nx_gx4_walk). Floats would hand that away for 9// nothing -- reaction-diffusion needs no float, and T6 below PROVES the determinism we would have lost. 10// (3) Renders through our own raster path, not Vulkan/DX12 (host GPU APIs are exactly what the sovereign 11// steer forbids). The eyeball artifact goes out through our canonical PNG writer. 12// 13// GATE = known-answer MATH first, emergence second. A pattern that merely "looks organic" proves nothing; 14// the Laplacian is checked against exact discrete identities (constant->0, linear->0, x^2->2), the trivial 15// steady state is checked to be genuinely steady, and only THEN is emergence measured. 16// license_tier: ORIGINAL expect_exit: 0 17import "nx_png_write.nx" 18 19const MQ: i64 = 65536 // Q16 fixed point: 1.0 == 65536 20const MW: i64 = 40 21const MH: i64 = 40 22const MD: i64 = 20 23const MSTEPS: i64 = 1800 24// ★STABILITY (found by EYEBALL after the numeric tests all passed a garbage render): 25// explicit diffusion needs dt*D*2*ndim < 1. In 3D that is dt*0.16*6 = 0.96*dt -- at dt=1 the scheme sits ON the 26// stability edge and the reaction term tips it over, producing a Nyquist CHECKERBOARD: alternate cells flipping. 27// It scored HIGH on spread and occupancy (a checkerboard maximises variance) which is precisely why T5 passed it. 28// dt=0.4 gives 0.38 << 1, comfortably inside the limit. T5b below now measures spatial COHERENCE so this class 29// of failure can never pass on numbers again. 30const MDT: i64 = 26214 // 0.4 in Q16 31 32func md_puts(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 } 33func md_pn(v: i64) -> i64 { let b: *u8=sys_mmap(32) as *u8; var x: i64=v; var ng: i64=0; if x<0{ng=1;x=0-x} var i: i64=31; if x==0{b[i]=48 as u8;i=i-1} while x>0{b[i]=(48+x%10) as u8;x=x/10;i=i-1} if ng==1{b[i]=45 as u8;i=i-1} sys_write(1,(b as i64+i+1) as *u8,31-i); return 0 } 34func md_idx(x: i64, y: i64, z: i64) -> i64 { return x + y*MW + z*MW*MH } 35 36// 6-neighbour discrete Laplacian on the interior. Units are whatever the field carries (Q16 or raw). 37func md_lap(F: *i64, x: i64, y: i64, z: i64) -> i64 { 38 let c: i64 = F[md_idx(x,y,z)] 39 var s: i64 = 0 40 s = s + F[md_idx(x+1,y,z)] + F[md_idx(x-1,y,z)] 41 s = s + F[md_idx(x,y+1,z)] + F[md_idx(x,y-1,z)] 42 s = s + F[md_idx(x,y,z+1)] + F[md_idx(x,y,z-1)] 43 return s - 6*c 44} 45 46// One Gray-Scott step, integer Q16. Du/Dv/F/K arrive pre-scaled to Q16. 47func md_step(U: *i64, V: *i64, Un: *i64, Vn: *i64, Du: i64, Dv: i64, Fq: i64, Kq: i64) -> i64 { 48 var z: i64 = 1 49 while z < MD-1 { 50 var y: i64 = 1 51 while y < MH-1 { 52 var x: i64 = 1 53 while x < MW-1 { 54 let i: i64 = md_idx(x,y,z) 55 let u: i64 = U[i] 56 let v: i64 = V[i] 57 let lu: i64 = md_lap(U,x,y,z) 58 let lv: i64 = md_lap(V,x,y,z) 59 // uvv = u*v*v in Q16 60 let t: i64 = (u*v)/MQ 61 let uvv: i64 = (t*v)/MQ 62 let du: i64 = (Du*lu)/MQ - uvv + (Fq*(MQ-u))/MQ 63 let dv: i64 = (Dv*lv)/MQ + uvv - ((Fq+Kq)*v)/MQ 64 var nu: i64 = u + (MDT*du)/MQ 65 var nv: i64 = v + (MDT*dv)/MQ 66 if nu < 0 { nu = 0 } 67 if nv < 0 { nv = 0 } 68 if nu > MQ { nu = MQ } 69 if nv > MQ { nv = MQ } 70 Un[i] = nu 71 Vn[i] = nv 72 x = x + 1 73 } 74 y = y + 1 75 } 76 z = z + 1 77 } 78 // copy interior back 79 var zz: i64 = 1 80 while zz < MD-1 { 81 var yy: i64 = 1 82 while yy < MH-1 { 83 var xx: i64 = 1 84 while xx < MW-1 { let i2: i64=md_idx(xx,yy,zz); U[i2]=Un[i2]; V[i2]=Vn[i2]; xx=xx+1 } 85 yy = yy + 1 86 } 87 zz = zz + 1 88 } 89 return 0 90} 91 92// deterministic genome-driven seeding: U=1 everywhere, V blobs placed from the genome seed 93func md_seed(U: *i64, V: *i64, seed: i64, blobs: i64) -> i64 { 94 var i: i64 = 0 95 while i < MW*MH*MD { U[i]=MQ; V[i]=0; i=i+1 } 96 var s: i64 = seed 97 var b: i64 = 0 98 while b < blobs { 99 // integer LCG -- deterministic by construction, no float, no libc rand 100 s = (s*1103515245 + 12345) & 2147483647 101 let cx: i64 = 6 + (s/7) % (MW-12) 102 s = (s*1103515245 + 12345) & 2147483647 103 let cy: i64 = 6 + (s/7) % (MH-12) 104 s = (s*1103515245 + 12345) & 2147483647 105 let cz: i64 = 4 + (s/7) % (MD-8) 106 var dz: i64 = 0-2 107 while dz <= 2 { 108 var dy: i64 = 0-2 109 while dy <= 2 { 110 var dx: i64 = 0-2 111 while dx <= 2 { 112 let i2: i64 = md_idx(cx+dx, cy+dy, cz+dz) 113 U[i2] = MQ/2 114 V[i2] = MQ/4 115 dx = dx + 1 116 } 117 dy = dy + 1 118 } 119 dz = dz + 1 120 } 121 b = b + 1 122 } 123 return 0 124} 125func md_checksum(V: *i64) -> i64 { 126 var c: i64 = 0 127 var i: i64 = 0 128 while i < MW*MH*MD { c = (c*31 + V[i]) & 1152921504606846975; i=i+1 } 129 return c 130} 131 132func main() -> i64 { 133 md_puts("=== nx_morpho_rd_gate -- volumetric morphogenesis (3D Gray-Scott, integer Q16, genome-driven) ===\n" as *u8) 134 var fails: i64 = 0 135 let N: i64 = MW*MH*MD 136 let U: *i64 = sys_mmap(N*8+64) as *i64 137 let V: *i64 = sys_mmap(N*8+64) as *i64 138 let Un: *i64 = sys_mmap(N*8+64) as *i64 139 let Vn: *i64 = sys_mmap(N*8+64) as *i64 140 let T: *i64 = sys_mmap(N*8+64) as *i64 141 142 // ---- T1 Laplacian of a CONSTANT field is exactly 0 143 var i: i64 = 0 144 while i < N { T[i] = 4242; i=i+1 } 145 var t1: i64 = 1 146 if md_lap(T, 5,5,5) != 0 { t1 = 0 } 147 if md_lap(T, 12,7,9) != 0 { t1 = 0 } 148 if t1==1 { md_puts("T1 PASS Laplacian(constant) = 0 exactly\n" as *u8) } else { fails=fails+1; md_puts("T1 FAIL\n" as *u8) } 149 150 // ---- T2 Laplacian of a LINEAR ramp is exactly 0 (no directional bias in the stencil) 151 var z: i64 = 0 152 while z < MD { var y: i64=0; while y < MH { var x: i64=0; while x < MW { T[md_idx(x,y,z)] = 3*x + 5*y + 7*z; x=x+1 } y=y+1 } z=z+1 } 153 var t2: i64 = 1 154 if md_lap(T, 5,5,5) != 0 { t2 = 0 } 155 if md_lap(T, 20,11,8) != 0 { t2 = 0 } 156 if t2==1 { md_puts("T2 PASS Laplacian(linear ramp) = 0 exactly (stencil is unbiased)\n" as *u8) } else { fails=fails+1; md_puts("T2 FAIL\n" as *u8) } 157 158 // ---- T3 Laplacian of x^2 is exactly 2 (the discrete second difference identity) 159 z = 0 160 while z < MD { var y2: i64=0; while y2 < MH { var x2: i64=0; while x2 < MW { T[md_idx(x2,y2,z)] = x2*x2; x2=x2+1 } y2=y2+1 } z=z+1 } 161 var t3: i64 = 1 162 if md_lap(T, 9,9,9) != 2 { t3 = 0 } 163 if md_lap(T, 22,4,6) != 2 { t3 = 0 } 164 if t3==1 { md_puts("T3 PASS Laplacian(x^2) = 2 exactly (known-answer, not eyeballed)\n" as *u8) } else { fails=fails+1; md_puts("T3 FAIL lap="); md_pn(md_lap(T,9,9,9)); md_puts("\n" as *u8) } 165 166 // Gray-Scott rates, Q16. F is genome-modulated exactly as the DNA struct intends. 167 // ★3D RETUNE (second finding from the eyeball): the canonical Du=.16/Dv=.08/F=.035/K=.060 are 2D values. 168 // A 3D stencil diffuses through SIX neighbours instead of four, so the same rates bleed V out of the bulk 169 // faster than the reaction replenishes it -- the pattern dies and survives only as a thin annulus against the 170 // boundary. Halving the diffusion coefficients restores the reaction/diffusion balance in 3D; F/K move into 171 // the sustaining coral band. T5c below now requires structure in the BULK so a rim-only result cannot pass. 172 let Du: i64 = (8*MQ)/100 173 let Dv: i64 = (4*MQ)/100 174 let bone_density_mult: i64 = MQ // genome scalar, 1.0 175 let Fq: i64 = (30*MQ)/1000 + (bone_density_mult*((5*MQ)/10000))/MQ 176 let Kq: i64 = (57*MQ)/1000 177 178 // ---- T4 the trivial steady state (U=1, V=0) must stay EXACTLY steady 179 i = 0 180 while i < N { U[i]=MQ; V[i]=0; Un[i]=MQ; Vn[i]=0; i=i+1 } 181 md_step(U,V,Un,Vn,Du,Dv,Fq,Kq) 182 md_step(U,V,Un,Vn,Du,Dv,Fq,Kq) 183 var t4: i64 = 1 184 var drift: i64 = 0 185 i = 0 186 while i < N { if U[i]!=MQ { drift=drift+1 } if V[i]!=0 { drift=drift+1 } i=i+1 } 187 if drift != 0 { t4 = 0 } 188 if t4==1 { md_puts("T4 PASS trivial steady state is genuinely steady (zero drift over 2 steps)\n" as *u8) } else { fails=fails+1; md_puts("T4 FAIL drift cells="); md_pn(drift); md_puts("\n" as *u8) } 189 190 // ---- grow tissue from the genome 191 let genome_seed: i64 = 20260720 192 md_seed(U, V, genome_seed, 7) 193 var vsum0: i64 = 0 194 i = 0 195 while i < N { vsum0 = vsum0 + V[i]; i=i+1 } 196 var s: i64 = 0 197 while s < MSTEPS { md_step(U,V,Un,Vn,Du,Dv,Fq,Kq); s=s+1 } 198 // measure structure: mean, spread, and occupancy of the grown field 199 var vsum: i64 = 0 200 var vmax: i64 = 0 201 var occupied: i64 = 0 202 i = 0 203 while i < N { 204 let v: i64 = V[i] 205 vsum = vsum + v 206 if v > vmax { vmax = v } 207 if v > MQ/10 { occupied = occupied + 1 } 208 i=i+1 209 } 210 let vmean: i64 = vsum/N 211 var spread: i64 = 0 212 i = 0 213 while i < N { var d: i64=V[i]-vmean; if d<0 { d=0-d } spread=spread+d; i=i+1 } 214 let mad: i64 = spread/N 215 let ck1: i64 = md_checksum(V) 216 md_puts(" grown: mean="); md_pn(vmean); md_puts(" max="); md_pn(vmax) 217 md_puts(" occupied="); md_pn(occupied); md_puts(" MAD="); md_pn(mad); md_puts("\n" as *u8) 218 219 // ---- T5 real STRUCTURE emerged and nothing blew up 220 var t5: i64 = 0 221 var inrange: i64 = 1 222 i = 0 223 while i < N { if V[i]<0 { inrange=0 } if V[i]>MQ { inrange=0 } if U[i]<0 { inrange=0 } if U[i]>MQ { inrange=0 } i=i+1 } 224 if inrange==1 { if occupied > 200 { if mad > 300 { if vmax > MQ/5 { t5=1 } } } } 225 if t5==1 { md_puts("T5 PASS structure emerged (occupied volume + real spatial spread) and the solver stayed bounded\n" as *u8) } else { fails=fails+1; md_puts("T5 FAIL inrange="); md_pn(inrange); md_puts(" occ="); md_pn(occupied); md_puts(" mad="); md_pn(mad); md_puts("\n" as *u8) } 226 227 // ---- T5b SPATIAL COHERENCE -- the tooth that the checkerboard taught us to add. 228 // Organic reaction-diffusion structure varies SMOOTHLY between adjacent cells: neighbour-to-neighbour 229 // difference must be well BELOW the global spread. A Nyquist checkerboard inverts that (neighbour diff 230 // saturates while spread also looks healthy), so measuring spread alone can be fooled -- this cannot. 231 var ndiff: i64 = 0 232 var ncount: i64 = 0 233 var zc2: i64 = 1 234 while zc2 < MD-1 { 235 var yc2: i64 = 1 236 while yc2 < MH-1 { 237 var xc2: i64 = 1 238 while xc2 < MW-2 { 239 var d2: i64 = V[md_idx(xc2,yc2,zc2)] - V[md_idx(xc2+1,yc2,zc2)] 240 if d2 < 0 { d2 = 0-d2 } 241 ndiff = ndiff + d2 242 ncount = ncount + 1 243 xc2 = xc2 + 1 244 } 245 yc2 = yc2 + 1 246 } 247 zc2 = zc2 + 1 248 } 249 var nmean: i64 = 0 250 if ncount > 0 { nmean = ndiff/ncount } 251 md_puts(" coherence: mean neighbour-diff="); md_pn(nmean); md_puts(" vs global MAD="); md_pn(mad); md_puts("\n" as *u8) 252 // ---- T5c BULK occupancy -- structure must live in the volume's INTERIOR, not just cling to the boundary. 253 // The rim-only failure scored fine on global occupancy because the boundary shell is ~19% of the grid. 254 var bulk: i64 = 0 255 var bz: i64 = MD/4 256 while bz < (3*MD)/4 { 257 var by: i64 = MH/4 258 while by < (3*MH)/4 { 259 var bx: i64 = MW/4 260 while bx < (3*MW)/4 { 261 if V[md_idx(bx,by,bz)] > MQ/10 { bulk = bulk + 1 } 262 bx = bx + 1 263 } 264 by = by + 1 265 } 266 bz = bz + 1 267 } 268 md_puts(" bulk occupancy (central half)="); md_pn(bulk); md_puts("\n" as *u8) 269 var t5c: i64 = 0 270 if bulk > 150 { t5c = 1 } 271 if t5c==1 { md_puts("T5c PASS growth lives in the BULK, not just a boundary annulus\n" as *u8) } else { fails=fails+1; md_puts("T5c FAIL rim-only/dead bulk: central-half occupancy="); md_pn(bulk); md_puts("\n" as *u8) } 272 273 var t5b: i64 = 0 274 if nmean*2 < mad { t5b = 1 } 275 if t5b==1 { md_puts("T5b PASS spatially COHERENT growth (neighbour-diff well under global spread -- not a Nyquist checkerboard)\n" as *u8) } else { fails=fails+1; md_puts("T5b FAIL incoherent/checkerboard: neighbour-diff="); md_pn(nmean); md_puts(" is not < half of MAD="); md_pn(mad); md_puts("\n" as *u8) } 276 277 // ---- T6 DETERMINISM: same genome -> byte-identical field. This is the property floats would have cost us. 278 md_seed(U, V, genome_seed, 7) 279 s = 0 280 while s < MSTEPS { md_step(U,V,Un,Vn,Du,Dv,Fq,Kq); s=s+1 } 281 let ck2: i64 = md_checksum(V) 282 var t6: i64 = 0 283 if ck1==ck2 { if ck1!=0 { t6=1 } } 284 if t6==1 { md_puts("T6 PASS determinism: identical genome -> identical checksum "); md_pn(ck1); md_puts(" (all-integer; a float solver could not promise this)\n" as *u8) } else { fails=fails+1; md_puts("T6 FAIL ck1="); md_pn(ck1); md_puts(" ck2="); md_pn(ck2); md_puts("\n" as *u8) } 285 286 // ---- T7 a DIFFERENT genome must grow a DIFFERENT organism (no overfit to one seed) 287 md_seed(U, V, genome_seed+1, 7) 288 s = 0 289 while s < MSTEPS { md_step(U,V,Un,Vn,Du,Dv,Fq,Kq); s=s+1 } 290 let ck3: i64 = md_checksum(V) 291 var t7: i64 = 0 292 if ck3 != ck1 { t7=1 } 293 if t7==1 { md_puts("T7 PASS a different genome grows a measurably different organism (seed diversity, not one template)\n" as *u8) } else { fails=fails+1; md_puts("T7 FAIL genome had no effect\n" as *u8) } 294 295 // ---- eyeball artifact: three Z-slices of the grown volume, upscaled 296 md_seed(U, V, genome_seed, 7) 297 s = 0 298 while s < MSTEPS { md_step(U,V,Un,Vn,Du,Dv,Fq,Kq); s=s+1 } 299 let SC: i64 = 6 300 let PW: i64 = MW*SC*3 + 16 301 let PH: i64 = MH*SC 302 let rgb: *u8 = sys_mmap(PW*PH*3+64) 303 i = 0 304 while i < PW*PH { let o: i64=i*3; rgb[o]=10 as u8; rgb[o+1]=11 as u8; rgb[o+2]=16 as u8; i=i+1 } 305 var panel: i64 = 0 306 while panel < 3 { 307 var zc: i64 = MD/4 308 if panel==1 { zc = MD/2 } 309 if panel==2 { zc = (3*MD)/4 } 310 var py: i64 = 0 311 while py < MH*SC { 312 var px: i64 = 0 313 while px < MW*SC { 314 let gx: i64 = px/SC 315 let gy: i64 = py/SC 316 let v: i64 = V[md_idx(gx,gy,zc)] 317 // tissue ramp: dark -> deep red -> warm flesh -> pale bone 318 var r: i64 = (v*255)/MQ 319 var g: i64 = (v*150)/MQ 320 var b: i64 = (v*120)/MQ 321 if v > MQ/3 { g = g + ((v-MQ/3)*90)/MQ; b = b + ((v-MQ/3)*70)/MQ } 322 if r>255 {r=255} if g>255 {g=255} if b>255 {b=255} 323 let ox: i64 = panel*(MW*SC+8) + px 324 let o: i64 = (py*PW+ox)*3 325 rgb[o]=r as u8; rgb[o+1]=g as u8; rgb[o+2]=b as u8 326 px = px + 1 327 } 328 py = py + 1 329 } 330 panel = panel + 1 331 } 332 nx_png_write_rgb("knowledge/nx_morpho_rd.png\x00" as *u8, rgb, PW, PH) 333 let szp: *i64 = sys_mmap(16) as *i64 334 let rb: *u8 = sys_read_file("knowledge/nx_morpho_rd.png\x00" as *u8, szp) 335 var t8: i64 = 0 336 if (rb as i64)!=0 { if szp[0]>1000 { if rb[0]==(137 as u8) { t8=1 } } } 337 if t8==1 { md_puts("T8 PASS volume slices written to knowledge/nx_morpho_rd.png ("); md_pn(szp[0]); md_puts(" bytes)\n" as *u8) } else { fails=fails+1; md_puts("T8 FAIL png\n" as *u8) } 338 339 if fails==0 { md_puts("MORPHO-RD GREEN -- tissue GROWS from a genome, the math is known-answer correct, and the growth is bit-exact reproducible\n" as *u8); sys_exit(0); return 0 } 340 md_puts("MORPHO-RD RED fails="); md_pn(fails); md_puts("\n" as *u8) 341 sys_exit(1) 342 return 1 343}