Commit before breaking everything
[matches/honours.git] / research / transmission_spectroscopy / universesim / src / update.c
diff --git a/research/transmission_spectroscopy/universesim/src/update.c b/research/transmission_spectroscopy/universesim/src/update.c
new file mode 100644 (file)
index 0000000..2a0ba66
--- /dev/null
@@ -0,0 +1,257 @@
+/*
+ */
+#include <common.h>
+#include <stdio.h>
+#include <video.h>     // For the thread functions
+
+// === CONSTANTS ===
+#define G_CONSTANT     200     // Gravitational Constant
+#define E_CONSTANT     400     // Electric Constant
+#define N_CONSTANT     50      // Nuclear Constant
+#define WN_CONSTANT    100     // Weak Nuclear Constant
+
+#define        MAX_THREADS     32
+
+#define        SHOW_FORCES     1
+
+#define DEBUG  0
+#define DEBUG_SCAN     (DEBUG&&)
+#define DEBUG_CHECKS   (DEBUG&&0)
+#define DEBUG_INNER    (DEBUG&&0)
+#define DEBUG_STATE    (DEBUG&&0)
+
+// === PROTOTYPES ===
+void   Update_DoTimestep(void);
+void   Update_ParticleForces(tParticle *Part);
+void   Update_ParticleVelocity(tParticle *Part);
+void   Update_ParticlePosition(tParticle *Part);
+
+// === GLOBALS ===
+ int   giNumberOfJobs = 16;
+volatile int   gaThreadStatuses[MAX_THREADS];  // -1 = Die, 0 = Completed, 1 = Working
+
+// === CODE ===
+int Update_ProcessThread(void *Offset)
+{
+        int    ofs = (intptr_t)Offset; // Also Thread ID
+        int    i;
+       
+       while( gaThreadStatuses[ofs] != -1 )
+       {
+               while( gaThreadStatuses[ofs] == 0 )
+                       Thread_Yield();
+               if( gaThreadStatuses[ofs] == -1 )
+                       break;
+               for( i = ofs; i < giNumParticles; i += giNumberOfJobs )
+               {
+                       Update_ParticleForces( &gpParticles[i] );
+               }
+               for( i = ofs; i < giNumParticles; i += giNumberOfJobs )
+               {
+                       Update_ParticleVelocity( &gpParticles[i] );
+               }
+               gaThreadStatuses[ofs] = 0;
+       }
+       return 0;
+}
+
+/**
+ * Start update threads
+ */
+void Update_Initialise(void)
+{
+        int    i;
+       for( i = 1; i < giNumberOfJobs; i++ ) {
+               Thread_Create(Update_ProcessThread, (void*)(intptr_t)i);
+       }
+}
+
+void Update_Cleanup(void)
+{
+        int    i;
+       for( i = 1; i < giNumberOfJobs; i++ ) {
+               gaThreadStatuses[i] = -1;
+       }
+}
+
+void Update_DoTimestep(void)
+{
+        int    i;
+       
+       // Start jobs again
+       for( i = 1; i < giNumberOfJobs; i++ ) {
+               gaThreadStatuses[i] = 1;        // You have work to do
+       }
+       
+       for( i = 0; i < giNumParticles; i += giNumberOfJobs )
+       {
+               #if DEBUG | SHOW_FORCES
+               printf(" Forces for #%i          \r", i);
+               fflush(stdout);
+               #endif
+               Update_ParticleForces( &gpParticles[i] );
+       }
+       #if SHOW_FORCES
+       printf("                         \r");
+       #endif
+       
+       #if DEBUG
+       printf(" Forces Done             \n");
+       printf(" Velocities\n");
+       #endif
+       for( i = 0; i < giNumParticles; i += giNumberOfJobs )
+       {
+               #if DEBUG
+               printf(" Accel & Velocity for %i          %c", i, DEBUG_SCAN?'\r':'\n');
+               #endif
+               Update_ParticleVelocity( &gpParticles[i] );
+       }
+       
+       // Wait for jobs to terminate
+       for( i = 1; i < giNumberOfJobs; i++ ) {
+               while( gaThreadStatuses[i] == 1 )
+                       Thread_Yield();
+       }
+       
+       #if DEBUG
+       printf(" Positions                        \n");
+       #endif
+       for( i = 0; i < giNumParticles; i++ )
+       {
+               Update_ParticlePosition( &gpParticles[i] );
+       }
+}
+
+void Update_ParticleForces(tParticle *Part)
+{
+        int    i;
+       tLargeInt       dist, dist2, dist3, dist4;
+       tLargeInt       force, tmpQuad;
+       tVector line;
+       tLargeInt       *partMass = &Part->Mass;
+       
+       Vector_Zero(&Part->Forces);
+       
+       for( i = 0; i < giNumParticles; i++ )
+       {
+               if( &gpParticles[i] == Part )   continue;
+               #if DEBUG_CHECKS
+               printf("  Checking against %4i ", i);
+               # if DEBUG_INNER
+               printf("\n");
+               # else
+               printf("\r");
+               # endif
+               #endif
+               
+               Vector_Set( &line, &gpParticles[i].Location );
+               Vector_Sub( &line, &Part->Location );
+               Vector_Magnitude( &dist, &line );
+               LargeInt_PowNative( &dist2, &dist, 2 );
+               LargeInt_PowNative( &dist3, &dist, 3 );
+               LargeInt_PowNative( &dist4, &dist, 4 );
+               
+               #if DEBUG_INNER
+               printf("   Calculating Gravity\n");
+               #endif
+               // Gravitational Forces
+               // -(mM)*G/(dist^2)
+               LargeInt_Mul( &tmpQuad, NULL, partMass, &gpParticles[i].Mass );
+               //printf("   tmpQuad = %s\n", LargeInt_DumpEx(&tmpQuad, 0) );
+               LargeInt_MulNative( &tmpQuad, NULL, &tmpQuad, G_CONSTANT );
+               LargeInt_Div( &force, NULL, &tmpQuad, &dist2 );
+               LargeInt_Neg( &force, &force );
+               
+               #if DEBUG_INNER
+               printf("   Calculating Electric\n");
+               #endif
+               // Electric Forces
+               // - Opposites Attract, Like Repels, so no need to negate
+               // (e1e2)*E/(dist^2)
+               //printf("   Charges %s and %s\n",
+               //      LargeInt_DumpEx(&Part->Charge, 0),
+               //      LargeInt_DumpEx(&gpParticles[i].Charge, 1)
+               //      );
+               LargeInt_Mul( &tmpQuad, NULL, &Part->Charge, &gpParticles[i].Charge );
+               //printf("   tmpQuad = %s\n", LargeInt_DumpEx(&tmpQuad, 0) );
+               LargeInt_MulNative( &tmpQuad, NULL, &tmpQuad, E_CONSTANT );
+               LargeInt_Div( &tmpQuad, NULL, &tmpQuad, &dist2 );
+               LargeInt_Add( &force, &force, &tmpQuad );
+               
+               #if DEBUG_INNER
+               printf("   Calculating Nuclear\n");
+               #endif
+               // Nuclear Forces
+               // > Strong Nuclear (Attractive, 1/d^3)
+               // -(mM)*N/(dist^3)
+               LargeInt_Mul( &tmpQuad, NULL, &Part->Mass, &gpParticles[i].Mass );
+               LargeInt_MulNative( &tmpQuad, NULL, &tmpQuad, N_CONSTANT );
+               LargeInt_Div( &tmpQuad, NULL, &tmpQuad, &dist3 );
+               LargeInt_Neg( &tmpQuad, &tmpQuad );
+               LargeInt_Add( &force, &force, &tmpQuad );
+               // > Weak Nuclear (Repulsive, d^4)
+               // (mM)*N/(dist^4)
+               LargeInt_Mul( &tmpQuad, NULL, &Part->Mass, &gpParticles[i].Mass );
+               LargeInt_MulNative( &tmpQuad, NULL, &tmpQuad, WN_CONSTANT );
+               LargeInt_Div( &tmpQuad, NULL, &tmpQuad, &dist4 );
+               LargeInt_Add( &force, &force, &tmpQuad );
+               
+               #if DEBUG_INNER
+               printf("   Calculating final force\n");
+               #endif
+               #if DEBUG_INNER >= 2
+               printf("   Mul (%s,%s) *= %s\n",
+                       LargeInt_DumpEx(&line.C[0], 0),
+                       LargeInt_DumpEx(&line.C[1], 1),
+                       LargeInt_DumpEx(&force, 2)
+                       );
+               #endif
+               Vector_MulScalar( &line, &force );
+               
+               Vector_DivScalar( &line, &dist );
+               Vector_Add(&Part->Forces, &line);
+       }
+       
+       #if 0
+       printf("   Part->Forces = (%s,%s)\n",
+               LargeInt_DumpEx(&Part->Forces.C[0], 0),
+               LargeInt_DumpEx(&Part->Forces.C[1], 1)
+               );
+       #endif
+       
+       #if DEBUG_CHECKS
+       # if DEBUG_INNER
+       printf("\n");
+       # endif
+       #endif
+}
+
+void Update_ParticleVelocity(tParticle *Part)
+{
+       tVector accel;
+       #if DEBUG_STATE
+       printf("   Set\n");
+       #endif
+       Vector_Set( &accel, &Part->Forces );
+       #if DEBUG_STATE
+       printf("   Div (%s,%s) /= %s\n",
+               LargeInt_DumpEx(&accel.C[0], 0),
+               LargeInt_DumpEx(&accel.C[1], 1),
+               LargeInt_DumpEx(&Part->Mass, 2)
+               );
+       #endif
+       Vector_DivScalar( &accel, &Part->Mass );
+       #if DEBUG_STATE
+       printf("   = (%s,%s)\n",
+               LargeInt_DumpEx(&accel.C[0], 0),
+               LargeInt_DumpEx(&accel.C[1], 1)
+               );
+       printf("   Add\n");
+       #endif
+       Vector_Add( &Part->Velocity, &accel );  
+}
+
+void Update_ParticlePosition(tParticle *Part)
+{
+       Vector_Add( &Part->Location, &Part->Velocity );
+}

UCC git Repository :: git.ucc.asn.au