Example #1
0
int tclcommand_inter_coulomb_parse_ewald(Tcl_Interp * interp, int argc, char ** argv)
{
  double r_cut, alpha;
  int i, kmax;

  coulomb.method = COULOMB_EWALD;
    
#ifdef PARTIAL_PERIODIC
  if(PERIODIC(0) == 0 ||
     PERIODIC(1) == 0 ||
     PERIODIC(2) == 0)
    {
      Tcl_AppendResult(interp, "Need periodicity (1,1,1) with Coulomb EWALD",
		       (char *) NULL);
      return TCL_ERROR;  
    }
#endif

  if (argc < 2) {
    Tcl_AppendResult(interp, "expected: inter coulomb <bjerrum> ewald <r_cut> <alpha> <kmax>",
		     (char *) NULL);
    return TCL_ERROR;  
  }

  if(! ARG0_IS_D(r_cut))
    return TCL_ERROR;  

  if(argc != 3) {
    Tcl_AppendResult(interp, "wrong # arguments: inter coulomb <bjerrum> ewald <r_cut> <alpha> <kmax>",
		     (char *) NULL);
    return TCL_ERROR;  
  }

  if(! ARG_IS_D(1, alpha))
    return TCL_ERROR;

  if(! ARG_IS_I(2, kmax))
    return TCL_ERROR;

  if ((i = ewald_set_params(r_cut, alpha, kmax)) < 0) {
    switch (i) {
    case -1:
      Tcl_AppendResult(interp, "r_cut must be positive", (char *) NULL);
      break;
    case -4:
      Tcl_AppendResult(interp, "alpha must be positive", (char *) NULL);
      break;
    case -5:
      Tcl_AppendResult(interp, "kmax must be greater than zero", (char *) NULL);
    default:;
      Tcl_AppendResult(interp, "unspecified error", (char *) NULL);
    }

    return TCL_ERROR;

  }

  return TCL_OK;
}
void Mmm1dgpuForce::check_periodicity()
{
	if (PERIODIC(0) || PERIODIC(1) || !PERIODIC(2))
	{
		std::cerr << "MMM1D requires periodicity (0,0,1)" << std::endl;
		exit(EXIT_FAILURE);
	}
}
Example #3
0
int mdlc_sanity_checks()
{
#ifdef PARTIAL_PERIODIC  
  char *errtxt;
  if (!PERIODIC(0) || !PERIODIC(1) || !PERIODIC(2)) {
    errtxt = runtime_error(128);
    ERROR_SPRINTF(errtxt, "{006 mdlc requires periodicity 1 1 1} ");
    return 1;
  }
#endif  
  return 0;
}
Example #4
0
int mdlc_sanity_checks()
{
  if (!PERIODIC(0) || !PERIODIC(1) || !PERIODIC(2)) {
      ostringstream msg;
      msg <<"mdlc requires periodicity 1 1 1";
      runtimeError(msg);
    return 1;
  }

  // It will be desirable to have a  checking function that check that the slab geometry is such that 
  // the short direction is along the z component.

  return 0;
}
Example #5
0
int MMM1D_sanity_checks()
{
  char *errtxt;
  if (PERIODIC(0) || PERIODIC(1) || !PERIODIC(2)) {
    errtxt = runtime_error(128);
    ERROR_SPRINTF(errtxt, "{022 MMM1D requires periodicity 0 0 1} ");
    return 1;
  }

  if (cell_structure.type != CELL_STRUCTURE_NSQUARE) {
    errtxt = runtime_error(128);
    ERROR_SPRINTF(errtxt, "{023 MMM1D requires n-square cellsystem} ");
    return 1;
  }
  return 0;
}
// Update the pos of the given virtual particle as defined by the real 
// particles in the same molecule
void update_mol_pos_particle(Particle *p)
{
 // First obtain the real particle responsible for this virtual particle:
 // Find the 1st real particle in the topology for the virtual particle's mol_id
 Particle *p_real = vs_relative_get_real_particle(p);
 // Check, if a real particle was found
 if (!p_real)
 {
   char *errtxt = runtime_error(128 + 3*ES_INTEGER_SPACE);
   ERROR_SPRINTF(errtxt,"virtual_sites_relative.cpp - update_mol_pos_particle(): No real particle associated with virtual site.\n");
   return;
 }
 
 // Calculate the quaternion defining the orientation of the vecotr connectinhg
 // the virtual site and the real particle
 // This is obtained, by multiplying the quaternion representing the director
 // of the real particle with the quaternion of the virtual particle, which 
 // specifies the relative orientation.
 double q[4];
 multiply_quaternions(p_real->r.quat,p->r.quat,q);
 // Calculate the director resulting from the quaternions
 double director[3];
 convert_quat_to_quatu(q,director);
 // normalize
 double l =sqrt(sqrlen(director));
 // Division comes in the loop below
 
 // Calculate the new position of the virtual sites from
 // position of real particle + director 
 int i;
 double new_pos[3];
 double tmp;
 for (i=0;i<3;i++)
 {
  new_pos[i] =p_real->r.p[i] +director[i]/l*p->p.vs_relative_distance;
  // Handle the case that one of the particles had gone over the periodic
  // boundary and its coordinate has been folded
  #ifdef PARTIAL_PERIODIC
   if (PERIODIC(i)) 
  #endif
  {
    tmp =p->r.p[i] -new_pos[i];
    //printf("%f\n",tmp);
    if (tmp > box_l[i]/2.) {
     //printf("greater than box_l/2 %f\n",tmp);
     p->r.p[i] =new_pos[i] + box_l[i];
    }
    else if (tmp < -box_l[i]/2.) {
     //printf("smaller than box_l/2 %f\n",tmp);
     p->r.p[i] =new_pos[i] - box_l[i];
    }
    else p->r.p[i] =new_pos[i];
   }
   #ifdef PARTIAL_PERIODIC
    else p->r.p[i] =new_pos[i];
   #endif
//   fold_coordinate(p->r.p,p->l.i,i);

 }
}
Example #7
0
int mdlc_sanity_checks()
{
#ifdef PARTIAL_PERIODIC  
  char *errtxt;
  if (!PERIODIC(0) || !PERIODIC(1) || !PERIODIC(2)) {
    errtxt = runtime_error(128);
    ERROR_SPRINTF(errtxt, "{006 mdlc requires periodicity 1 1 1} ");
    return 1;
  }
#endif  

  // It will be desirable to have a  checking function that check that the slab geometry is such that 
  // the short direction is along the z component.

  return 0;
}
Example #8
0
static void putInteractingInPrevList(int atom,struct parameters *par,struct systemPos *pos,struct bondList *blist,  int *posInPrevList){
  int j,bondListPosj,ngbrListPosj;
  double drx_ij,dry_ij,drz_ij;
  double rij2;
  double r02;
  
  /* r02 is the distance at which ngbr atoms are included, shoud this include skin ? probably not! */
  /*  r02=POW2(sqrt(wwwPar.repR02)+par->skin); */
  r02=wwwPar.repR02;
  
  
  /* then the atoms it is bonded to */
  bondListPosj=blist->head[atom]; /*where the bonds start*/
  while(blist->list[bondListPosj]!=-1) /*get bonds of i, stops when the bonds od atom i+1 comes*/
    prevInteractionList[(*posInPrevList)++]=blist->list[bondListPosj++];
  
  
  /* and last the atoms it is ngbr with */
  if(wwwPar.includeRepPot){
    ngbrListPosj=nd.head[atom]; /*where the ngbrs start*/
    while(nd.list[ngbrListPosj]!=-1){ /*get ngbrs of i, stops when the ngbrs of atom i+1 comes*/
      j=nd.list[ngbrListPosj++]; /*j is the ngbr*/
	
      drx_ij=pos->x[j]-pos->x[atom]; 
      dry_ij=pos->y[j]-pos->y[atom]; 
      drz_ij=pos->z[j]-pos->z[atom];	
      PERIODIC(drx_ij,dry_ij,drz_ij);
      rij2=LENGTH2(drx_ij,dry_ij,drz_ij);
      if( rij2 <r02 )
		  prevInteractionList[(*posInPrevList)++]=j;
	
    }
  }
  prevInteractionList[(*posInPrevList)++]=-1;
}
Example #9
0
/** update the 'shift' member of those GhostCommunicators, which use
    that value to speed up the folding process of its ghost members
    (see \ref dd_prepare_comm for the original), i.e. all which have
    GHOSTTRANS_POSSHFTD or'd into 'data_parts' upon execution of \ref
    dd_prepare_comm. */
