void Validate_Lists( reax_system *system, storage *workspace, reax_list **lists,
		     int step, int n, int N, int numH, MPI_Comm comm )
{
  int i, comp, Hindex;
  reax_list *bonds, *hbonds;
  reallocate_data *realloc;
  realloc = &(workspace->realloc);

  /* bond list */
  if( N > 0 ) {
    bonds = *lists + BONDS;
    
    for( i = 0; i < N; ++i ) {
      // if( i < n ) - we need to update ghost estimates for delayed nbrings
      system->my_atoms[i].num_bonds = MAX(Num_Entries(i,bonds)*2, MIN_BONDS);
     
      //if( End_Index(i, bonds) >= Start_Index(i+1, bonds)-2 )
      //workspace->realloc.bonds = 1;
      
      if( i < N-1 )
	comp = Start_Index(i+1, bonds);
      else comp = bonds->num_intrs;
      
      if( End_Index(i, bonds) > comp ) {
	fprintf( stderr, "step%d-bondchk failed: i=%d end(i)=%d str(i+1)=%d\n",
		 step, i, End_Index(i,bonds), comp );
	MPI_Abort( comm, INSUFFICIENT_MEMORY );
      }
    }
  }


  /* hbonds list */
  if( numH > 0 ) {
    hbonds = *lists + HBONDS;
    
    for( i = 0; i < n; ++i ) {
      Hindex = system->my_atoms[i].Hindex;
      if( Hindex > -1 ) {
	system->my_atoms[i].num_hbonds = 
	  (int)(MAX( Num_Entries(Hindex, hbonds)*SAFER_ZONE, MIN_HBONDS ));
	
	//if( Num_Entries(i, hbonds) >= 
	//(Start_Index(i+1,hbonds)-Start_Index(i,hbonds))*0.90/*DANGER_ZONE*/){
	//  workspace->realloc.hbonds = 1;
	
	if( Hindex < numH-1 )
	  comp = Start_Index(Hindex+1, hbonds);
	else comp = hbonds->num_intrs;
	
	if( End_Index(Hindex, hbonds) > comp ) {
	  fprintf(stderr,"step%d-hbondchk failed: H=%d end(H)=%d str(H+1)=%d\n",
		  step, Hindex, End_Index(Hindex,hbonds), comp );
	  MPI_Abort( comm, INSUFFICIENT_MEMORY );
	}
      }
    }
  }
}
Exemple #2
0
// copy bond list into old bond list
void Copy_Bond_List( reax_system *system, control_params *control,
		     list **lists )
{
  int i, j, top_old;
  list *new_bonds = (*lists) + BONDS;
  list *old_bonds = (*lists) + OLD_BONDS;

  for( top_old = 0, i = 0; i < system->N; ++i ) {
    Set_Start_Index( i, top_old, old_bonds );

    // fprintf( stdout, "%d: ", i );
    for( j = Start_Index( i, new_bonds ); j < End_Index( i, new_bonds ); ++j )
      if( new_bonds->select.bond_list[j].bo_data.BO >= control->bg_cut ) {
	// fprintf( stderr, "%d ", new_bonds->select.bond_list[j].nbr );
	old_bonds->select.bond_list[ top_old ].nbr =
	  new_bonds->select.bond_list[j].nbr;
	old_bonds->select.bond_list[ top_old ].bo_data.BO =
	  new_bonds->select.bond_list[j].bo_data.BO;
	top_old++;
      }

    Set_End_Index( i, top_old, old_bonds);
    // fprintf( stderr, "--- s: %d, e: %d\n",
    // Start_Index( i, old_bonds ),  End_Index( i, old_bonds ) );
  }
}
Exemple #3
0
/* This version of Compute_Total_Force computes forces from coefficients 
 accumulated by all interaction functions. Saves enormous time & space! */
void Compute_Total_Force(reax_system *system, control_params *control,
		simulation_data *data, static_storage *workspace, list **lists) {
	int i, pj;
	list *bonds = (*lists) + BONDS;

	for (i = 0; i < system->N; ++i)
		for (pj = Start_Index(i, bonds); pj < End_Index(i, bonds); ++pj)
			if (i < bonds->select.bond_list[pj].nbr) {
				if (control->ensemble == NVE || control->ensemble == NVT)
					Add_dBond_to_Forces(i, pj, system, data, workspace, lists);
				else
					Add_dBond_to_Forces_NPT(i, pj, system, data, workspace,
							lists);
			}
}
void Compute_Total_Force( reax_system *system, control_params *control,
                          simulation_data *data, storage *workspace,
                          reax_list **lists, mpi_datatypes *mpi_data )
{
  int i, pj;
  reax_list *bonds = (*lists) + BONDS;

  for( i = 0; i < system->N; ++i )
    for( pj = Start_Index(i, bonds); pj < End_Index(i, bonds); ++pj )
      if( i < bonds->select.bond_list[pj].nbr ) {
        if( control->virial == 0 )
          Add_dBond_to_Forces( system, i, pj, workspace, lists );
        else
          Add_dBond_to_Forces_NPT( i, pj, data, workspace, lists );
      }

}
Exemple #5
0
/* this version of Compute_Total_Force computes forces from
   coefficients accumulated by all interaction functions.
   Saves enormous time & space! */
