NAMD
GlobalMasterSymmetry.C
Go to the documentation of this file.
1 
7 #include "InfoStream.h"
8 #include "Node.h"
9 #include "Molecule.h"
10 #include "NamdTypes.h"
11 
12 #include "SimParameters.h"
13 #include "GlobalMasterSymmetry.h"
14 #include "PDB.h"
15 #include "PDBData.h"
16 #include "fitrms.h"
17 #include "ConfigList.h"
18 #include <fstream>
19 #include <sstream>
20 #include <algorithm>
21 #include <iterator>
22 #include <stdlib.h>
23 //#define DEBUGM
24 #define MIN_DEBUG_LEVEL 1
25 #include "Debug.h"
26 //using namespace __gnu_cxx;
27 using namespace std;
28 //Read in and parse matrix file
29 void GlobalMasterSymmetry::parseMatrix(int id, char fileName []){
30  int count = 1;
31  string line;
32  ifstream matrixFile (fileName);
33  if (! matrixFile.is_open()){
34  NAMD_err((std::string("Error opening symmetry matrix file ") + fileName).c_str());
35  } else {
36  while (!matrixFile.eof()){
37  vector <string> tmp;
38  for (int i = 0; i < 4; i++){
39  getline(matrixFile, line);
40  istringstream iss(line);
41  copy(istream_iterator<string>(iss),
42  istream_iterator<string>(),
43  back_inserter<vector <string> >(tmp));
44  }
45  getline(matrixFile, line);
46  Matrix4Symmetry tmpmatrix;
47  if (tmp.size() < 16){NAMD_die("Error reading matrix file. Please check layout of the matrix file(s).");}
48  for(int j = 0; j < 16; j++){
49  tmpmatrix.mat[j] = atof(tmp[j].c_str());
50  }
51  tmpmatrix.transpose();
52  matrices.push_back(tmpmatrix);
53  count++;
54  }
55  matrixFile.close();
56  }
57 }
59  DebugM(3,"initialize called\n");
61  currentStep = params->firstTimestep;
62  firstStep = params->symmetryFirstStep;
63  lastStep = params->symmetryLastStep;
64  firstFullStep = params->symmetryFirstFullStep;
65  lastFullStep = params->symmetryLastFullStep;
66  K = params->symmetryk;
67 
68  StringList *klist = Node::Object()->configList->find("symmetrykfile");
69  if (!K){
70  //if (!params->symmetrykfile){NAMD_die("A pdb file containing per-atom force constants must be specified if symmetryk is not in configuration file!");}
71  if (!klist){NAMD_die("A pdb file containing per-atom force constants must be specified if symmetryk is not in configuration file!");}
72  //symmetrykfile = params->symmetrykfile;
73  }
74  scaleForces = params->symmetryScaleForces;
75  if (scaleForces && lastStep == -1){
76  NAMD_die("symmetryLastStep must be specified if symmetryScaleForces is enabled!");
77  }
78  StringList *matrixList = Node::Object()->configList->find("symmetryMatrixFile");
79  StringList *symmetryList = Node::Object()->configList->find("symmetryFile");
80  int symfileindex = 0;
81  if (!K) {symmetrykfile = klist->data;}
82  for (; symmetryList; symmetryList = symmetryList->next) {
83  parseAtoms(symmetryList->data, Node::Object()->molecule->numAtoms, symfileindex);
84  if(!K){
85  klist = klist->next;
86  if (klist){ symmetrykfile = klist->data;}
87  }
88  }
89 
90  map<int, vector<int> >::iterator it = simmap.begin();
91  if (!matrixList) {initialTransform();}
92  for (; matrixList; matrixList = matrixList->next, ++it){
93  parseMatrix(it->first, matrixList->data);
94  }
95 
96  DebugM(1,"done with initialize\n");
97 }
98 
99 //Aligns monomers based on transformation matrices
100 //found in matrix file
101 /*
102 void GlobalMasterSymmetry::alignMonomers(){
103  //this is assuming the matrices are written
104  //in order of monomer id designation (0, 1, 2,..etc)
105  map<int, vector<int> >::iterator simit = simmap.begin();
106  for (; simit!=simmap.end(); ++simit){
107  for(int x = 0; x < simit->second.size(); x++){
108  map<int, vector<int> >::iterator mit = dmap.find(simit->second[x]);
109  for (int i = 0; i < mit->second.size(); i++){
110  map<int, BigReal *>::iterator it = posmap.find(mit->second[i]);
111  matrices[(mit->first)-1].multpoint(it->second);
112  }
113  }
114  }
115 }
116 */
117 bool GlobalMasterSymmetry::gluInvertMatrix(const BigReal m[16], BigReal invOut[16])
118 {
119  BigReal inv[16], det;
120  int i;
121 
122  inv[0] = m[5]*m[10]*m[15] - m[5]*m[11]*m[14] - m[9]*m[6]*m[15]
123  + m[9]*m[7]*m[14] + m[13]*m[6]*m[11] - m[13]*m[7]*m[10];
124  inv[4] = -m[4]*m[10]*m[15] + m[4]*m[11]*m[14] + m[8]*m[6]*m[15]
125  - m[8]*m[7]*m[14] - m[12]*m[6]*m[11] + m[12]*m[7]*m[10];
126  inv[8] = m[4]*m[9]*m[15] - m[4]*m[11]*m[13] - m[8]*m[5]*m[15]
127  + m[8]*m[7]*m[13] + m[12]*m[5]*m[11] - m[12]*m[7]*m[9];
128  inv[12] = -m[4]*m[9]*m[14] + m[4]*m[10]*m[13] + m[8]*m[5]*m[14]
129  - m[8]*m[6]*m[13] - m[12]*m[5]*m[10] + m[12]*m[6]*m[9];
130  inv[1] = -m[1]*m[10]*m[15] + m[1]*m[11]*m[14] + m[9]*m[2]*m[15]
131  - m[9]*m[3]*m[14] - m[13]*m[2]*m[11] + m[13]*m[3]*m[10];
132  inv[5] = m[0]*m[10]*m[15] - m[0]*m[11]*m[14] - m[8]*m[2]*m[15]
133  + m[8]*m[3]*m[14] + m[12]*m[2]*m[11] - m[12]*m[3]*m[10];
134  inv[9] = -m[0]*m[9]*m[15] + m[0]*m[11]*m[13] + m[8]*m[1]*m[15]
135  - m[8]*m[3]*m[13] - m[12]*m[1]*m[11] + m[12]*m[3]*m[9];
136  inv[13] = m[0]*m[9]*m[14] - m[0]*m[10]*m[13] - m[8]*m[1]*m[14]
137  + m[8]*m[2]*m[13] + m[12]*m[1]*m[10] - m[12]*m[2]*m[9];
138  inv[2] = m[1]*m[6]*m[15] - m[1]*m[7]*m[14] - m[5]*m[2]*m[15]
139  + m[5]*m[3]*m[14] + m[13]*m[2]*m[7] - m[13]*m[3]*m[6];
140  inv[6] = -m[0]*m[6]*m[15] + m[0]*m[7]*m[14] + m[4]*m[2]*m[15]
141  - m[4]*m[3]*m[14] - m[12]*m[2]*m[7] + m[12]*m[3]*m[6];
142  inv[10] = m[0]*m[5]*m[15] - m[0]*m[7]*m[13] - m[4]*m[1]*m[15]
143  + m[4]*m[3]*m[13] + m[12]*m[1]*m[7] - m[12]*m[3]*m[5];
144  inv[14] = -m[0]*m[5]*m[14] + m[0]*m[6]*m[13] + m[4]*m[1]*m[14]
145  - m[4]*m[2]*m[13] - m[12]*m[1]*m[6] + m[12]*m[2]*m[5];
146  inv[3] = -m[1]*m[6]*m[11] + m[1]*m[7]*m[10] + m[5]*m[2]*m[11]
147  - m[5]*m[3]*m[10] - m[9]*m[2]*m[7] + m[9]*m[3]*m[6];
148  inv[7] = m[0]*m[6]*m[11] - m[0]*m[7]*m[10] - m[4]*m[2]*m[11]
149  + m[4]*m[3]*m[10] + m[8]*m[2]*m[7] - m[8]*m[3]*m[6];
150  inv[11] = -m[0]*m[5]*m[11] + m[0]*m[7]*m[9] + m[4]*m[1]*m[11]
151  - m[4]*m[3]*m[9] - m[8]*m[1]*m[7] + m[8]*m[3]*m[5];
152  inv[15] = m[0]*m[5]*m[10] - m[0]*m[6]*m[9] - m[4]*m[1]*m[10]
153  + m[4]*m[2]*m[9] + m[8]*m[1]*m[6] - m[8]*m[2]*m[5];
154 
155  det = m[0]*inv[0] + m[1]*inv[4] + m[2]*inv[8] + m[3]*inv[12];
156  if (det == 0)
157  return false;
158 
159  det = 1.0 / det;
160 
161  for (i = 0; i < 16; i++)
162  invOut[i] = inv[i] * det;
163 
164  return true;
165 }
166 
167 void GlobalMasterSymmetry::initialTransform(){
168  map<int, vector<int> >::iterator simit = simmap.begin();
169 
170  for (; simit!=simmap.end(); ++simit){
171  map<int, vector<int> >::iterator fit = dmap.find(simit->second[0]);
172  BigReal * first = new BigReal [3*fit->second.size()];
173  for(int i = 0; i < fit->second.size(); i++){
174  map<int, BigReal *>::iterator sit = posmap.find(fit->second[i]);
175  first[3*i] = sit->second[0];
176  first[3*i+1] = sit->second[1];
177  first[3*i+2] = sit->second[2];
178  }
179 
180  map<int, vector<int> >::iterator it = dmap.begin();
181  for(; it != dmap.end(); ++it){
182  if (std::find(simit->second.begin(), simit->second.end(), it->first)!=simit->second.end()){
183  BigReal * arr = new BigReal [3*it->second.size()];
184  for (int i = 0; i<it->second.size(); i++){
185  map<int, BigReal *>::iterator sit = posmap.find(it->second[i]);
186  arr[3*i] = sit->second[0];
187  arr[3*i+1] = sit->second[1];
188  arr[3*i+2] = sit->second[2];
189  }
190  BigReal ttt[16], pre[3], post[3];
191  BigReal curRMS = MatrixFitRMS(it->second.size(), arr, first, NULL, ttt);
192  int j;
193  for (j=0; j<3; j++) {
194  post[j] = ttt[4*j+3];
195  ttt[4*j+3] = 0;
196  pre[j] = ttt[12+j];
197  ttt[12+j] = 0;
198  }
199  Matrix4Symmetry result;
200  result.translate(pre);
201  result.multmatrix(Matrix4Symmetry(ttt));
202  result.translate(post);
203  matrices.push_back(result);
204 
205  delete [] arr;
206  }
207  }
208  delete [] first;
209  }
210 
211  for (int i = 0; i < matrices.size(); i++) {
212  matrices[i].transpose();
213  //iout << "Matrix: " << i << " " << matrices[i].mat[0] << " " << matrices[i].mat[1] << " " << matrices[i].mat[2] << " "<<matrices[i].mat[3] << "\n";
214  //iout << "Matrix: " << i << " " << matrices[i].mat[4] << " " << matrices[i].mat[5] << " " << matrices[i].mat[6] << " "<<matrices[i].mat[7] << "\n";
215  //iout << "Matrix: " << i << " " << matrices[i].mat[8] << " " << matrices[i].mat[9] << " " << matrices[i].mat[10] << " "<<matrices[i].mat[11] << "\n";
216  //iout << "Matrix: " << i << " " << matrices[i].mat[12] << " " << matrices[i].mat[13] << " " << matrices[i].mat[14] << " "<<matrices[i].mat[15] << "\n";
217  //iout <<"\n"<<endi;
218  matrices[i].transpose();
219  }
220 }
221 
222 void GlobalMasterSymmetry::parseAtoms(const char *file, int numTotalAtoms, int symfileindex) {
223  DebugM(3,"parseAtoms called\n");
224  PDB tmdpdb(file);
225  int numatoms = tmdpdb.num_atoms();
226  if (numatoms < 1)
227  NAMD_die("No atoms found in symmetryFile\n");
228  if (numatoms < numTotalAtoms)
229  iout << iWARN << "The number of atoms in symmetryFile is less than the total number of atoms in the structure.\n" << endi;
230  if (numatoms > numTotalAtoms)
231  NAMD_die("The number of atoms in symmetryFile must not exceed the total number of atoms in the structure!");
232  // if ( modifyRequestedAtoms().size() )
233  // NAMD_bug("GlobalMasterSymmetry::parseAtoms() modifyRequestedAtoms() not empty");
234 
235  Vector * atompos = new Vector[numatoms];
236  tmdpdb.get_all_positions(atompos);
237  if (K){symmetrykfile = file;}
238  PDB kpdb(symmetrykfile);
239 
240  int i;
241  for (i=0; i<numatoms; i++) {
242 #ifdef MEM_OPT_VERSION
243  PDBCoreData *atom = tmdpdb.atom(i);
244 #else
245  PDBAtom *atom = tmdpdb.atom(i); // get an atom from the file
246 #endif
247 
248  if (atom->occupancy() && atom->temperaturefactor()) { // if occupancy and beta are not 0, then add it!
249  // add the atom to the list
250  modifyRequestedAtoms().add(i);
251  if(!K){
252  #ifdef MEM_OPT_VERSION
253  PDBCoreData *atomk = kpdb.atom(i);
254  #else
255  PDBAtom *atomk = kpdb.atom(i); // get an atom from the file
256  #endif
257  //kmap[i] = atomk->occupancy();
258  kdmap[atom->temperaturefactor()][i] = atomk->occupancy();
259  }
260  BigReal *arr = new BigReal [3];
261  arr[0] = atompos[i].x;
262  arr[1] = atompos[i].y;
263  arr[2] = atompos[i].z;
264  posmap[i] = arr;
265 
266  bmap[atom->temperaturefactor()] = atom->occupancy();
267  //check to see if monomer id is already in the map
268  map <int, vector<int> >::iterator it = dmap.find((int)atom->temperaturefactor());
269  map <int, vector<int> >::iterator simit = simmap.find((int)atom->occupancy());
270  if (it != dmap.end()){
271  it->second.push_back(i); //add atomid to vector in proper existing monomer id
272  }
273  else{
274  dmap[(int)atom->temperaturefactor()] = vector <int> (1,i); //create new monomer id with atomid
275  }
276  if (simit != simmap.end()){
277  if (std::find(simit->second.begin(), simit->second.end(), atom->temperaturefactor()) == simit->second.end()){
278  simit->second.push_back(atom->temperaturefactor());
279  }
280  }
281  else {
282  simmap[(int)atom->occupancy()] = vector <int> (1, atom->temperaturefactor());
283  }
284  }
285  }
286 
287  map <int, vector<int> >::iterator simit = simmap.begin();
288  for (; simit != simmap.end(); ++simit){
289  map <int, vector<int> >::iterator sit = dmap.find(simit->second[0]);
290  int numatoms = sit->second.size();
291  for (int i = 0; i<simit->second.size(); i++){
292  map <int, vector<int> >::iterator fit = dmap.find(simit->second[i]);
293  if (fit->second.size() != numatoms){
294  NAMD_die("Every monomer must contain the same number of atoms!");
295  }
296  }
297  }
298  delete [] atompos;
299 }
300 
301 void GlobalMasterSymmetry::determineAverage() {
302 
303  map <int, vector<BigReal *> >::iterator delit = averagePos.begin();
304  for (; delit != averagePos.end(); ++delit){
305  for (int i = 0; i < delit->second.size(); i++){
306  delete [] delit->second[i];
307  }
308  delit->second.erase(delit->second.begin(), delit->second.end());
309  }
310  //std::map <int, BigReal * > posmap;
311  map <int, BigReal *>::iterator posit;
312  map <int, vector<int> >::iterator simit = simmap.begin();
313  for (; simit != simmap.end(); ++simit){
314 
315 
316  map <int, BigReal *>::iterator pit = posmap.begin();
317  for (; pit != posmap.end(); ++pit){delete [] pit->second;}
318  posmap.clear();
319 
320  map <int, vector<int> >::iterator dit = dmap.begin();
321  for (; dit!=dmap.end(); ++dit){
322  for (int i = 0; i < dit->second.size(); i++){
323  if (std::find(simit->second.begin(), simit->second.end(), dit->first)!=simit->second.end()){
324 
325  BigReal* arr = new BigReal[3];
326  arr[0] = positions[dit->second[i]].x;
327  arr[1] = positions[dit->second[i]].y;
328  arr[2] = positions[dit->second[i]].z;
329 
330  posmap[dit->second[i]] = arr;
331  }
332  }
333  }
334  averagePos[simit->first] = vector <BigReal *> ();
335  map <int, vector<int> >::iterator it = dmap.begin();
336  map <int, vector<int> >::iterator sit = dmap.find(simit->second[0]);
337  int numatoms = sit->second.size();
338  for (int i = 0; i < numatoms; i++){
339  BigReal *arr = new BigReal [3];
340  arr[0] = 0;
341  arr[1] = 0;
342  arr[2] = 0;
343  for (; it!=dmap.end(); ++it){
344  if (std::find(simit->second.begin(), simit->second.end(), it->first)!=simit->second.end()){
345  posit = posmap.find(it->second[i]);
346  matrices[(it->first)-1].multpoint(posit->second);
347  arr[0] += posit->second[0];
348  arr[1] += posit->second[1];
349  arr[2] += posit->second[2];
350  }
351  }
352  it = dmap.begin();
353  BigReal *avg = new BigReal[3];
354  avg[0] = arr[0]/(simit->second.size());
355  avg[1] = arr[1]/(simit->second.size());
356  avg[2] = arr[2]/(simit->second.size());
357  averagePos[simit->first].push_back(avg);
358  delete [] arr;
359  }
360 
361  }
362 
363 }
364 
365 void GlobalMasterSymmetry::backTransform(){
366  map <int, BigReal *>::iterator bit = backavg.begin();
367  for (; bit != backavg.end(); ++bit){delete [] bit->second;}
368  backavg.clear();
369 
370  map <int, vector<int> >::iterator it = dmap.begin();
371  for (; it!=dmap.end(); ++it){
372  map<int, int >::iterator bmit = bmap.find(it->first);
373  int bm = bmit->second;
374  map<int, vector <BigReal *> >::iterator avit = averagePos.find(bmit->second);
375  int numatoms = it->second.size();
376  BigReal *avg = new BigReal [3*numatoms];
377  for (int i = 0; i < numatoms; i++){
378  avg[3*i] = avit->second[i][0];
379  avg[3*i+1] = avit->second[i][1];
380  avg[3*i+2] = avit->second[i][2];
381  }
382  BigReal inverse[16];
383  matrices[it->first-1].transpose();
384  gluInvertMatrix(matrices[it->first-1].mat, inverse);
385  Matrix4Symmetry inv(inverse);
386  inv.transpose();
387  matrices[it->first-1].transpose();
388 
389  for (int k = 0; k < numatoms; k++){
390  inv.multpoint(avg+3*k);
391  }
392  backavg[it->first] = avg;
393  }
394 
395 }
397  map <int, BigReal *>::iterator pit = posmap.begin();
398  for (; pit != posmap.end(); ++pit){delete pit->second;}
399 }
400 void GlobalMasterSymmetry::calculate() {
401  // have to reset my forces every time.
402  modifyAppliedForces().resize(0);
403  modifyForcedAtoms().resize(0);
404 
405  // see if symmetry restraints should be active
406  if (currentStep < firstStep || (currentStep >= lastStep && lastStep != -1)) {
407  currentStep++;
408  return;
409  }
410 
411  //map<int, Position> positions;
412  AtomIDList::const_iterator a_i = getAtomIdBegin();
413  AtomIDList::const_iterator a_e = getAtomIdEnd();
414  PositionList::const_iterator p_i = getAtomPositionBegin();
415 
416  //create mapping of positions now to avoid
417  //going through these iterators for each domain
418  for ( ; a_i != a_e; ++a_i, ++p_i ){
419  positions[*a_i] = *p_i;
420  }
421 
422  map <int, vector<int> >::iterator it;
423  //map <int, BigReal *>::iterator pit = posmap.begin();
424  //for (; pit != posmap.end(); ++pit){delete [] pit->second;}
425 
426  // posmap.clear();
427  //for (it = dmap.begin(); it != dmap.end(); ++it){
428  // fetch the current coordinates
429 
430  //for (int i = 0; i < it->second.size(); i++){
431 
432  //BigReal* arr = new BigReal[3];
433  //arr[0] = positions[it->second[i]].x;
434  //arr[1] = positions[it->second[i]].y;
435  //arr[2] = positions[it->second[i]].z;
436 
437  // posmap[it->second[i]] = arr;
438  // }
439 //}
440 
441 // alignMonomers();
442  determineAverage();
443  backTransform();
444 
445  //iterate through all domains
446  for (it = dmap.begin(); it != dmap.end(); ++it){
447 
448  // fetch the current coordinates
449  BigReal *curpos = new BigReal[3*(it->second.size())];
450  for (int i = 0; i < it->second.size(); i++){
451  curpos[3*i ] = positions[it->second[i]].x;
452  curpos[3*i+1] = positions[it->second[i]].y;
453  curpos[3*i+2] = positions[it->second[i]].z;
454  }
455 
456 
457  BigReal *tmpavg = backavg[it->first];
458 
459  for (int i=0; i<it->second.size(); i++) {
460  BigReal k;
461  if(!K){
462  //k = kmap[it->second[i]];
463  k = kdmap[it->first][it->second[i]];
464  }
465  else{
466  k = K/it->second.size();
467  }
468  BigReal maxforce2 = 0.;
469  BigReal frac = -k;
470  if (scaleForces){
471 
472  if (currentStep < firstFullStep){
473  BigReal linear_evolve = (BigReal(currentStep-firstStep)) /
474  (firstFullStep-firstStep);
475  frac = frac*(linear_evolve);
476  }
477  if (currentStep > lastFullStep)
478  {
479  BigReal linear_evolve = (BigReal(currentStep-lastFullStep)) /
480  (lastStep-lastFullStep);
481  frac = frac*(1-linear_evolve);
482  }
483 
484  }
485  BigReal dx = curpos[3*i ] - tmpavg[3*i];
486 // iout << "DX: " << dx << "\n" << endi;
487  BigReal dy = curpos[3*i+1] - tmpavg[3*i+1];
488  BigReal dz = curpos[3*i+2] - tmpavg[3*i+2];
489  BigReal fvec[3] = { dx, dy, dz };
490  Vector force(fvec[0]*frac, fvec[1]*frac, fvec[2]*frac);
491  modifyForcedAtoms().add(it->second[i]);
492  modifyAppliedForces().add(force);
493  BigReal force2 = force.length2();
494  if ( force2 > maxforce2 ) maxforce2 = force2;
495  }
496  delete [] curpos;
497  }
498 
499  currentStep++;
500 }
static Node * Object()
Definition: Node.h:86
Definition: PDB.h:36
void NAMD_err(const char *err_msg)
Definition: common.C:170
void multmatrix(const Matrix4Symmetry &)
premultiply the matrix by the given matrix, this->other * this
BigReal temperaturefactor(void)
Definition: PDBData.C:450
void translate(BigReal x, BigReal y, BigReal z)
Definition: Vector.h:72
SimParameters * simParameters
Definition: Node.h:181
BigReal mat[16]
static int numatoms
Definition: ScriptTcl.C:65
int symmetryLastFullStep
#define DebugM(x, y)
Definition: Debug.h:75
std::ostream & endi(std::ostream &s)
Definition: InfoStream.C:54
BigReal z
Definition: Vector.h:74
std::ostream & iWARN(std::ostream &s)
Definition: InfoStream.C:82
#define iout
Definition: InfoStream.h:51
Bool symmetryScaleForces
const AtomID * const_iterator
Definition: ResizeArray.h:38
BigReal x
Definition: Vector.h:74
int numAtoms
Definition: Molecule.h:585
void NAMD_die(const char *err_msg)
Definition: common.C:147
ConfigList * configList
Definition: Node.h:182
BigReal MatrixFitRMS(int n, BigReal *v1, BigReal *v2, const BigReal *wt, BigReal *ttt)
Definition: fitrms.C:91
StringList * next
Definition: ConfigList.h:49
char * data
Definition: ConfigList.h:48
BigReal y
Definition: Vector.h:74
BigReal symmetryk
int symmetryFirstFullStep
BigReal occupancy(void)
Definition: PDBData.C:444
StringList * find(const char *name) const
Definition: ConfigList.C:341
Molecule * molecule
Definition: Node.h:179
double BigReal
Definition: common.h:123