void dd_update_communicators_w_boxl()
{
  int cnt=0;
  /* direction loop: x, y, z */
  for(int dir=0; dir<3; dir++) {
    /* lr loop: left right */
    for(int lr=0; lr<2; lr++) {
      if(node_grid[dir] == 1) {
#ifdef PARTIAL_PERIODIC
	if( PERIODIC(dir ) || (boundary[2*dir+lr] == 0) ) 
#endif
	  {
	    /* prepare folding of ghost positions */
	    if(boundary[2*dir+lr] != 0) {
	      cell_structure.exchange_ghosts_comm.comm[cnt].shift[dir] = boundary[2*dir+lr]*box_l[dir]; 
	      cell_structure.update_ghost_pos_comm.comm[cnt].shift[dir] = boundary[2*dir+lr]*box_l[dir]; 
	    }
	    cnt++;
	  }
      }
      else {
	/* i: send/recv loop */
	for(int i=0; i<2; i++) {  
#ifdef PARTIAL_PERIODIC
	  if( PERIODIC(dir) || (boundary[2*dir+lr] == 0) ) 
#endif
	    if((node_pos[dir]+i)%2==0) {
	      /* prepare folding of ghost positions */
	      if(boundary[2*dir+lr] != 0) {
		cell_structure.exchange_ghosts_comm.comm[cnt].shift[dir] = boundary[2*dir+lr]*box_l[dir];
		cell_structure.update_ghost_pos_comm.comm[cnt].shift[dir] = boundary[2*dir+lr]*box_l[dir];
	      }
	      cnt++;
	    }
#ifdef PARTIAL_PERIODIC
	  if( PERIODIC(dir) || (boundary[2*dir+(1-lr)] == 0) ) 
#endif
	    if((node_pos[dir]+(1-i))%2==0) {
	      cnt++;
	    }
	}
      }
    }
  }
}
Example #10
0
static void set_params_safe(const std::string &method, const std::string &params, bool dipolar_ia) {
  if(scafacos && (scafacos->method != method)) {
    delete scafacos;
    scafacos = 0;
  }
  
  scafacos = new Scafacos(method, comm_cart, params);

  scafacos->parse_parameters(params);
  int per[3] = { PERIODIC(0) != 0, PERIODIC(1) != 0, PERIODIC(2) != 0 };
  scafacos->set_dipolar(dipolar_ia);
  scafacos->set_common_parameters(box_l, per, n_part);

  on_coulomb_change();
  
  tune();

  on_coulomb_change();
}
  void computeEnergy(SystemInterface &s) {
    dds_float box[3];
    int per[3];
    for (int i=0;i<3;i++)
    {
     box[i]=s.box()[i];
     per[i] = (PERIODIC(i));
    }
    DipolarDirectSum_kernel_wrapper_energy(k,s.npart_gpu(),
					 s.rGpuBegin(), s.dipGpuBegin(), box,per,(&(((CUDA_energy*)s.eGpu())->dipolar)));
 };
  void computeForces(SystemInterface &s) {
    dds_float box[3];
    int per[3];
    for (int i=0;i<3;i++)
    {
     box[i]=s.box()[i];
     per[i] = (PERIODIC(i));
    }
    DipolarDirectSum_kernel_wrapper_force(k,s.npart_gpu(),
					 s.rGpuBegin(), s.dipGpuBegin(), s.fGpuBegin(),s.torqueGpuBegin(),box,per);
  };
