Skip to content

refactor: EnergyNode and SPCFw unit test#2326

Merged
trisyoungs merged 29 commits intodevelop2from
dissolve2/energy-unit-tests
Mar 18, 2026
Merged

refactor: EnergyNode and SPCFw unit test#2326
trisyoungs merged 29 commits intodevelop2from
dissolve2/energy-unit-tests

Conversation

@trisyoungs
Copy link
Member

@trisyoungs trisyoungs commented Feb 25, 2026

This PR makes a fairly significant refactoring of the EnergyNode, simplifying its functions (along with those of the old EnergyModule) and providing only calculation of test energies with simple loops. Only the SPC/Fw energy tests are reimplemented here since there is a strong relationship with the ForcesModule unit tests in terms of data. So, with the added bonus of not bloating the PR too much, other energy tests will be implemented once ForcesModule testing is moved over.

@trisyoungs trisyoungs force-pushed the dissolve2/energy-unit-tests branch from edfa223 to 6547b83 Compare February 25, 2026 11:16
@trisyoungs trisyoungs marked this pull request as draft February 26, 2026 08:57
@trisyoungs trisyoungs force-pushed the dissolve2/energy-unit-tests branch 2 times, most recently from ca3e9e4 to 5d290f5 Compare March 6, 2026 14:28
@trisyoungs trisyoungs force-pushed the dissolve2/energy-unit-tests branch from 5d290f5 to 65e5f5c Compare March 11, 2026 09:21
Copy link
Contributor

@rprospero rprospero left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good. Just included some thoughts that it inspired.

Comment on lines +56 to +86
// Update histories
totalEnergyHistory_.push(energy.pairPotential.total() + energy.geometry.total(), podHistoryLength_);
totalPairPotentialHistory_.push(energy.pairPotential.total(), podHistoryLength_);
totalMoleculePPHistory_.push(energy.pairPotential.intraMolecular, podHistoryLength_);
totalCohesiveHistory.push(energy.pairPotential.interMolecular, podHistoryLength_);
totalGeometryHistory_.push(energy.geometry.total(), podHistoryLength_);
bondHistory_.push(energy.geometry.bondEnergy, podHistoryLength_);
angleHistory_.push(energy.geometry.angleEnergy, podHistoryLength_);
torsionHistory_.push(energy.geometry.torsionEnergy, podHistoryLength_);
improperHistory_.push(energy.geometry.improperEnergy, podHistoryLength_);

// Determine stability of energy
// Check number of points already stored for the Configuration
auto grad = 0.0;
auto stable = false;
if (stabilityWindow_ > totalEnergyHistory_.history().size())
message("Too few points to assess stability.\n");
else
{
auto yMean = 0.0;
grad = Regression::linearGradient(totalEnergyHistory_.history(), stabilityWindow_, yMean);
auto thresholdValue = fabs(stabilityThreshold_ * yMean);
stable = fabs(grad) < thresholdValue;

message("Gradient of last {} points is {:e} kJ/mol/step (absolute threshold value is "
"{:e}, stable = {}).\n",
stabilityWindow_, grad, thresholdValue, DissolveSys::btoa(stable));
}

targetConfiguration_->setEnergyGradient(grad);
targetConfiguration_->setEnergyStable(stable);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think that we should change any of this code right now, but it has given me some thoughts.

First, I'm thinking about a history node. The idea being that the node has a single Number input, a name option, and a history output. That opens up a couple of options. The user could pass the history to a graph node and get a graph of the history in a separate tab. It would also be possible to gain access to the gradient and perhaps perform different actions based on it.

Second, I'm also wondering about a user customizable dashboard. Values, such as strings, Numbers, or histories, could be sent into sinks in the graph with a name option. Then, in a separate panel, this information could all be in one place as a custom display to watch the simulation progress.

Finally, I'm thinking that I need to do more work on inner graphs. If we went with my history node idea and broken up the energy node into multiple parts, it would be an annoying pain for the users to wire everything back up again for every input file. Instead, we'd likely want to provide a node which did all of this for them. More concretely, I believe that we want

  1. A folder with a library of common subgraphs
  2. The ability to insert a library subgraph as a node
  3. The ability to add these subgraphs to the regular "Insert" menu in the GUI

I feel like we'll need this inner graph part even if we don't head down the history or dashboard roads.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, absolutely - the dashboard road is basically what I had in mind from the beginning in my mind's eye, as either a side panel, a full (separate) overview panel, or as individual tiny readouts / graphs on the nodes themselves (perhaps as a sort of GraphViewType option, switching between the display of inputs / outputs / options and the readout data).

Whether this data presentation / access should be achieved via Nodes I'm not so sure. This adds another layer of effort for the user to achieve what should be (in my opinion) a one-click (menu) operation. We could instead consider the idea of tagging data internally as exportable / plottable / viewable in the Node constructor, and just presenting those as options where necessary.

@trisyoungs trisyoungs merged commit 0bc2daa into develop2 Mar 18, 2026
8 of 9 checks passed
@trisyoungs trisyoungs deleted the dissolve2/energy-unit-tests branch March 18, 2026 09:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants