1 package AtomTypes::UFFAtomTypes; 2 # 3 # $RCSfile: UFFAtomTypes.pm,v $ 4 # $Date: 2015/02/28 20:48:03 $ 5 # $Revision: 1.20 $ 6 # 7 # Author: Manish Sud <msud@san.rr.com> 8 # 9 # Copyright (C) 2015 Manish Sud. All rights reserved. 10 # 11 # This file is part of MayaChemTools. 12 # 13 # MayaChemTools is free software; you can redistribute it and/or modify it under 14 # the terms of the GNU Lesser General Public License as published by the Free 15 # Software Foundation; either version 3 of the License, or (at your option) any 16 # later version. 17 # 18 # MayaChemTools is distributed in the hope that it will be useful, but without 19 # any warranty; without even the implied warranty of merchantability of fitness 20 # for a particular purpose. See the GNU Lesser General Public License for more 21 # details. 22 # 23 # You should have received a copy of the GNU Lesser General Public License 24 # along with MayaChemTools; if not, see <http://www.gnu.org/licenses/> or 25 # write to the Free Software Foundation Inc., 59 Temple Place, Suite 330, 26 # Boston, MA, 02111-1307, USA. 27 # 28 29 use strict; 30 use Carp; 31 use Exporter; 32 use Scalar::Util (); 33 use AtomTypes::AtomTypes; 34 use Molecule; 35 36 use vars qw(@ISA @EXPORT @EXPORT_OK %EXPORT_TAGS); 37 38 @ISA = qw(AtomTypes::AtomTypes Exporter); 39 @EXPORT = qw(GetUFFAtomTypesData GetAllPossibleUFFAtomTypes GetAllPossibleUFFNonHydrogenAtomTypes); 40 @EXPORT_OK = qw(); 41 42 %EXPORT_TAGS = (all => [@EXPORT, @EXPORT_OK]); 43 44 # Setup class variables... 45 my($ClassName, %UFFAtomTypesDataMap); 46 _InitializeClass(); 47 48 # Overload Perl functions... 49 use overload '""' => 'StringifyUFFAtomTypes'; 50 51 # Class constructor... 52 sub new { 53 my($Class, %NamesAndValues) = @_; 54 55 # Initialize object... 56 my $This = $Class->SUPER::new(); 57 bless $This, ref($Class) || $Class; 58 $This->_InitializeUFFAtomTypes(); 59 60 $This->_InitializeUFFAtomTypesProperties(%NamesAndValues); 61 62 return $This; 63 } 64 65 # Initialize class ... 66 sub _InitializeClass { 67 #Class name... 68 $ClassName = __PACKAGE__; 69 70 # Initialize the data hash. It'll be loaded on demand later... 71 %UFFAtomTypesDataMap = (); 72 } 73 74 # Initialize object data... 75 # 76 sub _InitializeUFFAtomTypes { 77 my($This) = @_; 78 79 # Type of AtomTypes... 80 $This->{Type} = 'UFF'; 81 82 # By default, UFF atom types are also assigned to hydrogens... 83 $This->{IgnoreHydrogens} = 0; 84 85 return $This; 86 } 87 88 # Initialize object properties... 89 # 90 sub _InitializeUFFAtomTypesProperties { 91 my($This, %NamesAndValues) = @_; 92 93 my($Name, $Value, $MethodName); 94 while (($Name, $Value) = each %NamesAndValues) { 95 $MethodName = "Set${Name}"; 96 $This->$MethodName($Value); 97 } 98 99 # Make sure molecule object was specified... 100 if (!exists $NamesAndValues{Molecule}) { 101 croak "Error: ${ClassName}->New: Object can't be instantiated without specifying molecule..."; 102 } 103 104 return $This; 105 } 106 107 # Get UFF atom types and associated data loaded from UFF data file as 108 # a reference to hash with the following hash data format: 109 # 110 # @{$UFFAtomTypesDataMap{AtomTypes}} - Array of all possible atom types for all atoms 111 # @{$UFFAtomTypesDataMap{NonHydrogenAtomTypes}} - Array of all possible atom types for non-hydrogen atoms 112 # @{$UFFAtomTypesDataMap->{ColLabels}} - Array of column labels 113 # %{$UFFAtomTypesDataMap->{DataCol<Num>}} - Hash keys pair: <DataCol<Num>, AtomType> 114 # 115 # This functionality can be either invoked as a class function or an 116 # object method. 117 # 118 sub GetUFFAtomTypesData { 119 120 # Make sure data is loaded... 121 _CheckAndLoadUFFAtomTypesData(); 122 123 return \%UFFAtomTypesDataMap; 124 } 125 126 # Get all possible UFF atom types corresponding to hydrogen and non-hydrogen 127 # atoms as an array reference... 128 # 129 # This functionality can be either invoked as a class function or an 130 # object method. 131 # 132 sub GetAllPossibleUFFAtomTypes { 133 return _GetAllPossibleUFFAtomTypes(); 134 } 135 136 # Get all possible UFF atom types corresponding to non-hydrogen atoms 137 # as an array reference... 138 # 139 # This functionality can be either invoked as a class function or an 140 # object method. 141 # 142 sub GetAllPossibleUFFNonHydrogenAtomTypes { 143 my($NonHydrogensOnly); 144 145 $NonHydrogensOnly = 1; 146 return _GetAllPossibleUFFAtomTypes($NonHydrogensOnly); 147 } 148 149 # Get all possible UFF atom types as an array reference... 150 # 151 sub _GetAllPossibleUFFAtomTypes { 152 my($NonHydrogensOnly) = @_; 153 my($UFFAtomTypesDataRef); 154 155 $NonHydrogensOnly = defined $NonHydrogensOnly ? $NonHydrogensOnly : 0; 156 157 $UFFAtomTypesDataRef = GetUFFAtomTypesData(); 158 159 return $NonHydrogensOnly ? \@{$UFFAtomTypesDataRef->{NonHydrogenAtomTypes}}: \@{$UFFAtomTypesDataRef->{AtomTypes}}; 160 } 161 # Assign UFF [ Ref 81-82 ] atom types to all atoms... 162 # 163 # Notes: 164 # . Some listed atom types - O_3_z, 165 # are not assigned to any atom 166 # o 126 UFF atom types are listed for elements with atomic number upto 103 167 # o AtomTypes::AtomTypes::UFFAtomTypes.pm module is used to assign UFF atom types 168 # o Units: 169 # o ValenceBondRadius and NonBondRadius: Angstroms 170 # o ValenceAngle: Degrees 171 # o NonBondEnergy and SP3TorsionalBarrier: kcal/mol 172 # o Five-character mnemonic label for UFF atom types 173 # o First two characters correspond to chemical symbol with an underscore as second 174 # character for elements with one character symbol 175 # o Third character describes hybridization or geometry: 1 - linear; 2 - trigonal; R - resonant; 176 # 3 = tetrahedral; 4 - square planar; 5 - trigonal bipyramidal; 6 - octahedral 177 # o Fourth and fifth characters are used as indicators of alternate parameters: formal oxidation 178 # state, bridging hydrogens and so on. 179 # 180 # 181 sub AssignAtomTypes { 182 my($This) = @_; 183 my($Atom, $AtomType); 184 185 ATOM: for $Atom ($This->GetMolecule()->GetAtoms()) { 186 if ($This->{IgnoreHydrogens} && $Atom->IsHydrogen()) { 187 next ATOM; 188 } 189 $AtomType = $This->_GetAtomType($Atom); 190 $This->SetAtomType($Atom, $AtomType); 191 } 192 return $This; 193 } 194 195 # Get UFF atom type for atom... 196 # 197 sub _GetAtomType { 198 my($This, $Atom) = @_; 199 my($AtomType); 200 201 $AtomType = ''; 202 203 ATOM: { 204 if ($Atom->IsCarbon()) { 205 $AtomType = $This->_GetAtomTypeForCarbon($Atom); 206 last ATOM; 207 } 208 if ($Atom->IsNitrogen()) { 209 $AtomType = $This->_GetAtomTypeForNitrogen($Atom); 210 last ATOM; 211 } 212 if ($Atom->IsOxygen()) { 213 $AtomType = $This->_GetAtomTypeForOxygen($Atom); 214 last ATOM; 215 } 216 if ($Atom->IsPhosphorus()) { 217 $AtomType = $This->_GetAtomTypeForPhosphorus($Atom); 218 last ATOM; 219 } 220 if ($Atom->IsSulfur()) { 221 $AtomType = $This->_GetAtomTypeForSulfur($Atom); 222 last ATOM; 223 } 224 if ($Atom->IsHydrogen()) { 225 $AtomType = $This->_GetAtomTypeForHydrogen($Atom); 226 last ATOM; 227 } 228 $AtomType = $This->_GetAtomTypeForOtherAtoms($Atom); 229 } 230 231 return $AtomType; 232 } 233 234 # Get UFF atom type for Carbon atom... 235 # 236 sub _GetAtomTypeForCarbon { 237 my($This, $Atom) = @_; 238 my($AtomType, $NumOfSigmaBonds, $NumOfPiBonds); 239 240 $AtomType = 'None'; 241 242 ($NumOfSigmaBonds, $NumOfPiBonds) = ('0') x 2; 243 244 ($NumOfSigmaBonds, $NumOfPiBonds) = $Atom->GetNumOfSigmaAndPiBondsToNonHydrogenAtoms(); 245 $NumOfSigmaBonds += $Atom->GetAtomicInvariantValue('H'); 246 247 ATOMTYPE: { 248 if ($Atom->IsAromatic()) { 249 $AtomType = 'C_R'; 250 last ATOMTYPE; 251 } 252 253 # Only single bonds... 254 if ($NumOfPiBonds == 0) { 255 $AtomType = 'C_3'; 256 last ATOMTYPE; 257 } 258 259 # One double bond... 260 if ($NumOfPiBonds == 1) { 261 $AtomType = 'C_2'; 262 last ATOMTYPE; 263 } 264 265 # One triple bond or two double bonds... 266 if ($NumOfPiBonds == 2) { 267 $AtomType = 'C_1'; 268 last ATOMTYPE; 269 } 270 271 $AtomType = 'None'; 272 carp "Warning: ${ClassName}->_GetAtomTypeForCarbon: UFF atom types for Carbon cann't be assigned..."; 273 } 274 275 return $AtomType; 276 } 277 278 # Get UFF atom type for Nitrogen atom... 279 # 280 sub _GetAtomTypeForNitrogen { 281 my($This, $Atom) = @_; 282 my($AtomType, $NumOfSigmaBonds, $NumOfPiBonds); 283 284 $AtomType = 'None'; 285 286 ($NumOfSigmaBonds, $NumOfPiBonds) = ('0') x 2; 287 288 ($NumOfSigmaBonds, $NumOfPiBonds) = $Atom->GetNumOfSigmaAndPiBondsToNonHydrogenAtoms(); 289 $NumOfSigmaBonds += $Atom->GetAtomicInvariantValue('H'); 290 291 ATOMTYPE: { 292 if ($Atom->IsAromatic()) { 293 $AtomType = 'N_R'; 294 last ATOMTYPE; 295 } 296 297 # Only single bonds... 298 if ($NumOfPiBonds == 0) { 299 $AtomType = 'N_3'; 300 last ATOMTYPE; 301 } 302 303 # One double bond... 304 if ($NumOfPiBonds == 1) { 305 $AtomType = 'N_2'; 306 last ATOMTYPE; 307 } 308 309 # One triple bond or two double bonds... 310 if ($NumOfPiBonds == 2) { 311 $AtomType = 'N_1'; 312 last ATOMTYPE; 313 } 314 $AtomType = 'None'; 315 carp "Warning: ${ClassName}->_GetAtomTypeForNitrogen: UFF atom types for Nitrogen cann't be assigned..."; 316 } 317 318 return $AtomType; 319 } 320 321 # Get UFF atom type for Oxygen atom... 322 # 323 sub _GetAtomTypeForOxygen { 324 my($This, $Atom) = @_; 325 my($AtomType, $NumOfSigmaBonds, $NumOfPiBonds); 326 327 $AtomType = 'None'; 328 329 ($NumOfSigmaBonds, $NumOfPiBonds) = ('0') x 2; 330 331 ($NumOfSigmaBonds, $NumOfPiBonds) = $Atom->GetNumOfSigmaAndPiBondsToNonHydrogenAtoms(); 332 $NumOfSigmaBonds += $Atom->GetAtomicInvariantValue('H'); 333 334 ATOMTYPE: { 335 if ($Atom->IsAromatic()) { 336 $AtomType = 'O_R'; 337 last ATOMTYPE; 338 } 339 340 # Only single bonds... 341 if ($NumOfPiBonds == 0) { 342 $AtomType = 'O_3'; 343 last ATOMTYPE; 344 } 345 346 # One double bond... 347 if ($NumOfPiBonds == 1) { 348 $AtomType = 'O_2'; 349 last ATOMTYPE; 350 } 351 352 # One triple bond or two double bonds... 353 if ($NumOfPiBonds == 2) { 354 $AtomType = 'O_1'; 355 last ATOMTYPE; 356 } 357 358 $AtomType = 'None'; 359 carp "Warning: ${ClassName}->_GetAtomTypeForOxygen: UFF atom types for Oxygen cann't be assigned..."; 360 } 361 362 return $AtomType; 363 } 364 365 # Get UFF atom type for Phosphorus atom... 366 # 367 sub _GetAtomTypeForPhosphorus { 368 my($This, $Atom) = @_; 369 my($AtomType, $NumOfSigmaBonds, $NumOfPiBonds); 370 371 $AtomType = 'None'; 372 373 ($NumOfSigmaBonds, $NumOfPiBonds) = ('0') x 2; 374 375 ($NumOfSigmaBonds, $NumOfPiBonds) = $Atom->GetNumOfSigmaAndPiBondsToNonHydrogenAtoms(); 376 $NumOfSigmaBonds += $Atom->GetAtomicInvariantValue('H'); 377 378 ATOMTYPE: { 379 # Is it a four-coordinated Phosphorus for describing organometallic coordinated phosphines? 380 if ($This->_IsFourCoordinatedOrganometallicPhosphorus($Atom)) { 381 $AtomType = 'P_3+q'; 382 last ATOMTYPE; 383 } 384 385 # -P(-)- 386 if ($NumOfSigmaBonds == 3 && $NumOfPiBonds == 0) { 387 $AtomType = 'P_3+3'; 388 last ATOMTYPE; 389 } 390 391 # =P(-)(-)- 392 if ($NumOfSigmaBonds == 4 && $NumOfPiBonds == 1) { 393 $AtomType = 'P_3+5'; 394 last ATOMTYPE; 395 } 396 397 $AtomType = 'None'; 398 carp "Warning: ${ClassName}->_GetAtomTypeForPhosphorus: UFF atom types for Phosphorus cann't be assigned..."; 399 } 400 401 return $AtomType; 402 } 403 404 # Get UFF atom type for Sulfur atom... 405 # 406 sub _GetAtomTypeForSulfur { 407 my($This, $Atom) = @_; 408 my($AtomType, $NumOfSigmaBonds, $NumOfPiBonds); 409 410 $AtomType = 'None'; 411 412 ($NumOfSigmaBonds, $NumOfPiBonds) = ('0') x 2; 413 414 ($NumOfSigmaBonds, $NumOfPiBonds) = $Atom->GetNumOfSigmaAndPiBondsToNonHydrogenAtoms(); 415 $NumOfSigmaBonds += $Atom->GetAtomicInvariantValue('H'); 416 417 ATOMTYPE: { 418 if ($Atom->IsAromatic()) { 419 $AtomType = 'S_R'; 420 last ATOMTYPE; 421 } 422 423 # -S- 424 if ($NumOfSigmaBonds == 2 && $NumOfPiBonds == 0) { 425 $AtomType = 'S_3+2'; 426 last ATOMTYPE; 427 } 428 429 # -S(=)- 430 if ($NumOfSigmaBonds == 3 && $NumOfPiBonds == 1) { 431 $AtomType = 'S_3+4'; 432 last ATOMTYPE; 433 } 434 435 # -S(=)(=)- 436 if ($NumOfSigmaBonds == 4 && $NumOfPiBonds == 2) { 437 $AtomType = 'S_3+6'; 438 last ATOMTYPE; 439 } 440 441 # S= 442 if ($NumOfSigmaBonds == 1 && $NumOfPiBonds == 1) { 443 $AtomType = 'S_2'; 444 last ATOMTYPE; 445 } 446 447 $AtomType = 'None'; 448 carp "Warning: ${ClassName}->_GetAtomTypeForSulfur: UFF atom types for Sulfur cann't be assigned..."; 449 } 450 return $AtomType; 451 } 452 453 # Get UFF atom type for Hydrogen atom... 454 # 455 sub _GetAtomTypeForHydrogen { 456 my($This, $Atom) = @_; 457 my($AtomType); 458 459 if ($Atom->GetNumOfHeavyAtomNeighbors() > 1) { 460 # Bridging hydrogen as in B2H6 461 $AtomType = 'H___b'; 462 } 463 else { 464 $AtomType = 'H_'; 465 } 466 467 return $AtomType; 468 } 469 470 # Get UFF atom type for atoms other than Carbon, Nitrogen, Oxygen, Phosporus, 471 # Sulfur and Hydrogen... 472 # 473 sub _GetAtomTypeForOtherAtoms { 474 my($This, $Atom) = @_; 475 my($AtomType, $AtomicNumber, $AtomSymbol, $GroupNumber, $MethodName); 476 477 $AtomType = 'None'; 478 479 $AtomicNumber = $Atom->GetAtomicNumber(); 480 $AtomSymbol = $Atom->GetAtomSymbol(); 481 $GroupNumber = $Atom->GetGroupNumber(); 482 483 ATOMTYPE: { 484 # Get atom types for atoms in a valid periodic table group number... 485 if (defined($GroupNumber) && $GroupNumber) { 486 $MethodName = "_GetAtomTypeForOtherAtomsInGroupNumber${GroupNumber}"; 487 $AtomType = $This->$MethodName($Atom); 488 last ATOMTYPE; 489 } 490 491 # Get atom types for Lanthanidies... 492 if ($AtomicNumber >= 57 && $AtomicNumber <= 71) { 493 $AtomType = $This->_GetAtomTypeForOtherAtomsInLanthanoidGroup($Atom); 494 last ATOMTYPE; 495 } 496 497 # Get atom types for Actinides... 498 if ($AtomicNumber >= 89 && $AtomicNumber <= 103) { 499 $AtomType = $This->_GetAtomTypeForOtherAtomsInActinoidGroup($Atom); 500 last ATOMTYPE; 501 } 502 503 $AtomType = 'None'; 504 carp "Warning: ${ClassName}->_GetAtomTypeForOtherAtoms: UFF atom types for atom, $AtomSymbol, with atomic number, $AtomicNumber, cann't be assigned..."; 505 } 506 507 return $AtomType; 508 } 509 510 # Get UFF atom type for atoms in periodic table group number 1... 511 # 512 # Group number 1 contains: H, Li, Na, K, Rb, Cs, Fr 513 # 514 # And corresponding UFF atom types are: Li, Na, K_, Rb, Cs, Fr 515 # 516 # Notes: 517 # . This method doesn't assign UFF atom type for H. 518 # 519 sub _GetAtomTypeForOtherAtomsInGroupNumber1 { 520 my($This, $Atom) = @_; 521 my($AtomType, $AtomSymbol); 522 523 $AtomSymbol = $Atom->GetAtomSymbol(); 524 $AtomType = (length($AtomSymbol) == 1) ? "${AtomSymbol}_" : $AtomSymbol; 525 526 return $AtomType; 527 } 528 529 # Get UFF atom type for atoms in periodic table group number 2... 530 # 531 # Group number 2 contains: Be, Mg, Ca, Sr, Ba, Ra 532 # 533 # And corresponding UFF atom types are: Be3+2, Mg3+2, Ca6+2, Sr6+2, Ba6+2, Ra6+2 534 # 535 # Notes: 536 # . Although the number of valence electrons is two, the tetrahedral and octahedral 537 # geometry is attributed to coordination bonds from other atoms. 538 # 539 sub _GetAtomTypeForOtherAtomsInGroupNumber2 { 540 my($This, $Atom) = @_; 541 my($AtomSymbol, $AtomType, $NumOfNeighbors, $FormalOxidationState, $FormalCharge, $MethodName); 542 543 $AtomType = 'None'; 544 $MethodName = '_GetAtomTypeForOtherAtomsInGroupNumber2'; 545 546 $AtomSymbol = $Atom->GetAtomSymbol(); 547 ($NumOfNeighbors, $FormalOxidationState, $FormalCharge) = $This->_GetAtomEnvironmentInfoForUFFAtomTypes($Atom); 548 549 ATOMSYMBOL: { 550 if ($AtomSymbol =~ /^(Be|Mg)$/) { 551 $AtomType = "${AtomSymbol}3+2"; 552 $This->_CheckGeometryAndFormalChargeMismatch($MethodName, $AtomSymbol, $AtomType, $NumOfNeighbors, $FormalCharge, 'tetrahedral', 4, 2); 553 last ATOMSYMBOL; 554 } 555 556 if ($AtomSymbol =~ /^(Ca|Sr|Ba|Ra)$/) { 557 $AtomType = "${AtomSymbol}6+2"; 558 $This->_CheckGeometryAndFormalChargeMismatch($MethodName, $AtomSymbol, $AtomType, $NumOfNeighbors, $FormalCharge, 'octahedral', 6, 2); 559 last ATOMSYMBOL; 560 } 561 $AtomType = 'None'; 562 } 563 564 return $AtomType; 565 } 566 567 # Get UFF atom type for atoms in periodic table group number 3... 568 # 569 # Group number 3 contains: Sc, Y, Lu, Lr 570 # 571 # And corresponding UFF atom types are: Sc3+3, Y_3+3, Lu6+3, Lr6+3 572 # 573 sub _GetAtomTypeForOtherAtomsInGroupNumber3 { 574 my($This, $Atom) = @_; 575 my($AtomSymbol, $AtomType, $NumOfNeighbors, $FormalOxidationState, $FormalCharge, $MethodName); 576 577 $AtomType = 'None'; 578 $MethodName = '_GetAtomTypeForOtherAtomsInGroupNumber3'; 579 580 ($NumOfNeighbors, $FormalOxidationState, $FormalCharge) = $This->_GetAtomEnvironmentInfoForUFFAtomTypes($Atom); 581 582 $AtomSymbol = $Atom->GetAtomSymbol(); 583 584 ATOMSYMBOL: { 585 if ($AtomSymbol =~ /^(Sc|Y)$/) { 586 $AtomType = (length($AtomSymbol) == 1) ? "${AtomSymbol}_3+3" : "${AtomSymbol}3+3"; 587 $This->_CheckGeometryAndFormalChargeMismatch($MethodName, $AtomSymbol, $AtomType, $NumOfNeighbors, $FormalCharge, 'tetrahedral', 4, 3); 588 last ATOMSYMBOL; 589 } 590 591 if ($AtomSymbol =~ /^(Lu|Lr)$/) { 592 $AtomType = "${AtomSymbol}6+3"; 593 $This->_CheckGeometryAndFormalChargeMismatch($MethodName, $AtomSymbol, $AtomType, $NumOfNeighbors, $FormalCharge, 'octahedral', 6, 3); 594 last ATOMSYMBOL; 595 } 596 597 $AtomType = 'None'; 598 } 599 600 return $AtomType; 601 } 602 603 # Get UFF atom type for atoms in periodic table group number 4... 604 # 605 # Group number 4 contains: Ti, Zr, Hf, Rf 606 # 607 # And corresponding UFF atom types are: Ti3+4, Ti3+6, Zr3+4, Hf3+4 608 # 609 # Notes: 610 # . No UFF atom type for Rf 611 # 612 sub _GetAtomTypeForOtherAtomsInGroupNumber4 { 613 my($This, $Atom) = @_; 614 my($AtomSymbol, $AtomType, $NumOfNeighbors, $FormalOxidationState, $FormalCharge, $MethodName); 615 616 $AtomType = 'None'; 617 $MethodName = '_GetAtomTypeForOtherAtomsInGroupNumber4'; 618 619 $AtomSymbol = $Atom->GetAtomSymbol(); 620 ($NumOfNeighbors, $FormalOxidationState, $FormalCharge) = $This->_GetAtomEnvironmentInfoForUFFAtomTypes($Atom); 621 622 ATOMSYMBOL: { 623 if ($AtomSymbol =~ /^Ti$/) { 624 TI: { 625 if ($NumOfNeighbors == 4 && $FormalOxidationState == 4) { 626 $AtomType = "Ti3+4"; 627 $This->_CheckGeometryAndOxidationStateMismatch($MethodName, $AtomSymbol, $AtomType, $NumOfNeighbors, $FormalOxidationState, 'tetrahedral', 4, 4); 628 last TI; 629 } 630 631 if ($NumOfNeighbors == 4 && $FormalOxidationState == 6) { 632 $AtomType = "Ti3+6"; 633 $This->_CheckGeometryAndOxidationStateMismatch($MethodName, $AtomSymbol, $AtomType, $NumOfNeighbors, $FormalOxidationState, 'tetrahedral', 4, 6); 634 last TI; 635 } 636 637 # Assign default value... 638 $AtomType = "Ti3+6"; 639 $This->_CheckGeometryAndOxidationStateMismatch($MethodName, $AtomSymbol, $AtomType, $NumOfNeighbors, $FormalOxidationState, 'tetrahedral', 4, 6); 640 } 641 last ATOMSYMBOL; 642 } 643 644 if ($AtomSymbol =~ /^(Zr|Hf)$/) { 645 $AtomType = "${AtomSymbol}3+4"; 646 $This->_CheckGeometryAndOxidationStateMismatch($MethodName, $AtomSymbol, $AtomType, $NumOfNeighbors, $FormalOxidationState, 'tetrahedral', 4, 4); 647 last ATOMSYMBOL; 648 } 649 650 $AtomType = 'None'; 651 } 652 653 return $AtomType; 654 } 655 656 # Get UFF atom type for atoms in periodic table group number 5... 657 # 658 # Group number 5 contains: V, Nb, Ta, Db 659 # 660 # And corresponding UFF atom types are: V_3+5, Nb3+5, Ta3+5 661 # 662 # Notes: 663 # . No UFF atom type for Db 664 # 665 sub _GetAtomTypeForOtherAtomsInGroupNumber5 { 666 my($This, $Atom) = @_; 667 my($AtomSymbol, $AtomType, $NumOfNeighbors, $FormalOxidationState, $FormalCharge, $MethodName); 668 669 $AtomType = 'None'; 670 $MethodName = '_GetAtomTypeForOtherAtomsInGroupNumber5'; 671 672 $AtomSymbol = $Atom->GetAtomSymbol(); 673 ($NumOfNeighbors, $FormalOxidationState, $FormalCharge) = $This->_GetAtomEnvironmentInfoForUFFAtomTypes($Atom); 674 675 ATOMSYMBOL: { 676 if ($AtomSymbol =~ /^(V|Nb|Ta)$/) { 677 $AtomType = (length($AtomSymbol) == 1) ? "${AtomSymbol}_3+5" : "${AtomSymbol}3+5"; 678 $This->_CheckGeometryAndOxidationStateMismatch($MethodName, $AtomSymbol, $AtomType, $NumOfNeighbors, $FormalOxidationState, 'tetrahedral', 4, 5); 679 last ATOMSYMBOL; 680 } 681 682 $AtomType = 'None'; 683 } 684 685 return $AtomType; 686 } 687 688 # Get UFF atom type for atoms in periodic table group number 6... 689 # 690 # Group number 6 contains: Cr, Mo, W, Sg 691 # 692 # And corresponding UFF atom types are: Cr6+3, Mo6+6, Mo3+6, W_6+6, W_3+4, W_3+6 693 # 694 # Notes: 695 # . No UFF atom type for Sg 696 # 697 sub _GetAtomTypeForOtherAtomsInGroupNumber6 { 698 my($This, $Atom) = @_; 699 my($AtomSymbol, $AtomType, $NumOfNeighbors, $FormalOxidationState, $FormalCharge, $MethodName); 700 701 $AtomType = 'None'; 702 $MethodName = '_GetAtomTypeForOtherAtomsInGroupNumber6'; 703 704 $AtomSymbol = $Atom->GetAtomSymbol(); 705 ($NumOfNeighbors, $FormalOxidationState, $FormalCharge) = $This->_GetAtomEnvironmentInfoForUFFAtomTypes($Atom); 706 707 ATOMSYMBOL: { 708 if ($AtomSymbol =~ /^Cr$/) { 709 $AtomType = "Cr6+3"; 710 $This->_CheckGeometryAndFormalChargeMismatch($MethodName, $AtomSymbol, $AtomType, $NumOfNeighbors, $FormalCharge, 'octahedral', 6, 3); 711 last ATOMSYMBOL; 712 } 713 714 if ($AtomSymbol =~ /^Mo$/) { 715 MO: { 716 if ($NumOfNeighbors == 6 && $FormalOxidationState == 6) { 717 $AtomType = "Mo6+6"; 718 $This->_CheckGeometryAndOxidationStateMismatch($MethodName, $AtomSymbol, $AtomType, $NumOfNeighbors, $FormalOxidationState, 'octahedral', 6, 6); 719 last MO; 720 } 721 722 if ($NumOfNeighbors == 4 && $FormalOxidationState == 6) { 723 $AtomType = "Mo3+6"; 724 $This->_CheckGeometryAndOxidationStateMismatch($MethodName, $AtomSymbol, $AtomType, $NumOfNeighbors, $FormalOxidationState, 'tetrahedral', 4, 6); 725 last MO; 726 } 727 728 # Assign default value... 729 $AtomType = "Mo6+6"; 730 $This->_CheckGeometryAndOxidationStateMismatch($MethodName, $AtomSymbol, $AtomType, $NumOfNeighbors, $FormalOxidationState, 'octahedral', 6, 6); 731 } 732 last ATOMSYMBOL; 733 } 734 735 if ($AtomSymbol =~ /^W$/) { 736 W: { 737 if ($NumOfNeighbors == 4 && $FormalOxidationState == 4) { 738 $AtomType = "W_3+4"; 739 $This->_CheckGeometryAndOxidationStateMismatch($MethodName, $AtomSymbol, $AtomType, $NumOfNeighbors, $FormalOxidationState, 'tetrahedral', 4, 4); 740 last W; 741 } 742 743 if ($NumOfNeighbors == 4 && $FormalOxidationState == 6) { 744 $AtomType = "W_3+6"; 745 $This->_CheckGeometryAndOxidationStateMismatch($MethodName, $AtomSymbol, $AtomType, $NumOfNeighbors, $FormalOxidationState, 'tetrahedral', 4, 6); 746 last W; 747 } 748 749 if ($NumOfNeighbors == 6 && $FormalOxidationState == 6) { 750 $AtomType = "W_6+6"; 751 $This->_CheckGeometryAndOxidationStateMismatch($MethodName, $AtomSymbol, $AtomType, $NumOfNeighbors, $FormalOxidationState, 'octahedral', 6, 6); 752 last W; 753 } 754 755 # Assign default value... 756 $AtomType = "W_6+6"; 757 $This->_CheckGeometryAndOxidationStateMismatch($MethodName, $AtomSymbol, $AtomType, $NumOfNeighbors, $FormalOxidationState, 'octahedral', 6, 6); 758 } 759 last ATOMSYMBOL; 760 } 761 762 $AtomType = 'None'; 763 } 764 765 return $AtomType; 766 } 767 768 # Get UFF atom type for atoms in periodic table group number 7... 769 # 770 # Group number 7 contains: Mn, Tc, Re, Bh 771 # 772 # And corresponding UFF atom types are: Mn6+2, Tc6+5, Re6+5, Re3+7 773 # 774 # Notes: 775 # . No UFF atom type for Bh 776 # 777 sub _GetAtomTypeForOtherAtomsInGroupNumber7 { 778 my($This, $Atom) = @_; 779 my($AtomSymbol, $AtomType, $NumOfNeighbors, $FormalOxidationState, $FormalCharge, $MethodName); 780 781 $AtomType = 'None'; 782 $MethodName = '_GetAtomTypeForOtherAtomsInGroupNumber7'; 783 784 $AtomSymbol = $Atom->GetAtomSymbol(); 785 ($NumOfNeighbors, $FormalOxidationState, $FormalCharge) = $This->_GetAtomEnvironmentInfoForUFFAtomTypes($Atom); 786 787 ATOMSYMBOL: { 788 if ($AtomSymbol =~ /^Mn$/) { 789 $AtomType = "Mn6+2"; 790 $This->_CheckGeometryAndFormalChargeMismatch($MethodName, $AtomSymbol, $AtomType, $NumOfNeighbors, $FormalCharge, 'octahedral', 6, 2); 791 last ATOMSYMBOL; 792 } 793 794 if ($AtomSymbol =~ /^Tc$/) { 795 $AtomType = "Tc6+5"; 796 $This->_CheckGeometryAndOxidationStateMismatch($MethodName, $AtomSymbol, $AtomType, $NumOfNeighbors, $FormalCharge, 'octahedral', 6, 6); 797 last ATOMSYMBOL; 798 } 799 800 if ($AtomSymbol =~ /^Re$/) { 801 RE: { 802 if ($NumOfNeighbors == 6) { 803 $AtomType = "Re6+5"; 804 $This->_CheckGeometryAndOxidationStateMismatch($MethodName, $AtomSymbol, $AtomType, $NumOfNeighbors, $FormalOxidationState, 'octahedral', 6, 6); 805 last RE; 806 } 807 808 if ($NumOfNeighbors == 4 && $FormalOxidationState == 7) { 809 $AtomType = "Re3+7"; 810 $This->_CheckGeometryAndOxidationStateMismatch($MethodName, $AtomSymbol, $AtomType, $NumOfNeighbors, $FormalOxidationState, 'tetrahedral', 4, 7); 811 last RE; 812 } 813 814 # Assign default value... 815 $AtomType = "Re6+5"; 816 $This->_CheckGeometryAndOxidationStateMismatch($MethodName, $AtomSymbol, $AtomType, $NumOfNeighbors, $FormalOxidationState, 'octahedral', 6, 6); 817 } 818 last ATOMSYMBOL; 819 } 820 821 $AtomType = 'None'; 822 } 823 824 return $AtomType; 825 } 826 827 # Get UFF atom type for atoms in periodic table group number 8... 828 # 829 # Group number 8 contains: Fe, Ru, Os, Hs 830 # 831 # And corresponding UFF atom types are: Fe6+2, Ru6+2, Ru6+3, Os6+6 832 # 833 # Notes: 834 # . No UFF atom type for Hs 835 # 836 sub _GetAtomTypeForOtherAtomsInGroupNumber8 { 837 my($This, $Atom) = @_; 838 my($AtomSymbol, $AtomType, $NumOfNeighbors, $FormalOxidationState, $FormalCharge, $MethodName); 839 840 $AtomType = 'None'; 841 $MethodName = '_GetAtomTypeForOtherAtomsInGroupNumber8'; 842 843 $AtomSymbol = $Atom->GetAtomSymbol(); 844 ($NumOfNeighbors, $FormalOxidationState, $FormalCharge) = $This->_GetAtomEnvironmentInfoForUFFAtomTypes($Atom); 845 846 ATOMSYMBOL: { 847 if ($AtomSymbol =~ /^Fe$/) { 848 $AtomType = "Fe6+2"; 849 $This->_CheckGeometryAndFormalChargeMismatch($MethodName, $AtomSymbol, $AtomType, $NumOfNeighbors, $FormalCharge, 'octahedral', 6, 2); 850 last ATOMSYMBOL; 851 } 852 853 if ($AtomSymbol =~ /^Ru$/) { 854 RU: { 855 if ($NumOfNeighbors == 6 && $FormalCharge == 2) { 856 $AtomType = "Ru6+2"; 857 $This->_CheckGeometryAndFormalChargeMismatch($MethodName, $AtomSymbol, $AtomType, $NumOfNeighbors, $FormalCharge, 'octahedral', 6, 2); 858 last RU; 859 } 860 861 if ($NumOfNeighbors == 6 && $FormalCharge == 3) { 862 $AtomType = "Ru6+3"; 863 $This->_CheckGeometryAndFormalChargeMismatch($MethodName, $AtomSymbol, $AtomType, $NumOfNeighbors, $FormalCharge, 'octahedral', 6, 3); 864 last RU; 865 } 866 867 # Assign default value... 868 $AtomType = "Ru6+3"; 869 $This->_CheckGeometryAndFormalChargeMismatch($MethodName, $AtomSymbol, $AtomType, $NumOfNeighbors, $FormalCharge, 'octahedral', 6, 2); 870 } 871 last ATOMSYMBOL; 872 } 873 874 if ($AtomSymbol =~ /^Os$/) { 875 $AtomType = "Os6+6"; 876 $This->_CheckGeometryAndOxidationStateMismatch($MethodName, $AtomSymbol, $AtomType, $NumOfNeighbors, $FormalCharge, 'octahedral', 6, 6); 877 last ATOMSYMBOL; 878 } 879 880 $AtomType = 'None'; 881 } 882 883 return $AtomType; 884 } 885 886 # Get UFF atom type for atoms in periodic table group number 9... 887 # 888 # Group number 9 contains: Co, Rh, Ir, Mt 889 # 890 # And corresponding UFF atom types are: Co6+3, Rh6+3, Ir6+3 891 # 892 # Notes: 893 # . No UFF atom type for Mt 894 # 895 sub _GetAtomTypeForOtherAtomsInGroupNumber9 { 896 my($This, $Atom) = @_; 897 my($AtomSymbol, $AtomType, $NumOfNeighbors, $FormalOxidationState, $FormalCharge, $MethodName); 898 899 $AtomType = 'None'; 900 $MethodName = '_GetAtomTypeForOtherAtomsInGroupNumber9'; 901 902 $AtomSymbol = $Atom->GetAtomSymbol(); 903 ($NumOfNeighbors, $FormalOxidationState, $FormalCharge) = $This->_GetAtomEnvironmentInfoForUFFAtomTypes($Atom); 904 905 ATOMSYMBOL: { 906 if ($AtomSymbol =~ /^(Co|Rh|Ir)$/) { 907 $AtomType = "${AtomSymbol}6+3"; 908 $This->_CheckGeometryAndFormalChargeMismatch($MethodName, $AtomSymbol, $AtomType, $NumOfNeighbors, $FormalCharge, 'octahedral', 6, 3); 909 last ATOMSYMBOL; 910 } 911 912 $AtomType = 'None'; 913 } 914 915 return $AtomType; 916 } 917 918 # Get UFF atom type for atoms in periodic table group number 10... 919 # 920 # Group number 10 contains: Ni, Pd, Pt 921 # 922 # And corresponding UFF atom types are: Ni4+2, Pd4+2, Pt4+2 923 # 924 sub _GetAtomTypeForOtherAtomsInGroupNumber10 { 925 my($This, $Atom) = @_; 926 my($AtomSymbol, $AtomType, $NumOfNeighbors, $FormalOxidationState, $FormalCharge, $MethodName); 927 928 $AtomType = 'None'; 929 $MethodName = '_GetAtomTypeForOtherAtomsInGroupNumber10'; 930 931 $AtomSymbol = $Atom->GetAtomSymbol(); 932 ($NumOfNeighbors, $FormalOxidationState, $FormalCharge) = $This->_GetAtomEnvironmentInfoForUFFAtomTypes($Atom); 933 934 ATOMSYMBOL: { 935 if ($AtomSymbol =~ /^(Ni|Pd|Pt)$/) { 936 $AtomType = "${AtomSymbol}4+2"; 937 $This->_CheckGeometryAndFormalChargeMismatch($MethodName, $AtomSymbol, $AtomType, $NumOfNeighbors, $FormalCharge, 'planar', 4, 2); 938 last ATOMSYMBOL; 939 } 940 941 $AtomType = 'None'; 942 } 943 944 return $AtomType; 945 } 946 947 # Get UFF atom type for atoms in periodic table group number 11... 948 # 949 # Group number 11 contains: Cu, Ag, Au 950 # 951 # And corresponding UFF atom types are: Cu3+1, Ag1+1, Au4+3 952 # 953 sub _GetAtomTypeForOtherAtomsInGroupNumber11 { 954 my($This, $Atom) = @_; 955 my($AtomSymbol, $AtomType, $NumOfNeighbors, $FormalOxidationState, $FormalCharge, $MethodName); 956 957 $AtomType = 'None'; 958 $MethodName = '_GetAtomTypeForOtherAtomsInGroupNumber11'; 959 960 $AtomSymbol = $Atom->GetAtomSymbol(); 961 ($NumOfNeighbors, $FormalOxidationState, $FormalCharge) = $This->_GetAtomEnvironmentInfoForUFFAtomTypes($Atom); 962 963 ATOMSYMBOL: { 964 if ($AtomSymbol =~ /^Cu$/) { 965 $AtomType = "Cu3+1"; 966 $This->_CheckGeometryAndFormalChargeMismatch($MethodName, $AtomSymbol, $AtomType, $NumOfNeighbors, $FormalCharge, 'tetrahedral', 4, 1); 967 last ATOMSYMBOL; 968 } 969 970 if ($AtomSymbol =~ /^Ag$/) { 971 $AtomType = "Ag1+1"; 972 $This->_CheckGeometryAndFormalChargeMismatch($MethodName, $AtomSymbol, $AtomType, $NumOfNeighbors, $FormalCharge, 'linear', 1, 1); 973 last ATOMSYMBOL; 974 } 975 976 if ($AtomSymbol =~ /^Au$/) { 977 $AtomType = "Au4+3"; 978 $This->_CheckGeometryAndFormalChargeMismatch($MethodName, $AtomSymbol, $AtomType, $NumOfNeighbors, $FormalCharge, 'planar', 4, 3); 979 last ATOMSYMBOL; 980 } 981 982 $AtomType = 'None'; 983 } 984 985 return $AtomType; 986 } 987 988 # Get UFF atom type for atoms in periodic table group number 102.. 989 # 990 # Group number 12 contains: Zn, Cd, Hg 991 # 992 # And corresponding UFF atom types are: Zn3+2, Cd3+2, Hg1+2 993 # 994 sub _GetAtomTypeForOtherAtomsInGroupNumber12 { 995 my($This, $Atom) = @_; 996 my($AtomSymbol, $AtomType, $NumOfNeighbors, $FormalOxidationState, $FormalCharge, $MethodName); 997 998 $AtomType = 'None'; 999 $MethodName = '_GetAtomTypeForOtherAtomsInGroupNumber12'; 1000 1001 $AtomSymbol = $Atom->GetAtomSymbol(); 1002 ($NumOfNeighbors, $FormalOxidationState, $FormalCharge) = $This->_GetAtomEnvironmentInfoForUFFAtomTypes($Atom); 1003 1004 ATOMSYMBOL: { 1005 if ($AtomSymbol =~ /^(Zn|Cd)$/) { 1006 $AtomType = "${AtomSymbol}3+2"; 1007 $This->_CheckGeometryAndFormalChargeMismatch($MethodName, $AtomSymbol, $AtomType, $NumOfNeighbors, $FormalCharge, 'tetrahedral', 4, 2); 1008 last ATOMSYMBOL; 1009 } 1010 1011 if ($AtomSymbol =~ /^Hg$/) { 1012 $AtomType = "Hg1+2"; 1013 $This->_CheckGeometryAndFormalChargeMismatch($MethodName, $AtomSymbol, $AtomType, $NumOfNeighbors, $FormalCharge, 'linear', 1, 2); 1014 last ATOMSYMBOL; 1015 } 1016 1017 $AtomType = 'None'; 1018 } 1019 1020 return $AtomType; 1021 } 1022 1023 # Get UFF atom type for atoms in periodic table group number 13... 1024 # 1025 # Group number 13 contains: B, Al, Ga, In, Tl 1026 # 1027 # And corresponding UFF atom types are: B_3, B_2, Al3, Ga3+3, In3+3, Tl3+3 1028 # 1029 sub _GetAtomTypeForOtherAtomsInGroupNumber13 { 1030 my($This, $Atom) = @_; 1031 my($AtomSymbol, $AtomType, $NumOfNeighbors, $FormalOxidationState, $FormalCharge, $MethodName); 1032 1033 $AtomType = 'None'; 1034 $MethodName = '_GetAtomTypeForOtherAtomsInGroupNumber13'; 1035 1036 $AtomSymbol = $Atom->GetAtomSymbol(); 1037 ($NumOfNeighbors, $FormalOxidationState, $FormalCharge) = $This->_GetAtomEnvironmentInfoForUFFAtomTypes($Atom); 1038 1039 ATOMSYMBOL: { 1040 if ($AtomSymbol =~ /^B$/) { 1041 B: { 1042 if ($NumOfNeighbors == 4) { 1043 $AtomType = "B_3"; 1044 $This->_CheckGeometryAndFormalChargeMismatch($MethodName, $AtomSymbol, $AtomType, $NumOfNeighbors, $FormalCharge, 'tetrahedral', 4, 0); 1045 last B; 1046 } 1047 1048 if ($NumOfNeighbors == 3) { 1049 $AtomType = "B_2"; 1050 $This->_CheckGeometryAndFormalChargeMismatch($MethodName, $AtomSymbol, $AtomType, $NumOfNeighbors, $FormalCharge, 'trigonal', 3, 0); 1051 last B; 1052 } 1053 1054 # Assign default value... 1055 $AtomType = "B_2"; 1056 $This->_CheckGeometryAndFormalChargeMismatch($MethodName, $AtomSymbol, $AtomType, $NumOfNeighbors, $FormalCharge, 'trigonal', 3, 0); 1057 } 1058 1059 last ATOMSYMBOL; 1060 } 1061 1062 if ($AtomSymbol =~ /^Al$/) { 1063 $AtomType = "Al3"; 1064 $This->_CheckGeometryAndFormalChargeMismatch($MethodName, $AtomSymbol, $AtomType, $NumOfNeighbors, $FormalCharge, 'tetrahedral', 4, 0); 1065 last ATOMSYMBOL; 1066 } 1067 1068 if ($AtomSymbol =~ /^(Ga|In|Tl)$/) { 1069 $AtomType = "${AtomSymbol}3+3"; 1070 $This->_CheckGeometryAndFormalChargeMismatch($MethodName, $AtomSymbol, $AtomType, $NumOfNeighbors, $FormalCharge, 'tetrahedral', 4, 3); 1071 last ATOMSYMBOL; 1072 } 1073 1074 $AtomType = 'None'; 1075 } 1076 1077 return $AtomType; 1078 } 1079 1080 # Get UFF atom type for atoms in periodic table group number 14... 1081 # 1082 # Group number 14 contains: C, Si, Ge, Sn, Pb 1083 # 1084 # And corresponding UFF atom types are: Si3, Ge3, Sn3, Pb3 1085 # 1086 # Notes: 1087 # . This method doesn't assign UFF atom type for C. 1088 # 1089 sub _GetAtomTypeForOtherAtomsInGroupNumber14 { 1090 my($This, $Atom) = @_; 1091 my($AtomSymbol, $AtomType, $NumOfNeighbors, $FormalOxidationState, $FormalCharge, $MethodName); 1092 1093 $AtomType = 'None'; 1094 $MethodName = '_GetAtomTypeForOtherAtomsInGroupNumber14'; 1095 1096 $AtomSymbol = $Atom->GetAtomSymbol(); 1097 ($NumOfNeighbors, $FormalOxidationState, $FormalCharge) = $This->_GetAtomEnvironmentInfoForUFFAtomTypes($Atom); 1098 1099 ATOMSYMBOL: { 1100 if ($AtomSymbol =~ /^(Si|Ge|Sn|Pb)$/) { 1101 $AtomType = "${AtomSymbol}3"; 1102 $This->_CheckGeometryAndFormalChargeMismatch($MethodName, $AtomSymbol, $AtomType, $NumOfNeighbors, $FormalCharge, 'tetrahedral', 4, 0); 1103 last ATOMSYMBOL; 1104 } 1105 1106 $AtomType = 'None'; 1107 } 1108 1109 return $AtomType; 1110 } 1111 1112 # Get UFF atom type for atoms in periodic table group number 15... 1113 # 1114 # Group number 15 contains: N, P, As, Sb, Bi 1115 # 1116 # And corresponding UFF atom types are: As3+3, Sb3+3, Bi3+3 1117 # 1118 # Notes: 1119 # . This method doesn't assign UFF atom type for N and P. 1120 # 1121 sub _GetAtomTypeForOtherAtomsInGroupNumber15 { 1122 my($This, $Atom) = @_; 1123 my($AtomSymbol, $AtomType, $NumOfNeighbors, $FormalOxidationState, $FormalCharge, $MethodName); 1124 1125 $AtomType = 'None'; 1126 $MethodName = '_GetAtomTypeForOtherAtomsInGroupNumber15'; 1127 1128 $AtomSymbol = $Atom->GetAtomSymbol(); 1129 ($NumOfNeighbors, $FormalOxidationState, $FormalCharge) = $This->_GetAtomEnvironmentInfoForUFFAtomTypes($Atom); 1130 1131 ATOMSYMBOL: { 1132 if ($AtomSymbol =~ /^(As|Sb|Bi)$/) { 1133 $AtomType = "${AtomSymbol}3+3"; 1134 $This->_CheckGeometryAndOxidationStateMismatch($MethodName, $AtomSymbol, $AtomType, $NumOfNeighbors, $FormalOxidationState, 'tetrahedral', 3, 3); 1135 last ATOMSYMBOL; 1136 } 1137 1138 $AtomType = 'None'; 1139 } 1140 1141 return $AtomType; 1142 } 1143 1144 # Get UFF atom type for atoms in periodic table group number 16... 1145 # 1146 # Group number 16 contains: O, S, Se, Te, Po 1147 # 1148 # And corresponding UFF atom types are: Se3+2, Te3+2, Po3+2 1149 # 1150 # Notes: 1151 # . This method doesn't assign UFF atom type for O and S. 1152 # 1153 sub _GetAtomTypeForOtherAtomsInGroupNumber16 { 1154 my($This, $Atom) = @_; 1155 my($AtomSymbol, $AtomType, $NumOfNeighbors, $FormalOxidationState, $FormalCharge, $MethodName); 1156 1157 $AtomType = 'None'; 1158 $MethodName = '_GetAtomTypeForOtherAtomsInGroupNumber16'; 1159 1160 $AtomSymbol = $Atom->GetAtomSymbol(); 1161 ($NumOfNeighbors, $FormalOxidationState, $FormalCharge) = $This->_GetAtomEnvironmentInfoForUFFAtomTypes($Atom); 1162 1163 ATOMSYMBOL: { 1164 if ($AtomSymbol =~ /^(Se|Te|Po)$/) { 1165 $AtomType = "${AtomSymbol}3+2"; 1166 $This->_CheckGeometryAndOxidationStateMismatch($MethodName, $AtomSymbol, $AtomType, $NumOfNeighbors, $FormalOxidationState, 'tetrahedral', 2, 2); 1167 last ATOMSYMBOL; 1168 } 1169 1170 $AtomType = 'None'; 1171 } 1172 1173 return $AtomType; 1174 } 1175 1176 # Get UFF atom type for atoms in periodic table group number 17... 1177 # 1178 # Group number 17 contains: F, Cl, Br, I, At 1179 # 1180 # And corresponding UFF atom types are: F_, Cl, Br, I_, At 1181 # 1182 sub _GetAtomTypeForOtherAtomsInGroupNumber17 { 1183 my($This, $Atom) = @_; 1184 my($AtomType, $AtomSymbol); 1185 1186 $AtomSymbol = $Atom->GetAtomSymbol(); 1187 $AtomType = (length($AtomSymbol) == 1) ? "${AtomSymbol}_" : $AtomSymbol; 1188 1189 return $AtomType; 1190 } 1191 1192 # Get UFF atom type for atoms in periodic table group number 18... 1193 # 1194 # Group number 18 contains: He, Ne, Ar, Kr, Xe, Rn 1195 # 1196 # And corresponding UFF atom types are: He4+4, Ne4+4, Ar4+4, Kr4+4, Xe4+4, Rn4+4 1197 # 1198 sub _GetAtomTypeForOtherAtomsInGroupNumber18 { 1199 my($This, $Atom) = @_; 1200 my($AtomSymbol, $AtomType); 1201 1202 $AtomType = 'None'; 1203 1204 $AtomSymbol = $Atom->GetAtomSymbol(); 1205 $AtomType = "${AtomSymbol}4+4"; 1206 1207 return $AtomType; 1208 } 1209 1210 # Get UFF atom type for atoms in periodic table group name Lanthanoid... 1211 # 1212 # Group name Lanthanoid contains: La, Ce, Pr, Nd, Pm, Sm, Eu, Gd, Tb, Dy, Ho, Er, Tm, Yb, Lu 1213 # 1214 # And corresponding UFF atom types are: La3+3, Ce6+3, Pr6+3, Nd6+3, Pm6+3, Sm6+3, 1215 # Eu6+3, Gd6+3, Tb6+3, Dy6+3, Ho6+3, Er6+3, Tm6+3, Yb6+3, Lu6+3 1216 # 1217 sub _GetAtomTypeForOtherAtomsInLanthanoidGroup { 1218 my($This, $Atom) = @_; 1219 my($AtomSymbol, $AtomType, $NumOfNeighbors, $FormalOxidationState, $FormalCharge, $MethodName); 1220 1221 $AtomType = 'None'; 1222 $MethodName = '_GetAtomTypeForOtherAtomsInLanthanoidGroup'; 1223 1224 $AtomSymbol = $Atom->GetAtomSymbol(); 1225 ($NumOfNeighbors, $FormalOxidationState, $FormalCharge) = $This->_GetAtomEnvironmentInfoForUFFAtomTypes($Atom); 1226 1227 ATOMSYMBOL: { 1228 if ($AtomSymbol =~ /^La$/) { 1229 $AtomType = "La3+3"; 1230 $This->_CheckGeometryAndFormalChargeMismatch($MethodName, $AtomSymbol, $AtomType, $NumOfNeighbors, $FormalCharge, 'tetrahedral', 4, 3); 1231 last ATOMSYMBOL; 1232 } 1233 1234 $AtomType = "${AtomSymbol}6+3"; 1235 $This->_CheckGeometryAndFormalChargeMismatch($MethodName, $AtomSymbol, $AtomType, $NumOfNeighbors, $FormalCharge, 'octahedral', 6, 3); 1236 } 1237 1238 return $AtomType; 1239 1240 } 1241 1242 # Get UFF atom type for atoms in periodic table group name Actinoid... 1243 # 1244 # Group name Actinoid contains: Ac, Th, Pa, U, Np, Pu, Am, Cm, Bk, Cf, Es, Fm, Md, No, Lr 1245 # 1246 # And corresponding UFF atom types are: Ac6+3, Th6+4, Pa6+4, U_6+4, Np6+4, Pu6+4, 1247 # Am6+4, Cm6+3, Bk6+3, Cf6+3, Es6+3, Fm6+3, Md6+3, No6+3, Lr6+3 1248 # 1249 sub _GetAtomTypeForOtherAtomsInActinoidGroup { 1250 my($This, $Atom) = @_; 1251 my($AtomSymbol, $AtomType, $NumOfNeighbors, $FormalOxidationState, $FormalCharge, $MethodName); 1252 1253 $AtomType = 'None'; 1254 $MethodName = '_GetAtomTypeForOtherAtomsInActinoidGroup'; 1255 1256 $AtomSymbol = $Atom->GetAtomSymbol(); 1257 ($NumOfNeighbors, $FormalOxidationState, $FormalCharge) = $This->_GetAtomEnvironmentInfoForUFFAtomTypes($Atom); 1258 1259 ATOMSYMBOL: { 1260 if ($AtomSymbol =~ /^(Ac|Cm|Bk|Cf|Es|Fm|Md|No|Lr)$/) { 1261 $AtomType = "${AtomSymbol}6+3"; 1262 $This->_CheckGeometryAndOxidationStateMismatch($MethodName, $AtomSymbol, $AtomType, $NumOfNeighbors, $FormalOxidationState, 'octahedral', 6, 3); 1263 last ATOMSYMBOL; 1264 } 1265 1266 if ($AtomSymbol =~ /^(Th|Pa|U|Np|Pu|Am)$/) { 1267 $AtomType = length($AtomSymbol) == 1 ? "${AtomSymbol}_6+4" : "${AtomSymbol}6+4"; 1268 $This->_CheckGeometryAndOxidationStateMismatch($MethodName, $AtomSymbol, $AtomType, $NumOfNeighbors, $FormalOxidationState, 'octahedral', 6, 4); 1269 last ATOMSYMBOL; 1270 } 1271 1272 $AtomType = 'None'; 1273 } 1274 1275 return $AtomType; 1276 } 1277 1278 1279 # Is it a four-coordinated Phosphorus for describing organometallic coordinated phosphines? 1280 # 1281 sub _IsFourCoordinatedOrganometallicPhosphorus { 1282 my($This, $Atom) = @_; 1283 my($AtomNeighbor, $NumOfNeighbors, $MetalNeighborFound, @AtomNeighbors); 1284 1285 @AtomNeighbors = $Atom->GetHeavyAtomNeighbors(); 1286 1287 # Is it attached to a metallic atom? 1288 $MetalNeighborFound = 0; 1289 NEIGHBOR: for $AtomNeighbor (@AtomNeighbors) { 1290 if ($AtomNeighbor->IsMetallic()) { 1291 $MetalNeighborFound = 1; 1292 last NEIGHBOR; 1293 } 1294 } 1295 1296 if (!$MetalNeighborFound) { 1297 return 0; 1298 } 1299 1300 # Is it four coordinated Phosphorus? 1301 $NumOfNeighbors = scalar @AtomNeighbors; 1302 if ($NumOfNeighbors <= 4) { 1303 # As long as total number of heavy atom neighbors, including attached 1304 # metal atom is <= 4, missing hydrogens would make it a tetra coordinated 1305 # Phosphorous... 1306 return 1; 1307 } 1308 1309 return 0; 1310 } 1311 1312 # Get UFF atom environment information, number of neighbors and formal oxidatiion state, 1313 # for assigning UFF atom types... 1314 # 1315 sub _GetAtomEnvironmentInfoForUFFAtomTypes { 1316 my($This, $Atom) = @_; 1317 my($NumOfNeighbors, $NumOfHydrogens, $FormalOxidationState, $FormalCharge); 1318 1319 $NumOfHydrogens = $Atom->GetNumOfMissingHydrogens() + $Atom->GetExplicitHydrogens(); 1320 1321 # Total number of neighbor atoms... 1322 $NumOfNeighbors = $Atom->GetNumOfNonHydrogenAtomNeighbors() + $NumOfHydrogens; 1323 1324 # UFF formal oxidation state appears to just the sum of bond orders to all attched non-hyrdogen 1325 # atoms and all hydrogen atoms... 1326 # 1327 $FormalOxidationState = $Atom->GetSumOfBondOrdersToNonHydrogenAtoms() + $NumOfHydrogens; 1328 1329 # Any explicit formal charge... 1330 $FormalCharge = $Atom->GetFormalCharge(); 1331 1332 return ($NumOfNeighbors, $FormalOxidationState, $FormalCharge); 1333 } 1334 1335 # Check and warn about any geometry and/or formal charge mismatch... 1336 # 1337 sub _CheckGeometryAndFormalChargeMismatch { 1338 my($This, $CallingMethod, $AtomSymbol, $AssignedAtomType, $NumOfNeighbors, $FormalCharge, $ExpectedGeometryType, $ExpectedNumOfNeighbors, $ExpectedFormalCharge) = @_; 1339 my($MsgHeader); 1340 1341 $MsgHeader = "Warning: ${ClassName}->${CallingMethod}:_CheckGeometryAndFormalChargeMismatch"; 1342 1343 if ($NumOfNeighbors !=$ExpectedNumOfNeighbors && $FormalCharge != $ExpectedFormalCharge) { 1344 carp "\n${MsgHeader}: UFF atom type for $AtomSymbol corresponding to $ExpectedGeometryType geometry and formal charge $ExpectedFormalCharge cann't be assigned; Number of neighbors, $NumOfNeighbors, is different from $ExpectedNumOfNeighbors and formal charge, $FormalCharge, is different from $ExpectedFormalCharge. Default UFF atom type, $AssignedAtomType, has been assigned..."; 1345 } 1346 elsif ($NumOfNeighbors !=$ExpectedNumOfNeighbors) { 1347 carp "\n${MsgHeader}: UFF atom type for $AtomSymbol corresponding to $ExpectedGeometryType geometry and formal charge $ExpectedFormalCharge cann't be assigned; Number of neighbors, $NumOfNeighbors, is different from $ExpectedNumOfNeighbors. Default UFF atom type, $AssignedAtomType, has been assigned..."; 1348 } 1349 elsif ($FormalCharge != $ExpectedFormalCharge) { 1350 carp "\n${MsgHeader}: UFF atom type for $AtomSymbol corresponding to $ExpectedGeometryType geometry and formal charge $ExpectedFormalCharge cann't be assigned; Formal charge, $FormalCharge, is different from $ExpectedFormalCharge. Default UFF atom type, $AssignedAtomType, has been assigned..."; 1351 } 1352 } 1353 1354 # Check and warn about any geometry and/or formal oxidation state mismatch... 1355 # 1356 sub _CheckGeometryAndOxidationStateMismatch { 1357 my($This, $CallingMethod, $AtomSymbol, $AssignedAtomType, $NumOfNeighbors, $FormalOxidationState, $ExpectedGeometryType, $ExpectedNumOfNeighbors, $ExpectedFormalOxidationState) = @_; 1358 my($MsgHeader); 1359 1360 $MsgHeader = "Warning: ${ClassName}->${CallingMethod}:_CheckGeometryAndOxidationStateMismatch"; 1361 1362 if ($NumOfNeighbors !=$ExpectedNumOfNeighbors && $FormalOxidationState != $ExpectedFormalOxidationState) { 1363 carp "\n${MsgHeader}: UFF atom type for $AtomSymbol corresponding to $ExpectedGeometryType geometry and formal oxidation state $ExpectedFormalOxidationState cann't be assigned; Number of neighbors, $NumOfNeighbors, is different from $ExpectedNumOfNeighbors and formal oxidation state, $FormalOxidationState, is different from $ExpectedFormalOxidationState. Default UFF atom type, $AssignedAtomType, has been assigned..."; 1364 } 1365 elsif ($NumOfNeighbors !=$ExpectedNumOfNeighbors) { 1366 carp "\n${MsgHeader}: UFF atom type for $AtomSymbol corresponding to $ExpectedGeometryType geometry and formal oxidation state $ExpectedFormalOxidationState cann't be assigned; Number of neighbors, $NumOfNeighbors, is different from $ExpectedNumOfNeighbors. Default UFF atom type, $AssignedAtomType, has been assigned..."; 1367 } 1368 elsif ($FormalOxidationState != $ExpectedFormalOxidationState) { 1369 carp "\n${MsgHeader}: UFF atom type for $AtomSymbol corresponding to $ExpectedGeometryType geometry and formal oxidation state $ExpectedFormalOxidationState cann't be assigned; Formal oxidation state, $FormalOxidationState, is different from $ExpectedFormalOxidationState. Default UFF atom type, $AssignedAtomType, has been assigned..."; 1370 } 1371 } 1372 1373 1374 # Return a string containg data for UFFAtomTypes object... 1375 # 1376 sub StringifyUFFAtomTypes { 1377 my($This) = @_; 1378 my($AtomTypesString); 1379 1380 # Type of AtomTypes... 1381 $AtomTypesString = "AtomTypes: $This->{Type}; IgnoreHydrogens: " . ($This->{IgnoreHydrogens} ? "Yes" : "No"); 1382 1383 # Setup atom types information... 1384 my($AtomID, $AtomType, @AtomTypesInfo, %AssignedAtomTypes); 1385 1386 @AtomTypesInfo = (); 1387 %AssignedAtomTypes = $This->GetAtomTypes(); 1388 1389 for $AtomID (sort { $a <=> $b } keys %AssignedAtomTypes) { 1390 $AtomType = $AssignedAtomTypes{$AtomID} ? $AssignedAtomTypes{$AtomID} : 'None'; 1391 push @AtomTypesInfo, "$AtomID:$AtomType"; 1392 } 1393 $AtomTypesString .= "; AtomIDs:AtomTypes: <" . TextUtil::JoinWords(\@AtomTypesInfo, ", ", 0) . ">"; 1394 1395 return $AtomTypesString; 1396 } 1397 1398 # Is it a UFFAtomTypes object? 1399 sub _IsUFFAtomTypes { 1400 my($Object) = @_; 1401 1402 return (Scalar::Util::blessed($Object) && $Object->isa($ClassName)) ? 1 : 0; 1403 } 1404 1405 # Check and load UFF atom types data... 1406 # 1407 sub _CheckAndLoadUFFAtomTypesData { 1408 1409 # Is it already loaded? 1410 if (exists $UFFAtomTypesDataMap{AtomTypes}) { 1411 return; 1412 } 1413 1414 _LoadUFFAtomTypesData(); 1415 } 1416 1417 # Load UFF atom types data from the file assuming first column to be atom type symbol.. 1418 # 1419 # Format: 1420 # 1421 # "AtomType","Mass","ValenceBondRadius","ValenceAngle","NonBondRadius","NonBondEnergy","NonBondScale","EffectiveCharge","SP3TorsionalBarrier" 1422 # "H_","1.0080","0.354","180.000","2.886","0.044","12.000","0.733","0.000" 1423 # "C_3","12.0110","0.757","109.471","3.851","0.105","12.730","1.967","2.119" 1424 # "C_R","12.0110","0.729","120.000","3.851","0.105","12.730","1.967","0.000" 1425 # "C_2","12.0110","0.732","120.000","3.851","0.105","12.730","1.967","0.000" 1426 # "C_1","12.0110","0.711","180.000","3.851","0.105","12.730","1.967","0.000" 1427 # 1428 sub _LoadUFFAtomTypesData { 1429 my($AtomTypesDataFile, $MayaChemToolsLibDir); 1430 1431 $MayaChemToolsLibDir = FileUtil::GetMayaChemToolsLibDirName(); 1432 1433 $AtomTypesDataFile = "$MayaChemToolsLibDir" . "/data/UFFAtomTypes.csv"; 1434 if (! -e "$AtomTypesDataFile") { 1435 croak "Error: MayaChemTools package file, $AtomTypesDataFile, is missing: Possible installation problems..."; 1436 } 1437 1438 %UFFAtomTypesDataMap = (); 1439 AtomTypes::AtomTypes::LoadAtomTypesData($AtomTypesDataFile, \%UFFAtomTypesDataMap); 1440 } 1441