Slicing atoms (and calculating surface area) in each frame of a trajectory

Quote from Gonzalo García Vidable on August 20, 2019, 11:00 pmHi.
I have a series of simulation dumps with an indentation experiment I am performing. I am interested in calculating the area of the contact surface between the sample and the indenter. My idea was to use the Slice modifier to keep just the atoms at indenter height and then make the Construct Surface Mesh modifier calculate the surface of this layer of atoms. I can perform this individually on each frame, but as I got quite a few of them, it was my intention to load the whole trajectory with the import_file("simulation.dump.*") feature. Then I figured I could put the setting up of modifiers for my pipeline inside the for loop so as to update the height of the slice for each frame to keep track of the indenter. I read the warning in the manual about repeating modifiers in the list, I thought I could by pass that, by ending my for statement with the clear() method for lists on the modifier list.
The result: no error message whatsoever, script won't go pass frame 0. By commenting and uncommenting I found out the script stops going through the loop when and only when I apply compute method inside it (which of course is absolutely necessary).
I've changed my approach (instead "slicing" via numpy array subsetting) because I became convinced that I can't update my modifiers inside the for loop and that the spirit of the law here is that only compute statements must go inside it. But I need confirmation: Can it or can't it be done in this way?
Hi.
I have a series of simulation dumps with an indentation experiment I am performing. I am interested in calculating the area of the contact surface between the sample and the indenter. My idea was to use the Slice modifier to keep just the atoms at indenter height and then make the Construct Surface Mesh modifier calculate the surface of this layer of atoms. I can perform this individually on each frame, but as I got quite a few of them, it was my intention to load the whole trajectory with the import_file("simulation.dump.*") feature. Then I figured I could put the setting up of modifiers for my pipeline inside the for loop so as to update the height of the slice for each frame to keep track of the indenter. I read the warning in the manual about repeating modifiers in the list, I thought I could by pass that, by ending my for statement with the clear() method for lists on the modifier list.
The result: no error message whatsoever, script won't go pass frame 0. By commenting and uncommenting I found out the script stops going through the loop when and only when I apply compute method inside it (which of course is absolutely necessary).
I've changed my approach (instead "slicing" via numpy array subsetting) because I became convinced that I can't update my modifiers inside the for loop and that the spirit of the law here is that only compute statements must go inside it. But I need confirmation: Can it or can't it be done in this way?

Quote from Alexander Stukowski on August 20, 2019, 11:21 pmDear Gonzalo,
Yes, normally it is not correct to insert new modifiers into a pipeline inside of a for-loop over the frames of a simulation. Typically, you should do this only before the for-loop. However, it is always okay to change/update the parameters of the existing modifiers within the for-loop. And you are right: Calling the Pipeline.compute() method inside the for-loop is typically what you want to do -otherwise Ovito wouldn't evaluate the pipeline and perform any calculation.
I'm concerned by your statement that script execution stops when you call compute() within the for-loop. This behavior seems weird. Please post the full script code so I can get a better picture of what you are doing.
-Alex
Dear Gonzalo,
Yes, normally it is not correct to insert new modifiers into a pipeline inside of a for-loop over the frames of a simulation. Typically, you should do this only before the for-loop. However, it is always okay to change/update the parameters of the existing modifiers within the for-loop. And you are right: Calling the Pipeline.compute() method inside the for-loop is typically what you want to do -otherwise Ovito wouldn't evaluate the pipeline and perform any calculation.
I'm concerned by your statement that script execution stops when you call compute() within the for-loop. This behavior seems weird. Please post the full script code so I can get a better picture of what you are doing.
-Alex

