Coordinate transformation on single RVecs
authorChristian Blau <cblau@gwdg.de>
Mon, 17 Feb 2020 15:22:36 +0000 (16:22 +0100)
committerJoe Jordan <ejjordan12@gmail.com>
Thu, 2 Jul 2020 10:58:16 +0000 (10:58 +0000)
So far, coordinate transforamtions of TranslateAndScale and Scale
classes could only performed on ArrayRefs. This meant that
transformations of single RVecs had to be done by first constructing an
ArrayRef on a single RVec x with the unintuitive and cumbersome
transform({&x,&x+1}).

Now this call is reduced to transform(&x) and respective calls.

Change-Id: I0d1f9d2f5ba90a46b1afc9b617af606995e0df59

src/gromacs/applied_forces/densityfittingforceprovider.cpp
src/gromacs/math/coordinatetransformation.cpp
src/gromacs/math/coordinatetransformation.h
src/gromacs/math/tests/coordinatetransformation.cpp

index f278fd94770c28be42984f7b4e7d5d450852ee07..3ee0e9cdbf8f3c4034c587ea5c0fb24833acb286 100644 (file)
@@ -76,7 +76,7 @@ namespace
 GaussianSpreadKernelParameters::Shape makeSpreadKernel(real sigma, real nSigma, const ScaleCoordinates& scaleToLattice)
 {
     RVec sigmaInLatticeCoordinates{ sigma, sigma, sigma };
-    scaleToLattice({ &sigmaInLatticeCoordinates, &sigmaInLatticeCoordinates + 1 });
+    scaleToLattice(&sigmaInLatticeCoordinates);
     return { DVec{ sigmaInLatticeCoordinates[XX], sigmaInLatticeCoordinates[YY],
                    sigmaInLatticeCoordinates[ZZ] },
              nSigma };
@@ -163,14 +163,12 @@ DensityFittingForceProvider::Impl::Impl(const DensityFittingParameters&
     referenceDensityCenter_ = { real(referenceDensity.extent(XX)) / 2,
                                 real(referenceDensity.extent(YY)) / 2,
                                 real(referenceDensity.extent(ZZ)) / 2 };
-    transformationToDensityLattice_.scaleOperationOnly().inverseIgnoringZeroScale(
-            { &referenceDensityCenter_, &referenceDensityCenter_ + 1 });
+    transformationToDensityLattice_.scaleOperationOnly().inverseIgnoringZeroScale(&referenceDensityCenter_);
     // correct the reference density center for a shift
     // if the reference density does not have its origin at (0,0,0)
     RVec referenceDensityOriginShift(0, 0, 0);
-    transformationToDensityLattice_({ &referenceDensityOriginShift, &referenceDensityOriginShift + 1 });
-    transformationToDensityLattice_.scaleOperationOnly().inverseIgnoringZeroScale(
-            { &referenceDensityOriginShift, &referenceDensityOriginShift + 1 });
+    transformationToDensityLattice_(&referenceDensityOriginShift);
+    transformationToDensityLattice_.scaleOperationOnly().inverseIgnoringZeroScale(&referenceDensityOriginShift);
     referenceDensityCenter_ -= referenceDensityOriginShift;
 }
 
index e93cdc125eec69dd4372e861e5528fed6b8477dc..354525a1f503fad9b3eff3ff3d8bc508820254db 100644 (file)
@@ -100,11 +100,21 @@ void ScaleCoordinates::operator()(ArrayRef<RVec> coordinates) const
     impl_->scale(coordinates);
 }
 
+void ScaleCoordinates::operator()(RVec* coordinate) const
+{
+    impl_->scale({ coordinate, coordinate + 1 });
+}
+
 void ScaleCoordinates::inverseIgnoringZeroScale(ArrayRef<RVec> coordinates) const
 {
     impl_->inverseIgnoringZeroScale(coordinates);
 }
 
+void ScaleCoordinates::inverseIgnoringZeroScale(RVec* coordinate) const
+{
+    impl_->inverseIgnoringZeroScale({ coordinate, coordinate + 1 });
+}
+
 ScaleCoordinates::~ScaleCoordinates() = default;
 
 ScaleCoordinates::ScaleCoordinates(const ScaleCoordinates& other) : impl_(new Impl(*other.impl_)) {}
@@ -164,6 +174,11 @@ void TranslateAndScale::operator()(ArrayRef<RVec> coordinates) const
     impl_->transform(coordinates);
 }
 
