nextstep.c 6.31 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
}

void
Cassio Kirch's avatar
Cassio Kirch committed
83 84
setNextVelocity (struct Boid* const boid, const struct Box* boxes)
/* Where 'boid' is address of a single struct and 'boxes' 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
  /* check neighbors in the same box */
Cassio Kirch's avatar
Cassio Kirch committed
99
  conductor = boxes[boid -> boxID].first;
100
  makeSum(boid, conductor, sumF, sumV);
Cassio Kirch's avatar
Cassio Kirch committed
101 102
  
  /* check neighbors in the north box */
Cassio Kirch's avatar
Cassio Kirch committed
103
  conductor = boxes[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
  /* check neighbors in the south box */
Cassio Kirch's avatar
Cassio Kirch committed
107
  conductor = boxes[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
  /* check neighbors in the west box */
Cassio Kirch's avatar
Cassio Kirch committed
111
  conductor = boxes[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
  /* check neighbors in the east box */
Cassio Kirch's avatar
Cassio Kirch committed
115
  conductor = boxes[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
  /* check neighbors in the northeast box */
Cassio Kirch's avatar
Cassio Kirch committed
119
  conductor = boxes[getEastBoxID (getNorthBoxID (boid -> boxID))].first;
120
    makeSum(boid, conductor, sumF, sumV);
Cassio Kirch's avatar
Cassio Kirch committed
121 122

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

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

  /* check neighbors in the southwest box */
Cassio Kirch's avatar
Cassio Kirch committed
131
  conductor = boxes[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
}

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;
Cassio Kirch's avatar
Cassio Kirch committed
165 166
  struct Boid* const boids = parameters -> boids;  /* struct Boid array. */
  //struct Box* const boxes  = parameters  ->  boxes;  /* struct Box array. */
Cassio Kirch's avatar
Cassio Kirch committed
167 168 169 170 171

  unsigned int boidCount;

  for (boidCount = parameters -> left;
       boidCount < parameters -> right; ++boidCount)
Cassio Kirch's avatar
Cassio Kirch committed
172
    setNextPosition ((boids + boidCount));
Cassio Kirch's avatar
Cassio Kirch committed
173 174 175 176 177 178 179
  return NULL;
}

void*
callNextVelocityThread (void *input)
{
  const struct Parameters* const parameters = input;
Cassio Kirch's avatar
Cassio Kirch committed
180 181
  struct Boid* const boids = parameters -> boids;    /* struct Boid array. */
  struct Box* const boxes = parameters -> boxes;    /* struct Box array. */
Cassio Kirch's avatar
Cassio Kirch committed
182 183 184 185
  unsigned int boidCount;

  for (boidCount = parameters -> left;
       boidCount < parameters -> right; ++boidCount)
Cassio Kirch's avatar
Cassio Kirch committed
186
    setNextVelocity (boids + boidCount, boxes);
Cassio Kirch's avatar
Cassio Kirch committed
187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205
  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);
}