namespace test
{
-//! Enumeration controlling which trajectory frames are compared
-enum class FramesToCompare : int
+/*! \internal
+ * \brief Named struct indicating the max number of frames to be compared */
+struct MaxNumFrames
{
- AllFrames,
- OnlyFirstFrame, // e.g. because step-0 quantities are most useful to compare
- Count
+ //! Explicit constructor
+ explicit MaxNumFrames(unsigned int maxFrame) : maxFrame_(maxFrame) {}
+
+ //! Implicit conversion to int - struct can be used like underlying type
+ operator unsigned int() const { return maxFrame_; }
+
+ //! Return a MaxNumFrames that will try to compare all frames
+ [[nodiscard]] static MaxNumFrames compareAllFrames()
+ {
+ return MaxNumFrames(std::numeric_limits<decltype(maxFrame_)>::max());
+ }
+
+private:
+ //! Internal value
+ const unsigned int maxFrame_;
};
} // namespace test
};
EnergyComparison::EnergyComparison(const EnergyTermsToCompare& energyTermsToCompare,
- FramesToCompare framesToCompare) :
+ MaxNumFrames maxNumFrames) :
energyTermsToCompare_(energyTermsToCompare),
- framesToCompare_(framesToCompare)
+ maxNumFrames_(maxNumFrames)
{
}
void EnergyComparison::operator()(const EnergyFrame& reference, const EnergyFrame& test) const
{
- if (framesToCompare_ == FramesToCompare::OnlyFirstFrame && firstFrameHasBeenCompared_)
+ if (numComparedFrames_ >= maxNumFrames_)
{
// Nothing should be compared
return;
ADD_FAILURE() << "Could not find energy component from reference frame in test frame";
}
}
- firstFrameHasBeenCompared_ = true;
+ numComparedFrames_++;
}
void checkEnergiesAgainstReferenceData(const std::string& energyFilename,
const EnergyTermsToCompare& energyTermsToCompare,
- TestReferenceChecker* checker)
+ TestReferenceChecker* checker,
+ MaxNumFrames maxNumEnergyFrames)
{
const bool thisRankChecks = (gmx_node_rank() == 0);
if (thisRankChecks)
{
- EnergyComparison energyComparison(energyTermsToCompare, FramesToCompare::AllFrames);
+ EnergyComparison energyComparison(energyTermsToCompare, maxNumEnergyFrames);
auto energyReader = openEnergyFileToReadTerms(energyFilename, energyComparison.getEnergyNames());
std::unordered_map<std::string, TestReferenceChecker> checkers;
// frames with the same step number. But we need a unique
// identifier so we match the intended reference data, so we
// keep track of the number of the frame read from the file.
- int frameNumber = 0;
- while (energyReader->readNextFrame())
+ unsigned int frameNumber = 0;
+ while (frameNumber < maxNumEnergyFrames && energyReader->readNextFrame())
{
- const EnergyFrame& frame = energyReader->frame();
- const std::string frameName = frame.frameName() + " in frame " + toString(frameNumber);
+ const EnergyFrame& frame = energyReader->frame();
+ const std::string frameName =
+ frame.frameName() + " in frame " + toString(static_cast<int64_t>(frameNumber));
SCOPED_TRACE("Comparing frame " + frameName);
for (const auto& energyTermToCompare : energyTermsToCompare)
}
++frameNumber;
}
+ if (frameNumber == maxNumEnergyFrames && energyReader->readNextFrame())
+ {
+ // There would have been at least one more frame!
+ checker->disableUnusedEntriesCheck();
+ }
}
else
{
}
}
+void checkEnergiesAgainstReferenceData(const std::string& energyFilename,
+ const EnergyTermsToCompare& energyTermsToCompare,
+ TestReferenceChecker* checker)
+{
+ checkEnergiesAgainstReferenceData(energyFilename, energyTermsToCompare, checker,
+ MaxNumFrames::compareAllFrames());
+}
+
} // namespace test
} // namespace gmx
//! Defaults for energy comparisons
static EnergyTermsToCompare defaultEnergyTermsToCompare();
//! Constructor
- EnergyComparison(const EnergyTermsToCompare& energyTermsToCompare, FramesToCompare framesToCompare);
+ EnergyComparison(const EnergyTermsToCompare& energyTermsToCompare, MaxNumFrames maxNumFrames);
/*! \brief Return the names of energies that will be compared
*
* This function can be used to provide an input for
private:
//! Energy terms to match with given tolerances.
EnergyTermsToCompare energyTermsToCompare_;
- //! Which frames should be compared.
- FramesToCompare framesToCompare_ = FramesToCompare::AllFrames;
- /*! \brief Whether the first frame has been compared yet
+ //! How many frames should be compared.
+ MaxNumFrames maxNumFrames_ = MaxNumFrames::compareAllFrames();
+ /*! \brief The number of frames that have been compared until now
*
* This field is mutable because the need to update the flag
- * after the first frame is merely an implementation detail,
+ * when checking frames is merely an implementation detail,
* rather than a proper change of internal state triggered
* by the caller. */
- mutable bool firstFrameHasBeenCompared_ = false;
+ mutable unsigned int numComparedFrames_ = 0;
};
/*! \brief Check a subset of the energies found in an energy file
* \param[in] energyFilename The name of an energy file.
* \param[in] energyTermsToCompare Set of energies to match at given tolerances.
* \param[in] checker Root checker for reference data.
+ * \param[in] maxNumEnergyFrames The maximum number of frames to check
*
* \todo This is quite similar to the functionality used in PmeTest,
* and we should consider reducing the duplication.
*/
+void checkEnergiesAgainstReferenceData(const std::string& energyFilename,
+ const EnergyTermsToCompare& energyTermsToCompare,
+ TestReferenceChecker* checker,
+ MaxNumFrames maxNumEnergyFrames);
+
+/*!
+ * \brief Check a subset of the energies found in an energy file
+ * against reference data.
+ *
+ * Convenience overload using all frames
+ *
+ * \see checkEnergiesAgainstReferenceData(const std::string&, const EnergyTermsToCompare&, TestReferenceChecker*, MaxNumFrames)
+ */
void checkEnergiesAgainstReferenceData(const std::string& energyFilename,
const EnergyTermsToCompare& energyTermsToCompare,
TestReferenceChecker* checker);
// Build the functor that will compare energy frames on the chosen
// energy terms.
- EnergyComparison energyComparison(energyTermsToCompare, FramesToCompare::AllFrames);
+ EnergyComparison energyComparison(energyTermsToCompare, MaxNumFrames::compareAllFrames());
// Build the manager that will present matching pairs of frames to compare.
//
ReferenceFileNames referenceFileNames_ = { fileManager_.getTemporaryFilePath("reference.edr") };
//! Functor for energy comparison
EnergyComparison energyComparison_{ EnergyComparison::defaultEnergyTermsToCompare(),
- FramesToCompare::AllFrames };
+ MaxNumFrames::compareAllFrames() };
//! Names of energies compared by energyComparison_
std::vector<std::string> namesOfEnergiesToMatch_ = energyComparison_.getEnergyNames();
};
ComparisonConditions::MustCompare,
ComparisonConditions::NoComparison,
ComparisonConditions::MustCompare,
- FramesToCompare::AllFrames
+ MaxNumFrames::compareAllFrames()
};
void executeRerunTest(TestFileManager* fileManager,
ComparisonConditions::MustCompare,
ComparisonConditions::MustCompare,
ComparisonConditions::MustCompare,
- FramesToCompare::AllFrames };
+ MaxNumFrames::compareAllFrames() };
TrajectoryTolerances trajectoryTolerances = TrajectoryComparison::s_defaultTrajectoryTolerances;
if (simulationName != "argon12")
{
{
// Build the functor that will compare energy frames on the chosen
// energy terms.
- EnergyComparison energyComparison(energyTermsToCompare, FramesToCompare::AllFrames);
+ EnergyComparison energyComparison(energyTermsToCompare, MaxNumFrames::compareAllFrames());
// Build the manager that will present matching pairs of frames to compare.
//
void TrajectoryComparison::operator()(const TrajectoryFrame& reference, const TrajectoryFrame& test) const
{
- if (matchSettings_.framesToCompare == FramesToCompare::OnlyFirstFrame && firstFrameHasBeenCompared_)
+ if (numComparedFrames_ >= matchSettings_.maxNumTrajectoryFrames)
{
// Nothing should be compared
return;
compareCoordinates(reference, test, matchSettings_, tolerances_.coordinates);
compareVelocities(reference, test, matchSettings_, tolerances_.velocities);
compareForces(reference, test, matchSettings_, tolerances_.forces);
- firstFrameHasBeenCompared_ = true;
+ numComparedFrames_++;
}
} // namespace test
ComparisonConditions velocitiesComparison = ComparisonConditions::CompareIfBothFound;
//! Whether forces must be compared.
ComparisonConditions forcesComparison = ComparisonConditions::CompareIfBothFound;
- //! Which frames will be compared
- FramesToCompare framesToCompare = FramesToCompare::AllFrames;
+ //! How many frames will be compared.
+ MaxNumFrames maxNumTrajectoryFrames = MaxNumFrames::compareAllFrames();
};
/*! \internal
TrajectoryFrameMatchSettings matchSettings_;
//! Trajectory fields to match with given tolerances.
TrajectoryTolerances tolerances_;
- /*! \brief Whether the first frame has been compared yet
+ /*! \brief The number of frames that have been compared until now
*
* This field is mutable because the need to update the flag
- * after the first frame is merely an implementation detail,
+ * when checking frames is merely an implementation detail,
* rather than a proper change of internal state triggered
* by the caller. */
- mutable bool firstFrameHasBeenCompared_ = false;
+ mutable unsigned int numComparedFrames_ = 0;
};
} // namespace test
}
}
+void TestReferenceChecker::disableUnusedEntriesCheck()
+{
+ if (impl_->compareRootEntry_)
+ {
+ impl_->compareRootEntry_->setCheckedIncludingChildren();
+ }
+}
+
bool TestReferenceChecker::checkPresent(bool bPresent, const char* id)
{
*/
void checkUnusedEntries();
+ /*! \brief Disables checking for unused entries
+ *
+ * \see checkUnusedEntries()
+ */
+ void disableUnusedEntriesCheck();
+
/*! \brief
* Checks whether a data item is present.
*