~ubuntu-branches/ubuntu/vivid/psicode/vivid

« back to all changes in this revision

Viewing changes to src/lib/libqt/orient_fragment.cc

  • Committer: Bazaar Package Importer
  • Author(s): Michael Banck, Michael Banck, Daniel Leidert
  • Date: 2009-02-23 00:12:02 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20090223001202-rutldoy3dimfpesc
Tags: 3.4.0-1
* New upstream release.

[ Michael Banck ]
* debian/patches/01_DESTDIR.dpatch: Refreshed.
* debian/patches/02_FHS.dpatch: Removed, applied upstream.
* debian/patches/03_debian_docdir: Likewise.
* debian/patches/04_man.dpatch: Likewise.
* debian/patches/06_466828_fix_gcc_43_ftbfs.dpatch: Likewise.
* debian/patches/07_464867_move_executables: Fixed and refreshed.
* debian/patches/00list: Adjusted.
* debian/control: Improved description.
* debian/patches-held: Removed.
* debian/rules (install/psi3): Do not ship the ruby bindings for now.

[ Daniel Leidert ]
* debian/rules: Fix txtdir via DEB_MAKE_INSTALL_TARGET.
* debian/patches/01_DESTDIR.dpatch: Refreshed.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*! \file 
 
2
    \ingroup QT
 
3
    \brief function which places one fragment into the coordinate system of another
 
4
 
 
5
   int natoms_A, natoms_B - number of atoms in each fragment
 
6
   int P_A, P_B - number of ref pts to worry about, less than 3 for linear fragments
 
7
   double **geom_A, double **geom_B - geometry of fragments A and B - geom B is changed
 
8
   double **ref_coeff_A, double **ref_coeff_B - linear combinations which specify reference atoms
 
9
   double R_AB - distance between reference atoms #1 on each fragment
 
10
   theta_A, theta_B, tau, chi-A, chi-B - interfragment angles
 
11
*/
 
12
#include <stdio.h>
 
13
#include <stdlib.h>
 
14
#include <libciomr/libciomr.h>
 
15
#include <libqt/qt.h>
 
16
#include <math.h>
 
17
#include <physconst.h>
 
18
#include <psifiles.h>
 
