Swarm-NG  1.1
gravitation_accjerk.hpp
Go to the documentation of this file.
1 /*************************************************************************
2  * Copyright (C) 2010 by Saleh Dindar and the Swarm-NG Development Team *
3  * *
4  * This program is free software; you can redistribute it and/or modify *
5  * it under the terms of the GNU General Public License as published by *
6  * the Free Software Foundation; either version 3 of the License. *
7  * *
8  * This program is distributed in the hope that it will be useful, *
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
11  * GNU General Public License for more details. *
12  * *
13  * You should have received a copy of the GNU General Public License *
14  * along with this program; if not, write to the *
15  * Free Software Foundation, Inc., *
16  * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
17  ************************************************************************/
18 
26 #pragma once
27 
28 #include "gravitation_common.hpp"
29 
30 namespace swarm { namespace gpu { namespace bppt {
31 
55 template<class T>
57  public:
58  const static int nbod = T::n;
59  const static int pair_count = (nbod*(nbod-1))/2;
60  const static int CHUNK_SIZE = SHMEM_CHUNK_SIZE;
61 
62  typedef GravitationAccJerkScalars<CHUNK_SIZE> shared_data [pair_count][3];
63 
64  private:
65  public: // hack to make this public to test whether it's worth using shared memory for some small steps
66  ensemble::SystemRef& sys;
67  shared_data &shared;
68 
69 
70  public:
71 
81  GENERIC GravitationAccJerk(ensemble::SystemRef& sys,shared_data &shared):sys(sys),shared(shared){ }
82 
83  private:
84 
92  GENERIC void calc_pair(int ij)const{
93  int i = first<nbod>( ij );
94  int j = second<nbod>( ij );
95  if(i != j){
96 
97  // Relative vector from planet i to planet j
98  double dx[3] = { sys[j][0].pos()- sys[i][0].pos(),sys[j][1].pos()- sys[i][1].pos(), sys[j][2].pos()- sys[i][2].pos() };
99  // Relative velocity between the planets
100  double dv[3] = { sys[j][0].vel()- sys[i][0].vel(),sys[j][1].vel()- sys[i][1].vel(), sys[j][2].vel()- sys[i][2].vel() };
101 
102  // Distance between the planets
103  double r2 = dx[0]*dx[0]+dx[1]*dx[1]+dx[2]*dx[2];
104 
105  double jerk_mag = inner_product(dx,dv) * 3.0 / r2;
106  double acc_mag = rsqrt(r2) / r2;
107 
108 #pragma unroll
109  for(int c = 0; c < 3; c ++)
110  {
111  shared[ij][c].acc() = dx[c]* acc_mag;
112  shared[ij][c].jerk() = (dv[c] - dx[c] * jerk_mag ) * acc_mag;
113  }
114  }
115 
116  }
117 
118 
119  public:
120 
129  GENERIC void sum(int b,int c,double& acc, double & jerk)const{
130  // Total acceleration from other planets
131  double acc_from_planets = 0.0;
132  // Total acceleration from body 0 (sun or star)
133  double acc_from_sun = 0.0;
134  // Total jerk from other planets
135  double jerk_from_planets = 0.0;
136  // Total jerk from body 0 (sun or star)
137  double jerk_from_sun = 0.0;
138 
140 #pragma unroll
141  for(int d = 0; d < pair_count; d++){
142  int x = first<nbod>(d), y= second<nbod>(d);
143 
144  if(x == b){
145  if(y == 0) {
146  acc_from_sun += shared[d][c].acc() * sys[y].mass();
147  jerk_from_sun += shared[d][c].jerk() * sys[y].mass();
148  } else {
149  acc_from_planets += shared[d][c].acc() * sys[y].mass();
150  jerk_from_planets += shared[d][c].jerk() * sys[y].mass();
151  }
152  }else if(y == b){
153  if(x == 0) {
154  acc_from_sun -= shared[d][c].acc() * sys[x].mass();
155  jerk_from_sun -= shared[d][c].jerk() * sys[x].mass();
156  } else {
157  acc_from_planets -= shared[d][c].acc() * sys[x].mass();
158  jerk_from_planets -= shared[d][c].jerk() * sys[x].mass();
159  }
160  }
161  }
162 
163  acc = acc_from_sun + acc_from_planets;
164  jerk = jerk_from_sun + jerk_from_planets;
165  }
166 
167  public:
168 
186  GPUAPI void operator() (int ij,int b,int c,double& pos,double& vel,double& acc,double& jerk) const{
187  // Write positions to shared (global) memory
188  if(b < nbod && c < 3)
189  sys[b][c].pos() = pos , sys[b][c].vel() = vel;
190  __syncthreads();
191  if(ij < pair_count)
192  calc_pair(ij);
193  __syncthreads();
194  if(b < nbod && c < 3){
195  sum(b,c,acc,jerk);
196  }
197  }
198 
201  return (nbod*3>(nbod-1)*nbod/2) ? nbod*3 : (nbod-1)*nbod/2;
202  }
203 
205  static GENERIC int shmem_per_system() {
206  return sizeof(shared_data)/CHUNK_SIZE;
207  }
208 
209 
210 
211 };
212 
213 } } } // end of namespace bppt :: gpu :: swarm