nextstep.c 6.27 KB
Newer Older
Cassio Kirch's avatar
Cassio Kirch committed
1
#include <stdio.h>
Cassio Kirch's avatar
Cassio Kirch committed
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
#include <stdlib.h>
#include <stdbool.h>
#include <math.h>
#include <err.h>

#include "define.h"
#include "boid.h"
#include "box.h"
#include "distance.h"
#include "nextstep.h"

void
checkLimits (struct Boid* const boid)
{
  while (boid -> position[X] < -(RANGE / 2.0))
    boid -> position[X] += RANGE;
  while (boid -> position[X] > (RANGE / 2.0))
    boid -> position[X] -= RANGE;
  while (boid -> position[Y] < -(RANGE / 2.0))
    boid -> position[Y] += RANGE;
  while (boid -> position[Y] > (RANGE / 2.0))
    boid -> position[Y] -= RANGE;
}

void
makeSum (struct Boid* const boid, const struct Boid* conductor, \
28 29
         double* const sumF, double* const sumV)
/* Where 'sumF' and 'sumV' are arrays. */
Cassio Kirch's avatar
Cassio Kirch committed
30 31 32 33
{
  struct Distance distance;
  double force;
  while (conductor != NULL)
Cassio Kirch's avatar
Cassio Kirch committed
34 35
  {
    if (boid != conductor)
Cassio Kirch's avatar
Cassio Kirch committed
36
    {
Cassio Kirch's avatar
Cassio Kirch committed
37 38 39 40 41 42 43 44
      distance = getDistance (boid, conductor);
      if (distance.module <= NEIGHBOR_DISTANCE)
      {
        //boid -> neighbors++;
        force = getForce (distance.module);
        
        if (conductor -> type == ENDODERM &&    \
            boid -> type == ENDODERM)
Cassio Kirch's avatar
Cassio Kirch committed
45
        {
46 47 48 49
          sumF[X] += BETA11 * force * distance.cosine;
          sumF[Y] += BETA11 * force * distance.sine;
          sumV[X] += ALPHA11 * conductor -> velocity[X] / V0;
          sumV[Y] += ALPHA11 * conductor -> velocity[Y] / V0;
Cassio Kirch's avatar
Cassio Kirch committed
50
        }
Cassio Kirch's avatar
Cassio Kirch committed
51 52 53 54
        
        else if (conductor -> type == ECTODERM &&       \
                 boid -> type == ECTODERM)
        {
55 56 57 58
          sumF[X] += BETA22 * force * distance.cosine;
          sumF[Y] += BETA22 * force * distance.sine;
          sumV[X] += ALPHA22 * conductor -> velocity[X] / V0;
          sumV[Y] += ALPHA22 * conductor -> velocity[Y] / V0;
Cassio Kirch's avatar
Cassio Kirch committed
59 60 61 62
        }
        
        else
        {
63 64 65 66
          sumF[X] += BETA12 * force * distance.cosine;
          sumF[Y] += BETA12 * force * distance.sine;
          sumV[X] += ALPHA12 * conductor -> velocity[X] / V0;
          sumV[Y] += ALPHA12 * conductor -> velocity[Y] / V0;
Cassio Kirch's avatar
Cassio Kirch committed
67
        }
Cassio Kirch's avatar
Cassio Kirch committed
68 69

#if defined(ENDO_GAMMA) || defined(ECTO_GAMMA) || defined(COUNT_NEIGHBORS)
Cassio Kirch's avatar
Cassio Kirch committed
70
        if (conductor -> type == ECTODERM)
Cassio Kirch's avatar
Cassio Kirch committed
71
          (boid -> ectoNeighbors)++;
72
        else /* Assume ENDODERM. */
Cassio Kirch's avatar
Cassio Kirch committed
73
          (boid -> endoNeighbors)++;
Cassio Kirch's avatar
Cassio Kirch committed
74
#endif
75

Cassio Kirch's avatar
Cassio Kirch committed
76
      }
Cassio Kirch's avatar
Cassio Kirch committed
77
    }
Cassio Kirch's avatar
Cassio Kirch committed
78 79
    conductor = conductor -> next;
  }
Cassio Kirch's avatar
Cassio Kirch committed
80 81 82 83
}