void Compute_Total_Force( reax_system *system, control_params *control,
                          simulation_data *data, storage *workspace,
                          reax_list **lists, mpi_datatypes *mpi_data )
{
  int i, pj;
  reax_list *bonds = (*lists) + BONDS;

  for( i = 0; i < system->N; ++i )
    for( pj = Start_Index(i, bonds); pj < End_Index(i, bonds); ++pj )
      if( i < bonds->select.bond_list[pj].nbr ) {
        if( control->virial == 0 )
          Add_dBond_to_Forces( system, i, pj, workspace, lists );
        else
          Add_dBond_to_Forces_NPT( i, pj, data, workspace, lists );
      }

  //Print_Total_Force( system, data, workspace );
#if defined(PURE_REAX)
  /* now all forces are computed to their partially-final values
     based on the neighbors information each processor has had.
     final values of force on each atom needs to be computed by adding up
     all partially-final pieces */
  Coll( system, mpi_data, workspace->f, mpi_data->mpi_rvec,
        sizeof(rvec)/sizeof(void), rvec_unpacker );
  for( i = 0; i < system->n; ++i )
    rvec_Copy( system->my_atoms[i].f, workspace->f[i] );

#if defined(TEST_FORCES)
  Coll( system, mpi_data, workspace->f_ele, mpi_data->mpi_rvec, rvec_unpacker);
  Coll( system, mpi_data, workspace->f_vdw, mpi_data->mpi_rvec, rvec_unpacker);
  Coll( system, mpi_data, workspace->f_be, mpi_data->mpi_rvec, rvec_unpacker );
  Coll( system, mpi_data, workspace->f_lp, mpi_data->mpi_rvec, rvec_unpacker );
  Coll( system, mpi_data, workspace->f_ov, mpi_data->mpi_rvec, rvec_unpacker );
  Coll( system, mpi_data, workspace->f_un, mpi_data->mpi_rvec, rvec_unpacker );
  Coll( system, mpi_data, workspace->f_ang, mpi_data->mpi_rvec, rvec_unpacker);
  Coll( system, mpi_data, workspace->f_coa, mpi_data->mpi_rvec, rvec_unpacker);
  Coll( system, mpi_data, workspace->f_pen, mpi_data->mpi_rvec, rvec_unpacker);
  Coll( system, mpi_data, workspace->f_hb, mpi_data->mpi_rvec, rvec_unpacker );
  Coll( system, mpi_data, workspace->f_tor, mpi_data->mpi_rvec, rvec_unpacker);
  Coll( system, mpi_data, workspace->f_con, mpi_data->mpi_rvec, rvec_unpacker);
#endif

#endif
}
Exemple #6
0
void Visit_Bonds( int atom, int *mark, int *type, reax_system *system,
		  control_params *control, list *bonds, int ignore )
{
  int i, t, start, end, nbr;
  real bo;

  mark[atom] = 1;
  t = system->atoms[atom].type;
  if( ignore && control->ignore[t] )
    return;
  type[t]++;

  start = Start_Index( atom, bonds );
  end = End_Index( atom, bonds );
  for( i = start; i < end; ++i ) {
    nbr = bonds->select.bond_list[i].nbr;
    bo = bonds->select.bond_list[i].bo_data.BO;
    if( bo >= control->bg_cut && !mark[nbr] )
      Visit_Bonds( nbr, mark, type, system, control, bonds, ignore );
  }
}
Exemple #7
0
void Get_Molecule( int atom, molecule *m, int *mark, reax_system *system,
		   control_params *control, list *bonds, int print,
		   FILE *fout )
{
  int i, start, end;

  start = Start_Index( atom, bonds );
  end = End_Index( atom, bonds );

  if( print )
    fprintf( fout, "%5d(%2s)",
	     atom+1, system->reaxprm.sbp[ system->atoms[atom].type ].name );
  mark[atom] = 1;
  m->atom_list[ m->atom_count++ ] = atom;
  m->mtypes[ system->atoms[ atom ].type ]++;

  for( i = start; i < end; ++i )
    if( bonds->select.bond_list[i].bo_data.BO >= control->bg_cut &&
	!mark[bonds->select.bond_list[i].nbr] )
      Get_Molecule( bonds->select.bond_list[i].nbr, m, mark,
		    system, control, bonds, print, fout );
}
Exemple #8
0
void Estimate_Storage_Sizes(reax_system *system, control_params *control,
		list **lists, int *Htop, int *hb_top, int *bond_top, int *num_3body) {
	int i, j, pj;
	int start_i, end_i;
	int type_i, type_j;
	int ihb, jhb;
	real r_ij, r2;
	real C12, C34, C56;
	real BO, BO_s, BO_pi, BO_pi2;
	real p_boc1, p_boc2;
	list *far_nbrs;
	single_body_parameters *sbp_i, *sbp_j;
	two_body_parameters *twbp;
	far_neighbor_data *nbr_pj;
	reax_atom *atom_i, *atom_j;

	far_nbrs = *lists + FAR_NBRS;
	p_boc1 = system->reaxprm.gp.l[0];
	p_boc2 = system->reaxprm.gp.l[1];

	for (i = 0; i < system->N; ++i) {
		atom_i = &(system->atoms[i]);
		type_i = atom_i->type;
		start_i = Start_Index(i, far_nbrs);
		end_i = End_Index(i, far_nbrs);
		sbp_i = &(system->reaxprm.sbp[type_i]);
		ihb = sbp_i->p_hbond;

		for (pj = start_i; pj < end_i; ++pj) {
			nbr_pj = &(far_nbrs->select.far_nbr_list[pj]);
			j = nbr_pj->nbr;
			atom_j = &(system->atoms[j]);
			type_j = atom_j->type;
			sbp_j = &(system->reaxprm.sbp[type_j]);
			twbp = &(system->reaxprm.tbp[type_i][type_j]);

			if (nbr_pj->d <= control->r_cut) {
				++(*Htop);

				/* hydrogen bond lists */
				if (control->hb_cut > 0.1 && (ihb == 1 || ihb == 2)
						&& nbr_pj->d <= control->hb_cut) {
					jhb = sbp_j->p_hbond;
					if (ihb == 1 && jhb == 2)
						++hb_top[i];
					else if (ihb == 2 && jhb == 1)
						++hb_top[j];
				}

				/* uncorrected bond orders */
				if (nbr_pj->d <= control->nbr_cut) {
					r_ij = nbr_pj->d;
					r2 = SQR(r_ij);

					if (sbp_i->r_s > 0.0 && sbp_j->r_s > 0.0) {
						C12 = twbp->p_bo1 * POW(r_ij / twbp->r_s, twbp->p_bo2);
						BO_s = (1.0 + control->bo_cut) * EXP(C12);
					} else
						BO_s = C12 = 0.0;

					if (sbp_i->r_pi > 0.0 && sbp_j->r_pi > 0.0) {
						C34 = twbp->p_bo3 * POW(r_ij / twbp->r_p, twbp->p_bo4);
						BO_pi = EXP(C34);
					} else
						BO_pi = C34 = 0.0;

					if (sbp_i->r_pi_pi > 0.0 && sbp_j->r_pi_pi > 0.0) {
						C56 = twbp->p_bo5 * POW(r_ij / twbp->r_pp, twbp->p_bo6);
						BO_pi2 = EXP(C56);
					} else
						BO_pi2 = C56 = 0.0;

					/* Initially BO values are the uncorrected ones, page 1 */
					BO = BO_s + BO_pi + BO_pi2;

					if (BO >= control->bo_cut) {
						++bond_top[i];
						++bond_top[j];
					}
				}
			}
		}
	}

	*Htop += system->N;
	*Htop *= SAFE_ZONE;
	for (i = 0; i < system->N; ++i) {
		hb_top[i] = MAX( hb_top[i] * SAFE_HBONDS, MIN_HBONDS );
		*num_3body += SQR(bond_top[i]);
		bond_top[i] = MAX( bond_top[i] * 2, MIN_BONDS );
	}
	*num_3body *= SAFE_ZONE;
}
Exemple #9
0
void Validate_Lists(static_storage *workspace, list **lists, int step, int n,
		int Hmax, int Htop, int num_bonds, int num_hbonds) {
	int i, flag;
	list *bonds, *hbonds;

	bonds = *lists + BONDS;
	hbonds = *lists + HBONDS;

	/* far neighbors */
	if (Htop > Hmax * DANGER_ZONE) {
		workspace->realloc.Htop = Htop;
		if (Htop > Hmax) {
			fprintf(stderr,
					"step%d - ran out of space on H matrix: Htop=%d, max = %d",
					step, Htop, Hmax);
			exit(INSUFFICIENT_SPACE);
		}
	}

	/* bond list */
	flag = -1;
	workspace->realloc.num_bonds = num_bonds;
	for (i = 0; i < n - 1; ++i)
		if (End_Index(i, bonds) >= Start_Index(i + 1, bonds) - 2) {
			workspace->realloc.bonds = 1;
			if (End_Index(i, bonds) > Start_Index(i + 1, bonds))
				flag = i;
		}

	if (flag > -1) {
		fprintf(stderr, "step%d-bondchk failed: i=%d end(i)=%d str(i+1)=%d\n",
				step, flag, End_Index(flag, bonds),
				Start_Index(flag + 1, bonds));
		exit(INSUFFICIENT_SPACE);
	}

	if (End_Index(i, bonds) >= bonds->num_intrs - 2) {
		workspace->realloc.bonds = 1;

		if (End_Index(i, bonds) > bonds->num_intrs) {
			fprintf(stderr,
					"step%d-bondchk failed: i=%d end(i)=%d bond_end=%d\n",
					step, flag, End_Index(i, bonds), bonds->num_intrs);
			exit(INSUFFICIENT_SPACE);
		}
	}

	/* hbonds list */
	if (workspace->num_H > 0) {
		flag = -1;
		workspace->realloc.num_hbonds = num_hbonds;
		for (i = 0; i < workspace->num_H - 1; ++i)
			if (Num_Entries(i, hbonds) >= (Start_Index(i + 1, hbonds)
					- Start_Index(i, hbonds)) * DANGER_ZONE) {
				workspace->realloc.hbonds = 1;
				if (End_Index(i, hbonds) > Start_Index(i + 1, hbonds))
					flag = i;
			}

		if (flag > -1) {
			fprintf(stderr,
					"step%d-hbondchk failed: i=%d end(i)=%d str(i+1)=%d\n",
					step, flag, End_Index(flag, hbonds), Start_Index(flag + 1,
							hbonds));
			exit(INSUFFICIENT_SPACE);
		}

		if (Num_Entries(i, hbonds) >= (hbonds->num_intrs - Start_Index(i,
				hbonds)) * DANGER_ZONE) {
			workspace->realloc.hbonds = 1;

			if (End_Index(i, hbonds) > hbonds->num_intrs) {
				fprintf(stderr,
						"step%d-hbondchk failed: i=%d end(i)=%d hbondend=%d\n",
						step, flag, End_Index(i, hbonds), hbonds->num_intrs);
				exit(INSUFFICIENT_SPACE);
			}
		}
	}
}
void Valence_Angles( reax_system *system, control_params *control,
                     simulation_data *data, storage *workspace,
                     reax_list **lists, output_controls *out_control )
{
  int i, j, pi, k, pk, t;
  int type_i, type_j, type_k;
  int start_j, end_j, start_pk, end_pk;
  int cnt, num_thb_intrs;

  double temp, temp_bo_jt, pBOjt7;
  double p_val1, p_val2, p_val3, p_val4, p_val5;
  double p_val6, p_val7, p_val8, p_val9, p_val10;
  double p_pen1, p_pen2, p_pen3, p_pen4;
  double p_coa1, p_coa2, p_coa3, p_coa4;
  double trm8, expval6, expval7, expval2theta, expval12theta, exp3ij, exp3jk;
  double exp_pen2ij, exp_pen2jk, exp_pen3, exp_pen4, trm_pen34, exp_coa2;
  double dSBO1, dSBO2, SBO, SBO2, CSBO2, SBOp, prod_SBO, vlpadj;
  double CEval1, CEval2, CEval3, CEval4, CEval5, CEval6, CEval7, CEval8;
  double CEpen1, CEpen2, CEpen3;
  double e_ang, e_coa, e_pen;
  double CEcoa1, CEcoa2, CEcoa3, CEcoa4, CEcoa5;
  double Cf7ij, Cf7jk, Cf8j, Cf9j;
  double f7_ij, f7_jk, f8_Dj, f9_Dj;
  double Ctheta_0, theta_0, theta_00, theta, cos_theta, sin_theta;
  double BOA_ij, BOA_jk;
  rvec force, ext_press;

  // Tallying variables
  double eng_tmp, fi_tmp[3], fj_tmp[3], fk_tmp[3];
  double delij[3], delkj[3];

  three_body_header *thbh;
  three_body_parameters *thbp;
  three_body_interaction_data *p_ijk, *p_kji;
  bond_data *pbond_ij, *pbond_jk, *pbond_jt;
  bond_order_data *bo_ij, *bo_jk, *bo_jt;
  reax_list *bonds = (*lists) + BONDS;
  reax_list *thb_intrs =  (*lists) + THREE_BODIES;

  /* global parameters used in these calculations */
  p_val6 = system->reax_param.gp.l[14];
  p_val8 = system->reax_param.gp.l[33];
  p_val9 = system->reax_param.gp.l[16];
  p_val10 = system->reax_param.gp.l[17];
  num_thb_intrs = 0;


  for( j = 0; j < system->N; ++j ) {         // Ray: the first one with system->N
    type_j = system->my_atoms[j].type;
    if (type_j < 0) continue;
    start_j = Start_Index(j, bonds);
    end_j = End_Index(j, bonds);

    p_val3 = system->reax_param.sbp[ type_j ].p_val3;
    p_val5 = system->reax_param.sbp[ type_j ].p_val5;

    SBOp = 0, prod_SBO = 1;
    for( t = start_j; t < end_j; ++t ) {
      bo_jt = &(bonds->select.bond_list[t].bo_data);
      SBOp += (bo_jt->BO_pi + bo_jt->BO_pi2);
      temp = SQR( bo_jt->BO );
      temp *= temp;
      temp *= temp;
      prod_SBO *= exp( -temp );
    }

    if( workspace->vlpex[j] >= 0 ){
      vlpadj = 0;
      dSBO2 = prod_SBO - 1;
    }
    else{
      vlpadj = workspace->nlp[j];
      dSBO2 = (prod_SBO - 1) * (1 - p_val8 * workspace->dDelta_lp[j]);
    }

    SBO = SBOp + (1 - prod_SBO) * (-workspace->Delta_boc[j] - p_val8 * vlpadj);
    dSBO1 = -8 * prod_SBO * ( workspace->Delta_boc[j] + p_val8 * vlpadj );

    if( SBO <= 0 )
      SBO2 = 0, CSBO2 = 0;
    else if( SBO > 0 && SBO <= 1 ) {
        SBO2 = pow( SBO, p_val9 );
        CSBO2 = p_val9 * pow( SBO, p_val9 - 1 );
    }
    else if( SBO > 1 && SBO < 2 ) {
      SBO2 = 2 - pow( 2-SBO, p_val9 );
      CSBO2 = p_val9 * pow( 2 - SBO, p_val9 - 1 );
    }
    else
      SBO2 = 2, CSBO2 = 0;

    expval6 = exp( p_val6 * workspace->Delta_boc[j] );

    for( pi = start_j; pi < end_j; ++pi ) {
      Set_Start_Index( pi, num_thb_intrs, thb_intrs );
      pbond_ij = &(bonds->select.bond_list[pi]);
      bo_ij = &(pbond_ij->bo_data);
      BOA_ij = bo_ij->BO - control->thb_cut;


      if( BOA_ij/*bo_ij->BO*/ > 0.0 &&
          ( j < system->n || pbond_ij->nbr < system->n ) ) {
        i = pbond_ij->nbr;
        type_i = system->my_atoms[i].type;

        for( pk = start_j; pk < pi; ++pk ) {
          start_pk = Start_Index( pk, thb_intrs );
          end_pk = End_Index( pk, thb_intrs );

          for( t = start_pk; t < end_pk; ++t )
            if( thb_intrs->select.three_body_list[t].thb == i ) {
              p_ijk = &(thb_intrs->select.three_body_list[num_thb_intrs] );
              p_kji = &(thb_intrs->select.three_body_list[t]);

              p_ijk->thb = bonds->select.bond_list[pk].nbr;
              p_ijk->pthb  = pk;
              p_ijk->theta = p_kji->theta;
              rvec_Copy( p_ijk->dcos_di, p_kji->dcos_dk );
              rvec_Copy( p_ijk->dcos_dj, p_kji->dcos_dj );
              rvec_Copy( p_ijk->dcos_dk, p_kji->dcos_di );

              ++num_thb_intrs;
              break;
            }
        }

        for( pk = pi+1; pk < end_j; ++pk ) {
          pbond_jk = &(bonds->select.bond_list[pk]);
          bo_jk    = &(pbond_jk->bo_data);
          BOA_jk   = bo_jk->BO - control->thb_cut;
          k        = pbond_jk->nbr;
          type_k   = system->my_atoms[k].type;
          p_ijk    = &( thb_intrs->select.three_body_list[num_thb_intrs] );

          Calculate_Theta( pbond_ij->dvec, pbond_ij->d,
                           pbond_jk->dvec, pbond_jk->d,
                           &theta, &cos_theta );

          Calculate_dCos_Theta( pbond_ij->dvec, pbond_ij->d,
                                pbond_jk->dvec, pbond_jk->d,
                                &(p_ijk->dcos_di), &(p_ijk->dcos_dj),
                                &(p_ijk->dcos_dk) );
          p_ijk->thb = k;
          p_ijk->pthb = pk;
          p_ijk->theta = theta;

          sin_theta = sin( theta );
          if( sin_theta < 1.0e-5 )
            sin_theta = 1.0e-5;

          ++num_thb_intrs;


          if( (j < system->n) && (BOA_jk > 0.0) &&
              (bo_ij->BO > control->thb_cut) &&
              (bo_jk->BO > control->thb_cut) &&
              (bo_ij->BO * bo_jk->BO > control->thb_cutsq) ) {
            thbh = &( system->reax_param.thbp[ type_i ][ type_j ][ type_k ] );

            for( cnt = 0; cnt < thbh->cnt; ++cnt ) {
              if( fabs(thbh->prm[cnt].p_val1) > 0.001 ) {
                thbp = &( thbh->prm[cnt] );

                /* ANGLE ENERGY */
                p_val1 = thbp->p_val1;
                p_val2 = thbp->p_val2;
                p_val4 = thbp->p_val4;
                p_val7 = thbp->p_val7;
                theta_00 = thbp->theta_00;

                exp3ij = exp( -p_val3 * pow( BOA_ij, p_val4 ) );
                f7_ij = 1.0 - exp3ij;
                Cf7ij = p_val3 * p_val4 * pow( BOA_ij, p_val4 - 1.0 ) * exp3ij;

                exp3jk = exp( -p_val3 * pow( BOA_jk, p_val4 ) );
                f7_jk = 1.0 - exp3jk;
                Cf7jk = p_val3 * p_val4 * pow( BOA_jk, p_val4 - 1.0 ) * exp3jk;

                expval7 = exp( -p_val7 * workspace->Delta_boc[j] );
                trm8 = 1.0 + expval6 + expval7;
                f8_Dj = p_val5 - ( (p_val5 - 1.0) * (2.0 + expval6) / trm8 );
                Cf8j = ( (1.0 - p_val5) / SQR(trm8) ) *
                  ( p_val6 * expval6 * trm8 -
                    (2.0 + expval6) * ( p_val6*expval6 - p_val7*expval7 ) );

                theta_0 = 180.0 - theta_00 * (1.0 -
                                              exp(-p_val10 * (2.0 - SBO2)));
                theta_0 = DEG2RAD( theta_0 );

                expval2theta  = exp( -p_val2 * SQR(theta_0 - theta) );
                if( p_val1 >= 0 )
                  expval12theta = p_val1 * (1.0 - expval2theta);
                else // To avoid linear Me-H-Me angles (6/6/06)
                  expval12theta = p_val1 * -expval2theta;

                CEval1 = Cf7ij * f7_jk * f8_Dj * expval12theta;
                CEval2 = Cf7jk * f7_ij * f8_Dj * expval12theta;
                CEval3 = Cf8j  * f7_ij * f7_jk * expval12theta;
                CEval4 = -2.0 * p_val1 * p_val2 * f7_ij * f7_jk * f8_Dj *
                  expval2theta * (theta_0 - theta);

                Ctheta_0 = p_val10 * DEG2RAD(theta_00) *
                  exp( -p_val10 * (2.0 - SBO2) );

                CEval5 = -CEval4 * Ctheta_0 * CSBO2;
                CEval6 = CEval5 * dSBO1;
                CEval7 = CEval5 * dSBO2;
                CEval8 = -CEval4 / sin_theta;

                data->my_en.e_ang += e_ang =
                  f7_ij * f7_jk * f8_Dj * expval12theta;
                /* END ANGLE ENERGY*/

                /* PENALTY ENERGY */
                p_pen1 = thbp->p_pen1;
                p_pen2 = system->reax_param.gp.l[19];
                p_pen3 = system->reax_param.gp.l[20];
                p_pen4 = system->reax_param.gp.l[21];

                exp_pen2ij = exp( -p_pen2 * SQR( BOA_ij - 2.0 ) );
                exp_pen2jk = exp( -p_pen2 * SQR( BOA_jk - 2.0 ) );
                exp_pen3 = exp( -p_pen3 * workspace->Delta[j] );
                exp_pen4 = exp(  p_pen4 * workspace->Delta[j] );
                trm_pen34 = 1.0 + exp_pen3 + exp_pen4;
                f9_Dj = ( 2.0 + exp_pen3 ) / trm_pen34;
                Cf9j = ( -p_pen3 * exp_pen3 * trm_pen34 -
                         (2.0 + exp_pen3) * ( -p_pen3 * exp_pen3 +
                                              p_pen4 * exp_pen4 ) ) /
                  SQR( trm_pen34 );

                data->my_en.e_pen += e_pen =
                  p_pen1 * f9_Dj * exp_pen2ij * exp_pen2jk;

                CEpen1 = e_pen * Cf9j / f9_Dj;
                temp   = -2.0 * p_pen2 * e_pen;
                CEpen2 = temp * (BOA_ij - 2.0);
                CEpen3 = temp * (BOA_jk - 2.0);
                /* END PENALTY ENERGY */

                /* COALITION ENERGY */
                p_coa1 = thbp->p_coa1;
                p_coa2 = system->reax_param.gp.l[2];
                p_coa3 = system->reax_param.gp.l[38];
                p_coa4 = system->reax_param.gp.l[30];

                exp_coa2 = exp( p_coa2 * workspace->Delta_val[j] );
                data->my_en.e_coa += e_coa =
                  p_coa1 / (1. + exp_coa2) *
                  exp( -p_coa3 * SQR(workspace->total_bond_order[i]-BOA_ij) ) *
                  exp( -p_coa3 * SQR(workspace->total_bond_order[k]-BOA_jk) ) *
                  exp( -p_coa4 * SQR(BOA_ij - 1.5) ) *
                  exp( -p_coa4 * SQR(BOA_jk - 1.5) );

                CEcoa1 = -2 * p_coa4 * (BOA_ij - 1.5) * e_coa;
                CEcoa2 = -2 * p_coa4 * (BOA_jk - 1.5) * e_coa;
                CEcoa3 = -p_coa2 * exp_coa2 * e_coa / (1 + exp_coa2);
                CEcoa4 = -2 * p_coa3 *
                  (workspace->total_bond_order[i]-BOA_ij) * e_coa;
                CEcoa5 = -2 * p_coa3 *
                  (workspace->total_bond_order[k]-BOA_jk) * e_coa;
                /* END COALITION ENERGY */

                /* FORCES */
                bo_ij->Cdbo += (CEval1 + CEpen2 + (CEcoa1 - CEcoa4));
                bo_jk->Cdbo += (CEval2 + CEpen3 + (CEcoa2 - CEcoa5));
                workspace->CdDelta[j] += ((CEval3 + CEval7) + CEpen1 + CEcoa3);
                workspace->CdDelta[i] += CEcoa4;
                workspace->CdDelta[k] += CEcoa5;

                for( t = start_j; t < end_j; ++t ) {
                    pbond_jt = &( bonds->select.bond_list[t] );
                    bo_jt = &(pbond_jt->bo_data);
                    temp_bo_jt = bo_jt->BO;
                    temp = CUBE( temp_bo_jt );
                    pBOjt7 = temp * temp * temp_bo_jt;

                    bo_jt->Cdbo += (CEval6 * pBOjt7);
                    bo_jt->Cdbopi += CEval5;
                    bo_jt->Cdbopi2 += CEval5;
                }

                if( control->virial == 0 ) {
                  rvec_ScaledAdd( workspace->f[i], CEval8, p_ijk->dcos_di );
                  rvec_ScaledAdd( workspace->f[j], CEval8, p_ijk->dcos_dj );
                  rvec_ScaledAdd( workspace->f[k], CEval8, p_ijk->dcos_dk );
                }
                else {
                  rvec_Scale( force, CEval8, p_ijk->dcos_di );
                  rvec_Add( workspace->f[i], force );
                  rvec_iMultiply( ext_press, pbond_ij->rel_box, force );
                  rvec_Add( data->my_ext_press, ext_press );

                  rvec_ScaledAdd( workspace->f[j], CEval8, p_ijk->dcos_dj );

                  rvec_Scale( force, CEval8, p_ijk->dcos_dk );
                  rvec_Add( workspace->f[k], force );
                  rvec_iMultiply( ext_press, pbond_jk->rel_box, force );
                  rvec_Add( data->my_ext_press, ext_press );
                }

                /* tally into per-atom virials */
                if( system->pair_ptr->vflag_atom || system->pair_ptr->evflag) {

                  /* Acquire vectors */
                  rvec_ScaledSum( delij, 1., system->my_atoms[i].x,
                                        -1., system->my_atoms[j].x );
                  rvec_ScaledSum( delkj, 1., system->my_atoms[k].x,
                                        -1., system->my_atoms[j].x );

                  rvec_Scale( fi_tmp, -CEval8, p_ijk->dcos_di );
                  rvec_Scale( fj_tmp, -CEval8, p_ijk->dcos_dj );
                  rvec_Scale( fk_tmp, -CEval8, p_ijk->dcos_dk );

                  eng_tmp = e_ang + e_pen + e_coa;

                  if( system->pair_ptr->evflag)
                          system->pair_ptr->ev_tally(j,j,system->N,1,eng_tmp,0.0,0.0,0.0,0.0,0.0);
                  if( system->pair_ptr->vflag_atom)
                          system->pair_ptr->v_tally3(i,j,k,fi_tmp,fk_tmp,delij,delkj);
                }
              }
            }
          }
        }
      }

      Set_End_Index(pi, num_thb_intrs, thb_intrs );
    }
  }

  if( num_thb_intrs >= thb_intrs->num_intrs * DANGER_ZONE ) {
    workspace->realloc.num_3body = num_thb_intrs;
    if( num_thb_intrs > thb_intrs->num_intrs ) {
      fprintf( stderr, "step%d-ran out of space on angle_list: top=%d, max=%d",
               data->step, num_thb_intrs, thb_intrs->num_intrs );
      MPI_Abort( MPI_COMM_WORLD, INSUFFICIENT_MEMORY );
    }
  }

}
Exemple #11
0
void Init_Forces_Tab(reax_system *system, control_params *control,
		simulation_data *data, static_storage *workspace, list **lists,
		output_controls *out_control) {
	int i, j, pj;
	int start_i, end_i;
	int type_i, type_j;
	int Htop, btop_i, btop_j, num_bonds, num_hbonds;
	int tmin, tmax, r;
	int ihb, jhb, ihb_top, jhb_top;
	int flag;
	real r_ij, r2, self_coef;
	real val, dif, base;
	real C12, C34, C56;
	real Cln_BOp_s, Cln_BOp_pi, Cln_BOp_pi2;
	real BO, BO_s, BO_pi, BO_pi2;
	real p_boc1, p_boc2;
	sparse_matrix *H;
	list *far_nbrs, *bonds, *hbonds;
	single_body_parameters *sbp_i, *sbp_j;
	two_body_parameters *twbp;
	far_neighbor_data *nbr_pj;
	LR_lookup_table *t;
	reax_atom *atom_i, *atom_j;
	bond_data *ibond, *jbond;
	bond_order_data *bo_ij, *bo_ji;

	far_nbrs = *lists + FAR_NBRS;
	bonds = *lists + BONDS;
	hbonds = *lists + HBONDS;

	H = workspace->H;
	Htop = 0;
	num_bonds = 0;
	num_hbonds = 0;
	btop_i = btop_j = 0;
	p_boc1 = system->reaxprm.gp.l[0];
	p_boc2 = system->reaxprm.gp.l[1];

	for (i = 0; i < system->N; ++i) {
		atom_i = &(system->atoms[i]);
		type_i = atom_i->type;
		start_i = Start_Index(i, far_nbrs);
		end_i = End_Index(i, far_nbrs);
		H->start[i] = Htop;
		btop_i = End_Index(i, bonds);
		sbp_i = &(system->reaxprm.sbp[type_i]);
		ihb = ihb_top = -1;
		if (control->hb_cut > 0 && (ihb = sbp_i->p_hbond) == 1)
			ihb_top = End_Index(workspace->hbond_index[i], hbonds);

		for (pj = start_i; pj < end_i; ++pj) {
			nbr_pj = &(far_nbrs->select.far_nbr_list[pj]);
			j = nbr_pj->nbr;
			atom_j = &(system->atoms[j]);

			flag = 0;
			if ((data->step - data->prev_steps) % control->reneighbor == 0) {
				if (nbr_pj->d <= control->r_cut)
					flag = 1;
				else
					flag = 0;
			} else if ((nbr_pj->d = Sq_Distance_on_T3(atom_i->x, atom_j->x,
					&(system->box), nbr_pj->dvec)) <= SQR(control->r_cut)) {
				nbr_pj->d = sqrt(nbr_pj->d);
				flag = 1;
			}

			if (flag) {
				type_j = system->atoms[j].type;
				r_ij = nbr_pj->d;
				sbp_j = &(system->reaxprm.sbp[type_j]);
				twbp = &(system->reaxprm.tbp[type_i][type_j]);
				self_coef = (i == j) ? 0.5 : 1.0;
				tmin = MIN( type_i, type_j );
				tmax = MAX( type_i, type_j );
				t = &(LR[tmin][tmax]);

				/* cubic spline interpolation */
				r = (int) (r_ij * t->inv_dx);
				if (r == 0)
					++r;
				base = (real) (r + 1) * t->dx;
				dif = r_ij - base;
				val = ((t->ele[r].d * dif + t->ele[r].c) * dif + t->ele[r].b)
						* dif + t->ele[r].a;
				val *= EV_to_KCALpMOL / C_ele;

				H->entries[Htop].j = j;
				H->entries[Htop].val = self_coef * val;
				++Htop;

				/* hydrogen bond lists */
				if (control->hb_cut > 0 && (ihb == 1 || ihb == 2) && nbr_pj->d
						<= control->hb_cut) {
					// fprintf( stderr, "%d %d\n", atom1, atom2 );
					jhb = sbp_j->p_hbond;
					if (ihb == 1 && jhb == 2) {
						hbonds->select.hbond_list[ihb_top].nbr = j;
						hbonds->select.hbond_list[ihb_top].scl = 1;
						hbonds->select.hbond_list[ihb_top].ptr = nbr_pj;
						++ihb_top;
						++num_hbonds;
					} else if (ihb == 2 && jhb == 1) {
						jhb_top = End_Index(workspace->hbond_index[j], hbonds);
						hbonds->select.hbond_list[jhb_top].nbr = i;
						hbonds->select.hbond_list[jhb_top].scl = -1;
						hbonds->select.hbond_list[jhb_top].ptr = nbr_pj;
						Set_End_Index(workspace->hbond_index[j], jhb_top + 1,
								hbonds);
						++num_hbonds;
					}
				}

				/* uncorrected bond orders */
				if (far_nbrs->select.far_nbr_list[pj].d <= control->nbr_cut) {
					r2 = SQR(r_ij);

					if (sbp_i->r_s > 0.0 && sbp_j->r_s > 0.0) {
						C12 = twbp->p_bo1 * POW(r_ij / twbp->r_s, twbp->p_bo2);
						BO_s = (1.0 + control->bo_cut) * EXP(C12);
					} else
						BO_s = C12 = 0.0;

					if (sbp_i->r_pi > 0.0 && sbp_j->r_pi > 0.0) {
						C34 = twbp->p_bo3 * POW(r_ij / twbp->r_p, twbp->p_bo4);
						BO_pi = EXP(C34);
					} else
						BO_pi = C34 = 0.0;

					if (sbp_i->r_pi_pi > 0.0 && sbp_j->r_pi_pi > 0.0) {
						C56 = twbp->p_bo5 * POW(r_ij / twbp->r_pp, twbp->p_bo6);
						BO_pi2 = EXP(C56);
					} else
						BO_pi2 = C56 = 0.0;

					/* Initially BO values are the uncorrected ones, page 1 */
					BO = BO_s + BO_pi + BO_pi2;

					if (BO >= control->bo_cut) {
						num_bonds += 2;
						/****** bonds i-j and j-i ******/
						ibond = &(bonds->select.bond_list[btop_i]);
						btop_j = End_Index(j, bonds);
						jbond = &(bonds->select.bond_list[btop_j]);

						ibond->nbr = j;
						jbond->nbr = i;
						ibond->d = r_ij;
						jbond->d = r_ij;
						rvec_Copy(ibond->dvec, nbr_pj->dvec);
						rvec_Scale(jbond->dvec, -1, nbr_pj->dvec);
						ivec_Copy(ibond->rel_box, nbr_pj->rel_box);
						ivec_Scale(jbond->rel_box, -1, nbr_pj->rel_box);
						ibond->dbond_index = btop_i;
						jbond->dbond_index = btop_i;
						ibond->sym_index = btop_j;
						jbond->sym_index = btop_i;
						++btop_i;
						Set_End_Index(j, btop_j + 1, bonds);

						bo_ij = &(ibond->bo_data);
						bo_ji = &(jbond->bo_data);
						bo_ji->BO = bo_ij->BO = BO;
						bo_ji->BO_s = bo_ij->BO_s = BO_s;
						bo_ji->BO_pi = bo_ij->BO_pi = BO_pi;
						bo_ji->BO_pi2 = bo_ij->BO_pi2 = BO_pi2;

						/* Bond Order page2-3, derivative of total bond order prime */
						Cln_BOp_s = twbp->p_bo2 * C12 / r2;
						Cln_BOp_pi = twbp->p_bo4 * C34 / r2;
						Cln_BOp_pi2 = twbp->p_bo6 * C56 / r2;

						/* Only dln_BOp_xx wrt. dr_i is stored here, note that
						 dln_BOp_xx/dr_i = -dln_BOp_xx/dr_j and all others are 0 */
						rvec_Scale(bo_ij->dln_BOp_s, -bo_ij->BO_s * Cln_BOp_s,
								ibond->dvec);
						rvec_Scale(bo_ij->dln_BOp_pi, -bo_ij->BO_pi
								* Cln_BOp_pi, ibond->dvec);
						rvec_Scale(bo_ij->dln_BOp_pi2, -bo_ij->BO_pi2
								* Cln_BOp_pi2, ibond->dvec);
						rvec_Scale(bo_ji->dln_BOp_s, -1., bo_ij->dln_BOp_s);
						rvec_Scale(bo_ji->dln_BOp_pi, -1., bo_ij->dln_BOp_pi);
						rvec_Scale(bo_ji->dln_BOp_pi2, -1., bo_ij->dln_BOp_pi2);

						/* Only dBOp wrt. dr_i is stored here, note that
						 dBOp/dr_i = -dBOp/dr_j and all others are 0 */
						rvec_Scale(bo_ij->dBOp, -(bo_ij->BO_s * Cln_BOp_s
								+ bo_ij->BO_pi * Cln_BOp_pi + bo_ij->BO_pi2
								* Cln_BOp_pi2), ibond->dvec);
						rvec_Scale(bo_ji->dBOp, -1., bo_ij->dBOp);

						rvec_Add(workspace->dDeltap_self[i], bo_ij->dBOp);
						rvec_Add(workspace->dDeltap_self[j], bo_ji->dBOp);

						bo_ij->BO_s -= control->bo_cut;
						bo_ij->BO -= control->bo_cut;
						bo_ji->BO_s -= control->bo_cut;
						bo_ji->BO -= control->bo_cut;
						workspace->total_bond_order[i] += bo_ij->BO; //currently total_BOp
						workspace->total_bond_order[j] += bo_ji->BO; //currently total_BOp
						bo_ij->Cdbo = bo_ij->Cdbopi = bo_ij->Cdbopi2 = 0.0;
						bo_ji->Cdbo = bo_ji->Cdbopi = bo_ji->Cdbopi2 = 0.0;

						Set_End_Index(j, btop_j + 1, bonds);
					}
				}
			}
		}

		H->entries[Htop].j = i;
		H->entries[Htop].val = system->reaxprm.sbp[type_i].eta;
		++Htop;

		Set_End_Index(i, btop_i, bonds);
		if (ihb == 1)
			Set_End_Index(workspace->hbond_index[i], ihb_top, hbonds);
	}

	// mark the end of j list
	H->start[i] = Htop;
	/* validate lists - decide if reallocation is required! */
	Validate_Lists(workspace, lists, data->step, system->N, H->m, Htop,
			num_bonds, num_hbonds);

#if defined(DEBUG_FOCUS)
	fprintf( stderr, "step%d: Htop = %d, num_bonds = %d, num_hbonds = %d\n",
			data->step, Htop, num_bonds, num_hbonds );
	//Print_Bonds( system, bonds, "sbonds.out" );
	//Print_Bond_List2( system, bonds, "sbonds.out" );
	//Print_Sparse_Matrix2( H, "H.out" );
#endif
}
Exemple #12
0
void Tabulated_vdW_Coulomb_Energy( reax_system *system,control_params *control, 
				   simulation_data *data, storage *workspace, 
				   reax_list **lists, 
				   output_controls *out_control )
{
  int i, j, pj, r, natoms, steps, update_freq, update_energies;
  int type_i, type_j, tmin, tmax;
  int start_i, end_i, orig_i, orig_j;
  real r_ij, base, dif;
  real e_vdW, e_ele;
  real CEvd, CEclmb;
  rvec temp, ext_press;
  far_neighbor_data *nbr_pj;
  reax_list *far_nbrs;
  LR_lookup_table *t;

  natoms = system->n;
  far_nbrs = (*lists) + FAR_NBRS;
  steps = data->step - data->prev_steps;
  update_freq = out_control->energy_update_freq;
  update_energies = update_freq > 0 && steps % update_freq == 0;
  e_ele = e_vdW = 0;

  for( i = 0; i < natoms; ++i ) {
    type_i  = system->my_atoms[i].type;
    start_i = Start_Index(i,far_nbrs);
    end_i   = End_Index(i,far_nbrs);
    orig_i  = system->my_atoms[i].orig_id;

    for( pj = start_i; pj < end_i; ++pj ) {
      nbr_pj = &(far_nbrs->select.far_nbr_list[pj]);
      j = nbr_pj->nbr;
      orig_j  = system->my_atoms[j].orig_id;

      if( nbr_pj->d <= control->nonb_cut && (j < natoms || orig_i < orig_j) ) {
      j = nbr_pj->nbr;
      type_j = system->my_atoms[j].type;
      r_ij   = nbr_pj->d;
      tmin  = MIN( type_i, type_j );
      tmax  = MAX( type_i, type_j );
      t = &( LR[tmin][tmax] ); 
      //t = &( LR[type_i][type_j] ); 

      /* Cubic Spline Interpolation */
      r = (int)(r_ij * t->inv_dx);
      if( r == 0 )  ++r;
      base = (real)(r+1) * t->dx;
      dif = r_ij - base;
      //fprintf(stderr, "r: %f, i: %d, base: %f, dif: %f\n", r, i, base, dif);
      
      if( update_energies ) {
	e_vdW = ((t->vdW[r].d*dif + t->vdW[r].c)*dif + t->vdW[r].b)*dif + 
	  t->vdW[r].a;
	
	e_ele = ((t->ele[r].d*dif + t->ele[r].c)*dif + t->ele[r].b)*dif + 
	  t->ele[r].a;
	e_ele *= system->my_atoms[i].q * system->my_atoms[j].q;
	
	data->my_en.e_vdW += e_vdW;
	data->my_en.e_ele += e_ele;
      }	
      
      CEvd = ((t->CEvd[r].d*dif + t->CEvd[r].c)*dif + t->CEvd[r].b)*dif + 
	t->CEvd[r].a;
            
      CEclmb = ((t->CEclmb[r].d*dif+t->CEclmb[r].c)*dif+t->CEclmb[r].b)*dif + 
	t->CEclmb[r].a;
      CEclmb *= system->my_atoms[i].q * system->my_atoms[j].q;
      
      if( control->virial == 0 ) {
	rvec_ScaledAdd( workspace->f[i], -(CEvd + CEclmb), nbr_pj->dvec );
	rvec_ScaledAdd( workspace->f[j], +(CEvd + CEclmb), nbr_pj->dvec );
      }
      else { // NPT, iNPT or sNPT
	/* for pressure coupling, terms not related to bond order derivatives
	   are added directly into pressure vector/tensor */
	rvec_Scale( temp, CEvd + CEclmb, nbr_pj->dvec );
	      
	rvec_ScaledAdd( workspace->f[i], -1., temp );
	rvec_Add( workspace->f[j], temp );
	      
	rvec_iMultiply( ext_press, nbr_pj->rel_box, temp );
	rvec_Add( data->my_ext_press, ext_press );
      }

#ifdef TEST_ENERGY
      //fprintf( out_control->evdw, "%6d%6d%24.15e%24.15e%24.15e\n",
      fprintf( out_control->evdw, "%6d%6d%12.4f%12.4f%12.4f\n",
	       system->my_atoms[i].orig_id, system->my_atoms[j].orig_id, 
	       r_ij, e_vdW, data->my_en.e_vdW );
      //fprintf(out_control->ecou,"%6d%6d%24.15e%24.15e%24.15e%24.15e%24.15e\n",
      fprintf( out_control->ecou, "%6d%6d%12.4f%12.4f%12.4f%12.4f%12.4f\n",
	       system->my_atoms[i].orig_id, system->my_atoms[j].orig_id,
	       r_ij, system->my_atoms[i].q, system->my_atoms[j].q, 
	       e_ele, data->my_en.e_ele );
#endif
#ifdef TEST_FORCES
      rvec_ScaledAdd( workspace->f_vdw[i], -CEvd, nbr_pj->dvec );
      rvec_ScaledAdd( workspace->f_vdw[j], +CEvd, nbr_pj->dvec );
      rvec_ScaledAdd( workspace->f_ele[i], -CEclmb, nbr_pj->dvec );
      rvec_ScaledAdd( workspace->f_ele[j], +CEclmb, nbr_pj->dvec );
#endif
      }
    }
  }

  Compute_Polarization_Energy( system, data );
}
void BO( reax_system *system, control_params *control, simulation_data *data,
         storage *workspace, reax_list **lists, output_controls *out_control )
{
  int i, j, pj, type_i, type_j;
  int start_i, end_i, sym_index;
  double val_i, Deltap_i, Deltap_boc_i;
  double val_j, Deltap_j, Deltap_boc_j;
  double f1, f2, f3, f4, f5, f4f5, exp_f4, exp_f5;
  double exp_p1i,        exp_p2i, exp_p1j, exp_p2j;
  double temp, u1_ij, u1_ji, Cf1A_ij, Cf1B_ij, Cf1_ij, Cf1_ji;
  double Cf45_ij, Cf45_ji, p_lp1; //u_ij, u_ji
  double A0_ij, A1_ij, A2_ij, A2_ji, A3_ij, A3_ji;
  double explp1, p_boc1, p_boc2;
  single_body_parameters *sbp_i, *sbp_j;
  two_body_parameters *twbp;
  bond_order_data *bo_ij, *bo_ji;
  reax_list *bonds = (*lists) + BONDS;

  p_boc1 = system->reax_param.gp.l[0];
  p_boc2 = system->reax_param.gp.l[1];

 /* Calculate Deltaprime, Deltaprime_boc values */
  for( i = 0; i < system->N; ++i ) {
    type_i = system->my_atoms[i].type;
    if (type_i < 0) continue;
    sbp_i = &(system->reax_param.sbp[type_i]);
    workspace->Deltap[i] = workspace->total_bond_order[i] - sbp_i->valency;
    workspace->Deltap_boc[i] =
      workspace->total_bond_order[i] - sbp_i->valency_val;

    workspace->total_bond_order[i] = 0;
  }

  /* Corrected Bond Order calculations */
  for( i = 0; i < system->N; ++i ) {
    type_i = system->my_atoms[i].type;
    if (type_i < 0) continue;
    sbp_i = &(system->reax_param.sbp[type_i]);
    val_i = sbp_i->valency;
    Deltap_i = workspace->Deltap[i];
    Deltap_boc_i = workspace->Deltap_boc[i];
    start_i = Start_Index(i, bonds);
    end_i = End_Index(i, bonds);

    for( pj = start_i; pj < end_i; ++pj ) {
      j = bonds->select.bond_list[pj].nbr;
      type_j = system->my_atoms[j].type;
      if (type_j < 0) continue;
      bo_ij = &( bonds->select.bond_list[pj].bo_data );
      // fprintf( stderr, "\tj:%d - ubo: %8.3f\n", j+1, bo_ij->BO );

      if( i < j || workspace->bond_mark[j] > 3 ) {
        twbp = &( system->reax_param.tbp[type_i][type_j] );

        if( twbp->ovc < 0.001 && twbp->v13cor < 0.001 ) {
          bo_ij->C1dbo = 1.000000;
          bo_ij->C2dbo = 0.000000;
          bo_ij->C3dbo = 0.000000;

          bo_ij->C1dbopi = bo_ij->BO_pi;
          bo_ij->C2dbopi = 0.000000;
          bo_ij->C3dbopi = 0.000000;
          bo_ij->C4dbopi = 0.000000;

          bo_ij->C1dbopi2 = bo_ij->BO_pi2;
          bo_ij->C2dbopi2 = 0.000000;
          bo_ij->C3dbopi2 = 0.000000;
          bo_ij->C4dbopi2 = 0.000000;

        }
        else {
          val_j = system->reax_param.sbp[type_j].valency;
          Deltap_j = workspace->Deltap[j];
          Deltap_boc_j = workspace->Deltap_boc[j];

          /* on page 1 */
          if( twbp->ovc >= 0.001 ) {
            /* Correction for overcoordination */
            exp_p1i = exp( -p_boc1 * Deltap_i );
            exp_p2i = exp( -p_boc2 * Deltap_i );
            exp_p1j = exp( -p_boc1 * Deltap_j );
            exp_p2j = exp( -p_boc2 * Deltap_j );

            f2 = exp_p1i + exp_p1j;
            f3 = -1.0 / p_boc2 * log( 0.5 * ( exp_p2i  + exp_p2j ) );
            f1 = 0.5 * ( ( val_i + f2 )/( val_i + f2 + f3 ) +
                         ( val_j + f2 )/( val_j + f2 + f3 ) );

            temp = f2 + f3;
            u1_ij = val_i + temp;
            u1_ji = val_j + temp;
            Cf1A_ij = 0.5 * f3 * (1.0 / SQR( u1_ij ) +
                                  1.0 / SQR( u1_ji ));
            Cf1B_ij = -0.5 * (( u1_ij - f3 ) / SQR( u1_ij ) +
                              ( u1_ji - f3 ) / SQR( u1_ji ));

            Cf1_ij = 0.50 * ( -p_boc1 * exp_p1i / u1_ij -
                              ((val_i+f2) / SQR(u1_ij)) *
                              ( -p_boc1 * exp_p1i +
                                exp_p2i / ( exp_p2i + exp_p2j ) ) +
                              -p_boc1 * exp_p1i / u1_ji -
                              ((val_j+f2) / SQR(u1_ji)) *
                              ( -p_boc1 * exp_p1i +
                                exp_p2i / ( exp_p2i + exp_p2j ) ));


            Cf1_ji = -Cf1A_ij * p_boc1 * exp_p1j +
              Cf1B_ij * exp_p2j / ( exp_p2i + exp_p2j );

          }
          else {
            /* No overcoordination correction! */
            f1 = 1.0;
            Cf1_ij = Cf1_ji = 0.0;
          }

          if( twbp->v13cor >= 0.001 ) {
            /* Correction for 1-3 bond orders */
            exp_f4 =exp(-(twbp->p_boc4 * SQR( bo_ij->BO ) -
                          Deltap_boc_i) * twbp->p_boc3 + twbp->p_boc5);
            exp_f5 =exp(-(twbp->p_boc4 * SQR( bo_ij->BO ) -
                          Deltap_boc_j) * twbp->p_boc3 + twbp->p_boc5);

            f4 = 1. / (1. + exp_f4);
            f5 = 1. / (1. + exp_f5);
            f4f5 = f4 * f5;

            /* Bond Order pages 8-9, derivative of f4 and f5 */
            Cf45_ij = -f4 * exp_f4;
            Cf45_ji = -f5 * exp_f5;
          }
          else {
            f4 = f5 = f4f5 = 1.0;
            Cf45_ij = Cf45_ji = 0.0;
          }

          /* Bond Order page 10, derivative of total bond order */
          A0_ij = f1 * f4f5;
          A1_ij = -2 * twbp->p_boc3 * twbp->p_boc4 * bo_ij->BO *
            (Cf45_ij + Cf45_ji);
          A2_ij = Cf1_ij / f1 + twbp->p_boc3 * Cf45_ij;
          A2_ji = Cf1_ji / f1 + twbp->p_boc3 * Cf45_ji;
          A3_ij = A2_ij + Cf1_ij / f1;
          A3_ji = A2_ji + Cf1_ji / f1;

          /* find corrected bond orders and their derivative coef */
          bo_ij->BO    = bo_ij->BO    * A0_ij;
          bo_ij->BO_pi = bo_ij->BO_pi * A0_ij *f1;
          bo_ij->BO_pi2= bo_ij->BO_pi2* A0_ij *f1;
          bo_ij->BO_s  = bo_ij->BO - ( bo_ij->BO_pi + bo_ij->BO_pi2 );

          bo_ij->C1dbo = A0_ij + bo_ij->BO * A1_ij;
          bo_ij->C2dbo = bo_ij->BO * A2_ij;
          bo_ij->C3dbo = bo_ij->BO * A2_ji;

          bo_ij->C1dbopi = f1*f1*f4*f5;
          bo_ij->C2dbopi = bo_ij->BO_pi * A1_ij;
          bo_ij->C3dbopi = bo_ij->BO_pi * A3_ij;
          bo_ij->C4dbopi = bo_ij->BO_pi * A3_ji;

          bo_ij->C1dbopi2 = f1*f1*f4*f5;
          bo_ij->C2dbopi2 = bo_ij->BO_pi2 * A1_ij;
          bo_ij->C3dbopi2 = bo_ij->BO_pi2 * A3_ij;
          bo_ij->C4dbopi2 = bo_ij->BO_pi2 * A3_ji;

        }

        /* neglect bonds that are < 1e-10 */
        if( bo_ij->BO < 1e-10 )
          bo_ij->BO = 0.0;
        if( bo_ij->BO_s < 1e-10 )
          bo_ij->BO_s = 0.0;
        if( bo_ij->BO_pi < 1e-10 )
          bo_ij->BO_pi = 0.0;
        if( bo_ij->BO_pi2 < 1e-10 )
          bo_ij->BO_pi2 = 0.0;

        workspace->total_bond_order[i] += bo_ij->BO; //now keeps total_BO

      }
      else {
        /* We only need to update bond orders from bo_ji
           everything else is set in uncorrected_bo calculations */
        sym_index = bonds->select.bond_list[pj].sym_index;
        bo_ji = &(bonds->select.bond_list[ sym_index ].bo_data);
        bo_ij->BO = bo_ji->BO;
        bo_ij->BO_s = bo_ji->BO_s;
        bo_ij->BO_pi = bo_ji->BO_pi;
        bo_ij->BO_pi2 = bo_ji->BO_pi2;

        workspace->total_bond_order[i] += bo_ij->BO;// now keeps total_BO
      }
    }

  }

  p_lp1 = system->reax_param.gp.l[15];
  for( j = 0; j < system->N; ++j ){
    type_j = system->my_atoms[j].type;
    if (type_j < 0) continue;
    sbp_j = &(system->reax_param.sbp[ type_j ]);

    workspace->Delta[j] = workspace->total_bond_order[j] - sbp_j->valency;
    workspace->Delta_e[j] = workspace->total_bond_order[j] - sbp_j->valency_e;
    workspace->Delta_boc[j] = workspace->total_bond_order[j] -
      sbp_j->valency_boc;
    workspace->Delta_val[j] = workspace->total_bond_order[j] -
      sbp_j->valency_val;

    workspace->vlpex[j] = workspace->Delta_e[j] -
      2.0 * (int)(workspace->Delta_e[j]/2.0);
    explp1 = exp(-p_lp1 * SQR(2.0 + workspace->vlpex[j]));
    workspace->nlp[j] = explp1 - (int)(workspace->Delta_e[j] / 2.0);
    workspace->Delta_lp[j] = sbp_j->nlp_opt - workspace->nlp[j];
    workspace->Clp[j] = 2.0 * p_lp1 * explp1 * (2.0 + workspace->vlpex[j]);
    workspace->dDelta_lp[j] = workspace->Clp[j];

    if( sbp_j->mass > 21.0 ) {
      workspace->nlp_temp[j] = 0.5 * (sbp_j->valency_e - sbp_j->valency);
      workspace->Delta_lp_temp[j] = sbp_j->nlp_opt - workspace->nlp_temp[j];
      workspace->dDelta_lp_temp[j] = 0.;
    }
    else {
      workspace->nlp_temp[j] = workspace->nlp[j];
      workspace->Delta_lp_temp[j] = sbp_j->nlp_opt - workspace->nlp_temp[j];
      workspace->dDelta_lp_temp[j] = workspace->Clp[j];
    }

  }

}
void Hydrogen_Bonds( reax_system *system, control_params *control,
                     simulation_data *data, storage *workspace,
                     reax_list **lists, output_controls *out_control )
{
  int  i, j, k, pi, pk;
  int  type_i, type_j, type_k;
  int  start_j, end_j, hb_start_j, hb_end_j;
  int  hblist[MAX_BONDS];
  int  itr, top;
  int  num_hb_intrs = 0;
  ivec rel_jk;
  real r_ij, r_jk, theta, cos_theta, sin_xhz4, cos_xhz1, sin_theta2;
  real e_hb, exp_hb2, exp_hb3, CEhb1, CEhb2, CEhb3;
  rvec dcos_theta_di, dcos_theta_dj, dcos_theta_dk;
  rvec dvec_jk, force, ext_press;
  // rtensor temp_rtensor, total_rtensor;
  hbond_parameters *hbp;
  bond_order_data *bo_ij;
  bond_data *pbond_ij;
  far_neighbor_data *nbr_jk;
  reax_list *bonds, *hbonds;
  bond_data *bond_list;
  hbond_data *hbond_list;

  // tally variables
  real fi_tmp[3], fk_tmp[3], delij[3], delkj[3];

  bonds = (*lists) + BONDS;
  bond_list = bonds->select.bond_list;
  hbonds = (*lists) + HBONDS;
  hbond_list = hbonds->select.hbond_list;

  /* loops below discover the Hydrogen bonds between i-j-k triplets.
     here j is H atom and there has to be some bond between i and j.
     Hydrogen bond is between j and k.
     so in this function i->X, j->H, k->Z when we map
     variables onto the ones in the handout.*/
  for( j = 0; j < system->n; ++j )
    /* j has to be of type H */
    if( system->reax_param.sbp[system->my_atoms[j].type].p_hbond == 1 ) {
      /*set j's variables */
      type_j     = system->my_atoms[j].type;
      start_j    = Start_Index(j, bonds);
      end_j      = End_Index(j, bonds);
      hb_start_j = Start_Index( system->my_atoms[j].Hindex, hbonds );
      hb_end_j   = End_Index( system->my_atoms[j].Hindex, hbonds );

      top = 0;
      for( pi = start_j; pi < end_j; ++pi )  {
        pbond_ij = &( bond_list[pi] );
        i = pbond_ij->nbr;
        bo_ij = &(pbond_ij->bo_data);
        type_i = system->my_atoms[i].type;

        if( system->reax_param.sbp[type_i].p_hbond == 2 &&
            bo_ij->BO >= HB_THRESHOLD )
          hblist[top++] = pi;
      }

      // fprintf( stderr, "j: %d, top: %d, hb_start_j: %d, hb_end_j:%d\n",
      //          j, top, hb_start_j, hb_end_j );

      for( pk = hb_start_j; pk < hb_end_j; ++pk ) {
        /* set k's varibles */
        k = hbond_list[pk].nbr;
        type_k = system->my_atoms[k].type;
        nbr_jk = hbond_list[pk].ptr;
        r_jk = nbr_jk->d;
        rvec_Scale( dvec_jk, hbond_list[pk].scl, nbr_jk->dvec );

        for( itr = 0; itr < top; ++itr ) {
          pi = hblist[itr];
          pbond_ij = &( bonds->select.bond_list[pi] );
          i = pbond_ij->nbr;

          if( system->my_atoms[i].orig_id != system->my_atoms[k].orig_id ) {
            bo_ij = &(pbond_ij->bo_data);
            type_i = system->my_atoms[i].type;
            r_ij = pbond_ij->d;
            hbp = &(system->reax_param.hbp[ type_i ][ type_j ][ type_k ]);
            ++num_hb_intrs;

            Calculate_Theta( pbond_ij->dvec, pbond_ij->d, dvec_jk, r_jk,
                             &theta, &cos_theta );
            /* the derivative of cos(theta) */
            Calculate_dCos_Theta( pbond_ij->dvec, pbond_ij->d, dvec_jk, r_jk,
                                  &dcos_theta_di, &dcos_theta_dj,
                                  &dcos_theta_dk );

            /* hyrogen bond energy*/
            sin_theta2 = sin( theta/2.0 );
            sin_xhz4 = SQR(sin_theta2);
            sin_xhz4 *= sin_xhz4;
            cos_xhz1 = ( 1.0 - cos_theta );
            exp_hb2 = exp( -hbp->p_hb2 * bo_ij->BO );
            exp_hb3 = exp( -hbp->p_hb3 * ( hbp->r0_hb / r_jk +
                                           r_jk / hbp->r0_hb - 2.0 ) );

            data->my_en.e_hb += e_hb =
              hbp->p_hb1 * (1.0 - exp_hb2) * exp_hb3 * sin_xhz4;

            CEhb1 = hbp->p_hb1 * hbp->p_hb2 * exp_hb2 * exp_hb3 * sin_xhz4;
            CEhb2 = -hbp->p_hb1/2.0 * (1.0 - exp_hb2) * exp_hb3 * cos_xhz1;
            CEhb3 = -hbp->p_hb3 *
              (-hbp->r0_hb / SQR(r_jk) + 1.0 / hbp->r0_hb) * e_hb;

            /*fprintf( stdout,
              "%6d%6d%6d%12.6f%12.6f%12.6f%12.6f%12.6f%12.6f%12.6f%12.6f%12.6f\n",
              system->my_atoms[i].orig_id, system->my_atoms[j].orig_id,
              system->my_atoms[k].orig_id,
              r_jk, theta, hbp->p_hb1, exp_hb2, hbp->p_hb3, hbp->r0_hb,
              exp_hb3, sin_xhz4, e_hb ); */

            /* hydrogen bond forces */
            bo_ij->Cdbo += CEhb1; // dbo term

            if( control->virial == 0 ) {
              // dcos terms
              rvec_ScaledAdd( workspace->f[i], +CEhb2, dcos_theta_di );
              rvec_ScaledAdd( workspace->f[j], +CEhb2, dcos_theta_dj );
              rvec_ScaledAdd( workspace->f[k], +CEhb2, dcos_theta_dk );
              // dr terms
              rvec_ScaledAdd( workspace->f[j], -CEhb3/r_jk, dvec_jk );
              rvec_ScaledAdd( workspace->f[k], +CEhb3/r_jk, dvec_jk );
            }
            else {
              /* for pressure coupling, terms that are not related to bond order
                 derivatives are added directly into pressure vector/tensor */
              rvec_Scale( force, +CEhb2, dcos_theta_di ); // dcos terms
              rvec_Add( workspace->f[i], force );
              rvec_iMultiply( ext_press, pbond_ij->rel_box, force );
              rvec_ScaledAdd( data->my_ext_press, 1.0, ext_press );

              rvec_ScaledAdd( workspace->f[j], +CEhb2, dcos_theta_dj );

              ivec_Scale( rel_jk, hbond_list[pk].scl, nbr_jk->rel_box );
              rvec_Scale( force, +CEhb2, dcos_theta_dk );
              rvec_Add( workspace->f[k], force );
              rvec_iMultiply( ext_press, rel_jk, force );
              rvec_ScaledAdd( data->my_ext_press, 1.0, ext_press );
              // dr terms
              rvec_ScaledAdd( workspace->f[j], -CEhb3/r_jk, dvec_jk );

              rvec_Scale( force, CEhb3/r_jk, dvec_jk );
              rvec_Add( workspace->f[k], force );
              rvec_iMultiply( ext_press, rel_jk, force );
              rvec_ScaledAdd( data->my_ext_press, 1.0, ext_press );
            }

            /* tally into per-atom virials */
            if (system->pair_ptr->vflag_atom || system->pair_ptr->evflag) {
              rvec_ScaledSum( delij, 1., system->my_atoms[i].x,
                                    -1., system->my_atoms[j].x );
              rvec_ScaledSum( delkj, 1., system->my_atoms[k].x,
                                     -1., system->my_atoms[j].x );

              rvec_Scale(fi_tmp, CEhb2, dcos_theta_di);
              rvec_Scale(fk_tmp, CEhb2, dcos_theta_dk);
              rvec_ScaledAdd(fk_tmp, CEhb3/r_jk, dvec_jk);

              system->pair_ptr->ev_tally3(i,j,k,e_hb,0.0,fi_tmp,fk_tmp,delij,delkj);
            }

#ifdef TEST_ENERGY
            /* fprintf( out_control->ehb,
               "%24.15e%24.15e%24.15e\n%24.15e%24.15e%24.15e\n%24.15e%24.15e%24.15e\n",
               dcos_theta_di[0], dcos_theta_di[1], dcos_theta_di[2],
               dcos_theta_dj[0], dcos_theta_dj[1], dcos_theta_dj[2],
               dcos_theta_dk[0], dcos_theta_dk[1], dcos_theta_dk[2]);
               fprintf( out_control->ehb, "%24.15e%24.15e%24.15e\n",
               CEhb1, CEhb2, CEhb3 ); */
            fprintf( out_control->ehb,
                     //"%6d%6d%6d%24.15e%24.15e%24.15e%24.15e%24.15e\n",
                     "%6d%6d%6d%12.4f%12.4f%12.4f%12.4f%12.4f\n",
                     system->my_atoms[i].orig_id, system->my_atoms[j].orig_id,
                     system->my_atoms[k].orig_id,
                     r_jk, theta, bo_ij->BO, e_hb, data->my_en.e_hb );
#endif
#ifdef TEST_FORCES
            Add_dBO( system, lists, j, pi, +CEhb1, workspace->f_hb ); //dbo term
            // dcos terms
            rvec_ScaledAdd( workspace->f_hb[i], +CEhb2, dcos_theta_di );
            rvec_ScaledAdd( workspace->f_hb[j], +CEhb2, dcos_theta_dj );
            rvec_ScaledAdd( workspace->f_hb[k], +CEhb2, dcos_theta_dk );
            // dr terms
            rvec_ScaledAdd( workspace->f_hb[j], -CEhb3/r_jk, dvec_jk );
            rvec_ScaledAdd( workspace->f_hb[k], +CEhb3/r_jk, dvec_jk );
#endif
          }
        }
      }
    }

#if defined(DEBUG)
  fprintf( stderr, "Number of hydrogen bonds: %d\n", num_hb_intrs );
  fprintf( stderr, "Hydrogen Bond Energy: %g\n", data->my_en.e_hb );
  fprintf( stderr, "hydbonds: ext_press (%24.15e %24.15e %24.15e)\n",
           data->ext_press[0], data->ext_press[1], data->ext_press[2] );
#endif
}
void vdW_Coulomb_Energy( reax_system *system, control_params *control,
                         simulation_data *data, storage *workspace,
                         reax_list **lists, output_controls *out_control )
{
  int i, j, pj, natoms;
  int start_i, end_i, flag;
  rc_tagint orig_i, orig_j;
  double p_vdW1, p_vdW1i;
  double powr_vdW1, powgi_vdW1;
  double tmp, r_ij, fn13, exp1, exp2;
  double Tap, dTap, dfn13, CEvd, CEclmb, de_core;
  double dr3gamij_1, dr3gamij_3;
  double e_ele, e_vdW, e_core, SMALL = 0.0001;
  double e_lg, de_lg, r_ij5, r_ij6, re6;
  rvec temp, ext_press;
  two_body_parameters *twbp;
  far_neighbor_data *nbr_pj;
  reax_list *far_nbrs;

  // Tallying variables:
  double pe_vdw, f_tmp, delij[3];

  natoms = system->n;
  far_nbrs = (*lists) + FAR_NBRS;
  p_vdW1 = system->reax_param.gp.l[28];
  p_vdW1i = 1.0 / p_vdW1;
  e_core = 0;
  e_vdW = 0;
  e_lg = de_lg = 0.0;

  for( i = 0; i < natoms; ++i ) {
    if (system->my_atoms[i].type < 0) continue;
    start_i = Start_Index(i, far_nbrs);
    end_i   = End_Index(i, far_nbrs);
    orig_i  = system->my_atoms[i].orig_id;

    for( pj = start_i; pj < end_i; ++pj ) {
      nbr_pj = &(far_nbrs->select.far_nbr_list[pj]);
      j = nbr_pj->nbr;
      if (system->my_atoms[j].type < 0) continue;
      orig_j  = system->my_atoms[j].orig_id;

      flag = 0;
      if(nbr_pj->d <= control->nonb_cut) {
        if (j < natoms) flag = 1;
        else if (orig_i < orig_j) flag = 1;
        else if (orig_i == orig_j) {
          if (nbr_pj->dvec[2] > SMALL) flag = 1;
          else if (fabs(nbr_pj->dvec[2]) < SMALL) {
            if (nbr_pj->dvec[1] > SMALL) flag = 1;
            else if (fabs(nbr_pj->dvec[1]) < SMALL && nbr_pj->dvec[0] > SMALL)
              flag = 1;
          }
        }
      }

      if (flag) {

      r_ij = nbr_pj->d;
      twbp = &(system->reax_param.tbp[ system->my_atoms[i].type ]
                                       [ system->my_atoms[j].type ]);

      Tap = workspace->Tap[7] * r_ij + workspace->Tap[6];
      Tap = Tap * r_ij + workspace->Tap[5];
      Tap = Tap * r_ij + workspace->Tap[4];
      Tap = Tap * r_ij + workspace->Tap[3];
      Tap = Tap * r_ij + workspace->Tap[2];
      Tap = Tap * r_ij + workspace->Tap[1];
      Tap = Tap * r_ij + workspace->Tap[0];

      dTap = 7*workspace->Tap[7] * r_ij + 6*workspace->Tap[6];
      dTap = dTap * r_ij + 5*workspace->Tap[5];
      dTap = dTap * r_ij + 4*workspace->Tap[4];
      dTap = dTap * r_ij + 3*workspace->Tap[3];
      dTap = dTap * r_ij + 2*workspace->Tap[2];
      dTap += workspace->Tap[1]/r_ij;

      /*vdWaals Calculations*/
      if(system->reax_param.gp.vdw_type==1 || system->reax_param.gp.vdw_type==3)
        { // shielding
          powr_vdW1 = pow(r_ij, p_vdW1);
          powgi_vdW1 = pow( 1.0 / twbp->gamma_w, p_vdW1);

          fn13 = pow( powr_vdW1 + powgi_vdW1, p_vdW1i );
          exp1 = exp( twbp->alpha * (1.0 - fn13 / twbp->r_vdW) );
          exp2 = exp( 0.5 * twbp->alpha * (1.0 - fn13 / twbp->r_vdW) );

          e_vdW = twbp->D * (exp1 - 2.0 * exp2);
          data->my_en.e_vdW += Tap * e_vdW;

          dfn13 = pow( powr_vdW1 + powgi_vdW1, p_vdW1i - 1.0) *
            pow(r_ij, p_vdW1 - 2.0);

          CEvd = dTap * e_vdW -
            Tap * twbp->D * (twbp->alpha / twbp->r_vdW) * (exp1 - exp2) * dfn13;
        }
      else{ // no shielding
        exp1 = exp( twbp->alpha * (1.0 - r_ij / twbp->r_vdW) );
        exp2 = exp( 0.5 * twbp->alpha * (1.0 - r_ij / twbp->r_vdW) );

        e_vdW = twbp->D * (exp1 - 2.0 * exp2);
        data->my_en.e_vdW += Tap * e_vdW;

        CEvd = dTap * e_vdW -
          Tap * twbp->D * (twbp->alpha / twbp->r_vdW) * (exp1 - exp2) / r_ij;
      }

      if(system->reax_param.gp.vdw_type==2 || system->reax_param.gp.vdw_type==3)
        { // innner wall
          e_core = twbp->ecore * exp(twbp->acore * (1.0-(r_ij/twbp->rcore)));
          data->my_en.e_vdW += Tap * e_core;

          de_core = -(twbp->acore/twbp->rcore) * e_core;
          CEvd += dTap * e_core + Tap * de_core / r_ij;

          //  lg correction, only if lgvdw is yes
          if (control->lgflag) {
            r_ij5 = pow( r_ij, 5.0 );
            r_ij6 = pow( r_ij, 6.0 );
            re6 = pow( twbp->lgre, 6.0 );
            e_lg = -(twbp->lgcij/( r_ij6 + re6 ));
            data->my_en.e_vdW += Tap * e_lg;

            de_lg = -6.0 * e_lg *  r_ij5 / ( r_ij6 + re6 ) ;
            CEvd += dTap * e_lg + Tap * de_lg / r_ij;
          }

        }

      /*Coulomb Calculations*/
      dr3gamij_1 = ( r_ij * r_ij * r_ij + twbp->gamma );
      dr3gamij_3 = pow( dr3gamij_1 , 0.33333333333333 );

      tmp = Tap / dr3gamij_3;
      data->my_en.e_ele += e_ele =
        C_ele * system->my_atoms[i].q * system->my_atoms[j].q * tmp;

      CEclmb = C_ele * system->my_atoms[i].q * system->my_atoms[j].q *
        ( dTap -  Tap * r_ij / dr3gamij_1 ) / dr3gamij_3;

      /* tally into per-atom energy */
      if( system->pair_ptr->evflag || system->pair_ptr->vflag_atom) {
        pe_vdw = Tap * (e_vdW + e_core + e_lg);
        rvec_ScaledSum( delij, 1., system->my_atoms[i].x,
                              -1., system->my_atoms[j].x );
        f_tmp = -(CEvd + CEclmb);
        system->pair_ptr->ev_tally(i,j,natoms,1,pe_vdw,e_ele,
                        f_tmp,delij[0],delij[1],delij[2]);
      }

      if( control->virial == 0 ) {
        rvec_ScaledAdd( workspace->f[i], -(CEvd + CEclmb), nbr_pj->dvec );
        rvec_ScaledAdd( workspace->f[j], +(CEvd + CEclmb), nbr_pj->dvec );
      }
      else { /* NPT, iNPT or sNPT */
        rvec_Scale( temp, CEvd + CEclmb, nbr_pj->dvec );

        rvec_ScaledAdd( workspace->f[i], -1., temp );
        rvec_Add( workspace->f[j], temp );

        rvec_iMultiply( ext_press, nbr_pj->rel_box, temp );
        rvec_Add( data->my_ext_press, ext_press );
      }
      }
    }
  }

  Compute_Polarization_Energy( system, data );
}
Exemple #16
0
void Report_Bond_Change( reax_system *system, control_params *control,
			 static_storage *workspace,  list *old_bonds,
			 list *new_bonds, int a1, int a2, int flag,
			 FILE *fout )
{
  int i;
  int rev1, rev2;
  int mol1 = -1, mol2 = -1;
  // which molecule the atom belongs to, 0: Silica, 1: Water

  rev1 = workspace->orig_id[a1];
  rev2 = workspace->orig_id[a2];

  if( !strcmp( system->atoms[a1].name, "  Si" ) ||
      !strcmp( system->atoms[a1].name, "   O" ) )
    mol1 = 0;
  else mol1 = 1;

  if( !strcmp( system->atoms[a2].name, "  Si" ) ||
      !strcmp( system->atoms[a2].name, "   O" ) )
    mol2 = 0;
  else mol2 = 1;


  if( mol1 == 0 && mol2 == 0 ) {  // silica-silica
    if( flag )
      fprintf( fout, "silica bond formation:" );
    else fprintf( fout, "silica bond breakage :" );

    fprintf( fout, "%5d(%s)-%5d(%s)\n",
	     rev1, system->atoms[a1].name, rev2, system->atoms[a2].name );
  }
  else if( mol1 == 1 && mol2 == 1 ) { // water-water
    if( flag )
      fprintf( fout, "water bond formation:" );
    else fprintf( fout, "water bond breakage :" );

    fprintf( fout, "%5d(%s)-%5d(%s)\n",
	     rev1, system->atoms[a1].name, rev2, system->atoms[a2].name );
  }
  else  { // water-silica!
    if( flag )
      fprintf( fout, "SILICA-WATER bond formation:" );
    else fprintf( fout, "SILICA-WATER bond breakage :" );

    fprintf( fout, "%5d(%s)-%5d(%s)\n",
	     rev1, system->atoms[a1].name, rev2, system->atoms[a2].name );

    fprintf( fout, "%5d(%s) was connected to:", rev1, system->atoms[a1].name );
    for( i = Start_Index(a1, old_bonds); i < End_Index(a1, old_bonds); ++i )
      if( old_bonds->select.bond_list[i].bo_data.BO >= control->bg_cut )
	fprintf( fout, " %5d(%s)",
		 workspace->orig_id[ old_bonds->select.bond_list[i].nbr ],
		 system->atoms[ old_bonds->select.bond_list[i].nbr ].name );
    fprintf( fout, "\n" );

    fprintf( fout, "%5d(%s) was connected to:", rev2, system->atoms[a2].name );
    for( i = Start_Index(a2, old_bonds); i < End_Index(a2, old_bonds); ++i )
      if( old_bonds->select.bond_list[i].bo_data.BO >= control->bg_cut )
	fprintf( fout, " %5d(%s)",
		 workspace->orig_id[ old_bonds->select.bond_list[i].nbr ],
		 system->atoms[ old_bonds->select.bond_list[i].nbr ].name );
    fprintf( fout, "\n" );
  }
}
Exemple #17
0
void Compute_Bond_Boost_Force(reax_system *system, control_params *control,
		simulation_data *data, static_storage *workspace, list **lists, 
        output_controls *out_control) {
  int i, j, pj;
  int type_i, type_j;
  int adatom, adatom2; // label the boost atom
  int nbond, nrad; // Nb
  int start_i, end_i;
  real e, emax, r, re, r_max; // eta, eta_max, r, r_e
  real bo;
  real A, dA, V; // A(\eta^max), and \Delta A(\eta^max)
  real *rv, *rv_max;
  real q, P1, vmax; // q, P1 in equation 13
  real S1, S2, f1, f2, C1, C2;
  real bf; // boost force scale
  rvec df; // boost force
  reax_atom *atom1, *atom2;
  bond_order_data *bo_ij;
  two_body_parameters *twbp;
  list *bonds;

  nrad = Find_Radicals(system, control, data, workspace, lists, out_control);
  //printf("-------------------------step %d  -----------------\n", data->step);
  bonds = (*lists) + BONDS;

  // bond boost parameters
  q = control->bboost_q; // should read this from control file
  P1 = control->bboost_P1; 
  vmax = control->bboost_Vmax;

  // initiate parameters
  e = 0;
  adatom = 0;
  adatom2 = 0;
  nbond = 0;
  emax = 0.0;
  bo = 0.0;
  re = 0.001;

  A = 0.0;
  dA = 0.0;
  r_max = 0.0;

  // first get the max bond order
  for( i=0; i < system->N; ++i ) {
    re = 0.001;
    start_i = Start_Index(i, bonds);
    end_i = End_Index(i, bonds);
    for( pj = start_i; pj < end_i; ++pj ){
      if( i < bonds->select.bond_list[pj].nbr ) {
        j = bonds->select.bond_list[pj].nbr;
        type_i = system->atoms[i].type;
        type_j = system->atoms[j].type;
        twbp = &( system->reaxprm.tbp[type_i][type_j] );
        bo_ij = &( bonds->select.bond_list[pj].bo_data );
        re = twbp->r_e; // get r_e from ffield.ext
        r = bonds->select.bond_list[pj].d;
        e = (r - re)/re; // eta
        //printf("r = %f, re = %f, e = %f\n", r, re, e);
        bo = bo_ij->BO;
        if ( (fabs (emax) < fabs(e)) & (bo > q)) {
            emax = e;
            adatom = i;
            adatom2 = j;
        }
      }
    }
  }
  /*
  printf("atom1 = %s ", system->reaxprm.sbp[ system->atoms[adatom].type ].name);
  printf("atom2 = %s ", system->reaxprm.sbp[ system->atoms[adatom2].type ].name);
  printf("bo = %f\n", bo);
  */

  V = 0.0; // boost energy

  if (fabs(emax) < q && nrad == 0) {
      i = adatom;
      vmax = control->bboost_Vmax;

      // calculate A, and dA
      S1 = emax/q;
      S2 = S1 * S1;
      C1 = 1 - (emax/q)*(emax/q);
      C2 = 1 - P1*P1*S2;
      A = C1 * C1 / C2;

      /*
      printf("S1 = %f, S2 = %f ", S1, S2);
      printf("C1 = %f, C2 = %f ", C1, C2);
      printf("A = %f, emax = %f\n", A, emax);
      */

      start_i = Start_Index(i, bonds);
      end_i = End_Index(i, bonds);
      for( pj = start_i; pj < end_i; ++pj ) {
        if( i < bonds->select.bond_list[pj].nbr ) {
            bo_ij = &( bonds->select.bond_list[pj].bo_data );
            bo = bo_ij->BO;
            if (bo > 0.3)
                nbond += 1;
        }
      }

      for( pj = start_i; pj < end_i; ++pj ) {
        if( i < bonds->select.bond_list[pj].nbr ) {
          bo_ij = &( bonds->select.bond_list[pj].bo_data );
          bo = bo_ij->BO;
          if (bo > 0.3) {
            j = bonds->select.bond_list[pj].nbr;
            r = bonds->select.bond_list[pj].d;
            rv = bonds->select.bond_list[pj].dvec;
            type_i = system->atoms[i].type;
            type_j = system->atoms[j].type;
            twbp = &( system->reaxprm.tbp[type_i][type_j] );
            vmax = twbp->v_max;
            re = twbp->r_e; // get r_e from ffield.ext

            e = (r - re)/re; // eta
            C1 = 1 - e*e/(q*q);
            V += vmax / nbond * C1;
            bf = 2*A*vmax*e/(nbond*q*re);

            /*
            printf("e = %.3f, emax = %.3f, C1 = %.3f, re = %.3f, V = %.3f, A = %.3f bf = %.3f, vmax = %.3f, \n",\
                    e, emax, C1, re, V, A, bf, vmax);
            */

            if (fabs(e - emax) < 0.00001) {
                C2 = 1 - e*e*P1*P1/(q*q);
                f1 = 2/(q*re);
                f2 = f1/2*P1*P1;
                dA = 2*e*C1/C2*(f1 - f2*C1/C2);
                rv_max = bonds->select.bond_list[pj].dvec;
                r_max = bonds->select.bond_list[pj].d;;
            }
            rvec_Scale(df, bf, rv);
            //rvec_Scale(df, 1/r, df);
            // assign the boost force
            atom1 = &( system->atoms[i] );
            atom2 = &( system->atoms[j] );
            /* printf("ofx = %8.3f ofy = %8.3f ofz = %8.3f \n", system->atoms[i].f[0],\
                    system->atoms[i].f[1], system->atoms[i].f[2]);
            */
            rvec_Add(system->atoms[i].f, df);
            //printf(" fx = %8.3f  fy = %8.3f  fz = %8.3f \n", df[0], df[1], df[2]);
            /*
            rvec_Scale(df, -1, df);
            rvec_Add(system->atoms[j].f, df);
            */
          }
        }
      }
      // add the contribution of evalope function A
      bf = dA * V;
      rvec_Scale(df, bf, rv_max);
      //rvec_Scale(df, 1/r_max, df);
      //printf("Max bf = %8.3f\n", bf);
      /*
      printf("Mfx = %8.3f Mfy = %8.3f Mfz = %8.3f dA = %8.3f V = %8.3f emax = %8.3f \n",\
             df[0], df[1], df[2], dA, V, emax);
      */
      atom1 = &( system->atoms[i] );
      rvec_Add(system->atoms[i].f, df);
  }

  fprintf( out_control->bboost, "%-10d%6d%6d%10.4f%10.4f%10.4f", \
  data->step, adatom + 1, adatom2 + 1, bo, emax, A*V );

  fprintf( out_control->bboost, " %4s %4s\n", \
  system->reaxprm.sbp[ system->atoms[adatom].type ].name, 
  system->reaxprm.sbp[ system->atoms[adatom2].type ].name);
  fflush( out_control->bboost);
}
Exemple #18
0
// ASSUMPTION: Bond lists are sorted
int Compare_Bond_Lists( int atom, control_params *control, list **lists )
{
  int oldp, newp;
  list *new_bonds = (*lists) + BONDS;
  list *old_bonds = (*lists) + OLD_BONDS;

  /*fprintf( stdout, "\n%d\nold_bonds:", atom );
    for( oldp = Start_Index( atom, old_bonds );
         oldp < End_Index( atom, old_bonds ); ++oldp )
    if( old_bonds->select.bond_list[oldp].bo_data.BO >= control->bg_cut )
    fprintf( stdout, "%5d", old_bonds->select.bond_list[oldp].nbr );

    fprintf( stdout, "\nnew_bonds:" );
    for( newp = Start_Index( atom, new_bonds );
         newp < End_Index( atom, new_bonds ); ++newp )
    if( new_bonds->select.bond_list[newp].bo_data.BO >= control->bg_cut )
    fprintf( stdout, "%5d", new_bonds->select.bond_list[newp].nbr );*/


  for( oldp = Start_Index( atom, old_bonds ),
	 newp = Start_Index( atom, new_bonds );
       oldp < End_Index(atom, old_bonds) || newp < End_Index(atom, new_bonds);
       oldp = MIN( oldp + 1, End_Index( atom, old_bonds ) ),
	 newp = MIN( newp + 1, End_Index( atom, new_bonds ) ) ) {
    while( oldp < End_Index( atom, old_bonds ) &&
	   old_bonds->select.bond_list[oldp].bo_data.BO < control->bg_cut )
      ++oldp;

    while( newp < End_Index( atom, new_bonds ) &&
	   new_bonds->select.bond_list[newp].bo_data.BO < control->bg_cut )
      ++newp;

    /*fprintf( fout, "%d, oldp: %d - %d, newp: %d - %d",
      atom, oldp, old_bonds->select.bond_list[oldp].nbr,
      newp,  new_bonds->select.bond_list[newp].nbr );*/

    if( oldp < End_Index( atom, old_bonds ) ) {
      /* there are some other bonds in the old list */
      if( newp < End_Index( atom, new_bonds ) ) {
	if( old_bonds->select.bond_list[oldp].nbr !=
	    new_bonds->select.bond_list[newp].nbr ) {
	  //fprintf( fout, " --> case1, return 1\n" );
	  return 1;
	}
      }
      else {
	/* there is no other bond in the new list */
	//fprintf( fout, " --> case2, return 1\n" );
	return 1;
      }
    }
    else {
      /* there are no more bonds in old_bond list */
      if( newp < End_Index( atom, new_bonds ) ) {
	/* there is at least one other bond in the new list */
	//fprintf( fout, " --> case 3, return 1\n" );
	return 1;
      }
      else {
	/* there is no other bond in the new list, either */
	//fprintf( fout, " --> case 4, return 0\n" );
	return 0;
      }
    }
  }

  return 0;
}
Exemple #19
0
void Analyze_Silica( reax_system *system, control_params *control,
		     simulation_data *data, static_storage *workspace,
		     list **lists, FILE *fout )
{
  int atom, i, j, k, pi, pk, pk_j, newp, coord;
  int O_SI_O_count, SI_O_SI_count;
  int si_coord[10], ox_coord[10];
  real O_SI_O, SI_O_SI;
  list *new_bonds = (*lists) + BONDS;
  list *thb_intrs =  (*lists) + THREE_BODIES;

  Analyze_Fragments( system, control, data, workspace, lists, fout, 0 );

  /* analyze atom coordinations */
  for( i = 0; i < 10; ++i )
    si_coord[i] = ox_coord[i] = 0;

  for( atom = 0; atom < system->N; ++atom ) {
    coord = 0;

    for( newp = Start_Index( atom, new_bonds );
	 newp < End_Index( atom, new_bonds ); ++newp )
      if( new_bonds->select.bond_list[newp].bo_data.BO >= control->bg_cut )
	++coord;

    if( system->atoms[ atom ].type == SI_ATOM ) {
      /*if( coord == 4 )
	full_coord_SI++;
	else less_coord_SI++;*/
      ++si_coord[coord];
    }
    else if( system->atoms[ atom ].type == O_ATOM ) {
      /*if( coord == 2 )
	full_coord_O++;
	else less_coord_O++;*/
      ++ox_coord[coord];
    }
  }

  /* fprintf( fout, "\nFour Coordinated SI: %.2f%\n",
     (double)full_coord_SI / (full_coord_SI + less_coord_SI) * 100. );
     fprintf( fout, "Four Coordinated O : %.2f%\n",
     (double)full_coord_O  / (full_coord_O  + less_coord_O ) * 100. ); */

  fprintf( fout, "Silicon coordinations:\n" );
  for( i = 1; i < 10; ++i )
    if( si_coord[i] )
      fprintf( fout, "\t%d-coord: %d\n", i, si_coord[i] );

  fprintf( fout, "\nOxygen coordinations:\n" );
  for( i = 1; i < 10; ++i )
    if( ox_coord[i] )
      fprintf( fout, "\t%d-coord: %d\n", i, ox_coord[i] );


  /* analyze bond angles */
  O_SI_O = 0;
  O_SI_O_count = 0;

  SI_O_SI = 0;
  SI_O_SI_count = 0;

  for( j = 0; j < system->N; ++j )
    if( system->atoms[j].type == O_ATOM || system->atoms[j].type == SI_ATOM )
      for( pi = Start_Index(j, new_bonds); pi < End_Index(j, new_bonds); ++pi )
	if( new_bonds->select.bond_list[pi].bo_data.BO >= control->bg_cut ) {
	  i = new_bonds->select.bond_list[pi].nbr;

	  if(system->atoms[i].type==O_ATOM || system->atoms[i].type==SI_ATOM) {
	    for( pk = Start_Index( pi, thb_intrs );
		 pk < End_Index( pi, thb_intrs ); ++pk ) {
	      k = thb_intrs->select.three_body_list[pk].thb;
	      pk_j = thb_intrs->select.three_body_list[pk].pthb;
	      // get k's pointer on j's bond list

	      if( new_bonds->select.bond_list[pk_j].bo_data.BO >=
		  control->bg_cut ) { // physical j&k bond
		/*fprintf( fout, "%5d(%d) %5d(%d) %5d(%d)   %8.3f\n",
		  i, system->atoms[i].type, j, system->atoms[j].type,
		  k, system->atoms[k].type,
		  thb_intrs->select.three_body_list[pk].theta );*/

		if( system->atoms[i].type == O_ATOM &&
		    system->atoms[j].type == SI_ATOM &&
		    system->atoms[k].type == O_ATOM ){
		  O_SI_O_count++;
		  O_SI_O += thb_intrs->select.three_body_list[pk].theta;
		}
		else if ( system->atoms[i].type == SI_ATOM &&
			  system->atoms[j].type == O_ATOM &&
			  system->atoms[k].type == SI_ATOM ){
		  SI_O_SI_count++;
		  SI_O_SI += thb_intrs->select.three_body_list[pk].theta;
		}
	      }
	    }
	  }
	}

  fprintf( fout, "\nAverage O-Si-O angle: %8.2f\n",
	   RAD2DEG(O_SI_O / O_SI_O_count) );
  fprintf( fout, "Average Si-O-Si angle:  %8.2f\n\n\n",
	   RAD2DEG(SI_O_SI / SI_O_SI_count) );

  fflush( fout );
}
Exemple #20
0
/* ASSUMPTION: Bond lists are sorted */
void Compare_Bonding( int atom, reax_system *system, control_params *control,
		      static_storage *workspace, list *old_bonds,
		      list *new_bonds, FILE *fout )
{
  int oldp, newp;

  /* fprintf( fout, "\n%d\nold_bonds:", atom );
     for( oldp = Start_Index( atom, old_bonds );
          oldp < End_Index( atom, old_bonds ); ++oldp )
     if( old_bonds->select.bond_list[oldp].bo_data.BO >= control->bg_cut )
     fprintf( fout, "%5d", old_bonds->select.bond_list[oldp].nbr );

     fprintf( fout, "\nnew_bonds:" );
     for( newp = Start_Index( atom, new_bonds );
          newp < End_Index( atom, new_bonds ); ++newp )
     if( new_bonds->select.bond_list[newp].bo_data.BO >= control->bg_cut )
     fprintf( fout, "%6d", new_bonds->select.bond_list[newp].nbr );
     fprintf( fout, "\n" ); */

  for( oldp = Start_Index( atom, old_bonds );
        oldp < End_Index( atom, old_bonds ) &&
	 old_bonds->select.bond_list[oldp].nbr < atom;
	++oldp );

  for( newp = Start_Index( atom, new_bonds );
        newp < End_Index( atom, new_bonds ) &&
	 new_bonds->select.bond_list[newp].nbr < atom;
	++newp );

  while( oldp < End_Index( atom, old_bonds ) ||
	 newp < End_Index( atom, new_bonds ) ) {
    while( oldp < End_Index( atom, old_bonds ) &&
	   old_bonds->select.bond_list[oldp].bo_data.BO < control->bg_cut )
      ++oldp;

    while( newp < End_Index( atom, new_bonds ) &&
	   new_bonds->select.bond_list[newp].bo_data.BO < control->bg_cut )
      ++newp;

    /*fprintf( fout, "%d, oldp: %d - %d: %f    newp: %d - %d: %f",
      atom, oldp, old_bonds->select.bond_list[oldp].nbr,
      old_bonds->select.bond_list[oldp].bo_data.BO,
      newp,  new_bonds->select.bond_list[newp].nbr,
      new_bonds->select.bond_list[newp].bo_data.BO ); */

    if( oldp < End_Index( atom, old_bonds ) ) {
      /* there are some more bonds in the old list */
      if( newp < End_Index( atom, new_bonds ) ) {
	if( old_bonds->select.bond_list[oldp].nbr <
	    new_bonds->select.bond_list[newp].nbr ) {
	  // fprintf( fout, "%5d-%5d bond broken\n",
	  // atom, old_bonds->select.bond_list[oldp].nbr );
	  Report_Bond_Change( system, control, workspace, old_bonds, new_bonds,
			      atom, old_bonds->select.bond_list[oldp].nbr, 0,
			      fout );
	  ++oldp;
	}
	else if( old_bonds->select.bond_list[oldp].nbr >
		 new_bonds->select.bond_list[newp].nbr ) {
	  // fprintf( fout, "%5d-%5d bond formed\n",
	  // atom, new_bonds->select.bond_list[newp].nbr );
	  Report_Bond_Change( system, control, workspace, old_bonds, new_bonds,
			      atom, new_bonds->select.bond_list[newp].nbr, 1,
			      fout );
	  ++newp;
	}
	else
	  ++newp, ++oldp;
      }
      else
	/* there is no other bond in the new list */
	while( oldp < End_Index( atom, old_bonds ) ) {
	  if( old_bonds->select.bond_list[oldp].bo_data.BO>=control->bg_cut ) {
	    // fprintf( fout, "%5d-%5d bond broken\n",
	    // atom, old_bonds->select.bond_list[oldp].nbr );
	    Report_Bond_Change( system, control, workspace,
				old_bonds, new_bonds, atom,
				old_bonds->select.bond_list[oldp].nbr, 0,
				fout );
	  }
	  ++oldp;
	}
    }
    else {
      /* there are no more bonds in old_bond list */
      if( newp < End_Index( atom, new_bonds ) )
	/* there is at least one other bond in the new list */
	while( newp < End_Index( atom, new_bonds ) ) {
	  if( new_bonds->select.bond_list[newp].bo_data.BO>=control->bg_cut ){
	    // fprintf( fout, "%5d-%5d bond formed\n",
	    // atom, new_bonds->select.bond_list[newp].nbr );
	    Report_Bond_Change( system, control, workspace,
				old_bonds, new_bonds, atom,
				new_bonds->select.bond_list[newp].nbr, 1,
				fout );
	  }
	  ++newp;
	}
      else {
	/* there is no other bond in the new list, either --
	   no need to do anything */
      }
    }
  }
}
Exemple #21
0
void Compute_Bond_Boost_Force_All_Couple(reax_system *system, control_params *control,
		simulation_data *data, static_storage *workspace, list **lists, 
        output_controls *out_control) {
  int i, j, pj;
  int type_i, type_j;
  int adatom, adatom2; // label the boost atom
  int nbond, nrad; // Nb
  int start_i, end_i;
  real e, emax, r, re, r_max; // eta, eta_max, r, r_e
  real bo;
  real A, dA, V; // A(\eta^max), and \Delta A(\eta^max)
  real *rv, *rv_max;
  real q, P1, vmax; // q, P1 in equation 13
  real S1, S2, f1, f2, C1, C2;
  real T;
  real bf, bfactor; // boost force scale
  rvec df; // boost force
  reax_atom *atom1, *atom2;
  bond_order_data *bo_ij;
  two_body_parameters *twbp;
  list *bonds;

  nrad = Find_Radicals(system, control, data, workspace, lists, out_control);
  //nrad = 0;
  //printf("-------------------------step %d  -----------------\n", data->step);
  bonds = (*lists) + BONDS;

  // bond boost parameters
  q = control->bboost_q; // should read this from control file
  P1 = control->bboost_P1; 
  vmax = control->bboost_Vmax;

  // initiate parameters
  e = 0;
  adatom = 0;
  adatom2 = 0;
  bo = 0.0;
  re = 0.001;

  A = 0.0;
  dA = 0.0;
  r_max = 0.0;
  bfactor = 1.0;
  T = control->T_final;
  V = 0.0; // bost energy
  nbond = 0;
  emax = 0.0;

  // first get the max bond order
  for( i=0; i < system->N; ++i ) {
    start_i = Start_Index(i, bonds);
    end_i = End_Index(i, bonds);
    for( pj = start_i; pj < end_i; ++pj ){
      if( i < bonds->select.bond_list[pj].nbr ) {
        j = bonds->select.bond_list[pj].nbr;
        type_i = system->atoms[i].type;
        type_j = system->atoms[j].type;
        twbp = &( system->reaxprm.tbp[type_i][type_j] );
        vmax = control->bboost_Vmax;
        vmax = twbp->v_max;
        bo_ij = &( bonds->select.bond_list[pj].bo_data );
        re = twbp->r_e; // get r_e from ffield.ext
        r = bonds->select.bond_list[pj].d;
        e = (r - re)/re; // eta
        bo = bo_ij->BO;
        if (bo > q && vmax > 0) {
            nbond += 1;
            if ( fabs(emax) < fabs(e) ) {
                emax = e;
                adatom = i;
                adatom2 = j;
                /* for debug
                printf("i = %d, j = %d, re = %.2f, r = %.2f ", i, j, re, r);
                printf("x1 = %.2f, y1 = %.2f, z1 = %.2f, ", \
                system->atoms[i].x[0], system->atoms[i].x[1], system->atoms[i].x[2]);
                printf("x2 = %.2f, y2 = %.2f, z2 = %.2f\n", \
                system->atoms[j].x[0], system->atoms[j].x[1], system->atoms[j].x[2]);
                printf( " %4s %4s\n", \
                system->reaxprm.sbp[ system->atoms[i].type ].name, 
                system->reaxprm.sbp[ system->atoms[j].type ].name);
                */
                rv_max = bonds->select.bond_list[pj].dvec;
                r_max = bonds->select.bond_list[pj].d;;
            }
        }
      }
    }
  }

  int ntmp; 
  if (fabs(emax) < q && nbond > 0 && nrad <= control->bboost_nrad) {
    data->boost ++ ;
    // calculate A, and dA
    S1 = emax/q;
    S2 = S1 * S1;
    C1 = 1 - (emax/q)*(emax/q);
    C2 = 1 - P1*P1*S2;
    A = C1 * C1 / C2;

    ntmp = 0;
    for( i=0; i < system->N; ++i ) {
      start_i = Start_Index(i, bonds);
      end_i = End_Index(i, bonds);
      for( pj = start_i; pj < end_i; ++pj ) {
        if( i < bonds->select.bond_list[pj].nbr ) {
          j = bonds->select.bond_list[pj].nbr;
          type_i = system->atoms[i].type;
          type_j = system->atoms[j].type;
          twbp = &( system->reaxprm.tbp[type_i][type_j] );
          vmax = control->bboost_Vmax;
          vmax = twbp->v_max;
          bo_ij = &( bonds->select.bond_list[pj].bo_data );
          r = bonds->select.bond_list[pj].d;
          re = twbp->r_e; // get r_e from ffield.ext
          rv = bonds->select.bond_list[pj].dvec;
          bo = bo_ij->BO;
          if (bo > q && vmax > 0) {

            e = (r - re)/re; // eta
            C1 = 1 - e*e/(q*q);
            V += vmax / nbond * C1;
            bf = 2*A*vmax*e/(nbond*q*q*re);

            if (fabs(e - emax) < 0.00001) {
                C2 = 1 - e*e*P1*P1/(q*q);
                f1 = 2/(q*q*re);
                f2 = f1/2*P1*P1;
                dA = 2*e*C1/C2*(f1 - f2*C1/C2);
            }
            rvec_Scale(df, bf, rv);
            atom1 = &( system->atoms[i] );
            atom2 = &( system->atoms[j] );
            rvec_Add(system->atoms[i].f, df);
            rvec_ScaledAdd(system->atoms[j].f, -1, df);
            ntmp++;
          }
        }
      }
    }
    // add the contribution of evalope function A
    bf = dA * V;
    rvec_Scale(df, bf, rv_max);
    atom1 = &( system->atoms[adatom]);
    rvec_Add(system->atoms[adatom].f, df);
    rvec_ScaledAdd(system->atoms[adatom2].f, -1, df);
  }
  else {
    data->boost = 0;
  }
  bfactor = exp(4184 * A * V/(T * 8.314));
  //bfactor = V;
  fprintf( out_control->bboost, "%-10d%6d%6d%6d%3d%8.4f%8.4f %44.4f", \
  data->step, nbond, adatom, adatom2, nrad, r_max, emax, bfactor );

  fprintf( out_control->bboost, " %4s %4s\n", \
  system->reaxprm.sbp[ system->atoms[adatom].type ].name, 
  system->reaxprm.sbp[ system->atoms[adatom2].type ].name);
  fflush( out_control->bboost);
}
Exemple #22
0
void Init_Forces( reax_system *system, control_params *control,
                  simulation_data *data, storage *workspace, reax_list **lists,
                  output_controls *out_control, MPI_Comm comm ) {
  int i, j, pj;
  int start_i, end_i;
  int type_i, type_j;
  int Htop, btop_i, btop_j, num_bonds, num_hbonds;
  int ihb, jhb, ihb_top, jhb_top;
  int local, flag, renbr;
  real r_ij, cutoff;
  sparse_matrix *H;
  reax_list *far_nbrs, *bonds, *hbonds;
  single_body_parameters *sbp_i, *sbp_j;
  two_body_parameters *twbp;
  far_neighbor_data *nbr_pj;
  reax_atom *atom_i, *atom_j;

  far_nbrs = *lists + FAR_NBRS;
  bonds = *lists + BONDS;
  hbonds = *lists + HBONDS;

  for( i = 0; i < system->n; ++i )
    workspace->bond_mark[i] = 0;
  for( i = system->n; i < system->N; ++i ) {
    workspace->bond_mark[i] = 1000; // put ghost atoms to an infinite distance
    //workspace->done_after[i] = Start_Index( i, far_nbrs );
  }

  H = workspace->H;
  H->n = system->n;
  Htop = 0;
  num_bonds = 0;
  num_hbonds = 0;
  btop_i = btop_j = 0;
  renbr = (data->step-data->prev_steps) % control->reneighbor == 0;

  for( i = 0; i < system->N; ++i ) {
    atom_i = &(system->my_atoms[i]);
    type_i  = atom_i->type;
    start_i = Start_Index(i, far_nbrs);
    end_i   = End_Index(i, far_nbrs);
    btop_i = End_Index( i, bonds );
    sbp_i = &(system->reax_param.sbp[type_i]);

    if( i < system->n ) {
      local = 1;
      cutoff = control->nonb_cut;
    }
    else {
      local = 0;
      cutoff = control->bond_cut;
    }

    ihb = -1;
    ihb_top = -1;
    if( local ) {
      H->start[i] = Htop;
      H->entries[Htop].j = i;
      H->entries[Htop].val = sbp_i->eta;
      ++Htop;

      if( control->hbond_cut > 0 ) {
        ihb = sbp_i->p_hbond;
        if( ihb == 1 )
          ihb_top = End_Index( atom_i->Hindex, hbonds );
        else ihb_top = -1;
      }
    }

    /* update i-j distance - check if j is within cutoff */
    for( pj = start_i; pj < end_i; ++pj ) {
      nbr_pj = &( far_nbrs->select.far_nbr_list[pj] );
      j = nbr_pj->nbr;
      atom_j = &(system->my_atoms[j]);
      //fprintf( stderr, "%d%d i=%d x_i: %f %f %f,j=%d x_j: %f %f %f, d=%f\n",
      //         MIN(atom_i->orig_id, atom_j->orig_id),
      //         MAX(atom_i->orig_id, atom_j->orig_id),
      //         i, atom_i->x[0], atom_i->x[1], atom_i->x[2],
      //         j, atom_j->x[0], atom_j->x[1], atom_j->x[2], nbr_pj->d );
      if( renbr ) {
        if(nbr_pj->d <= cutoff)
          flag = 1;
        else flag = 0;
      }
      else{
        nbr_pj->dvec[0] = atom_j->x[0] - atom_i->x[0];
        nbr_pj->dvec[1] = atom_j->x[1] - atom_i->x[1];
        nbr_pj->dvec[2] = atom_j->x[2] - atom_i->x[2];
        nbr_pj->d = rvec_Norm_Sqr( nbr_pj->dvec );
        if( nbr_pj->d <= SQR(cutoff) ) {
          nbr_pj->d = sqrt(nbr_pj->d);
          flag = 1;
        }
        else {
          flag = 0;
        }
      }

      if( flag ){
        type_j = atom_j->type;
        r_ij = nbr_pj->d;
        sbp_j = &(system->reax_param.sbp[type_j]);
        twbp = &(system->reax_param.tbp[type_i][type_j]);

        if( local ) {
          /* H matrix entry */
          if( j < system->n || atom_i->orig_id < atom_j->orig_id ) {//tryQEq||1
            H->entries[Htop].j = j;
            //fprintf( stdout, "%d%d %d %d\n",
            //     MIN(atom_i->orig_id, atom_j->orig_id),
            //     MAX(atom_i->orig_id, atom_j->orig_id),
            //     MIN(atom_i->orig_id, atom_j->orig_id),
            //     MAX(atom_i->orig_id, atom_j->orig_id) );
            if( control->tabulate == 0 )
              H->entries[Htop].val = Compute_H(r_ij,twbp->gamma,workspace->Tap);
            else H->entries[Htop].val = Compute_tabH(r_ij, type_i, type_j);
            ++Htop;
          }

          /* hydrogen bond lists */
          if( control->hbond_cut > 0 && (ihb==1 || ihb==2) &&
              nbr_pj->d <= control->hbond_cut ) {
            // fprintf( stderr, "%d %d\n", atom1, atom2 );
            jhb = sbp_j->p_hbond;
            if( ihb == 1 && jhb == 2 ) {
              hbonds->select.hbond_list[ihb_top].nbr = j;
              hbonds->select.hbond_list[ihb_top].scl = 1;
              hbonds->select.hbond_list[ihb_top].ptr = nbr_pj;
              ++ihb_top;
              ++num_hbonds;
            }
            else if( j < system->n && ihb == 2 && jhb == 1 ) {
              jhb_top = End_Index( atom_j->Hindex, hbonds );
              hbonds->select.hbond_list[jhb_top].nbr = i;
              hbonds->select.hbond_list[jhb_top].scl = -1;
              hbonds->select.hbond_list[jhb_top].ptr = nbr_pj;
              Set_End_Index( atom_j->Hindex, jhb_top+1, hbonds );
              ++num_hbonds;
            }
          }
        }

        /* uncorrected bond orders */
        if( //(workspace->bond_mark[i] < 3 || workspace->bond_mark[j] < 3) &&
            nbr_pj->d <= control->bond_cut &&
            BOp( workspace, bonds, control->bo_cut,
                 i , btop_i, nbr_pj, sbp_i, sbp_j, twbp ) ) {
          num_bonds += 2;
          ++btop_i;

          if( workspace->bond_mark[j] > workspace->bond_mark[i] + 1 )
            workspace->bond_mark[j] = workspace->bond_mark[i] + 1;
          else if( workspace->bond_mark[i] > workspace->bond_mark[j] + 1 ) {
            workspace->bond_mark[i] = workspace->bond_mark[j] + 1;
            //if( workspace->bond_mark[i] == 1000 )
            //  workspace->done_after[i] = pj;
          }
          //fprintf( stdout, "%d%d - %d(%d) %d(%d)\n",
          //   i , j, i, workspace->bond_mark[i], j, workspace->bond_mark[j] );
        }
      }
    }

    Set_End_Index( i, btop_i, bonds );
    if( local ) {
      H->end[i] = Htop;
      if( ihb == 1 )
        Set_End_Index( atom_i->Hindex, ihb_top, hbonds );
    }
  }

  //fprintf( stderr, "after the first init loop\n" );
  /*for( i = system->n; i < system->N; ++i )
    if( workspace->bond_mark[i] > 3 ) {
      start_i = Start_Index(i, bonds);
      end_i = End_Index(i, bonds);
      num_bonds -= (end_i - start_i);
      Set_End_Index(i, start_i, bonds );
      }*/

  /*for( i = system->n; i < system->N; ++i ) {
    start_i = Start_Index(i, far_nbrs);
    end_i = workspace->done_after[i];

    if( workspace->bond_mark[i] >= 2 && start_i < end_i ) {
      atom_i = &(system->my_atoms[i]);
      type_i = atom_i->type;
      btop_i = End_Index( i, bonds );
      sbp_i = &(system->reax_param.sbp[type_i]);

      for( pj = start_i; pj < end_i; ++pj ) {
        nbr_pj = &( far_nbrs->select.far_nbr_list[pj] );
        j = nbr_pj->nbr;

        if( workspace->bond_mark[j] >= 2 && nbr_pj->d <= control->bond_cut ) {
          atom_j = &(system->my_atoms[j]);
          type_j = atom_j->type;
          sbp_j = &(system->reax_param.sbp[type_j]);
          twbp = &(system->reax_param.tbp[type_i][type_j]);

          if( BOp( workspace, bonds, control->bo_cut,
                   i , btop_i, nbr_pj, sbp_i, sbp_j, twbp ) ) {
            num_bonds += 2;
            ++btop_i;

            if( workspace->bond_mark[j] > workspace->bond_mark[i] + 1 )
              workspace->bond_mark[j] = workspace->bond_mark[i] + 1;
            else if( workspace->bond_mark[i] > workspace->bond_mark[j] + 1 )
              workspace->bond_mark[i] = workspace->bond_mark[j] + 1;

            //fprintf( stdout, "%d%d - %d(%d) %d(%d) new\n",
            // i , j, i, workspace->bond_mark[i], j, workspace->bond_mark[j] );
          }
        }
      }
      Set_End_Index( i, btop_i, bonds );
    }
    }*/

  workspace->realloc.Htop = Htop;
  workspace->realloc.num_bonds = num_bonds;
  workspace->realloc.num_hbonds = num_hbonds;

#if defined(DEBUG_FOCUS)
  fprintf( stderr, "p%d @ step%d: Htop = %d num_bonds = %d num_hbonds = %d\n",
           system->my_rank, data->step, Htop, num_bonds, num_hbonds );
  MPI_Barrier( comm );
#endif
#if defined( DEBUG )
  Print_Bonds( system, bonds, "debugbonds.out" );
  Print_Bond_List2( system, bonds, "pbonds.out" );
  Print_Sparse_Matrix( system, H );
  for( i = 0; i < H->n; ++i )
    for( j = H->start[i]; j < H->end[i]; ++j )
      fprintf( stderr, "%d %d %.15e\n",
               MIN(system->my_atoms[i].orig_id,
                   system->my_atoms[H->entries[j].j].orig_id),
               MAX(system->my_atoms[i].orig_id,
                   system->my_atoms[H->entries[j].j].orig_id),
               H->entries[j].val );
#endif

  Validate_Lists( system, workspace, lists, data->step,
                  system->n, system->N, system->numH, comm );
}
Exemple #23
0
void Init_Forces(reax_system *system, control_params *control,
		simulation_data *data, static_storage *workspace, list **lists,
		output_controls *out_control) {
	int i, j, pj;
	int start_i, end_i;
	int type_i, type_j;
	int Htop, btop_i, btop_j, num_bonds, num_hbonds;
	int ihb, jhb, ihb_top, jhb_top;
	int flag;
	real r_ij, r2, self_coef;
	real dr3gamij_1, dr3gamij_3, Tap;
	//real val, dif, base;
	real C12, C34, C56;
	real Cln_BOp_s, Cln_BOp_pi, Cln_BOp_pi2;
	real BO, BO_s, BO_pi, BO_pi2;
	real p_boc1, p_boc2;
	sparse_matrix *H;
	list *far_nbrs, *bonds, *hbonds;
	single_body_parameters *sbp_i, *sbp_j;
	two_body_parameters *twbp;
	far_neighbor_data *nbr_pj;
	//LR_lookup_table *t;
	reax_atom *atom_i, *atom_j;
	bond_data *ibond, *jbond;
	bond_order_data *bo_ij, *bo_ji;

	far_nbrs = *lists + FAR_NBRS;
	bonds = *lists + BONDS;
	hbonds = *lists + HBONDS;

	H = workspace->H;
	Htop = 0;
	num_bonds = 0;
	num_hbonds = 0;
	btop_i = btop_j = 0;
	p_boc1 = system->reaxprm.gp.l[0];
	p_boc2 = system->reaxprm.gp.l[1];

	for (i = 0; i < system->N; ++i) {
		atom_i = &(system->atoms[i]);
		type_i = atom_i->type;
		start_i = Start_Index(i, far_nbrs);
		end_i = End_Index(i, far_nbrs);
		H->start[i] = Htop;
		btop_i = End_Index(i, bonds);
		sbp_i = &(system->reaxprm.sbp[type_i]);
		ihb = ihb_top = -1;
		if (control->hb_cut > 0 && (ihb = sbp_i->p_hbond) == 1)
			ihb_top = End_Index(workspace->hbond_index[i], hbonds);

		for (pj = start_i; pj < end_i; ++pj) {
			nbr_pj = &(far_nbrs->select.far_nbr_list[pj]);
			j = nbr_pj->nbr;
			atom_j = &(system->atoms[j]);

			flag = 0;
			if ((data->step - data->prev_steps) % control->reneighbor == 0) {
				if (nbr_pj->d <= control->r_cut)
					flag = 1;
				else
					flag = 0;
			} else if ((nbr_pj->d = Sq_Distance_on_T3(atom_i->x, atom_j->x,
					&(system->box), nbr_pj->dvec)) <= SQR(control->r_cut)) {
				nbr_pj->d = sqrt(nbr_pj->d);
				flag = 1;
			}

			if (flag) {
				type_j = system->atoms[j].type;
				r_ij = nbr_pj->d;
				sbp_j = &(system->reaxprm.sbp[type_j]);
				twbp = &(system->reaxprm.tbp[type_i][type_j]);
				self_coef = (i == j) ? 0.5 : 1.0;

				/* H matrix entry */
				Tap = control->Tap7 * r_ij + control->Tap6;
				Tap = Tap * r_ij + control->Tap5;
				Tap = Tap * r_ij + control->Tap4;
				Tap = Tap * r_ij + control->Tap3;
				Tap = Tap * r_ij + control->Tap2;
				Tap = Tap * r_ij + control->Tap1;
				Tap = Tap * r_ij + control->Tap0;

				dr3gamij_1 = (r_ij * r_ij * r_ij + twbp->gamma);
				dr3gamij_3 = POW(dr3gamij_1, 0.33333333333333);

				H->entries[Htop].j = j;
				H->entries[Htop].val = self_coef * Tap * EV_to_KCALpMOL
						/ dr3gamij_3;
				++Htop;

				/* hydrogen bond lists */
				if (control->hb_cut > 0 && (ihb == 1 || ihb == 2) && nbr_pj->d
						<= control->hb_cut) {
					// fprintf( stderr, "%d %d\n", atom1, atom2 );
					jhb = sbp_j->p_hbond;
					if (ihb == 1 && jhb == 2) {
						hbonds->select.hbond_list[ihb_top].nbr = j;
						hbonds->select.hbond_list[ihb_top].scl = 1;
						hbonds->select.hbond_list[ihb_top].ptr = nbr_pj;
						++ihb_top;
						++num_hbonds;
					} else if (ihb == 2 && jhb == 1) {
						jhb_top = End_Index(workspace->hbond_index[j], hbonds);
						hbonds->select.hbond_list[jhb_top].nbr = i;
						hbonds->select.hbond_list[jhb_top].scl = -1;
						hbonds->select.hbond_list[jhb_top].ptr = nbr_pj;
						Set_End_Index(workspace->hbond_index[j], jhb_top + 1,
								hbonds);
						++num_hbonds;
					}
				}

				/* uncorrected bond orders */
				if (far_nbrs->select.far_nbr_list[pj].d <= control->nbr_cut) {
					r2 = SQR(r_ij);

					if (sbp_i->r_s > 0.0 && sbp_j->r_s > 0.0) {
						C12 = twbp->p_bo1 * POW(r_ij / twbp->r_s, twbp->p_bo2);
						BO_s = (1.0 + control->bo_cut) * EXP(C12);
					} else
						BO_s = C12 = 0.0;

					if (sbp_i->r_pi > 0.0 && sbp_j->r_pi > 0.0) {
						C34 = twbp->p_bo3 * POW(r_ij / twbp->r_p, twbp->p_bo4);
						BO_pi = EXP(C34);
					} else
						BO_pi = C34 = 0.0;

					if (sbp_i->r_pi_pi > 0.0 && sbp_j->r_pi_pi > 0.0) {
						C56 = twbp->p_bo5 * POW(r_ij / twbp->r_pp, twbp->p_bo6);
						BO_pi2 = EXP(C56);
					} else
						BO_pi2 = C56 = 0.0;

					/* Initially BO values are the uncorrected ones, page 1 */
					BO = BO_s + BO_pi + BO_pi2;

					if (BO >= control->bo_cut) {
						num_bonds += 2;
						/****** bonds i-j and j-i ******/
						ibond = &(bonds->select.bond_list[btop_i]);
						btop_j = End_Index(j, bonds);
						jbond = &(bonds->select.bond_list[btop_j]);

						ibond->nbr = j;
						jbond->nbr = i;
						ibond->d = r_ij;
						jbond->d = r_ij;
						rvec_Copy(ibond->dvec, nbr_pj->dvec);
						rvec_Scale(jbond->dvec, -1, nbr_pj->dvec);
						ivec_Copy(ibond->rel_box, nbr_pj->rel_box);
						ivec_Scale(jbond->rel_box, -1, nbr_pj->rel_box);
						ibond->dbond_index = btop_i;
						jbond->dbond_index = btop_i;
						ibond->sym_index = btop_j;
						jbond->sym_index = btop_i;
						++btop_i;
						Set_End_Index(j, btop_j + 1, bonds);

						bo_ij = &(ibond->bo_data);
						bo_ji = &(jbond->bo_data);
						bo_ji->BO = bo_ij->BO = BO;
						bo_ji->BO_s = bo_ij->BO_s = BO_s;
						bo_ji->BO_pi = bo_ij->BO_pi = BO_pi;
						bo_ji->BO_pi2 = bo_ij->BO_pi2 = BO_pi2;

						/* Bond Order page2-3, derivative of total bond order prime */
						Cln_BOp_s = twbp->p_bo2 * C12 / r2;
						Cln_BOp_pi = twbp->p_bo4 * C34 / r2;
						Cln_BOp_pi2 = twbp->p_bo6 * C56 / r2;

						/* Only dln_BOp_xx wrt. dr_i is stored here, note that
						 dln_BOp_xx/dr_i = -dln_BOp_xx/dr_j and all others are 0 */
						rvec_Scale(bo_ij->dln_BOp_s, -bo_ij->BO_s * Cln_BOp_s,
								ibond->dvec);
						rvec_Scale(bo_ij->dln_BOp_pi, -bo_ij->BO_pi
								* Cln_BOp_pi, ibond->dvec);
						rvec_Scale(bo_ij->dln_BOp_pi2, -bo_ij->BO_pi2
								* Cln_BOp_pi2, ibond->dvec);
						rvec_Scale(bo_ji->dln_BOp_s, -1., bo_ij->dln_BOp_s);
						rvec_Scale(bo_ji->dln_BOp_pi, -1., bo_ij->dln_BOp_pi);
						rvec_Scale(bo_ji->dln_BOp_pi2, -1., bo_ij->dln_BOp_pi2);

						/* Only dBOp wrt. dr_i is stored here, note that
						 dBOp/dr_i = -dBOp/dr_j and all others are 0 */
						rvec_Scale(bo_ij->dBOp, -(bo_ij->BO_s * Cln_BOp_s
								+ bo_ij->BO_pi * Cln_BOp_pi + bo_ij->BO_pi2
								* Cln_BOp_pi2), ibond->dvec);
						rvec_Scale(bo_ji->dBOp, -1., bo_ij->dBOp);

						rvec_Add(workspace->dDeltap_self[i], bo_ij->dBOp);
						rvec_Add(workspace->dDeltap_self[j], bo_ji->dBOp);

						bo_ij->BO_s -= control->bo_cut;
						bo_ij->BO -= control->bo_cut;
						bo_ji->BO_s -= control->bo_cut;
						bo_ji->BO -= control->bo_cut;
						workspace->total_bond_order[i] += bo_ij->BO; //currently total_BOp
						workspace->total_bond_order[j] += bo_ji->BO; //currently total_BOp
						bo_ij->Cdbo = bo_ij->Cdbopi = bo_ij->Cdbopi2 = 0.0;
						bo_ji->Cdbo = bo_ji->Cdbopi = bo_ji->Cdbopi2 = 0.0;

						/*fprintf( stderr, "%d %d %g %g %g\n",
						 i+1, j+1, bo_ij->BO, bo_ij->BO_pi, bo_ij->BO_pi2 );*/

						/*fprintf( stderr, "Cln_BOp_s: %f, pbo2: %f, C12:%f\n",
						 Cln_BOp_s, twbp->p_bo2, C12 );
						 fprintf( stderr, "Cln_BOp_pi: %f, pbo4: %f, C34:%f\n",
						 Cln_BOp_pi, twbp->p_bo4, C34 );
						 fprintf( stderr, "Cln_BOp_pi2: %f, pbo6: %f, C56:%f\n",
						 Cln_BOp_pi2, twbp->p_bo6, C56 );*/
						/*fprintf(stderr, "pbo1: %f, pbo2:%f\n", twbp->p_bo1, twbp->p_bo2);
						 fprintf(stderr, "pbo3: %f, pbo4:%f\n", twbp->p_bo3, twbp->p_bo4);
						 fprintf(stderr, "pbo5: %f, pbo6:%f\n", twbp->p_bo5, twbp->p_bo6);
						 fprintf( stderr, "r_s: %f, r_p: %f, r_pp: %f\n",
						 twbp->r_s, twbp->r_p, twbp->r_pp );
						 fprintf( stderr, "C12: %g, C34:%g, C56:%g\n", C12, C34, C56 );*/

						/*fprintf( stderr, "\tfactors: %g %g %g\n",
						 -(bo_ij->BO_s * Cln_BOp_s + bo_ij->BO_pi * Cln_BOp_pi +
						 bo_ij->BO_pi2 * Cln_BOp_pp),
						 -bo_ij->BO_pi * Cln_BOp_pi, -bo_ij->BO_pi2 * Cln_BOp_pi2 );*/
						/*fprintf( stderr, "dBOpi:\t[%g, %g, %g]\n",
						 bo_ij->dBOp[0], bo_ij->dBOp[1], bo_ij->dBOp[2] );
						 fprintf( stderr, "dBOpi:\t[%g, %g, %g]\n",
						 bo_ij->dln_BOp_pi[0], bo_ij->dln_BOp_pi[1],
						 bo_ij->dln_BOp_pi[2] );
						 fprintf( stderr, "dBOpi2:\t[%g, %g, %g]\n\n",
						 bo_ij->dln_BOp_pi2[0], bo_ij->dln_BOp_pi2[1],
						 bo_ij->dln_BOp_pi2[2] );*/

						Set_End_Index(j, btop_j + 1, bonds);
					}
				}
			}
		}

		H->entries[Htop].j = i;
		H->entries[Htop].val = system->reaxprm.sbp[type_i].eta;
		++Htop;

		Set_End_Index(i, btop_i, bonds);
		if (ihb == 1)
			Set_End_Index(workspace->hbond_index[i], ihb_top, hbonds);
		//fprintf( stderr, "%d bonds start: %d, end: %d\n",
		//     i, Start_Index( i, bonds ), End_Index( i, bonds ) );
	}

	// mark the end of j list
	H->start[i] = Htop;
	/* validate lists - decide if reallocation is required! */
	Validate_Lists(workspace, lists, data->step, system->N, H->m, Htop,
			num_bonds, num_hbonds);

#if defined(DEBUG_FOCUS)
	fprintf( stderr, "step%d: Htop = %d, num_bonds = %d, num_hbonds = %d\n",
			data->step, Htop, num_bonds, num_hbonds );

#endif
}
void Atom_Energy( reax_system *system, control_params *control,
                  simulation_data *data, storage *workspace, reax_list **lists,
                  output_controls *out_control )
{
  int i, j, pj, type_i, type_j;
  real Delta_lpcorr, dfvl;
  real e_lp, expvd2, inv_expvd2, dElp, CElp, DlpVi;
  real e_lph, Di, vov3, deahu2dbo, deahu2dsbo;
  real e_ov, CEover1, CEover2, CEover3, CEover4;
  real exp_ovun1, exp_ovun2, sum_ovun1, sum_ovun2;
  real exp_ovun2n, exp_ovun6, exp_ovun8;
  real inv_exp_ovun1, inv_exp_ovun2, inv_exp_ovun2n, inv_exp_ovun8;
  real e_un, CEunder1, CEunder2, CEunder3, CEunder4;
  real p_lp2, p_lp3;
  real p_ovun2, p_ovun3, p_ovun4, p_ovun5, p_ovun6, p_ovun7, p_ovun8;
  real eng_tmp;
  int numbonds;

  single_body_parameters *sbp_i;
  two_body_parameters *twbp;
  bond_data *pbond;
  bond_order_data *bo_ij;
  reax_list *bonds = (*lists) + BONDS;

  /* Initialize parameters */
  p_lp3 = system->reax_param.gp.l[5];
  p_ovun3 = system->reax_param.gp.l[32];
  p_ovun4 = system->reax_param.gp.l[31];
  p_ovun6 = system->reax_param.gp.l[6];
  p_ovun7 = system->reax_param.gp.l[8];
  p_ovun8 = system->reax_param.gp.l[9];

  for( i = 0; i < system->n; ++i ) {
    /* set the parameter pointer */
    type_i = system->my_atoms[i].type;
    if (type_i < 0) continue;
    sbp_i = &(system->reax_param.sbp[ type_i ]);

    /* lone-pair Energy */
    p_lp2 = sbp_i->p_lp2;
    expvd2 = exp( -75 * workspace->Delta_lp[i] );
    inv_expvd2 = 1. / (1. + expvd2 );

    numbonds = 0;
    e_lp = 0.0;
    for( pj = Start_Index(i, bonds); pj < End_Index(i, bonds); ++pj )
      numbonds ++;

    /* calculate the energy */
    if (numbonds > 0)
      data->my_en.e_lp += e_lp =
        p_lp2 * workspace->Delta_lp[i] * inv_expvd2;

    dElp = p_lp2 * inv_expvd2 +
      75 * p_lp2 * workspace->Delta_lp[i] * expvd2 * SQR(inv_expvd2);
    CElp = dElp * workspace->dDelta_lp[i];

    if (numbonds > 0) workspace->CdDelta[i] += CElp;  // lp - 1st term

    /* tally into per-atom energy */
    if( system->pair_ptr->evflag)
      system->pair_ptr->ev_tally(i,i,system->n,1,e_lp,0.0,0.0,0.0,0.0,0.0);

    /* correction for C2 */
    if( p_lp3 > 0.001 && !strcmp(system->reax_param.sbp[type_i].name, "C") )
      for( pj = Start_Index(i, bonds); pj < End_Index(i, bonds); ++pj ) {
        j = bonds->select.bond_list[pj].nbr;
        type_j = system->my_atoms[j].type;
	if (type_j < 0) continue;

        if( !strcmp( system->reax_param.sbp[type_j].name, "C" ) ) {
          twbp = &( system->reax_param.tbp[type_i][type_j]);
          bo_ij = &( bonds->select.bond_list[pj].bo_data );
          Di = workspace->Delta[i];
          vov3 = bo_ij->BO - Di - 0.040*pow(Di, 4.);

          if( vov3 > 3. ) {
            data->my_en.e_lp += e_lph = p_lp3 * SQR(vov3-3.0);

            deahu2dbo = 2.*p_lp3*(vov3 - 3.);
            deahu2dsbo = 2.*p_lp3*(vov3 - 3.)*(-1. - 0.16*pow(Di, 3.));

            bo_ij->Cdbo += deahu2dbo;
            workspace->CdDelta[i] += deahu2dsbo;

            /* tally into per-atom energy */
            if( system->pair_ptr->evflag)
              system->pair_ptr->ev_tally(i,j,system->n,1,e_lph,0.0,0.0,0.0,0.0,0.0);

          }
        }
      }
  }


  for( i = 0; i < system->n; ++i ) {
    type_i = system->my_atoms[i].type;
    if (type_i < 0) continue;
    sbp_i = &(system->reax_param.sbp[ type_i ]);

    /* over-coordination energy */
    if( sbp_i->mass > 21.0 )
      dfvl = 0.0;
    else dfvl = 1.0; // only for 1st-row elements

    p_ovun2 = sbp_i->p_ovun2;
    sum_ovun1 = sum_ovun2 = 0;
    for( pj = Start_Index(i, bonds); pj < End_Index(i, bonds); ++pj ) {
        j = bonds->select.bond_list[pj].nbr;
        type_j = system->my_atoms[j].type;
	if (type_j < 0) continue;
        bo_ij = &(bonds->select.bond_list[pj].bo_data);
        twbp = &(system->reax_param.tbp[ type_i ][ type_j ]);

        sum_ovun1 += twbp->p_ovun1 * twbp->De_s * bo_ij->BO;
        sum_ovun2 += (workspace->Delta[j] - dfvl*workspace->Delta_lp_temp[j])*
          ( bo_ij->BO_pi + bo_ij->BO_pi2 );

      }

    exp_ovun1 = p_ovun3 * exp( p_ovun4 * sum_ovun2 );
    inv_exp_ovun1 = 1.0 / (1 + exp_ovun1);
    Delta_lpcorr  = workspace->Delta[i] -
      (dfvl * workspace->Delta_lp_temp[i]) * inv_exp_ovun1;

    exp_ovun2 = exp( p_ovun2 * Delta_lpcorr );
    inv_exp_ovun2 = 1.0 / (1.0 + exp_ovun2);

    DlpVi = 1.0 / (Delta_lpcorr + sbp_i->valency + 1e-8);
    CEover1 = Delta_lpcorr * DlpVi * inv_exp_ovun2;

    data->my_en.e_ov += e_ov = sum_ovun1 * CEover1;

    CEover2 = sum_ovun1 * DlpVi * inv_exp_ovun2 *
      (1.0 - Delta_lpcorr * ( DlpVi + p_ovun2 * exp_ovun2 * inv_exp_ovun2 ));

    CEover3 = CEover2 * (1.0 - dfvl * workspace->dDelta_lp[i] * inv_exp_ovun1 );

    CEover4 = CEover2 * (dfvl * workspace->Delta_lp_temp[i]) *
      p_ovun4 * exp_ovun1 * SQR(inv_exp_ovun1);


    /* under-coordination potential */
    p_ovun2 = sbp_i->p_ovun2;
    p_ovun5 = sbp_i->p_ovun5;

    exp_ovun2n = 1.0 / exp_ovun2;
    exp_ovun6 = exp( p_ovun6 * Delta_lpcorr );
    exp_ovun8 = p_ovun7 * exp(p_ovun8 * sum_ovun2);
    inv_exp_ovun2n = 1.0 / (1.0 + exp_ovun2n);
    inv_exp_ovun8 = 1.0 / (1.0 + exp_ovun8);

    numbonds = 0;
    e_un = 0.0;
    for( pj = Start_Index(i, bonds); pj < End_Index(i, bonds); ++pj )
      numbonds ++;

    if (numbonds > 0)
      data->my_en.e_un += e_un =
        -p_ovun5 * (1.0 - exp_ovun6) * inv_exp_ovun2n * inv_exp_ovun8;

    CEunder1 = inv_exp_ovun2n *
      ( p_ovun5 * p_ovun6 * exp_ovun6 * inv_exp_ovun8 +
        p_ovun2 * e_un * exp_ovun2n );
    CEunder2 = -e_un * p_ovun8 * exp_ovun8 * inv_exp_ovun8;
    CEunder3 = CEunder1 * (1.0 - dfvl*workspace->dDelta_lp[i]*inv_exp_ovun1);
    CEunder4 = CEunder1 * (dfvl*workspace->Delta_lp_temp[i]) *
      p_ovun4 * exp_ovun1 * SQR(inv_exp_ovun1) + CEunder2;

    /* tally into per-atom energy */
    if( system->pair_ptr->evflag) {
      eng_tmp = e_ov;
      if (numbonds > 0) eng_tmp += e_un;
      system->pair_ptr->ev_tally(i,i,system->n,1,eng_tmp,0.0,0.0,0.0,0.0,0.0);
    }

    /* forces */
    workspace->CdDelta[i] += CEover3;   // OvCoor - 2nd term
    if (numbonds > 0) workspace->CdDelta[i] += CEunder3;  // UnCoor - 1st term

    for( pj = Start_Index(i, bonds); pj < End_Index(i, bonds); ++pj ) {
      pbond = &(bonds->select.bond_list[pj]);
      j = pbond->nbr;
      bo_ij = &(pbond->bo_data);
      twbp  = &(system->reax_param.tbp[ system->my_atoms[i].type ]
                [system->my_atoms[pbond->nbr].type]);


      bo_ij->Cdbo += CEover1 * twbp->p_ovun1 * twbp->De_s;// OvCoor-1st
      workspace->CdDelta[j] += CEover4 * (1.0 - dfvl*workspace->dDelta_lp[j]) *
        (bo_ij->BO_pi + bo_ij->BO_pi2); // OvCoor-3a
      bo_ij->Cdbopi += CEover4 *
        (workspace->Delta[j] - dfvl*workspace->Delta_lp_temp[j]); // OvCoor-3b
      bo_ij->Cdbopi2 += CEover4 *
        (workspace->Delta[j] - dfvl*workspace->Delta_lp_temp[j]);  // OvCoor-3b


      workspace->CdDelta[j] += CEunder4 * (1.0 - dfvl*workspace->dDelta_lp[j]) *
        (bo_ij->BO_pi + bo_ij->BO_pi2);   // UnCoor - 2a
      bo_ij->Cdbopi += CEunder4 *
        (workspace->Delta[j] - dfvl*workspace->Delta_lp_temp[j]);  // UnCoor-2b
      bo_ij->Cdbopi2 += CEunder4 *
        (workspace->Delta[j] - dfvl*workspace->Delta_lp_temp[j]);  // UnCoor-2b

    }

  }
}
void Tabulated_vdW_Coulomb_Energy( reax_system *system,control_params *control,
                                   simulation_data *data, storage *workspace,
                                   reax_list **lists,
                                   output_controls *out_control )
{
  int i, j, pj, r, natoms;
  int type_i, type_j, tmin, tmax;
  int start_i, end_i, flag;
  rc_tagint orig_i, orig_j;
  double r_ij, base, dif;
  double e_vdW, e_ele;
  double CEvd, CEclmb, SMALL = 0.0001;
  double f_tmp, delij[3];

  rvec temp, ext_press;
  far_neighbor_data *nbr_pj;
  reax_list *far_nbrs;
  LR_lookup_table *t;

  natoms = system->n;
  far_nbrs = (*lists) + FAR_NBRS;

  e_ele = e_vdW = 0;

  for( i = 0; i < natoms; ++i ) {
    type_i  = system->my_atoms[i].type;
    if (type_i < 0) continue;
    start_i = Start_Index(i,far_nbrs);
    end_i   = End_Index(i,far_nbrs);
    orig_i  = system->my_atoms[i].orig_id;

    for( pj = start_i; pj < end_i; ++pj ) {
      nbr_pj = &(far_nbrs->select.far_nbr_list[pj]);
      j = nbr_pj->nbr;
      type_j = system->my_atoms[j].type;
      if (type_j < 0) continue;
      orig_j  = system->my_atoms[j].orig_id;

      flag = 0;
      if(nbr_pj->d <= control->nonb_cut) {
        if (j < natoms) flag = 1;
        else if (orig_i < orig_j) flag = 1;
        else if (orig_i == orig_j) {
          if (nbr_pj->dvec[2] > SMALL) flag = 1;
          else if (fabs(nbr_pj->dvec[2]) < SMALL) {
            if (nbr_pj->dvec[1] > SMALL) flag = 1;
            else if (fabs(nbr_pj->dvec[1]) < SMALL && nbr_pj->dvec[0] > SMALL)
              flag = 1;
          }
        }
      }

      if (flag) {

      r_ij   = nbr_pj->d;
      tmin  = MIN( type_i, type_j );
      tmax  = MAX( type_i, type_j );
      t = &( LR[tmin][tmax] );

      /* Cubic Spline Interpolation */
      r = (int)(r_ij * t->inv_dx);
      if( r == 0 )  ++r;
      base = (double)(r+1) * t->dx;
      dif = r_ij - base;

      e_vdW = ((t->vdW[r].d*dif + t->vdW[r].c)*dif + t->vdW[r].b)*dif +
        t->vdW[r].a;

      e_ele = ((t->ele[r].d*dif + t->ele[r].c)*dif + t->ele[r].b)*dif +
        t->ele[r].a;
      e_ele *= system->my_atoms[i].q * system->my_atoms[j].q;

      data->my_en.e_vdW += e_vdW;
      data->my_en.e_ele += e_ele;

      CEvd = ((t->CEvd[r].d*dif + t->CEvd[r].c)*dif + t->CEvd[r].b)*dif +
        t->CEvd[r].a;

      CEclmb = ((t->CEclmb[r].d*dif+t->CEclmb[r].c)*dif+t->CEclmb[r].b)*dif +
        t->CEclmb[r].a;
      CEclmb *= system->my_atoms[i].q * system->my_atoms[j].q;

      /* tally into per-atom energy */
      if( system->pair_ptr->evflag || system->pair_ptr->vflag_atom) {
        rvec_ScaledSum( delij, 1., system->my_atoms[i].x,
                              -1., system->my_atoms[j].x );
        f_tmp = -(CEvd + CEclmb);
        system->pair_ptr->ev_tally(i,j,natoms,1,e_vdW,e_ele,
                        f_tmp,delij[0],delij[1],delij[2]);
      }

      if( control->virial == 0 ) {
        rvec_ScaledAdd( workspace->f[i], -(CEvd + CEclmb), nbr_pj->dvec );
        rvec_ScaledAdd( workspace->f[j], +(CEvd + CEclmb), nbr_pj->dvec );
      }
      else { // NPT, iNPT or sNPT
        rvec_Scale( temp, CEvd + CEclmb, nbr_pj->dvec );

        rvec_ScaledAdd( workspace->f[i], -1., temp );
        rvec_Add( workspace->f[j], temp );

        rvec_iMultiply( ext_press, nbr_pj->rel_box, temp );
        rvec_Add( data->my_ext_press, ext_press );
      }
      }
    }
  }

  Compute_Polarization_Energy( system, data );
}
void Init_Forces_noQEq( reax_system *system, control_params *control,
                        simulation_data *data, storage *workspace,
                        reax_list **lists, output_controls *out_control,
                        MPI_Comm comm ) {
  int i, j, pj;
  int start_i, end_i;
  int type_i, type_j;
  int btop_i, btop_j, num_bonds, num_hbonds;
  int ihb, jhb, ihb_top, jhb_top;
  int local, flag, renbr;
  double cutoff;
  reax_list *far_nbrs, *bonds, *hbonds;
  single_body_parameters *sbp_i, *sbp_j;
  two_body_parameters *twbp;
  far_neighbor_data *nbr_pj;
  reax_atom *atom_i, *atom_j;

  far_nbrs = *lists + FAR_NBRS;
  bonds = *lists + BONDS;
  hbonds = *lists + HBONDS;

  for( i = 0; i < system->n; ++i )
    workspace->bond_mark[i] = 0;
  for( i = system->n; i < system->N; ++i ) {
    workspace->bond_mark[i] = 1000; // put ghost atoms to an infinite distance
  }

  num_bonds = 0;
  num_hbonds = 0;
  btop_i = btop_j = 0;
  renbr = (data->step-data->prev_steps) % control->reneighbor == 0;

  for( i = 0; i < system->N; ++i ) {
    atom_i = &(system->my_atoms[i]);
    type_i  = atom_i->type;
    if (type_i < 0) continue;
    start_i = Start_Index(i, far_nbrs);
    end_i   = End_Index(i, far_nbrs);
    btop_i = End_Index( i, bonds );
    sbp_i = &(system->reax_param.sbp[type_i]);

    if( i < system->n ) {
      local = 1;
      cutoff = MAX( control->hbond_cut, control->bond_cut );
    }
    else {
      local = 0;
      cutoff = control->bond_cut;
    }

    ihb = -1;
    ihb_top = -1;
    if( local && control->hbond_cut > 0 ) {
      ihb = sbp_i->p_hbond;
      if( ihb == 1 )
        ihb_top = End_Index( atom_i->Hindex, hbonds );
      else ihb_top = -1;
    }

    /* update i-j distance - check if j is within cutoff */
    for( pj = start_i; pj < end_i; ++pj ) {
      nbr_pj = &( far_nbrs->select.far_nbr_list[pj] );
      j = nbr_pj->nbr;
      atom_j = &(system->my_atoms[j]);

      if( renbr ) {
        if( nbr_pj->d <= cutoff )
          flag = 1;
        else flag = 0;
      }
      else{
        nbr_pj->dvec[0] = atom_j->x[0] - atom_i->x[0];
        nbr_pj->dvec[1] = atom_j->x[1] - atom_i->x[1];
        nbr_pj->dvec[2] = atom_j->x[2] - atom_i->x[2];
        nbr_pj->d = rvec_Norm_Sqr( nbr_pj->dvec );
        if( nbr_pj->d <= SQR(cutoff) ) {
          nbr_pj->d = sqrt(nbr_pj->d);
          flag = 1;
        }
        else {
          flag = 0;
        }
      }

      if( flag ) {
        type_j = atom_j->type;
	if (type_j < 0) continue;
        sbp_j = &(system->reax_param.sbp[type_j]);
        twbp = &(system->reax_param.tbp[type_i][type_j]);

        if( local ) {
          /* hydrogen bond lists */
          if( control->hbond_cut > 0 && (ihb==1 || ihb==2) &&
              nbr_pj->d <= control->hbond_cut ) {
            // fprintf( stderr, "%d %d\n", atom1, atom2 );
            jhb = sbp_j->p_hbond;
            if( ihb == 1 && jhb == 2 ) {
              hbonds->select.hbond_list[ihb_top].nbr = j;
              hbonds->select.hbond_list[ihb_top].scl = 1;
              hbonds->select.hbond_list[ihb_top].ptr = nbr_pj;
              ++ihb_top;
              ++num_hbonds;
            }
            else if( j < system->n && ihb == 2 && jhb == 1 ) {
              jhb_top = End_Index( atom_j->Hindex, hbonds );
              hbonds->select.hbond_list[jhb_top].nbr = i;
              hbonds->select.hbond_list[jhb_top].scl = -1;
              hbonds->select.hbond_list[jhb_top].ptr = nbr_pj;
              Set_End_Index( atom_j->Hindex, jhb_top+1, hbonds );
              ++num_hbonds;
            }
          }
        }

        if( //(workspace->bond_mark[i] < 3 || workspace->bond_mark[j] < 3) &&
            nbr_pj->d <= control->bond_cut &&
            BOp( workspace, bonds, control->bo_cut,
                 i , btop_i, nbr_pj, sbp_i, sbp_j, twbp ) ) {
          num_bonds += 2;
          ++btop_i;

          if( workspace->bond_mark[j] > workspace->bond_mark[i] + 1 )
            workspace->bond_mark[j] = workspace->bond_mark[i] + 1;
          else if( workspace->bond_mark[i] > workspace->bond_mark[j] + 1 ) {
            workspace->bond_mark[i] = workspace->bond_mark[j] + 1;
          }
        }
      }
    }

    Set_End_Index( i, btop_i, bonds );
    if( local && ihb == 1 )
      Set_End_Index( atom_i->Hindex, ihb_top, hbonds );
  }


  workspace->realloc.num_bonds = num_bonds;
  workspace->realloc.num_hbonds = num_hbonds;

  Validate_Lists( system, workspace, lists, data->step,
                  system->n, system->N, system->numH, comm );
}
Exemple #27
0
void Bonds( reax_system *system, control_params *control,
            simulation_data *data, storage *workspace, reax_list **lists,
            output_controls *out_control )
{
  int i, j, pj, natoms;
  int start_i, end_i;
  int type_i, type_j;
  double ebond, pow_BOs_be2, exp_be12, CEbo;
  double gp3, gp4, gp7, gp10, gp37;
  double exphu, exphua1, exphub1, exphuov, hulpov, estriph;
  double decobdbo, decobdboua, decobdboub;
  single_body_parameters *sbp_i, *sbp_j;
  two_body_parameters *twbp;
  bond_order_data *bo_ij;
  reax_list *bonds;

  bonds = (*lists) + BONDS;
  gp3 = system->reax_param.gp.l[3];
  gp4 = system->reax_param.gp.l[4];
  gp7 = system->reax_param.gp.l[7];
  gp10 = system->reax_param.gp.l[10];
  gp37 = (int) system->reax_param.gp.l[37];
  natoms = system->n;

  for( i = 0; i < natoms; ++i ) {
    start_i = Start_Index(i, bonds);
    end_i = End_Index(i, bonds);

    for( pj = start_i; pj < end_i; ++pj ) {
      j = bonds->select.bond_list[pj].nbr;

      if( system->my_atoms[i].orig_id > system->my_atoms[j].orig_id )
	continue;
      if( system->my_atoms[i].orig_id == system->my_atoms[j].orig_id ) {
        if (system->my_atoms[j].x[2] <  system->my_atoms[i].x[2]) continue;
      	if (system->my_atoms[j].x[2] == system->my_atoms[i].x[2] &&
      	    system->my_atoms[j].x[1] <  system->my_atoms[i].x[1]) continue;
        if (system->my_atoms[j].x[2] == system->my_atoms[i].x[2] &&
      	    system->my_atoms[j].x[1] == system->my_atoms[i].x[1] &&
      	    system->my_atoms[j].x[0] <  system->my_atoms[i].x[0]) continue;
      }

      /* set the pointers */
      type_i = system->my_atoms[i].type;
      type_j = system->my_atoms[j].type;
      sbp_i = &( system->reax_param.sbp[type_i] );
      sbp_j = &( system->reax_param.sbp[type_j] );
      twbp = &( system->reax_param.tbp[type_i][type_j] );
      bo_ij = &( bonds->select.bond_list[pj].bo_data );

      /* calculate the constants */
      pow_BOs_be2 = pow( bo_ij->BO_s, twbp->p_be2 );
      exp_be12 = exp( twbp->p_be1 * ( 1.0 - pow_BOs_be2 ) );
      CEbo = -twbp->De_s * exp_be12 *
	( 1.0 - twbp->p_be1 * twbp->p_be2 * pow_BOs_be2 );

      /* calculate the Bond Energy */
      data->my_en.e_bond += ebond =
	-twbp->De_s * bo_ij->BO_s * exp_be12
	-twbp->De_p * bo_ij->BO_pi
	-twbp->De_pp * bo_ij->BO_pi2;

      /* tally into per-atom energy */
      if( system->pair_ptr->evflag)
	system->pair_ptr->ev_tally(i,j,natoms,1,ebond,0.0,0.0,0.0,0.0,0.0);

      /* calculate derivatives of Bond Orders */
      bo_ij->Cdbo += CEbo;
      bo_ij->Cdbopi -= (CEbo + twbp->De_p);
      bo_ij->Cdbopi2 -= (CEbo + twbp->De_pp);

      /* Stabilisation terminal triple bond */
      if( bo_ij->BO >= 1.00 ) {
	if( gp37 == 2 ||
	    (sbp_i->mass == 12.0000 && sbp_j->mass == 15.9990) ||
	    (sbp_j->mass == 12.0000 && sbp_i->mass == 15.9990) ) {
	  exphu = exp( -gp7 * SQR(bo_ij->BO - 2.50) );
	  exphua1 = exp(-gp3 * (workspace->total_bond_order[i]-bo_ij->BO));
	  exphub1 = exp(-gp3 * (workspace->total_bond_order[j]-bo_ij->BO));
	  exphuov = exp(gp4 * (workspace->Delta[i] + workspace->Delta[j]));
	  hulpov = 1.0 / (1.0 + 25.0 * exphuov);

	  estriph = gp10 * exphu * hulpov * (exphua1 + exphub1);
	  data->my_en.e_bond += estriph;

	  decobdbo = gp10 * exphu * hulpov * (exphua1 + exphub1) *
	    ( gp3 - 2.0 * gp7 * (bo_ij->BO-2.50) );
	  decobdboua = -gp10 * exphu * hulpov *
	    (gp3*exphua1 + 25.0*gp4*exphuov*hulpov*(exphua1+exphub1));
	  decobdboub = -gp10 * exphu * hulpov *
	    (gp3*exphub1 + 25.0*gp4*exphuov*hulpov*(exphua1+exphub1));

	  /* tally into per-atom energy */
	  if( system->pair_ptr->evflag)
	    system->pair_ptr->ev_tally(i,j,natoms,1,estriph,0.0,0.0,0.0,0.0,0.0);

	  bo_ij->Cdbo += decobdbo;
	  workspace->CdDelta[i] += decobdboua;
	  workspace->CdDelta[j] += decobdboub;
	}
      }
    }
  }
}
void Estimate_Storages( reax_system *system, control_params *control,
                        reax_list **lists, int *Htop, int *hb_top,
                        int *bond_top, int *num_3body, MPI_Comm comm )
{
  int i, j, pj;
  int start_i, end_i;
  int type_i, type_j;
  int ihb, jhb;
  int local;
  double cutoff;
  double r_ij;
  double C12, C34, C56;
  double BO, BO_s, BO_pi, BO_pi2;
  reax_list *far_nbrs;
  single_body_parameters *sbp_i, *sbp_j;
  two_body_parameters *twbp;
  far_neighbor_data *nbr_pj;
  reax_atom *atom_i, *atom_j;

  int mincap = system->mincap;
  double safezone = system->safezone;
  double saferzone = system->saferzone;

  far_nbrs = *lists + FAR_NBRS;
  *Htop = 0;
  memset( hb_top, 0, sizeof(int) * system->local_cap );
  memset( bond_top, 0, sizeof(int) * system->total_cap );
  *num_3body = 0;

  for( i = 0; i < system->N; ++i ) {
    atom_i = &(system->my_atoms[i]);
    type_i  = atom_i->type;
    if (type_i < 0) continue;
    start_i = Start_Index(i, far_nbrs);
    end_i   = End_Index(i, far_nbrs);
    sbp_i = &(system->reax_param.sbp[type_i]);

    if( i < system->n ) {
      local = 1;
      cutoff = control->nonb_cut;
      ++(*Htop);
      ihb = sbp_i->p_hbond;
    }
    else {
      local = 0;
      cutoff = control->bond_cut;
      ihb = -1;
    }

    for( pj = start_i; pj < end_i; ++pj ) {
      nbr_pj = &( far_nbrs->select.far_nbr_list[pj] );
      j = nbr_pj->nbr;
      atom_j = &(system->my_atoms[j]);

      if(nbr_pj->d <= cutoff) {
        type_j = system->my_atoms[j].type;
        if (type_j < 0) continue;
        r_ij = nbr_pj->d;
        sbp_j = &(system->reax_param.sbp[type_j]);
        twbp = &(system->reax_param.tbp[type_i][type_j]);

        if( local ) {
          if( j < system->n || atom_i->orig_id < atom_j->orig_id ) //tryQEq ||1
            ++(*Htop);

          /* hydrogen bond lists */
          if( control->hbond_cut > 0.1 && (ihb==1 || ihb==2) &&
              nbr_pj->d <= control->hbond_cut ) {
            jhb = sbp_j->p_hbond;
            if( ihb == 1 && jhb == 2 )
              ++hb_top[i];
            else if( j < system->n && ihb == 2 && jhb == 1 )
              ++hb_top[j];
          }
        }

        /* uncorrected bond orders */
        if( nbr_pj->d <= control->bond_cut ) {
          if( sbp_i->r_s > 0.0 && sbp_j->r_s > 0.0) {
            C12 = twbp->p_bo1 * pow( r_ij / twbp->r_s, twbp->p_bo2 );
            BO_s = (1.0 + control->bo_cut) * exp( C12 );
          }
          else BO_s = C12 = 0.0;

          if( sbp_i->r_pi > 0.0 && sbp_j->r_pi > 0.0) {
            C34 = twbp->p_bo3 * pow( r_ij / twbp->r_p, twbp->p_bo4 );
            BO_pi = exp( C34 );
          }
          else BO_pi = C34 = 0.0;

          if( sbp_i->r_pi_pi > 0.0 && sbp_j->r_pi_pi > 0.0) {
            C56 = twbp->p_bo5 * pow( r_ij / twbp->r_pp, twbp->p_bo6 );
            BO_pi2= exp( C56 );
          }
          else BO_pi2 = C56 = 0.0;

          /* Initially BO values are the uncorrected ones, page 1 */
          BO = BO_s + BO_pi + BO_pi2;

          if( BO >= control->bo_cut ) {
            ++bond_top[i];
            ++bond_top[j];
          }
        }
      }
    }
  }

  *Htop = (int)(MAX( *Htop * safezone, mincap * MIN_HENTRIES ));
  for( i = 0; i < system->n; ++i )
    hb_top[i] = (int)(MAX( hb_top[i] * saferzone, MIN_HBONDS ));

  for( i = 0; i < system->N; ++i ) {
    *num_3body += SQR(bond_top[i]);
    bond_top[i] = MAX( bond_top[i] * 2, MIN_BONDS );
  }

}
Exemple #29
0
void vdW_Coulomb_Energy( reax_system *system, control_params *control, 
			 simulation_data *data, storage *workspace, 
			 reax_list **lists, output_controls *out_control )
{
  int i, j, pj, natoms;
  int start_i, end_i, orig_i, orig_j;
  real p_vdW1, p_vdW1i;
  real powr_vdW1, powgi_vdW1;
  real tmp, r_ij, fn13, exp1, exp2;
  real Tap, dTap, dfn13, CEvd, CEclmb, de_core;
  real dr3gamij_1, dr3gamij_3;
  real e_ele, e_vdW, e_core;
  rvec temp, ext_press;
  two_body_parameters *twbp;
  far_neighbor_data *nbr_pj;
  reax_list *far_nbrs;
  // rtensor temp_rtensor, total_rtensor;

  natoms = system->n;
  far_nbrs = (*lists) + FAR_NBRS;
  p_vdW1 = system->reax_param.gp.l[28];
  p_vdW1i = 1.0 / p_vdW1;
  e_core = 0;
  e_vdW = 0;

  for( i = 0; i < natoms; ++i ) {
    start_i = Start_Index(i, far_nbrs);
    end_i   = End_Index(i, far_nbrs);
    orig_i  = system->my_atoms[i].orig_id;
    //fprintf( stderr, "i:%d, start_i: %d, end_i: %d\n", i, start_i, end_i );

    for( pj = start_i; pj < end_i; ++pj ) {
      nbr_pj = &(far_nbrs->select.far_nbr_list[pj]);
      j = nbr_pj->nbr;
      orig_j  = system->my_atoms[j].orig_id;

      if( nbr_pj->d <= control->nonb_cut && (j < natoms || orig_i < orig_j) ) {
	r_ij = nbr_pj->d;
	twbp = &(system->reax_param.tbp[ system->my_atoms[i].type ]
		                       [ system->my_atoms[j].type ]);

      /* Calculate Taper and its derivative */
      // Tap = nbr_pj->Tap;   -- precomputed during compte_H
      Tap = workspace->Tap[7] * r_ij + workspace->Tap[6];
      Tap = Tap * r_ij + workspace->Tap[5];
      Tap = Tap * r_ij + workspace->Tap[4];
      Tap = Tap * r_ij + workspace->Tap[3];
      Tap = Tap * r_ij + workspace->Tap[2];
      Tap = Tap * r_ij + workspace->Tap[1];
      Tap = Tap * r_ij + workspace->Tap[0];
	  
      dTap = 7*workspace->Tap[7] * r_ij + 6*workspace->Tap[6];
      dTap = dTap * r_ij + 5*workspace->Tap[5];
      dTap = dTap * r_ij + 4*workspace->Tap[4];
      dTap = dTap * r_ij + 3*workspace->Tap[3];
      dTap = dTap * r_ij + 2*workspace->Tap[2];
      dTap += workspace->Tap[1]/r_ij;

      /*vdWaals Calculations*/
      if(system->reax_param.gp.vdw_type==1 || system->reax_param.gp.vdw_type==3)
	{ // shielding
	  powr_vdW1 = pow(r_ij, p_vdW1);
	  powgi_vdW1 = pow( 1.0 / twbp->gamma_w, p_vdW1);
	
	  fn13 = pow( powr_vdW1 + powgi_vdW1, p_vdW1i );
	  exp1 = exp( twbp->alpha * (1.0 - fn13 / twbp->r_vdW) );
	  exp2 = exp( 0.5 * twbp->alpha * (1.0 - fn13 / twbp->r_vdW) );

	  e_vdW = twbp->D * (exp1 - 2.0 * exp2);	  
	  data->my_en.e_vdW += Tap * e_vdW;
	
	  dfn13 = pow( powr_vdW1 + powgi_vdW1, p_vdW1i - 1.0) * 
	    pow(r_ij, p_vdW1 - 2.0);
	  
	  CEvd = dTap * e_vdW - 
	    Tap * twbp->D * (twbp->alpha / twbp->r_vdW) * (exp1 - exp2) * dfn13;
	}
      else{ // no shielding
	exp1 = exp( twbp->alpha * (1.0 - r_ij / twbp->r_vdW) );
	exp2 = exp( 0.5 * twbp->alpha * (1.0 - r_ij / twbp->r_vdW) );
	
	e_vdW = twbp->D * (exp1 - 2.0 * exp2);
	data->my_en.e_vdW += Tap * e_vdW;

	CEvd = dTap * e_vdW - 
	  Tap * twbp->D * (twbp->alpha / twbp->r_vdW) * (exp1 - exp2) / r_ij;
      }

      if(system->reax_param.gp.vdw_type==2 || system->reax_param.gp.vdw_type==3)
	{ // innner wall
	  e_core = twbp->ecore * exp(twbp->acore * (1.0-(r_ij/twbp->rcore)));
	  data->my_en.e_vdW += Tap * e_core;

	  de_core = -(twbp->acore/twbp->rcore) * e_core;
	  CEvd += dTap * e_core + Tap * de_core / r_ij;
	}

      /*Coulomb Calculations*/
      dr3gamij_1 = ( r_ij * r_ij * r_ij + twbp->gamma );
      dr3gamij_3 = pow( dr3gamij_1 , 0.33333333333333 );

      tmp = Tap / dr3gamij_3;
      data->my_en.e_ele += e_ele = 
	C_ele * system->my_atoms[i].q * system->my_atoms[j].q * tmp;
		
	  
      CEclmb = C_ele * system->my_atoms[i].q * system->my_atoms[j].q * 
	( dTap -  Tap * r_ij / dr3gamij_1 ) / dr3gamij_3;
      // fprintf( fout, "%5d %5d %10.6f %10.6f\n",
      //   MIN( system->my_atoms[i].orig_id, system->my_atoms[j].orig_id ),
      //   MAX( system->my_atoms[i].orig_id, system->my_atoms[j].orig_id ), 
      //   CEvd, CEclmb );       	  		  

      if( control->virial == 0 ) {
	rvec_ScaledAdd( workspace->f[i], -(CEvd + CEclmb), nbr_pj->dvec );
	rvec_ScaledAdd( workspace->f[j], +(CEvd + CEclmb), nbr_pj->dvec );
      }
      else { /* NPT, iNPT or sNPT */
	/* for pressure coupling, terms not related to bond order 
	   derivatives are added directly into pressure vector/tensor */
	rvec_Scale( temp, CEvd + CEclmb, nbr_pj->dvec );
	    
	rvec_ScaledAdd( workspace->f[i], -1., temp );
	rvec_Add( workspace->f[j], temp );
	    
	rvec_iMultiply( ext_press, nbr_pj->rel_box, temp );
	rvec_Add( data->my_ext_press, ext_press );
	    
	// fprintf( stderr, "nonbonded(%d,%d): rel_box (%f %f %f)
	//   force(%f %f %f) ext_press (%12.6f %12.6f %12.6f)\n", 
	//   i, j, nbr_pj->rel_box[0], nbr_pj->rel_box[1], nbr_pj->rel_box[2],
	//   temp[0], temp[1], temp[2],
	//   data->ext_press[0], data->ext_press[1], data->ext_press[2] );
      }

#ifdef TEST_ENERGY
      // fprintf( out_control->evdw, 
      // "%12.9f%12.9f%12.9f%12.9f%12.9f%12.9f%12.9f%12.9f\n", 
      // workspace->Tap[7],workspace->Tap[6],workspace->Tap[5],
      // workspace->Tap[4],workspace->Tap[3],workspace->Tap[2], 
      // workspace->Tap[1], Tap );
      //fprintf( out_control->evdw, "%6d%6d%24.15e%24.15e%24.15e\n",
      fprintf( out_control->evdw, "%6d%6d%12.4f%12.4f%12.4f\n",
	       system->my_atoms[i].orig_id, system->my_atoms[j].orig_id, 
	       r_ij, e_vdW, data->my_en.e_vdW );
      //fprintf(out_control->ecou,"%6d%6d%24.15e%24.15e%24.15e%24.15e%24.15e\n",
      fprintf( out_control->ecou, "%6d%6d%12.4f%12.4f%12.4f%12.4f%12.4f\n",
	       system->my_atoms[i].orig_id, system->my_atoms[j].orig_id,
	       r_ij, system->my_atoms[i].q, system->my_atoms[j].q, 
	       e_ele, data->my_en.e_ele );
#endif
#ifdef TEST_FORCES
      rvec_ScaledAdd( workspace->f_vdw[i], -CEvd, nbr_pj->dvec );
      rvec_ScaledAdd( workspace->f_vdw[j], +CEvd, nbr_pj->dvec );
      rvec_ScaledAdd( workspace->f_ele[i], -CEclmb, nbr_pj->dvec );
      rvec_ScaledAdd( workspace->f_ele[j], +CEclmb, nbr_pj->dvec );
#endif
      }
    }
  }

#if defined(DEBUG)
  fprintf( stderr, "nonbonded: ext_press (%12.6f %12.6f %12.6f)\n", 
	   data->ext_press[0], data->ext_press[1], data->ext_press[2] );
  MPI_Barrier( MPI_COMM_WORLD );
#endif

  Compute_Polarization_Energy( system, data );
}
void Add_dBond_to_Forces_NPT( int i, int pj, simulation_data *data,
                              storage *workspace, reax_list **lists )
{
  reax_list *bonds = (*lists) + BONDS;
  bond_data *nbr_j, *nbr_k;
  bond_order_data *bo_ij, *bo_ji;
  dbond_coefficients coef;
  rvec temp, ext_press;
  ivec rel_box;
  int pk, k, j;

  /* Initializations */
  nbr_j = &(bonds->select.bond_list[pj]);
  j = nbr_j->nbr;
  bo_ij = &(nbr_j->bo_data);
  bo_ji = &(bonds->select.bond_list[ nbr_j->sym_index ].bo_data);

  coef.C1dbo = bo_ij->C1dbo * (bo_ij->Cdbo + bo_ji->Cdbo);
  coef.C2dbo = bo_ij->C2dbo * (bo_ij->Cdbo + bo_ji->Cdbo);
  coef.C3dbo = bo_ij->C3dbo * (bo_ij->Cdbo + bo_ji->Cdbo);

  coef.C1dbopi = bo_ij->C1dbopi * (bo_ij->Cdbopi + bo_ji->Cdbopi);
  coef.C2dbopi = bo_ij->C2dbopi * (bo_ij->Cdbopi + bo_ji->Cdbopi);
  coef.C3dbopi = bo_ij->C3dbopi * (bo_ij->Cdbopi + bo_ji->Cdbopi);
  coef.C4dbopi = bo_ij->C4dbopi * (bo_ij->Cdbopi + bo_ji->Cdbopi);

  coef.C1dbopi2 = bo_ij->C1dbopi2 * (bo_ij->Cdbopi2 + bo_ji->Cdbopi2);
  coef.C2dbopi2 = bo_ij->C2dbopi2 * (bo_ij->Cdbopi2 + bo_ji->Cdbopi2);
  coef.C3dbopi2 = bo_ij->C3dbopi2 * (bo_ij->Cdbopi2 + bo_ji->Cdbopi2);
  coef.C4dbopi2 = bo_ij->C4dbopi2 * (bo_ij->Cdbopi2 + bo_ji->Cdbopi2);

  coef.C1dDelta = bo_ij->C1dbo * (workspace->CdDelta[i]+workspace->CdDelta[j]);
  coef.C2dDelta = bo_ij->C2dbo * (workspace->CdDelta[i]+workspace->CdDelta[j]);
  coef.C3dDelta = bo_ij->C3dbo * (workspace->CdDelta[i]+workspace->CdDelta[j]);

  for( pk = Start_Index(i, bonds); pk < End_Index(i, bonds); ++pk ) {
    nbr_k = &(bonds->select.bond_list[pk]);
    k = nbr_k->nbr;

    rvec_Scale(temp, -coef.C2dbo, nbr_k->bo_data.dBOp);       /*2nd, dBO*/
    rvec_ScaledAdd(temp, -coef.C2dDelta, nbr_k->bo_data.dBOp);/*dDelta*/
    rvec_ScaledAdd(temp, -coef.C3dbopi, nbr_k->bo_data.dBOp); /*3rd, dBOpi*/
    rvec_ScaledAdd(temp, -coef.C3dbopi2, nbr_k->bo_data.dBOp);/*3rd, dBOpi2*/

    /* force */
    rvec_Add( workspace->f[k], temp );
    /* pressure */
    rvec_iMultiply( ext_press, nbr_k->rel_box, temp );
    rvec_Add( data->my_ext_press, ext_press );

  }

  /* then atom i itself  */
  rvec_Scale( temp, coef.C1dbo, bo_ij->dBOp );                      /*1st,dBO*/
  rvec_ScaledAdd( temp, coef.C2dbo, workspace->dDeltap_self[i] );   /*2nd,dBO*/
  rvec_ScaledAdd( temp, coef.C1dDelta, bo_ij->dBOp );               /*1st,dBO*/
  rvec_ScaledAdd( temp, coef.C2dDelta, workspace->dDeltap_self[i] );/*2nd,dBO*/
  rvec_ScaledAdd( temp, coef.C1dbopi, bo_ij->dln_BOp_pi );        /*1st,dBOpi*/
  rvec_ScaledAdd( temp, coef.C2dbopi, bo_ij->dBOp );              /*2nd,dBOpi*/
  rvec_ScaledAdd( temp, coef.C3dbopi, workspace->dDeltap_self[i]);/*3rd,dBOpi*/

  rvec_ScaledAdd( temp, coef.C1dbopi2, bo_ij->dln_BOp_pi2 );  /*1st,dBO_pi2*/
  rvec_ScaledAdd( temp, coef.C2dbopi2, bo_ij->dBOp );         /*2nd,dBO_pi2*/
  rvec_ScaledAdd( temp, coef.C3dbopi2, workspace->dDeltap_self[i] );/*3rd*/

  /* force */
  rvec_Add( workspace->f[i], temp );

  for( pk = Start_Index(j, bonds); pk < End_Index(j, bonds); ++pk ) {
    nbr_k = &(bonds->select.bond_list[pk]);
    k = nbr_k->nbr;

    rvec_Scale( temp, -coef.C3dbo, nbr_k->bo_data.dBOp );      /*3rd,dBO*/
    rvec_ScaledAdd( temp, -coef.C3dDelta, nbr_k->bo_data.dBOp);/*dDelta*/
    rvec_ScaledAdd( temp, -coef.C4dbopi, nbr_k->bo_data.dBOp); /*4th,dBOpi*/
    rvec_ScaledAdd( temp, -coef.C4dbopi2, nbr_k->bo_data.dBOp);/*4th,dBOpi2*/

    /* force */
    rvec_Add( workspace->f[k], temp );
    /* pressure */
    if( k != i ) {
      ivec_Sum( rel_box, nbr_k->rel_box, nbr_j->rel_box ); //rel_box(k, i)
      rvec_iMultiply( ext_press, rel_box, temp );
      rvec_Add( data->my_ext_press, ext_press );

    }
  }

  /* then atom j itself */
  rvec_Scale( temp, -coef.C1dbo, bo_ij->dBOp );                    /*1st, dBO*/
  rvec_ScaledAdd( temp, coef.C3dbo, workspace->dDeltap_self[j] );  /*2nd, dBO*/
  rvec_ScaledAdd( temp, -coef.C1dDelta, bo_ij->dBOp );             /*1st, dBO*/
  rvec_ScaledAdd( temp, coef.C3dDelta, workspace->dDeltap_self[j]);/*2nd, dBO*/

  rvec_ScaledAdd( temp, -coef.C1dbopi, bo_ij->dln_BOp_pi );       /*1st,dBOpi*/
  rvec_ScaledAdd( temp, -coef.C2dbopi, bo_ij->dBOp );             /*2nd,dBOpi*/
  rvec_ScaledAdd( temp, coef.C4dbopi, workspace->dDeltap_self[j]);/*3rd,dBOpi*/

  rvec_ScaledAdd( temp, -coef.C1dbopi2, bo_ij->dln_BOp_pi2 );    /*1st,dBOpi2*/
  rvec_ScaledAdd( temp, -coef.C2dbopi2, bo_ij->dBOp );           /*2nd,dBOpi2*/
  rvec_ScaledAdd( temp,coef.C4dbopi2,workspace->dDeltap_self[j]);/*3rd,dBOpi2*/

  /* force */
  rvec_Add( workspace->f[j], temp );
  /* pressure */
  rvec_iMultiply( ext_press, nbr_j->rel_box, temp );
  rvec_Add( data->my_ext_press, ext_press );

}