Exemple #1
0
void get_transform_to_orthonormal_cell(const float *cell, const float *center, Matrix4 &transform) {
  // Orthogonalize system:
  // Find an orthonormal basis of the cell (in cartesian coords).
  // If the cell vectors from VMD/NAMD are used this should actually always
  // return the identity matrix due to the way the cell vectors A, B and C
  // are defined (i.e. A || x; B lies in the x,y-plane; A, B, C form a right
  // hand system).
  float obase[3*3];
  orthonormal_basis(cell, obase);

  // Get orthonormal base in cartesian coordinates (it is the inverse of the
  // obase->cartesian transformation):
  float identity[3*3] = {1, 0, 0, 0, 1, 0, 0, 0, 1};
  float obase_cartcoor[3*3];
  basis_change(obase, identity, obase_cartcoor, 3);


  // Transform 3x3 into 4x4 matrix:
  Matrix4 obase2cartinv;
  trans_from_rotate(obase_cartcoor, &obase2cartinv);

  // This is the matrix for the obase->cartesian transformation:
  Matrix4 obase2cart = obase2cartinv;
  obase2cart.inverse();

  // Get coordinates of cell in terms of obase
  float m[3*3]; 
  basis_change(cell, obase, m, 3);
  Matrix4 rotmat;
  trans_from_rotate(m, &rotmat);
  rotmat.inverse();

  
  // Actually we have:
  // transform = translation * obase2cart * obase2cartinv * rotmat * obase2cart
  //                           `------------v------------'
  //                                       = 1
  transform = obase2cart;
  transform.multmatrix(rotmat); // pre-multiplication

  // Finally we need to apply the translation of the origin
  float origin[3];
  vec_copy(origin, center);
  vec_scaled_add(origin, -0.5, &cell[0]);
  vec_scaled_add(origin, -0.5, &cell[3]);
  vec_scaled_add(origin, -0.5, &cell[6]);
  vec_negate(origin, origin);
  //printf("origin={%g %g %g}\n", origin[0], origin[1], origin[2]);
  transform.translate(origin);
}
Exemple #2
0
void SMat<CoeffRing>::subtractInPlace(const SMat<CoeffRing> &B)
// this -= B.
// assumption:the assert statements below:
{
  assert(&B.ring() == &ring());
  assert(B.numRows() == numRows());
  assert(B.numColumns() == numColumns());

  for (size_t c = 0; c < numColumns(); c++)
    {
      sparsevec *v = vec_copy(B.columns_[c]);
      vec_negate(v);
      vec_add_to(columns_[c], v);
    }
}
void TachyonDisplayDevice::start_clipgroup(void) {
  int i;
  int planesenabled = 0;

  for (i=0; i<VMD_MAX_CLIP_PLANE; i++) {
    if (clip_mode[i] > 0) {
      planesenabled++;  /* count number of active clipping planes */
      if (clip_mode[i] > 1)
        warningflags |= FILERENDERER_NOCLIP; /* emit warnings */
    }
  }

  if (planesenabled > 0) {
    fprintf(outfile, "Start_ClipGroup\n");
    fprintf(outfile, " NumPlanes %d\n", planesenabled);
    for (i=0; i<VMD_MAX_CLIP_PLANE; i++) { 
      if (clip_mode[i] > 0) {
        float tachyon_clip_center[3]; 
        float tachyon_clip_normal[3];
        float tachyon_clip_distance;

        inclipgroup = 1; // we're in a clipping group presently

        // Transform the plane center and the normal
        (transMat.top()).multpoint3d(clip_center[i], tachyon_clip_center);
        (transMat.top()).multnorm3d(clip_normal[i], tachyon_clip_normal);
        vec_negate(tachyon_clip_normal, tachyon_clip_normal);

        // Tachyon uses the distance from the origin to the plane for its
        // representation, instead of the plane center
        tachyon_clip_distance = dot_prod(tachyon_clip_normal, tachyon_clip_center);

        fprintf(outfile, "%g %g %g %g\n", tachyon_clip_normal[0], 
                tachyon_clip_normal[1], -tachyon_clip_normal[2], 
                tachyon_clip_distance);
      }    
    }
    fprintf(outfile, "\n");
  } else {
    inclipgroup = 0; // Not currently in a clipping group
  }
}
Exemple #4
0
vec<N,S>
operator-(vec<N,S> const& v) {
  return vec_negate(v);
}
Exemple #5
0
static void
compute_grad_point(struct efp *efp, size_t frag_idx, size_t pt_idx)
{
	const struct frag *fr_i = efp->frags + frag_idx;
	const struct polarizable_pt *pt_i = fr_i->polarizable_pts + pt_idx;
	size_t idx_i = fr_i->polarizable_offset + pt_idx;

	vec_t dipole_i = {
		0.5 * (efp->indip[idx_i].x + efp->indipconj[idx_i].x),
		0.5 * (efp->indip[idx_i].y + efp->indipconj[idx_i].y),
		0.5 * (efp->indip[idx_i].z + efp->indipconj[idx_i].z)
	};

	for (size_t j = 0; j < efp->n_frag; j++) {
		if (j == frag_idx || efp_skip_frag_pair(efp, frag_idx, j))
			continue;

		struct frag *fr_j = efp->frags + j;
		struct swf swf = efp_make_swf(efp, fr_i, fr_j);

		/* energy without switching applied */
		double energy = 0.0;

		/* induced dipole - nuclei */
		for (size_t k = 0; k < fr_j->n_atoms; k++) {
			struct efp_atom *at_j = fr_j->atoms + k;

			vec_t dr = {
				at_j->x - pt_i->x - swf.cell.x,
				at_j->y - pt_i->y - swf.cell.y,
				at_j->z - pt_i->z - swf.cell.z
			};

			double p1 = 1.0, p2 = 0.0;

			if (efp->opts.pol_damp == EFP_POL_DAMP_TT) {
				double r = vec_len(&dr);

				p1 = efp_get_pol_damp_tt(r, fr_i->pol_damp,
						fr_j->pol_damp);
				p2 = efp_get_pol_damp_tt_grad(r, fr_i->pol_damp,
						fr_j->pol_damp);
			}

			vec_t force, add_i, add_j;

			double e = -efp_charge_dipole_energy(at_j->znuc, &dipole_i, &dr);

			efp_charge_dipole_grad(at_j->znuc, &dipole_i, &dr,
					       &force, &add_j, &add_i);
			vec_negate(&force);

			vec_scale(&force, p1);
			vec_scale(&add_i, p1);
			vec_scale(&add_j, p1);

			force.x += p2 * e * dr.x;
			force.y += p2 * e * dr.y;
			force.z += p2 * e * dr.z;

			vec_scale(&force, swf.swf);
			vec_scale(&add_i, swf.swf);
			vec_scale(&add_j, swf.swf);

			efp_add_force(efp->grad + frag_idx, CVEC(fr_i->x),
					CVEC(pt_i->x), &force, &add_i);
			efp_sub_force(efp->grad + j, CVEC(fr_j->x),
					CVEC(at_j->x), &force, &add_j);
			efp_add_stress(&swf.dr, &force, &efp->stress);

			energy += p1 * e;
		}

		/* induced dipole - multipoles */
		for (size_t k = 0; k < fr_j->n_multipole_pts; k++) {
			struct multipole_pt *pt_j = fr_j->multipole_pts + k;

			vec_t dr = {
				pt_j->x - pt_i->x - swf.cell.x,
				pt_j->y - pt_i->y - swf.cell.y,
				pt_j->z - pt_i->z - swf.cell.z
			};

			double p1 = 1.0, p2 = 0.0;

			if (efp->opts.pol_damp == EFP_POL_DAMP_TT) {
				double r = vec_len(&dr);

				p1 = efp_get_pol_damp_tt(r, fr_i->pol_damp,
						fr_j->pol_damp);
				p2 = efp_get_pol_damp_tt_grad(r, fr_i->pol_damp,
						fr_j->pol_damp);
			}

			double e = 0.0;

			vec_t force_, add_i_, add_j_;
			vec_t force = vec_zero, add_i = vec_zero, add_j = vec_zero;

			/* induced dipole - charge */
			e -= efp_charge_dipole_energy(pt_j->monopole, &dipole_i, &dr);

			efp_charge_dipole_grad(pt_j->monopole, &dipole_i, &dr,
					       &force_, &add_j_, &add_i_);
			vec_negate(&force_);
			add_3(&force, &force_, &add_i, &add_i_, &add_j, &add_j_);

			/* induced dipole - dipole */
			e += efp_dipole_dipole_energy(&dipole_i, &pt_j->dipole, &dr);

			efp_dipole_dipole_grad(&dipole_i, &pt_j->dipole, &dr,
					       &force_, &add_i_, &add_j_);
			vec_negate(&add_j_);
			add_3(&force, &force_, &add_i, &add_i_, &add_j, &add_j_);

			/* induced dipole - quadrupole */
			e += efp_dipole_quadrupole_energy(&dipole_i, pt_j->quadrupole, &dr);

			efp_dipole_quadrupole_grad(&dipole_i, pt_j->quadrupole, &dr,
						   &force_, &add_i_, &add_j_);
			add_3(&force, &force_, &add_i, &add_i_, &add_j, &add_j_);

			/* induced dipole - octupole interactions are ignored */

			vec_scale(&force, p1);
			vec_scale(&add_i, p1);
			vec_scale(&add_j, p1);

			force.x += p2 * e * dr.x;
			force.y += p2 * e * dr.y;
			force.z += p2 * e * dr.z;

			vec_scale(&force, swf.swf);
			vec_scale(&add_i, swf.swf);
			vec_scale(&add_j, swf.swf);

			efp_add_force(efp->grad + frag_idx, CVEC(fr_i->x),
					CVEC(pt_i->x), &force, &add_i);
			efp_sub_force(efp->grad + j, CVEC(fr_j->x),
					CVEC(pt_j->x), &force, &add_j);
			efp_add_stress(&swf.dr, &force, &efp->stress);

			energy += p1 * e;
		}

		/* induced dipole - induced dipoles */
		for (size_t jj = 0; jj < fr_j->n_polarizable_pts; jj++) {
			struct polarizable_pt *pt_j = fr_j->polarizable_pts + jj;
			size_t idx_j = fr_j->polarizable_offset + jj;

			vec_t dr = {
				pt_j->x - pt_i->x - swf.cell.x,
				pt_j->y - pt_i->y - swf.cell.y,
				pt_j->z - pt_i->z - swf.cell.z
			};

			vec_t half_dipole_i = {
				0.5 * efp->indip[idx_i].x,
				0.5 * efp->indip[idx_i].y,
				0.5 * efp->indip[idx_i].z
			};

			double p1 = 1.0, p2 = 0.0;

			if (efp->opts.pol_damp == EFP_POL_DAMP_TT) {
				double r = vec_len(&dr);

				p1 = efp_get_pol_damp_tt(r, fr_i->pol_damp,
						fr_j->pol_damp);
				p2 = efp_get_pol_damp_tt_grad(r, fr_i->pol_damp,
						fr_j->pol_damp);
			}

			vec_t force, add_i, add_j;

			double e = efp_dipole_dipole_energy(&half_dipole_i,
						&efp->indipconj[idx_j], &dr);

			efp_dipole_dipole_grad(&half_dipole_i, &efp->indipconj[idx_j],
						&dr, &force, &add_i, &add_j);
			vec_negate(&add_j);

			vec_scale(&force, p1);
			vec_scale(&add_i, p1);
			vec_scale(&add_j, p1);

			force.x += p2 * e * dr.x;
			force.y += p2 * e * dr.y;
			force.z += p2 * e * dr.z;

			vec_scale(&force, swf.swf);
			vec_scale(&add_i, swf.swf);
			vec_scale(&add_j, swf.swf);

			efp_add_force(efp->grad + frag_idx, CVEC(fr_i->x),
					CVEC(pt_i->x), &force, &add_i);
			efp_sub_force(efp->grad + j, CVEC(fr_j->x),
					CVEC(pt_j->x), &force, &add_j);
			efp_add_stress(&swf.dr, &force, &efp->stress);

			energy += p1 * e;
		}

		vec_t force = {
			swf.dswf.x * energy,
			swf.dswf.y * energy,
			swf.dswf.z * energy
		};

		six_atomic_add_xyz(efp->grad + frag_idx, &force);
		six_atomic_sub_xyz(efp->grad + j, &force);
		efp_add_stress(&swf.dr, &force, &efp->stress);
	}

	/* induced dipole - ab initio nuclei */
	if (efp->opts.terms & EFP_TERM_AI_POL) {
		for (size_t j = 0; j < efp->n_ptc; j++) {
			vec_t dr = vec_sub(efp->ptc_xyz + j, CVEC(pt_i->x));
			vec_t force, add_i, add_j;

			efp_charge_dipole_grad(efp->ptc[j], &dipole_i, &dr,
					       &force, &add_j, &add_i);
			vec_negate(&add_i);

			vec_atomic_add(efp->ptc_grad + j, &force);
			efp_sub_force(efp->grad + frag_idx, CVEC(fr_i->x),
					CVEC(pt_i->x), &force, &add_i);
		}
	}
}
Exemple #6
0
int measure_pbc_neighbors(MoleculeList *mlist, AtomSel *sel, int molid,
			  int frame, const Matrix4 *alignment,
			  const float *center, const float *cutoff, const float *box,
			  ResizeArray<float> *extcoord_array,
			  ResizeArray<int> *indexmap_array) {
  int orig_ts, max_ts;
  if (!box && !cutoff[0] && !cutoff[1] && !cutoff[2]) return MEASURE_NOERR;

  Molecule *mol = mlist->mol_from_id(molid);
  if( !mol )
    return MEASURE_ERR_NOMOLECULE;
 
  // get current frame number and make sure there are frames
  if((orig_ts = mol->frame()) < 0)
    return MEASURE_ERR_NOFRAMES;
  
  // get the max frame number and determine current frame
  max_ts = mol->numframes()-1;
  if (frame==-2)  frame = orig_ts;
  else if (frame>max_ts || frame==-1) frame = max_ts;

  Timestep *ts = mol->get_frame(frame);
  if (!ts) return MEASURE_ERR_NOMOLECULE;

  // Get the displacement vectors (in form of translation matrices)
  Matrix4 Tpbc[3][2];
  ts->get_transforms(Tpbc[0][1], Tpbc[1][1], Tpbc[2][1]);

  // Assign the negative cell translation vectors
  Tpbc[0][0] = Tpbc[0][1];
  Tpbc[1][0] = Tpbc[1][1];
  Tpbc[2][0] = Tpbc[2][1];
  Tpbc[0][0].inverse();
  Tpbc[1][0].inverse();
  Tpbc[2][0].inverse();

  // Construct the cell spanning vectors
  float cell[9];
  cell[0] = Tpbc[0][1].mat[12];
  cell[1] = Tpbc[0][1].mat[13];
  cell[2] = Tpbc[0][1].mat[14];
  cell[3] = Tpbc[1][1].mat[12];
  cell[4] = Tpbc[1][1].mat[13];
  cell[5] = Tpbc[1][1].mat[14];
  cell[6] = Tpbc[2][1].mat[12];
  cell[7] = Tpbc[2][1].mat[13];
  cell[8] = Tpbc[2][1].mat[14];

  float len[3];
  len[0] = sqrtf(dot_prod(&cell[0], &cell[0]));
  len[1] = sqrtf(dot_prod(&cell[3], &cell[3]));
  len[2] = sqrtf(dot_prod(&cell[6], &cell[6]));
  //printf("len={%.3f %.3f %.3f}\n", len[0], len[1], len[2]);

  int i;
  float minlen = len[0];
  if (len[1] && len[1]<minlen) minlen = len[1];
  if (len[2] && len[2]<minlen) minlen = len[2];
  minlen--;

  // The algorithm works only for atoms in adjacent neighbor cells.
  if (!box && (cutoff[0]>=len[0] || cutoff[1]>=len[1] || cutoff[2]>=len[2])) {
    return MEASURE_ERR_BADCUTOFF;
  }

  bool bigrim = 1;
  float corecell[9];
  float diag[3];
  float origin[3];
  memset(origin, 0, 3*sizeof(float));
  Matrix4 M_norm;

  if (box) {
    // Get the matrix M_norm that transforms all atoms inside the 
    // unit cell into the normalized unitcell spanned by 
    // {1/len[0] 0 0} {0 1/len[1] 0} {0 0 1/len[2]}.
    bigrim = 1;

    float vtmp[3];
    vec_add(vtmp, &cell[0], &cell[3]);
    vec_add(diag, &cell[6], vtmp);
    //printf("diag={%.3f %.3f %.3f}\n", diag[0], diag[1], diag[2]);

    // Finally we need to apply the translation of the cell origin
    vec_copy(origin, center);
    vec_scaled_add(origin, -0.5, &cell[0]);
    vec_scaled_add(origin, -0.5, &cell[3]);
    vec_scaled_add(origin, -0.5, &cell[6]);
    vec_negate(origin, origin);
    //printf("origin={%.3f %.3f %.3f}\n", origin[0], origin[1], origin[2]);

  } else if (2.0f*cutoff[0]<minlen && 2.0f*cutoff[1]<minlen && 2.0f*cutoff[2]<minlen) {
    // The cutoff must not be larger than half of the smallest cell dimension
    // otherwise we would have to use a less efficient algorithm.

    // Get the matrix M_norm that transforms all atoms inside the 
    // corecell into the orthonormal unitcell spanned by {1 0 0} {0 1 0} {0 0 1}.
    // The corecell ist the pbc cell minus cutoffs for each dimension.
    vec_scale(&corecell[0], (len[0]-cutoff[0])/len[0], &cell[0]);
    vec_scale(&corecell[3], (len[1]-cutoff[1])/len[1], &cell[3]);
    vec_scale(&corecell[6], (len[2]-cutoff[2])/len[2], &cell[6]);
    get_transform_to_orthonormal_cell(corecell, center, M_norm);
    //printf("Using algorithm for small PBC environment.\n");

  } else {
    // Get the matrix M_norm that transforms all atoms inside the 
    // unit cell into the orthonormal unitcell spanned by {1 0 0} {0 1 0} {0 0 1}.
    get_transform_to_orthonormal_cell(cell, center, M_norm);

    bigrim = 1;
    //printf("Using algorithm for large PBC environment.\n");
  }

  // In case the molecule was aligned our pbc cell is rotated and shifted.
  // In order to transform a point P into the orthonormal cell (P') it 
  // first has to be unaligned (the inverse of the alignment):
  // P' = M_norm * (alignment^-1) * P
  Matrix4 alignmentinv(*alignment);
  alignmentinv.inverse();
  Matrix4 M_coretransform(M_norm);
  M_coretransform.multmatrix(alignmentinv);

  //printf("alignment = \n");
  //print_Matrix4(alignment);

  // Similarly if we want to transform a point P into its image P' we
  // first have to unalign it, then apply the PBC translation and 
  // finally realign:
  // P' = alignment * Tpbc * (alignment^-1) * P
  //      `-------------v--------------'
  //                transform
  int j, u;
  Matrix4 Tpbc_aligned[3][2];
  if (!box) {
    for (i=0; i<3; i++) {
      for (j=0; j<2; j++) {
        Tpbc_aligned[i][j].loadmatrix(*alignment);
        Tpbc_aligned[i][j].multmatrix(Tpbc[i][j]);
        Tpbc_aligned[i][j].multmatrix(alignmentinv);
      }
    }
  }

  Matrix4 M[3];
  float *coords = ts->pos;
  float *coor;
  float orthcoor[3], wrapcoor[3];

  //printf("cutoff={%.3f %.3f %.3f}\n", cutoff[0], cutoff[1], cutoff[2]);

  if (box) {
    float min_coord[3], max_coord[3];
    // Increase box by cutoff
    vec_sub(min_coord, box,   cutoff);
    vec_add(max_coord, box+3, cutoff);
    //printf("Wrapping atoms into rectangular bounding box.\n");
    //printf("min_coord={%.3f %.3f %.3f}\n", min_coord[0], min_coord[1], min_coord[2]);
    //printf("max_coord={%.3f %.3f %.3f}\n", max_coord[0], max_coord[1], max_coord[2]);
    vec_add(min_coord, min_coord, origin);
    vec_add(max_coord, max_coord, origin);

    float testcoor[9];
    int idx, k;
    // Loop over all atoms
    for (idx=0; idx<ts->num; idx++) { 
      coor = coords+3*idx;

      // Apply the inverse alignment transformation
      // to the current test point.
      M_coretransform.multpoint3d(coor, orthcoor);

      // Loop over all 26 neighbor cells
      // x
      for (i=-1; i<=1; i++) {
        // Choose the direction of translation
        if      (i>0) M[0].loadmatrix(Tpbc[0][1]);
        else if (i<0) M[0].loadmatrix(Tpbc[0][0]);
        else 	      M[0].identity();
        // Translate the unaligned atom
        M[0].multpoint3d(orthcoor, testcoor);

        // y
        for (j=-1; j<=1; j++) {
          // Choose the direction of translation
          if      (j>0) M[1].loadmatrix(Tpbc[1][1]);
          else if (j<0) M[1].loadmatrix(Tpbc[1][0]);
          else 	        M[1].identity();
          // Translate the unaligned atom
          M[1].multpoint3d(testcoor, testcoor+3);

          // z
          for (k=-1; k<=1; k++) {
            if(i==0 && j==0 && k==0) continue;

            // Choose the direction of translation
            if      (k>0) M[2].loadmatrix(Tpbc[2][1]);
            else if (k<0) M[2].loadmatrix(Tpbc[2][0]);
            else    	  M[2].identity();
            // Translate the unaligned atom
            M[2].multpoint3d(testcoor+3, testcoor+6);

            // Realign atom
            alignment->multpoint3d(testcoor+6, wrapcoor);

            vec_add(testcoor+6, wrapcoor, origin);
            if (testcoor[6]<min_coord[0] || testcoor[6]>max_coord[0]) continue;
            if (testcoor[7]<min_coord[1] || testcoor[7]>max_coord[1]) continue;
            if (testcoor[8]<min_coord[2] || testcoor[8]>max_coord[2]) continue;

            // Atom is inside cutoff, add it to the list	    
            for (int n=0; n<3; n++) extcoord_array->append(wrapcoor[n]);
            indexmap_array->append(idx);
          }
        }
      }
    }

  } else if (bigrim) {
    // This is the more general but slower algorithm.
    // We loop over all atoms, move each atom to all 26 neighbor cells
    // and check if it lies inside cutoff
    float min_coord[3], max_coord[3];
    min_coord[0] = -cutoff[0]/len[0];
    min_coord[1] = -cutoff[1]/len[1];
    min_coord[2] = -cutoff[2]/len[2];
    max_coord[0] = 1.0f + cutoff[0]/len[0];
    max_coord[1] = 1.0f + cutoff[1]/len[1];
    max_coord[2] = 1.0f + cutoff[2]/len[2];

    float testcoor[3];
    int idx, k;
    // Loop over all atoms
    for (idx=0; idx<ts->num; idx++) { 
      coor = coords+3*idx;

      // Apply the PBC --> orthonormal unitcell transformation
      // to the current test point.
      M_coretransform.multpoint3d(coor, orthcoor);

      // Loop over all 26 neighbor cells
      // x
      for (i=-1; i<=1; i++) {
        testcoor[0] = orthcoor[0]+(float)(i);
        if (testcoor[0]<min_coord[0] || testcoor[0]>max_coord[0]) continue;

        // Choose the direction of translation
        if      (i>0) M[0].loadmatrix(Tpbc_aligned[0][1]);
        else if (i<0) M[0].loadmatrix(Tpbc_aligned[0][0]);
        else          M[0].identity();

        // y
        for (j=-1; j<=1; j++) {
          testcoor[1] = orthcoor[1]+(float)(j);
          if (testcoor[1]<min_coord[1] || testcoor[1]>max_coord[1]) continue;

          // Choose the direction of translation
          if      (j>0) M[1].loadmatrix(Tpbc_aligned[1][1]);
          else if (j<0) M[1].loadmatrix(Tpbc_aligned[1][0]);
          else          M[1].identity();

          // z
          for (k=-1; k<=1; k++) {
            testcoor[2] = orthcoor[2]+(float)(k);
            if (testcoor[2]<min_coord[2] || testcoor[2]>max_coord[2]) continue;

            if(i==0 && j==0 && k==0) continue;

            // Choose the direction of translation
            if      (k>0) M[2].loadmatrix(Tpbc_aligned[2][1]);
            else if (k<0) M[2].loadmatrix(Tpbc_aligned[2][0]);
            else          M[2].identity();

            M[0].multpoint3d(coor, wrapcoor);
            M[1].multpoint3d(wrapcoor, wrapcoor);
            M[2].multpoint3d(wrapcoor, wrapcoor);

            // Atom is inside cutoff, add it to the list            
            for (int n=0; n<3; n++) extcoord_array->append(wrapcoor[n]);
            indexmap_array->append(idx);
          }
        }
      }
    }
  
  } else {
    Matrix4 Mtmp;

    for (i=0; i < ts->num; i++) { 
      // Apply the PBC --> orthonormal unitcell transformation
      // to the current test point.
      M_coretransform.multpoint3d(coords+3*i, orthcoor);

      // Determine in which cell we are.
      int cellindex[3];    
      if      (orthcoor[0]<0) cellindex[0] = -1;
      else if (orthcoor[0]>1) cellindex[0] =  1;
      else                    cellindex[0] =  0;
      if      (orthcoor[1]<0) cellindex[1] = -1;
      else if (orthcoor[1]>1) cellindex[1] =  1;
      else                    cellindex[1] =  0;
      if      (orthcoor[2]<0) cellindex[2] = -1;
      else if (orthcoor[2]>1) cellindex[2] =  1;
      else                    cellindex[2] =  0;

      // All zero means we're inside the core --> no image.
      if (!cellindex[0] && !cellindex[1] && !cellindex[2]) continue;

      // Choose the direction of translation
      if      (orthcoor[0]<0) M[0].loadmatrix(Tpbc_aligned[0][1]);
      else if (orthcoor[0]>1) M[0].loadmatrix(Tpbc_aligned[0][0]);
      if      (orthcoor[1]<0) M[1].loadmatrix(Tpbc_aligned[1][1]);
      else if (orthcoor[1]>1) M[1].loadmatrix(Tpbc_aligned[1][0]);
      if      (orthcoor[2]<0) M[2].loadmatrix(Tpbc_aligned[2][1]);
      else if (orthcoor[2]>1) M[2].loadmatrix(Tpbc_aligned[2][0]);

      // Create wrapped copies of the atom:
      // x, y, z planes
      coor = coords+3*i;
      for (u=0; u<3; u++) {
        if (cellindex[u] && cutoff[u]) {
          M[u].multpoint3d(coor, wrapcoor);
          for (j=0; j<3; j++) extcoord_array->append(wrapcoor[j]);
          indexmap_array->append(i);
        }
      }

      Mtmp = M[0];

      // xy edge
      if (cellindex[0] && cellindex[1] && cutoff[0] && cutoff[1]) {
        M[0].multmatrix(M[1]);
        M[0].multpoint3d(coor, wrapcoor);
        for (j=0; j<3; j++) extcoord_array->append(wrapcoor[j]);
        indexmap_array->append(i);
      }

      // yz edge
      if (cellindex[1] && cellindex[2] && cutoff[1] && cutoff[2]) {
        M[1].multmatrix(M[2]);
        M[1].multpoint3d(coor, wrapcoor);
        for (j=0; j<3; j++) extcoord_array->append(wrapcoor[j]);
        indexmap_array->append(i);
      }

      // zx edge
      if (cellindex[0] && cellindex[2] && cutoff[0] && cutoff[2]) {
        M[2].multmatrix(Mtmp);
        M[2].multpoint3d(coor, wrapcoor);
        for (j=0; j<3; j++) extcoord_array->append(wrapcoor[j]);
        indexmap_array->append(i);
      }

      // xyz corner
      if (cellindex[0] && cellindex[1] && cellindex[2]) {
        M[1].multmatrix(Mtmp);
        M[1].multpoint3d(coor, wrapcoor);
        for (j=0; j<3; j++) extcoord_array->append(wrapcoor[j]);
        indexmap_array->append(i);
      }

    }

  } // endif

  // If a selection was provided we select extcoords
  // within cutoff of the original selection:
  if (sel) {
    int numext = sel->selected+indexmap_array->num();
    float *extcoords = new float[3*numext];
    int   *indexmap  = new int[numext];
    int   *others    = new int[numext];
    memset(others, 0, numext);

    // Use the largest given cutoff
    float maxcutoff = cutoff[0];
    for (i=1; i<3; i++) {
      if (cutoff[i]>maxcutoff) maxcutoff = cutoff[i];
    }

    // Prepare C-array of coordinates for find_within()
    j=0;
    for (i=0; i < sel->num_atoms; i++) { 
      if (!sel->on[i]) continue; //atom is not selected
      extcoords[3*j]   = coords[3*i];
      extcoords[3*j+1] = coords[3*i+1];
      extcoords[3*j+2] = coords[3*i+2];
      indexmap[j] = i;
      others[j++] = 1;
    }
    for (i=0; i<indexmap_array->num(); i++) {
      extcoords[3*j]   = (*extcoord_array)[3*i];
      extcoords[3*j+1] = (*extcoord_array)[3*i+1];
      extcoords[3*j+2] = (*extcoord_array)[3*i+2];
      indexmap[j] = (*indexmap_array)[i];
      others[j++] = 0;
    }

    // Initialize flags array to true, find_within() results are AND'd/OR'd in.
    int *flgs   = new int[numext];
    for (i=0; i<numext; i++) {
      flgs[i] = 1;
    }

    // Find coordinates from extcoords that are within cutoff of the ones
    // with flagged in 'others' and set the flgs accordingly:
    find_within(extcoords, flgs, others, numext, maxcutoff);

    extcoord_array->clear();
    indexmap_array->clear();
    for (i=sel->selected; i<numext; i++) {
      if (!flgs[i]) continue;

      extcoord_array->append(extcoords[3*i]);
      extcoord_array->append(extcoords[3*i+1]);
      extcoord_array->append(extcoords[3*i+2]);
      indexmap_array->append(indexmap[i]);
    }

  }

  return MEASURE_NOERR;
}  
Exemple #7
0
void POV3DisplayDevice::start_clipgroup(void) {
  int i, num_clipplanes[3], mode;
  float pov_clip_center[3], pov_clip_distance[VMD_MAX_CLIP_PLANE];
  float pov_clip_normal[VMD_MAX_CLIP_PLANE][3];

  write_materials();

  memset(num_clipplanes, 0, 3*sizeof(int));
  for (i = 0; i < VMD_MAX_CLIP_PLANE; i++) {
    if (clip_mode[i] != 0) {
      // Count the number of clipping planes for each clip mode
      num_clipplanes[clip_mode[i]]++;

      // Translate the plane center
      (transMat.top()).multpoint3d(clip_center[i], pov_clip_center);

      // and the normal
      (transMat.top()).multnorm3d(clip_normal[i], pov_clip_normal[i]);
      vec_negate(pov_clip_normal[i], pov_clip_normal[i]);

      // POV-Ray uses the distance from the origin to the plane for its
      // representation, instead of the plane center
      pov_clip_distance[i] = dot_prod(pov_clip_normal[i], pov_clip_center);
    }
  }

  // Define the clip object for each clip mode
  for (mode = 1; mode < 3; mode++) {
    if (num_clipplanes[mode] > 0) {
      // This flag is used within VMD to determine if clipping information
      // should be written to the scene file
      clip_on[mode] = 1;

      // This flag is used within POV to determine if clipping should be done
      // within macros
      fprintf(outfile, "#declare VMD_clip_on[%d]=1;\n", mode);

      if (num_clipplanes[mode] == 1) {
        for (i = 0; i < VMD_MAX_CLIP_PLANE; i++) {
          if (clip_mode[i] == mode) {
            if (mode == 2) {
              // Textured plane for CSG clipping
              fprintf(outfile, "#declare VMD_clip[%d] = plane { <%.4f, %.4f, %.4f>, %.4f texture { pigment { rgbt<%.3f, %.3f, %.3f, %.3f> } } }\n",
                      mode, pov_clip_normal[i][0], pov_clip_normal[i][1], 
                      -pov_clip_normal[i][2], pov_clip_distance[i],
                      clip_color[i][0], clip_color[i][1], clip_color[i][2],
                      1 - mat_opacity);
            } else {
              // Non-textured plane for non-CSG clipping
              fprintf(outfile, "#declare VMD_clip[%d] = plane { <%.4f, %.4f, %.4f>, %.4f }\n",
                      mode, pov_clip_normal[i][0], pov_clip_normal[i][1], 
                      -pov_clip_normal[i][2], pov_clip_distance[i]);

#if defined(POVRAY_BRAIN_DAMAGE_WORKAROUND)
              // Non-textured plane for non-CSG clipping, but scaled for use
              // when emitting meshes with the scaling hack.
              fprintf(outfile, "#declare VMD_scaledclip[%d] = plane { <%.4f, %.4f, %.4f>, %.4f }\n",
                      mode, pov_clip_normal[i][0], pov_clip_normal[i][1], -pov_clip_normal[i][2], 
                      pov_clip_distance[i] * POVRAY_SCALEHACK);
#endif
            }
          }
        }
      }

      // Declare the clipping object to be an intersection of planes
      else {
        fprintf(outfile, "#declare VMD_clip[%d] = intersection {\n", mode);
        for (i = 0; i < VMD_MAX_CLIP_PLANE; i++) {
          if (clip_mode[i] == mode) {
            if (mode == 2) {
              // Textured plane for CSG clipping
              fprintf(outfile, "  plane { <%.4f, %.4f, %.4f>, %.4f texture { pigment { rgbt<%.3f, %.3f, %.3f, %.3f> } } }\n",
                      pov_clip_normal[i][0], pov_clip_normal[i][1], 
                      -pov_clip_normal[i][2], pov_clip_distance[i],
                      clip_color[i][0], clip_color[i][1], clip_color[i][2],
                      1 - mat_opacity);
            } else {
              // Non-textured plane for non-CSG clipping
              fprintf(outfile, "  plane { <%.4f, %.4f, %.4f>, %.4f }\n",
                    pov_clip_normal[i][0], pov_clip_normal[i][1], 
                    -pov_clip_normal[i][2], pov_clip_distance[i]);
            }
          }
        }
        fprintf(outfile, "}\n");

#if defined(POVRAY_BRAIN_DAMAGE_WORKAROUND)
        fprintf(outfile, "#declare VMD_scaledclip[%d] = intersection {\n", mode);
        for (i = 0; i < VMD_MAX_CLIP_PLANE; i++) {
          if (clip_mode[i] == mode) {
            if (mode == 2) {
              // Textured plane for CSG clipping
              fprintf(outfile, "  plane { <%.4f, %.4f, %.4f>, %.4f texture { pigment { rgbt<%.3f, %.3f, %.3f, %.3f> } } }\n",
                      pov_clip_normal[i][0], pov_clip_normal[i][1], 
                      -pov_clip_normal[i][2], pov_clip_distance[i] * POVRAY_SCALEHACK,
                      clip_color[i][0], clip_color[i][1], clip_color[i][2],
                      1 - mat_opacity);
            } else {
              // Non-textured plane for non-CSG clipping
              fprintf(outfile, "  plane { <%.4f, %.4f, %.4f>, %.4f }\n",
                    pov_clip_normal[i][0], pov_clip_normal[i][1], 
                    -pov_clip_normal[i][2], pov_clip_distance[i] * POVRAY_SCALEHACK);
            }
          }
        }
        fprintf(outfile, "}\n");
#endif


      }

    }
  }
}