void
setNextVelocity (struct Boid* const boid, const struct Box box[])
84
/* Where 'boid' is address of a single struct and box is a array. */
Cassio Kirch's avatar
Cassio Kirch committed
85
{
86 87 88
  double sumV[] = {0.0, 0.0};    /* For alpha and velocity sum. */
  double uAngle, u[2];    /* For eta and random things. */
  double sumF[] = {0.0, 0.0};    /* For beta and force sum. */
Cassio Kirch's avatar
Cassio Kirch committed
89 90
  double sum, sumX, sumY;
  struct Boid *conductor;
91

Cassio Kirch's avatar
Cassio Kirch committed
92
#if defined (ENDO_GAMMA) || defined (ECTO_GAMMA) || defined (COUNT_NEIGHBORS)
Cassio Kirch's avatar
Cassio Kirch committed
93 94
  boid -> endoNeighbors = 0u;
  boid -> ectoNeighbors = 0u;
Cassio Kirch's avatar
Cassio Kirch committed
95
  boid -> gamma = 0.0;
96
#endif
Cassio Kirch's avatar
Cassio Kirch committed
97
  
Cassio Kirch's avatar
Cassio Kirch committed
98 99
  /* check neighbors in the same box */
  conductor = box[boid -> boxID].first;
100
  makeSum(boid, conductor, sumF, sumV);
Cassio Kirch's avatar
Cassio Kirch committed
101 102 103
  
  /* check neighbors in the north box */
  conductor = box[getNorthBoxID (boid -> boxID)].first;
104
    makeSum(boid, conductor, sumF, sumV);
Cassio Kirch's avatar
Cassio Kirch committed
105
  
Cassio Kirch's avatar
Cassio Kirch committed
106 107
  /* check neighbors in the south box */
  conductor = box[getSouthBoxID (boid -> boxID)].first;
108
    makeSum(boid, conductor, sumF, sumV);
Cassio Kirch's avatar
Cassio Kirch committed
109
  
Cassio Kirch's avatar
Cassio Kirch committed
110 111
  /* check neighbors in the west box */
  conductor = box[getWestBoxID (boid -> boxID)].first;
112
    makeSum(boid, conductor, sumF, sumV);
Cassio Kirch's avatar
Cassio Kirch committed
113
  
Cassio Kirch's avatar
Cassio Kirch committed
114 115
  /* check neighbors in the east box */
  conductor = box[getEastBoxID (boid -> boxID)].first;
116
    makeSum(boid, conductor, sumF, sumV);
Cassio Kirch's avatar
Cassio Kirch committed
117
  
Cassio Kirch's avatar
Cassio Kirch committed
118 119
  /* check neighbors in the northeast box */
  conductor = box[getEastBoxID (getNorthBoxID (boid -> boxID))].first;
120
    makeSum(boid, conductor, sumF, sumV);
Cassio Kirch's avatar
Cassio Kirch committed
121 122 123

  /* check neighbors in the southeast box */
  conductor = box[getEastBoxID (getSouthBoxID (boid -> boxID))].first;
124
    makeSum(boid, conductor, sumF, sumV);
Cassio Kirch's avatar
Cassio Kirch committed
125 126 127

  /* check neighbors in the northwest box */
  conductor = box[getWestBoxID (getNorthBoxID (boid -> boxID))].first;
128
    makeSum(boid, conductor, sumF, sumV);
Cassio Kirch's avatar
Cassio Kirch committed
129 130 131

  /* check neighbors in the southwest box */
  conductor = box[getWestBoxID (getSouthBoxID (boid -> boxID))].first;
132
    makeSum(boid, conductor, sumF, sumV);
Cassio Kirch's avatar
Cassio Kirch committed
133 134

  uAngle = RANDOM_0 (PI * 2.0);
135 136
  u[X] = cos (uAngle);
  u[Y] = sin (uAngle);
Cassio Kirch's avatar
Cassio Kirch committed
137

138 139
  sumX = (ETA * u[X]) + sumV[X] + sumF[X];
  sumY = (ETA * u[Y]) + sumV[Y] + sumF[Y];
Cassio Kirch's avatar
Cassio Kirch committed
140 141 142 143
  sum = sqrt (pow (sumX, 2.0) + pow (sumY, 2.0));

  boid -> newVelocity[X] = V0 * sumX / sum;
  boid -> newVelocity[Y] = V0 * sumY / sum;
Cassio Kirch's avatar
Cassio Kirch committed
144

145
#if defined (ENDO_GAMMA) || defined (ECTO_GAMMA)
Cassio Kirch's avatar
Cassio Kirch committed
146
  if (boid -> ectoNeighbors != 0u || boid -> endoNeighbors != 0u)
Cassio Kirch's avatar
Cassio Kirch committed
147 148
    boid -> gamma = (double)boid -> ectoNeighbors / \
      (boid -> endoNeighbors + boid -> ectoNeighbors);
149
#endif
Cassio Kirch's avatar
Cassio Kirch committed
150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205
}

void
setNextPosition (struct Boid* const boid)
{
  boid -> position[X] += boid -> newVelocity[X] * DT;
  boid -> position[Y] += boid -> newVelocity[Y] * DT;
  boid -> velocity[X] = boid -> newVelocity[X];
  boid -> velocity[Y] = boid -> newVelocity[Y];
}

void*
callNextPositionThread (void* const input)
{
  const struct Parameters* const parameters = input;
  struct Boid* const boid = parameters -> boid;  /* struct Boid array. */
  //struct Box* const box  = parameters  ->  box;  /* struct Box array. */

  unsigned int boidCount;

  for (boidCount = parameters -> left;
       boidCount < parameters -> right; ++boidCount)
    setNextPosition ((boid + boidCount));
  return NULL;
}

void*
callNextVelocityThread (void *input)
{
  const struct Parameters* const parameters = input;
  struct Boid* const boid = parameters -> boid;    /* struct Boid array. */
  struct Box* const box = parameters -> box;    /* struct Box array. */
  unsigned int boidCount;

  for (boidCount = parameters -> left;
       boidCount < parameters -> right; ++boidCount)
    setNextVelocity (boid + boidCount, box);
  return NULL;
}

void
nextStep (void* const parameters[])
{
  unsigned int threadID;

  for (threadID = 0; threadID < NUM_THREADS; ++threadID)
    pthread_create (&thread[threadID], NULL, callNextVelocityThread,
            parameters[threadID]);
  for (threadID = 0; threadID < NUM_THREADS; ++threadID)
    pthread_join (thread[threadID], NULL);
  for (threadID = 0; threadID < NUM_THREADS; ++threadID)
    pthread_create (&thread[threadID], NULL, callNextPositionThread,
            parameters[threadID]);
  for (threadID = 0; threadID < NUM_THREADS; ++threadID)
    pthread_join (thread[threadID], NULL);
}