diff --git a/documentation/source/reference/molecule/atomtype.rst b/documentation/source/reference/molecule/atomtype.rst index a3394c44f0..d6a6509d22 100644 --- a/documentation/source/reference/molecule/atomtype.rst +++ b/documentation/source/reference/molecule/atomtype.rst @@ -86,6 +86,28 @@ Atom type Description ``Sit`` silicon atom with one triple bond and one single bond ``Sib`` silicon atom with two benzene bonds and one single bond ``Sibf`` silicon atom with three benzene bonds +*Phosphorus atom types* +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ +``P`` phosphorus atom with any local bond structure +``P0sc`` charged phosphorus atom with three lone pairs (valence 0) and up to 1 single bond +``P1s`` phosphorus atom with two lone pairs (valence 1) and up to 1 single bond +``P1sc`` charged phosphorus atom with two lone pairs (valence 1) and up to 2 single bonds +``P1dc`` charged phosphorus atom with two lone pairs (valence 1) and 1 double bond +``P3s`` phosphorus atom with one lone pair (valence 3) and up to 3 single bonds +``P3d`` phosphorus atom with one lone pair (valence 3), 1 double bond and up to 1 single bond +``P3t`` phosphorus atom with one lone pair (valence 3) and 1 triple bond +``P3b`` phosphorus atom with one lone pair (valence 3) and 2 benzene bonds +``P5s`` phosphorus atom with no lone pairs (valence 5) and up to 5 single bonds +``P5sc`` charged phosphorus atom with no lone pairs (valence 5) and up to 6 single bonds +``P5d`` phosphorus atom with no lone pairs (valence 5), 1 double bond and up to 3 single bonds +``P5dd`` phosphorus atom with no lone pairs (valence 5), 2 double bonds and up to 1 single bond +``P5dc`` charged phosphorus atom with no lone pairs (valence 5), 1 double bond and up to 2 single bonds +``P5ddc`` charged phosphorus atom with no lone pairs (valence 5) and 2 double bonds +``P5t`` phosphorus atom with no lone pairs (valence 5), 1 triple bond and up to 2 single bonds +``P5td`` phosphorus atom with no lone pairs (valence 5), 1 triple bond and 1 double bond +``P5tc`` charged phosphorus atom with no lone pairs (valence 5), 1 triple bond and up to 1 single bond +``P5b`` phosphorus atom with no lone pairs (valence 5), 2 benzene bonds and up to 1 single bond +``P5bd`` phosphorus atom with no lone pairs (valence 5), 2 benzene bonds and 1 double bond *Sulfur atom types* ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ ``S`` sulfur atom with any local bond structure diff --git a/documentation/source/users/rmg/database/introduction.rst b/documentation/source/users/rmg/database/introduction.rst index b5d339816c..11ac0a4519 100644 --- a/documentation/source/users/rmg/database/introduction.rst +++ b/documentation/source/users/rmg/database/introduction.rst @@ -135,6 +135,46 @@ table below shows all atoms types in RMG. +----------+-------------------+------------------------------------------------------------------------------------------------------------------+ |Sibf |Silicon |Three benzene bonds (fused aromatics) | +----------+-------------------+------------------------------------------------------------------------------------------------------------------+ +|P |Phosphorus |No requirements | ++----------+-------------------+------------------------------------------------------------------------------------------------------------------+ +|P0sc |Phosphorus |Three lone pairs, up to one single bond, charged -2 | ++----------+-------------------+------------------------------------------------------------------------------------------------------------------+ +|P1s |Phosphorus |Two lone pairs, up to one single bond | ++----------+-------------------+------------------------------------------------------------------------------------------------------------------+ +|P1sc |Phosphorus |Two lone pairs, up to two single bonds, charged -1 | ++----------+-------------------+------------------------------------------------------------------------------------------------------------------+ +|P1dc |Phosphorus |Two lone pairs, one double bond, charged -1 | ++----------+-------------------+------------------------------------------------------------------------------------------------------------------+ +|P3s |Phosphorus |One lone pair, up to three single bonds | ++----------+-------------------+------------------------------------------------------------------------------------------------------------------+ +|P3d |Phosphorus |One lone pair, one double bond, up to one single bond | ++----------+-------------------+------------------------------------------------------------------------------------------------------------------+ +|P3t |Phosphorus |One lone pair, one triple bond | ++----------+-------------------+------------------------------------------------------------------------------------------------------------------+ +|P3b |Phosphorus |One lone pair, two aromatic bonds | ++----------+-------------------+------------------------------------------------------------------------------------------------------------------+ +|P5s |Phosphorus |No lone pairs, up to five single bonds | ++----------+-------------------+------------------------------------------------------------------------------------------------------------------+ +|P5sc |Phosphorus |No lone pairs, up to six single bonds, charged -1/+1/+2 | ++----------+-------------------+------------------------------------------------------------------------------------------------------------------+ +|P5d |Phosphorus |No lone pairs, one double bond, up to three single bonds | ++----------+-------------------+------------------------------------------------------------------------------------------------------------------+ +|P5dd |Phosphorus |No lone pairs, two double bonds, up to one single bond | ++----------+-------------------+------------------------------------------------------------------------------------------------------------------+ +|P5dc |Phosphorus |No lone pairs, one double bond, up to two single bonds, charged +1 | ++----------+-------------------+------------------------------------------------------------------------------------------------------------------+ +|P5ddc |Phosphorus |No lone pairs, two double bonds, charged +1 | ++----------+-------------------+------------------------------------------------------------------------------------------------------------------+ +|P5t |Phosphorus |No lone pairs, one triple bond, up to two single bonds | ++----------+-------------------+------------------------------------------------------------------------------------------------------------------+ +|P5td |Phosphorus |No lone pairs, one triple bond, one double bond | ++----------+-------------------+------------------------------------------------------------------------------------------------------------------+ +|P5tc |Phosphorus |No lone pairs, one triple bond, up to one single bond, charged +1 | ++----------+-------------------+------------------------------------------------------------------------------------------------------------------+ +|P5b |Phosphorus |No lone pairs, two aromatic bonds, up to one single bond, charged 0/+1 | ++----------+-------------------+------------------------------------------------------------------------------------------------------------------+ +|P5bd |Phosphorus |No lone pairs, two aromatic bonds, one double bond | ++----------+-------------------+------------------------------------------------------------------------------------------------------------------+ |S |Sulfur |No requirements | +----------+-------------------+------------------------------------------------------------------------------------------------------------------+ |Sa |Sulfur |Atomic sulfur with three lone pairs and no bonds | diff --git a/rmgpy/molecule/atomtype.py b/rmgpy/molecule/atomtype.py index 45951af6f9..265af1192d 100644 --- a/rmgpy/molecule/atomtype.py +++ b/rmgpy/molecule/atomtype.py @@ -262,6 +262,7 @@ def get_features(self): 'N','N0sc','N1s','N1sc','N1dc','N3s','N3sc','N3d','N3t','N3b','N5sc','N5dc','N5ddc','N5dddc','N5tc','N5b','N5bd', 'O','Oa','O0sc','O2s','O2sc','O2d','O4sc','O4dc','O4tc','O4b', 'Si','Sis','Sid','Sidd','Sit','SiO','Sib','Sibf','Siq', + 'P','P0sc','P1s','P1sc','P1dc','P3s','P3d','P3t','P3b','P5s','P5sc','P5d','P5dd','P5dc','P5ddc','P5t','P5td','P5tc','P5b','P5bd', 'S','Sa','S0sc','S2s','S2sc','S2d','S2dc','S2tc','S4s','S4sc','S4d','S4dd','S4dc','S4b','S4t','S4tdc','S6s','S6sc','S6d','S6dd','S6ddd','S6dc','S6t','S6td','S6tt','S6tdc', 'Cl','Cl1s', 'Br','Br1s', @@ -275,6 +276,7 @@ def get_features(self): 'N','N0sc','N1s','N1sc','N1dc','N3s','N3sc','N3d','N3t','N3b','N5sc','N5dc','N5ddc','N5dddc','N5tc','N5b','N5bd', 'O','Oa','O0sc','O2s','O2sc','O2d','O4sc','O4dc','O4tc','O4b', 'Si','Sis','Sid','Sidd','Sit','SiO','Sib','Sibf','Siq', + 'P','P0sc','P1s','P1sc','P1dc','P3s','P3d','P3t','P3b','P5s','P5sc','P5d','P5dd','P5dc','P5ddc','P5t','P5td','P5tc','P5b','P5bd', 'S','Sa','S0sc','S2s','S2sc','S2d','S2dc','S2tc','S4s','S4sc','S4d','S4dd','S4dc','S4b','S4t','S4tdc','S6s','S6sc','S6d','S6dd','S6ddd','S6dc','S6t','S6td','S6tt','S6tdc', 'Cl','Cl1s', 'Br','Br1s', @@ -286,7 +288,8 @@ def get_features(self): 'Si','Sis','Sid','Sidd','Sit','SiO','Sib','Sibf','Siq']) ATOMTYPES['Val5'] = AtomType(label='Val5', generic=['R', 'R!H'], specific=[ - 'N','N0sc','N1s','N1sc','N1dc','N3s','N3sc','N3d','N3t','N3b','N5sc','N5dc','N5ddc','N5dddc','N5tc','N5b','N5bd']) + 'N','N0sc','N1s','N1sc','N1dc','N3s','N3sc','N3d','N3t','N3b','N5sc','N5dc','N5ddc','N5dddc','N5tc','N5b','N5bd', + 'P','P0sc','P1s','P1sc','P1dc','P3s','P3d','P3t','P3b','P5s','P5sc','P5d','P5dd','P5dc','P5ddc','P5t','P5td','P5tc','P5b','P5bd']) ATOMTYPES['Val6'] = AtomType(label='Val6', generic=['R', 'R!H'], specific=[ 'O','Oa','O0sc','O2s','O2sc','O2d','O4sc','O4dc','O4tc','O4b', @@ -437,7 +440,7 @@ def get_features(self): # examples for O4tc: [C-]#[O+] ATOMTYPES['O4b'] = AtomType('O4b', generic=['R', 'R!H', 'O', 'Val6'], specific=[], single=[0], all_double=[0], r_double=[0], o_double=[0], s_double=[0], triple=[0], quadruple=[], benzene=[2], lone_pairs=[1], charge=[0]) -# examples for S4b: Furane, Benzofurane, Benzo[c]thiophene, Oxazole... +# examples for O4b: Furane, Benzofurane, Oxazole... ATOMTYPES['Ne'] = AtomType('Ne', generic=['R', 'R!H'], specific=[]) ATOMTYPES['Si'] = AtomType('Si', generic=['R', 'R!H', 'Val4'], specific=['Sis', 'Sid', 'Sidd', 'Sit', 'SiO', 'Sib', 'Sibf', 'Siq'], @@ -459,6 +462,66 @@ def get_features(self): ATOMTYPES['Siq'] = AtomType('Siq', generic=['R', 'R!H', 'Si', 'Val4'], specific=[], single=[0], all_double=[0], r_double=[0], o_double=[0], s_double=[0], triple=[0], quadruple=[1], benzene=[0], lone_pairs=[], charge=[]) +ATOMTYPES['P'] = AtomType('P', generic=['R', 'R!H', 'Val5'], specific=['P0sc', 'P1s', 'P1sc', 'P1dc', 'P3s', 'P3d', 'P3t', 'P3b', 'P5s', 'P5sc', 'P5d', 'P5dd', 'P5dc', 'P5ddc', 'P5t', 'P5td', 'P5tc', 'P5b', 'P5bd'], + single=[], all_double=[], r_double=[], o_double=[], s_double=[], triple=[], quadruple=[], benzene=[], lone_pairs=[], charge=[]) +ATOMTYPES['P0sc'] = AtomType('P0sc', generic=['R', 'R!H', 'P', 'Val5'], specific=[], + single=[0,1], all_double=[0], r_double=[0], o_double=[0], s_double=[0], triple=[0], quadruple=[], benzene=[0], lone_pairs=[3], charge=[-2]) +# examples for P0sc: [PH-2] (Phosphanediide), [P-2][P+]#[PH+] with adjList '''1 P u0 p3 c-2 {2,S} 2 P u0 p0 c+1 {1,S} {3,T} 3 P u0 p0 c+1 {2,T} {4,S} 4 H u0 p0 c0 {3,S}''' +ATOMTYPES['P1s'] = AtomType('P1s', generic=['R', 'R!H', 'P', 'Val5'], specific=[], + single=[0,1], all_double=[0], r_double=[0], o_double=[0], s_double=[0], triple=[0], quadruple=[], benzene=[0], lone_pairs=[2], charge=[0]) +# examples for P1s: closed shell [PH] (Phosphinidene) +ATOMTYPES['P1sc'] = AtomType('P1sc', generic=['R', 'R!H', 'P', 'Val5'], specific=[], + single=[0,1,2], all_double=[0], r_double=[], o_double=[], s_double=[], triple=[0], quadruple=[], benzene=[0], lone_pairs=[2], charge=[-1]) +# examples for P1sc: C[PH-] (methylphosphanide) +ATOMTYPES['P1dc'] = AtomType('P1dc', generic=['R', 'R!H', 'P', 'Val5'], specific=[], + single=[0], all_double=[1], r_double=[], o_double=[], s_double=[], triple=[0], quadruple=[], benzene=[0], lone_pairs=[2], charge=[-1]) +# examples for P1dc: C=[P-] (methylidenephosphanide) +ATOMTYPES['P3s'] = AtomType('P3s', generic=['R', 'R!H', 'P', 'Val5'], specific=[], + single=[0,1,2,3], all_double=[0], r_double=[0], o_double=[0], s_double=[0], triple=[0], quadruple=[], benzene=[0], lone_pairs=[1], charge=[0]) +# examples for P3s: PH3, PCl3 +ATOMTYPES['P3d'] = AtomType('P3d', generic=['R', 'R!H', 'P', 'Val5'], specific=[], + single=[0,1], all_double=[1], r_double=[], o_double=[], s_double=[], triple=[0], quadruple=[], benzene=[0], lone_pairs=[1], charge=[0]) +# examples for P3d: O=[PH] with adjList '''1 O u0 p2 c0 {2,D} 2 P u0 p1 c0 {1,D} {3,S} 3 H u0 p0 c0 {2,S}''' +ATOMTYPES['P3t'] = AtomType('P3t', generic=['R', 'R!H', 'P', 'Val5'], specific=[], + single=[0], all_double=[0], r_double=[0], o_double=[0], s_double=[0], triple=[1], quadruple=[], benzene=[0], lone_pairs=[1], charge=[0]) +# examples for P3t: P#P (diphosphorus) +ATOMTYPES['P3b'] = AtomType('P3b', generic=['R', 'R!H', 'P', 'Val5'], specific=[], + single=[0], all_double=[0], r_double=[0], o_double=[0], s_double=[0], triple=[0], quadruple=[], benzene=[2], lone_pairs=[1], charge=[0]) +# examples for P3b: c1ccpcc1 (phosphorine) with InChI 'InChI=1S/C5H5P/c1-2-4-6-5-3-1/h1-5H' +ATOMTYPES['P5s'] = AtomType('P5s', generic=['R', 'R!H', 'P', 'Val5'], specific=[], + single=[0,1,2,3,4,5], all_double=[0], r_double=[0], o_double=[0], s_double=[0], triple=[0], quadruple=[0], benzene=[0], lone_pairs=[0], charge=[0]) +# examples for P5s: P(Cl)(Cl)(Cl)(Cl)Cl (phosphorus pentachloride) +ATOMTYPES['P5sc'] = AtomType('P5sc', generic=['R', 'R!H', 'P', 'Val5'], specific=[], + single=[0,1,2,3,4,5,6], all_double=[0], r_double=[0], o_double=[0], s_double=[0], triple=[0], benzene=[0], lone_pairs=[0], charge=[-1, +1, +2]) +# examples for P5sc: [O-][PH3+] (oxidophosphanium), F[P-](F)(F)(F)(F)F (Hexafluorophosphate) +ATOMTYPES['P5d'] = AtomType('P5d', generic=['R', 'R!H', 'P', 'Val5'], specific=[], + single=[0,1,2,3], all_double=[1], r_double=[], o_double=[], s_double=[], triple=[0], quadruple=[0], benzene=[0], lone_pairs=[0], charge=[0]) +# examples for P5d: OP(=O)(O)O (phosphoric acid) +ATOMTYPES['P5dd'] = AtomType('P5dd', generic=['R', 'R!H', 'P', 'Val5'], specific=[], + single=[0,1], all_double=[2], r_double=[], o_double=[], s_double=[], triple=[0], quadruple=[0], benzene=[0], lone_pairs=[0], charge=[0]) +# examples for P5dd: CP(=O)=O (methylphosphinate) +ATOMTYPES['P5dc'] = AtomType('P5dc', generic=['R', 'R!H', 'P', 'Val5'], specific=[], + single=[0,1,2], all_double=[1], r_double=[], o_double=[], s_double=[], triple=[0], quadruple=[], benzene=[0], lone_pairs=[0], charge=[+1]) +# examples for P5dc: C=C[P+](=N)[O-] (ethenyl-imino-oxidophosphanium), C[P+](=C)C (methylenedimethylphosphorane) +ATOMTYPES['P5ddc'] = AtomType('P5ddc', generic=['R', 'R!H', 'P', 'Val5'], specific=[], + single=[0], all_double=[2], r_double=[], o_double=[], s_double=[], triple=[0], quadruple=[], benzene=[0], lone_pairs=[0], charge=[+1]) +# examples for P5ddc: C=[P+]=N (imino(methylidene)phosphanium) +ATOMTYPES['P5t'] = AtomType('P5t', generic=['R', 'R!H', 'P', 'Val5'], specific=[], + single=[0,1,2], all_double=[0], r_double=[], o_double=[], s_double=[], triple=[1], quadruple=[], benzene=[0], lone_pairs=[0], charge=[0]) +# examples for P5t: N#P(Cl)Cl (phosphonitrile chloride) +ATOMTYPES['P5td'] = AtomType('P5td', generic=['R', 'R!H', 'P', 'Val5'], specific=[], + single=[0], all_double=[1], r_double=[], o_double=[], s_double=[], triple=[1], quadruple=[], benzene=[0], lone_pairs=[0], charge=[0]) +# examples for P5td: COC(=O)C#P=O (methyl phosphorylacetate) +ATOMTYPES['P5tc'] = AtomType('P5tc', generic=['R', 'R!H', 'P', 'Val5'], specific=[], + single=[0,1], all_double=[0], r_double=[0], o_double=[0], s_double=[0], triple=[1], quadruple=[], benzene=[0], lone_pairs=[0], charge=[+1]) +# examples for P5tc: C[P+]#C (methyl(methylidyne)phosphanium), C#[P+]O (hydroxy(methylidyne)phosphanium) +ATOMTYPES['P5b'] = AtomType('P5b', generic=['R', 'R!H', 'P', 'Val5'], specific=[], + single=[0,1], all_double=[0], r_double=[0], o_double=[0], s_double=[0], triple=[0], quadruple=[], benzene=[2], lone_pairs=[0], charge=[0, +1]) +# examples for P5b: C1=CC=[PH+]C=C1 (Phosphoniabenzene) +ATOMTYPES['P5bd'] = AtomType('P5bd', generic=['R', 'R!H', 'P', 'Val5'], specific=[], + single=[0], all_double=[1], r_double=[], o_double=[], s_double=[], triple=[0], quadruple=[], benzene=[2], lone_pairs=[0], charge=[0]) +# examples for P5bd: C1=CC=P(=S)C=C1 (Phosphorin 1-sulfide), C1=CC=P(=O)C=C1 (Phosphorin 1-oxide) + ATOMTYPES['S'] = AtomType('S', generic=['R', 'R!H', 'Val6'], specific=['Sa', 'S0sc', 'S2s', 'S2sc', 'S2d', 'S2dc', 'S2tc', 'S4s', 'S4sc', 'S4d', 'S4dd', 'S4dc', 'S4b', 'S4t', 'S4tdc', 'S6s', 'S6sc', 'S6d', 'S6dd', 'S6ddd', 'S6dc', 'S6t', 'S6td', 'S6tt', 'S6tdc'], single=[], all_double=[], r_double=[], o_double=[], s_double=[], triple=[], quadruple=[], benzene=[], lone_pairs=[], charge=[]) ATOMTYPES['Sa'] = AtomType('Sa', generic=['R', 'R!H', 'S', 'Val6'], specific=[], # (shared electrons = 6) @@ -633,6 +696,27 @@ def get_features(self): ATOMTYPES['Sibf'].set_actions(increment_bond=[], decrement_bond=[], form_bond=[], break_bond=[], increment_radical=[], decrement_radical=[], increment_lone_pair=[], decrement_lone_pair=[]) ATOMTYPES['Siq'].set_actions(increment_bond=[], decrement_bond=['Sit'], form_bond=[], break_bond=[], increment_radical=[], decrement_radical=[], increment_lone_pair=[], decrement_lone_pair=[]) +ATOMTYPES['P'].set_actions(increment_bond=['P'], decrement_bond=['P'], form_bond=['P'], break_bond=['P'], increment_radical=['P'], decrement_radical=['P'], increment_lone_pair=['P'], decrement_lone_pair=['P']) +ATOMTYPES['P0sc'].set_actions(increment_bond=[], decrement_bond=[], form_bond=['P0sc'], break_bond=['P0sc'], increment_radical=['P0sc'], decrement_radical=['P0sc'], increment_lone_pair=[], decrement_lone_pair=['P1s', 'P1sc']) +ATOMTYPES['P1s'].set_actions(increment_bond=['P1dc'], decrement_bond=[], form_bond=['P1s'], break_bond=['P1s'], increment_radical=['P1s'], decrement_radical=['P1s'], increment_lone_pair=['P0sc'], decrement_lone_pair=['P3s']) +ATOMTYPES['P1sc'].set_actions(increment_bond=['P1dc'], decrement_bond=[], form_bond=['P1sc'], break_bond=['P1sc'], increment_radical=['P1sc'], decrement_radical=['P1sc'], increment_lone_pair=['P0sc'], decrement_lone_pair=['P3s']) +ATOMTYPES['P1dc'].set_actions(increment_bond=[], decrement_bond=['P1s'], form_bond=[], break_bond=[], increment_radical=[], decrement_radical=[], increment_lone_pair=[], decrement_lone_pair=['P3d']) +ATOMTYPES['P3s'].set_actions(increment_bond=['P3d'], decrement_bond=[], form_bond=['P3s'], break_bond=['P3s'], increment_radical=['P3s'], decrement_radical=['P3s'], increment_lone_pair=['P1s', 'P1sc'], decrement_lone_pair=['P5s', 'P5sc']) +ATOMTYPES['P3d'].set_actions(increment_bond=['P3t'], decrement_bond=['P3s'], form_bond=['P3d'], break_bond=['P3d'], increment_radical=['P3d'], decrement_radical=['P3d'], increment_lone_pair=['P1dc'], decrement_lone_pair=['P5d', 'P5dc']) +ATOMTYPES['P3t'].set_actions(increment_bond=[], decrement_bond=['P3d'], form_bond=[], break_bond=[], increment_radical=[], decrement_radical=[], increment_lone_pair=[], decrement_lone_pair=['P5t', 'P5tc']) +ATOMTYPES['P3b'].set_actions(increment_bond=[], decrement_bond=[], form_bond=[], break_bond=[], increment_radical=[], decrement_radical=[], increment_lone_pair=[], decrement_lone_pair=[]) +ATOMTYPES['P5s'].set_actions(increment_bond=['P5d', 'P5dc'], decrement_bond=[], form_bond=['P5s'], break_bond=['P5s'], increment_radical=['P5s'], decrement_radical=['P5s'], increment_lone_pair=['P3s'], decrement_lone_pair=[]) +ATOMTYPES['P5sc'].set_actions(increment_bond=['P5dc'], decrement_bond=[], form_bond=['P5sc'], break_bond=['P5sc'], increment_radical=['P5sc'], decrement_radical=['P5sc'], increment_lone_pair=['P3s'], decrement_lone_pair=[]) +ATOMTYPES['P5d'].set_actions(increment_bond=['P5dd', 'P5ddc', 'P5t', 'P5tc'], decrement_bond=['P5s'], form_bond=['P5d'], break_bond=['P5d'], increment_radical=['P5d'], decrement_radical=['P5d'], increment_lone_pair=['P3d'], decrement_lone_pair=[]) +ATOMTYPES['P5dd'].set_actions(increment_bond=['P5td'], decrement_bond=['P5d', 'P5dc'], form_bond=['P5dd'], break_bond=['P5dd'], increment_radical=['P5dd'], decrement_radical=['P5dd'], increment_lone_pair=[], decrement_lone_pair=[]) +ATOMTYPES['P5dc'].set_actions(increment_bond=['P5dd', 'P5ddc', 'P5tc'], decrement_bond=['P5sc'], form_bond=['P5dc'], break_bond=['P5dc'], increment_radical=['P5dc'], decrement_radical=['P5dc'], increment_lone_pair=['P3d'], decrement_lone_pair=[]) +ATOMTYPES['P5ddc'].set_actions(increment_bond=[], decrement_bond=['P5dc'], form_bond=[], break_bond=[], increment_radical=[], decrement_radical=[], increment_lone_pair=[], decrement_lone_pair=[]) +ATOMTYPES['P5t'].set_actions(increment_bond=['P5td'], decrement_bond=['P5d'], form_bond=['P5t'], break_bond=['P5t'], increment_radical=['P5t'], decrement_radical=['P5t'], increment_lone_pair=['P3t'], decrement_lone_pair=[]) +ATOMTYPES['P5td'].set_actions(increment_bond=[], decrement_bond=['P5t', 'P5dd'], form_bond=[], break_bond=[], increment_radical=[], decrement_radical=[], increment_lone_pair=[], decrement_lone_pair=[]) +ATOMTYPES['P5tc'].set_actions(increment_bond=[], decrement_bond=['P5dc'], form_bond=['P5tc'], break_bond=['P5tc'], increment_radical=['P5tc'], decrement_radical=['P5tc'], increment_lone_pair=[], decrement_lone_pair=[]) +ATOMTYPES['P5b'].set_actions(increment_bond=['P5bd'], decrement_bond=[], form_bond=['P5b'], break_bond=['P5b'], increment_radical=['P5b'], decrement_radical=['P5b'], increment_lone_pair=[], decrement_lone_pair=[]) +ATOMTYPES['P5bd'].set_actions(increment_bond=[], decrement_bond=['P5b'], form_bond=[], break_bond=[], increment_radical=[], decrement_radical=[], increment_lone_pair=[], decrement_lone_pair=[]) + ATOMTYPES['S'].set_actions(increment_bond=['S'], decrement_bond=['S'], form_bond=['S'], break_bond=['S'], increment_radical=['S'], decrement_radical=['S'], increment_lone_pair=['S'], decrement_lone_pair=['S']) ATOMTYPES['S0sc'].set_actions(increment_bond=['S0sc'], decrement_bond=['S0sc'], form_bond=['S0sc'], break_bond=['Sa', 'S0sc'], increment_radical=['S0sc'], decrement_radical=['S0sc'], increment_lone_pair=[], decrement_lone_pair=['S2s', 'S2sc', 'S2dc', 'S2tc']) ATOMTYPES['Sa'].set_actions(increment_bond=[], decrement_bond=[], form_bond=['S0sc'], break_bond=[], increment_radical=[], decrement_radical=[], increment_lone_pair=[], decrement_lone_pair=['S2s']) @@ -673,7 +757,7 @@ def get_features(self): ATOMTYPES['F1s'].set_actions(increment_bond=[], decrement_bond=[], form_bond=['F1s'], break_bond=['F1s'], increment_radical=['F1s'], decrement_radical=['F1s'], increment_lone_pair=[], decrement_lone_pair=[]) # these are ordered in priority of picking if a more general atomtype is encountered -allElements = ['H', 'C', 'O', 'N', 'S', 'Si', 'F', 'Cl', 'Br', 'I', 'Ne', 'Ar', 'He', 'X'] +allElements = ['H', 'C', 'O', 'N', 'S', 'P', 'Si', 'F', 'Cl', 'Br', 'I', 'Ne', 'Ar', 'He', 'X'] # list of elements that do not have more specific atomTypes nonSpecifics = ['H', 'He', 'Ne', 'Ar',] diff --git a/rmgpy/molecule/atomtypeTest.py b/rmgpy/molecule/atomtypeTest.py index b444498b60..2c0816a274 100644 --- a/rmgpy/molecule/atomtypeTest.py +++ b/rmgpy/molecule/atomtypeTest.py @@ -506,6 +506,110 @@ def setUp(self): self.mol79 = Molecule().from_adjacency_list('''1 H u0 p0 c0 {2,S} 2 Br u0 p3 c0 {1,S}''') + self.mol80 = Molecule().from_adjacency_list('''1 P u0 p3 c-2 {2,S} + 2 P u0 p0 c+1 {1,S} {3,T} + 3 P u0 p0 c+1 {2,T} {4,S} + 4 H u0 p0 c0 {3,S}''') + + self.mol81 = Molecule().from_adjacency_list('''1 P u0 p2 c0 {2,S} + 2 H u0 p0 c0 {1,S}''') + + self.mol82 = Molecule().from_adjacency_list('''1 P u0 p2 c-1 {2,S} {3,S} + 2 H u0 p0 c0 {1,S} + 3 P u0 p0 c+1 {1,S} {4,T} + 4 C u0 p0 c0 {3,T} {5,S} + 5 H u0 p0 c0 {4,S}''') + + self.mol83 = Molecule().from_adjacency_list('''1 H u0 p0 {3,S} + 2 H u0 p0 {3,S} + 3 P u0 p0 c+1 {1,S} {2,S} {4,D} + 4 P u0 p2 c-1 {3,D}''') + + self.mol84 = Molecule().from_adjacency_list('''1 P u0 p1 c0 {4,S} {7,S} {8,S} + 2 P u0 p1 c0 {3,D} {4,S} + 3 O u0 p2 c0 {2,D} + 4 C u0 p0 c0 {1,S} {2,S} {5,S} {6,S} + 5 H u0 p0 c0 {4,S} + 6 H u0 p0 c0 {4,S} + 7 H u0 p0 c0 {1,S} + 8 H u0 p0 c0 {1,S}''') + + self.mol85 = Molecule().from_adjacency_list('''1 P u0 p1 c0 {2,T} + 2 C u0 p0 c0 {1,T} {3,S} + 3 H u0 p0 c0 {2,S}''') + + self.mol86 = Molecule().from_adjacency_list('''1 P u0 p0 c+1 {2,B} {6,B} {7,S} + 2 C u0 p0 {1,B} {3,B} {8,S} + 3 C u0 p0 {2,B} {4,B} {9,S} + 4 C u0 p0 {3,B} {5,B} {10,S} + 5 C u0 p0 {4,B} {6,B} {11,S} + 6 P u0 p1 {1,B} {5,B} + 7 O u0 p3 c-1 {1,S} + 8 H u0 p0 {2,S} + 9 H u0 p0 {3,S} + 10 H u0 p0 {4,S} + 11 H u0 p0 {5,S}''') + + self.mol87 = Molecule().from_adjacency_list('''1 P u0 p0 c0 {2,S} {3,S} {4,S} {5,S} {6,S} + 2 Cl u0 p3 c0 {1,S} + 3 Cl u0 p3 c0 {1,S} + 4 Cl u0 p3 c0 {1,S} + 5 Cl u0 p3 c0 {1,S} + 6 Cl u0 p3 c0 {1,S}''') + + self.mol88 = Molecule().from_adjacency_list('''1 P u0 p0 c+1 {2,S} {3,S} {4,S} {5,S} + 2 O u0 p2 c0 {1,S} {6,S} + 3 O u0 p3 c-1 {1,S} + 4 H u0 p0 c0 {1,S} + 5 H u0 p0 c0 {1,S} + 6 H u0 p0 c0 {2,S}''') + + self.mol89 = Molecule().from_adjacency_list('''1 P u0 p0 c0 {2,S} {3,S} {4,S} {5,D} + 2 O u0 p2 c0 {1,S} {6,S} + 3 O u0 p2 c0 {1,S} {7,S} + 4 O u0 p2 c0 {1,S} {8,S} + 5 O u0 p2 c0 {1,D} + 6 H u0 p0 c0 {2,S} + 7 H u0 p0 c0 {3,S} + 8 H u0 p0 c0 {4,S}''') + + self.mol90 = Molecule().from_adjacency_list('''1 P u0 p0 c0 {2,D} {3,D} {4,S} + 2 O u0 p2 c0 {1,D} + 3 O u0 p2 c0 {1,D} + 4 C u0 p0 c0 {1,S} {5,S} {6,S} {7,S} + 5 H u0 p0 c0 {4,S} + 6 H u0 p0 c0 {4,S} + 7 H u0 p0 c0 {4,S}''') + + self.mol91 = Molecule().from_adjacency_list('''1 P u0 p0 c+1 {2,D} {3,D} + 2 N u0 p2 c-1 {1,D} + 3 C u0 p0 c0 {1,D} {4,S} {5,S} + 4 H u0 p0 c0 {3,S} + 5 H u0 p0 c0 {3,S}''') + + self.mol92 = Molecule().from_adjacency_list('''1 P u0 p0 c0 {2,T} {3,S} {4,S} + 2 N u0 p1 c0 {1,T} + 3 Cl u0 p3 c0 {1,S} + 4 Cl u0 p3 c0 {1,S}''') + + self.mol93 = Molecule().from_adjacency_list('''1 P u0 p0 c0 {2,D} {3,T} + 2 O u0 p2 c0 {1,D} + 3 C u0 p0 c0 {1,T} {4,S} + 4 H u0 p0 c0 {3,S}''') + + self.mol94 = Molecule().from_adjacency_list('''1 P u0 p0 {2,B} {6,B} {7,D} + 2 C u0 p0 {1,B} {3,B} {8,S} + 3 C u0 p0 {2,B} {4,B} {9,S} + 4 C u0 p0 {3,B} {5,B} {10,S} + 5 C u0 p0 {4,B} {6,B} {11,S} + 6 C u0 p0 {1,B} {5,B} {12,S} + 7 S u0 p2 {1,D} + 8 H u0 p0 {2,S} + 9 H u0 p0 {3,S} + 10 H u0 p0 {4,S} + 11 H u0 p0 {5,S} + 12 H u0 p0 {6,S}''') + def atom_type(self, mol, atom_id): atom = mol.atoms[atom_id] atom_type = get_atomtype(atom, mol.get_bonds(atom)) @@ -590,6 +694,30 @@ def test_silicon_types(self): self.assertEqual(self.atom_type(self.mol4, 4), 'Sidd') self.assertEqual(self.atom_type(self.mol4, 7), 'Sit') # todo: add in Siq unit test? + def test_phosphorus_types(self): + """ + Test that get_atomtype() returns appropriate phosphorus atom types. + """ + self.assertEqual(self.atom_type(self.mol80, 0), 'P0sc') + self.assertEqual(self.atom_type(self.mol81, 0), 'P1s') + self.assertEqual(self.atom_type(self.mol82, 0), 'P1sc') + self.assertEqual(self.atom_type(self.mol83, 3), 'P1dc') + self.assertEqual(self.atom_type(self.mol84, 0), 'P3s') + self.assertEqual(self.atom_type(self.mol84, 1), 'P3d') + self.assertEqual(self.atom_type(self.mol85, 0), 'P3t') + self.assertEqual(self.atom_type(self.mol86, 5), 'P3b') + self.assertEqual(self.atom_type(self.mol87, 0), 'P5s') + self.assertEqual(self.atom_type(self.mol88, 0), 'P5sc') + self.assertEqual(self.atom_type(self.mol89, 0), 'P5d') + self.assertEqual(self.atom_type(self.mol90, 0), 'P5dd') + self.assertEqual(self.atom_type(self.mol83, 2), 'P5dc') + self.assertEqual(self.atom_type(self.mol91, 0), 'P5ddc') + self.assertEqual(self.atom_type(self.mol92, 0), 'P5t') + self.assertEqual(self.atom_type(self.mol93, 0), 'P5td') + self.assertEqual(self.atom_type(self.mol80, 1), 'P5tc') + self.assertEqual(self.atom_type(self.mol86, 0), 'P5b') + self.assertEqual(self.atom_type(self.mol94, 0), 'P5bd') + def test_sulfur_types(self): """ Test that get_atomtype() returns appropriate sulfur atom types. diff --git a/rmgpy/molecule/element.py b/rmgpy/molecule/element.py index d6e8dd7edf..39f2be15e3 100644 --- a/rmgpy/molecule/element.py +++ b/rmgpy/molecule/element.py @@ -123,13 +123,13 @@ class PeriodicSystem(object): isotopes of the same element may have slight different electronegativities, which is not reflected below """ valences = {'H': 1, 'He': 0, 'C': 4, 'N': 3, 'O': 2, 'F': 1, 'Ne': 0, - 'Si': 4, 'S': 2, 'Cl': 1, 'Br': 1, 'Ar': 0, 'I': 1, 'X': 4} + 'Si': 4, 'P': 3, 'S': 2, 'Cl': 1, 'Br': 1, 'Ar': 0, 'I': 1, 'X': 4} valence_electrons = {'H': 1, 'He': 2, 'C': 4, 'N': 5, 'O': 6, 'F': 7, 'Ne': 8, - 'Si': 4, 'S': 6, 'Cl': 7, 'Br': 7, 'Ar': 8, 'I': 7, 'X': 4} + 'Si': 4, 'P': 5, 'S': 6, 'Cl': 7, 'Br': 7, 'Ar': 8, 'I': 7, 'X': 4} lone_pairs = {'H': 0, 'He': 1, 'C': 0, 'N': 1, 'O': 2, 'F': 3, 'Ne': 4, - 'Si': 0, 'S': 2, 'Cl': 3, 'Br': 3, 'Ar': 4, 'I': 3, 'X': 0} + 'Si': 0, 'P': 1, 'S': 2, 'Cl': 3, 'Br': 3, 'Ar': 4, 'I': 3, 'X': 0} electronegativity = {'H': 2.20, 'D': 2.20, 'T': 2.20, 'C': 2.55, 'C13': 2.55, 'N': 3.04, 'O': 3.44, 'O18': 3.44, - 'F': 3.98, 'Si': 1.90, 'S': 2.58, 'Cl': 3.16, 'Br': 2.96, 'I': 2.66, 'X': 0.0} + 'F': 3.98, 'Si': 1.90, 'P': 2.19, 'S': 2.58, 'Cl': 3.16, 'Br': 2.96, 'I': 2.66, 'X': 0.0} ################################################################################ @@ -329,27 +329,47 @@ def get_element(value, isotope=-1): # (C,C,1.5) was taken from an unsourced table that had similar values to those used below, should be replaced # if a sourced value becomes available # (C,C,2.5) is C#C - (CbenzeneC - C-C) -bde_elements = ['C', 'N', 'H', 'O', 'S', 'Cl', 'Si'] # elements supported by BDE +# P=P value is from: https://www2.chemistry.msu.edu/faculty/reusch/OrgPage/bndenrgy.htm +# The reference state is gaseous state at 298 K, but some of the values in the bde_dict might be coming from 0 K. +# The bond dissociation energy at 298 K is greater than the bond dissociation energy at 0 K by 0.6 to 0.9 kcal/mol +# (between RT and 3/2 RT), and this difference is usually much smaller than the uncertainty in the bond dissociation +# energy itself. Therefore, the discrepancy between 0 K and 298 K shouldn't matter too much. +# But for any new entries, try to use the consistent reference state of 298 K. +bde_elements = ['C', 'N', 'H', 'O', 'S', 'Cl', 'Si', 'P', 'F', 'Br', 'I'] # elements supported by BDE bde_dict = {('H', 'H', 1.0): (432.0, 'kJ/mol'), ('H', 'C', 1): (411.0, 'kJ/mol'), ('H', 'N', 1): (386.0, 'kJ/mol'), ('H', 'O', 1.0): (459.0, 'kJ/mol'), - ('H', 'S', 1): (363.0, 'kJ/mol'), ('H', 'Cl', 1): (428.0, 'kJ/mol'), + ('H', 'P', 1): (322.0, 'kJ/mol'), ('H', 'S', 1): (363.0, 'kJ/mol'), + ('H', 'F', 1): (565.0, 'kJ/mol'), ('H', 'Cl', 1): (428.0, 'kJ/mol'), + ('H', 'Br', 1): (362.0, 'kJ/mol'), ('H', 'I', 1): (295.0, 'kJ/mol'), ('C', 'C', 1): (346.0, 'kJ/mol'), ('C', 'C', 2): (602.0, 'kJ/mol'), - ('C', 'C', 3): (835.0, 'kJ/mol'), ('C', 'Si', 1): (318.0, 'kJ/mol'), + ('C', 'C', 3): (835.0, 'kJ/mol'), ('C', 'C', 1.5): (518.0, 'kJ/mol'), + ('C', 'C', 2.5): (663.0, 'kJ/mol'), ('C', 'Si', 1): (318.0, 'kJ/mol'), ('C', 'N', 1): (305.0, 'kJ/mol'), ('C', 'N', 2): (615.0, 'kJ/mol'), ('C', 'N', 3): (887.0, 'kJ/mol'), ('C', 'O', 1): (358.0, 'kJ/mol'), ('C', 'O', 2): (799.0, 'kJ/mol'), ('C', 'O', 3): (1072.0, 'kJ/mol'), - ('C', 'S', 1): (272.0, 'kJ/mol'), ('C', 'S', 2): (573.0, 'kJ/mol'), - ('C', 'Cl', 1): (327.0, 'kJ/mol'), ('Si', 'Si', 1): (222.0, 'kJ/mol'), - ('Si', 'N', 1): (355.0, 'kJ/mol'), ('Si', 'O', 1): (452.0, 'kJ/mol'), - ('Si', 'S', 1): (293.0, 'kJ/mol'), ('Si', 'Cl', 1): (381.0, 'kJ/mol'), + ('C', 'P', 1): (264.0, 'kJ/mol'), ('C', 'S', 1): (272.0, 'kJ/mol'), + ('C', 'S', 2): (573.0, 'kJ/mol'), ('C', 'F', 1): (485.0, 'kJ/mol'), + ('C', 'Cl', 1): (327.0, 'kJ/mol'), ('C', 'Br', 1): (285.0, 'kJ/mol'), + ('C', 'I', 1): (213.0, 'kJ/mol'), + ('Si', 'Si', 1): (222.0, 'kJ/mol'), ('Si', 'N', 1): (355.0, 'kJ/mol'), + ('Si', 'O', 1): (452.0, 'kJ/mol'), ('Si', 'S', 1): (293.0, 'kJ/mol'), + ('Si', 'F', 1): (565.0, 'kJ/mol'), ('Si', 'Cl', 1): (381.0, 'kJ/mol'), + ('Si', 'Br', 1): (310.0, 'kJ/mol'), ('Si', 'I', 1): (234.0, 'kJ/mol'), ('N', 'N', 1): (167.0, 'kJ/mol'), ('N', 'N', 2): (418.0, 'kJ/mol'), ('N', 'N', 3): (942.0, 'kJ/mol'), ('N', 'O', 1): (201.0, 'kJ/mol'), - ('N', 'O', 2): (607.0, 'kJ/mol'), ('N', 'Cl', 1): (313.0, 'kJ/mol'), + ('N', 'O', 2): (607.0, 'kJ/mol'), ('N', 'F', 1): (283.0, 'kJ/mol'), + ('N', 'Cl', 1): (313.0, 'kJ/mol'), ('O', 'O', 1): (142.0, 'kJ/mol'), ('O', 'O', 2): (494.0, 'kJ/mol'), - ('S', 'O', 2): (522.0, 'kJ/mol'), ('S', 'S', 1): (226.0, 'kJ/mol'), - ('S', 'S', 2): (425.0, 'kJ/mol'), ('S', 'Cl', 1): (255.0, 'kJ/mol'), - ('Cl', 'Cl', 1): (240.0, 'kJ/mol'), ('C', 'C', 1.5): (518.0, 'kJ/mol'), - ('O', 'S', 1): (265.0, 'kJ/mol'), ('C', 'C', 2.5): (663.0, 'kJ/mol')} + ('O', 'P', 1): (335.0, 'kJ/mol'), ('O', 'P', 2): (544.0, 'kJ/mol'), + ('O', 'S', 1): (265.0, 'kJ/mol'), ('O', 'S', 2): (522.0, 'kJ/mol'), + ('P', 'P', 1): (201.0, 'kJ/mol'), ('P', 'P', 2): (351.0, 'kJ/mol'), + ('P', 'P', 3): (489.0, 'kJ/mol'), ('P', 'S', 2): (335.0, 'kJ/mol'), + ('P', 'F', 1): (490.0, 'kJ/mol'), ('P', 'Cl', 1): (326.0, 'kJ/mol'), + ('P', 'Br', 1): (264.0, 'kJ/mol'), ('P', 'I', 2): (184.0, 'kJ/mol'), + ('S', 'S', 1): (226.0, 'kJ/mol'), ('S', 'S', 2): (425.0, 'kJ/mol'), + ('S', 'Cl', 1): (255.0, 'kJ/mol'), + ('F', 'F', 1): (155.0, 'kJ/mol'), ('Cl', 'Cl', 1): (240.0, 'kJ/mol'), + ('Br', 'Br', 1): (190.0, 'kJ/mol'), ('I', 'I', 1): (148.0, 'kJ/mol')} bdes = {} for key, value in bde_dict.items(): diff --git a/rmgpy/molecule/group.py b/rmgpy/molecule/group.py index d3fdf511b4..3e7f786090 100644 --- a/rmgpy/molecule/group.py +++ b/rmgpy/molecule/group.py @@ -584,10 +584,12 @@ def make_sample_atom(self): 'O': 2, 'N': 1, 'Si': 0, + 'P': 1, 'S': 2, 'Ne': 4, 'Cl': 3, 'F': 3, + 'Br': 3, 'I': 3, 'Ar': 4, 'X': 0, @@ -2654,11 +2656,13 @@ def make_sample_molecule(self): positive_charged = ['Csc', 'Cdc', 'N3sc', 'N5sc', 'N5dc', 'N5ddc', 'N5tc', 'N5b', 'O2sc', 'O4sc', 'O4dc', 'O4tc', + 'P5sc', 'P5dc', 'P5ddc', 'P5tc', 'P5b', 'S2sc', 'S4sc', 'S4dc', 'S4tdc', 'S6sc', 'S6dc', 'S6tdc'] negative_charged = ['C2sc', 'C2dc', 'C2tc', 'N0sc', 'N1sc', 'N1dc', 'N5dddc', 'O0sc', - 'S0sc', 'S2sc', 'S2dc', 'S2tc', 'S4dc', 'S4tdc', 'S6sc', 'S6dc', 'S6tdc'] + 'P0sc', 'P1sc', 'P1dc', 'P5sc', + 'S0sc', 'S2sc', 'S2dc', 'S2tc', 'S4sc', 'S4dc', 'S4tdc', 'S6sc', 'S6dc', 'S6tdc'] if group_atom.atomtype[0] in [ATOMTYPES[x] for x in positive_charged] and atom.charge > 0: pass elif group_atom.atomtype[0] in [ATOMTYPES[x] for x in negative_charged] and atom.charge < 0: diff --git a/rmgpy/molecule/groupTest.py b/rmgpy/molecule/groupTest.py index 6e3b396619..b93c359b62 100644 --- a/rmgpy/molecule/groupTest.py +++ b/rmgpy/molecule/groupTest.py @@ -1325,6 +1325,12 @@ def perform_samp_mole_comparison(_adjlist, _answer_smiles): answer_smiles = '[NH4+]' self.assertTrue(perform_samp_mole_comparison(adjlist, answer_smiles)) + adjlist = """ +1 *1 P5dc u0 +""" + answer_smiles = '[PH2+]=C' + self.assertTrue(perform_samp_mole_comparison(adjlist, answer_smiles)) + # test the creation of a negatively charged species adjlist = """ 1 *1 N1sc u0 @@ -1332,6 +1338,12 @@ def perform_samp_mole_comparison(_adjlist, _answer_smiles): answer_smiles = '[NH2-]' self.assertTrue(perform_samp_mole_comparison(adjlist, answer_smiles)) + adjlist = """ +1 *1 P5sc u0 +""" + answer_smiles = '[PH6-]' + self.assertTrue(perform_samp_mole_comparison(adjlist, answer_smiles)) + # test creation of charged species when some single bonds present adjlist = """ 1 *2 [N5sc,N5dc] u0 {2,S} {3,S} @@ -1475,9 +1487,10 @@ def test_get_element_count(self): 1 R!H u0 {2,S} 2 [Cs,Cd,Ct,Cb] u0 {1,S} {3,S} 3 [Cs,Cd,Ct,Cb,O2s,S2s] u0 {2,S} {4,S} -4 N1s u0 {3,S} +4 N3s u0 {3,S} {5,S} +5 P1s u0 {4,S} """) - expected = {'C': 1, 'N': 1} + expected = {'C': 1, 'N': 1, 'P': 1} result = group.get_element_count() self.assertEqual(expected, result) diff --git a/rmgpy/molecule/isomorphismTest.py b/rmgpy/molecule/isomorphismTest.py index 5627f53c22..17aec40d69 100644 --- a/rmgpy/molecule/isomorphismTest.py +++ b/rmgpy/molecule/isomorphismTest.py @@ -37,7 +37,7 @@ from rmgpy.molecule.group import Group from rmgpy.molecule.molecule import Molecule -molecule_atom_types = ['C', 'O', 'N', 'S', 'Si', 'Cl', 'Br', 'I', 'F'] +molecule_atom_types = ['C', 'O', 'N', 'S', 'P', 'Si', 'Cl', 'Br', 'I', 'F'] group_atomtypes = {} for item in create_atom_types(): @@ -78,12 +78,17 @@ def create_molecule(element, u1, c1): adjlist = get_molecule_string(element, u1, c1) logging.info('Creating molecule: {0}'.format(adjlist)) mol = None - try: - mol = Molecule().from_adjacency_list(adjlist) - except (ValueError, InvalidAdjacencyListError): - # Either a non-neutral molecule, incompatible multiplcity, or an improper valence - # was assigned with this combination. + if element == 'P' and c1 == 1 and get_lone_pairs(element) == 1: + # AtomTypeError is raised when phosphorus has +1 partial charge and 1 lone pair. + # Although this will not raise InvalidAdjacencyListError, these are chemically infeasible. pass + else: + try: + mol = Molecule().from_adjacency_list(adjlist) + except (ValueError, InvalidAdjacencyListError): + # Either a non-neutral molecule, incompatible multiplcity, or an improper valence + # was assigned with this combination. + pass return mol, adjlist diff --git a/rmgpy/molecule/molecule.pxd b/rmgpy/molecule/molecule.pxd index 8b9bf93d8e..3726cae4fa 100644 --- a/rmgpy/molecule/molecule.pxd +++ b/rmgpy/molecule/molecule.pxd @@ -66,6 +66,8 @@ cdef class Atom(Vertex): cpdef bint is_silicon(self) + cpdef bint is_phosphorus(self) + cpdef bint is_sulfur(self) cpdef bint is_chlorine(self) diff --git a/rmgpy/molecule/molecule.py b/rmgpy/molecule/molecule.py index ed4b9690a3..06b8946c90 100644 --- a/rmgpy/molecule/molecule.py +++ b/rmgpy/molecule/molecule.py @@ -376,6 +376,13 @@ def is_silicon(self): """ return self.element.number == 14 + def is_phosphorus(self): + """ + Return ``True`` if the atom represents a phosphorus atom or ``False`` if + not. + """ + return self.element.number == 15 + def is_sulfur(self): """ Return ``True`` if the atom represents a sulfur atom or ``False`` if diff --git a/rmgpy/molecule/moleculeTest.py b/rmgpy/molecule/moleculeTest.py index 8a253bda9d..9c4200163c 100644 --- a/rmgpy/molecule/moleculeTest.py +++ b/rmgpy/molecule/moleculeTest.py @@ -164,6 +164,17 @@ def test_is_nitrogen(self): else: self.assertFalse(atom.is_nitrogen()) + def test_is_phosphorus(self): + """ + Test the Atom.is_phosphorus() method. + """ + for element in element_list: + atom = Atom(element=element, radical_electrons=1, charge=0, label='*1', lone_pairs=1) + if element.symbol == 'P': + self.assertTrue(atom.is_phosphorus()) + else: + self.assertFalse(atom.is_phosphorus()) + def test_is_sulfur(self): """ Test the Atom.is_sulfur() method. diff --git a/rmgpy/reaction.py b/rmgpy/reaction.py index 37e80840fd..8f6766ff1a 100644 --- a/rmgpy/reaction.py +++ b/rmgpy/reaction.py @@ -1108,7 +1108,7 @@ def generate_pairs(self): def get_sorting_key(spc): # List of elements to sort by, order is intentional - numbers = [6, 8, 7, 14, 16, 17, 53, 9, 35] # C, O, N, Si, S, Cl, I, F, Br + numbers = [6, 8, 7, 14, 16, 15, 17, 53, 9, 35] # C, O, N, Si, S, P, Cl, I, F, Br return tuple(sum([1 for atom in spc.molecule[0].atoms if atom.element.number == n]) for n in numbers) # Sort the reactants and products by element counts diff --git a/rmgpy/reactionTest.py b/rmgpy/reactionTest.py index fb99a3c093..3d8b229a88 100644 --- a/rmgpy/reactionTest.py +++ b/rmgpy/reactionTest.py @@ -450,6 +450,17 @@ def setUp(self): products=[so3], kinetics=Arrhenius(A=(3.7e+11, 'cm^3/(mol*s)'), n=0, Ea=(1689, 'cal/mol'), T0=(1, 'K'))) + H2 = Species().from_smiles('[H][H]') + PO3 = Species().from_smiles('[O]P(=O)=O') + HOPO2 = Species().from_smiles('OP(=O)=O') + H_atom = Species().from_smiles('[H]') + + self.reaction4 = Reaction( + reactants=[H2, PO3], + products=[HOPO2, H_atom], + kinetics=Arrhenius(A=(2.4e+7, 'cm^3/(mol*s)'), n=1.38, Ea=(15.38, 'kcal/mol'), T0=(1, 'K'))) + self.reaction4_pairs = [(PO3, HOPO2), (H2, H_atom)] + def test_is_isomerization(self): """ Test the Reaction.is_isomerization() method. @@ -1324,6 +1335,16 @@ def test_sulfur_reaction_pairs(self): self.assertEqual(len(self.reaction3.pairs[0]), 2) self.assertEqual(len(self.reaction3.pairs[1]), 2) + def test_phosphorus_reaction_pairs(self): + """ + This method tests that reaction pairs are being generated for phosphorus species + """ + + self.reaction4.generate_pairs() + self.assertEqual(len(self.reaction4.pairs[0]), 2) + self.assertEqual(len(self.reaction4.pairs[1]), 2) + self.assertEqual(self.reaction4.pairs, self.reaction4_pairs) + class TestReactionToCantera(unittest.TestCase): """