00001
00007 #include "InfoStream.h"
00008 #include "Node.h"
00009 #include "Molecule.h"
00010 #include "NamdTypes.h"
00011
00012 #include "SimParameters.h"
00013 #include "GlobalMasterSymmetry.h"
00014 #include "PDB.h"
00015 #include "PDBData.h"
00016 #include "fitrms.h"
00017 #include <fstream>
00018 #include <sstream>
00019 #include <algorithm>
00020 #include <iterator>
00021 #include <stdlib.h>
00022
00023 #define MIN_DEBUG_LEVEL 1
00024 #include "Debug.h"
00025
00026 using namespace std;
00027
00028 void GlobalMasterSymmetry::parseMatrix(int id, char fileName []){
00029 int count = 1;
00030 string line;
00031 ifstream matrixFile (fileName);
00032 if (matrixFile.is_open()){
00033 while (!matrixFile.eof()){
00034 vector <string> tmp;
00035 for (int i = 0; i < 4; i++){
00036 getline(matrixFile, line);
00037 istringstream iss(line);
00038 copy(istream_iterator<string>(iss),
00039 istream_iterator<string>(),
00040 back_inserter<vector <string> >(tmp));
00041 }
00042 getline(matrixFile, line);
00043 Matrix4Symmetry tmpmatrix;
00044 if (tmp.size() < 16){NAMD_die("Error reading matrix file. Please check layout of the matrix file(s).");}
00045 for(int j = 0; j < 16; j++){
00046 tmpmatrix.mat[j] = atof(tmp[j].c_str());
00047 }
00048 tmpmatrix.transpose();
00049 matrices.push_back(tmpmatrix);
00050 count++;
00051 }
00052 matrixFile.close();
00053 }
00054 }
00055 GlobalMasterSymmetry::GlobalMasterSymmetry() {
00056 DebugM(3,"initialize called\n");
00057 SimParameters *params = Node::Object()->simParameters;
00058 currentStep = params->firstTimestep;
00059 firstStep = params->symmetryFirstStep;
00060 lastStep = params->symmetryLastStep;
00061 firstFullStep = params->symmetryFirstFullStep;
00062 lastFullStep = params->symmetryLastFullStep;
00063 K = params->symmetryk;
00064
00065 StringList *klist = Node::Object()->configList->find("symmetrykfile");
00066 if (!K){
00067
00068 if (!klist){NAMD_die("A pdb file containing per-atom force constants must be specified if symmetryk is not in configuration file!");}
00069
00070 }
00071 scaleForces = params->symmetryScaleForces;
00072 if (scaleForces && lastStep == -1){
00073 NAMD_die("symmetryLastStep must be specified if symmetryScaleForces is enabled!");
00074 }
00075 StringList *matrixList = Node::Object()->configList->find("symmetryMatrixFile");
00076 StringList *symmetryList = Node::Object()->configList->find("symmetryFile");
00077 int symfileindex = 0;
00078 if (!K) {symmetrykfile = klist->data;}
00079 for (; symmetryList; symmetryList = symmetryList->next) {
00080 parseAtoms(symmetryList->data, Node::Object()->molecule->numAtoms, symfileindex);
00081 if(!K){
00082 klist = klist->next;
00083 if (klist){ symmetrykfile = klist->data;}
00084 }
00085 }
00086
00087 map<int, vector<int> >::iterator it = simmap.begin();
00088 if (!matrixList) {initialTransform();}
00089 for (; matrixList; matrixList = matrixList->next, ++it){
00090 parseMatrix(it->first, matrixList->data);
00091 }
00092
00093 DebugM(1,"done with initialize\n");
00094 }
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114 bool GlobalMasterSymmetry::gluInvertMatrix(const BigReal m[16], BigReal invOut[16])
00115 {
00116 BigReal inv[16], det;
00117 int i;
00118
00119 inv[0] = m[5]*m[10]*m[15] - m[5]*m[11]*m[14] - m[9]*m[6]*m[15]
00120 + m[9]*m[7]*m[14] + m[13]*m[6]*m[11] - m[13]*m[7]*m[10];
00121 inv[4] = -m[4]*m[10]*m[15] + m[4]*m[11]*m[14] + m[8]*m[6]*m[15]
00122 - m[8]*m[7]*m[14] - m[12]*m[6]*m[11] + m[12]*m[7]*m[10];
00123 inv[8] = m[4]*m[9]*m[15] - m[4]*m[11]*m[13] - m[8]*m[5]*m[15]
00124 + m[8]*m[7]*m[13] + m[12]*m[5]*m[11] - m[12]*m[7]*m[9];
00125 inv[12] = -m[4]*m[9]*m[14] + m[4]*m[10]*m[13] + m[8]*m[5]*m[14]
00126 - m[8]*m[6]*m[13] - m[12]*m[5]*m[10] + m[12]*m[6]*m[9];
00127 inv[1] = -m[1]*m[10]*m[15] + m[1]*m[11]*m[14] + m[9]*m[2]*m[15]
00128 - m[9]*m[3]*m[14] - m[13]*m[2]*m[11] + m[13]*m[3]*m[10];
00129 inv[5] = m[0]*m[10]*m[15] - m[0]*m[11]*m[14] - m[8]*m[2]*m[15]
00130 + m[8]*m[3]*m[14] + m[12]*m[2]*m[11] - m[12]*m[3]*m[10];
00131 inv[9] = -m[0]*m[9]*m[15] + m[0]*m[11]*m[13] + m[8]*m[1]*m[15]
00132 - m[8]*m[3]*m[13] - m[12]*m[1]*m[11] + m[12]*m[3]*m[9];
00133 inv[13] = m[0]*m[9]*m[14] - m[0]*m[10]*m[13] - m[8]*m[1]*m[14]
00134 + m[8]*m[2]*m[13] + m[12]*m[1]*m[10] - m[12]*m[2]*m[9];
00135 inv[2] = m[1]*m[6]*m[15] - m[1]*m[7]*m[14] - m[5]*m[2]*m[15]
00136 + m[5]*m[3]*m[14] + m[13]*m[2]*m[7] - m[13]*m[3]*m[6];
00137 inv[6] = -m[0]*m[6]*m[15] + m[0]*m[7]*m[14] + m[4]*m[2]*m[15]
00138 - m[4]*m[3]*m[14] - m[12]*m[2]*m[7] + m[12]*m[3]*m[6];
00139 inv[10] = m[0]*m[5]*m[15] - m[0]*m[7]*m[13] - m[4]*m[1]*m[15]
00140 + m[4]*m[3]*m[13] + m[12]*m[1]*m[7] - m[12]*m[3]*m[5];
00141 inv[14] = -m[0]*m[5]*m[14] + m[0]*m[6]*m[13] + m[4]*m[1]*m[14]
00142 - m[4]*m[2]*m[13] - m[12]*m[1]*m[6] + m[12]*m[2]*m[5];
00143 inv[3] = -m[1]*m[6]*m[11] + m[1]*m[7]*m[10] + m[5]*m[2]*m[11]
00144 - m[5]*m[3]*m[10] - m[9]*m[2]*m[7] + m[9]*m[3]*m[6];
00145 inv[7] = m[0]*m[6]*m[11] - m[0]*m[7]*m[10] - m[4]*m[2]*m[11]
00146 + m[4]*m[3]*m[10] + m[8]*m[2]*m[7] - m[8]*m[3]*m[6];
00147 inv[11] = -m[0]*m[5]*m[11] + m[0]*m[7]*m[9] + m[4]*m[1]*m[11]
00148 - m[4]*m[3]*m[9] - m[8]*m[1]*m[7] + m[8]*m[3]*m[5];
00149 inv[15] = m[0]*m[5]*m[10] - m[0]*m[6]*m[9] - m[4]*m[1]*m[10]
00150 + m[4]*m[2]*m[9] + m[8]*m[1]*m[6] - m[8]*m[2]*m[5];
00151
00152 det = m[0]*inv[0] + m[1]*inv[4] + m[2]*inv[8] + m[3]*inv[12];
00153 if (det == 0)
00154 return false;
00155
00156 det = 1.0 / det;
00157
00158 for (i = 0; i < 16; i++)
00159 invOut[i] = inv[i] * det;
00160
00161 return true;
00162 }
00163
00164 void GlobalMasterSymmetry::initialTransform(){
00165 map<int, vector<int> >::iterator simit = simmap.begin();
00166
00167 for (; simit!=simmap.end(); ++simit){
00168 map<int, vector<int> >::iterator fit = dmap.find(simit->second[0]);
00169 BigReal * first = new BigReal [3*fit->second.size()];
00170 for(int i = 0; i < fit->second.size(); i++){
00171 map<int, BigReal *>::iterator sit = posmap.find(fit->second[i]);
00172 first[3*i] = sit->second[0];
00173 first[3*i+1] = sit->second[1];
00174 first[3*i+2] = sit->second[2];
00175 }
00176
00177 map<int, vector<int> >::iterator it = dmap.begin();
00178 for(; it != dmap.end(); ++it){
00179 if (std::find(simit->second.begin(), simit->second.end(), it->first)!=simit->second.end()){
00180 BigReal * arr = new BigReal [3*it->second.size()];
00181 for (int i = 0; i<it->second.size(); i++){
00182 map<int, BigReal *>::iterator sit = posmap.find(it->second[i]);
00183 arr[3*i] = sit->second[0];
00184 arr[3*i+1] = sit->second[1];
00185 arr[3*i+2] = sit->second[2];
00186 }
00187 BigReal ttt[16], pre[3], post[3];
00188 BigReal curRMS = MatrixFitRMS(it->second.size(), arr, first, NULL, ttt);
00189 int j;
00190 for (j=0; j<3; j++) {
00191 post[j] = ttt[4*j+3];
00192 ttt[4*j+3] = 0;
00193 pre[j] = ttt[12+j];
00194 ttt[12+j] = 0;
00195 }
00196 Matrix4Symmetry result;
00197 result.translate(pre);
00198 result.multmatrix(Matrix4Symmetry(ttt));
00199 result.translate(post);
00200 matrices.push_back(result);
00201
00202 delete [] arr;
00203 }
00204 }
00205 delete [] first;
00206 }
00207
00208 for (int i = 0; i < matrices.size(); i++) {
00209 matrices[i].transpose();
00210
00211
00212
00213
00214
00215 matrices[i].transpose();
00216 }
00217 }
00218
00219 void GlobalMasterSymmetry::parseAtoms(const char *file, int numTotalAtoms, int symfileindex) {
00220 DebugM(3,"parseAtoms called\n");
00221 PDB tmdpdb(file);
00222 int numatoms = tmdpdb.num_atoms();
00223 if (numatoms < 1)
00224 NAMD_die("No atoms found in symmetryFile\n");
00225 if (numatoms != numTotalAtoms)
00226 NAMD_die("The number of atoms in symmetryFile must be equal to the total number of atoms in the structure!");
00227
00228
00229
00230 Vector * atompos = new Vector[numatoms];
00231 tmdpdb.get_all_positions(atompos);
00232 if (K){symmetrykfile = file;}
00233 PDB kpdb(symmetrykfile);
00234
00235 int i;
00236 for (i=0; i<numatoms; i++) {
00237 #ifdef MEM_OPT_VERSION
00238 PDBCoreData *atom = tmdpdb.atom(i);
00239 #else
00240 PDBAtom *atom = tmdpdb.atom(i);
00241 #endif
00242
00243 if (atom->occupancy() && atom->temperaturefactor()) {
00244
00245 modifyRequestedAtoms().add(i);
00246 if(!K){
00247 #ifdef MEM_OPT_VERSION
00248 PDBCoreData *atomk = kpdb.atom(i);
00249 #else
00250 PDBAtom *atomk = kpdb.atom(i);
00251 #endif
00252
00253 kdmap[atom->temperaturefactor()][i] = atomk->occupancy();
00254 }
00255 BigReal *arr = new BigReal [3];
00256 arr[0] = atompos[i].x;
00257 arr[1] = atompos[i].y;
00258 arr[2] = atompos[i].z;
00259 posmap[i] = arr;
00260
00261 bmap[atom->temperaturefactor()] = atom->occupancy();
00262
00263 map <int, vector<int> >::iterator it = dmap.find((int)atom->temperaturefactor());
00264 map <int, vector<int> >::iterator simit = simmap.find((int)atom->occupancy());
00265 if (it != dmap.end()){
00266 it->second.push_back(i);
00267 }
00268 else{
00269 dmap[(int)atom->temperaturefactor()] = vector <int> (1,i);
00270 }
00271 if (simit != simmap.end()){
00272 if (std::find(simit->second.begin(), simit->second.end(), atom->temperaturefactor()) == simit->second.end()){
00273 simit->second.push_back(atom->temperaturefactor());
00274 }
00275 }
00276 else {
00277 simmap[(int)atom->occupancy()] = vector <int> (1, atom->temperaturefactor());
00278 }
00279 }
00280 }
00281
00282 map <int, vector<int> >::iterator simit = simmap.begin();
00283 for (; simit != simmap.end(); ++simit){
00284 map <int, vector<int> >::iterator sit = dmap.find(simit->second[0]);
00285 int numatoms = sit->second.size();
00286 for (int i = 0; i<simit->second.size(); i++){
00287 map <int, vector<int> >::iterator fit = dmap.find(simit->second[i]);
00288 if (fit->second.size() != numatoms){
00289 NAMD_die("Every monomer must contain the same number of atoms!");
00290 }
00291 }
00292 }
00293 delete [] atompos;
00294 }
00295
00296 void GlobalMasterSymmetry::determineAverage() {
00297
00298 map <int, vector<BigReal *> >::iterator delit = averagePos.begin();
00299 for (; delit != averagePos.end(); ++delit){
00300 for (int i = 0; i < delit->second.size(); i++){
00301 delete [] delit->second[i];
00302 }
00303 delit->second.erase(delit->second.begin(), delit->second.end());
00304 }
00305
00306 map <int, BigReal *>::iterator posit;
00307 map <int, vector<int> >::iterator simit = simmap.begin();
00308 for (; simit != simmap.end(); ++simit){
00309
00310
00311 map <int, BigReal *>::iterator pit = posmap.begin();
00312 for (; pit != posmap.end(); ++pit){delete [] pit->second;}
00313 posmap.clear();
00314
00315 map <int, vector<int> >::iterator dit = dmap.begin();
00316 for (; dit!=dmap.end(); ++dit){
00317 for (int i = 0; i < dit->second.size(); i++){
00318 if (std::find(simit->second.begin(), simit->second.end(), dit->first)!=simit->second.end()){
00319
00320 BigReal* arr = new BigReal[3];
00321 arr[0] = positions[dit->second[i]].x;
00322 arr[1] = positions[dit->second[i]].y;
00323 arr[2] = positions[dit->second[i]].z;
00324
00325 posmap[dit->second[i]] = arr;
00326 }
00327 }
00328 }
00329 averagePos[simit->first] = vector <BigReal *> ();
00330 map <int, vector<int> >::iterator it = dmap.begin();
00331 map <int, vector<int> >::iterator sit = dmap.find(simit->second[0]);
00332 int numatoms = sit->second.size();
00333 for (int i = 0; i < numatoms; i++){
00334 BigReal *arr = new BigReal [3];
00335 arr[0] = 0;
00336 arr[1] = 0;
00337 arr[2] = 0;
00338 for (; it!=dmap.end(); ++it){
00339 if (std::find(simit->second.begin(), simit->second.end(), it->first)!=simit->second.end()){
00340 posit = posmap.find(it->second[i]);
00341 matrices[(it->first)-1].multpoint(posit->second);
00342 arr[0] += posit->second[0];
00343 arr[1] += posit->second[1];
00344 arr[2] += posit->second[2];
00345 }
00346 }
00347 it = dmap.begin();
00348 BigReal *avg = new BigReal[3];
00349 avg[0] = arr[0]/(simit->second.size());
00350 avg[1] = arr[1]/(simit->second.size());
00351 avg[2] = arr[2]/(simit->second.size());
00352 averagePos[simit->first].push_back(avg);
00353 delete [] arr;
00354 }
00355
00356 }
00357
00358 }
00359
00360 void GlobalMasterSymmetry::backTransform(){
00361 map <int, BigReal *>::iterator bit = backavg.begin();
00362 for (; bit != backavg.end(); ++bit){delete [] bit->second;}
00363 backavg.clear();
00364
00365 map <int, vector<int> >::iterator it = dmap.begin();
00366 for (; it!=dmap.end(); ++it){
00367 map<int, int >::iterator bmit = bmap.find(it->first);
00368 int bm = bmit->second;
00369 map<int, vector <BigReal *> >::iterator avit = averagePos.find(bmit->second);
00370 int numatoms = it->second.size();
00371 BigReal *avg = new BigReal [3*numatoms];
00372 for (int i = 0; i < numatoms; i++){
00373 avg[3*i] = avit->second[i][0];
00374 avg[3*i+1] = avit->second[i][1];
00375 avg[3*i+2] = avit->second[i][2];
00376 }
00377 BigReal inverse[16];
00378 matrices[it->first-1].transpose();
00379 gluInvertMatrix(matrices[it->first-1].mat, inverse);
00380 Matrix4Symmetry inv(inverse);
00381 inv.transpose();
00382 matrices[it->first-1].transpose();
00383
00384 for (int k = 0; k < numatoms; k++){
00385 inv.multpoint(avg+3*k);
00386 }
00387 backavg[it->first] = avg;
00388 }
00389
00390 }
00391 GlobalMasterSymmetry::~GlobalMasterSymmetry() {
00392 map <int, BigReal *>::iterator pit = posmap.begin();
00393 for (; pit != posmap.end(); ++pit){delete pit->second;}
00394 }
00395 void GlobalMasterSymmetry::calculate() {
00396
00397 modifyAppliedForces().resize(0);
00398 modifyForcedAtoms().resize(0);
00399
00400
00401 if (currentStep < firstStep || (currentStep >= lastStep && lastStep != -1)) {
00402 currentStep++;
00403 return;
00404 }
00405
00406
00407 AtomIDList::const_iterator a_i = getAtomIdBegin();
00408 AtomIDList::const_iterator a_e = getAtomIdEnd();
00409 PositionList::const_iterator p_i = getAtomPositionBegin();
00410
00411
00412
00413 for ( ; a_i != a_e; ++a_i, ++p_i ){
00414 positions[*a_i] = *p_i;
00415 }
00416
00417 map <int, vector<int> >::iterator it;
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437 determineAverage();
00438 backTransform();
00439
00440
00441 for (it = dmap.begin(); it != dmap.end(); ++it){
00442
00443
00444 BigReal *curpos = new BigReal[3*(it->second.size())];
00445 for (int i = 0; i < it->second.size(); i++){
00446 curpos[3*i ] = positions[it->second[i]].x;
00447 curpos[3*i+1] = positions[it->second[i]].y;
00448 curpos[3*i+2] = positions[it->second[i]].z;
00449 }
00450
00451
00452 BigReal *tmpavg = backavg[it->first];
00453
00454 for (int i=0; i<it->second.size(); i++) {
00455 BigReal k;
00456 if(!K){
00457
00458 k = kdmap[it->first][it->second[i]];
00459 }
00460 else{
00461 k = K/it->second.size();
00462 }
00463 BigReal maxforce2 = 0.;
00464 BigReal frac = -k;
00465 if (scaleForces){
00466
00467 if (currentStep < firstFullStep){
00468 BigReal linear_evolve = (BigReal(currentStep-firstStep)) /
00469 (firstFullStep-firstStep);
00470 frac = frac*(linear_evolve);
00471 }
00472 if (currentStep > lastFullStep)
00473 {
00474 BigReal linear_evolve = (BigReal(currentStep-lastFullStep)) /
00475 (lastStep-lastFullStep);
00476 frac = frac*(1-linear_evolve);
00477 }
00478
00479 }
00480 BigReal dx = curpos[3*i ] - tmpavg[3*i];
00481
00482 BigReal dy = curpos[3*i+1] - tmpavg[3*i+1];
00483 BigReal dz = curpos[3*i+2] - tmpavg[3*i+2];
00484 BigReal fvec[3] = { dx, dy, dz };
00485 Vector force(fvec[0]*frac, fvec[1]*frac, fvec[2]*frac);
00486 modifyForcedAtoms().add(it->second[i]);
00487 modifyAppliedForces().add(force);
00488 BigReal force2 = force.length2();
00489 if ( force2 > maxforce2 ) maxforce2 = force2;
00490 }
00491 delete [] curpos;
00492 }
00493
00494 currentStep++;
00495 }