Example #13
0
int EWALD_sanity_checks()
{
  char *errtxt;
  int ret = 0;

  if (!PERIODIC(0) || !PERIODIC(1) || !PERIODIC(2)) {
    errtxt = runtime_error(128);
    sprintf(errtxt, "{EWALD requires periodicity 1 1 1} ");
    ret = 1;
  }
  
  if( (box_l[0] != box_l[1]) || (box_l[1] != box_l[2]) ) {
    errtxt = runtime_error(128);
    sprintf(errtxt,"{EWALD at present requires a cubic box} ");
    ret = 1;
  }

  if (EWALD_sanity_checks_boxl()) ret = 1;

  return ret;
}
Example #14
0
/* new version for new topology structure */
int analyze_fold_molecules(float *coord, double shift[3])
{
  int m,p,i, tmp;
  int mol_size, ind;
  double cm_tmp, com[3];

  #ifdef LEES_EDWARDS
  if(lees_edwards_offset != 0.0 ){
    fprintf(stderr, "Error: Folding molecules not supported under Lees-Edwards.\n");
    exit(8);
  }
  #endif
  
  /* check molecule information */
  if ( n_molecules < 0 ) return ES_ERROR;

  if (!sortPartCfg()) {
      ostringstream msg;
      msg <<"analyze_fold_molecules: could not sort particle config, particle ids not consecutive?";
      runtimeError(msg);
    return ES_ERROR;
  }

  /* loop molecules */
  for(m=0; m<n_molecules; m++) {
    mol_size = topology[m].part.n;
    if(mol_size > 0) {
      /* calc center of mass */
      calc_mol_center_of_mass(topology[m],com);
      /* fold coordinates */
      for(i=0; i<3; i++) {
	if ( PERIODIC(i) ) { 
	  tmp = (int)floor((com[i]+shift[i])*box_l_i[i]);
	  cm_tmp =0.0;
	  for(p=0; p<mol_size; p++) {
	    ind        = 3*topology[m].part.e[p] + i;
	    coord[ind] -= tmp*box_l[i];
	    coord[ind] += shift[i];
	    cm_tmp     += coord[ind];
	  }
	  cm_tmp /= (double)mol_size;
      if(cm_tmp < -10e-6 || cm_tmp > box_l[i]+10e-6) {
          ostringstream msg;
          msg <<"analyze_fold_molecules: chain center of mass is out of range (coord " << i << ": " << cm_tmp << " not in box_l " << box_l[i] << ")";
          runtimeError(msg);
	    return ES_ERROR;
	  }
	}
      }
    }
  }
  return ES_OK;
}
Example #15
0
int comfixed_set_params(int part_type_a, int part_type_b, int flag)
{
    Particle *p;
    int i, j, np, c;
    Cell *cell;
    IA_parameters *data = get_ia_param_safe(part_type_a, part_type_b);

    if (!data)
        return 1;

    if (n_nodes > 1)
        return 2;

    if (PERIODIC(0) || PERIODIC(1) || PERIODIC(2)) {
        return 3;
    }

    data->COMFIXED_flag    = flag;

    /* broadcast interaction parameters */
    mpi_bcast_ia_params(part_type_a, part_type_b);

    for (c = 0; c < local_cells.n; c++) {
        cell = local_cells.cell[c];
        p  = cell->part;
        np = cell->n;
        for(i = 0; i < np; i++) {
            if(p[i].p.type==part_type_a) {
                for(j = 0; j < 3; j++) {
                    p[i].m.v[j] = 0.;
                    p[i].f.f[j] = 0.;
                }
            }
        }
    }

    return ES_OK;
}
/* new version for new topology structure */
int analyze_fold_molecules(float *coord, double shift[3])
{
  int m,p,i, tmp;
  int mol_size, ind;
  double cm_tmp, com[3];

  /* check molecule information */
  if ( n_molecules < 0 ) return (TCL_ERROR);

  if (!sortPartCfg()) {
    char *errtxt = runtime_error(128);
    ERROR_SPRINTF(errtxt, "{059 analyze_fold_molecules: could not sort particle config, particle ids not consecutive?} ");
    return TCL_ERROR;
  }

  /* loop molecules */
  for(m=0; m<n_molecules; m++) {
    mol_size = topology[m].part.n;
    if(mol_size > 0) {
      /* calc center of mass */
      calc_mol_center_of_mass(topology[m],com);
      /* fold coordinates */
      for(i=0; i<3; i++) {
	if ( PERIODIC(i) ) { 
	  tmp = (int)floor((com[i]+shift[i])*box_l_i[i]);
	  cm_tmp =0.0;
	  for(p=0; p<mol_size; p++) {
	    ind        = 3*topology[m].part.e[p] + i;
	    coord[ind] -= tmp*box_l[i];
	    coord[ind] += shift[i];
	    cm_tmp     += coord[ind];
	  }
	  cm_tmp /= (double)mol_size;
	  if(cm_tmp < -10e-6 || cm_tmp > box_l[i]+10e-6) {
	    char *errtxt = runtime_error(128 + TCL_INTEGER_SPACE + 2*TCL_DOUBLE_SPACE);
	    ERROR_SPRINTF(errtxt,"{060 analyze_fold_molecules: chain center of mass is out of range (coord %d: %.14f not in box_l %.14f)} ",
		    i,cm_tmp,box_l[i]);
	    return (TCL_ERROR);
	  }
	}
      }
    }
  }
  return (TCL_OK);
}
Example #17
0
void check_particles()
{
  Particle *part;
  int *is_here;
  Cell *cell;
  int n, np, dir, c, p;
  int cell_part_cnt=0, local_part_cnt=0;
  int cell_err_cnt=0;
  double skin2 = (skin != -1) ? skin/2 : 0;

  CELL_TRACE(fprintf(stderr, "%d: entering check_particles\n", this_node));

  /* check the consistency of particle_nodes */
  /* to this aim the array is broadcasted temporarily */
  if (this_node != 0)
    particle_node = malloc((max_seen_particle + 1)*sizeof(int));
  is_here = malloc((max_seen_particle + 1)*sizeof(int));
  memset(is_here, 0, (max_seen_particle + 1)*sizeof(int));

  MPI_Bcast(particle_node, max_seen_particle + 1, MPI_INT, 0, MPI_COMM_WORLD);

  /* checks: part_id, part_pos, local_particles id */
  for (c = 0; c < local_cells.n; c++) {
    cell = local_cells.cell[c];
    cell_part_cnt += cell->n;
    part = cell->part;
    np   = cell->n;
    for(n=0; n<cell->n ; n++) {
      if(part[n].p.identity < 0 || part[n].p.identity > max_seen_particle) {
	fprintf(stderr,"%d: check_particles: ERROR: Cell %d Part %d has corrupted id=%d\n",
		this_node,c,n,cell->part[n].p.identity);
	errexit();
      }

      is_here[part[n].p.identity] = 1;

      for(dir=0;dir<3;dir++) {
	if(PERIODIC(dir) && (part[n].r.p[dir] < -skin2 || part[n].r.p[dir] > box_l[dir] + skin2)) {
	  fprintf(stderr,"%d: check_particles: ERROR: illegal pos[%d]=%f of part %d id=%d in cell %d\n",
		  this_node,dir,part[n].r.p[dir],n,part[n].p.identity,c);
	  errexit();
	}
      }
      if(local_particles[part[n].p.identity] != &part[n]) {
	fprintf(stderr,"%d: check_particles: ERROR: address mismatch for part id %d: local: %p cell: %p in cell %d\n",
		this_node,part[n].p.identity,local_particles[part[n].p.identity],
		&part[n],c);
	errexit();
      }
      if (particle_node[part[n].p.identity] != this_node) {
	fprintf(stderr,"%d: check_particles: ERROR: node for particle %d wrong\n",
		this_node,part[n].p.identity);
	errexit();
      }
    }
  }
  CELL_TRACE(fprintf(stderr,"%d: check_particles: %d particles in local cells.\n",
		     this_node,cell_part_cnt));

  /* checks: local particle id */
  for(n = 0; n <= max_seen_particle; n++) {
    if(local_particles[n] != NULL) {
      local_part_cnt ++;
      if(local_particles[n]->p.identity != n) {
	fprintf(stderr,"%d: check_particles: ERROR: local_particles part %d has corrupted id %d\n",
		this_node,n,local_particles[n]->p.identity);
	errexit();
      }
    }
  }
  CELL_TRACE(fprintf(stderr,"%d: check_particles: %d particles in local_particles.\n",
		     this_node,local_part_cnt));

  /* EXIT on severe errors */
  if(cell_err_cnt>0) {
    fprintf(stderr,"%d: check_particles: %d ERRORS detected in cell structure!\n",this_node,cell_err_cnt);
    errexit();
  }

  /* check whether the particles on my node are actually here */
  for (p = 0; p <= max_seen_particle; p++) {
    if (particle_node[p] == this_node) {
      if (!is_here[p]) {
 	fprintf(stderr,"%d: check_particles: ERROR: particle %d on this node, but not in local cell\n", this_node, p);
      }
    }
  }

  free(is_here);

  if (this_node != 0) {
    free(particle_node);
    particle_node = NULL;
  }
  else {
    /* check whether the total count of particles is ok */
    c = 0;
    for (p = 0; p <= max_seen_particle; p++)
      if (particle_node[p] != -1) c++;
    if (c != n_total_particles) {
      fprintf(stderr,"%d: check_particles: #particles in particle_node inconsistent\n", this_node);
      errexit();
    }
    CELL_TRACE(fprintf(stderr,"%d: check_particles: %d particles in particle_node.\n",
		       this_node,c));
  }
  CELL_TRACE(fprintf(stderr, "%d: leaving check_particles\n", this_node));
}
Example #18
0
void check_particle_consistency()
{
  Particle *part;
  Cell *cell;
  int n, np, dir, c, p;
  int cell_part_cnt=0, ghost_part_cnt=0, local_part_cnt=0;
  int cell_err_cnt=0;

  /* checks: part_id, part_pos, local_particles id */
  for (c = 0; c < local_cells.n; c++) {
    cell = local_cells.cell[c];
    cell_part_cnt += cell->n;
    part = cell->part;
    np   = cell->n;
    for(n=0; n<cell->n ; n++) {
      if(part[n].p.identity < 0 || part[n].p.identity > max_seen_particle) {
	fprintf(stderr,"%d: check_particle_consistency: ERROR: Cell %d Part %d has corrupted id=%d\n",
		this_node,c,n,cell->part[n].p.identity);
	errexit();
      }
      for(dir=0;dir<3;dir++) {
	if(PERIODIC(dir) && (part[n].r.p[dir] < -ROUND_ERROR_PREC || part[n].r.p[dir] - box_l[dir] > ROUND_ERROR_PREC)) {
	  fprintf(stderr,"%d: check_particle_consistency: ERROR: illegal pos[%d]=%f of part %d id=%d in cell %d\n",
		  this_node,dir,part[n].r.p[dir],n,part[n].p.identity,c);
	  errexit();
	}
      }
      if(local_particles[part[n].p.identity] != &part[n]) {
	fprintf(stderr,"%d: check_particle_consistency: ERROR: address mismatch for part id %d: local: %p cell: %p in cell %d\n",
		this_node,part[n].p.identity,local_particles[part[n].p.identity],
		&part[n],c);
	errexit();
	
      }
    }
  }

  for (c = 0; c < ghost_cells.n; c++) {
    cell = ghost_cells.cell[c];
    if(cell->n>0) {
      ghost_part_cnt += cell->n;
      fprintf(stderr,"%d: check_particle_consistency: WARNING: ghost_cell %d contains %d particles!\n",
	      this_node,c,cell->n);
    }
  }
  CELL_TRACE(fprintf(stderr,"%d: check_particle_consistency: %d particles in cells, %d particles in ghost_cells.\n",
		     this_node,cell_part_cnt, ghost_part_cnt));
  /* checks: local particle id */
  for(n=0; n< max_seen_particle+1; n++) {
    if(local_particles[n] != NULL) {
      local_part_cnt ++;
      if(local_particles[n]->p.identity != n) {
	fprintf(stderr,"%d: check_particle_consistency: ERROR: local_particles part %d has corrupted id %d\n",
		this_node,n,local_particles[n]->p.identity);
	errexit();
      }
    }
  }
  CELL_TRACE(fprintf(stderr,"%d: check_particle_consistency: %d particles in local_particles.\n",
		     this_node,local_part_cnt));

  /* EXIT on severe errors */
  if(cell_err_cnt>0) {
    fprintf(stderr,"%d: check_particle_consistency: %d ERRORS detected in cell structure!\n",this_node,cell_err_cnt);
    errexit();
  }
  if(local_part_cnt != cell_part_cnt) {
    fprintf(stderr,"%d: check_particle_consistency: ERROR: %d parts in cells but %d parts in local_particles\n",
	    this_node,cell_part_cnt,local_part_cnt);

    for (c = 0; c < local_cells.n; c++) {
      for(p = 0; p < local_cells.cell[c]->n; p++)
	fprintf(stderr, "%d: got particle %d in cell %d\n", this_node, local_cells.cell[c]->part[p].p.identity, c);
    }
    
    for(p = 0; p < n_total_particles; p++)
      if (local_particles[p])
	fprintf(stderr, "%d: got particle %d in local_particles\n", this_node, p);

    if(ghost_part_cnt==0) errexit();
  }
  if(ghost_part_cnt>0) {
    fprintf(stderr,"%d: check_particle_consistency: ERROR: Found %d illegal ghost particles!\n",
	    this_node,ghost_part_cnt);
    errexit();
  }
}
Example #19
0
/** Calculate lj-angle force between particle p1 and p2
    Involves 6 particles total */
