SurfaceMesh.locate_point() for all data.particles.positions

I try to create a new particle property that shows the spatial region containing the particle:

from import *
from ovito.modifiers import ConstructSurfaceModifier

def modify(frame: int, data: DataCollection):
data.particles_.create_property(‘Inside’, data=region)

data.particles.region[0] = SurfaceMesh.locate_point(data.particles.positions[0], 0.0)

resulting in
TypeError: locate_point(): incompatible function arguments. The following argument types are supported:
1. (self:, pos: Point3, eps: float = 1e-06) → object

Can someone help with the syntax?

The locate_point() method must be called on an instance of the SurfaceMesh class, not on the SurfaceMesh itself. If the ConstructSurfaceModifier was used to generate the surface mesh, you first have to retrieve it from the DataCollection, and then you can use the locate_point() method:

surface_mesh = data.surfaces["surface"]
region = surface_mesh.locate_point(data.particles.positions[0], 0.0)

Then, to store the determined region id in a new particle property:

region_property = data.particles_.create_property("Inside", dtype=int, components=1)
region_property[0] = region

Thank you very much,
this works but takes a lot of time:
surface_mesh = data.surfaces[“surface”]
region_property = data.particles_.create_property(“Region”, dtype=int, components=1)
for i in range(data.particles.count):
region = surface_mesh.locate_point(data.particles.positions[i], 0.0)
region_property[i] = region
for 1.5 million particles it takes about 3 minutes on my office pc. The average particle-count in my systems is about 15 million and I need to evaluate a few hundred systems. Is there a faster method?

Yes, this approach can quickly become very expensive for large systems. The algorithmic complexity of the SurfaceMesh.locate_point() method grows linearly with the number of faces and vertices in the surface mesh.

Could you please describe your goal in some more detail?

In principle, it would be possible to extend the capabilities of the ConstructSurfaceModifier and let it compute each atom’s association with a volumetric region. Doing this during the surface construction process would be much cheaper (assuming you are using the alpha-shape method and not the Gaussian density method). One question would be, however, what to do with surface atoms that form the vertices of the surface. An atom may be part of more than one surface manifold, which means that there is an ambiguity as to which region such an atom should be attributed to by the algorithm. Some tie-breaker rule will be needed to resolve this ambiguity if we require that an atom may only be part of one region.

The intermediate goal is to calculate volumefractions of explicit solvent beads and polymerbeads for spherical microgels(bead-spring model). To construct the surface mesh I use the alpha shape method applied on the selection of the polymerbead fraction.The total number of solvent beads/ polymer beads located inside the filled region is sufficent to reach this intermediate goal but for more elaborate calculations of structural properties in the later stage of the project the additional property type “region” is needed. The surface atoms that form the vertices of the surface are part of the polymer- networkstructure, so for my purposes these surface particles belong to the filled region. Adding the new region property as optional feature to the surface construction process would be really great. Even if I calculate the volumefractions of all my systems with some pythonscripts running in parallel the process of constructing pipelines in OVITO for more advanced calculations relies on this slow python script modifier and every time the pipeline gets reevaluated I have to make a half hour coffee break.

Here is a snapshot of a sliced system. In green the surface mesh, inside a fraction of (red) polymerbeads and a fraction of (blue) solvent beads.

Hmm. The fast and simple extension to the alpha-shape algorithm I had in mind has the following limitation: It can only determine the region of particles that are part of the input point set of the surface construction algorithm. In your case, however, the blue solvent beads are not part of the input set.

I will think about more sophisticated strategies that are able to classify particles which not part of the input set efficiently. Would you mind sharing one of your simulation snapshots with me? That would give me a good test case, which I can use during development. Thank you.

I’ve extended the alpha-shape algorithm to directly attribute particles to the spatial regions separated by the surface mesh. Please give it a try. This approach should be fast enough to classify even a large number of solvent beads as being either inside or outside of the closed surface.

In Python scripts, the new option is enabled by the ConstructSurfaceModifier.map_particles_to_regions flag. New builds of OVITO Pro and the ovito Python module providing the new option are available here:

1 Like

This works great for me and it is so much faster. Thank you very much.