Revision b695f83ab5b508e1bf4de76a862a7402f85efc7c authored by Tim Haines on 29 July 2016, 02:19:32 UTC, committed by Tim Haines on 12 August 2016, 05:27:38 UTC
Change-Id: I2491786cd5d79c69f33defee5a59c223f076ce65
1 parent a8354b8
moments.c
/*
* Mulitpole moment routines.
* Main author: Joachim Stadel as part of PKGRAV
*/
#include "moments.h"
#include <assert.h>
#include <math.h>
#include <stdio.h>
void momClearLocr(LOCR *l) {
l->m = 0;
l->x = 0;
l->y = 0;
l->z = 0;
l->xx = 0;
l->xy = 0;
l->yy = 0;
l->xz = 0;
l->yz = 0;
l->xxx = 0;
l->xxy = 0;
l->xyy = 0;
l->yyy = 0;
l->xxz = 0;
l->xyz = 0;
l->yyz = 0;
l->xxxx = 0;
l->xxxy = 0;
l->xxyy = 0;
l->xyyy = 0;
l->yyyy = 0;
l->xxxz = 0;
l->xxyz = 0;
l->xyyz = 0;
l->yyyz = 0;
l->xxxxx = 0;
l->xxxxy = 0;
l->xxxyy = 0;
l->xxyyy = 0;
l->xyyyy = 0;
l->yyyyy = 0;
l->xxxxz = 0;
l->xxxyz = 0;
l->xxyyz = 0;
l->xyyyz = 0;
l->yyyyz = 0;
}
void momClearMomr(MOMR *mr) {
mr->m = 0.0;
mr->xx = 0.0;
mr->yy = 0.0;
mr->xy = 0.0;
mr->xz = 0.0;
mr->yz = 0.0;
mr->xxx = 0.0;
mr->xyy = 0.0;
mr->xxy = 0.0;
mr->yyy = 0.0;
mr->xxz = 0.0;
mr->yyz = 0.0;
mr->xyz = 0.0;
mr->xxxx = 0.0;
mr->xyyy = 0.0;
mr->xxxy = 0.0;
mr->yyyy = 0.0;
mr->xxxz = 0.0;
mr->yyyz = 0.0;
mr->xxyy = 0.0;
mr->xxyz = 0.0;
mr->xyyz = 0.0;
}
void momClearFmomr(FMOMR *l) {
l->m = 0;
l->xx = 0;
l->yy = 0;
l->xy = 0;
l->xz = 0;
l->yz = 0;
l->xxx = 0;
l->xyy = 0;
l->xxy = 0;
l->yyy = 0;
l->xxz = 0;
l->yyz = 0;
l->xyz = 0;
l->xxxx = 0;
l->xyyy = 0;
l->xxxy = 0;
l->yyyy = 0;
l->xxxz = 0;
l->yyyz = 0;
l->xxyy = 0;
l->xxyz = 0;
l->xyyz = 0;
}
/*
** This function adds the complete moment ma to the complete moment mc
*/
void momAddMomc(MOMC *mc, MOMC *ma) {
mc->m += ma->m;
mc->xx += ma->xx;
mc->yy += ma->yy;
mc->xy += ma->xy;
mc->xz += ma->xz;
mc->yz += ma->yz;
mc->xxx += ma->xxx;
mc->xyy += ma->xyy;
mc->xxy += ma->xxy;
mc->yyy += ma->yyy;
mc->xxz += ma->xxz;
mc->yyz += ma->yyz;
mc->xyz += ma->xyz;
mc->xxxx += ma->xxxx;
mc->xyyy += ma->xyyy;
mc->xxxy += ma->xxxy;
mc->yyyy += ma->yyyy;
mc->xxxz += ma->xxxz;
mc->yyyz += ma->yyyz;
mc->xxyy += ma->xxyy;
mc->xxyz += ma->xxyz;
mc->xyyz += ma->xyyz;
mc->zz += ma->zz;
mc->xzz += ma->xzz;
mc->yzz += ma->yzz;
mc->zzz += ma->zzz;
mc->xxzz += ma->xxzz;
mc->xyzz += ma->xyzz;
mc->xzzz += ma->xzzz;
mc->yyzz += ma->yyzz;
mc->yzzz += ma->yzzz;
mc->zzzz += ma->zzzz;
}
/*
** This function adds the reduced moment ma to the reduced moment mc
*/
void momAddMomr(MOMR *mr, MOMR *ma) {
mr->m += ma->m;
mr->xx += ma->xx;
mr->yy += ma->yy;
mr->xy += ma->xy;
mr->xz += ma->xz;
mr->yz += ma->yz;
mr->xxx += ma->xxx;
mr->xyy += ma->xyy;
mr->xxy += ma->xxy;
mr->yyy += ma->yyy;
mr->xxz += ma->xxz;
mr->yyz += ma->yyz;
mr->xyz += ma->xyz;
mr->xxxx += ma->xxxx;
mr->xyyy += ma->xyyy;
mr->xxxy += ma->xxxy;
mr->yyyy += ma->yyyy;
mr->xxxz += ma->xxxz;
mr->yyyz += ma->yyyz;
mr->xxyy += ma->xxyy;
mr->xxyz += ma->xxyz;
mr->xyyz += ma->xyyz;
}
/*
** This function adds the reduced moment ma to the reduced moment mr.
*/
void momAddFmomr(FMOMR *mr, FMOMR *ma) {
mr->m += ma->m;
mr->xx += ma->xx;
mr->yy += ma->yy;
mr->xy += ma->xy;
mr->xz += ma->xz;
mr->yz += ma->yz;
mr->xxx += ma->xxx;
mr->xyy += ma->xyy;
mr->xxy += ma->xxy;
mr->yyy += ma->yyy;
mr->xxz += ma->xxz;
mr->yyz += ma->yyz;
mr->xyz += ma->xyz;
mr->xxxx += ma->xxxx;
mr->xyyy += ma->xyyy;
mr->xxxy += ma->xxxy;
mr->yyyy += ma->yyyy;
mr->xxxz += ma->xxxz;
mr->yyyz += ma->yyyz;
mr->xxyy += ma->xxyy;
mr->xxyz += ma->xxyz;
mr->xyyz += ma->xyyz;
}
/*
** This function adds the reduced scaled moment ma to the reduced scaled moment
*mr.
** It needs to correctly rescale the moments of ma to be compatible with the
*scaling of mr.
*/
void momScaledAddFmomr(FMOMR *mr, cosmoType ur, FMOMR *ma, cosmoType ua) {
cosmoType f, s;
assert(ur > 0.0 && ua > 0);
f = ua / ur;
s = f;
mr->m += ma->m;
s *= f;
mr->xx += s * ma->xx;
mr->yy += s * ma->yy;
mr->xy += s * ma->xy;
mr->xz += s * ma->xz;
mr->yz += s * ma->yz;
s *= f;
mr->xxx += s * ma->xxx;
mr->xyy += s * ma->xyy;
mr->xxy += s * ma->xxy;
mr->yyy += s * ma->yyy;
mr->xxz += s * ma->xxz;
mr->yyz += s * ma->yyz;
mr->xyz += s * ma->xyz;
s *= f;
mr->xxxx += s * ma->xxxx;
mr->xyyy += s * ma->xyyy;
mr->xxxy += s * ma->xxxy;
mr->yyyy += s * ma->yyyy;
mr->xxxz += s * ma->xxxz;
mr->yyyz += s * ma->yyyz;
mr->xxyy += s * ma->xxyy;
mr->xxyz += s * ma->xxyz;
mr->xyyz += s * ma->xyyz;
}
/*
** This function rescales reduced scaled moment mr.
*/
void momRescaleFmomr(FMOMR *mr, cosmoType unew, cosmoType uold) {
cosmoType f, s;
f = uold / unew;
s = f;
s *= f;
mr->xx *= s;
mr->yy *= s;
mr->xy *= s;
mr->xz *= s;
mr->yz *= s;
s *= f;
mr->xxx *= s;
mr->xyy *= s;
mr->xxy *= s;
mr->yyy *= s;
mr->xxz *= s;
mr->yyz *= s;
mr->xyz *= s;
s *= f;
mr->xxxx *= s;
mr->xyyy *= s;
mr->xxxy *= s;
mr->yyyy *= s;
mr->xxxz *= s;
mr->yyyz *= s;
mr->xxyy *= s;
mr->xxyz *= s;
mr->xyyz *= s;
}
/*
** This function multiply-adds the complete moment ma
*/
void momMulAddMomc(MOMC *mc, double m, MOMC *ma) {
mc->m += m * ma->m;
mc->xx += m * ma->xx;
mc->yy += m * ma->yy;
mc->xy += m * ma->xy;
mc->xz += m * ma->xz;
mc->yz += m * ma->yz;
mc->xxx += m * ma->xxx;
mc->xyy += m * ma->xyy;
mc->xxy += m * ma->xxy;
mc->yyy += m * ma->yyy;
mc->xxz += m * ma->xxz;
mc->yyz += m * ma->yyz;
mc->xyz += m * ma->xyz;
mc->xxxx += m * ma->xxxx;
mc->xyyy += m * ma->xyyy;
mc->xxxy += m * ma->xxxy;
mc->yyyy += m * ma->yyyy;
mc->xxxz += m * ma->xxxz;
mc->yyyz += m * ma->yyyz;
mc->xxyy += m * ma->xxyy;
mc->xxyz += m * ma->xxyz;
mc->xyyz += m * ma->xyyz;
mc->zz += m * ma->zz;
mc->xzz += m * ma->xzz;
mc->yzz += m * ma->yzz;
mc->zzz += m * ma->zzz;
mc->xxzz += m * ma->xxzz;
mc->xyzz += m * ma->xyzz;
mc->xzzz += m * ma->xzzz;
mc->yyzz += m * ma->yyzz;
mc->yzzz += m * ma->yzzz;
mc->zzzz += m * ma->zzzz;
}
/*
** This function multiply-adds the reduced moment ma
*/
void momMulAddMomr(MOMR *mr, double m, MOMR *ma) {
mr->m += m * ma->m;
mr->xx += m * ma->xx;
mr->yy += m * ma->yy;
mr->xy += m * ma->xy;
mr->xz += m * ma->xz;
mr->yz += m * ma->yz;
mr->xxx += m * ma->xxx;
mr->xyy += m * ma->xyy;
mr->xxy += m * ma->xxy;
mr->yyy += m * ma->yyy;
mr->xxz += m * ma->xxz;
mr->yyz += m * ma->yyz;
mr->xyz += m * ma->xyz;
mr->xxxx += m * ma->xxxx;
mr->xyyy += m * ma->xyyy;
mr->xxxy += m * ma->xxxy;
mr->yyyy += m * ma->yyyy;
mr->xxxz += m * ma->xxxz;
mr->yyyz += m * ma->yyyz;
mr->xxyy += m * ma->xxyy;
mr->xxyz += m * ma->xxyz;
mr->xyyz += m * ma->xyyz;
}
/*
** This function multiply-adds the reduced scaled moment ma
*/
void momMulAddFmomr(FMOMR *mr, cosmoType ur, cosmoType m, FMOMR *ma,
cosmoType ua) {
cosmoType f;
assert(ua > 0.0 && ur > 0.0);
f = ua / ur;
mr->m += m * ma->m;
m *= f;
m *= f;
mr->xx += m * ma->xx;
mr->yy += m * ma->yy;
mr->xy += m * ma->xy;
mr->xz += m * ma->xz;
mr->yz += m * ma->yz;
m *= f;
mr->xxx += m * ma->xxx;
mr->xyy += m * ma->xyy;
mr->xxy += m * ma->xxy;
mr->yyy += m * ma->yyy;
mr->xxz += m * ma->xxz;
mr->yyz += m * ma->yyz;
mr->xyz += m * ma->xyz;
m *= f;
mr->xxxx += m * ma->xxxx;
mr->xyyy += m * ma->xyyy;
mr->xxxy += m * ma->xxxy;
mr->yyyy += m * ma->yyyy;
mr->xxxz += m * ma->xxxz;
mr->yyyz += m * ma->yyyz;
mr->xxyy += m * ma->xxyy;
mr->xxyz += m * ma->xxyz;
mr->xyyz += m * ma->xyyz;
}
/*
** This function adds the reduced local expansion la to the reduced local
*explansion lr.
*/
void momAddFlocr(FLOCR *lr, FLOCR *la) {
lr->m += la->m;
lr->x += la->x;
lr->y += la->y;
lr->z += la->z;
lr->xx += la->xx;
lr->yy += la->yy;
lr->xy += la->xy;
lr->xz += la->xz;
lr->yz += la->yz;
lr->xxx += la->xxx;
lr->xyy += la->xyy;
lr->xxy += la->xxy;
lr->yyy += la->yyy;
lr->xxz += la->xxz;
lr->yyz += la->yyz;
lr->xyz += la->xyz;
lr->xxxx += la->xxxx;
lr->xyyy += la->xyyy;
lr->xxxy += la->xxxy;
lr->yyyy += la->yyyy;
lr->xxxz += la->xxxz;
lr->yyyz += la->yyyz;
lr->xxyy += la->xxyy;
lr->xxyz += la->xxyz;
lr->xyyz += la->xyyz;
lr->xxxxx += la->xxxxx;
lr->xyyyy += la->xyyyy;
lr->xxxxy += la->xxxxy;
lr->yyyyy += la->yyyyy;
lr->xxxxz += la->xxxxz;
lr->yyyyz += la->yyyyz;
lr->xxxyy += la->xxxyy;
lr->xxyyy += la->xxyyy;
lr->xxxyz += la->xxxyz;
lr->xyyyz += la->xyyyz;
lr->xxyyz += la->xxyyz;
}
/*
** This function adds the reduced scaled local expansion la to the reduced
*scaled local expansion lr.
** It needs to correctly rescale the elements of la to be compatible with the
*scaling of lr.
*/
void momScaledAddFlocr(FLOCR *lr, cosmoType vr, FLOCR *la, cosmoType va) {
cosmoType f, s;
assert(vr > 0.0 && va > 0);
f = va / vr;
s = f;
lr->m += la->m;
lr->x += s * la->x;
lr->y += s * la->y;
lr->z += s * la->z;
s *= f;
lr->xx += s * la->xx;
lr->yy += s * la->yy;
lr->xy += s * la->xy;
lr->xz += s * la->xz;
lr->yz += s * la->yz;
s *= f;
lr->xxx += s * la->xxx;
lr->xyy += s * la->xyy;
lr->xxy += s * la->xxy;
lr->yyy += s * la->yyy;
lr->xxz += s * la->xxz;
lr->yyz += s * la->yyz;
lr->xyz += s * la->xyz;
s *= f;
lr->xxxx += s * la->xxxx;
lr->xyyy += s * la->xyyy;
lr->xxxy += s * la->xxxy;
lr->yyyy += s * la->yyyy;
lr->xxxz += s * la->xxxz;
lr->yyyz += s * la->yyyz;
lr->xxyy += s * la->xxyy;
lr->xxyz += s * la->xxyz;
lr->xyyz += s * la->xyyz;
s *= f;
lr->xxxxx += s * la->xxxxx;
lr->xyyyy += s * la->xyyyy;
lr->xxxxy += s * la->xxxxy;
lr->yyyyy += s * la->yyyyy;
lr->xxxxz += s * la->xxxxz;
lr->yyyyz += s * la->yyyyz;
lr->xxxyy += s * la->xxxyy;
lr->xxyyy += s * la->xxyyy;
lr->xxxyz += s * la->xxxyz;
lr->xyyyz += s * la->xyyyz;
lr->xxyyz += s * la->xxyyz;
}
/*
** This function rescales the reduced scaled local expansion lr.
*/
void momRescaleFlocr(FLOCR *lr, cosmoType vnew, cosmoType vold) {
cosmoType f, s;
assert(vnew > 0.0 && vold > 0);
f = vnew / vold;
s = f;
lr->x *= s;
lr->y *= s;
lr->z *= s;
s *= f;
lr->xx *= s;
lr->yy *= s;
lr->xy *= s;
lr->xz *= s;
lr->yz *= s;
s *= f;
lr->xxx *= s;
lr->xyy *= s;
lr->xxy *= s;
lr->yyy *= s;
lr->xxz *= s;
lr->yyz *= s;
lr->xyz *= s;
s *= f;
lr->xxxx *= s;
lr->xyyy *= s;
lr->xxxy *= s;
lr->yyyy *= s;
lr->xxxz *= s;
lr->yyyz *= s;
lr->xxyy *= s;
lr->xxyz *= s;
lr->xyyz *= s;
s *= f;
lr->xxxxx *= s;
lr->xyyyy *= s;
lr->xxxxy *= s;
lr->yyyyy *= s;
lr->xxxxz *= s;
lr->yyyyz *= s;
lr->xxxyy *= s;
lr->xxyyy *= s;
lr->xxxyz *= s;
lr->xyyyz *= s;
lr->xxyyz *= s;
}
/*
** This function subtracts the complete moment ma from the complete moment mc
*/
void momSubMomc(MOMC *mc, MOMC *ma) {
mc->m -= ma->m;
mc->xx -= ma->xx;
mc->yy -= ma->yy;
mc->xy -= ma->xy;
mc->xz -= ma->xz;
mc->yz -= ma->yz;
mc->xxx -= ma->xxx;
mc->xyy -= ma->xyy;
mc->xxy -= ma->xxy;
mc->yyy -= ma->yyy;
mc->xxz -= ma->xxz;
mc->yyz -= ma->yyz;
mc->xyz -= ma->xyz;
mc->xxxx -= ma->xxxx;
mc->xyyy -= ma->xyyy;
mc->xxxy -= ma->xxxy;
mc->yyyy -= ma->yyyy;
mc->xxxz -= ma->xxxz;
mc->yyyz -= ma->yyyz;
mc->xxyy -= ma->xxyy;
mc->xxyz -= ma->xxyz;
mc->xyyz -= ma->xyyz;
mc->zz -= ma->zz;
mc->xzz -= ma->xzz;
mc->yzz -= ma->yzz;
mc->zzz -= ma->zzz;
mc->xxzz -= ma->xxzz;
mc->xyzz -= ma->xyzz;
mc->xzzz -= ma->xzzz;
mc->yyzz -= ma->yyzz;
mc->yzzz -= ma->yzzz;
mc->zzzz -= ma->zzzz;
}
/*
** This function subtracts the reduced moment ma from the reduced moment mr
*/
void momSubMomr(MOMR *mr, MOMR *ma) {
mr->m -= ma->m;
mr->xx -= ma->xx;
mr->yy -= ma->yy;
mr->xy -= ma->xy;
mr->xz -= ma->xz;
mr->yz -= ma->yz;
mr->xxx -= ma->xxx;
mr->xyy -= ma->xyy;
mr->xxy -= ma->xxy;
mr->yyy -= ma->yyy;
mr->xxz -= ma->xxz;
mr->yyz -= ma->yyz;
mr->xyz -= ma->xyz;
mr->xxxx -= ma->xxxx;
mr->xyyy -= ma->xyyy;
mr->xxxy -= ma->xxxy;
mr->yyyy -= ma->yyyy;
mr->xxxz -= ma->xxxz;
mr->yyyz -= ma->yyyz;
mr->xxyy -= ma->xxyy;
mr->xxyz -= ma->xxyz;
mr->xyyz -= ma->xyyz;
}
/*
** This function subtracts the reduced scaled moment ma to the
** reduced scaled moment mr.
** It needs to correctly rescale the moments of ma to be compatible
** with the scaling of mr.
*/
void momScaledSubFmomr(FMOMR *mr, cosmoType ur, FMOMR *ma, cosmoType ua) {
cosmoType f, s;
assert(ur > 0.0 && ua > 0);
f = ua / ur;
s = f;
mr->m -= ma->m;
s *= f;
mr->xx -= s * ma->xx;
mr->yy -= s * ma->yy;
mr->xy -= s * ma->xy;
mr->xz -= s * ma->xz;
mr->yz -= s * ma->yz;
s *= f;
mr->xxx -= s * ma->xxx;
mr->xyy -= s * ma->xyy;
mr->xxy -= s * ma->xxy;
mr->yyy -= s * ma->yyy;
mr->xxz -= s * ma->xxz;
mr->yyz -= s * ma->yyz;
mr->xyz -= s * ma->xyz;
s *= f;
mr->xxxx -= s * ma->xxxx;
mr->xyyy -= s * ma->xyyy;
mr->xxxy -= s * ma->xxxy;
mr->yyyy -= s * ma->yyyy;
mr->xxxz -= s * ma->xxxz;
mr->yyyz -= s * ma->yyyz;
mr->xxyy -= s * ma->xxyy;
mr->xxyz -= s * ma->xxyz;
mr->xyyz -= s * ma->xyyz;
}
/*
** This function calculates a complete multipole from a single
** particle at position <x,y,z> from the center of mass.
** The strange order of evaluation reduces the number of
** multiplications to a minimum.
** <x,y,z> := d := r(particle) - rcm.
**
** OpCount (*,+) = (34,0)
**
*/
void momMakeMomc(MOMC *mc, double m, double x, double y, double z) {
double tx, ty, tz;
mc->m = m;
/*
** Calculate the Quadrupole Moment.
*/
tx = m * x;
ty = m * y;
mc->xy = tx * y;
mc->xz = tx * z;
mc->yz = ty * z;
tx *= x;
ty *= y;
tz = m * z * z;
mc->xx = tx;
mc->yy = ty;
mc->zz = tz;
/*
** Calculate the Octopole Moment.
*/
mc->xxy = tx * y;
mc->xxz = tx * z;
mc->yyz = ty * z;
mc->xyy = ty * x;
mc->xzz = tz * x;
mc->yzz = tz * y;
mc->xyz = mc->xy * z;
tx *= x;
ty *= y;
tz *= z;
mc->xxx = tx;
mc->yyy = ty;
mc->zzz = tz;
/*
** Calculate the Hexadecapole Moment.
*/
mc->xxxx = tx * x;
mc->xxxy = tx * y;
mc->xxxz = tx * z;
mc->xyyy = ty * x;
mc->yyyy = ty * y;
mc->yyyz = ty * z;
mc->xzzz = tz * x;
mc->yzzz = tz * y;
mc->zzzz = tz * z;
mc->xxyy = mc->xxy * y;
mc->xxyz = mc->xxy * z;
mc->xyyz = mc->yyz * x;
mc->yyzz = mc->yyz * z;
mc->xxzz = mc->xzz * x;
mc->xyzz = mc->xzz * y;
}
/*
** This function calculates a reduced multipole from a single
** particle at position <x,y,z> from the center of mass.
** The strange order of evaluation reduces the number of
** multiplications to a minimum.
** <x,y,z> := d := r(particle) - rcm.
** returns: d^2
**
** OpCount (*,+) = (43,18) = ~60
*/
double momMakeMomr(MOMR *mr, double m, double x, double y, double z) {
double tx, ty, t, dx, dy;
double x2 = x * x;
double y2 = y * y;
double d2 = x2 + y2 + z * z;
mr->m = m;
/*
** Calculate the Quadrupole Moment.
*/
tx = m * x;
ty = m * y;
mr->xy = tx * y;
mr->xz = tx * z;
mr->yz = ty * z;
tx *= x;
ty *= y;
m *= d2;
t = m / 3;
mr->xx = tx - t;
mr->yy = ty - t;
/*
** Calculate the Octopole Moment.
*/
t = 0.2 * m;
dx = tx - t;
dy = ty - t;
mr->xxy = dx * y;
mr->xxz = dx * z;
mr->yyz = dy * z;
mr->xyy = dy * x;
mr->xyz = mr->xy * z;
t *= 3;
mr->xxx = (tx - t) * x;
mr->yyy = (ty - t) * y;
/*
** Calculate the Hexadecapole Moment.
*/
t = m / 7;
mr->xxyz = (tx - t) * y * z;
mr->xyyz = (ty - t) * x * z;
dx = (tx - 3 * t) * x;
dy = (ty - 3 * t) * y;
mr->xxxy = dx * y;
mr->xxxz = dx * z;
mr->xyyy = dy * x;
mr->yyyz = dy * z;
dx = t * (x2 - 0.1 * d2);
dy = t * (y2 - 0.1 * d2);
mr->xxxx = tx * x2 - 6 * dx;
mr->yyyy = ty * y2 - 6 * dy;
mr->xxyy = tx * y2 - dx - dy;
return (d2);
}
/*
** This function calculates a reduced scaled multipole from a single
** particle at position <x,y,z> from the any type of "center". A scaling
** factor 'u' for the positions must also be specified, which should
** typically be the value of b_max.
**
** The strange order of evaluation reduces the number of
** multiplications to a minimum.
** <x,y,z> := d := r(particle) - rcm.
** returns: d^2 scaled by u^2.
**
** OpCount (*,+) = (43,18) = ~60
*/
cosmoType momMakeFmomr(FMOMR *mr, cosmoType m, cosmoType u, cosmoType x,
cosmoType y, cosmoType z) {
cosmoType tx, ty, t, dx, dy;
cosmoType x2;
cosmoType y2;
cosmoType d2, iu;
assert(u > 0.0);
iu = 1.0f / u;
x *= iu;
y *= iu;
z *= iu;
x2 = x * x;
y2 = y * y;
d2 = x2 + y2 + z * z;
mr->m = m;
tx = m * x;
ty = m * y;
/*
** Calculate the Quadrupole Moment.
*/
mr->xy = tx * y;
mr->xz = tx * z;
mr->yz = ty * z;
tx *= x;
ty *= y;
m *= d2;
t = (1.0f / 3.0f) * m;
mr->xx = tx - t;
mr->yy = ty - t;
/*
** Calculate the Octopole Moment.
*/
t = 0.2f * m;
dx = tx - t;
dy = ty - t;
mr->xxy = dx * y;
mr->xxz = dx * z;
mr->yyz = dy * z;
mr->xyy = dy * x;
mr->xyz = mr->xy * z;
t *= 3.0f;
mr->xxx = (tx - t) * x;
mr->yyy = (ty - t) * y;
/*
** Calculate the Hexadecapole Moment.
*/
t = (1.0f / 7.0f) * m;
mr->xxyz = (tx - t) * y * z;
mr->xyyz = (ty - t) * x * z;
dx = (tx - 3.0f * t) * x;
dy = (ty - 3.0f * t) * y;
mr->xxxy = dx * y;
mr->xxxz = dx * z;
mr->xyyy = dy * x;
mr->yyyz = dy * z;
dx = t * (x2 - 0.1f * d2);
dy = t * (y2 - 0.1f * d2);
mr->xxxx = tx * x2 - 6.0f * dx;
mr->yyyy = ty * y2 - 6.0f * dy;
mr->xxyy = tx * y2 - dx - dy;
return (d2);
}
/*
** This function calculates a reduced multipole from a single
** particle at position <x,y,z> from the center of mass.
** This is the "straight forward" implementation which we
** used in the original version of PKDGRAV. It remains a good
** test of more peculiar looking code.
**
** <x,y,z> := d := r(particle) - rcm.
**
** OpCount (*,+) = (115,20) = ~135
*/
void momOldMakeMomr(MOMR *mr, double m, double x, double y, double z) {
double d2 = x * x + y * y + z * z;
mr->xxxx = m * (x * x * x * x - 6.0 / 7.0 * d2 * (x * x - 0.1 * d2));
mr->xyyy = m * (x * y * y * y - 3.0 / 7.0 * d2 * x * y);
mr->xxxy = m * (x * x * x * y - 3.0 / 7.0 * d2 * x * y);
mr->yyyy = m * (y * y * y * y - 6.0 / 7.0 * d2 * (y * y - 0.1 * d2));
mr->xxxz = m * (x * x * x * z - 3.0 / 7.0 * d2 * x * z);
mr->yyyz = m * (y * y * y * z - 3.0 / 7.0 * d2 * y * z);
mr->xxyy =
m * (x * x * y * y - 1.0 / 7.0 * d2 * (x * x + y * y - 0.2 * d2));
mr->xxyz = m * (x * x * y * z - 1.0 / 7.0 * d2 * y * z);
mr->xyyz = m * (x * y * y * z - 1.0 / 7.0 * d2 * x * z);
/*
** Calculate reduced octopole moment...
*/
mr->xxx = m * (x * x * x - 0.6 * d2 * x);
mr->xyy = m * (x * y * y - 0.2 * d2 * x);
mr->xxy = m * (x * x * y - 0.2 * d2 * y);
mr->yyy = m * (y * y * y - 0.6 * d2 * y);
mr->xxz = m * (x * x * z - 0.2 * d2 * z);
mr->yyz = m * (y * y * z - 0.2 * d2 * z);
mr->xyz = m * x * y * z;
/*
** Calculate quadrupole moment...
*/
mr->xx = m * (x * x - 1.0 / 3.0 * d2);
mr->yy = m * (y * y - 1.0 / 3.0 * d2);
mr->xy = m * x * y;
mr->xz = m * x * z;
mr->yz = m * y * z;
mr->m = m;
}
/*
** This function shifts a complete multipole (MOMC) to a new center of mass.
** <x,y,z> := d := rcm(old) - rcm(new).
**
** OpCount ShiftMomc (*,+) = (111,84)
** MakeMomc (*,+) = (34,0)
** MulAddMomc (*,+) = (32,32)
** Total (*,+) = (177,116) = 293
*/
void momShiftMomc(MOMC *m, double x, double y, double z) {
MOMC f;
momMakeMomc(&f, 1, x, y, z);
/*
** Shift the Hexadecapole.
*/
m->xxxx += 4 * m->xxx * x + 6 * m->xx * f.xx;
m->yyyy += 4 * m->yyy * y + 6 * m->yy * f.yy;
m->zzzz += 4 * m->zzz * z + 6 * m->zz * f.zz;
m->xyyy += m->yyy * x + 3 * (m->xyy * y + m->yy * f.xy + m->xy * f.yy);
m->xxxy += m->xxx * y + 3 * (m->xxy * x + m->xx * f.xy + m->xy * f.xx);
m->xxxz += m->xxx * z + 3 * (m->xxz * x + m->xx * f.xz + m->xz * f.xx);
m->yyyz += m->yyy * z + 3 * (m->yyz * y + m->yy * f.yz + m->yz * f.yy);
m->xzzz += m->zzz * x + 3 * (m->xzz * z + m->zz * f.xz + m->xz * f.zz);
m->yzzz += m->zzz * y + 3 * (m->yzz * z + m->zz * f.yz + m->yz * f.zz);
m->xxyy += 2 * (m->xxy * y + m->xyy * x) + m->xx * f.yy + m->yy * f.xx +
4 * m->xy * f.xy;
m->xxzz += 2 * (m->xxz * z + m->xzz * x) + m->xx * f.zz + m->zz * f.xx +
4 * m->xz * f.xz;
m->yyzz += 2 * (m->yyz * z + m->yzz * y) + m->yy * f.zz + m->zz * f.yy +
4 * m->yz * f.yz;
m->xxyz += m->xxy * z + m->xxz * y + m->xx * f.yz + m->yz * f.xx +
2 * (m->xyz * x + m->xy * f.xz + m->xz * f.xy);
m->xyyz += m->xyy * z + m->yyz * x + m->yy * f.xz + m->xz * f.yy +
2 * (m->xyz * y + m->xy * f.yz + m->yz * f.xy);
m->xyzz += m->yzz * x + m->xzz * y + m->zz * f.xy + m->xy * f.zz +
2 * (m->xyz * z + m->yz * f.xz + m->xz * f.yz);
/*
** Now shift the Octopole.
*/
m->xxx += 3 * m->xx * x;
m->yyy += 3 * m->yy * y;
m->zzz += 3 * m->zz * z;
m->xyy += 2 * m->xy * y + m->yy * x;
m->xzz += 2 * m->xz * z + m->zz * x;
m->yzz += 2 * m->yz * z + m->zz * y;
m->xxy += 2 * m->xy * x + m->xx * y;
m->xxz += 2 * m->xz * x + m->xx * z;
m->yyz += 2 * m->yz * y + m->yy * z;
m->xyz += m->xy * z + m->xz * y + m->yz * x;
/*
** Now deal with the monopole terms.
*/
f.m = 0;
momMulAddMomc(m, m->m, &f);
}
/*
** This function shifts a reduced multipole (MOMR) to a new center of mass.
** <x,y,z> := d := rcm(old) - rcm(new).
**
** OpCount ShiftMomr (*,+) = (128,111)
** MakeMomr (*,+) = (43,18)
** MulAddMomr (*,+) = (22,22)
** Total (*,+) = (193,151) = 344
*/
void momShiftMomr(MOMR *m, double x, double y, double z) {
MOMR f;
double t, tx, ty, tz, txx, tyy, txy, tyz, txz;
const double twosevenths = 2.0 / 7.0;
momMakeMomr(&f, 1, x, y, z);
/*
** Calculate the correction terms.
*/
tx = 0.4 * (m->xx * x + m->xy * y + m->xz * z);
ty = 0.4 * (m->xy * x + m->yy * y + m->yz * z);
tz = 0.4 * (m->xz * x + m->yz * y - (m->xx + m->yy) * z);
t = tx * x + ty * y + tz * z;
txx = twosevenths *
(m->xxx * x + m->xxy * y + m->xxz * z +
2 * (m->xx * f.xx + m->xy * f.xy + m->xz * f.xz) - 0.5 * t);
tyy = twosevenths *
(m->xyy * x + m->yyy * y + m->yyz * z +
2 * (m->xy * f.xy + m->yy * f.yy + m->yz * f.yz) - 0.5 * t);
txy = twosevenths *
(m->xxy * x + m->xyy * y + m->xyz * z + m->xy * (f.xx + f.yy) +
(m->xx + m->yy) * f.xy + m->yz * f.xz + m->xz * f.yz);
tyz = twosevenths *
(m->xyz * x + m->yyz * y - (m->xxy + m->yyy) * z - m->yz * f.xx -
m->xx * f.yz + m->xz * f.xy + m->xy * f.xz);
txz = twosevenths *
(m->xxz * x + m->xyz * y - (m->xxx + m->xyy) * z - m->xz * f.yy -
m->yy * f.xz + m->yz * f.xy + m->xy * f.yz);
/*
** Shift the Hexadecapole.
*/
m->xxxx += 4 * m->xxx * x + 6 * (m->xx * f.xx - txx);
m->yyyy += 4 * m->yyy * y + 6 * (m->yy * f.yy - tyy);
m->xyyy +=
m->yyy * x + 3 * (m->xyy * y + m->yy * f.xy + m->xy * f.yy - txy);
m->xxxy +=
m->xxx * y + 3 * (m->xxy * x + m->xx * f.xy + m->xy * f.xx - txy);
m->xxxz +=
m->xxx * z + 3 * (m->xxz * x + m->xx * f.xz + m->xz * f.xx - txz);
m->yyyz +=
m->yyy * z + 3 * (m->yyz * y + m->yy * f.yz + m->yz * f.yy - tyz);
m->xxyy += 2 * (m->xxy * y + m->xyy * x) + m->xx * f.yy + m->yy * f.xx +
4 * m->xy * f.xy - txx - tyy;
m->xxyz += m->xxy * z + m->xxz * y + m->xx * f.yz + m->yz * f.xx +
2 * (m->xyz * x + m->xy * f.xz + m->xz * f.xy) - tyz;
m->xyyz += m->xyy * z + m->yyz * x + m->yy * f.xz + m->xz * f.yy +
2 * (m->xyz * y + m->xy * f.yz + m->yz * f.xy) - txz;
/*
** Now shift the Octopole.
*/
m->xxx += 3 * (m->xx * x - tx);
m->xyy += 2 * m->xy * y + m->yy * x - tx;
m->yyy += 3 * (m->yy * y - ty);
m->xxy += 2 * m->xy * x + m->xx * y - ty;
m->xxz += 2 * m->xz * x + m->xx * z - tz;
m->yyz += 2 * m->yz * y + m->yy * z - tz;
m->xyz += m->xy * z + m->xz * y + m->yz * x;
/*
** Now deal with the monopole terms.
*/
f.m = 0;
momMulAddMomr(m, m->m, &f);
}
/*
** This function shifts a reduced scaled multipole (FMOMR) to a new center of
*mass.
** <x,y,z> := d := rcm(old) - rcm(new).
**
** OpCount ShiftMomr (*,+) = (128,111)
** MakeMomr (*,+) = (43,18)
** MulAddMomr (*,+) = (22,22)
** Total (*,+) = (193,151) = 344
*/
void momShiftFmomr(FMOMR *m, cosmoType u, cosmoType x, cosmoType y,
cosmoType z) {
FMOMR f;
cosmoType t, tx, ty, tz, txx, tyy, txy, tyz, txz, iu;
const cosmoType twosevenths = 2.0f / 7.0f;
momMakeFmomr(&f, 1.0f, u, x, y, z);
iu = 1.0f / u;
x *= iu;
y *= iu;
z *= iu;
/*
** Calculate the correction terms.
*/
tx = 0.4f * (m->xx * x + m->xy * y + m->xz * z);
ty = 0.4f * (m->xy * x + m->yy * y + m->yz * z);
tz = 0.4f * (m->xz * x + m->yz * y - (m->xx + m->yy) * z);
t = tx * x + ty * y + tz * z;
txx = twosevenths *
(m->xxx * x + m->xxy * y + m->xxz * z +
2.0f * (m->xx * f.xx + m->xy * f.xy + m->xz * f.xz) - 0.5f * t);
tyy = twosevenths *
(m->xyy * x + m->yyy * y + m->yyz * z +
2.0f * (m->xy * f.xy + m->yy * f.yy + m->yz * f.yz) - 0.5f * t);
txy = twosevenths *
(m->xxy * x + m->xyy * y + m->xyz * z + m->xy * (f.xx + f.yy) +
(m->xx + m->yy) * f.xy + m->yz * f.xz + m->xz * f.yz);
tyz = twosevenths *
(m->xyz * x + m->yyz * y - (m->xxy + m->yyy) * z - m->yz * f.xx -
m->xx * f.yz + m->xz * f.xy + m->xy * f.xz);
txz = twosevenths *
(m->xxz * x + m->xyz * y - (m->xxx + m->xyy) * z - m->xz * f.yy -
m->yy * f.xz + m->yz * f.xy + m->xy * f.yz);
/*
** Shift the Hexadecapole.
*/
m->xxxx += 4.0f * m->xxx * x + 6.0f * (m->xx * f.xx - txx);
m->yyyy += 4.0f * m->yyy * y + 6.0f * (m->yy * f.yy - tyy);
m->xyyy +=
m->yyy * x + 3.0f * (m->xyy * y + m->yy * f.xy + m->xy * f.yy - txy);
m->xxxy +=
m->xxx * y + 3.0f * (m->xxy * x + m->xx * f.xy + m->xy * f.xx - txy);
m->xxxz +=
m->xxx * z + 3.0f * (m->xxz * x + m->xx * f.xz + m->xz * f.xx - txz);
m->yyyz +=
m->yyy * z + 3.0f * (m->yyz * y + m->yy * f.yz + m->yz * f.yy - tyz);
m->xxyy += 2.0f * (m->xxy * y + m->xyy * x) + m->xx * f.yy + m->yy * f.xx +
4.0f * m->xy * f.xy - txx - tyy;
m->xxyz += m->xxy * z + m->xxz * y + m->xx * f.yz + m->yz * f.xx +
2.0f * (m->xyz * x + m->xy * f.xz + m->xz * f.xy) - tyz;
m->xyyz += m->xyy * z + m->yyz * x + m->yy * f.xz + m->xz * f.yy +
2.0f * (m->xyz * y + m->xy * f.yz + m->yz * f.xy) - txz;
/*
** Now shift the Octopole.
*/
m->xxx += 3.0f * (m->xx * x - tx);
m->xyy += 2.0f * m->xy * y + m->yy * x - tx;
m->yyy += 3.0f * (m->yy * y - ty);
m->xxy += 2.0f * m->xy * x + m->xx * y - ty;
m->xxz += 2.0f * m->xz * x + m->xx * z - tz;
m->yyz += 2.0f * m->yz * y + m->yy * z - tz;
m->xyz += m->xy * z + m->xz * y + m->yz * x;
/*
** Now deal with the monopole terms.
*/
f.m = 0;
momMulAddFmomr(m, 1.0, m->m, &f, 1.0);
}
/*
** This function shifts a reduced local expansion (LOCR) to a new center of
*expansion.
** <x,y,z> := d := rexp(new) - rexp(old).
**
** Op Count (*,+) = (159,173) = 332
*/
/* IBM brain damage */
#undef hz
double momShiftLocr(LOCR *l, double x, double y, double z) {
const double onethird = 1.0 / 3.0;
double hx, hy, hz, tx, ty, tz;
double L, Lx, Ly, Lz, Lxx, Lxy, Lxz, Lyy, Lyz, Lxxx, Lxxy, Lxxz, Lxyy, Lxyz,
Lyyy, Lyyz;
double Lxxxx, Lxxxy, Lxxyy, Lxyyy, Lyyyy, Lxxxz, Lxxyz, Lxyyz, Lyyyz;
hx = 0.5 * x;
hy = 0.5 * y;
hz = 0.5 * z;
tx = onethird * x;
ty = onethird * y;
tz = onethird * z;
L = l->x * x + l->y * y + l->z * z;
l->m += L;
Lx = l->xx * x + l->xy * y + l->xz * z;
Ly = l->xy * x + l->yy * y + l->yz * z;
Lz = l->xz * x + l->yz * y - (l->xx + l->yy) * z;
L = Lx * hx + Ly * hy + Lz * hz;
l->x += Lx;
l->y += Ly;
l->z += Lz;
l->m += L;
Lxx = l->xxx * x + l->xxy * y + l->xxz * z;
Lxy = l->xxy * x + l->xyy * y + l->xyz * z;
Lxz = l->xxz * x + l->xyz * y - (l->xxx + l->xyy) * z;
Lyy = l->xyy * x + l->yyy * y + l->yyz * z;
Lyz = l->xyz * x + l->yyz * y - (l->xxy + l->yyy) * z;
Lx = Lxx * hx + Lxy * hy + Lxz * hz;
Ly = Lxy * hx + Lyy * hy + Lyz * hz;
Lz = Lxz * hx + Lyz * hy - (Lxx + Lyy) * hz;
L = Lx * tx + Ly * ty + Lz * tz;
l->xx += Lxx;
l->xy += Lxy;
l->xz += Lxz;
l->yy += Lyy;
l->yz += Lyz;
l->x += Lx;
l->y += Ly;
l->z += Lz;
l->m += L;
Lxxx = l->xxxx * x + l->xxxy * y + l->xxxz * z;
Lxxy = l->xxxy * x + l->xxyy * y + l->xxyz * z;
Lxxz = l->xxxz * x + l->xxyz * y - (l->xxxx + l->xxyy) * z;
Lxyy = l->xxyy * x + l->xyyy * y + l->xyyz * z;
Lxyz = l->xxyz * x + l->xyyz * y - (l->xxxy + l->xyyy) * z;
Lyyy = l->xyyy * x + l->yyyy * y + l->yyyz * z;
Lyyz = l->xyyz * x + l->yyyz * y - (l->xxyy + l->yyyy) * z;
Lxx = Lxxx * hx + Lxxy * hy + Lxxz * hz;
Lxy = Lxxy * hx + Lxyy * hy + Lxyz * hz;
Lxz = Lxxz * hx + Lxyz * hy - (Lxxx + Lxyy) * hz;
Lyy = Lxyy * hx + Lyyy * hy + Lyyz * hz;
Lyz = Lxyz * hx + Lyyz * hy - (Lxxy + Lyyy) * hz;
Lx = Lxx * tx + Lxy * ty + Lxz * tz;
Ly = Lxy * tx + Lyy * ty + Lyz * tz;
Lz = Lxz * tx + Lyz * ty - (Lxx + Lyy) * tz;
L = Lx * hx + Ly * hy + Lz * hz;
l->xxx += Lxxx;
l->xxy += Lxxy;
l->xxz += Lxxz;
l->xyy += Lxyy;
l->xyz += Lxyz;
l->yyy += Lyyy;
l->yyz += Lyyz;
l->xx += Lxx;
l->xy += Lxy;
l->xz += Lxz;
l->yy += Lyy;
l->yz += Lyz;
l->x += Lx;
l->y += Ly;
l->z += Lz;
l->m += 0.5 * L;
Lxxxx = l->xxxxx * x + l->xxxxy * y + l->xxxxz * z;
Lxxxy = l->xxxxy * x + l->xxxyy * y + l->xxxyz * z;
Lxxyy = l->xxxyy * x + l->xxyyy * y + l->xxyyz * z;
Lxyyy = l->xxyyy * x + l->xyyyy * y + l->xyyyz * z;
Lyyyy = l->xyyyy * x + l->yyyyy * y + l->yyyyz * z;
Lxxxz = l->xxxxz * x + l->xxxyz * y - (l->xxxxx + l->xxxyy) * z;
Lxxyz = l->xxxyz * x + l->xxyyz * y - (l->xxxxy + l->xxyyy) * z;
Lxyyz = l->xxyyz * x + l->xyyyz * y - (l->xxxyy + l->xyyyy) * z;
Lyyyz = l->xyyyz * x + l->yyyyz * y - (l->xxyyy + l->yyyyy) * z;
Lxxx = Lxxxx * hx + Lxxxy * hy + Lxxxz * hz;
Lxxy = Lxxxy * hx + Lxxyy * hy + Lxxyz * hz;
Lxyy = Lxxyy * hx + Lxyyy * hy + Lxyyz * hz;
Lyyy = Lxyyy * hx + Lyyyy * hy + Lyyyz * hz;
Lxxz = Lxxxz * hx + Lxxyz * hy - (Lxxxx + Lxxyy) * hz;
Lxyz = Lxxyz * hx + Lxyyz * hy - (Lxxxy + Lxyyy) * hz;
Lyyz = Lxyyz * hx + Lyyyz * hy - (Lxxyy + Lyyyy) * hz;
Lxx = Lxxx * tx + Lxxy * ty + Lxxz * tz;
Lxy = Lxxy * tx + Lxyy * ty + Lxyz * tz;
Lyy = Lxyy * tx + Lyyy * ty + Lyyz * tz;
Lxz = Lxxz * tx + Lxyz * ty - (Lxxx + Lxyy) * tz;
Lyz = Lxyz * tx + Lyyz * ty - (Lxxy + Lyyy) * tz;
Lx = Lxx * hx + Lxy * hy + Lxz * hz;
Ly = Lxy * hx + Lyy * hy + Lyz * hz;
Lz = Lxz * hx + Lyz * hy - (Lxx + Lyy) * hz;
L = Lx * hx + Ly * hy + Lz * hz;
l->xxxx += Lxxxx;
l->xxxy += Lxxxy;
l->xxyy += Lxxyy;
l->xyyy += Lxyyy;
l->yyyy += Lyyyy;
l->xxxz += Lxxxz;
l->xxyz += Lxxyz;
l->xyyz += Lxyyz;
l->yyyz += Lyyyz;
l->xxx += Lxxx;
l->xxy += Lxxy;
l->xxz += Lxxz;
l->xyy += Lxyy;
l->xyz += Lxyz;
l->yyy += Lyyy;
l->yyz += Lyyz;
l->xx += Lxx;
l->xy += Lxy;
l->xz += Lxz;
l->yy += Lyy;
l->yz += Lyz;
l->x += 0.5 * Lx;
l->y += 0.5 * Ly;
l->z += 0.5 * Lz;
l->m += 0.2 * L;
return 332.0;
}
/*
** This function shifts a reduced scaled local expansion (FLOCR) to a new
*center of expansion.
** <x,y,z> := d := rexp(new) - rexp(old).
**
** Op Count (/,*,+) = (1,162,173) = 336
*/
double momShiftFlocr(FLOCR *l, cosmoType v, cosmoType x, cosmoType y,
cosmoType z) {
const cosmoType onethird = 1.0f / 3.0f;
cosmoType iv, hx, hy, hz, tx, ty, tz;
cosmoType L, Lx, Ly, Lz, Lxx, Lxy, Lxz, Lyy, Lyz, Lxxx, Lxxy, Lxxz, Lxyy,
Lxyz, Lyyy, Lyyz;
cosmoType Lxxxx, Lxxxy, Lxxyy, Lxyyy, Lyyyy, Lxxxz, Lxxyz, Lxyyz, Lyyyz;
iv = 1.0f / v;
x *= iv;
y *= iv;
z *= iv;
hx = 0.5 * x;
hy = 0.5 * y;
hz = 0.5 * z;
tx = onethird * x;
ty = onethird * y;
tz = onethird * z;
L = l->x * x + l->y * y + l->z * z;
l->m += L;
Lx = l->xx * x + l->xy * y + l->xz * z;
Ly = l->xy * x + l->yy * y + l->yz * z;
Lz = l->xz * x + l->yz * y - (l->xx + l->yy) * z;
L = Lx * hx + Ly * hy + Lz * hz;
l->x += Lx;
l->y += Ly;
l->z += Lz;
l->m += L;
Lxx = l->xxx * x + l->xxy * y + l->xxz * z;
Lxy = l->xxy * x + l->xyy * y + l->xyz * z;
Lxz = l->xxz * x + l->xyz * y - (l->xxx + l->xyy) * z;
Lyy = l->xyy * x + l->yyy * y + l->yyz * z;
Lyz = l->xyz * x + l->yyz * y - (l->xxy + l->yyy) * z;
Lx = Lxx * hx + Lxy * hy + Lxz * hz;
Ly = Lxy * hx + Lyy * hy + Lyz * hz;
Lz = Lxz * hx + Lyz * hy - (Lxx + Lyy) * hz;
L = Lx * tx + Ly * ty + Lz * tz;
l->xx += Lxx;
l->xy += Lxy;
l->xz += Lxz;
l->yy += Lyy;
l->yz += Lyz;
l->x += Lx;
l->y += Ly;
l->z += Lz;
l->m += L;
Lxxx = l->xxxx * x + l->xxxy * y + l->xxxz * z;
Lxxy = l->xxxy * x + l->xxyy * y + l->xxyz * z;
Lxxz = l->xxxz * x + l->xxyz * y - (l->xxxx + l->xxyy) * z;
Lxyy = l->xxyy * x + l->xyyy * y + l->xyyz * z;
Lxyz = l->xxyz * x + l->xyyz * y - (l->xxxy + l->xyyy) * z;
Lyyy = l->xyyy * x + l->yyyy * y + l->yyyz * z;
Lyyz = l->xyyz * x + l->yyyz * y - (l->xxyy + l->yyyy) * z;
Lxx = Lxxx * hx + Lxxy * hy + Lxxz * hz;
Lxy = Lxxy * hx + Lxyy * hy + Lxyz * hz;
Lxz = Lxxz * hx + Lxyz * hy - (Lxxx + Lxyy) * hz;
Lyy = Lxyy * hx + Lyyy * hy + Lyyz * hz;
Lyz = Lxyz * hx + Lyyz * hy - (Lxxy + Lyyy) * hz;
Lx = Lxx * tx + Lxy * ty + Lxz * tz;
Ly = Lxy * tx + Lyy * ty + Lyz * tz;
Lz = Lxz * tx + Lyz * ty - (Lxx + Lyy) * tz;
L = Lx * hx + Ly * hy + Lz * hz;
l->xxx += Lxxx;
l->xxy += Lxxy;
l->xxz += Lxxz;
l->xyy += Lxyy;
l->xyz += Lxyz;
l->yyy += Lyyy;
l->yyz += Lyyz;
l->xx += Lxx;
l->xy += Lxy;
l->xz += Lxz;
l->yy += Lyy;
l->yz += Lyz;
l->x += Lx;
l->y += Ly;
l->z += Lz;
l->m += 0.5 * L;
Lxxxx = l->xxxxx * x + l->xxxxy * y + l->xxxxz * z;
Lxxxy = l->xxxxy * x + l->xxxyy * y + l->xxxyz * z;
Lxxyy = l->xxxyy * x + l->xxyyy * y + l->xxyyz * z;
Lxyyy = l->xxyyy * x + l->xyyyy * y + l->xyyyz * z;
Lyyyy = l->xyyyy * x + l->yyyyy * y + l->yyyyz * z;
Lxxxz = l->xxxxz * x + l->xxxyz * y - (l->xxxxx + l->xxxyy) * z;
Lxxyz = l->xxxyz * x + l->xxyyz * y - (l->xxxxy + l->xxyyy) * z;
Lxyyz = l->xxyyz * x + l->xyyyz * y - (l->xxxyy + l->xyyyy) * z;
Lyyyz = l->xyyyz * x + l->yyyyz * y - (l->xxyyy + l->yyyyy) * z;
Lxxx = Lxxxx * hx + Lxxxy * hy + Lxxxz * hz;
Lxxy = Lxxxy * hx + Lxxyy * hy + Lxxyz * hz;
Lxyy = Lxxyy * hx + Lxyyy * hy + Lxyyz * hz;
Lyyy = Lxyyy * hx + Lyyyy * hy + Lyyyz * hz;
Lxxz = Lxxxz * hx + Lxxyz * hy - (Lxxxx + Lxxyy) * hz;
Lxyz = Lxxyz * hx + Lxyyz * hy - (Lxxxy + Lxyyy) * hz;
Lyyz = Lxyyz * hx + Lyyyz * hy - (Lxxyy + Lyyyy) * hz;
Lxx = Lxxx * tx + Lxxy * ty + Lxxz * tz;
Lxy = Lxxy * tx + Lxyy * ty + Lxyz * tz;
Lyy = Lxyy * tx + Lyyy * ty + Lyyz * tz;
Lxz = Lxxz * tx + Lxyz * ty - (Lxxx + Lxyy) * tz;
Lyz = Lxyz * tx + Lyyz * ty - (Lxxy + Lyyy) * tz;
Lx = Lxx * hx + Lxy * hy + Lxz * hz;
Ly = Lxy * hx + Lyy * hy + Lyz * hz;
Lz = Lxz * hx + Lyz * hy - (Lxx + Lyy) * hz;
L = Lx * hx + Ly * hy + Lz * hz;
l->xxxx += Lxxxx;
l->xxxy += Lxxxy;
l->xxyy += Lxxyy;
l->xyyy += Lxyyy;
l->yyyy += Lyyyy;
l->xxxz += Lxxxz;
l->xxyz += Lxxyz;
l->xyyz += Lxyyz;
l->yyyz += Lyyyz;
l->xxx += Lxxx;
l->xxy += Lxxy;
l->xxz += Lxxz;
l->xyy += Lxyy;
l->xyz += Lxyz;
l->yyy += Lyyy;
l->yyz += Lyyz;
l->xx += Lxx;
l->xy += Lxy;
l->xz += Lxz;
l->yy += Lyy;
l->yz += Lyz;
l->x += 0.5 * Lx;
l->y += 0.5 * Ly;
l->z += 0.5 * Lz;
l->m += 0.2 * L;
return 332.0;
}
/*
** This function converts a complete multipole (MOMC) to a reduced one (MOMR).
*/
void momReduceMomc(MOMC *mc, MOMR *mr) {
double t, tx, ty, tz, txx, txy, txz, tyy, tyz, tzz;
/*
** First reduce Hexadecapole.
*/
txx = (mc->xxxx + mc->xxyy + mc->xxzz) / 7;
txy = (mc->xxxy + mc->xyyy + mc->xyzz) / 7;
txz = (mc->xxxz + mc->xyyz + mc->xzzz) / 7;
tyy = (mc->xxyy + mc->yyyy + mc->yyzz) / 7;
tyz = (mc->xxyz + mc->yyyz + mc->yzzz) / 7;
tzz = (mc->xxzz + mc->yyzz + mc->zzzz) / 7;
t = 0.1 * (txx + tyy + tzz);
mr->xxxx = mc->xxxx - 6 * (txx - t);
mr->xyyy = mc->xyyy - 3 * txy;
mr->xxxy = mc->xxxy - 3 * txy;
mr->yyyy = mc->yyyy - 6 * (tyy - t);
mr->xxxz = mc->xxxz - 3 * txz;
mr->yyyz = mc->yyyz - 3 * tyz;
mr->xxyy = mc->xxyy - (txx + tyy - 2 * t);
mr->xxyz = mc->xxyz - tyz;
mr->xyyz = mc->xyyz - txz;
/*
** Now reduce the Octopole.
*/
tx = (mc->xxx + mc->xyy + mc->xzz) / 5;
ty = (mc->xxy + mc->yyy + mc->yzz) / 5;
tz = (mc->xxz + mc->yyz + mc->zzz) / 5;
mr->xxx = mc->xxx - 3 * tx;
mr->xyy = mc->xyy - tx;
mr->xxy = mc->xxy - ty;
mr->yyy = mc->yyy - 3 * ty;
mr->xxz = mc->xxz - tz;
mr->yyz = mc->yyz - tz;
mr->xyz = mc->xyz;
/*
** Now reduce the Quadrupole.
*/
t = (mc->xx + mc->yy + mc->zz) / 3;
mr->xx = mc->xx - t;
mr->yy = mc->yy - t;
mr->xy = mc->xy;
mr->xz = mc->xz;
mr->yz = mc->yz;
/*
** Finally the mass remains the same.
*/
mr->m = mc->m;
}
/*
** This is a new fast version of QEVAL which evaluates
** the interaction due to the reduced moment 'm'.
** This version is nearly two times as fast as a naive
** implementation.
**
** OpCount = (*,+) = (103,72) = 175 - 8 = 167
*/
void momEvalMomr(MOMR *m, double dir0, double x, double y, double z,
double *fPot, double *ax, double *ay, double *az) {
const double onethird = 1.0 / 3.0;
double xx, xy, xz, yy, yz, zz;
double xxx, xxy, xxz, xyy, yyy, yyz, xyz;
double tx, ty, tz, dir2, g2, g3, g4;
double dir = -dir0;
dir2 = dir * dir;
g2 = 3 * dir * dir2 * dir2;
g3 = -5 * g2 * dir2;
g4 = -7 * g3 * dir2;
/*
** Calculate the funky distance terms.
*/
xx = 0.5 * x * x;
xy = x * y;
xz = x * z;
yy = 0.5 * y * y;
yz = y * z;
zz = 0.5 * z * z;
xxx = x * (onethird * xx - zz);
xxz = z * (xx - onethird * zz);
yyy = y * (onethird * yy - zz);
yyz = z * (yy - onethird * zz);
xx -= zz;
yy -= zz;
xxy = y * xx;
xyy = x * yy;
xyz = xy * z;
/*
** Now calculate the interaction up to Hexadecapole order.
*/
tx = g4 * (m->xxxx * xxx + m->xyyy * yyy + m->xxxy * xxy + m->xxxz * xxz +
m->xxyy * xyy + m->xxyz * xyz + m->xyyz * yyz);
ty = g4 * (m->xyyy * xyy + m->xxxy * xxx + m->yyyy * yyy + m->yyyz * yyz +
m->xxyy * xxy + m->xxyz * xxz + m->xyyz * xyz);
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);
g4 = 0.25 * (tx * x + ty * y + tz * z);
xxx = g3 *
(m->xxx * xx + m->xyy * yy + m->xxy * xy + m->xxz * xz + m->xyz * yz);
xxy = g3 *
(m->xyy * xy + m->xxy * xx + m->yyy * yy + m->yyz * yz + m->xyz * xz);
xxz = g3 * (-(m->xxx + m->xyy) * xz - (m->xxy + m->yyy) * yz + m->xxz * xx +
m->yyz * yy + m->xyz * xy);
g3 = onethird * (xxx * x + xxy * y + xxz * z);
xx = g2 * (m->xx * x + m->xy * y + m->xz * z);
xy = g2 * (m->yy * y + m->xy * x + m->yz * z);
xz = g2 * (-(m->xx + m->yy) * z + m->xz * x + m->yz * y);
g2 = 0.5 * (xx * x + xy * y + xz * z);
dir *= m->m;
dir2 *= -(dir + 5 * g2 + 7 * g3 + 9 * g4);
*fPot += dir + g2 + g3 + g4;
*ax += xx + xxx + tx + x * dir2;
*ay += xy + xxy + ty + y * dir2;
*az += xz + xxz + tz + z * dir2;
}
/*
** This is a new fast version of QEVAL which evaluates
** the interaction due to the reduced moment 'm'.
** This version is nearly two times as fast as a naive
** implementation.
**
** March 23, 2007: This function now uses unit vectors
** which reduces the required precision in the exponent
** since the highest power of r is now 5 (g4 ~ r^(-5)).
**
** OpCount = (*,+) = (106,72) = 178 - 8 = 170
**
*/
void momEvalFmomrcm(FMOMR *m, cosmoType u, cosmoType dir, cosmoType x,
cosmoType y, cosmoType z, cosmoType *fPot, cosmoType *ax,
cosmoType *ay, cosmoType *az, cosmoType *magai) {
const cosmoType onethird = 1.0f / 3.0f;
cosmoType xx, xy, xz, yy, yz, zz;
cosmoType xxx, xxy, xxz, xyy, yyy, yyz, xyz;
cosmoType tx, ty, tz, g0, g2, g3, g4;
u *= dir;
g0 = dir;
g2 = 3 * dir * u * u;
g3 = 5 * g2 * u;
g4 = 7 * g3 * u;
/*
** Calculate the trace-free distance terms.
*/
x *= dir;
y *= dir;
z *= dir;
xx = 0.5 * x * x;
xy = x * y;
xz = x * z;
yy = 0.5 * y * y;
yz = y * z;
zz = 0.5 * z * z;
xxx = x * (onethird * xx - zz);
xxz = z * (xx - onethird * zz);
yyy = y * (onethird * yy - zz);
yyz = z * (yy - onethird * zz);
xx -= zz;
yy -= zz;
xxy = y * xx;
xyy = x * yy;
xyz = xy * z;
/*
** Now calculate the interaction up to Hexadecapole order.
*/
tx = g4 * (m->xxxx * xxx + m->xyyy * yyy + m->xxxy * xxy + m->xxxz * xxz +
m->xxyy * xyy + m->xxyz * xyz + m->xyyz * yyz);
ty = g4 * (m->xyyy * xyy + m->xxxy * xxx + m->yyyy * yyy + m->yyyz * yyz +
m->xxyy * xxy + m->xxyz * xxz + m->xyyz * xyz);
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);
g4 = 0.25 * (tx * x + ty * y + tz * z);
xxx = g3 *
(m->xxx * xx + m->xyy * yy + m->xxy * xy + m->xxz * xz + m->xyz * yz);
xxy = g3 *
(m->xyy * xy + m->xxy * xx + m->yyy * yy + m->yyz * yz + m->xyz * xz);
xxz = g3 * (-(m->xxx + m->xyy) * xz - (m->xxy + m->yyy) * yz + m->xxz * xx +
m->yyz * yy + m->xyz * xy);
g3 = onethird * (xxx * x + xxy * y + xxz * z);
xx = g2 * (m->xx * x + m->xy * y + m->xz * z);
xy = g2 * (m->yy * y + m->xy * x + m->yz * z);
xz = g2 * (-(m->xx + m->yy) * z + m->xz * x + m->yz * y);
g2 = 0.5 * (xx * x + xy * y + xz * z);
g0 *= m->m;
*fPot += -(g0 + g2 + g3 + g4);
g0 += 5 * g2 + 7 * g3 + 9 * g4;
*ax += dir * (xx + xxx + tx - x * g0);
*ay += dir * (xy + xxy + ty - y * g0);
*az += dir * (xz + xxz + tz - z * g0);
*magai = g0 * dir;
}
void momMomr2Momc(MOMR *ma, MOMC *mc) {
mc->m = ma->m;
mc->xx = ma->xx;
mc->yy = ma->yy;
mc->xy = ma->xy;
mc->xz = ma->xz;
mc->yz = ma->yz;
mc->xxx = ma->xxx;
mc->xyy = ma->xyy;
mc->xxy = ma->xxy;
mc->yyy = ma->yyy;
mc->xxz = ma->xxz;
mc->yyz = ma->yyz;
mc->xyz = ma->xyz;
mc->xxxx = ma->xxxx;
mc->xyyy = ma->xyyy;
mc->xxxy = ma->xxxy;
mc->yyyy = ma->yyyy;
mc->xxxz = ma->xxxz;
mc->yyyz = ma->yyyz;
mc->xxyy = ma->xxyy;
mc->xxyz = ma->xxyz;
mc->xyyz = ma->xyyz;
mc->zz = -(ma->xx + ma->yy);
mc->xzz = -(ma->xxx + ma->xyy);
mc->yzz = -(ma->xxy + ma->yyy);
mc->zzz = -(ma->xxz + ma->yyz);
mc->xxzz = -(ma->xxxx + ma->xxyy);
mc->xyzz = -(ma->xxxy + ma->xyyy);
mc->xzzz = -(ma->xxxz + ma->xyyz);
mc->yyzz = -(ma->xxyy + ma->yyyy);
mc->yzzz = -(ma->xxyz + ma->yyyz);
mc->zzzz = -(mc->xxzz + mc->yyzz);
}
void momFmomr2Momc(FMOMR *ma, MOMC *mc) {
mc->m = ma->m;
mc->xx = ma->xx;
mc->yy = ma->yy;
mc->xy = ma->xy;
mc->xz = ma->xz;
mc->yz = ma->yz;
mc->xxx = ma->xxx;
mc->xyy = ma->xyy;
mc->xxy = ma->xxy;
mc->yyy = ma->yyy;
mc->xxz = ma->xxz;
mc->yyz = ma->yyz;
mc->xyz = ma->xyz;
mc->xxxx = ma->xxxx;
mc->xyyy = ma->xyyy;
mc->xxxy = ma->xxxy;
mc->yyyy = ma->yyyy;
mc->xxxz = ma->xxxz;
mc->yyyz = ma->yyyz;
mc->xxyy = ma->xxyy;
mc->xxyz = ma->xxyz;
mc->xyyz = ma->xyyz;
mc->zz = -(ma->xx + ma->yy);
mc->xzz = -(ma->xxx + ma->xyy);
mc->yzz = -(ma->xxy + ma->yyy);
mc->zzz = -(ma->xxz + ma->yyz);
mc->xxzz = -(ma->xxxx + ma->xxyy);
mc->xyzz = -(ma->xxxy + ma->xyyy);
mc->xzzz = -(ma->xxxz + ma->xyyz);
mc->yyzz = -(ma->xxyy + ma->yyyy);
mc->yzzz = -(ma->xxyz + ma->yyyz);
mc->zzzz = -(mc->xxzz + mc->yyzz);
}
/*
** Op Count = (*,+) = (302,207) = 509
*/
double momLocrAddMomr5(LOCR *l, MOMR *m, double dir, double x, double y,
double z, double *tax, double *tay, double *taz) {
const double onethird = 1.0 / 3.0;
double xx, xy, xz, yy, yz, zz;
double xxx, xxy, xyy, yyy, xxz, xyz, yyz;
double Ax, Ay, Az, A, Bxx, Bxy, Byy, Bxz, Byz, Bx, By, Bz, B, Cx, Cy, Cz, C;
double R1, R2, R3, T2, T3;
double g0, g1, g2, g3, g4, g5;
double g4xx, g4yy, g5xx, g5yy, fxx, fyy;
x *= dir;
y *= dir;
z *= dir;
g0 = -dir;
g1 = -g0 * dir;
g2 = -3 * g1 * dir;
g3 = -5 * g2 * dir;
g4 = -7 * g3 * dir;
g5 = -9 * g4 * dir;
/*
** Calculate the funky distance terms.
*/
xx = 0.5 * x * x;
xy = x * y;
yy = 0.5 * y * y;
xz = x * z;
yz = y * z;
zz = 0.5 * z * z;
xxx = x * (onethird * xx - zz);
xxz = z * (xx - onethird * zz);
yyy = y * (onethird * yy - zz);
yyz = z * (yy - onethird * zz);
xx -= zz;
yy -= zz;
xxy = y * xx;
xyy = x * yy;
xyz = xy * z;
Bxx = x * m->xxx + y * m->xxy + z * m->xxz;
Bxy = x * m->xxy + y * m->xyy + z * m->xyz;
Byy = x * m->xyy + y * m->yyy + z * m->yyz;
Bxz = x * m->xxz + y * m->xyz - z * (m->xxx + m->xyy);
Byz = x * m->xyz + y * m->yyz - z * (m->xxy + m->yyy);
Cx = m->xxxx * xxx + m->xyyy * yyy + m->xxxy * xxy + m->xxxz * xxz +
m->xxyy * xyy + m->xxyz * xyz + m->xyyz * yyz;
Cy = m->xyyy * xyy + m->xxxy * xxx + m->yyyy * yyy + m->yyyz * yyz +
m->xxyy * xxy + m->xxyz * xxz + m->xyyz * xyz;
Cz = -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;
Ax = x * m->xx + y * m->xy + z * m->xz;
Ay = x * m->xy + y * m->yy + z * m->yz;
Az = x * m->xz + y * m->yz - z * (m->xx + m->yy);
Bx = 0.5 * (x * Bxx + y * Bxy + z * Bxz);
By = 0.5 * (x * Bxy + y * Byy + z * Byz);
Bz = 0.5 * (x * Bxz + y * Byz - z * (Bxx + Byy));
C = 0.25 * (x * Cx + y * Cy + z * Cz);
A = 0.5 * (x * Ax + y * Ay + z * Az);
B = onethird * (x * Bx + y * By + z * Bz);
xx = x * x;
yy = y * y;
l->m += g0 * m->m + g2 * A - g3 * B + g4 * C;
R1 = g1 * m->m + g3 * A - g4 * B + g5 * C;
R2 = g2 * m->m + g4 * A - g5 * B;
R3 = g3 * m->m + g5 * A;
g1 *= dir;
g2 *= dir;
g3 *= dir;
T2 = g1 * m->m + g3 * A;
T3 = g2 * m->m;
*tax = -(g2 * Ax - g3 * Bx + x * R1);
*tay = -(g2 * Ay - g3 * By + y * R1);
*taz = -(g2 * Az - g3 * Bz + z * R1);
g2 *= dir;
g4xx = g4 * xx;
g4yy = g4 * yy;
l->xxxx += (3 * g2 + (6 * g3 + g4xx) * xx) * m->m;
l->yyyy += (3 * g2 + (6 * g3 + g4yy) * yy) * m->m;
fxx = (3 * g3 + g4xx) * m->m;
l->xxxy += fxx * xy;
l->xxxz += fxx * xz;
fyy = (3 * g3 + g4yy) * m->m;
l->xyyy += fyy * xy;
l->yyyz += fyy * yz;
fxx = (g3 + g4xx);
l->xxyz += fxx * yz * m->m;
l->xxyy += (g2 + g3 * xx + fxx * yy) * m->m;
l->xyyz += (g3 + g4yy) * xz * m->m;
g4 *= dir;
T2 -= g4 * B;
T3 += g4 * A;
*tax -= g4 * Cx;
*tay -= g4 * Cy;
*taz -= g4 * Cz;
l->x -= *tax;
l->y -= *tay;
l->z -= *taz;
l->xx += g2 * m->xx + T2 + R2 * xx + 2 * g3 * Ax * x - 2 * g4 * Bx * x;
l->yy += g2 * m->yy + T2 + R2 * yy + 2 * g3 * Ay * y - 2 * g4 * By * y;
l->xy +=
g2 * m->xy + R2 * xy + g3 * (Ax * y + Ay * x) - g4 * (Bx * y + By * x);
l->xz +=
g2 * m->xz + R2 * xz + g3 * (Ax * z + Az * x) - g4 * (Bx * z + Bz * x);
l->yz +=
g2 * m->yz + R2 * yz + g3 * (Ay * z + Az * y) - g4 * (By * z + Bz * y);
g3 *= dir;
g5xx = g5 * xx;
g5yy = g5 * yy;
l->xx -= g3 * Bxx;
l->xy -= g3 * Bxy;
l->yy -= g3 * Byy;
l->xz -= g3 * Bxz;
l->yz -= g3 * Byz;
fxx = T3 + R3 * xx;
fyy = T3 + R3 * yy;
l->xxy += fxx * y + g4 * (2 * xy * Ax + xx * Ay) +
g3 * (Ay + 2 * m->xy * x + m->xx * y);
l->xxz += fxx * z + g4 * (2 * xz * Ax + xx * Az) +
g3 * (Az + 2 * m->xz * x + m->xx * z);
l->xyy += fyy * x + g4 * (2 * xy * Ay + yy * Ax) +
g3 * (Ax + 2 * m->xy * y + m->yy * x);
l->yyz += fyy * z + g4 * (2 * yz * Ay + yy * Az) +
g3 * (Az + 2 * m->yz * y + m->yy * z);
l->xyz += R3 * xy * z + g4 * (yz * Ax + xz * Ay + xy * Az) +
g3 * (m->xy * z + m->xz * y + m->yz * x);
fxx += 2 * T3;
fyy += 2 * T3;
l->xxx += fxx * x + 3 * (g4 * xx * Ax + g3 * (Ax + m->xx * x));
l->yyy += fyy * y + 3 * (g4 * yy * Ay + g3 * (Ay + m->yy * y));
fxx = 3 * g3 + (6 * g4 + g5xx) * xx;
fyy = 3 * g3 + (6 * g4 + g5yy) * yy;
x *= m->m;
y *= m->m;
z *= m->m;
l->xxxxx += (15 * g3 + (10 * g4 + g5xx) * xx) * x;
l->yyyyy += (15 * g3 + (10 * g4 + g5yy) * yy) * y;
l->xxxyy += (3 * g3 + 3 * g4 * yy + (g4 + g5yy) * xx) * x;
l->xxyyy += (3 * g3 + 3 * g4 * xx + (g4 + g5xx) * yy) * y;
l->xxyyz += (g3 + g4 * xx + (g4 + g5xx) * yy) * z;
l->xxxxy += fxx * y;
l->xxxxz += fxx * z;
l->xyyyy += fyy * x;
l->yyyyz += fyy * z;
l->xxxyz += (3 * g4 + g5xx) * xy * z;
l->xyyyz += (3 * g4 + g5yy) * xy * z;
return 509.0; /* a guess right now */
}
/*
** Op Count = (*,+,-) = (265,150,49) = 464
*/
double momFlocrAddFmomr5cm(FLOCR *l, cosmoType v, FMOMR *m, cosmoType u,
cosmoType dir, cosmoType x, cosmoType y, cosmoType z,
cosmoType *tax, cosmoType *tay, cosmoType *taz) {
const cosmoType onethird = 1.0f / 3.0f;
cosmoType u2, u3, u4;
cosmoType xx, xy, xz, yy, yz, zz;
cosmoType xxx, xxy, xyy, yyy, xxz, xyz, yyz;
cosmoType R2xx, R2xy, R2xz, R2yy, R2yz, R2x, R2y, R2z, R2, R3xx, R3xy, R3yy,
R3xz, R3yz, R3x, R3y, R3z, R3, R4x, R4y, R4z, R4;
cosmoType T0, txx, tyy, t1, t1x, t1y, t1z, t1xx, t1yy, t2x, t2y, t2z, t2xx,
t2yy, txxxx, tyyyy;
u *= dir;
x *= dir;
y *= dir;
z *= dir;
dir = -dir;
v *= dir;
u2 = 15.0f * u * u; /* becomes 15.0f*u2! */
/*
** Calculate the funky distance terms.
*/
xx = 0.5f * x * x;
xy = x * y;
yy = 0.5f * y * y;
xz = x * z;
yz = y * z;
zz = 0.5f * z * z;
xxx = x * (onethird * xx - zz);
xxz = z * (xx - onethird * zz);
yyy = y * (onethird * yy - zz);
yyz = z * (yy - onethird * zz);
xx -= zz;
yy -= zz;
xxy = y * xx;
xyy = x * yy;
xyz = xy * z;
u3 = u2 * u; /* becomes 5.0f*u3! */
R2xx = u2 * m->xx;
R2xy = u2 * m->xy;
R2xz = u2 * m->xz;
R2yy = u2 * m->yy;
R2yz = u2 * m->yz;
u4 = 7.0f * u3 * u; /* becomes 7.0f*5.0f*u4! */
R2x = x * R2xx + y * R2xy + z * R2xz;
R2y = x * R2xy + y * R2yy + z * R2yz;
R2z = x * R2xz + y * R2yz - z * (R2xx + R2yy);
R3xx = u3 * (x * m->xxx + y * m->xxy + z * m->xxz);
R3xy = u3 * (x * m->xxy + y * m->xyy + z * m->xyz);
R3yy = u3 * (x * m->xyy + y * m->yyy + z * m->yyz);
R3xz = u3 * (x * m->xxz + y * m->xyz - z * (m->xxx + m->xyy));
R3yz = u3 * (x * m->xyz + y * m->yyz - z * (m->xxy + m->yyy));
R4x = u4 * (m->xxxx * xxx + m->xyyy * yyy + m->xxxy * xxy + m->xxxz * xxz +
m->xxyy * xyy + m->xxyz * xyz + m->xyyz * yyz);
R4y = u4 * (m->xyyy * xyy + m->xxxy * xxx + m->yyyy * yyy + m->yyyz * yyz +
m->xxyy * xxy + m->xxyz * xxz + m->xyyz * xyz);
R4z = u4 * (-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);
R3x = 0.5f * (x * R3xx + y * R3xy + z * R3xz);
R3y = 0.5f * (x * R3xy + y * R3yy + z * R3yz);
R3z = 0.5f * (x * R3xz + y * R3yz - z * (R3xx + R3yy));
R4 = 0.25f * (x * R4x + y * R4y + z * R4z);
R2 = 0.5f * (x * R2x + y * R2y + z * R2z);
R3 = onethird * (x * R3x + y * R3y + z * R3z);
xx = x * x;
yy = y * y;
/*
** Now we use the 'R's.
*/
l->m += dir * (m->m + 0.2f * R2 + R3 + R4);
dir *= v;
T0 = -(m->m + R2 + 7.0f * R3 + 9.0f * R4);
*tax = dir * (T0 * x + 0.2f * R2x + R3x + R4x);
*tay = dir * (T0 * y + 0.2f * R2y + R3y + R4y);
*taz = dir * (T0 * z + 0.2f * R2z + R3z + R4z);
l->x -= *tax;
l->y -= *tay;
l->z -= *taz;
dir *= v;
T0 = 3.0f * m->m + 7.0f * (R2 + 9.0f * R3);
t1 = m->m + R2 + 7.0f * R3;
t1x = R2x + 7.0f * R3x;
t1y = R2y + 7.0f * R3y;
t1z = R2z + 7.0f * R3z;
l->xx += dir * (T0 * xx - t1 - 2.0f * x * t1x + 0.2f * R2xx + R3xx);
l->yy += dir * (T0 * yy - t1 - 2.0f * y * t1y + 0.2f * R2yy + R3yy);
l->xy += dir * (T0 * xy - y * t1x - x * t1y + 0.2f * R2xy + R3xy);
l->xz += dir * (T0 * xz - z * t1x - x * t1z + 0.2f * R2xz + R3xz);
l->yz += dir * (T0 * yz - z * t1y - y * t1z + 0.2f * R2yz + R3yz);
dir *= v;
T0 = 15.0f * m->m + 63.0f * R2;
txx = T0 * xx;
tyy = T0 * yy;
t1 = 3.0f * m->m + 7.0f * R2;
t2x = -7.0f * R2x;
t2y = -7.0f * R2y;
t2z = -7.0f * R2z;
t1xx = txx - t1 + 2.0f * x * t2x + R2xx;
t1yy = tyy - t1 + 2.0f * y * t2y + R2yy;
l->xxx += dir * (x * (txx - 3.0f * (t1 - t2x * x - R2xx)) + 3.0f * R2x);
l->yyy += dir * (y * (tyy - 3.0f * (t1 - t2y * y - R2yy)) + 3.0f * R2y);
l->xxy += dir * (y * t1xx + xx * t2y + R2y + 2.0f * R2xy * x);
l->xxz += dir * (z * t1xx + xx * t2z + R2z + 2.0f * R2xz * x);
l->xyy += dir * (x * t1yy + yy * t2x + R2x + 2.0f * R2xy * y);
l->yyz += dir * (z * t1yy + yy * t2z + R2z + 2.0f * R2yz * y);
l->xyz += dir * (T0 * xyz + (yz * t2x + xz * t2y + xy * t2z) + R2xy * z +
R2yz * x + R2xz * y);
dir *= v * m->m;
txx = 105.0f * xx;
tyy = 105.0f * yy;
t2xx = txx - 90.0f;
t2yy = tyy - 90.0f;
l->xxxx += dir * (xx * t2xx + 9.0f);
l->yyyy += dir * (yy * t2yy + 9.0f);
t2xx += 45.0f;
t2yy += 45.0f;
l->xxxy += dir * xy * t2xx;
l->xxxz += dir * xz * t2xx;
l->xyyy += dir * xy * t2yy;
l->yyyz += dir * yz * t2yy;
t2xx += 30.0f;
t2yy += 30.0f;
l->xxyy += dir * (yy * t2xx - xx * 15.0f + 3.0f);
l->xxyz += dir * (yz * t2xx);
l->xyyz += dir * (xz * t2yy);
dir *= v;
x *= dir;
y *= dir;
z *= dir;
txx = 9.0f * xx - 10.0f;
tyy = 9.0f * yy - 10.0f;
xx *= 105.0f;
yy *= 105.0f;
xy *= z * 105.0f;
l->xxxxx += x * (xx * txx + 225.0f);
l->yyyyy += y * (yy * tyy + 225.0f);
txx += 4.0f;
tyy += 4.0f;
txxxx = xx * txx + 45.0f;
tyyyy = yy * tyy + 45.0f;
l->xxxxy += y * txxxx;
l->xxxxz += z * txxxx;
l->xyyyy += x * tyyyy;
l->yyyyz += z * tyyyy;
txx += 3.0f;
tyy += 3.0f;
l->xxxyz += xy * txx;
l->xyyyz += xy * tyy;
l->xxxyy += x * (yy * txx - xx + 45.0f);
l->xxyyy += y * (xx * tyy - yy + 45.0f);
tyy += 2.0f;
l->xxyyz += z * (xx * tyy - yy + 15.0f);
return (464.0);
}
/*
** Op Count = (*,+,-) = (,,) =
*/
double momFlocrAddMono5(FLOCR *l, cosmoType v, cosmoType m, cosmoType dir,
cosmoType x, cosmoType y, cosmoType z, cosmoType *tax,
cosmoType *tay, cosmoType *taz) {
cosmoType xx, xy, xz, yy, yz;
cosmoType T0, txx, tyy, t1, t1xx, t1yy, t2, txxxx, tyyyy;
x *= dir;
y *= dir;
z *= dir;
dir = -dir;
v *= dir;
/*
** Calculate the funky distance terms.
*/
xy = x * y;
xz = x * z;
yz = y * z;
xx = x * x;
yy = y * y;
l->m += dir * m;
dir *= v;
T0 = -m * dir;
*tax = T0 * x;
*tay = T0 * y;
*taz = T0 * z;
l->x -= *tax;
l->y -= *tay;
l->z -= *taz;
dir *= v;
T0 = 3.0f * m * dir;
t1 = m * dir;
l->xx += T0 * xx - t1;
l->yy += T0 * yy - t1;
l->xy += T0 * xy;
l->xz += T0 * xz;
l->yz += T0 * yz;
dir *= v;
T0 = 15.0f * m * dir;
txx = T0 * xx;
tyy = T0 * yy;
t1 = 3.0f * m * dir;
t1xx = txx - t1;
t1yy = tyy - t1;
l->xxx += x * (txx - 3.0f * t1);
l->yyy += y * (tyy - 3.0f * t1);
l->xxy += y * t1xx;
l->xxz += z * t1xx;
l->xyy += x * t1yy;
l->yyz += z * t1yy;
l->xyz += T0 * x * yz;
dir *= v;
T0 = 105.0f * m * dir;
txx = T0 * xx;
tyy = T0 * yy;
t2 = 3.0f * m * dir;
t1 = 5.0f * t2;
l->xxxx += xx * (txx - 6.0f * t1) + 3.0f * t2;
l->yyyy += yy * (tyy - 6.0f * t1) + 3.0f * t2;
t1xx = txx - 3.0f * t1;
t1yy = tyy - 3.0f * t1;
l->xxxy += xy * t1xx;
l->xxxz += xz * t1xx;
l->xyyy += xy * t1yy;
l->yyyz += yz * t1yy;
l->xxyy += yy * txx - (xx + yy) * t1 + t2;
l->xxyz += yz * (txx - t1);
l->xyyz += xz * (tyy - t1);
dir *= v * m;
x *= dir;
y *= dir;
z *= dir;
txx = 9.0f * xx - 10.0f;
tyy = 9.0f * yy - 10.0f;
xx *= 105.0f;
yy *= 105.0f;
xy *= z * 105.0f;
l->xxxxx += x * (xx * txx + 225.0f);
l->yyyyy += y * (yy * tyy + 225.0f);
txx += 4.0f;
tyy += 4.0f;
txxxx = xx * txx + 45.0f;
tyyyy = yy * tyy + 45.0f;
l->xxxxy += y * txxxx;
l->xxxxz += z * txxxx;
l->xyyyy += x * tyyyy;
l->yyyyz += z * tyyyy;
txx += 3.0f;
tyy += 3.0f;
l->xxxyz += xy * txx;
l->xyyyz += xy * tyy;
l->xxxyy += x * (yy * txx - xx + 45.0f);
l->xxyyy += y * (xx * tyy - yy + 45.0f);
tyy += 2.0f;
l->xxyyz += z * (xx * tyy - yy + 15.0f);
return (200.0);
}
void momEvalLocr(LOCR *l, double x, double y, double z, double *fPot,
double *ax, double *ay, double *az) {
const double onethird = 1.0 / 3.0;
double xx, xy, xz, yy, yz, zz, xxx, xxz, yyy, yyz, xxy, xyy, xyz, xxxx,
xxxy, xxyy, xyyy, yyyy, xxxz, xxyz, xyyz, yyyz;
double g1, A, Ax, Ay, Az, B, Bx, By, Bz, C, Cx, Cy, Cz, D, Dx, Dy, Dz;
/*
** Calculate the funky distance terms.
*/
xx = 0.5 * x * x;
xy = x * y;
xz = x * z;
yy = 0.5 * y * y;
yz = y * z;
zz = 0.5 * z * z;
xxx = x * (onethird * xx - zz);
xxz = z * (xx - onethird * zz);
yyy = y * (onethird * yy - zz);
yyz = z * (yy - onethird * zz);
xx -= zz;
yy -= zz;
xxy = y * xx;
xyy = x * yy;
xyz = xy * z;
xxxx = 0.25 * (x * xxx - z * xxz);
xxxy = y * xxx;
xxyy = xx * yy - 2 * onethird * zz * zz;
xyyy = x * yyy;
yyyy = 0.25 * (y * yyy - z * yyz);
xxxz = onethird * x * z * xx;
xxyz = y * xxz;
xyyz = x * yyz;
yyyz = y * yyz;
/*
** Now calculate the interaction.
*/
Dx = l->xxxxx * xxxx + l->xxxxy * xxxy + l->xxxyy * xxyy + l->xxyyy * xyyy +
l->xyyyy * yyyy + l->xxxxz * xxxz + l->xxxyz * xxyz + l->xxyyz * xyyz +
l->xyyyz * yyyz;
Dy = l->xxxxy * xxxx + l->xxxyy * xxxy + l->xxyyy * xxyy + l->xyyyy * xyyy +
l->yyyyy * yyyy + l->xxxyz * xxxz + l->xxyyz * xxyz + l->xyyyz * xyyz +
l->yyyyz * yyyz;
Dz = l->xxxxz * xxxx + l->xxxyz * xxxy + l->xxyyz * xxyy + l->xyyyz * xyyy +
l->yyyyz * yyyy - l->xxxxx * xxxz - l->xxxxy * xxyz -
l->xxxyy * (xxxz + xyyz) - l->xxyyy * (xxyz + yyyz) + l->xyyyy * xyyz +
l->yyyyy * yyyz;
Cx = l->xxxx * xxx + l->xyyy * yyy + l->xxxy * xxy + l->xxxz * xxz +
l->xxyy * xyy + l->xxyz * xyz + l->xyyz * yyz;
Cy = l->xyyy * xyy + l->xxxy * xxx + l->yyyy * yyy + l->yyyz * yyz +
l->xxyy * xxy + l->xxyz * xxz + l->xyyz * xyz;
Cz = -l->xxxx * xxz - (l->xyyy + l->xxxy) * xyz - l->yyyy * yyz +
l->xxxz * xxx + l->yyyz * yyy - l->xxyy * (xxz + yyz) + l->xxyz * xxy +
l->xyyz * xyy;
Bx = l->xxx * xx + l->xyy * yy + l->xxy * xy + l->xxz * xz + l->xyz * yz;
By = l->xyy * xy + l->xxy * xx + l->yyy * yy + l->yyz * yz + l->xyz * xz;
Bz = -(l->xxx + l->xyy) * xz - (l->xxy + l->yyy) * yz + l->xxz * xx +
l->yyz * yy + l->xyz * xy;
Ax = l->xx * x + l->xy * y + l->xz * z;
Ay = l->yy * y + l->xy * x + l->yz * z;
Az = -(l->xx + l->yy) * z + l->xz * x + l->yz * y;
D = 0.2 * (Dx * x + Dy * y + Dz * z);
C = 0.25 * (Cx * x + Cy * y + Cz * z);
B = onethird * (Bx * x + By * y + Bz * z);
A = 0.5 * (Ax * x + Ay * y + Az * z);
g1 = x * l->x + y * l->y + z * l->z;
*ax -= l->x + Ax + Bx + Cx + Dx;
*ay -= l->y + Ay + By + Cy + Dy;
*az -= l->z + Az + Bz + Cz + Dz;
*fPot += l->m + g1 + A + B + C + D;
}
void momEvalFlocr(FLOCR *l, cosmoType v, cosmoType x, cosmoType y, cosmoType z,
cosmoType *fPot, cosmoType *ax, cosmoType *ay,
cosmoType *az) {
const cosmoType onethird = 1.0f / 3.0f;
cosmoType xx, xy, xz, yy, yz, zz, xxx, xxz, yyy, yyz, xxy, xyy, xyz, xxxx,
xxxy, xxyy, xyyy, yyyy, xxxz, xxyz, xyyz, yyyz;
cosmoType g1, A, Ax, Ay, Az, B, Bx, By, Bz, C, Cx, Cy, Cz, D, Dx, Dy, Dz;
cosmoType iv;
/*
** Calculate the funky distance terms, but first scale x,y,z so that they
*are of order unity!
*/
iv = 1 / v;
x *= iv;
y *= iv;
z *= iv;
xx = 0.5 * x * x;
xy = x * y;
xz = x * z;
yy = 0.5 * y * y;
yz = y * z;
zz = 0.5 * z * z;
xxx = x * (onethird * xx - zz);
xxz = z * (xx - onethird * zz);
yyy = y * (onethird * yy - zz);
yyz = z * (yy - onethird * zz);
xx -= zz;
yy -= zz;
xxy = y * xx;
xyy = x * yy;
xyz = xy * z;
xxxx = 0.25 * (x * xxx - z * xxz);
xxxy = y * xxx;
xxyy = xx * yy - 2 * onethird * zz * zz;
xyyy = x * yyy;
yyyy = 0.25 * (y * yyy - z * yyz);
xxxz = onethird * x * z * xx;
xxyz = y * xxz;
xyyz = x * yyz;
yyyz = y * yyz;
/*
** Now calculate the interaction.
*/
Dx = l->xxxxx * xxxx + l->xxxxy * xxxy + l->xxxyy * xxyy + l->xxyyy * xyyy +
l->xyyyy * yyyy + l->xxxxz * xxxz + l->xxxyz * xxyz + l->xxyyz * xyyz +
l->xyyyz * yyyz;
Dy = l->xxxxy * xxxx + l->xxxyy * xxxy + l->xxyyy * xxyy + l->xyyyy * xyyy +
l->yyyyy * yyyy + l->xxxyz * xxxz + l->xxyyz * xxyz + l->xyyyz * xyyz +
l->yyyyz * yyyz;
Dz = l->xxxxz * xxxx + l->xxxyz * xxxy + l->xxyyz * xxyy + l->xyyyz * xyyy +
l->yyyyz * yyyy - l->xxxxx * xxxz - l->xxxxy * xxyz -
l->xxxyy * (xxxz + xyyz) - l->xxyyy * (xxyz + yyyz) + l->xyyyy * xyyz +
l->yyyyy * yyyz;
Cx = l->xxxx * xxx + l->xyyy * yyy + l->xxxy * xxy + l->xxxz * xxz +
l->xxyy * xyy + l->xxyz * xyz + l->xyyz * yyz;
Cy = l->xyyy * xyy + l->xxxy * xxx + l->yyyy * yyy + l->yyyz * yyz +
l->xxyy * xxy + l->xxyz * xxz + l->xyyz * xyz;
Cz = -l->xxxx * xxz - (l->xyyy + l->xxxy) * xyz - l->yyyy * yyz +
l->xxxz * xxx + l->yyyz * yyy - l->xxyy * (xxz + yyz) + l->xxyz * xxy +
l->xyyz * xyy;
Bx = l->xxx * xx + l->xyy * yy + l->xxy * xy + l->xxz * xz + l->xyz * yz;
By = l->xyy * xy + l->xxy * xx + l->yyy * yy + l->yyz * yz + l->xyz * xz;
Bz = -(l->xxx + l->xyy) * xz - (l->xxy + l->yyy) * yz + l->xxz * xx +
l->yyz * yy + l->xyz * xy;
Ax = l->xx * x + l->xy * y + l->xz * z;
Ay = l->yy * y + l->xy * x + l->yz * z;
Az = -(l->xx + l->yy) * z + l->xz * x + l->yz * y;
D = 0.2 * (Dx * x + Dy * y + Dz * z);
C = 0.25 * (Cx * x + Cy * y + Cz * z);
B = onethird * (Bx * x + By * y + Bz * z);
A = 0.5 * (Ax * x + Ay * y + Az * z);
g1 = x * l->x + y * l->y + z * l->z;
*ax -= iv * (l->x + Ax + Bx + Cx + Dx);
*ay -= iv * (l->y + Ay + By + Cy + Dy);
*az -= iv * (l->z + Az + Bz + Cz + Dz);
*fPot += l->m + g1 + A + B + C + D;
}
void momPrintMomc(MOMC *m) {
printf("MOMC:%20.15g\n", (double)m->m);
printf(" xx:%20.15g yy:%20.15g zz:%20.15g\n", (double)m->xx,
(double)m->yy, (double)m->zz);
printf(" xy:%20.15g yz:%20.15g xz:%20.15g\n", (double)m->xy,
(double)m->yz, (double)m->xz);
printf(" xxx:%20.15g xyy:%20.15g xzz:%20.15g\n", (double)m->xxx,
(double)m->xyy, (double)m->xzz);
printf(" xxy:%20.15g yyy:%20.15g yzz:%20.15g\n", (double)m->xxy,
(double)m->yyy, (double)m->yzz);
printf(" xxz:%20.15g yyz:%20.15g zzz:%20.15g\n", (double)m->xxz,
(double)m->yyz, (double)m->zzz);
printf(" xyz:%20.15g\n", (double)m->xyz);
printf("xxxx:%20.15g xxxy:%20.15g xxxz:%20.15g\n", (double)m->xxxx,
(double)m->xxxy, (double)m->xxxz);
printf("xyyy:%20.15g yyyy:%20.15g yyyz:%20.15g\n", (double)m->xyyy,
(double)m->yyyy, (double)m->yyyz);
printf("xzzz:%20.15g yzzz:%20.15g zzzz:%20.15g\n", (double)m->xzzz,
(double)m->yzzz, (double)m->zzzz);
printf("xxyy:%20.15g xxyz:%20.15g xyyz:%20.15g\n", (double)m->xxyy,
(double)m->xxyz, (double)m->xyyz);
printf("yyzz:%20.15g xxzz:%20.15g xyzz:%20.15g\n", (double)m->yyzz,
(double)m->xxzz, (double)m->xyzz);
}
void momPrintMomr(MOMR *m) {
printf("MOMR:%20.15g\n", (double)m->m);
printf(" xx:%20.15g yy:%20.15g\n", (double)m->xx, (double)m->yy);
printf(" xy:%20.15g yz:%20.15g xz:%20.15g\n", (double)m->xy,
(double)m->yz, (double)m->xz);
printf(" xxx:%20.15g xyy:%20.15g\n", (double)m->xxx, (double)m->xyy);
printf(" xxy:%20.15g yyy:%20.15g\n", (double)m->xxy, (double)m->yyy);
printf(" xxz:%20.15g yyz:%20.15g\n", (double)m->xxz, (double)m->yyz);
printf(" xyz:%20.15g\n", (double)m->xyz);
printf("xxxx:%20.15g xxxy:%20.15g xxxz:%20.15g\n", (double)m->xxxx,
(double)m->xxxy, (double)m->xxxz);
printf("xyyy:%20.15g yyyy:%20.15g yyyz:%20.15g\n", (double)m->xyyy,
(double)m->yyyy, (double)m->yyyz);
printf("xxyy:%20.15g xxyz:%20.15g xyyz:%20.15g\n", (double)m->xxyy,
(double)m->xxyz, (double)m->xyyz);
}
Computing file changes ...