From 2de213ed39ff19cce7f99bebb17d4a3aafc6226c Mon Sep 17 00:00:00 2001 From: Tim Hutton Date: Sun, 9 Aug 2015 15:28:46 +0100 Subject: [PATCH] Added Dan Wills' patterns to CMakeLists.txt and Help/changes.html. Fixed usual float/double issue for intolerant OpenCL drivers. --- CMakeLists.txt | 5 + Help/changes.html | 1 + ...historyWaveDC_dualPhaseSolitonWormFlow.vti | 29 ++- ...t-historyWaveDC_movingWormsAndSolitons.vti | 28 +- ...n-boiling-history-wave_glidersUnstable.vti | 32 +-- .../orbitsNova_buildAndDestroyBlobs.vti | 244 +++++++++--------- .../Experiments/DanWills/orbits_epochs.vti | 18 +- 7 files changed, 185 insertions(+), 172 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index dc3e0cc44..1455340d5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -177,6 +177,11 @@ set( PATTERN_FILES Patterns/Experiments/DanWills/orbits_explodey_init.vti Patterns/Experiments/DanWills/orbits_sharpWaves-init.vti Patterns/Experiments/DanWills/grayscott-historyWave_coralGrow.vti + Patterns/Experiments/DanWills/grayscott-historyWaveDC_movingWormsAndSolitons.vti + Patterns/Experiments/DanWills/orbitsNova_buildAndDestroyBlobs.vti + Patterns/Experiments/DanWills/orbits_epochs.vti + Patterns/Experiments/DanWills/grayscott-historyWaveDC_dualPhaseSolitonWormFlow.vti + Patterns/Experiments/DanWills/heat-equation-boiling-history-wave_glidersUnstable.vti Patterns/Experiments/SimonGladman/vermiformSolitons.vti Patterns/Experiments/TimHutton/LifeBlur.vti Patterns/Experiments/CornusAmmonis/MandelbrotWorms.vti diff --git a/Help/changes.html b/Help/changes.html index 74a8212d9..1da8a2dc9 100644 --- a/Help/changes.html +++ b/Help/changes.html @@ -48,6 +48,7 @@

