double power_1(int x, int n) { if (n == 0) { return 1; } else if (n % 2 == 0) { return power_1(x * x, n / 2); } else { return x * power_1(x * x, n / 2); } }
int main(int argc, char *argv[]) { printf("%f\n", power_0(4, 10)); printf("%f\n", power_0(4, 11)); printf("%f\n", power_1(4, 10)); printf("%f\n", power_1(4, 11)); printf("%f\n", power_2(4, 10, 1)); printf("%f\n", power_2(4, 11, 1)); printf("%f\n", power_3(4, 10); printf("%f\n", power_3(4, 11)); return 0; }
void csw2_value(double r, double *p, double *f) { static double power; power_1(&power, &r, &p[3]); *f = (1. + p[0] * cos(p[1] * r + p[2])) / power; return; }
void eopp_exp_value(double r, double *p, double *f) { static double power; power_1(&power, &r, &p[3]); *f = p[0] * exp(-p[1] * r) + (p[2] / power) * cos(p[4] * r + p[5]); return; }
void softshell_value(double r, double *p, double *f) { static double x, y; x = p[0] / r; y = p[1]; power_1(f, &x, &y); return; }
void sheng_F_value(double r, double *p, double *f) { static double x, y, power; x = r; y = p[1]; power_1(&power, &x, &y); *f = p[0] * power + p[2] * r + p[3]; return; }
void bjs_value(double r, double *p, double *f) { static double power; if (r == 0) *f = 0; else { power_1(&power, &r, &p[1]); *f = p[0] * (1. - p[1] * log(r)) * power + p[2] * r; } return; }
void power_decay_value(double r, double *p, double *f) { static double x, y, power; x = 1. / r; y = p[1]; power_1(&power, &x, &y); *f = p[0] * power; return; }
void mishin_value(double r, double *p, double *f) { static double z; static double temp; static double power; z = r - p[3]; temp = exp(-p[5] * r); power_1(&power, &z, &p[4]); *f = p[0] * power * temp * (1. + p[1] * temp) + p[2]; return; }
void vpair_value(double r, double *p, double *f) { static double x[7], y, z; y = r; z = p[1]; power_1(&x[0], &y, &z); x[1] = r * r; x[2] = x[1] * x[1]; x[3] = p[2] * p[2]; x[4] = p[3] * p[3]; x[5] = p[4] * x[4] + p[5] * x[3]; x[6] = exp(-r / p[6]); *f = 14.4 * (p[0] / x[0] - 0.5 * (x[5] / x[2]) * x[6]); return; }
void RateMatrix::SetMatrix( vector<double>& matrix, double len ) { int i,j,k; double expt[numStates]; vector<double>::iterator P; // P(t)ij = SUM Cijk * exp{Root*t} P=matrix.begin(); if (len<1e-6) { for (i=0; i<numStates; i++) { for (j=0; j<numStates; j++) { if (i==j) (*P)=1.0; else (*P)=0.0; P++; } } return; } for (k=1; k<numStates; k++) { expt[k]=exp(len*Root[k]); } vector<unsigned int> squared (numStates, 0), power_1 (numStates, 0); for (i=0; i<numStates; i++) { squared[i]=i*numStates_squared; power_1[i]=i*numStates; } for (i=0; i<numStates; i++) { for (j=0; j<numStates; j++) { (*P)=Cijk.at(squared[i]+power_1[j]+0); for (k=1; k<numStates; k++) { (*P)+=Cijk.at(squared[i]+power_1[j]+k)*expt[k]; } P++; } } }
void sheng_rho_value(double r, double *p, double *f) { static double sig_d_rad6, sig_d_rad12, x, y, power; static int h, k; h = (r > 1.45) ? 1 : 0; k = (r <= 1.45) ? 1 : 0; x = r; y = p[1]; power_1(&power, &x, &y); sig_d_rad6 = (p[4] * p[4]) / (r * r); sig_d_rad6 = sig_d_rad6 * sig_d_rad6 * sig_d_rad6; sig_d_rad12 = dsquare(sig_d_rad6); *f = (p[0] * power + p[2]) * k + (4. * p[3] * (sig_d_rad12 - sig_d_rad6)) * h; return; }
void RateMatrix::SetupMatrix(bool transition_probability_independent_sites_setup) { unsigned int i,j,k; double mr; double sum; double U[numStates_squared+1], V[numStates_squared+1], T1[numStates_squared+1], T2[numStates_squared+1]; double Qij2pass[numStates_squared+1]; ////////// /// transition_probability_independent_sites_setup: /// If we are calculating the transition probabilities as independent sites models, then we need /// to run the code in the if statements. However, if we are doing the pseudo-dependent sites /// calculations, we want to skip those code segments. /// Segment #1: /// * Sets the Qij entries to be the input substitution model. /// -> For pseudo-dependent sites, we excise the Q matrix from the 4^N X 4^N sequence model. /// Segment #2: /// * Sets Qij so that branch length corresponds to expected number of changes. /// -> pseudo-dependent sites branch lengths correspond not to 1 change per site, but whatever /// the dependent sites model constrains it to. ////////// CheckFrequencies(); k=0; if (transition_probability_independent_sites_setup) { for (i=0; i<numStates-1; i++) { for (j=i+1; j<numStates; j++) { Qij.at(i*numStates+j) = Qij.at(j*numStates+i) = Sij.at(k++); } } for (i=0; i<numStates; i++) { for (j=0; j<numStates; j++) { Qij.at(i*numStates+j) *= pi.at(j); } } mr=0; for (i=0; i<numStates; i++) { sum = 0; Qij.at(i*numStates+i)=0; for (j=0; j<numStates; j++) { sum += Qij.at(i*numStates+j); } Qij.at(i*numStates+i) = -sum; mr += pi.at(i) * sum; } ////////// /// Multiplies every element of Qij by 1.0/mr. This is abyx. ////////// for (i=0; i<numStates_squared; Qij.at(i)*=1.0/mr,i++) ; } // Testcode: Print Qij. //if (!transition_probability_independent_sites_setup) printQij(); //Testcode: does sum = 1? sum = 0; double partial = 0; for (i = 0; i < numStates; i++) { partial = 0; for (j = 0; j < numStates; j++) { if (i != j) partial += Qij.at(i*numStates+j); } sum += pi.at(i) * partial; } //if (!transition_probability_independent_sites_setup) cerr << "Sum: " << sum << endl; for (i = 0; i < numStates_squared; i++) Qij2pass[i]=Qij.at(i); if ((k=eigen(1, Qij2pass, numStates, Root, T1, U, V, T2))!=0) { fprintf(stderr, "\ncomplex roots in SetupMatrix"); exit(EXIT_FAILURE); } xtoy (U, V, numStates_squared); matinv (V, numStates, numStates, T1); vector<unsigned int> squared (numStates, 0), power_1 (numStates, 0); for (i=0; i<numStates; i++) { squared[i]=i*numStates_squared; power_1[i]=i*numStates; } for (i=0; i<numStates; i++) { for (j=0; j<numStates; j++) { for (k=0; k<numStates; k++) { Cijk.at(squared[i]+power_1[j]+k) = U[power_1[i]+k]*V[power_1[k]+j]; } } } }
double calc_forces(double* xi_opt, double* forces, int flag) { tersoff_t const* ters = &g_pot.apot_table.tersoff; #if !defined(MPI) g_mpi.myconf = g_config.nconf; #endif // !MPI // This is the start of an infinite loop while (1) { // sum of squares of local process double error_sum = 0.0; #if defined(MPI) MPI_Bcast(&flag, 1, MPI_INT, 0, MPI_COMM_WORLD); if (flag == 1) break; // Exception: flag 1 means clean up if (g_mpi.myid == 0) apot_check_params(xi_opt); MPI_Bcast(xi_opt, g_calc.ndimtot, MPI_DOUBLE, 0, MPI_COMM_WORLD); #else apot_check_params(xi_opt); #endif // MPI update_tersoff_pointers(xi_opt); // loop over configurations for (int config_idx = g_mpi.firstconf; config_idx < g_mpi.firstconf + g_mpi.myconf; config_idx++) { int uf = g_config.conf_uf[config_idx - g_mpi.firstconf]; // reset energies and stresses forces[g_calc.energy_p + config_idx] = 0.0; #if defined(STRESS) int us = g_config.conf_us[config_idx - g_mpi.firstconf]; int stress_idx = g_calc.stress_p + 6 * config_idx; memset(forces + stress_idx, 0, 6 * sizeof(double)); #endif // STRESS // first loop over all atoms: reset forces for (int atom_idx = 0; atom_idx < g_config.inconf[config_idx]; atom_idx++) { int n_i = 3 * (g_config.cnfstart[config_idx] + atom_idx); if (uf) { forces[n_i + 0] = -g_config.force_0[n_i + 0]; forces[n_i + 1] = -g_config.force_0[n_i + 1]; forces[n_i + 2] = -g_config.force_0[n_i + 2]; } else { memset(forces + n_i, 0, 3 * sizeof(double)); } } // second loop: calculate cutoff function f_c for all neighbor for (int atom_idx = 0; atom_idx < g_config.inconf[config_idx]; atom_idx++) { atom_t* atom = g_config.conf_atoms + atom_idx + g_config.cnfstart[config_idx] - g_mpi.firstatom; int n_i = 3 * (g_config.cnfstart[config_idx] + atom_idx); // loop over neighbors for (int neigh_idx = 0; neigh_idx < atom->num_neigh; neigh_idx++) { neigh_t* neigh_j = atom->neigh + neigh_idx; int col_j = neigh_j->col[0]; // check if we are within the cutoff range if (neigh_j->r < ters->S[col_j][0]) { int self = (neigh_j->nr == atom_idx + g_config.cnfstart[config_idx]) ? 1 : 0; // calculate cutoff function f_c and store it for every neighbor double cut_tmp = M_PI / (ters->S[col_j][0] - ters->R[col_j][0]); double cut_tmp_j = cut_tmp * (neigh_j->r - ters->R[col_j][0]); if (neigh_j->r < ters->R[col_j][0]) { neigh_j->f = 1.0; neigh_j->df = 0.0; } else { neigh_j->f = 0.5 * (1.0 + cos(cut_tmp_j)); neigh_j->df = -0.5 * cut_tmp * sin(cut_tmp_j); } // calculate pair part f_c*A*exp(-lambda*r) and the derivative double tmp = exp(-ters->lambda[col_j][0] * neigh_j->r); double phi_val = neigh_j->f * ters->A[col_j][0] * tmp; double phi_grad = neigh_j->df - ters->lambda[col_j][0] * neigh_j->f; phi_grad *= ters->A[col_j][0] * tmp; // avoid double counting if atom is interacting with itself if (self) { phi_val *= 0.5; phi_grad *= 0.5; } // only half cohesive energy because we have a full neighbor list forces[g_calc.energy_p + config_idx] += 0.5 * phi_val; if (uf) { // calculate pair forces vector tmp_force; tmp_force.x = neigh_j->dist_r.x * phi_grad; tmp_force.y = neigh_j->dist_r.y * phi_grad; tmp_force.z = neigh_j->dist_r.z * phi_grad; forces[n_i + 0] += tmp_force.x; forces[n_i + 1] += tmp_force.y; forces[n_i + 2] += tmp_force.z; #if defined(STRESS) // also calculate pair stresses if (us) { forces[stress_idx + 0] -= 0.5 * neigh_j->dist.x * tmp_force.x; forces[stress_idx + 1] -= 0.5 * neigh_j->dist.y * tmp_force.y; forces[stress_idx + 2] -= 0.5 * neigh_j->dist.z * tmp_force.z; forces[stress_idx + 3] -= 0.5 * neigh_j->dist.x * tmp_force.y; forces[stress_idx + 4] -= 0.5 * neigh_j->dist.y * tmp_force.z; forces[stress_idx + 5] -= 0.5 * neigh_j->dist.z * tmp_force.x; } #endif // STRESS } } else { neigh_j->f = 0.0; neigh_j->df = 0.0; } } // loop over neighbors // calculate threebody part for (int neigh_j_idx = 0; neigh_j_idx < atom->num_neigh; neigh_j_idx++) { neigh_t* neigh_j = atom->neigh + neigh_j_idx; int col_j = neigh_j->col[0]; // check if we are within the cutoff range if (neigh_j->r < ters->S[col_j][0]) { int ijk = neigh_j->ijk_start; int n_j = 3 * neigh_j->nr; // skip neighbor if coefficient is zero if (ters->B[col_j][0] == 0.0) continue; // reset variables for each neighbor double zeta = 0.0; vector dzeta_i = {0.0, 0.0, 0.0}; vector dzeta_j = {0.0, 0.0, 0.0}; // inner loop over neighbors for (int neigh_k_idx = 0; neigh_k_idx < atom->num_neigh; neigh_k_idx++) { if (neigh_k_idx == neigh_j_idx) continue; neigh_t* neigh_k = atom->neigh + neigh_k_idx; int col_k = neigh_k->col[0]; angle_t* angle = atom->angle_part + ijk++; if (neigh_k->r < ters->S[col_k][0]) { double tmp_jk = 1.0 / (neigh_j->r * neigh_k->r); double tmp_1 = ters->h[col_j][0] - angle->cos; double tmp_2 = 1.0 / (ters->d2[col_j] + tmp_1 * tmp_1); double g_theta = 1.0 + ters->c2[col_j] / ters->d2[col_j] - ters->c2[col_j] * tmp_2; // zeta zeta += neigh_k->f * ters->omega[col_k][0] * g_theta; double tmp_j2 = angle->cos / (neigh_j->r * neigh_j->r); double tmp_k2 = angle->cos / (neigh_k->r * neigh_k->r); vector dcos_j; dcos_j.x = tmp_jk * neigh_k->dist.x - tmp_j2 * neigh_j->dist.x; dcos_j.y = tmp_jk * neigh_k->dist.y - tmp_j2 * neigh_j->dist.y; dcos_j.z = tmp_jk * neigh_k->dist.z - tmp_j2 * neigh_j->dist.z; vector dcos_k; dcos_k.x = tmp_jk * neigh_j->dist.x - tmp_k2 * neigh_k->dist.x; dcos_k.y = tmp_jk * neigh_j->dist.y - tmp_k2 * neigh_k->dist.y; dcos_k.z = tmp_jk * neigh_j->dist.z - tmp_k2 * neigh_k->dist.z; double tmp_3 = 2.0 * ters->c2[col_j] * tmp_1 * tmp_2 * tmp_2 * neigh_k->f * ters->omega[col_k][0]; double tmp_grad = neigh_k->df / neigh_k->r * g_theta * ters->omega[col_k][0]; neigh_k->dzeta.x = tmp_grad * neigh_k->dist.x - tmp_3 * dcos_k.x; neigh_k->dzeta.y = tmp_grad * neigh_k->dist.y - tmp_3 * dcos_k.y; neigh_k->dzeta.z = tmp_grad * neigh_k->dist.z - tmp_3 * dcos_k.z; dzeta_i.x -= neigh_k->dzeta.x; dzeta_i.y -= neigh_k->dzeta.y; dzeta_i.z -= neigh_k->dzeta.z; dzeta_j.x -= tmp_3 * dcos_j.x; dzeta_j.y -= tmp_3 * dcos_j.y; dzeta_j.z -= tmp_3 * dcos_j.z; } } // neigh_k_idx double phi_a = 0.5 * ters->B[col_j][0] * exp(-ters->mu[col_j][0] * neigh_j->r); double tmp_pow_1 = ters->gamma[col_j][0] * zeta; double tmp_4 = 0.0; power_1(&tmp_4, &tmp_pow_1, ters->n[col_j]); tmp_pow_1 = 1.0 + tmp_4; double tmp_pow_2 = -1.0 / (2.0 * ters->n[col_j][0]); double b_ij = 0.0; power_1(&b_ij, &tmp_pow_1, &tmp_pow_2); double phi_val = -b_ij * phi_a; forces[g_calc.energy_p + config_idx] += neigh_j->f * phi_val; double tmp_5 = 0.0; if (zeta != 0.0) tmp_5 = -b_ij * neigh_j->f * phi_a * tmp_4 / (2.0 * zeta * (1.0 + tmp_4)); double tmp_6 = (neigh_j->f * phi_a * ters->mu[col_j][0] * b_ij + neigh_j->df * phi_val) / neigh_j->r; vector force_j; force_j.x = -tmp_6 * neigh_j->dist.x + tmp_5 * dzeta_j.x; force_j.y = -tmp_6 * neigh_j->dist.y + tmp_5 * dzeta_j.y; force_j.z = -tmp_6 * neigh_j->dist.z + tmp_5 * dzeta_j.z; for (int neigh_k_idx = 0; neigh_k_idx < atom->num_neigh; neigh_k_idx++) { if (neigh_k_idx != neigh_j_idx) { neigh_t* neigh_k = atom->neigh + neigh_k_idx; int col_k = neigh_k->col[0]; if (neigh_k->r < ters->S[col_k][0]) { int n_k = 3 * neigh_k->nr; // update force on particle k forces[n_k + 0] += tmp_5 * neigh_k->dzeta.x; forces[n_k + 1] += tmp_5 * neigh_k->dzeta.y; forces[n_k + 2] += tmp_5 * neigh_k->dzeta.z; #if defined(STRESS) if (us) { // Distribute stress among atoms forces[stress_idx + 0] += neigh_k->dist.x * tmp_5 * neigh_k->dzeta.x; forces[stress_idx + 1] += neigh_k->dist.y * tmp_5 * neigh_k->dzeta.y; forces[stress_idx + 2] += neigh_k->dist.z * tmp_5 * neigh_k->dzeta.z; forces[stress_idx + 3] += 0.5 * tmp_5 * (neigh_k->dist.x * neigh_k->dzeta.y + neigh_k->dist.y * neigh_k->dzeta.x); forces[stress_idx + 4] += 0.5 * tmp_5 * (neigh_k->dist.y * neigh_k->dzeta.z + neigh_k->dist.z * neigh_k->dzeta.y); forces[stress_idx + 5] += 0.5 * tmp_5 * (neigh_k->dist.z * neigh_k->dzeta.x + neigh_k->dist.x * neigh_k->dzeta.z); } #endif // STRESS } } // neigh_k_idx != neigh_j_idx } // neigh_k_idx loop // update force on particle j forces[n_j + 0] += force_j.x; forces[n_j + 1] += force_j.y; forces[n_j + 2] += force_j.z; // update force on particle i forces[n_i + 0] += tmp_5 * dzeta_i.x - force_j.x; forces[n_i + 1] += tmp_5 * dzeta_i.y - force_j.y; forces[n_i + 2] += tmp_5 * dzeta_i.z - force_j.z; #if defined(STRESS) if (us) { // Distribute stress among atoms forces[stress_idx + 0] += neigh_j->dist.x * force_j.x; forces[stress_idx + 1] += neigh_j->dist.y * force_j.y; forces[stress_idx + 2] += neigh_j->dist.z * force_j.z; forces[stress_idx + 3] += 0.5 * (neigh_j->dist.x * force_j.y + neigh_j->dist.y * force_j.x); forces[stress_idx + 4] += 0.5 * (neigh_j->dist.y * force_j.z + neigh_j->dist.z * force_j.y); forces[stress_idx + 5] += 0.5 * (neigh_j->dist.z * force_j.x + neigh_j->dist.x * force_j.z); } #endif // STRESS } // neigh_j_idx } } // end second loop over all atoms // third loop over all atoms, sum up forces if (uf) { for (int atom_idx = 0; atom_idx < g_config.inconf[config_idx]; atom_idx++) { atom_t* atom = g_config.conf_atoms + atom_idx + g_config.cnfstart[config_idx] - g_mpi.firstatom; int n_i = 3 * (g_config.cnfstart[config_idx] + atom_idx); #if defined(FWEIGHT) // Weigh by absolute value of force forces[n_i + 0] /= FORCE_EPS + atom->absforce; forces[n_i + 1] /= FORCE_EPS + atom->absforce; forces[n_i + 2] /= FORCE_EPS + atom->absforce; #endif // FWEIGHT // sum up forces #if defined(CONTRIB) if (atom->contrib) #endif // CONTRIB error_sum += g_config.conf_weight[config_idx] * (dsquare(forces[n_i + 0]) + dsquare(forces[n_i + 1]) + dsquare(forces[n_i + 2])); } } // end third loop over all atoms // energy contributions forces[g_calc.energy_p + config_idx] /= (double)g_config.inconf[config_idx]; forces[g_calc.energy_p + config_idx] -= g_config.force_0[g_calc.energy_p + config_idx]; error_sum += g_config.conf_weight[config_idx] * g_param.eweight * dsquare(forces[g_calc.energy_p + config_idx]); #if defined(STRESS) // stress contributions if (uf && us) { for (int i = 0; i < 6; i++) { forces[stress_idx + i] /= g_config.conf_vol[config_idx - g_mpi.firstconf]; forces[stress_idx + i] -= g_config.force_0[stress_idx + i]; error_sum += g_config.conf_weight[config_idx] * g_param.sweight * dsquare(forces[stress_idx + i]); } } #endif // STRESS } // loop over configurations // add punishment for out of bounds (mostly for powell_lsq) if (g_mpi.myid == 0) error_sum += apot_punish(xi_opt, forces); gather_forces(&error_sum, forces); // root process exits this function now if (g_mpi.myid == 0) { // Increase function call counter g_calc.fcalls++; if (isnan(error_sum)) { #if defined(DEBUG) printf("\n--> Force is nan! <--\n\n"); #endif // DEBUG return 10e10; } else return error_sum; } } // end of infinite loop // once a non-root process arrives here, all is done return -1.0; }