Skip to content

Commit dceb4c0

Browse files
trisyoungsTristan Youngs
andauthored
feat: Data history storage (for averaging) (#2206)
Co-authored-by: Tristan Youngs <trisyoungs@googlemail.com>
1 parent 554a0b6 commit dceb4c0

7 files changed

Lines changed: 60 additions & 20 deletions

File tree

src/classes/partialSet.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -499,6 +499,13 @@ void PartialSet::operator*=(const double factor)
499499
unboundTotal_ *= factor;
500500
}
501501

502+
PartialSet PartialSet::operator*(const double factor) const
503+
{
504+
auto result = (*this);
505+
result *= factor;
506+
return result;
507+
}
508+
502509
/*
503510
* Searchers
504511
*/

src/classes/partialSet.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,7 @@ class PartialSet
135135
void operator+=(const PartialSet &source);
136136
void operator-=(const double delta);
137137
void operator*=(const double factor);
138+
PartialSet operator*(const double factor) const;
138139

139140
/*
140141
* Searchers

src/math/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ add_library(
3939
histogram2D.h
4040
histogram3D.cpp
4141
histogram3D.h
42+
history.h
4243
integerHistogram1D.cpp
4344
integerHistogram1D.h
4445
integrator.cpp

src/math/history.h

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// SPDX-License-Identifier: GPL-3.0-or-later
2+
// Copyright (c) 2025 Team Dissolve and contributors
3+
4+
#pragma once
5+
6+
#include "base/serialiser.h"
7+
#include <memory>
8+
#include <vector>
9+
10+
// Data History
11+
template <class T> class History
12+
{
13+
private:
14+
// Stored historical data
15+
std::vector<std::unique_ptr<T>> history_;
16+
17+
public:
18+
// Update history with supplied data and return current average
19+
T average(const T &currentData, int averagingLength)
20+
{
21+
// Push the current data onto the history stack
22+
history_.emplace_back(std::make_unique<T>(currentData));
23+
24+
// Prune old data to get to the averagingLength
25+
while (history_.size() > averagingLength)
26+
history_.erase(history_.begin());
27+
28+
// Perform averaging of the datasets that we have
29+
T averaged;
30+
auto weight = 1.0 / history_.size();
31+
for (auto &data : history_)
32+
averaged += *data * weight;
33+
34+
return averaged;
35+
};
36+
// Express data as a serialisable value
37+
SerialisedValue serialise()
38+
requires(std::is_base_of_v<Serialisable<>, T>)
39+
{
40+
SerialisedValue result;
41+
result["size"] = history_.size();
42+
Serialisable<>::fromVectorToTable(history_, "data", result);
43+
return result;
44+
}
45+
};

src/nodes/gr/gr.cpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,6 @@ GRNode::GRNode(Graph *parentGraph) : Node(parentGraph)
1111
addOption<std::optional<Number>>("Range", "Maximum r to calculate g(r) out to", requestedRange_);
1212
addOption<std::optional<Number>>("Averaging", "Number of historical partial sets to combine into final partials",
1313
averagingLength_);
14-
addOption<Averaging::AveragingScheme>("AveragingScheme", "Weighting scheme to use when averaging partials",
15-
averagingScheme_);
1614
addOption<Function1DWrapper>("IntraBroadening", "Type of broadening to apply to intramolecular g(r)", intraBroadening_);
1715
addOption<std::optional<Number>>("Smoothing", "Specifies the degree of smoothing to apply to calculated g(r)", nSmooths_);
1816
addOption<bool>("Save", "Whether to save partials and total functions to disk", save_);

src/nodes/gr/gr.h

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,10 @@
88
#include "classes/partialSet.h"
99
#include "classes/species.h"
1010
#include "items/list.h"
11-
#include "math/averaging.h"
12-
#include "math/data1D.h"
1311
#include "math/function1D.h"
14-
#include "nodes/graph.h"
12+
#include "math/history.h"
1513
#include "nodes/node.h"
1614
#include "nodes/number.h"
17-
#include "nodes/parameter.h"
1815
#include <vector>
1916

2017
class GRNode : public Node
@@ -47,12 +44,12 @@ class GRNode : public Node
4744
Configuration *targetConfiguration_{nullptr};
4845
// Raw simulation g(r)
4946
std::optional<PartialSet> rawGR_;
47+
// Historical raw g(r)
48+
History<PartialSet> rawGRHistory_;
5049
// Unweighted g(r)
5150
std::optional<PartialSet> unweightedGR_;
5251
// Number of historical partial sets to combine into final partials
5352
std::optional<Number> averagingLength_{5};
54-
// Weighting scheme to use when averaging partials
55-
Averaging::AveragingScheme averagingScheme_{Averaging::LinearAveraging};
5653
// Bin width (spacing in r) to use
5754
Number binWidth_{0.001};
5855
// Perform internal check of calculated partials against a set calculated by a simple unoptimised double-loop

src/nodes/gr/process.cpp

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,7 @@ NodeConstants::ProcessResult GRNode::process()
2525
message("Partials will be calculated out to {} Angstroms.\n", requestedRange_.value().asDouble());
2626
message("Bin-width to use is {} Angstroms.\n", binWidth_.asDouble());
2727
if (averagingLength_)
28-
message("Partials will be averaged over {} sets (scheme = {}).\n", averagingLength_.value().asDouble(),
29-
Averaging::averagingSchemes().keyword(averagingScheme_));
28+
message("Partials will be averaged over {} sets.\n", averagingLength_.value().asDouble());
3029
else
3130
message("No averaging of partials will be performed.\n");
3231
if (intraBroadening_.form() == Functions1D::Form::None)
@@ -80,17 +79,9 @@ NodeConstants::ProcessResult GRNode::process()
8079
bool alreadyUpToDate;
8180
calculateRawGR(grRange, alreadyUpToDate);
8281

83-
// Perform averagingLength_ of unweighted partials if requested, and if we're not already up-to-date
84-
/*
82+
// Perform averaging of unweighted partials if requested, and if we're not already up-to-date
8583
if ((averagingLength_.value_or(1) > 1) && (!alreadyUpToDate))
86-
{
87-
// Store the current fingerprint, since we must ensure we retain it in the averaged T.
88-
std::string currentFingerprint{rawGR_.fingerprint()};
89-
90-
Averaging::average<PartialSet>(dissolve().processingModuleData(), std::format("{}//OriginalGR",
91-
targetConfiguration_->niceName()), name(), averagingLength_.value().asDouble(), averagingScheme_);
92-
}
93-
*/
84+
(*rawGR_) = rawGRHistory_.average(*rawGR_, averagingLength_.value().asInteger());
9485

9586
/*
9687
// Perform internal test of original g(r)?

0 commit comments

Comments
 (0)