Changes

  • gaussian-smoothlife.vti - a variant of Stephan Rafler's SmoothLife system with neighborhoods computed with 2-pass 1D gaussian convolution.
  • fast-mccabe.vti - McCabeism implemented with 2-pass 1D gaussian convolution.
  • From Dave Mann: smiley_faces.vti. +
  • Five new patterns from Dan Wills: grayscott-historyWaveDC_movingWormsAndSolitons.vti, orbitsNova_buildAndDestroyBlobs.vti, orbits_epochs.vti, grayscott-historyWaveDC_dualPhaseSolitonWormFlow.vti, heat-equation-boiling-history-wave_glidersUnstable.vti.
  • Fix for blank lines being inserted into files on every save.
  • Fix for font size problems with the color bar. diff --git a/Patterns/Experiments/DanWills/grayscott-historyWaveDC_dualPhaseSolitonWormFlow.vti b/Patterns/Experiments/DanWills/grayscott-historyWaveDC_dualPhaseSolitonWormFlow.vti index 94795ab16..1f4116f1f 100644 --- a/Patterns/Experiments/DanWills/grayscott-historyWaveDC_dualPhaseSolitonWormFlow.vti +++ b/Patterns/Experiments/DanWills/grayscott-historyWaveDC_dualPhaseSolitonWormFlow.vti @@ -2,15 +2,16 @@ -A gray-scott reaction-diffusion system is simulated in the a and b reagents, with two coupled simpler systems in c,d,e. -The c reagent implements a diffuse kind of 'history' of the other reagents (ie so that gliders can leave a 'trail'). -The d and e reagents implement the wave equation, with additional damping and shaping controls, which is fed by the other reagents (for example gliders can leave a rippley 'wake' behind them). -The extra reagents can feed back into the gray-scott ones, and also control the gray-scott parameters (including diffusion). -Implemented by Dan Wills (gdanzo@gmail.com) based on existing work in the Ready codebase. + A Gray-Scott reaction-diffusion system is simulated in the a and b reagents, with two coupled simpler systems in c,d,e. + The c reagent implements a diffuse kind of 'history' of the other reagents (ie so that gliders can leave a 'trail'). + The d and e reagents implement the wave equation, with additional damping and shaping controls, which is fed by the other reagents (for example gliders can leave a rippley 'wake' behind them). + The extra reagents can feed back into the Gray-Scott ones, and also control the Gray-Scott parameters (including diffusion). + + Implemented by Dan Wills (gdanzo@gmail.com) based on existing work in the Ready codebase. -This example starts as flowing maze-like growth which *usually* (not always) decays forming a flowing field of worms and solitons. When conditions are right, they switch back to this 'elevated' form of growth, that is both stronger growing and generally more maze-forming. The dynamic behaviour switching has an interesting long-term chaotic effect on the underlying behaviour, which would otherwise tend to end in a constant state or loop. + This example starts as flowing maze-like growth which *usually* (not always) decays forming a flowing field of worms and solitons. When conditions are right, they switch back to this 'elevated' form of growth, that is both stronger growing and generally more maze-forming. The dynamic behaviour switching has an interesting long-term chaotic effect on the underlying behaviour, which would otherwise tend to end in a constant state or loop. -There are very rare initial states that end up with the system stuck in the 'elevated' state, and it may stay that way for some time. So, if it looks flowing fingerprints and no dots for ages, you might need to generate a new initial state. + There are very rare initial states that end up with the system stuck in the 'elevated' state, and it may stay that way for some time. So, if it looks flowing fingerprints and no dots for ages, you might need to generate a new initial state. @@ -122,13 +123,13 @@ There are very rare initial states that end up with the system stuck in the 'ele 0.0056 - delta_a = (D_a + c*c_to_Da + (d-wave_DC_value)*wave_to_Da) * laplacian_a - pow(a,(float4)a_pow)*pow(b,(float4)b_pow) + (F + c_to_F*c + (d-wave_DC_value)*wave_to_F)*(1.0f-a) + c*c_to_a + (d-wave_DC_value)*wave_to_a; -delta_b = (D_b + c*c_to_Db + (d-wave_DC_value)*wave_to_Db) * laplacian_b + pow(a,(float4)a_pow)*pow(b,(float4)b_pow) - ((F + c_to_F*c + (d-wave_DC_value)*wave_to_F)+(k + c*c_to_k + (d-wave_DC_value)*wave_to_k))*b + c*c_to_b + (d-wave_DC_value)*wave_to_b; -delta_c = -c*c_damp + a*a_to_c + b*b_to_c + (d-wave_DC_value)*wave_to_c + D_c * laplacian_c; -c = clamp( pow( (float4)( fabs(c)/c_pow_norm ), (float4)c_pow )*c_pow_norm, c_clamp_min, c_clamp_max ); -d = wave_DC_value + clamp( sign(d-wave_DC_value) * pow( (float4)( fabs(d-wave_DC_value) * wave_damp), (float4)wave_power ) + a * a_to_wave + b * b_to_wave + c * c_to_wave, -wave_clamp, wave_clamp); -delta_e = (laplacian_d) * wave_diffusion; -delta_d = e + delta_e; + delta_a = (D_a + c*c_to_Da + (d-wave_DC_value)*wave_to_Da) * laplacian_a - pow(a,(float4)a_pow)*pow(b,(float4)b_pow) + (F + c_to_F*c + (d-wave_DC_value)*wave_to_F)*(1.0f-a) + c*c_to_a + (d-wave_DC_value)*wave_to_a; + delta_b = (D_b + c*c_to_Db + (d-wave_DC_value)*wave_to_Db) * laplacian_b + pow(a,(float4)a_pow)*pow(b,(float4)b_pow) - ((F + c_to_F*c + (d-wave_DC_value)*wave_to_F)+(k + c*c_to_k + (d-wave_DC_value)*wave_to_k))*b + c*c_to_b + (d-wave_DC_value)*wave_to_b; + delta_c = -c*c_damp + a*a_to_c + b*b_to_c + (d-wave_DC_value)*wave_to_c + D_c * laplacian_c; + c = clamp( pow( (float4)( fabs(c)/c_pow_norm ), (float4)c_pow )*c_pow_norm, c_clamp_min, c_clamp_max ); + d = wave_DC_value + clamp( sign(d-wave_DC_value) * pow( (float4)( fabs(d-wave_DC_value) * wave_damp), (float4)wave_power ) + a * a_to_wave + b * b_to_wave + c * c_to_wave, -wave_clamp, wave_clamp); + delta_e = (laplacian_d) * wave_diffusion; + delta_d = e + delta_e; diff --git a/Patterns/Experiments/DanWills/grayscott-historyWaveDC_movingWormsAndSolitons.vti b/Patterns/Experiments/DanWills/grayscott-historyWaveDC_movingWormsAndSolitons.vti index ae994bf94..bc09603d5 100644 --- a/Patterns/Experiments/DanWills/grayscott-historyWaveDC_movingWormsAndSolitons.vti +++ b/Patterns/Experiments/DanWills/grayscott-historyWaveDC_movingWormsAndSolitons.vti @@ -2,11 +2,15 @@ -A gray-scott reaction-diffusion system is simulated in the a and b reagents, with two coupled simpler systems in c,d,e. -The c reagent implements a diffuse kind of 'history' of the other reagents (ie so that gliders can leave a 'trail'). -The d and e reagents implement the wave equation, with additional damping and shaping controls, which is fed by the other reagents (for example gliders can leave a rippley 'wake' behind them). -The extra reagents can feed back into the gray-scott ones, and also control the gray-scott parameters (including diffusion). -Implemented by Dan Wills (gdanzo@gmail.com) based on earlier work from the Ready codebase. + A Gray-Scott reaction-diffusion system is simulated in the a and b reagents, with two coupled simpler systems in c,d,e. + + The c reagent implements a diffuse kind of 'history' of the other reagents (ie so that gliders can leave a 'trail'). + + The d and e reagents implement the wave equation, with additional damping and shaping controls, which is fed by the other reagents (for example gliders can leave a rippley 'wake' behind them). + + The extra reagents can feed back into the Gray-Scott ones, and also control the Gray-Scott parameters (including diffusion). + + Implemented by Dan Wills (gdanzo@gmail.com) based on earlier work from the Ready codebase. @@ -118,13 +122,13 @@ Implemented by Dan Wills (gdanzo@gmail.com) based on earlier work from the Ready 0 - delta_a = (D_a + c*c_to_Da + (d-wave_DC_value)*wave_to_Da) * laplacian_a - pow(a,(float4)a_pow)*pow(b,(float4)b_pow) + (F + c_to_F*c + (d-wave_DC_value)*wave_to_F)*(1.0f-a) + c*c_to_a + (d-wave_DC_value)*wave_to_a; -delta_b = (D_b + c*c_to_Db + (d-wave_DC_value)*wave_to_Db) * laplacian_b + pow(a,(float4)a_pow)*pow(b,(float4)b_pow) - ((F + c_to_F*c + (d-wave_DC_value)*wave_to_F)+(k + c*c_to_k + (d-wave_DC_value)*wave_to_k))*b + c*c_to_b + (d-wave_DC_value)*wave_to_b; -delta_c = -c*c_damp + a*a_to_c + b*b_to_c + (d-wave_DC_value)*wave_to_c + D_c * laplacian_c; -c = clamp( pow( (float4)( fabs(c)/c_pow_norm ), (float4)c_pow )*c_pow_norm, c_clamp_min, c_clamp_max ); -d = wave_DC_value + clamp( sign(d-wave_DC_value) * pow( (float4)( fabs(d-wave_DC_value) * wave_damp), (float4)wave_power ) + a * a_to_wave + b * b_to_wave + c * c_to_wave, -wave_clamp, wave_clamp); -delta_e = (laplacian_d) * wave_diffusion; -delta_d = e + delta_e; + delta_a = (D_a + c*c_to_Da + (d-wave_DC_value)*wave_to_Da) * laplacian_a - pow(a,(float4)a_pow)*pow(b,(float4)b_pow) + (F + c_to_F*c + (d-wave_DC_value)*wave_to_F)*(1.0f-a) + c*c_to_a + (d-wave_DC_value)*wave_to_a; + delta_b = (D_b + c*c_to_Db + (d-wave_DC_value)*wave_to_Db) * laplacian_b + pow(a,(float4)a_pow)*pow(b,(float4)b_pow) - ((F + c_to_F*c + (d-wave_DC_value)*wave_to_F)+(k + c*c_to_k + (d-wave_DC_value)*wave_to_k))*b + c*c_to_b + (d-wave_DC_value)*wave_to_b; + delta_c = -c*c_damp + a*a_to_c + b*b_to_c + (d-wave_DC_value)*wave_to_c + D_c * laplacian_c; + c = clamp( pow( (float4)( fabs(c)/c_pow_norm ), (float4)c_pow )*c_pow_norm, c_clamp_min, c_clamp_max ); + d = wave_DC_value + clamp( sign(d-wave_DC_value) * pow( (float4)( fabs(d-wave_DC_value) * wave_damp), (float4)wave_power ) + a * a_to_wave + b * b_to_wave + c * c_to_wave, -wave_clamp, wave_clamp); + delta_e = (laplacian_d) * wave_diffusion; + delta_d = e + delta_e; diff --git a/Patterns/Experiments/DanWills/heat-equation-boiling-history-wave_glidersUnstable.vti b/Patterns/Experiments/DanWills/heat-equation-boiling-history-wave_glidersUnstable.vti index a3498262d..212624333 100644 --- a/Patterns/Experiments/DanWills/heat-equation-boiling-history-wave_glidersUnstable.vti +++ b/Patterns/Experiments/DanWills/heat-equation-boiling-history-wave_glidersUnstable.vti @@ -2,13 +2,13 @@ -The <a href="http://en.wikipedia.org/wiki/Heat_equation">heat equation</a>, also known as the diffusion equation, describes multiple phenomena including the spreading-out of heat in a solid body and the diffusion of chemicals in a liquid. - -This formula adds additional reagents to the Heat Equation that model something akin to 'Boil History' in B and 'Boil Wave/Wake' in C and D. When the boil threshold is exceeded, the boil-event emits value into history and wave, allowing it to leave a diffusing history behind it, as well as a rippling wake. - -In this pattern (using the boiling heat formula as described above), moving glider-like wavefronts form against a background of chaotic boil-events. Constant creation and annihlation usually ends up with a particular flow-direction winning out overall, and wider wavefronts can form once this direction is established, which tend to dominate the individual smaller wavefronts. - -Written by Dan Wills, (as a bit of an homage-to-CAPOW by Rudy Rucker) based on earlier code in the Ready repo. + The <a href="http://en.wikipedia.org/wiki/Heat_equation">heat equation</a>, also known as the diffusion equation, describes multiple phenomena including the spreading-out of heat in a solid body and the diffusion of chemicals in a liquid. + + This formula adds additional reagents to the Heat Equation that model something akin to 'Boil History' in B and 'Boil Wave/Wake' in C and D. When the boil threshold is exceeded, the boil-event emits value into history and wave, allowing it to leave a diffusing history behind it, as well as a rippling wake. + + In this pattern (using the boiling heat formula as described above), moving glider-like wavefronts form against a background of chaotic boil-events. Constant creation and annihlation usually ends up with a particular flow-direction winning out overall, and wider wavefronts can form once this direction is established, which tend to dominate the individual smaller wavefronts. + + Written by Dan Wills, (as a bit of an homage-to-CAPOW by Rudy Rucker) based on earlier code in the Ready repo. @@ -114,15 +114,15 @@ Written by Dan Wills, (as a bit of an homage-to-CAPOW by Rudy Rucker) based on e 0 - a = clamp( sign(a) * pow( fabs( a + a_boil_rate ), (float4) a_power ) + (c-wave_DC_value)*wave_to_a, (float4) a_clamp_min, (float4) a_clamp_max); -float4 boil = pow( clamp( (float4) ( ((a+laplacian_a * boil_diffusion) - boil_threshold ) * boil_heat_loss ), (float4) 0.0, (float4) 1.0 ), (float4)boil_power ); -a = a + ( -a * boil + b * -a * a_boil_history_rate ); -delta_a = laplacian_a * (a_diffusion_rate + (c-wave_DC_value)*wave_to_Da) + (c-wave_DC_value)*wave_to_a + b*a_from_b; -delta_b = -b*(b_damp + c*wave_to_b_damp) + a*b_from_a + boil*b_from_boil + (b_diffusion + (c-wave_DC_value)*wave_to_Db) * laplacian_b + (c-wave_DC_value)*wave_to_b; -b = clamp( sign(b) * pow( (float4)( fabs(b)/b_pow_norm ), (float4)b_pow )*b_pow_norm, b_clamp_min, b_clamp_max ); -c = wave_DC_value + clamp( sign(c-wave_DC_value) * pow( (float4)( fabs(c-wave_DC_value)/wave_pow_norm * wave_damp ), (float4)wave_power )*wave_pow_norm, -wave_clamp, wave_clamp); -delta_d = (laplacian_c) * wave_diffusion; -delta_c = d + delta_d + a * wave_from_a + b * wave_from_b + boil*wave_from_boil; + a = clamp( sign(a) * pow( fabs( a + a_boil_rate ), (float4) a_power ) + (c-wave_DC_value)*wave_to_a, (float4) a_clamp_min, (float4) a_clamp_max); + float4 boil = pow( clamp( (float4) ( ((a+laplacian_a * boil_diffusion) - boil_threshold ) * boil_heat_loss ), (float4) 0.0f, (float4) 1.0f ), (float4)boil_power ); + a = a + ( -a * boil + b * -a * a_boil_history_rate ); + delta_a = laplacian_a * (a_diffusion_rate + (c-wave_DC_value)*wave_to_Da) + (c-wave_DC_value)*wave_to_a + b*a_from_b; + delta_b = -b*(b_damp + c*wave_to_b_damp) + a*b_from_a + boil*b_from_boil + (b_diffusion + (c-wave_DC_value)*wave_to_Db) * laplacian_b + (c-wave_DC_value)*wave_to_b; + b = clamp( sign(b) * pow( (float4)( fabs(b)/b_pow_norm ), (float4)b_pow )*b_pow_norm, b_clamp_min, b_clamp_max ); + c = wave_DC_value + clamp( sign(c-wave_DC_value) * pow( (float4)( fabs(c-wave_DC_value)/wave_pow_norm * wave_damp ), (float4)wave_power )*wave_pow_norm, -wave_clamp, wave_clamp); + delta_d = (laplacian_c) * wave_diffusion; + delta_c = d + delta_d + a * wave_from_a + b * wave_from_b + boil*wave_from_boil; diff --git a/Patterns/Experiments/DanWills/orbitsNova_buildAndDestroyBlobs.vti b/Patterns/Experiments/DanWills/orbitsNova_buildAndDestroyBlobs.vti index bc69fa8cc..482a1ab01 100644 --- a/Patterns/Experiments/DanWills/orbitsNova_buildAndDestroyBlobs.vti +++ b/Patterns/Experiments/DanWills/orbitsNova_buildAndDestroyBlobs.vti @@ -2,9 +2,9 @@ -An RD that uses an iteration step implemented to treat reagents a and b as a complex number (a+bi) and raising it to a power, similarly to a Nova orbits-fractal step. There are extensive notes about this in the comments in the code. -Implemented by Dan Wills - gdanzo@gmail.com -</a> + An RD that uses an iteration step implemented to treat reagents a and b as a complex number (a+bi) and raising it to a power, similarly to a Nova orbits-fractal step. There are extensive notes about this in the comments in the code. + + Implemented by Dan Wills - gdanzo@gmail.com @@ -56,125 +56,125 @@ Implemented by Dan Wills - gdanzo@gmail.com 1.17 -// Nova is: z = z - R * ( (z^p - 1) / (p * z^(p-1)) ) + complexOffset -// Where: -// z is the complex value: (a+ib) -// p is the complex power: (c+id) (these are changed to u and t in the implemented code) -// R is the complex relaxation: (e+if) -// c is the complex offset: (g+ih) -// z^p is the complex number z, raised to complex power p, which we precompute: (p + iq) -// z^(p-1) is the complex number z, raised to complex power (p-1), which we precompute: (r + is) -// E is the real constant e ( a literal is used here: 2.718281828459045235360287471352 ) -// for reference: complex power of z=(a+ib), where MAG is z's magnitude and PHASE is z's phase: -// real part: pow( MAG, powerReal) * pow( E, -powerImag * PHASE ) * cos( powerReal * PHASE + powerImag * log( MAG ) ) -// imag part: same as real but with sin instead of cos -// Complex fraction manipulation reference: -// http://www.purplemath.com/modules/complex2.htm -// Nova formula, substituting variable names from above: -// change in z = (-e - if) * ( ( (p - 1.0 + iq) ) / ( (c+id ) * (r+is) ) ) + (g+ih) -// Denominator: (c+id) * (r+is), becomes: cr - ds + i(cs + dr) -// Multiplying R into the numerator of the central fraction: -// (-e - if) * (p - 1.0 + iq) -// Which gives: -ep + e - ieq - ifp + if + fq -// Collect into real and imag: -// -ep + e + fq - i( eq + fp - f ) -// Now we need to get the +c in terms of the denominator, so we multiply it by denom/denom. -// new c denominator is: cr - ds + i(cs + dr): -// c new numerator: -// ( g + ih ) * ( cr - ds + i(cs + dr) ) -// Which is: -// gcr - gds + igcs + igdr + ihcr - ihds - csh - hdr -// Collect into real and imag (c numerator): -// gcr - gds - hcs - hdr + i( gcs + gdr + hcr - hds ) -// now the numerators can be added together: -// -ep + e + fq - i( eq + fp - f ) + gcr - gds - hcs - hdr + i( gcs + gdr + hcr - hds ) -// Which makes the forumula: -// -// -ep + e + fq + gcr - gds - hcs - hdr + i( eq + fp - f + gcs + gdr + hcr - hds ) -// ------------------------------------------------ -// cr - ds + i(cs + dr) -// -// We need to separate into real and imaginary in order to actually apply it, so: -// To get rid of i in the denominator, we need to multiply by the fractional complex conjugate identity, in other words, mult by: -// cr - ds - i(cs + dr) -// * ---------------------- -// cr - ds - i(cs + dr) -// This will give a new denominator of: -// ( (cr - ds) + i(cs + dr)) * ( (cr - ds) - i(cs + dr)) -// Which expands to: -// (cr - ds)(cr - ds) - i(cr - ds)(cs + dr) + i(cs + dr)(cr - ds) + (cs + dr)(cs + dr) -// The imaginary bits cancel out, leaving: -// (cr - ds)^2 + (cs + dr)^2 -// Which expands to: -// (cr - ds)(cr - ds) + (cs + dr)(cs + dr) -// Expanded: -// crcr - 2(crds) + cscs + 2(csdr) + drdr -// ccrr + ccss + ddrr + ddss -// The new denominator, simplified: -// cc( rr + ss ) + dd( rr + ss ) -// On top, we now have this monster: -// ( -ep + e + fq + gcr - gds - hcs - hdr + i( eq + fp - f + gcs + gdr + hcr - hds ) ) * ( cr - ds - i(cs + dr) ) -// Expanded: -// (-ep + e + fq + gcr - gds - hcs - hdr) * (cr - ds) - (-ep + e + fq + gcr - gds - hcs - hdr) * i(cs + dr) + -// i(eq + fp - f + gcs + gdr + hcr - hds) * (cr - ds) - i(eq + fp - f + gcs + gdr + hcr - hds) * i(cs + dr) -// Real bit: -// (-ep + e + fq + gcr - gds - hcs - hdr) * (cr - ds) - ( ieq + ifp - if + igcs + igdr + ihcr - ihds ) * ( ics + idr ) ) -// Expanded: -// -epcr + epds + ecr - eds + fqcr - fqds + gcrcr - gcrds - gdscr + gdsds - hcscr + hcsds - hdrcr + hdrds -// + eqcs + eqdr + fpcs + fpdr - fcs - fdr + gcscs + gcsdr + gdrcs + gdrdr + hcrcs + hcrdr - hdscs - hdsdr -// Reordered: -// -epcr + epds + ecr - eds + fqcr - fqds + gcrcr + gdsds - gcrds - gdscr - hcscr + hcsds - hcrdr + hddrs -// + eqcs + eqdr + fpcs + fpdr - fcs - fdr + gcscs + gdrdr + gcrds + gdscr + hcscr - hcsds + hcrdr - hddrs -// From which we can cancel a few things, giving: -// -epcr + epds + ecr - eds + eqcs + eqdr + fpcs + fpdr - fcs - fdr + fqcr - fqds + gcrcr + gdsds + gcscs + gdrdr -// simplified: -// e( c( -pr + r + qs ) + d( ps - s + qr ) ) + -// f( p( cs + dr ) + q( -cr - ds ) - cs - dr ) + -// g( cc( rr + ss ) + dd( ss + rr ) ) -// imag bit: -// - (-ep + e + fq + gcr - gds - hcs - hdr) * i(cs + dr) + i(eq + fp - f + gcs + gdr + hcr - hds) * (cr - ds) -// (ep - e - fq - gcr + gds + hcs + hdr) * i(cs + dr) + i(eq + fp - f + gcs + gdr + hcr - hds) * (cr - ds) -// Expanded: -// iepcs + iepdr - iecs - iedr -ifqcs -ifqdr - igcrcs - igcrdr + igdscs + igdsdr + ihcscs + ihcsdr + ihdrcs + ihdrdr + -// ieqcr - ieqds + ifpcr - ifpds -ifcr + ifds + igcscr - igcsds + igdrcr - igdrds + ihcrcr - ihcrds - ihdscr + ihdsds -// cancellation -// iepcs + iepdr - iecs - iedr -ifqcs -ifqdr + ihcscs + ihdrdr -// + ieqcr - ieqds + ifpcr - ifpds -ifcr + ifds + ihcrcr + ihdsds -// simplification: -// i( e( c( ps + qr - s ) + d( pr - qs - r ) ) + f( c( pr - qs - r ) + d ( -ps - qr + s ) ) + h( cc( rr + + ss ) + dd( rr + ss ) ) ) -//optimizations: -// precompute: -// PrQsR = pr - qs - r -// PsQrS = ps + qr - s -// RRSS = r*r + s*s -// this makes the formula: -// i( e( c( PsQrS ) + d( PrQsR ) ) + -// f( c( PrQsR ) + d ( -PsQrS ) ) + -// h( cc( RRSS ) + dd( RRSS ) ) ) -c = pow(a*a + b*b, mag_power) * mag_amp + mag_add; -d = atan2( b, a ) * phase_scale + phase_offset; -float4 p = pow( c, powerReal) * pow( 2.718281828459045235360287471352, -powerImag*d ) * cos( powerImag * log( c ) + powerReal * d ); -float4 q = pow( c, powerReal) * pow( 2.718281828459045235360287471352, -powerImag*d ) * sin( powerImag * log( c ) + powerReal * d ); -float4 r = pow( c, powerReal-1.0) * pow( 2.718281828459045235360287471352, -powerImag*d ) * cos( powerImag * log( c ) + (powerReal-1.0) * d ); -float4 s = pow( c, powerReal-1.0) * pow( 2.718281828459045235360287471352, -powerImag*d ) * sin( powerImag * log( c ) + (powerReal-1.0) * d ); -float4 e = relaxReal; -float4 f = relaxImag; -float4 g = constReal; -float4 h = constImag; -float4 t = powerReal; -float4 u = powerImag; -// bit of crunching later.. -// precompute inner bits: -float4 rr_plus_ss = ( r*r + s*s ); -float4 csdr = ( c*s + d*r ); -float4 PrQsR = p*r - q*s - r; -float4 PsQrS = p*s + q*r - s; -float4 denominator = t*t*rr_plus_ss + u*u*rr_plus_ss; -//remap c TO t and d TO u -float4 realNumerator = e*( t*( -PrQsR ) + u*( PsQrS ) ) + f*( p*( t*u*s*r ) + q*( -t*s*u*r ) - t*s - u*r ) + g*( t*t*rr_plus_ss + u*u*rr_plus_ss ); -float4 imagNumerator = e*( t*( PsQrS ) + u*( PrQsR ) ) + f*( t*( PrQsR ) + u*( -PsQrS ) ) + h*( t*t*( rr_plus_ss ) + u*u*( rr_plus_ss ) ); -delta_a = clamp( ( realNumerator / denominator ), clampMin, clampMax ) + D_a * laplacian_a; -delta_b = clamp( ( imagNumerator / denominator ), clampMin, clampMax ) + D_b * laplacian_b; + // Nova is: z = z - R * ( (z^p - 1) / (p * z^(p-1)) ) + complexOffset + // Where: + // z is the complex value: (a+ib) + // p is the complex power: (c+id) (these are changed to u and t in the implemented code) + // R is the complex relaxation: (e+if) + // c is the complex offset: (g+ih) + // z^p is the complex number z, raised to complex power p, which we precompute: (p + iq) + // z^(p-1) is the complex number z, raised to complex power (p-1), which we precompute: (r + is) + // E is the real constant e ( a literal is used here: 2.718281828459045235360287471352 ) + // for reference: complex power of z=(a+ib), where MAG is z's magnitude and PHASE is z's phase: + // real part: pow( MAG, powerReal) * pow( E, -powerImag * PHASE ) * cos( powerReal * PHASE + powerImag * log( MAG ) ) + // imag part: same as real but with sin instead of cos + // Complex fraction manipulation reference: + // http://www.purplemath.com/modules/complex2.htm + // Nova formula, substituting variable names from above: + // change in z = (-e - if) * ( ( (p - 1.0 + iq) ) / ( (c+id ) * (r+is) ) ) + (g+ih) + // Denominator: (c+id) * (r+is), becomes: cr - ds + i(cs + dr) + // Multiplying R into the numerator of the central fraction: + // (-e - if) * (p - 1.0 + iq) + // Which gives: -ep + e - ieq - ifp + if + fq + // Collect into real and imag: + // -ep + e + fq - i( eq + fp - f ) + // Now we need to get the +c in terms of the denominator, so we multiply it by denom/denom. + // new c denominator is: cr - ds + i(cs + dr): + // c new numerator: + // ( g + ih ) * ( cr - ds + i(cs + dr) ) + // Which is: + // gcr - gds + igcs + igdr + ihcr - ihds - csh - hdr + // Collect into real and imag (c numerator): + // gcr - gds - hcs - hdr + i( gcs + gdr + hcr - hds ) + // now the numerators can be added together: + // -ep + e + fq - i( eq + fp - f ) + gcr - gds - hcs - hdr + i( gcs + gdr + hcr - hds ) + // Which makes the forumula: + // + // -ep + e + fq + gcr - gds - hcs - hdr + i( eq + fp - f + gcs + gdr + hcr - hds ) + // ------------------------------------------------ + // cr - ds + i(cs + dr) + // + // We need to separate into real and imaginary in order to actually apply it, so: + // To get rid of i in the denominator, we need to multiply by the fractional complex conjugate identity, in other words, mult by: + // cr - ds - i(cs + dr) + // * ---------------------- + // cr - ds - i(cs + dr) + // This will give a new denominator of: + // ( (cr - ds) + i(cs + dr)) * ( (cr - ds) - i(cs + dr)) + // Which expands to: + // (cr - ds)(cr - ds) - i(cr - ds)(cs + dr) + i(cs + dr)(cr - ds) + (cs + dr)(cs + dr) + // The imaginary bits cancel out, leaving: + // (cr - ds)^2 + (cs + dr)^2 + // Which expands to: + // (cr - ds)(cr - ds) + (cs + dr)(cs + dr) + // Expanded: + // crcr - 2(crds) + cscs + 2(csdr) + drdr + // ccrr + ccss + ddrr + ddss + // The new denominator, simplified: + // cc( rr + ss ) + dd( rr + ss ) + // On top, we now have this monster: + // ( -ep + e + fq + gcr - gds - hcs - hdr + i( eq + fp - f + gcs + gdr + hcr - hds ) ) * ( cr - ds - i(cs + dr) ) + // Expanded: + // (-ep + e + fq + gcr - gds - hcs - hdr) * (cr - ds) - (-ep + e + fq + gcr - gds - hcs - hdr) * i(cs + dr) + + // i(eq + fp - f + gcs + gdr + hcr - hds) * (cr - ds) - i(eq + fp - f + gcs + gdr + hcr - hds) * i(cs + dr) + // Real bit: + // (-ep + e + fq + gcr - gds - hcs - hdr) * (cr - ds) - ( ieq + ifp - if + igcs + igdr + ihcr - ihds ) * ( ics + idr ) ) + // Expanded: + // -epcr + epds + ecr - eds + fqcr - fqds + gcrcr - gcrds - gdscr + gdsds - hcscr + hcsds - hdrcr + hdrds + // + eqcs + eqdr + fpcs + fpdr - fcs - fdr + gcscs + gcsdr + gdrcs + gdrdr + hcrcs + hcrdr - hdscs - hdsdr + // Reordered: + // -epcr + epds + ecr - eds + fqcr - fqds + gcrcr + gdsds - gcrds - gdscr - hcscr + hcsds - hcrdr + hddrs + // + eqcs + eqdr + fpcs + fpdr - fcs - fdr + gcscs + gdrdr + gcrds + gdscr + hcscr - hcsds + hcrdr - hddrs + // From which we can cancel a few things, giving: + // -epcr + epds + ecr - eds + eqcs + eqdr + fpcs + fpdr - fcs - fdr + fqcr - fqds + gcrcr + gdsds + gcscs + gdrdr + // simplified: + // e( c( -pr + r + qs ) + d( ps - s + qr ) ) + + // f( p( cs + dr ) + q( -cr - ds ) - cs - dr ) + + // g( cc( rr + ss ) + dd( ss + rr ) ) + // imag bit: + // - (-ep + e + fq + gcr - gds - hcs - hdr) * i(cs + dr) + i(eq + fp - f + gcs + gdr + hcr - hds) * (cr - ds) + // (ep - e - fq - gcr + gds + hcs + hdr) * i(cs + dr) + i(eq + fp - f + gcs + gdr + hcr - hds) * (cr - ds) + // Expanded: + // iepcs + iepdr - iecs - iedr -ifqcs -ifqdr - igcrcs - igcrdr + igdscs + igdsdr + ihcscs + ihcsdr + ihdrcs + ihdrdr + + // ieqcr - ieqds + ifpcr - ifpds -ifcr + ifds + igcscr - igcsds + igdrcr - igdrds + ihcrcr - ihcrds - ihdscr + ihdsds + // cancellation + // iepcs + iepdr - iecs - iedr -ifqcs -ifqdr + ihcscs + ihdrdr + // + ieqcr - ieqds + ifpcr - ifpds -ifcr + ifds + ihcrcr + ihdsds + // simplification: + // i( e( c( ps + qr - s ) + d( pr - qs - r ) ) + f( c( pr - qs - r ) + d ( -ps - qr + s ) ) + h( cc( rr + + ss ) + dd( rr + ss ) ) ) + //optimizations: + // precompute: + // PrQsR = pr - qs - r + // PsQrS = ps + qr - s + // RRSS = r*r + s*s + // this makes the formula: + // i( e( c( PsQrS ) + d( PrQsR ) ) + + // f( c( PrQsR ) + d ( -PsQrS ) ) + + // h( cc( RRSS ) + dd( RRSS ) ) ) + c = pow(a*a + b*b, mag_power) * mag_amp + mag_add; + d = atan2( b, a ) * phase_scale + phase_offset; + float4 p = pow( c, powerReal) * pow( 2.718281828459045235360287471352f, -powerImag*d ) * cos( powerImag * log( c ) + powerReal * d ); + float4 q = pow( c, powerReal) * pow( 2.718281828459045235360287471352f, -powerImag*d ) * sin( powerImag * log( c ) + powerReal * d ); + float4 r = pow( c, powerReal-1.0f) * pow( 2.718281828459045235360287471352f, -powerImag*d ) * cos( powerImag * log( c ) + (powerReal-1.0f) * d ); + float4 s = pow( c, powerReal-1.0f) * pow( 2.718281828459045235360287471352f, -powerImag*d ) * sin( powerImag * log( c ) + (powerReal-1.0f) * d ); + float4 e = relaxReal; + float4 f = relaxImag; + float4 g = constReal; + float4 h = constImag; + float4 t = powerReal; + float4 u = powerImag; + // bit of crunching later.. + // precompute inner bits: + float4 rr_plus_ss = ( r*r + s*s ); + float4 csdr = ( c*s + d*r ); + float4 PrQsR = p*r - q*s - r; + float4 PsQrS = p*s + q*r - s; + float4 denominator = t*t*rr_plus_ss + u*u*rr_plus_ss; + //remap c TO t and d TO u + float4 realNumerator = e*( t*( -PrQsR ) + u*( PsQrS ) ) + f*( p*( t*u*s*r ) + q*( -t*s*u*r ) - t*s - u*r ) + g*( t*t*rr_plus_ss + u*u*rr_plus_ss ); + float4 imagNumerator = e*( t*( PsQrS ) + u*( PrQsR ) ) + f*( t*( PrQsR ) + u*( -PsQrS ) ) + h*( t*t*( rr_plus_ss ) + u*u*( rr_plus_ss ) ); + delta_a = clamp( ( realNumerator / denominator ), clampMin, clampMax ) + D_a * laplacian_a; + delta_b = clamp( ( imagNumerator / denominator ), clampMin, clampMax ) + D_b * laplacian_b; diff --git a/Patterns/Experiments/DanWills/orbits_epochs.vti b/Patterns/Experiments/DanWills/orbits_epochs.vti index 5f68e4bc0..ce042c621 100644 --- a/Patterns/Experiments/DanWills/orbits_epochs.vti +++ b/Patterns/Experiments/DanWills/orbits_epochs.vti @@ -2,8 +2,9 @@ -This is an rd formula that uses an iteration step implemented to treat reagents a and b as a complex number (a+bi) and raise it to a power. Inspired by what a normal orbits-fractal (eg Julia, Mandelbrot) step does. -Implemented by Dan Wills - gdanzo@gmail.com + This is an RD formula that uses an iteration step implemented to treat reagents a and b as a complex number (a+bi) and raise it to a power. Inspired by what a normal orbits-fractal (eg Julia, Mandelbrot) step does. + + Implemented by Dan Wills - gdanzo@gmail.com @@ -75,12 +76,13 @@ Implemented by Dan Wills - gdanzo@gmail.com 1 - c = pow((a+constRealInner)*(a+constRealInner) + (b+constImagInner)*(b+constImagInner), mag_power) * mag_amp + mag_zeroPt; -d = atan2( b+constRealInner, a+constRealInner ) * phaseAmp + phaseOffset; -delta_a = clamp( timestep * pow( c, realPower) * pow( eConst, -imagPower*d ) * cos( imagPower * log( c ) + realPower * d ) + D_a * laplacian_a - unDa_b * laplacian_b + constReal, clampMin, clampMax ); -delta_b = clamp( timestep * pow( c, realPower) * pow( eConst, -imagPower*d ) * sin( imagPower * log( c ) + realPower * d ) + D_b * laplacian_b - unDb_a * laplacian_a + constImag, clampMin, clampMax ); -c = (c + cDisplayOffset) * cDisplayMult; -d = (d + dDisplayOffset) * dDisplayMult; + + c = pow( (a+constRealInner) * (a+constRealInner) + (b+constImagInner) * (b+constImagInner), mag_power) * mag_amp + mag_zeroPt; + d = atan2( b+constRealInner, a+constRealInner ) * phaseAmp + phaseOffset; + delta_a = clamp( timestep * pow( c, realPower) * pow( eConst, -imagPower*d ) * cos( imagPower * log( c ) + realPower * d ) + D_a * laplacian_a - unDa_b * laplacian_b + constReal, clampMin, clampMax ); + delta_b = clamp( timestep * pow( c, realPower) * pow( eConst, -imagPower*d ) * sin( imagPower * log( c ) + realPower * d ) + D_b * laplacian_b - unDb_a * laplacian_a + constImag, clampMin, clampMax ); + c = (c + cDisplayOffset) * cDisplayMult; + d = (d + dDisplayOffset) * dDisplayMult;