I'm trying to develop a data structure for a mesh using the MATLAB OOP functionalities. Long story short, I'm modifying a field from an instance that inherits from the same base class as another instance, and both instances are being modified, as if the field was declared static!
I have this code inside an abstract base class (m_element) in MATLAB:
properties(Access = protected)
nodes = containers.Map('KeyType','int64', 'ValueType', 'any');
faces = containers.Map('KeyType','int64', 'ValueType', 'any');
end
These field represent the connectivity of each element. For example, which nodes are neighbors of the n'th node, or which faces are adjacent to the n'th node.
I also have two other classes: m_face and m_node, each one inheriting from m_element. m_node is very simple:
classdef m_node < m_element
properties
x = 0;
y = 0;
z = 0;
end
methods
function node = m_node(gmsh_id, x, y, z)
node = node@m_element(gmsh_id);
node.x = x;
node.y = y;
node.z = z;
end
end
end
But when it comes to m_face, I'm facing an issue. Here's the constructor, where the problem is arising:
function face = m_face(varargin)
face = face@m_element(varargin{1});
for k = 2:nargin
nod = varargin{k};
if(~isa(nod, 'm_node'))
error('Algum dos argumentos não é um node!');
elseif (~isvalid(nod))
error('Algum dos argumentos não é válido!');
else
face.nodes(nod.gmsh_id) = nod;
nod.faces(face.gmsh_id) = face;
end
end
end
The m_face constructor expects the face ID to come as the first argument, and the rest should be the nodes that forms the face. The line face.nodes(nod.gmsh_id) = nod;
seems to be causing my problem. I have a m_mesh class which shall hold every node and face:
classdef m_mesh < handle
properties(SetAccess = private)
nodes = containers.Map('KeyType','int64', 'ValueType', 'any');
faces = containers.Map('KeyType','int64', 'ValueType', 'any');
end
methods
function theMesh = m_mesh(msh)
for idx = 1:numel(msh.POS(:,1))
n = msh.POS(idx,:);
theMesh.nodes(idx) = m_node(idx, n(1), n(2), n(3));
end
for idx = 1:numel(msh.TRIANGLES(:,1))
ele = msh.TRIANGLES(idx,:);
nod(1) = theMesh.nodes(ele(1));
nod(2) = theMesh.nodes(ele(2));
nod(3) = theMesh.nodes(ele(3));
theMesh.faces(idx) = m_face(idx, nod(1), nod(2), nod(3));
end
end
end
end
The msh
argument to the constructor holds the nodes spatial positions, and also the nodes that composes each face (which in this case are triangles).
Here's what I get when I build the mesh:
>> mesh = m_mesh(m)
mesh =
m_mesh with properties:
nodes: [5x1 containers.Map]
edges: [0x1 containers.Map]
faces: [4x1 containers.Map]
>> nod = mesh.nodes.values();
>> nod{1}.i_nodes
ans =
[1x1 m_node] [1x1 m_node] [1x1 m_node] [1x1 m_node] [1x1 m_node]
The i_nodes returns the instance map values. Now, how's that possible? Why does my first (and all the others!) node have FIVE adjacent nodes, if I haven't set this yet? Why should MATLAB change an non-static field for all instances and all subclasses when I access this field from a random instance?