+void TranslateAndScale::operator()(RVec* coordinate) const
+{
+    impl_->transform({ coordinate, coordinate + 1 });
+}
+
 ScaleCoordinates TranslateAndScale::scaleOperationOnly() const
 {
     return ScaleCoordinates{ impl_->scale_ };
index 70b74697e23da157dd5b2f1f1906f80836498d06..96571c613189177ffe949a2a033421ea6d9e029b 100644 (file)
@@ -71,11 +71,22 @@ public:
      * \param[in] coordinates to be transformed
      */
     void operator()(ArrayRef<RVec> coordinates) const;
+
+    /*! \brief Perform a coordinate transformation on an input coordinate.
+     * \param[in] coordinate to be transformed
+     */
+    void operator()(RVec* coordinate) const;
+
     /*! \brief Apply the inverse scale to coordinates, ignoring dimensions for which scale is zero.
      * \param[in] coordinates to be transformed
      */
     void inverseIgnoringZeroScale(ArrayRef<RVec> coordinates) const;
 
+    /*! \brief Apply the inverse scale to a coordinate, ignoring dimensions for which scale is zero.
+     * \param[in] coordinate to be transformed
+     */
+    void inverseIgnoringZeroScale(RVec* coordinate) const;
+
 private:
     class Impl;
     PrivateImplPointer<Impl> impl_;
@@ -110,6 +121,11 @@ public:
      */
     void operator()(ArrayRef<RVec> coordinates) const;
 
+    /*! \brief Perform a coordinate transformation on a coordinate.
+     * \param[in] coordinate to be transformed
+     */
+    void operator()(RVec* coordinate) const;
+
     /*! \brief Returns the scaling operation, discarding the translation.
      */
     ScaleCoordinates scaleOperationOnly() const;
index 5abb0b6f03f7128bf53a043ec5b04e22c5b3727f..1b389fd0587191e65005c2e399e728d623938705 100644 (file)
@@ -110,6 +110,17 @@ TEST_F(TranslateAndScaleTest, translationAndScalingNonTrivial)
     EXPECT_THAT(expected, Pointwise(RVecEq(defaultFloatTolerance()), testVectors_));
 }
 
+TEST_F(TranslateAndScaleTest, translationAndScalingNonTrivialSingeVector)
+{
+    TranslateAndScale translateAndScale({ -1e10, 2, 0 }, { 1, -1, 2 });
+    RVec              test(0, 0, 0);
+    translateAndScale(&test);
+
+    EXPECT_REAL_EQ(-1e+10, test[XX]);
+    EXPECT_REAL_EQ(-2, test[YY]);
+    EXPECT_REAL_EQ(0, test[ZZ]);
+}
+
 TEST_F(TranslateAndScaleTest, scalingIdentity)
 {
     ScaleCoordinates scale(identityScale_);
@@ -128,6 +139,18 @@ TEST_F(TranslateAndScaleTest, scalingNonTrivial)
     EXPECT_THAT(expected, Pointwise(RVecEq(defaultFloatTolerance()), testVectors_));
 }
 
+TEST_F(TranslateAndScaleTest, scalingNonTrivialSingleVector)
+{
+    ScaleCoordinates scale({ -100, 0.1, 0 });
+    RVec             test(3, -6, 2.5);
+    scale(&test);
+
+    EXPECT_REAL_EQ(-300, test[XX]);
+    EXPECT_REAL_EQ(-0.6, test[YY]);
+    EXPECT_REAL_EQ(0, test[ZZ]);
+}
+
+
 TEST_F(TranslateAndScaleTest, scalingInverseNoZero)
 {
     ScaleCoordinates scale({ -100, 0.1, 3 });
@@ -146,5 +169,19 @@ TEST_F(TranslateAndScaleTest, scalingInverseWithOneScaleDimensionZero)
     EXPECT_THAT(expected, Pointwise(RVecEq(defaultFloatTolerance()), testVectors_));
 }
 
+TEST_F(TranslateAndScaleTest, scalingInverseWithOneScaleDimensionZeroSingleVector)
+{
+    ScaleCoordinates scale({ -100, 0.1, 0 });
+    RVec             test(3, -6, 2.5);
+
+    scale(&test);
+    scale.inverseIgnoringZeroScale(&test);
+
+    EXPECT_REAL_EQ(3, test[XX]);
+    EXPECT_REAL_EQ(-6, test[YY]);
+    EXPECT_REAL_EQ(0, test[ZZ]);
+}
+
+
 } // namespace test
 } // namespace gmx