19
 
 
20
extern "C" {
 
21
 
 
22
double dot_prod(double *v1, double *v2);
 
23
void cross_prod(double *v1, double *v2, double *out);
 
24
void unit_vec(double *B, double *A, double *AB);
 
25
 
 
26
void orient_fragment(int natom_A, int natom_B, int P_A, int P_B, double **geom_A, double **geom_B,
 
27
  double **ref_coeff_A, double **ref_coeff_B, double R_AB, double theta_A, double theta_B,
 
28
  double tau, double phi_A, double phi_B, FILE *outfile)
 
29
{
 
30
  int i, j, errcod, pts, xyz;
 
31
  double tval, norm, B_angle, R_B1B2, R_B2B3, e12[3], e12b[3], e12c[3], e12d[3], erot[3];
 
32
  double **ref_A, **ref_B, **ref_B_final;
 
33
  double sign, cross1[3], cross2[3], cross3[3], phi2, phi3;
 
34
 
 
35
  ref_A = block_matrix(3,3);
 
36
  ref_B = block_matrix(3,3);
 
37
  ref_B_final = block_matrix(3,3);
 
38
 
 
39
  /* stick SOMETHING in for non-specified reference atoms - necessary to prevent complaints
 
40
     about collinear reference atoms and to make zmat_point() work in such cases */
 
41
  if (P_A < 3) {
 
42
      for (xyz=0; xyz<3; ++xyz)
 
43
        ref_A[2][xyz] = (xyz+1)/_pi;
 
44
  }
 
45
  if (P_A < 2) {
 
46
      for (xyz=0; xyz<3; ++xyz)
 
47
        ref_A[1][xyz] = (xyz+1)/(2*_pi);
 
48
  }
 
49
 
 
50
  for (pts=0; pts<P_A; ++pts)
 
51
    for (xyz=0; xyz<3; ++xyz)
 
52
      for (i=0; i<natom_A; ++i)
 
53
        ref_A[pts][xyz] += ref_coeff_A[pts][i] * geom_A[i][xyz];
 
54
 
 
55
  for (pts=0; pts<P_B; ++pts)
 
56
    for (xyz=0; xyz<3; ++xyz)
 
57
      for (i=0; i<natom_B;++i)
 
58
        ref_B[pts][xyz] += ref_coeff_B[pts][i] * geom_B[i][xyz];
 
59
 
 
60
fprintf(outfile,"\tCoordinates for reference points on fragment A\n");
 
61
print_mat(ref_A,P_A,3,outfile);
 
62
fprintf(outfile,"\tCoordinates for reference points on fragment B (initial) \n");
 
63
print_mat(ref_B,P_B,3,outfile);
 
64
fprintf(outfile,"\tInterfragment coordinates:\n");
 
65
fprintf(outfile,"\t(1/)R_AB:%10.5f, theta_A:%10.5f, theta_B:%10.5f\n", R_AB, theta_A, theta_B);
 
66
fprintf(outfile,"\t     tau:%10.5f,   phi_A:%10.5f,   phi_B:%10.5f\n", tau, phi_A, phi_B);
 
67
 
 
68
  /* compute B1-B2 distance, B2-B3 distance, and B1-B2-B3 angle */
 
69
  R_B1B2 = 0.0;
 
70
  if (P_B>1) {
 
71
    for (xyz=0; xyz<3; ++xyz)
 
72
      R_B1B2 += (ref_B[1][xyz]-ref_B[0][xyz])*(ref_B[1][xyz]-ref_B[0][xyz]);
 
73
    R_B1B2 = sqrt(R_B1B2);
 
74
  }
 
75
  R_B2B3 = 0.0;
 
76
  B_angle = 0.0;
 
77
  if (P_B>2) {
 
78
    for (xyz=0; xyz<3; ++xyz)
 
79
      R_B2B3 += (ref_B[2][xyz]-ref_B[1][xyz])*(ref_B[2][xyz]-ref_B[1][xyz]);
 
80
    R_B2B3 = sqrt(R_B2B3);
 
81
    unit_vec(ref_B[1],ref_B[0],e12);
 
82
    unit_vec(ref_B[1],ref_B[2],e12b);
 
83
    B_angle = acos(dot_prod(e12,e12b))*180.0/_pi;
 
84
  }
 
85
 
 
86
    /* determine location of reference pts for B in coordinate system of A */
 
87
  zmat_point(ref_A[2], ref_A[1], ref_A[0], R_AB, theta_A, phi_A, ref_B_final[0]);
 
88
  if (P_B>1)
 
89
    zmat_point(ref_A[1], ref_A[0], ref_B_final[0], R_B1B2, theta_B, tau, ref_B_final[1]);
 
90
  if (P_B>2)
 
91
    zmat_point(ref_A[0], ref_B_final[0], ref_B_final[1], R_B2B3, B_angle, phi_B, ref_B_final[2]);
 
92
 
 
93
  fprintf(outfile,"Coordinates for references points for fragment B in coordinate system of A\n");
 
94
  print_mat(ref_B_final,P_B,3,outfile);
 
95
 
 
96
  /* translate geom_B to place B1 in correct location */
 
97
  for (xyz=0; xyz<3; ++xyz) {
 
98
    tval = ref_B_final[0][xyz] - ref_B[0][xyz];
 
99
    for (i=0; i<natom_B; ++i)
 
100
      geom_B[i][xyz] += tval;
 
101
  }
 
102
 
 
103
  for (pts=0; pts<P_B; ++pts)
 
104
    for (xyz=0; xyz<3; ++xyz) {
 
105
      ref_B[pts][xyz] = 0.0;
 
106
      for (i=0; i<natom_B;++i)
 
107
        ref_B[pts][xyz] += ref_coeff_B[pts][i] * geom_B[i][xyz];
 
108
    }
 
109
  //fprintf(outfile,"Reference points after translation (to fix point B1):\n");
 
110
  //print_mat(ref_B,P_B,3,outfile);
 
111
 
 
112
  if (P_B>1) { /* move fragment B to place reference point B2 in correct location */
 
113
    /* Determine rotational angle and axis */
 
114
    unit_vec(ref_B[1],       ref_B[0], e12);  /* v B1->B2 */
 
115
    unit_vec(ref_B_final[1], ref_B[0], e12b); /* v B1->B2_final */
 
116
    B_angle = acos(dot_prod(e12b,e12));
 
117
    fprintf(outfile,"Rotation by %f degrees (to fix point B2)\n", 180.0*B_angle/_pi); 
 
118
    if (fabs(B_angle) > 1.0e-7) {
 
119
      cross_prod(e12,e12b,erot);
 
120
 
 
121
      /* Move B to put B1 at origin */
 
122
      for (xyz=0; xyz<3; ++xyz) 
 
123
        for (i=0; i<natom_B;++i)
 
124
          geom_B[i][xyz] -= ref_B[0][xyz];
 
125
 
 
126
      /* Rotate B */
 
127
      rotate_vecs(erot, B_angle, geom_B, natom_B);
 
128
 
 
129
      /* Move B back to coordinate system of A */
 
130
      for (xyz=0; xyz<3; ++xyz) 
 
131
        for (i=0; i<natom_B;++i)
 
132
          geom_B[i][xyz] += ref_B[0][xyz];
 
133
 
 
134
      for (pts=0; pts<P_B; ++pts)
 
135
        for (xyz=0; xyz<3; ++xyz) {
 
136
          ref_B[pts][xyz] = 0.0;
 
137
          for (i=0; i<natom_B;++i)
 
138
            ref_B[pts][xyz] += ref_coeff_B[pts][i] * geom_B[i][xyz];
 
139
        }
 
140
      //fprintf(outfile,"Reference points after rotation (to fix point B2) \n");
 
141
      //print_mat(ref_B,P_B,3,outfile);
 
142
    }
 
143
  }
 
144
 
 
145
  if (P_B==3) { /* move fragment B to place reference point B3 in correct location */
 
146
    /* Determine rotational angle and axis */
 
147
    unit_vec(ref_B[1], ref_B[0], erot);  /* B1 -> B2 is rotation axis */
 
148
 
 
149
    /* Calculate B3-B1-B2-B3' torsion angle */
 
150
    unit_vec(ref_B[2], ref_B[0], e12);  /* v B1->B3 */
 
151
    unit_vec(ref_B[1], ref_B[0], e12b); /* v B1->B2 */
 
152
    phi2 = acos(dot_prod(e12,e12b));
 
153
    unit_vec(ref_B[0], ref_B[1], e12c);  /* v B2->B1 */
 
154
    unit_vec(ref_B_final[2], ref_B[1], e12d); /* v B2->B3' */
 
155
    phi3 = acos(dot_prod(e12c,e12d));
 
156
 
 
157
    cross_prod(e12 , e12b, cross1) ; /* B3->B1 x B1->B2 */
 
158
    cross_prod(e12c, e12d, cross2) ; /* B1->B2 x B2->B3 */
 
159
    tval = dot_prod(cross1, cross2) ;
 
160
 
 
161
    if ((sin(phi2) > 0.00001) && (sin(phi3) > 0.00001)) {
 
162
      tval /= sin(phi2) ;
 
163
      tval /= sin(phi3) ;
 
164
    }
 
165
    else tval = 2.0;
 
166
 
 
167
    if (tval > 0.99999) B_angle = 0.0000;
 
168
    else if (tval < -0.99999) B_angle = _pi;
 
169
    else B_angle = acos(tval) ;
 
170
 
 
171
    sign = 1.0; /* check sign */
 
172
    cross_prod(cross1, cross2, cross3);
 
173
    norm = sqrt(dot_prod(cross3, cross3));
 
174
    if (fabs(norm) > 0.00001) {
 
175
      for (xyz=0; xyz<3; ++xyz)
 
176
        cross3[xyz] *= 1.0/norm;
 
177
      tval = dot_prod(cross3, e12b);
 
178
      if (tval < 0.0) sign = -1.0;
 
179
    }
 
180
    B_angle *= sign;
 
181
 
 
182
    if (fabs(B_angle) > 1.0e-7) {
 
183
      fprintf(outfile,"Rotation by %f degrees (to fix point B3)\n", 180.0*B_angle/_pi); 
 
184
 
 
185
      /* Move B to put B2 at origin */
 
186
      for (xyz=0; xyz<3; ++xyz) 
 
187
        for (i=0; i<natom_B;++i)
 
188
          geom_B[i][xyz] -= ref_B[1][xyz];
 
189
  
 
190
      rotate_vecs(erot, B_angle, geom_B, natom_B);
 
191
  
 
192
      /* Translate B1 back to coordinate system of A */
 
193
      for (xyz=0; xyz<3; ++xyz) 
 
194
        for (i=0; i<natom_B;++i)
 
195
          geom_B[i][xyz] += ref_B[1][xyz];
 
196
 
 
197
      for (pts=0; pts<P_B; ++pts)
 
198
        for (xyz=0; xyz<3; ++xyz) {
 
199
          ref_B[pts][xyz] = 0.0;
 
200
          for (i=0; i<natom_B;++i)
 
201
            ref_B[pts][xyz] += ref_coeff_B[pts][i] * geom_B[i][xyz];
 
202
        }
 
203
        //fprintf(outfile,"Reference points on B after rotation for B2 \n");
 
204
        //print_mat(ref_B,P_B,3,outfile);
 
205
      }
 
206
  }
 
207
 
 
208
   /* check to see if desired reference points were obtained */
 
209
   tval = 0.0;
 
210
   for (i=0; i<P_B; ++i)
 
211
     for (xyz=0; xyz<3; ++xyz)
 
212
       tval += fabs(ref_B[i][xyz] - ref_B_final[i][xyz]);
 
213
   if (tval > 1.0e10) {
 
214
     fprintf(outfile, "Unable to construct multi-fragment geometry.");
 
215
     exit(PSI_RETURN_FAILURE);
 
216
   }
 
217
   else
 
218
     fprintf(outfile,"Successfully constructed multifragment geometry.\n");
 
219
 
 
220
  free_block(ref_A);
 
221
  free_block(ref_B);
 
222
  free_block(ref_B_final);
 
223
  return;
 
224
}
 
225
 
 
226
double dot_prod(double *v1, double *v2) {
 
227
  return v1[0]*v2[0]+ v1[1]*v2[1]+ v1[2]*v2[2];
 
228
}
 
229
void cross_prod(double *v1, double *v2, double *out) {
 
230
  out[0] = v1[1]*v2[2]-v1[2]*v2[1];
 
231
  out[1] = -v1[0]*v2[2]+v1[2]*v2[0];
 
232
  out[2] = v1[0]*v2[1]-v1[1]*v2[0];
 
233
  return;
 
234
}
 
235
void unit_vec(double *B, double *A, double *AB) {
 
236
  double norm = 0.0;
 
237
  int i;
 
238
  
 
239
  for (i=0; i<3; i++)
 
240
    norm += (A[i]-B[i])*(A[i]-B[i]);
 
241
  norm = sqrt(norm);
 
242
  for (i=0; i<3; i++)
 
243
    AB[i] = (B[i] - A[i]) / norm;
 
244
  return;
 
245
}
 
246
 
 
247
} /* extern "C" */
 
248