inline void add_ljangle_force(Particle *p1, Particle *p2, IA_parameters *ia_params,
                              double d[3], double dist)
{
    if(!CUTOFF_CHECK(dist < ia_params->LJANGLE_cut))
        return;
    int j;
    double frac2=0.0, frac10=0.0, rad=0.0, radprime=0.0;
    double r31[3], r41[3], r52[3], r62[3], rij[3], rik[3], rkn[3];
    double l_rij, l_rik, l_rkn, l_rij2, l_rik2, l_rkn2;
    double cos_jik, cos_ikn;
    double angular_jik, angular_ikn, angular_jik_prime, angular_ikn_prime;
    /* Recreate angular dependence of potential by including 6 particles instead of 2. */
    Particle *p3=NULL, *p4=NULL, *p5=NULL, *p6=NULL;
    int part1p, part1n, part2p, part2n;
    /* Optional 2nd environment */
    double effective_eps=ia_params->LJANGLE_eps, z1, z2, z_middle, z_ref, z_ref5,
           localz0=ia_params->LJANGLE_z0, localdz2=ia_params->LJANGLE_dz/2.,
           localkappa6=pow(1/ia_params->LJANGLE_kappa,6);



    /* Retrieve the bonded partners from parsing */
    if (ia_params->LJANGLE_bonded1type == p1->p.type) {
        part1p = p1->p.identity + ia_params->LJANGLE_bonded1pos;
        part1n = p1->p.identity + ia_params->LJANGLE_bonded1neg;
        part2p = p2->p.identity + ia_params->LJANGLE_bonded2pos;
        part2n = p2->p.identity + ia_params->LJANGLE_bonded2neg;
    } else {
        part1p = p1->p.identity + ia_params->LJANGLE_bonded2pos;
        part1n = p1->p.identity + ia_params->LJANGLE_bonded2neg;
        part2p = p2->p.identity + ia_params->LJANGLE_bonded1pos;
        part2n = p2->p.identity + ia_params->LJANGLE_bonded1neg;
    }

    if (part1p >= 0 && part1p < n_part &&
            part1n >= 0 && part1n < n_part &&
            part2p >= 0 && part2p < n_part &&
            part2n >= 0 && part2n < n_part     ) {

        p3 = local_particles[part1p];
        p4 = local_particles[part1n];
        p5 = local_particles[part2p];
        p6 = local_particles[part2n];

        /* Check whether pointers have been allocated.
         * Otherwise, there's a communication error (verlet skin too small).
         */
        if (p3==NULL ||p4==NULL ||p5==NULL ||p6==NULL)
            fprintf(stderr, "LJANGLE - Communication error, all particles cannot be reached locally.\n");



        get_mi_vector(r31, p1->r.p, p3->r.p);
        get_mi_vector(r41, p1->r.p, p4->r.p);
        get_mi_vector(r52, p2->r.p, p5->r.p);
        get_mi_vector(r62, p2->r.p, p6->r.p);


        /* Bead i represents the central particle of monomer 1.
         * Bead j is the virtual particle that gives the orientation of monomer 1.
         * Bead k represents the central particle of monomer 2.
         * Bead n is the virtual particle that gives the orientation of monomer 2.
         */
        for(j=0; j<3; ++j) {
            rij[j] = r31[j] + r41[j];
            rik[j] = -d[j]; /* At this point, rik[3] has length dist */
            rkn[j] = r52[j] + r62[j];
        }

        l_rij2 = sqrlen(rij);
        l_rik2 = dist*dist;
        l_rkn2 = sqrlen(rkn);
        l_rij  = sqrt(l_rij2);
        l_rik  = dist;
        l_rkn  = sqrt(l_rkn2);

        cos_jik = scalar(rij,rik)/(l_rij*l_rik);
        cos_ikn = -scalar(rik,rkn)/(l_rik*l_rkn);

        if(cos_jik>0. && cos_ikn>0.) {
            angular_jik       = pow(cos_jik,2);
            angular_ikn       = pow(cos_ikn,2);
            angular_jik_prime = -2*cos_jik;
            angular_ikn_prime = -2*cos_ikn;

            /* Optional 2nd environment */
            if (localdz2 > 0.) {
                /* calculate center position of the interaction (calculate minimal distance) */
                z1  = p1->r.p[2];
                z2  = p2->r.p[2];
                z_middle  = z1 + z2;
                z_middle /= 2.;
                if (PERIODIC(2))
                    if (z_middle > box_l[2] || z_middle < 0.)
                        z_middle -= dround(z_middle *box_l_i[2])*box_l[2];

                /* If we're in the environment #2 region, calculate the new interaction strength */
                if (z_middle > localz0 - localdz2 && z_middle <= localz0) {
                    z_ref = z_middle - localz0 + localdz2;
                    z_ref5 = pow(z_ref,5);
                    effective_eps += (ia_params->LJANGLE_epsprime - ia_params->LJANGLE_eps) *
                                     localkappa6*z_ref5*fabs(z_ref) /
                                     (1 + localkappa6*z_ref5*z_ref);
                } else if (z_middle > localz0 && z_middle < localz0 + localdz2) {
                    z_ref = z_middle - localz0 - localdz2;
                    z_ref5 = pow(z_ref,5);
                    effective_eps -= (ia_params->LJANGLE_epsprime - ia_params->LJANGLE_eps) *
                                     localkappa6*z_ref5*fabs(z_ref) /
                                     (1 + localkappa6*z_ref5*z_ref);
                }
            }

            /* normal case: resulting force/energy smaller than capping. */
            if(dist > ia_params->LJANGLE_capradius) {
                frac2 = SQR(ia_params->LJANGLE_sig/dist);
                frac10 = frac2*frac2*frac2*frac2*frac2;
                rad        = effective_eps * frac10*(5.0 * frac2 - 6.0);
                radprime   = 60.0 * effective_eps * frac10*(1.0 - frac2) / dist;

#ifdef LJ_WARN_WHEN_CLOSE
                if(radprime > 1000) fprintf(stderr,"%d: LJANGLE-Warning: Pair (%d-%d) force=%f dist=%f\n",
                                                this_node,p1->p.identity,p2->p.identity,radprime,dist);
#endif
            }
            /* capped part of lj-angle potential. */
            else if(dist > 0.0) {
                /* set the length of rik to capradius */
                for (j=0; j<3; ++j)
                    rik[j] *= ia_params->LJANGLE_capradius/dist;

                l_rik = ia_params->LJANGLE_capradius;

                frac2 = SQR(ia_params->LJANGLE_sig/ia_params->LJANGLE_capradius);
                frac10 = frac2*frac2*frac2*frac2*frac2;

                rad        = effective_eps * frac10*(5.0 * frac2 - 6.0);
                radprime   = 60.0 * effective_eps * frac10*(1.0 - frac2) / (ia_params->LJANGLE_capradius);
            }

            /* Regroup the last two cases in one */
            /* Propagate all forces in this function rather than in the forces.hpp file */
            if (dist > 0.0) {
                for(j=0; j<3; ++j) {
                    p1->f.f[j] += angular_jik * angular_ikn * rik[j]/l_rik *radprime
                                  + angular_ikn * rad * angular_jik_prime
                                  * ( ( 2*rik[j]-rij[j] )/( l_rij*l_rik )
                                      - cos_jik*( 2*rij[j]/l_rij2 - rik[j]/l_rik2 ) )
                                  + angular_jik * rad * angular_ikn_prime
                                  * ( rkn[j]/( l_rik*l_rkn )
                                      + cos_ikn*rik[j]/l_rik2 );
                    p2->f.f[j] += -angular_jik * angular_ikn * rik[j]/l_rik *radprime
                                  + angular_ikn * rad * angular_jik_prime
                                  * ( rij[j]/( l_rij*l_rik )
                                      - cos_jik*rik[j]/l_rik2 )
                                  + angular_jik * rad * angular_ikn_prime
                                  * ( -(2*rik[j]+rkn[j])/(l_rik*l_rkn)
                                      - cos_ikn*( 2*rkn[j]/l_rkn2 + rik[j]/l_rik2 ) );
                    p3->f.f[j] += angular_ikn * rad * angular_jik_prime
                                  * ( -rik[j]/(l_rij*l_rik)
                                      + cos_jik*rij[j]/l_rij2 );
                    p4->f.f[j] += angular_ikn * rad * angular_jik_prime
                                  * ( -rik[j]/(l_rij*l_rik)
                                      + cos_jik*rij[j]/l_rij2 );
                    p5->f.f[j] += angular_jik * rad * angular_ikn_prime
                                  * ( rik[j]/(l_rik*l_rkn)
                                      + cos_ikn*rkn[j]/l_rkn2 );
                    p6->f.f[j] += angular_jik * rad * angular_ikn_prime
                                  * ( rik[j]/(l_rik*l_rkn)
                                      + cos_ikn*rkn[j]/l_rkn2 );
                }
            }


            /* this should not happen! In this case consider only radial potential*/
            else {
                LJ_TRACE(fprintf(stderr, "%d: LJ-angle warning: Particles id1=%d id2=%d exactly on top of each other\n",this_node,p1->p.identity,p2->p.identity));

                frac2 = SQR(ia_params->LJANGLE_sig/ia_params->LJANGLE_capradius);
                frac10 = frac2*frac2*frac2*frac2*frac2;
                rad   = effective_eps * frac10*(5.0 * frac2 - 6.0) / ia_params->LJANGLE_capradius;

                p1->f.f[0] += rad * ia_params->LJANGLE_capradius;
            }


            ONEPART_TRACE(if(p1->p.identity==check_id) fprintf(stderr,"%d: OPT: LJANGLE   f = (%.3e,%.3e,%.3e) with part id=%d at dist %f fac %.3e\n",this_node,p1->f.f[0],p1->f.f[1],p1->f.f[2],p2->p.identity,dist,radprime));
            ONEPART_TRACE(if(p2->p.identity==check_id) fprintf(stderr,"%d: OPT: LJANGLE   f = (%.3e,%.3e,%.3e) with part id=%d at dist %f fac %.3e\n",this_node,p2->f.f[0],p2->f.f[1],p2->f.f[2],p1->p.identity,dist,radprime));

            LJ_TRACE(fprintf(stderr,"%d: LJANGLE: Pair (%d-%d) dist=%.3f: force+-: (%.3e,%.3e,%.3e)\n",
                             this_node,p1->p.identity,p2->p.identity,dist,rad*d[0],rad*d[1],rad*d[2]));
        }
Example #20
0
/** Preparation of the halo parallelization scheme. Sets up the
 *  necessary datastructures for \ref halo_communication
 * @param hc         halo communicator beeing created (Input/Output)
 * @param lattice    lattice the communcation is created for (Input)
 * @param fieldtype  field layout of the lattice data (Input)
 * @param datatype   MPI datatype for the lattice data (Input)
 */
void prepare_halo_communication(HaloCommunicator *hc, Lattice *lattice, Fieldtype fieldtype, MPI_Datatype datatype) {
  int k, n, dir, lr, cnt, num = 0 ;
  int *grid  = lattice->grid ;
  int *period = lattice->halo_grid ;

  for (n=0; n<hc->num; n++) {
    MPI_Type_free(&(hc->halo_info[n].datatype));
  }

  num = 2*3; /* two communications in each space direction */

  hc->num = num ;
  hc->halo_info = realloc(hc->halo_info,num*sizeof(HaloInfo)) ;

  int extent = fieldtype->extent;

  cnt = 0 ;
  for (dir=0; dir<3; dir++) {
    for (lr=0; lr<2; lr++) {

	      HaloInfo *hinfo = &(hc->halo_info[cnt]) ;

	      int nblocks = 1 ;
	      for (k=dir+1;k<3;k++) {
		  nblocks *= period[k] ;
	      }
	      int stride = 1 ;
	      for (k=0;k<dir;k++) {
		  stride *= period[k] ;
	      }
	      int skip = 1 ;
	      for (k=0;k<dir+1 && k<2;k++) {
		  skip *= period[k] ;
	      }	      

	      if (lr==0) {
		/* send to left, recv from right */
		hinfo->s_offset = extent * stride * 1;
		hinfo->r_offset = extent * stride * (grid[dir]+1);	      
	      } else {
		/* send to right, recv from left */
		hinfo->s_offset = extent * stride * grid[dir];
		hinfo->r_offset = extent * stride * 0;

	      } 

	      hinfo->source_node = node_neighbors[2*dir+1-lr];
	      hinfo->dest_node = node_neighbors[2*dir+lr];

	      halo_create_field_vector(nblocks, stride, skip, fieldtype, &hinfo->fieldtype);
	      
	      MPI_Type_vector(nblocks, stride, skip, datatype, &hinfo->datatype);
	      MPI_Type_commit(&hinfo->datatype);

#ifdef PARTIAL_PERIODIC
	      if ( !PERIODIC(dir) && (boundary[2*dir+lr] != 0 || boundary[2*dir+1-lr] != 0) ) {
		if (node_grid[dir] == 1) {
		  hinfo->type = HALO_OPEN;
		} 
		else if (lr == 0) {
		  if (boundary[2*dir+lr] == 1) {
		    hinfo->type = HALO_RECV;
		  } else {
		    hinfo->type = HALO_SEND;
		  }
		}
		else {
		  if (boundary[2*dir+lr] == -1) {
		    hinfo->type = HALO_RECV;
		  } else {
		    hinfo->type = HALO_SEND;
		  }
		}
	      } else
#endif
	      {
		if (node_grid[dir] == 1) {
		  hc->halo_info[cnt].type = HALO_LOCL;
		}
		else {
		  hc->halo_info[cnt].type = HALO_SENDRECV;
		}
	      }

	      HALO_TRACE(fprintf(stderr,"%d: prepare_halo_communication dir=%d lr=%d s_offset=%ld r_offset=%ld s_node=%d d_node=%d type=%d\n",this_node,dir,lr,hinfo->s_offset,hinfo->r_offset,hinfo->source_node,hinfo->dest_node,hinfo->type)) ;

	      cnt++;

    }
  }

}
Example #21
0
/** Create communicators for cell structure domain decomposition. (see \ref GhostCommunicator) */
void  dd_prepare_comm(GhostCommunicator *comm, int data_parts)
{
  int dir,lr,i,cnt, num, n_comm_cells[3];
  int lc[3],hc[3],done[3]={0,0,0};

  /* calculate number of communications */
  num = 0;
  for(dir=0; dir<3; dir++) { 
    for(lr=0; lr<2; lr++) {
#ifdef PARTIAL_PERIODIC
      /* No communication for border of non periodic direction */
      if( PERIODIC(dir) || (boundary[2*dir+lr] == 0) ) 
#endif
	{
	  if(node_grid[dir] == 1 ) num++;
	  else num += 2;
	}
    }
  }

  /* prepare communicator */
  CELL_TRACE(fprintf(stderr,"%d Create Communicator: prep_comm data_parts %d num %d\n",this_node,data_parts,num));
  prepare_comm(comm, data_parts, num);

  /* number of cells to communicate in a direction */
  n_comm_cells[0] = dd.cell_grid[1]       * dd.cell_grid[2];
  n_comm_cells[1] = dd.cell_grid[2]       * dd.ghost_cell_grid[0];
  n_comm_cells[2] = dd.ghost_cell_grid[0] * dd.ghost_cell_grid[1];

  cnt=0;
  /* direction loop: x, y, z */
  for(dir=0; dir<3; dir++) {
    lc[(dir+1)%3] = 1-done[(dir+1)%3]; 
    lc[(dir+2)%3] = 1-done[(dir+2)%3];
    hc[(dir+1)%3] = dd.cell_grid[(dir+1)%3]+done[(dir+1)%3];
    hc[(dir+2)%3] = dd.cell_grid[(dir+2)%3]+done[(dir+2)%3];
    /* lr loop: left right */
    /* here we could in principle build in a one sided ghost
       communication, simply by taking the lr loop only over one
       value */
    for(lr=0; lr<2; lr++) {
      if(node_grid[dir] == 1) {
	/* just copy cells on a single node */
#ifdef PARTIAL_PERIODIC
	if( PERIODIC(dir ) || (boundary[2*dir+lr] == 0) ) 
#endif
	  {
	    comm->comm[cnt].type          = GHOST_LOCL;
	    comm->comm[cnt].node          = this_node;
	    /* Buffer has to contain Send and Recv cells -> factor 2 */
	    comm->comm[cnt].part_lists    = malloc(2*n_comm_cells[dir]*sizeof(ParticleList *));
	    comm->comm[cnt].n_part_lists  = 2*n_comm_cells[dir];
	    /* prepare folding of ghost positions */
	    if((data_parts & GHOSTTRANS_POSSHFTD) && boundary[2*dir+lr] != 0) 
	      comm->comm[cnt].shift[dir] = boundary[2*dir+lr]*box_l[dir];
	    /* fill send comm cells */
	    lc[(dir+0)%3] = hc[(dir+0)%3] = 1+lr*(dd.cell_grid[(dir+0)%3]-1);  
	    dd_fill_comm_cell_lists(comm->comm[cnt].part_lists,lc,hc);
	    CELL_TRACE(fprintf(stderr,"%d: prep_comm %d copy to          grid (%d,%d,%d)-(%d,%d,%d)\n",this_node,cnt,
			       lc[0],lc[1],lc[2],hc[0],hc[1],hc[2]));
	    /* fill recv comm cells */
	    lc[(dir+0)%3] = hc[(dir+0)%3] = 0+(1-lr)*(dd.cell_grid[(dir+0)%3]+1);
	    /* place recieve cells after send cells */
	    dd_fill_comm_cell_lists(&comm->comm[cnt].part_lists[n_comm_cells[dir]],lc,hc);
	    CELL_TRACE(fprintf(stderr,"%d: prep_comm %d copy from        grid (%d,%d,%d)-(%d,%d,%d)\n",this_node,cnt,lc[0],lc[1],lc[2],hc[0],hc[1],hc[2]));
	    cnt++;
	  }
      }
      else {
	/* i: send/recv loop */
	for(i=0; i<2; i++) {  
#ifdef PARTIAL_PERIODIC
	  if( PERIODIC(dir) || (boundary[2*dir+lr] == 0) ) 
#endif
	    if((node_pos[dir]+i)%2==0) {
	      comm->comm[cnt].type          = GHOST_SEND;
	      comm->comm[cnt].node          = node_neighbors[2*dir+lr];
	      comm->comm[cnt].part_lists    = malloc(n_comm_cells[dir]*sizeof(ParticleList *));
	      comm->comm[cnt].n_part_lists  = n_comm_cells[dir];
	      /* prepare folding of ghost positions */
	      if((data_parts & GHOSTTRANS_POSSHFTD) && boundary[2*dir+lr] != 0) 
		comm->comm[cnt].shift[dir] = boundary[2*dir+lr]*box_l[dir];
	      
	      lc[(dir+0)%3] = hc[(dir+0)%3] = 1+lr*(dd.cell_grid[(dir+0)%3]-1);  
	      dd_fill_comm_cell_lists(comm->comm[cnt].part_lists,lc,hc);
	      
	      CELL_TRACE(fprintf(stderr,"%d: prep_comm %d send to   node %d grid (%d,%d,%d)-(%d,%d,%d)\n",this_node,cnt,
				 comm->comm[cnt].node,lc[0],lc[1],lc[2],hc[0],hc[1],hc[2]));
	      cnt++;
	    }
#ifdef PARTIAL_PERIODIC
	  if( PERIODIC(dir) || (boundary[2*dir+(1-lr)] == 0) ) 
#endif
	    if((node_pos[dir]+(1-i))%2==0) {
	      comm->comm[cnt].type          = GHOST_RECV;
	      comm->comm[cnt].node          = node_neighbors[2*dir+(1-lr)];
	      comm->comm[cnt].part_lists    = malloc(n_comm_cells[dir]*sizeof(ParticleList *));
	      comm->comm[cnt].n_part_lists  = n_comm_cells[dir];
	      
	      lc[(dir+0)%3] = hc[(dir+0)%3] = 0+(1-lr)*(dd.cell_grid[(dir+0)%3]+1);
	      dd_fill_comm_cell_lists(comm->comm[cnt].part_lists,lc,hc);
	      
	      CELL_TRACE(fprintf(stderr,"%d: prep_comm %d recv from node %d grid (%d,%d,%d)-(%d,%d,%d)\n",this_node,cnt,
				 comm->comm[cnt].node,lc[0],lc[1],lc[2],hc[0],hc[1],hc[2]));
	      cnt++;
	    }
	}
      }
      done[dir]=1;
    }
  }
}
double  magnetic_dipolar_direct_sum_calculations(int force_flag, int energy_flag) {
  Cell *cell;
  Particle *part;
  int i,c,np;
  double *x=NULL,  *y=NULL, *z=NULL;
  double *mx=NULL,  *my=NULL, *mz=NULL;
  double *fx=NULL,  *fy=NULL, *fz=NULL;
#ifdef ROTATION
  double *tx=NULL,  *ty=NULL, *tz=NULL;
#endif
  int dip_particles,dip_particles2;
  double ppos[3];
  int img[3];
  double u;

  
  if(n_nodes!=1) {fprintf(stderr,"error: magnetic Direct Sum is just for one cpu .... \n"); errexit();}
  if(!(force_flag) && !(energy_flag) ) {fprintf(stderr," I don't know why you call dawaanr_caclulations with all flags zero \n"); return 0;}

  x = (double *) malloc(sizeof(double)*n_part);
  y = (double *) malloc(sizeof(double)*n_part);
  z = (double *) malloc(sizeof(double)*n_part);

  mx = (double *) malloc(sizeof(double)*n_part);
  my = (double *) malloc(sizeof(double)*n_part);
  mz = (double *) malloc(sizeof(double)*n_part);
 
  if(force_flag) {
    fx = (double *) malloc(sizeof(double)*n_part);
    fy = (double *) malloc(sizeof(double)*n_part);
    fz = (double *) malloc(sizeof(double)*n_part);
 
#ifdef ROTATION   
    tx = (double *) malloc(sizeof(double)*n_part);
    ty = (double *) malloc(sizeof(double)*n_part);
    tz = (double *) malloc(sizeof(double)*n_part);
#endif  
  }
 
  dip_particles=0;
  for (c = 0; c < local_cells.n; c++) {
    cell = local_cells.cell[c];
    part = cell->part;
    np   = cell->n;
    for(i=0;i<np;i++) {
      if( part[i].p.dipm > 1.e-11 ) {
       
	mx[dip_particles]=part[i].r.dip[0];
	my[dip_particles]=part[i].r.dip[1];
	mz[dip_particles]=part[i].r.dip[2];

	/* here we wish the coordinates to be folded into the primary box */
                  
	ppos[0]=part[i].r.p[0];	  
	ppos[1]=part[i].r.p[1];	  
	ppos[2]=part[i].r.p[2];	  
	img[0]=part[i].l.i[0];	  
	img[1]=part[i].l.i[1];	  
        img[2]=part[i].l.i[2];	  		  
        fold_position(ppos, img);
	 
	x[dip_particles]=ppos[0];
	y[dip_particles]=ppos[1];
	z[dip_particles]=ppos[2];
	 

	if(force_flag) {
	  fx[dip_particles]=0;
	  fy[dip_particles]=0;
	  fz[dip_particles]=0;
	 
#ifdef ROTATION
	  tx[dip_particles]=0;
	  ty[dip_particles]=0;
	  tz[dip_particles]=0;
#endif
	} 
	 
	dip_particles++;
	  	 
      }
    }
  }
 
  /*now we do the calculations */
   
  { /* beginning of the area of calculation */
    int nx,ny,nz,i,j;
    double r,rnx,rny,rnz,pe1,pe2,pe3,r3,r5,r2,r7;
    double a,b,c,d;
#ifdef ROTATION
    double ax,ay,az,bx,by,bz;
#endif
    double rx,ry,rz;
    double rnx2,rny2;
    int NCUT[3],NCUT2;
	 
    for(i=0;i<3;i++){
      NCUT[i]=Ncut_off_magnetic_dipolar_direct_sum;
      if(PERIODIC(i) == 0)  {NCUT[i]=0;}  
    }
    NCUT2=Ncut_off_magnetic_dipolar_direct_sum*Ncut_off_magnetic_dipolar_direct_sum;
	     
	   
    u=0;
     
    fprintf(stderr,"Magnetic Direct sum takes long time. Done of %d: \n",dip_particles);

    for(i=0;i<dip_particles;i++){
      fprintf(stderr,"%d\r",i);
      for(j=0;j<dip_particles;j++){
	pe1=mx[i]*mx[j]+my[i]*my[j]+mz[i]*mz[j];
	rx=x[i]-x[j];
	ry=y[i]-y[j];
	rz=z[i]-z[j];
           
	for(nx=-NCUT[0];nx<=NCUT[0];nx++){
	  rnx=rx+nx*box_l[0]; 
	  rnx2=rnx*rnx;
	  for(ny=-NCUT[1];ny<=NCUT[1];ny++){
	    rny=ry+ny*box_l[1];
	    rny2=rny*rny;
	    for(nz=-NCUT[2];nz<=NCUT[2];nz++){
	      if( !(i==j && nx==0 && ny==0 && nz==0) ) {
		if(nx*nx+ny*ny +nz*nz<=  NCUT2){
		  rnz=rz+nz*box_l[2]; 
		  r2=rnx2+rny2+rnz*rnz;
		  r=sqrt(r2);
		  r3=r2*r;
		  r5=r3*r2;
		  r7=r5*r2;
			    
   
		  pe2=mx[i]*rnx+my[i]*rny+mz[i]*rnz;
		  pe3=mx[j]*rnx+my[j]*rny+mz[j]*rnz;
    
		  /*fprintf(stderr,"--------------------------------\n");
		    fprintf(stderr,"ij: %d %d\n",i,j);
		    fprintf(stderr,"xyz[i]: %lf %lf %lf\n",x[i],y[i],z[i]);
		    fprintf(stderr,"xyz[j]: %lf %lf %lf\n",x[j],y[j],z[j]);
		    fprintf(stderr,"mu xyz[i]: %lf %lf %lf\n",mx[i],my[i],mz[i]);
		    fprintf(stderr,"mu xyz[j]: %lf %lf %lf\n",mx[j],my[j],mz[j]);
		    fprintf(stderr,"rnxyz:  %lf %lf %lf\n",rnx,rny,rnz);
		    fprintf(stderr,"--------------------------------\n");*/
 
    
		  //Energy ............................   
    
		  u+= pe1/r3 - 3.0*pe2*pe3/r5;
	     
		  if(force_flag) {
		    //force ............................
		    a=mx[i]*mx[j]+my[i]*my[j]+mz[i]*mz[j];
		    a=3.0*a/r5;
		    b=-15.0*pe2*pe3/r7;
		    c=3.0*pe3/r5;
		    d=3.0*pe2/r5;
	     
		    fx[i]+=(a+b)*rnx+c*mx[i]+d*mx[j];
		    fy[i]+=(a+b)*rny+c*my[i]+d*my[j];
		    fz[i]+=(a+b)*rnz+c*mz[i]+d*mz[j];
	     
#ifdef ROTATION
		    //torque ............................
		    c=3.0/r5*pe3;
		    ax=my[i]*mz[j]-my[j]*mz[i];
		    ay=mx[j]*mz[i]-mx[i]*mz[j];
		    az=mx[i]*my[j]-mx[j]*my[i];
	     
		    bx=my[i]*rnz-rny*mz[i];
		    by=rnx*mz[i]-mx[i]*rnz;
		    bz=mx[i]*rny-rnx*my[i];
	     
		    tx[i]+=-ax/r3+bx*c;
		    ty[i]+=-ay/r3+by*c;
		    tz[i]+=-az/r3+bz*c;
#endif	  
		  } /* of force_flag  */
	     
		} }/* of nx*nx+ny*ny +nz*nz< NCUT*NCUT   and   !(i==j && nx==0 && ny==0 && nz==0) */
	    }/* of  for nz */
          }/* of  for ny  */
        }/* of  for nx  */
      }}   /* of  j and i  */ 


    fprintf(stderr,"done \n");
  }/* end of the area of calculation */
    
    
    
  /* set the forces, and torques of the particles within Espresso */
  if(force_flag) {
   
    dip_particles2=0;
    for (c = 0; c < local_cells.n; c++) {
      cell = local_cells.cell[c];
      part = cell->part;
      np   = cell->n;
      for(i=0;i<np;i++) {
	if( part[i].p.dipm  > 1.e-11 ) {
	 
	  part[i].f.f[0]+=coulomb.Dprefactor*fx[dip_particles2];
	  part[i].f.f[1]+=coulomb.Dprefactor*fy[dip_particles2];
	  part[i].f.f[2]+=coulomb.Dprefactor*fz[dip_particles2];
	
#ifdef ROTATION 
	  part[i].f.torque[0]+=coulomb.Dprefactor*tx[dip_particles2];
	  part[i].f.torque[1]+=coulomb.Dprefactor*ty[dip_particles2];
	  part[i].f.torque[2]+=coulomb.Dprefactor*tz[dip_particles2];
#endif
	  dip_particles2++;
	  	 
	}
      }
    }
   
    /* small checking */
    if(dip_particles != dip_particles2) { fprintf(stderr,"magnetic direct sum calculations: error mismatch of particles \n"); errexit();}
  } /*of if force_flag */
  
  /* free memory used */

  free(x);
  free(y);
  free(z);
  free(mx);
  free(my);
  free(mz);
 
  if(force_flag) {
    free(fx);
    free(fy);
    free(fz);
#ifdef ROTATION
    free(tx);
    free(ty);
    free(tz);
#endif
  }
 
  return 0.5*u;
}