One thing I forgot to add yesterday: It actually shouldn’t be necessary to use the Voronoi bond information to find Voronoi faces that separate particle pairs of different types. Each Voronoi face is already associated with the two particles it separates through their Region
and Adjacent Cell
properties, which essentially are the particle indices. You can use those to look up their respective particle types.
Say you want to find all Voronoi faces separating particle pairs of type 1 and 2. Then, the following modifier function will do the job as long as you do not delete any particles or Voronoi cells in a previous step in your pipeline.
def modify(frame: int, data: DataCollection, type1 = 1, type2 = 2):
mesh = data.surfaces['voronoi-polyhedra_']
ptypes = data.particles['Particle Type']
sel = mesh.faces_.create_property("Selection", data = numpy.zeros(mesh.faces.count))
A = ptypes[mesh.faces["Region"]]
B = ptypes[mesh.faces["Adjacent Cell"]]
sel[:] = numpy.logical_not(numpy.logical_and(A == type1, B == type2))
mesh.delete_faces( mesh.faces['Selection'] == 1)
Note that for each particle pair (or Voronoi bond for that matter), you will have two faces listed in the surface mesh face property container, i.e., each face has an “opposite face” with the same vertices (belonging to the neighboring Voronoi cell). To find “both sides”, so to say, you could do:
numpy.logical_or( numpy.logical_and(A == type1, B == type2) , numpy.logical_and(A == type2, B == type1) )
Lastly, I’m not sure if you are trying to use this to calculate interface areas.
https://matsci.org/t/cluster-surface-area/54867
You can add up the surface areas of the remaining faces like this: numpy.sum(mesh.faces["Area"])
, but I would take that number with a grain of salt. The “interface” in the picture above, for example, looks quite rugged, so it’s likely that you’re overestimating the actual interface area you’re trying to find - or surface area of crystallites, like you mentioned in the other thread. Just something to keep in mind.