8 #ifndef MULTIPOLEMOMENTS_H
9 #define MULTIPOLEMOMENTS_H
15 #include <OrientedBox.h>
23 #if CMK_SSE && defined(HEXADECAPOLE)
33 void momEvalMomr(
MOMR *m,SSEcosmoType dir0,SSEcosmoType x,SSEcosmoType y,
34 SSEcosmoType z,SSEcosmoType *fPot,SSEcosmoType *ax,
35 SSEcosmoType *ay,SSEcosmoType *az)
37 const SSEcosmoType onethird = 1.0/3.0;
38 SSEcosmoType xx,xy,xz,yy,yz,zz;
39 SSEcosmoType xxx,xxy,xxz,xyy,yyy,yyz,xyz;
40 SSEcosmoType tx,ty,tz,dir2,g2,g3,g4;
45 g2 = 3.0*dir*dir2*dir2;
57 xxx = x*(onethird*xx - zz);
58 xxz = z*(xx - onethird*zz);
59 yyy = y*(onethird*yy - zz);
60 yyz = z*(yy - onethird*zz);
69 tx = g4*(m->xxxx*xxx + m->xyyy*yyy + m->xxxy*xxy + m->xxxz*xxz + m->xxyy*xyy + m->xxyz*xyz + m->xyyz*yyz);
70 ty = g4*(m->xyyy*xyy + m->xxxy*xxx + m->yyyy*yyy + m->yyyz*yyz + m->xxyy*xxy + m->xxyz*xxz + m->xyyz*xyz);
71 tz = g4*(-m->xxxx*xxz - (m->xyyy + m->xxxy)*xyz - m->yyyy*yyz + m->xxxz*xxx + m->yyyz*yyy - m->xxyy*(xxz + yyz) + m->xxyz*xxy + m->xyyz*xyy);
72 g4 = 0.25*(tx*x + ty*y + tz*z);
73 xxx = g3*(m->xxx*xx + m->xyy*yy + m->xxy*xy + m->xxz*xz + m->xyz*yz);
74 xxy = g3*(m->xyy*xy + m->xxy*xx + m->yyy*yy + m->yyz*yz + m->xyz*xz);
75 xxz = g3*(-(m->xxx + m->xyy)*xz - (m->xxy + m->yyy)*yz + m->xxz*xx + m->yyz*yy + m->xyz*xy);
76 g3 = onethird*(xxx*x + xxy*y + xxz*z);
77 xx = g2*(m->xx*x + m->xy*y + m->xz*z);
78 xy = g2*(m->yy*y + m->xy*x + m->yz*z);
79 xz = g2*(-(m->xx + m->yy)*z + m->xz*x + m->yz*y);
80 g2 = 0.5*(xx*x + xy*y + xz*z);
82 dir2 *= -(dir + 5.0*g2 + 7.0*g3 + 9.0*g4);
83 *fPot += dir + g2 + g3 + g4;
84 *ax += xx + xxx + tx + x*dir2;
85 *ay += xy + xxy + ty + y*dir2;
86 *az += xz + xxz + tz + z*dir2;
102 void momEvalFmomrcm(
FMOMR *m,SSEcosmoType u,SSEcosmoType dir,SSEcosmoType x,
103 SSEcosmoType y,SSEcosmoType z,
104 SSEcosmoType *fPot,SSEcosmoType *ax,SSEcosmoType *ay,
105 SSEcosmoType *az,SSEcosmoType *magai) {
106 const SSEcosmoType onethird = 1.0f/3.0f;
107 SSEcosmoType xx,xy,xz,yy,yz,zz;
108 SSEcosmoType xxx,xxy,xxz,xyy,yyy,yyz,xyz;
109 SSEcosmoType tx,ty,tz,g0,g2,g3,g4;
128 xxx = x*(onethird*xx - zz);
129 xxz = z*(xx - onethird*zz);
130 yyy = y*(onethird*yy - zz);
131 yyz = z*(yy - onethird*zz);
140 tx = g4*(m->xxxx*xxx + m->xyyy*yyy + m->xxxy*xxy + m->xxxz*xxz + m->xxyy*xyy + m->xxyz*xyz + m->xyyz*yyz);
141 ty = g4*(m->xyyy*xyy + m->xxxy*xxx + m->yyyy*yyy + m->yyyz*yyz + m->xxyy*xxy + m->xxyz*xxz + m->xyyz*xyz);
142 tz = g4*(-m->xxxx*xxz - (m->xyyy + m->xxxy)*xyz - m->yyyy*yyz + m->xxxz*xxx + m->yyyz*yyy - m->xxyy*(xxz + yyz) + m->xxyz*xxy + m->xyyz*xyy);
143 g4 = 0.25*(tx*x + ty*y + tz*z);
144 xxx = g3*(m->xxx*xx + m->xyy*yy + m->xxy*xy + m->xxz*xz + m->xyz*yz);
145 xxy = g3*(m->xyy*xy + m->xxy*xx + m->yyy*yy + m->yyz*yz + m->xyz*xz);
146 xxz = g3*(-(m->xxx + m->xyy)*xz - (m->xxy + m->yyy)*yz + m->xxz*xx + m->yyz*yy + m->xyz*xy);
147 g3 = onethird*(xxx*x + xxy*y + xxz*z);
148 xx = g2*(m->xx*x + m->xy*y + m->xz*z);
149 xy = g2*(m->yy*y + m->xy*x + m->yz*z);
150 xz = g2*(-(m->xx + m->yy)*z + m->xz*x + m->yz*y);
151 g2 = 0.5*(xx*x + xy*y + xz*z);
153 *fPot += -(g0 + g2 + g3 + g4);
154 g0 += 5*g2 + 7*g3 + 9*g4;
155 *ax += dir*(xx + xxx + tx - x*g0);
156 *ay += dir*(xy + xxy + ty - y*g0);
157 *az += dir*(xz + xxz + tz - z*g0);
174 Vector3D<cosmoType>
cm;
176 #ifdef COOLING_MOLECULARH
177 double totalLW, totalgas;
178 Vector3D<double> cLW, cgas;
179 double xxgas, yygas, zzgas;
185 //Tensor for higher order moments goes here
186 double xx, xy, xz, yy, yz, zz;
192 #ifdef COOLING_MOLECULARH
193 totalLW = 0, totalgas = 0;
194 cLW.x = cLW.y = cLW.z = 0;
195 cgas.x = cgas.y = cgas.z = 0;
196 xxgas = yygas = zzgas = 0;
202 xx = xy = xz = yy = yz = zz = 0;
212 soft = 0.5*(soft + m.soft);
223 Vector3D<cosmoType> cm1 =
cm;
225 #ifdef COOLING_MOLECULARH
226 double totalLW1 = totalLW;
227 if (m.totalLW != 0) {
228 totalLW = log10(pow(10,totalLW - 30.0) + pow(10,m.totalLW - 30.0)) + 30.0;
229 cLW = (pow(10,totalLW1 - 30.0)*cLW + pow(10,m.totalLW - 30.0)*m.cLW)/pow(10,totalLW - 30.0);
232 double totalgas1 = totalgas;
233 totalgas += m.totalgas;
234 Vector3D<double> cgas1 = cgas;
236 cgas = (totalgas1*cgas1 + m.totalgas*m.cgas)/totalgas;
238 Vector3D<double> drgas = cgas1 - cgas;
239 xxgas += totalgas1*drgas[0]*drgas[0];
240 yygas += totalgas1*drgas[1]*drgas[1];
241 zzgas += totalgas1*drgas[2]*drgas[2];
242 drgas = m.cgas - cgas;
243 xxgas += m.xxgas + m.totalgas*drgas[0]*drgas[0];
244 yygas += m.yygas + m.totalgas*drgas[1]*drgas[1];
245 zzgas += m.zzgas + m.totalgas*drgas[2]*drgas[2];
248 Vector3D<cosmoType> dr = cm1 -
cm;
249 momShiftFmomr(&mom, radius, dr.x, dr.y, dr.z);
252 momShiftFmomr(&mom2, m.radius, dr.x, dr.y, dr.z);
253 momScaledAddFmomr(&mom, radius, &mom2, m.radius);
256 Vector3D<double> dr = cm1 -
cm;
257 xx += m1*dr[0]*dr[0];
258 yy += m1*dr[1]*dr[1];
259 zz += m1*dr[2]*dr[2];
260 xy += m1*dr[0]*dr[1];
261 xz += m1*dr[0]*dr[2];
262 yz += m1*dr[1]*dr[2];
275 template <
typename ParticleType>
280 soft = 0.5*(soft + p.soft);
281 cm = 0.5*(
cm + p.position);
284 soft = (m1*soft + p.mass*p.soft)/
totalMass;
285 Vector3D<cosmoType> cm1 =
cm;
287 #ifdef COOLING_MOLECULARH
288 double totalLW1 = totalLW;
290 if (p.dStarLymanWerner() != 0) {
291 totalLW = log10(pow(10,totalLW - 30.0) + pow(10,p.dStarLymanWerner() - 30.0)) + 30.0;
292 cLW = (pow(10,totalLW1 - 30.0)*cLW + pow(10,p.dStarLymanWerner() - 30.0)*p.position)/pow(10,totalLW - 30.0);
296 double totalgas1 = totalgas;
297 Vector3D<double> cgas1 = cgas;
301 cgas = (totalgas1*cgas1 + p.mass * p.position)/totalgas;
304 Vector3D<double> drgas = cgas1 - cgas;
306 xxgas += totalgas1*drgas[0]*drgas[0];
307 yygas += totalgas1*drgas[1]*drgas[1];
308 zzgas += totalgas1*drgas[2]*drgas[2];
310 drgas = p.position - cgas;
312 xxgas += p.mass*drgas[0]*drgas[0];
313 yygas += p.mass*drgas[1]*drgas[1];
314 zzgas += p.mass*drgas[2]*drgas[2];
324 Vector3D<cosmoType> dr = cm1 -
cm;
325 momShiftFmomr(&mom, radius, dr.x, dr.y, dr.z);
326 dr = p.position -
cm;
328 momMakeFmomr(&momPart, p.mass, radius, dr.x, dr.y, dr.z);
329 momAddFmomr(&mom, &momPart);
332 Vector3D<double> dr = cm1 -
cm;
334 xx += m1*dr[0]*dr[0];
335 yy += m1*dr[1]*dr[1];
336 zz += m1*dr[2]*dr[2];
337 xy += m1*dr[0]*dr[1];
338 xz += m1*dr[0]*dr[2];
339 yz += m1*dr[1]*dr[2];
341 dr = p.position -
cm;
343 xx += p.mass*dr[0]*dr[0];
344 yy += p.mass*dr[1]*dr[1];
345 zz += p.mass*dr[2]*dr[2];
346 xy += p.mass*dr[0]*dr[1];
347 xz += p.mass*dr[0]*dr[2];
348 yz += p.mass*dr[1]*dr[2];
359 soft = 0.5*(soft - m.soft);
368 Vector3D<cosmoType> dr =
cm - newMoments.
cm;
369 newMoments.mom = mom;
370 momShiftFmomr(&mom, radius, dr.x, dr.y, dr.z);
372 dr = m.
cm - newMoments.
cm;
373 momShiftFmomr(&mom2, m.radius, dr.x, dr.y, dr.z);
374 momScaledSubFmomr(&newMoments.mom, radius, &mom2, m.radius);
377 Vector3D<double> dr =
cm - newMoments.
cm;
378 newMoments.xx = xx +
totalMass*dr[0]*dr[0];
379 newMoments.yy = yy +
totalMass*dr[1]*dr[1];
380 newMoments.zz = zz +
totalMass*dr[2]*dr[2];
381 newMoments.xy = xy +
totalMass*dr[0]*dr[1];
382 newMoments.xz = xz +
totalMass*dr[0]*dr[2];
383 newMoments.yz = yz +
totalMass*dr[1]*dr[2];
384 dr = m.
cm - newMoments.
cm;
385 newMoments.xx -= m.xx + m.
totalMass*dr[0]*dr[0];
386 newMoments.yy -= m.yy + m.
totalMass*dr[1]*dr[1];
387 newMoments.zz -= m.zz + m.
totalMass*dr[2]*dr[2];
388 newMoments.xy -= m.xy + m.
totalMass*dr[0]*dr[1];
389 newMoments.xz -= m.xz + m.
totalMass*dr[0]*dr[2];
390 newMoments.yz -= m.yz + m.
totalMass*dr[1]*dr[2];
405 xx = xy = xz = yy = yz = zz = 0;
408 inline cosmoType getRadius()
const {
return radius;}
411 const OrientedBox<double>& box);
412 template<
typename ParticleType>
414 const ParticleType * begin,
415 const ParticleType * end);
417 const OrientedBox<double>& box);
429 #ifdef COOLING_MOLECULARH
439 p((
char *) &m.mom,
sizeof(m.mom));
456 Vector3D<cosmoType> delta1 = m.
cm - box.lesser_corner;
457 Vector3D<cosmoType> delta2 = box.greater_corner - m.
cm;
458 delta1.x = (delta1.x > delta2.x ? delta1.x : delta2.x);
459 delta1.y = (delta1.y > delta2.y ? delta1.y : delta2.y);
460 delta1.z = (delta1.z > delta2.z ? delta1.z : delta2.z);
461 cosmoType newradius = delta1.length();
463 momRescaleFmomr(&m.mom, newradius, m.radius);
465 m.radius = newradius;
471 const OrientedBox<double>& box) {
472 Vector3D<cosmoType> delta = box.greater_corner - box.lesser_corner;
473 cosmoType newradius = 0.5*delta.length();
476 momRescaleFmomr(&m.mom, newradius, m.radius);
478 m.radius = newradius;
482 template <
typename ParticleType>
484 Vector3D<cosmoType> cm = m.
cm;
486 cosmoType newradius = 0;
487 for(
const ParticleType* iter = begin; iter != end; ++iter) {
488 d = (cm - iter->position).lengthSquared();
492 if(newradius > 0.0) {
493 newradius = sqrt(newradius);
495 momRescaleFmomr(&m.mom, newradius, m.radius);
497 m.radius = newradius;
501 #endif //MULTIPOLEMOMENTS_H
A representation of a multipole expansion.
Definition: MultipoleMoments.h:163
friend void calculateRadiusBox(MultipoleMoments &m, const OrientedBox< double > &box)
Definition: MultipoleMoments.h:470
Version of MultipoleMoments using cudatype.
Definition: cuda_typedef.h:95
moment tensor components for reduced multipoles.
Definition: moments.h:30
MultipoleMoments operator-(const MultipoleMoments &m)
Subtract an expansion from this larger one, yielding the leftover.
Definition: MultipoleMoments.h:355
void calculateRadiusFarthestCorner(MultipoleMoments &m, const OrientedBox< double > &box)
Given an enclosing box, set the multipole expansion size to the distance from the center of mass to t...
Definition: MultipoleMoments.h:455
void calculateRadiusBox(MultipoleMoments &m, const OrientedBox< double > &box)
Definition: MultipoleMoments.h:470
void clear()
Reset this expansion to nothing.
Definition: MultipoleMoments.h:396
MultipoleMoments & operator+=(const MultipoleMoments &m)
Add two expansions together, using parallel axis theorem.
Definition: MultipoleMoments.h:207
MultipoleMoments & operator+=(const ParticleType &p)
Add the contribution of a particle to this multipole expansion.
Definition: MultipoleMoments.h:276
friend void calculateRadiusFarthestCorner(MultipoleMoments &m, const OrientedBox< double > &box)
Given an enclosing box, set the multipole expansion size to the distance from the center of mass to t...
Definition: MultipoleMoments.h:455
void calculateRadiusFarthestParticle(MultipoleMoments &m, const ParticleType *begin, const ParticleType *end)
Given the positions that make up a multipole expansion, set the distance to the farthest particle fro...
Definition: MultipoleMoments.h:483
cosmoType totalMass
The total mass represented by this expansion.
Definition: MultipoleMoments.h:172
Vector3D< cosmoType > cm
The center of mass (zeroth order multipole)
Definition: MultipoleMoments.h:174
friend void calculateRadiusFarthestParticle(MultipoleMoments &m, const ParticleType *begin, const ParticleType *end)
Given the positions that make up a multipole expansion, set the distance to the farthest particle fro...
Definition: MultipoleMoments.h:483