nextstep.c 6.61 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
28
29
30
31
32
33
#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, \
         double* const sumFX, double* const sumFY,              \
         double* const sumVX, double* const sumVY)
{
  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
        {
Cassio Kirch's avatar
Cassio Kirch committed
46
47
48
49
          *sumFX += BETA11 * force * distance.cosine;
          *sumFY += BETA11 * force * distance.sine;
          *sumVX += ALPHA11 * conductor -> velocity[X] / V0;
          *sumVY += ALPHA11 * conductor -> velocity[Y] / V0;
Cassio Kirch's avatar
Cassio Kirch committed
50
        }
Cassio Kirch's avatar
Cassio Kirch committed
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
        
        else if (conductor -> type == ECTODERM &&       \
                 boid -> type == ECTODERM)
        {
          *sumFX += BETA22 * force * distance.cosine;
          *sumFY += BETA22 * force * distance.sine;
          *sumVX += ALPHA22 * conductor -> velocity[X] / V0;
          *sumVY += ALPHA22 * conductor -> velocity[Y] / V0;
        }
        
        else
        {
          *sumFX += BETA12 * force * distance.cosine;
          *sumFY += BETA12 * force * distance.sine;
          *sumVX += ALPHA12 * conductor -> velocity[X] / V0;
          *sumVY += ALPHA12 * conductor -> velocity[Y] / V0;
          //if (conductor -> type == ECTODERM) /* And boid->type==ENDO */
          //boid -> ectoNeighbors++;
        }
Cassio Kirch's avatar
Cassio Kirch committed
70
71

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

Cassio Kirch's avatar
Cassio Kirch committed
78
      }
Cassio Kirch's avatar
Cassio Kirch committed
79
    }
Cassio Kirch's avatar
Cassio Kirch committed
80
81
    conductor = conductor -> next;
  }
Cassio Kirch's avatar
Cassio Kirch committed
82
83
84
85
86
87
88
89
90
91
}

void
setNextVelocity (struct Boid* const boid, const struct Box box[])
{
  double sumVX = 0.0, sumVY = 0.0;    /* For alpha and velocity sum. */
  double uAngle, uX, uY;    /* For nu and random things. */
  double sumFX = 0.0, sumFY = 0.0;    /* For beta and force sum. */
  double sum, sumX, sumY;
  struct Boid *conductor;
92
93

#if defined (ENDO_GAMMA) || defined (ECTO_GAMMA)
Cassio Kirch's avatar
Cassio Kirch committed
94
95
  boid -> endoNeighbors = 0u;
  boid -> ectoNeighbors = 0u;
Cassio Kirch's avatar
Cassio Kirch committed
96
  boid -> gamma = 0.0;
97
#endif
Cassio Kirch's avatar
Cassio Kirch committed
98
  
Cassio Kirch's avatar
Cassio Kirch committed
99
100
101
102
103
104
105
  /* check neighbors in the same box */
  conductor = box[boid -> boxID].first;
  makeSum(boid, conductor, &sumFX, &sumFY, &sumVX, &sumVY);
  
  /* check neighbors in the north box */
  conductor = box[getNorthBoxID (boid -> boxID)].first;
  makeSum(boid, conductor, &sumFX, &sumFY, &sumVX, &sumVY);
Cassio Kirch's avatar
Cassio Kirch committed
106
  
Cassio Kirch's avatar
Cassio Kirch committed
107
108
109
  /* check neighbors in the south box */
  conductor = box[getSouthBoxID (boid -> boxID)].first;
  makeSum(boid, conductor, &sumFX, &sumFY, &sumVX, &sumVY);
Cassio Kirch's avatar
Cassio Kirch committed
110
  
Cassio Kirch's avatar
Cassio Kirch committed
111
112
113
  /* check neighbors in the west box */
  conductor = box[getWestBoxID (boid -> boxID)].first;
  makeSum(boid, conductor, &sumFX, &sumFY, &sumVX, &sumVY);
Cassio Kirch's avatar
Cassio Kirch committed
114
  
Cassio Kirch's avatar
Cassio Kirch committed
115
116
117
  /* check neighbors in the east box */
  conductor = box[getEastBoxID (boid -> boxID)].first;
  makeSum(boid, conductor, &sumFX, &sumFY, &sumVX, &sumVY);
Cassio Kirch's avatar
Cassio Kirch committed
118
  
Cassio Kirch's avatar
Cassio Kirch committed
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
  /* check neighbors in the northeast box */
  conductor = box[getEastBoxID (getNorthBoxID (boid -> boxID))].first;
  makeSum(boid, conductor, &sumFX, &sumFY, &sumVX, &sumVY);

  /* check neighbors in the southeast box */
  conductor = box[getEastBoxID (getSouthBoxID (boid -> boxID))].first;
  makeSum(boid, conductor, &sumFX, &sumFY, &sumVX, &sumVY);

  /* check neighbors in the northwest box */
  conductor = box[getWestBoxID (getNorthBoxID (boid -> boxID))].first;
  makeSum(boid, conductor, &sumFX, &sumFY, &sumVX, &sumVY);

  /* check neighbors in the southwest box */
  conductor = box[getWestBoxID (getSouthBoxID (boid -> boxID))].first;
  makeSum(boid, conductor, &sumFX, &sumFY, &sumVX, &sumVY);

  uAngle = RANDOM_0 (PI * 2.0);
  uX = cos (uAngle);
  uY = sin (uAngle);

  sumX = (double) ETA * uX + sumVX + sumFX;
  sumY = (double) ETA * uY + sumVY + sumFY;
  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
145

146
#if defined (ENDO_GAMMA) || defined (ECTO_GAMMA)
Cassio Kirch's avatar
Cassio Kirch committed
147
  if (boid -> ectoNeighbors != 0u || boid -> endoNeighbors != 0u)
Cassio Kirch's avatar
Cassio Kirch committed
148
149
    boid -> gamma = (double)boid -> ectoNeighbors / \
      (boid -> endoNeighbors + boid -> ectoNeighbors);
150
#endif
Cassio Kirch's avatar
Cassio Kirch committed
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
206
207
208
209
210
211
}

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)
     checkLimits(boid+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);
}