Quote from Gonzalo García Vidable on August 21, 2019, 4:45 pmDear Alex:
Thank you so much for your answer. I am attaching my script with this message. You will see a bunch of empty lists, this is realated to another issue I ran into. When I tried to store the computations of the for loop on a python list and then print it, my list ended up as empty as it started. This problem persisted even when I went ahead with my new approach that did not involve setting up modifiers inside the for loop. Once more, numpy came to the rescue, as creating an empty numpy array (of the appropiate shape, of course) and then filling it through the for loop successfully bypasses the issue.
Dear Alex:
Thank you so much for your answer. I am attaching my script with this message. You will see a bunch of empty lists, this is realated to another issue I ran into. When I tried to store the computations of the for loop on a python list and then print it, my list ended up as empty as it started. This problem persisted even when I went ahead with my new approach that did not involve setting up modifiers inside the for loop. Once more, numpy came to the rescue, as creating an empty numpy array (of the appropiate shape, of course) and then filling it through the for loop successfully bypasses the issue.
Uploaded files:
Quote from Constanze Kalcher on August 27, 2019, 4:39 pmDear Gonzalo,
I had a look at your script and as a general remark, this is how you would typically set up your pipeline and then loop over the different frames:
#CONSTANTS dt = 0.001 #ps #timeindenterDepth indentationSpeed = 1.0 #Angstrom/ps #indentation speed sphereRadius = 50.0 #Angstrom #radius of sphere #... pipeline = import_file(path+simulationDump) #UPPER CONTACT AREA (WITH INDENTER) THROUGH OVITO pipeline0 = import_file(path+simulationDump) #LOWER CONTACT AREA (WITH SIMULATION BOX) THROUGH OVITO pipeline1 = import_file(path+simulationDump) #UPPER CONTACT AREA (WITH INDENTER) WITH VERGELES' FORMULA pipeline2 = import_file(path+simulationDump) #LOWER CONTACT AREA (WITH SIMULATION BOX)WITH VERGELES' FORMULA #First set up the different pipelines slice_mod = SliceModifier(distance = 0, normal = (0,0,1) ,inverse = True) pipeline.modifiers.append(slice_mod) pipeline.modifiers.append(ConstructSurfaceModifier(radius = 80)) slice_mod0 = SliceModifier(... pipeline0.append(slice_mod0) #... #Loop over all frames for frame in range(pipeline.source.num_frames): step = frame*1000 indenterDepth = indentationSpeed*dt*step #Angstrom indenterHeight = sphereRadius-indenterDepth #Angstrom #and then simply edit the settings of the modifiers instead of appending a new instance of this modifier for each frame slice_mod.distance = indenterHeight # now evalute the pipeline for the current frame data = pipeline.compute(frame)If you like you can get back to us after you adapted your script and still run into problems.
-Constanze
Dear Gonzalo,
I had a look at your script and as a general remark, this is how you would typically set up your pipeline and then loop over the different frames:
#CONSTANTS dt = 0.001 #ps #timeindenterDepth indentationSpeed = 1.0 #Angstrom/ps #indentation speed sphereRadius = 50.0 #Angstrom #radius of sphere #... pipeline = import_file(path+simulationDump) #UPPER CONTACT AREA (WITH INDENTER) THROUGH OVITO pipeline0 = import_file(path+simulationDump) #LOWER CONTACT AREA (WITH SIMULATION BOX) THROUGH OVITO pipeline1 = import_file(path+simulationDump) #UPPER CONTACT AREA (WITH INDENTER) WITH VERGELES' FORMULA pipeline2 = import_file(path+simulationDump) #LOWER CONTACT AREA (WITH SIMULATION BOX)WITH VERGELES' FORMULA #First set up the different pipelines slice_mod = SliceModifier(distance = 0, normal = (0,0,1) ,inverse = True) pipeline.modifiers.append(slice_mod) pipeline.modifiers.append(ConstructSurfaceModifier(radius = 80)) slice_mod0 = SliceModifier(... pipeline0.append(slice_mod0) #... #Loop over all frames for frame in range(pipeline.source.num_frames): step = frame*1000 indenterDepth = indentationSpeed*dt*step #Angstrom indenterHeight = sphereRadius-indenterDepth #Angstrom #and then simply edit the settings of the modifiers instead of appending a new instance of this modifier for each frame slice_mod.distance = indenterHeight # now evalute the pipeline for the current frame data = pipeline.compute(frame)
If you like you can get back to us after you adapted your script and still run into problems.
-Constanze

