@@ -3871,7 +3871,7 @@ namespace BasisClasses
38713871
38723872 // Generate coeffients from a particle reader
38733873 CoefClasses::CoefStrPtr BiorthBasis::createFromReader
3874- (PR ::PRptr reader, std::vector<double > ctr)
3874+ (PR ::PRptr reader, std::vector<double > ctr, Eigen::Matrix3d rot )
38753875 {
38763876 CoefClasses::CoefStrPtr coef;
38773877
@@ -3901,6 +3901,10 @@ namespace BasisClasses
39013901 //
39023902 if (addCenter) coef->ctr = ctr;
39033903
3904+ // Add the rotation matrix
3905+ //
3906+ coef->rot = rot;
3907+
39043908 std::vector<double > pp (3 ), vv (3 );
39053909
39063910 reset_coefs ();
@@ -3916,18 +3920,21 @@ namespace BasisClasses
39163920 use = true ;
39173921 }
39183922
3919- if (use) accumulate (p->pos [0 ]-ctr[0 ],
3920- p->pos [1 ]-ctr[1 ],
3921- p->pos [2 ]-ctr[2 ],
3922- p->mass );
3923+ if (use) {
3924+ Eigen::Vector3d pp;
3925+ for (int k=0 ; k<3 ; k++) pp (k) = p->pos [k] - coefctr[k];
3926+ pp = coefrot * pp;
3927+
3928+ accumulate (pp (0 ), pp (1 ), pp (2 ), p->mass );
3929+ }
39233930 }
39243931 make_coefs ();
39253932 load_coefs (coef, reader->CurrentTime ());
39263933 return coef;
39273934 }
39283935
39293936 // Generate coefficients from a phase-space table
3930- void BiorthBasis::initFromArray (std::vector<double > ctr)
3937+ void BiorthBasis::initFromArray (std::vector<double > ctr, Eigen::Matrix3d rot )
39313938 {
39323939 if (name.compare (" sphereSL" ) == 0 )
39333940 coefret = std::make_shared<CoefClasses::SphStruct>();
@@ -3957,6 +3964,9 @@ namespace BasisClasses
39573964 //
39583965 coefctr = ctr;
39593966
3967+ // Register the rotation matrix
3968+ coefret->rot = rot;
3969+
39603970 // Clean up for accumulation
39613971 //
39623972 reset_coefs ();
@@ -4027,9 +4037,13 @@ namespace BasisClasses
40274037 }
40284038 coefindx++;
40294039
4030- if (use) accumulate (p (0 , n)-coefctr[0 ],
4031- p (1 , n)-coefctr[1 ],
4032- p (2 , n)-coefctr[2 ], m (n));
4040+ if (use) {
4041+ Eigen::Vector3d pp;
4042+ for (int k=0 ; k<3 ; k++) pp (k) = p (k, n) - coefctr[k];
4043+ pp = coefrot * pp;
4044+
4045+ accumulate (pp (0 ), pp (1 ), pp (2 ), m (n));
4046+ }
40334047 }
40344048 }
40354049
@@ -4055,9 +4069,13 @@ namespace BasisClasses
40554069 }
40564070 coefindx++;
40574071
4058- if (use) accumulate (p (n, 0 )-coefctr[0 ],
4059- p (n, 1 )-coefctr[1 ],
4060- p (n, 2 )-coefctr[2 ], m (n));
4072+ if (use) {
4073+ Eigen::Vector3d pp;
4074+ for (int k=0 ; k<3 ; k++) pp (k) = p (k, n) - coefctr[0 ];
4075+ pp = coefrot * pp;
4076+
4077+ accumulate (pp (0 ), pp (1 ), pp (2 ), m (n));
4078+ }
40614079 }
40624080 }
40634081 }
@@ -4075,9 +4093,9 @@ namespace BasisClasses
40754093 //
40764094 CoefClasses::CoefStrPtr BiorthBasis::createFromArray
40774095 (Eigen::VectorXd& m, RowMatrixXd& p, double time, std::vector<double > ctr,
4078- bool RoundRobin, bool PosVelRows)
4096+ Eigen::Matrix3d rot, bool RoundRobin, bool PosVelRows)
40794097 {
4080- initFromArray (ctr);
4098+ initFromArray (ctr, rot );
40814099 addFromArray (m, p, RoundRobin, PosVelRows);
40824100 return makeFromArray (time);
40834101 }
@@ -4095,13 +4113,20 @@ namespace BasisClasses
40954113 auto ctr = basis->getCenter ();
40964114 if (basis->usingNonInertial ()) ctr = {0 , 0 , 0 };
40974115
4116+ // Get rotation matrix
4117+ //
4118+ auto rot = basis->getRotation ();
4119+
40984120 // Get fields
40994121 //
41004122 int rows = accel.rows ();
41014123 for (int n=0 ; n<rows; n++) {
4102- auto v = basis->getFields (ps (n, 0 ) - ctr[0 ],
4103- ps (n, 1 ) - ctr[1 ],
4104- ps (n, 2 ) - ctr[2 ]);
4124+ Eigen::Vector3d pp;
4125+ for (int k=0 ; k<3 ; k++) pp (k) = ps (n, k) - ctr[k];
4126+ pp = rot * pp;
4127+
4128+ auto v = basis->getFields (pp (0 ), pp (1 ), pp (2 ));
4129+
41054130 // First 6 fields are density and potential, followed by acceleration
41064131 for (int k=0 ; k<3 ; k++) accel (n, k) += v[6 +k] - basis->pseudo (k);
41074132 }
@@ -4192,6 +4217,23 @@ namespace BasisClasses
41924217 newcoef->ctr [k] = a * coefsA->ctr [k] + b * coefsB->ctr [k];
41934218 }
41944219
4220+ // Interpolate rotation matrix followed by unitarization
4221+ //
4222+ Eigen::Matrix3d newrot;
4223+ for (int k=0 ; k<9 ; k++) {
4224+ newrot.data ()[k] =
4225+ a * coefsA->rot .data ()[k] + b * coefsB->rot .data ()[k];
4226+ }
4227+
4228+ // Closest unitary matrix in the Frobenius norm sense
4229+ //
4230+ Eigen::BDCSVD <Eigen::Matrix3d> svd (newrot,
4231+ Eigen::ComputeFullU | Eigen::ComputeFullV);
4232+ auto U = svd.matrixU ();
4233+ auto V = svd.matrixV ();
4234+
4235+ newcoef->rot = U * V.adjoint ();
4236+
41954237 // Install coefficients
41964238 //
41974239 basis->set_coefs (newcoef);
0 commit comments