27void get_vdw_params(
const int zatom,
double *c6,
double *alpha,
double *r0) {
410void fdamp(
const double rr,
const double r0ab,
const double dd,
const double sr,
411 double *ff,
double *dffdrab,
double *dffdr0) {
414 double ee =
exp(-dd * ((rr / (sr * r0ab)) - 1.0));
415 *ff = 1.0 / (1.0 + ee);
416 double dee = ee * (*ff) * (*ff);
420 *dffdrab = (dd / (sr * r0ab)) * dee;
424 *dffdr0 = -dd * rr / (sr * r0ab * r0ab) * dee;
428void distance(
const int iatom,
const int jatom,
const double coordinates[],
429 double *rr,
double *rr2,
double *rr6,
double *rr7) {
431 double x_ij = coordinates[3 * iatom + 0] - coordinates[3 * jatom + 0];
432 double y_ij = coordinates[3 * iatom + 1] - coordinates[3 * jatom + 1];
433 double z_ij = coordinates[3 * iatom + 2] - coordinates[3 * jatom + 2];
435 *rr2 = x_ij * x_ij + y_ij * y_ij + z_ij * z_ij;
436 *rr6 = rr2[0] * rr2[0] *
439 *rr7 = rr6[0] * rr[0];
448void vdw_calculate(
const int natoms,
const double dd,
const double sr,
449 const int zatom[],
const double coordinates[],
450 const double volume_ratio[],
double *energy,
double force[],
451 double derivative_coeff[]) {
457 for (ia = 0; ia < natoms; ia++) {
459 double c6_a, alpha_a, r0_a;
462 force[3 * ia + 0] = 0.0;
463 force[3 * ia + 1] = 0.0;
464 force[3 * ia + 2] = 0.0;
466 derivative_coeff[ia] = 0.0;
468 get_vdw_params(zatom[ia], &c6_a, &alpha_a, &r0_a);
470 for (ib = 0; ib < natoms; ib++) {
472 double c6_b, alpha_b, r0_b;
478 double rr, rr2, rr6, rr7;
479 distance(ia, ib, coordinates, &rr, &rr2, &rr6, &rr7);
481 get_vdw_params(zatom[ib], &c6_b, &alpha_b, &r0_b);
484 double num = 2.0 * c6_a * c6_b;
485 double den = (alpha_b / alpha_a) * c6_a + (alpha_a / alpha_b) * c6_b;
487 double c6abfree = num / den;
490 double c6abeff = volume_ratio[ia] * volume_ratio[ib] * c6abfree;
493 cbrt(volume_ratio[ia]) * r0_a +
cbrt(volume_ratio[ib]) * r0_b;
499 fdamp(rr, r0ab, dd, sr, &ff, &dffdrab, &dffdr0);
501 *energy += -0.5 * ff * c6abeff / rr6;
505 double deabdrab = dffdrab * c6abeff / rr6 - 6.0 * ff * c6abeff / rr7;
509 double dr0dvra = r0_a / (3.0 *
pow(volume_ratio[ia], 2.0 / 3.0));
513 double dffdvra = dffdr0 * dr0dvra;
518 dffdvra * c6abeff / rr6 + ff * volume_ratio[ib] * c6abfree / rr6;
521 deabdrab * (coordinates[3 * ia + 0] - coordinates[3 * ib + 0]) / rr;
523 deabdrab * (coordinates[3 * ia + 1] - coordinates[3 * ib + 1]) / rr;
525 deabdrab * (coordinates[3 * ia + 2] - coordinates[3 * ib + 2]) / rr;
527 derivative_coeff[ia] += deabdvra;
543void FC_FUNC_(f90_vdw_calculate,
544 F90_VDW_CALCULATE)(
const int *natoms,
const double *dd,
545 const double *sr,
const int zatom[],
546 const double coordinates[],
547 const double volume_ratio[],
double *energy,
548 double force[],
double derivative_coeff[]) {
549 vdw_calculate(*natoms, *dd, *sr, zatom, coordinates, volume_ratio, energy,
550 force, derivative_coeff);
557 const int natoms = 3;
558 const int zatom[] = {23, 29, 31};
559 const double volume_ratio[] = {1.0, 1.0, 1.0};
561 double force[natoms * 3];
562 double derivative_coeff[natoms];
565 for (x = 0.1; x < 10; x += 0.1) {
566 double coordinates[] = {0.2, -0.3, 0.5, -0.7, 1.1, -1.3, x, 0.0, 0.0};
568 vdw_calculate(natoms, zatom, coordinates, volume_ratio, &energy, force,
571 coordinates[5] += 0.001;
574 vdw_calculate(natoms, zatom, coordinates, volume_ratio, &energy_2, force,
double pow(double __x, double __y) __attribute__((__nothrow__
double exp(double __x) __attribute__((__nothrow__
void vdw_calculate(const int natoms, const double dd, const double sr, const int zatom[], const double coordinates[], const double volume_ratio[], double *energy, double force[], double derivative_coeff[])
double cbrt(double __x) __attribute__((__nothrow__
void fdamp(const double rr, const double r0ab, const double dd, const double sr, double *ff, double *dffdrab, double *dffdr0)
double sqrt(double __x) __attribute__((__nothrow__
void distance(const int iatom, const int jatom, const double coordinates[], double *rr, double *rr2, double *rr6, double *rr7)