Quote from Gonzalo García Vidable on August 30, 2019, 4:22 pmDear Constanze:
Thank you so much for your answer. I tried out your idea but it didn't do as intended. The problem is more or less the same, it does nothing unless I comment out just the most important part, namely:
slice_mod.distance = indenterHeight
Any guess as to why this may happen? Does it have anything to do with my OVITO version (3.0.0.)? Also, do you know anything about my additional issue with storing the output of the for loop in an empty Python list?
I am attaching my implementation of your idea, in case you would like to give it a look.
Dear Constanze:
Thank you so much for your answer. I tried out your idea but it didn't do as intended. The problem is more or less the same, it does nothing unless I comment out just the most important part, namely:
slice_mod.distance = indenterHeight
Any guess as to why this may happen? Does it have anything to do with my OVITO version (3.0.0.)? Also, do you know anything about my additional issue with storing the output of the for loop in an empty Python list?
I am attaching my implementation of your idea, in case you would like to give it a look.
Uploaded files:
Quote from Constanze Kalcher on September 2, 2019, 2:08 pmDear Gonzalo,
sorry I'm still having trouble finding out what causes you problems. I tested your script "constanzes_script.py" with some example data of mine and it works just fine both under linux and windows. I used the latest developer version ovito-3.0.0-dev469.
So when I execute:
"C:\Program Files\Ovito\ovitos.exe" constanzes_script.pyI get the following terminal output
0.000000 0.000000 50.000000 50.000000 1000.000000 1.000000 49.000000 49.000000 2000.000000 2.000000 48.000000 48.000000 3000.000000 3.000000 47.000000 47.000000 4000.000000 4.000000 46.000000 46.000000 5000.000000 5.000000 45.000000 45.000000 6000.000000 6.000000 44.000000 44.000000 7000.000000 7.000000 43.000000 43.000000 8000.000000 8.000000 42.000000 42.000000which means that
slice_mod.distance = indenterHeightcorrectly updates the distance of the slice plane in the slice modifier.
Could you please show me a screenshot of your terminal output, so we can figure out together what's going on?
-Constanze
Dear Gonzalo,
sorry I'm still having trouble finding out what causes you problems. I tested your script "constanzes_script.py" with some example data of mine and it works just fine both under linux and windows. I used the latest developer version ovito-3.0.0-dev469.
So when I execute:
"C:\Program Files\Ovito\ovitos.exe" constanzes_script.py
I get the following terminal output
0.000000 0.000000 50.000000 50.000000 1000.000000 1.000000 49.000000 49.000000 2000.000000 2.000000 48.000000 48.000000 3000.000000 3.000000 47.000000 47.000000 4000.000000 4.000000 46.000000 46.000000 5000.000000 5.000000 45.000000 45.000000 6000.000000 6.000000 44.000000 44.000000 7000.000000 7.000000 43.000000 43.000000 8000.000000 8.000000 42.000000 42.000000
which means that
slice_mod.distance = indenterHeight
correctly updates the distance of the slice plane in the slice modifier.
Could you please show me a screenshot of your terminal output, so we can figure out together what's going on?
-Constanze

Quote from Gonzalo García Vidable on September 7, 2019, 11:26 pmDear Constanze:
I updated my working version to ovito-3.0.0-dev469 and the script worked perfectly. Could it be a bug of previous dev versions?
Thank you so much for your help and time in any case.
Dear Constanze:
I updated my working version to ovito-3.0.0-dev469 and the script worked perfectly. Could it be a bug of previous dev versions?
Thank you so much for your help and time in any case.

Quote from Constanze Kalcher on September 9, 2019, 2:23 pmDear Gonzalo,
we haven't been aware of any problems with the previous developer versions, but I'm glad this issue is resolved. Just let us know if you run into problems again.
-Constanze
Dear Gonzalo,
we haven't been aware of any problems with the previous developer versions, but I'm glad this issue is resolved. Just let us know if you run into problems again.
-Constanze
新的OVITO微信频道!
New for our users in China: OVITO on WeChat
Official OVITO WeChat channel operated by Foshan Diesi Technology Co., Ltd.
