static void rand_rot(int natoms, rvec x[], rvec v[], vec4 xrot[], vec4 vrot[], gmx::DefaultRandomEngine * rng, rvec max_rot) { mat4 mt1, mt2, mr[DIM], mtemp1, mtemp2, mtemp3, mxtot, mvtot; rvec xcm; real phi; int i, m; gmx::UniformRealDistribution<real> dist(-1.0, 1.0); clear_rvec(xcm); for (i = 0; (i < natoms); i++) { for (m = 0; (m < DIM); m++) { xcm[m] += x[i][m]/natoms; /* get center of mass of one molecule */ } } fprintf(stderr, "center of geometry: %f, %f, %f\n", xcm[0], xcm[1], xcm[2]); /* move c.o.ma to origin */ gmx_mat4_init_translation(-xcm[XX], -xcm[YY], -xcm[ZZ], mt1); for (m = 0; (m < DIM); m++) { phi = M_PI*max_rot[m]*dist(*rng)/180; gmx_mat4_init_rotation(m, phi, mr[m]); } gmx_mat4_init_translation(xcm[XX], xcm[YY], xcm[ZZ], mt2); /* For gmx_mat4_mmul() we need to multiply in the opposite order * compared to normal mathematical notation. */ gmx_mat4_mmul(mtemp1, mt1, mr[XX]); gmx_mat4_mmul(mtemp2, mr[YY], mr[ZZ]); gmx_mat4_mmul(mtemp3, mtemp1, mtemp2); gmx_mat4_mmul(mxtot, mtemp3, mt2); gmx_mat4_mmul(mvtot, mr[XX], mtemp2); for (i = 0; (i < natoms); i++) { gmx_mat4_transform_point(mxtot, x[i], xrot[i]); gmx_mat4_transform_point(mvtot, v[i], vrot[i]); } }
static void rot_conf(t_atoms *atoms, rvec x[], rvec v[], real trans, real angle, rvec head, rvec tail, int isize, atom_id index[], rvec xout[], rvec vout[]) { rvec arrow, xcm; real theta, phi, arrow_len; mat4 Rx, Ry, Rz, Rinvy, Rinvz, Mtot; mat4 temp1, temp2, temp3; vec4 xv; int i, ai; rvec_sub(tail, head, arrow); arrow_len = norm(arrow); if (debug) { fprintf(debug, "Arrow vector: %10.4f %10.4f %10.4f\n", arrow[XX], arrow[YY], arrow[ZZ]); fprintf(debug, "Effective translation %g nm\n", trans); } if (arrow_len == 0.0) { gmx_fatal(FARGS, "Arrow vector not given"); } /* Copy all aoms to output */ for (i = 0; (i < atoms->nr); i++) { copy_rvec(x[i], xout[i]); copy_rvec(v[i], vout[i]); } /* Compute center of mass and move atoms there */ clear_rvec(xcm); for (i = 0; (i < isize); i++) { rvec_inc(xcm, x[index[i]]); } for (i = 0; (i < DIM); i++) { xcm[i] /= isize; } if (debug) { fprintf(debug, "Center of mass: %10.4f %10.4f %10.4f\n", xcm[XX], xcm[YY], xcm[ZZ]); } for (i = 0; (i < isize); i++) { rvec_sub(x[index[i]], xcm, xout[index[i]]); } /* Compute theta and phi that describe the arrow */ theta = std::acos(arrow[ZZ]/arrow_len); phi = std::atan2(arrow[YY]/arrow_len, arrow[XX]/arrow_len); if (debug) { fprintf(debug, "Phi = %.1f, Theta = %.1f\n", RAD2DEG*phi, RAD2DEG*theta); } /* Now the total rotation matrix: */ /* Rotate a couple of times */ gmx_mat4_init_rotation(ZZ, -phi, Rz); gmx_mat4_init_rotation(YY, M_PI/2-theta, Ry); gmx_mat4_init_rotation(XX, angle*DEG2RAD, Rx); Rx[WW][XX] = trans; gmx_mat4_init_rotation(YY, theta-M_PI/2, Rinvy); gmx_mat4_init_rotation(ZZ, phi, Rinvz); gmx_mat4_mmul(temp1, Ry, Rz); gmx_mat4_mmul(temp2, Rinvy, Rx); gmx_mat4_mmul(temp3, temp2, temp1); gmx_mat4_mmul(Mtot, Rinvz, temp3); if (debug) { gmx_mat4_print(debug, "Rz", Rz); gmx_mat4_print(debug, "Ry", Ry); gmx_mat4_print(debug, "Rx", Rx); gmx_mat4_print(debug, "Rinvy", Rinvy); gmx_mat4_print(debug, "Rinvz", Rinvz); gmx_mat4_print(debug, "Mtot", Mtot); } for (i = 0; (i < isize); i++) { ai = index[i]; gmx_mat4_transform_point(Mtot, xout[ai], xv); rvec_add(xv, xcm, xout[ai]); gmx_mat4_transform_point(Mtot, v[ai], xv); copy_rvec(xv, vout[ai]); } }