Updating of "How to measure dihedral angles between two vectors ? "


Dear Reinier,

I read your post about "How to measure dihedral angles between two vectors" (Updated Link​​​​​​​)

And I modified the following script according to your recommendation in above post. However, the angle is still between 60-120 degree as Jingjing mentioned before.  If it's available for you, would you please update the correct script?  Following image is the perfect result I am looking for.


----------------------------------

#!perl


use strict;

use MaterialsScript qw(:all);

use Math::Trig;


my \\\$doc = \\\$Documents{"Layer.xtd"};

my \\\$setA = "Si";

my \\\$setB = "H2O";



# get the trajectory data

my \\\$trj = \\\$doc->Trajectory;

my \\\$numFrames = \\\$trj->NumFrames;


# create a study table for the results

my \\\$std = Documents->New(\\\$doc->Name.".std");

\\\$std->ColumnHeading(0) = "Angle (deg)";

\\\$std->ColumnHeading(1) = "Distance (angstrom)";



my \\\$setMolecules = \\\$doc->UnitCell->Sets(\\\$setB)->Molecules;


# run over all frames in the trajectory

my \\\$irow = 0;

my \\\$setAtoms = \\\$doc->UnitCell->Sets(\\\$setA)->Atoms;

my \\\$plane = \\\$doc->UnitCell->CreateBestFitPlane(\\\$setAtoms);

my \\\$bestFitPlane = \\\$plane->BestFitPlane;

for(my \\\$frame = 1; \\\$frame <= 1000; \\\$frame++)

{

   \\\$trj->CurrentFrame = \\\$frame;

  

   # get the normal vector of the plane

   my \\\$normal = \\\$plane->BestFitPlane->UnitNormalVector;

  

   foreach my \\\$setMolecule(@\\\$setMolecules)

   {  

     # z position of the molecule

     my \\\$distance = \\\$setMolecule->Center->Z;

     # get dipole moment

    

     my \\\$dipoleMoment = \\\$setMolecule->DipoleMoment;

    

    

     # calculate the angle between the dipole and the surface normal  

     my \\\$cosAngle = InProduct(\\\$normal, \\\$dipoleMoment);

     my \\\$angle =180/pi*acos(\\\$cosAngle);

    

     # store the data in the study table

     \\\$std->Cell(\\\$irow,0) = \\\$angle;       

     \\\$std->Cell(\\\$irow++,1) = \\\$distance;

   }

}

\\\$doc->Discard; # discard any changes made


sub InProduct(){

my(\\\$a, \\\$b) = @_;

return \\\$a->X*\\\$b->X+\\\$a->Y*\\\$b->Y+\\\$a->Z*\\\$b->Z

}


Regards,

Jingjing


reinier

The problem is probably in your InProduct function;it has a prototype () indicating the function takes no parameters, whereas it takes two,


sub InProduct(){

my(\\\$a, \\\$b) = @_;

return \\\$a->X*\\\$b->X+\\\$a->Y*\\\$b->Y+\\\$a->Z*\\\$b->Z

}

Deleting () should resolve the problem.


reinier

You need to normalize the dipole moment vector before taking the inproduct, as above,



     # get the direction of the dipole

     my \\\$dipoleMoment = \\\$molecule->DipoleMoment;

     my \\\$direction = Normalize(\\\$dipoleMoment);


     # calculate the angle between the dipole and the z-axis    

     my \\\$angle = 180/pi*acos(InProduct(\\\$direction, \\\$axis));

------------------------------------