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);
}