From c51400c7214073c168549192d5449e277dae5ab7 Mon Sep 17 00:00:00 2001 From: ndlevinzon Date: Mon, 31 Aug 2026 14:39:08 -0600 Subject: [PATCH 01/17] Add 'surftension' command to calculate capillary-wave surface tension of a liquid slab - Introduced the 'surftension' command with detailed options for calculating surface tension based on height fluctuations. - Updated ChangeLog to reflect the new command and its usage. - Registered the command in Command.cpp and included necessary source and header files. - Added a test target for 'surftension' in the Makefile and included it in the complete tests list. - Bumped version to 7.11.0 to signify the addition of this new functionality. --- doc/ChangeLog.surftension.md | 91 ++ doc/ChangeLog.v7.md | 24 + src/Action_SurfaceTension.cpp | 1559 ++++++++++++++++++++++++++++++ src/Action_SurfaceTension.h | 123 +++ src/Command.cpp | 2 + src/Version.h | 2 +- src/cpptrajfiles | 1 + src/cpptrajheaders | 1 + test/Makefile | 4 + test/Test_SurfTension/RunTest.sh | 75 ++ 10 files changed, 1881 insertions(+), 1 deletion(-) create mode 100644 doc/ChangeLog.surftension.md create mode 100644 src/Action_SurfaceTension.cpp create mode 100644 src/Action_SurfaceTension.h create mode 100644 test/Test_SurfTension/RunTest.sh diff --git a/doc/ChangeLog.surftension.md b/doc/ChangeLog.surftension.md new file mode 100644 index 0000000000..27f32e976e --- /dev/null +++ b/doc/ChangeLog.surftension.md @@ -0,0 +1,91 @@ +# Changelog: `surftension` Action + +Branch: `action-surface_tension` +Started: 2026-08-31 +Target version: V7.11.0 +Author: Nathan D Levinzon + +Working log for the capillary-wave surface-tension Action. + +--- + +## ChangeLog.v7.md (landed) + +New command `surftension` added under New Commands. Internal version `V7.11.0`. + +``` +surftension [] temp + [normal {x|y|z}] [interface {willard|itim}] + [gridspacing ] [dz | dnormal ] + [sigmaxy ] [sigmaz | sigmanormal ] + [bulkhalfwidth ] [threshold ] + [qmin ] [qmax ] [lx ] [ly ] [lz ] + [nblock ] + [spectrumout ] [roughout ] [blockout ] + [spectrumagr ] [roughagr ] [blockagr ] + [spectrumgnu ] [roughgnu ] [blockgnu ] +``` + +--- + +## Files changed + +| File | Change | +|------|--------| +| `src/Action_SurfaceTension.h` | New Action class; MPI `SyncAction` / `trajComm_` | +| `src/Action_SurfaceTension.cpp` | Init / Setup / DoAction / Print / SyncAction + helpers | +| `src/Command.cpp` | `#include` and `AddCmd(..., "surftension")` | +| `src/cpptrajfiles` | `Action_SurfaceTension.cpp` in `COMMON_SOURCES` | +| `src/cpptrajheaders` | Install header for libcpptraj | +| `src/Version.h` | `V7.10.0` → `V7.11.0` | +| `doc/ChangeLog.v7.md` | New Commands entry | +| `test/Test_SurfTension/RunTest.sh` | Help + smoke test | +| `test/Makefile` | `test.surftension` target | + +--- + +## Development log + +### 2026-08-31 + +- Created this changelog on branch `action-surface_tension` before any Action source. +- Implemented `Action_SurfaceTension`: z-slab capillary-wave γ from Gaussian-smoothed + density interfaces, 2D DFT height spectrum, q-shell averaging, optional `*out` files. +- Wired `surftension` in `Command.cpp` and `cpptrajfiles`. +- Bumped version to V7.11.0; documented in `ChangeLog.v7.md`. +- Added `test/Test_SurfTension` smoke test (help + 1-frame Init/Setup). +- NVT (fixed Lx, Ly). No plots. +- MPI `SyncAction`: packed `ReduceMaster` SUM of the three |h_q|² spectra + (Radial-style). Frame counts / leftover `nblock` frames AllReduce SUM; + nx, ny, |q|, Lx, Ly AllReduce/ReduceMaster MAX so empty ranks (zeros) do + not clobber. Roughness and block DataSets keep default concat sync. + `nblock` is per-rank. Print block SEM uses `block_gamma_->Size()` after + DataSet sync, not the master's local `n_blocks_`. +- `interface {willard|itim}`: default Willard-Chandler is the existing Gaussian + density isosurface. `itim` is per-column min/max of ``, split at Lz/2 + after circular recenter (empty half-column skips the frame). `dz` / Gaussian + / `threshold` apply only to Willard-Chandler. +- OpenMP on the 2-D DFT (`ST_HeightPower`): flattened (kx, ky) loop with + `schedule(dynamic)`, same style as `radial` / `rms2d` (no `collapse()`). +- OpenMP on the 3-D Gaussian filter: one parallel region, three separable + passes; each 1-D line is an independent `omp for` with thread-local buffers. +- Grace (xmgrace) and gnuplot DataFile writers: `*out` uses the extension + (`.agr`/`.xmgr`, `.gnu`); `spectrumagr`/`spectrumgnu` (and rough/block) + force the format. Spectrum meshes get xlabel `q (Ang^-1)`. +- Bending modulus κ: Helfrich linear fit of `1/(q² S)` vs `q²` on `[qmin,qmax]` + (≥ 3 shells). Reports κ in kT (and J); `kappaq` / `kappaqtop` / `kappaqbot` + vs q; `bkappa` with `nblock`. Plateau γ is unchanged (Python). +- `normal {x|y|z}` (default z): permute Cartesian coordinates into + (lateral 1, lateral 2, normal) before wrap / circular recenter / Willard / + ITIM / DFT. Freeze lateral lengths only (NVT). Area = Lt1×Lt2. + `lx`/`ly`/`lz` override Cartesian box lengths. `dnormal` ≡ `dz`, + `sigmanormal` ≡ `sigmaz` (error if both given and they differ). + Init/Print report e.g. `Slab normal: z (interface plane x-y)`. Warns on + non-orthogonal boxes. + +--- + +## Not in this change + +- ITIM probe-sphere radius (min/max is the probe → 0 limit) +- Numeric regression vs a water-slab trajectory (no slab traj in the test suite yet) diff --git a/doc/ChangeLog.v7.md b/doc/ChangeLog.v7.md index 21382198e7..27dfcf57fc 100644 --- a/doc/ChangeLog.v7.md +++ b/doc/ChangeLog.v7.md @@ -13,6 +13,30 @@ New Commands - `desc` - DEBUG: describe a selection in the same manner as leap. +- `surftension` - Calculate capillary-wave surface tension of a liquid slab. + Builds Gaussian-smoothed instantaneous upper and lower interfaces from a number-density + field, Fourier-transforms height fluctuations, and reports γ in mN/m from the small-q + plateau of q²⟨|h_q|²⟩. κ (kT) is the Helfrich slope of 1/(q² S) vs q². + `normal {x|y|z}` selects the slab normal (default z). `interface {willard|itim}` + selects a Willard-Chandler density isosurface (default) or ITIM per-column min/max. + Optional outputs (`spectrumout`, `roughout`, `blockout`) follow the filename extension + (`.agr`/`.xmgr` = xmgrace, `.gnu` = gnuplot). Dedicated `*agr`/`*gnu` + keywords force Grace or gnuplot. MPI-parallel (packed + spectral SUM to the master). Assumes NVT (fixed lateral box lengths). + +``` +surftension [] temp + [normal {x|y|z}] [interface {willard|itim}] + [gridspacing ] [dz | dnormal ] + [sigmaxy ] [sigmaz | sigmanormal ] + [bulkhalfwidth ] [threshold ] + [qmin ] [qmax ] [lx ] [ly ] [lz ] + [nblock ] + [spectrumout ] [roughout ] [blockout ] + [spectrumagr ] [roughagr ] [blockagr ] + [spectrumgnu ] [roughgnu ] [blockgnu ] +``` + New functionality ================= - Read topology/coordinates with the 'readdata' command. diff --git a/src/Action_SurfaceTension.cpp b/src/Action_SurfaceTension.cpp new file mode 100644 index 0000000000..fe518665fe --- /dev/null +++ b/src/Action_SurfaceTension.cpp @@ -0,0 +1,1559 @@ +// Action_SurfaceTension +// Capillary-wave surface tension of a liquid slab (Cartesian normal x, y, or z). +// See Action_SurfaceTension.h for the physical formulae. +// \author Nathan D Levinzon +#include +#include +#include +#include +#include +#include "Action_SurfaceTension.h" +#include "Constants.h" +#include "CpptrajStdio.h" +#include "DataFile.h" +#include "DataSet_1D.h" +#include "DataSet_Mesh.h" +#include "Frame.h" +#ifdef _OPENMP +# include +#endif + +// File-local helpers. Names are prefixed ST_ so they do not collide with +// other Action translation units. + +/// Boltzmann constant (J/K); SI, matching the reference Python analysis. +static const double ST_KB = 1.380649e-23; +/// Convert Ų → m². +static const double ST_ANG2_TO_M2 = 1.0e-20; +/// scipy.ndimage.gaussian_filter default truncate (kernel radius = truncate × σ). +static const double ST_GAUSS_TRUNCATE = 4.0; + +/// \return true if x is finite (not NaN or ±Inf). +static inline bool ST_Finite(double x) { + return (x == x) && + (x < std::numeric_limits::infinity()) && + (x > -std::numeric_limits::infinity()); +} + +static inline double ST_NaN() { + return std::numeric_limits::quiet_NaN(); +} + +/// Linear index of density_(ix, iy, iz) with z the fastest dimension. +static inline size_t ST_Idx3(int ix, int iy, int iz, int ny, int nz) { + return ((size_t)ix * (size_t)ny + (size_t)iy) * (size_t)nz + (size_t)iz; +} + +/// Linear index of an nx×ny field stored row-major in x, then y. +static inline size_t ST_Idx2(int ix, int iy, int ny) { + return (size_t)ix * (size_t)ny + (size_t)iy; +} + +/// Round a non-negative value to the nearest integer (ties away from −∞). +static inline int ST_IRound(double x) { + return (int)floor(x + 0.5); +} + +/** Wrap x into [0, L). Handles negative values; maps x == L back to 0. */ +static double ST_Wrap(double x, double L) { + if (L <= 0.0) return x; + double y = fmod(x, L); + if (y < 0.0) y += L; + if (y >= L) y = 0.0; + return y; +} + +/** Recenter a periodic slab so its circular mean along the normal lies at L/2. + * Mapping n → θ = 2π n / L, then using atan2(⟨sin θ⟩, ⟨cos θ⟩), avoids + * failure when the slab straddles the periodic boundary. + */ +static void ST_CircularRecenter(std::vector& n, double L) { + if (n.empty() || L <= 0.0) return; + double mean_sin = 0.0; + double mean_cos = 0.0; + for (size_t i = 0; i < n.size(); i++) { + double theta = Constants::TWOPI * ST_Wrap(n[i], L) / L; + mean_sin += sin(theta); + mean_cos += cos(theta); + } + mean_sin /= (double)n.size(); + mean_cos /= (double)n.size(); + double angle = atan2(mean_sin, mean_cos); + if (angle < 0.0) angle += Constants::TWOPI; + double slab_center = L * angle / Constants::TWOPI; + for (size_t i = 0; i < n.size(); i++) + n[i] = ST_Wrap(n[i] - slab_center + 0.5 * L, L); +} + +/// Cartesian axis name for Help / mprintf (ASCII). +static const char* ST_AxisName(int axis) { + if (axis == 0) return "x"; + if (axis == 1) return "y"; + return "z"; +} + +/// Lateral axis names for a given Cartesian normal. +static void ST_PlaneAxes(int normal, const char*& t1, const char*& t2) { + if (normal == 0) { t1 = "y"; t2 = "z"; } + else if (normal == 1) { t1 = "x"; t2 = "z"; } + else { t1 = "x"; t2 = "y"; } +} + +/// Split Cartesian box lengths into lateral 1, lateral 2, and normal. +static void ST_SplitBox(int normal, double Lx, double Ly, double Lz, + double& Lt1, double& Lt2, double& Ln) +{ + if (normal == 0) { Lt1 = Ly; Lt2 = Lz; Ln = Lx; } + else if (normal == 1) { Lt1 = Lx; Lt2 = Lz; Ln = Ly; } + else { Lt1 = Lx; Lt2 = Ly; Ln = Lz; } +} + +/// Split a Cartesian point into lateral 1, lateral 2, and normal. +static void ST_SplitXYZ(int normal, double x, double y, double z, + double& t1, double& t2, double& n) +{ + if (normal == 0) { t1 = y; t2 = z; n = x; } + else if (normal == 1) { t1 = x; t2 = z; n = y; } + else { t1 = x; t2 = y; n = z; } +} + +/** Normalized 1-D Gaussian kernel matching scipy.ndimage._gaussian_kernel1d. + * σ is in pixels. Radius = round(4 σ). Empty kernel means “do not filter”. + */ +static void ST_GaussianKernel(double sigma, std::vector& kernel) { + kernel.clear(); + if (sigma <= 0.0) return; + int radius = ST_IRound(ST_GAUSS_TRUNCATE * sigma); + if (radius < 0) radius = 0; + kernel.assign((size_t)(2 * radius + 1), 0.0); + double sigma2 = sigma * sigma; + double sum = 0.0; + for (int i = -radius; i <= radius; i++) { + double v = exp(-0.5 * ((double)i * (double)i) / sigma2); + kernel[i + radius] = v; + sum += v; + } + if (sum > 0.0) { + for (size_t i = 0; i < kernel.size(); i++) + kernel[i] /= sum; + } +} + +/** 1-D convolution with periodic (wrap) boundaries. + * The Gaussian kernel is symmetric, so correlate and convolve agree. + */ +static void ST_ConvolveWrap(std::vector const& in, std::vector const& kernel, + std::vector& out) +{ + int n = (int)in.size(); + int ksize = (int)kernel.size(); + int radius = (ksize - 1) / 2; + out.assign((size_t)n, 0.0); + if (n == 0) return; + if (kernel.empty() || ksize < 1) { + out = in; + return; + } + for (int i = 0; i < n; i++) { + double acc = 0.0; + for (int k = -radius; k <= radius; k++) { + int j = i + k; + j %= n; + if (j < 0) j += n; + acc += in[j] * kernel[k + radius]; + } + out[i] = acc; + } +} + +/** Separable Gaussian smooth of ρ(ix,iy,iz) with periodic boundaries on every axis. + * σx, σy, σz are in pixels (Å / bin width), as in scipy.ndimage.gaussian_filter. + * OpenMP: each 1-D line in a pass is independent. One parallel region covers + * the z, y, and x passes so thread-local line buffers are reused. + */ +static void ST_GaussianFilter3D(std::vector& rho, int nx, int ny, int nz, + double sigma_x, double sigma_y, double sigma_z) +{ + std::vector kx, ky, kz; + ST_GaussianKernel(sigma_x, kx); + ST_GaussianKernel(sigma_y, ky); + ST_GaussianKernel(sigma_z, kz); + if (kx.empty() && ky.empty() && kz.empty()) return; + +# ifdef _OPENMP +# pragma omp parallel +# endif + { + std::vector line, conv; + int col; + + if (!kz.empty()) { + line.resize((size_t)nz); + int nxy = nx * ny; +# ifdef _OPENMP +# pragma omp for schedule(dynamic) +# endif + for (col = 0; col < nxy; col++) { + int ix = col / ny; + int iy = col - ix * ny; + for (int iz = 0; iz < nz; iz++) + line[iz] = rho[ST_Idx3(ix, iy, iz, ny, nz)]; + ST_ConvolveWrap(line, kz, conv); + for (int iz = 0; iz < nz; iz++) + rho[ST_Idx3(ix, iy, iz, ny, nz)] = conv[iz]; + } + } + + if (!ky.empty()) { + line.resize((size_t)ny); + int nxz = nx * nz; +# ifdef _OPENMP +# pragma omp for schedule(dynamic) +# endif + for (col = 0; col < nxz; col++) { + int ix = col / nz; + int iz = col - ix * nz; + for (int iy = 0; iy < ny; iy++) + line[iy] = rho[ST_Idx3(ix, iy, iz, ny, nz)]; + ST_ConvolveWrap(line, ky, conv); + for (int iy = 0; iy < ny; iy++) + rho[ST_Idx3(ix, iy, iz, ny, nz)] = conv[iy]; + } + } + + if (!kx.empty()) { + line.resize((size_t)nx); + int nyz = ny * nz; +# ifdef _OPENMP +# pragma omp for schedule(dynamic) +# endif + for (col = 0; col < nyz; col++) { + int iy = col / nz; + int iz = col - iy * nz; + for (int ix = 0; ix < nx; ix++) + line[ix] = rho[ST_Idx3(ix, iy, iz, ny, nz)]; + ST_ConvolveWrap(line, kx, conv); + for (int ix = 0; ix < nx; ix++) + rho[ST_Idx3(ix, iy, iz, ny, nz)] = conv[ix]; + } + } + } +} + +/** Locate the instantaneous interface along one lateral column. + * Walks from the slab center toward +n (upper) or -n (lower) and returns the + * linearly interpolated normal coordinate where rho crosses the bulk-density + * threshold. \return NaN if no crossing is found. + */ +static double ST_FindCrossing(std::vector const& z_grid, + std::vector const& density, + double threshold, int center_index, bool upper) +{ + int nz = (int)z_grid.size(); + if (nz < 2 || center_index < 0 || center_index >= nz) + return ST_NaN(); + if (upper) { + for (int k = center_index; k < nz - 1; k++) { + double rho0 = density[k]; + double rho1 = density[k + 1]; + if (rho0 >= threshold && rho1 < threshold) { + if (fabs(rho1 - rho0) < Constants::SMALL) + return 0.5 * (z_grid[k] + z_grid[k + 1]); + return z_grid[k] + (threshold - rho0) * (z_grid[k + 1] - z_grid[k]) / (rho1 - rho0); + } + } + } else { + for (int k = center_index; k > 0; k--) { + double rho0 = density[k]; + double rho1 = density[k - 1]; + if (rho0 >= threshold && rho1 < threshold) { + if (fabs(rho1 - rho0) < Constants::SMALL) + return 0.5 * (z_grid[k] + z_grid[k - 1]); + return z_grid[k] + (threshold - rho0) * (z_grid[k - 1] - z_grid[k]) / (rho1 - rho0); + } + } + } + return ST_NaN(); +} + +/** ITIM-style slab interfaces after circular recentering at Ln/2. + * In each lateral column: upper = max n of atoms with n >= Ln/2, lower = min n + * of atoms with n < Ln/2. Empty half-columns return false. + * t1/t2/n are lateral 1, lateral 2, and the slab normal. + */ +static bool ST_ItimMinMax(std::vector const& t1, + std::vector const& t2, + std::vector const& n, + int natom, double Lt1, double Lt2, double Ln, + int nx, int ny, + std::vector& h_upper, + std::vector& h_lower) +{ + double dx = Lt1 / (double)nx; + double dy = Lt2 / (double)ny; + double mid = 0.5 * Ln; + size_t n2 = (size_t)nx * (size_t)ny; + const double inf = std::numeric_limits::infinity(); + std::vector zmax(n2, -inf), zmin(n2, inf); + std::vector has_u(n2, 0), has_l(n2, 0); + for (int i = 0; i < natom; i++) { + int ix = (int)floor(t1[i] / dx); + int iy = (int)floor(t2[i] / dy); + if (ix < 0) ix = 0; + if (iy < 0) iy = 0; + if (ix >= nx) ix = nx - 1; + if (iy >= ny) iy = ny - 1; + size_t idx = ST_Idx2(ix, iy, ny); + if (n[i] >= mid) { + if (!has_u[idx] || n[i] > zmax[idx]) zmax[idx] = n[i]; + has_u[idx] = 1; + } else { + if (!has_l[idx] || n[i] < zmin[idx]) zmin[idx] = n[i]; + has_l[idx] = 1; + } + } + for (size_t i = 0; i < n2; i++) { + if (!has_u[i] || !has_l[i]) return false; + h_upper[i] = zmax[i]; + h_lower[i] = zmin[i]; + } + return true; +} + +/** Number density of mask atoms with |n - Ln/2| <= bulk_halfwidth (Ang^-3). */ +static double ST_RhoBulkFromAtoms(std::vector const& ncoord, int natom, + double Lt1, double Lt2, double Ln, + double bulk_halfwidth) +{ + double mid = 0.5 * Ln; + int nbulk = 0; + for (int i = 0; i < natom; i++) { + if (fabs(ncoord[i] - mid) <= bulk_halfwidth) + nbulk++; + } + double vol = Lt1 * Lt2 * 2.0 * bulk_halfwidth; + if (vol <= 0.0) return 0.0; + return (double)nbulk / vol; +} + +/** RMS height fluctuation w = √⟨(h − ⟨h⟩)²⟩_xy (Å). */ +static double ST_RMS(std::vector const& h) { + if (h.empty()) return ST_NaN(); + double mean = 0.0; + for (size_t i = 0; i < h.size(); i++) + mean += h[i]; + mean /= (double)h.size(); + double acc = 0.0; + for (size_t i = 0; i < h.size(); i++) { + double d = h[i] - mean; + acc += d * d; + } + return sqrt(acc / (double)h.size()); +} + +/** Sample frequencies, identical to numpy.fft.fftfreq(n, d)[k]. + * d is the real-space sample spacing (Å). Result is in Å⁻¹. + */ +static double ST_FftFreq(int k, int n, double d) { + int p; + if (k <= (n - 1) / 2) + p = k; + else + p = k - n; + return (double)p / ((double)n * d); +} + +/** 2-D power spectrum of a height field. + * Subtract ⟨h⟩ (q = 0 translation), then + * h_q = (1 / N) Σ h(x,y) exp(−i q · r) N = nx ny + * which matches numpy.fft.fft2(h) / h.size. Power is |h_q|² (Ų). + * Direct DFT is used so nx, ny need not be powers of two. + * OpenMP: each (kx, ky) mode is independent; the loop is flattened so it + * does not need collapse() (OpenMP 3.0), matching other cpptraj Actions. + */ +static void ST_HeightPower(std::vector const& h, int nx, int ny, + std::vector& power) +{ + int nxy = nx * ny; + power.assign((size_t)nxy, 0.0); + if (nxy == 0) return; + double mean = 0.0; + for (int i = 0; i < nxy; i++) + mean += h[i]; + mean /= (double)nxy; + double Ninv = 1.0 / (double)nxy; + int k; +# ifdef _OPENMP +# pragma omp parallel for schedule(dynamic) +# endif + for (k = 0; k < nxy; k++) { + int kx = k / ny; + int ky = k - kx * ny; + double re = 0.0; + double im = 0.0; + for (int ix = 0; ix < nx; ix++) { + for (int iy = 0; iy < ny; iy++) { + double hv = h[ST_Idx2(ix, iy, ny)] - mean; + double ang = Constants::TWOPI * + ((double)kx * (double)ix / (double)nx + + (double)ky * (double)iy / (double)ny); + re += hv * cos(ang); + im -= hv * sin(ang); + } + } + re *= Ninv; + im *= Ninv; + power[k] = re * re + im * im; + } +} + +/** |q| = √(qx² + qy²) for each Fourier mode, qx = 2π fftfreq(nx, Lx/nx). */ +static void ST_MakeQGrid(int nx, int ny, double Lx, double Ly, std::vector& q) { + q.resize((size_t)nx * (size_t)ny); + double dx = Lx / (double)nx; + double dy = Ly / (double)ny; + for (int kx = 0; kx < nx; kx++) { + double qx = Constants::TWOPI * ST_FftFreq(kx, nx, dx); + for (int ky = 0; ky < ny; ky++) { + double qy = Constants::TWOPI * ST_FftFreq(ky, ny, dy); + q[ST_Idx2(kx, ky, ny)] = sqrt(qx * qx + qy * qy); + } + } +} + +/// One isotropic |q| shell after averaging degenerate Fourier modes. +struct ST_Shell { + double q; ///< Mean |q| of modes in this shell (Å⁻¹) + double S; ///< Combined ⟨|h_q|²⟩ (Ų) + double Stop; ///< Upper-interface ⟨|h_q|²⟩ + double Sbot; ///< Lower-interface ⟨|h_q|²⟩ + int n; ///< Number of modes averaged into this shell +}; + +/// Sort shells by increasing |q|. +static bool ST_ShellQCmp(ST_Shell const& a, ST_Shell const& b) { + return a.q < b.q; +} + +/** Isotropic shell average: group modes with the same q² (10 decimal places), + * as in pandas round(q², decimals=10). q = 0 is dropped. + */ +static void ST_ShellAverage(std::vector const& q, + std::vector const& combined, + std::vector const& top, + std::vector const& bot, + std::vector& shells) +{ + shells.clear(); + struct Acc { + Acc() : qsum(0.0), S(0.0), Stop(0.0), Sbot(0.0), n(0) {} + double qsum, S, Stop, Sbot; + int n; + }; + std::map bins; + size_t n = q.size(); + for (size_t i = 0; i < n; i++) { + if (q[i] <= 0.0) continue; + // Group by rounded q², matching numpy.round(q**2, decimals=10). + long long key = (long long)floor(q[i] * q[i] * 1.0e10 + 0.5); + Acc& a = bins[key]; + a.qsum += q[i]; + a.S += combined[i]; + a.Stop += top[i]; + a.Sbot += bot[i]; + a.n++; + } + shells.reserve(bins.size()); + for (std::map::const_iterator it = bins.begin(); it != bins.end(); ++it) { + ST_Shell s; + s.n = it->second.n; + s.q = it->second.qsum / (double)s.n; + s.S = it->second.S / (double)s.n; + s.Stop = it->second.Stop / (double)s.n; + s.Sbot = it->second.Sbot / (double)s.n; + shells.push_back(s); + } + std::sort(shells.begin(), shells.end(), ST_ShellQCmp); +} + +/** Capillary-wave γ from the mean q² S(q) plateau on [qmin, qmax]. + * plateau = ⟨ q² S(q) ⟩_shells + * γ (N/m) = k_B T / (A plateau), then ×1000 → mN/m + * Equal weight per q-shell. Needs at least two shells. + * \return 0 on success, 1 on failure (γ/plateau set to NaN). + */ +static int ST_CalcGamma(std::vector const& shells, double temperature, + double area_A2, double qmin, double qmax, + double& gamma, double& plateau) +{ + gamma = ST_NaN(); + plateau = ST_NaN(); + double acc = 0.0; + int nfit = 0; + for (size_t i = 0; i < shells.size(); i++) { + if (shells[i].q >= qmin && shells[i].q <= qmax) { + acc += shells[i].q * shells[i].q * shells[i].S; + nfit++; + } + } + if (nfit < 2) return 1; + plateau = acc / (double)nfit; + if (plateau <= 0.0) return 1; + double area_m2 = area_A2 * ST_ANG2_TO_M2; + gamma = 1000.0 * ST_KB * temperature / (area_m2 * plateau); + return 0; +} + +/** Helfrich fit on [qmin, qmax]: + * 1 / (q² S) = a + b q² + * q in Å⁻¹, S in Ų, so q² S is dimensionless. + * γ (mN/m) = 1000 k_B T a / A_m² (intercept) + * κ / kT = b / A_Ų (slope) + * Equal weight per shell. Needs at least three shells with S > 0. + * \return 0 on success, 1 on failure (outputs set to NaN). + */ +static int ST_CalcKappa(std::vector const& shells, double temperature, + double area_A2, double qmin, double qmax, + double& gamma, double& kappa_kT) +{ + gamma = ST_NaN(); + kappa_kT = ST_NaN(); + double sx = 0.0, sy = 0.0, sxx = 0.0, sxy = 0.0; + int n = 0; + for (size_t i = 0; i < shells.size(); i++) { + if (shells[i].q < qmin || shells[i].q > qmax) continue; + double q2 = shells[i].q * shells[i].q; + double q2S = q2 * shells[i].S; + if (q2S <= 0.0 || !ST_Finite(q2S)) continue; + double x = q2; + double y = 1.0 / q2S; + sx += x; + sy += y; + sxx += x * x; + sxy += x * y; + n++; + } + if (n < 3) return 1; + double den = (double)n * sxx - sx * sx; + if (fabs(den) < Constants::SMALL) return 1; + double a = (sxx * sy - sx * sxy) / den; + double b = ((double)n * sxy - sx * sy) / den; + if (a <= 0.0 || !ST_Finite(a) || !ST_Finite(b)) return 1; + double area_m2 = area_A2 * ST_ANG2_TO_M2; + gamma = 1000.0 * ST_KB * temperature * a / area_m2; + kappa_kT = b / area_A2; + return 0; +} + +/** Apparent κ(q)/kT given γ (mN/m): invert γ q² + κ q⁴ at one shell. */ +static double ST_ShellKappa(double q, double S, double temperature, double area_A2, + double gamma_mNm) +{ + if (q <= 0.0 || S <= 0.0 || !ST_Finite(gamma_mNm)) return ST_NaN(); + double q2 = q * q; + double q2S = q2 * S; + if (q2S <= 0.0) return ST_NaN(); + double y = 1.0 / q2S; + double area_m2 = area_A2 * ST_ANG2_TO_M2; + double a = area_m2 * (gamma_mNm / 1000.0) / (ST_KB * temperature); + double b = (y - a) / q2; + return b / area_A2; +} + +/** Apparent γ(q) = k_B T / (A q² S(q)) in mN/m. */ +static double ST_ShellGamma(double q, double S, double temperature, double area_A2) { + double q2S = q * q * S; + if (q2S <= 0.0) return ST_NaN(); + double area_m2 = area_A2 * ST_ANG2_TO_M2; + return 1000.0 * ST_KB * temperature / (area_m2 * q2S); +} + +/** Ordinary least-squares slope of log S vs log q on [qmin, qmax]. + * Ideal capillary waves give slope ≈ −2. Sfield selects S / Stop / Sbot. + */ +static double ST_LogSlope(std::vector const& shells, double qmin, double qmax, + double ST_Shell::* Sfield) +{ + double sx = 0.0, sy = 0.0, sxx = 0.0, sxy = 0.0; + int n = 0; + for (size_t i = 0; i < shells.size(); i++) { + double Sval = shells[i].*Sfield; + if (shells[i].q >= qmin && shells[i].q <= qmax && Sval > 0.0) { + double x = log(shells[i].q); + double y = log(Sval); + sx += x; + sy += y; + sxx += x * x; + sxy += x * y; + n++; + } + } + if (n < 2) return ST_NaN(); + double den = (double)n * sxx - sx * sx; + if (fabs(den) < Constants::SMALL) return ST_NaN(); + return ((double)n * sxy - sx * sy) / den; +} + +/** Add ds to each non-null DataFile (ASCII / Grace / gnuplot). */ +static void ST_AddSetToFiles(DataSet* ds, DataFile* a, DataFile* b, DataFile* c) { + if (ds == 0) return; + if (a != 0) a->AddDataSet(ds); + if (b != 0) b->AddDataSet(ds); + if (c != 0) c->AddDataSet(ds); +} + +// ----------------------------------------------------------------------------- +/// CONSTRUCTOR — defaults match the reference Python analysis. +Action_SurfaceTension::Action_SurfaceTension() : + iface_(WILLARD), + normal_(AXIS_Z), + temp_(-1.0), + gridspacing_(2.5), + dz_(1.0), + sigma_xy_(2.5), + sigma_z_(1.5), + bulk_halfwidth_(5.0), + threshold_frac_(0.5), + qmin_(0.033283), + qmax_(0.174649), + lx_user_(-1.0), + ly_user_(-1.0), + lz_user_(-1.0), + nblock_(0), + debug_(0), + S_(0), S_top_(0), S_bot_(0), + q2S_(0), q2S_top_(0), q2S_bot_(0), + gammaq_(0), gammaq_top_(0), gammaq_bot_(0), + kappaq_(0), kappaq_top_(0), kappaq_bot_(0), + wtop_(0), wbot_(0), wmean_(0), rhobulk_(0), + block_gamma_(0), block_kappa_(0), block_wmean_(0), block_wtop_(0), block_wbot_(0), + nx_(0), ny_(0), nz_(0), + Lt1_ref_(0.0), Lt2_ref_(0.0), + grid_ready_(false), + n_frames_(0), n_surfaces_(0), n_skipped_(0), n_blocks_(0), + block_surface_count_(0), block_frame_count_(0), + block_w_sum_(0.0), block_wtop_sum_(0.0), block_wbot_sum_(0.0) +{} + +// Action_SurfaceTension::Help() +void Action_SurfaceTension::Help() const { + mprintf("\t[] temp \n" + "\t[normal {x|y|z}] [interface {willard|itim}]\n" + "\t[gridspacing ] [dz | dnormal ]\n" + "\t[sigmaxy ] [sigmaz | sigmanormal ]\n" + "\t[bulkhalfwidth ] [threshold ]\n" + "\t[qmin ] [qmax ] [lx ] [ly ] [lz ]\n" + "\t[nblock ]\n" + "\t[spectrumout ] [roughout ] [blockout ]\n" + "\t[spectrumagr ] [roughagr ] [blockagr ]\n" + "\t[spectrumgnu ] [roughgnu ] [blockgnu ]\n" + " Calculate capillary-wave surface tension (mN/m) for a liquid slab.\n" + " normal x|y|z selects the slab normal (default z). gridspacing and\n" + " sigmaxy apply in the interface plane; dz (alias dnormal) and sigmaz\n" + " (alias sigmanormal) apply along the normal. should select\n" + " interfacial density atoms (e.g. ':WAT@O'). Interfaces are a\n" + " Willard-Chandler Gaussian density isosurface (default) or ITIM\n" + " per-column min/max of , split at mid-box along the normal.\n" + " Height fluctuations are Fourier transformed; gamma is the small-q\n" + " plateau of q^2 <|h_q|^2>. kappa (kT) is the slope of 1/(q^2 S) vs\n" + " q^2 on the same q window. lx/ly/lz optionally replace Cartesian box\n" + " lengths. Lateral lengths are held fixed (NVT). Assumes an X-aligned\n" + " orthogonal box. DataSets are always created; files are written only\n" + " when the matching *out/*agr/*gnu keyword is given. *out format\n" + " follows the extension (.agr/.xmgr = xmgrace, .gnu = gnuplot,\n" + " otherwise ASCII). *agr/*gnu force Grace or gnuplot. In MPI,\n" + " nblock is per-rank; spectra are summed onto the master.\n"); +} + +// Action_SurfaceTension::Init() +/** Parse keywords, allocate DataSets, attach optional output files. + * Spectrum / roughness DataSets always exist so writedata can dump them. + * Files are written only if the matching *out / *agr / *gnu keyword is given. + * *out uses the DataFile writer for the filename extension (canonical + * cpptraj: .agr/.xmgr = Grace/xmgrace, .gnu = gnuplot). *agr/*gnu force + * DataFile::XMGRACE / GNUPLOT even when the extension is not recognized. + */ +Action::RetType Action_SurfaceTension::Init(ArgList& actionArgs, ActionInit& init, int debugIn) +{ +# ifdef MPI + trajComm_ = init.TrajComm(); +# endif + debug_ = debugIn; + // Optional output files. AddDataFile returns 0 if the keyword is absent. + DataFile* spectrumFile = init.DFL().AddDataFile(actionArgs.GetStringKey("spectrumout"), actionArgs); + DataFile* roughFile = init.DFL().AddDataFile(actionArgs.GetStringKey("roughout"), actionArgs); + DataFile* blockFile = init.DFL().AddDataFile(actionArgs.GetStringKey("blockout"), actionArgs); + DataFile* spectrumAgr = init.DFL().AddDataFile(actionArgs.GetStringKey("spectrumagr"), actionArgs, DataFile::XMGRACE); + DataFile* roughAgr = init.DFL().AddDataFile(actionArgs.GetStringKey("roughagr"), actionArgs, DataFile::XMGRACE); + DataFile* blockAgr = init.DFL().AddDataFile(actionArgs.GetStringKey("blockagr"), actionArgs, DataFile::XMGRACE); + DataFile* spectrumGnu = init.DFL().AddDataFile(actionArgs.GetStringKey("spectrumgnu"), actionArgs, DataFile::GNUPLOT); + DataFile* roughGnu = init.DFL().AddDataFile(actionArgs.GetStringKey("roughgnu"), actionArgs, DataFile::GNUPLOT); + DataFile* blockGnu = init.DFL().AddDataFile(actionArgs.GetStringKey("blockgnu"), actionArgs, DataFile::GNUPLOT); + + temp_ = actionArgs.getKeyDouble("temp", -1.0); + if (temp_ <= 0.0) { + mprinterr("Error: Temperature must be specified with 'temp ' (T > 0).\n"); + return Action::ERR; + } + gridspacing_ = actionArgs.getKeyDouble("gridspacing", 2.5); + sigma_xy_ = actionArgs.getKeyDouble("sigmaxy", 2.5); + bulk_halfwidth_ = actionArgs.getKeyDouble("bulkhalfwidth", 5.0); + threshold_frac_ = actionArgs.getKeyDouble("threshold", 0.5); + qmin_ = actionArgs.getKeyDouble("qmin", 0.033283); + qmax_ = actionArgs.getKeyDouble("qmax", 0.174649); + bool has_lx = actionArgs.Contains("lx"); + bool has_ly = actionArgs.Contains("ly"); + bool has_lz = actionArgs.Contains("lz"); + lx_user_ = actionArgs.getKeyDouble("lx", -1.0); + ly_user_ = actionArgs.getKeyDouble("ly", -1.0); + lz_user_ = actionArgs.getKeyDouble("lz", -1.0); + nblock_ = actionArgs.getKeyInt("nblock", 0); + + // dz / dnormal and sigmaz / sigmanormal are aliases (normal-axis spacing / sigma). + bool has_dz = actionArgs.Contains("dz"); + bool has_dnormal = actionArgs.Contains("dnormal"); + double dz_val = actionArgs.getKeyDouble("dz", 1.0); + double dnormal_val = actionArgs.getKeyDouble("dnormal", 1.0); + if (has_dz && has_dnormal && fabs(dz_val - dnormal_val) > 1.0e-12) { + mprinterr("Error: dz and dnormal both specified and differ.\n"); + return Action::ERR; + } + dz_ = has_dnormal ? dnormal_val : dz_val; + + bool has_sigmaz = actionArgs.Contains("sigmaz"); + bool has_sigman = actionArgs.Contains("sigmanormal"); + double sigmaz_val = actionArgs.getKeyDouble("sigmaz", 1.5); + double sigman_val = actionArgs.getKeyDouble("sigmanormal", 1.5); + if (has_sigmaz && has_sigman && fabs(sigmaz_val - sigman_val) > 1.0e-12) { + mprinterr("Error: sigmaz and sigmanormal both specified and differ.\n"); + return Action::ERR; + } + sigma_z_ = has_sigman ? sigman_val : sigmaz_val; + + std::string nstr = actionArgs.GetStringKey("normal"); + if (nstr.empty() && actionArgs.Contains("normal")) { + mprinterr("Error: 'normal' requires x, y, or z.\n"); + return Action::ERR; + } + if (nstr.empty()) + nstr = "z"; + if (nstr == "x" || nstr == "X") + normal_ = AXIS_X; + else if (nstr == "y" || nstr == "Y") + normal_ = AXIS_Y; + else if (nstr == "z" || nstr == "Z") + normal_ = AXIS_Z; + else { + mprinterr("Error: normal must be 'x', 'y', or 'z'.\n"); + return Action::ERR; + } + + std::string ifacestr = actionArgs.GetStringKey("interface"); + if (ifacestr.empty() && actionArgs.Contains("interface")) { + mprinterr("Error: interface must be 'willard' or 'itim'.\n"); + return Action::ERR; + } + if (ifacestr.empty()) + ifacestr = "willard"; + if (ifacestr == "willard" || ifacestr == "wc") + iface_ = WILLARD; + else if (ifacestr == "itim" || ifacestr == "minmax") + iface_ = ITIM; + else { + mprinterr("Error: interface must be 'willard' or 'itim'.\n"); + return Action::ERR; + } + + if (has_lx && lx_user_ <= 0.0) { + mprinterr("Error: lx must be > 0.\n"); + return Action::ERR; + } + if (has_ly && ly_user_ <= 0.0) { + mprinterr("Error: ly must be > 0.\n"); + return Action::ERR; + } + if (has_lz && lz_user_ <= 0.0) { + mprinterr("Error: lz must be > 0.\n"); + return Action::ERR; + } + + if (gridspacing_ <= 0.0) { + mprinterr("Error: gridspacing must be > 0.\n"); + return Action::ERR; + } + if (iface_ == WILLARD) { + if (dz_ <= 0.0) { + mprinterr("Error: dz (or dnormal) must be > 0.\n"); + return Action::ERR; + } + if (sigma_xy_ < 0.0 || sigma_z_ < 0.0) { + mprinterr("Error: sigmaxy and sigmaz (or sigmanormal) must be >= 0.\n"); + return Action::ERR; + } + if (threshold_frac_ <= 0.0 || threshold_frac_ >= 1.0) { + mprinterr("Error: threshold must be between 0 and 1.\n"); + return Action::ERR; + } + } + if (bulk_halfwidth_ <= 0.0) { + mprinterr("Error: bulkhalfwidth must be > 0.\n"); + return Action::ERR; + } + if (qmax_ <= qmin_) { + mprinterr("Error: qmax must be greater than qmin.\n"); + return Action::ERR; + } + if (nblock_ < 0) { + mprinterr("Error: nblock must be >= 0.\n"); + return Action::ERR; + } + if ((blockFile != 0 || blockAgr != 0 || blockGnu != 0) && nblock_ < 1) { + mprinterr("Error: 'blockout'/'blockagr'/'blockgnu' require 'nblock '.\n"); + return Action::ERR; + } + + std::string maskexp = actionArgs.GetMaskNext(); + if (maskexp.empty()) { + mprinterr("Error: No atom mask given.\n"); + return Action::ERR; + } + if (Mask_.SetMaskString(maskexp)) return Action::ERR; + + // Dataset name is the leftover argument (cpptraj convention). Reuse the + // generated name so all aspects share one set family (ST_00000, …). + std::string dsname = actionArgs.GetStringNext(); + S_ = (DataSet_Mesh*)init.DSL().AddSet(DataSet::XYMESH, MetaData(dsname, "S", MetaData::NOT_TS), "ST"); + if (S_ == 0) return Action::ERR; + dsname = S_->Meta().Name(); + S_top_ = (DataSet_Mesh*)init.DSL().AddSet(DataSet::XYMESH, MetaData(dsname, "Stop", MetaData::NOT_TS), "ST"); + S_bot_ = (DataSet_Mesh*)init.DSL().AddSet(DataSet::XYMESH, MetaData(dsname, "Sbot", MetaData::NOT_TS), "ST"); + q2S_ = (DataSet_Mesh*)init.DSL().AddSet(DataSet::XYMESH, MetaData(dsname, "q2S", MetaData::NOT_TS), "ST"); + q2S_top_ = (DataSet_Mesh*)init.DSL().AddSet(DataSet::XYMESH, MetaData(dsname, "q2Stop", MetaData::NOT_TS), "ST"); + q2S_bot_ = (DataSet_Mesh*)init.DSL().AddSet(DataSet::XYMESH, MetaData(dsname, "q2Sbot", MetaData::NOT_TS), "ST"); + gammaq_ = (DataSet_Mesh*)init.DSL().AddSet(DataSet::XYMESH, MetaData(dsname, "gammaq", MetaData::NOT_TS), "ST"); + gammaq_top_= (DataSet_Mesh*)init.DSL().AddSet(DataSet::XYMESH, MetaData(dsname, "gammaqtop", MetaData::NOT_TS), "ST"); + gammaq_bot_= (DataSet_Mesh*)init.DSL().AddSet(DataSet::XYMESH, MetaData(dsname, "gammaqbot", MetaData::NOT_TS), "ST"); + kappaq_ = (DataSet_Mesh*)init.DSL().AddSet(DataSet::XYMESH, MetaData(dsname, "kappaq", MetaData::NOT_TS), "ST"); + kappaq_top_= (DataSet_Mesh*)init.DSL().AddSet(DataSet::XYMESH, MetaData(dsname, "kappaqtop", MetaData::NOT_TS), "ST"); + kappaq_bot_= (DataSet_Mesh*)init.DSL().AddSet(DataSet::XYMESH, MetaData(dsname, "kappaqbot", MetaData::NOT_TS), "ST"); + if (S_==0 || S_top_==0 || S_bot_==0 || q2S_==0 || q2S_top_==0 || q2S_bot_==0 || + gammaq_==0 || gammaq_top_==0 || gammaq_bot_==0 || + kappaq_==0 || kappaq_top_==0 || kappaq_bot_==0) + return Action::ERR; + // Grace/gnuplot xlabel comes from Dim(0). Mesh X values are q, not a uniform grid. + Dimension qdim(0.0, 1.0, "q (Ang^-1)"); + S_->SetDim(Dimension::X, qdim); + S_top_->SetDim(Dimension::X, qdim); + S_bot_->SetDim(Dimension::X, qdim); + q2S_->SetDim(Dimension::X, qdim); + q2S_top_->SetDim(Dimension::X, qdim); + q2S_bot_->SetDim(Dimension::X, qdim); + gammaq_->SetDim(Dimension::X, qdim); + gammaq_top_->SetDim(Dimension::X, qdim); + gammaq_bot_->SetDim(Dimension::X, qdim); + kappaq_->SetDim(Dimension::X, qdim); + kappaq_top_->SetDim(Dimension::X, qdim); + kappaq_bot_->SetDim(Dimension::X, qdim); + // Print() fills these from the accumulated spectra; they are not time series. + // MPI: SyncAction reduces |h_q|^2; skip DataSet concat of empty meshes. +# ifdef MPI + S_->SetNeedsSync(false); S_top_->SetNeedsSync(false); S_bot_->SetNeedsSync(false); + q2S_->SetNeedsSync(false); q2S_top_->SetNeedsSync(false); q2S_bot_->SetNeedsSync(false); + gammaq_->SetNeedsSync(false); gammaq_top_->SetNeedsSync(false); gammaq_bot_->SetNeedsSync(false); + kappaq_->SetNeedsSync(false); kappaq_top_->SetNeedsSync(false); kappaq_bot_->SetNeedsSync(false); +# endif + ST_AddSetToFiles(S_, spectrumFile, spectrumAgr, spectrumGnu); + ST_AddSetToFiles(S_top_, spectrumFile, spectrumAgr, spectrumGnu); + ST_AddSetToFiles(S_bot_, spectrumFile, spectrumAgr, spectrumGnu); + ST_AddSetToFiles(q2S_, spectrumFile, spectrumAgr, spectrumGnu); + ST_AddSetToFiles(q2S_top_, spectrumFile, spectrumAgr, spectrumGnu); + ST_AddSetToFiles(q2S_bot_, spectrumFile, spectrumAgr, spectrumGnu); + ST_AddSetToFiles(gammaq_, spectrumFile, spectrumAgr, spectrumGnu); + ST_AddSetToFiles(gammaq_top_, spectrumFile, spectrumAgr, spectrumGnu); + ST_AddSetToFiles(gammaq_bot_, spectrumFile, spectrumAgr, spectrumGnu); + ST_AddSetToFiles(kappaq_, spectrumFile, spectrumAgr, spectrumGnu); + ST_AddSetToFiles(kappaq_top_, spectrumFile, spectrumAgr, spectrumGnu); + ST_AddSetToFiles(kappaq_bot_, spectrumFile, spectrumAgr, spectrumGnu); + + wtop_ = init.DSL().AddSet(DataSet::DOUBLE, MetaData(dsname, "wtop"), "ST"); + wbot_ = init.DSL().AddSet(DataSet::DOUBLE, MetaData(dsname, "wbot"), "ST"); + wmean_ = init.DSL().AddSet(DataSet::DOUBLE, MetaData(dsname, "wmean"), "ST"); + rhobulk_= init.DSL().AddSet(DataSet::DOUBLE, MetaData(dsname, "rhobulk"), "ST"); + if (wtop_==0 || wbot_==0 || wmean_==0 || rhobulk_==0) return Action::ERR; + ST_AddSetToFiles(wtop_, roughFile, roughAgr, roughGnu); + ST_AddSetToFiles(wbot_, roughFile, roughAgr, roughGnu); + ST_AddSetToFiles(wmean_, roughFile, roughAgr, roughGnu); + ST_AddSetToFiles(rhobulk_, roughFile, roughAgr, roughGnu); + + if (nblock_ > 0) { + // Block DataSets are indexed by completed block, not by frame. + block_gamma_ = init.DSL().AddSet(DataSet::DOUBLE, MetaData(dsname, "bgamma"), "ST"); + block_kappa_ = init.DSL().AddSet(DataSet::DOUBLE, MetaData(dsname, "bkappa"), "ST"); + block_wmean_ = init.DSL().AddSet(DataSet::DOUBLE, MetaData(dsname, "bwmean"), "ST"); + block_wtop_ = init.DSL().AddSet(DataSet::DOUBLE, MetaData(dsname, "bwtop"), "ST"); + block_wbot_ = init.DSL().AddSet(DataSet::DOUBLE, MetaData(dsname, "bwbot"), "ST"); + if (block_gamma_==0 || block_kappa_==0 || block_wmean_==0 || block_wtop_==0 || block_wbot_==0) + return Action::ERR; + ST_AddSetToFiles(block_gamma_, blockFile, blockAgr, blockGnu); + ST_AddSetToFiles(block_kappa_, blockFile, blockAgr, blockGnu); + ST_AddSetToFiles(block_wmean_, blockFile, blockAgr, blockGnu); + ST_AddSetToFiles(block_wtop_, blockFile, blockAgr, blockGnu); + ST_AddSetToFiles(block_wbot_, blockFile, blockAgr, blockGnu); + } + + mprintf(" SURFTENSION: Capillary-wave surface tension.\n"); + mprintf("\tMask: '%s'\n", Mask_.MaskString()); + { + const char* t1 = 0; + const char* t2 = 0; + ST_PlaneAxes((int)normal_, t1, t2); + mprintf("\tSlab normal: %s (interface plane %s-%s)\n", + ST_AxisName((int)normal_), t1, t2); + } + if (iface_ == WILLARD) + mprintf("\tInterface: Willard-Chandler density isosurface.\n"); + else + mprintf("\tInterface: ITIM min/max (per-column, split at mid-box along %s).\n", + ST_AxisName((int)normal_)); + mprintf("\tTemperature= %g K\n", temp_); + mprintf("\tInterface-plane grid spacing= %g Ang\n", gridspacing_); + if (iface_ == WILLARD) { + mprintf("\tNormal-axis bin spacing (dz)= %g Ang\n", dz_); + mprintf("\tGaussian sigma in plane= %g Ang, along normal= %g Ang\n", + sigma_xy_, sigma_z_); + mprintf("\tBulk half-width= %g Ang, threshold fraction= %g\n", + bulk_halfwidth_, threshold_frac_); + } else { + mprintf("\tBulk half-width (rho_bulk only)= %g Ang\n", bulk_halfwidth_); + } + mprintf("\tFit q range= %g to %g Ang^-1\n", qmin_, qmax_); + mprintf("\tHelfrich kappa: linear fit of 1/(q^2 S) vs q^2 on that window.\n"); + if (lx_user_ > 0.0) + mprintf("\tUsing fixed Lx= %g Ang (%s)\n", lx_user_, + (normal_ == AXIS_X) ? "normal" : "lateral"); + if (ly_user_ > 0.0) + mprintf("\tUsing fixed Ly= %g Ang (%s)\n", ly_user_, + (normal_ == AXIS_Y) ? "normal" : "lateral"); + if (lz_user_ > 0.0) + mprintf("\tUsing fixed Lz= %g Ang (%s)\n", lz_user_, + (normal_ == AXIS_Z) ? "normal" : "lateral"); + if (nblock_ > 0) { + mprintf("\tBlock averaging every %i analyzed frames", nblock_); +# ifdef MPI + if (trajComm_.Size() > 1) + mprintf(" (per rank)"); +# endif + mprintf(".\n"); + } else + mprintf("\tBlock averaging disabled.\n"); + mprintf("\tSpectrum DataSets: %s %s %s %s %s %s %s %s %s %s %s %s\n", + S_->legend(), S_top_->legend(), S_bot_->legend(), + q2S_->legend(), q2S_top_->legend(), q2S_bot_->legend(), + gammaq_->legend(), gammaq_top_->legend(), gammaq_bot_->legend(), + kappaq_->legend(), kappaq_top_->legend(), kappaq_bot_->legend()); + if (spectrumFile != 0) + mprintf("\tSpectrum output to '%s' (%s)\n", spectrumFile->DataFilename().full(), + spectrumFile->FormatString()); + if (spectrumAgr != 0) + mprintf("\tSpectrum Grace output to '%s'\n", spectrumAgr->DataFilename().full()); + if (spectrumGnu != 0) + mprintf("\tSpectrum gnuplot output to '%s'\n", spectrumGnu->DataFilename().full()); + if (roughFile != 0) + mprintf("\tRoughness output to '%s' (%s)\n", roughFile->DataFilename().full(), + roughFile->FormatString()); + if (roughAgr != 0) + mprintf("\tRoughness Grace output to '%s'\n", roughAgr->DataFilename().full()); + if (roughGnu != 0) + mprintf("\tRoughness gnuplot output to '%s'\n", roughGnu->DataFilename().full()); + if (blockFile != 0) + mprintf("\tBlock output to '%s' (%s)\n", blockFile->DataFilename().full(), + blockFile->FormatString()); + if (blockAgr != 0) + mprintf("\tBlock Grace output to '%s'\n", blockAgr->DataFilename().full()); + if (blockGnu != 0) + mprintf("\tBlock gnuplot output to '%s'\n", blockGnu->DataFilename().full()); +# ifdef _OPENMP + { + int nthreads = 1; +# pragma omp parallel + { +# pragma omp master + nthreads = omp_get_num_threads(); + } + if (nthreads > 1) { + mprintf("\tOpenMP: 2-D DFT"); + if (iface_ == WILLARD) + mprintf(" and 3-D Gaussian filter"); + mprintf(" parallelized with %i threads.\n", nthreads); + } + } +# endif +# ifdef MPI + if (trajComm_.Size() > 1) + mprintf("\tMPI: |h_q|^2 spectra reduced to master with one packed SUM.\n"); +# endif + return Action::OK; +} + +// Action_SurfaceTension::Setup() +Action::RetType Action_SurfaceTension::Setup(ActionSetup& setup) +{ + if (!setup.CoordInfo().HasBox()) { + mprintf("Warning: No unit cell; surface tension cannot be calculated for '%s'\n", + setup.Top().c_str()); + return Action::SKIP; + } + if (!setup.CoordInfo().TrajBox().Is_X_Aligned_Ortho()) { + mprintf("Warning: Box is not X-aligned orthorhombic; wrapping Cartesian\n" + "Warning: coordinates independently may not be correct.\n"); + } + if (setup.Top().SetupIntegerMask(Mask_)) return Action::ERR; + Mask_.MaskInfo(); + if (Mask_.None()) { + mprintf("Warning: Mask '%s' selects no atoms.\n", Mask_.MaskString()); + return Action::SKIP; + } + return Action::OK; +} + +// Action_SurfaceTension::AllocateGrid() +int Action_SurfaceTension::AllocateGrid(int nx, int ny, int nz) { + nx_ = nx; + ny_ = ny; + nz_ = nz; + size_t n3 = (size_t)nx * (size_t)ny * (size_t)nz; + size_t n2 = (size_t)nx * (size_t)ny; + if (nz > 0) + density_.assign(n3, 0.0); + else + density_.clear(); + h_upper_.assign(n2, 0.0); + h_lower_.assign(n2, 0.0); + total_power_.assign(n2, 0.0); + top_power_.assign(n2, 0.0); + bottom_power_.assign(n2, 0.0); + block_power_.assign(n2, 0.0); + ST_MakeQGrid(nx_, ny_, Lt1_ref_, Lt2_ref_, q_grid_); + grid_ready_ = true; + double qmin_acc = 0.0; + bool haveq = false; + for (size_t i = 0; i < q_grid_.size(); i++) { + if (q_grid_[i] > 0.0 && (!haveq || q_grid_[i] < qmin_acc)) { + qmin_acc = q_grid_[i]; + haveq = true; + } + } + const char* t1 = 0; + const char* t2 = 0; + ST_PlaneAxes((int)normal_, t1, t2); + mprintf("\tInterface grid = %i x %i", nx_, ny_); + if (nz_ > 0) + mprintf(" x %i", nz_); + mprintf(" (%s x %s", t1, t2); + if (nz_ > 0) + mprintf(" x %s", ST_AxisName((int)normal_)); + mprintf(")\n"); + mprintf("\t%s x %s = %g x %g Ang\n", t1, t2, Lt1_ref_, Lt2_ref_); + if (haveq) + mprintf("\tSmallest accessible q = %g Ang^-1\n", qmin_acc); + return 0; +} + +// Action_SurfaceTension::ProcessFrame() +/** Wrap laterals, recenter along the normal, build instantaneous interfaces, + * then accumulate roughness and |h_q|^2. First good frame freezes nx, ny, + * Lt1, Lt2 (and nz for Willard-Chandler). Cartesian Lx/Ly/Lz are permuted + * into (Lt1, Lt2, Ln) according to normal_. + */ +int Action_SurfaceTension::ProcessFrame(Frame const& frm, double Lx, double Ly, double Lz) +{ + int nax = (int)normal_; + double Lt1, Lt2, Ln; + ST_SplitBox(nax, Lx, Ly, Lz, Lt1, Lt2, Ln); + + int natom = Mask_.Nselected(); + std::vector t1((size_t)natom), t2((size_t)natom), n((size_t)natom); + int idx = 0; + for (AtomMask::const_iterator at = Mask_.begin(); at != Mask_.end(); ++at, ++idx) { + const double* xyz = frm.XYZ(*at); + double a, b, c; + ST_SplitXYZ(nax, xyz[0], xyz[1], xyz[2], a, b, c); + t1[idx] = ST_Wrap(a, Lt1); + t2[idx] = ST_Wrap(b, Lt2); + n[idx] = c; + } + ST_CircularRecenter(n, Ln); + + // Same bin counts as the reference Python: max(8, round(L/spacing)) in the + // interface plane, max(32, round(Ln/dz)) along the normal (Willard only). + int nx = std::max(8, ST_IRound(Lt1 / gridspacing_)); + int ny = std::max(8, ST_IRound(Lt2 / gridspacing_)); + int nz = 0; + if (iface_ == WILLARD) + nz = std::max(32, ST_IRound(Ln / dz_)); + + if (!grid_ready_) { + Lt1_ref_ = Lt1; + Lt2_ref_ = Lt2; + AllocateGrid(nx, ny, nz); + } else { + if (nx != nx_ || ny != ny_) { + mprinterr("Error: Interface grid dimensions changed during the trajectory.\n"); + return 2; + } + if (fabs(Lt1 - Lt1_ref_) > 1.0e-5 || fabs(Lt2 - Lt2_ref_) > 1.0e-5) { + mprinterr("Error: Lateral box dimensions changed. surftension assumes a fixed interface plane (NVT).\n"); + return 2; + } + if (iface_ == WILLARD && nz != nz_) { + // Normal-axis length may jitter slightly; keep the first-frame nz. + nz = nz_; + } + } + + double rho_bulk = 0.0; + if (iface_ == ITIM) { + rho_bulk = ST_RhoBulkFromAtoms(n, natom, Lt1, Lt2, Ln, bulk_halfwidth_); + if (!ST_ItimMinMax(t1, t2, n, natom, Lt1, Lt2, Ln, nx_, ny_, h_upper_, h_lower_)) { + mprintf("Warning: Empty ITIM column; skipping frame.\n"); + return 1; + } + } else { + double dx = Lt1 / (double)nx_; + double dy = Lt2 / (double)ny_; + double dz = Ln / (double)nz_; + double voxel = dx * dy * dz; + // Histogram counts, then convert to number density (Ang^-3). + std::fill(density_.begin(), density_.end(), 0.0); + for (int i = 0; i < natom; i++) { + int ix = (int)floor(t1[i] / dx); + int iy = (int)floor(t2[i] / dy); + int iz = (int)floor(n[i] / dz); + if (ix < 0) ix = 0; + if (iy < 0) iy = 0; + if (iz < 0) iz = 0; + if (ix >= nx_) ix = nx_ - 1; + if (iy >= ny_) iy = ny_ - 1; + if (iz >= nz_) iz = nz_ - 1; + density_[ST_Idx3(ix, iy, iz, ny_, nz_)] += 1.0; + } + if (voxel > 0.0) { + for (size_t i = 0; i < density_.size(); i++) + density_[i] /= voxel; + } + + ST_GaussianFilter3D(density_, nx_, ny_, nz_, + sigma_xy_ / dx, sigma_xy_ / dy, sigma_z_ / dz); + + // Bin centers, matching 0.5 * (edges[:-1] + edges[1:]) of numpy.histogramdd. + std::vector n_grid((size_t)nz_); + for (int iz = 0; iz < nz_; iz++) + n_grid[iz] = ((double)iz + 0.5) * dz; + double slab_center = 0.5 * Ln; + int center_index = 0; + double best = fabs(n_grid[0] - slab_center); + for (int iz = 1; iz < nz_; iz++) { + double d = fabs(n_grid[iz] - slab_center); + if (d < best) { + best = d; + center_index = iz; + } + } + + std::vector rho_n((size_t)nz_, 0.0); + double nxy = (double)(nx_ * ny_); + for (int ix = 0; ix < nx_; ix++) { + for (int iy = 0; iy < ny_; iy++) { + for (int iz = 0; iz < nz_; iz++) + rho_n[iz] += density_[ST_Idx3(ix, iy, iz, ny_, nz_)]; + } + } + for (int iz = 0; iz < nz_; iz++) + rho_n[iz] /= nxy; + + // rho_bulk is the laterally averaged density within +/- bulk_halfwidth of Ln/2. + double rho_bulk_acc = 0.0; + int nbulk = 0; + for (int iz = 0; iz < nz_; iz++) { + if (fabs(n_grid[iz] - slab_center) <= bulk_halfwidth_) { + rho_bulk_acc += rho_n[iz]; + nbulk++; + } + } + if (nbulk < 1) { + mprintf("Warning: No bins along the normal fall within the bulk region; skipping frame.\n"); + return 1; + } + rho_bulk = rho_bulk_acc / (double)nbulk; + if (rho_bulk <= 0.0) { + mprintf("Warning: Bulk density is non-positive; skipping frame.\n"); + return 1; + } + double threshold = threshold_frac_ * rho_bulk; + + // One height pair per lateral column. Any missing crossing skips the frame. + std::vector col((size_t)nz_); + bool ok = true; + for (int ix = 0; ix < nx_ && ok; ix++) { + for (int iy = 0; iy < ny_; iy++) { + for (int iz = 0; iz < nz_; iz++) + col[iz] = density_[ST_Idx3(ix, iy, iz, ny_, nz_)]; + double hu = ST_FindCrossing(n_grid, col, threshold, center_index, true); + double hl = ST_FindCrossing(n_grid, col, threshold, center_index, false); + if (!ST_Finite(hu) || !ST_Finite(hl)) { + ok = false; + break; + } + h_upper_[ST_Idx2(ix, iy, ny_)] = hu; + h_lower_[ST_Idx2(ix, iy, ny_)] = hl; + } + } + if (!ok) { + mprintf("Warning: Could not identify a local interface; skipping frame.\n"); + return 1; + } + } + + double w_top = ST_RMS(h_upper_); + double w_bot = ST_RMS(h_lower_); + double w_mean = 0.5 * (w_top + w_bot); + + // Combined spectrum averages both surfaces (n_surfaces_ = 2 n_frames_). + std::vector p_upper, p_lower; + ST_HeightPower(h_upper_, nx_, ny_, p_upper); + ST_HeightPower(h_lower_, nx_, ny_, p_lower); + + for (size_t i = 0; i < top_power_.size(); i++) { + top_power_[i] += p_upper[i]; + bottom_power_[i] += p_lower[i]; + total_power_[i] += p_upper[i] + p_lower[i]; + block_power_[i] += p_upper[i] + p_lower[i]; + } + + n_frames_++; + n_surfaces_ += 2; + block_surface_count_ += 2; + block_frame_count_++; + block_w_sum_ += w_mean; + block_wtop_sum_ += w_top; + block_wbot_sum_ += w_bot; + + int fidx = n_frames_ - 1; + wtop_->Add(fidx, &w_top); + wbot_->Add(fidx, &w_bot); + wmean_->Add(fidx, &w_mean); + rhobulk_->Add(fidx, &rho_bulk); + + if (nblock_ > 0 && (n_frames_ % nblock_) == 0) { + if (FinishBlock()) return 2; + } + return 0; +} + +// Action_SurfaceTension::FinishBlock() +/** Average the open-block power, fit γ and κ, store roughness means, then reset. */ +int Action_SurfaceTension::FinishBlock() { + if (block_surface_count_ < 1 || block_frame_count_ < 1) return 0; + std::vector spec(block_power_.size()); + for (size_t i = 0; i < spec.size(); i++) + spec[i] = block_power_[i] / (double)block_surface_count_; + std::vector shells; + ST_ShellAverage(q_grid_, spec, spec, spec, shells); + double gamma, plateau; + double gamma_k, kappa_kT; + int err_g = ST_CalcGamma(shells, temp_, Lt1_ref_ * Lt2_ref_, qmin_, qmax_, gamma, plateau); + int err_k = ST_CalcKappa(shells, temp_, Lt1_ref_ * Lt2_ref_, qmin_, qmax_, gamma_k, kappa_kT); + (void)gamma_k; + if (err_g) { + mprintf("Warning: Block %i: fewer than two q shells in the fit range; skipping block gamma.\n", + n_blocks_ + 1); + } else { + double wmean = block_w_sum_ / (double)block_frame_count_; + double wtop = block_wtop_sum_ / (double)block_frame_count_; + double wbot = block_wbot_sum_ / (double)block_frame_count_; + if (block_gamma_ != 0) { + block_gamma_->Add(n_blocks_, &gamma); + if (block_kappa_ != 0) + block_kappa_->Add(n_blocks_, &kappa_kT); + block_wmean_->Add(n_blocks_, &wmean); + block_wtop_->Add(n_blocks_, &wtop); + block_wbot_->Add(n_blocks_, &wbot); + } + if (err_k) + mprintf("\tBlock %i: gamma = %g mN/m, roughness = %g Ang\n", + n_blocks_ + 1, gamma, wmean); + else + mprintf("\tBlock %i: gamma = %g mN/m, kappa = %g kT, roughness = %g Ang\n", + n_blocks_ + 1, gamma, kappa_kT, wmean); + n_blocks_++; + } + std::fill(block_power_.begin(), block_power_.end(), 0.0); + block_surface_count_ = 0; + block_frame_count_ = 0; + block_w_sum_ = block_wtop_sum_ = block_wbot_sum_ = 0.0; + return 0; +} + +// Action_SurfaceTension::DoAction() +Action::RetType Action_SurfaceTension::DoAction(int, ActionFrame& frm) +{ + if (!frm.Frm().BoxCrd().HasBox()) { + mprintf("Warning: Frame has no box; skipping.\n"); + n_skipped_++; + return Action::OK; + } + Vec3 lengths = frm.Frm().BoxCrd().Lengths(); + // Optional lx/ly/lz override the trajectory box (NVT slabs with noisy box records). + double Lx = (lx_user_ > 0.0) ? lx_user_ : lengths[0]; + double Ly = (ly_user_ > 0.0) ? ly_user_ : lengths[1]; + double Lz = (lz_user_ > 0.0) ? lz_user_ : lengths[2]; + if (Lx <= 0.0 || Ly <= 0.0 || Lz <= 0.0) { + mprintf("Warning: Invalid box lengths; skipping frame.\n"); + n_skipped_++; + return Action::OK; + } + int err = ProcessFrame(frm.Frm(), Lx, Ly, Lz); + if (err == 1) { + n_skipped_++; + return Action::OK; + } + if (err == 2) return Action::ERR; + return Action::OK; +} + +#ifdef MPI +// Action_SurfaceTension::SyncAction() +/** Radial-style reduction. Three small AllReduces (counts SUM, grid MAX, lateral + * box MAX) then one packed ReduceMaster SUM of combined/upper/lower |h_q|^2 onto + * the master. |q| uses a separate MAX (different MPI_Op). Print() is master + * only. Roughness / block series use DataSet::Sync (concat by rank). + */ +int Action_SurfaceTension::SyncAction() { + if (trajComm_.Size() < 2) return 0; + + int counts[4] = { n_frames_, n_surfaces_, n_skipped_, block_frame_count_ }; + trajComm_.AllReduce(counts, 4, MPI_INT, MPI_SUM); + n_frames_ = counts[0]; + n_surfaces_ = counts[1]; + n_skipped_ = counts[2]; + block_frame_count_ = counts[3]; + + int n2 = (int)total_power_.size(); + int imax[3] = { n2, nx_, ny_ }; + trajComm_.AllReduce(imax, 3, MPI_INT, MPI_MAX); + int n2max = imax[0]; + nx_ = imax[1]; + ny_ = imax[2]; + double box[2] = { Lt1_ref_, Lt2_ref_ }; + trajComm_.AllReduce(box, 2, MPI_DOUBLE, MPI_MAX); + Lt1_ref_ = box[0]; + Lt2_ref_ = box[1]; + + if (n2max < 1) return 0; + if (n2 != 0 && n2 != n2max) { + rprintf("Error: surftension Fourier grid size %i differs from other ranks (%i).\n", + n2, n2max); + return 1; + } + if (n2 == 0) { + total_power_.assign((size_t)n2max, 0.0); + top_power_.assign((size_t)n2max, 0.0); + bottom_power_.assign((size_t)n2max, 0.0); + q_grid_.assign((size_t)n2max, 0.0); + } + + // One ReduceMaster for all three spectra (latency-bound, not bandwidth). + int npack = n2max * 3; + std::vector send((size_t)npack); + std::copy(total_power_.begin(), total_power_.end(), send.begin()); + std::copy(top_power_.begin(), top_power_.end(), send.begin() + n2max); + std::copy(bottom_power_.begin(), bottom_power_.end(), send.begin() + 2 * n2max); + if (trajComm_.Master()) { + std::vector recv((size_t)npack); + trajComm_.ReduceMaster(&recv[0], &send[0], npack, MPI_DOUBLE, MPI_SUM); + total_power_.assign(recv.begin(), recv.begin() + n2max); + top_power_.assign(recv.begin() + n2max, recv.begin() + 2 * n2max); + bottom_power_.assign(recv.begin() + 2 * n2max, recv.end()); + } else { + trajComm_.ReduceMaster(0, &send[0], npack, MPI_DOUBLE, MPI_SUM); + } + + if (q_grid_.size() != (size_t)n2max) + q_grid_.assign((size_t)n2max, 0.0); + if (trajComm_.Master()) { + std::vector qmaxv((size_t)n2max); + trajComm_.ReduceMaster(&qmaxv[0], &q_grid_[0], n2max, MPI_DOUBLE, MPI_MAX); + q_grid_.swap(qmaxv); + grid_ready_ = true; + } else { + trajComm_.ReduceMaster(0, &q_grid_[0], n2max, MPI_DOUBLE, MPI_MAX); + } + return 0; +} +#endif + +// Action_SurfaceTension::Print() +/** Average accumulated spectra, fill q-meshes, report γ / roughness / blocks. */ +void Action_SurfaceTension::Print() +{ + const char* t1 = 0; + const char* t2 = 0; + ST_PlaneAxes((int)normal_, t1, t2); + mprintf(" SURFTENSION:\n"); + mprintf("\tSlab normal: %s (interface plane %s-%s)\n", + ST_AxisName((int)normal_), t1, t2); + if (iface_ == WILLARD) + mprintf("\tInterface: Willard-Chandler density isosurface.\n"); + else + mprintf("\tInterface: ITIM min/max.\n"); + if (nblock_ > 0 && block_frame_count_ > 0) { + mprintf("\tNOTE: Incomplete nblock window (%i frames) excluded from blockout.\n", + block_frame_count_); + } + if (n_frames_ < 1) { + mprinterr("Error: surftension: No frames were analyzed"); + if (n_skipped_ > 0) + mprinterr(" (%i skipped)", n_skipped_); + mprinterr(".\n"); + return; + } + + std::vector spec(total_power_.size()); + std::vector spec_top(top_power_.size()); + std::vector spec_bot(bottom_power_.size()); + for (size_t i = 0; i < spec.size(); i++) { + spec[i] = total_power_[i] / (double)n_surfaces_; + spec_top[i] = top_power_[i] / (double)n_frames_; + spec_bot[i] = bottom_power_[i] / (double)n_frames_; + } + std::vector shells; + ST_ShellAverage(q_grid_, spec, spec_top, spec_bot, shells); + + // Fit γ on the combined, upper-only, and lower-only shells. + double area = Lt1_ref_ * Lt2_ref_; + double gamma_full, plateau; + double gamma_top, plateau_top; + double gamma_bot, plateau_bot; + std::vector top_only = shells; + std::vector bot_only = shells; + for (size_t i = 0; i < shells.size(); i++) { + top_only[i].S = shells[i].Stop; + bot_only[i].S = shells[i].Sbot; + } + int err_full = ST_CalcGamma(shells, temp_, area, qmin_, qmax_, gamma_full, plateau); + int err_top = ST_CalcGamma(top_only, temp_, area, qmin_, qmax_, gamma_top, plateau_top); + int err_bot = ST_CalcGamma(bot_only, temp_, area, qmin_, qmax_, gamma_bot, plateau_bot); + (void)plateau_top; + (void)plateau_bot; + double gamma_h, kappa_h, gamma_h_top, kappa_h_top, gamma_h_bot, kappa_h_bot; + int err_kh = ST_CalcKappa(shells, temp_, area, qmin_, qmax_, gamma_h, kappa_h); + int err_kh_top = ST_CalcKappa(top_only, temp_, area, qmin_, qmax_, gamma_h_top, kappa_h_top); + int err_kh_bot = ST_CalcKappa(bot_only, temp_, area, qmin_, qmax_, gamma_h_bot, kappa_h_bot); + double gamma_for_kappaq = err_kh ? gamma_full : gamma_h; + + double slope = ST_LogSlope(shells, qmin_, qmax_, &ST_Shell::S); + double slope_top = ST_LogSlope(shells, qmin_, qmax_, &ST_Shell::Stop); + double slope_bot = ST_LogSlope(shells, qmin_, qmax_, &ST_Shell::Sbot); + + for (size_t i = 0; i < shells.size(); i++) { + double q = shells[i].q; + S_->AddXY(q, shells[i].S); + S_top_->AddXY(q, shells[i].Stop); + S_bot_->AddXY(q, shells[i].Sbot); + q2S_->AddXY(q, q * q * shells[i].S); + q2S_top_->AddXY(q, q * q * shells[i].Stop); + q2S_bot_->AddXY(q, q * q * shells[i].Sbot); + gammaq_->AddXY(q, ST_ShellGamma(q, shells[i].S, temp_, area)); + gammaq_top_->AddXY(q, ST_ShellGamma(q, shells[i].Stop, temp_, area)); + gammaq_bot_->AddXY(q, ST_ShellGamma(q, shells[i].Sbot, temp_, area)); + kappaq_->AddXY(q, ST_ShellKappa(q, shells[i].S, temp_, area, gamma_for_kappaq)); + kappaq_top_->AddXY(q, ST_ShellKappa(q, shells[i].Stop, temp_, area, + err_kh_top ? gamma_top : gamma_h_top)); + kappaq_bot_->AddXY(q, ST_ShellKappa(q, shells[i].Sbot, temp_, area, + err_kh_bot ? gamma_bot : gamma_h_bot)); + } + + double mean_w = 0.0, mean_wt = 0.0, mean_wb = 0.0; + if (wmean_->Size() > 0) { + for (size_t i = 0; i < wmean_->Size(); i++) { + mean_w += ((DataSet_1D*)wmean_)->Dval(i); + mean_wt += ((DataSet_1D*)wtop_)->Dval(i); + mean_wb += ((DataSet_1D*)wbot_)->Dval(i); + } + mean_w /= (double)wmean_->Size(); + mean_wt /= (double)wtop_->Size(); + mean_wb /= (double)wbot_->Size(); + } + + mprintf("\tT = %g K\n", temp_); + mprintf("\tFrames analyzed = %i", n_frames_); + if (n_skipped_ > 0) + mprintf(" (%i skipped)", n_skipped_); + mprintf("\n"); + mprintf("\t%s x %s = %g x %g Ang\n", t1, t2, Lt1_ref_, Lt2_ref_); + mprintf("\tArea = %g Ang^2\n", area); + mprintf("\tFit q range = %g to %g Ang^-1\n", qmin_, qmax_); + if (ST_Finite(slope)) + mprintf("\tLow-q log-log slope = %g (ideal capillary-wave slope is about -2)\n", slope); + if (err_full) + mprinterr("Error: Combined-surface gamma fit failed.\n"); + else + mprintf("\tgamma, combined surfaces = %g mN/m (q^2 S plateau = %g)\n", gamma_full, plateau); + if (!err_top) + mprintf("\tgamma, upper surface = %g mN/m\n", gamma_top); + if (!err_bot) + mprintf("\tgamma, lower surface = %g mN/m\n", gamma_bot); + if (err_kh) + mprintf("\tNOTE: Helfrich kappa fit needs at least three q shells in the fit range.\n"); + else { + mprintf("\tgamma, Helfrich intercept = %g mN/m\n", gamma_h); + mprintf("\tkappa, combined surfaces = %g kT (%g J)\n", + kappa_h, kappa_h * ST_KB * temp_); + } + if (!err_kh_top) + mprintf("\tkappa, upper surface = %g kT\n", kappa_h_top); + if (!err_kh_bot) + mprintf("\tkappa, lower surface = %g kT\n", kappa_h_bot); + if (ST_Finite(slope_top) && ST_Finite(slope_bot)) + mprintf("\tLow-q slope upper/lower = %g / %g\n", slope_top, slope_bot); + mprintf("\tMean roughness = %g Ang (upper %g, lower %g)\n", mean_w, mean_wt, mean_wb); + + if (block_gamma_ != 0 && block_gamma_->Size() > 1) { + double gmean = 0.0, g2 = 0.0; + for (size_t i = 0; i < block_gamma_->Size(); i++) { + double g = ((DataSet_1D*)block_gamma_)->Dval(i); + gmean += g; + g2 += g * g; + } + gmean /= (double)block_gamma_->Size(); + double var = (g2 - (double)block_gamma_->Size() * gmean * gmean) / + (double)(block_gamma_->Size() - 1); + double sd = (var > 0.0) ? sqrt(var) : 0.0; + double sem = sd / sqrt((double)block_gamma_->Size()); + mprintf("\tBlock mean gamma = %g mN/m\n", gmean); + mprintf("\tBlock SD gamma = %g mN/m\n", sd); + mprintf("\tBlock SEM gamma = %g mN/m\n", sem); + mprintf("\tgamma +/- 2 SEM = %g mN/m\n", 2.0 * sem); + } + if (block_kappa_ != 0 && block_kappa_->Size() > 1) { + double kmean = 0.0, k2 = 0.0; + int nk = 0; + for (size_t i = 0; i < block_kappa_->Size(); i++) { + double k = ((DataSet_1D*)block_kappa_)->Dval(i); + if (!ST_Finite(k)) continue; + kmean += k; + k2 += k * k; + nk++; + } + if (nk > 1) { + kmean /= (double)nk; + double var = (k2 - (double)nk * kmean * kmean) / (double)(nk - 1); + double sd = (var > 0.0) ? sqrt(var) : 0.0; + double sem = sd / sqrt((double)nk); + mprintf("\tBlock mean kappa = %g kT\n", kmean); + mprintf("\tBlock SD kappa = %g kT\n", sd); + mprintf("\tBlock SEM kappa = %g kT\n", sem); + mprintf("\tkappa +/- 2 SEM = %g kT\n", 2.0 * sem); + } + } +} diff --git a/src/Action_SurfaceTension.h b/src/Action_SurfaceTension.h new file mode 100644 index 0000000000..8b40626c16 --- /dev/null +++ b/src/Action_SurfaceTension.h @@ -0,0 +1,123 @@ +#ifndef INC_ACTION_SURFACETENSION_H +#define INC_ACTION_SURFACETENSION_H +#include +#include "Action.h" +#include "AtomMask.h" +class DataSet_Mesh; +/// Capillary-wave surface tension of a liquid slab (Cartesian normal). +/** Instantaneous upper and lower interfaces are either a Willard-Chandler + * isosurface of a Gaussian-smoothed number-density field (default) or an + * ITIM-style per-column min/max of , split at mid-box along the normal. + * Height fluctuations in the interface plane are Fourier transformed with + * the numpy convention + * h_q = (1 / N₁N₂) Σ h(t1,t2) exp(−i q · r) + * Capillary-wave theory including bending rigidity κ is + * ⟨|h_q|²⟩ = k_B T / (A (γ q² + κ q⁴)) + * so γ (mN/m) is obtained from the small-q plateau of q² S(q), and κ (in kT) + * from the slope of 1/(q² S) vs q² on the same window. + * The slab normal is x, y, or z (default z); gridspacing/sigmaxy apply in the + * interface plane and dz/sigmaz along the normal. Lateral box lengths are + * held fixed (NVT). DataSets are always created; files are written only when + * the matching *out keyword is given. MPI: packed ReduceMaster of |h_q|². + * \author Nathan D Levinzon + */ +class Action_SurfaceTension : public Action { + public: + Action_SurfaceTension(); + DispatchObject* Alloc() const { return (DispatchObject*)new Action_SurfaceTension(); } + void Help() const; + private: + Action::RetType Init(ArgList&, ActionInit&, int); + Action::RetType Setup(ActionSetup&); + Action::RetType DoAction(int, ActionFrame&); + void Print(); +# ifdef MPI + /// Sum Fourier accumulators onto the master rank. + int SyncAction(); + Parallel::Comm trajComm_; +# endif + + /// Allocate density / height / power arrays for the lateral grid (and nz). + int AllocateGrid(int, int, int); + /// Build interfaces and accumulate spectra for one frame. + /** \return 0 OK, 1 skip frame, 2 fatal (grid or lateral box changed). */ + int ProcessFrame(Frame const&, double, double, double); + /// Finish one complete nblock window (γ, κ, and roughness). + int FinishBlock(); + + /// Instantaneous-interface definition. + enum IfaceType { WILLARD = 0, ITIM }; + /// Cartesian slab normal. + enum NormalAxis { AXIS_X = 0, AXIS_Y = 1, AXIS_Z = 2 }; + + AtomMask Mask_; ///< Atoms used for the number-density / ITIM field + IfaceType iface_; ///< Willard-Chandler isosurface or ITIM min/max + NormalAxis normal_; ///< Slab normal (default z) + + double temp_; ///< Temperature (K) + double gridspacing_; ///< Target bin spacing in the interface plane (Å) + double dz_; ///< Target bin spacing along the slab normal (Å) + double sigma_xy_; ///< Gaussian smoothing in the interface plane (Å) + double sigma_z_; ///< Gaussian smoothing along the slab normal (Å) + double bulk_halfwidth_; ///< Half-width around slab center for ρ_bulk (Å) + double threshold_frac_; ///< Interface is this fraction of ρ_bulk + double qmin_; ///< Fit-window minimum |q| (Å⁻¹) + double qmax_; ///< Fit-window maximum |q| (Å⁻¹) + double lx_user_; ///< Optional fixed box Lx; < 0 means use the box + double ly_user_; ///< Optional fixed box Ly; < 0 means use the box + double lz_user_; ///< Optional fixed box Lz; < 0 means use the box + int nblock_; ///< Frames per uncertainty block; 0 disables + int debug_; ///< Debug level from ActionInit + + // ----- Spectrum vs q; filled in Print() -------------------------------- + DataSet_Mesh* S_; ///< Combined S(q) = ⟨|h_q|²⟩ (Ų) + DataSet_Mesh* S_top_; ///< Upper-interface S(q) + DataSet_Mesh* S_bot_; ///< Lower-interface S(q) + DataSet_Mesh* q2S_; ///< Combined q² S(q) + DataSet_Mesh* q2S_top_; ///< Upper q² S(q) + DataSet_Mesh* q2S_bot_; ///< Lower q² S(q) + DataSet_Mesh* gammaq_; ///< Apparent γ(q) (mN/m), combined + DataSet_Mesh* gammaq_top_; ///< Apparent γ(q), upper + DataSet_Mesh* gammaq_bot_; ///< Apparent γ(q), lower + DataSet_Mesh* kappaq_; ///< Apparent κ(q) (kT), combined + DataSet_Mesh* kappaq_top_; ///< Apparent κ(q), upper + DataSet_Mesh* kappaq_bot_; ///< Apparent κ(q), lower + // ----- Per-frame roughness / bulk density ------------------------------ + DataSet* wtop_; ///< Upper RMS roughness w (Å) + DataSet* wbot_; ///< Lower RMS roughness w (Å) + DataSet* wmean_; ///< Mean of upper and lower w (Å) + DataSet* rhobulk_; ///< Bulk number density (Å⁻³) + // ----- Per-block results (only if nblock > 0) -------------------------- + DataSet* block_gamma_; ///< Block γ (mN/m) + DataSet* block_kappa_; ///< Block κ (kT) + DataSet* block_wmean_; ///< Block mean roughness (Å) + DataSet* block_wtop_; ///< Block upper roughness (Å) + DataSet* block_wbot_; ///< Block lower roughness (Å) + + std::vector density_; ///< n1×n2×nz number density (Å⁻³); unused for ITIM + std::vector h_upper_; ///< n1×n2 upper height field along the normal (Å) + std::vector h_lower_; ///< n1×n2 lower height field along the normal (Å) + std::vector total_power_; ///< Accumulated |h_q|², both surfaces + std::vector top_power_; ///< Accumulated |h_q|², upper + std::vector bottom_power_; ///< Accumulated |h_q|², lower + std::vector block_power_; ///< Combined |h_q|² for the open block + std::vector q_grid_; ///< |q| for each Fourier mode (Å⁻¹) + + int nx_; ///< Bins along lateral axis 1 + int ny_; ///< Bins along lateral axis 2 + int nz_; ///< Density bins along the slab normal + double Lt1_ref_; ///< Lateral length 1 from the first good frame (Å) + double Lt2_ref_; ///< Lateral length 2 from the first good frame (Å) + bool grid_ready_; ///< True after the first successful frame + + int n_frames_; ///< Frames that contributed to the spectra + int n_surfaces_; ///< 2 × n_frames_ (upper + lower) + int n_skipped_; ///< Frames skipped (no interface / no box) + int n_blocks_; ///< Completed uncertainty blocks + int block_surface_count_; ///< Surfaces accumulated in the open block + int block_frame_count_; ///< Frames accumulated in the open block + double block_w_sum_; ///< Running sum of mean w in the open block + double block_wtop_sum_; ///< Running sum of upper w + double block_wbot_sum_; ///< Running sum of lower w +}; +#endif diff --git a/src/Command.cpp b/src/Command.cpp index 02ca517658..b9435004e4 100644 --- a/src/Command.cpp +++ b/src/Command.cpp @@ -88,6 +88,7 @@ #include "Action_Center.h" #include "Action_Image.h" #include "Action_Surf.h" +#include "Action_SurfaceTension.h" #include "Action_Radgyr.h" #include "Action_Mask.h" #include "Action_Closest.h" @@ -411,6 +412,7 @@ void Command::Init() { Command::AddCmd( new Action_STFC_Diffusion(),Cmd::ACT, 1, "stfcdiffusion" ); Command::AddCmd( new Action_Strip(), Cmd::ACT, 1, "strip" ); Command::AddCmd( new Action_Surf(), Cmd::ACT, 1, "surf" ); + Command::AddCmd( new Action_SurfaceTension(),Cmd::ACT, 1, "surftension" ); Command::AddCmd( new Action_SymmetricRmsd(), Cmd::ACT, 1, "symmrmsd" ); Command::AddCmd( new Action_Temperature(), Cmd::ACT, 1, "temperature" ); Command::AddCmd( new Action_Test(), Cmd::ACT, 1, "testtest" ); // HIDDEN diff --git a/src/Version.h b/src/Version.h index de05d7979a..29bb0f0030 100644 --- a/src/Version.h +++ b/src/Version.h @@ -12,7 +12,7 @@ * Whenever a number that precedes is incremented, all subsequent * numbers should be reset to 0. */ -#define CPPTRAJ_INTERNAL_VERSION "V7.10.0" +#define CPPTRAJ_INTERNAL_VERSION "V7.11.0" /// PYTRAJ relies on this #define CPPTRAJ_VERSION_STRING CPPTRAJ_INTERNAL_VERSION #endif diff --git a/src/cpptrajfiles b/src/cpptrajfiles index ee9491a98e..641b7935cb 100644 --- a/src/cpptrajfiles +++ b/src/cpptrajfiles @@ -85,6 +85,7 @@ COMMON_SOURCES= \ Action_Spam.cpp \ Action_Strip.cpp \ Action_Surf.cpp \ + Action_SurfaceTension.cpp \ Action_SymmetricRmsd.cpp \ Action_Temperature.cpp \ Action_Test.cpp \ diff --git a/src/cpptrajheaders b/src/cpptrajheaders index 07f2afd243..3ed37c33a9 100644 --- a/src/cpptrajheaders +++ b/src/cpptrajheaders @@ -86,6 +86,7 @@ CPPTRAJ_HEADERS = \ ./Action_STFC_Diffusion.h \ ./Action_Strip.h \ ./Action_Surf.h \ + ./Action_SurfaceTension.h \ ./Action_SymmetricRmsd.h \ ./Action_Temperature.h \ ./Action_Test.h \ diff --git a/test/Makefile b/test/Makefile index d0859c944d..c4739b09a9 100644 --- a/test/Makefile +++ b/test/Makefile @@ -375,6 +375,9 @@ test.distance: test.volume: @-cd Test_Volume && ./RunTest.sh $(OPT) +test.surftension: + @-cd Test_SurfTension && ./RunTest.sh $(OPT) + test.setvelocity: @-cd Test_SetVelocity && ./RunTest.sh $(OPT) @@ -694,6 +697,7 @@ COMPLETETESTS=test.general \ test.fiximagedbonds \ test.distance \ test.volume \ + test.surftension \ test.setvelocity \ test.remlog \ test.areapermol \ diff --git a/test/Test_SurfTension/RunTest.sh b/test/Test_SurfTension/RunTest.sh new file mode 100644 index 0000000000..234b4fe7de --- /dev/null +++ b/test/Test_SurfTension/RunTest.sh @@ -0,0 +1,75 @@ +#!/bin/bash +# Smoke tests for the surftension Action. +# tz2.ortho is a solvated protein box, not a liquid slab, so the 1-frame run +# only checks that Init/Setup do not crash. Numeric γ comparison needs a +# dedicated slab trajectory. + +. ../MasterTest.sh + +CleanFiles st.in + +TESTNAME='Surface tension (surftension) tests' + +# Command is registered and Help() prints. +UNITNAME='surftension help' +cat > st.in < st.in < st.in < st.in < st.in < Date: Mon, 31 Aug 2026 14:56:10 -0600 Subject: [PATCH 02/17] Fix documentation typo in Action_SurfaceTension.cpp regarding agr/gnu keywords --- src/Action_SurfaceTension.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Action_SurfaceTension.cpp b/src/Action_SurfaceTension.cpp index fe518665fe..fed32de847 100644 --- a/src/Action_SurfaceTension.cpp +++ b/src/Action_SurfaceTension.cpp @@ -670,7 +670,7 @@ void Action_SurfaceTension::Help() const { * Spectrum / roughness DataSets always exist so writedata can dump them. * Files are written only if the matching *out / *agr / *gnu keyword is given. * *out uses the DataFile writer for the filename extension (canonical - * cpptraj: .agr/.xmgr = Grace/xmgrace, .gnu = gnuplot). *agr/*gnu force + * cpptraj: .agr/.xmgr = Grace/xmgrace, .gnu = gnuplot). agr/gnu keywords force * DataFile::XMGRACE / GNUPLOT even when the extension is not recognized. */ Action::RetType Action_SurfaceTension::Init(ArgList& actionArgs, ActionInit& init, int debugIn) From efb16d90d354a648a92294b4d09929d569f39caf Mon Sep 17 00:00:00 2001 From: ndlevinzon Date: Mon, 31 Aug 2026 15:25:53 -0600 Subject: [PATCH 03/17] Refactor output formatting in Action_SurfaceTension.cpp for clarity and consistency - Updated log messages to improve readability, changing "bins along" to "bins along" for better context. - Enhanced output in the Print function to include completed block information, displaying gamma, kappa, and roughness more clearly. - Removed redundant error message logging for kappa when it is not applicable. - Adjusted variable names in output for consistency with other parts of the code. --- src/Action_SurfaceTension.cpp | 34 +++++++++++++++++++++++----------- 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/src/Action_SurfaceTension.cpp b/src/Action_SurfaceTension.cpp index fed32de847..4470b62474 100644 --- a/src/Action_SurfaceTension.cpp +++ b/src/Action_SurfaceTension.cpp @@ -1049,11 +1049,11 @@ int Action_SurfaceTension::AllocateGrid(int nx, int ny, int nz) { mprintf("\tInterface grid = %i x %i", nx_, ny_); if (nz_ > 0) mprintf(" x %i", nz_); - mprintf(" (%s x %s", t1, t2); + mprintf(" bins along %s, %s", t1, t2); if (nz_ > 0) - mprintf(" x %s", ST_AxisName((int)normal_)); - mprintf(")\n"); - mprintf("\t%s x %s = %g x %g Ang\n", t1, t2, Lt1_ref_, Lt2_ref_); + mprintf(", %s", ST_AxisName((int)normal_)); + mprintf("\n"); + mprintf("\tL(%s) = %g Ang, L(%s) = %g Ang\n", t1, Lt1_ref_, t2, Lt2_ref_); if (haveq) mprintf("\tSmallest accessible q = %g Ang^-1\n", qmin_acc); return 0; @@ -1264,6 +1264,7 @@ int Action_SurfaceTension::FinishBlock() { int err_g = ST_CalcGamma(shells, temp_, Lt1_ref_ * Lt2_ref_, qmin_, qmax_, gamma, plateau); int err_k = ST_CalcKappa(shells, temp_, Lt1_ref_ * Lt2_ref_, qmin_, qmax_, gamma_k, kappa_kT); (void)gamma_k; + (void)err_k; if (err_g) { mprintf("Warning: Block %i: fewer than two q shells in the fit range; skipping block gamma.\n", n_blocks_ + 1); @@ -1279,12 +1280,6 @@ int Action_SurfaceTension::FinishBlock() { block_wtop_->Add(n_blocks_, &wtop); block_wbot_->Add(n_blocks_, &wbot); } - if (err_k) - mprintf("\tBlock %i: gamma = %g mN/m, roughness = %g Ang\n", - n_blocks_ + 1, gamma, wmean); - else - mprintf("\tBlock %i: gamma = %g mN/m, kappa = %g kT, roughness = %g Ang\n", - n_blocks_ + 1, gamma, kappa_kT, wmean); n_blocks_++; } std::fill(block_power_.begin(), block_power_.end(), 0.0); @@ -1490,7 +1485,7 @@ void Action_SurfaceTension::Print() if (n_skipped_ > 0) mprintf(" (%i skipped)", n_skipped_); mprintf("\n"); - mprintf("\t%s x %s = %g x %g Ang\n", t1, t2, Lt1_ref_, Lt2_ref_); + mprintf("\tL(%s) = %g Ang, L(%s) = %g Ang\n", t1, Lt1_ref_, t2, Lt2_ref_); mprintf("\tArea = %g Ang^2\n", area); mprintf("\tFit q range = %g to %g Ang^-1\n", qmin_, qmax_); if (ST_Finite(slope)) @@ -1518,6 +1513,23 @@ void Action_SurfaceTension::Print() mprintf("\tLow-q slope upper/lower = %g / %g\n", slope_top, slope_bot); mprintf("\tMean roughness = %g Ang (upper %g, lower %g)\n", mean_w, mean_wt, mean_wb); + if (block_gamma_ != 0 && block_gamma_->Size() > 0) { + mprintf("\tCompleted blocks = %zu (nblock = %i frames)\n", + block_gamma_->Size(), nblock_); + for (size_t i = 0; i < block_gamma_->Size(); i++) { + double g = ((DataSet_1D*)block_gamma_)->Dval(i); + double w = (block_wmean_ != 0) ? ((DataSet_1D*)block_wmean_)->Dval(i) : ST_NaN(); + double k = ST_NaN(); + if (block_kappa_ != 0 && i < block_kappa_->Size()) + k = ((DataSet_1D*)block_kappa_)->Dval(i); + if (ST_Finite(k)) + mprintf("\tBlock %zu: gamma = %g mN/m, kappa = %g kT, roughness = %g Ang\n", + i + 1, g, k, w); + else + mprintf("\tBlock %zu: gamma = %g mN/m, roughness = %g Ang\n", + i + 1, g, w); + } + } if (block_gamma_ != 0 && block_gamma_->Size() > 1) { double gmean = 0.0, g2 = 0.0; for (size_t i = 0; i < block_gamma_->Size(); i++) { From 5b4849995329ccb1de294ae63e9d8ec0ea98541e Mon Sep 17 00:00:00 2001 From: ndlevinzon Date: Mon, 31 Aug 2026 15:30:15 -0600 Subject: [PATCH 04/17] Implement 2-D FFT for height fields in Action_SurfaceTension - Introduced a new HeightPower function that computes the 2-D FFT of height fields using cpptraj's PubFFT, matching numpy's fft2 convention. - Updated ChangeLog to reflect the new FFT implementation and its usage. - Adjusted output messages to include details about the new FFT method. - Removed the old direct DFT implementation for height power spectrum calculation. --- doc/ChangeLog.surftension.md | 3 + src/Action_SurfaceTension.cpp | 125 ++++++++++++++++++++-------------- src/Action_SurfaceTension.h | 13 +++- 3 files changed, 89 insertions(+), 52 deletions(-) diff --git a/doc/ChangeLog.surftension.md b/doc/ChangeLog.surftension.md index 27f32e976e..bd4d881406 100644 --- a/doc/ChangeLog.surftension.md +++ b/doc/ChangeLog.surftension.md @@ -82,6 +82,9 @@ surftension [] temp `sigmanormal` ≡ `sigmaz` (error if both given and they differ). Init/Print report e.g. `Slab normal: z (interface plane x-y)`. Warns on non-orthogonal boxes. +- Height-field 2-D FFT uses cpptraj `PubFFT` (row-column 1-D FFTs), then + divides by `nx*ny` (numpy `fft2` convention). Same `S(q)` as the old + direct DFT. Per-block γ/κ print in `Print()`, not during the frame loop. --- diff --git a/src/Action_SurfaceTension.cpp b/src/Action_SurfaceTension.cpp index 4470b62474..c03e79c55b 100644 --- a/src/Action_SurfaceTension.cpp +++ b/src/Action_SurfaceTension.cpp @@ -363,50 +363,6 @@ static double ST_FftFreq(int k, int n, double d) { return (double)p / ((double)n * d); } -/** 2-D power spectrum of a height field. - * Subtract ⟨h⟩ (q = 0 translation), then - * h_q = (1 / N) Σ h(x,y) exp(−i q · r) N = nx ny - * which matches numpy.fft.fft2(h) / h.size. Power is |h_q|² (Ų). - * Direct DFT is used so nx, ny need not be powers of two. - * OpenMP: each (kx, ky) mode is independent; the loop is flattened so it - * does not need collapse() (OpenMP 3.0), matching other cpptraj Actions. - */ -static void ST_HeightPower(std::vector const& h, int nx, int ny, - std::vector& power) -{ - int nxy = nx * ny; - power.assign((size_t)nxy, 0.0); - if (nxy == 0) return; - double mean = 0.0; - for (int i = 0; i < nxy; i++) - mean += h[i]; - mean /= (double)nxy; - double Ninv = 1.0 / (double)nxy; - int k; -# ifdef _OPENMP -# pragma omp parallel for schedule(dynamic) -# endif - for (k = 0; k < nxy; k++) { - int kx = k / ny; - int ky = k - kx * ny; - double re = 0.0; - double im = 0.0; - for (int ix = 0; ix < nx; ix++) { - for (int iy = 0; iy < ny; iy++) { - double hv = h[ST_Idx2(ix, iy, ny)] - mean; - double ang = Constants::TWOPI * - ((double)kx * (double)ix / (double)nx + - (double)ky * (double)iy / (double)ny); - re += hv * cos(ang); - im -= hv * sin(ang); - } - } - re *= Ninv; - im *= Ninv; - power[k] = re * re + im * im; - } -} - /** |q| = √(qx² + qy²) for each Fourier mode, qx = 2π fftfreq(nx, Lx/nx). */ static void ST_MakeQGrid(int nx, int ny, double Lx, double Ly, std::vector& q) { q.resize((size_t)nx * (size_t)ny); @@ -928,6 +884,7 @@ Action::RetType Action_SurfaceTension::Init(ArgList& actionArgs, ActionInit& ini } mprintf("\tFit q range= %g to %g Ang^-1\n", qmin_, qmax_); mprintf("\tHelfrich kappa: linear fit of 1/(q^2 S) vs q^2 on that window.\n"); + mprintf("\tHeight-field 2-D FFT: PubFFT (numpy fft2 / (nx*ny)).\n"); if (lx_user_ > 0.0) mprintf("\tUsing fixed Lx= %g Ang (%s)\n", lx_user_, (normal_ == AXIS_X) ? "normal" : "lateral"); @@ -981,10 +938,8 @@ Action::RetType Action_SurfaceTension::Init(ArgList& actionArgs, ActionInit& ini nthreads = omp_get_num_threads(); } if (nthreads > 1) { - mprintf("\tOpenMP: 2-D DFT"); if (iface_ == WILLARD) - mprintf(" and 3-D Gaussian filter"); - mprintf(" parallelized with %i threads.\n", nthreads); + mprintf("\tOpenMP: 3-D Gaussian filter parallelized with %i threads.\n", nthreads); } } # endif @@ -1033,6 +988,13 @@ int Action_SurfaceTension::AllocateGrid(int nx, int ny, int nz) { top_power_.assign(n2, 0.0); bottom_power_.assign(n2, 0.0); block_power_.assign(n2, 0.0); + if (fft_n1_.SetupFFTforN(nx_) || fft_n2_.SetupFFTforN(ny_)) { + mprinterr("Error: Could not set up 2-D FFT (nx = %i, ny = %i).\n", nx_, ny_); + return 1; + } + fft_grid_.Allocate(nx_ * ny_); + fft_row_.Allocate(ny_); + fft_col_.Allocate(nx_); ST_MakeQGrid(nx_, ny_, Lt1_ref_, Lt2_ref_, q_grid_); grid_ready_ = true; double qmin_acc = 0.0; @@ -1059,6 +1021,69 @@ int Action_SurfaceTension::AllocateGrid(int nx, int ny, int nz) { return 0; } +// Action_SurfaceTension::HeightPower() +/** 2-D FFT of h − ⟨h⟩ via row-column PubFFT 1-D transforms, then + * h_q = FFT2 / (nx ny) + * matching numpy.fft.fft2(h) / h.size. Power is |h_q|² (Ang^2). + * fft_n2_ transforms along iy (contiguous); fft_n1_ along ix. + */ +void Action_SurfaceTension::HeightPower(std::vector const& h, + std::vector& power) +{ + int nx = nx_; + int ny = ny_; + int nxy = nx * ny; + power.assign((size_t)nxy, 0.0); + if (nxy == 0) return; + + double mean = 0.0; + for (int i = 0; i < nxy; i++) + mean += h[i]; + mean /= (double)nxy; + + for (int ix = 0; ix < nx; ix++) { + for (int iy = 0; iy < ny; iy++) { + int idx = ST_Idx2(ix, iy, ny); + fft_grid_[2 * idx] = h[idx] - mean; + fft_grid_[2 * idx + 1] = 0.0; + } + } + + for (int ix = 0; ix < nx; ix++) { + int base = ix * ny; + for (int iy = 0; iy < ny; iy++) { + fft_row_[2 * iy] = fft_grid_[2 * (base + iy)]; + fft_row_[2 * iy + 1] = fft_grid_[2 * (base + iy) + 1]; + } + fft_n2_.Forward(fft_row_); + for (int iy = 0; iy < ny; iy++) { + fft_grid_[2 * (base + iy)] = fft_row_[2 * iy]; + fft_grid_[2 * (base + iy) + 1] = fft_row_[2 * iy + 1]; + } + } + + for (int iy = 0; iy < ny; iy++) { + for (int ix = 0; ix < nx; ix++) { + int idx = ST_Idx2(ix, iy, ny); + fft_col_[2 * ix] = fft_grid_[2 * idx]; + fft_col_[2 * ix + 1] = fft_grid_[2 * idx + 1]; + } + fft_n1_.Forward(fft_col_); + for (int ix = 0; ix < nx; ix++) { + int idx = ST_Idx2(ix, iy, ny); + fft_grid_[2 * idx] = fft_col_[2 * ix]; + fft_grid_[2 * idx + 1] = fft_col_[2 * ix + 1]; + } + } + + double Ninv = 1.0 / (double)nxy; + for (int k = 0; k < nxy; k++) { + double re = fft_grid_[2 * k] * Ninv; + double im = fft_grid_[2 * k + 1] * Ninv; + power[k] = re * re + im * im; + } +} + // Action_SurfaceTension::ProcessFrame() /** Wrap laterals, recenter along the normal, build instantaneous interfaces, * then accumulate roughness and |h_q|^2. First good frame freezes nx, ny, @@ -1095,7 +1120,7 @@ int Action_SurfaceTension::ProcessFrame(Frame const& frm, double Lx, double Ly, if (!grid_ready_) { Lt1_ref_ = Lt1; Lt2_ref_ = Lt2; - AllocateGrid(nx, ny, nz); + if (AllocateGrid(nx, ny, nz)) return 2; } else { if (nx != nx_ || ny != ny_) { mprinterr("Error: Interface grid dimensions changed during the trajectory.\n"); @@ -1220,8 +1245,8 @@ int Action_SurfaceTension::ProcessFrame(Frame const& frm, double Lx, double Ly, // Combined spectrum averages both surfaces (n_surfaces_ = 2 n_frames_). std::vector p_upper, p_lower; - ST_HeightPower(h_upper_, nx_, ny_, p_upper); - ST_HeightPower(h_lower_, nx_, ny_, p_lower); + HeightPower(h_upper_, p_upper); + HeightPower(h_lower_, p_lower); for (size_t i = 0; i < top_power_.size(); i++) { top_power_[i] += p_upper[i]; diff --git a/src/Action_SurfaceTension.h b/src/Action_SurfaceTension.h index 8b40626c16..4ae68486ca 100644 --- a/src/Action_SurfaceTension.h +++ b/src/Action_SurfaceTension.h @@ -3,14 +3,15 @@ #include #include "Action.h" #include "AtomMask.h" +#include "PubFFT.h" class DataSet_Mesh; /// Capillary-wave surface tension of a liquid slab (Cartesian normal). /** Instantaneous upper and lower interfaces are either a Willard-Chandler * isosurface of a Gaussian-smoothed number-density field (default) or an * ITIM-style per-column min/max of , split at mid-box along the normal. * Height fluctuations in the interface plane are Fourier transformed with - * the numpy convention - * h_q = (1 / N₁N₂) Σ h(t1,t2) exp(−i q · r) + * cpptraj PubFFT (row-column 1-D FFTs) using the numpy convention + * h_q = (1 / N₁N₂) FFT2(h − ⟨h⟩) * Capillary-wave theory including bending rigidity κ is * ⟨|h_q|²⟩ = k_B T / (A (γ q² + κ q⁴)) * so γ (mN/m) is obtained from the small-q plateau of q² S(q), and κ (in kT) @@ -44,6 +45,8 @@ class Action_SurfaceTension : public Action { int ProcessFrame(Frame const&, double, double, double); /// Finish one complete nblock window (γ, κ, and roughness). int FinishBlock(); + /// |h_q|² of a height field via 2-D PubFFT / (nx ny). + void HeightPower(std::vector const&, std::vector&); /// Instantaneous-interface definition. enum IfaceType { WILLARD = 0, ITIM }; @@ -103,6 +106,12 @@ class Action_SurfaceTension : public Action { std::vector block_power_; ///< Combined |h_q|² for the open block std::vector q_grid_; ///< |q| for each Fourier mode (Å⁻¹) + PubFFT fft_n1_; ///< 1-D FFT along lateral axis 1 (nx) + PubFFT fft_n2_; ///< 1-D FFT along lateral axis 2 (ny) + ComplexArray fft_grid_; ///< nx×ny complex grid for the 2-D FFT + ComplexArray fft_row_; ///< Length-ny row buffer + ComplexArray fft_col_; ///< Length-nx column buffer + int nx_; ///< Bins along lateral axis 1 int ny_; ///< Bins along lateral axis 2 int nz_; ///< Density bins along the slab normal From 9a20df2aaed0d71fc327af154d816c2ffa2ee7aa Mon Sep 17 00:00:00 2001 From: ndlevinzon Date: Mon, 31 Aug 2026 15:47:01 -0600 Subject: [PATCH 05/17] Enhance 'surftension' command with new options and functionality - Updated the 'surftension' command to support an additional mask for lower surfaces, allowing for single or double interface configurations. - Introduced new parameters: 'nsurf' to specify the number of interfaces, 'side' to select the interface for single interface cases, and 'summaryout' for outputting a key/value summary file. - Adjusted the default behavior for 'qmin' and added 'blocktime' and 'dt' parameters for better control over analysis. - Enhanced documentation in ChangeLog to reflect these changes and added tests for new functionalities in the RunTest script. - Bumped version to 7.11.0 to signify the addition of these features. --- doc/ChangeLog.surftension.md | 21 +- doc/ChangeLog.v7.md | 22 +- src/Action_SurfaceTension.cpp | 730 +++++++++++++++++++++++-------- src/Action_SurfaceTension.h | 187 ++++---- test/Test_SurfTension/RunTest.sh | 28 +- 5 files changed, 715 insertions(+), 273 deletions(-) diff --git a/doc/ChangeLog.surftension.md b/doc/ChangeLog.surftension.md index bd4d881406..9f231f4a32 100644 --- a/doc/ChangeLog.surftension.md +++ b/doc/ChangeLog.surftension.md @@ -14,14 +14,16 @@ Working log for the capillary-wave surface-tension Action. New command `surftension` added under New Commands. Internal version `V7.11.0`. ``` -surftension [] temp - [normal {x|y|z}] [interface {willard|itim}] +surftension [] [mask2 ] temp + [normal {x|y|z}] [nsurf {1|2}] [side {upper|lower}] + [interface {willard|itim}] [gridspacing ] [dz | dnormal ] [sigmaxy ] [sigmaz | sigmanormal ] [bulkhalfwidth ] [threshold ] [qmin ] [qmax ] [lx ] [ly ] [lz ] - [nblock ] + [nblock ] [dt ] [blocktime ] [spectrumout ] [roughout ] [blockout ] + [summaryout ] [spectrumagr ] [roughagr ] [blockagr ] [spectrumgnu ] [roughgnu ] [blockgnu ] ``` @@ -82,9 +84,20 @@ surftension [] temp `sigmanormal` ≡ `sigmaz` (error if both given and they differ). Init/Print report e.g. `Slab normal: z (interface plane x-y)`. Warns on non-orthogonal boxes. -- Height-field 2-D FFT uses cpptraj `PubFFT` (row-column 1-D FFTs), then +- Height-field 2-D FFT uses cpptraj `PubFFT` (row-column 1-D FFTs), then divides by `nx*ny` (numpy `fft2` convention). Same `S(q)` as the old direct DFT. Per-block γ/κ print in `Print()`, not during the frame loop. +- Default `qmin` is the smallest fundamental wavevector from the unit-cell + laterals, `2π/max(Lt1,Lt2)`, set on the first good frame. Both `2π/Lt1` + and `2π/Lt2` are printed. `summaryout` writes a parseable key/value file + (γ, κ, roughness, q window, box, frames). Skip-frame warnings are capped + at 5. `blocktime` (ps) with `dt` (analyzed-frame spacing) sets `nblock`. + Output directories are not created; the user must give existing paths. +- `nsurf {1|2}` (default 2, vacuum or a second phase on both sides of the + film). `nsurf 1` with `side {upper|lower}` uses one interface. `mask2` + is a second mask for the lower surface (leaflet / liquid–liquid); the + upper surface then comes from `` with no mid-box split. Both + masks share one circular recenter so the film is not split apart. --- diff --git a/doc/ChangeLog.v7.md b/doc/ChangeLog.v7.md index 27dfcf57fc..c49fdc32c0 100644 --- a/doc/ChangeLog.v7.md +++ b/doc/ChangeLog.v7.md @@ -19,20 +19,28 @@ New Commands plateau of q²⟨|h_q|²⟩. κ (kT) is the Helfrich slope of 1/(q² S) vs q². `normal {x|y|z}` selects the slab normal (default z). `interface {willard|itim}` selects a Willard-Chandler density isosurface (default) or ITIM per-column min/max. - Optional outputs (`spectrumout`, `roughout`, `blockout`) follow the filename extension - (`.agr`/`.xmgr` = xmgrace, `.gnu` = gnuplot). Dedicated `*agr`/`*gnu` - keywords force Grace or gnuplot. MPI-parallel (packed - spectral SUM to the master). Assumes NVT (fixed lateral box lengths). + Default is two interfaces (e.g. a water slab with vacuum at +z and −z). `nsurf 1` + with `side {upper|lower}` is a single interface. `mask2` supplies a second atom + set for the lower surface (leaflet / liquid–liquid). Lateral lengths come from + the unit cell unless `lx`/`ly`/`lz` are set. If `qmin` is omitted it is + 2π/max(Lt1,Lt2) from the first frame. `blocktime` (ps) with `dt` sets `nblock`. + Optional outputs (`spectrumout`, `roughout`, `blockout`, `summaryout`) follow + the filename extension (`.agr`/`.xmgr` = xmgrace, `.gnu` = gnuplot). Dedicated + `*agr`/`*gnu` keywords force Grace or gnuplot. Parent directories must already + exist. MPI-parallel (packed spectral SUM to the master). Assumes NVT (fixed + lateral box lengths). ``` -surftension [] temp - [normal {x|y|z}] [interface {willard|itim}] +surftension [] [mask2 ] temp + [normal {x|y|z}] [nsurf {1|2}] [side {upper|lower}] + [interface {willard|itim}] [gridspacing ] [dz | dnormal ] [sigmaxy ] [sigmaz | sigmanormal ] [bulkhalfwidth ] [threshold ] [qmin ] [qmax ] [lx ] [ly ] [lz ] - [nblock ] + [nblock ] [dt ] [blocktime ] [spectrumout ] [roughout ] [blockout ] + [summaryout ] [spectrumagr ] [roughagr ] [blockagr ] [spectrumgnu ] [roughgnu ] [blockgnu ] ``` diff --git a/src/Action_SurfaceTension.cpp b/src/Action_SurfaceTension.cpp index c03e79c55b..0d13c2bbf3 100644 --- a/src/Action_SurfaceTension.cpp +++ b/src/Action_SurfaceTension.cpp @@ -13,6 +13,7 @@ #include "DataFile.h" #include "DataSet_1D.h" #include "DataSet_Mesh.h" +#include "CpptrajFile.h" #include "Frame.h" #ifdef _OPENMP # include @@ -63,28 +64,54 @@ static double ST_Wrap(double x, double L) { return y; } -/** Recenter a periodic slab so its circular mean along the normal lies at L/2. - * Mapping n → θ = 2π n / L, then using atan2(⟨sin θ⟩, ⟨cos θ⟩), avoids - * failure when the slab straddles the periodic boundary. +/** Circular-mean slab center along the normal (periodic). n2 may be 0. + * Mapping n → θ = 2π n / L, then atan2(⟨sin θ⟩, ⟨cos θ⟩), so a slab that + * straddles the periodic boundary is still recentered correctly. */ -static void ST_CircularRecenter(std::vector& n, double L) { - if (n.empty() || L <= 0.0) return; +static double ST_CircularSlabCenter(std::vector const& n1, int n1n, + std::vector const* n2, int n2n, + double L) +{ + if (L <= 0.0) return 0.0; double mean_sin = 0.0; double mean_cos = 0.0; - for (size_t i = 0; i < n.size(); i++) { - double theta = Constants::TWOPI * ST_Wrap(n[i], L) / L; + int ntot = 0; + for (int i = 0; i < n1n; i++) { + double theta = Constants::TWOPI * ST_Wrap(n1[i], L) / L; mean_sin += sin(theta); mean_cos += cos(theta); + ntot++; + } + if (n2 != 0) { + for (int i = 0; i < n2n; i++) { + double theta = Constants::TWOPI * ST_Wrap((*n2)[i], L) / L; + mean_sin += sin(theta); + mean_cos += cos(theta); + ntot++; + } } - mean_sin /= (double)n.size(); - mean_cos /= (double)n.size(); + if (ntot < 1) return 0.0; + mean_sin /= (double)ntot; + mean_cos /= (double)ntot; double angle = atan2(mean_sin, mean_cos); if (angle < 0.0) angle += Constants::TWOPI; - double slab_center = L * angle / Constants::TWOPI; + return L * angle / Constants::TWOPI; +} + +static void ST_ApplyCircularRecenter(std::vector& n, double L, + double slab_center) +{ + if (n.empty() || L <= 0.0) return; for (size_t i = 0; i < n.size(); i++) n[i] = ST_Wrap(n[i] - slab_center + 0.5 * L, L); } +/** Recenter a periodic slab so its circular mean along the normal lies at L/2. */ +static void ST_CircularRecenter(std::vector& n, double L) { + if (n.empty() || L <= 0.0) return; + ST_ApplyCircularRecenter(n, L, ST_CircularSlabCenter(n, (int)n.size(), 0, 0, L)); +} + /// Cartesian axis name for Help / mprintf (ASCII). static const char* ST_AxisName(int axis) { if (axis == 0) return "x"; @@ -286,6 +313,7 @@ static bool ST_ItimMinMax(std::vector const& t1, std::vector const& n, int natom, double Lt1, double Lt2, double Ln, int nx, int ny, + bool need_u, bool need_l, std::vector& h_upper, std::vector& h_lower) { @@ -312,6 +340,57 @@ static bool ST_ItimMinMax(std::vector const& t1, has_l[idx] = 1; } } + for (size_t i = 0; i < n2; i++) { + if (need_u && !has_u[i]) return false; + if (need_l && !has_l[i]) return false; + if (need_u) h_upper[i] = zmax[i]; + if (need_l) h_lower[i] = zmin[i]; + } + return true; +} + +/** ITIM from two atom sets: upper = max n of set 1, lower = min n of set 2. */ +static bool ST_ItimTwoMasks(std::vector const& t1u, + std::vector const& t2u, + std::vector const& nu, + int natomu, + std::vector const& t1l, + std::vector const& t2l, + std::vector const& nl, + int natoml, + double Lt1, double Lt2, + int nx, int ny, + std::vector& h_upper, + std::vector& h_lower) +{ + double dx = Lt1 / (double)nx; + double dy = Lt2 / (double)ny; + size_t n2 = (size_t)nx * (size_t)ny; + const double inf = std::numeric_limits::infinity(); + std::vector zmax(n2, -inf), zmin(n2, inf); + std::vector has_u(n2, 0), has_l(n2, 0); + for (int i = 0; i < natomu; i++) { + int ix = (int)floor(t1u[i] / dx); + int iy = (int)floor(t2u[i] / dy); + if (ix < 0) ix = 0; + if (iy < 0) iy = 0; + if (ix >= nx) ix = nx - 1; + if (iy >= ny) iy = ny - 1; + size_t idx = ST_Idx2(ix, iy, ny); + if (!has_u[idx] || nu[i] > zmax[idx]) zmax[idx] = nu[i]; + has_u[idx] = 1; + } + for (int i = 0; i < natoml; i++) { + int ix = (int)floor(t1l[i] / dx); + int iy = (int)floor(t2l[i] / dy); + if (ix < 0) ix = 0; + if (iy < 0) iy = 0; + if (ix >= nx) ix = nx - 1; + if (iy >= ny) iy = ny - 1; + size_t idx = ST_Idx2(ix, iy, ny); + if (!has_l[idx] || nl[i] < zmin[idx]) zmin[idx] = nl[i]; + has_l[idx] = 1; + } for (size_t i = 0; i < n2; i++) { if (!has_u[i] || !has_l[i]) return false; h_upper[i] = zmax[i]; @@ -320,6 +399,29 @@ static bool ST_ItimMinMax(std::vector const& t1, return true; } +/** Split Cartesian coordinates into wrapped laterals and a recentered normal. */ +static void ST_SplitAtomCoords(Frame const& frm, AtomMask const& mask, int nax, + double Lx, double Ly, double Lz, + std::vector& t1, std::vector& t2, + std::vector& n) +{ + double Lt1, Lt2, Ln; + ST_SplitBox(nax, Lx, Ly, Lz, Lt1, Lt2, Ln); + int natom = mask.Nselected(); + t1.resize((size_t)natom); + t2.resize((size_t)natom); + n.resize((size_t)natom); + int idx = 0; + for (AtomMask::const_iterator at = mask.begin(); at != mask.end(); ++at, ++idx) { + const double* xyz = frm.XYZ(*at); + double a, b, c; + ST_SplitXYZ(nax, xyz[0], xyz[1], xyz[2], a, b, c); + t1[idx] = ST_Wrap(a, Lt1); + t2[idx] = ST_Wrap(b, Lt2); + n[idx] = c; + } +} + /** Number density of mask atoms with |n - Ln/2| <= bulk_halfwidth (Ang^-3). */ static double ST_RhoBulkFromAtoms(std::vector const& ncoord, int natom, double Lt1, double Lt2, double Ln, @@ -558,11 +660,33 @@ static void ST_AddSetToFiles(DataSet* ds, DataFile* a, DataFile* b, DataFile* c) if (c != 0) c->AddDataSet(ds); } +/// Write a key/value line; skip non-finite doubles. +static void ST_SummaryD(CpptrajFile* f, const char* key, double v) { + if (f == 0 || !ST_Finite(v)) return; + f->Printf("%s %g\n", key, v); +} + +static void ST_SummaryI(CpptrajFile* f, const char* key, int v) { + if (f == 0) return; + f->Printf("%s %i\n", key, v); +} + +static void ST_SummaryS(CpptrajFile* f, const char* key, const char* v) { + if (f == 0 || v == 0) return; + f->Printf("%s %s\n", key, v); +} + // ----------------------------------------------------------------------------- /// CONSTRUCTOR — defaults match the reference Python analysis. Action_SurfaceTension::Action_SurfaceTension() : iface_(WILLARD), normal_(AXIS_Z), + side_(SIDE_UPPER), + nsurf_(2), + has_mask2_(false), + do_upper_(true), + do_lower_(true), + qmin_specified_(false), temp_(-1.0), gridspacing_(2.5), dz_(1.0), @@ -570,19 +694,24 @@ Action_SurfaceTension::Action_SurfaceTension() : sigma_z_(1.5), bulk_halfwidth_(5.0), threshold_frac_(0.5), - qmin_(0.033283), + qmin_(-1.0), qmax_(0.174649), + q_fundamental_(0.0), lx_user_(-1.0), ly_user_(-1.0), lz_user_(-1.0), + dt_(-1.0), + blocktime_(-1.0), nblock_(0), debug_(0), + n_skip_warn_(0), S_(0), S_top_(0), S_bot_(0), q2S_(0), q2S_top_(0), q2S_bot_(0), gammaq_(0), gammaq_top_(0), gammaq_bot_(0), kappaq_(0), kappaq_top_(0), kappaq_bot_(0), wtop_(0), wbot_(0), wmean_(0), rhobulk_(0), block_gamma_(0), block_kappa_(0), block_wmean_(0), block_wtop_(0), block_wbot_(0), + summaryFile_(0), nx_(0), ny_(0), nz_(0), Lt1_ref_(0.0), Lt2_ref_(0.0), grid_ready_(false), @@ -593,32 +722,29 @@ Action_SurfaceTension::Action_SurfaceTension() : // Action_SurfaceTension::Help() void Action_SurfaceTension::Help() const { - mprintf("\t[] temp \n" - "\t[normal {x|y|z}] [interface {willard|itim}]\n" + mprintf("\t[] [mask2 ] temp \n" + "\t[normal {x|y|z}] [nsurf {1|2}] [side {upper|lower}]\n" + "\t[interface {willard|itim}]\n" "\t[gridspacing ] [dz | dnormal ]\n" "\t[sigmaxy ] [sigmaz | sigmanormal ]\n" "\t[bulkhalfwidth ] [threshold ]\n" "\t[qmin ] [qmax ] [lx ] [ly ] [lz ]\n" - "\t[nblock ]\n" + "\t[nblock ] [dt ] [blocktime ]\n" "\t[spectrumout ] [roughout ] [blockout ]\n" + "\t[summaryout ]\n" "\t[spectrumagr ] [roughagr ] [blockagr ]\n" "\t[spectrumgnu ] [roughgnu ] [blockgnu ]\n" - " Calculate capillary-wave surface tension (mN/m) for a liquid slab.\n" - " normal x|y|z selects the slab normal (default z). gridspacing and\n" - " sigmaxy apply in the interface plane; dz (alias dnormal) and sigmaz\n" - " (alias sigmanormal) apply along the normal. should select\n" - " interfacial density atoms (e.g. ':WAT@O'). Interfaces are a\n" - " Willard-Chandler Gaussian density isosurface (default) or ITIM\n" - " per-column min/max of , split at mid-box along the normal.\n" - " Height fluctuations are Fourier transformed; gamma is the small-q\n" - " plateau of q^2 <|h_q|^2>. kappa (kT) is the slope of 1/(q^2 S) vs\n" - " q^2 on the same q window. lx/ly/lz optionally replace Cartesian box\n" - " lengths. Lateral lengths are held fixed (NVT). Assumes an X-aligned\n" - " orthogonal box. DataSets are always created; files are written only\n" - " when the matching *out/*agr/*gnu keyword is given. *out format\n" - " follows the extension (.agr/.xmgr = xmgrace, .gnu = gnuplot,\n" - " otherwise ASCII). *agr/*gnu force Grace or gnuplot. In MPI,\n" - " nblock is per-rank; spectra are summed onto the master.\n"); + " Capillary-wave surface tension (mN/m) for a liquid slab.\n" + " Lateral box lengths come from the unit cell (NVT). lx/ly/lz only\n" + " override noisy box records. Default is two interfaces (vacuum or a\n" + " second phase on both sides, e.g. water slab with vacuum at +z and\n" + " -z). nsurf 1 is a single interface (side upper|lower). mask2 is a\n" + " second atom set for the lower surface (leaflet or second liquid);\n" + " the upper surface then comes from with no mid-box split.\n" + " If qmin is omitted it is 2*pi/max(Lt1,Lt2) from the first frame.\n" + " blocktime (ps) with dt (analyzed-frame spacing, ps) sets nblock.\n" + " Output files are written only to paths the user gives; parent\n" + " directories must already exist.\n"); } // Action_SurfaceTension::Init() @@ -645,6 +771,7 @@ Action::RetType Action_SurfaceTension::Init(ArgList& actionArgs, ActionInit& ini DataFile* spectrumGnu = init.DFL().AddDataFile(actionArgs.GetStringKey("spectrumgnu"), actionArgs, DataFile::GNUPLOT); DataFile* roughGnu = init.DFL().AddDataFile(actionArgs.GetStringKey("roughgnu"), actionArgs, DataFile::GNUPLOT); DataFile* blockGnu = init.DFL().AddDataFile(actionArgs.GetStringKey("blockgnu"), actionArgs, DataFile::GNUPLOT); + summaryFile_ = init.DFL().AddCpptrajFile(actionArgs.GetStringKey("summaryout"), "SurfTension summary"); temp_ = actionArgs.getKeyDouble("temp", -1.0); if (temp_ <= 0.0) { @@ -655,7 +782,8 @@ Action::RetType Action_SurfaceTension::Init(ArgList& actionArgs, ActionInit& ini sigma_xy_ = actionArgs.getKeyDouble("sigmaxy", 2.5); bulk_halfwidth_ = actionArgs.getKeyDouble("bulkhalfwidth", 5.0); threshold_frac_ = actionArgs.getKeyDouble("threshold", 0.5); - qmin_ = actionArgs.getKeyDouble("qmin", 0.033283); + qmin_specified_ = actionArgs.Contains("qmin"); + qmin_ = actionArgs.getKeyDouble("qmin", -1.0); qmax_ = actionArgs.getKeyDouble("qmax", 0.174649); bool has_lx = actionArgs.Contains("lx"); bool has_ly = actionArgs.Contains("ly"); @@ -663,7 +791,11 @@ Action::RetType Action_SurfaceTension::Init(ArgList& actionArgs, ActionInit& ini lx_user_ = actionArgs.getKeyDouble("lx", -1.0); ly_user_ = actionArgs.getKeyDouble("ly", -1.0); lz_user_ = actionArgs.getKeyDouble("lz", -1.0); + bool has_nblock = actionArgs.Contains("nblock"); + bool has_blocktime = actionArgs.Contains("blocktime"); nblock_ = actionArgs.getKeyInt("nblock", 0); + dt_ = actionArgs.getKeyDouble("dt", -1.0); + blocktime_ = actionArgs.getKeyDouble("blocktime", -1.0); // dz / dnormal and sigmaz / sigmanormal are aliases (normal-axis spacing / sigma). bool has_dz = actionArgs.Contains("dz"); @@ -720,6 +852,47 @@ Action::RetType Action_SurfaceTension::Init(ArgList& actionArgs, ActionInit& ini return Action::ERR; } + nsurf_ = actionArgs.getKeyInt("nsurf", 2); + if (nsurf_ != 1 && nsurf_ != 2) { + mprinterr("Error: nsurf must be 1 or 2.\n"); + return Action::ERR; + } + bool has_side = actionArgs.Contains("side"); + std::string sidestr = actionArgs.GetStringKey("side"); + if (sidestr.empty() && has_side) { + mprinterr("Error: 'side' requires upper or lower.\n"); + return Action::ERR; + } + if (sidestr.empty()) + sidestr = "upper"; + if (sidestr == "upper" || sidestr == "top") + side_ = SIDE_UPPER; + else if (sidestr == "lower" || sidestr == "bot" || sidestr == "bottom") + side_ = SIDE_LOWER; + else { + mprinterr("Error: side must be 'upper' or 'lower'.\n"); + return Action::ERR; + } + if (nsurf_ == 2) { + do_upper_ = true; + do_lower_ = true; + if (has_side) + mprintf("Warning: 'side' is ignored when nsurf is 2.\n"); + } else { + do_upper_ = (side_ == SIDE_UPPER); + do_lower_ = (side_ == SIDE_LOWER); + } + + std::string mask2exp = actionArgs.GetStringKey("mask2"); + has_mask2_ = !mask2exp.empty(); + if (has_mask2_) { + if (nsurf_ != 2) { + mprinterr("Error: mask2 requires nsurf 2 (upper from , lower from mask2).\n"); + return Action::ERR; + } + if (Mask2_.SetMaskString(mask2exp)) return Action::ERR; + } + if (has_lx && lx_user_ <= 0.0) { mprinterr("Error: lx must be > 0.\n"); return Action::ERR; @@ -755,16 +928,47 @@ Action::RetType Action_SurfaceTension::Init(ArgList& actionArgs, ActionInit& ini mprinterr("Error: bulkhalfwidth must be > 0.\n"); return Action::ERR; } - if (qmax_ <= qmin_) { - mprinterr("Error: qmax must be greater than qmin.\n"); + if (qmax_ <= 0.0) { + mprinterr("Error: qmax must be > 0.\n"); return Action::ERR; } + if (qmin_specified_) { + if (qmin_ <= 0.0) { + mprinterr("Error: qmin must be > 0.\n"); + return Action::ERR; + } + if (qmax_ <= qmin_) { + mprinterr("Error: qmax must be greater than qmin.\n"); + return Action::ERR; + } + } + if (has_blocktime) { + if (dt_ <= 0.0) { + mprinterr("Error: 'blocktime' requires 'dt ' (time between analyzed frames).\n"); + return Action::ERR; + } + if (blocktime_ <= 0.0) { + mprinterr("Error: blocktime must be > 0.\n"); + return Action::ERR; + } + int nfromtime = ST_IRound(blocktime_ / dt_); + if (nfromtime < 1) { + mprinterr("Error: blocktime / dt is less than one frame.\n"); + return Action::ERR; + } + if (has_nblock && nblock_ != nfromtime) { + mprinterr("Error: nblock (%i) does not match blocktime/dt (%i frames).\n", + nblock_, nfromtime); + return Action::ERR; + } + nblock_ = nfromtime; + } if (nblock_ < 0) { mprinterr("Error: nblock must be >= 0.\n"); return Action::ERR; } if ((blockFile != 0 || blockAgr != 0 || blockGnu != 0) && nblock_ < 1) { - mprinterr("Error: 'blockout'/'blockagr'/'blockgnu' require 'nblock '.\n"); + mprinterr("Error: 'blockout'/'blockagr'/'blockgnu' require 'nblock' or 'blocktime'.\n"); return Action::ERR; } @@ -859,6 +1063,8 @@ Action::RetType Action_SurfaceTension::Init(ArgList& actionArgs, ActionInit& ini mprintf(" SURFTENSION: Capillary-wave surface tension.\n"); mprintf("\tMask: '%s'\n", Mask_.MaskString()); + if (has_mask2_) + mprintf("\tMask2 (lower surface): '%s'\n", Mask2_.MaskString()); { const char* t1 = 0; const char* t2 = 0; @@ -866,12 +1072,22 @@ Action::RetType Action_SurfaceTension::Init(ArgList& actionArgs, ActionInit& ini mprintf("\tSlab normal: %s (interface plane %s-%s)\n", ST_AxisName((int)normal_), t1, t2); } + if (nsurf_ == 2) + mprintf("\tSurfaces: 2 (upper and lower; vacuum/second phase on both sides).\n"); + else + mprintf("\tSurfaces: 1 (%s only).\n", (side_ == SIDE_UPPER) ? "upper" : "lower"); if (iface_ == WILLARD) mprintf("\tInterface: Willard-Chandler density isosurface.\n"); + else if (has_mask2_) + mprintf("\tInterface: ITIM (upper = max of mask, lower = min of mask2).\n"); else mprintf("\tInterface: ITIM min/max (per-column, split at mid-box along %s).\n", ST_AxisName((int)normal_)); mprintf("\tTemperature= %g K\n", temp_); + mprintf("\tLateral box lengths: from the unit cell"); + if (lx_user_ > 0.0 || ly_user_ > 0.0 || lz_user_ > 0.0) + mprintf(" (some Cartesian lengths overridden)"); + mprintf(".\n"); mprintf("\tInterface-plane grid spacing= %g Ang\n", gridspacing_); if (iface_ == WILLARD) { mprintf("\tNormal-axis bin spacing (dz)= %g Ang\n", dz_); @@ -882,7 +1098,11 @@ Action::RetType Action_SurfaceTension::Init(ArgList& actionArgs, ActionInit& ini } else { mprintf("\tBulk half-width (rho_bulk only)= %g Ang\n", bulk_halfwidth_); } - mprintf("\tFit q range= %g to %g Ang^-1\n", qmin_, qmax_); + if (qmin_specified_) + mprintf("\tFit q range= %g to %g Ang^-1\n", qmin_, qmax_); + else + mprintf("\tFit qmin: 2*pi/max(Lt1,Lt2) from the first frame; qmax= %g Ang^-1\n", + qmax_); mprintf("\tHelfrich kappa: linear fit of 1/(q^2 S) vs q^2 on that window.\n"); mprintf("\tHeight-field 2-D FFT: PubFFT (numpy fft2 / (nx*ny)).\n"); if (lx_user_ > 0.0) @@ -896,6 +1116,8 @@ Action::RetType Action_SurfaceTension::Init(ArgList& actionArgs, ActionInit& ini (normal_ == AXIS_Z) ? "normal" : "lateral"); if (nblock_ > 0) { mprintf("\tBlock averaging every %i analyzed frames", nblock_); + if (blocktime_ > 0.0 && dt_ > 0.0) + mprintf(" (blocktime %g ps, dt %g ps)", blocktime_, dt_); # ifdef MPI if (trajComm_.Size() > 1) mprintf(" (per rank)"); @@ -929,6 +1151,8 @@ Action::RetType Action_SurfaceTension::Init(ArgList& actionArgs, ActionInit& ini mprintf("\tBlock Grace output to '%s'\n", blockAgr->DataFilename().full()); if (blockGnu != 0) mprintf("\tBlock gnuplot output to '%s'\n", blockGnu->DataFilename().full()); + if (summaryFile_ != 0) + mprintf("\tSummary output to '%s'\n", summaryFile_->Filename().full()); # ifdef _OPENMP { int nthreads = 1; @@ -968,6 +1192,14 @@ Action::RetType Action_SurfaceTension::Setup(ActionSetup& setup) mprintf("Warning: Mask '%s' selects no atoms.\n", Mask_.MaskString()); return Action::SKIP; } + if (has_mask2_) { + if (setup.Top().SetupIntegerMask(Mask2_)) return Action::ERR; + Mask2_.MaskInfo(); + if (Mask2_.None()) { + mprintf("Warning: Mask2 '%s' selects no atoms.\n", Mask2_.MaskString()); + return Action::SKIP; + } + } return Action::OK; } @@ -982,6 +1214,10 @@ int Action_SurfaceTension::AllocateGrid(int nx, int ny, int nz) { density_.assign(n3, 0.0); else density_.clear(); + if (nz > 0 && has_mask2_) + density2_.assign(n3, 0.0); + else + density2_.clear(); h_upper_.assign(n2, 0.0); h_lower_.assign(n2, 0.0); total_power_.assign(n2, 0.0); @@ -996,7 +1232,6 @@ int Action_SurfaceTension::AllocateGrid(int nx, int ny, int nz) { fft_row_.Allocate(ny_); fft_col_.Allocate(nx_); ST_MakeQGrid(nx_, ny_, Lt1_ref_, Lt2_ref_, q_grid_); - grid_ready_ = true; double qmin_acc = 0.0; bool haveq = false; for (size_t i = 0; i < q_grid_.size(); i++) { @@ -1016,8 +1251,139 @@ int Action_SurfaceTension::AllocateGrid(int nx, int ny, int nz) { mprintf(", %s", ST_AxisName((int)normal_)); mprintf("\n"); mprintf("\tL(%s) = %g Ang, L(%s) = %g Ang\n", t1, Lt1_ref_, t2, Lt2_ref_); + { + double q1 = Constants::TWOPI / Lt1_ref_; + double q2 = Constants::TWOPI / Lt2_ref_; + q_fundamental_ = (q1 < q2) ? q1 : q2; + mprintf("\tFundamental q: 2*pi/L(%s) = %g, 2*pi/L(%s) = %g Ang^-1\n", + t1, q1, t2, q2); + mprintf("\tSmallest fundamental |q| = %g Ang^-1\n", q_fundamental_); + if (!qmin_specified_) { + qmin_ = q_fundamental_; + mprintf("\tFit qmin set from the box = %g Ang^-1\n", qmin_); + } + if (qmax_ <= qmin_) { + mprinterr("Error: qmax (%g) must be greater than qmin (%g).\n", qmax_, qmin_); + return 1; + } + } if (haveq) - mprintf("\tSmallest accessible q = %g Ang^-1\n", qmin_acc); + mprintf("\tSmallest accessible q (FFT grid) = %g Ang^-1\n", qmin_acc); + grid_ready_ = true; + return 0; +} + +void Action_SurfaceTension::SkipWarn(const char* msg) +{ + const int maxw = 5; + if (n_skip_warn_ < maxw) + mprintf("Warning: %s\n", msg); + else if (n_skip_warn_ == maxw) + mprintf("Warning: Further skip-frame messages suppressed.\n"); + n_skip_warn_++; +} + +// Action_SurfaceTension::WillardHeights() +int Action_SurfaceTension::WillardHeights(std::vector const& t1, + std::vector const& t2, + std::vector const& ncoord, + int natom, + double Lt1, double Lt2, double Ln, + std::vector& density, + bool want_u, bool want_l, + double& rho_bulk) +{ + double dx = Lt1 / (double)nx_; + double dy = Lt2 / (double)ny_; + double dz = Ln / (double)nz_; + double voxel = dx * dy * dz; + std::fill(density.begin(), density.end(), 0.0); + for (int i = 0; i < natom; i++) { + int ix = (int)floor(t1[i] / dx); + int iy = (int)floor(t2[i] / dy); + int iz = (int)floor(ncoord[i] / dz); + if (ix < 0) ix = 0; + if (iy < 0) iy = 0; + if (iz < 0) iz = 0; + if (ix >= nx_) ix = nx_ - 1; + if (iy >= ny_) iy = ny_ - 1; + if (iz >= nz_) iz = nz_ - 1; + density[ST_Idx3(ix, iy, iz, ny_, nz_)] += 1.0; + } + if (voxel > 0.0) { + for (size_t i = 0; i < density.size(); i++) + density[i] /= voxel; + } + ST_GaussianFilter3D(density, nx_, ny_, nz_, + sigma_xy_ / dx, sigma_xy_ / dy, sigma_z_ / dz); + + std::vector n_grid((size_t)nz_); + for (int iz = 0; iz < nz_; iz++) + n_grid[iz] = ((double)iz + 0.5) * dz; + double slab_center = 0.5 * Ln; + int center_index = 0; + double best = fabs(n_grid[0] - slab_center); + for (int iz = 1; iz < nz_; iz++) { + double d = fabs(n_grid[iz] - slab_center); + if (d < best) { + best = d; + center_index = iz; + } + } + + std::vector rho_n((size_t)nz_, 0.0); + double nxy = (double)(nx_ * ny_); + for (int ix = 0; ix < nx_; ix++) { + for (int iy = 0; iy < ny_; iy++) { + for (int iz = 0; iz < nz_; iz++) + rho_n[iz] += density[ST_Idx3(ix, iy, iz, ny_, nz_)]; + } + } + for (int iz = 0; iz < nz_; iz++) + rho_n[iz] /= nxy; + + double rho_bulk_acc = 0.0; + int nbulk = 0; + for (int iz = 0; iz < nz_; iz++) { + if (fabs(n_grid[iz] - slab_center) <= bulk_halfwidth_) { + rho_bulk_acc += rho_n[iz]; + nbulk++; + } + } + if (nbulk < 1) { + SkipWarn("No bins along the normal fall within the bulk region; skipping frame."); + return 1; + } + rho_bulk = rho_bulk_acc / (double)nbulk; + if (rho_bulk <= 0.0) { + SkipWarn("Bulk density is non-positive; skipping frame."); + return 1; + } + double threshold = threshold_frac_ * rho_bulk; + + std::vector col((size_t)nz_); + for (int ix = 0; ix < nx_; ix++) { + for (int iy = 0; iy < ny_; iy++) { + for (int iz = 0; iz < nz_; iz++) + col[iz] = density[ST_Idx3(ix, iy, iz, ny_, nz_)]; + if (want_u) { + double hu = ST_FindCrossing(n_grid, col, threshold, center_index, true); + if (!ST_Finite(hu)) { + SkipWarn("Could not identify a local interface; skipping frame."); + return 1; + } + h_upper_[ST_Idx2(ix, iy, ny_)] = hu; + } + if (want_l) { + double hl = ST_FindCrossing(n_grid, col, threshold, center_index, false); + if (!ST_Finite(hl)) { + SkipWarn("Could not identify a local interface; skipping frame."); + return 1; + } + h_lower_[ST_Idx2(ix, iy, ny_)] = hl; + } + } + } return 0; } @@ -1096,21 +1462,22 @@ int Action_SurfaceTension::ProcessFrame(Frame const& frm, double Lx, double Ly, double Lt1, Lt2, Ln; ST_SplitBox(nax, Lx, Ly, Lz, Lt1, Lt2, Ln); + std::vector t1, t2, n; + ST_SplitAtomCoords(frm, Mask_, nax, Lx, Ly, Lz, t1, t2, n); int natom = Mask_.Nselected(); - std::vector t1((size_t)natom), t2((size_t)natom), n((size_t)natom); - int idx = 0; - for (AtomMask::const_iterator at = Mask_.begin(); at != Mask_.end(); ++at, ++idx) { - const double* xyz = frm.XYZ(*at); - double a, b, c; - ST_SplitXYZ(nax, xyz[0], xyz[1], xyz[2], a, b, c); - t1[idx] = ST_Wrap(a, Lt1); - t2[idx] = ST_Wrap(b, Lt2); - n[idx] = c; + + std::vector t1b, t2b, nb; + int natom2 = 0; + if (has_mask2_) { + ST_SplitAtomCoords(frm, Mask2_, nax, Lx, Ly, Lz, t1b, t2b, nb); + natom2 = Mask2_.Nselected(); + double slab_center = ST_CircularSlabCenter(n, natom, &nb, natom2, Ln); + ST_ApplyCircularRecenter(n, Ln, slab_center); + ST_ApplyCircularRecenter(nb, Ln, slab_center); + } else { + ST_CircularRecenter(n, Ln); } - ST_CircularRecenter(n, Ln); - // Same bin counts as the reference Python: max(8, round(L/spacing)) in the - // interface plane, max(32, round(Ln/dz)) along the normal (Willard only). int nx = std::max(8, ST_IRound(Lt1 / gridspacing_)); int ny = std::max(8, ST_IRound(Lt2 / gridspacing_)); int nz = 0; @@ -1130,134 +1497,73 @@ int Action_SurfaceTension::ProcessFrame(Frame const& frm, double Lx, double Ly, mprinterr("Error: Lateral box dimensions changed. surftension assumes a fixed interface plane (NVT).\n"); return 2; } - if (iface_ == WILLARD && nz != nz_) { - // Normal-axis length may jitter slightly; keep the first-frame nz. + if (iface_ == WILLARD && nz != nz_) nz = nz_; - } } double rho_bulk = 0.0; if (iface_ == ITIM) { - rho_bulk = ST_RhoBulkFromAtoms(n, natom, Lt1, Lt2, Ln, bulk_halfwidth_); - if (!ST_ItimMinMax(t1, t2, n, natom, Lt1, Lt2, Ln, nx_, ny_, h_upper_, h_lower_)) { - mprintf("Warning: Empty ITIM column; skipping frame.\n"); - return 1; - } - } else { - double dx = Lt1 / (double)nx_; - double dy = Lt2 / (double)ny_; - double dz = Ln / (double)nz_; - double voxel = dx * dy * dz; - // Histogram counts, then convert to number density (Ang^-3). - std::fill(density_.begin(), density_.end(), 0.0); - for (int i = 0; i < natom; i++) { - int ix = (int)floor(t1[i] / dx); - int iy = (int)floor(t2[i] / dy); - int iz = (int)floor(n[i] / dz); - if (ix < 0) ix = 0; - if (iy < 0) iy = 0; - if (iz < 0) iz = 0; - if (ix >= nx_) ix = nx_ - 1; - if (iy >= ny_) iy = ny_ - 1; - if (iz >= nz_) iz = nz_ - 1; - density_[ST_Idx3(ix, iy, iz, ny_, nz_)] += 1.0; - } - if (voxel > 0.0) { - for (size_t i = 0; i < density_.size(); i++) - density_[i] /= voxel; - } - - ST_GaussianFilter3D(density_, nx_, ny_, nz_, - sigma_xy_ / dx, sigma_xy_ / dy, sigma_z_ / dz); - - // Bin centers, matching 0.5 * (edges[:-1] + edges[1:]) of numpy.histogramdd. - std::vector n_grid((size_t)nz_); - for (int iz = 0; iz < nz_; iz++) - n_grid[iz] = ((double)iz + 0.5) * dz; - double slab_center = 0.5 * Ln; - int center_index = 0; - double best = fabs(n_grid[0] - slab_center); - for (int iz = 1; iz < nz_; iz++) { - double d = fabs(n_grid[iz] - slab_center); - if (d < best) { - best = d; - center_index = iz; + if (has_mask2_) { + rho_bulk = ST_RhoBulkFromAtoms(n, natom, Lt1, Lt2, Ln, bulk_halfwidth_); + if (!ST_ItimTwoMasks(t1, t2, n, natom, t1b, t2b, nb, natom2, + Lt1, Lt2, nx_, ny_, h_upper_, h_lower_)) { + SkipWarn("Empty ITIM column; skipping frame."); + return 1; } - } - - std::vector rho_n((size_t)nz_, 0.0); - double nxy = (double)(nx_ * ny_); - for (int ix = 0; ix < nx_; ix++) { - for (int iy = 0; iy < ny_; iy++) { - for (int iz = 0; iz < nz_; iz++) - rho_n[iz] += density_[ST_Idx3(ix, iy, iz, ny_, nz_)]; - } - } - for (int iz = 0; iz < nz_; iz++) - rho_n[iz] /= nxy; - - // rho_bulk is the laterally averaged density within +/- bulk_halfwidth of Ln/2. - double rho_bulk_acc = 0.0; - int nbulk = 0; - for (int iz = 0; iz < nz_; iz++) { - if (fabs(n_grid[iz] - slab_center) <= bulk_halfwidth_) { - rho_bulk_acc += rho_n[iz]; - nbulk++; + } else { + rho_bulk = ST_RhoBulkFromAtoms(n, natom, Lt1, Lt2, Ln, bulk_halfwidth_); + if (!ST_ItimMinMax(t1, t2, n, natom, Lt1, Lt2, Ln, nx_, ny_, + do_upper_, do_lower_, h_upper_, h_lower_)) { + SkipWarn("Empty ITIM column; skipping frame."); + return 1; } } - if (nbulk < 1) { - mprintf("Warning: No bins along the normal fall within the bulk region; skipping frame.\n"); + } else if (has_mask2_) { + double rho1 = 0.0, rho2 = 0.0; + if (WillardHeights(t1, t2, n, natom, Lt1, Lt2, Ln, density_, true, false, rho1)) return 1; - } - rho_bulk = rho_bulk_acc / (double)nbulk; - if (rho_bulk <= 0.0) { - mprintf("Warning: Bulk density is non-positive; skipping frame.\n"); + if (WillardHeights(t1b, t2b, nb, natom2, Lt1, Lt2, Ln, density2_, false, true, rho2)) return 1; - } - double threshold = threshold_frac_ * rho_bulk; - - // One height pair per lateral column. Any missing crossing skips the frame. - std::vector col((size_t)nz_); - bool ok = true; - for (int ix = 0; ix < nx_ && ok; ix++) { - for (int iy = 0; iy < ny_; iy++) { - for (int iz = 0; iz < nz_; iz++) - col[iz] = density_[ST_Idx3(ix, iy, iz, ny_, nz_)]; - double hu = ST_FindCrossing(n_grid, col, threshold, center_index, true); - double hl = ST_FindCrossing(n_grid, col, threshold, center_index, false); - if (!ST_Finite(hu) || !ST_Finite(hl)) { - ok = false; - break; - } - h_upper_[ST_Idx2(ix, iy, ny_)] = hu; - h_lower_[ST_Idx2(ix, iy, ny_)] = hl; - } - } - if (!ok) { - mprintf("Warning: Could not identify a local interface; skipping frame.\n"); + rho_bulk = 0.5 * (rho1 + rho2); + } else { + if (WillardHeights(t1, t2, n, natom, Lt1, Lt2, Ln, density_, + do_upper_, do_lower_, rho_bulk)) return 1; - } } - double w_top = ST_RMS(h_upper_); - double w_bot = ST_RMS(h_lower_); - double w_mean = 0.5 * (w_top + w_bot); + double w_top = do_upper_ ? ST_RMS(h_upper_) : ST_NaN(); + double w_bot = do_lower_ ? ST_RMS(h_lower_) : ST_NaN(); + double w_mean; + if (do_upper_ && do_lower_) + w_mean = 0.5 * (w_top + w_bot); + else + w_mean = do_upper_ ? w_top : w_bot; - // Combined spectrum averages both surfaces (n_surfaces_ = 2 n_frames_). std::vector p_upper, p_lower; - HeightPower(h_upper_, p_upper); - HeightPower(h_lower_, p_lower); + int nsurf_this = 0; + if (do_upper_) { + HeightPower(h_upper_, p_upper); + nsurf_this++; + } else { + p_upper.assign(top_power_.size(), 0.0); + } + if (do_lower_) { + HeightPower(h_lower_, p_lower); + nsurf_this++; + } else { + p_lower.assign(bottom_power_.size(), 0.0); + } for (size_t i = 0; i < top_power_.size(); i++) { - top_power_[i] += p_upper[i]; - bottom_power_[i] += p_lower[i]; + if (do_upper_) top_power_[i] += p_upper[i]; + if (do_lower_) bottom_power_[i] += p_lower[i]; total_power_[i] += p_upper[i] + p_lower[i]; block_power_[i] += p_upper[i] + p_lower[i]; } n_frames_++; - n_surfaces_ += 2; - block_surface_count_ += 2; + n_surfaces_ += nsurf_this; + block_surface_count_ += nsurf_this; block_frame_count_++; block_w_sum_ += w_mean; block_wtop_sum_ += w_top; @@ -1318,7 +1624,7 @@ int Action_SurfaceTension::FinishBlock() { Action::RetType Action_SurfaceTension::DoAction(int, ActionFrame& frm) { if (!frm.Frm().BoxCrd().HasBox()) { - mprintf("Warning: Frame has no box; skipping.\n"); + SkipWarn("Frame has no box; skipping."); n_skipped_++; return Action::OK; } @@ -1328,7 +1634,7 @@ Action::RetType Action_SurfaceTension::DoAction(int, ActionFrame& frm) double Ly = (ly_user_ > 0.0) ? ly_user_ : lengths[1]; double Lz = (lz_user_ > 0.0) ? lz_user_ : lengths[2]; if (Lx <= 0.0 || Ly <= 0.0 || Lz <= 0.0) { - mprintf("Warning: Invalid box lengths; skipping frame.\n"); + SkipWarn("Invalid box lengths; skipping frame."); n_skipped_++; return Action::OK; } @@ -1364,10 +1670,12 @@ int Action_SurfaceTension::SyncAction() { int n2max = imax[0]; nx_ = imax[1]; ny_ = imax[2]; - double box[2] = { Lt1_ref_, Lt2_ref_ }; - trajComm_.AllReduce(box, 2, MPI_DOUBLE, MPI_MAX); + double box[4] = { Lt1_ref_, Lt2_ref_, qmin_, q_fundamental_ }; + trajComm_.AllReduce(box, 4, MPI_DOUBLE, MPI_MAX); Lt1_ref_ = box[0]; Lt2_ref_ = box[1]; + qmin_ = box[2]; + q_fundamental_ = box[3]; if (n2max < 1) return 0; if (n2 != 0 && n2 != n2max) { @@ -1426,6 +1734,12 @@ void Action_SurfaceTension::Print() mprintf("\tInterface: Willard-Chandler density isosurface.\n"); else mprintf("\tInterface: ITIM min/max.\n"); + mprintf("\tSurfaces: %i", nsurf_); + if (nsurf_ == 1) + mprintf(" (%s)", (side_ == SIDE_UPPER) ? "upper" : "lower"); + mprintf("\n"); + if (has_mask2_) + mprintf("\tMask2 (lower): '%s'\n", Mask2_.MaskString()); if (nblock_ > 0 && block_frame_count_ > 0) { mprintf("\tNOTE: Incomplete nblock window (%i frames) excluded from blockout.\n", block_frame_count_); @@ -1435,6 +1749,11 @@ void Action_SurfaceTension::Print() if (n_skipped_ > 0) mprinterr(" (%i skipped)", n_skipped_); mprinterr(".\n"); + if (summaryFile_ != 0) { + summaryFile_->Printf("# surftension summary\n"); + ST_SummaryI(summaryFile_, "frames", 0); + ST_SummaryI(summaryFile_, "skipped", n_skipped_); + } return; } @@ -1461,14 +1780,20 @@ void Action_SurfaceTension::Print() bot_only[i].S = shells[i].Sbot; } int err_full = ST_CalcGamma(shells, temp_, area, qmin_, qmax_, gamma_full, plateau); - int err_top = ST_CalcGamma(top_only, temp_, area, qmin_, qmax_, gamma_top, plateau_top); - int err_bot = ST_CalcGamma(bot_only, temp_, area, qmin_, qmax_, gamma_bot, plateau_bot); + int err_top = 1, err_bot = 1; + if (do_upper_) + err_top = ST_CalcGamma(top_only, temp_, area, qmin_, qmax_, gamma_top, plateau_top); + if (do_lower_) + err_bot = ST_CalcGamma(bot_only, temp_, area, qmin_, qmax_, gamma_bot, plateau_bot); (void)plateau_top; (void)plateau_bot; double gamma_h, kappa_h, gamma_h_top, kappa_h_top, gamma_h_bot, kappa_h_bot; int err_kh = ST_CalcKappa(shells, temp_, area, qmin_, qmax_, gamma_h, kappa_h); - int err_kh_top = ST_CalcKappa(top_only, temp_, area, qmin_, qmax_, gamma_h_top, kappa_h_top); - int err_kh_bot = ST_CalcKappa(bot_only, temp_, area, qmin_, qmax_, gamma_h_bot, kappa_h_bot); + int err_kh_top = 1, err_kh_bot = 1; + if (do_upper_) + err_kh_top = ST_CalcKappa(top_only, temp_, area, qmin_, qmax_, gamma_h_top, kappa_h_top); + if (do_lower_) + err_kh_bot = ST_CalcKappa(bot_only, temp_, area, qmin_, qmax_, gamma_h_bot, kappa_h_bot); double gamma_for_kappaq = err_kh ? gamma_full : gamma_h; double slope = ST_LogSlope(shells, qmin_, qmax_, &ST_Shell::S); @@ -1495,14 +1820,21 @@ void Action_SurfaceTension::Print() double mean_w = 0.0, mean_wt = 0.0, mean_wb = 0.0; if (wmean_->Size() > 0) { + int nu = 0, nl = 0; for (size_t i = 0; i < wmean_->Size(); i++) { - mean_w += ((DataSet_1D*)wmean_)->Dval(i); - mean_wt += ((DataSet_1D*)wtop_)->Dval(i); - mean_wb += ((DataSet_1D*)wbot_)->Dval(i); + mean_w += ((DataSet_1D*)wmean_)->Dval(i); + if (do_upper_) { + mean_wt += ((DataSet_1D*)wtop_)->Dval(i); + nu++; + } + if (do_lower_) { + mean_wb += ((DataSet_1D*)wbot_)->Dval(i); + nl++; + } } - mean_w /= (double)wmean_->Size(); - mean_wt /= (double)wtop_->Size(); - mean_wb /= (double)wbot_->Size(); + mean_w /= (double)wmean_->Size(); + if (nu > 0) mean_wt /= (double)nu; + if (nl > 0) mean_wb /= (double)nl; } mprintf("\tT = %g K\n", temp_); @@ -1510,8 +1842,11 @@ void Action_SurfaceTension::Print() if (n_skipped_ > 0) mprintf(" (%i skipped)", n_skipped_); mprintf("\n"); - mprintf("\tL(%s) = %g Ang, L(%s) = %g Ang\n", t1, Lt1_ref_, t2, Lt2_ref_); + mprintf("\tL(%s) = %g Ang, L(%s) = %g Ang (from unit cell unless lx/ly/lz set)\n", + t1, Lt1_ref_, t2, Lt2_ref_); mprintf("\tArea = %g Ang^2\n", area); + if (q_fundamental_ > 0.0) + mprintf("\tFundamental |q| = %g Ang^-1\n", q_fundamental_); mprintf("\tFit q range = %g to %g Ang^-1\n", qmin_, qmax_); if (ST_Finite(slope)) mprintf("\tLow-q log-log slope = %g (ideal capillary-wave slope is about -2)\n", slope); @@ -1534,9 +1869,14 @@ void Action_SurfaceTension::Print() mprintf("\tkappa, upper surface = %g kT\n", kappa_h_top); if (!err_kh_bot) mprintf("\tkappa, lower surface = %g kT\n", kappa_h_bot); - if (ST_Finite(slope_top) && ST_Finite(slope_bot)) + if (do_upper_ && do_lower_ && ST_Finite(slope_top) && ST_Finite(slope_bot)) mprintf("\tLow-q slope upper/lower = %g / %g\n", slope_top, slope_bot); - mprintf("\tMean roughness = %g Ang (upper %g, lower %g)\n", mean_w, mean_wt, mean_wb); + if (do_upper_ && do_lower_) + mprintf("\tMean roughness = %g Ang (upper %g, lower %g)\n", mean_w, mean_wt, mean_wb); + else if (do_upper_) + mprintf("\tMean roughness (upper) = %g Ang\n", mean_wt); + else + mprintf("\tMean roughness (lower) = %g Ang\n", mean_wb); if (block_gamma_ != 0 && block_gamma_->Size() > 0) { mprintf("\tCompleted blocks = %zu (nblock = %i frames)\n", @@ -1555,6 +1895,8 @@ void Action_SurfaceTension::Print() i + 1, g, w); } } + double block_gmean = ST_NaN(), block_gsd = ST_NaN(), block_gsem = ST_NaN(); + double block_kmean = ST_NaN(), block_ksd = ST_NaN(), block_ksem = ST_NaN(); if (block_gamma_ != 0 && block_gamma_->Size() > 1) { double gmean = 0.0, g2 = 0.0; for (size_t i = 0; i < block_gamma_->Size(); i++) { @@ -1567,6 +1909,9 @@ void Action_SurfaceTension::Print() (double)(block_gamma_->Size() - 1); double sd = (var > 0.0) ? sqrt(var) : 0.0; double sem = sd / sqrt((double)block_gamma_->Size()); + block_gmean = gmean; + block_gsd = sd; + block_gsem = sem; mprintf("\tBlock mean gamma = %g mN/m\n", gmean); mprintf("\tBlock SD gamma = %g mN/m\n", sd); mprintf("\tBlock SEM gamma = %g mN/m\n", sem); @@ -1587,10 +1932,51 @@ void Action_SurfaceTension::Print() double var = (k2 - (double)nk * kmean * kmean) / (double)(nk - 1); double sd = (var > 0.0) ? sqrt(var) : 0.0; double sem = sd / sqrt((double)nk); + block_kmean = kmean; + block_ksd = sd; + block_ksem = sem; mprintf("\tBlock mean kappa = %g kT\n", kmean); mprintf("\tBlock SD kappa = %g kT\n", sd); mprintf("\tBlock SEM kappa = %g kT\n", sem); mprintf("\tkappa +/- 2 SEM = %g kT\n", 2.0 * sem); } } + + if (summaryFile_ != 0) { + summaryFile_->Printf("# surftension summary\n"); + ST_SummaryD(summaryFile_, "temperature", temp_); + ST_SummaryI(summaryFile_, "nsurf", nsurf_); + ST_SummaryS(summaryFile_, "normal", ST_AxisName((int)normal_)); + ST_SummaryS(summaryFile_, "interface", (iface_ == WILLARD) ? "willard" : "itim"); + ST_SummaryS(summaryFile_, "mask", Mask_.MaskString()); + if (has_mask2_) + ST_SummaryS(summaryFile_, "mask2", Mask2_.MaskString()); + ST_SummaryD(summaryFile_, "L_t1", Lt1_ref_); + ST_SummaryD(summaryFile_, "L_t2", Lt2_ref_); + ST_SummaryD(summaryFile_, "area", area); + ST_SummaryD(summaryFile_, "q_fundamental", q_fundamental_); + ST_SummaryD(summaryFile_, "qmin", qmin_); + ST_SummaryD(summaryFile_, "qmax", qmax_); + ST_SummaryI(summaryFile_, "frames", n_frames_); + ST_SummaryI(summaryFile_, "skipped", n_skipped_); + if (!err_full) + ST_SummaryD(summaryFile_, "gamma", gamma_full); + if (do_upper_ && !err_top) + ST_SummaryD(summaryFile_, "gamma_upper", gamma_top); + if (do_lower_ && !err_bot) + ST_SummaryD(summaryFile_, "gamma_lower", gamma_bot); + if (!err_kh) + ST_SummaryD(summaryFile_, "kappa", kappa_h); + ST_SummaryD(summaryFile_, "roughness", mean_w); + if (do_upper_) + ST_SummaryD(summaryFile_, "roughness_upper", mean_wt); + if (do_lower_) + ST_SummaryD(summaryFile_, "roughness_lower", mean_wb); + ST_SummaryD(summaryFile_, "block_mean_gamma", block_gmean); + ST_SummaryD(summaryFile_, "block_sd_gamma", block_gsd); + ST_SummaryD(summaryFile_, "block_sem_gamma", block_gsem); + ST_SummaryD(summaryFile_, "block_mean_kappa", block_kmean); + ST_SummaryD(summaryFile_, "block_sd_kappa", block_ksd); + ST_SummaryD(summaryFile_, "block_sem_kappa", block_ksem); + } } diff --git a/src/Action_SurfaceTension.h b/src/Action_SurfaceTension.h index 4ae68486ca..56c757ce2a 100644 --- a/src/Action_SurfaceTension.h +++ b/src/Action_SurfaceTension.h @@ -5,21 +5,19 @@ #include "AtomMask.h" #include "PubFFT.h" class DataSet_Mesh; +class CpptrajFile; /// Capillary-wave surface tension of a liquid slab (Cartesian normal). -/** Instantaneous upper and lower interfaces are either a Willard-Chandler - * isosurface of a Gaussian-smoothed number-density field (default) or an - * ITIM-style per-column min/max of , split at mid-box along the normal. - * Height fluctuations in the interface plane are Fourier transformed with - * cpptraj PubFFT (row-column 1-D FFTs) using the numpy convention +/** Instantaneous interfaces are a Willard-Chandler isosurface of a + * Gaussian-smoothed number-density field (default) or ITIM min/max. + * Default is a two-interface slab (vacuum or a second phase on both + * sides of the film). nsurf 1 is a single interface. An optional + * second mask supplies the lower surface (leaflet / liquid-liquid). + * Lateral box lengths come from the unit cell unless lx/ly/lz are set. + * Height fluctuations are Fourier transformed with cpptraj PubFFT + * (row-column 1-D FFTs) using the numpy convention * h_q = (1 / N₁N₂) FFT2(h − ⟨h⟩) - * Capillary-wave theory including bending rigidity κ is - * ⟨|h_q|²⟩ = k_B T / (A (γ q² + κ q⁴)) - * so γ (mN/m) is obtained from the small-q plateau of q² S(q), and κ (in kT) - * from the slope of 1/(q² S) vs q² on the same window. - * The slab normal is x, y, or z (default z); gridspacing/sigmaxy apply in the - * interface plane and dz/sigmaz along the normal. Lateral box lengths are - * held fixed (NVT). DataSets are always created; files are written only when - * the matching *out keyword is given. MPI: packed ReduceMaster of |h_q|². + * γ (mN/m) from the small-q plateau of q² S(q); κ (kT) from the slope + * of 1/(q² S) vs q². If qmin is omitted it is 2π / max(Lt1, Lt2). * \author Nathan D Levinzon */ class Action_SurfaceTension : public Action { @@ -33,100 +31,111 @@ class Action_SurfaceTension : public Action { Action::RetType DoAction(int, ActionFrame&); void Print(); # ifdef MPI - /// Sum Fourier accumulators onto the master rank. int SyncAction(); Parallel::Comm trajComm_; # endif - /// Allocate density / height / power arrays for the lateral grid (and nz). int AllocateGrid(int, int, int); - /// Build interfaces and accumulate spectra for one frame. /** \return 0 OK, 1 skip frame, 2 fatal (grid or lateral box changed). */ int ProcessFrame(Frame const&, double, double, double); - /// Finish one complete nblock window (γ, κ, and roughness). int FinishBlock(); - /// |h_q|² of a height field via 2-D PubFFT / (nx ny). void HeightPower(std::vector const&, std::vector&); + /// Willard-Chandler heights from one atom set into the given density buffer. + /** \return 0 OK, 1 skip. */ + int WillardHeights(std::vector const&, std::vector const&, + std::vector const&, int, + double, double, double, + std::vector&, bool, bool, double&); + void SkipWarn(const char*); - /// Instantaneous-interface definition. enum IfaceType { WILLARD = 0, ITIM }; - /// Cartesian slab normal. enum NormalAxis { AXIS_X = 0, AXIS_Y = 1, AXIS_Z = 2 }; + enum SideType { SIDE_UPPER = 0, SIDE_LOWER }; - AtomMask Mask_; ///< Atoms used for the number-density / ITIM field - IfaceType iface_; ///< Willard-Chandler isosurface or ITIM min/max - NormalAxis normal_; ///< Slab normal (default z) + AtomMask Mask_; ///< Primary density / ITIM atoms (upper if mask2) + AtomMask Mask2_; ///< Optional lower-surface atoms (leaflet / 2nd liquid) + IfaceType iface_; + NormalAxis normal_; + SideType side_; ///< Which interface when nsurf == 1 + int nsurf_; ///< 1 or 2 instantaneous interfaces + bool has_mask2_; + bool do_upper_; + bool do_lower_; + bool qmin_specified_; - double temp_; ///< Temperature (K) - double gridspacing_; ///< Target bin spacing in the interface plane (Å) - double dz_; ///< Target bin spacing along the slab normal (Å) - double sigma_xy_; ///< Gaussian smoothing in the interface plane (Å) - double sigma_z_; ///< Gaussian smoothing along the slab normal (Å) - double bulk_halfwidth_; ///< Half-width around slab center for ρ_bulk (Å) - double threshold_frac_; ///< Interface is this fraction of ρ_bulk - double qmin_; ///< Fit-window minimum |q| (Å⁻¹) - double qmax_; ///< Fit-window maximum |q| (Å⁻¹) - double lx_user_; ///< Optional fixed box Lx; < 0 means use the box - double ly_user_; ///< Optional fixed box Ly; < 0 means use the box - double lz_user_; ///< Optional fixed box Lz; < 0 means use the box - int nblock_; ///< Frames per uncertainty block; 0 disables - int debug_; ///< Debug level from ActionInit + double temp_; + double gridspacing_; + double dz_; + double sigma_xy_; + double sigma_z_; + double bulk_halfwidth_; + double threshold_frac_; + double qmin_; + double qmax_; + double q_fund_; ///< min(2π/Lt1, 2π/Lt2) from the first good frame + double lx_user_; + double ly_user_; + double lz_user_; + double dt_; ///< Analyzed-frame spacing (ps); < 0 unused + double blocktime_; ///< Block length (ps); < 0 unused + int nblock_; + int debug_; + int n_skip_warn_; ///< Skip-frame warnings already printed - // ----- Spectrum vs q; filled in Print() -------------------------------- - DataSet_Mesh* S_; ///< Combined S(q) = ⟨|h_q|²⟩ (Ų) - DataSet_Mesh* S_top_; ///< Upper-interface S(q) - DataSet_Mesh* S_bot_; ///< Lower-interface S(q) - DataSet_Mesh* q2S_; ///< Combined q² S(q) - DataSet_Mesh* q2S_top_; ///< Upper q² S(q) - DataSet_Mesh* q2S_bot_; ///< Lower q² S(q) - DataSet_Mesh* gammaq_; ///< Apparent γ(q) (mN/m), combined - DataSet_Mesh* gammaq_top_; ///< Apparent γ(q), upper - DataSet_Mesh* gammaq_bot_; ///< Apparent γ(q), lower - DataSet_Mesh* kappaq_; ///< Apparent κ(q) (kT), combined - DataSet_Mesh* kappaq_top_; ///< Apparent κ(q), upper - DataSet_Mesh* kappaq_bot_; ///< Apparent κ(q), lower - // ----- Per-frame roughness / bulk density ------------------------------ - DataSet* wtop_; ///< Upper RMS roughness w (Å) - DataSet* wbot_; ///< Lower RMS roughness w (Å) - DataSet* wmean_; ///< Mean of upper and lower w (Å) - DataSet* rhobulk_; ///< Bulk number density (Å⁻³) - // ----- Per-block results (only if nblock > 0) -------------------------- - DataSet* block_gamma_; ///< Block γ (mN/m) - DataSet* block_kappa_; ///< Block κ (kT) - DataSet* block_wmean_; ///< Block mean roughness (Å) - DataSet* block_wtop_; ///< Block upper roughness (Å) - DataSet* block_wbot_; ///< Block lower roughness (Å) + DataSet_Mesh* S_; + DataSet_Mesh* S_top_; + DataSet_Mesh* S_bot_; + DataSet_Mesh* q2S_; + DataSet_Mesh* q2S_top_; + DataSet_Mesh* q2S_bot_; + DataSet_Mesh* gammaq_; + DataSet_Mesh* gammaq_top_; + DataSet_Mesh* gammaq_bot_; + DataSet_Mesh* kappaq_; + DataSet_Mesh* kappaq_top_; + DataSet_Mesh* kappaq_bot_; + DataSet* wtop_; + DataSet* wbot_; + DataSet* wmean_; + DataSet* rhobulk_; + DataSet* block_gamma_; + DataSet* block_kappa_; + DataSet* block_wmean_; + DataSet* block_wtop_; + DataSet* block_wbot_; + CpptrajFile* summaryFile_; ///< Optional key/value summary (summaryout) - std::vector density_; ///< n1×n2×nz number density (Å⁻³); unused for ITIM - std::vector h_upper_; ///< n1×n2 upper height field along the normal (Å) - std::vector h_lower_; ///< n1×n2 lower height field along the normal (Å) - std::vector total_power_; ///< Accumulated |h_q|², both surfaces - std::vector top_power_; ///< Accumulated |h_q|², upper - std::vector bottom_power_; ///< Accumulated |h_q|², lower - std::vector block_power_; ///< Combined |h_q|² for the open block - std::vector q_grid_; ///< |q| for each Fourier mode (Å⁻¹) + std::vector density_; ///< Willard field for Mask_ + std::vector density2_; ///< Willard field for Mask2_ + std::vector h_upper_; + std::vector h_lower_; + std::vector total_power_; + std::vector top_power_; + std::vector bottom_power_; + std::vector block_power_; + std::vector q_grid_; - PubFFT fft_n1_; ///< 1-D FFT along lateral axis 1 (nx) - PubFFT fft_n2_; ///< 1-D FFT along lateral axis 2 (ny) - ComplexArray fft_grid_; ///< nx×ny complex grid for the 2-D FFT - ComplexArray fft_row_; ///< Length-ny row buffer - ComplexArray fft_col_; ///< Length-nx column buffer + PubFFT fft_n1_; + PubFFT fft_n2_; + ComplexArray fft_grid_; + ComplexArray fft_row_; + ComplexArray fft_col_; - int nx_; ///< Bins along lateral axis 1 - int ny_; ///< Bins along lateral axis 2 - int nz_; ///< Density bins along the slab normal - double Lt1_ref_; ///< Lateral length 1 from the first good frame (Å) - double Lt2_ref_; ///< Lateral length 2 from the first good frame (Å) - bool grid_ready_; ///< True after the first successful frame + int nx_; + int ny_; + int nz_; + double Lt1_ref_; + double Lt2_ref_; + bool grid_ready_; - int n_frames_; ///< Frames that contributed to the spectra - int n_surfaces_; ///< 2 × n_frames_ (upper + lower) - int n_skipped_; ///< Frames skipped (no interface / no box) - int n_blocks_; ///< Completed uncertainty blocks - int block_surface_count_; ///< Surfaces accumulated in the open block - int block_frame_count_; ///< Frames accumulated in the open block - double block_w_sum_; ///< Running sum of mean w in the open block - double block_wtop_sum_; ///< Running sum of upper w - double block_wbot_sum_; ///< Running sum of lower w + int n_frames_; + int n_surfaces_; + int n_skipped_; + int n_blocks_; + int block_surface_count_; + int block_frame_count_; + double block_w_sum_; + double block_wtop_sum_; + double block_wbot_sum_; }; #endif diff --git a/test/Test_SurfTension/RunTest.sh b/test/Test_SurfTension/RunTest.sh index 234b4fe7de..20471fbe04 100644 --- a/test/Test_SurfTension/RunTest.sh +++ b/test/Test_SurfTension/RunTest.sh @@ -6,7 +6,7 @@ . ../MasterTest.sh -CleanFiles st.in +CleanFiles st.in st.summary.dat TESTNAME='Surface tension (surftension) tests' @@ -71,5 +71,31 @@ EOF RunCpptraj "$UNITNAME" fi +UNITNAME='surftension smoke (nsurf 1)' +CheckFor netcdf +if [ $? -eq 0 ] ; then + cat > st.in < st.in < Date: Mon, 31 Aug 2026 15:51:22 -0600 Subject: [PATCH 06/17] Update 'surftension' command to include 'out' alias and directory checks - Changed the 'spectrumout' parameter to be aliased as 'out' for simplified usage. - Implemented error handling in the initialization phase to ensure that the parent directory for output files exists, preventing loss of data during long trajectory writes. - Updated documentation in ChangeLog to reflect these changes and clarify output file handling. --- doc/ChangeLog.surftension.md | 5 ++- doc/ChangeLog.v7.md | 2 +- src/Action_SurfaceTension.cpp | 57 ++++++++++++++++++++++++++++++++--- 3 files changed, 57 insertions(+), 7 deletions(-) diff --git a/doc/ChangeLog.surftension.md b/doc/ChangeLog.surftension.md index 9f231f4a32..6f8064da50 100644 --- a/doc/ChangeLog.surftension.md +++ b/doc/ChangeLog.surftension.md @@ -22,7 +22,7 @@ surftension [] [mask2 ] temp [bulkhalfwidth ] [threshold ] [qmin ] [qmax ] [lx ] [ly ] [lz ] [nblock ] [dt ] [blocktime ] - [spectrumout ] [roughout ] [blockout ] + [out | spectrumout ] [roughout ] [blockout ] [summaryout ] [spectrumagr ] [roughagr ] [blockagr ] [spectrumgnu ] [roughgnu ] [blockgnu ] @@ -98,6 +98,9 @@ surftension [] [mask2 ] temp is a second mask for the lower surface (leaflet / liquid–liquid); the upper surface then comes from `` with no mid-box split. Both masks share one circular recenter so the film is not split apart. +- `out` is an alias for `spectrumout`. Init now errors if an `*out` path + names a directory that does not exist (DataFiles are opened only after + `run`, which previously lost a full trajectory write). --- diff --git a/doc/ChangeLog.v7.md b/doc/ChangeLog.v7.md index c49fdc32c0..1fe3d45a16 100644 --- a/doc/ChangeLog.v7.md +++ b/doc/ChangeLog.v7.md @@ -39,7 +39,7 @@ surftension [] [mask2 ] temp [bulkhalfwidth ] [threshold ] [qmin ] [qmax ] [lx ] [ly ] [lz ] [nblock ] [dt ] [blocktime ] - [spectrumout ] [roughout ] [blockout ] + [out | spectrumout ] [roughout ] [blockout ] [summaryout ] [spectrumagr ] [roughagr ] [blockagr ] [spectrumgnu ] [roughgnu ] [blockgnu ] diff --git a/src/Action_SurfaceTension.cpp b/src/Action_SurfaceTension.cpp index 0d13c2bbf3..a70cea8d12 100644 --- a/src/Action_SurfaceTension.cpp +++ b/src/Action_SurfaceTension.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include "Action_SurfaceTension.h" #include "Constants.h" @@ -14,6 +15,7 @@ #include "DataSet_1D.h" #include "DataSet_Mesh.h" #include "CpptrajFile.h" +#include "FileName.h" #include "Frame.h" #ifdef _OPENMP # include @@ -676,6 +678,23 @@ static void ST_SummaryS(CpptrajFile* f, const char* key, const char* v) { f->Printf("%s %s\n", key, v); } +/** DataFiles are opened only at the end of the run. Fail at Init if the + * parent directory is missing so a long trajectory is not processed only + * to lose the write. + */ +static int ST_CheckParentDir(DataFile* df, const char* key) { + if (df == 0) return 0; + std::string dir = df->DataFilename().DirPrefix_NoSlash(); + if (dir.empty()) return 0; + struct stat st; + if (stat(dir.c_str(), &st) != 0) { + mprinterr("Error: Directory '%s' for %s does not exist.\n", dir.c_str(), key); + mprinterr("Error: Create it first, or give a filename in the current directory.\n"); + return 1; + } + return 0; +} + // ----------------------------------------------------------------------------- /// CONSTRUCTOR — defaults match the reference Python analysis. Action_SurfaceTension::Action_SurfaceTension() : @@ -730,7 +749,7 @@ void Action_SurfaceTension::Help() const { "\t[bulkhalfwidth ] [threshold ]\n" "\t[qmin ] [qmax ] [lx ] [ly ] [lz ]\n" "\t[nblock ] [dt ] [blocktime ]\n" - "\t[spectrumout ] [roughout ] [blockout ]\n" + "\t[out | spectrumout ] [roughout ] [blockout ]\n" "\t[summaryout ]\n" "\t[spectrumagr ] [roughagr ] [blockagr ]\n" "\t[spectrumgnu ] [roughgnu ] [blockgnu ]\n" @@ -743,8 +762,9 @@ void Action_SurfaceTension::Help() const { " the upper surface then comes from with no mid-box split.\n" " If qmin is omitted it is 2*pi/max(Lt1,Lt2) from the first frame.\n" " blocktime (ps) with dt (analyzed-frame spacing, ps) sets nblock.\n" - " Output files are written only to paths the user gives; parent\n" - " directories must already exist.\n"); + " out is an alias for spectrumout. Write to the current directory,\n" + " e.g. spectrumout spec.dat roughout rough.dat blockout blocks.dat.\n" + " A directory in the name must already exist; it is not created.\n"); } // Action_SurfaceTension::Init() @@ -762,7 +782,20 @@ Action::RetType Action_SurfaceTension::Init(ArgList& actionArgs, ActionInit& ini # endif debug_ = debugIn; // Optional output files. AddDataFile returns 0 if the keyword is absent. - DataFile* spectrumFile = init.DFL().AddDataFile(actionArgs.GetStringKey("spectrumout"), actionArgs); + // out == spectrumout (usual cpptraj keyword for the main result file). + bool has_spectrumout = actionArgs.Contains("spectrumout"); + bool has_out = actionArgs.Contains("out"); + std::string specname = actionArgs.GetStringKey("spectrumout"); + std::string outname = actionArgs.GetStringKey("out"); + if (has_spectrumout && has_out && specname != outname) { + mprinterr("Error: 'out' and 'spectrumout' both specified and differ.\n"); + return Action::ERR; + } + if (specname.empty()) + specname = outname; + bool has_summaryout = actionArgs.Contains("summaryout"); + std::string sumname = actionArgs.GetStringKey("summaryout"); + DataFile* spectrumFile = init.DFL().AddDataFile(specname, actionArgs); DataFile* roughFile = init.DFL().AddDataFile(actionArgs.GetStringKey("roughout"), actionArgs); DataFile* blockFile = init.DFL().AddDataFile(actionArgs.GetStringKey("blockout"), actionArgs); DataFile* spectrumAgr = init.DFL().AddDataFile(actionArgs.GetStringKey("spectrumagr"), actionArgs, DataFile::XMGRACE); @@ -771,7 +804,21 @@ Action::RetType Action_SurfaceTension::Init(ArgList& actionArgs, ActionInit& ini DataFile* spectrumGnu = init.DFL().AddDataFile(actionArgs.GetStringKey("spectrumgnu"), actionArgs, DataFile::GNUPLOT); DataFile* roughGnu = init.DFL().AddDataFile(actionArgs.GetStringKey("roughgnu"), actionArgs, DataFile::GNUPLOT); DataFile* blockGnu = init.DFL().AddDataFile(actionArgs.GetStringKey("blockgnu"), actionArgs, DataFile::GNUPLOT); - summaryFile_ = init.DFL().AddCpptrajFile(actionArgs.GetStringKey("summaryout"), "SurfTension summary"); + summaryFile_ = init.DFL().AddCpptrajFile(sumname, "SurfTension summary"); + if (has_summaryout && summaryFile_ == 0) { + mprinterr("Error: Could not open summaryout '%s'.\n", sumname.c_str()); + return Action::ERR; + } + if (ST_CheckParentDir(spectrumFile, "spectrumout") || + ST_CheckParentDir(roughFile, "roughout") || + ST_CheckParentDir(blockFile, "blockout") || + ST_CheckParentDir(spectrumAgr, "spectrumagr") || + ST_CheckParentDir(roughAgr, "roughagr") || + ST_CheckParentDir(blockAgr, "blockagr") || + ST_CheckParentDir(spectrumGnu, "spectrumgnu") || + ST_CheckParentDir(roughGnu, "roughgnu") || + ST_CheckParentDir(blockGnu, "blockgnu")) + return Action::ERR; temp_ = actionArgs.getKeyDouble("temp", -1.0); if (temp_ <= 0.0) { From 57c456be138835f41aae93fe1956cf4c99eaf2c3 Mon Sep 17 00:00:00 2001 From: ndlevinzon Date: Mon, 31 Aug 2026 15:58:04 -0600 Subject: [PATCH 07/17] Refine documentation and formatting in Action_SurfaceTension MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Updated author name formatting for consistency. - Corrected mathematical symbols in comments for clarity, including replacing "n" with "−n" and "≤" with "≤". - Enhanced descriptions of functions and parameters to improve understanding of the capillary-wave theory and its implementation. - Adjusted comments to reflect accurate mathematical expressions and units, ensuring clarity in the context of surface tension calculations. - Improved overall readability of the code documentation. --- src/Action_SurfaceTension.cpp | 58 ++++++++++++++++++----------------- src/Action_SurfaceTension.h | 53 ++++++++++++++++++++++++++------ 2 files changed, 73 insertions(+), 38 deletions(-) diff --git a/src/Action_SurfaceTension.cpp b/src/Action_SurfaceTension.cpp index a70cea8d12..d89d74d6bd 100644 --- a/src/Action_SurfaceTension.cpp +++ b/src/Action_SurfaceTension.cpp @@ -1,7 +1,7 @@ // Action_SurfaceTension // Capillary-wave surface tension of a liquid slab (Cartesian normal x, y, or z). // See Action_SurfaceTension.h for the physical formulae. -// \author Nathan D Levinzon +// \author Nathan D. Levinzon #include #include #include @@ -270,7 +270,7 @@ static void ST_GaussianFilter3D(std::vector& rho, int nx, int ny, int nz } /** Locate the instantaneous interface along one lateral column. - * Walks from the slab center toward +n (upper) or -n (lower) and returns the + * Walks from the slab center toward +n (upper) or −n (lower) and returns the * linearly interpolated normal coordinate where rho crosses the bulk-density * threshold. \return NaN if no crossing is found. */ @@ -306,7 +306,7 @@ static double ST_FindCrossing(std::vector const& z_grid, } /** ITIM-style slab interfaces after circular recentering at Ln/2. - * In each lateral column: upper = max n of atoms with n >= Ln/2, lower = min n + * In each lateral column: upper = max n of atoms with n ≥ Ln/2, lower = min n * of atoms with n < Ln/2. Empty half-columns return false. * t1/t2/n are lateral 1, lateral 2, and the slab normal. */ @@ -424,7 +424,7 @@ static void ST_SplitAtomCoords(Frame const& frm, AtomMask const& mask, int nax, } } -/** Number density of mask atoms with |n - Ln/2| <= bulk_halfwidth (Ang^-3). */ +/** Number density of mask atoms with |n − Ln/2| ≤ bulk_halfwidth (Å⁻³). */ static double ST_RhoBulkFromAtoms(std::vector const& ncoord, int natom, double Lt1, double Lt2, double Ln, double bulk_halfwidth) @@ -455,8 +455,8 @@ static double ST_RMS(std::vector const& h) { return sqrt(acc / (double)h.size()); } -/** Sample frequencies, identical to numpy.fft.fftfreq(n, d)[k]. - * d is the real-space sample spacing (Å). Result is in Å⁻¹. +/** Wrapped mode index of bin k on an N-point grid of spacing Δ (Å). + * n ∈ (−N/2, N/2]; frequency is n / (N Δ). Used as q_α = 2π n_α / L_α. */ static double ST_FftFreq(int k, int n, double d) { int p; @@ -467,7 +467,7 @@ static double ST_FftFreq(int k, int n, double d) { return (double)p / ((double)n * d); } -/** |q| = √(qx² + qy²) for each Fourier mode, qx = 2π fftfreq(nx, Lx/nx). */ +/** |q| = √(q₁² + q₂²) with q₁ = 2π n₁ / L₁, q₂ = 2π n₂ / L₂. */ static void ST_MakeQGrid(int nx, int ny, double Lx, double Ly, std::vector& q) { q.resize((size_t)nx * (size_t)ny); double dx = Lx / (double)nx; @@ -536,11 +536,13 @@ static void ST_ShellAverage(std::vector const& q, std::sort(shells.begin(), shells.end(), ST_ShellQCmp); } -/** Capillary-wave γ from the mean q² S(q) plateau on [qmin, qmax]. - * plateau = ⟨ q² S(q) ⟩_shells - * γ (N/m) = k_B T / (A plateau), then ×1000 → mN/m - * Equal weight per q-shell. Needs at least two shells. - * \return 0 on success, 1 on failure (γ/plateau set to NaN). +/** Capillary-wave γ from the small-q plateau of q² S(q). + * S(q) = k_B T / (A γ q²) (κ → 0) + * γ = k_B T / (A ⟨q² S(q)⟩) + * ⟨…⟩ is an equal-weight mean over shells on [q_min, q_max]. + * A is converted Ų → m²; γ is then ×1000 → mN/m. + * Needs at least two shells. + * \return 0 on success, 1 on failure (γ / ⟨q² S⟩ set to NaN). */ static int ST_CalcGamma(std::vector const& shells, double temperature, double area_A2, double qmin, double qmax, @@ -564,12 +566,12 @@ static int ST_CalcGamma(std::vector const& shells, double temperature, return 0; } -/** Helfrich fit on [qmin, qmax]: - * 1 / (q² S) = a + b q² - * q in Å⁻¹, S in Ų, so q² S is dimensionless. - * γ (mN/m) = 1000 k_B T a / A_m² (intercept) - * κ / kT = b / A_Ų (slope) - * Equal weight per shell. Needs at least three shells with S > 0. +/** Helfrich inversion of S(q) = k_B T / [A (γ q² + κ q⁴)]: + * 1/(q² S) = (A / k_B T) (γ + κ q²) = a + b q² + * γ = k_B T a / A (N/m, then ×1000 → mN/m) + * κ / k_B T = b / A (A in Ų) + * q in Å⁻¹, S in Ų; q² S is dimensionless. Equal weight per shell. + * Needs at least three shells with S > 0. * \return 0 on success, 1 on failure (outputs set to NaN). */ static int ST_CalcKappa(std::vector const& shells, double temperature, @@ -605,7 +607,7 @@ static int ST_CalcKappa(std::vector const& shells, double temperature, return 0; } -/** Apparent κ(q)/kT given γ (mN/m): invert γ q² + κ q⁴ at one shell. */ +/** Apparent κ(q)/k_B T at one shell: invert S = k_B T / [A (γ q² + κ q⁴)]. */ static double ST_ShellKappa(double q, double S, double temperature, double area_A2, double gamma_mNm) { @@ -620,7 +622,7 @@ static double ST_ShellKappa(double q, double S, double temperature, double area_ return b / area_A2; } -/** Apparent γ(q) = k_B T / (A q² S(q)) in mN/m. */ +/** Apparent γ(q) = k_B T / (A q² S(q)), reported in mN/m. */ static double ST_ShellGamma(double q, double S, double temperature, double area_A2) { double q2S = q * q * S; if (q2S <= 0.0) return ST_NaN(); @@ -1062,7 +1064,7 @@ Action::RetType Action_SurfaceTension::Init(ArgList& actionArgs, ActionInit& ini kappaq_top_->SetDim(Dimension::X, qdim); kappaq_bot_->SetDim(Dimension::X, qdim); // Print() fills these from the accumulated spectra; they are not time series. - // MPI: SyncAction reduces |h_q|^2; skip DataSet concat of empty meshes. + // MPI: SyncAction reduces |h_q|²; skip DataSet concat of empty meshes. # ifdef MPI S_->SetNeedsSync(false); S_top_->SetNeedsSync(false); S_bot_->SetNeedsSync(false); q2S_->SetNeedsSync(false); q2S_top_->SetNeedsSync(false); q2S_bot_->SetNeedsSync(false); @@ -1435,10 +1437,10 @@ int Action_SurfaceTension::WillardHeights(std::vector const& t1, } // Action_SurfaceTension::HeightPower() -/** 2-D FFT of h − ⟨h⟩ via row-column PubFFT 1-D transforms, then - * h_q = FFT2 / (nx ny) - * matching numpy.fft.fft2(h) / h.size. Power is |h_q|² (Ang^2). - * fft_n2_ transforms along iy (contiguous); fft_n1_ along ix. +/** Discrete Fourier transform of h − ⟨h⟩ (row–column 1-D PubFFTs). + * h_q = (1/(N₁ N₂)) Σ (h − ⟨h⟩) exp(−i q · r) + * implemented as unnormalized FFTW / numpy fft2, then ÷ (N₁ N₂). + * Power is |h_q|² (Ų). fft_n2_ along n₂; fft_n1_ along n₁. */ void Action_SurfaceTension::HeightPower(std::vector const& h, std::vector& power) @@ -1499,8 +1501,8 @@ void Action_SurfaceTension::HeightPower(std::vector const& h, // Action_SurfaceTension::ProcessFrame() /** Wrap laterals, recenter along the normal, build instantaneous interfaces, - * then accumulate roughness and |h_q|^2. First good frame freezes nx, ny, - * Lt1, Lt2 (and nz for Willard-Chandler). Cartesian Lx/Ly/Lz are permuted + * then accumulate roughness and |h_q|². First good frame freezes nx, ny, + * Lt1, Lt2 (and nz for Willard–Chandler). Cartesian Lx/Ly/Lz are permuted * into (Lt1, Lt2, Ln) according to normal_. */ int Action_SurfaceTension::ProcessFrame(Frame const& frm, double Lx, double Ly, double Lz) @@ -1697,7 +1699,7 @@ Action::RetType Action_SurfaceTension::DoAction(int, ActionFrame& frm) #ifdef MPI // Action_SurfaceTension::SyncAction() /** Radial-style reduction. Three small AllReduces (counts SUM, grid MAX, lateral - * box MAX) then one packed ReduceMaster SUM of combined/upper/lower |h_q|^2 onto + * box MAX) then one packed ReduceMaster SUM of combined/upper/lower |h_q|² onto * the master. |q| uses a separate MAX (different MPI_Op). Print() is master * only. Roughness / block series use DataSet::Sync (concat by rank). */ diff --git a/src/Action_SurfaceTension.h b/src/Action_SurfaceTension.h index 56c757ce2a..e6aa2232ef 100644 --- a/src/Action_SurfaceTension.h +++ b/src/Action_SurfaceTension.h @@ -7,18 +7,51 @@ class DataSet_Mesh; class CpptrajFile; /// Capillary-wave surface tension of a liquid slab (Cartesian normal). -/** Instantaneous interfaces are a Willard-Chandler isosurface of a +/** Instantaneous interfaces are a Willard–Chandler isosurface of a * Gaussian-smoothed number-density field (default) or ITIM min/max. * Default is a two-interface slab (vacuum or a second phase on both * sides of the film). nsurf 1 is a single interface. An optional - * second mask supplies the lower surface (leaflet / liquid-liquid). - * Lateral box lengths come from the unit cell unless lx/ly/lz are set. - * Height fluctuations are Fourier transformed with cpptraj PubFFT - * (row-column 1-D FFTs) using the numpy convention - * h_q = (1 / N₁N₂) FFT2(h − ⟨h⟩) - * γ (mN/m) from the small-q plateau of q² S(q); κ (kT) from the slope - * of 1/(q² S) vs q². If qmin is omitted it is 2π / max(Lt1, Lt2). - * \author Nathan D Levinzon + * second mask supplies the lower surface (leaflet / liquid–liquid). + * Lateral lengths L₁, L₂ come from the unit cell unless lx/ly/lz are + * set. Area A = L₁ L₂. + * + * Discrete Fourier modes of the height (FFTW / numpy unnormalized + * transform, then divide by N): + * h_q = (1/(N₁ N₂)) Σ_{n₁,n₂} (h − ⟨h⟩) exp(−i q · r) + * q = (2π n₁/L₁, 2π n₂/L₂), S(q) ≡ ⟨|h_q|²⟩ + * + * Capillary-wave theory (Helfrich): + * S(q) = k_B T / [A (γ q² + κ q⁴)] + * Small-q (κ → 0): q² S(q) → k_B T / (A γ), so + * γ = k_B T / (A ⟨q² S(q)⟩) on [q_min, q_max] + * reported in mN/m (×1000 from N/m). If q_min is omitted it is the + * fundamental wavevector 2π / max(L₁, L₂). + * + * Bending modulus from the linear form + * 1/(q² S) = (A / k_B T) (γ + κ q²) + * intercept → γ, slope → κ / k_B T. + * + * \author Nathan D. Levinzon + * + * References (for interested parties or lowly PhD students like me): + * Willard–Chandler instantaneous interface + * A. P. Willard and D. Chandler, J. Phys. Chem. B 114, 1954 (2010). + * https://doi.org/10.1021/jp909219k + * ITIM (Identification of Truly Interfacial Molecules) + * L. B. Pártay, G. Hantal, P. Jedlovszky, Á. Vincze, and G. Horvai, + * J. Comput. Chem. 29, 945 (2008). + * https://doi.org/10.1002/jcc.20852 + * Capillary-wave theory + * F. P. Buff, R. A. Lovett, and F. H. Stillinger, + * Phys. Rev. Lett. 15, 621 (1965). + * https://doi.org/10.1103/PhysRevLett.15.621 + * Height-fluctuation surface tension in MD + * S. W. Sides, G. S. Grest, and M.-D. Lacasse, + * Phys. Rev. E 60, 6708 (1999). + * https://doi.org/10.1103/PhysRevE.60.6708 + * Helfrich bending energy + * W. Helfrich, Z. Naturforsch. C 28, 693 (1973). + * https://doi.org/10.1515/znc-1973-11-1209 */ class Action_SurfaceTension : public Action { public: @@ -40,7 +73,7 @@ class Action_SurfaceTension : public Action { int ProcessFrame(Frame const&, double, double, double); int FinishBlock(); void HeightPower(std::vector const&, std::vector&); - /// Willard-Chandler heights from one atom set into the given density buffer. + /// Willard–Chandler heights from one atom set into the given density buffer. /** \return 0 OK, 1 skip. */ int WillardHeights(std::vector const&, std::vector const&, std::vector const&, int, From e099e4111369029d16ebb6bdeae17d58f287c1fc Mon Sep 17 00:00:00 2001 From: ndlevinzon Date: Mon, 31 Aug 2026 16:01:30 -0600 Subject: [PATCH 08/17] Enhance documentation in Action_SurfaceTension.cpp for clarity and detail - Expanded comments to provide a clearer understanding of the capillary-wave surface tension calculations and the per-frame processing pipeline. - Improved descriptions of functions, parameters, and mathematical expressions to ensure accuracy and readability. - Updated variable and function comments to reflect consistent terminology and units, enhancing overall documentation quality. --- src/Action_SurfaceTension.cpp | 216 +++++++++++++++++++++++----------- 1 file changed, 149 insertions(+), 67 deletions(-) diff --git a/src/Action_SurfaceTension.cpp b/src/Action_SurfaceTension.cpp index d89d74d6bd..24d9e62e10 100644 --- a/src/Action_SurfaceTension.cpp +++ b/src/Action_SurfaceTension.cpp @@ -1,6 +1,18 @@ // Action_SurfaceTension // Capillary-wave surface tension of a liquid slab (Cartesian normal x, y, or z). -// See Action_SurfaceTension.h for the physical formulae. +// Formulae, units, and references: Action_SurfaceTension.h +// +// Per-frame pipeline (after Init / Setup): +// 1. Permute Cartesian (x,y,z) into (t1, t2, n) for the chosen normal. +// 2. Wrap laterals into [0, L_α). Recenter the normal so the circular +// mean of the film sits at L_n/2 (one shared shift if mask2 is set). +// 3. Instantaneous height h(t1, t2): Willard–Chandler isosurface or ITIM. +// 4. Roughness w = √⟨(h − ⟨h⟩)²⟩ and power |h_q|² from the DFT +// h_q = (1/(N₁ N₂)) Σ (h − ⟨h⟩) exp(−i q · r) +// 5. Print() forms S(q) ≡ ⟨|h_q|²⟩, shell-averages, then +// S(q) = k_B T / [A (γ q² + κ q⁴)] +// +// NVT: first good frame freezes N₁, N₂, L₁, L₂ (and N_n for Willard). // \author Nathan D. Levinzon #include #include @@ -24,15 +36,14 @@ // File-local helpers. Names are prefixed ST_ so they do not collide with // other Action translation units. -/// Boltzmann constant (J/K); SI, matching the reference Python analysis. +/// k_B (J/K), CODATA 2018. γ uses SI: k_B T / (A_m² ⟨q² S⟩), then ×1000 → mN/m. static const double ST_KB = 1.380649e-23; -/// Convert Ų → m². +/// Ų → m² so A in the CWT formula is consistent with γ in N/m. static const double ST_ANG2_TO_M2 = 1.0e-20; -/// scipy.ndimage.gaussian_filter default truncate (kernel radius = truncate × σ). +/// scipy.ndimage.gaussian_filter default: kernel radius = truncate × σ (pixels). static const double ST_GAUSS_TRUNCATE = 4.0; -/// \return true if x is finite (not NaN or ±Inf). -static inline bool ST_Finite(double x) { +/// \return true if x is finite (not NaN or ±Inf). Used to reject failed crossings. return (x == x) && (x < std::numeric_limits::infinity()) && (x > -std::numeric_limits::infinity()); @@ -42,12 +53,12 @@ static inline double ST_NaN() { return std::numeric_limits::quiet_NaN(); } -/// Linear index of density_(ix, iy, iz) with z the fastest dimension. +/// Linear index of ρ(i₁, i₂, i_n) with the normal the fastest dimension. static inline size_t ST_Idx3(int ix, int iy, int iz, int ny, int nz) { return ((size_t)ix * (size_t)ny + (size_t)iy) * (size_t)nz + (size_t)iz; } -/// Linear index of an nx×ny field stored row-major in x, then y. +/// Linear index of an N₁×N₂ field, row-major in the first lateral index. static inline size_t ST_Idx2(int ix, int iy, int ny) { return (size_t)ix * (size_t)ny + (size_t)iy; } @@ -57,7 +68,10 @@ static inline int ST_IRound(double x) { return (int)floor(x + 0.5); } -/** Wrap x into [0, L). Handles negative values; maps x == L back to 0. */ +/** Minimum-image wrap of a Cartesian coordinate into [0, L). + * fmod of a negative argument is negative on IEEE-754; that case is lifted + * back into the interval. x == L maps to 0 so the last bin is not empty. + */ static double ST_Wrap(double x, double L) { if (L <= 0.0) return x; double y = fmod(x, L); @@ -66,9 +80,12 @@ static double ST_Wrap(double x, double L) { return y; } -/** Circular-mean slab center along the normal (periodic). n2 may be 0. - * Mapping n → θ = 2π n / L, then atan2(⟨sin θ⟩, ⟨cos θ⟩), so a slab that - * straddles the periodic boundary is still recentered correctly. +/** Circular mean of the film along the periodic normal, in Å. + * Map n → θ = 2π n / L_n and take atan2(⟨sin θ⟩, ⟨cos θ⟩). A slab that + * straddles n = 0 is then a single cluster on the circle. n2 may be 0; + * when both masks are given they share this one mean so leaflets are not + * pulled onto the same mid-box plane independently. + * \return the lab-frame coordinate of that mean, in [0, L_n). */ static double ST_CircularSlabCenter(std::vector const& n1, int n1n, std::vector const* n2, int n2n, @@ -100,6 +117,7 @@ static double ST_CircularSlabCenter(std::vector const& n1, int n1n, return L * angle / Constants::TWOPI; } +/** Shift n so slab_center maps to L_n/2, then wrap into [0, L_n). */ static void ST_ApplyCircularRecenter(std::vector& n, double L, double slab_center) { @@ -108,27 +126,31 @@ static void ST_ApplyCircularRecenter(std::vector& n, double L, n[i] = ST_Wrap(n[i] - slab_center + 0.5 * L, L); } -/** Recenter a periodic slab so its circular mean along the normal lies at L/2. */ +/** Recenter one atom set so its circular mean along the normal lies at L_n/2. */ static void ST_CircularRecenter(std::vector& n, double L) { if (n.empty() || L <= 0.0) return; ST_ApplyCircularRecenter(n, L, ST_CircularSlabCenter(n, (int)n.size(), 0, 0, L)); } -/// Cartesian axis name for Help / mprintf (ASCII). +/// ASCII name of a Cartesian axis for Help / mprintf (terminals are not UTF-8). static const char* ST_AxisName(int axis) { if (axis == 0) return "x"; if (axis == 1) return "y"; return "z"; } -/// Lateral axis names for a given Cartesian normal. +/// Names of the two lateral axes for Cartesian normal ∈ {0,1,2} = {x,y,z}. static void ST_PlaneAxes(int normal, const char*& t1, const char*& t2) { if (normal == 0) { t1 = "y"; t2 = "z"; } else if (normal == 1) { t1 = "x"; t2 = "z"; } else { t1 = "x"; t2 = "y"; } } -/// Split Cartesian box lengths into lateral 1, lateral 2, and normal. +/** Permute (L_x, L_y, L_z) into (L₁, L₂, L_n). + * n = z: L₁ = L_x, L₂ = L_y, L_n = L_z + * n = y: L₁ = L_x, L₂ = L_z, L_n = L_y + * n = x: L₁ = L_y, L₂ = L_z, L_n = L_x + */ static void ST_SplitBox(int normal, double Lx, double Ly, double Lz, double& Lt1, double& Lt2, double& Ln) { @@ -137,7 +159,7 @@ static void ST_SplitBox(int normal, double Lx, double Ly, double Lz, else { Lt1 = Lx; Lt2 = Ly; Ln = Lz; } } -/// Split a Cartesian point into lateral 1, lateral 2, and normal. +/// Same permutation as ST_SplitBox, applied to one Cartesian point. static void ST_SplitXYZ(int normal, double x, double y, double z, double& t1, double& t2, double& n) { @@ -146,8 +168,10 @@ static void ST_SplitXYZ(int normal, double x, double y, double z, else { t1 = x; t2 = y; n = z; } } -/** Normalized 1-D Gaussian kernel matching scipy.ndimage._gaussian_kernel1d. - * σ is in pixels. Radius = round(4 σ). Empty kernel means “do not filter”. +/** Normalized 1-D Gaussian matching scipy.ndimage._gaussian_kernel1d. + * σ is in pixels (Å / bin width). Radius = round(4 σ). Weights are + * K_i = exp(−i² / (2 σ²)) / Σ_j K_j , i ∈ [−R, R] + * An empty kernel (σ ≤ 0) means that axis is left unfiltered. */ static void ST_GaussianKernel(double sigma, std::vector& kernel) { kernel.clear(); @@ -168,8 +192,8 @@ static void ST_GaussianKernel(double sigma, std::vector& kernel) { } } -/** 1-D convolution with periodic (wrap) boundaries. - * The Gaussian kernel is symmetric, so correlate and convolve agree. +/** Periodic 1-D convolution, out[i] = Σ_k K_k in[(i+k) mod N]. + * The Gaussian is even, so convolution and correlation are identical. */ static void ST_ConvolveWrap(std::vector const& in, std::vector const& kernel, std::vector& out) @@ -195,10 +219,10 @@ static void ST_ConvolveWrap(std::vector const& in, std::vector c } } -/** Separable Gaussian smooth of ρ(ix,iy,iz) with periodic boundaries on every axis. - * σx, σy, σz are in pixels (Å / bin width), as in scipy.ndimage.gaussian_filter. - * OpenMP: each 1-D line in a pass is independent. One parallel region covers - * the z, y, and x passes so thread-local line buffers are reused. +/** Separable periodic Gaussian on ρ(i₁, i₂, i_n), Willard–Chandler coarse-graining. + * σ_α in pixels (Å / Δ_α), same as scipy.ndimage.gaussian_filter. Three + * 1-D passes (n, then t2, then t1). OpenMP: each line in a pass is + * independent; one parallel region reuses thread-local buffers. */ static void ST_GaussianFilter3D(std::vector& rho, int nx, int ny, int nz, double sigma_x, double sigma_y, double sigma_z) @@ -269,10 +293,12 @@ static void ST_GaussianFilter3D(std::vector& rho, int nx, int ny, int nz } } -/** Locate the instantaneous interface along one lateral column. - * Walks from the slab center toward +n (upper) or −n (lower) and returns the - * linearly interpolated normal coordinate where rho crosses the bulk-density - * threshold. \return NaN if no crossing is found. +/** Willard–Chandler crossing along one lateral column. + * Walk from the slab mid-plane toward +n (upper) or −n (lower). The + * interface is the first point where ρ drops through θ ρ_bulk, with θ + * the threshold fraction. Linear interpolation between the two bins: + * n* = n_k + (θ ρ_bulk − ρ_k) (n_{k±1} − n_k) / (ρ_{k±1} − ρ_k) + * \return NaN if no crossing exists (caller skips the frame). */ static double ST_FindCrossing(std::vector const& z_grid, std::vector const& density, @@ -305,10 +331,12 @@ static double ST_FindCrossing(std::vector const& z_grid, return ST_NaN(); } -/** ITIM-style slab interfaces after circular recentering at Ln/2. - * In each lateral column: upper = max n of atoms with n ≥ Ln/2, lower = min n - * of atoms with n < Ln/2. Empty half-columns return false. - * t1/t2/n are lateral 1, lateral 2, and the slab normal. +/** ITIM in the probe → 0 limit, after the film has been recentered at L_n/2. + * Each lateral column is split at mid-box: + * h_upper = max { n_i | n_i ≥ L_n/2 } (need_u) + * h_lower = min { n_i | n_i < L_n/2 } (need_l) + * An empty required half-column returns false (skip the frame). This is + * not a finite-radius ITIM probe; it is the min/max of the mask. */ static bool ST_ItimMinMax(std::vector const& t1, std::vector const& t2, @@ -351,7 +379,11 @@ static bool ST_ItimMinMax(std::vector const& t1, return true; } -/** ITIM from two atom sets: upper = max n of set 1, lower = min n of set 2. */ +/** Two-mask ITIM (leaflet / liquid–liquid): no mid-box split. + * h_upper(i₁,i₂) = max n of mask 1 in that column + * h_lower(i₁,i₂) = min n of mask 2 in that column + * \return false if any required column is empty. + */ static bool ST_ItimTwoMasks(std::vector const& t1u, std::vector const& t2u, std::vector const& nu, @@ -401,7 +433,10 @@ static bool ST_ItimTwoMasks(std::vector const& t1u, return true; } -/** Split Cartesian coordinates into wrapped laterals and a recentered normal. */ +/** Extract (t1, t2, n) for one mask. Laterals are wrapped into [0, L_α); + * the normal is left unshifted. Recenter is applied afterwards so two + * masks can share one circular mean. + */ static void ST_SplitAtomCoords(Frame const& frm, AtomMask const& mask, int nax, double Lx, double Ly, double Lz, std::vector& t1, std::vector& t2, @@ -424,7 +459,10 @@ static void ST_SplitAtomCoords(Frame const& frm, AtomMask const& mask, int nax, } } -/** Number density of mask atoms with |n − Ln/2| ≤ bulk_halfwidth (Å⁻³). */ +/** Number density of mask atoms in the mid-slab slab |n − L_n/2| ≤ w (Å⁻³). + * Volume is L₁ L₂ (2w). Used for the rhobulk DataSet on the ITIM path; + * Willard–Chandler ρ_bulk is the laterally averaged coarse-grained field. + */ static double ST_RhoBulkFromAtoms(std::vector const& ncoord, int natom, double Lt1, double Lt2, double Ln, double bulk_halfwidth) @@ -440,7 +478,10 @@ static double ST_RhoBulkFromAtoms(std::vector const& ncoord, int natom, return (double)nbulk / vol; } -/** RMS height fluctuation w = √⟨(h − ⟨h⟩)²⟩_xy (Å). */ +/** Capillary roughness of one instantaneous surface, in Å: + * w = √⟨ (h − ⟨h⟩)² ⟩_{i₁,i₂} + * the RMS of the same field whose DFT gives S(q). + */ static double ST_RMS(std::vector const& h) { if (h.empty()) return ST_NaN(); double mean = 0.0; @@ -455,8 +496,9 @@ static double ST_RMS(std::vector const& h) { return sqrt(acc / (double)h.size()); } -/** Wrapped mode index of bin k on an N-point grid of spacing Δ (Å). - * n ∈ (−N/2, N/2]; frequency is n / (N Δ). Used as q_α = 2π n_α / L_α. +/** Cyclic frequency of DFT bin k on an N-point grid of spacing Δ (Å). + * Mode index n ∈ (−N/2, N/2]; frequency is n / (N Δ) = n / L_α. + * Wavevector component is then q_α = 2π n / L_α (Å⁻¹). */ static double ST_FftFreq(int k, int n, double d) { int p; @@ -467,7 +509,7 @@ static double ST_FftFreq(int k, int n, double d) { return (double)p / ((double)n * d); } -/** |q| = √(q₁² + q₂²) with q₁ = 2π n₁ / L₁, q₂ = 2π n₂ / L₂. */ +/** |q| = √(q₁² + q₂²) on the N₁×N₂ Fourier mesh, q_α = 2π n_α / L_α. */ static void ST_MakeQGrid(int nx, int ny, double Lx, double Ly, std::vector& q) { q.resize((size_t)nx * (size_t)ny); double dx = Lx / (double)nx; @@ -481,13 +523,13 @@ static void ST_MakeQGrid(int nx, int ny, double Lx, double Ly, std::vector const& q, std::vector const& combined, @@ -607,7 +651,10 @@ static int ST_CalcKappa(std::vector const& shells, double temperature, return 0; } -/** Apparent κ(q)/k_B T at one shell: invert S = k_B T / [A (γ q² + κ q⁴)]. */ +/** Apparent κ(q)/k_B T at one shell, given a reference γ (mN/m). + * Invert S = k_B T / [A (γ q² + κ q⁴)] → κ / k_B T = [1/(q² S) − A γ / k_B T] / (A q²). + * Negative κ is allowed (the linear Helfrich slope may change sign). + */ static double ST_ShellKappa(double q, double S, double temperature, double area_A2, double gamma_mNm) { @@ -622,7 +669,9 @@ static double ST_ShellKappa(double q, double S, double temperature, double area_ return b / area_A2; } -/** Apparent γ(q) = k_B T / (A q² S(q)), reported in mN/m. */ +/** Apparent γ(q) = k_B T / (A q² S(q)) from one shell, in mN/m. + * Equals the plateau γ only where q² S is flat (κ → 0). + */ static double ST_ShellGamma(double q, double S, double temperature, double area_A2) { double q2S = q * q * S; if (q2S <= 0.0) return ST_NaN(); @@ -630,8 +679,9 @@ static double ST_ShellGamma(double q, double S, double temperature, double area_ return 1000.0 * ST_KB * temperature / (area_m2 * q2S); } -/** Ordinary least-squares slope of log S vs log q on [qmin, qmax]. - * Ideal capillary waves give slope ≈ −2. Sfield selects S / Stop / Sbot. +/** OLS slope of ln S vs ln q on [q_min, q_max]. + * Pure capillary waves have S(q) ∝ q⁻², so the slope is −2. A slope + * near −4 is Helfrich-dominated. Sfield selects S / S_upper / S_lower. */ static double ST_LogSlope(std::vector const& shells, double qmin, double qmax, double ST_Shell::* Sfield) @@ -698,7 +748,7 @@ static int ST_CheckParentDir(DataFile* df, const char* key) { } // ----------------------------------------------------------------------------- -/// CONSTRUCTOR — defaults match the reference Python analysis. +/// CONSTRUCTOR — Willard–Chandler, nsurf 2, normal z; grid / σ match the Python. Action_SurfaceTension::Action_SurfaceTension() : iface_(WILLARD), normal_(AXIS_Z), @@ -742,6 +792,7 @@ Action_SurfaceTension::Action_SurfaceTension() : {} // Action_SurfaceTension::Help() +/** ASCII-only (terminals). Formulae live in the class header, not here. */ void Action_SurfaceTension::Help() const { mprintf("\t[] [mask2 ] temp \n" "\t[normal {x|y|z}] [nsurf {1|2}] [side {upper|lower}]\n" @@ -771,11 +822,12 @@ void Action_SurfaceTension::Help() const { // Action_SurfaceTension::Init() /** Parse keywords, allocate DataSets, attach optional output files. - * Spectrum / roughness DataSets always exist so writedata can dump them. - * Files are written only if the matching *out / *agr / *gnu keyword is given. - * *out uses the DataFile writer for the filename extension (canonical - * cpptraj: .agr/.xmgr = Grace/xmgrace, .gnu = gnuplot). agr/gnu keywords force - * DataFile::XMGRACE / GNUPLOT even when the extension is not recognized. + * Spectrum / roughness meshes always exist so writedata can dump them after + * Print() fills S(q). Files are written only if the matching *out / *agr / + * *gnu keyword is given. Parent directories are checked here: DataFiles + * open only after run, so a missing path would otherwise lose the write. + * out is an alias for spectrumout. agr/gnu force Grace / gnuplot. + * Contains() is called before getKey* so flags are not already consumed. */ Action::RetType Action_SurfaceTension::Init(ArgList& actionArgs, ActionInit& init, int debugIn) { @@ -1224,6 +1276,9 @@ Action::RetType Action_SurfaceTension::Init(ArgList& actionArgs, ActionInit& ini } // Action_SurfaceTension::Setup() +/** Require an orthorhombic unit cell (L₁, L₂, L_n) and bind the mask(s). + * Non-X-aligned boxes are warned: laterals are wrapped independently. + */ Action::RetType Action_SurfaceTension::Setup(ActionSetup& setup) { if (!setup.CoordInfo().HasBox()) { @@ -1253,6 +1308,11 @@ Action::RetType Action_SurfaceTension::Setup(ActionSetup& setup) } // Action_SurfaceTension::AllocateGrid() +/** First good frame: freeze N₁, N₂, L₁, L₂ and (Willard) N_n. + * Allocates ρ, h, |h_q|² accumulators, PubFFT plans, and q_α = 2π n_α / L_α. + * If q_min was omitted it is set to 2π / max(L₁, L₂). + * \return 0 OK, 1 fatal (FFT setup or q_max ≤ q_min). + */ int Action_SurfaceTension::AllocateGrid(int nx, int ny, int nz) { nx_ = nx; ny_ = ny; @@ -1322,6 +1382,7 @@ int Action_SurfaceTension::AllocateGrid(int nx, int ny, int nz) { return 0; } +/** Cap skip-frame warnings at 5, then one “further messages suppressed.” */ void Action_SurfaceTension::SkipWarn(const char* msg) { const int maxw = 5; @@ -1333,6 +1394,12 @@ void Action_SurfaceTension::SkipWarn(const char* msg) } // Action_SurfaceTension::WillardHeights() +/** Willard–Chandler heights from one atom set into the given density buffer. + * Histogram atoms onto N₁×N₂×N_n, convert to number density (Å⁻³), apply + * the periodic Gaussian, take ρ_bulk as the mid-slab lateral mean, then + * find the ±n crossings of θ ρ_bulk. Writes h_upper_ / h_lower_. + * \return 0 OK, 1 skip (no bulk bins, ρ_bulk ≤ 0, or a column has no crossing). + */ int Action_SurfaceTension::WillardHeights(std::vector const& t1, std::vector const& t2, std::vector const& ncoord, @@ -1500,10 +1567,11 @@ void Action_SurfaceTension::HeightPower(std::vector const& h, } // Action_SurfaceTension::ProcessFrame() -/** Wrap laterals, recenter along the normal, build instantaneous interfaces, - * then accumulate roughness and |h_q|². First good frame freezes nx, ny, - * Lt1, Lt2 (and nz for Willard–Chandler). Cartesian Lx/Ly/Lz are permuted - * into (Lt1, Lt2, Ln) according to normal_. +/** One NVT frame: permute → wrap / recenter → h(t1,t2) → w and |h_q|². + * First good frame freezes N₁, N₂, L₁, L₂ (and N_n for Willard). Later + * frames must keep the same lateral box (NVT). Combined power is summed + * over the surfaces actually used (nsurf 1 or 2). + * \return 0 OK, 1 skip frame, 2 fatal (grid or L₁, L₂ changed). */ int Action_SurfaceTension::ProcessFrame(Frame const& frm, double Lx, double Ly, double Lz) { @@ -1631,7 +1699,10 @@ int Action_SurfaceTension::ProcessFrame(Frame const& frm, double Lx, double Ly, } // Action_SurfaceTension::FinishBlock() -/** Average the open-block power, fit γ and κ, store roughness means, then reset. */ +/** Close one nblock window: S(q) = (Σ |h_q|²) / n_surfaces in the block, + * then the same CWT γ / κ fits as Print(). Incomplete final window is + * left in the running spectra but not written to blockout. + */ int Action_SurfaceTension::FinishBlock() { if (block_surface_count_ < 1 || block_frame_count_ < 1) return 0; std::vector spec(block_power_.size()); @@ -1670,6 +1741,10 @@ int Action_SurfaceTension::FinishBlock() { } // Action_SurfaceTension::DoAction() +/** Read the unit-cell lengths (or lx/ly/lz overrides) and ProcessFrame. + * Skip (Action::OK) if the box is missing or a crossing failed; ERR if + * the lateral grid changed (not NVT). + */ Action::RetType Action_SurfaceTension::DoAction(int, ActionFrame& frm) { if (!frm.Frm().BoxCrd().HasBox()) { @@ -1698,10 +1773,13 @@ Action::RetType Action_SurfaceTension::DoAction(int, ActionFrame& frm) #ifdef MPI // Action_SurfaceTension::SyncAction() -/** Radial-style reduction. Three small AllReduces (counts SUM, grid MAX, lateral - * box MAX) then one packed ReduceMaster SUM of combined/upper/lower |h_q|² onto - * the master. |q| uses a separate MAX (different MPI_Op). Print() is master - * only. Roughness / block series use DataSet::Sync (concat by rank). +/** Reduce per-rank |h_q|² so Print() sees the global S(q) = ⟨|h_q|²⟩. + * Counts (frames, surfaces, skipped) AllReduce SUM. Grid size, L₁, L₂, + * q_min, and q_fundamental AllReduce MAX so empty ranks (zeros) do not + * clobber. One packed ReduceMaster SUM of combined / upper / lower + * power; |q| is a separate MAX. Roughness and block series stay on + * DataSet::Sync (concat by rank). nblock is per-rank. Print() is master + * only. */ int Action_SurfaceTension::SyncAction() { if (trajComm_.Size() < 2) return 0; @@ -1770,7 +1848,11 @@ int Action_SurfaceTension::SyncAction() { #endif // Action_SurfaceTension::Print() -/** Average accumulated spectra, fill q-meshes, report γ / roughness / blocks. */ +/** Form S(q) = (Σ |h_q|²) / n_surfaces, shell-average, then the CWT fits + * γ = k_B T / (A ⟨q² S⟩) , 1/(q² S) = (A / k_B T) (γ + κ q²) + * Fill the q-meshes, print the numeric summary, and write summaryout. + * Per-block γ / κ are printed here, not during the frame loop. + */ void Action_SurfaceTension::Print() { const char* t1 = 0; From da306bd1f688972898286ed13f54f15b7c70e445 Mon Sep 17 00:00:00 2001 From: ndlevinzon Date: Mon, 31 Aug 2026 16:03:39 -0600 Subject: [PATCH 09/17] Add ST_Finite function to Action_SurfaceTension.cpp for finite number checks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Introduced a static inline function, ST_Finite, to determine if a given double value is finite (not NaN or ±Inf). - This addition enhances the robustness of numerical calculations by providing a utility for validating input values in surface tension computations. --- src/Action_SurfaceTension.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Action_SurfaceTension.cpp b/src/Action_SurfaceTension.cpp index 24d9e62e10..e7e53098f5 100644 --- a/src/Action_SurfaceTension.cpp +++ b/src/Action_SurfaceTension.cpp @@ -44,6 +44,7 @@ static const double ST_ANG2_TO_M2 = 1.0e-20; static const double ST_GAUSS_TRUNCATE = 4.0; /// \return true if x is finite (not NaN or ±Inf). Used to reject failed crossings. +static inline bool ST_Finite(double x) { return (x == x) && (x < std::numeric_limits::infinity()) && (x > -std::numeric_limits::infinity()); From c33271c1832defd1b00dfb129ef3be57214f1a3b Mon Sep 17 00:00:00 2001 From: ndlevinzon Date: Mon, 31 Aug 2026 16:05:10 -0600 Subject: [PATCH 10/17] Update variable name in Action_SurfaceTension.h for clarity MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Renamed 'q_fund_' to 'q_fundamental_' to better reflect its purpose as 2π / max(L₁, L₂) from the first good frame. - This change enhances code readability and maintains consistency in terminology. --- src/Action_SurfaceTension.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Action_SurfaceTension.h b/src/Action_SurfaceTension.h index e6aa2232ef..c07ba36d61 100644 --- a/src/Action_SurfaceTension.h +++ b/src/Action_SurfaceTension.h @@ -105,7 +105,7 @@ class Action_SurfaceTension : public Action { double threshold_frac_; double qmin_; double qmax_; - double q_fund_; ///< min(2π/Lt1, 2π/Lt2) from the first good frame + double q_fundamental_; ///< 2π / max(L₁, L₂) from the first good frame double lx_user_; double ly_user_; double lz_user_; From 3b4222b72af04db3d6984a9d82197f79e72c417c Mon Sep 17 00:00:00 2001 From: ndlevinzon Date: Mon, 31 Aug 2026 16:06:13 -0600 Subject: [PATCH 11/17] Initialize gamma and kappa variables in Action_SurfaceTension::Print for improved clarity - Updated the initialization of gamma and kappa variables to use ST_NaN() for better handling of uninitialized values. - This change enhances code readability and ensures that variables are explicitly set to a known state before use. --- src/Action_SurfaceTension.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/Action_SurfaceTension.cpp b/src/Action_SurfaceTension.cpp index e7e53098f5..129b8fb4b2 100644 --- a/src/Action_SurfaceTension.cpp +++ b/src/Action_SurfaceTension.cpp @@ -1902,9 +1902,9 @@ void Action_SurfaceTension::Print() // Fit γ on the combined, upper-only, and lower-only shells. double area = Lt1_ref_ * Lt2_ref_; - double gamma_full, plateau; - double gamma_top, plateau_top; - double gamma_bot, plateau_bot; + double gamma_full = ST_NaN(), plateau = ST_NaN(); + double gamma_top = ST_NaN(), plateau_top = ST_NaN(); + double gamma_bot = ST_NaN(), plateau_bot = ST_NaN(); std::vector top_only = shells; std::vector bot_only = shells; for (size_t i = 0; i < shells.size(); i++) { @@ -1919,7 +1919,9 @@ void Action_SurfaceTension::Print() err_bot = ST_CalcGamma(bot_only, temp_, area, qmin_, qmax_, gamma_bot, plateau_bot); (void)plateau_top; (void)plateau_bot; - double gamma_h, kappa_h, gamma_h_top, kappa_h_top, gamma_h_bot, kappa_h_bot; + double gamma_h = ST_NaN(), kappa_h = ST_NaN(); + double gamma_h_top = ST_NaN(), kappa_h_top = ST_NaN(); + double gamma_h_bot = ST_NaN(), kappa_h_bot = ST_NaN(); int err_kh = ST_CalcKappa(shells, temp_, area, qmin_, qmax_, gamma_h, kappa_h); int err_kh_top = 1, err_kh_bot = 1; if (do_upper_) From e0d85a687b6a4323d5b495fd7891be24be3de95f Mon Sep 17 00:00:00 2001 From: ndlevinzon Date: Mon, 31 Aug 2026 16:08:39 -0600 Subject: [PATCH 12/17] Add 'surftension' command to Command.cpp and ensure synchronization with Action_SurfaceTension.h - Introduced the 'surftension' command to maintain consistency with the Action_SurfaceTension.h file. - Added comments to clarify the need for synchronization due to the standalone Makefile's lack of header dependencies, preventing potential issues with stale object files. --- src/Command.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Command.cpp b/src/Command.cpp index b9435004e4..e15a1edee1 100644 --- a/src/Command.cpp +++ b/src/Command.cpp @@ -412,6 +412,8 @@ void Command::Init() { Command::AddCmd( new Action_STFC_Diffusion(),Cmd::ACT, 1, "stfcdiffusion" ); Command::AddCmd( new Action_Strip(), Cmd::ACT, 1, "strip" ); Command::AddCmd( new Action_Surf(), Cmd::ACT, 1, "surf" ); + // surftension: keep Command.cpp in sync with Action_SurfaceTension.h + // (standalone Makefile has no header deps; stale Command.o undersizes new). Command::AddCmd( new Action_SurfaceTension(),Cmd::ACT, 1, "surftension" ); Command::AddCmd( new Action_SymmetricRmsd(), Cmd::ACT, 1, "symmrmsd" ); Command::AddCmd( new Action_Temperature(), Cmd::ACT, 1, "temperature" ); From 954bde019721dc27d6ed60c7f1669a20013c8755 Mon Sep 17 00:00:00 2001 From: ndlevinzon Date: Wed, 2 Sep 2026 11:04:17 -0600 Subject: [PATCH 13/17] Update RunTest.sh for surftension tests with new input parameters and output files - Modified the script to use a cubic lattice of O atoms for testing surface tension. - Updated input files and commands for Willard-Chandler, ITIM, normal x, normal y, and nsurf 1 tests. - Added summary output files for each test case to enhance result tracking and analysis. - Removed obsolete smoke test sections to streamline the testing process. --- test/Test_SurfTension/RunTest.sh | 132 ++++++++++++++----------------- 1 file changed, 60 insertions(+), 72 deletions(-) mode change 100644 => 100755 test/Test_SurfTension/RunTest.sh diff --git a/test/Test_SurfTension/RunTest.sh b/test/Test_SurfTension/RunTest.sh old mode 100644 new mode 100755 index 20471fbe04..c8dd71549e --- a/test/Test_SurfTension/RunTest.sh +++ b/test/Test_SurfTension/RunTest.sh @@ -1,101 +1,89 @@ #!/bin/bash -# Smoke tests for the surftension Action. -# tz2.ortho is a solvated protein box, not a liquid slab, so the 1-frame run -# only checks that Init/Setup do not crash. Numeric γ comparison needs a -# dedicated slab trajectory. +# surftension tests. +# slab.pdb is a 20 A cubic lattice of O atoms. Stretching one box length +# creates vacuum on both sides of a slab so Willard/ITIM can find interfaces. . ../MasterTest.sh -CleanFiles st.in st.summary.dat +CleanFiles st.in st.willard.dat st.itim.dat st.normalx.dat st.normaly.dat \ + st.nsurf1.dat st2_summary.dat TESTNAME='Surface tension (surftension) tests' -# Command is registered and Help() prints. -UNITNAME='surftension help' -cat > st.in < st.in < st.in < st.in < st.in < st.in < st.in < st.in < st.in < st.in < st.in < st.in < st.in < Date: Wed, 2 Sep 2026 11:04:25 -0600 Subject: [PATCH 14/17] Enhance 'surftension' command with output file prefix support and documentation updates - Added 'fprefix' parameter to prepend a specified prefix to output file names, allowing for better organization of results. - Updated documentation in Action_SurfaceTension and ChangeLog to reflect the new 'fprefix' functionality and its usage. - Improved error handling for parent directory checks to ensure output files are correctly managed during execution. --- doc/ChangeLog.v7.md | 8 +- doc/DocumentChecksums.txt | 2 +- doc/cpptraj.bib | 51 + doc/cpptraj.lyx | 284 +++++- src/Action_SurfaceTension.cpp | 62 +- test/Test_SurfTension/slab.pdb | 1003 ++++++++++++++++++++ test/Test_SurfTension/st.itim.dat.save | 17 + test/Test_SurfTension/st.normalx.dat.save | 20 + test/Test_SurfTension/st.normaly.dat.save | 20 + test/Test_SurfTension/st.nsurf1.dat.save | 18 + test/Test_SurfTension/st.willard.dat.save | 20 + test/Test_SurfTension/st2_summary.dat.save | 21 + 12 files changed, 1504 insertions(+), 22 deletions(-) create mode 100644 test/Test_SurfTension/slab.pdb create mode 100644 test/Test_SurfTension/st.itim.dat.save create mode 100644 test/Test_SurfTension/st.normalx.dat.save create mode 100644 test/Test_SurfTension/st.normaly.dat.save create mode 100644 test/Test_SurfTension/st.nsurf1.dat.save create mode 100644 test/Test_SurfTension/st.willard.dat.save create mode 100644 test/Test_SurfTension/st2_summary.dat.save diff --git a/doc/ChangeLog.v7.md b/doc/ChangeLog.v7.md index 1fe3d45a16..805ea3fb40 100644 --- a/doc/ChangeLog.v7.md +++ b/doc/ChangeLog.v7.md @@ -26,9 +26,9 @@ New Commands 2π/max(Lt1,Lt2) from the first frame. `blocktime` (ps) with `dt` sets `nblock`. Optional outputs (`spectrumout`, `roughout`, `blockout`, `summaryout`) follow the filename extension (`.agr`/`.xmgr` = xmgrace, `.gnu` = gnuplot). Dedicated - `*agr`/`*gnu` keywords force Grace or gnuplot. Parent directories must already - exist. MPI-parallel (packed spectral SUM to the master). Assumes NVT (fixed - lateral box lengths). + `*agr`/`*gnu` keywords force Grace or gnuplot. `fprefix` is prepended to each + of those file names. Parent directories must already exist. MPI-parallel + (packed spectral SUM to the master). Assumes NVT (fixed lateral box lengths). ``` surftension [] [mask2 ] temp @@ -38,7 +38,7 @@ surftension [] [mask2 ] temp [sigmaxy ] [sigmaz | sigmanormal ] [bulkhalfwidth ] [threshold ] [qmin ] [qmax ] [lx ] [ly ] [lz ] - [nblock ] [dt ] [blocktime ] + [nblock ] [dt ] [blocktime ] [fprefix ] [out | spectrumout ] [roughout ] [blockout ] [summaryout ] [spectrumagr ] [roughagr ] [blockagr ] diff --git a/doc/DocumentChecksums.txt b/doc/DocumentChecksums.txt index bb2f2a27e3..8b4d27854e 100644 --- a/doc/DocumentChecksums.txt +++ b/doc/DocumentChecksums.txt @@ -1,3 +1,3 @@ f6f8cb1a79951d80a9d2656fd9c30f55 CpptrajDevelopmentGuide.lyx -8ba86aca8b37cdcb5b01ef05141e5dce cpptraj.lyx +f7837faf109fc9c36db4e0274ff6d92f cpptraj.lyx 5d9b5b5ed47a3ded57b6464df99b3585 CpptrajManual.lyx diff --git a/doc/cpptraj.bib b/doc/cpptraj.bib index 96e77b003d..0de9ba5b89 100644 --- a/doc/cpptraj.bib +++ b/doc/cpptraj.bib @@ -470,3 +470,54 @@ @article{Noe2016 doi = {10.1021/acs.jctc.6b00762}, URL = { https://doi.org/10.1021/acs.jctc.6b00762 }, } + +@Article{Willard10, + author = {Willard, A. P. and Chandler, D.}, + title = {{Instantaneous Liquid Interfaces}}, + journal = {J. Phys. Chem. B}, + volume = {114}, + pages = {1954-1958}, + year = {2010}, + doi = {10.1021/jp909219k} +} + +@Article{Partay08, + author = {P{\'a}rtay, L. B. and Hantal, G. and Jedlovszky, P. and Vincze, {\'A}. and Horvai, G.}, + title = {{A new method for determining the interfacial molecules and characterizing the surface roughness in computer simulations. + Application to the liquid--vapor interface of water}}, + journal = {J. Comput. Chem.}, + volume = {29}, + pages = {945-956}, + year = {2008}, + doi = {10.1002/jcc.20852} +} + +@Article{Buff65, + author = {Buff, F. P. and Lovett, R. A. and Stillinger, F. H.}, + title = {{Interfacial Density Profile for Fluids in the Critical Region}}, + journal = {Phys. Rev. Lett.}, + volume = {15}, + pages = {621-623}, + year = {1965}, + doi = {10.1103/PhysRevLett.15.621} +} + +@Article{Sides99, + author = {Sides, S. W. and Grest, G. S. and Lacasse, M.-D.}, + title = {{Capillary waves at liquid-vapor interfaces: A molecular dynamics simulation}}, + journal = {Phys. Rev. E}, + volume = {60}, + pages = {6708-6713}, + year = {1999}, + doi = {10.1103/PhysRevE.60.6708} +} + +@Article{Helfrich73, + author = {Helfrich, W.}, + title = {{Elastic Properties of Lipid Bilayers: Theory and Possible Experiments}}, + journal = {Z. Naturforsch. C}, + volume = {28}, + pages = {693-703}, + year = {1973}, + doi = {10.1515/znc-1973-11-1209} +} diff --git a/doc/cpptraj.lyx b/doc/cpptraj.lyx index a750220c87..2c86d02116 100644 --- a/doc/cpptraj.lyx +++ b/doc/cpptraj.lyx @@ -1349,6 +1349,10 @@ spam surf \end_layout +\begin_layout LyX-Code +surftension (3-D Gaussian filter only) +\end_layout + \begin_layout LyX-Code tordiff \end_layout @@ -22656,7 +22660,7 @@ Mod \begin_layout Standard \align center \begin_inset Tabular - + @@ -25031,6 +25035,35 @@ Calculate the LCPO surface area of specified atoms. \begin_inset Text +\begin_layout Plain Layout +surftension +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +Calculate capillary-wave surface tension of a liquid slab. +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\end_layout + +\end_inset + + + + +\begin_inset Text + \begin_layout Plain Layout symmrmsd \end_layout @@ -44795,6 +44828,255 @@ surf out surf.dat surf :1 out surf.dat \end_layout +\begin_layout Subsection +surftension +\begin_inset CommandInset label +LatexCommand label +name "subsec:cpptraj_surftension" + +\end_inset + + +\end_layout + +\begin_layout LyX-Code +surftension +\begin_inset Index idx +range none +pageformat default +status collapsed + +\begin_layout Plain Layout +surftension +\end_layout + +\end_inset + + [] [mask2 ] temp +\end_layout + +\begin_layout LyX-Code + [normal {x|y|z}] [nsurf {1|2}] [side {upper|lower}] +\end_layout + +\begin_layout LyX-Code + [interface {willard|itim}] +\end_layout + +\begin_layout LyX-Code + [gridspacing ] [dz | dnormal ] +\end_layout + +\begin_layout LyX-Code + [sigmaxy ] [sigmaz | sigmanormal ] +\end_layout + +\begin_layout LyX-Code + [bulkhalfwidth ] [threshold ] +\end_layout + +\begin_layout LyX-Code + [qmin ] [qmax ] [lx ] [ly ] [lz ] +\end_layout + +\begin_layout LyX-Code + [nblock ] [dt ] [blocktime ] [fprefix ] +\end_layout + +\begin_layout LyX-Code + [out | spectrumout ] [roughout ] [blockout ] +\end_layout + +\begin_layout LyX-Code + [summaryout ] +\end_layout + +\begin_layout LyX-Code + [spectrumagr ] [roughagr ] [blockagr ] +\end_layout + +\begin_layout LyX-Code + [spectrumgnu ] [roughgnu ] [blockgnu ] +\begin_inset Separator latexpar +\end_inset + + +\end_layout + +\begin_deeper +\begin_layout Description + Output data set name. +\end_layout + +\begin_layout Description + Atoms used to build the instantaneous interface (typically heavy atoms of the liquid, e.g. + :WAT@O). +\end_layout + +\begin_layout Description +mask2 +\begin_inset space ~ +\end_inset + + Optional atoms for the lower surface (leaflet or second liquid). + The upper surface then comes from with no mid-box split. + Both masks share one circular recenter. +\end_layout + +\begin_layout Description +temp +\begin_inset space ~ +\end_inset + + Temperature in K (required). +\end_layout + +\begin_layout Description +normal +\begin_inset space ~ +\end_inset + +{x|y|z} Cartesian slab normal (default z). + The other two axes span the interface plane. +\end_layout + +\begin_layout Description +nsurf +\begin_inset space ~ +\end_inset + +{1|2} Number of interfaces (default 2). + Use 2 for a film with vacuum or a second phase on both sides. +\end_layout + +\begin_layout Description +side +\begin_inset space ~ +\end_inset + +{upper|lower} Which interface when nsurf is 1 (default upper). +\end_layout + +\begin_layout Description +interface +\begin_inset space ~ +\end_inset + +{willard|itim} Instantaneous interface: Willard–Chandler density isosurface (default) or ITIM per-column min/max. +\end_layout + +\begin_layout Description +gridspacing +\begin_inset space ~ +\end_inset + + Lateral histogram spacing in Ang. + (default 2.5). +\end_layout + +\begin_layout Description +dz / dnormal +\begin_inset space ~ +\end_inset + + Bin spacing along the normal for Willard–Chandler (default 1.0). +\end_layout + +\begin_layout Description +sigmaxy / sigmaz / sigmanormal +\begin_inset space ~ +\end_inset + +Gaussian widths in Ang. + for the Willard–Chandler density (defaults 2.5 and 1.5). +\end_layout + +\begin_layout Description +qmin / qmax +\begin_inset space ~ +\end_inset + +Fit window in Ang. +^-1. + If qmin is omitted it is 2*pi/max(L1,L2) from the first good frame. +\end_layout + +\begin_layout Description +lx / ly / lz +\begin_inset space ~ +\end_inset + +Override Cartesian box lengths (NVT slabs with noisy box records). +\end_layout + +\begin_layout Description +nblock / dt / blocktime +\begin_inset space ~ +\end_inset + +Block averaging. + blocktime (ps) with dt (analyzed-frame spacing, ps) sets nblock. +\end_layout + +\begin_layout Description +fprefix +\begin_inset space ~ +\end_inset + + Prepended to each output file basename (directory unchanged) so multiple runs can share a directory. +\end_layout + +\begin_layout Description +out / spectrumout / roughout / blockout / summaryout +\begin_inset space ~ +\end_inset + +Optional output files. + out is an alias for spectrumout. + Parent directories must already exist. +\end_layout + +\begin_layout Description +*agr / *gnu +\begin_inset space ~ +\end_inset + +Force Grace or gnuplot format for spectrum, roughness, or block files. +\end_layout + +\end_deeper +\begin_layout Standard +Calculate the capillary-wave surface tension of a liquid slab from height fluctuations of instantaneous interfaces +\begin_inset CommandInset citation +LatexCommand citep +key "Buff65,Sides99,Willard10,Partay08,Helfrich73" +literal "true" + +\end_inset + +. + Frames are recentered so the film sits at mid-box along the chosen normal. + The default interface is a Willard–Chandler isosurface of a Gaussian-smoothed number-density field; + interface itim uses per-column min/max of (probe radius to 0). + The height field is Fourier transformed (numpy fft2 convention), shell-averaged to S(q), and gamma (mN/m) is taken from the small-q plateau of q^2 S(q). + A Helfrich fit of 1/(q^2 S) vs q^2 on the same window gives kappa in kT. + The trajectory is assumed NVT (fixed lateral box lengths). + The 3-D Gaussian filter is OpenMP-parallel. +\end_layout + +\begin_layout Standard +For example, + to analyze a water slab with vacuum along z: +\end_layout + +\begin_layout LyX-Code +surftension :WAT@O temp 300 qmax 0.30 summaryout st.summary.dat +\end_layout + +\begin_layout LyX-Code + spectrumout st.spectrum.dat roughout st.rough.dat +\end_layout + \begin_layout Subsection symmrmsd \begin_inset CommandInset label diff --git a/src/Action_SurfaceTension.cpp b/src/Action_SurfaceTension.cpp index 129b8fb4b2..703dd8c2e6 100644 --- a/src/Action_SurfaceTension.cpp +++ b/src/Action_SurfaceTension.cpp @@ -731,13 +731,21 @@ static void ST_SummaryS(CpptrajFile* f, const char* key, const char* v) { f->Printf("%s %s\n", key, v); } +/** Prepend fprefix to the basename; directory is unchanged. Empty name stays empty. */ +static FileName ST_OutName(std::string const& name, std::string const& prefix) { + if (name.empty()) return FileName(); + FileName fn(name); + if (prefix.empty()) return fn; + return fn.PrependFileName(prefix); +} + /** DataFiles are opened only at the end of the run. Fail at Init if the * parent directory is missing so a long trajectory is not processed only * to lose the write. */ -static int ST_CheckParentDir(DataFile* df, const char* key) { - if (df == 0) return 0; - std::string dir = df->DataFilename().DirPrefix_NoSlash(); +static int ST_CheckParentDir(FileName const& fn, const char* key) { + if (fn.empty()) return 0; + std::string dir = fn.DirPrefix_NoSlash(); if (dir.empty()) return 0; struct stat st; if (stat(dir.c_str(), &st) != 0) { @@ -748,6 +756,11 @@ static int ST_CheckParentDir(DataFile* df, const char* key) { return 0; } +static int ST_CheckParentDir(DataFile* df, const char* key) { + if (df == 0) return 0; + return ST_CheckParentDir(df->DataFilename(), key); +} + // ----------------------------------------------------------------------------- /// CONSTRUCTOR — Willard–Chandler, nsurf 2, normal z; grid / σ match the Python. Action_SurfaceTension::Action_SurfaceTension() : @@ -802,7 +815,7 @@ void Action_SurfaceTension::Help() const { "\t[sigmaxy ] [sigmaz | sigmanormal ]\n" "\t[bulkhalfwidth ] [threshold ]\n" "\t[qmin ] [qmax ] [lx ] [ly ] [lz ]\n" - "\t[nblock ] [dt ] [blocktime ]\n" + "\t[nblock ] [dt ] [blocktime ] [fprefix ]\n" "\t[out | spectrumout ] [roughout ] [blockout ]\n" "\t[summaryout ]\n" "\t[spectrumagr ] [roughagr ] [blockagr ]\n" @@ -818,6 +831,8 @@ void Action_SurfaceTension::Help() const { " blocktime (ps) with dt (analyzed-frame spacing, ps) sets nblock.\n" " out is an alias for spectrumout. Write to the current directory,\n" " e.g. spectrumout spec.dat roughout rough.dat blockout blocks.dat.\n" + " fprefix is prepended to each of those file names (directory unchanged),\n" + " e.g. fprefix 150K_ spectrumout spec.dat writes 150K_spec.dat.\n" " A directory in the name must already exist; it is not created.\n"); } @@ -838,6 +853,8 @@ Action::RetType Action_SurfaceTension::Init(ArgList& actionArgs, ActionInit& ini debug_ = debugIn; // Optional output files. AddDataFile returns 0 if the keyword is absent. // out == spectrumout (usual cpptraj keyword for the main result file). + // fprefix is prepended to each basename so multiple runs can share a directory. + std::string fprefix = actionArgs.GetStringKey("fprefix"); bool has_spectrumout = actionArgs.Contains("spectrumout"); bool has_out = actionArgs.Contains("out"); std::string specname = actionArgs.GetStringKey("spectrumout"); @@ -849,21 +866,32 @@ Action::RetType Action_SurfaceTension::Init(ArgList& actionArgs, ActionInit& ini if (specname.empty()) specname = outname; bool has_summaryout = actionArgs.Contains("summaryout"); - std::string sumname = actionArgs.GetStringKey("summaryout"); - DataFile* spectrumFile = init.DFL().AddDataFile(specname, actionArgs); - DataFile* roughFile = init.DFL().AddDataFile(actionArgs.GetStringKey("roughout"), actionArgs); - DataFile* blockFile = init.DFL().AddDataFile(actionArgs.GetStringKey("blockout"), actionArgs); - DataFile* spectrumAgr = init.DFL().AddDataFile(actionArgs.GetStringKey("spectrumagr"), actionArgs, DataFile::XMGRACE); - DataFile* roughAgr = init.DFL().AddDataFile(actionArgs.GetStringKey("roughagr"), actionArgs, DataFile::XMGRACE); - DataFile* blockAgr = init.DFL().AddDataFile(actionArgs.GetStringKey("blockagr"), actionArgs, DataFile::XMGRACE); - DataFile* spectrumGnu = init.DFL().AddDataFile(actionArgs.GetStringKey("spectrumgnu"), actionArgs, DataFile::GNUPLOT); - DataFile* roughGnu = init.DFL().AddDataFile(actionArgs.GetStringKey("roughgnu"), actionArgs, DataFile::GNUPLOT); - DataFile* blockGnu = init.DFL().AddDataFile(actionArgs.GetStringKey("blockgnu"), actionArgs, DataFile::GNUPLOT); - summaryFile_ = init.DFL().AddCpptrajFile(sumname, "SurfTension summary"); + FileName specFileName = ST_OutName(specname, fprefix); + FileName roughName = ST_OutName(actionArgs.GetStringKey("roughout"), fprefix); + FileName blockName = ST_OutName(actionArgs.GetStringKey("blockout"), fprefix); + FileName specAgrName = ST_OutName(actionArgs.GetStringKey("spectrumagr"), fprefix); + FileName roughAgrName = ST_OutName(actionArgs.GetStringKey("roughagr"), fprefix); + FileName blockAgrName = ST_OutName(actionArgs.GetStringKey("blockagr"), fprefix); + FileName specGnuName = ST_OutName(actionArgs.GetStringKey("spectrumgnu"), fprefix); + FileName roughGnuName = ST_OutName(actionArgs.GetStringKey("roughgnu"), fprefix); + FileName blockGnuName = ST_OutName(actionArgs.GetStringKey("blockgnu"), fprefix); + FileName sumName = ST_OutName(actionArgs.GetStringKey("summaryout"), fprefix); + DataFile* spectrumFile = init.DFL().AddDataFile(specFileName, actionArgs); + DataFile* roughFile = init.DFL().AddDataFile(roughName, actionArgs); + DataFile* blockFile = init.DFL().AddDataFile(blockName, actionArgs); + DataFile* spectrumAgr = init.DFL().AddDataFile(specAgrName, actionArgs, DataFile::XMGRACE); + DataFile* roughAgr = init.DFL().AddDataFile(roughAgrName, actionArgs, DataFile::XMGRACE); + DataFile* blockAgr = init.DFL().AddDataFile(blockAgrName, actionArgs, DataFile::XMGRACE); + DataFile* spectrumGnu = init.DFL().AddDataFile(specGnuName, actionArgs, DataFile::GNUPLOT); + DataFile* roughGnu = init.DFL().AddDataFile(roughGnuName, actionArgs, DataFile::GNUPLOT); + DataFile* blockGnu = init.DFL().AddDataFile(blockGnuName, actionArgs, DataFile::GNUPLOT); + summaryFile_ = init.DFL().AddCpptrajFile(sumName, "SurfTension summary"); if (has_summaryout && summaryFile_ == 0) { - mprinterr("Error: Could not open summaryout '%s'.\n", sumname.c_str()); + mprinterr("Error: Could not open summaryout '%s'.\n", sumName.full()); return Action::ERR; } + if (ST_CheckParentDir(sumName, "summaryout")) + return Action::ERR; if (ST_CheckParentDir(spectrumFile, "spectrumout") || ST_CheckParentDir(roughFile, "roughout") || ST_CheckParentDir(blockFile, "blockout") || @@ -1207,6 +1235,8 @@ Action::RetType Action_SurfaceTension::Init(ArgList& actionArgs, ActionInit& ini qmax_); mprintf("\tHelfrich kappa: linear fit of 1/(q^2 S) vs q^2 on that window.\n"); mprintf("\tHeight-field 2-D FFT: PubFFT (numpy fft2 / (nx*ny)).\n"); + if (!fprefix.empty()) + mprintf("\tOutput file prefix: '%s'\n", fprefix.c_str()); if (lx_user_ > 0.0) mprintf("\tUsing fixed Lx= %g Ang (%s)\n", lx_user_, (normal_ == AXIS_X) ? "normal" : "lateral"); diff --git a/test/Test_SurfTension/slab.pdb b/test/Test_SurfTension/slab.pdb new file mode 100644 index 0000000000..569238ab15 --- /dev/null +++ b/test/Test_SurfTension/slab.pdb @@ -0,0 +1,1003 @@ +CRYST1 20.000 20.000 20.000 90.00 90.00 90.00 P 1 1 +REMARK synthetic cubic lattice for surftension tests +ATOM 1 O WAT 1 1.000 1.000 1.000 1.00 0.00 O +ATOM 2 O WAT 2 1.000 1.000 3.000 1.00 0.00 O +ATOM 3 O WAT 3 1.000 1.000 5.000 1.00 0.00 O +ATOM 4 O WAT 4 1.000 1.000 7.000 1.00 0.00 O +ATOM 5 O WAT 5 1.000 1.000 9.000 1.00 0.00 O +ATOM 6 O WAT 6 1.000 1.000 11.000 1.00 0.00 O +ATOM 7 O WAT 7 1.000 1.000 13.000 1.00 0.00 O +ATOM 8 O WAT 8 1.000 1.000 15.000 1.00 0.00 O +ATOM 9 O WAT 9 1.000 1.000 17.000 1.00 0.00 O +ATOM 10 O WAT 10 1.000 1.000 19.000 1.00 0.00 O +ATOM 11 O WAT 11 1.000 3.000 1.000 1.00 0.00 O +ATOM 12 O WAT 12 1.000 3.000 3.000 1.00 0.00 O +ATOM 13 O WAT 13 1.000 3.000 5.000 1.00 0.00 O +ATOM 14 O WAT 14 1.000 3.000 7.000 1.00 0.00 O +ATOM 15 O WAT 15 1.000 3.000 9.000 1.00 0.00 O +ATOM 16 O WAT 16 1.000 3.000 11.000 1.00 0.00 O +ATOM 17 O WAT 17 1.000 3.000 13.000 1.00 0.00 O +ATOM 18 O WAT 18 1.000 3.000 15.000 1.00 0.00 O +ATOM 19 O WAT 19 1.000 3.000 17.000 1.00 0.00 O +ATOM 20 O WAT 20 1.000 3.000 19.000 1.00 0.00 O +ATOM 21 O WAT 21 1.000 5.000 1.000 1.00 0.00 O +ATOM 22 O WAT 22 1.000 5.000 3.000 1.00 0.00 O +ATOM 23 O WAT 23 1.000 5.000 5.000 1.00 0.00 O +ATOM 24 O WAT 24 1.000 5.000 7.000 1.00 0.00 O +ATOM 25 O WAT 25 1.000 5.000 9.000 1.00 0.00 O +ATOM 26 O WAT 26 1.000 5.000 11.000 1.00 0.00 O +ATOM 27 O WAT 27 1.000 5.000 13.000 1.00 0.00 O +ATOM 28 O WAT 28 1.000 5.000 15.000 1.00 0.00 O +ATOM 29 O WAT 29 1.000 5.000 17.000 1.00 0.00 O +ATOM 30 O WAT 30 1.000 5.000 19.000 1.00 0.00 O +ATOM 31 O WAT 31 1.000 7.000 1.000 1.00 0.00 O +ATOM 32 O WAT 32 1.000 7.000 3.000 1.00 0.00 O +ATOM 33 O WAT 33 1.000 7.000 5.000 1.00 0.00 O +ATOM 34 O WAT 34 1.000 7.000 7.000 1.00 0.00 O +ATOM 35 O WAT 35 1.000 7.000 9.000 1.00 0.00 O +ATOM 36 O WAT 36 1.000 7.000 11.000 1.00 0.00 O +ATOM 37 O WAT 37 1.000 7.000 13.000 1.00 0.00 O +ATOM 38 O WAT 38 1.000 7.000 15.000 1.00 0.00 O +ATOM 39 O WAT 39 1.000 7.000 17.000 1.00 0.00 O +ATOM 40 O WAT 40 1.000 7.000 19.000 1.00 0.00 O +ATOM 41 O WAT 41 1.000 9.000 1.000 1.00 0.00 O +ATOM 42 O WAT 42 1.000 9.000 3.000 1.00 0.00 O +ATOM 43 O WAT 43 1.000 9.000 5.000 1.00 0.00 O +ATOM 44 O WAT 44 1.000 9.000 7.000 1.00 0.00 O +ATOM 45 O WAT 45 1.000 9.000 9.000 1.00 0.00 O +ATOM 46 O WAT 46 1.000 9.000 11.000 1.00 0.00 O +ATOM 47 O WAT 47 1.000 9.000 13.000 1.00 0.00 O +ATOM 48 O WAT 48 1.000 9.000 15.000 1.00 0.00 O +ATOM 49 O WAT 49 1.000 9.000 17.000 1.00 0.00 O +ATOM 50 O WAT 50 1.000 9.000 19.000 1.00 0.00 O +ATOM 51 O WAT 51 1.000 11.000 1.000 1.00 0.00 O +ATOM 52 O WAT 52 1.000 11.000 3.000 1.00 0.00 O +ATOM 53 O WAT 53 1.000 11.000 5.000 1.00 0.00 O +ATOM 54 O WAT 54 1.000 11.000 7.000 1.00 0.00 O +ATOM 55 O WAT 55 1.000 11.000 9.000 1.00 0.00 O +ATOM 56 O WAT 56 1.000 11.000 11.000 1.00 0.00 O +ATOM 57 O WAT 57 1.000 11.000 13.000 1.00 0.00 O +ATOM 58 O WAT 58 1.000 11.000 15.000 1.00 0.00 O +ATOM 59 O WAT 59 1.000 11.000 17.000 1.00 0.00 O +ATOM 60 O WAT 60 1.000 11.000 19.000 1.00 0.00 O +ATOM 61 O WAT 61 1.000 13.000 1.000 1.00 0.00 O +ATOM 62 O WAT 62 1.000 13.000 3.000 1.00 0.00 O +ATOM 63 O WAT 63 1.000 13.000 5.000 1.00 0.00 O +ATOM 64 O WAT 64 1.000 13.000 7.000 1.00 0.00 O +ATOM 65 O WAT 65 1.000 13.000 9.000 1.00 0.00 O +ATOM 66 O WAT 66 1.000 13.000 11.000 1.00 0.00 O +ATOM 67 O WAT 67 1.000 13.000 13.000 1.00 0.00 O +ATOM 68 O WAT 68 1.000 13.000 15.000 1.00 0.00 O +ATOM 69 O WAT 69 1.000 13.000 17.000 1.00 0.00 O +ATOM 70 O WAT 70 1.000 13.000 19.000 1.00 0.00 O +ATOM 71 O WAT 71 1.000 15.000 1.000 1.00 0.00 O +ATOM 72 O WAT 72 1.000 15.000 3.000 1.00 0.00 O +ATOM 73 O WAT 73 1.000 15.000 5.000 1.00 0.00 O +ATOM 74 O WAT 74 1.000 15.000 7.000 1.00 0.00 O +ATOM 75 O WAT 75 1.000 15.000 9.000 1.00 0.00 O +ATOM 76 O WAT 76 1.000 15.000 11.000 1.00 0.00 O +ATOM 77 O WAT 77 1.000 15.000 13.000 1.00 0.00 O +ATOM 78 O WAT 78 1.000 15.000 15.000 1.00 0.00 O +ATOM 79 O WAT 79 1.000 15.000 17.000 1.00 0.00 O +ATOM 80 O WAT 80 1.000 15.000 19.000 1.00 0.00 O +ATOM 81 O WAT 81 1.000 17.000 1.000 1.00 0.00 O +ATOM 82 O WAT 82 1.000 17.000 3.000 1.00 0.00 O +ATOM 83 O WAT 83 1.000 17.000 5.000 1.00 0.00 O +ATOM 84 O WAT 84 1.000 17.000 7.000 1.00 0.00 O +ATOM 85 O WAT 85 1.000 17.000 9.000 1.00 0.00 O +ATOM 86 O WAT 86 1.000 17.000 11.000 1.00 0.00 O +ATOM 87 O WAT 87 1.000 17.000 13.000 1.00 0.00 O +ATOM 88 O WAT 88 1.000 17.000 15.000 1.00 0.00 O +ATOM 89 O WAT 89 1.000 17.000 17.000 1.00 0.00 O +ATOM 90 O WAT 90 1.000 17.000 19.000 1.00 0.00 O +ATOM 91 O WAT 91 1.000 19.000 1.000 1.00 0.00 O +ATOM 92 O WAT 92 1.000 19.000 3.000 1.00 0.00 O +ATOM 93 O WAT 93 1.000 19.000 5.000 1.00 0.00 O +ATOM 94 O WAT 94 1.000 19.000 7.000 1.00 0.00 O +ATOM 95 O WAT 95 1.000 19.000 9.000 1.00 0.00 O +ATOM 96 O WAT 96 1.000 19.000 11.000 1.00 0.00 O +ATOM 97 O WAT 97 1.000 19.000 13.000 1.00 0.00 O +ATOM 98 O WAT 98 1.000 19.000 15.000 1.00 0.00 O +ATOM 99 O WAT 99 1.000 19.000 17.000 1.00 0.00 O +ATOM 100 O WAT 100 1.000 19.000 19.000 1.00 0.00 O +ATOM 101 O WAT 101 3.000 1.000 1.000 1.00 0.00 O +ATOM 102 O WAT 102 3.000 1.000 3.000 1.00 0.00 O +ATOM 103 O WAT 103 3.000 1.000 5.000 1.00 0.00 O +ATOM 104 O WAT 104 3.000 1.000 7.000 1.00 0.00 O +ATOM 105 O WAT 105 3.000 1.000 9.000 1.00 0.00 O +ATOM 106 O WAT 106 3.000 1.000 11.000 1.00 0.00 O +ATOM 107 O WAT 107 3.000 1.000 13.000 1.00 0.00 O +ATOM 108 O WAT 108 3.000 1.000 15.000 1.00 0.00 O +ATOM 109 O WAT 109 3.000 1.000 17.000 1.00 0.00 O +ATOM 110 O WAT 110 3.000 1.000 19.000 1.00 0.00 O +ATOM 111 O WAT 111 3.000 3.000 1.000 1.00 0.00 O +ATOM 112 O WAT 112 3.000 3.000 3.000 1.00 0.00 O +ATOM 113 O WAT 113 3.000 3.000 5.000 1.00 0.00 O +ATOM 114 O WAT 114 3.000 3.000 7.000 1.00 0.00 O +ATOM 115 O WAT 115 3.000 3.000 9.000 1.00 0.00 O +ATOM 116 O WAT 116 3.000 3.000 11.000 1.00 0.00 O +ATOM 117 O WAT 117 3.000 3.000 13.000 1.00 0.00 O +ATOM 118 O WAT 118 3.000 3.000 15.000 1.00 0.00 O +ATOM 119 O WAT 119 3.000 3.000 17.000 1.00 0.00 O +ATOM 120 O WAT 120 3.000 3.000 19.000 1.00 0.00 O +ATOM 121 O WAT 121 3.000 5.000 1.000 1.00 0.00 O +ATOM 122 O WAT 122 3.000 5.000 3.000 1.00 0.00 O +ATOM 123 O WAT 123 3.000 5.000 5.000 1.00 0.00 O +ATOM 124 O WAT 124 3.000 5.000 7.000 1.00 0.00 O +ATOM 125 O WAT 125 3.000 5.000 9.000 1.00 0.00 O +ATOM 126 O WAT 126 3.000 5.000 11.000 1.00 0.00 O +ATOM 127 O WAT 127 3.000 5.000 13.000 1.00 0.00 O +ATOM 128 O WAT 128 3.000 5.000 15.000 1.00 0.00 O +ATOM 129 O WAT 129 3.000 5.000 17.000 1.00 0.00 O +ATOM 130 O WAT 130 3.000 5.000 19.000 1.00 0.00 O +ATOM 131 O WAT 131 3.000 7.000 1.000 1.00 0.00 O +ATOM 132 O WAT 132 3.000 7.000 3.000 1.00 0.00 O +ATOM 133 O WAT 133 3.000 7.000 5.000 1.00 0.00 O +ATOM 134 O WAT 134 3.000 7.000 7.000 1.00 0.00 O +ATOM 135 O WAT 135 3.000 7.000 9.000 1.00 0.00 O +ATOM 136 O WAT 136 3.000 7.000 11.000 1.00 0.00 O +ATOM 137 O WAT 137 3.000 7.000 13.000 1.00 0.00 O +ATOM 138 O WAT 138 3.000 7.000 15.000 1.00 0.00 O +ATOM 139 O WAT 139 3.000 7.000 17.000 1.00 0.00 O +ATOM 140 O WAT 140 3.000 7.000 19.000 1.00 0.00 O +ATOM 141 O WAT 141 3.000 9.000 1.000 1.00 0.00 O +ATOM 142 O WAT 142 3.000 9.000 3.000 1.00 0.00 O +ATOM 143 O WAT 143 3.000 9.000 5.000 1.00 0.00 O +ATOM 144 O WAT 144 3.000 9.000 7.000 1.00 0.00 O +ATOM 145 O WAT 145 3.000 9.000 9.000 1.00 0.00 O +ATOM 146 O WAT 146 3.000 9.000 11.000 1.00 0.00 O +ATOM 147 O WAT 147 3.000 9.000 13.000 1.00 0.00 O +ATOM 148 O WAT 148 3.000 9.000 15.000 1.00 0.00 O +ATOM 149 O WAT 149 3.000 9.000 17.000 1.00 0.00 O +ATOM 150 O WAT 150 3.000 9.000 19.000 1.00 0.00 O +ATOM 151 O WAT 151 3.000 11.000 1.000 1.00 0.00 O +ATOM 152 O WAT 152 3.000 11.000 3.000 1.00 0.00 O +ATOM 153 O WAT 153 3.000 11.000 5.000 1.00 0.00 O +ATOM 154 O WAT 154 3.000 11.000 7.000 1.00 0.00 O +ATOM 155 O WAT 155 3.000 11.000 9.000 1.00 0.00 O +ATOM 156 O WAT 156 3.000 11.000 11.000 1.00 0.00 O +ATOM 157 O WAT 157 3.000 11.000 13.000 1.00 0.00 O +ATOM 158 O WAT 158 3.000 11.000 15.000 1.00 0.00 O +ATOM 159 O WAT 159 3.000 11.000 17.000 1.00 0.00 O +ATOM 160 O WAT 160 3.000 11.000 19.000 1.00 0.00 O +ATOM 161 O WAT 161 3.000 13.000 1.000 1.00 0.00 O +ATOM 162 O WAT 162 3.000 13.000 3.000 1.00 0.00 O +ATOM 163 O WAT 163 3.000 13.000 5.000 1.00 0.00 O +ATOM 164 O WAT 164 3.000 13.000 7.000 1.00 0.00 O +ATOM 165 O WAT 165 3.000 13.000 9.000 1.00 0.00 O +ATOM 166 O WAT 166 3.000 13.000 11.000 1.00 0.00 O +ATOM 167 O WAT 167 3.000 13.000 13.000 1.00 0.00 O +ATOM 168 O WAT 168 3.000 13.000 15.000 1.00 0.00 O +ATOM 169 O WAT 169 3.000 13.000 17.000 1.00 0.00 O +ATOM 170 O WAT 170 3.000 13.000 19.000 1.00 0.00 O +ATOM 171 O WAT 171 3.000 15.000 1.000 1.00 0.00 O +ATOM 172 O WAT 172 3.000 15.000 3.000 1.00 0.00 O +ATOM 173 O WAT 173 3.000 15.000 5.000 1.00 0.00 O +ATOM 174 O WAT 174 3.000 15.000 7.000 1.00 0.00 O +ATOM 175 O WAT 175 3.000 15.000 9.000 1.00 0.00 O +ATOM 176 O WAT 176 3.000 15.000 11.000 1.00 0.00 O +ATOM 177 O WAT 177 3.000 15.000 13.000 1.00 0.00 O +ATOM 178 O WAT 178 3.000 15.000 15.000 1.00 0.00 O +ATOM 179 O WAT 179 3.000 15.000 17.000 1.00 0.00 O +ATOM 180 O WAT 180 3.000 15.000 19.000 1.00 0.00 O +ATOM 181 O WAT 181 3.000 17.000 1.000 1.00 0.00 O +ATOM 182 O WAT 182 3.000 17.000 3.000 1.00 0.00 O +ATOM 183 O WAT 183 3.000 17.000 5.000 1.00 0.00 O +ATOM 184 O WAT 184 3.000 17.000 7.000 1.00 0.00 O +ATOM 185 O WAT 185 3.000 17.000 9.000 1.00 0.00 O +ATOM 186 O WAT 186 3.000 17.000 11.000 1.00 0.00 O +ATOM 187 O WAT 187 3.000 17.000 13.000 1.00 0.00 O +ATOM 188 O WAT 188 3.000 17.000 15.000 1.00 0.00 O +ATOM 189 O WAT 189 3.000 17.000 17.000 1.00 0.00 O +ATOM 190 O WAT 190 3.000 17.000 19.000 1.00 0.00 O +ATOM 191 O WAT 191 3.000 19.000 1.000 1.00 0.00 O +ATOM 192 O WAT 192 3.000 19.000 3.000 1.00 0.00 O +ATOM 193 O WAT 193 3.000 19.000 5.000 1.00 0.00 O +ATOM 194 O WAT 194 3.000 19.000 7.000 1.00 0.00 O +ATOM 195 O WAT 195 3.000 19.000 9.000 1.00 0.00 O +ATOM 196 O WAT 196 3.000 19.000 11.000 1.00 0.00 O +ATOM 197 O WAT 197 3.000 19.000 13.000 1.00 0.00 O +ATOM 198 O WAT 198 3.000 19.000 15.000 1.00 0.00 O +ATOM 199 O WAT 199 3.000 19.000 17.000 1.00 0.00 O +ATOM 200 O WAT 200 3.000 19.000 19.000 1.00 0.00 O +ATOM 201 O WAT 201 5.000 1.000 1.000 1.00 0.00 O +ATOM 202 O WAT 202 5.000 1.000 3.000 1.00 0.00 O +ATOM 203 O WAT 203 5.000 1.000 5.000 1.00 0.00 O +ATOM 204 O WAT 204 5.000 1.000 7.000 1.00 0.00 O +ATOM 205 O WAT 205 5.000 1.000 9.000 1.00 0.00 O +ATOM 206 O WAT 206 5.000 1.000 11.000 1.00 0.00 O +ATOM 207 O WAT 207 5.000 1.000 13.000 1.00 0.00 O +ATOM 208 O WAT 208 5.000 1.000 15.000 1.00 0.00 O +ATOM 209 O WAT 209 5.000 1.000 17.000 1.00 0.00 O +ATOM 210 O WAT 210 5.000 1.000 19.000 1.00 0.00 O +ATOM 211 O WAT 211 5.000 3.000 1.000 1.00 0.00 O +ATOM 212 O WAT 212 5.000 3.000 3.000 1.00 0.00 O +ATOM 213 O WAT 213 5.000 3.000 5.000 1.00 0.00 O +ATOM 214 O WAT 214 5.000 3.000 7.000 1.00 0.00 O +ATOM 215 O WAT 215 5.000 3.000 9.000 1.00 0.00 O +ATOM 216 O WAT 216 5.000 3.000 11.000 1.00 0.00 O +ATOM 217 O WAT 217 5.000 3.000 13.000 1.00 0.00 O +ATOM 218 O WAT 218 5.000 3.000 15.000 1.00 0.00 O +ATOM 219 O WAT 219 5.000 3.000 17.000 1.00 0.00 O +ATOM 220 O WAT 220 5.000 3.000 19.000 1.00 0.00 O +ATOM 221 O WAT 221 5.000 5.000 1.000 1.00 0.00 O +ATOM 222 O WAT 222 5.000 5.000 3.000 1.00 0.00 O +ATOM 223 O WAT 223 5.000 5.000 5.000 1.00 0.00 O +ATOM 224 O WAT 224 5.000 5.000 7.000 1.00 0.00 O +ATOM 225 O WAT 225 5.000 5.000 9.000 1.00 0.00 O +ATOM 226 O WAT 226 5.000 5.000 11.000 1.00 0.00 O +ATOM 227 O WAT 227 5.000 5.000 13.000 1.00 0.00 O +ATOM 228 O WAT 228 5.000 5.000 15.000 1.00 0.00 O +ATOM 229 O WAT 229 5.000 5.000 17.000 1.00 0.00 O +ATOM 230 O WAT 230 5.000 5.000 19.000 1.00 0.00 O +ATOM 231 O WAT 231 5.000 7.000 1.000 1.00 0.00 O +ATOM 232 O WAT 232 5.000 7.000 3.000 1.00 0.00 O +ATOM 233 O WAT 233 5.000 7.000 5.000 1.00 0.00 O +ATOM 234 O WAT 234 5.000 7.000 7.000 1.00 0.00 O +ATOM 235 O WAT 235 5.000 7.000 9.000 1.00 0.00 O +ATOM 236 O WAT 236 5.000 7.000 11.000 1.00 0.00 O +ATOM 237 O WAT 237 5.000 7.000 13.000 1.00 0.00 O +ATOM 238 O WAT 238 5.000 7.000 15.000 1.00 0.00 O +ATOM 239 O WAT 239 5.000 7.000 17.000 1.00 0.00 O +ATOM 240 O WAT 240 5.000 7.000 19.000 1.00 0.00 O +ATOM 241 O WAT 241 5.000 9.000 1.000 1.00 0.00 O +ATOM 242 O WAT 242 5.000 9.000 3.000 1.00 0.00 O +ATOM 243 O WAT 243 5.000 9.000 5.000 1.00 0.00 O +ATOM 244 O WAT 244 5.000 9.000 7.000 1.00 0.00 O +ATOM 245 O WAT 245 5.000 9.000 9.000 1.00 0.00 O +ATOM 246 O WAT 246 5.000 9.000 11.000 1.00 0.00 O +ATOM 247 O WAT 247 5.000 9.000 13.000 1.00 0.00 O +ATOM 248 O WAT 248 5.000 9.000 15.000 1.00 0.00 O +ATOM 249 O WAT 249 5.000 9.000 17.000 1.00 0.00 O +ATOM 250 O WAT 250 5.000 9.000 19.000 1.00 0.00 O +ATOM 251 O WAT 251 5.000 11.000 1.000 1.00 0.00 O +ATOM 252 O WAT 252 5.000 11.000 3.000 1.00 0.00 O +ATOM 253 O WAT 253 5.000 11.000 5.000 1.00 0.00 O +ATOM 254 O WAT 254 5.000 11.000 7.000 1.00 0.00 O +ATOM 255 O WAT 255 5.000 11.000 9.000 1.00 0.00 O +ATOM 256 O WAT 256 5.000 11.000 11.000 1.00 0.00 O +ATOM 257 O WAT 257 5.000 11.000 13.000 1.00 0.00 O +ATOM 258 O WAT 258 5.000 11.000 15.000 1.00 0.00 O +ATOM 259 O WAT 259 5.000 11.000 17.000 1.00 0.00 O +ATOM 260 O WAT 260 5.000 11.000 19.000 1.00 0.00 O +ATOM 261 O WAT 261 5.000 13.000 1.000 1.00 0.00 O +ATOM 262 O WAT 262 5.000 13.000 3.000 1.00 0.00 O +ATOM 263 O WAT 263 5.000 13.000 5.000 1.00 0.00 O +ATOM 264 O WAT 264 5.000 13.000 7.000 1.00 0.00 O +ATOM 265 O WAT 265 5.000 13.000 9.000 1.00 0.00 O +ATOM 266 O WAT 266 5.000 13.000 11.000 1.00 0.00 O +ATOM 267 O WAT 267 5.000 13.000 13.000 1.00 0.00 O +ATOM 268 O WAT 268 5.000 13.000 15.000 1.00 0.00 O +ATOM 269 O WAT 269 5.000 13.000 17.000 1.00 0.00 O +ATOM 270 O WAT 270 5.000 13.000 19.000 1.00 0.00 O +ATOM 271 O WAT 271 5.000 15.000 1.000 1.00 0.00 O +ATOM 272 O WAT 272 5.000 15.000 3.000 1.00 0.00 O +ATOM 273 O WAT 273 5.000 15.000 5.000 1.00 0.00 O +ATOM 274 O WAT 274 5.000 15.000 7.000 1.00 0.00 O +ATOM 275 O WAT 275 5.000 15.000 9.000 1.00 0.00 O +ATOM 276 O WAT 276 5.000 15.000 11.000 1.00 0.00 O +ATOM 277 O WAT 277 5.000 15.000 13.000 1.00 0.00 O +ATOM 278 O WAT 278 5.000 15.000 15.000 1.00 0.00 O +ATOM 279 O WAT 279 5.000 15.000 17.000 1.00 0.00 O +ATOM 280 O WAT 280 5.000 15.000 19.000 1.00 0.00 O +ATOM 281 O WAT 281 5.000 17.000 1.000 1.00 0.00 O +ATOM 282 O WAT 282 5.000 17.000 3.000 1.00 0.00 O +ATOM 283 O WAT 283 5.000 17.000 5.000 1.00 0.00 O +ATOM 284 O WAT 284 5.000 17.000 7.000 1.00 0.00 O +ATOM 285 O WAT 285 5.000 17.000 9.000 1.00 0.00 O +ATOM 286 O WAT 286 5.000 17.000 11.000 1.00 0.00 O +ATOM 287 O WAT 287 5.000 17.000 13.000 1.00 0.00 O +ATOM 288 O WAT 288 5.000 17.000 15.000 1.00 0.00 O +ATOM 289 O WAT 289 5.000 17.000 17.000 1.00 0.00 O +ATOM 290 O WAT 290 5.000 17.000 19.000 1.00 0.00 O +ATOM 291 O WAT 291 5.000 19.000 1.000 1.00 0.00 O +ATOM 292 O WAT 292 5.000 19.000 3.000 1.00 0.00 O +ATOM 293 O WAT 293 5.000 19.000 5.000 1.00 0.00 O +ATOM 294 O WAT 294 5.000 19.000 7.000 1.00 0.00 O +ATOM 295 O WAT 295 5.000 19.000 9.000 1.00 0.00 O +ATOM 296 O WAT 296 5.000 19.000 11.000 1.00 0.00 O +ATOM 297 O WAT 297 5.000 19.000 13.000 1.00 0.00 O +ATOM 298 O WAT 298 5.000 19.000 15.000 1.00 0.00 O +ATOM 299 O WAT 299 5.000 19.000 17.000 1.00 0.00 O +ATOM 300 O WAT 300 5.000 19.000 19.000 1.00 0.00 O +ATOM 301 O WAT 301 7.000 1.000 1.000 1.00 0.00 O +ATOM 302 O WAT 302 7.000 1.000 3.000 1.00 0.00 O +ATOM 303 O WAT 303 7.000 1.000 5.000 1.00 0.00 O +ATOM 304 O WAT 304 7.000 1.000 7.000 1.00 0.00 O +ATOM 305 O WAT 305 7.000 1.000 9.000 1.00 0.00 O +ATOM 306 O WAT 306 7.000 1.000 11.000 1.00 0.00 O +ATOM 307 O WAT 307 7.000 1.000 13.000 1.00 0.00 O +ATOM 308 O WAT 308 7.000 1.000 15.000 1.00 0.00 O +ATOM 309 O WAT 309 7.000 1.000 17.000 1.00 0.00 O +ATOM 310 O WAT 310 7.000 1.000 19.000 1.00 0.00 O +ATOM 311 O WAT 311 7.000 3.000 1.000 1.00 0.00 O +ATOM 312 O WAT 312 7.000 3.000 3.000 1.00 0.00 O +ATOM 313 O WAT 313 7.000 3.000 5.000 1.00 0.00 O +ATOM 314 O WAT 314 7.000 3.000 7.000 1.00 0.00 O +ATOM 315 O WAT 315 7.000 3.000 9.000 1.00 0.00 O +ATOM 316 O WAT 316 7.000 3.000 11.000 1.00 0.00 O +ATOM 317 O WAT 317 7.000 3.000 13.000 1.00 0.00 O +ATOM 318 O WAT 318 7.000 3.000 15.000 1.00 0.00 O +ATOM 319 O WAT 319 7.000 3.000 17.000 1.00 0.00 O +ATOM 320 O WAT 320 7.000 3.000 19.000 1.00 0.00 O +ATOM 321 O WAT 321 7.000 5.000 1.000 1.00 0.00 O +ATOM 322 O WAT 322 7.000 5.000 3.000 1.00 0.00 O +ATOM 323 O WAT 323 7.000 5.000 5.000 1.00 0.00 O +ATOM 324 O WAT 324 7.000 5.000 7.000 1.00 0.00 O +ATOM 325 O WAT 325 7.000 5.000 9.000 1.00 0.00 O +ATOM 326 O WAT 326 7.000 5.000 11.000 1.00 0.00 O +ATOM 327 O WAT 327 7.000 5.000 13.000 1.00 0.00 O +ATOM 328 O WAT 328 7.000 5.000 15.000 1.00 0.00 O +ATOM 329 O WAT 329 7.000 5.000 17.000 1.00 0.00 O +ATOM 330 O WAT 330 7.000 5.000 19.000 1.00 0.00 O +ATOM 331 O WAT 331 7.000 7.000 1.000 1.00 0.00 O +ATOM 332 O WAT 332 7.000 7.000 3.000 1.00 0.00 O +ATOM 333 O WAT 333 7.000 7.000 5.000 1.00 0.00 O +ATOM 334 O WAT 334 7.000 7.000 7.000 1.00 0.00 O +ATOM 335 O WAT 335 7.000 7.000 9.000 1.00 0.00 O +ATOM 336 O WAT 336 7.000 7.000 11.000 1.00 0.00 O +ATOM 337 O WAT 337 7.000 7.000 13.000 1.00 0.00 O +ATOM 338 O WAT 338 7.000 7.000 15.000 1.00 0.00 O +ATOM 339 O WAT 339 7.000 7.000 17.000 1.00 0.00 O +ATOM 340 O WAT 340 7.000 7.000 19.000 1.00 0.00 O +ATOM 341 O WAT 341 7.000 9.000 1.000 1.00 0.00 O +ATOM 342 O WAT 342 7.000 9.000 3.000 1.00 0.00 O +ATOM 343 O WAT 343 7.000 9.000 5.000 1.00 0.00 O +ATOM 344 O WAT 344 7.000 9.000 7.000 1.00 0.00 O +ATOM 345 O WAT 345 7.000 9.000 9.000 1.00 0.00 O +ATOM 346 O WAT 346 7.000 9.000 11.000 1.00 0.00 O +ATOM 347 O WAT 347 7.000 9.000 13.000 1.00 0.00 O +ATOM 348 O WAT 348 7.000 9.000 15.000 1.00 0.00 O +ATOM 349 O WAT 349 7.000 9.000 17.000 1.00 0.00 O +ATOM 350 O WAT 350 7.000 9.000 19.000 1.00 0.00 O +ATOM 351 O WAT 351 7.000 11.000 1.000 1.00 0.00 O +ATOM 352 O WAT 352 7.000 11.000 3.000 1.00 0.00 O +ATOM 353 O WAT 353 7.000 11.000 5.000 1.00 0.00 O +ATOM 354 O WAT 354 7.000 11.000 7.000 1.00 0.00 O +ATOM 355 O WAT 355 7.000 11.000 9.000 1.00 0.00 O +ATOM 356 O WAT 356 7.000 11.000 11.000 1.00 0.00 O +ATOM 357 O WAT 357 7.000 11.000 13.000 1.00 0.00 O +ATOM 358 O WAT 358 7.000 11.000 15.000 1.00 0.00 O +ATOM 359 O WAT 359 7.000 11.000 17.000 1.00 0.00 O +ATOM 360 O WAT 360 7.000 11.000 19.000 1.00 0.00 O +ATOM 361 O WAT 361 7.000 13.000 1.000 1.00 0.00 O +ATOM 362 O WAT 362 7.000 13.000 3.000 1.00 0.00 O +ATOM 363 O WAT 363 7.000 13.000 5.000 1.00 0.00 O +ATOM 364 O WAT 364 7.000 13.000 7.000 1.00 0.00 O +ATOM 365 O WAT 365 7.000 13.000 9.000 1.00 0.00 O +ATOM 366 O WAT 366 7.000 13.000 11.000 1.00 0.00 O +ATOM 367 O WAT 367 7.000 13.000 13.000 1.00 0.00 O +ATOM 368 O WAT 368 7.000 13.000 15.000 1.00 0.00 O +ATOM 369 O WAT 369 7.000 13.000 17.000 1.00 0.00 O +ATOM 370 O WAT 370 7.000 13.000 19.000 1.00 0.00 O +ATOM 371 O WAT 371 7.000 15.000 1.000 1.00 0.00 O +ATOM 372 O WAT 372 7.000 15.000 3.000 1.00 0.00 O +ATOM 373 O WAT 373 7.000 15.000 5.000 1.00 0.00 O +ATOM 374 O WAT 374 7.000 15.000 7.000 1.00 0.00 O +ATOM 375 O WAT 375 7.000 15.000 9.000 1.00 0.00 O +ATOM 376 O WAT 376 7.000 15.000 11.000 1.00 0.00 O +ATOM 377 O WAT 377 7.000 15.000 13.000 1.00 0.00 O +ATOM 378 O WAT 378 7.000 15.000 15.000 1.00 0.00 O +ATOM 379 O WAT 379 7.000 15.000 17.000 1.00 0.00 O +ATOM 380 O WAT 380 7.000 15.000 19.000 1.00 0.00 O +ATOM 381 O WAT 381 7.000 17.000 1.000 1.00 0.00 O +ATOM 382 O WAT 382 7.000 17.000 3.000 1.00 0.00 O +ATOM 383 O WAT 383 7.000 17.000 5.000 1.00 0.00 O +ATOM 384 O WAT 384 7.000 17.000 7.000 1.00 0.00 O +ATOM 385 O WAT 385 7.000 17.000 9.000 1.00 0.00 O +ATOM 386 O WAT 386 7.000 17.000 11.000 1.00 0.00 O +ATOM 387 O WAT 387 7.000 17.000 13.000 1.00 0.00 O +ATOM 388 O WAT 388 7.000 17.000 15.000 1.00 0.00 O +ATOM 389 O WAT 389 7.000 17.000 17.000 1.00 0.00 O +ATOM 390 O WAT 390 7.000 17.000 19.000 1.00 0.00 O +ATOM 391 O WAT 391 7.000 19.000 1.000 1.00 0.00 O +ATOM 392 O WAT 392 7.000 19.000 3.000 1.00 0.00 O +ATOM 393 O WAT 393 7.000 19.000 5.000 1.00 0.00 O +ATOM 394 O WAT 394 7.000 19.000 7.000 1.00 0.00 O +ATOM 395 O WAT 395 7.000 19.000 9.000 1.00 0.00 O +ATOM 396 O WAT 396 7.000 19.000 11.000 1.00 0.00 O +ATOM 397 O WAT 397 7.000 19.000 13.000 1.00 0.00 O +ATOM 398 O WAT 398 7.000 19.000 15.000 1.00 0.00 O +ATOM 399 O WAT 399 7.000 19.000 17.000 1.00 0.00 O +ATOM 400 O WAT 400 7.000 19.000 19.000 1.00 0.00 O +ATOM 401 O WAT 401 9.000 1.000 1.000 1.00 0.00 O +ATOM 402 O WAT 402 9.000 1.000 3.000 1.00 0.00 O +ATOM 403 O WAT 403 9.000 1.000 5.000 1.00 0.00 O +ATOM 404 O WAT 404 9.000 1.000 7.000 1.00 0.00 O +ATOM 405 O WAT 405 9.000 1.000 9.000 1.00 0.00 O +ATOM 406 O WAT 406 9.000 1.000 11.000 1.00 0.00 O +ATOM 407 O WAT 407 9.000 1.000 13.000 1.00 0.00 O +ATOM 408 O WAT 408 9.000 1.000 15.000 1.00 0.00 O +ATOM 409 O WAT 409 9.000 1.000 17.000 1.00 0.00 O +ATOM 410 O WAT 410 9.000 1.000 19.000 1.00 0.00 O +ATOM 411 O WAT 411 9.000 3.000 1.000 1.00 0.00 O +ATOM 412 O WAT 412 9.000 3.000 3.000 1.00 0.00 O +ATOM 413 O WAT 413 9.000 3.000 5.000 1.00 0.00 O +ATOM 414 O WAT 414 9.000 3.000 7.000 1.00 0.00 O +ATOM 415 O WAT 415 9.000 3.000 9.000 1.00 0.00 O +ATOM 416 O WAT 416 9.000 3.000 11.000 1.00 0.00 O +ATOM 417 O WAT 417 9.000 3.000 13.000 1.00 0.00 O +ATOM 418 O WAT 418 9.000 3.000 15.000 1.00 0.00 O +ATOM 419 O WAT 419 9.000 3.000 17.000 1.00 0.00 O +ATOM 420 O WAT 420 9.000 3.000 19.000 1.00 0.00 O +ATOM 421 O WAT 421 9.000 5.000 1.000 1.00 0.00 O +ATOM 422 O WAT 422 9.000 5.000 3.000 1.00 0.00 O +ATOM 423 O WAT 423 9.000 5.000 5.000 1.00 0.00 O +ATOM 424 O WAT 424 9.000 5.000 7.000 1.00 0.00 O +ATOM 425 O WAT 425 9.000 5.000 9.000 1.00 0.00 O +ATOM 426 O WAT 426 9.000 5.000 11.000 1.00 0.00 O +ATOM 427 O WAT 427 9.000 5.000 13.000 1.00 0.00 O +ATOM 428 O WAT 428 9.000 5.000 15.000 1.00 0.00 O +ATOM 429 O WAT 429 9.000 5.000 17.000 1.00 0.00 O +ATOM 430 O WAT 430 9.000 5.000 19.000 1.00 0.00 O +ATOM 431 O WAT 431 9.000 7.000 1.000 1.00 0.00 O +ATOM 432 O WAT 432 9.000 7.000 3.000 1.00 0.00 O +ATOM 433 O WAT 433 9.000 7.000 5.000 1.00 0.00 O +ATOM 434 O WAT 434 9.000 7.000 7.000 1.00 0.00 O +ATOM 435 O WAT 435 9.000 7.000 9.000 1.00 0.00 O +ATOM 436 O WAT 436 9.000 7.000 11.000 1.00 0.00 O +ATOM 437 O WAT 437 9.000 7.000 13.000 1.00 0.00 O +ATOM 438 O WAT 438 9.000 7.000 15.000 1.00 0.00 O +ATOM 439 O WAT 439 9.000 7.000 17.000 1.00 0.00 O +ATOM 440 O WAT 440 9.000 7.000 19.000 1.00 0.00 O +ATOM 441 O WAT 441 9.000 9.000 1.000 1.00 0.00 O +ATOM 442 O WAT 442 9.000 9.000 3.000 1.00 0.00 O +ATOM 443 O WAT 443 9.000 9.000 5.000 1.00 0.00 O +ATOM 444 O WAT 444 9.000 9.000 7.000 1.00 0.00 O +ATOM 445 O WAT 445 9.000 9.000 9.000 1.00 0.00 O +ATOM 446 O WAT 446 9.000 9.000 11.000 1.00 0.00 O +ATOM 447 O WAT 447 9.000 9.000 13.000 1.00 0.00 O +ATOM 448 O WAT 448 9.000 9.000 15.000 1.00 0.00 O +ATOM 449 O WAT 449 9.000 9.000 17.000 1.00 0.00 O +ATOM 450 O WAT 450 9.000 9.000 19.000 1.00 0.00 O +ATOM 451 O WAT 451 9.000 11.000 1.000 1.00 0.00 O +ATOM 452 O WAT 452 9.000 11.000 3.000 1.00 0.00 O +ATOM 453 O WAT 453 9.000 11.000 5.000 1.00 0.00 O +ATOM 454 O WAT 454 9.000 11.000 7.000 1.00 0.00 O +ATOM 455 O WAT 455 9.000 11.000 9.000 1.00 0.00 O +ATOM 456 O WAT 456 9.000 11.000 11.000 1.00 0.00 O +ATOM 457 O WAT 457 9.000 11.000 13.000 1.00 0.00 O +ATOM 458 O WAT 458 9.000 11.000 15.000 1.00 0.00 O +ATOM 459 O WAT 459 9.000 11.000 17.000 1.00 0.00 O +ATOM 460 O WAT 460 9.000 11.000 19.000 1.00 0.00 O +ATOM 461 O WAT 461 9.000 13.000 1.000 1.00 0.00 O +ATOM 462 O WAT 462 9.000 13.000 3.000 1.00 0.00 O +ATOM 463 O WAT 463 9.000 13.000 5.000 1.00 0.00 O +ATOM 464 O WAT 464 9.000 13.000 7.000 1.00 0.00 O +ATOM 465 O WAT 465 9.000 13.000 9.000 1.00 0.00 O +ATOM 466 O WAT 466 9.000 13.000 11.000 1.00 0.00 O +ATOM 467 O WAT 467 9.000 13.000 13.000 1.00 0.00 O +ATOM 468 O WAT 468 9.000 13.000 15.000 1.00 0.00 O +ATOM 469 O WAT 469 9.000 13.000 17.000 1.00 0.00 O +ATOM 470 O WAT 470 9.000 13.000 19.000 1.00 0.00 O +ATOM 471 O WAT 471 9.000 15.000 1.000 1.00 0.00 O +ATOM 472 O WAT 472 9.000 15.000 3.000 1.00 0.00 O +ATOM 473 O WAT 473 9.000 15.000 5.000 1.00 0.00 O +ATOM 474 O WAT 474 9.000 15.000 7.000 1.00 0.00 O +ATOM 475 O WAT 475 9.000 15.000 9.000 1.00 0.00 O +ATOM 476 O WAT 476 9.000 15.000 11.000 1.00 0.00 O +ATOM 477 O WAT 477 9.000 15.000 13.000 1.00 0.00 O +ATOM 478 O WAT 478 9.000 15.000 15.000 1.00 0.00 O +ATOM 479 O WAT 479 9.000 15.000 17.000 1.00 0.00 O +ATOM 480 O WAT 480 9.000 15.000 19.000 1.00 0.00 O +ATOM 481 O WAT 481 9.000 17.000 1.000 1.00 0.00 O +ATOM 482 O WAT 482 9.000 17.000 3.000 1.00 0.00 O +ATOM 483 O WAT 483 9.000 17.000 5.000 1.00 0.00 O +ATOM 484 O WAT 484 9.000 17.000 7.000 1.00 0.00 O +ATOM 485 O WAT 485 9.000 17.000 9.000 1.00 0.00 O +ATOM 486 O WAT 486 9.000 17.000 11.000 1.00 0.00 O +ATOM 487 O WAT 487 9.000 17.000 13.000 1.00 0.00 O +ATOM 488 O WAT 488 9.000 17.000 15.000 1.00 0.00 O +ATOM 489 O WAT 489 9.000 17.000 17.000 1.00 0.00 O +ATOM 490 O WAT 490 9.000 17.000 19.000 1.00 0.00 O +ATOM 491 O WAT 491 9.000 19.000 1.000 1.00 0.00 O +ATOM 492 O WAT 492 9.000 19.000 3.000 1.00 0.00 O +ATOM 493 O WAT 493 9.000 19.000 5.000 1.00 0.00 O +ATOM 494 O WAT 494 9.000 19.000 7.000 1.00 0.00 O +ATOM 495 O WAT 495 9.000 19.000 9.000 1.00 0.00 O +ATOM 496 O WAT 496 9.000 19.000 11.000 1.00 0.00 O +ATOM 497 O WAT 497 9.000 19.000 13.000 1.00 0.00 O +ATOM 498 O WAT 498 9.000 19.000 15.000 1.00 0.00 O +ATOM 499 O WAT 499 9.000 19.000 17.000 1.00 0.00 O +ATOM 500 O WAT 500 9.000 19.000 19.000 1.00 0.00 O +ATOM 501 O WAT 501 11.000 1.000 1.000 1.00 0.00 O +ATOM 502 O WAT 502 11.000 1.000 3.000 1.00 0.00 O +ATOM 503 O WAT 503 11.000 1.000 5.000 1.00 0.00 O +ATOM 504 O WAT 504 11.000 1.000 7.000 1.00 0.00 O +ATOM 505 O WAT 505 11.000 1.000 9.000 1.00 0.00 O +ATOM 506 O WAT 506 11.000 1.000 11.000 1.00 0.00 O +ATOM 507 O WAT 507 11.000 1.000 13.000 1.00 0.00 O +ATOM 508 O WAT 508 11.000 1.000 15.000 1.00 0.00 O +ATOM 509 O WAT 509 11.000 1.000 17.000 1.00 0.00 O +ATOM 510 O WAT 510 11.000 1.000 19.000 1.00 0.00 O +ATOM 511 O WAT 511 11.000 3.000 1.000 1.00 0.00 O +ATOM 512 O WAT 512 11.000 3.000 3.000 1.00 0.00 O +ATOM 513 O WAT 513 11.000 3.000 5.000 1.00 0.00 O +ATOM 514 O WAT 514 11.000 3.000 7.000 1.00 0.00 O +ATOM 515 O WAT 515 11.000 3.000 9.000 1.00 0.00 O +ATOM 516 O WAT 516 11.000 3.000 11.000 1.00 0.00 O +ATOM 517 O WAT 517 11.000 3.000 13.000 1.00 0.00 O +ATOM 518 O WAT 518 11.000 3.000 15.000 1.00 0.00 O +ATOM 519 O WAT 519 11.000 3.000 17.000 1.00 0.00 O +ATOM 520 O WAT 520 11.000 3.000 19.000 1.00 0.00 O +ATOM 521 O WAT 521 11.000 5.000 1.000 1.00 0.00 O +ATOM 522 O WAT 522 11.000 5.000 3.000 1.00 0.00 O +ATOM 523 O WAT 523 11.000 5.000 5.000 1.00 0.00 O +ATOM 524 O WAT 524 11.000 5.000 7.000 1.00 0.00 O +ATOM 525 O WAT 525 11.000 5.000 9.000 1.00 0.00 O +ATOM 526 O WAT 526 11.000 5.000 11.000 1.00 0.00 O +ATOM 527 O WAT 527 11.000 5.000 13.000 1.00 0.00 O +ATOM 528 O WAT 528 11.000 5.000 15.000 1.00 0.00 O +ATOM 529 O WAT 529 11.000 5.000 17.000 1.00 0.00 O +ATOM 530 O WAT 530 11.000 5.000 19.000 1.00 0.00 O +ATOM 531 O WAT 531 11.000 7.000 1.000 1.00 0.00 O +ATOM 532 O WAT 532 11.000 7.000 3.000 1.00 0.00 O +ATOM 533 O WAT 533 11.000 7.000 5.000 1.00 0.00 O +ATOM 534 O WAT 534 11.000 7.000 7.000 1.00 0.00 O +ATOM 535 O WAT 535 11.000 7.000 9.000 1.00 0.00 O +ATOM 536 O WAT 536 11.000 7.000 11.000 1.00 0.00 O +ATOM 537 O WAT 537 11.000 7.000 13.000 1.00 0.00 O +ATOM 538 O WAT 538 11.000 7.000 15.000 1.00 0.00 O +ATOM 539 O WAT 539 11.000 7.000 17.000 1.00 0.00 O +ATOM 540 O WAT 540 11.000 7.000 19.000 1.00 0.00 O +ATOM 541 O WAT 541 11.000 9.000 1.000 1.00 0.00 O +ATOM 542 O WAT 542 11.000 9.000 3.000 1.00 0.00 O +ATOM 543 O WAT 543 11.000 9.000 5.000 1.00 0.00 O +ATOM 544 O WAT 544 11.000 9.000 7.000 1.00 0.00 O +ATOM 545 O WAT 545 11.000 9.000 9.000 1.00 0.00 O +ATOM 546 O WAT 546 11.000 9.000 11.000 1.00 0.00 O +ATOM 547 O WAT 547 11.000 9.000 13.000 1.00 0.00 O +ATOM 548 O WAT 548 11.000 9.000 15.000 1.00 0.00 O +ATOM 549 O WAT 549 11.000 9.000 17.000 1.00 0.00 O +ATOM 550 O WAT 550 11.000 9.000 19.000 1.00 0.00 O +ATOM 551 O WAT 551 11.000 11.000 1.000 1.00 0.00 O +ATOM 552 O WAT 552 11.000 11.000 3.000 1.00 0.00 O +ATOM 553 O WAT 553 11.000 11.000 5.000 1.00 0.00 O +ATOM 554 O WAT 554 11.000 11.000 7.000 1.00 0.00 O +ATOM 555 O WAT 555 11.000 11.000 9.000 1.00 0.00 O +ATOM 556 O WAT 556 11.000 11.000 11.000 1.00 0.00 O +ATOM 557 O WAT 557 11.000 11.000 13.000 1.00 0.00 O +ATOM 558 O WAT 558 11.000 11.000 15.000 1.00 0.00 O +ATOM 559 O WAT 559 11.000 11.000 17.000 1.00 0.00 O +ATOM 560 O WAT 560 11.000 11.000 19.000 1.00 0.00 O +ATOM 561 O WAT 561 11.000 13.000 1.000 1.00 0.00 O +ATOM 562 O WAT 562 11.000 13.000 3.000 1.00 0.00 O +ATOM 563 O WAT 563 11.000 13.000 5.000 1.00 0.00 O +ATOM 564 O WAT 564 11.000 13.000 7.000 1.00 0.00 O +ATOM 565 O WAT 565 11.000 13.000 9.000 1.00 0.00 O +ATOM 566 O WAT 566 11.000 13.000 11.000 1.00 0.00 O +ATOM 567 O WAT 567 11.000 13.000 13.000 1.00 0.00 O +ATOM 568 O WAT 568 11.000 13.000 15.000 1.00 0.00 O +ATOM 569 O WAT 569 11.000 13.000 17.000 1.00 0.00 O +ATOM 570 O WAT 570 11.000 13.000 19.000 1.00 0.00 O +ATOM 571 O WAT 571 11.000 15.000 1.000 1.00 0.00 O +ATOM 572 O WAT 572 11.000 15.000 3.000 1.00 0.00 O +ATOM 573 O WAT 573 11.000 15.000 5.000 1.00 0.00 O +ATOM 574 O WAT 574 11.000 15.000 7.000 1.00 0.00 O +ATOM 575 O WAT 575 11.000 15.000 9.000 1.00 0.00 O +ATOM 576 O WAT 576 11.000 15.000 11.000 1.00 0.00 O +ATOM 577 O WAT 577 11.000 15.000 13.000 1.00 0.00 O +ATOM 578 O WAT 578 11.000 15.000 15.000 1.00 0.00 O +ATOM 579 O WAT 579 11.000 15.000 17.000 1.00 0.00 O +ATOM 580 O WAT 580 11.000 15.000 19.000 1.00 0.00 O +ATOM 581 O WAT 581 11.000 17.000 1.000 1.00 0.00 O +ATOM 582 O WAT 582 11.000 17.000 3.000 1.00 0.00 O +ATOM 583 O WAT 583 11.000 17.000 5.000 1.00 0.00 O +ATOM 584 O WAT 584 11.000 17.000 7.000 1.00 0.00 O +ATOM 585 O WAT 585 11.000 17.000 9.000 1.00 0.00 O +ATOM 586 O WAT 586 11.000 17.000 11.000 1.00 0.00 O +ATOM 587 O WAT 587 11.000 17.000 13.000 1.00 0.00 O +ATOM 588 O WAT 588 11.000 17.000 15.000 1.00 0.00 O +ATOM 589 O WAT 589 11.000 17.000 17.000 1.00 0.00 O +ATOM 590 O WAT 590 11.000 17.000 19.000 1.00 0.00 O +ATOM 591 O WAT 591 11.000 19.000 1.000 1.00 0.00 O +ATOM 592 O WAT 592 11.000 19.000 3.000 1.00 0.00 O +ATOM 593 O WAT 593 11.000 19.000 5.000 1.00 0.00 O +ATOM 594 O WAT 594 11.000 19.000 7.000 1.00 0.00 O +ATOM 595 O WAT 595 11.000 19.000 9.000 1.00 0.00 O +ATOM 596 O WAT 596 11.000 19.000 11.000 1.00 0.00 O +ATOM 597 O WAT 597 11.000 19.000 13.000 1.00 0.00 O +ATOM 598 O WAT 598 11.000 19.000 15.000 1.00 0.00 O +ATOM 599 O WAT 599 11.000 19.000 17.000 1.00 0.00 O +ATOM 600 O WAT 600 11.000 19.000 19.000 1.00 0.00 O +ATOM 601 O WAT 601 13.000 1.000 1.000 1.00 0.00 O +ATOM 602 O WAT 602 13.000 1.000 3.000 1.00 0.00 O +ATOM 603 O WAT 603 13.000 1.000 5.000 1.00 0.00 O +ATOM 604 O WAT 604 13.000 1.000 7.000 1.00 0.00 O +ATOM 605 O WAT 605 13.000 1.000 9.000 1.00 0.00 O +ATOM 606 O WAT 606 13.000 1.000 11.000 1.00 0.00 O +ATOM 607 O WAT 607 13.000 1.000 13.000 1.00 0.00 O +ATOM 608 O WAT 608 13.000 1.000 15.000 1.00 0.00 O +ATOM 609 O WAT 609 13.000 1.000 17.000 1.00 0.00 O +ATOM 610 O WAT 610 13.000 1.000 19.000 1.00 0.00 O +ATOM 611 O WAT 611 13.000 3.000 1.000 1.00 0.00 O +ATOM 612 O WAT 612 13.000 3.000 3.000 1.00 0.00 O +ATOM 613 O WAT 613 13.000 3.000 5.000 1.00 0.00 O +ATOM 614 O WAT 614 13.000 3.000 7.000 1.00 0.00 O +ATOM 615 O WAT 615 13.000 3.000 9.000 1.00 0.00 O +ATOM 616 O WAT 616 13.000 3.000 11.000 1.00 0.00 O +ATOM 617 O WAT 617 13.000 3.000 13.000 1.00 0.00 O +ATOM 618 O WAT 618 13.000 3.000 15.000 1.00 0.00 O +ATOM 619 O WAT 619 13.000 3.000 17.000 1.00 0.00 O +ATOM 620 O WAT 620 13.000 3.000 19.000 1.00 0.00 O +ATOM 621 O WAT 621 13.000 5.000 1.000 1.00 0.00 O +ATOM 622 O WAT 622 13.000 5.000 3.000 1.00 0.00 O +ATOM 623 O WAT 623 13.000 5.000 5.000 1.00 0.00 O +ATOM 624 O WAT 624 13.000 5.000 7.000 1.00 0.00 O +ATOM 625 O WAT 625 13.000 5.000 9.000 1.00 0.00 O +ATOM 626 O WAT 626 13.000 5.000 11.000 1.00 0.00 O +ATOM 627 O WAT 627 13.000 5.000 13.000 1.00 0.00 O +ATOM 628 O WAT 628 13.000 5.000 15.000 1.00 0.00 O +ATOM 629 O WAT 629 13.000 5.000 17.000 1.00 0.00 O +ATOM 630 O WAT 630 13.000 5.000 19.000 1.00 0.00 O +ATOM 631 O WAT 631 13.000 7.000 1.000 1.00 0.00 O +ATOM 632 O WAT 632 13.000 7.000 3.000 1.00 0.00 O +ATOM 633 O WAT 633 13.000 7.000 5.000 1.00 0.00 O +ATOM 634 O WAT 634 13.000 7.000 7.000 1.00 0.00 O +ATOM 635 O WAT 635 13.000 7.000 9.000 1.00 0.00 O +ATOM 636 O WAT 636 13.000 7.000 11.000 1.00 0.00 O +ATOM 637 O WAT 637 13.000 7.000 13.000 1.00 0.00 O +ATOM 638 O WAT 638 13.000 7.000 15.000 1.00 0.00 O +ATOM 639 O WAT 639 13.000 7.000 17.000 1.00 0.00 O +ATOM 640 O WAT 640 13.000 7.000 19.000 1.00 0.00 O +ATOM 641 O WAT 641 13.000 9.000 1.000 1.00 0.00 O +ATOM 642 O WAT 642 13.000 9.000 3.000 1.00 0.00 O +ATOM 643 O WAT 643 13.000 9.000 5.000 1.00 0.00 O +ATOM 644 O WAT 644 13.000 9.000 7.000 1.00 0.00 O +ATOM 645 O WAT 645 13.000 9.000 9.000 1.00 0.00 O +ATOM 646 O WAT 646 13.000 9.000 11.000 1.00 0.00 O +ATOM 647 O WAT 647 13.000 9.000 13.000 1.00 0.00 O +ATOM 648 O WAT 648 13.000 9.000 15.000 1.00 0.00 O +ATOM 649 O WAT 649 13.000 9.000 17.000 1.00 0.00 O +ATOM 650 O WAT 650 13.000 9.000 19.000 1.00 0.00 O +ATOM 651 O WAT 651 13.000 11.000 1.000 1.00 0.00 O +ATOM 652 O WAT 652 13.000 11.000 3.000 1.00 0.00 O +ATOM 653 O WAT 653 13.000 11.000 5.000 1.00 0.00 O +ATOM 654 O WAT 654 13.000 11.000 7.000 1.00 0.00 O +ATOM 655 O WAT 655 13.000 11.000 9.000 1.00 0.00 O +ATOM 656 O WAT 656 13.000 11.000 11.000 1.00 0.00 O +ATOM 657 O WAT 657 13.000 11.000 13.000 1.00 0.00 O +ATOM 658 O WAT 658 13.000 11.000 15.000 1.00 0.00 O +ATOM 659 O WAT 659 13.000 11.000 17.000 1.00 0.00 O +ATOM 660 O WAT 660 13.000 11.000 19.000 1.00 0.00 O +ATOM 661 O WAT 661 13.000 13.000 1.000 1.00 0.00 O +ATOM 662 O WAT 662 13.000 13.000 3.000 1.00 0.00 O +ATOM 663 O WAT 663 13.000 13.000 5.000 1.00 0.00 O +ATOM 664 O WAT 664 13.000 13.000 7.000 1.00 0.00 O +ATOM 665 O WAT 665 13.000 13.000 9.000 1.00 0.00 O +ATOM 666 O WAT 666 13.000 13.000 11.000 1.00 0.00 O +ATOM 667 O WAT 667 13.000 13.000 13.000 1.00 0.00 O +ATOM 668 O WAT 668 13.000 13.000 15.000 1.00 0.00 O +ATOM 669 O WAT 669 13.000 13.000 17.000 1.00 0.00 O +ATOM 670 O WAT 670 13.000 13.000 19.000 1.00 0.00 O +ATOM 671 O WAT 671 13.000 15.000 1.000 1.00 0.00 O +ATOM 672 O WAT 672 13.000 15.000 3.000 1.00 0.00 O +ATOM 673 O WAT 673 13.000 15.000 5.000 1.00 0.00 O +ATOM 674 O WAT 674 13.000 15.000 7.000 1.00 0.00 O +ATOM 675 O WAT 675 13.000 15.000 9.000 1.00 0.00 O +ATOM 676 O WAT 676 13.000 15.000 11.000 1.00 0.00 O +ATOM 677 O WAT 677 13.000 15.000 13.000 1.00 0.00 O +ATOM 678 O WAT 678 13.000 15.000 15.000 1.00 0.00 O +ATOM 679 O WAT 679 13.000 15.000 17.000 1.00 0.00 O +ATOM 680 O WAT 680 13.000 15.000 19.000 1.00 0.00 O +ATOM 681 O WAT 681 13.000 17.000 1.000 1.00 0.00 O +ATOM 682 O WAT 682 13.000 17.000 3.000 1.00 0.00 O +ATOM 683 O WAT 683 13.000 17.000 5.000 1.00 0.00 O +ATOM 684 O WAT 684 13.000 17.000 7.000 1.00 0.00 O +ATOM 685 O WAT 685 13.000 17.000 9.000 1.00 0.00 O +ATOM 686 O WAT 686 13.000 17.000 11.000 1.00 0.00 O +ATOM 687 O WAT 687 13.000 17.000 13.000 1.00 0.00 O +ATOM 688 O WAT 688 13.000 17.000 15.000 1.00 0.00 O +ATOM 689 O WAT 689 13.000 17.000 17.000 1.00 0.00 O +ATOM 690 O WAT 690 13.000 17.000 19.000 1.00 0.00 O +ATOM 691 O WAT 691 13.000 19.000 1.000 1.00 0.00 O +ATOM 692 O WAT 692 13.000 19.000 3.000 1.00 0.00 O +ATOM 693 O WAT 693 13.000 19.000 5.000 1.00 0.00 O +ATOM 694 O WAT 694 13.000 19.000 7.000 1.00 0.00 O +ATOM 695 O WAT 695 13.000 19.000 9.000 1.00 0.00 O +ATOM 696 O WAT 696 13.000 19.000 11.000 1.00 0.00 O +ATOM 697 O WAT 697 13.000 19.000 13.000 1.00 0.00 O +ATOM 698 O WAT 698 13.000 19.000 15.000 1.00 0.00 O +ATOM 699 O WAT 699 13.000 19.000 17.000 1.00 0.00 O +ATOM 700 O WAT 700 13.000 19.000 19.000 1.00 0.00 O +ATOM 701 O WAT 701 15.000 1.000 1.000 1.00 0.00 O +ATOM 702 O WAT 702 15.000 1.000 3.000 1.00 0.00 O +ATOM 703 O WAT 703 15.000 1.000 5.000 1.00 0.00 O +ATOM 704 O WAT 704 15.000 1.000 7.000 1.00 0.00 O +ATOM 705 O WAT 705 15.000 1.000 9.000 1.00 0.00 O +ATOM 706 O WAT 706 15.000 1.000 11.000 1.00 0.00 O +ATOM 707 O WAT 707 15.000 1.000 13.000 1.00 0.00 O +ATOM 708 O WAT 708 15.000 1.000 15.000 1.00 0.00 O +ATOM 709 O WAT 709 15.000 1.000 17.000 1.00 0.00 O +ATOM 710 O WAT 710 15.000 1.000 19.000 1.00 0.00 O +ATOM 711 O WAT 711 15.000 3.000 1.000 1.00 0.00 O +ATOM 712 O WAT 712 15.000 3.000 3.000 1.00 0.00 O +ATOM 713 O WAT 713 15.000 3.000 5.000 1.00 0.00 O +ATOM 714 O WAT 714 15.000 3.000 7.000 1.00 0.00 O +ATOM 715 O WAT 715 15.000 3.000 9.000 1.00 0.00 O +ATOM 716 O WAT 716 15.000 3.000 11.000 1.00 0.00 O +ATOM 717 O WAT 717 15.000 3.000 13.000 1.00 0.00 O +ATOM 718 O WAT 718 15.000 3.000 15.000 1.00 0.00 O +ATOM 719 O WAT 719 15.000 3.000 17.000 1.00 0.00 O +ATOM 720 O WAT 720 15.000 3.000 19.000 1.00 0.00 O +ATOM 721 O WAT 721 15.000 5.000 1.000 1.00 0.00 O +ATOM 722 O WAT 722 15.000 5.000 3.000 1.00 0.00 O +ATOM 723 O WAT 723 15.000 5.000 5.000 1.00 0.00 O +ATOM 724 O WAT 724 15.000 5.000 7.000 1.00 0.00 O +ATOM 725 O WAT 725 15.000 5.000 9.000 1.00 0.00 O +ATOM 726 O WAT 726 15.000 5.000 11.000 1.00 0.00 O +ATOM 727 O WAT 727 15.000 5.000 13.000 1.00 0.00 O +ATOM 728 O WAT 728 15.000 5.000 15.000 1.00 0.00 O +ATOM 729 O WAT 729 15.000 5.000 17.000 1.00 0.00 O +ATOM 730 O WAT 730 15.000 5.000 19.000 1.00 0.00 O +ATOM 731 O WAT 731 15.000 7.000 1.000 1.00 0.00 O +ATOM 732 O WAT 732 15.000 7.000 3.000 1.00 0.00 O +ATOM 733 O WAT 733 15.000 7.000 5.000 1.00 0.00 O +ATOM 734 O WAT 734 15.000 7.000 7.000 1.00 0.00 O +ATOM 735 O WAT 735 15.000 7.000 9.000 1.00 0.00 O +ATOM 736 O WAT 736 15.000 7.000 11.000 1.00 0.00 O +ATOM 737 O WAT 737 15.000 7.000 13.000 1.00 0.00 O +ATOM 738 O WAT 738 15.000 7.000 15.000 1.00 0.00 O +ATOM 739 O WAT 739 15.000 7.000 17.000 1.00 0.00 O +ATOM 740 O WAT 740 15.000 7.000 19.000 1.00 0.00 O +ATOM 741 O WAT 741 15.000 9.000 1.000 1.00 0.00 O +ATOM 742 O WAT 742 15.000 9.000 3.000 1.00 0.00 O +ATOM 743 O WAT 743 15.000 9.000 5.000 1.00 0.00 O +ATOM 744 O WAT 744 15.000 9.000 7.000 1.00 0.00 O +ATOM 745 O WAT 745 15.000 9.000 9.000 1.00 0.00 O +ATOM 746 O WAT 746 15.000 9.000 11.000 1.00 0.00 O +ATOM 747 O WAT 747 15.000 9.000 13.000 1.00 0.00 O +ATOM 748 O WAT 748 15.000 9.000 15.000 1.00 0.00 O +ATOM 749 O WAT 749 15.000 9.000 17.000 1.00 0.00 O +ATOM 750 O WAT 750 15.000 9.000 19.000 1.00 0.00 O +ATOM 751 O WAT 751 15.000 11.000 1.000 1.00 0.00 O +ATOM 752 O WAT 752 15.000 11.000 3.000 1.00 0.00 O +ATOM 753 O WAT 753 15.000 11.000 5.000 1.00 0.00 O +ATOM 754 O WAT 754 15.000 11.000 7.000 1.00 0.00 O +ATOM 755 O WAT 755 15.000 11.000 9.000 1.00 0.00 O +ATOM 756 O WAT 756 15.000 11.000 11.000 1.00 0.00 O +ATOM 757 O WAT 757 15.000 11.000 13.000 1.00 0.00 O +ATOM 758 O WAT 758 15.000 11.000 15.000 1.00 0.00 O +ATOM 759 O WAT 759 15.000 11.000 17.000 1.00 0.00 O +ATOM 760 O WAT 760 15.000 11.000 19.000 1.00 0.00 O +ATOM 761 O WAT 761 15.000 13.000 1.000 1.00 0.00 O +ATOM 762 O WAT 762 15.000 13.000 3.000 1.00 0.00 O +ATOM 763 O WAT 763 15.000 13.000 5.000 1.00 0.00 O +ATOM 764 O WAT 764 15.000 13.000 7.000 1.00 0.00 O +ATOM 765 O WAT 765 15.000 13.000 9.000 1.00 0.00 O +ATOM 766 O WAT 766 15.000 13.000 11.000 1.00 0.00 O +ATOM 767 O WAT 767 15.000 13.000 13.000 1.00 0.00 O +ATOM 768 O WAT 768 15.000 13.000 15.000 1.00 0.00 O +ATOM 769 O WAT 769 15.000 13.000 17.000 1.00 0.00 O +ATOM 770 O WAT 770 15.000 13.000 19.000 1.00 0.00 O +ATOM 771 O WAT 771 15.000 15.000 1.000 1.00 0.00 O +ATOM 772 O WAT 772 15.000 15.000 3.000 1.00 0.00 O +ATOM 773 O WAT 773 15.000 15.000 5.000 1.00 0.00 O +ATOM 774 O WAT 774 15.000 15.000 7.000 1.00 0.00 O +ATOM 775 O WAT 775 15.000 15.000 9.000 1.00 0.00 O +ATOM 776 O WAT 776 15.000 15.000 11.000 1.00 0.00 O +ATOM 777 O WAT 777 15.000 15.000 13.000 1.00 0.00 O +ATOM 778 O WAT 778 15.000 15.000 15.000 1.00 0.00 O +ATOM 779 O WAT 779 15.000 15.000 17.000 1.00 0.00 O +ATOM 780 O WAT 780 15.000 15.000 19.000 1.00 0.00 O +ATOM 781 O WAT 781 15.000 17.000 1.000 1.00 0.00 O +ATOM 782 O WAT 782 15.000 17.000 3.000 1.00 0.00 O +ATOM 783 O WAT 783 15.000 17.000 5.000 1.00 0.00 O +ATOM 784 O WAT 784 15.000 17.000 7.000 1.00 0.00 O +ATOM 785 O WAT 785 15.000 17.000 9.000 1.00 0.00 O +ATOM 786 O WAT 786 15.000 17.000 11.000 1.00 0.00 O +ATOM 787 O WAT 787 15.000 17.000 13.000 1.00 0.00 O +ATOM 788 O WAT 788 15.000 17.000 15.000 1.00 0.00 O +ATOM 789 O WAT 789 15.000 17.000 17.000 1.00 0.00 O +ATOM 790 O WAT 790 15.000 17.000 19.000 1.00 0.00 O +ATOM 791 O WAT 791 15.000 19.000 1.000 1.00 0.00 O +ATOM 792 O WAT 792 15.000 19.000 3.000 1.00 0.00 O +ATOM 793 O WAT 793 15.000 19.000 5.000 1.00 0.00 O +ATOM 794 O WAT 794 15.000 19.000 7.000 1.00 0.00 O +ATOM 795 O WAT 795 15.000 19.000 9.000 1.00 0.00 O +ATOM 796 O WAT 796 15.000 19.000 11.000 1.00 0.00 O +ATOM 797 O WAT 797 15.000 19.000 13.000 1.00 0.00 O +ATOM 798 O WAT 798 15.000 19.000 15.000 1.00 0.00 O +ATOM 799 O WAT 799 15.000 19.000 17.000 1.00 0.00 O +ATOM 800 O WAT 800 15.000 19.000 19.000 1.00 0.00 O +ATOM 801 O WAT 801 17.000 1.000 1.000 1.00 0.00 O +ATOM 802 O WAT 802 17.000 1.000 3.000 1.00 0.00 O +ATOM 803 O WAT 803 17.000 1.000 5.000 1.00 0.00 O +ATOM 804 O WAT 804 17.000 1.000 7.000 1.00 0.00 O +ATOM 805 O WAT 805 17.000 1.000 9.000 1.00 0.00 O +ATOM 806 O WAT 806 17.000 1.000 11.000 1.00 0.00 O +ATOM 807 O WAT 807 17.000 1.000 13.000 1.00 0.00 O +ATOM 808 O WAT 808 17.000 1.000 15.000 1.00 0.00 O +ATOM 809 O WAT 809 17.000 1.000 17.000 1.00 0.00 O +ATOM 810 O WAT 810 17.000 1.000 19.000 1.00 0.00 O +ATOM 811 O WAT 811 17.000 3.000 1.000 1.00 0.00 O +ATOM 812 O WAT 812 17.000 3.000 3.000 1.00 0.00 O +ATOM 813 O WAT 813 17.000 3.000 5.000 1.00 0.00 O +ATOM 814 O WAT 814 17.000 3.000 7.000 1.00 0.00 O +ATOM 815 O WAT 815 17.000 3.000 9.000 1.00 0.00 O +ATOM 816 O WAT 816 17.000 3.000 11.000 1.00 0.00 O +ATOM 817 O WAT 817 17.000 3.000 13.000 1.00 0.00 O +ATOM 818 O WAT 818 17.000 3.000 15.000 1.00 0.00 O +ATOM 819 O WAT 819 17.000 3.000 17.000 1.00 0.00 O +ATOM 820 O WAT 820 17.000 3.000 19.000 1.00 0.00 O +ATOM 821 O WAT 821 17.000 5.000 1.000 1.00 0.00 O +ATOM 822 O WAT 822 17.000 5.000 3.000 1.00 0.00 O +ATOM 823 O WAT 823 17.000 5.000 5.000 1.00 0.00 O +ATOM 824 O WAT 824 17.000 5.000 7.000 1.00 0.00 O +ATOM 825 O WAT 825 17.000 5.000 9.000 1.00 0.00 O +ATOM 826 O WAT 826 17.000 5.000 11.000 1.00 0.00 O +ATOM 827 O WAT 827 17.000 5.000 13.000 1.00 0.00 O +ATOM 828 O WAT 828 17.000 5.000 15.000 1.00 0.00 O +ATOM 829 O WAT 829 17.000 5.000 17.000 1.00 0.00 O +ATOM 830 O WAT 830 17.000 5.000 19.000 1.00 0.00 O +ATOM 831 O WAT 831 17.000 7.000 1.000 1.00 0.00 O +ATOM 832 O WAT 832 17.000 7.000 3.000 1.00 0.00 O +ATOM 833 O WAT 833 17.000 7.000 5.000 1.00 0.00 O +ATOM 834 O WAT 834 17.000 7.000 7.000 1.00 0.00 O +ATOM 835 O WAT 835 17.000 7.000 9.000 1.00 0.00 O +ATOM 836 O WAT 836 17.000 7.000 11.000 1.00 0.00 O +ATOM 837 O WAT 837 17.000 7.000 13.000 1.00 0.00 O +ATOM 838 O WAT 838 17.000 7.000 15.000 1.00 0.00 O +ATOM 839 O WAT 839 17.000 7.000 17.000 1.00 0.00 O +ATOM 840 O WAT 840 17.000 7.000 19.000 1.00 0.00 O +ATOM 841 O WAT 841 17.000 9.000 1.000 1.00 0.00 O +ATOM 842 O WAT 842 17.000 9.000 3.000 1.00 0.00 O +ATOM 843 O WAT 843 17.000 9.000 5.000 1.00 0.00 O +ATOM 844 O WAT 844 17.000 9.000 7.000 1.00 0.00 O +ATOM 845 O WAT 845 17.000 9.000 9.000 1.00 0.00 O +ATOM 846 O WAT 846 17.000 9.000 11.000 1.00 0.00 O +ATOM 847 O WAT 847 17.000 9.000 13.000 1.00 0.00 O +ATOM 848 O WAT 848 17.000 9.000 15.000 1.00 0.00 O +ATOM 849 O WAT 849 17.000 9.000 17.000 1.00 0.00 O +ATOM 850 O WAT 850 17.000 9.000 19.000 1.00 0.00 O +ATOM 851 O WAT 851 17.000 11.000 1.000 1.00 0.00 O +ATOM 852 O WAT 852 17.000 11.000 3.000 1.00 0.00 O +ATOM 853 O WAT 853 17.000 11.000 5.000 1.00 0.00 O +ATOM 854 O WAT 854 17.000 11.000 7.000 1.00 0.00 O +ATOM 855 O WAT 855 17.000 11.000 9.000 1.00 0.00 O +ATOM 856 O WAT 856 17.000 11.000 11.000 1.00 0.00 O +ATOM 857 O WAT 857 17.000 11.000 13.000 1.00 0.00 O +ATOM 858 O WAT 858 17.000 11.000 15.000 1.00 0.00 O +ATOM 859 O WAT 859 17.000 11.000 17.000 1.00 0.00 O +ATOM 860 O WAT 860 17.000 11.000 19.000 1.00 0.00 O +ATOM 861 O WAT 861 17.000 13.000 1.000 1.00 0.00 O +ATOM 862 O WAT 862 17.000 13.000 3.000 1.00 0.00 O +ATOM 863 O WAT 863 17.000 13.000 5.000 1.00 0.00 O +ATOM 864 O WAT 864 17.000 13.000 7.000 1.00 0.00 O +ATOM 865 O WAT 865 17.000 13.000 9.000 1.00 0.00 O +ATOM 866 O WAT 866 17.000 13.000 11.000 1.00 0.00 O +ATOM 867 O WAT 867 17.000 13.000 13.000 1.00 0.00 O +ATOM 868 O WAT 868 17.000 13.000 15.000 1.00 0.00 O +ATOM 869 O WAT 869 17.000 13.000 17.000 1.00 0.00 O +ATOM 870 O WAT 870 17.000 13.000 19.000 1.00 0.00 O +ATOM 871 O WAT 871 17.000 15.000 1.000 1.00 0.00 O +ATOM 872 O WAT 872 17.000 15.000 3.000 1.00 0.00 O +ATOM 873 O WAT 873 17.000 15.000 5.000 1.00 0.00 O +ATOM 874 O WAT 874 17.000 15.000 7.000 1.00 0.00 O +ATOM 875 O WAT 875 17.000 15.000 9.000 1.00 0.00 O +ATOM 876 O WAT 876 17.000 15.000 11.000 1.00 0.00 O +ATOM 877 O WAT 877 17.000 15.000 13.000 1.00 0.00 O +ATOM 878 O WAT 878 17.000 15.000 15.000 1.00 0.00 O +ATOM 879 O WAT 879 17.000 15.000 17.000 1.00 0.00 O +ATOM 880 O WAT 880 17.000 15.000 19.000 1.00 0.00 O +ATOM 881 O WAT 881 17.000 17.000 1.000 1.00 0.00 O +ATOM 882 O WAT 882 17.000 17.000 3.000 1.00 0.00 O +ATOM 883 O WAT 883 17.000 17.000 5.000 1.00 0.00 O +ATOM 884 O WAT 884 17.000 17.000 7.000 1.00 0.00 O +ATOM 885 O WAT 885 17.000 17.000 9.000 1.00 0.00 O +ATOM 886 O WAT 886 17.000 17.000 11.000 1.00 0.00 O +ATOM 887 O WAT 887 17.000 17.000 13.000 1.00 0.00 O +ATOM 888 O WAT 888 17.000 17.000 15.000 1.00 0.00 O +ATOM 889 O WAT 889 17.000 17.000 17.000 1.00 0.00 O +ATOM 890 O WAT 890 17.000 17.000 19.000 1.00 0.00 O +ATOM 891 O WAT 891 17.000 19.000 1.000 1.00 0.00 O +ATOM 892 O WAT 892 17.000 19.000 3.000 1.00 0.00 O +ATOM 893 O WAT 893 17.000 19.000 5.000 1.00 0.00 O +ATOM 894 O WAT 894 17.000 19.000 7.000 1.00 0.00 O +ATOM 895 O WAT 895 17.000 19.000 9.000 1.00 0.00 O +ATOM 896 O WAT 896 17.000 19.000 11.000 1.00 0.00 O +ATOM 897 O WAT 897 17.000 19.000 13.000 1.00 0.00 O +ATOM 898 O WAT 898 17.000 19.000 15.000 1.00 0.00 O +ATOM 899 O WAT 899 17.000 19.000 17.000 1.00 0.00 O +ATOM 900 O WAT 900 17.000 19.000 19.000 1.00 0.00 O +ATOM 901 O WAT 901 19.000 1.000 1.000 1.00 0.00 O +ATOM 902 O WAT 902 19.000 1.000 3.000 1.00 0.00 O +ATOM 903 O WAT 903 19.000 1.000 5.000 1.00 0.00 O +ATOM 904 O WAT 904 19.000 1.000 7.000 1.00 0.00 O +ATOM 905 O WAT 905 19.000 1.000 9.000 1.00 0.00 O +ATOM 906 O WAT 906 19.000 1.000 11.000 1.00 0.00 O +ATOM 907 O WAT 907 19.000 1.000 13.000 1.00 0.00 O +ATOM 908 O WAT 908 19.000 1.000 15.000 1.00 0.00 O +ATOM 909 O WAT 909 19.000 1.000 17.000 1.00 0.00 O +ATOM 910 O WAT 910 19.000 1.000 19.000 1.00 0.00 O +ATOM 911 O WAT 911 19.000 3.000 1.000 1.00 0.00 O +ATOM 912 O WAT 912 19.000 3.000 3.000 1.00 0.00 O +ATOM 913 O WAT 913 19.000 3.000 5.000 1.00 0.00 O +ATOM 914 O WAT 914 19.000 3.000 7.000 1.00 0.00 O +ATOM 915 O WAT 915 19.000 3.000 9.000 1.00 0.00 O +ATOM 916 O WAT 916 19.000 3.000 11.000 1.00 0.00 O +ATOM 917 O WAT 917 19.000 3.000 13.000 1.00 0.00 O +ATOM 918 O WAT 918 19.000 3.000 15.000 1.00 0.00 O +ATOM 919 O WAT 919 19.000 3.000 17.000 1.00 0.00 O +ATOM 920 O WAT 920 19.000 3.000 19.000 1.00 0.00 O +ATOM 921 O WAT 921 19.000 5.000 1.000 1.00 0.00 O +ATOM 922 O WAT 922 19.000 5.000 3.000 1.00 0.00 O +ATOM 923 O WAT 923 19.000 5.000 5.000 1.00 0.00 O +ATOM 924 O WAT 924 19.000 5.000 7.000 1.00 0.00 O +ATOM 925 O WAT 925 19.000 5.000 9.000 1.00 0.00 O +ATOM 926 O WAT 926 19.000 5.000 11.000 1.00 0.00 O +ATOM 927 O WAT 927 19.000 5.000 13.000 1.00 0.00 O +ATOM 928 O WAT 928 19.000 5.000 15.000 1.00 0.00 O +ATOM 929 O WAT 929 19.000 5.000 17.000 1.00 0.00 O +ATOM 930 O WAT 930 19.000 5.000 19.000 1.00 0.00 O +ATOM 931 O WAT 931 19.000 7.000 1.000 1.00 0.00 O +ATOM 932 O WAT 932 19.000 7.000 3.000 1.00 0.00 O +ATOM 933 O WAT 933 19.000 7.000 5.000 1.00 0.00 O +ATOM 934 O WAT 934 19.000 7.000 7.000 1.00 0.00 O +ATOM 935 O WAT 935 19.000 7.000 9.000 1.00 0.00 O +ATOM 936 O WAT 936 19.000 7.000 11.000 1.00 0.00 O +ATOM 937 O WAT 937 19.000 7.000 13.000 1.00 0.00 O +ATOM 938 O WAT 938 19.000 7.000 15.000 1.00 0.00 O +ATOM 939 O WAT 939 19.000 7.000 17.000 1.00 0.00 O +ATOM 940 O WAT 940 19.000 7.000 19.000 1.00 0.00 O +ATOM 941 O WAT 941 19.000 9.000 1.000 1.00 0.00 O +ATOM 942 O WAT 942 19.000 9.000 3.000 1.00 0.00 O +ATOM 943 O WAT 943 19.000 9.000 5.000 1.00 0.00 O +ATOM 944 O WAT 944 19.000 9.000 7.000 1.00 0.00 O +ATOM 945 O WAT 945 19.000 9.000 9.000 1.00 0.00 O +ATOM 946 O WAT 946 19.000 9.000 11.000 1.00 0.00 O +ATOM 947 O WAT 947 19.000 9.000 13.000 1.00 0.00 O +ATOM 948 O WAT 948 19.000 9.000 15.000 1.00 0.00 O +ATOM 949 O WAT 949 19.000 9.000 17.000 1.00 0.00 O +ATOM 950 O WAT 950 19.000 9.000 19.000 1.00 0.00 O +ATOM 951 O WAT 951 19.000 11.000 1.000 1.00 0.00 O +ATOM 952 O WAT 952 19.000 11.000 3.000 1.00 0.00 O +ATOM 953 O WAT 953 19.000 11.000 5.000 1.00 0.00 O +ATOM 954 O WAT 954 19.000 11.000 7.000 1.00 0.00 O +ATOM 955 O WAT 955 19.000 11.000 9.000 1.00 0.00 O +ATOM 956 O WAT 956 19.000 11.000 11.000 1.00 0.00 O +ATOM 957 O WAT 957 19.000 11.000 13.000 1.00 0.00 O +ATOM 958 O WAT 958 19.000 11.000 15.000 1.00 0.00 O +ATOM 959 O WAT 959 19.000 11.000 17.000 1.00 0.00 O +ATOM 960 O WAT 960 19.000 11.000 19.000 1.00 0.00 O +ATOM 961 O WAT 961 19.000 13.000 1.000 1.00 0.00 O +ATOM 962 O WAT 962 19.000 13.000 3.000 1.00 0.00 O +ATOM 963 O WAT 963 19.000 13.000 5.000 1.00 0.00 O +ATOM 964 O WAT 964 19.000 13.000 7.000 1.00 0.00 O +ATOM 965 O WAT 965 19.000 13.000 9.000 1.00 0.00 O +ATOM 966 O WAT 966 19.000 13.000 11.000 1.00 0.00 O +ATOM 967 O WAT 967 19.000 13.000 13.000 1.00 0.00 O +ATOM 968 O WAT 968 19.000 13.000 15.000 1.00 0.00 O +ATOM 969 O WAT 969 19.000 13.000 17.000 1.00 0.00 O +ATOM 970 O WAT 970 19.000 13.000 19.000 1.00 0.00 O +ATOM 971 O WAT 971 19.000 15.000 1.000 1.00 0.00 O +ATOM 972 O WAT 972 19.000 15.000 3.000 1.00 0.00 O +ATOM 973 O WAT 973 19.000 15.000 5.000 1.00 0.00 O +ATOM 974 O WAT 974 19.000 15.000 7.000 1.00 0.00 O +ATOM 975 O WAT 975 19.000 15.000 9.000 1.00 0.00 O +ATOM 976 O WAT 976 19.000 15.000 11.000 1.00 0.00 O +ATOM 977 O WAT 977 19.000 15.000 13.000 1.00 0.00 O +ATOM 978 O WAT 978 19.000 15.000 15.000 1.00 0.00 O +ATOM 979 O WAT 979 19.000 15.000 17.000 1.00 0.00 O +ATOM 980 O WAT 980 19.000 15.000 19.000 1.00 0.00 O +ATOM 981 O WAT 981 19.000 17.000 1.000 1.00 0.00 O +ATOM 982 O WAT 982 19.000 17.000 3.000 1.00 0.00 O +ATOM 983 O WAT 983 19.000 17.000 5.000 1.00 0.00 O +ATOM 984 O WAT 984 19.000 17.000 7.000 1.00 0.00 O +ATOM 985 O WAT 985 19.000 17.000 9.000 1.00 0.00 O +ATOM 986 O WAT 986 19.000 17.000 11.000 1.00 0.00 O +ATOM 987 O WAT 987 19.000 17.000 13.000 1.00 0.00 O +ATOM 988 O WAT 988 19.000 17.000 15.000 1.00 0.00 O +ATOM 989 O WAT 989 19.000 17.000 17.000 1.00 0.00 O +ATOM 990 O WAT 990 19.000 17.000 19.000 1.00 0.00 O +ATOM 991 O WAT 991 19.000 19.000 1.000 1.00 0.00 O +ATOM 992 O WAT 992 19.000 19.000 3.000 1.00 0.00 O +ATOM 993 O WAT 993 19.000 19.000 5.000 1.00 0.00 O +ATOM 994 O WAT 994 19.000 19.000 7.000 1.00 0.00 O +ATOM 995 O WAT 995 19.000 19.000 9.000 1.00 0.00 O +ATOM 996 O WAT 996 19.000 19.000 11.000 1.00 0.00 O +ATOM 997 O WAT 997 19.000 19.000 13.000 1.00 0.00 O +ATOM 998 O WAT 998 19.000 19.000 15.000 1.00 0.00 O +ATOM 999 O WAT 999 19.000 19.000 17.000 1.00 0.00 O +ATOM 1000 O WAT 1000 19.000 19.000 19.000 1.00 0.00 O +END diff --git a/test/Test_SurfTension/st.itim.dat.save b/test/Test_SurfTension/st.itim.dat.save new file mode 100644 index 0000000000..f0659b28f3 --- /dev/null +++ b/test/Test_SurfTension/st.itim.dat.save @@ -0,0 +1,17 @@ +# surftension summary +temperature 300 +nsurf 2 +normal z +interface itim +mask :WAT@O +L_t1 20 +L_t2 20 +area 400 +q_fundamental 0.314159 +qmin 0.314159 +qmax 0.8 +frames 1 +skipped 0 +roughness 0 +roughness_upper 0 +roughness_lower 0 diff --git a/test/Test_SurfTension/st.normalx.dat.save b/test/Test_SurfTension/st.normalx.dat.save new file mode 100644 index 0000000000..fa365576d4 --- /dev/null +++ b/test/Test_SurfTension/st.normalx.dat.save @@ -0,0 +1,20 @@ +# surftension summary +temperature 300 +nsurf 2 +normal x +interface willard +mask :WAT@O +L_t1 20 +L_t2 20 +area 400 +q_fundamental 0.314159 +qmin 0.314159 +qmax 0.8 +frames 1 +skipped 0 +gamma 849.84 +gamma_upper 849.84 +gamma_lower 849.84 +roughness 0.222848 +roughness_upper 0.222848 +roughness_lower 0.222848 diff --git a/test/Test_SurfTension/st.normaly.dat.save b/test/Test_SurfTension/st.normaly.dat.save new file mode 100644 index 0000000000..bd7ab194f1 --- /dev/null +++ b/test/Test_SurfTension/st.normaly.dat.save @@ -0,0 +1,20 @@ +# surftension summary +temperature 300 +nsurf 2 +normal y +interface willard +mask :WAT@O +L_t1 20 +L_t2 20 +area 400 +q_fundamental 0.314159 +qmin 0.314159 +qmax 0.8 +frames 1 +skipped 0 +gamma 849.84 +gamma_upper 849.84 +gamma_lower 849.84 +roughness 0.222848 +roughness_upper 0.222848 +roughness_lower 0.222848 diff --git a/test/Test_SurfTension/st.nsurf1.dat.save b/test/Test_SurfTension/st.nsurf1.dat.save new file mode 100644 index 0000000000..7b7042973b --- /dev/null +++ b/test/Test_SurfTension/st.nsurf1.dat.save @@ -0,0 +1,18 @@ +# surftension summary +temperature 300 +nsurf 1 +normal z +interface willard +mask :WAT@O +L_t1 20 +L_t2 20 +area 400 +q_fundamental 0.314159 +qmin 0.314159 +qmax 0.8 +frames 1 +skipped 0 +gamma 849.84 +gamma_upper 849.84 +roughness 0.222848 +roughness_upper 0.222848 diff --git a/test/Test_SurfTension/st.willard.dat.save b/test/Test_SurfTension/st.willard.dat.save new file mode 100644 index 0000000000..f257deb3b5 --- /dev/null +++ b/test/Test_SurfTension/st.willard.dat.save @@ -0,0 +1,20 @@ +# surftension summary +temperature 300 +nsurf 2 +normal z +interface willard +mask :WAT@O +L_t1 20 +L_t2 20 +area 400 +q_fundamental 0.314159 +qmin 0.314159 +qmax 0.8 +frames 1 +skipped 0 +gamma 849.84 +gamma_upper 849.84 +gamma_lower 849.84 +roughness 0.222848 +roughness_upper 0.222848 +roughness_lower 0.222848 diff --git a/test/Test_SurfTension/st2_summary.dat.save b/test/Test_SurfTension/st2_summary.dat.save new file mode 100644 index 0000000000..b3cad2b69f --- /dev/null +++ b/test/Test_SurfTension/st2_summary.dat.save @@ -0,0 +1,21 @@ +# surftension summary +temperature 300 +nsurf 2 +normal z +interface willard +mask :WAT@O +mask2 :WAT@O +L_t1 20 +L_t2 20 +area 400 +q_fundamental 0.314159 +qmin 0.314159 +qmax 0.8 +frames 1 +skipped 0 +gamma 849.84 +gamma_upper 849.84 +gamma_lower 849.84 +roughness 0.222848 +roughness_upper 0.222848 +roughness_lower 0.222848 From b44dd8100af25df74806d4ba488c56c203b3a6ca Mon Sep 17 00:00:00 2001 From: ndlevinzon Date: Wed, 2 Sep 2026 11:13:28 -0600 Subject: [PATCH 15/17] Update surftension test files and parameters for improved accuracy - Enhanced RunTest.sh documentation to clarify the characteristics of slab.pdb. - Updated surface tension data files with new gamma and roughness values for better simulation fidelity. - Adjusted parameters in st.itim.dat.save, st.normalx.dat.save, st.normaly.dat.save, st.nsurf1.dat.save, st.willard.dat.save, and st2_summary.dat.save to reflect recent findings and improve test results. --- test/Test_SurfTension/RunTest.sh | 5 +- test/Test_SurfTension/slab.pdb | 2002 ++++++++++---------- test/Test_SurfTension/st.itim.dat.save | 9 +- test/Test_SurfTension/st.normalx.dat.save | 13 +- test/Test_SurfTension/st.normaly.dat.save | 12 +- test/Test_SurfTension/st.nsurf1.dat.save | 8 +- test/Test_SurfTension/st.willard.dat.save | 12 +- test/Test_SurfTension/st2_summary.dat.save | 12 +- 8 files changed, 1039 insertions(+), 1034 deletions(-) diff --git a/test/Test_SurfTension/RunTest.sh b/test/Test_SurfTension/RunTest.sh index c8dd71549e..5ba5c78b0e 100755 --- a/test/Test_SurfTension/RunTest.sh +++ b/test/Test_SurfTension/RunTest.sh @@ -1,7 +1,8 @@ #!/bin/bash # surftension tests. -# slab.pdb is a 20 A cubic lattice of O atoms. Stretching one box length -# creates vacuum on both sides of a slab so Willard/ITIM can find interfaces. +# slab.pdb is a 20 A cubic lattice of O atoms with a small z-corrugation +# so ITIM min/max is not flat. Stretching one box length creates vacuum +# on both sides of a slab so Willard/ITIM can find interfaces. . ../MasterTest.sh diff --git a/test/Test_SurfTension/slab.pdb b/test/Test_SurfTension/slab.pdb index 569238ab15..51c5fc1dd3 100644 --- a/test/Test_SurfTension/slab.pdb +++ b/test/Test_SurfTension/slab.pdb @@ -1,1003 +1,1003 @@ CRYST1 20.000 20.000 20.000 90.00 90.00 90.00 P 1 1 -REMARK synthetic cubic lattice for surftension tests -ATOM 1 O WAT 1 1.000 1.000 1.000 1.00 0.00 O -ATOM 2 O WAT 2 1.000 1.000 3.000 1.00 0.00 O -ATOM 3 O WAT 3 1.000 1.000 5.000 1.00 0.00 O -ATOM 4 O WAT 4 1.000 1.000 7.000 1.00 0.00 O -ATOM 5 O WAT 5 1.000 1.000 9.000 1.00 0.00 O -ATOM 6 O WAT 6 1.000 1.000 11.000 1.00 0.00 O -ATOM 7 O WAT 7 1.000 1.000 13.000 1.00 0.00 O -ATOM 8 O WAT 8 1.000 1.000 15.000 1.00 0.00 O -ATOM 9 O WAT 9 1.000 1.000 17.000 1.00 0.00 O -ATOM 10 O WAT 10 1.000 1.000 19.000 1.00 0.00 O -ATOM 11 O WAT 11 1.000 3.000 1.000 1.00 0.00 O -ATOM 12 O WAT 12 1.000 3.000 3.000 1.00 0.00 O -ATOM 13 O WAT 13 1.000 3.000 5.000 1.00 0.00 O -ATOM 14 O WAT 14 1.000 3.000 7.000 1.00 0.00 O -ATOM 15 O WAT 15 1.000 3.000 9.000 1.00 0.00 O -ATOM 16 O WAT 16 1.000 3.000 11.000 1.00 0.00 O -ATOM 17 O WAT 17 1.000 3.000 13.000 1.00 0.00 O -ATOM 18 O WAT 18 1.000 3.000 15.000 1.00 0.00 O -ATOM 19 O WAT 19 1.000 3.000 17.000 1.00 0.00 O -ATOM 20 O WAT 20 1.000 3.000 19.000 1.00 0.00 O -ATOM 21 O WAT 21 1.000 5.000 1.000 1.00 0.00 O -ATOM 22 O WAT 22 1.000 5.000 3.000 1.00 0.00 O -ATOM 23 O WAT 23 1.000 5.000 5.000 1.00 0.00 O -ATOM 24 O WAT 24 1.000 5.000 7.000 1.00 0.00 O -ATOM 25 O WAT 25 1.000 5.000 9.000 1.00 0.00 O -ATOM 26 O WAT 26 1.000 5.000 11.000 1.00 0.00 O -ATOM 27 O WAT 27 1.000 5.000 13.000 1.00 0.00 O -ATOM 28 O WAT 28 1.000 5.000 15.000 1.00 0.00 O -ATOM 29 O WAT 29 1.000 5.000 17.000 1.00 0.00 O -ATOM 30 O WAT 30 1.000 5.000 19.000 1.00 0.00 O -ATOM 31 O WAT 31 1.000 7.000 1.000 1.00 0.00 O -ATOM 32 O WAT 32 1.000 7.000 3.000 1.00 0.00 O -ATOM 33 O WAT 33 1.000 7.000 5.000 1.00 0.00 O -ATOM 34 O WAT 34 1.000 7.000 7.000 1.00 0.00 O -ATOM 35 O WAT 35 1.000 7.000 9.000 1.00 0.00 O -ATOM 36 O WAT 36 1.000 7.000 11.000 1.00 0.00 O -ATOM 37 O WAT 37 1.000 7.000 13.000 1.00 0.00 O -ATOM 38 O WAT 38 1.000 7.000 15.000 1.00 0.00 O -ATOM 39 O WAT 39 1.000 7.000 17.000 1.00 0.00 O -ATOM 40 O WAT 40 1.000 7.000 19.000 1.00 0.00 O -ATOM 41 O WAT 41 1.000 9.000 1.000 1.00 0.00 O -ATOM 42 O WAT 42 1.000 9.000 3.000 1.00 0.00 O -ATOM 43 O WAT 43 1.000 9.000 5.000 1.00 0.00 O -ATOM 44 O WAT 44 1.000 9.000 7.000 1.00 0.00 O -ATOM 45 O WAT 45 1.000 9.000 9.000 1.00 0.00 O -ATOM 46 O WAT 46 1.000 9.000 11.000 1.00 0.00 O -ATOM 47 O WAT 47 1.000 9.000 13.000 1.00 0.00 O -ATOM 48 O WAT 48 1.000 9.000 15.000 1.00 0.00 O -ATOM 49 O WAT 49 1.000 9.000 17.000 1.00 0.00 O -ATOM 50 O WAT 50 1.000 9.000 19.000 1.00 0.00 O -ATOM 51 O WAT 51 1.000 11.000 1.000 1.00 0.00 O -ATOM 52 O WAT 52 1.000 11.000 3.000 1.00 0.00 O -ATOM 53 O WAT 53 1.000 11.000 5.000 1.00 0.00 O -ATOM 54 O WAT 54 1.000 11.000 7.000 1.00 0.00 O -ATOM 55 O WAT 55 1.000 11.000 9.000 1.00 0.00 O -ATOM 56 O WAT 56 1.000 11.000 11.000 1.00 0.00 O -ATOM 57 O WAT 57 1.000 11.000 13.000 1.00 0.00 O -ATOM 58 O WAT 58 1.000 11.000 15.000 1.00 0.00 O -ATOM 59 O WAT 59 1.000 11.000 17.000 1.00 0.00 O -ATOM 60 O WAT 60 1.000 11.000 19.000 1.00 0.00 O -ATOM 61 O WAT 61 1.000 13.000 1.000 1.00 0.00 O -ATOM 62 O WAT 62 1.000 13.000 3.000 1.00 0.00 O -ATOM 63 O WAT 63 1.000 13.000 5.000 1.00 0.00 O -ATOM 64 O WAT 64 1.000 13.000 7.000 1.00 0.00 O -ATOM 65 O WAT 65 1.000 13.000 9.000 1.00 0.00 O -ATOM 66 O WAT 66 1.000 13.000 11.000 1.00 0.00 O -ATOM 67 O WAT 67 1.000 13.000 13.000 1.00 0.00 O -ATOM 68 O WAT 68 1.000 13.000 15.000 1.00 0.00 O -ATOM 69 O WAT 69 1.000 13.000 17.000 1.00 0.00 O -ATOM 70 O WAT 70 1.000 13.000 19.000 1.00 0.00 O -ATOM 71 O WAT 71 1.000 15.000 1.000 1.00 0.00 O -ATOM 72 O WAT 72 1.000 15.000 3.000 1.00 0.00 O -ATOM 73 O WAT 73 1.000 15.000 5.000 1.00 0.00 O -ATOM 74 O WAT 74 1.000 15.000 7.000 1.00 0.00 O -ATOM 75 O WAT 75 1.000 15.000 9.000 1.00 0.00 O -ATOM 76 O WAT 76 1.000 15.000 11.000 1.00 0.00 O -ATOM 77 O WAT 77 1.000 15.000 13.000 1.00 0.00 O -ATOM 78 O WAT 78 1.000 15.000 15.000 1.00 0.00 O -ATOM 79 O WAT 79 1.000 15.000 17.000 1.00 0.00 O -ATOM 80 O WAT 80 1.000 15.000 19.000 1.00 0.00 O -ATOM 81 O WAT 81 1.000 17.000 1.000 1.00 0.00 O -ATOM 82 O WAT 82 1.000 17.000 3.000 1.00 0.00 O -ATOM 83 O WAT 83 1.000 17.000 5.000 1.00 0.00 O -ATOM 84 O WAT 84 1.000 17.000 7.000 1.00 0.00 O -ATOM 85 O WAT 85 1.000 17.000 9.000 1.00 0.00 O -ATOM 86 O WAT 86 1.000 17.000 11.000 1.00 0.00 O -ATOM 87 O WAT 87 1.000 17.000 13.000 1.00 0.00 O -ATOM 88 O WAT 88 1.000 17.000 15.000 1.00 0.00 O -ATOM 89 O WAT 89 1.000 17.000 17.000 1.00 0.00 O -ATOM 90 O WAT 90 1.000 17.000 19.000 1.00 0.00 O -ATOM 91 O WAT 91 1.000 19.000 1.000 1.00 0.00 O -ATOM 92 O WAT 92 1.000 19.000 3.000 1.00 0.00 O -ATOM 93 O WAT 93 1.000 19.000 5.000 1.00 0.00 O -ATOM 94 O WAT 94 1.000 19.000 7.000 1.00 0.00 O -ATOM 95 O WAT 95 1.000 19.000 9.000 1.00 0.00 O -ATOM 96 O WAT 96 1.000 19.000 11.000 1.00 0.00 O -ATOM 97 O WAT 97 1.000 19.000 13.000 1.00 0.00 O -ATOM 98 O WAT 98 1.000 19.000 15.000 1.00 0.00 O -ATOM 99 O WAT 99 1.000 19.000 17.000 1.00 0.00 O -ATOM 100 O WAT 100 1.000 19.000 19.000 1.00 0.00 O -ATOM 101 O WAT 101 3.000 1.000 1.000 1.00 0.00 O -ATOM 102 O WAT 102 3.000 1.000 3.000 1.00 0.00 O -ATOM 103 O WAT 103 3.000 1.000 5.000 1.00 0.00 O -ATOM 104 O WAT 104 3.000 1.000 7.000 1.00 0.00 O -ATOM 105 O WAT 105 3.000 1.000 9.000 1.00 0.00 O -ATOM 106 O WAT 106 3.000 1.000 11.000 1.00 0.00 O -ATOM 107 O WAT 107 3.000 1.000 13.000 1.00 0.00 O -ATOM 108 O WAT 108 3.000 1.000 15.000 1.00 0.00 O -ATOM 109 O WAT 109 3.000 1.000 17.000 1.00 0.00 O -ATOM 110 O WAT 110 3.000 1.000 19.000 1.00 0.00 O -ATOM 111 O WAT 111 3.000 3.000 1.000 1.00 0.00 O -ATOM 112 O WAT 112 3.000 3.000 3.000 1.00 0.00 O -ATOM 113 O WAT 113 3.000 3.000 5.000 1.00 0.00 O -ATOM 114 O WAT 114 3.000 3.000 7.000 1.00 0.00 O -ATOM 115 O WAT 115 3.000 3.000 9.000 1.00 0.00 O -ATOM 116 O WAT 116 3.000 3.000 11.000 1.00 0.00 O -ATOM 117 O WAT 117 3.000 3.000 13.000 1.00 0.00 O -ATOM 118 O WAT 118 3.000 3.000 15.000 1.00 0.00 O -ATOM 119 O WAT 119 3.000 3.000 17.000 1.00 0.00 O -ATOM 120 O WAT 120 3.000 3.000 19.000 1.00 0.00 O -ATOM 121 O WAT 121 3.000 5.000 1.000 1.00 0.00 O -ATOM 122 O WAT 122 3.000 5.000 3.000 1.00 0.00 O -ATOM 123 O WAT 123 3.000 5.000 5.000 1.00 0.00 O -ATOM 124 O WAT 124 3.000 5.000 7.000 1.00 0.00 O -ATOM 125 O WAT 125 3.000 5.000 9.000 1.00 0.00 O -ATOM 126 O WAT 126 3.000 5.000 11.000 1.00 0.00 O -ATOM 127 O WAT 127 3.000 5.000 13.000 1.00 0.00 O -ATOM 128 O WAT 128 3.000 5.000 15.000 1.00 0.00 O -ATOM 129 O WAT 129 3.000 5.000 17.000 1.00 0.00 O -ATOM 130 O WAT 130 3.000 5.000 19.000 1.00 0.00 O -ATOM 131 O WAT 131 3.000 7.000 1.000 1.00 0.00 O -ATOM 132 O WAT 132 3.000 7.000 3.000 1.00 0.00 O -ATOM 133 O WAT 133 3.000 7.000 5.000 1.00 0.00 O -ATOM 134 O WAT 134 3.000 7.000 7.000 1.00 0.00 O -ATOM 135 O WAT 135 3.000 7.000 9.000 1.00 0.00 O -ATOM 136 O WAT 136 3.000 7.000 11.000 1.00 0.00 O -ATOM 137 O WAT 137 3.000 7.000 13.000 1.00 0.00 O -ATOM 138 O WAT 138 3.000 7.000 15.000 1.00 0.00 O -ATOM 139 O WAT 139 3.000 7.000 17.000 1.00 0.00 O -ATOM 140 O WAT 140 3.000 7.000 19.000 1.00 0.00 O -ATOM 141 O WAT 141 3.000 9.000 1.000 1.00 0.00 O -ATOM 142 O WAT 142 3.000 9.000 3.000 1.00 0.00 O -ATOM 143 O WAT 143 3.000 9.000 5.000 1.00 0.00 O -ATOM 144 O WAT 144 3.000 9.000 7.000 1.00 0.00 O -ATOM 145 O WAT 145 3.000 9.000 9.000 1.00 0.00 O -ATOM 146 O WAT 146 3.000 9.000 11.000 1.00 0.00 O -ATOM 147 O WAT 147 3.000 9.000 13.000 1.00 0.00 O -ATOM 148 O WAT 148 3.000 9.000 15.000 1.00 0.00 O -ATOM 149 O WAT 149 3.000 9.000 17.000 1.00 0.00 O -ATOM 150 O WAT 150 3.000 9.000 19.000 1.00 0.00 O -ATOM 151 O WAT 151 3.000 11.000 1.000 1.00 0.00 O -ATOM 152 O WAT 152 3.000 11.000 3.000 1.00 0.00 O -ATOM 153 O WAT 153 3.000 11.000 5.000 1.00 0.00 O -ATOM 154 O WAT 154 3.000 11.000 7.000 1.00 0.00 O -ATOM 155 O WAT 155 3.000 11.000 9.000 1.00 0.00 O -ATOM 156 O WAT 156 3.000 11.000 11.000 1.00 0.00 O -ATOM 157 O WAT 157 3.000 11.000 13.000 1.00 0.00 O -ATOM 158 O WAT 158 3.000 11.000 15.000 1.00 0.00 O -ATOM 159 O WAT 159 3.000 11.000 17.000 1.00 0.00 O -ATOM 160 O WAT 160 3.000 11.000 19.000 1.00 0.00 O -ATOM 161 O WAT 161 3.000 13.000 1.000 1.00 0.00 O -ATOM 162 O WAT 162 3.000 13.000 3.000 1.00 0.00 O -ATOM 163 O WAT 163 3.000 13.000 5.000 1.00 0.00 O -ATOM 164 O WAT 164 3.000 13.000 7.000 1.00 0.00 O -ATOM 165 O WAT 165 3.000 13.000 9.000 1.00 0.00 O -ATOM 166 O WAT 166 3.000 13.000 11.000 1.00 0.00 O -ATOM 167 O WAT 167 3.000 13.000 13.000 1.00 0.00 O -ATOM 168 O WAT 168 3.000 13.000 15.000 1.00 0.00 O -ATOM 169 O WAT 169 3.000 13.000 17.000 1.00 0.00 O -ATOM 170 O WAT 170 3.000 13.000 19.000 1.00 0.00 O -ATOM 171 O WAT 171 3.000 15.000 1.000 1.00 0.00 O -ATOM 172 O WAT 172 3.000 15.000 3.000 1.00 0.00 O -ATOM 173 O WAT 173 3.000 15.000 5.000 1.00 0.00 O -ATOM 174 O WAT 174 3.000 15.000 7.000 1.00 0.00 O -ATOM 175 O WAT 175 3.000 15.000 9.000 1.00 0.00 O -ATOM 176 O WAT 176 3.000 15.000 11.000 1.00 0.00 O -ATOM 177 O WAT 177 3.000 15.000 13.000 1.00 0.00 O -ATOM 178 O WAT 178 3.000 15.000 15.000 1.00 0.00 O -ATOM 179 O WAT 179 3.000 15.000 17.000 1.00 0.00 O -ATOM 180 O WAT 180 3.000 15.000 19.000 1.00 0.00 O -ATOM 181 O WAT 181 3.000 17.000 1.000 1.00 0.00 O -ATOM 182 O WAT 182 3.000 17.000 3.000 1.00 0.00 O -ATOM 183 O WAT 183 3.000 17.000 5.000 1.00 0.00 O -ATOM 184 O WAT 184 3.000 17.000 7.000 1.00 0.00 O -ATOM 185 O WAT 185 3.000 17.000 9.000 1.00 0.00 O -ATOM 186 O WAT 186 3.000 17.000 11.000 1.00 0.00 O -ATOM 187 O WAT 187 3.000 17.000 13.000 1.00 0.00 O -ATOM 188 O WAT 188 3.000 17.000 15.000 1.00 0.00 O -ATOM 189 O WAT 189 3.000 17.000 17.000 1.00 0.00 O -ATOM 190 O WAT 190 3.000 17.000 19.000 1.00 0.00 O -ATOM 191 O WAT 191 3.000 19.000 1.000 1.00 0.00 O -ATOM 192 O WAT 192 3.000 19.000 3.000 1.00 0.00 O -ATOM 193 O WAT 193 3.000 19.000 5.000 1.00 0.00 O -ATOM 194 O WAT 194 3.000 19.000 7.000 1.00 0.00 O -ATOM 195 O WAT 195 3.000 19.000 9.000 1.00 0.00 O -ATOM 196 O WAT 196 3.000 19.000 11.000 1.00 0.00 O -ATOM 197 O WAT 197 3.000 19.000 13.000 1.00 0.00 O -ATOM 198 O WAT 198 3.000 19.000 15.000 1.00 0.00 O -ATOM 199 O WAT 199 3.000 19.000 17.000 1.00 0.00 O -ATOM 200 O WAT 200 3.000 19.000 19.000 1.00 0.00 O -ATOM 201 O WAT 201 5.000 1.000 1.000 1.00 0.00 O -ATOM 202 O WAT 202 5.000 1.000 3.000 1.00 0.00 O -ATOM 203 O WAT 203 5.000 1.000 5.000 1.00 0.00 O -ATOM 204 O WAT 204 5.000 1.000 7.000 1.00 0.00 O -ATOM 205 O WAT 205 5.000 1.000 9.000 1.00 0.00 O -ATOM 206 O WAT 206 5.000 1.000 11.000 1.00 0.00 O -ATOM 207 O WAT 207 5.000 1.000 13.000 1.00 0.00 O -ATOM 208 O WAT 208 5.000 1.000 15.000 1.00 0.00 O -ATOM 209 O WAT 209 5.000 1.000 17.000 1.00 0.00 O -ATOM 210 O WAT 210 5.000 1.000 19.000 1.00 0.00 O -ATOM 211 O WAT 211 5.000 3.000 1.000 1.00 0.00 O -ATOM 212 O WAT 212 5.000 3.000 3.000 1.00 0.00 O -ATOM 213 O WAT 213 5.000 3.000 5.000 1.00 0.00 O -ATOM 214 O WAT 214 5.000 3.000 7.000 1.00 0.00 O -ATOM 215 O WAT 215 5.000 3.000 9.000 1.00 0.00 O -ATOM 216 O WAT 216 5.000 3.000 11.000 1.00 0.00 O -ATOM 217 O WAT 217 5.000 3.000 13.000 1.00 0.00 O -ATOM 218 O WAT 218 5.000 3.000 15.000 1.00 0.00 O -ATOM 219 O WAT 219 5.000 3.000 17.000 1.00 0.00 O -ATOM 220 O WAT 220 5.000 3.000 19.000 1.00 0.00 O -ATOM 221 O WAT 221 5.000 5.000 1.000 1.00 0.00 O -ATOM 222 O WAT 222 5.000 5.000 3.000 1.00 0.00 O -ATOM 223 O WAT 223 5.000 5.000 5.000 1.00 0.00 O -ATOM 224 O WAT 224 5.000 5.000 7.000 1.00 0.00 O -ATOM 225 O WAT 225 5.000 5.000 9.000 1.00 0.00 O -ATOM 226 O WAT 226 5.000 5.000 11.000 1.00 0.00 O -ATOM 227 O WAT 227 5.000 5.000 13.000 1.00 0.00 O -ATOM 228 O WAT 228 5.000 5.000 15.000 1.00 0.00 O -ATOM 229 O WAT 229 5.000 5.000 17.000 1.00 0.00 O -ATOM 230 O WAT 230 5.000 5.000 19.000 1.00 0.00 O -ATOM 231 O WAT 231 5.000 7.000 1.000 1.00 0.00 O -ATOM 232 O WAT 232 5.000 7.000 3.000 1.00 0.00 O -ATOM 233 O WAT 233 5.000 7.000 5.000 1.00 0.00 O -ATOM 234 O WAT 234 5.000 7.000 7.000 1.00 0.00 O -ATOM 235 O WAT 235 5.000 7.000 9.000 1.00 0.00 O -ATOM 236 O WAT 236 5.000 7.000 11.000 1.00 0.00 O -ATOM 237 O WAT 237 5.000 7.000 13.000 1.00 0.00 O -ATOM 238 O WAT 238 5.000 7.000 15.000 1.00 0.00 O -ATOM 239 O WAT 239 5.000 7.000 17.000 1.00 0.00 O -ATOM 240 O WAT 240 5.000 7.000 19.000 1.00 0.00 O -ATOM 241 O WAT 241 5.000 9.000 1.000 1.00 0.00 O -ATOM 242 O WAT 242 5.000 9.000 3.000 1.00 0.00 O -ATOM 243 O WAT 243 5.000 9.000 5.000 1.00 0.00 O -ATOM 244 O WAT 244 5.000 9.000 7.000 1.00 0.00 O -ATOM 245 O WAT 245 5.000 9.000 9.000 1.00 0.00 O -ATOM 246 O WAT 246 5.000 9.000 11.000 1.00 0.00 O -ATOM 247 O WAT 247 5.000 9.000 13.000 1.00 0.00 O -ATOM 248 O WAT 248 5.000 9.000 15.000 1.00 0.00 O -ATOM 249 O WAT 249 5.000 9.000 17.000 1.00 0.00 O -ATOM 250 O WAT 250 5.000 9.000 19.000 1.00 0.00 O -ATOM 251 O WAT 251 5.000 11.000 1.000 1.00 0.00 O -ATOM 252 O WAT 252 5.000 11.000 3.000 1.00 0.00 O -ATOM 253 O WAT 253 5.000 11.000 5.000 1.00 0.00 O -ATOM 254 O WAT 254 5.000 11.000 7.000 1.00 0.00 O -ATOM 255 O WAT 255 5.000 11.000 9.000 1.00 0.00 O -ATOM 256 O WAT 256 5.000 11.000 11.000 1.00 0.00 O -ATOM 257 O WAT 257 5.000 11.000 13.000 1.00 0.00 O -ATOM 258 O WAT 258 5.000 11.000 15.000 1.00 0.00 O -ATOM 259 O WAT 259 5.000 11.000 17.000 1.00 0.00 O -ATOM 260 O WAT 260 5.000 11.000 19.000 1.00 0.00 O -ATOM 261 O WAT 261 5.000 13.000 1.000 1.00 0.00 O -ATOM 262 O WAT 262 5.000 13.000 3.000 1.00 0.00 O -ATOM 263 O WAT 263 5.000 13.000 5.000 1.00 0.00 O -ATOM 264 O WAT 264 5.000 13.000 7.000 1.00 0.00 O -ATOM 265 O WAT 265 5.000 13.000 9.000 1.00 0.00 O -ATOM 266 O WAT 266 5.000 13.000 11.000 1.00 0.00 O -ATOM 267 O WAT 267 5.000 13.000 13.000 1.00 0.00 O -ATOM 268 O WAT 268 5.000 13.000 15.000 1.00 0.00 O -ATOM 269 O WAT 269 5.000 13.000 17.000 1.00 0.00 O -ATOM 270 O WAT 270 5.000 13.000 19.000 1.00 0.00 O -ATOM 271 O WAT 271 5.000 15.000 1.000 1.00 0.00 O -ATOM 272 O WAT 272 5.000 15.000 3.000 1.00 0.00 O -ATOM 273 O WAT 273 5.000 15.000 5.000 1.00 0.00 O -ATOM 274 O WAT 274 5.000 15.000 7.000 1.00 0.00 O -ATOM 275 O WAT 275 5.000 15.000 9.000 1.00 0.00 O -ATOM 276 O WAT 276 5.000 15.000 11.000 1.00 0.00 O -ATOM 277 O WAT 277 5.000 15.000 13.000 1.00 0.00 O -ATOM 278 O WAT 278 5.000 15.000 15.000 1.00 0.00 O -ATOM 279 O WAT 279 5.000 15.000 17.000 1.00 0.00 O -ATOM 280 O WAT 280 5.000 15.000 19.000 1.00 0.00 O -ATOM 281 O WAT 281 5.000 17.000 1.000 1.00 0.00 O -ATOM 282 O WAT 282 5.000 17.000 3.000 1.00 0.00 O -ATOM 283 O WAT 283 5.000 17.000 5.000 1.00 0.00 O -ATOM 284 O WAT 284 5.000 17.000 7.000 1.00 0.00 O -ATOM 285 O WAT 285 5.000 17.000 9.000 1.00 0.00 O -ATOM 286 O WAT 286 5.000 17.000 11.000 1.00 0.00 O -ATOM 287 O WAT 287 5.000 17.000 13.000 1.00 0.00 O -ATOM 288 O WAT 288 5.000 17.000 15.000 1.00 0.00 O -ATOM 289 O WAT 289 5.000 17.000 17.000 1.00 0.00 O -ATOM 290 O WAT 290 5.000 17.000 19.000 1.00 0.00 O -ATOM 291 O WAT 291 5.000 19.000 1.000 1.00 0.00 O -ATOM 292 O WAT 292 5.000 19.000 3.000 1.00 0.00 O -ATOM 293 O WAT 293 5.000 19.000 5.000 1.00 0.00 O -ATOM 294 O WAT 294 5.000 19.000 7.000 1.00 0.00 O -ATOM 295 O WAT 295 5.000 19.000 9.000 1.00 0.00 O -ATOM 296 O WAT 296 5.000 19.000 11.000 1.00 0.00 O -ATOM 297 O WAT 297 5.000 19.000 13.000 1.00 0.00 O -ATOM 298 O WAT 298 5.000 19.000 15.000 1.00 0.00 O -ATOM 299 O WAT 299 5.000 19.000 17.000 1.00 0.00 O -ATOM 300 O WAT 300 5.000 19.000 19.000 1.00 0.00 O -ATOM 301 O WAT 301 7.000 1.000 1.000 1.00 0.00 O -ATOM 302 O WAT 302 7.000 1.000 3.000 1.00 0.00 O -ATOM 303 O WAT 303 7.000 1.000 5.000 1.00 0.00 O -ATOM 304 O WAT 304 7.000 1.000 7.000 1.00 0.00 O -ATOM 305 O WAT 305 7.000 1.000 9.000 1.00 0.00 O -ATOM 306 O WAT 306 7.000 1.000 11.000 1.00 0.00 O -ATOM 307 O WAT 307 7.000 1.000 13.000 1.00 0.00 O -ATOM 308 O WAT 308 7.000 1.000 15.000 1.00 0.00 O -ATOM 309 O WAT 309 7.000 1.000 17.000 1.00 0.00 O -ATOM 310 O WAT 310 7.000 1.000 19.000 1.00 0.00 O -ATOM 311 O WAT 311 7.000 3.000 1.000 1.00 0.00 O -ATOM 312 O WAT 312 7.000 3.000 3.000 1.00 0.00 O -ATOM 313 O WAT 313 7.000 3.000 5.000 1.00 0.00 O -ATOM 314 O WAT 314 7.000 3.000 7.000 1.00 0.00 O -ATOM 315 O WAT 315 7.000 3.000 9.000 1.00 0.00 O -ATOM 316 O WAT 316 7.000 3.000 11.000 1.00 0.00 O -ATOM 317 O WAT 317 7.000 3.000 13.000 1.00 0.00 O -ATOM 318 O WAT 318 7.000 3.000 15.000 1.00 0.00 O -ATOM 319 O WAT 319 7.000 3.000 17.000 1.00 0.00 O -ATOM 320 O WAT 320 7.000 3.000 19.000 1.00 0.00 O -ATOM 321 O WAT 321 7.000 5.000 1.000 1.00 0.00 O -ATOM 322 O WAT 322 7.000 5.000 3.000 1.00 0.00 O -ATOM 323 O WAT 323 7.000 5.000 5.000 1.00 0.00 O -ATOM 324 O WAT 324 7.000 5.000 7.000 1.00 0.00 O -ATOM 325 O WAT 325 7.000 5.000 9.000 1.00 0.00 O -ATOM 326 O WAT 326 7.000 5.000 11.000 1.00 0.00 O -ATOM 327 O WAT 327 7.000 5.000 13.000 1.00 0.00 O -ATOM 328 O WAT 328 7.000 5.000 15.000 1.00 0.00 O -ATOM 329 O WAT 329 7.000 5.000 17.000 1.00 0.00 O -ATOM 330 O WAT 330 7.000 5.000 19.000 1.00 0.00 O -ATOM 331 O WAT 331 7.000 7.000 1.000 1.00 0.00 O -ATOM 332 O WAT 332 7.000 7.000 3.000 1.00 0.00 O -ATOM 333 O WAT 333 7.000 7.000 5.000 1.00 0.00 O -ATOM 334 O WAT 334 7.000 7.000 7.000 1.00 0.00 O -ATOM 335 O WAT 335 7.000 7.000 9.000 1.00 0.00 O -ATOM 336 O WAT 336 7.000 7.000 11.000 1.00 0.00 O -ATOM 337 O WAT 337 7.000 7.000 13.000 1.00 0.00 O -ATOM 338 O WAT 338 7.000 7.000 15.000 1.00 0.00 O -ATOM 339 O WAT 339 7.000 7.000 17.000 1.00 0.00 O -ATOM 340 O WAT 340 7.000 7.000 19.000 1.00 0.00 O -ATOM 341 O WAT 341 7.000 9.000 1.000 1.00 0.00 O -ATOM 342 O WAT 342 7.000 9.000 3.000 1.00 0.00 O -ATOM 343 O WAT 343 7.000 9.000 5.000 1.00 0.00 O -ATOM 344 O WAT 344 7.000 9.000 7.000 1.00 0.00 O -ATOM 345 O WAT 345 7.000 9.000 9.000 1.00 0.00 O -ATOM 346 O WAT 346 7.000 9.000 11.000 1.00 0.00 O -ATOM 347 O WAT 347 7.000 9.000 13.000 1.00 0.00 O -ATOM 348 O WAT 348 7.000 9.000 15.000 1.00 0.00 O -ATOM 349 O WAT 349 7.000 9.000 17.000 1.00 0.00 O -ATOM 350 O WAT 350 7.000 9.000 19.000 1.00 0.00 O -ATOM 351 O WAT 351 7.000 11.000 1.000 1.00 0.00 O -ATOM 352 O WAT 352 7.000 11.000 3.000 1.00 0.00 O -ATOM 353 O WAT 353 7.000 11.000 5.000 1.00 0.00 O -ATOM 354 O WAT 354 7.000 11.000 7.000 1.00 0.00 O -ATOM 355 O WAT 355 7.000 11.000 9.000 1.00 0.00 O -ATOM 356 O WAT 356 7.000 11.000 11.000 1.00 0.00 O -ATOM 357 O WAT 357 7.000 11.000 13.000 1.00 0.00 O -ATOM 358 O WAT 358 7.000 11.000 15.000 1.00 0.00 O -ATOM 359 O WAT 359 7.000 11.000 17.000 1.00 0.00 O -ATOM 360 O WAT 360 7.000 11.000 19.000 1.00 0.00 O -ATOM 361 O WAT 361 7.000 13.000 1.000 1.00 0.00 O -ATOM 362 O WAT 362 7.000 13.000 3.000 1.00 0.00 O -ATOM 363 O WAT 363 7.000 13.000 5.000 1.00 0.00 O -ATOM 364 O WAT 364 7.000 13.000 7.000 1.00 0.00 O -ATOM 365 O WAT 365 7.000 13.000 9.000 1.00 0.00 O -ATOM 366 O WAT 366 7.000 13.000 11.000 1.00 0.00 O -ATOM 367 O WAT 367 7.000 13.000 13.000 1.00 0.00 O -ATOM 368 O WAT 368 7.000 13.000 15.000 1.00 0.00 O -ATOM 369 O WAT 369 7.000 13.000 17.000 1.00 0.00 O -ATOM 370 O WAT 370 7.000 13.000 19.000 1.00 0.00 O -ATOM 371 O WAT 371 7.000 15.000 1.000 1.00 0.00 O -ATOM 372 O WAT 372 7.000 15.000 3.000 1.00 0.00 O -ATOM 373 O WAT 373 7.000 15.000 5.000 1.00 0.00 O -ATOM 374 O WAT 374 7.000 15.000 7.000 1.00 0.00 O -ATOM 375 O WAT 375 7.000 15.000 9.000 1.00 0.00 O -ATOM 376 O WAT 376 7.000 15.000 11.000 1.00 0.00 O -ATOM 377 O WAT 377 7.000 15.000 13.000 1.00 0.00 O -ATOM 378 O WAT 378 7.000 15.000 15.000 1.00 0.00 O -ATOM 379 O WAT 379 7.000 15.000 17.000 1.00 0.00 O -ATOM 380 O WAT 380 7.000 15.000 19.000 1.00 0.00 O -ATOM 381 O WAT 381 7.000 17.000 1.000 1.00 0.00 O -ATOM 382 O WAT 382 7.000 17.000 3.000 1.00 0.00 O -ATOM 383 O WAT 383 7.000 17.000 5.000 1.00 0.00 O -ATOM 384 O WAT 384 7.000 17.000 7.000 1.00 0.00 O -ATOM 385 O WAT 385 7.000 17.000 9.000 1.00 0.00 O -ATOM 386 O WAT 386 7.000 17.000 11.000 1.00 0.00 O -ATOM 387 O WAT 387 7.000 17.000 13.000 1.00 0.00 O -ATOM 388 O WAT 388 7.000 17.000 15.000 1.00 0.00 O -ATOM 389 O WAT 389 7.000 17.000 17.000 1.00 0.00 O -ATOM 390 O WAT 390 7.000 17.000 19.000 1.00 0.00 O -ATOM 391 O WAT 391 7.000 19.000 1.000 1.00 0.00 O -ATOM 392 O WAT 392 7.000 19.000 3.000 1.00 0.00 O -ATOM 393 O WAT 393 7.000 19.000 5.000 1.00 0.00 O -ATOM 394 O WAT 394 7.000 19.000 7.000 1.00 0.00 O -ATOM 395 O WAT 395 7.000 19.000 9.000 1.00 0.00 O -ATOM 396 O WAT 396 7.000 19.000 11.000 1.00 0.00 O -ATOM 397 O WAT 397 7.000 19.000 13.000 1.00 0.00 O -ATOM 398 O WAT 398 7.000 19.000 15.000 1.00 0.00 O -ATOM 399 O WAT 399 7.000 19.000 17.000 1.00 0.00 O -ATOM 400 O WAT 400 7.000 19.000 19.000 1.00 0.00 O -ATOM 401 O WAT 401 9.000 1.000 1.000 1.00 0.00 O -ATOM 402 O WAT 402 9.000 1.000 3.000 1.00 0.00 O -ATOM 403 O WAT 403 9.000 1.000 5.000 1.00 0.00 O -ATOM 404 O WAT 404 9.000 1.000 7.000 1.00 0.00 O -ATOM 405 O WAT 405 9.000 1.000 9.000 1.00 0.00 O -ATOM 406 O WAT 406 9.000 1.000 11.000 1.00 0.00 O -ATOM 407 O WAT 407 9.000 1.000 13.000 1.00 0.00 O -ATOM 408 O WAT 408 9.000 1.000 15.000 1.00 0.00 O -ATOM 409 O WAT 409 9.000 1.000 17.000 1.00 0.00 O -ATOM 410 O WAT 410 9.000 1.000 19.000 1.00 0.00 O -ATOM 411 O WAT 411 9.000 3.000 1.000 1.00 0.00 O -ATOM 412 O WAT 412 9.000 3.000 3.000 1.00 0.00 O -ATOM 413 O WAT 413 9.000 3.000 5.000 1.00 0.00 O -ATOM 414 O WAT 414 9.000 3.000 7.000 1.00 0.00 O -ATOM 415 O WAT 415 9.000 3.000 9.000 1.00 0.00 O -ATOM 416 O WAT 416 9.000 3.000 11.000 1.00 0.00 O -ATOM 417 O WAT 417 9.000 3.000 13.000 1.00 0.00 O -ATOM 418 O WAT 418 9.000 3.000 15.000 1.00 0.00 O -ATOM 419 O WAT 419 9.000 3.000 17.000 1.00 0.00 O -ATOM 420 O WAT 420 9.000 3.000 19.000 1.00 0.00 O -ATOM 421 O WAT 421 9.000 5.000 1.000 1.00 0.00 O -ATOM 422 O WAT 422 9.000 5.000 3.000 1.00 0.00 O -ATOM 423 O WAT 423 9.000 5.000 5.000 1.00 0.00 O -ATOM 424 O WAT 424 9.000 5.000 7.000 1.00 0.00 O -ATOM 425 O WAT 425 9.000 5.000 9.000 1.00 0.00 O -ATOM 426 O WAT 426 9.000 5.000 11.000 1.00 0.00 O -ATOM 427 O WAT 427 9.000 5.000 13.000 1.00 0.00 O -ATOM 428 O WAT 428 9.000 5.000 15.000 1.00 0.00 O -ATOM 429 O WAT 429 9.000 5.000 17.000 1.00 0.00 O -ATOM 430 O WAT 430 9.000 5.000 19.000 1.00 0.00 O -ATOM 431 O WAT 431 9.000 7.000 1.000 1.00 0.00 O -ATOM 432 O WAT 432 9.000 7.000 3.000 1.00 0.00 O -ATOM 433 O WAT 433 9.000 7.000 5.000 1.00 0.00 O -ATOM 434 O WAT 434 9.000 7.000 7.000 1.00 0.00 O -ATOM 435 O WAT 435 9.000 7.000 9.000 1.00 0.00 O -ATOM 436 O WAT 436 9.000 7.000 11.000 1.00 0.00 O -ATOM 437 O WAT 437 9.000 7.000 13.000 1.00 0.00 O -ATOM 438 O WAT 438 9.000 7.000 15.000 1.00 0.00 O -ATOM 439 O WAT 439 9.000 7.000 17.000 1.00 0.00 O -ATOM 440 O WAT 440 9.000 7.000 19.000 1.00 0.00 O -ATOM 441 O WAT 441 9.000 9.000 1.000 1.00 0.00 O -ATOM 442 O WAT 442 9.000 9.000 3.000 1.00 0.00 O -ATOM 443 O WAT 443 9.000 9.000 5.000 1.00 0.00 O -ATOM 444 O WAT 444 9.000 9.000 7.000 1.00 0.00 O -ATOM 445 O WAT 445 9.000 9.000 9.000 1.00 0.00 O -ATOM 446 O WAT 446 9.000 9.000 11.000 1.00 0.00 O -ATOM 447 O WAT 447 9.000 9.000 13.000 1.00 0.00 O -ATOM 448 O WAT 448 9.000 9.000 15.000 1.00 0.00 O -ATOM 449 O WAT 449 9.000 9.000 17.000 1.00 0.00 O -ATOM 450 O WAT 450 9.000 9.000 19.000 1.00 0.00 O -ATOM 451 O WAT 451 9.000 11.000 1.000 1.00 0.00 O -ATOM 452 O WAT 452 9.000 11.000 3.000 1.00 0.00 O -ATOM 453 O WAT 453 9.000 11.000 5.000 1.00 0.00 O -ATOM 454 O WAT 454 9.000 11.000 7.000 1.00 0.00 O -ATOM 455 O WAT 455 9.000 11.000 9.000 1.00 0.00 O -ATOM 456 O WAT 456 9.000 11.000 11.000 1.00 0.00 O -ATOM 457 O WAT 457 9.000 11.000 13.000 1.00 0.00 O -ATOM 458 O WAT 458 9.000 11.000 15.000 1.00 0.00 O -ATOM 459 O WAT 459 9.000 11.000 17.000 1.00 0.00 O -ATOM 460 O WAT 460 9.000 11.000 19.000 1.00 0.00 O -ATOM 461 O WAT 461 9.000 13.000 1.000 1.00 0.00 O -ATOM 462 O WAT 462 9.000 13.000 3.000 1.00 0.00 O -ATOM 463 O WAT 463 9.000 13.000 5.000 1.00 0.00 O -ATOM 464 O WAT 464 9.000 13.000 7.000 1.00 0.00 O -ATOM 465 O WAT 465 9.000 13.000 9.000 1.00 0.00 O -ATOM 466 O WAT 466 9.000 13.000 11.000 1.00 0.00 O -ATOM 467 O WAT 467 9.000 13.000 13.000 1.00 0.00 O -ATOM 468 O WAT 468 9.000 13.000 15.000 1.00 0.00 O -ATOM 469 O WAT 469 9.000 13.000 17.000 1.00 0.00 O -ATOM 470 O WAT 470 9.000 13.000 19.000 1.00 0.00 O -ATOM 471 O WAT 471 9.000 15.000 1.000 1.00 0.00 O -ATOM 472 O WAT 472 9.000 15.000 3.000 1.00 0.00 O -ATOM 473 O WAT 473 9.000 15.000 5.000 1.00 0.00 O -ATOM 474 O WAT 474 9.000 15.000 7.000 1.00 0.00 O -ATOM 475 O WAT 475 9.000 15.000 9.000 1.00 0.00 O -ATOM 476 O WAT 476 9.000 15.000 11.000 1.00 0.00 O -ATOM 477 O WAT 477 9.000 15.000 13.000 1.00 0.00 O -ATOM 478 O WAT 478 9.000 15.000 15.000 1.00 0.00 O -ATOM 479 O WAT 479 9.000 15.000 17.000 1.00 0.00 O -ATOM 480 O WAT 480 9.000 15.000 19.000 1.00 0.00 O -ATOM 481 O WAT 481 9.000 17.000 1.000 1.00 0.00 O -ATOM 482 O WAT 482 9.000 17.000 3.000 1.00 0.00 O -ATOM 483 O WAT 483 9.000 17.000 5.000 1.00 0.00 O -ATOM 484 O WAT 484 9.000 17.000 7.000 1.00 0.00 O -ATOM 485 O WAT 485 9.000 17.000 9.000 1.00 0.00 O -ATOM 486 O WAT 486 9.000 17.000 11.000 1.00 0.00 O -ATOM 487 O WAT 487 9.000 17.000 13.000 1.00 0.00 O -ATOM 488 O WAT 488 9.000 17.000 15.000 1.00 0.00 O -ATOM 489 O WAT 489 9.000 17.000 17.000 1.00 0.00 O -ATOM 490 O WAT 490 9.000 17.000 19.000 1.00 0.00 O -ATOM 491 O WAT 491 9.000 19.000 1.000 1.00 0.00 O -ATOM 492 O WAT 492 9.000 19.000 3.000 1.00 0.00 O -ATOM 493 O WAT 493 9.000 19.000 5.000 1.00 0.00 O -ATOM 494 O WAT 494 9.000 19.000 7.000 1.00 0.00 O -ATOM 495 O WAT 495 9.000 19.000 9.000 1.00 0.00 O -ATOM 496 O WAT 496 9.000 19.000 11.000 1.00 0.00 O -ATOM 497 O WAT 497 9.000 19.000 13.000 1.00 0.00 O -ATOM 498 O WAT 498 9.000 19.000 15.000 1.00 0.00 O -ATOM 499 O WAT 499 9.000 19.000 17.000 1.00 0.00 O -ATOM 500 O WAT 500 9.000 19.000 19.000 1.00 0.00 O -ATOM 501 O WAT 501 11.000 1.000 1.000 1.00 0.00 O -ATOM 502 O WAT 502 11.000 1.000 3.000 1.00 0.00 O -ATOM 503 O WAT 503 11.000 1.000 5.000 1.00 0.00 O -ATOM 504 O WAT 504 11.000 1.000 7.000 1.00 0.00 O -ATOM 505 O WAT 505 11.000 1.000 9.000 1.00 0.00 O -ATOM 506 O WAT 506 11.000 1.000 11.000 1.00 0.00 O -ATOM 507 O WAT 507 11.000 1.000 13.000 1.00 0.00 O -ATOM 508 O WAT 508 11.000 1.000 15.000 1.00 0.00 O -ATOM 509 O WAT 509 11.000 1.000 17.000 1.00 0.00 O -ATOM 510 O WAT 510 11.000 1.000 19.000 1.00 0.00 O -ATOM 511 O WAT 511 11.000 3.000 1.000 1.00 0.00 O -ATOM 512 O WAT 512 11.000 3.000 3.000 1.00 0.00 O -ATOM 513 O WAT 513 11.000 3.000 5.000 1.00 0.00 O -ATOM 514 O WAT 514 11.000 3.000 7.000 1.00 0.00 O -ATOM 515 O WAT 515 11.000 3.000 9.000 1.00 0.00 O -ATOM 516 O WAT 516 11.000 3.000 11.000 1.00 0.00 O -ATOM 517 O WAT 517 11.000 3.000 13.000 1.00 0.00 O -ATOM 518 O WAT 518 11.000 3.000 15.000 1.00 0.00 O -ATOM 519 O WAT 519 11.000 3.000 17.000 1.00 0.00 O -ATOM 520 O WAT 520 11.000 3.000 19.000 1.00 0.00 O -ATOM 521 O WAT 521 11.000 5.000 1.000 1.00 0.00 O -ATOM 522 O WAT 522 11.000 5.000 3.000 1.00 0.00 O -ATOM 523 O WAT 523 11.000 5.000 5.000 1.00 0.00 O -ATOM 524 O WAT 524 11.000 5.000 7.000 1.00 0.00 O -ATOM 525 O WAT 525 11.000 5.000 9.000 1.00 0.00 O -ATOM 526 O WAT 526 11.000 5.000 11.000 1.00 0.00 O -ATOM 527 O WAT 527 11.000 5.000 13.000 1.00 0.00 O -ATOM 528 O WAT 528 11.000 5.000 15.000 1.00 0.00 O -ATOM 529 O WAT 529 11.000 5.000 17.000 1.00 0.00 O -ATOM 530 O WAT 530 11.000 5.000 19.000 1.00 0.00 O -ATOM 531 O WAT 531 11.000 7.000 1.000 1.00 0.00 O -ATOM 532 O WAT 532 11.000 7.000 3.000 1.00 0.00 O -ATOM 533 O WAT 533 11.000 7.000 5.000 1.00 0.00 O -ATOM 534 O WAT 534 11.000 7.000 7.000 1.00 0.00 O -ATOM 535 O WAT 535 11.000 7.000 9.000 1.00 0.00 O -ATOM 536 O WAT 536 11.000 7.000 11.000 1.00 0.00 O -ATOM 537 O WAT 537 11.000 7.000 13.000 1.00 0.00 O -ATOM 538 O WAT 538 11.000 7.000 15.000 1.00 0.00 O -ATOM 539 O WAT 539 11.000 7.000 17.000 1.00 0.00 O -ATOM 540 O WAT 540 11.000 7.000 19.000 1.00 0.00 O -ATOM 541 O WAT 541 11.000 9.000 1.000 1.00 0.00 O -ATOM 542 O WAT 542 11.000 9.000 3.000 1.00 0.00 O -ATOM 543 O WAT 543 11.000 9.000 5.000 1.00 0.00 O -ATOM 544 O WAT 544 11.000 9.000 7.000 1.00 0.00 O -ATOM 545 O WAT 545 11.000 9.000 9.000 1.00 0.00 O -ATOM 546 O WAT 546 11.000 9.000 11.000 1.00 0.00 O -ATOM 547 O WAT 547 11.000 9.000 13.000 1.00 0.00 O -ATOM 548 O WAT 548 11.000 9.000 15.000 1.00 0.00 O -ATOM 549 O WAT 549 11.000 9.000 17.000 1.00 0.00 O -ATOM 550 O WAT 550 11.000 9.000 19.000 1.00 0.00 O -ATOM 551 O WAT 551 11.000 11.000 1.000 1.00 0.00 O -ATOM 552 O WAT 552 11.000 11.000 3.000 1.00 0.00 O -ATOM 553 O WAT 553 11.000 11.000 5.000 1.00 0.00 O -ATOM 554 O WAT 554 11.000 11.000 7.000 1.00 0.00 O -ATOM 555 O WAT 555 11.000 11.000 9.000 1.00 0.00 O -ATOM 556 O WAT 556 11.000 11.000 11.000 1.00 0.00 O -ATOM 557 O WAT 557 11.000 11.000 13.000 1.00 0.00 O -ATOM 558 O WAT 558 11.000 11.000 15.000 1.00 0.00 O -ATOM 559 O WAT 559 11.000 11.000 17.000 1.00 0.00 O -ATOM 560 O WAT 560 11.000 11.000 19.000 1.00 0.00 O -ATOM 561 O WAT 561 11.000 13.000 1.000 1.00 0.00 O -ATOM 562 O WAT 562 11.000 13.000 3.000 1.00 0.00 O -ATOM 563 O WAT 563 11.000 13.000 5.000 1.00 0.00 O -ATOM 564 O WAT 564 11.000 13.000 7.000 1.00 0.00 O -ATOM 565 O WAT 565 11.000 13.000 9.000 1.00 0.00 O -ATOM 566 O WAT 566 11.000 13.000 11.000 1.00 0.00 O -ATOM 567 O WAT 567 11.000 13.000 13.000 1.00 0.00 O -ATOM 568 O WAT 568 11.000 13.000 15.000 1.00 0.00 O -ATOM 569 O WAT 569 11.000 13.000 17.000 1.00 0.00 O -ATOM 570 O WAT 570 11.000 13.000 19.000 1.00 0.00 O -ATOM 571 O WAT 571 11.000 15.000 1.000 1.00 0.00 O -ATOM 572 O WAT 572 11.000 15.000 3.000 1.00 0.00 O -ATOM 573 O WAT 573 11.000 15.000 5.000 1.00 0.00 O -ATOM 574 O WAT 574 11.000 15.000 7.000 1.00 0.00 O -ATOM 575 O WAT 575 11.000 15.000 9.000 1.00 0.00 O -ATOM 576 O WAT 576 11.000 15.000 11.000 1.00 0.00 O -ATOM 577 O WAT 577 11.000 15.000 13.000 1.00 0.00 O -ATOM 578 O WAT 578 11.000 15.000 15.000 1.00 0.00 O -ATOM 579 O WAT 579 11.000 15.000 17.000 1.00 0.00 O -ATOM 580 O WAT 580 11.000 15.000 19.000 1.00 0.00 O -ATOM 581 O WAT 581 11.000 17.000 1.000 1.00 0.00 O -ATOM 582 O WAT 582 11.000 17.000 3.000 1.00 0.00 O -ATOM 583 O WAT 583 11.000 17.000 5.000 1.00 0.00 O -ATOM 584 O WAT 584 11.000 17.000 7.000 1.00 0.00 O -ATOM 585 O WAT 585 11.000 17.000 9.000 1.00 0.00 O -ATOM 586 O WAT 586 11.000 17.000 11.000 1.00 0.00 O -ATOM 587 O WAT 587 11.000 17.000 13.000 1.00 0.00 O -ATOM 588 O WAT 588 11.000 17.000 15.000 1.00 0.00 O -ATOM 589 O WAT 589 11.000 17.000 17.000 1.00 0.00 O -ATOM 590 O WAT 590 11.000 17.000 19.000 1.00 0.00 O -ATOM 591 O WAT 591 11.000 19.000 1.000 1.00 0.00 O -ATOM 592 O WAT 592 11.000 19.000 3.000 1.00 0.00 O -ATOM 593 O WAT 593 11.000 19.000 5.000 1.00 0.00 O -ATOM 594 O WAT 594 11.000 19.000 7.000 1.00 0.00 O -ATOM 595 O WAT 595 11.000 19.000 9.000 1.00 0.00 O -ATOM 596 O WAT 596 11.000 19.000 11.000 1.00 0.00 O -ATOM 597 O WAT 597 11.000 19.000 13.000 1.00 0.00 O -ATOM 598 O WAT 598 11.000 19.000 15.000 1.00 0.00 O -ATOM 599 O WAT 599 11.000 19.000 17.000 1.00 0.00 O -ATOM 600 O WAT 600 11.000 19.000 19.000 1.00 0.00 O -ATOM 601 O WAT 601 13.000 1.000 1.000 1.00 0.00 O -ATOM 602 O WAT 602 13.000 1.000 3.000 1.00 0.00 O -ATOM 603 O WAT 603 13.000 1.000 5.000 1.00 0.00 O -ATOM 604 O WAT 604 13.000 1.000 7.000 1.00 0.00 O -ATOM 605 O WAT 605 13.000 1.000 9.000 1.00 0.00 O -ATOM 606 O WAT 606 13.000 1.000 11.000 1.00 0.00 O -ATOM 607 O WAT 607 13.000 1.000 13.000 1.00 0.00 O -ATOM 608 O WAT 608 13.000 1.000 15.000 1.00 0.00 O -ATOM 609 O WAT 609 13.000 1.000 17.000 1.00 0.00 O -ATOM 610 O WAT 610 13.000 1.000 19.000 1.00 0.00 O -ATOM 611 O WAT 611 13.000 3.000 1.000 1.00 0.00 O -ATOM 612 O WAT 612 13.000 3.000 3.000 1.00 0.00 O -ATOM 613 O WAT 613 13.000 3.000 5.000 1.00 0.00 O -ATOM 614 O WAT 614 13.000 3.000 7.000 1.00 0.00 O -ATOM 615 O WAT 615 13.000 3.000 9.000 1.00 0.00 O -ATOM 616 O WAT 616 13.000 3.000 11.000 1.00 0.00 O -ATOM 617 O WAT 617 13.000 3.000 13.000 1.00 0.00 O -ATOM 618 O WAT 618 13.000 3.000 15.000 1.00 0.00 O -ATOM 619 O WAT 619 13.000 3.000 17.000 1.00 0.00 O -ATOM 620 O WAT 620 13.000 3.000 19.000 1.00 0.00 O -ATOM 621 O WAT 621 13.000 5.000 1.000 1.00 0.00 O -ATOM 622 O WAT 622 13.000 5.000 3.000 1.00 0.00 O -ATOM 623 O WAT 623 13.000 5.000 5.000 1.00 0.00 O -ATOM 624 O WAT 624 13.000 5.000 7.000 1.00 0.00 O -ATOM 625 O WAT 625 13.000 5.000 9.000 1.00 0.00 O -ATOM 626 O WAT 626 13.000 5.000 11.000 1.00 0.00 O -ATOM 627 O WAT 627 13.000 5.000 13.000 1.00 0.00 O -ATOM 628 O WAT 628 13.000 5.000 15.000 1.00 0.00 O -ATOM 629 O WAT 629 13.000 5.000 17.000 1.00 0.00 O -ATOM 630 O WAT 630 13.000 5.000 19.000 1.00 0.00 O -ATOM 631 O WAT 631 13.000 7.000 1.000 1.00 0.00 O -ATOM 632 O WAT 632 13.000 7.000 3.000 1.00 0.00 O -ATOM 633 O WAT 633 13.000 7.000 5.000 1.00 0.00 O -ATOM 634 O WAT 634 13.000 7.000 7.000 1.00 0.00 O -ATOM 635 O WAT 635 13.000 7.000 9.000 1.00 0.00 O -ATOM 636 O WAT 636 13.000 7.000 11.000 1.00 0.00 O -ATOM 637 O WAT 637 13.000 7.000 13.000 1.00 0.00 O -ATOM 638 O WAT 638 13.000 7.000 15.000 1.00 0.00 O -ATOM 639 O WAT 639 13.000 7.000 17.000 1.00 0.00 O -ATOM 640 O WAT 640 13.000 7.000 19.000 1.00 0.00 O -ATOM 641 O WAT 641 13.000 9.000 1.000 1.00 0.00 O -ATOM 642 O WAT 642 13.000 9.000 3.000 1.00 0.00 O -ATOM 643 O WAT 643 13.000 9.000 5.000 1.00 0.00 O -ATOM 644 O WAT 644 13.000 9.000 7.000 1.00 0.00 O -ATOM 645 O WAT 645 13.000 9.000 9.000 1.00 0.00 O -ATOM 646 O WAT 646 13.000 9.000 11.000 1.00 0.00 O -ATOM 647 O WAT 647 13.000 9.000 13.000 1.00 0.00 O -ATOM 648 O WAT 648 13.000 9.000 15.000 1.00 0.00 O -ATOM 649 O WAT 649 13.000 9.000 17.000 1.00 0.00 O -ATOM 650 O WAT 650 13.000 9.000 19.000 1.00 0.00 O -ATOM 651 O WAT 651 13.000 11.000 1.000 1.00 0.00 O -ATOM 652 O WAT 652 13.000 11.000 3.000 1.00 0.00 O -ATOM 653 O WAT 653 13.000 11.000 5.000 1.00 0.00 O -ATOM 654 O WAT 654 13.000 11.000 7.000 1.00 0.00 O -ATOM 655 O WAT 655 13.000 11.000 9.000 1.00 0.00 O -ATOM 656 O WAT 656 13.000 11.000 11.000 1.00 0.00 O -ATOM 657 O WAT 657 13.000 11.000 13.000 1.00 0.00 O -ATOM 658 O WAT 658 13.000 11.000 15.000 1.00 0.00 O -ATOM 659 O WAT 659 13.000 11.000 17.000 1.00 0.00 O -ATOM 660 O WAT 660 13.000 11.000 19.000 1.00 0.00 O -ATOM 661 O WAT 661 13.000 13.000 1.000 1.00 0.00 O -ATOM 662 O WAT 662 13.000 13.000 3.000 1.00 0.00 O -ATOM 663 O WAT 663 13.000 13.000 5.000 1.00 0.00 O -ATOM 664 O WAT 664 13.000 13.000 7.000 1.00 0.00 O -ATOM 665 O WAT 665 13.000 13.000 9.000 1.00 0.00 O -ATOM 666 O WAT 666 13.000 13.000 11.000 1.00 0.00 O -ATOM 667 O WAT 667 13.000 13.000 13.000 1.00 0.00 O -ATOM 668 O WAT 668 13.000 13.000 15.000 1.00 0.00 O -ATOM 669 O WAT 669 13.000 13.000 17.000 1.00 0.00 O -ATOM 670 O WAT 670 13.000 13.000 19.000 1.00 0.00 O -ATOM 671 O WAT 671 13.000 15.000 1.000 1.00 0.00 O -ATOM 672 O WAT 672 13.000 15.000 3.000 1.00 0.00 O -ATOM 673 O WAT 673 13.000 15.000 5.000 1.00 0.00 O -ATOM 674 O WAT 674 13.000 15.000 7.000 1.00 0.00 O -ATOM 675 O WAT 675 13.000 15.000 9.000 1.00 0.00 O -ATOM 676 O WAT 676 13.000 15.000 11.000 1.00 0.00 O -ATOM 677 O WAT 677 13.000 15.000 13.000 1.00 0.00 O -ATOM 678 O WAT 678 13.000 15.000 15.000 1.00 0.00 O -ATOM 679 O WAT 679 13.000 15.000 17.000 1.00 0.00 O -ATOM 680 O WAT 680 13.000 15.000 19.000 1.00 0.00 O -ATOM 681 O WAT 681 13.000 17.000 1.000 1.00 0.00 O -ATOM 682 O WAT 682 13.000 17.000 3.000 1.00 0.00 O -ATOM 683 O WAT 683 13.000 17.000 5.000 1.00 0.00 O -ATOM 684 O WAT 684 13.000 17.000 7.000 1.00 0.00 O -ATOM 685 O WAT 685 13.000 17.000 9.000 1.00 0.00 O -ATOM 686 O WAT 686 13.000 17.000 11.000 1.00 0.00 O -ATOM 687 O WAT 687 13.000 17.000 13.000 1.00 0.00 O -ATOM 688 O WAT 688 13.000 17.000 15.000 1.00 0.00 O -ATOM 689 O WAT 689 13.000 17.000 17.000 1.00 0.00 O -ATOM 690 O WAT 690 13.000 17.000 19.000 1.00 0.00 O -ATOM 691 O WAT 691 13.000 19.000 1.000 1.00 0.00 O -ATOM 692 O WAT 692 13.000 19.000 3.000 1.00 0.00 O -ATOM 693 O WAT 693 13.000 19.000 5.000 1.00 0.00 O -ATOM 694 O WAT 694 13.000 19.000 7.000 1.00 0.00 O -ATOM 695 O WAT 695 13.000 19.000 9.000 1.00 0.00 O -ATOM 696 O WAT 696 13.000 19.000 11.000 1.00 0.00 O -ATOM 697 O WAT 697 13.000 19.000 13.000 1.00 0.00 O -ATOM 698 O WAT 698 13.000 19.000 15.000 1.00 0.00 O -ATOM 699 O WAT 699 13.000 19.000 17.000 1.00 0.00 O -ATOM 700 O WAT 700 13.000 19.000 19.000 1.00 0.00 O -ATOM 701 O WAT 701 15.000 1.000 1.000 1.00 0.00 O -ATOM 702 O WAT 702 15.000 1.000 3.000 1.00 0.00 O -ATOM 703 O WAT 703 15.000 1.000 5.000 1.00 0.00 O -ATOM 704 O WAT 704 15.000 1.000 7.000 1.00 0.00 O -ATOM 705 O WAT 705 15.000 1.000 9.000 1.00 0.00 O -ATOM 706 O WAT 706 15.000 1.000 11.000 1.00 0.00 O -ATOM 707 O WAT 707 15.000 1.000 13.000 1.00 0.00 O -ATOM 708 O WAT 708 15.000 1.000 15.000 1.00 0.00 O -ATOM 709 O WAT 709 15.000 1.000 17.000 1.00 0.00 O -ATOM 710 O WAT 710 15.000 1.000 19.000 1.00 0.00 O -ATOM 711 O WAT 711 15.000 3.000 1.000 1.00 0.00 O -ATOM 712 O WAT 712 15.000 3.000 3.000 1.00 0.00 O -ATOM 713 O WAT 713 15.000 3.000 5.000 1.00 0.00 O -ATOM 714 O WAT 714 15.000 3.000 7.000 1.00 0.00 O -ATOM 715 O WAT 715 15.000 3.000 9.000 1.00 0.00 O -ATOM 716 O WAT 716 15.000 3.000 11.000 1.00 0.00 O -ATOM 717 O WAT 717 15.000 3.000 13.000 1.00 0.00 O -ATOM 718 O WAT 718 15.000 3.000 15.000 1.00 0.00 O -ATOM 719 O WAT 719 15.000 3.000 17.000 1.00 0.00 O -ATOM 720 O WAT 720 15.000 3.000 19.000 1.00 0.00 O -ATOM 721 O WAT 721 15.000 5.000 1.000 1.00 0.00 O -ATOM 722 O WAT 722 15.000 5.000 3.000 1.00 0.00 O -ATOM 723 O WAT 723 15.000 5.000 5.000 1.00 0.00 O -ATOM 724 O WAT 724 15.000 5.000 7.000 1.00 0.00 O -ATOM 725 O WAT 725 15.000 5.000 9.000 1.00 0.00 O -ATOM 726 O WAT 726 15.000 5.000 11.000 1.00 0.00 O -ATOM 727 O WAT 727 15.000 5.000 13.000 1.00 0.00 O -ATOM 728 O WAT 728 15.000 5.000 15.000 1.00 0.00 O -ATOM 729 O WAT 729 15.000 5.000 17.000 1.00 0.00 O -ATOM 730 O WAT 730 15.000 5.000 19.000 1.00 0.00 O -ATOM 731 O WAT 731 15.000 7.000 1.000 1.00 0.00 O -ATOM 732 O WAT 732 15.000 7.000 3.000 1.00 0.00 O -ATOM 733 O WAT 733 15.000 7.000 5.000 1.00 0.00 O -ATOM 734 O WAT 734 15.000 7.000 7.000 1.00 0.00 O -ATOM 735 O WAT 735 15.000 7.000 9.000 1.00 0.00 O -ATOM 736 O WAT 736 15.000 7.000 11.000 1.00 0.00 O -ATOM 737 O WAT 737 15.000 7.000 13.000 1.00 0.00 O -ATOM 738 O WAT 738 15.000 7.000 15.000 1.00 0.00 O -ATOM 739 O WAT 739 15.000 7.000 17.000 1.00 0.00 O -ATOM 740 O WAT 740 15.000 7.000 19.000 1.00 0.00 O -ATOM 741 O WAT 741 15.000 9.000 1.000 1.00 0.00 O -ATOM 742 O WAT 742 15.000 9.000 3.000 1.00 0.00 O -ATOM 743 O WAT 743 15.000 9.000 5.000 1.00 0.00 O -ATOM 744 O WAT 744 15.000 9.000 7.000 1.00 0.00 O -ATOM 745 O WAT 745 15.000 9.000 9.000 1.00 0.00 O -ATOM 746 O WAT 746 15.000 9.000 11.000 1.00 0.00 O -ATOM 747 O WAT 747 15.000 9.000 13.000 1.00 0.00 O -ATOM 748 O WAT 748 15.000 9.000 15.000 1.00 0.00 O -ATOM 749 O WAT 749 15.000 9.000 17.000 1.00 0.00 O -ATOM 750 O WAT 750 15.000 9.000 19.000 1.00 0.00 O -ATOM 751 O WAT 751 15.000 11.000 1.000 1.00 0.00 O -ATOM 752 O WAT 752 15.000 11.000 3.000 1.00 0.00 O -ATOM 753 O WAT 753 15.000 11.000 5.000 1.00 0.00 O -ATOM 754 O WAT 754 15.000 11.000 7.000 1.00 0.00 O -ATOM 755 O WAT 755 15.000 11.000 9.000 1.00 0.00 O -ATOM 756 O WAT 756 15.000 11.000 11.000 1.00 0.00 O -ATOM 757 O WAT 757 15.000 11.000 13.000 1.00 0.00 O -ATOM 758 O WAT 758 15.000 11.000 15.000 1.00 0.00 O -ATOM 759 O WAT 759 15.000 11.000 17.000 1.00 0.00 O -ATOM 760 O WAT 760 15.000 11.000 19.000 1.00 0.00 O -ATOM 761 O WAT 761 15.000 13.000 1.000 1.00 0.00 O -ATOM 762 O WAT 762 15.000 13.000 3.000 1.00 0.00 O -ATOM 763 O WAT 763 15.000 13.000 5.000 1.00 0.00 O -ATOM 764 O WAT 764 15.000 13.000 7.000 1.00 0.00 O -ATOM 765 O WAT 765 15.000 13.000 9.000 1.00 0.00 O -ATOM 766 O WAT 766 15.000 13.000 11.000 1.00 0.00 O -ATOM 767 O WAT 767 15.000 13.000 13.000 1.00 0.00 O -ATOM 768 O WAT 768 15.000 13.000 15.000 1.00 0.00 O -ATOM 769 O WAT 769 15.000 13.000 17.000 1.00 0.00 O -ATOM 770 O WAT 770 15.000 13.000 19.000 1.00 0.00 O -ATOM 771 O WAT 771 15.000 15.000 1.000 1.00 0.00 O -ATOM 772 O WAT 772 15.000 15.000 3.000 1.00 0.00 O -ATOM 773 O WAT 773 15.000 15.000 5.000 1.00 0.00 O -ATOM 774 O WAT 774 15.000 15.000 7.000 1.00 0.00 O -ATOM 775 O WAT 775 15.000 15.000 9.000 1.00 0.00 O -ATOM 776 O WAT 776 15.000 15.000 11.000 1.00 0.00 O -ATOM 777 O WAT 777 15.000 15.000 13.000 1.00 0.00 O -ATOM 778 O WAT 778 15.000 15.000 15.000 1.00 0.00 O -ATOM 779 O WAT 779 15.000 15.000 17.000 1.00 0.00 O -ATOM 780 O WAT 780 15.000 15.000 19.000 1.00 0.00 O -ATOM 781 O WAT 781 15.000 17.000 1.000 1.00 0.00 O -ATOM 782 O WAT 782 15.000 17.000 3.000 1.00 0.00 O -ATOM 783 O WAT 783 15.000 17.000 5.000 1.00 0.00 O -ATOM 784 O WAT 784 15.000 17.000 7.000 1.00 0.00 O -ATOM 785 O WAT 785 15.000 17.000 9.000 1.00 0.00 O -ATOM 786 O WAT 786 15.000 17.000 11.000 1.00 0.00 O -ATOM 787 O WAT 787 15.000 17.000 13.000 1.00 0.00 O -ATOM 788 O WAT 788 15.000 17.000 15.000 1.00 0.00 O -ATOM 789 O WAT 789 15.000 17.000 17.000 1.00 0.00 O -ATOM 790 O WAT 790 15.000 17.000 19.000 1.00 0.00 O -ATOM 791 O WAT 791 15.000 19.000 1.000 1.00 0.00 O -ATOM 792 O WAT 792 15.000 19.000 3.000 1.00 0.00 O -ATOM 793 O WAT 793 15.000 19.000 5.000 1.00 0.00 O -ATOM 794 O WAT 794 15.000 19.000 7.000 1.00 0.00 O -ATOM 795 O WAT 795 15.000 19.000 9.000 1.00 0.00 O -ATOM 796 O WAT 796 15.000 19.000 11.000 1.00 0.00 O -ATOM 797 O WAT 797 15.000 19.000 13.000 1.00 0.00 O -ATOM 798 O WAT 798 15.000 19.000 15.000 1.00 0.00 O -ATOM 799 O WAT 799 15.000 19.000 17.000 1.00 0.00 O -ATOM 800 O WAT 800 15.000 19.000 19.000 1.00 0.00 O -ATOM 801 O WAT 801 17.000 1.000 1.000 1.00 0.00 O -ATOM 802 O WAT 802 17.000 1.000 3.000 1.00 0.00 O -ATOM 803 O WAT 803 17.000 1.000 5.000 1.00 0.00 O -ATOM 804 O WAT 804 17.000 1.000 7.000 1.00 0.00 O -ATOM 805 O WAT 805 17.000 1.000 9.000 1.00 0.00 O -ATOM 806 O WAT 806 17.000 1.000 11.000 1.00 0.00 O -ATOM 807 O WAT 807 17.000 1.000 13.000 1.00 0.00 O -ATOM 808 O WAT 808 17.000 1.000 15.000 1.00 0.00 O -ATOM 809 O WAT 809 17.000 1.000 17.000 1.00 0.00 O -ATOM 810 O WAT 810 17.000 1.000 19.000 1.00 0.00 O -ATOM 811 O WAT 811 17.000 3.000 1.000 1.00 0.00 O -ATOM 812 O WAT 812 17.000 3.000 3.000 1.00 0.00 O -ATOM 813 O WAT 813 17.000 3.000 5.000 1.00 0.00 O -ATOM 814 O WAT 814 17.000 3.000 7.000 1.00 0.00 O -ATOM 815 O WAT 815 17.000 3.000 9.000 1.00 0.00 O -ATOM 816 O WAT 816 17.000 3.000 11.000 1.00 0.00 O -ATOM 817 O WAT 817 17.000 3.000 13.000 1.00 0.00 O -ATOM 818 O WAT 818 17.000 3.000 15.000 1.00 0.00 O -ATOM 819 O WAT 819 17.000 3.000 17.000 1.00 0.00 O -ATOM 820 O WAT 820 17.000 3.000 19.000 1.00 0.00 O -ATOM 821 O WAT 821 17.000 5.000 1.000 1.00 0.00 O -ATOM 822 O WAT 822 17.000 5.000 3.000 1.00 0.00 O -ATOM 823 O WAT 823 17.000 5.000 5.000 1.00 0.00 O -ATOM 824 O WAT 824 17.000 5.000 7.000 1.00 0.00 O -ATOM 825 O WAT 825 17.000 5.000 9.000 1.00 0.00 O -ATOM 826 O WAT 826 17.000 5.000 11.000 1.00 0.00 O -ATOM 827 O WAT 827 17.000 5.000 13.000 1.00 0.00 O -ATOM 828 O WAT 828 17.000 5.000 15.000 1.00 0.00 O -ATOM 829 O WAT 829 17.000 5.000 17.000 1.00 0.00 O -ATOM 830 O WAT 830 17.000 5.000 19.000 1.00 0.00 O -ATOM 831 O WAT 831 17.000 7.000 1.000 1.00 0.00 O -ATOM 832 O WAT 832 17.000 7.000 3.000 1.00 0.00 O -ATOM 833 O WAT 833 17.000 7.000 5.000 1.00 0.00 O -ATOM 834 O WAT 834 17.000 7.000 7.000 1.00 0.00 O -ATOM 835 O WAT 835 17.000 7.000 9.000 1.00 0.00 O -ATOM 836 O WAT 836 17.000 7.000 11.000 1.00 0.00 O -ATOM 837 O WAT 837 17.000 7.000 13.000 1.00 0.00 O -ATOM 838 O WAT 838 17.000 7.000 15.000 1.00 0.00 O -ATOM 839 O WAT 839 17.000 7.000 17.000 1.00 0.00 O -ATOM 840 O WAT 840 17.000 7.000 19.000 1.00 0.00 O -ATOM 841 O WAT 841 17.000 9.000 1.000 1.00 0.00 O -ATOM 842 O WAT 842 17.000 9.000 3.000 1.00 0.00 O -ATOM 843 O WAT 843 17.000 9.000 5.000 1.00 0.00 O -ATOM 844 O WAT 844 17.000 9.000 7.000 1.00 0.00 O -ATOM 845 O WAT 845 17.000 9.000 9.000 1.00 0.00 O -ATOM 846 O WAT 846 17.000 9.000 11.000 1.00 0.00 O -ATOM 847 O WAT 847 17.000 9.000 13.000 1.00 0.00 O -ATOM 848 O WAT 848 17.000 9.000 15.000 1.00 0.00 O -ATOM 849 O WAT 849 17.000 9.000 17.000 1.00 0.00 O -ATOM 850 O WAT 850 17.000 9.000 19.000 1.00 0.00 O -ATOM 851 O WAT 851 17.000 11.000 1.000 1.00 0.00 O -ATOM 852 O WAT 852 17.000 11.000 3.000 1.00 0.00 O -ATOM 853 O WAT 853 17.000 11.000 5.000 1.00 0.00 O -ATOM 854 O WAT 854 17.000 11.000 7.000 1.00 0.00 O -ATOM 855 O WAT 855 17.000 11.000 9.000 1.00 0.00 O -ATOM 856 O WAT 856 17.000 11.000 11.000 1.00 0.00 O -ATOM 857 O WAT 857 17.000 11.000 13.000 1.00 0.00 O -ATOM 858 O WAT 858 17.000 11.000 15.000 1.00 0.00 O -ATOM 859 O WAT 859 17.000 11.000 17.000 1.00 0.00 O -ATOM 860 O WAT 860 17.000 11.000 19.000 1.00 0.00 O -ATOM 861 O WAT 861 17.000 13.000 1.000 1.00 0.00 O -ATOM 862 O WAT 862 17.000 13.000 3.000 1.00 0.00 O -ATOM 863 O WAT 863 17.000 13.000 5.000 1.00 0.00 O -ATOM 864 O WAT 864 17.000 13.000 7.000 1.00 0.00 O -ATOM 865 O WAT 865 17.000 13.000 9.000 1.00 0.00 O -ATOM 866 O WAT 866 17.000 13.000 11.000 1.00 0.00 O -ATOM 867 O WAT 867 17.000 13.000 13.000 1.00 0.00 O -ATOM 868 O WAT 868 17.000 13.000 15.000 1.00 0.00 O -ATOM 869 O WAT 869 17.000 13.000 17.000 1.00 0.00 O -ATOM 870 O WAT 870 17.000 13.000 19.000 1.00 0.00 O -ATOM 871 O WAT 871 17.000 15.000 1.000 1.00 0.00 O -ATOM 872 O WAT 872 17.000 15.000 3.000 1.00 0.00 O -ATOM 873 O WAT 873 17.000 15.000 5.000 1.00 0.00 O -ATOM 874 O WAT 874 17.000 15.000 7.000 1.00 0.00 O -ATOM 875 O WAT 875 17.000 15.000 9.000 1.00 0.00 O -ATOM 876 O WAT 876 17.000 15.000 11.000 1.00 0.00 O -ATOM 877 O WAT 877 17.000 15.000 13.000 1.00 0.00 O -ATOM 878 O WAT 878 17.000 15.000 15.000 1.00 0.00 O -ATOM 879 O WAT 879 17.000 15.000 17.000 1.00 0.00 O -ATOM 880 O WAT 880 17.000 15.000 19.000 1.00 0.00 O -ATOM 881 O WAT 881 17.000 17.000 1.000 1.00 0.00 O -ATOM 882 O WAT 882 17.000 17.000 3.000 1.00 0.00 O -ATOM 883 O WAT 883 17.000 17.000 5.000 1.00 0.00 O -ATOM 884 O WAT 884 17.000 17.000 7.000 1.00 0.00 O -ATOM 885 O WAT 885 17.000 17.000 9.000 1.00 0.00 O -ATOM 886 O WAT 886 17.000 17.000 11.000 1.00 0.00 O -ATOM 887 O WAT 887 17.000 17.000 13.000 1.00 0.00 O -ATOM 888 O WAT 888 17.000 17.000 15.000 1.00 0.00 O -ATOM 889 O WAT 889 17.000 17.000 17.000 1.00 0.00 O -ATOM 890 O WAT 890 17.000 17.000 19.000 1.00 0.00 O -ATOM 891 O WAT 891 17.000 19.000 1.000 1.00 0.00 O -ATOM 892 O WAT 892 17.000 19.000 3.000 1.00 0.00 O -ATOM 893 O WAT 893 17.000 19.000 5.000 1.00 0.00 O -ATOM 894 O WAT 894 17.000 19.000 7.000 1.00 0.00 O -ATOM 895 O WAT 895 17.000 19.000 9.000 1.00 0.00 O -ATOM 896 O WAT 896 17.000 19.000 11.000 1.00 0.00 O -ATOM 897 O WAT 897 17.000 19.000 13.000 1.00 0.00 O -ATOM 898 O WAT 898 17.000 19.000 15.000 1.00 0.00 O -ATOM 899 O WAT 899 17.000 19.000 17.000 1.00 0.00 O -ATOM 900 O WAT 900 17.000 19.000 19.000 1.00 0.00 O -ATOM 901 O WAT 901 19.000 1.000 1.000 1.00 0.00 O -ATOM 902 O WAT 902 19.000 1.000 3.000 1.00 0.00 O -ATOM 903 O WAT 903 19.000 1.000 5.000 1.00 0.00 O -ATOM 904 O WAT 904 19.000 1.000 7.000 1.00 0.00 O -ATOM 905 O WAT 905 19.000 1.000 9.000 1.00 0.00 O -ATOM 906 O WAT 906 19.000 1.000 11.000 1.00 0.00 O -ATOM 907 O WAT 907 19.000 1.000 13.000 1.00 0.00 O -ATOM 908 O WAT 908 19.000 1.000 15.000 1.00 0.00 O -ATOM 909 O WAT 909 19.000 1.000 17.000 1.00 0.00 O -ATOM 910 O WAT 910 19.000 1.000 19.000 1.00 0.00 O -ATOM 911 O WAT 911 19.000 3.000 1.000 1.00 0.00 O -ATOM 912 O WAT 912 19.000 3.000 3.000 1.00 0.00 O -ATOM 913 O WAT 913 19.000 3.000 5.000 1.00 0.00 O -ATOM 914 O WAT 914 19.000 3.000 7.000 1.00 0.00 O -ATOM 915 O WAT 915 19.000 3.000 9.000 1.00 0.00 O -ATOM 916 O WAT 916 19.000 3.000 11.000 1.00 0.00 O -ATOM 917 O WAT 917 19.000 3.000 13.000 1.00 0.00 O -ATOM 918 O WAT 918 19.000 3.000 15.000 1.00 0.00 O -ATOM 919 O WAT 919 19.000 3.000 17.000 1.00 0.00 O -ATOM 920 O WAT 920 19.000 3.000 19.000 1.00 0.00 O -ATOM 921 O WAT 921 19.000 5.000 1.000 1.00 0.00 O -ATOM 922 O WAT 922 19.000 5.000 3.000 1.00 0.00 O -ATOM 923 O WAT 923 19.000 5.000 5.000 1.00 0.00 O -ATOM 924 O WAT 924 19.000 5.000 7.000 1.00 0.00 O -ATOM 925 O WAT 925 19.000 5.000 9.000 1.00 0.00 O -ATOM 926 O WAT 926 19.000 5.000 11.000 1.00 0.00 O -ATOM 927 O WAT 927 19.000 5.000 13.000 1.00 0.00 O -ATOM 928 O WAT 928 19.000 5.000 15.000 1.00 0.00 O -ATOM 929 O WAT 929 19.000 5.000 17.000 1.00 0.00 O -ATOM 930 O WAT 930 19.000 5.000 19.000 1.00 0.00 O -ATOM 931 O WAT 931 19.000 7.000 1.000 1.00 0.00 O -ATOM 932 O WAT 932 19.000 7.000 3.000 1.00 0.00 O -ATOM 933 O WAT 933 19.000 7.000 5.000 1.00 0.00 O -ATOM 934 O WAT 934 19.000 7.000 7.000 1.00 0.00 O -ATOM 935 O WAT 935 19.000 7.000 9.000 1.00 0.00 O -ATOM 936 O WAT 936 19.000 7.000 11.000 1.00 0.00 O -ATOM 937 O WAT 937 19.000 7.000 13.000 1.00 0.00 O -ATOM 938 O WAT 938 19.000 7.000 15.000 1.00 0.00 O -ATOM 939 O WAT 939 19.000 7.000 17.000 1.00 0.00 O -ATOM 940 O WAT 940 19.000 7.000 19.000 1.00 0.00 O -ATOM 941 O WAT 941 19.000 9.000 1.000 1.00 0.00 O -ATOM 942 O WAT 942 19.000 9.000 3.000 1.00 0.00 O -ATOM 943 O WAT 943 19.000 9.000 5.000 1.00 0.00 O -ATOM 944 O WAT 944 19.000 9.000 7.000 1.00 0.00 O -ATOM 945 O WAT 945 19.000 9.000 9.000 1.00 0.00 O -ATOM 946 O WAT 946 19.000 9.000 11.000 1.00 0.00 O -ATOM 947 O WAT 947 19.000 9.000 13.000 1.00 0.00 O -ATOM 948 O WAT 948 19.000 9.000 15.000 1.00 0.00 O -ATOM 949 O WAT 949 19.000 9.000 17.000 1.00 0.00 O -ATOM 950 O WAT 950 19.000 9.000 19.000 1.00 0.00 O -ATOM 951 O WAT 951 19.000 11.000 1.000 1.00 0.00 O -ATOM 952 O WAT 952 19.000 11.000 3.000 1.00 0.00 O -ATOM 953 O WAT 953 19.000 11.000 5.000 1.00 0.00 O -ATOM 954 O WAT 954 19.000 11.000 7.000 1.00 0.00 O -ATOM 955 O WAT 955 19.000 11.000 9.000 1.00 0.00 O -ATOM 956 O WAT 956 19.000 11.000 11.000 1.00 0.00 O -ATOM 957 O WAT 957 19.000 11.000 13.000 1.00 0.00 O -ATOM 958 O WAT 958 19.000 11.000 15.000 1.00 0.00 O -ATOM 959 O WAT 959 19.000 11.000 17.000 1.00 0.00 O -ATOM 960 O WAT 960 19.000 11.000 19.000 1.00 0.00 O -ATOM 961 O WAT 961 19.000 13.000 1.000 1.00 0.00 O -ATOM 962 O WAT 962 19.000 13.000 3.000 1.00 0.00 O -ATOM 963 O WAT 963 19.000 13.000 5.000 1.00 0.00 O -ATOM 964 O WAT 964 19.000 13.000 7.000 1.00 0.00 O -ATOM 965 O WAT 965 19.000 13.000 9.000 1.00 0.00 O -ATOM 966 O WAT 966 19.000 13.000 11.000 1.00 0.00 O -ATOM 967 O WAT 967 19.000 13.000 13.000 1.00 0.00 O -ATOM 968 O WAT 968 19.000 13.000 15.000 1.00 0.00 O -ATOM 969 O WAT 969 19.000 13.000 17.000 1.00 0.00 O -ATOM 970 O WAT 970 19.000 13.000 19.000 1.00 0.00 O -ATOM 971 O WAT 971 19.000 15.000 1.000 1.00 0.00 O -ATOM 972 O WAT 972 19.000 15.000 3.000 1.00 0.00 O -ATOM 973 O WAT 973 19.000 15.000 5.000 1.00 0.00 O -ATOM 974 O WAT 974 19.000 15.000 7.000 1.00 0.00 O -ATOM 975 O WAT 975 19.000 15.000 9.000 1.00 0.00 O -ATOM 976 O WAT 976 19.000 15.000 11.000 1.00 0.00 O -ATOM 977 O WAT 977 19.000 15.000 13.000 1.00 0.00 O -ATOM 978 O WAT 978 19.000 15.000 15.000 1.00 0.00 O -ATOM 979 O WAT 979 19.000 15.000 17.000 1.00 0.00 O -ATOM 980 O WAT 980 19.000 15.000 19.000 1.00 0.00 O -ATOM 981 O WAT 981 19.000 17.000 1.000 1.00 0.00 O -ATOM 982 O WAT 982 19.000 17.000 3.000 1.00 0.00 O -ATOM 983 O WAT 983 19.000 17.000 5.000 1.00 0.00 O -ATOM 984 O WAT 984 19.000 17.000 7.000 1.00 0.00 O -ATOM 985 O WAT 985 19.000 17.000 9.000 1.00 0.00 O -ATOM 986 O WAT 986 19.000 17.000 11.000 1.00 0.00 O -ATOM 987 O WAT 987 19.000 17.000 13.000 1.00 0.00 O -ATOM 988 O WAT 988 19.000 17.000 15.000 1.00 0.00 O -ATOM 989 O WAT 989 19.000 17.000 17.000 1.00 0.00 O -ATOM 990 O WAT 990 19.000 17.000 19.000 1.00 0.00 O -ATOM 991 O WAT 991 19.000 19.000 1.000 1.00 0.00 O -ATOM 992 O WAT 992 19.000 19.000 3.000 1.00 0.00 O -ATOM 993 O WAT 993 19.000 19.000 5.000 1.00 0.00 O -ATOM 994 O WAT 994 19.000 19.000 7.000 1.00 0.00 O -ATOM 995 O WAT 995 19.000 19.000 9.000 1.00 0.00 O -ATOM 996 O WAT 996 19.000 19.000 11.000 1.00 0.00 O -ATOM 997 O WAT 997 19.000 19.000 13.000 1.00 0.00 O -ATOM 998 O WAT 998 19.000 19.000 15.000 1.00 0.00 O -ATOM 999 O WAT 999 19.000 19.000 17.000 1.00 0.00 O -ATOM 1000 O WAT 1000 19.000 19.000 19.000 1.00 0.00 O +REMARK cubic lattice with z-corrugation for surftension tests +ATOM 1 O WAT 1 1.000 1.000 1.029 1.00 0.00 O +ATOM 2 O WAT 2 1.000 1.000 3.029 1.00 0.00 O +ATOM 3 O WAT 3 1.000 1.000 5.029 1.00 0.00 O +ATOM 4 O WAT 4 1.000 1.000 7.029 1.00 0.00 O +ATOM 5 O WAT 5 1.000 1.000 9.029 1.00 0.00 O +ATOM 6 O WAT 6 1.000 1.000 11.029 1.00 0.00 O +ATOM 7 O WAT 7 1.000 1.000 13.029 1.00 0.00 O +ATOM 8 O WAT 8 1.000 1.000 15.029 1.00 0.00 O +ATOM 9 O WAT 9 1.000 1.000 17.029 1.00 0.00 O +ATOM 10 O WAT 10 1.000 1.000 19.029 1.00 0.00 O +ATOM 11 O WAT 11 1.000 3.000 1.075 1.00 0.00 O +ATOM 12 O WAT 12 1.000 3.000 3.075 1.00 0.00 O +ATOM 13 O WAT 13 1.000 3.000 5.075 1.00 0.00 O +ATOM 14 O WAT 14 1.000 3.000 7.075 1.00 0.00 O +ATOM 15 O WAT 15 1.000 3.000 9.075 1.00 0.00 O +ATOM 16 O WAT 16 1.000 3.000 11.075 1.00 0.00 O +ATOM 17 O WAT 17 1.000 3.000 13.075 1.00 0.00 O +ATOM 18 O WAT 18 1.000 3.000 15.075 1.00 0.00 O +ATOM 19 O WAT 19 1.000 3.000 17.075 1.00 0.00 O +ATOM 20 O WAT 20 1.000 3.000 19.075 1.00 0.00 O +ATOM 21 O WAT 21 1.000 5.000 1.093 1.00 0.00 O +ATOM 22 O WAT 22 1.000 5.000 3.093 1.00 0.00 O +ATOM 23 O WAT 23 1.000 5.000 5.093 1.00 0.00 O +ATOM 24 O WAT 24 1.000 5.000 7.093 1.00 0.00 O +ATOM 25 O WAT 25 1.000 5.000 9.093 1.00 0.00 O +ATOM 26 O WAT 26 1.000 5.000 11.093 1.00 0.00 O +ATOM 27 O WAT 27 1.000 5.000 13.093 1.00 0.00 O +ATOM 28 O WAT 28 1.000 5.000 15.093 1.00 0.00 O +ATOM 29 O WAT 29 1.000 5.000 17.093 1.00 0.00 O +ATOM 30 O WAT 30 1.000 5.000 19.093 1.00 0.00 O +ATOM 31 O WAT 31 1.000 7.000 1.075 1.00 0.00 O +ATOM 32 O WAT 32 1.000 7.000 3.075 1.00 0.00 O +ATOM 33 O WAT 33 1.000 7.000 5.075 1.00 0.00 O +ATOM 34 O WAT 34 1.000 7.000 7.075 1.00 0.00 O +ATOM 35 O WAT 35 1.000 7.000 9.075 1.00 0.00 O +ATOM 36 O WAT 36 1.000 7.000 11.075 1.00 0.00 O +ATOM 37 O WAT 37 1.000 7.000 13.075 1.00 0.00 O +ATOM 38 O WAT 38 1.000 7.000 15.075 1.00 0.00 O +ATOM 39 O WAT 39 1.000 7.000 17.075 1.00 0.00 O +ATOM 40 O WAT 40 1.000 7.000 19.075 1.00 0.00 O +ATOM 41 O WAT 41 1.000 9.000 1.029 1.00 0.00 O +ATOM 42 O WAT 42 1.000 9.000 3.029 1.00 0.00 O +ATOM 43 O WAT 43 1.000 9.000 5.029 1.00 0.00 O +ATOM 44 O WAT 44 1.000 9.000 7.029 1.00 0.00 O +ATOM 45 O WAT 45 1.000 9.000 9.029 1.00 0.00 O +ATOM 46 O WAT 46 1.000 9.000 11.029 1.00 0.00 O +ATOM 47 O WAT 47 1.000 9.000 13.029 1.00 0.00 O +ATOM 48 O WAT 48 1.000 9.000 15.029 1.00 0.00 O +ATOM 49 O WAT 49 1.000 9.000 17.029 1.00 0.00 O +ATOM 50 O WAT 50 1.000 9.000 19.029 1.00 0.00 O +ATOM 51 O WAT 51 1.000 11.000 0.971 1.00 0.00 O +ATOM 52 O WAT 52 1.000 11.000 2.971 1.00 0.00 O +ATOM 53 O WAT 53 1.000 11.000 4.971 1.00 0.00 O +ATOM 54 O WAT 54 1.000 11.000 6.971 1.00 0.00 O +ATOM 55 O WAT 55 1.000 11.000 8.971 1.00 0.00 O +ATOM 56 O WAT 56 1.000 11.000 10.971 1.00 0.00 O +ATOM 57 O WAT 57 1.000 11.000 12.971 1.00 0.00 O +ATOM 58 O WAT 58 1.000 11.000 14.971 1.00 0.00 O +ATOM 59 O WAT 59 1.000 11.000 16.971 1.00 0.00 O +ATOM 60 O WAT 60 1.000 11.000 18.971 1.00 0.00 O +ATOM 61 O WAT 61 1.000 13.000 0.925 1.00 0.00 O +ATOM 62 O WAT 62 1.000 13.000 2.925 1.00 0.00 O +ATOM 63 O WAT 63 1.000 13.000 4.925 1.00 0.00 O +ATOM 64 O WAT 64 1.000 13.000 6.925 1.00 0.00 O +ATOM 65 O WAT 65 1.000 13.000 8.925 1.00 0.00 O +ATOM 66 O WAT 66 1.000 13.000 10.925 1.00 0.00 O +ATOM 67 O WAT 67 1.000 13.000 12.925 1.00 0.00 O +ATOM 68 O WAT 68 1.000 13.000 14.925 1.00 0.00 O +ATOM 69 O WAT 69 1.000 13.000 16.925 1.00 0.00 O +ATOM 70 O WAT 70 1.000 13.000 18.925 1.00 0.00 O +ATOM 71 O WAT 71 1.000 15.000 0.907 1.00 0.00 O +ATOM 72 O WAT 72 1.000 15.000 2.907 1.00 0.00 O +ATOM 73 O WAT 73 1.000 15.000 4.907 1.00 0.00 O +ATOM 74 O WAT 74 1.000 15.000 6.907 1.00 0.00 O +ATOM 75 O WAT 75 1.000 15.000 8.907 1.00 0.00 O +ATOM 76 O WAT 76 1.000 15.000 10.907 1.00 0.00 O +ATOM 77 O WAT 77 1.000 15.000 12.907 1.00 0.00 O +ATOM 78 O WAT 78 1.000 15.000 14.907 1.00 0.00 O +ATOM 79 O WAT 79 1.000 15.000 16.907 1.00 0.00 O +ATOM 80 O WAT 80 1.000 15.000 18.907 1.00 0.00 O +ATOM 81 O WAT 81 1.000 17.000 0.925 1.00 0.00 O +ATOM 82 O WAT 82 1.000 17.000 2.925 1.00 0.00 O +ATOM 83 O WAT 83 1.000 17.000 4.925 1.00 0.00 O +ATOM 84 O WAT 84 1.000 17.000 6.925 1.00 0.00 O +ATOM 85 O WAT 85 1.000 17.000 8.925 1.00 0.00 O +ATOM 86 O WAT 86 1.000 17.000 10.925 1.00 0.00 O +ATOM 87 O WAT 87 1.000 17.000 12.925 1.00 0.00 O +ATOM 88 O WAT 88 1.000 17.000 14.925 1.00 0.00 O +ATOM 89 O WAT 89 1.000 17.000 16.925 1.00 0.00 O +ATOM 90 O WAT 90 1.000 17.000 18.925 1.00 0.00 O +ATOM 91 O WAT 91 1.000 19.000 0.971 1.00 0.00 O +ATOM 92 O WAT 92 1.000 19.000 2.971 1.00 0.00 O +ATOM 93 O WAT 93 1.000 19.000 4.971 1.00 0.00 O +ATOM 94 O WAT 94 1.000 19.000 6.971 1.00 0.00 O +ATOM 95 O WAT 95 1.000 19.000 8.971 1.00 0.00 O +ATOM 96 O WAT 96 1.000 19.000 10.971 1.00 0.00 O +ATOM 97 O WAT 97 1.000 19.000 12.971 1.00 0.00 O +ATOM 98 O WAT 98 1.000 19.000 14.971 1.00 0.00 O +ATOM 99 O WAT 99 1.000 19.000 16.971 1.00 0.00 O +ATOM 100 O WAT 100 1.000 19.000 18.971 1.00 0.00 O +ATOM 101 O WAT 101 3.000 1.000 1.075 1.00 0.00 O +ATOM 102 O WAT 102 3.000 1.000 3.075 1.00 0.00 O +ATOM 103 O WAT 103 3.000 1.000 5.075 1.00 0.00 O +ATOM 104 O WAT 104 3.000 1.000 7.075 1.00 0.00 O +ATOM 105 O WAT 105 3.000 1.000 9.075 1.00 0.00 O +ATOM 106 O WAT 106 3.000 1.000 11.075 1.00 0.00 O +ATOM 107 O WAT 107 3.000 1.000 13.075 1.00 0.00 O +ATOM 108 O WAT 108 3.000 1.000 15.075 1.00 0.00 O +ATOM 109 O WAT 109 3.000 1.000 17.075 1.00 0.00 O +ATOM 110 O WAT 110 3.000 1.000 19.075 1.00 0.00 O +ATOM 111 O WAT 111 3.000 3.000 1.196 1.00 0.00 O +ATOM 112 O WAT 112 3.000 3.000 3.196 1.00 0.00 O +ATOM 113 O WAT 113 3.000 3.000 5.196 1.00 0.00 O +ATOM 114 O WAT 114 3.000 3.000 7.196 1.00 0.00 O +ATOM 115 O WAT 115 3.000 3.000 9.196 1.00 0.00 O +ATOM 116 O WAT 116 3.000 3.000 11.196 1.00 0.00 O +ATOM 117 O WAT 117 3.000 3.000 13.196 1.00 0.00 O +ATOM 118 O WAT 118 3.000 3.000 15.196 1.00 0.00 O +ATOM 119 O WAT 119 3.000 3.000 17.196 1.00 0.00 O +ATOM 120 O WAT 120 3.000 3.000 19.196 1.00 0.00 O +ATOM 121 O WAT 121 3.000 5.000 1.243 1.00 0.00 O +ATOM 122 O WAT 122 3.000 5.000 3.243 1.00 0.00 O +ATOM 123 O WAT 123 3.000 5.000 5.243 1.00 0.00 O +ATOM 124 O WAT 124 3.000 5.000 7.243 1.00 0.00 O +ATOM 125 O WAT 125 3.000 5.000 9.243 1.00 0.00 O +ATOM 126 O WAT 126 3.000 5.000 11.243 1.00 0.00 O +ATOM 127 O WAT 127 3.000 5.000 13.243 1.00 0.00 O +ATOM 128 O WAT 128 3.000 5.000 15.243 1.00 0.00 O +ATOM 129 O WAT 129 3.000 5.000 17.243 1.00 0.00 O +ATOM 130 O WAT 130 3.000 5.000 19.243 1.00 0.00 O +ATOM 131 O WAT 131 3.000 7.000 1.196 1.00 0.00 O +ATOM 132 O WAT 132 3.000 7.000 3.196 1.00 0.00 O +ATOM 133 O WAT 133 3.000 7.000 5.196 1.00 0.00 O +ATOM 134 O WAT 134 3.000 7.000 7.196 1.00 0.00 O +ATOM 135 O WAT 135 3.000 7.000 9.196 1.00 0.00 O +ATOM 136 O WAT 136 3.000 7.000 11.196 1.00 0.00 O +ATOM 137 O WAT 137 3.000 7.000 13.196 1.00 0.00 O +ATOM 138 O WAT 138 3.000 7.000 15.196 1.00 0.00 O +ATOM 139 O WAT 139 3.000 7.000 17.196 1.00 0.00 O +ATOM 140 O WAT 140 3.000 7.000 19.196 1.00 0.00 O +ATOM 141 O WAT 141 3.000 9.000 1.075 1.00 0.00 O +ATOM 142 O WAT 142 3.000 9.000 3.075 1.00 0.00 O +ATOM 143 O WAT 143 3.000 9.000 5.075 1.00 0.00 O +ATOM 144 O WAT 144 3.000 9.000 7.075 1.00 0.00 O +ATOM 145 O WAT 145 3.000 9.000 9.075 1.00 0.00 O +ATOM 146 O WAT 146 3.000 9.000 11.075 1.00 0.00 O +ATOM 147 O WAT 147 3.000 9.000 13.075 1.00 0.00 O +ATOM 148 O WAT 148 3.000 9.000 15.075 1.00 0.00 O +ATOM 149 O WAT 149 3.000 9.000 17.075 1.00 0.00 O +ATOM 150 O WAT 150 3.000 9.000 19.075 1.00 0.00 O +ATOM 151 O WAT 151 3.000 11.000 0.925 1.00 0.00 O +ATOM 152 O WAT 152 3.000 11.000 2.925 1.00 0.00 O +ATOM 153 O WAT 153 3.000 11.000 4.925 1.00 0.00 O +ATOM 154 O WAT 154 3.000 11.000 6.925 1.00 0.00 O +ATOM 155 O WAT 155 3.000 11.000 8.925 1.00 0.00 O +ATOM 156 O WAT 156 3.000 11.000 10.925 1.00 0.00 O +ATOM 157 O WAT 157 3.000 11.000 12.925 1.00 0.00 O +ATOM 158 O WAT 158 3.000 11.000 14.925 1.00 0.00 O +ATOM 159 O WAT 159 3.000 11.000 16.925 1.00 0.00 O +ATOM 160 O WAT 160 3.000 11.000 18.925 1.00 0.00 O +ATOM 161 O WAT 161 3.000 13.000 0.804 1.00 0.00 O +ATOM 162 O WAT 162 3.000 13.000 2.804 1.00 0.00 O +ATOM 163 O WAT 163 3.000 13.000 4.804 1.00 0.00 O +ATOM 164 O WAT 164 3.000 13.000 6.804 1.00 0.00 O +ATOM 165 O WAT 165 3.000 13.000 8.804 1.00 0.00 O +ATOM 166 O WAT 166 3.000 13.000 10.804 1.00 0.00 O +ATOM 167 O WAT 167 3.000 13.000 12.804 1.00 0.00 O +ATOM 168 O WAT 168 3.000 13.000 14.804 1.00 0.00 O +ATOM 169 O WAT 169 3.000 13.000 16.804 1.00 0.00 O +ATOM 170 O WAT 170 3.000 13.000 18.804 1.00 0.00 O +ATOM 171 O WAT 171 3.000 15.000 0.757 1.00 0.00 O +ATOM 172 O WAT 172 3.000 15.000 2.757 1.00 0.00 O +ATOM 173 O WAT 173 3.000 15.000 4.757 1.00 0.00 O +ATOM 174 O WAT 174 3.000 15.000 6.757 1.00 0.00 O +ATOM 175 O WAT 175 3.000 15.000 8.757 1.00 0.00 O +ATOM 176 O WAT 176 3.000 15.000 10.757 1.00 0.00 O +ATOM 177 O WAT 177 3.000 15.000 12.757 1.00 0.00 O +ATOM 178 O WAT 178 3.000 15.000 14.757 1.00 0.00 O +ATOM 179 O WAT 179 3.000 15.000 16.757 1.00 0.00 O +ATOM 180 O WAT 180 3.000 15.000 18.757 1.00 0.00 O +ATOM 181 O WAT 181 3.000 17.000 0.804 1.00 0.00 O +ATOM 182 O WAT 182 3.000 17.000 2.804 1.00 0.00 O +ATOM 183 O WAT 183 3.000 17.000 4.804 1.00 0.00 O +ATOM 184 O WAT 184 3.000 17.000 6.804 1.00 0.00 O +ATOM 185 O WAT 185 3.000 17.000 8.804 1.00 0.00 O +ATOM 186 O WAT 186 3.000 17.000 10.804 1.00 0.00 O +ATOM 187 O WAT 187 3.000 17.000 12.804 1.00 0.00 O +ATOM 188 O WAT 188 3.000 17.000 14.804 1.00 0.00 O +ATOM 189 O WAT 189 3.000 17.000 16.804 1.00 0.00 O +ATOM 190 O WAT 190 3.000 17.000 18.804 1.00 0.00 O +ATOM 191 O WAT 191 3.000 19.000 0.925 1.00 0.00 O +ATOM 192 O WAT 192 3.000 19.000 2.925 1.00 0.00 O +ATOM 193 O WAT 193 3.000 19.000 4.925 1.00 0.00 O +ATOM 194 O WAT 194 3.000 19.000 6.925 1.00 0.00 O +ATOM 195 O WAT 195 3.000 19.000 8.925 1.00 0.00 O +ATOM 196 O WAT 196 3.000 19.000 10.925 1.00 0.00 O +ATOM 197 O WAT 197 3.000 19.000 12.925 1.00 0.00 O +ATOM 198 O WAT 198 3.000 19.000 14.925 1.00 0.00 O +ATOM 199 O WAT 199 3.000 19.000 16.925 1.00 0.00 O +ATOM 200 O WAT 200 3.000 19.000 18.925 1.00 0.00 O +ATOM 201 O WAT 201 5.000 1.000 1.093 1.00 0.00 O +ATOM 202 O WAT 202 5.000 1.000 3.093 1.00 0.00 O +ATOM 203 O WAT 203 5.000 1.000 5.093 1.00 0.00 O +ATOM 204 O WAT 204 5.000 1.000 7.093 1.00 0.00 O +ATOM 205 O WAT 205 5.000 1.000 9.093 1.00 0.00 O +ATOM 206 O WAT 206 5.000 1.000 11.093 1.00 0.00 O +ATOM 207 O WAT 207 5.000 1.000 13.093 1.00 0.00 O +ATOM 208 O WAT 208 5.000 1.000 15.093 1.00 0.00 O +ATOM 209 O WAT 209 5.000 1.000 17.093 1.00 0.00 O +ATOM 210 O WAT 210 5.000 1.000 19.093 1.00 0.00 O +ATOM 211 O WAT 211 5.000 3.000 1.243 1.00 0.00 O +ATOM 212 O WAT 212 5.000 3.000 3.243 1.00 0.00 O +ATOM 213 O WAT 213 5.000 3.000 5.243 1.00 0.00 O +ATOM 214 O WAT 214 5.000 3.000 7.243 1.00 0.00 O +ATOM 215 O WAT 215 5.000 3.000 9.243 1.00 0.00 O +ATOM 216 O WAT 216 5.000 3.000 11.243 1.00 0.00 O +ATOM 217 O WAT 217 5.000 3.000 13.243 1.00 0.00 O +ATOM 218 O WAT 218 5.000 3.000 15.243 1.00 0.00 O +ATOM 219 O WAT 219 5.000 3.000 17.243 1.00 0.00 O +ATOM 220 O WAT 220 5.000 3.000 19.243 1.00 0.00 O +ATOM 221 O WAT 221 5.000 5.000 1.300 1.00 0.00 O +ATOM 222 O WAT 222 5.000 5.000 3.300 1.00 0.00 O +ATOM 223 O WAT 223 5.000 5.000 5.300 1.00 0.00 O +ATOM 224 O WAT 224 5.000 5.000 7.300 1.00 0.00 O +ATOM 225 O WAT 225 5.000 5.000 9.300 1.00 0.00 O +ATOM 226 O WAT 226 5.000 5.000 11.300 1.00 0.00 O +ATOM 227 O WAT 227 5.000 5.000 13.300 1.00 0.00 O +ATOM 228 O WAT 228 5.000 5.000 15.300 1.00 0.00 O +ATOM 229 O WAT 229 5.000 5.000 17.300 1.00 0.00 O +ATOM 230 O WAT 230 5.000 5.000 19.300 1.00 0.00 O +ATOM 231 O WAT 231 5.000 7.000 1.243 1.00 0.00 O +ATOM 232 O WAT 232 5.000 7.000 3.243 1.00 0.00 O +ATOM 233 O WAT 233 5.000 7.000 5.243 1.00 0.00 O +ATOM 234 O WAT 234 5.000 7.000 7.243 1.00 0.00 O +ATOM 235 O WAT 235 5.000 7.000 9.243 1.00 0.00 O +ATOM 236 O WAT 236 5.000 7.000 11.243 1.00 0.00 O +ATOM 237 O WAT 237 5.000 7.000 13.243 1.00 0.00 O +ATOM 238 O WAT 238 5.000 7.000 15.243 1.00 0.00 O +ATOM 239 O WAT 239 5.000 7.000 17.243 1.00 0.00 O +ATOM 240 O WAT 240 5.000 7.000 19.243 1.00 0.00 O +ATOM 241 O WAT 241 5.000 9.000 1.093 1.00 0.00 O +ATOM 242 O WAT 242 5.000 9.000 3.093 1.00 0.00 O +ATOM 243 O WAT 243 5.000 9.000 5.093 1.00 0.00 O +ATOM 244 O WAT 244 5.000 9.000 7.093 1.00 0.00 O +ATOM 245 O WAT 245 5.000 9.000 9.093 1.00 0.00 O +ATOM 246 O WAT 246 5.000 9.000 11.093 1.00 0.00 O +ATOM 247 O WAT 247 5.000 9.000 13.093 1.00 0.00 O +ATOM 248 O WAT 248 5.000 9.000 15.093 1.00 0.00 O +ATOM 249 O WAT 249 5.000 9.000 17.093 1.00 0.00 O +ATOM 250 O WAT 250 5.000 9.000 19.093 1.00 0.00 O +ATOM 251 O WAT 251 5.000 11.000 0.907 1.00 0.00 O +ATOM 252 O WAT 252 5.000 11.000 2.907 1.00 0.00 O +ATOM 253 O WAT 253 5.000 11.000 4.907 1.00 0.00 O +ATOM 254 O WAT 254 5.000 11.000 6.907 1.00 0.00 O +ATOM 255 O WAT 255 5.000 11.000 8.907 1.00 0.00 O +ATOM 256 O WAT 256 5.000 11.000 10.907 1.00 0.00 O +ATOM 257 O WAT 257 5.000 11.000 12.907 1.00 0.00 O +ATOM 258 O WAT 258 5.000 11.000 14.907 1.00 0.00 O +ATOM 259 O WAT 259 5.000 11.000 16.907 1.00 0.00 O +ATOM 260 O WAT 260 5.000 11.000 18.907 1.00 0.00 O +ATOM 261 O WAT 261 5.000 13.000 0.757 1.00 0.00 O +ATOM 262 O WAT 262 5.000 13.000 2.757 1.00 0.00 O +ATOM 263 O WAT 263 5.000 13.000 4.757 1.00 0.00 O +ATOM 264 O WAT 264 5.000 13.000 6.757 1.00 0.00 O +ATOM 265 O WAT 265 5.000 13.000 8.757 1.00 0.00 O +ATOM 266 O WAT 266 5.000 13.000 10.757 1.00 0.00 O +ATOM 267 O WAT 267 5.000 13.000 12.757 1.00 0.00 O +ATOM 268 O WAT 268 5.000 13.000 14.757 1.00 0.00 O +ATOM 269 O WAT 269 5.000 13.000 16.757 1.00 0.00 O +ATOM 270 O WAT 270 5.000 13.000 18.757 1.00 0.00 O +ATOM 271 O WAT 271 5.000 15.000 0.700 1.00 0.00 O +ATOM 272 O WAT 272 5.000 15.000 2.700 1.00 0.00 O +ATOM 273 O WAT 273 5.000 15.000 4.700 1.00 0.00 O +ATOM 274 O WAT 274 5.000 15.000 6.700 1.00 0.00 O +ATOM 275 O WAT 275 5.000 15.000 8.700 1.00 0.00 O +ATOM 276 O WAT 276 5.000 15.000 10.700 1.00 0.00 O +ATOM 277 O WAT 277 5.000 15.000 12.700 1.00 0.00 O +ATOM 278 O WAT 278 5.000 15.000 14.700 1.00 0.00 O +ATOM 279 O WAT 279 5.000 15.000 16.700 1.00 0.00 O +ATOM 280 O WAT 280 5.000 15.000 18.700 1.00 0.00 O +ATOM 281 O WAT 281 5.000 17.000 0.757 1.00 0.00 O +ATOM 282 O WAT 282 5.000 17.000 2.757 1.00 0.00 O +ATOM 283 O WAT 283 5.000 17.000 4.757 1.00 0.00 O +ATOM 284 O WAT 284 5.000 17.000 6.757 1.00 0.00 O +ATOM 285 O WAT 285 5.000 17.000 8.757 1.00 0.00 O +ATOM 286 O WAT 286 5.000 17.000 10.757 1.00 0.00 O +ATOM 287 O WAT 287 5.000 17.000 12.757 1.00 0.00 O +ATOM 288 O WAT 288 5.000 17.000 14.757 1.00 0.00 O +ATOM 289 O WAT 289 5.000 17.000 16.757 1.00 0.00 O +ATOM 290 O WAT 290 5.000 17.000 18.757 1.00 0.00 O +ATOM 291 O WAT 291 5.000 19.000 0.907 1.00 0.00 O +ATOM 292 O WAT 292 5.000 19.000 2.907 1.00 0.00 O +ATOM 293 O WAT 293 5.000 19.000 4.907 1.00 0.00 O +ATOM 294 O WAT 294 5.000 19.000 6.907 1.00 0.00 O +ATOM 295 O WAT 295 5.000 19.000 8.907 1.00 0.00 O +ATOM 296 O WAT 296 5.000 19.000 10.907 1.00 0.00 O +ATOM 297 O WAT 297 5.000 19.000 12.907 1.00 0.00 O +ATOM 298 O WAT 298 5.000 19.000 14.907 1.00 0.00 O +ATOM 299 O WAT 299 5.000 19.000 16.907 1.00 0.00 O +ATOM 300 O WAT 300 5.000 19.000 18.907 1.00 0.00 O +ATOM 301 O WAT 301 7.000 1.000 1.075 1.00 0.00 O +ATOM 302 O WAT 302 7.000 1.000 3.075 1.00 0.00 O +ATOM 303 O WAT 303 7.000 1.000 5.075 1.00 0.00 O +ATOM 304 O WAT 304 7.000 1.000 7.075 1.00 0.00 O +ATOM 305 O WAT 305 7.000 1.000 9.075 1.00 0.00 O +ATOM 306 O WAT 306 7.000 1.000 11.075 1.00 0.00 O +ATOM 307 O WAT 307 7.000 1.000 13.075 1.00 0.00 O +ATOM 308 O WAT 308 7.000 1.000 15.075 1.00 0.00 O +ATOM 309 O WAT 309 7.000 1.000 17.075 1.00 0.00 O +ATOM 310 O WAT 310 7.000 1.000 19.075 1.00 0.00 O +ATOM 311 O WAT 311 7.000 3.000 1.196 1.00 0.00 O +ATOM 312 O WAT 312 7.000 3.000 3.196 1.00 0.00 O +ATOM 313 O WAT 313 7.000 3.000 5.196 1.00 0.00 O +ATOM 314 O WAT 314 7.000 3.000 7.196 1.00 0.00 O +ATOM 315 O WAT 315 7.000 3.000 9.196 1.00 0.00 O +ATOM 316 O WAT 316 7.000 3.000 11.196 1.00 0.00 O +ATOM 317 O WAT 317 7.000 3.000 13.196 1.00 0.00 O +ATOM 318 O WAT 318 7.000 3.000 15.196 1.00 0.00 O +ATOM 319 O WAT 319 7.000 3.000 17.196 1.00 0.00 O +ATOM 320 O WAT 320 7.000 3.000 19.196 1.00 0.00 O +ATOM 321 O WAT 321 7.000 5.000 1.243 1.00 0.00 O +ATOM 322 O WAT 322 7.000 5.000 3.243 1.00 0.00 O +ATOM 323 O WAT 323 7.000 5.000 5.243 1.00 0.00 O +ATOM 324 O WAT 324 7.000 5.000 7.243 1.00 0.00 O +ATOM 325 O WAT 325 7.000 5.000 9.243 1.00 0.00 O +ATOM 326 O WAT 326 7.000 5.000 11.243 1.00 0.00 O +ATOM 327 O WAT 327 7.000 5.000 13.243 1.00 0.00 O +ATOM 328 O WAT 328 7.000 5.000 15.243 1.00 0.00 O +ATOM 329 O WAT 329 7.000 5.000 17.243 1.00 0.00 O +ATOM 330 O WAT 330 7.000 5.000 19.243 1.00 0.00 O +ATOM 331 O WAT 331 7.000 7.000 1.196 1.00 0.00 O +ATOM 332 O WAT 332 7.000 7.000 3.196 1.00 0.00 O +ATOM 333 O WAT 333 7.000 7.000 5.196 1.00 0.00 O +ATOM 334 O WAT 334 7.000 7.000 7.196 1.00 0.00 O +ATOM 335 O WAT 335 7.000 7.000 9.196 1.00 0.00 O +ATOM 336 O WAT 336 7.000 7.000 11.196 1.00 0.00 O +ATOM 337 O WAT 337 7.000 7.000 13.196 1.00 0.00 O +ATOM 338 O WAT 338 7.000 7.000 15.196 1.00 0.00 O +ATOM 339 O WAT 339 7.000 7.000 17.196 1.00 0.00 O +ATOM 340 O WAT 340 7.000 7.000 19.196 1.00 0.00 O +ATOM 341 O WAT 341 7.000 9.000 1.075 1.00 0.00 O +ATOM 342 O WAT 342 7.000 9.000 3.075 1.00 0.00 O +ATOM 343 O WAT 343 7.000 9.000 5.075 1.00 0.00 O +ATOM 344 O WAT 344 7.000 9.000 7.075 1.00 0.00 O +ATOM 345 O WAT 345 7.000 9.000 9.075 1.00 0.00 O +ATOM 346 O WAT 346 7.000 9.000 11.075 1.00 0.00 O +ATOM 347 O WAT 347 7.000 9.000 13.075 1.00 0.00 O +ATOM 348 O WAT 348 7.000 9.000 15.075 1.00 0.00 O +ATOM 349 O WAT 349 7.000 9.000 17.075 1.00 0.00 O +ATOM 350 O WAT 350 7.000 9.000 19.075 1.00 0.00 O +ATOM 351 O WAT 351 7.000 11.000 0.925 1.00 0.00 O +ATOM 352 O WAT 352 7.000 11.000 2.925 1.00 0.00 O +ATOM 353 O WAT 353 7.000 11.000 4.925 1.00 0.00 O +ATOM 354 O WAT 354 7.000 11.000 6.925 1.00 0.00 O +ATOM 355 O WAT 355 7.000 11.000 8.925 1.00 0.00 O +ATOM 356 O WAT 356 7.000 11.000 10.925 1.00 0.00 O +ATOM 357 O WAT 357 7.000 11.000 12.925 1.00 0.00 O +ATOM 358 O WAT 358 7.000 11.000 14.925 1.00 0.00 O +ATOM 359 O WAT 359 7.000 11.000 16.925 1.00 0.00 O +ATOM 360 O WAT 360 7.000 11.000 18.925 1.00 0.00 O +ATOM 361 O WAT 361 7.000 13.000 0.804 1.00 0.00 O +ATOM 362 O WAT 362 7.000 13.000 2.804 1.00 0.00 O +ATOM 363 O WAT 363 7.000 13.000 4.804 1.00 0.00 O +ATOM 364 O WAT 364 7.000 13.000 6.804 1.00 0.00 O +ATOM 365 O WAT 365 7.000 13.000 8.804 1.00 0.00 O +ATOM 366 O WAT 366 7.000 13.000 10.804 1.00 0.00 O +ATOM 367 O WAT 367 7.000 13.000 12.804 1.00 0.00 O +ATOM 368 O WAT 368 7.000 13.000 14.804 1.00 0.00 O +ATOM 369 O WAT 369 7.000 13.000 16.804 1.00 0.00 O +ATOM 370 O WAT 370 7.000 13.000 18.804 1.00 0.00 O +ATOM 371 O WAT 371 7.000 15.000 0.757 1.00 0.00 O +ATOM 372 O WAT 372 7.000 15.000 2.757 1.00 0.00 O +ATOM 373 O WAT 373 7.000 15.000 4.757 1.00 0.00 O +ATOM 374 O WAT 374 7.000 15.000 6.757 1.00 0.00 O +ATOM 375 O WAT 375 7.000 15.000 8.757 1.00 0.00 O +ATOM 376 O WAT 376 7.000 15.000 10.757 1.00 0.00 O +ATOM 377 O WAT 377 7.000 15.000 12.757 1.00 0.00 O +ATOM 378 O WAT 378 7.000 15.000 14.757 1.00 0.00 O +ATOM 379 O WAT 379 7.000 15.000 16.757 1.00 0.00 O +ATOM 380 O WAT 380 7.000 15.000 18.757 1.00 0.00 O +ATOM 381 O WAT 381 7.000 17.000 0.804 1.00 0.00 O +ATOM 382 O WAT 382 7.000 17.000 2.804 1.00 0.00 O +ATOM 383 O WAT 383 7.000 17.000 4.804 1.00 0.00 O +ATOM 384 O WAT 384 7.000 17.000 6.804 1.00 0.00 O +ATOM 385 O WAT 385 7.000 17.000 8.804 1.00 0.00 O +ATOM 386 O WAT 386 7.000 17.000 10.804 1.00 0.00 O +ATOM 387 O WAT 387 7.000 17.000 12.804 1.00 0.00 O +ATOM 388 O WAT 388 7.000 17.000 14.804 1.00 0.00 O +ATOM 389 O WAT 389 7.000 17.000 16.804 1.00 0.00 O +ATOM 390 O WAT 390 7.000 17.000 18.804 1.00 0.00 O +ATOM 391 O WAT 391 7.000 19.000 0.925 1.00 0.00 O +ATOM 392 O WAT 392 7.000 19.000 2.925 1.00 0.00 O +ATOM 393 O WAT 393 7.000 19.000 4.925 1.00 0.00 O +ATOM 394 O WAT 394 7.000 19.000 6.925 1.00 0.00 O +ATOM 395 O WAT 395 7.000 19.000 8.925 1.00 0.00 O +ATOM 396 O WAT 396 7.000 19.000 10.925 1.00 0.00 O +ATOM 397 O WAT 397 7.000 19.000 12.925 1.00 0.00 O +ATOM 398 O WAT 398 7.000 19.000 14.925 1.00 0.00 O +ATOM 399 O WAT 399 7.000 19.000 16.925 1.00 0.00 O +ATOM 400 O WAT 400 7.000 19.000 18.925 1.00 0.00 O +ATOM 401 O WAT 401 9.000 1.000 1.029 1.00 0.00 O +ATOM 402 O WAT 402 9.000 1.000 3.029 1.00 0.00 O +ATOM 403 O WAT 403 9.000 1.000 5.029 1.00 0.00 O +ATOM 404 O WAT 404 9.000 1.000 7.029 1.00 0.00 O +ATOM 405 O WAT 405 9.000 1.000 9.029 1.00 0.00 O +ATOM 406 O WAT 406 9.000 1.000 11.029 1.00 0.00 O +ATOM 407 O WAT 407 9.000 1.000 13.029 1.00 0.00 O +ATOM 408 O WAT 408 9.000 1.000 15.029 1.00 0.00 O +ATOM 409 O WAT 409 9.000 1.000 17.029 1.00 0.00 O +ATOM 410 O WAT 410 9.000 1.000 19.029 1.00 0.00 O +ATOM 411 O WAT 411 9.000 3.000 1.075 1.00 0.00 O +ATOM 412 O WAT 412 9.000 3.000 3.075 1.00 0.00 O +ATOM 413 O WAT 413 9.000 3.000 5.075 1.00 0.00 O +ATOM 414 O WAT 414 9.000 3.000 7.075 1.00 0.00 O +ATOM 415 O WAT 415 9.000 3.000 9.075 1.00 0.00 O +ATOM 416 O WAT 416 9.000 3.000 11.075 1.00 0.00 O +ATOM 417 O WAT 417 9.000 3.000 13.075 1.00 0.00 O +ATOM 418 O WAT 418 9.000 3.000 15.075 1.00 0.00 O +ATOM 419 O WAT 419 9.000 3.000 17.075 1.00 0.00 O +ATOM 420 O WAT 420 9.000 3.000 19.075 1.00 0.00 O +ATOM 421 O WAT 421 9.000 5.000 1.093 1.00 0.00 O +ATOM 422 O WAT 422 9.000 5.000 3.093 1.00 0.00 O +ATOM 423 O WAT 423 9.000 5.000 5.093 1.00 0.00 O +ATOM 424 O WAT 424 9.000 5.000 7.093 1.00 0.00 O +ATOM 425 O WAT 425 9.000 5.000 9.093 1.00 0.00 O +ATOM 426 O WAT 426 9.000 5.000 11.093 1.00 0.00 O +ATOM 427 O WAT 427 9.000 5.000 13.093 1.00 0.00 O +ATOM 428 O WAT 428 9.000 5.000 15.093 1.00 0.00 O +ATOM 429 O WAT 429 9.000 5.000 17.093 1.00 0.00 O +ATOM 430 O WAT 430 9.000 5.000 19.093 1.00 0.00 O +ATOM 431 O WAT 431 9.000 7.000 1.075 1.00 0.00 O +ATOM 432 O WAT 432 9.000 7.000 3.075 1.00 0.00 O +ATOM 433 O WAT 433 9.000 7.000 5.075 1.00 0.00 O +ATOM 434 O WAT 434 9.000 7.000 7.075 1.00 0.00 O +ATOM 435 O WAT 435 9.000 7.000 9.075 1.00 0.00 O +ATOM 436 O WAT 436 9.000 7.000 11.075 1.00 0.00 O +ATOM 437 O WAT 437 9.000 7.000 13.075 1.00 0.00 O +ATOM 438 O WAT 438 9.000 7.000 15.075 1.00 0.00 O +ATOM 439 O WAT 439 9.000 7.000 17.075 1.00 0.00 O +ATOM 440 O WAT 440 9.000 7.000 19.075 1.00 0.00 O +ATOM 441 O WAT 441 9.000 9.000 1.029 1.00 0.00 O +ATOM 442 O WAT 442 9.000 9.000 3.029 1.00 0.00 O +ATOM 443 O WAT 443 9.000 9.000 5.029 1.00 0.00 O +ATOM 444 O WAT 444 9.000 9.000 7.029 1.00 0.00 O +ATOM 445 O WAT 445 9.000 9.000 9.029 1.00 0.00 O +ATOM 446 O WAT 446 9.000 9.000 11.029 1.00 0.00 O +ATOM 447 O WAT 447 9.000 9.000 13.029 1.00 0.00 O +ATOM 448 O WAT 448 9.000 9.000 15.029 1.00 0.00 O +ATOM 449 O WAT 449 9.000 9.000 17.029 1.00 0.00 O +ATOM 450 O WAT 450 9.000 9.000 19.029 1.00 0.00 O +ATOM 451 O WAT 451 9.000 11.000 0.971 1.00 0.00 O +ATOM 452 O WAT 452 9.000 11.000 2.971 1.00 0.00 O +ATOM 453 O WAT 453 9.000 11.000 4.971 1.00 0.00 O +ATOM 454 O WAT 454 9.000 11.000 6.971 1.00 0.00 O +ATOM 455 O WAT 455 9.000 11.000 8.971 1.00 0.00 O +ATOM 456 O WAT 456 9.000 11.000 10.971 1.00 0.00 O +ATOM 457 O WAT 457 9.000 11.000 12.971 1.00 0.00 O +ATOM 458 O WAT 458 9.000 11.000 14.971 1.00 0.00 O +ATOM 459 O WAT 459 9.000 11.000 16.971 1.00 0.00 O +ATOM 460 O WAT 460 9.000 11.000 18.971 1.00 0.00 O +ATOM 461 O WAT 461 9.000 13.000 0.925 1.00 0.00 O +ATOM 462 O WAT 462 9.000 13.000 2.925 1.00 0.00 O +ATOM 463 O WAT 463 9.000 13.000 4.925 1.00 0.00 O +ATOM 464 O WAT 464 9.000 13.000 6.925 1.00 0.00 O +ATOM 465 O WAT 465 9.000 13.000 8.925 1.00 0.00 O +ATOM 466 O WAT 466 9.000 13.000 10.925 1.00 0.00 O +ATOM 467 O WAT 467 9.000 13.000 12.925 1.00 0.00 O +ATOM 468 O WAT 468 9.000 13.000 14.925 1.00 0.00 O +ATOM 469 O WAT 469 9.000 13.000 16.925 1.00 0.00 O +ATOM 470 O WAT 470 9.000 13.000 18.925 1.00 0.00 O +ATOM 471 O WAT 471 9.000 15.000 0.907 1.00 0.00 O +ATOM 472 O WAT 472 9.000 15.000 2.907 1.00 0.00 O +ATOM 473 O WAT 473 9.000 15.000 4.907 1.00 0.00 O +ATOM 474 O WAT 474 9.000 15.000 6.907 1.00 0.00 O +ATOM 475 O WAT 475 9.000 15.000 8.907 1.00 0.00 O +ATOM 476 O WAT 476 9.000 15.000 10.907 1.00 0.00 O +ATOM 477 O WAT 477 9.000 15.000 12.907 1.00 0.00 O +ATOM 478 O WAT 478 9.000 15.000 14.907 1.00 0.00 O +ATOM 479 O WAT 479 9.000 15.000 16.907 1.00 0.00 O +ATOM 480 O WAT 480 9.000 15.000 18.907 1.00 0.00 O +ATOM 481 O WAT 481 9.000 17.000 0.925 1.00 0.00 O +ATOM 482 O WAT 482 9.000 17.000 2.925 1.00 0.00 O +ATOM 483 O WAT 483 9.000 17.000 4.925 1.00 0.00 O +ATOM 484 O WAT 484 9.000 17.000 6.925 1.00 0.00 O +ATOM 485 O WAT 485 9.000 17.000 8.925 1.00 0.00 O +ATOM 486 O WAT 486 9.000 17.000 10.925 1.00 0.00 O +ATOM 487 O WAT 487 9.000 17.000 12.925 1.00 0.00 O +ATOM 488 O WAT 488 9.000 17.000 14.925 1.00 0.00 O +ATOM 489 O WAT 489 9.000 17.000 16.925 1.00 0.00 O +ATOM 490 O WAT 490 9.000 17.000 18.925 1.00 0.00 O +ATOM 491 O WAT 491 9.000 19.000 0.971 1.00 0.00 O +ATOM 492 O WAT 492 9.000 19.000 2.971 1.00 0.00 O +ATOM 493 O WAT 493 9.000 19.000 4.971 1.00 0.00 O +ATOM 494 O WAT 494 9.000 19.000 6.971 1.00 0.00 O +ATOM 495 O WAT 495 9.000 19.000 8.971 1.00 0.00 O +ATOM 496 O WAT 496 9.000 19.000 10.971 1.00 0.00 O +ATOM 497 O WAT 497 9.000 19.000 12.971 1.00 0.00 O +ATOM 498 O WAT 498 9.000 19.000 14.971 1.00 0.00 O +ATOM 499 O WAT 499 9.000 19.000 16.971 1.00 0.00 O +ATOM 500 O WAT 500 9.000 19.000 18.971 1.00 0.00 O +ATOM 501 O WAT 501 11.000 1.000 0.971 1.00 0.00 O +ATOM 502 O WAT 502 11.000 1.000 2.971 1.00 0.00 O +ATOM 503 O WAT 503 11.000 1.000 4.971 1.00 0.00 O +ATOM 504 O WAT 504 11.000 1.000 6.971 1.00 0.00 O +ATOM 505 O WAT 505 11.000 1.000 8.971 1.00 0.00 O +ATOM 506 O WAT 506 11.000 1.000 10.971 1.00 0.00 O +ATOM 507 O WAT 507 11.000 1.000 12.971 1.00 0.00 O +ATOM 508 O WAT 508 11.000 1.000 14.971 1.00 0.00 O +ATOM 509 O WAT 509 11.000 1.000 16.971 1.00 0.00 O +ATOM 510 O WAT 510 11.000 1.000 18.971 1.00 0.00 O +ATOM 511 O WAT 511 11.000 3.000 0.925 1.00 0.00 O +ATOM 512 O WAT 512 11.000 3.000 2.925 1.00 0.00 O +ATOM 513 O WAT 513 11.000 3.000 4.925 1.00 0.00 O +ATOM 514 O WAT 514 11.000 3.000 6.925 1.00 0.00 O +ATOM 515 O WAT 515 11.000 3.000 8.925 1.00 0.00 O +ATOM 516 O WAT 516 11.000 3.000 10.925 1.00 0.00 O +ATOM 517 O WAT 517 11.000 3.000 12.925 1.00 0.00 O +ATOM 518 O WAT 518 11.000 3.000 14.925 1.00 0.00 O +ATOM 519 O WAT 519 11.000 3.000 16.925 1.00 0.00 O +ATOM 520 O WAT 520 11.000 3.000 18.925 1.00 0.00 O +ATOM 521 O WAT 521 11.000 5.000 0.907 1.00 0.00 O +ATOM 522 O WAT 522 11.000 5.000 2.907 1.00 0.00 O +ATOM 523 O WAT 523 11.000 5.000 4.907 1.00 0.00 O +ATOM 524 O WAT 524 11.000 5.000 6.907 1.00 0.00 O +ATOM 525 O WAT 525 11.000 5.000 8.907 1.00 0.00 O +ATOM 526 O WAT 526 11.000 5.000 10.907 1.00 0.00 O +ATOM 527 O WAT 527 11.000 5.000 12.907 1.00 0.00 O +ATOM 528 O WAT 528 11.000 5.000 14.907 1.00 0.00 O +ATOM 529 O WAT 529 11.000 5.000 16.907 1.00 0.00 O +ATOM 530 O WAT 530 11.000 5.000 18.907 1.00 0.00 O +ATOM 531 O WAT 531 11.000 7.000 0.925 1.00 0.00 O +ATOM 532 O WAT 532 11.000 7.000 2.925 1.00 0.00 O +ATOM 533 O WAT 533 11.000 7.000 4.925 1.00 0.00 O +ATOM 534 O WAT 534 11.000 7.000 6.925 1.00 0.00 O +ATOM 535 O WAT 535 11.000 7.000 8.925 1.00 0.00 O +ATOM 536 O WAT 536 11.000 7.000 10.925 1.00 0.00 O +ATOM 537 O WAT 537 11.000 7.000 12.925 1.00 0.00 O +ATOM 538 O WAT 538 11.000 7.000 14.925 1.00 0.00 O +ATOM 539 O WAT 539 11.000 7.000 16.925 1.00 0.00 O +ATOM 540 O WAT 540 11.000 7.000 18.925 1.00 0.00 O +ATOM 541 O WAT 541 11.000 9.000 0.971 1.00 0.00 O +ATOM 542 O WAT 542 11.000 9.000 2.971 1.00 0.00 O +ATOM 543 O WAT 543 11.000 9.000 4.971 1.00 0.00 O +ATOM 544 O WAT 544 11.000 9.000 6.971 1.00 0.00 O +ATOM 545 O WAT 545 11.000 9.000 8.971 1.00 0.00 O +ATOM 546 O WAT 546 11.000 9.000 10.971 1.00 0.00 O +ATOM 547 O WAT 547 11.000 9.000 12.971 1.00 0.00 O +ATOM 548 O WAT 548 11.000 9.000 14.971 1.00 0.00 O +ATOM 549 O WAT 549 11.000 9.000 16.971 1.00 0.00 O +ATOM 550 O WAT 550 11.000 9.000 18.971 1.00 0.00 O +ATOM 551 O WAT 551 11.000 11.000 1.029 1.00 0.00 O +ATOM 552 O WAT 552 11.000 11.000 3.029 1.00 0.00 O +ATOM 553 O WAT 553 11.000 11.000 5.029 1.00 0.00 O +ATOM 554 O WAT 554 11.000 11.000 7.029 1.00 0.00 O +ATOM 555 O WAT 555 11.000 11.000 9.029 1.00 0.00 O +ATOM 556 O WAT 556 11.000 11.000 11.029 1.00 0.00 O +ATOM 557 O WAT 557 11.000 11.000 13.029 1.00 0.00 O +ATOM 558 O WAT 558 11.000 11.000 15.029 1.00 0.00 O +ATOM 559 O WAT 559 11.000 11.000 17.029 1.00 0.00 O +ATOM 560 O WAT 560 11.000 11.000 19.029 1.00 0.00 O +ATOM 561 O WAT 561 11.000 13.000 1.075 1.00 0.00 O +ATOM 562 O WAT 562 11.000 13.000 3.075 1.00 0.00 O +ATOM 563 O WAT 563 11.000 13.000 5.075 1.00 0.00 O +ATOM 564 O WAT 564 11.000 13.000 7.075 1.00 0.00 O +ATOM 565 O WAT 565 11.000 13.000 9.075 1.00 0.00 O +ATOM 566 O WAT 566 11.000 13.000 11.075 1.00 0.00 O +ATOM 567 O WAT 567 11.000 13.000 13.075 1.00 0.00 O +ATOM 568 O WAT 568 11.000 13.000 15.075 1.00 0.00 O +ATOM 569 O WAT 569 11.000 13.000 17.075 1.00 0.00 O +ATOM 570 O WAT 570 11.000 13.000 19.075 1.00 0.00 O +ATOM 571 O WAT 571 11.000 15.000 1.093 1.00 0.00 O +ATOM 572 O WAT 572 11.000 15.000 3.093 1.00 0.00 O +ATOM 573 O WAT 573 11.000 15.000 5.093 1.00 0.00 O +ATOM 574 O WAT 574 11.000 15.000 7.093 1.00 0.00 O +ATOM 575 O WAT 575 11.000 15.000 9.093 1.00 0.00 O +ATOM 576 O WAT 576 11.000 15.000 11.093 1.00 0.00 O +ATOM 577 O WAT 577 11.000 15.000 13.093 1.00 0.00 O +ATOM 578 O WAT 578 11.000 15.000 15.093 1.00 0.00 O +ATOM 579 O WAT 579 11.000 15.000 17.093 1.00 0.00 O +ATOM 580 O WAT 580 11.000 15.000 19.093 1.00 0.00 O +ATOM 581 O WAT 581 11.000 17.000 1.075 1.00 0.00 O +ATOM 582 O WAT 582 11.000 17.000 3.075 1.00 0.00 O +ATOM 583 O WAT 583 11.000 17.000 5.075 1.00 0.00 O +ATOM 584 O WAT 584 11.000 17.000 7.075 1.00 0.00 O +ATOM 585 O WAT 585 11.000 17.000 9.075 1.00 0.00 O +ATOM 586 O WAT 586 11.000 17.000 11.075 1.00 0.00 O +ATOM 587 O WAT 587 11.000 17.000 13.075 1.00 0.00 O +ATOM 588 O WAT 588 11.000 17.000 15.075 1.00 0.00 O +ATOM 589 O WAT 589 11.000 17.000 17.075 1.00 0.00 O +ATOM 590 O WAT 590 11.000 17.000 19.075 1.00 0.00 O +ATOM 591 O WAT 591 11.000 19.000 1.029 1.00 0.00 O +ATOM 592 O WAT 592 11.000 19.000 3.029 1.00 0.00 O +ATOM 593 O WAT 593 11.000 19.000 5.029 1.00 0.00 O +ATOM 594 O WAT 594 11.000 19.000 7.029 1.00 0.00 O +ATOM 595 O WAT 595 11.000 19.000 9.029 1.00 0.00 O +ATOM 596 O WAT 596 11.000 19.000 11.029 1.00 0.00 O +ATOM 597 O WAT 597 11.000 19.000 13.029 1.00 0.00 O +ATOM 598 O WAT 598 11.000 19.000 15.029 1.00 0.00 O +ATOM 599 O WAT 599 11.000 19.000 17.029 1.00 0.00 O +ATOM 600 O WAT 600 11.000 19.000 19.029 1.00 0.00 O +ATOM 601 O WAT 601 13.000 1.000 0.925 1.00 0.00 O +ATOM 602 O WAT 602 13.000 1.000 2.925 1.00 0.00 O +ATOM 603 O WAT 603 13.000 1.000 4.925 1.00 0.00 O +ATOM 604 O WAT 604 13.000 1.000 6.925 1.00 0.00 O +ATOM 605 O WAT 605 13.000 1.000 8.925 1.00 0.00 O +ATOM 606 O WAT 606 13.000 1.000 10.925 1.00 0.00 O +ATOM 607 O WAT 607 13.000 1.000 12.925 1.00 0.00 O +ATOM 608 O WAT 608 13.000 1.000 14.925 1.00 0.00 O +ATOM 609 O WAT 609 13.000 1.000 16.925 1.00 0.00 O +ATOM 610 O WAT 610 13.000 1.000 18.925 1.00 0.00 O +ATOM 611 O WAT 611 13.000 3.000 0.804 1.00 0.00 O +ATOM 612 O WAT 612 13.000 3.000 2.804 1.00 0.00 O +ATOM 613 O WAT 613 13.000 3.000 4.804 1.00 0.00 O +ATOM 614 O WAT 614 13.000 3.000 6.804 1.00 0.00 O +ATOM 615 O WAT 615 13.000 3.000 8.804 1.00 0.00 O +ATOM 616 O WAT 616 13.000 3.000 10.804 1.00 0.00 O +ATOM 617 O WAT 617 13.000 3.000 12.804 1.00 0.00 O +ATOM 618 O WAT 618 13.000 3.000 14.804 1.00 0.00 O +ATOM 619 O WAT 619 13.000 3.000 16.804 1.00 0.00 O +ATOM 620 O WAT 620 13.000 3.000 18.804 1.00 0.00 O +ATOM 621 O WAT 621 13.000 5.000 0.757 1.00 0.00 O +ATOM 622 O WAT 622 13.000 5.000 2.757 1.00 0.00 O +ATOM 623 O WAT 623 13.000 5.000 4.757 1.00 0.00 O +ATOM 624 O WAT 624 13.000 5.000 6.757 1.00 0.00 O +ATOM 625 O WAT 625 13.000 5.000 8.757 1.00 0.00 O +ATOM 626 O WAT 626 13.000 5.000 10.757 1.00 0.00 O +ATOM 627 O WAT 627 13.000 5.000 12.757 1.00 0.00 O +ATOM 628 O WAT 628 13.000 5.000 14.757 1.00 0.00 O +ATOM 629 O WAT 629 13.000 5.000 16.757 1.00 0.00 O +ATOM 630 O WAT 630 13.000 5.000 18.757 1.00 0.00 O +ATOM 631 O WAT 631 13.000 7.000 0.804 1.00 0.00 O +ATOM 632 O WAT 632 13.000 7.000 2.804 1.00 0.00 O +ATOM 633 O WAT 633 13.000 7.000 4.804 1.00 0.00 O +ATOM 634 O WAT 634 13.000 7.000 6.804 1.00 0.00 O +ATOM 635 O WAT 635 13.000 7.000 8.804 1.00 0.00 O +ATOM 636 O WAT 636 13.000 7.000 10.804 1.00 0.00 O +ATOM 637 O WAT 637 13.000 7.000 12.804 1.00 0.00 O +ATOM 638 O WAT 638 13.000 7.000 14.804 1.00 0.00 O +ATOM 639 O WAT 639 13.000 7.000 16.804 1.00 0.00 O +ATOM 640 O WAT 640 13.000 7.000 18.804 1.00 0.00 O +ATOM 641 O WAT 641 13.000 9.000 0.925 1.00 0.00 O +ATOM 642 O WAT 642 13.000 9.000 2.925 1.00 0.00 O +ATOM 643 O WAT 643 13.000 9.000 4.925 1.00 0.00 O +ATOM 644 O WAT 644 13.000 9.000 6.925 1.00 0.00 O +ATOM 645 O WAT 645 13.000 9.000 8.925 1.00 0.00 O +ATOM 646 O WAT 646 13.000 9.000 10.925 1.00 0.00 O +ATOM 647 O WAT 647 13.000 9.000 12.925 1.00 0.00 O +ATOM 648 O WAT 648 13.000 9.000 14.925 1.00 0.00 O +ATOM 649 O WAT 649 13.000 9.000 16.925 1.00 0.00 O +ATOM 650 O WAT 650 13.000 9.000 18.925 1.00 0.00 O +ATOM 651 O WAT 651 13.000 11.000 1.075 1.00 0.00 O +ATOM 652 O WAT 652 13.000 11.000 3.075 1.00 0.00 O +ATOM 653 O WAT 653 13.000 11.000 5.075 1.00 0.00 O +ATOM 654 O WAT 654 13.000 11.000 7.075 1.00 0.00 O +ATOM 655 O WAT 655 13.000 11.000 9.075 1.00 0.00 O +ATOM 656 O WAT 656 13.000 11.000 11.075 1.00 0.00 O +ATOM 657 O WAT 657 13.000 11.000 13.075 1.00 0.00 O +ATOM 658 O WAT 658 13.000 11.000 15.075 1.00 0.00 O +ATOM 659 O WAT 659 13.000 11.000 17.075 1.00 0.00 O +ATOM 660 O WAT 660 13.000 11.000 19.075 1.00 0.00 O +ATOM 661 O WAT 661 13.000 13.000 1.196 1.00 0.00 O +ATOM 662 O WAT 662 13.000 13.000 3.196 1.00 0.00 O +ATOM 663 O WAT 663 13.000 13.000 5.196 1.00 0.00 O +ATOM 664 O WAT 664 13.000 13.000 7.196 1.00 0.00 O +ATOM 665 O WAT 665 13.000 13.000 9.196 1.00 0.00 O +ATOM 666 O WAT 666 13.000 13.000 11.196 1.00 0.00 O +ATOM 667 O WAT 667 13.000 13.000 13.196 1.00 0.00 O +ATOM 668 O WAT 668 13.000 13.000 15.196 1.00 0.00 O +ATOM 669 O WAT 669 13.000 13.000 17.196 1.00 0.00 O +ATOM 670 O WAT 670 13.000 13.000 19.196 1.00 0.00 O +ATOM 671 O WAT 671 13.000 15.000 1.243 1.00 0.00 O +ATOM 672 O WAT 672 13.000 15.000 3.243 1.00 0.00 O +ATOM 673 O WAT 673 13.000 15.000 5.243 1.00 0.00 O +ATOM 674 O WAT 674 13.000 15.000 7.243 1.00 0.00 O +ATOM 675 O WAT 675 13.000 15.000 9.243 1.00 0.00 O +ATOM 676 O WAT 676 13.000 15.000 11.243 1.00 0.00 O +ATOM 677 O WAT 677 13.000 15.000 13.243 1.00 0.00 O +ATOM 678 O WAT 678 13.000 15.000 15.243 1.00 0.00 O +ATOM 679 O WAT 679 13.000 15.000 17.243 1.00 0.00 O +ATOM 680 O WAT 680 13.000 15.000 19.243 1.00 0.00 O +ATOM 681 O WAT 681 13.000 17.000 1.196 1.00 0.00 O +ATOM 682 O WAT 682 13.000 17.000 3.196 1.00 0.00 O +ATOM 683 O WAT 683 13.000 17.000 5.196 1.00 0.00 O +ATOM 684 O WAT 684 13.000 17.000 7.196 1.00 0.00 O +ATOM 685 O WAT 685 13.000 17.000 9.196 1.00 0.00 O +ATOM 686 O WAT 686 13.000 17.000 11.196 1.00 0.00 O +ATOM 687 O WAT 687 13.000 17.000 13.196 1.00 0.00 O +ATOM 688 O WAT 688 13.000 17.000 15.196 1.00 0.00 O +ATOM 689 O WAT 689 13.000 17.000 17.196 1.00 0.00 O +ATOM 690 O WAT 690 13.000 17.000 19.196 1.00 0.00 O +ATOM 691 O WAT 691 13.000 19.000 1.075 1.00 0.00 O +ATOM 692 O WAT 692 13.000 19.000 3.075 1.00 0.00 O +ATOM 693 O WAT 693 13.000 19.000 5.075 1.00 0.00 O +ATOM 694 O WAT 694 13.000 19.000 7.075 1.00 0.00 O +ATOM 695 O WAT 695 13.000 19.000 9.075 1.00 0.00 O +ATOM 696 O WAT 696 13.000 19.000 11.075 1.00 0.00 O +ATOM 697 O WAT 697 13.000 19.000 13.075 1.00 0.00 O +ATOM 698 O WAT 698 13.000 19.000 15.075 1.00 0.00 O +ATOM 699 O WAT 699 13.000 19.000 17.075 1.00 0.00 O +ATOM 700 O WAT 700 13.000 19.000 19.075 1.00 0.00 O +ATOM 701 O WAT 701 15.000 1.000 0.907 1.00 0.00 O +ATOM 702 O WAT 702 15.000 1.000 2.907 1.00 0.00 O +ATOM 703 O WAT 703 15.000 1.000 4.907 1.00 0.00 O +ATOM 704 O WAT 704 15.000 1.000 6.907 1.00 0.00 O +ATOM 705 O WAT 705 15.000 1.000 8.907 1.00 0.00 O +ATOM 706 O WAT 706 15.000 1.000 10.907 1.00 0.00 O +ATOM 707 O WAT 707 15.000 1.000 12.907 1.00 0.00 O +ATOM 708 O WAT 708 15.000 1.000 14.907 1.00 0.00 O +ATOM 709 O WAT 709 15.000 1.000 16.907 1.00 0.00 O +ATOM 710 O WAT 710 15.000 1.000 18.907 1.00 0.00 O +ATOM 711 O WAT 711 15.000 3.000 0.757 1.00 0.00 O +ATOM 712 O WAT 712 15.000 3.000 2.757 1.00 0.00 O +ATOM 713 O WAT 713 15.000 3.000 4.757 1.00 0.00 O +ATOM 714 O WAT 714 15.000 3.000 6.757 1.00 0.00 O +ATOM 715 O WAT 715 15.000 3.000 8.757 1.00 0.00 O +ATOM 716 O WAT 716 15.000 3.000 10.757 1.00 0.00 O +ATOM 717 O WAT 717 15.000 3.000 12.757 1.00 0.00 O +ATOM 718 O WAT 718 15.000 3.000 14.757 1.00 0.00 O +ATOM 719 O WAT 719 15.000 3.000 16.757 1.00 0.00 O +ATOM 720 O WAT 720 15.000 3.000 18.757 1.00 0.00 O +ATOM 721 O WAT 721 15.000 5.000 0.700 1.00 0.00 O +ATOM 722 O WAT 722 15.000 5.000 2.700 1.00 0.00 O +ATOM 723 O WAT 723 15.000 5.000 4.700 1.00 0.00 O +ATOM 724 O WAT 724 15.000 5.000 6.700 1.00 0.00 O +ATOM 725 O WAT 725 15.000 5.000 8.700 1.00 0.00 O +ATOM 726 O WAT 726 15.000 5.000 10.700 1.00 0.00 O +ATOM 727 O WAT 727 15.000 5.000 12.700 1.00 0.00 O +ATOM 728 O WAT 728 15.000 5.000 14.700 1.00 0.00 O +ATOM 729 O WAT 729 15.000 5.000 16.700 1.00 0.00 O +ATOM 730 O WAT 730 15.000 5.000 18.700 1.00 0.00 O +ATOM 731 O WAT 731 15.000 7.000 0.757 1.00 0.00 O +ATOM 732 O WAT 732 15.000 7.000 2.757 1.00 0.00 O +ATOM 733 O WAT 733 15.000 7.000 4.757 1.00 0.00 O +ATOM 734 O WAT 734 15.000 7.000 6.757 1.00 0.00 O +ATOM 735 O WAT 735 15.000 7.000 8.757 1.00 0.00 O +ATOM 736 O WAT 736 15.000 7.000 10.757 1.00 0.00 O +ATOM 737 O WAT 737 15.000 7.000 12.757 1.00 0.00 O +ATOM 738 O WAT 738 15.000 7.000 14.757 1.00 0.00 O +ATOM 739 O WAT 739 15.000 7.000 16.757 1.00 0.00 O +ATOM 740 O WAT 740 15.000 7.000 18.757 1.00 0.00 O +ATOM 741 O WAT 741 15.000 9.000 0.907 1.00 0.00 O +ATOM 742 O WAT 742 15.000 9.000 2.907 1.00 0.00 O +ATOM 743 O WAT 743 15.000 9.000 4.907 1.00 0.00 O +ATOM 744 O WAT 744 15.000 9.000 6.907 1.00 0.00 O +ATOM 745 O WAT 745 15.000 9.000 8.907 1.00 0.00 O +ATOM 746 O WAT 746 15.000 9.000 10.907 1.00 0.00 O +ATOM 747 O WAT 747 15.000 9.000 12.907 1.00 0.00 O +ATOM 748 O WAT 748 15.000 9.000 14.907 1.00 0.00 O +ATOM 749 O WAT 749 15.000 9.000 16.907 1.00 0.00 O +ATOM 750 O WAT 750 15.000 9.000 18.907 1.00 0.00 O +ATOM 751 O WAT 751 15.000 11.000 1.093 1.00 0.00 O +ATOM 752 O WAT 752 15.000 11.000 3.093 1.00 0.00 O +ATOM 753 O WAT 753 15.000 11.000 5.093 1.00 0.00 O +ATOM 754 O WAT 754 15.000 11.000 7.093 1.00 0.00 O +ATOM 755 O WAT 755 15.000 11.000 9.093 1.00 0.00 O +ATOM 756 O WAT 756 15.000 11.000 11.093 1.00 0.00 O +ATOM 757 O WAT 757 15.000 11.000 13.093 1.00 0.00 O +ATOM 758 O WAT 758 15.000 11.000 15.093 1.00 0.00 O +ATOM 759 O WAT 759 15.000 11.000 17.093 1.00 0.00 O +ATOM 760 O WAT 760 15.000 11.000 19.093 1.00 0.00 O +ATOM 761 O WAT 761 15.000 13.000 1.243 1.00 0.00 O +ATOM 762 O WAT 762 15.000 13.000 3.243 1.00 0.00 O +ATOM 763 O WAT 763 15.000 13.000 5.243 1.00 0.00 O +ATOM 764 O WAT 764 15.000 13.000 7.243 1.00 0.00 O +ATOM 765 O WAT 765 15.000 13.000 9.243 1.00 0.00 O +ATOM 766 O WAT 766 15.000 13.000 11.243 1.00 0.00 O +ATOM 767 O WAT 767 15.000 13.000 13.243 1.00 0.00 O +ATOM 768 O WAT 768 15.000 13.000 15.243 1.00 0.00 O +ATOM 769 O WAT 769 15.000 13.000 17.243 1.00 0.00 O +ATOM 770 O WAT 770 15.000 13.000 19.243 1.00 0.00 O +ATOM 771 O WAT 771 15.000 15.000 1.300 1.00 0.00 O +ATOM 772 O WAT 772 15.000 15.000 3.300 1.00 0.00 O +ATOM 773 O WAT 773 15.000 15.000 5.300 1.00 0.00 O +ATOM 774 O WAT 774 15.000 15.000 7.300 1.00 0.00 O +ATOM 775 O WAT 775 15.000 15.000 9.300 1.00 0.00 O +ATOM 776 O WAT 776 15.000 15.000 11.300 1.00 0.00 O +ATOM 777 O WAT 777 15.000 15.000 13.300 1.00 0.00 O +ATOM 778 O WAT 778 15.000 15.000 15.300 1.00 0.00 O +ATOM 779 O WAT 779 15.000 15.000 17.300 1.00 0.00 O +ATOM 780 O WAT 780 15.000 15.000 19.300 1.00 0.00 O +ATOM 781 O WAT 781 15.000 17.000 1.243 1.00 0.00 O +ATOM 782 O WAT 782 15.000 17.000 3.243 1.00 0.00 O +ATOM 783 O WAT 783 15.000 17.000 5.243 1.00 0.00 O +ATOM 784 O WAT 784 15.000 17.000 7.243 1.00 0.00 O +ATOM 785 O WAT 785 15.000 17.000 9.243 1.00 0.00 O +ATOM 786 O WAT 786 15.000 17.000 11.243 1.00 0.00 O +ATOM 787 O WAT 787 15.000 17.000 13.243 1.00 0.00 O +ATOM 788 O WAT 788 15.000 17.000 15.243 1.00 0.00 O +ATOM 789 O WAT 789 15.000 17.000 17.243 1.00 0.00 O +ATOM 790 O WAT 790 15.000 17.000 19.243 1.00 0.00 O +ATOM 791 O WAT 791 15.000 19.000 1.093 1.00 0.00 O +ATOM 792 O WAT 792 15.000 19.000 3.093 1.00 0.00 O +ATOM 793 O WAT 793 15.000 19.000 5.093 1.00 0.00 O +ATOM 794 O WAT 794 15.000 19.000 7.093 1.00 0.00 O +ATOM 795 O WAT 795 15.000 19.000 9.093 1.00 0.00 O +ATOM 796 O WAT 796 15.000 19.000 11.093 1.00 0.00 O +ATOM 797 O WAT 797 15.000 19.000 13.093 1.00 0.00 O +ATOM 798 O WAT 798 15.000 19.000 15.093 1.00 0.00 O +ATOM 799 O WAT 799 15.000 19.000 17.093 1.00 0.00 O +ATOM 800 O WAT 800 15.000 19.000 19.093 1.00 0.00 O +ATOM 801 O WAT 801 17.000 1.000 0.925 1.00 0.00 O +ATOM 802 O WAT 802 17.000 1.000 2.925 1.00 0.00 O +ATOM 803 O WAT 803 17.000 1.000 4.925 1.00 0.00 O +ATOM 804 O WAT 804 17.000 1.000 6.925 1.00 0.00 O +ATOM 805 O WAT 805 17.000 1.000 8.925 1.00 0.00 O +ATOM 806 O WAT 806 17.000 1.000 10.925 1.00 0.00 O +ATOM 807 O WAT 807 17.000 1.000 12.925 1.00 0.00 O +ATOM 808 O WAT 808 17.000 1.000 14.925 1.00 0.00 O +ATOM 809 O WAT 809 17.000 1.000 16.925 1.00 0.00 O +ATOM 810 O WAT 810 17.000 1.000 18.925 1.00 0.00 O +ATOM 811 O WAT 811 17.000 3.000 0.804 1.00 0.00 O +ATOM 812 O WAT 812 17.000 3.000 2.804 1.00 0.00 O +ATOM 813 O WAT 813 17.000 3.000 4.804 1.00 0.00 O +ATOM 814 O WAT 814 17.000 3.000 6.804 1.00 0.00 O +ATOM 815 O WAT 815 17.000 3.000 8.804 1.00 0.00 O +ATOM 816 O WAT 816 17.000 3.000 10.804 1.00 0.00 O +ATOM 817 O WAT 817 17.000 3.000 12.804 1.00 0.00 O +ATOM 818 O WAT 818 17.000 3.000 14.804 1.00 0.00 O +ATOM 819 O WAT 819 17.000 3.000 16.804 1.00 0.00 O +ATOM 820 O WAT 820 17.000 3.000 18.804 1.00 0.00 O +ATOM 821 O WAT 821 17.000 5.000 0.757 1.00 0.00 O +ATOM 822 O WAT 822 17.000 5.000 2.757 1.00 0.00 O +ATOM 823 O WAT 823 17.000 5.000 4.757 1.00 0.00 O +ATOM 824 O WAT 824 17.000 5.000 6.757 1.00 0.00 O +ATOM 825 O WAT 825 17.000 5.000 8.757 1.00 0.00 O +ATOM 826 O WAT 826 17.000 5.000 10.757 1.00 0.00 O +ATOM 827 O WAT 827 17.000 5.000 12.757 1.00 0.00 O +ATOM 828 O WAT 828 17.000 5.000 14.757 1.00 0.00 O +ATOM 829 O WAT 829 17.000 5.000 16.757 1.00 0.00 O +ATOM 830 O WAT 830 17.000 5.000 18.757 1.00 0.00 O +ATOM 831 O WAT 831 17.000 7.000 0.804 1.00 0.00 O +ATOM 832 O WAT 832 17.000 7.000 2.804 1.00 0.00 O +ATOM 833 O WAT 833 17.000 7.000 4.804 1.00 0.00 O +ATOM 834 O WAT 834 17.000 7.000 6.804 1.00 0.00 O +ATOM 835 O WAT 835 17.000 7.000 8.804 1.00 0.00 O +ATOM 836 O WAT 836 17.000 7.000 10.804 1.00 0.00 O +ATOM 837 O WAT 837 17.000 7.000 12.804 1.00 0.00 O +ATOM 838 O WAT 838 17.000 7.000 14.804 1.00 0.00 O +ATOM 839 O WAT 839 17.000 7.000 16.804 1.00 0.00 O +ATOM 840 O WAT 840 17.000 7.000 18.804 1.00 0.00 O +ATOM 841 O WAT 841 17.000 9.000 0.925 1.00 0.00 O +ATOM 842 O WAT 842 17.000 9.000 2.925 1.00 0.00 O +ATOM 843 O WAT 843 17.000 9.000 4.925 1.00 0.00 O +ATOM 844 O WAT 844 17.000 9.000 6.925 1.00 0.00 O +ATOM 845 O WAT 845 17.000 9.000 8.925 1.00 0.00 O +ATOM 846 O WAT 846 17.000 9.000 10.925 1.00 0.00 O +ATOM 847 O WAT 847 17.000 9.000 12.925 1.00 0.00 O +ATOM 848 O WAT 848 17.000 9.000 14.925 1.00 0.00 O +ATOM 849 O WAT 849 17.000 9.000 16.925 1.00 0.00 O +ATOM 850 O WAT 850 17.000 9.000 18.925 1.00 0.00 O +ATOM 851 O WAT 851 17.000 11.000 1.075 1.00 0.00 O +ATOM 852 O WAT 852 17.000 11.000 3.075 1.00 0.00 O +ATOM 853 O WAT 853 17.000 11.000 5.075 1.00 0.00 O +ATOM 854 O WAT 854 17.000 11.000 7.075 1.00 0.00 O +ATOM 855 O WAT 855 17.000 11.000 9.075 1.00 0.00 O +ATOM 856 O WAT 856 17.000 11.000 11.075 1.00 0.00 O +ATOM 857 O WAT 857 17.000 11.000 13.075 1.00 0.00 O +ATOM 858 O WAT 858 17.000 11.000 15.075 1.00 0.00 O +ATOM 859 O WAT 859 17.000 11.000 17.075 1.00 0.00 O +ATOM 860 O WAT 860 17.000 11.000 19.075 1.00 0.00 O +ATOM 861 O WAT 861 17.000 13.000 1.196 1.00 0.00 O +ATOM 862 O WAT 862 17.000 13.000 3.196 1.00 0.00 O +ATOM 863 O WAT 863 17.000 13.000 5.196 1.00 0.00 O +ATOM 864 O WAT 864 17.000 13.000 7.196 1.00 0.00 O +ATOM 865 O WAT 865 17.000 13.000 9.196 1.00 0.00 O +ATOM 866 O WAT 866 17.000 13.000 11.196 1.00 0.00 O +ATOM 867 O WAT 867 17.000 13.000 13.196 1.00 0.00 O +ATOM 868 O WAT 868 17.000 13.000 15.196 1.00 0.00 O +ATOM 869 O WAT 869 17.000 13.000 17.196 1.00 0.00 O +ATOM 870 O WAT 870 17.000 13.000 19.196 1.00 0.00 O +ATOM 871 O WAT 871 17.000 15.000 1.243 1.00 0.00 O +ATOM 872 O WAT 872 17.000 15.000 3.243 1.00 0.00 O +ATOM 873 O WAT 873 17.000 15.000 5.243 1.00 0.00 O +ATOM 874 O WAT 874 17.000 15.000 7.243 1.00 0.00 O +ATOM 875 O WAT 875 17.000 15.000 9.243 1.00 0.00 O +ATOM 876 O WAT 876 17.000 15.000 11.243 1.00 0.00 O +ATOM 877 O WAT 877 17.000 15.000 13.243 1.00 0.00 O +ATOM 878 O WAT 878 17.000 15.000 15.243 1.00 0.00 O +ATOM 879 O WAT 879 17.000 15.000 17.243 1.00 0.00 O +ATOM 880 O WAT 880 17.000 15.000 19.243 1.00 0.00 O +ATOM 881 O WAT 881 17.000 17.000 1.196 1.00 0.00 O +ATOM 882 O WAT 882 17.000 17.000 3.196 1.00 0.00 O +ATOM 883 O WAT 883 17.000 17.000 5.196 1.00 0.00 O +ATOM 884 O WAT 884 17.000 17.000 7.196 1.00 0.00 O +ATOM 885 O WAT 885 17.000 17.000 9.196 1.00 0.00 O +ATOM 886 O WAT 886 17.000 17.000 11.196 1.00 0.00 O +ATOM 887 O WAT 887 17.000 17.000 13.196 1.00 0.00 O +ATOM 888 O WAT 888 17.000 17.000 15.196 1.00 0.00 O +ATOM 889 O WAT 889 17.000 17.000 17.196 1.00 0.00 O +ATOM 890 O WAT 890 17.000 17.000 19.196 1.00 0.00 O +ATOM 891 O WAT 891 17.000 19.000 1.075 1.00 0.00 O +ATOM 892 O WAT 892 17.000 19.000 3.075 1.00 0.00 O +ATOM 893 O WAT 893 17.000 19.000 5.075 1.00 0.00 O +ATOM 894 O WAT 894 17.000 19.000 7.075 1.00 0.00 O +ATOM 895 O WAT 895 17.000 19.000 9.075 1.00 0.00 O +ATOM 896 O WAT 896 17.000 19.000 11.075 1.00 0.00 O +ATOM 897 O WAT 897 17.000 19.000 13.075 1.00 0.00 O +ATOM 898 O WAT 898 17.000 19.000 15.075 1.00 0.00 O +ATOM 899 O WAT 899 17.000 19.000 17.075 1.00 0.00 O +ATOM 900 O WAT 900 17.000 19.000 19.075 1.00 0.00 O +ATOM 901 O WAT 901 19.000 1.000 0.971 1.00 0.00 O +ATOM 902 O WAT 902 19.000 1.000 2.971 1.00 0.00 O +ATOM 903 O WAT 903 19.000 1.000 4.971 1.00 0.00 O +ATOM 904 O WAT 904 19.000 1.000 6.971 1.00 0.00 O +ATOM 905 O WAT 905 19.000 1.000 8.971 1.00 0.00 O +ATOM 906 O WAT 906 19.000 1.000 10.971 1.00 0.00 O +ATOM 907 O WAT 907 19.000 1.000 12.971 1.00 0.00 O +ATOM 908 O WAT 908 19.000 1.000 14.971 1.00 0.00 O +ATOM 909 O WAT 909 19.000 1.000 16.971 1.00 0.00 O +ATOM 910 O WAT 910 19.000 1.000 18.971 1.00 0.00 O +ATOM 911 O WAT 911 19.000 3.000 0.925 1.00 0.00 O +ATOM 912 O WAT 912 19.000 3.000 2.925 1.00 0.00 O +ATOM 913 O WAT 913 19.000 3.000 4.925 1.00 0.00 O +ATOM 914 O WAT 914 19.000 3.000 6.925 1.00 0.00 O +ATOM 915 O WAT 915 19.000 3.000 8.925 1.00 0.00 O +ATOM 916 O WAT 916 19.000 3.000 10.925 1.00 0.00 O +ATOM 917 O WAT 917 19.000 3.000 12.925 1.00 0.00 O +ATOM 918 O WAT 918 19.000 3.000 14.925 1.00 0.00 O +ATOM 919 O WAT 919 19.000 3.000 16.925 1.00 0.00 O +ATOM 920 O WAT 920 19.000 3.000 18.925 1.00 0.00 O +ATOM 921 O WAT 921 19.000 5.000 0.907 1.00 0.00 O +ATOM 922 O WAT 922 19.000 5.000 2.907 1.00 0.00 O +ATOM 923 O WAT 923 19.000 5.000 4.907 1.00 0.00 O +ATOM 924 O WAT 924 19.000 5.000 6.907 1.00 0.00 O +ATOM 925 O WAT 925 19.000 5.000 8.907 1.00 0.00 O +ATOM 926 O WAT 926 19.000 5.000 10.907 1.00 0.00 O +ATOM 927 O WAT 927 19.000 5.000 12.907 1.00 0.00 O +ATOM 928 O WAT 928 19.000 5.000 14.907 1.00 0.00 O +ATOM 929 O WAT 929 19.000 5.000 16.907 1.00 0.00 O +ATOM 930 O WAT 930 19.000 5.000 18.907 1.00 0.00 O +ATOM 931 O WAT 931 19.000 7.000 0.925 1.00 0.00 O +ATOM 932 O WAT 932 19.000 7.000 2.925 1.00 0.00 O +ATOM 933 O WAT 933 19.000 7.000 4.925 1.00 0.00 O +ATOM 934 O WAT 934 19.000 7.000 6.925 1.00 0.00 O +ATOM 935 O WAT 935 19.000 7.000 8.925 1.00 0.00 O +ATOM 936 O WAT 936 19.000 7.000 10.925 1.00 0.00 O +ATOM 937 O WAT 937 19.000 7.000 12.925 1.00 0.00 O +ATOM 938 O WAT 938 19.000 7.000 14.925 1.00 0.00 O +ATOM 939 O WAT 939 19.000 7.000 16.925 1.00 0.00 O +ATOM 940 O WAT 940 19.000 7.000 18.925 1.00 0.00 O +ATOM 941 O WAT 941 19.000 9.000 0.971 1.00 0.00 O +ATOM 942 O WAT 942 19.000 9.000 2.971 1.00 0.00 O +ATOM 943 O WAT 943 19.000 9.000 4.971 1.00 0.00 O +ATOM 944 O WAT 944 19.000 9.000 6.971 1.00 0.00 O +ATOM 945 O WAT 945 19.000 9.000 8.971 1.00 0.00 O +ATOM 946 O WAT 946 19.000 9.000 10.971 1.00 0.00 O +ATOM 947 O WAT 947 19.000 9.000 12.971 1.00 0.00 O +ATOM 948 O WAT 948 19.000 9.000 14.971 1.00 0.00 O +ATOM 949 O WAT 949 19.000 9.000 16.971 1.00 0.00 O +ATOM 950 O WAT 950 19.000 9.000 18.971 1.00 0.00 O +ATOM 951 O WAT 951 19.000 11.000 1.029 1.00 0.00 O +ATOM 952 O WAT 952 19.000 11.000 3.029 1.00 0.00 O +ATOM 953 O WAT 953 19.000 11.000 5.029 1.00 0.00 O +ATOM 954 O WAT 954 19.000 11.000 7.029 1.00 0.00 O +ATOM 955 O WAT 955 19.000 11.000 9.029 1.00 0.00 O +ATOM 956 O WAT 956 19.000 11.000 11.029 1.00 0.00 O +ATOM 957 O WAT 957 19.000 11.000 13.029 1.00 0.00 O +ATOM 958 O WAT 958 19.000 11.000 15.029 1.00 0.00 O +ATOM 959 O WAT 959 19.000 11.000 17.029 1.00 0.00 O +ATOM 960 O WAT 960 19.000 11.000 19.029 1.00 0.00 O +ATOM 961 O WAT 961 19.000 13.000 1.075 1.00 0.00 O +ATOM 962 O WAT 962 19.000 13.000 3.075 1.00 0.00 O +ATOM 963 O WAT 963 19.000 13.000 5.075 1.00 0.00 O +ATOM 964 O WAT 964 19.000 13.000 7.075 1.00 0.00 O +ATOM 965 O WAT 965 19.000 13.000 9.075 1.00 0.00 O +ATOM 966 O WAT 966 19.000 13.000 11.075 1.00 0.00 O +ATOM 967 O WAT 967 19.000 13.000 13.075 1.00 0.00 O +ATOM 968 O WAT 968 19.000 13.000 15.075 1.00 0.00 O +ATOM 969 O WAT 969 19.000 13.000 17.075 1.00 0.00 O +ATOM 970 O WAT 970 19.000 13.000 19.075 1.00 0.00 O +ATOM 971 O WAT 971 19.000 15.000 1.093 1.00 0.00 O +ATOM 972 O WAT 972 19.000 15.000 3.093 1.00 0.00 O +ATOM 973 O WAT 973 19.000 15.000 5.093 1.00 0.00 O +ATOM 974 O WAT 974 19.000 15.000 7.093 1.00 0.00 O +ATOM 975 O WAT 975 19.000 15.000 9.093 1.00 0.00 O +ATOM 976 O WAT 976 19.000 15.000 11.093 1.00 0.00 O +ATOM 977 O WAT 977 19.000 15.000 13.093 1.00 0.00 O +ATOM 978 O WAT 978 19.000 15.000 15.093 1.00 0.00 O +ATOM 979 O WAT 979 19.000 15.000 17.093 1.00 0.00 O +ATOM 980 O WAT 980 19.000 15.000 19.093 1.00 0.00 O +ATOM 981 O WAT 981 19.000 17.000 1.075 1.00 0.00 O +ATOM 982 O WAT 982 19.000 17.000 3.075 1.00 0.00 O +ATOM 983 O WAT 983 19.000 17.000 5.075 1.00 0.00 O +ATOM 984 O WAT 984 19.000 17.000 7.075 1.00 0.00 O +ATOM 985 O WAT 985 19.000 17.000 9.075 1.00 0.00 O +ATOM 986 O WAT 986 19.000 17.000 11.075 1.00 0.00 O +ATOM 987 O WAT 987 19.000 17.000 13.075 1.00 0.00 O +ATOM 988 O WAT 988 19.000 17.000 15.075 1.00 0.00 O +ATOM 989 O WAT 989 19.000 17.000 17.075 1.00 0.00 O +ATOM 990 O WAT 990 19.000 17.000 19.075 1.00 0.00 O +ATOM 991 O WAT 991 19.000 19.000 1.029 1.00 0.00 O +ATOM 992 O WAT 992 19.000 19.000 3.029 1.00 0.00 O +ATOM 993 O WAT 993 19.000 19.000 5.029 1.00 0.00 O +ATOM 994 O WAT 994 19.000 19.000 7.029 1.00 0.00 O +ATOM 995 O WAT 995 19.000 19.000 9.029 1.00 0.00 O +ATOM 996 O WAT 996 19.000 19.000 11.029 1.00 0.00 O +ATOM 997 O WAT 997 19.000 19.000 13.029 1.00 0.00 O +ATOM 998 O WAT 998 19.000 19.000 15.029 1.00 0.00 O +ATOM 999 O WAT 999 19.000 19.000 17.029 1.00 0.00 O +ATOM 1000 O WAT 1000 19.000 19.000 19.029 1.00 0.00 O END diff --git a/test/Test_SurfTension/st.itim.dat.save b/test/Test_SurfTension/st.itim.dat.save index f0659b28f3..2f5447ab74 100644 --- a/test/Test_SurfTension/st.itim.dat.save +++ b/test/Test_SurfTension/st.itim.dat.save @@ -12,6 +12,9 @@ qmin 0.314159 qmax 0.8 frames 1 skipped 0 -roughness 0 -roughness_upper 0 -roughness_lower 0 +gamma 5336.11 +gamma_upper 5336.11 +gamma_lower 5336.11 +roughness 0.125838 +roughness_upper 0.125838 +roughness_lower 0.125838 diff --git a/test/Test_SurfTension/st.normalx.dat.save b/test/Test_SurfTension/st.normalx.dat.save index fa365576d4..647a58f108 100644 --- a/test/Test_SurfTension/st.normalx.dat.save +++ b/test/Test_SurfTension/st.normalx.dat.save @@ -12,9 +12,10 @@ qmin 0.314159 qmax 0.8 frames 1 skipped 0 -gamma 849.84 -gamma_upper 849.84 -gamma_lower 849.84 -roughness 0.222848 -roughness_upper 0.222848 -roughness_lower 0.222848 +gamma 1051.08 +gamma_upper 1051.08 +gamma_lower 1051.08 +kappa -1.53118e+32 +roughness 0.205627 +roughness_upper 0.205627 +roughness_lower 0.205627 diff --git a/test/Test_SurfTension/st.normaly.dat.save b/test/Test_SurfTension/st.normaly.dat.save index bd7ab194f1..adc743c2ba 100644 --- a/test/Test_SurfTension/st.normaly.dat.save +++ b/test/Test_SurfTension/st.normaly.dat.save @@ -12,9 +12,9 @@ qmin 0.314159 qmax 0.8 frames 1 skipped 0 -gamma 849.84 -gamma_upper 849.84 -gamma_lower 849.84 -roughness 0.222848 -roughness_upper 0.222848 -roughness_lower 0.222848 +gamma 1051.08 +gamma_upper 1051.08 +gamma_lower 1051.08 +roughness 0.205627 +roughness_upper 0.205627 +roughness_lower 0.205627 diff --git a/test/Test_SurfTension/st.nsurf1.dat.save b/test/Test_SurfTension/st.nsurf1.dat.save index 7b7042973b..dcac7d5244 100644 --- a/test/Test_SurfTension/st.nsurf1.dat.save +++ b/test/Test_SurfTension/st.nsurf1.dat.save @@ -12,7 +12,7 @@ qmin 0.314159 qmax 0.8 frames 1 skipped 0 -gamma 849.84 -gamma_upper 849.84 -roughness 0.222848 -roughness_upper 0.222848 +gamma 512.372 +gamma_upper 512.372 +roughness 0.338125 +roughness_upper 0.338125 diff --git a/test/Test_SurfTension/st.willard.dat.save b/test/Test_SurfTension/st.willard.dat.save index f257deb3b5..497c2df5c3 100644 --- a/test/Test_SurfTension/st.willard.dat.save +++ b/test/Test_SurfTension/st.willard.dat.save @@ -12,9 +12,9 @@ qmin 0.314159 qmax 0.8 frames 1 skipped 0 -gamma 849.84 -gamma_upper 849.84 -gamma_lower 849.84 -roughness 0.222848 -roughness_upper 0.222848 -roughness_lower 0.222848 +gamma 512.372 +gamma_upper 512.372 +gamma_lower 512.372 +roughness 0.338125 +roughness_upper 0.338125 +roughness_lower 0.338125 diff --git a/test/Test_SurfTension/st2_summary.dat.save b/test/Test_SurfTension/st2_summary.dat.save index b3cad2b69f..60ce7aa1e6 100644 --- a/test/Test_SurfTension/st2_summary.dat.save +++ b/test/Test_SurfTension/st2_summary.dat.save @@ -13,9 +13,9 @@ qmin 0.314159 qmax 0.8 frames 1 skipped 0 -gamma 849.84 -gamma_upper 849.84 -gamma_lower 849.84 -roughness 0.222848 -roughness_upper 0.222848 -roughness_lower 0.222848 +gamma 512.372 +gamma_upper 512.372 +gamma_lower 512.372 +roughness 0.338125 +roughness_upper 0.338125 +roughness_lower 0.338125 From 23375745356a650a78dc3d89b084382d6689a27b Mon Sep 17 00:00:00 2001 From: ndlevinzon Date: Wed, 2 Sep 2026 14:20:35 -0600 Subject: [PATCH 16/17] Add author credit for 'surftension' action in README.md - Included Nathan D. Levinzon (University of Utah, UT) as a contributor for the 'Action\surftension' implementation. - This update acknowledges contributions and enhances the documentation of the project. --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 921e3d9ea1..d4bd849c38 100644 --- a/README.md +++ b/README.md @@ -195,6 +195,9 @@ Enhancements to entropy calculation in original Action\_Gist. * Amit Roy (University of Utah, UT) Code for the CUDA version of the 'closest' Action. +* Nathan D. Levinzon (University of Utah, UT) +Action\surftension. + * Andrew Simmonett (National Institutes of Health) Code for the reciprocal part of the particle mesh Ewald calculation (electrostatic and Lennard-Jones). From 3406827ebd4b2a6e48639fa1d927f18f1e4246e6 Mon Sep 17 00:00:00 2001 From: ndlevinzon Date: Wed, 2 Sep 2026 14:26:01 -0600 Subject: [PATCH 17/17] Update RunTest.sh and data files for dual frame analysis in surface tension tests - Enhanced RunTest.sh to support dual frame analysis for both serial and MPI executions, ensuring consistent results across different ranks. - Updated input parameters in st.itim.dat.save, st.normalx.dat.save, st.normaly.dat.save, st.nsurf1.dat.save, st.willard.dat.save, and st2_summary.dat.save to reflect the change from 1 to 2 frames, improving the accuracy of simulation outputs. --- test/Test_SurfTension/RunTest.sh | 10 ++++++++++ test/Test_SurfTension/st.itim.dat.save | 2 +- test/Test_SurfTension/st.normalx.dat.save | 2 +- test/Test_SurfTension/st.normaly.dat.save | 2 +- test/Test_SurfTension/st.nsurf1.dat.save | 2 +- test/Test_SurfTension/st.willard.dat.save | 2 +- test/Test_SurfTension/st2_summary.dat.save | 2 +- 7 files changed, 16 insertions(+), 6 deletions(-) diff --git a/test/Test_SurfTension/RunTest.sh b/test/Test_SurfTension/RunTest.sh index 5ba5c78b0e..6ca5f2e66c 100755 --- a/test/Test_SurfTension/RunTest.sh +++ b/test/Test_SurfTension/RunTest.sh @@ -3,6 +3,8 @@ # slab.pdb is a 20 A cubic lattice of O atoms with a small z-corrugation # so ITIM min/max is not flat. Stretching one box length creates vacuum # on both sides of a slab so Willard/ITIM can find interfaces. +# The PDB is loaded twice so serial and MPI (2 ranks) both analyze 2 +# identical frames; SyncAction then reduces |h_q|^2 and the summaries match. . ../MasterTest.sh @@ -10,6 +12,8 @@ CleanFiles st.in st.willard.dat st.itim.dat st.normalx.dat st.normaly.dat \ st.nsurf1.dat st2_summary.dat TESTNAME='Surface tension (surftension) tests' +# Two frames: Jenkins mpiexec -n 2 assigns one frame per rank. +Requires maxthreads 2 INPUT='-i st.in' @@ -18,6 +22,7 @@ cat > st.in < st.in < st.in < st.in < st.in < st.in <