00001 #include <cmath>
00002
00003 #include "colvarmodule.h"
00004 #include "colvarvalue.h"
00005 #include "colvarparse.h"
00006 #include "colvar.h"
00007 #include "colvarcomp.h"
00008
00009
00010
00011 colvar::orientation::orientation (std::string const &conf)
00012 : cvc (conf)
00013 {
00014 function_type = "orientation";
00015 parse_group (conf, "atoms", atoms);
00016 x.type (colvarvalue::type_quaternion);
00017
00018 ref_pos.reserve (atoms.size());
00019
00020 if (get_keyval (conf, "refPositions", ref_pos, ref_pos)) {
00021 cvm::log ("Using reference positions from input file.\n");
00022 if (ref_pos.size() != atoms.size()) {
00023 cvm::fatal_error ("Error: reference positions do not "
00024 "match the number of atom indexes.\n");
00025 }
00026 }
00027
00028 {
00029 std::string file_name;
00030 if (get_keyval (conf, "refPositionsFile", file_name)) {
00031
00032 std::string file_col;
00033 get_keyval (conf, "refPositionsCol", file_col, std::string ("O"));
00034
00035 double file_col_value;
00036 bool found = get_keyval (conf, "refPositionsColValue", file_col_value, 0.0);
00037 if (found && !file_col_value)
00038 cvm::fatal_error ("Error: refPositionsColValue, "
00039 "if provided, must be non-zero.\n");
00040
00041 ref_pos.resize (atoms.size());
00042 cvm::load_coords (file_name.c_str(), ref_pos, file_col, file_col_value);
00043 }
00044 }
00045
00046 if (!ref_pos.size()) {
00047 cvm::fatal_error ("Error: must define a set of "
00048 "reference coordinates.\n");
00049 }
00050
00051
00052 cvm::log ("Centering the reference coordinates: it is "
00053 "assumed that each atom is the closest "
00054 "periodic image to the center of geometry.\n");
00055 cvm::rvector cog (0.0, 0.0, 0.0);
00056 for (size_t i = 0; i < ref_pos.size(); i++) {
00057 cog += ref_pos[i];
00058 }
00059 cog /= cvm::real (ref_pos.size());
00060 for (size_t i = 0; i < ref_pos.size(); i++) {
00061 ref_pos[i] -= cog;
00062 }
00063
00064 get_keyval (conf, "closestToQuaternion", ref_quat, cvm::quaternion (1.0, 0.0, 0.0, 0.0));
00065
00066
00067 if (!atoms.noforce) {
00068 rot.request_group2_gradients (atoms.size());
00069 }
00070
00071 rot.b_debug_gradients = this->b_debug_gradients;
00072 }
00073
00074
00075 colvar::orientation::orientation()
00076 : cvc ()
00077 {
00078 function_type = "orientation";
00079 x.type (colvarvalue::type_quaternion);
00080 }
00081
00082
00083 void colvar::orientation::calc_value()
00084 {
00085 atoms.reset_atoms_data();
00086 atoms.read_positions();
00087
00088 atoms_cog = atoms.center_of_geometry();
00089
00090 rot.calc_optimal_rotation (ref_pos, atoms.positions_shifted (-1.0 * atoms_cog));
00091
00092 if ((rot.q).inner (ref_quat) >= 0.0) {
00093 x.quaternion_value = rot.q;
00094 } else {
00095 x.quaternion_value = -1.0 * rot.q;
00096 }
00097 }
00098
00099
00100 void colvar::orientation::calc_gradients()
00101 {
00102
00103
00104
00105
00106 }
00107
00108
00109 void colvar::orientation::apply_force (colvarvalue const &force)
00110 {
00111 cvm::quaternion const &FQ = force.quaternion_value;
00112
00113 if (!atoms.noforce) {
00114 for (size_t ia = 0; ia < atoms.size(); ia++) {
00115 for (size_t i = 0; i < 4; i++) {
00116 atoms[ia].apply_force (FQ[i] * rot.dQ0_2[ia][i]);
00117 }
00118 }
00119 }
00120 }
00121
00122
00123
00124 colvar::orientation_angle::orientation_angle (std::string const &conf)
00125 : orientation (conf)
00126 {
00127 function_type = "orientation_angle";
00128 x.type (colvarvalue::type_scalar);
00129 }
00130
00131
00132 colvar::orientation_angle::orientation_angle()
00133 : orientation()
00134 {
00135 function_type = "orientation_angle";
00136 x.type (colvarvalue::type_scalar);
00137 }
00138
00139
00140 void colvar::orientation_angle::calc_value()
00141 {
00142 atoms.reset_atoms_data();
00143 atoms.read_positions();
00144
00145 atoms_cog = atoms.center_of_geometry();
00146
00147 rot.calc_optimal_rotation (ref_pos, atoms.positions_shifted (-1.0 * atoms_cog));
00148
00149 if ((rot.q).q0 >= 0.0) {
00150 x.real_value = (180.0/PI) * 2.0 * ::acos ((rot.q).q0);
00151 } else {
00152 x.real_value = (180.0/PI) * 2.0 * ::acos (-1.0 * (rot.q).q0);
00153 }
00154 }
00155
00156
00157 void colvar::orientation_angle::calc_gradients()
00158 {
00159 cvm::real const dxdq0 =
00160 ( ((rot.q).q0 * (rot.q).q0 < 1.0) ?
00161 ((180.0 / PI) * (-2.0) / ::sqrt (1.0 - ((rot.q).q0 * (rot.q).q0))) :
00162 0.0 );
00163
00164 for (size_t ia = 0; ia < atoms.size(); ia++) {
00165 atoms[ia].grad = (dxdq0 * (rot.dQ0_2[ia])[0]);
00166 }
00167 }
00168
00169
00170 void colvar::orientation_angle::apply_force (colvarvalue const &force)
00171 {
00172 cvm::real const &fw = force.real_value;
00173
00174 if (!atoms.noforce) {
00175 atoms.apply_colvar_force (fw);
00176 }
00177 }