Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Layer system #709

Merged
merged 12 commits into from
Aug 10, 2021
4 changes: 4 additions & 0 deletions avogadro/core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ set(HEADERS
gaussianset.h
gaussiansettools.h
graph.h
layer.h
layermanager.h
matrix.h
mesh.h
molecule.h
Expand Down Expand Up @@ -66,6 +68,8 @@ set(SOURCES
gaussianset.cpp
gaussiansettools.cpp
graph.cpp
layer.cpp
layermanager.cpp
mesh.cpp
mdlvalence_p.h
molecule.cpp
Expand Down
74 changes: 70 additions & 4 deletions avogadro/core/connectedgroup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,16 @@ ConnectedGroup::ConnectedGroup(size_t n) : m_groupToNode(n)
resetToSize(n);
}

void ConnectedGroup::addGroup(size_t group)
{
for (auto& nodeGroup : m_nodeToGroup) {
if (nodeGroup.second >= group) {
++nodeGroup.second;
}
}
m_groupToNode.insert(m_groupToNode.begin() + group, std::set<size_t>());
}

ConnectedGroup::~ConnectedGroup() {}

void ConnectedGroup::addNode(size_t index)
Expand All @@ -37,6 +47,23 @@ void ConnectedGroup::addNode(size_t index)
}
}

void ConnectedGroup::addNode(size_t node, size_t group)
{
assert(group < m_groupToNode.size());
auto it = m_nodeToGroup.find(node);
// if node already exists, remove it
if (it == m_nodeToGroup.end()) {
m_nodeToGroup[node] = group;
m_groupToNode[group].insert(node);
} else {
auto old_group = m_nodeToGroup[node];
m_nodeToGroup[node] = group;

m_groupToNode[old_group].erase(node);
m_groupToNode[group].insert(node);
}
}

void ConnectedGroup::addNodes(size_t n)
{
size_t offset = m_nodeToGroup.size();
Expand All @@ -45,6 +72,14 @@ void ConnectedGroup::addNodes(size_t n)
}
}

void ConnectedGroup::addNodes(size_t n, size_t group)
{
size_t offset = m_nodeToGroup.size();
for (size_t i = 0; i < n; ++i) {
addNode(i + offset, group);
}
}

