|
|
#!perl
use strict;
use MaterialsScript qw(:all);
use Math::Trig;
use Getopt::Long;
# Author: Reinier Akkermans
# Version: 1.0
# Materials Studio Version: 4.4
# Materials Studio Modules: Materials Visualizer
#
# This script attaches functional groups to the surface of a nanocluster.
# The input consists of:
# 1. A nanocluster in which broken bonds are capped with hydrogen atoms.
# 2. A fragment containing a linkage (such as those in .\share\Resources\Fragments\)
# 3. The surface coverage required as a fraction of the total surface
my $CLUSTER = $Documents{"Nanocluster.xsd"};
my %Args;
GetOptions(\%Args, "Fragment=s", "Coverage=f");
my $fragname = $Args{Fragment};
my $FRAGMENT = $Documents{"Toluene.xsd"};
my $COVERAGE = $Args{Coverage};
main();
#####################################################################
sub main(){
# output document
my $doc = Documents->New($CLUSTER->Name." + ".$FRAGMENT->Name.".xsd");
# copy structure in
$doc->CopyFrom($CLUSTER);
# first fix hydrogens with two bonds (artefact of nanocluster builder)
foreach my $atom (@{$doc->Atoms}) {
if(($atom->ElementSymbol eq "H") && ($atom->Bonds->Count == 2)){
# get the two atoms attached to this hydrogen
my $attachedAtoms = $atom->attachedAtoms;
# delete both bonds
$atom->Bonds->Delete;
#create a new H-atom
my $newAtom = $doc->CreateAtom("H",$atom->XYZ);
# create two new bonds
$doc->CreateBond($atom,$attachedAtoms->Item(0),"Single");
$doc->CreateBond($newAtom,$attachedAtoms->Item(1),"Single");
# clean up steric hindrance
$newAtom->Clean;
}
}
# attach fragments to the surface
foreach my $atom (@{$doc->Atoms}) {
if(($atom->ElementSymbol eq "H") && (rand()<$COVERAGE)){
# add a new fragment
my $fragment = $doc->CopyFrom($FRAGMENT);
# get the linkage atom
my $linkAtom = $fragment->Linkages(0)->LinkAtoms->Item(0);
# the two atoms between which to create a bond
my $atom1 = $atom->AttachedAtoms->Item(0);
my $atom2 = $linkAtom->AttachedAtoms->Item(0);
# translate the fragment such that the linkage atom is
# on top of the hydrogen atom
my $centroid = $doc->CreateCentroid($fragment->Atoms);
$centroid->Translate(Point(X => -$linkAtom->X, Y => -$linkAtom->Y, Z => -$linkAtom->Z));
$centroid->Translate(Point(X => $atom->X, Y => $atom->Y, Z => $atom->Z));
# rotate the fragment such that the linkage bond
# is parallel with the hydrogen bond
my $bond1 = Point(X => $atom1->X-$atom->X,Y => $atom1->Y-$atom->Y, Z => $atom1->Z-$atom->Z);
my $bond2 = Point(X => $atom2->X-$linkAtom->X,Y => $atom2->Y-$linkAtom->Y, Z =>$atom2->Z-$linkAtom->Z);
my $angle = 180-acos(InProduct($bond1,$bond2)/Length($bond1)/Length($bond2))*180/pi;
my $axis = CrossProduct($bond1,$bond2);
$centroid->RotateAboutPoint($angle,$axis,$atom->XYZ);
# delete centroid,linkage atom and hydrogen atom
$centroid->Delete;
$atom->Delete;
$linkAtom->Delete;
# attach to the nanocluster
$doc->CreateBond($atom1,$atom2,"Single");
}
}
# give it a few shakes to remove steric hindrance
for(my $i=0;$i<15;$i++){
$doc->Clean;
}
}
sub Length(){
my ($a) = @_;
return sqrt(InProduct($a,$a));
}
sub CrossProduct(){
my ($a,$b) = @_;
return Point(X => $a->Y*$b->Z-$a->Z*$b->Y, Y => $a->Z*$b->X-$a->X*$b->Z, Z => $a->X*$b->Y-$a->Y*$b->X);
}
sub InProduct(){
my ($a,$b) = @_;
return $a->X*$b->X+$a->Y*$b->Y+$a->Z*$b->Z;
}
|
|