From 4b3ea3fcfb5dfc45ebffd67c764f1c7824250fba Mon Sep 17 00:00:00 2001 From: Tristan Youngs Date: Sun, 14 Jun 2026 17:44:52 +0100 Subject: [PATCH 1/3] Remove distributors. --- src/classes/CMakeLists.txt | 8 - src/classes/cellDistributor.cpp | 22 -- src/classes/cellDistributor.h | 28 -- src/classes/moleculeDistributor.cpp | 37 -- src/classes/moleculeDistributor.h | 32 -- src/classes/regionalDistributor.cpp | 503 ---------------------------- src/classes/regionalDistributor.h | 102 ------ 7 files changed, 732 deletions(-) delete mode 100644 src/classes/cellDistributor.cpp delete mode 100644 src/classes/cellDistributor.h delete mode 100644 src/classes/moleculeDistributor.cpp delete mode 100644 src/classes/moleculeDistributor.h delete mode 100644 src/classes/regionalDistributor.cpp delete mode 100644 src/classes/regionalDistributor.h diff --git a/src/classes/CMakeLists.txt b/src/classes/CMakeLists.txt index 6e2bc9b4fe..980a8f4656 100644 --- a/src/classes/CMakeLists.txt +++ b/src/classes/CMakeLists.txt @@ -9,7 +9,6 @@ add_library( braggReflection.cpp cell.cpp cellArray.cpp - cellDistributor.cpp changeData.cpp changeStore.cpp configuration.cpp @@ -21,7 +20,6 @@ add_library( configuration_upkeep.cpp configurationAtom.cpp coreData.cpp - distributor.cpp empiricalFormula.cpp fullPairIterator.cpp histogramSet.cpp @@ -31,7 +29,6 @@ add_library( kVector.cpp localMolecule.cpp molecule.cpp - moleculeDistributor.cpp moleculeSet.cpp neutronWeights.cpp pairPotential.cpp @@ -42,7 +39,6 @@ add_library( partialSet.cpp partialSetAccumulator.cpp region.cpp - regionalDistributor.cpp scatteringMatrix.cpp shortRangeFunctions.cpp site.cpp @@ -79,14 +75,12 @@ add_library( braggReflection.h cell.h cellArray.h - cellDistributor.h changeData.h changeStore.h configuration.h configurationAtom.cpp coreData.h dataSource.h - distributor.h empiricalFormula.h fragment.h histogramSet.h @@ -97,7 +91,6 @@ add_library( kVector.h localMolecule.h molecule.h - moleculeDistributor.h moleculeSet.h neutronWeights.h pairPotential.h @@ -107,7 +100,6 @@ add_library( partialSetAccumulator.h potentialSet.h region.h - regionalDistributor.h scatteringMatrix.h shortRangeFunctions.h site.h diff --git a/src/classes/cellDistributor.cpp b/src/classes/cellDistributor.cpp deleted file mode 100644 index 7ab00bb07c..0000000000 --- a/src/classes/cellDistributor.cpp +++ /dev/null @@ -1,22 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-or-later -// Copyright (c) 2026 Team Dissolve and contributors - -#include "classes/cellDistributor.h" -#include "classes/cell.h" - -CellDistributor::CellDistributor(const CellArray &cellArray, bool repeatsAllowed) - : Distributor(cellArray.nCells(), cellArray, repeatsAllowed), cells_(cellArray) -{ -} - -CellDistributor::~CellDistributor() = default; - -/* - * Cells - */ - -// Return array of Cells that we must hard lock in order to modify the object with index specified -std::vector CellDistributor::cellsToBeModifiedForObject(int objectId) -{ - return std::vector({cells_.cell(objectId)}); -} diff --git a/src/classes/cellDistributor.h b/src/classes/cellDistributor.h deleted file mode 100644 index 40f9d1cc96..0000000000 --- a/src/classes/cellDistributor.h +++ /dev/null @@ -1,28 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-or-later -// Copyright (c) 2026 Team Dissolve and contributors - -#pragma once - -#include "classes/distributor.h" - -// Cell Distributor -class CellDistributor : public Distributor -{ - public: - CellDistributor(const CellArray &cellArray, bool repeatsAllowed); - ~CellDistributor() override; - - /* - * Data - */ - private: - // Source CellArray - const CellArray &cells_; - - /* - * Cells - */ - private: - // Return array of Cells that we must hard lock in order to modify the object with index specified - std::vector cellsToBeModifiedForObject(int objectId) override; -}; diff --git a/src/classes/moleculeDistributor.cpp b/src/classes/moleculeDistributor.cpp deleted file mode 100644 index 7685ac26ab..0000000000 --- a/src/classes/moleculeDistributor.cpp +++ /dev/null @@ -1,37 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-or-later -// Copyright (c) 2026 Team Dissolve and contributors - -#include "classes/moleculeDistributor.h" -#include "classes/configurationAtom.h" - -MoleculeDistributor::MoleculeDistributor(const std::deque> &moleculeArray, const CellArray &cellArray, - bool repeatsAllowed) - : Distributor(moleculeArray.size(), cellArray, repeatsAllowed), moleculeArray_(moleculeArray) -{ -} - -MoleculeDistributor::~MoleculeDistributor() = default; - -/* - * Cells - */ - -// Return array of Cells that we must hard lock in order to modify the object with index specified -std::vector MoleculeDistributor::cellsToBeModifiedForObject(int objectId) -{ - // Grab specified molecule - std::shared_ptr molecule = moleculeArray_[objectId]; - - // Loop over Atoms in the Molecule, and add the (unique) cellID each Atom is in - std::vector cells; - for (auto i = 0; i < molecule->nAtoms(); ++i) - { - auto *cell = molecule->atom(i)->cell(); - - // Is it already in the list? - if (std::find(cells.begin(), cells.end(), cell) == cells.end()) - cells.push_back(cell); - } - - return cells; -} diff --git a/src/classes/moleculeDistributor.h b/src/classes/moleculeDistributor.h deleted file mode 100644 index 34107349d4..0000000000 --- a/src/classes/moleculeDistributor.h +++ /dev/null @@ -1,32 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-or-later -// Copyright (c) 2026 Team Dissolve and contributors - -#pragma once - -#include "classes/distributor.h" -#include "classes/molecule.h" -#include -#include - -// Molecule Distributor -class MoleculeDistributor : public Distributor -{ - public: - MoleculeDistributor(const std::deque> &moleculeArray, const CellArray &cellArray, - bool repeatsAllowed); - ~MoleculeDistributor() override; - - /* - * Data - */ - private: - // Source Molecule Array - const std::deque> &moleculeArray_; - - /* - * Cells - */ - private: - // Return array of Cells that we must hard lock in order to modify the object with index specified - std::vector cellsToBeModifiedForObject(int objectId) override; -}; diff --git a/src/classes/regionalDistributor.cpp b/src/classes/regionalDistributor.cpp deleted file mode 100644 index 7b5ebd35b3..0000000000 --- a/src/classes/regionalDistributor.cpp +++ /dev/null @@ -1,503 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-or-later -// Copyright (c) 2026 Team Dissolve and contributors - -#include "classes/regionalDistributor.h" -#include "base/lineParser.h" -#include "classes/cell.h" -#include "classes/configurationAtom.h" -#include "classes/molecule.h" -#include - -// Debug Mode -const bool debugDistributor = false; - -RegionalDistributor::RegionalDistributor(const int nMolecules, const CellArray &cellArray) : cellArray_(cellArray) -{ - // Core - nProcessesOrGroups_ = 1; - processOrGroupIndex_ = 0; - nCycles_ = 0; - - // Cells - lockedCells_ = std::vector>(nProcessesOrGroups_); - cellStatusFlags_.resize(cellArray.nCells()); - std::fill(cellStatusFlags_.begin(), cellStatusFlags_.end(), CellStatusFlag::Unused); - cellLockOwners_.resize(cellArray.nCells()); - std::fill(cellLockOwners_.begin(), cellLockOwners_.end(), -1); - - // Molecules - nMolecules_ = nMolecules; - assignedMolecules_.resize(nProcessesOrGroups_); - moleculeStatus_.resize(nMolecules_); - std::fill(moleculeStatus_.begin(), moleculeStatus_.end(), MoleculeStatusFlag::ToDo); - nMoleculesToDistribute_ = nMolecules_; - nMoleculesDistributed_ = 0; -} - -// Return string for specified MoleculeStatusFlag -std::string_view RegionalDistributor::moleculeStatusFlag(RegionalDistributor::MoleculeStatusFlag flag) -{ - if (flag == MoleculeStatusFlag::ToDo) - return "ToDo"; - else if (flag == MoleculeStatusFlag::Assigned) - return "Assigned"; - else - return "Completed"; -} - -// Return string for specified CellStatusFlag -std::string_view RegionalDistributor::cellStatusFlag(RegionalDistributor::CellStatusFlag flag) -{ - if (flag == CellStatusFlag::Unused) - return "Unused"; - else if (flag == CellStatusFlag::LockedForEditing) - return "LockedForEditing"; - else if (flag == CellStatusFlag::ReadByOne) - return "ReadByOne"; - else - return "ReadByMany"; -} - -/* - * Core - */ - -// Set up next distribution of Molecules amongst processes/groups, returning false if there are no more Molecules to distribute -bool RegionalDistributor::cycle() -{ - /* - * All processes should call here together. - * We start by selecting a starting Cell index for the first process/group. Then, we choose a Molecule (partly) present - * in the Cell which needs to be calculated. If no such Molecule is available, we choose a new Cell (increase the Cell - * index) and try again. Once a Molecule has been located, we attempt to assign all Cells which the Molecule's atoms - * exist in, and all of the immediate adjacent neighbours, to that process/group. If any other process/group has already - * marked that Cell as 'Locked', or a Cell has been marked read-only by a process/group other than us, then we cannot - * modify the Molecule (since doing so would potentially lead to inconsistencies in the calculation of other Molecules). - * Once a Molecule has been successfully locked, we move on to the next process/group and repeat the procedure. - * When we return to the first process, we use the already-locked list of Cells as a source of potential Molecule - * candidates. - */ - - // Initial check - if all target Molecules have been distributed, we can return the AllComplete flag - if (nMoleculesDistributed_ == nMoleculesToDistribute_) - { - Messenger::printVerbose("All target Molecules distributed.\n"); - - return false; - } - - std::shared_ptr molecule; - std::vector allPossibleMoleculesAssigned(nProcessesOrGroups_, false); - int processOrGroup, allPossibleMoleculesAssignedCount = 0; - - // Set Molecule completed flags and clear distribution arrays - for (processOrGroup = 0; processOrGroup < nProcessesOrGroups_; ++processOrGroup) - { - assignedMolecules_[processOrGroup].clear(); - lockedCells_[processOrGroup].clear(); - } - - // Reset the Cell status flags - std::fill(cellStatusFlags_.begin(), cellStatusFlags_.end(), CellStatusFlag::Unused); - std::fill(cellLockOwners_.begin(), cellLockOwners_.end(), -1); - - // If there is only one process/group, put all Molecules in it. Otherwise loop over target groups/processes, assigning - // molecules sequentially to each - if (nProcessesOrGroups_ == 1) - { - for (auto n = 0; n < nMolecules_; ++n) - { - if (moleculeStatus_[n] == MoleculeStatusFlag::ToDo) - { - assignedMolecules_[0].push_back(n); - ++nMoleculesDistributed_; - } - } - } - else - while (allPossibleMoleculesAssignedCount < nProcessesOrGroups_) - { - for (processOrGroup = 0; processOrGroup < nProcessesOrGroups_; ++processOrGroup) - { - if (debugDistributor) - Messenger::print("\n ** Searching for suitable Molecule to assign to process/group {}...\n\n", - processOrGroup); - - // If we have already assigned all possible Molecules for this process/group, continue the loop - if (allPossibleMoleculesAssigned[processOrGroup]) - continue; - - // Try to assign a Molecule to this process/group - molecule = assignMolecule(processOrGroup); - if (!molecule) - { - allPossibleMoleculesAssigned[processOrGroup] = true; - ++allPossibleMoleculesAssignedCount; - - if (debugDistributor) - Messenger::print("Failed to find a suitable Molecule for process/group {}\n", processOrGroup); - } - else - { - // Valid Molecule found, so add it to our distribution array and mark it as such - assignedMolecules_[processOrGroup].push_back(molecule->arrayIndex()); - moleculeStatus_[molecule->arrayIndex()] = MoleculeStatusFlag::Assigned; - ++nMoleculesDistributed_; - - if (debugDistributor) - Messenger::print("Molecule {} assigned to process/group {} - nMoleculesDistributed is " - "now {}. Process/group has {} locked Cells in total.\n", - molecule->arrayIndex(), processOrGroup, nMoleculesDistributed_, - lockedCells_[processOrGroup].size()); - } - - // Have all possible Molecules been assigned? - if (allPossibleMoleculesAssignedCount == nProcessesOrGroups_) - break; - } - - /* - * We have assigned all possible Molecules, so let's sanity check exactly how we have divided them up. - * If only the first process/group has any Molecules assigned to it, we will revert to PoolStrategy and - * send the only populated Molecule list to all processes. - */ - if (std::any_of(assignedMolecules_.begin(), assignedMolecules_.end(), - [](const auto &procMols) { return procMols.empty(); })) - { - // Put all assigned molecules into group 0 - assignedMolecules_[0].clear(); - for (auto n = 0; n < nMolecules_; ++n) - if (moleculeStatus_[n] == MoleculeStatusFlag::Assigned) - assignedMolecules_[0].push_back(n); - - // Copy target molecule(s) to all groups - for (processOrGroup = 1; processOrGroup < nProcessesOrGroups_; ++processOrGroup) - assignedMolecules_[processOrGroup] = assignedMolecules_[0]; - - break; - } - } - - ++nCycles_; - - // Summarise - for (processOrGroup = 0; processOrGroup < nProcessesOrGroups_; ++processOrGroup) - { - Messenger::printVerbose( - "Distributor cycle {} : Process/Group {} has {} Molecules assigned to it over {} locked Cells.\n", nCycles_, - processOrGroup, assignedMolecules_[processOrGroup].size(), lockedCells_[processOrGroup].size()); - } - - // Change status of all "Assigned" molecules to "Completed" - for (auto n = 0; n < nMolecules_; ++n) - if (moleculeStatus_[n] == MoleculeStatusFlag::Assigned) - moleculeStatus_[n] = MoleculeStatusFlag::Completed; - - return true; -} - -/* - * Cells - */ - -// Return whether the specified processOrGroup can lock the given Cell index -bool RegionalDistributor::canLockCellForEditing(int processOrGroup, int cellIndex) -{ - CellStatusFlag status = cellStatusFlags_.at(cellIndex); - - if (debugDistributor) - Messenger::print(" 0-- Checking ability to lock Cell index {} for process/group {}: current status = {}\n", cellIndex, - processOrGroup, cellStatusFlag(cellStatusFlags_.at(cellIndex))); - - // If the Cell is flagged as unused, return true - if (status == CellStatusFlag::Unused) - return true; - - // If the Cell is flagged as 'LockedForEditing', and not by this processOrGroup, return false. If we have locked it, - // return true. - if (status == CellStatusFlag::LockedForEditing) - return (cellLockOwners_.at(cellIndex) == processOrGroup); - - // If the Cell is flagged as 'ReadByOne', but not by this processOrGroup, return false (if we are the sole reader, we - // can lock it) - if (status == CellStatusFlag::ReadByOne) - return (cellLockOwners_.at(cellIndex) == processOrGroup); - - // If the Cell is flagged as 'ReadByMany', there is no chance of locking it, so return false. - if (status == CellStatusFlag::ReadByMany) - return false; - - // That's all four possibilities, so raise an error if we get here (we never should) - Messenger::error("Failed to determine lock possibility correctly.\n"); - - return false; -} - -/* - * Molecules - */ - -// Assign Molecule to process/group if possible -bool RegionalDistributor::assignMolecule(const std::shared_ptr &mol, int processOrGroup) -{ - Cell *primaryCell = nullptr; - - // Obvious check first - is the Molecule available for distribution / assignment? - const auto molId = mol->arrayIndex(); - - if (debugDistributor) - Messenger::print(" -- Checking Molecule {} for process/group {}: status = {}\n", molId, processOrGroup, - moleculeStatusFlag(moleculeStatus_[molId])); - - if (moleculeStatus_[molId] != MoleculeStatusFlag::ToDo) - return false; - - // Go through the Atoms of the Molecule, assembling a list of primary Cells in which its Atoms are found. - std::vector primaryCells; - for (auto i = 0; i < mol->nAtoms(); ++i) - { - // Get Cell pointer and index - primaryCell = mol->atom(i)->cell(); - auto cellIndex = primaryCell->index(); - - // Make sure we can lock this Cell for editing, unless we have locked it already... - if ((cellLockOwners_[cellIndex] == processOrGroup) && (cellStatusFlags_[cellIndex] == CellStatusFlag::LockedForEditing)) - { - if (debugDistributor) - Messenger::print(" -- Cell {} is already locked by us ({})\n", cellIndex, cellLockOwners_[cellIndex]); - continue; - } - if (!canLockCellForEditing(processOrGroup, cellIndex)) - { - if (debugDistributor) - Messenger::print(" -- Cell {} cannot be locked for editing - current owner ({}) and/or status " - "({}) forbid it\n", - cellIndex, cellLockOwners_[cellIndex], cellStatusFlag(cellStatusFlags_[cellIndex])); - return false; - } - - if (debugDistributor) - Messenger::print(" -- Cell {} can be locked - current owner ({})\n", cellIndex, cellLockOwners_[cellIndex]); - - // Add to the primary Cells list - primaryCells.push_back(primaryCell); - } - - // We are able to lock all Cells that we need to edit, so now construct a list of those within the cutoff range of any - // primaryCell that we must be able to read (but not modify) - std::set readOnlyCells; - for (auto *cell : primaryCells) - { - // Loop over all neighbours for this primary Cell, taking care to ignore the entry corresponding to this cell itself - for (auto &nbr : cellArray_.neighbours(*cell)) - { - if (&nbr.cell == cell) - continue; - - auto nbrIndex = nbr.cell.index(); - - // If we have locked this Cell already, continue - if (cellStatusFlags_[nbrIndex] == CellStatusFlag::LockedForEditing) - { - if (cellLockOwners_[nbrIndex] == processOrGroup) - continue; - else - { - if (debugDistributor) - Messenger::print(" -- Can't add Cell {} as a read-only Cell, since " - "process/group {} has locked it for editing.\n", - nbrIndex, cellLockOwners_[nbrIndex]); - return false; - } - } - - // All good - add to our list - readOnlyCells.insert(&nbr.cell); - } - } - - // If we reach this point, we can lock all the necessary Cells for editing, and mark all those necessary for reading. - - // Add primary and secondary lock Cells to our list, sanity checking along the way - for (const auto *cell : primaryCells) - { - auto cellIndex = cell->index(); - - // Set lock index - if ((cellLockOwners_[cellIndex] == processOrGroup) || (cellLockOwners_[cellIndex] == -1)) - { - lockedCells_[processOrGroup].insert(primaryCell); - cellLockOwners_[cellIndex] = processOrGroup; - cellStatusFlags_[cellIndex] = CellStatusFlag::LockedForEditing; - } - else - return Messenger::error("Tried to lock a (primary) Cell which is already locked by someone else.\n"); - } - - // For the read-only Cells, we just need to set relevant ownership in the cellLockOwners_ array - for (const auto &readOnlyCell : readOnlyCells) - { - auto cellIndex = readOnlyCell->index(); - - // Check status - if (cellStatusFlags_[cellIndex] == CellStatusFlag::LockedForEditing) - { - if (cellLockOwners_[cellIndex] == processOrGroup) - continue; - else - return Messenger::error("Tried to mark a Cell for reading that is locked.\n"); - } - else if (cellStatusFlags_[cellIndex] == CellStatusFlag::Unused) - { - // Not currently used, so mark it as being read by one process/group (us) and set its new status - cellStatusFlags_[cellIndex] = CellStatusFlag::ReadByOne; - cellLockOwners_[cellIndex] = processOrGroup; - } - else if (cellStatusFlags_[cellIndex] == CellStatusFlag::ReadByOne) - { - // If the Cell is currently being read, but not by us, change the status to read-by-many - if (cellLockOwners_[cellIndex] != processOrGroup) - { - cellStatusFlags_[cellIndex] = CellStatusFlag::ReadByMany; - cellLockOwners_[cellIndex] = -1; - } - } - else if (cellStatusFlags_[cellIndex] == CellStatusFlag::ReadByMany) - { - // Already being read by more than one processs/group, so nothing more to do - } - } - - return true; -} - -// Try to assign a Molecule from the specified Cell to the process/group -std::shared_ptr RegionalDistributor::assignMolecule(const Cell *cell, int processOrGroup) -{ - // TODO May be beneficial to do this by size order (nAtoms in molecules)? - - if (debugDistributor) - Messenger::print(" Looking through molecules in Cell {} for process/group {}..\n", cell->index(), processOrGroup); - - // There will likely be multiple atoms from the same, so note each Molecule as we check it - std::vector> checkedMolecules; - - // Loop over Atoms in Cell - std::shared_ptr mol; - for (auto &atom : cell->atoms()) - { - // Get the Atom's Molecule pointer - mol = atom->molecule(); - - if (debugDistributor) - Messenger::print( - " <> Molecule index is {} and this molecule {} already in our list..\n", mol->arrayIndex(), - std::find(checkedMolecules.begin(), checkedMolecules.end(), mol) != checkedMolecules.end() ? "IS" : "IS NOT"); - - // Have we already checked this Molecule? - if (std::find(checkedMolecules.begin(), checkedMolecules.end(), mol) != checkedMolecules.end()) - continue; - - // Try to assign this Molecule to the present process/group - if (assignMolecule(mol, processOrGroup)) - return mol; - - // Not possible to assign the Molecule, so add it to our list of checked Molecules and move on - checkedMolecules.emplace_back(mol); - } - - return nullptr; -} - -// Try to find a Molecule target for the process/group -std::shared_ptr RegionalDistributor::assignMolecule(int processOrGroup) -{ - /* - * For this process/group, look at its current list of locked Cells, and search for a suitable Molecule within those. - * If there are no suitable Molecules (or there are no Cells, as is the case at the beginning), pick a suitable Cell - * close to those already in the list (or one at a suitable starting location for the current process/group). - */ - std::shared_ptr molecule = nullptr; - - for (auto *cell : lockedCells_[processOrGroup]) - { - if (debugDistributor) - Messenger::print(" Searching for suitable Molecule to assign to process/group {} from Cell index {} " - "(already locked by this process/group)...\n", - processOrGroup, cell->index()); - - // Try to assign a Molecule from those (partially) present in this Cell - molecule = assignMolecule(cell, processOrGroup); - - // If we have found a suitable Molecule for assignment, return it now - if (molecule) - return molecule; - } - - if (debugDistributor) - Messenger::print(" No Molecules available in locked cells for this process/group.\n"); - - /* - * If we did *not* find a suitable Molecule in the current list of locked Cells for this process/group, we need to get a - * new Cell. If there are Cells in the locked list, find one that is ReadByOne and assigned to this process, and search - * from there. If we fail, or there are zero Cells in the locked list, then try to add a Cell at a suitable 'distance' - * along the Cell Array for this process/group. - */ - int cellIndex; - if (lockedCells_[processOrGroup].size() > 0) - { - // Loop over all Cells, searching for one which this process/group alone has marked read-only - for (cellIndex = 0; cellIndex < cellArray_.nCells(); ++cellIndex) - { - if (debugDistributor) - Messenger::print(" Searching for suitable Molecule to assign to process/group {} from Cell " - "index {} (lock owner = {}, status == {})...\n", - processOrGroup, cellIndex, cellLockOwners_[cellIndex], - cellStatusFlag(cellStatusFlags_[cellIndex])); - - if (cellStatusFlags_[cellIndex] != CellStatusFlag::ReadByOne) - continue; - if (cellLockOwners_[cellIndex] != processOrGroup) - continue; - - // Found a Cell we have marked as read-only - does a suitable Molecule exist therein - molecule = assignMolecule(cellArray_.cell(cellIndex), processOrGroup); - if (molecule) - return molecule; - } - } - - // No suitable Molecule yet, so start searching over all Cells from a suitable point along the array. - for (auto n = 0; n < cellArray_.nCells(); ++n) - { - // Determine Cell index - cellIndex = n; - - if (debugDistributor) - Messenger::print(" -- Checking Cell {} for process/group {}: status = {}\n", cellIndex, processOrGroup, - cellStatusFlag(cellStatusFlags_[cellIndex])); - - if (cellStatusFlags_[cellIndex] != CellStatusFlag::Unused) - continue; - - // Found an unused cell - does a suitable Molecule exist therein? - molecule = assignMolecule(cellArray_.cell(cellIndex), processOrGroup); - if (molecule) - return molecule; - } - - return nullptr; -} - -// Set target molecules for the distributor -void RegionalDistributor::setTargetMolecules(const std::vector &targetMoleculeIndices) -{ - std::fill(moleculeStatus_.begin(), moleculeStatus_.end(), MoleculeStatusFlag::Completed); - for (auto id : targetMoleculeIndices) - moleculeStatus_[id] = MoleculeStatusFlag::ToDo; - nMoleculesToDistribute_ = targetMoleculeIndices.size(); - nMoleculesDistributed_ = 0; -} - -// Return next set of Molecule IDs assigned to this process -std::vector &RegionalDistributor::assignedMolecules() { return assignedMolecules_[processOrGroupIndex_]; } diff --git a/src/classes/regionalDistributor.h b/src/classes/regionalDistributor.h deleted file mode 100644 index f595c662c6..0000000000 --- a/src/classes/regionalDistributor.h +++ /dev/null @@ -1,102 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-or-later -// Copyright (c) 2026 Team Dissolve and contributors - -#pragma once - -#include "classes/cellArray.h" -#include -#include -#include -#include - -// Forward Declarations -class Molecule; - -// Regional Distributor -class RegionalDistributor -{ - public: - RegionalDistributor(const int nMolecules, const CellArray &cellArray); - ~RegionalDistributor() = default; - // Molecule Status Flag - enum class MoleculeStatusFlag - { - ToDo, - Assigned, - Completed - }; - // Return string for specified MoleculeStatusFlag - std::string_view moleculeStatusFlag(MoleculeStatusFlag flag); - // Cell Status Flag - enum class CellStatusFlag - { - Unused, - LockedForEditing, - ReadByOne, - ReadByMany - }; - // Return string for specified CellStatusFlag - std::string_view cellStatusFlag(CellStatusFlag flag); - - /* - * Core - */ - private: - // Number of processes / groups we are dealing with each time - int nProcessesOrGroups_; - // Our process / group index (assigned differently to each process / group of processes) - int processOrGroupIndex_; - // Number of cycles the distributor has been run for - int nCycles_; - - public: - // Set up next distribution of Molecules amongst processes/groups, returning false if there are no more Molecules to - // distribute - bool cycle(); - - /* - * Cell Data - */ - private: - // Source CellArray - const CellArray &cellArray_; - // Lists of Cells locked by each process/group - std::vector> lockedCells_; - // Cell process/group owners - std::vector cellLockOwners_; - // Cell status flags - std::vector cellStatusFlags_; - - private: - // Return whether the specified processOrGroup can lock the given Cell index - bool canLockCellForEditing(int processOrGroup, int cellIndex); - - /* - * Molecule Data - */ - private: - // Total number of molecules in the system - int nMolecules_; - // Number of Molecules to distribute - int nMoleculesToDistribute_; - // Counter for distributed Molecules - int nMoleculesDistributed_; - // Molecule status array - std::vector moleculeStatus_; - // Arrays of Molecule IDs assigned to each process / group - std::vector> assignedMolecules_; - - private: - // Assign Molecule to process/group if possible - bool assignMolecule(const std::shared_ptr &mol, int processOrGroup); - // Try to assign a Molecule from the specified Cell to the process/group - std::shared_ptr assignMolecule(const Cell *cell, int processOrGroup); - // Try to find a Molecule target for the process/group - std::shared_ptr assignMolecule(int processOrGroup); - - public: - // Set target molecules for the distributor - void setTargetMolecules(const std::vector &targetMoleculeIndices); - // Return next set of Molecule IDs assigned to this process - std::vector &assignedMolecules(); -}; From 03050fa039647ea82e37421d6de76615db53f09e Mon Sep 17 00:00:00 2001 From: Tristan Youngs Date: Sun, 14 Jun 2026 18:52:25 +0100 Subject: [PATCH 2/3] Remove ChangeStore and ChangeData. --- src/classes/CMakeLists.txt | 4 - src/classes/changeData.cpp | 59 --------------- src/classes/changeData.h | 47 ------------ src/classes/changeStore.cpp | 106 --------------------------- src/classes/changeStore.h | 67 ----------------- src/classes/configuration_upkeep.cpp | 1 - 6 files changed, 284 deletions(-) delete mode 100644 src/classes/changeData.cpp delete mode 100644 src/classes/changeData.h delete mode 100644 src/classes/changeStore.cpp delete mode 100644 src/classes/changeStore.h diff --git a/src/classes/CMakeLists.txt b/src/classes/CMakeLists.txt index 980a8f4656..11f81e9a57 100644 --- a/src/classes/CMakeLists.txt +++ b/src/classes/CMakeLists.txt @@ -9,8 +9,6 @@ add_library( braggReflection.cpp cell.cpp cellArray.cpp - changeData.cpp - changeStore.cpp configuration.cpp configuration_box.cpp configuration_contents.cpp @@ -75,8 +73,6 @@ add_library( braggReflection.h cell.h cellArray.h - changeData.h - changeStore.h configuration.h configurationAtom.cpp coreData.h diff --git a/src/classes/changeData.cpp b/src/classes/changeData.cpp deleted file mode 100644 index abe331ae38..0000000000 --- a/src/classes/changeData.cpp +++ /dev/null @@ -1,59 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-or-later -// Copyright (c) 2026 Team Dissolve and contributors - -#include "classes/changeData.h" -#include "base/messenger.h" -#include "classes/cell.h" -#include "classes/configurationAtom.h" -#include - -ChangeData::ChangeData() : atom_(nullptr) {} - -/* - * Target Data - */ - -// Set target atom -void ChangeData::setAtom(ConfigurationAtom *i) -{ - assert(i != nullptr); - - atom_ = i; - moved_ = false; - r_ = atom_->r(); - cell_ = i->cell(); -} - -// Return target Atom -ConfigurationAtom *ChangeData::atom() { return atom_; } - -// Return array index of stored Atom -int ChangeData::atomArrayIndex() const { return atom_->index(); } - -// Update local position, and flag as moved -void ChangeData::updatePosition() -{ - r_ = atom_->r(); - cell_ = atom_->cell(); - moved_ = true; -} - -// Revert atom to stored position -void ChangeData::revertPosition() -{ - // Set stored position - atom_->setR(r_); - - // If the cell changed with the move, revert that too - if (cell_ != atom_->cell()) - { - atom_->cell()->removeAtom(atom_); - cell_->addAtom(atom_); - } -} - -// Return whether atom has moved -bool ChangeData::hasMoved() { return moved_; } - -// Return position vector -Vector3 ChangeData::r() const { return r_; } diff --git a/src/classes/changeData.h b/src/classes/changeData.h deleted file mode 100644 index f2d3a68677..0000000000 --- a/src/classes/changeData.h +++ /dev/null @@ -1,47 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-or-later -// Copyright (c) 2026 Team Dissolve and contributors - -#pragma once - -#include "math/vector3.h" - -// Forward Declarations -class ConfigurationAtom; -class Cell; - -// Change Data -class ChangeData -{ - public: - ChangeData(); - ~ChangeData() = default; - - /* - * Target Data - */ - private: - // Atom - ConfigurationAtom *atom_; - // Flag indicating whether Atom has moved - bool moved_{false}; - // Stored coordinates of Atom - Vector3 r_; - // Stored Cell of Atom - Cell *cell_{nullptr}; - - public: - // Set target Atom - void setAtom(ConfigurationAtom *i); - // Return target Atom - ConfigurationAtom *atom(); - // Return array index of stored Atom - int atomArrayIndex() const; - // Update stored position, and flag as moved - void updatePosition(); - // Revert Atom to stored position - void revertPosition(); - // Return whether Atom has moved - bool hasMoved(); - // Return position vector - Vector3 r() const; -}; diff --git a/src/classes/changeStore.cpp b/src/classes/changeStore.cpp deleted file mode 100644 index 60d33de356..0000000000 --- a/src/classes/changeStore.cpp +++ /dev/null @@ -1,106 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-or-later -// Copyright (c) 2026 Team Dissolve and contributors - -#include "classes/changeStore.h" -#include "classes/cell.h" -#include "classes/configuration.h" -#include "classes/configurationAtom.h" -#include "classes/molecule.h" -#include -#include - -ChangeStore::ChangeStore() {} - -/* - * Watch Targets - */ - -// Add atom to watch -void ChangeStore::add(ConfigurationAtom *i) -{ - targetAtoms_.emplace_back(); - targetAtoms_.back().setAtom(std::move(i)); -} - -// Add Molecule to watch -void ChangeStore::add(const std::shared_ptr &mol) -{ - for (auto *atom : mol->atoms()) - add(atom); -} - -// Add Cell to watch -void ChangeStore::add(Cell *cell) -{ - for (auto &atom : cell->atoms()) - add(atom); -} - -/* - * Change Array - */ - -// Reset ChangeStore -void ChangeStore::reset() -{ - targetAtoms_.clear(); - changes_.clear(); -} - -// Update all Atom positions -void ChangeStore::updateAll() -{ - std::for_each(targetAtoms_.begin(), targetAtoms_.end(), [](auto &item) { item.updatePosition(); }); -} - -// Update single atom position -void ChangeStore::updateAtom(int id) -{ - assert(id >= 0 && id < targetAtoms_.size()); - targetAtoms_[id].updatePosition(); -} - -// Revert all atoms to their previous positions -void ChangeStore::revertAll() -{ - for (auto &item : targetAtoms_) - // revertPosition can make alterations to the cell that - // contains the item, so it cannot be safely run in parallel. - item.revertPosition(); -} - -// Revert specified index to stored position -void ChangeStore::revert(int id) -{ - assert(id >= 0 && id < targetAtoms_.size()); - targetAtoms_[id].revertPosition(); -} - -// Save Atom changes for broadcast, and reset arrays for new data -void ChangeStore::storeAndReset() -{ - for (auto item = targetAtoms_.begin(); item < targetAtoms_.end(); ++item) - { - // Has the position of this Atom been changed (i.e. updated)? - if (item->hasMoved()) - { - changes_.push_back(*item); - } - } - - // Clear target Atom data - targetAtoms_.clear(); -} - -// Apply changes -bool ChangeStore::apply(Configuration *cfg) -{ - for (auto &data : changes_) - { - // Set new coordinates and check cell position (Configuration::updateAtomInCell() will do all this) - data.revertPosition(); - cfg->updateAtomLocation(data.atom()); - } - - return true; -} diff --git a/src/classes/changeStore.h b/src/classes/changeStore.h deleted file mode 100644 index b4f4adf22a..0000000000 --- a/src/classes/changeStore.h +++ /dev/null @@ -1,67 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-or-later -// Copyright (c) 2026 Team Dissolve and contributors - -#pragma once - -#include "classes/changeData.h" -#include "templates/optionalRef.h" -#include -#include - -// Forward Declarations -class ConfigurationAtom; -class Cell; -class Molecule; -class Configuration; -class ProcessPool; -class Timer; - -// ChangeStore -class ChangeStore -{ - public: - ChangeStore(); - ~ChangeStore() = default; - - /* - * Watch Targets - */ - private: - // List of target atoms (and modification data) - std::vector targetAtoms_; - - public: - // Add atom to watch - void add(ConfigurationAtom *i); - // Add molecule to watch - void add(const std::shared_ptr &mol); - // Add cell to watch - void add(Cell *cell); - - /* - * Change Data - */ - private: - // List of local changes - std::vector changes_; - // Coordinate broadcast arrays - std::vector x_, y_, z_; - // Index broadcast array - std::vector indices_; - - public: - // Reset ChangeStore, forgetting all changes - void reset(); - // Update all Atom positions - void updateAll(); - // Update single atom position - void updateAtom(int id); - // Revert all atoms to stored positions - void revertAll(); - // Revert specified index to stored position - void revert(int id); - // Save Atom changes for broadcast, and reset arrays for new data - void storeAndReset(); - // Apply change data - bool apply(Configuration *cfg); -}; diff --git a/src/classes/configuration_upkeep.cpp b/src/classes/configuration_upkeep.cpp index 9f58566d6a..d20f4332c6 100644 --- a/src/classes/configuration_upkeep.cpp +++ b/src/classes/configuration_upkeep.cpp @@ -3,7 +3,6 @@ #include "classes/box.h" #include "classes/cell.h" -#include "classes/changeStore.h" #include "classes/configurationAtom.h" #include "main/dissolve.h" From e2fbaa5830d068596fd423abe61e4d9f22795fa9 Mon Sep 17 00:00:00 2001 From: Tristan Youngs Date: Sun, 14 Jun 2026 18:54:16 +0100 Subject: [PATCH 3/3] Remove DataSource. --- src/classes/CMakeLists.txt | 1 - src/classes/dataSource.h | 232 -------------------------------- src/keywords/CMakeLists.txt | 3 - src/keywords/dataSource.h | 222 ------------------------------ src/keywords/dataSourceBase.cpp | 3 - src/keywords/dataSourceBase.h | 19 --- 6 files changed, 480 deletions(-) delete mode 100644 src/classes/dataSource.h delete mode 100644 src/keywords/dataSource.h delete mode 100644 src/keywords/dataSourceBase.cpp delete mode 100644 src/keywords/dataSourceBase.h diff --git a/src/classes/CMakeLists.txt b/src/classes/CMakeLists.txt index 11f81e9a57..dd3c99d74d 100644 --- a/src/classes/CMakeLists.txt +++ b/src/classes/CMakeLists.txt @@ -76,7 +76,6 @@ add_library( configuration.h configurationAtom.cpp coreData.h - dataSource.h empiricalFormula.h fragment.h histogramSet.h diff --git a/src/classes/dataSource.h b/src/classes/dataSource.h deleted file mode 100644 index cbb5c6df17..0000000000 --- a/src/classes/dataSource.h +++ /dev/null @@ -1,232 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-or-later -// Copyright (c) 2026 Team Dissolve and contributors - -#pragma once - -#include "base/serialiser.h" -#include "io/fileAndFormat.h" -#include "items/list.h" -#include "math/data1D.h" -#include "math/data2D.h" -#include "math/data3D.h" -#include "math/sampledData1D.h" - -// Template arguments: data class (Data1D, Data2D ...) -template class DataSource : public Serialisable -{ - - public: - DataSource() = default; - ~DataSource() = default; - - public: - // Types of data sources allowed - enum DataSourceType - { - Internal, - External - }; - - public: - // Return enum options for DataSourceType - static EnumOptions dataSourceTypes() - { - return EnumOptions("DataSourceType", {{Internal, "Internal"}, {External, "External"}}); - } - // Return data source type enum - DataSourceType dataSourceType() const { return dataSourceType_; } - - /* - * Data - */ - - private: - // Name of data (tag or filename) - std::string dataName_; - // Type of data source being stored - DataSourceType dataSourceType_; - // String to hold internal data tag (if internal) - std::string internalDataSource_; - // Formatter object - typename DataType::Formatter externalDataSource_; - // Data object stored - DataType data_; - - public: - // Return data name - std::string_view dataName() const { return dataName_; } - // Return if data exists and has been initialised - bool dataExists() const - { - return (!internalDataSource_.empty() && dataSourceType_ == Internal) || - (externalDataSource_.hasFilename() && dataSourceType_ == External); - } - - // Changes data name to full filepath if data is external - void updateNameToPath() - { - if (dataSourceType_ == External) - { - dataName_ = externalDataSource_.filename(); - } - } - - std::string_view getFilepath() { return dataSourceType_ == External ? externalDataSource_.filename() : ""; } - - // Obtain data from the relevant source - bool sourceData(GenericList &processingModuleData) - { - if (!dataExists()) - { - return false; - } - if (dataSourceType_ == Internal) - { - // Locate target data from tag and cast to base - auto optData = processingModuleData.search(internalDataSource_); - if (!optData) - { - return Messenger::error("No data with tag '{}' exists.\n", internalDataSource_); - } - // Set data - data_ = optData->get(); - - return true; - } - else if (dataSourceType_ == External) - { - // For external datatypes, import the data - if (!externalDataSource_.importData(data_)) - { - return Messenger::error("Error importing data from '{}'", externalDataSource_.filename()); - } - - return true; - } - - return false; - } - - // Return the data - const DataType &data() const { return data_; } - - /* - * Serialisation - */ - public: - bool deserialise(LineParser &parser, int startArg, const CoreData &coreData) - { - if (!DataSource::dataSourceTypes().isValid(parser.argsv(0))) - { - return dataSourceTypes().errorAndPrintValid(parser.argsv(0)); - } - - // If data is internal - if (dataSourceTypes().enumeration(parser.argsv(startArg)) == Internal) - { - // Add data to dataSource - dataSourceType_ = Internal; - internalDataSource_ = parser.argsv(startArg + 1); - // Set data name to be data tag - dataName_ = internalDataSource_; - return true; - } - // If data is external - else if (dataSourceTypes().enumeration(parser.argsv(startArg)) == External) - { - // Read the supplied arguments - auto readResult = externalDataSource_.read(parser, startArg + 1, - std::format("End{}", dataSourceTypes().keyword(External)), coreData); - if (readResult == FileAndFormat::ReadResult::UnrecognisedFormat || - readResult == FileAndFormat::ReadResult::UnrecognisedOption) - { - return Messenger::error("Failed to read file/format for '{}'.\n", parser.argsv(startArg + 2)); - } - else - { - dataSourceType_ = External; - // Set data name to be base filename - dataName_ = externalDataSource_.filename().substr(externalDataSource_.filename().find_last_of("/\\") + 1); - return true; - } - } - return false; - } - - void deserialise(const SerialisedValue &node, const CoreData &coreData) - { - auto dataSourceType = toml::find(node, "dataSourceType"); - if (dataSourceTypes().enumeration(dataSourceType) == Internal) - { - dataSourceType_ = Internal; - // Set data to be the tag - internalDataSource_ = toml::find(node, "source"); - // Set data name to be data tag - dataName_ = toml::find(node, "source"); - } - // If data source type is external - else if (dataSourceTypes().enumeration(dataSourceType) == External) - { - dataSourceType_ = External; - // Read the file and format - externalDataSource_.deserialise(node.at("source"), coreData); - // Set the data name as root filename - dataName_ = externalDataSource_.filename().substr(externalDataSource_.filename().find_last_of("/\\") + 1); - } - } - - // Write through specified LineParser - bool serialise(LineParser &parser, std::string_view keywordName, std::string_view prefix) const - { - // Write source: internal/external - if (!parser.writeLineF(" {}{}", prefix, dataSourceTypes().keyword(dataSourceType_))) - { - return false; - } - - // If data is internal - if (dataSourceType_ == Internal) - { - if (!parser.writeLineF(" '{}'\n", internalDataSource_)) - return false; - } - - else if (dataSourceType_ == External) - { - // Write filename and format - if (!externalDataSource_.writeFilenameAndFormat(parser, " ")) - { - return false; - } - - // Write extra keywords - if (!externalDataSource_.writeBlock(parser, std::format(" {}", prefix))) - { - return false; - } - - // End the block - if (!parser.writeLineF(" End{}\n", dataSourceTypes().keyword(External))) - { - return false; - } - - return true; - } - - return true; - } - // Express as a serialisable value - void serialise(std::string tag, SerialisedValue &target) const - { - if (dataSourceType_ == Internal) - { - target[tag] = {{"dataSourceType", dataSourceTypes().keyword(dataSourceType_)}, {"source", internalDataSource_}}; - } - else - { - target[tag] = {{"dataSourceType", dataSourceTypes().keyword(dataSourceType_)}}; - externalDataSource_.serialise("source", target[tag]); - } - } -}; diff --git a/src/keywords/CMakeLists.txt b/src/keywords/CMakeLists.txt index 8cd2f0d8d4..a4b7940b80 100644 --- a/src/keywords/CMakeLists.txt +++ b/src/keywords/CMakeLists.txt @@ -4,7 +4,6 @@ add_library( bool.cpp configuration.cpp configurationVector.cpp - dataSourceBase.cpp double.cpp elementVector.cpp expression.cpp @@ -35,8 +34,6 @@ add_library( bool.h configuration.h configurationVector.h - dataSource.h - dataSourceBase.h double.h elementVector.h enumOptions.h diff --git a/src/keywords/dataSource.h b/src/keywords/dataSource.h deleted file mode 100644 index 8b4ee22606..0000000000 --- a/src/keywords/dataSource.h +++ /dev/null @@ -1,222 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-or-later -// Copyright (c) 2026 Team Dissolve and contributors - -#pragma once - -#include "classes/dataSource.h" -#include "io/import/data1D.h" -#include "io/import/data2D.h" -#include "io/import/data3D.h" -#include "keywords/dataSourceBase.h" -#include "math/data1D.h" -#include "math/data2D.h" -#include "math/data3D.h" -#include "templates/optionalRef.h" -#include - -// Keyword managing data sources -// Template arguments: data class (Data1D, Data2D ...) -template class DataSourceKeyword : public DataSourceKeywordBase -{ - // Typedef - public: - using DataPair = std::pair>, std::shared_ptr>>; - - public: - DataSourceKeyword(std::vector &dataSources, std::string_view endKeyword) - : DataSourceKeywordBase(), dataSources_(dataSources), endKeyword_(endKeyword) - { - } - ~DataSourceKeyword() override = default; - - /* - * Data - */ - private: - // Vector of data source pairs - std::vector &dataSources_; - // End keyword - const std::string endKeyword_; - // Gets path basename - std::string_view getBasename(std::string_view filename) const { return filename.substr(filename.find_last_of("/\\") + 1); } - - public: - // Return data source pairs - std::vector &dataSources() { return dataSources_; } - - /* - * Arguments - */ - public: - // Return minimum number of arguments accepted - int minArguments() const override { return 0; }; - // Return maximum number of arguments accepted - std::optional maxArguments() const override { return std::nullopt; }; - // Deserialise from supplied LineParser, starting at given argument offset - bool deserialise(LineParser &parser, int startArg, const CoreData &coreData) override - { - // Emplacing back on data vector and getting the reference to the objects - auto &[dataSourceA, dataSourceB] = - dataSources_.emplace_back(std::make_shared>(), std::make_shared>()); - // Create a queue for the dataSource objects - std::queue>> sourceQueue({dataSourceA, dataSourceB}); - - // Read the next line - if (parser.getArgsDelim(LineParser::Defaults) != LineParser::Success) - { - dataSources_.pop_back(); - return false; - } - - while (!parser.eofOrBlank()) - { - // Only allows maximum of two data sources per keyword - if (sourceQueue.empty()) - { - break; - } - // If data source type supplied is valid - if (!sourceQueue.front()->deserialise(parser, 0, coreData)) - { - // If not, print accepted options - dataSources_.pop_back(); - return false; - } - - // Check to make sure we don't have the same names - for (auto &[existingSourceA, existingSourceB] : dataSources_) - { - if (getBasename(existingSourceA->dataName()) == getBasename(sourceQueue.front()->dataName())) - { - if (existingSourceA->getFilepath() != sourceQueue.front()->getFilepath()) - { - existingSourceA->updateNameToPath(); - sourceQueue.front()->updateNameToPath(); - } - } - if (getBasename(existingSourceB->dataName()) == getBasename(sourceQueue.front()->dataName())) - { - if (existingSourceB->getFilepath() != sourceQueue.front()->getFilepath()) - { - existingSourceB->updateNameToPath(); - sourceQueue.front()->updateNameToPath(); - } - } - } - - sourceQueue.pop(); - - // Read the next line - if (parser.getArgsDelim() != LineParser::Success) - { - dataSources_.pop_back(); - return false; - } - - // Is this the end of the block? - if (DissolveSys::sameString(parser.argsv(0), endKeyword_)) - { - break; - } - } - - return true; - } - - // Serialise data to specified LineParser - bool serialise(LineParser &parser, std::string_view keywordName, std::string_view prefix) const override - { - for (auto &[dataSourceA, dataSourceB] : dataSources_) - { - // Write the keyword name - if (!parser.writeLineF("{}{}\n", prefix, keywordName)) - { - return false; - } - - // Serialise the first data source - if (!dataSourceA->serialise(parser, keywordName, prefix)) - { - return false; - } - - // Skip to next iteration if dataSourceB is undefined - if (!dataSourceB->dataExists()) - { - continue; - } - - // Serialise the second data source (optional) - if (!dataSourceB->serialise(parser, keywordName, prefix)) - { - return false; - } - - // Write end keyword - if (!parser.writeLineF("{}End{}\n", prefix, keywordName)) - { - return false; - } - } - - return true; - } - // Express as a serialisable value - void serialise(std::string tag, SerialisedValue &target) const override - { - target[tag] = fromVector(dataSources_, - [](const auto &item) -> SerialisedValue - { - auto &[dataSourceA, dataSourceB] = item; - SerialisedValue result; - dataSourceA->serialise("dataSourceA", result); - if (dataSourceB->dataExists()) - dataSourceB->serialise("dataSourceB", result); - return result; - }); - } - // Read values from a serialisable value - void deserialise(const SerialisedValue &node, const CoreData &coreData) override - { - toVector(node, - [this, &coreData](const auto &dataPair) - { - // Emplacing back on data vector and getting the reference to the objects - auto &[dataSourceA, dataSourceB] = dataSources_.emplace_back(std::make_shared>(), - std::make_shared>()); - // Create a queue for the dataSource objects - std::queue>> sourceQueue({dataSourceA, dataSourceB}); - - toMap(dataPair, - [this, &coreData, &sourceQueue](const auto &key, const auto &dataSource) - { - if (sourceQueue.empty()) - return; - // Add data to dataSource - sourceQueue.front()->deserialise(dataSource, coreData); - // Check to make sure we don't have the same names - for (auto &[existingSourceA, existingSourceB] : dataSources_) - { - if (getBasename(existingSourceA->dataName()) == getBasename(sourceQueue.front()->dataName())) - { - if (existingSourceA->getFilepath() != sourceQueue.front()->getFilepath()) - { - existingSourceA->updateNameToPath(); - sourceQueue.front()->updateNameToPath(); - } - } - if (getBasename(existingSourceB->dataName()) == getBasename(sourceQueue.front()->dataName())) - { - if (existingSourceB->getFilepath() != sourceQueue.front()->getFilepath()) - { - existingSourceB->updateNameToPath(); - sourceQueue.front()->updateNameToPath(); - } - } - } - // Remove dataSource from queue - sourceQueue.pop(); - }); - }); - } -}; diff --git a/src/keywords/dataSourceBase.cpp b/src/keywords/dataSourceBase.cpp deleted file mode 100644 index 191e76dbec..0000000000 --- a/src/keywords/dataSourceBase.cpp +++ /dev/null @@ -1,3 +0,0 @@ -#include "keywords/dataSourceBase.h" - -DataSourceKeywordBase::DataSourceKeywordBase() : KeywordBase(typeid(this)) {} \ No newline at end of file diff --git a/src/keywords/dataSourceBase.h b/src/keywords/dataSourceBase.h deleted file mode 100644 index 0f93f72ad7..0000000000 --- a/src/keywords/dataSourceBase.h +++ /dev/null @@ -1,19 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-or-later -// Copyright (c) 2026 Team Dissolve and contributors - -#pragma once - -#include "base/enumOptions.h" -#include "classes/dataSource.h" -#include "io/fileAndFormat.h" -#include "keywords/base.h" -#include "math/dataBase.h" - -// Base keyword for data source -class DataSourceKeywordBase : public KeywordBase -{ - - public: - DataSourceKeywordBase(); - ~DataSourceKeywordBase() override = default; -}; \ No newline at end of file