void ConnectedGroup::addConnection(size_t a, size_t b)
{
assert(m_nodeToGroup.find(a) != m_nodeToGroup.end());
Expand All @@ -64,10 +99,13 @@ void ConnectedGroup::addConnection(size_t a, size_t b)

void ConnectedGroup::removeNode(size_t index)
{
assert(m_nodeToGroup.find(index) != m_nodeToGroup.end());
removeConnection(index);
size_t group = m_nodeToGroup[index];
m_nodeToGroup.erase(group);
auto it = m_nodeToGroup.find(index);
if (it != m_nodeToGroup.end()) {
size_t group = it->second;
m_nodeToGroup.erase(it);
m_groupToNode[group].erase(index);
checkRemove(m_groupToNode);
}
}

void ConnectedGroup::removeConnections()
Expand Down Expand Up @@ -106,6 +144,24 @@ void ConnectedGroup::removeConnection(size_t a, size_t b,
checkRemove(m_groupToNode);
}

void ConnectedGroup::removeGroup(size_t group)
{
assert(group < m_nodeToGroup.size());
auto it = m_nodeToGroup.begin();
while (it != m_nodeToGroup.end()) {
if (it->second > group) {
--it->second;
++it;
} else if (it->second == group) {
it = m_nodeToGroup.erase(it);
} else {
++it;
}
}

m_groupToNode.erase(m_groupToNode.begin() + group);
}

void ConnectedGroup::clear()
{
m_nodeToGroup.clear();
Expand Down Expand Up @@ -142,10 +198,20 @@ size_t ConnectedGroup::groupCount() const
return m_groupToNode.size();
}

size_t ConnectedGroup::atomCount() const
{
return m_nodeToGroup.size();
}

size_t ConnectedGroup::getGroupSize(size_t node) const
{
return m_groupToNode.at(m_nodeToGroup.at(node)).size();
}

bool ConnectedGroup::hasAtom(size_t atom) const
{
return m_nodeToGroup.find(atom) != m_nodeToGroup.end();
}

} // namespace Core
} // namespace Avogadro
11 changes: 10 additions & 1 deletion avogadro/core/connectedgroup.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ namespace Avogadro {
namespace Core {

/**
* @class ConnectedGroup bimap.h <avogadro/core/graph.h>
* @class ConnectedGroup ConnectedGroup.h <avogadro/core/ConnectedGroup.h>
* @brief The ConnectedGroup class represents a bidirectional Map data structure
* between size_t (group) and a size_t set (nodes).
* @example graph.h where it computes the bonded atom sets
Expand All @@ -35,9 +35,11 @@ class AVOGADROCORE_EXPORT ConnectedGroup

/** check if @p index is already in a group otherwise create one for it */
void addNode(size_t index);
void addNode(size_t node, size_t group);

/** create @p n groups with 1 node each */
void addNodes(size_t n);
void addNodes(size_t n, size_t group);

/** node @p a and @p b will be in the same group */
void addConnection(size_t a, size_t b);
Expand All @@ -55,6 +57,10 @@ class AVOGADROCORE_EXPORT ConnectedGroup
* they don't */
void removeConnection(size_t a, size_t b, const std::set<size_t>& neighbors);

void removeGroup(size_t group);

void addGroup(size_t group);

/** Removes everything. */
void clear();

Expand All @@ -72,6 +78,9 @@ class AVOGADROCORE_EXPORT ConnectedGroup

/** @return the total groups existing */
size_t groupCount() const;
size_t atomCount() const;

bool hasAtom(size_t atom) const;

private:
std::map<size_t, size_t> m_nodeToGroup;
Expand Down
125 changes: 125 additions & 0 deletions avogadro/core/layer.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
/******************************************************************************
This source file is part of the Avogadro project.
This source code is released under the 3-Clause BSD License, (see "LICENSE").
******************************************************************************/

#include "layer.h"
#include <cassert>

namespace Avogadro {
namespace Core {

using std::swap;

Layer::Layer() : m_activeLayer(0), m_maxLayer(0) {}

void Layer::addAtom(size_t layer)
{
addAtom(layer, m_atomAndLayers.size());
}

void Layer::addAtom(size_t layer, Index atom)
{
assert(layer <= m_maxLayer);
if (atom == m_atomAndLayers.size()) {
m_atomAndLayers.push_back(layer);
} else if (atom > m_atomAndLayers.size()) {
m_atomAndLayers.resize(layer + 1, MaxIndex);
m_atomAndLayers[atom] = layer;
} else {
m_atomAndLayers[atom] = layer;
}
}

void Layer::addAtomToActiveLayer(Index atom)
{
addAtom(m_activeLayer, atom);
}

void Layer::setActiveLayer(size_t layer)
{
assert(layer <= m_maxLayer + 1);
m_activeLayer = layer;
}

void Layer::removeAtom(Index atom)
{
m_atomAndLayers.swapAndPop(atom);
}

void Layer::addLayer()
{
++m_maxLayer;
}

void Layer::addLayer(size_t layer)
{
assert(layer <= m_maxLayer + 1);
for (auto& atomLayer : m_atomAndLayers) {
if (atomLayer >= layer) {
++atomLayer;
}
}
++m_maxLayer;
}

size_t Layer::getLayerID(Index atom) const
{
if (atom >= m_atomAndLayers.size()) {
return MaxIndex;
} else {
return m_atomAndLayers[atom];
}
}

void Layer::clear()
{
m_atomAndLayers.clear();
m_activeLayer = m_maxLayer = 0;
}

size_t Layer::activeLayer() const
{
return m_activeLayer;
}

size_t Layer::maxLayer() const
ghutchis marked this conversation as resolved.
Show resolved Hide resolved
{
return m_maxLayer;
}

size_t Layer::atomCount() const
{
return m_atomAndLayers.size();
}

void Layer::removeLayer(size_t layer)
{
assert(layer <= m_maxLayer);
if (m_maxLayer >= 1) {
for (auto it = m_atomAndLayers.begin(); it != m_atomAndLayers.end();) {
if (*it == layer) {
it = m_atomAndLayers.erase(it);
} else {
if (*it > layer) {
--(*it);
}
++it;
}
}
--m_maxLayer;
}
}

void Layer::swapLayer(Index a, Index b)
{
swap(m_atomAndLayers[a], m_atomAndLayers[b]);
}

size_t Layer::layerCount() const
{
return m_maxLayer + 1;
}

} // namespace Core
} // namespace Avogadro
75 changes: 75 additions & 0 deletions avogadro/core/layer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/******************************************************************************
This source file is part of the Avogadro project.
This source code is released under the 3-Clause BSD License, (see "LICENSE").
******************************************************************************/

#ifndef AVOGADRO_CORE_LAYER_H
#define AVOGADRO_CORE_LAYER_H

#include "avogadrocore.h"

#include <avogadro/core/array.h>
#include <avogadro/core/connectedgroup.h>

namespace Avogadro {
namespace Core {

/**
* @class Layer layer.h <avogadro/core/layer.h>
* @brief The Layer class represents a relation one to one between atoms ID
* and layer ID, and stores the unique active layer.
* Layer's ID are consecutively and there can't be a ID bigger than @p
* m_maxLayer.
*/
class AVOGADROCORE_EXPORT Layer
ghutchis marked this conversation as resolved.
Show resolved Hide resolved
{
public:
Layer();

// att atom to param layer
void addAtom(size_t layer);
void addAtom(size_t layer, Index atom);
void addAtomToActiveLayer(Index atom);
void removeAtom(Index atom);
void removeLayer(size_t layer);

/** @return the layer ID from the @p atom. */
size_t getLayerID(Index atom) const;
/** @return the active Layer. */
size_t activeLayer() const;

/** @return the maximum layer allowed. */
size_t maxLayer() const;

/** @return the number of layers. */
size_t layerCount() const;

/** @return The number of atoms. */
size_t atomCount() const;

/** remove all IDs. */
void clear();

/** increase the maximum layer allowed .*/
void addLayer();

/** insert a layer at @p layer, equal or bigger previous layers will be
* shifted. */
void addLayer(size_t layer);

/** change @p m_activeLayer. */
void setActiveLayer(size_t layer);

/** swap the layer ID from @p a and @p b. */
void swapLayer(Index a, Index b);

private:
Core::Array<size_t> m_atomAndLayers;
size_t m_activeLayer;
size_t m_maxLayer;
};

} // namespace Core
} // namespace Avogadro

#endif
Loading