Merge pull request #159 from Electrostatics/nathan/issue_16c

Finite element solver input file support
This commit is contained in:
Darren Curtis
2021-07-05 12:21:31 -07:00
committed by GitHub
45 changed files with 1509 additions and 351 deletions

View File

@@ -1,10 +1,9 @@
"""Parameters for a finite-difference polar solvation calculation."""
import logging
from math import log2
from typing import Type
from .. import check
from .. import InputFile
from .generic import MobileIons
from .generic import MobileIons, UseMap, WriteMap
_LOGGER = logging.getLogger(__name__)
@@ -871,280 +870,6 @@ class Focus(InputFile):
self._fine_grid_center = value
class UseMap(InputFile):
"""Use a previously read in map.
Objects can be initialized with dictionary/JSON/YAML data with the
following keys:
* ``property``: what property being loaded from the map; see
:func:`property`
* ``alias``: alias assigned when reading in map; see :func:`alias`
"""
def __init__(self, dict_=None, yaml=None, json=None):
self._property = None
self._alias = None
super().__init__(dict_=dict_, yaml=yaml, json=json)
def from_dict(self, input_):
"""Load object from dictionary.
:raises KeyError: if missing items
"""
self.property = input_["property"]
self.alias = input_["alias"]
def to_dict(self) -> dict:
return {"property": self.property, "alias": self.alias}
def validate(self):
errors = []
if self.property is None:
errors.append("property not set.")
if self.alias is None:
errors.append("alias not set.")
if errors:
raise ValueError(" ".join(errors))
@property
def property(self) -> str:
"""Specify the property being read from the map.
One of the following values:
* ``dielectric``: Dielectric function map (as read in
:ref:`read_new_input`); this causes the
:func:`FiniteDifference.solute_dielectric`,
:func:`FiniteDifference.solvent_dielectric`,
:func:`FiniteDifference.solvent_radius`,
:func:`FiniteDifference.surface_method`, and
:func:`FiniteDifference.surface spline window` properties to be
ignored, along with the radii of the solute atoms.
Note that :func:`FiniteDifference.solute_dielectric` and
:func:`FiniteDifference.solvent_dielectric` are still used for some
boundary condition calculations (see
:func:`FiniteDifference.boundary_condition`)
* ``ion accessibility``: Mobile ion-accessibility function map (as read
in :ref:`read_new_input`); this causes the
:func:`FiniteDifference.surface_method`, and
:func:`FiniteDifference.surface spline window` properties to be
ignored, along with the radii of the solute atoms. The
:func:`FiniteDifference.ions` property is not ignored and will still
be used.
* ``charge density``: Charge distribution map (as read in
:ref:`read_new_input`); this causes the :func:`charge discretization`
parameter and the charges of the biomolecular atoms to be ignored when
assembling the fixed charge distribution for the Poisson-Boltzmann
equation.
* ``potential``: Potential map (as read in :ref:`read_new_input`); this
is used to set the boundary condition and causes the
:func:`boundary_condition` property to be ignored.
:raises TypeError: if not string
:raises ValueError: if not valid value
"""
return self._property
@property.setter
def property(self, value):
if not check.is_string(value):
raise TypeError(
f"Value {value} (type {type(value)}) is not a string."
)
value = value.lower()
if value not in [
"dielectric",
"ion accessibility",
"charge density",
"potential",
]:
raise ValueError(f"Value {value} is not valid.")
self._property = value
class WriteMap(InputFile):
"""Write the specified property to a map.
Objects can be initialized with dictionary/JSON/YAML data with the
following keys:
* ``property``: what property is being written to the map; see
:func:`property`
* ``format``: output format; see :func:`format`
* ``path``: a suggested path and file name for the map; see :func:`path`
"""
def __init__(self, dict_=None, yaml=None, json=None):
self._property = None
self._format = None
self._path = None
super().__init__(dict_=dict_, yaml=yaml, json=json)
def from_dict(self, input_):
self.property = input_["property"]
self.format = input_["format"]
self.path = input_["path"]
def to_dict(self) -> dict:
return {
"property": self.property,
"format": self.format,
"path": self.path,
}
def validate(self):
errors = []
if self.property is None:
errors.append("property not set.")
if self.format is None:
errors.append("format not set.")
if self.path is None:
errors.append("path not set.")
if errors:
raise ValueError(" ".join(errors))
@property
def path(self) -> str:
"""Suggested path for writing results.
This path is only a suggestion; if parallel calculations are performed,
then the filename will be modified to include the processor number for
the output.
:raises TypeError: if not set to string.
"""
return self._path
@path.setter
def path(self, value):
if not check.is_string(value):
raise TypeError(
f"Value {value} (type {type(value)}) is not a string."
)
self._path = value
@property
def format(self) -> str:
"""Format for writing output.
Allowed formats (see documentation for details) include:
* ``dx``: OpenDX-format data. This is the preferred format for APBS
input/output.
* ``dx.gz``: GZipped OpenDX-format data.
* ``flat``: Write out data as a plain text file.
* ``uhbd``: UHBD-format data.
:raises TypeError: if not set to a strinng
:raises ValueError: if invalid format specified
"""
return self._format
@format.setter
def format(self, value):
if not check.is_string(value):
raise TypeError(
f"Value {value} (type {type(value)}) is not a string."
)
value = value.lower()
if value not in ["dx", "dx.gz", "flat", "uhbd"]:
raise ValueError(f"Value {value} is not an allowed format.")
self._format = value
@property
def property(self) -> str:
"""Property to write to map.
See the documentation for a discussion of units for these properties.
One of:
* ``charge density``: Write out the biomolecular charge distribution in
units of :math:`e_c` (electron charge) per Å\\ :sup:`3`.
* ``potential``: Write out the electrostatic potential over the entire
problem domain in units of :math:`k_b \\, T \\, e_c^{-1}`.
* ``solvent accessibility``: Write out the solvent accessibility
defined by the molecular surface definition (see
:func:`FiniteDifference.surface_definition`). Values are unitless and
range from 0 (inaccessible) to 1 (accessible).
* ``ion accessibility``: Write out the inflated van der Waals-based ion
accessibility (see :func:`FiniteDifference.surface_definition`).
Values are unitless and range from 0 (inaccessible) to 1 (accessible).
* ``laplacian``: Write out the Laplacian of the potential
:math:`\\nabla^2 \\phi` in units of
k\\ :sub:`B` T e\\ :sub:`c`\\ :sup:`-1` Å\\ :sup:`-2`.
* ``energy density``: Write out the "energy density"
:math:`-\\nabla \\cdot \\epsilon \\nabla \\phi` in units of
k\\ :sub:`B` T e\\ :sub:`c`\\ :sup:`-1` Å\\ :sup:`-2`.
* ``ion number density``: Write out the total mobile ion number density
for all ion species in units of M. The output is calculated according
to the formula (for nonlinear PB calculations): :math:`\\rho(x) =
\\sum_i^N {\\bar{\\rho}_i e^{-q_i\\phi(x) - V_i (x)}}`, where
:math:`N` is the number of ion species, :math:`\\bar{\\rho}_i` is the
bulk density of ion species :math:`i`, :math:`q_i` is the charge of
ion species :math:`i`, :math:`\\phi(x)` is the electrostatic
potential, and :math:`V_i` is the solute-ion interaction potential for
species :math:`i`.
* ``ion charge density``: Write out the total mobile ion charge density
for all ion species in units of e\\ :sub:`c` M. The output is
calculated according to the formula (for nonlinear PB calculations):
:math:`\\rho(x) = \\sum_i^N {\\bar{\\rho}_i q_i e^{-q_i\\phi(x) -
V_i(x)}}`, where :math:`N` is the number of ion species,
:math:`\\bar{\\rho}_i` is the bulk density of ion species :math:`i`,
:math:`q_i` is the charge of ion species :math:`i`, :math:`\\phi(x)`
is the electrostatic potential, and :math:`V_i` is the solute-ion
interaction potential for species :math:`i`.
* ``dielectric x`` or ``dielectric y`` or ``dielectric z``: Write out
the dielectric map shifted by 1/2 grid spacing in the {``x``, ``y``,
``z``}-direction. The values are unitless.
:raises TypeError: if not a string
:raises ValueError: if invalid value
"""
return self._property
@property.setter
def property(self, value):
if not check.is_string(value):
raise TypeError(
f"Value {value} (type {type(value)}) is not a string."
)
value = value.lower()
if value not in [
"charge density",
"potential",
"atom potential",
"solvent accessibility",
"ion accessibility",
"laplacian",
"energy density",
"ion number density",
"ion charge density",
"dielectric x",
"dielectric y",
"dielectric z",
]:
raise ValueError(f"Property {value} is invalid.")
self._property = value
class FiniteDifference(InputFile):
"""Parameters for a finite-difference polar solvation Poisson-Boltzmann
calculation.

View File

@@ -0,0 +1,807 @@
"""Parameters for a finite-element polar solvation calculation."""
import logging
from typing import Type
from .. import check
from .. import InputFile
from .generic import MobileIons, UseMap, WriteMap
_LOGGER = logging.getLogger(__name__)
class FiniteElement(InputFile):
"""Parameters for a finite-difference polar solvation Poisson-Boltzmann
calculation.
Objects can be initialized with dictionary/JSON/YAML data with the
following keys:
* ``a priori refinement``: *a priori* mesh refinement strategy; see
:func:`a_priori_refinement`
* ``boundary condition``: :func:`boundary_condition`
* ``calculate energy``: see :func:`calculate_energy`
* ``calculate forces``: see :func:`calculate_forces`
* ``charge discretization``: method used to map charges onto the grid; see
:func:`charge_discretization`
* ``domain length``: see :func:`domain_length`
* ``error estimation``: how error is calculated for driving refinement;
see :func:`error_estimation`
* ``error-based refinement``: method for choosing which simplices to
refine based on error; see :func:`error_based_refinement`
* ``equation``: what version of the Poisson-Boltzmann equation to solve;
see :func:`equation`
* ``ions``: information about mobile ion species; see :func:`ions`
* ``initial mesh resolution``: target resolution of initial mesh; see
:func:`initial_mesh_resolution`
* ``initial mesh vertices``: target number of vertices in the initial
finite element mesh; see :func:`initial_mesh_vertices`
* ``maximum refinement iterations``: number of times to perform the
solve-estimate-refine iteration of the finite element solver; see
:func:`maximum_refinement_iterations`
* ``maximum vertices``: target for maximum number of vertices in mesh; see
:func:`maximum_vertices`
* ``molecule``: alias to molecule for calculation; see :func:`molecule`
* ``no-op``: determine whether the solver should be run; see :func:`noop`
* ``solute dielectric``: see :func:`solute_dielectric`
* ``solvent dielectric``: see :func:`solvent_dielectric`
* ``solvent radius``: see :func:`solvent_radius`
* ``surface method``: see :func:`surface_method`
* ``surface spline window``: see :func:`surface_spline_window`
* ``temperature``: see :func:`temperature`
* ``use maps``: use input map for one or more properties of the system; see
:func:`use_maps`
* ``write atom potentials``: write out atom potentials; see
:func:`write_atom_potentials`
* ``write maps``: write out one or more properties of the system to a map;
see :func:`write_maps`
"""
def __init__(self, dict_=None, yaml=None, json=None):
self._a_priori_refinement = None
self._boundary_condition = None
self._calculate_energy = None
self._calculate_forces = None
self._charge_discretization = None
self._domain_length = None
self._error_based_refinement = None
self._error_tolerance = None
self._equation = None
self._ions = None
self._initial_mesh_resolution = None
self._initial_mesh_vertices = None
self._maximum_refinement_iterations = None
self._maximum_vertices = None
self._molecule = None
self._solute_dielectric = None
self._solvent_dielectric = None
self._solvent_radius = None
self._surface_method = None
self._surface_spline_window = None
self._temperature = None
self._use_maps = []
self._write_atom_potentials = None
self._write_maps = []
super().__init__(dict_=dict_, yaml=yaml, json=json)
def from_dict(self, input_):
"""Populate object from dictionary.
:param dict input_: dictionary with input data.
:raises KeyError: if dictionary missing keys.
"""
self.a_priori_refinement = input_["a priori refinement"]
self.boundary_condition = input_["boundary condition"]
self.calculate_energy = input_["calculate energy"]
self.calculate_forces = input_["calculate forces"]
self.charge_discretization = input_["charge discretization"]
self.domain_length = input_["domain length"]
self.error_based_refinement = input_["error based refinement"]
self.error_tolerance = input_["error tolerance"]
self.equation = input_["equation"]
self.ions = MobileIons(dict_=input_["ions"])
self.initial_mesh_resolution = input_["initial mesh resolution"]
self.initial_mesh_vertices = input_["initial mesh vertices"]
self.maximum_refinement_iterations = input_[
"maximum refinement iterations"
]
self.maximum_vertices = input_["maximum vertices"]
self.molecule = input_["molecule"]
self.solute_dielectric = input_["solute dielectric"]
self.solvent_dielectric = input_["solvent dielectric"]
self.solvent_radius = input_["solvent radius"]
self.surface_method = input_["surface method"]
self.surface_spline_window = input_["surface spline window"]
self.temperature = input_["temperature"]
self.use_maps = [UseMap(dict_=dict_) for dict_ in input_["use maps"]]
self.write_atom_potentials = input_["write atom potentials"]
self.write_maps = [
WriteMap(dict_=dict_) for dict_ in input_["write maps"]
]
def to_dict(self) -> dict:
"""Dump dictionary from object."""
dict_ = {}
dict_["a priori refinement"] = self.a_priori_refinement
dict_["boundary condition"] = self.boundary_condition
dict_["calculate energy"] = self.calculate_energy
dict_["calculate forces"] = self.calculate_forces
dict_["charge discretization"] = self.charge_discretization
dict_["domain length"] = self.domain_length
dict_["error based refinement"] = self.error_based_refinement
dict_["error tolerance"] = self.error_tolerance
dict_["equation"] = self.equation
dict_["ions"] = self.ions.to_dict()
dict_["initial mesh resolution"] = self.initial_mesh_resolution
dict_["initial mesh vertices"] = self.initial_mesh_vertices
dict_[
"maximum refinement iterations"
] = self.maximum_refinement_iterations
dict_["maximum vertices"] = self.maximum_vertices
dict_["molecule"] = self.molecule
dict_["solute dielectric"] = self.solute_dielectric
dict_["solvent dielectric"] = self.solvent_dielectric
dict_["solvent radius"] = self.solvent_radius
dict_["surface method"] = self.surface_method
dict_["surface spline window"] = self.surface_spline_window
dict_["temperature"] = self.temperature
dict_["use maps"] = [map_.to_dict() for map_ in self.use_maps]
dict_["write atom potentials"] = self.write_atom_potentials
dict_["write maps"] = [map_.to_dict() for map_ in self.write_maps]
return dict_
def validate(self):
"""Validate this object.
Assumes that all attributes have been set via setters.
:raises ValueError: if object is invalid.
"""
for map_ in self.use_maps + self.write_maps:
map_.validate()
self.ions.validate()
if self.initial_mesh_vertices > self.maximum_vertices:
raise ValueError(
f"Initial mesh vertices {self.initial_mesh_vertices} setting "
f"is greater than maximum mesh vertices setting "
f"{self.maximum_vertices}."
)
@property
def write_maps(self) -> list:
"""Write out maps related to computed properties.
See :class:`WriteMap` for more information.
:raises TypeError: if set to wrong type
"""
return self._write_maps
@write_maps.setter
def write_maps(self, value):
if not check.is_list(value):
raise TypeError(
f"Value {value} (type {type(value)}) is not a list."
)
for elem in value:
if not isinstance(elem, WriteMap):
raise TypeError(
f"Value {elem} (type {type(elem)}) is not a WriteMap "
f"object."
)
self._write_maps.append(elem)
@property
def write_atom_potentials(self) -> str:
"""Write out the electrostatic potential at each atom location.
Write out text file with potential at center of atom in units of
:math:`k_b \\, T \\, e_c^{-1}`.
.. note::
These numbers are meaningless by themselves due to the presence of
"self-energy" terms that are sensitive to grid spacing and position.
These numbers should be evaluated with respect to a reference
calculation: the potentials from that reference calculation should
be subtracted from the target system. For example, one calculation
might include a molecule with a heterogeneous dielectric coefficient
and the reference system might be exactly the same system setup but
with a homeogeneous dielectric coefficient. If the results from the
reference calculation are substracted from the first calculation,
then the result will be a physically meaningful reaction field
potential. However, the results from the first and reference
calculations are meaningless by themselves.
:returns: path to text file for writing atom potential values.
:raises TypeError: if not set to string
"""
return self._write_atom_potentials
@write_atom_potentials.setter
def write_atom_potentials(self, value):
if not check.is_string(value):
raise TypeError(
f"Value {value} (type {type(value)}) is not a string."
)
self._write_atom_potentials = value
@property
def use_maps(self) -> list:
"""Information for (optionally) using maps read into APBS.
:returns: list of :class:`UseMap` objects
:raises TypeError: if not a list of :class:`UseMap` objects
"""
return self._use_maps
@use_maps.setter
def use_maps(self, value):
if not check.is_list(value):
raise TypeError(
f"Value {value} (type {type(value)}) is not a list."
)
for elem in value:
if not isinstance(elem, UseMap):
raise TypeError(
f"List contains element {elem} of type {type(elem)}."
)
self._use_maps.append(elem)
@property
def temperature(self) -> float:
"""Temperature for the calculation in Kelvin.
:raises ValueError: if not a positive number (no violations of the
3rd Law!)
"""
return self._temperature
@temperature.setter
def temperature(self, value):
if check.is_positive_definite(value):
self._temperature = value
else:
raise ValueError(f"{value} is not a positive number.")
@property
def surface_spline_window(self) -> float:
"""Window for spline-based surface definitions (not needed otherwise).
This is the distance (in Å) over which the spline transitions from the
solvent dielectric value to the solute dielectric value. A typical
value is 0.3 Å.
:returns: positive number
:raises TypeError: if not a positive number
"""
return self._surface_spline_window
@surface_spline_window.setter
def surface_spline_window(self, value):
if not check.is_positive_definite(value):
raise TypeError(f"Value {value} is not a positive number.")
self._surface_spline_window = value
@property
def surface_method(self) -> str:
"""Method used to defined solute-solvent interface.
One of the following values:
* ``molecular surface``: The dielectric coefficient is defined based on
a molecular surface definition. The problem domain is
divided into two spaces. The "free volume" space is defined by the
union of solvent-sized spheres (see :func:`solvent_radius`) which do
not overlap with the solute atoms. This free volume is assigned bulk
solvent dielectric values. The complement of this space is assigned
solute dielectric values. When the solvent radius is set to zero,
this method corresponds to a van der Waals surface definition. The
ion-accessibility coefficient is defined by an "inflated" van der
Waals model. Specifically, the radius of each biomolecular atom is
increased by the radius of the ion species (as specified with the
:func:`ion` property). The problem domain is then divided into two
spaces. The space inside the union of these inflated atomic spheres
is assigned an ion-accessibility value of 0; the complement space is
assigned the bulk ion accessibility value. See Connolly ML, J Appl
Crystallography 16 548-558, 1983 (`10.1107/S0021889883010985
<https://doi.org/10.1107/S0021889883010985>`_).
* ``smoothed molecular surface``: The dielectric and ion-accessibility
coefficients are defined as for the ``molecular surface`` (see
above). However, they are then "smoothed" by a 9-point harmonic
averaging to somewhat reduce sensitivity to the grid setup. See
Bruccoleri et al. J Comput Chem 18 268-276, 1997
(`10.1007/s00214-007-0397-0
<http://dx.doi.org/10.1007/s00214-007-0397-0>`_).
* ``cubic spline``: The dielectric and ion-accessibility coefficients
are defined by a cubic-spline surface as described by Im et al,
Comp Phys Commun 111 (1-3) 59-75, 1998
(`10.1016/S0010-4655(98)00016-2
<https://doi.org/10.1016/S0010-4655(98)00016-2>`_). The width of the
dielectric interface is controlled by the :func:`spline_window`
property. These spline-based surface definitions are very stable
with respect to grid parameters and therefore ideal for calculating
forces. However, they require substantial reparameterization of the
force field; interested users should consult Nina et al, Biophys
Chem 78 (1-2) 89-96, 1999 (`10.1016/S0301-4622(98)00236-1
<http://dx.doi.org/10.1016/S0301-4622(98)00236-1>`_). Additionally,
these surfaces can generate unphysical results with non-zero ionic
strengths.
* ``septic spline``: The dielectric and ion-accessibility coefficients
are defined by a 7th order polynomial. This surface definition has
characteristics similar to the cubic spline, but provides higher
order continuity necessary for stable force calculations with atomic
multipole force fields (up to quadrupole).
:raises TypeError: if not set to a string
:raises ValueError: if set to invalid value
"""
return self._surface_method
@surface_method.setter
def surface_method(self, value):
if not check.is_string(value):
raise TypeError(
f"Value {value} (type {type(value)} is not a string."
)
value = value.lower()
if value not in [
"molecular surface",
"smoothed molecular surface",
"cubic spline",
"septic spline",
]:
raise ValueError(f"Value {value} is an invalid surface method.")
self._surface_method = value
@property
def solvent_radius(self) -> float:
"""Radius of the solvent molecules.
This parameter is used to define various solvent-related surfaces and
volumes (see :func:`surface_method`). This value is usually set to 1.4
Å for a water-like molecular surface and set to 0 Å for a van der Waals
surface.
:raises ValueError: if value is not a non-negative number
"""
return self._solvent_radius
@solvent_radius.setter
def solvent_radius(self, value):
if check.is_positive_semidefinite(value):
self._solvent_radius = value
else:
raise ValueError(f"{value} is not a non-negative number.")
@property
def solvent_dielectric(self) -> float:
"""Solvent dielectric.
78.5 is a good choice for water at 298 K.
:returns: a floating point number greater than or equal to one
:raises TypeError: if not a number
:raises ValueError: if not greater than or equal to 1
"""
return self._solvent_dielectric
@solvent_dielectric.setter
def solvent_dielectric(self, value):
if not check.is_positive_definite(value):
raise TypeError(f"Value {value} is not a positive number.")
if value < 1:
raise ValueError(f"Value {value} is not >= 1.")
self._solvent_dielectric = value
@property
def solute_dielectric(self) -> float:
"""Solute dielectric.
The dielectric value of a solute is often chosen using the following
rules of thumb:
* 1: only used to compare calculation results with non-polarizable
molecular simulation
* 2-4: "molecular" dielectric value; used when conformational degrees
of freedom are modeled explicitly
* 4-8: used to mimic sidechain libration and other small-scale
conformational degrees of freedom
* 8-12: used to model larger-scale sidechain rearrangement
* 20-40: used to model larger-scale macromolecular conformational
changes and/or water penetration into interior of molecule
.. note::
What does the continuum dielectric value of a non-continuum molecule
mean? Hard to say -- this approximation can be very difficult to
interpret and can significant affect your results.
:returns: a floating point number greater than or equal to one
:raises TypeError: if not a number
:raises ValueError: if not greater than or equal to 1
"""
return self._solute_dielectric
@solute_dielectric.setter
def solute_dielectric(self, value):
if not check.is_positive_definite(value):
raise TypeError(f"Value {value} is not a positive number.")
if value < 1:
raise ValueError(f"Value {value} is not >= 1.")
self._solute_dielectric = value
@property
def molecule(self) -> str:
"""Specify which molecule to use for calculation.
:returns: alias for molecule read (see :ref:`read_new_input`)
:raises TypeError: if not set to a string
"""
return self._molecule
@molecule.setter
def molecule(self, value):
if not check.is_string(value):
raise TypeError(
f"Value {value} (type {type(value)}) is not a string."
)
self._molecule = value
@property
def maximum_vertices(self) -> int:
"""Maximum number of vertices produced in solve-estimate-refine
iterations.
The solve-estimate-refine loop will continue until the mesh has more
than this number of vertices or :func:`maximum_refinement_iterations`
has been reached.
.. todo:: add validation step to make sure this number is greater than
or equal to the initial number of vertices.
:raises TypeError: if not sent to positive integer
"""
return self._maximum_vertices
@maximum_vertices.setter
def maximum_vertices(self, value):
if not isinstance(value, int):
raise TypeError(f"{value} (type {type(value)}) is not an integer.")
if value < 1:
raise TypeError(f"{value} is not a positive integer.")
self._maximum_vertices = value
@property
def maximum_refinement_iterations(self) -> int:
"""Maximum number of solve-estimate-refine iterations.
The solve-estimate-refine loop will continue until this number of
iterations is reached or the mesh has more than
:func:`maximum_vertices` vertices.
:raises TypeError: if not sent to positive integer
"""
return self._maximum_refinement_iterations
@maximum_refinement_iterations.setter
def maximum_refinement_iterations(self, value):
if not isinstance(value, int):
raise TypeError(f"{value} (type {type(value)}) is not an integer.")
if value < 1:
raise TypeError(f"{value} is not a positive integer.")
self._maximum_refinement_iterations = value
@property
def initial_mesh_vertices(self) -> int:
"""Target number of vertices in initial mesh.
Initial refinement will continue until this number of vertices is
exceeded or :func:`initial_mesh_resolution` is reached.
:raises TypeError: if not set to a positive integer
"""
return self._initial_mesh_vertices
@initial_mesh_vertices.setter
def initial_mesh_vertices(self, value):
if not isinstance(value, int):
raise TypeError(f"{value} (type {type(value)}) is not an integer.")
if value < 1:
raise TypeError(f"{value} is not a positive integer.")
self._initial_mesh_vertices = value
@property
def initial_mesh_resolution(self) -> float:
"""Target spacing (in Å) of initial mesh.
Initial refinement will continue until this target spacing is met or
until :func:`initial_mesh_vertices` is exceeded.
:raises TypeError: if not set to a positive number
"""
return self._initial_mesh_resolution
@initial_mesh_resolution.setter
def initial_mesh_resolution(self, value):
if not check.is_positive_definite(value):
raise ValueError(f"Value {value} is not a positive number.")
self._initial_mesh_resolution = value
@property
def ions(self) -> MobileIons:
"""Descriptions of mobile ion species.
:raises TypeError: if not set to a :class:`Ions` object
"""
_LOGGER.debug(f"self.ions = {self._ions}.")
if self._ions is None:
raise TypeError("Ions are set to None.")
return self._ions
@ions.setter
def ions(self, value):
if not isinstance(value, MobileIons):
raise TypeError(
f"Value {value} (type {type(value)} is not an Ions object."
)
self._ions = value
@property
def domain_length(self) -> list:
"""Length of rectangular prism domain.
:returns: list of non-zero lengths for x, y, and z directions.
:raises TypeError: if not list of positive definite numbers.
:raises IndexError: if list not length 3
"""
return self._domain_length
@domain_length.setter
def domain_length(self, value):
if not check.is_list(value):
raise TypeError(f"{value} (type {type(value)}) is not a list.")
if len(value) != 3:
raise IndexError(f"{value} does not have length 3.")
for elem in value:
if not check.is_positive_definite(elem):
raise TypeError(f"{elem} is not a positive number.")
self._domain_length = value
@property
def a_priori_refinement(self) -> str:
"""Strategy for refining the initial very coarse 8-tetrahedron initial
finite element to a resolution suitable for the main
solve-estimate-refine iteration.
Allowed values include:
* ``geometric``: geometry-based refinement at molecular surface and
charges
* ``uniform``: uniform refinement of the mesh
:raises ValueError: if not set to allowed value
:raises TypeError: if not set to string
"""
return self._a_priori_refinement
@a_priori_refinement.setter
def a_priori_refinement(self, value):
if not check.is_string(value):
raise TypeError(f"{value} (type {type(value)}) is not a string.")
value = value.lower()
if value not in ["geometric", "uniform"]:
raise ValueError(f"{value} is not a recognized value.")
self._a_priori_refinement = value
@property
def boundary_condition(self) -> str:
"""Boundary condition for Poisson-Boltzmann equation.
This property can have one of the following values:
* ``zero``: Dirichlet condition where the potential at the boundary is
set to zero. This condition is not commonly used and can result in
large errors if used inappropriately.
* ``single sphere``: Dirichlet condition where the potential at the
boundary is set to the values prescribed by a Debye-Hückel model for a
single sphere with a point charge, dipole, and quadrupole. The sphere
radius in this model is set to the radius of the biomolecule and the
sphere charge, dipole, and quadrupole are set to the total moments of
the protein. This condition works best when the boundary is
sufficiently far (multiple Debye lengths) from the biomolecule.
* ``multiple sphere``: Dirichlet condition where the potential at the
boundary is set to the values prescribed by a Debye-Hückel model for
multiple, non-interacting spheres with a point charges. The radii of
the non-interacting spheres are set to the atomic radii of and the
sphere charges are set to the atomic charges. This condition works
better than ``single sphere`` for closer boundaries but can be very
slow for large biomolecules.
* ``focus`` :c:var:`alias`: Dirichlet condition where the potential at
the boundary is set to the values computed by a previous (usually
lower-resolution) PB calculation with alias :c:var:`alias`. All of the
boundary points should lie within the domain of the previous
calculation for best accuracy; if any boundary points lie outside,
their values are computed using the ``single sphere`` Debye-Hückel
boundary condition (see above).
:raises ValueError: if set to an invalid boundary type
:raise IndexError: if an insufficient number of words are present
"""
return self._boundary_condition
@boundary_condition.setter
def boundary_condition(self, value):
words = value.split()
if words[0] == "zero":
self._boundary_condition = "zero"
elif words[0] == "single" and words[1] == "sphere":
self._boundary_condition = "single sphere"
elif words[0] == "multiple" and words[1] == "sphere":
self._boundary_condition = "multiple sphere"
elif words[0] == "focus":
self._boundary_condition = " ".join(words)
else:
raise ValueError(f"Unknown boundary condition: {value}.")
@property
def calculate_energy(self) -> bool:
"""Indicate whether energy should be calculated.
:raises TypeError: if not Boolean
"""
return self._calculate_energy
@calculate_energy.setter
def calculate_energy(self, value):
if check.is_bool(value):
self._calculate_energy = value
else:
raise ValueError(f"{value} is not Boolean.")
@property
def calculate_forces(self) -> bool:
"""Indicate whether forces should be calculated.
:raises TypeError: if not Boolean
"""
return self._calculate_forces
@calculate_forces.setter
def calculate_forces(self, value):
if check.is_bool(value):
self._calculate_forces = value
else:
raise ValueError(f"{value} is not Boolean.")
@property
def charge_discretization(self) -> str:
"""The method by which the biomolecular point charges (i.e., Dirac
delta functions) by which charges are mapped to the grid used for the
finite difference calculation.
As we are attempting to model delta functions, the support (domain) of
these discretized charge distributions is always strongly dependent on
the grid spacing.
The following types of discretization are supported:
* ``linear``: Traditional trilinear interpolation (linear splines). The
charge is mapped onto the nearest-neighbor grid points. Resulting
potentials are very sensitive to grid spacing, length, and position.
* ``cubic``: Cubic B-spline discretization. The charge is mapped onto
the nearest- and next-nearest-neighbor grid points. Resulting
potentials are somewhat less sensitive (than ``linear``) to grid
spacing, length, and position.
* ``quintic``: Quintic B-spline discretization. Similar to ``cubic``,
except the charge/multipole is additionally mapped to include
next-next-nearest neighbors (125 grid points receive charge density).
:raises TypeError: if not set to string
:raises ValueError: if not one of the allowed values above
"""
return self._charge_discretization
@charge_discretization.setter
def charge_discretization(self, value):
if not check.is_string(value):
raise TypeError(f"{value} (type {type(value)}) is not a string.")
value = value.lower()
if value not in ["linear", "cubic", "quintic"]:
raise ValueError(f"{value} is not an allowed value.")
self._charge_discretization = value
@property
def error_based_refinement(self) -> str:
"""Specify error-based refinement strategy for simplices.
Can be assigned one of the following values:
* ``global``: this refines simplices until the global error is less
than the amount specified by :func:`error_tolerance`.
* ``simplex``: this refines simplices until the per-simplex error is
less than the amount specified by :func:`error_tolerance`.
* ``fraction``: this refines the specified fraction of simplices
with the largest per-simplex error. The fraction is specified by
:func:`error_tolerance`.
:raises TypeError: if not set to string
:raises ValueError: if not set to allowed value
"""
return self._error_based_refinement
@error_based_refinement.setter
def error_based_refinement(self, value):
if not check.is_string(value):
raise TypeError(f"{value} (type {type(value)} is not a string.")
value = value.lower()
if value not in ["global", "simplex", "fraction"]:
raise ValueError(f"Invalid value: {value}.")
self._error_based_refinement = value
@property
def error_tolerance(self) -> float:
"""Error tolerance for error-based refinement of simplices.
The meaning of this property changes based on the setting of
:func:`error_based_refinement`.
raises TypeError: if not a positive number.
"""
return self._error_tolerance
@error_tolerance.setter
def error_tolerance(self, value):
if not check.is_positive_definite(value):
raise TypeError(f"{value} is not a positive number.")
self._error_tolerance = value
@property
def equation(self) -> str:
"""Specifies which version of the Poisson-Boltzmann equation (PBE) to
solve:
* Most users should use one of these:
* ``linearized pbe``
* ``nonlinear pbe``
* These versions are experimental and unstable:
* ``linearized regularized pbe``
* ``nonlinear regularized pbe``
.. todo:: Confirm that all of these forms of the PBE work for FEM.
:raises TypeError: if not set to a string.
:raises ValueError: if set to an invalid value
"""
return self._equation
@equation.setter
def equation(self, value):
if not check.is_string(value):
raise TypeError(
f"Value {value} (type {type(value)}) is not a string."
)
value = value.lower()
if value not in [
"linearized pbe",
"nonlinear pbe",
"linearized regularized pbe",
"nonlinear regularized pbe",
]:
raise ValueError(f"Value {value} is invalid.")
self._equation = value

View File

@@ -155,3 +155,277 @@ class MobileIons(InputFile):
raise ValueError(
f"The net mobile ion charge ({net_charge} e) is not zero."
)
class WriteMap(InputFile):
"""Write the specified property to a map.
Objects can be initialized with dictionary/JSON/YAML data with the
following keys:
* ``property``: what property is being written to the map; see
:func:`property`
* ``format``: output format; see :func:`format`
* ``path``: a suggested path and file name for the map; see :func:`path`
"""
def __init__(self, dict_=None, yaml=None, json=None):
self._property = None
self._format = None
self._path = None
super().__init__(dict_=dict_, yaml=yaml, json=json)
def from_dict(self, input_):
self.property = input_["property"]
self.format = input_["format"]
self.path = input_["path"]
def to_dict(self) -> dict:
return {
"property": self.property,
"format": self.format,
"path": self.path,
}
def validate(self):
errors = []
if self.property is None:
errors.append("property not set.")
if self.format is None:
errors.append("format not set.")
if self.path is None:
errors.append("path not set.")
if errors:
raise ValueError(" ".join(errors))
@property
def path(self) -> str:
"""Suggested path for writing results.
This path is only a suggestion; if parallel calculations are performed,
then the filename will be modified to include the processor number for
the output.
:raises TypeError: if not set to string.
"""
return self._path
@path.setter
def path(self, value):
if not check.is_string(value):
raise TypeError(
f"Value {value} (type {type(value)}) is not a string."
)
self._path = value
@property
def format(self) -> str:
"""Format for writing output.
Allowed formats (see documentation for details) include:
* ``dx``: OpenDX-format data. This is the preferred format for APBS
input/output.
* ``dx.gz``: GZipped OpenDX-format data.
* ``flat``: Write out data as a plain text file.
* ``uhbd``: UHBD-format data.
:raises TypeError: if not set to a strinng
:raises ValueError: if invalid format specified
"""
return self._format
@format.setter
def format(self, value):
if not check.is_string(value):
raise TypeError(
f"Value {value} (type {type(value)}) is not a string."
)
value = value.lower()
if value not in ["dx", "dx.gz", "flat", "uhbd"]:
raise ValueError(f"Value {value} is not an allowed format.")
self._format = value
@property
def property(self) -> str:
"""Property to write to map.
See the documentation for a discussion of units for these properties.
One of:
* ``charge density``: Write out the biomolecular charge distribution in
units of :math:`e_c` (electron charge) per Å\\ :sup:`3`.
* ``potential``: Write out the electrostatic potential over the entire
problem domain in units of :math:`k_b \\, T \\, e_c^{-1}`.
* ``solvent accessibility``: Write out the solvent accessibility
defined by the molecular surface definition (see
:func:`FiniteDifference.surface_definition`). Values are unitless and
range from 0 (inaccessible) to 1 (accessible).
* ``ion accessibility``: Write out the inflated van der Waals-based ion
accessibility (see :func:`FiniteDifference.surface_definition`).
Values are unitless and range from 0 (inaccessible) to 1 (accessible).
* ``laplacian``: Write out the Laplacian of the potential
:math:`\\nabla^2 \\phi` in units of
k\\ :sub:`B` T e\\ :sub:`c`\\ :sup:`-1` Å\\ :sup:`-2`.
* ``energy density``: Write out the "energy density"
:math:`-\\nabla \\cdot \\epsilon \\nabla \\phi` in units of
k\\ :sub:`B` T e\\ :sub:`c`\\ :sup:`-1` Å\\ :sup:`-2`.
* ``ion number density``: Write out the total mobile ion number density
for all ion species in units of M. The output is calculated according
to the formula (for nonlinear PB calculations): :math:`\\rho(x) =
\\sum_i^N {\\bar{\\rho}_i e^{-q_i\\phi(x) - V_i (x)}}`, where
:math:`N` is the number of ion species, :math:`\\bar{\\rho}_i` is the
bulk density of ion species :math:`i`, :math:`q_i` is the charge of
ion species :math:`i`, :math:`\\phi(x)` is the electrostatic
potential, and :math:`V_i` is the solute-ion interaction potential for
species :math:`i`.
* ``ion charge density``: Write out the total mobile ion charge density
for all ion species in units of e\\ :sub:`c` M. The output is
calculated according to the formula (for nonlinear PB calculations):
:math:`\\rho(x) = \\sum_i^N {\\bar{\\rho}_i q_i e^{-q_i\\phi(x) -
V_i(x)}}`, where :math:`N` is the number of ion species,
:math:`\\bar{\\rho}_i` is the bulk density of ion species :math:`i`,
:math:`q_i` is the charge of ion species :math:`i`, :math:`\\phi(x)`
is the electrostatic potential, and :math:`V_i` is the solute-ion
interaction potential for species :math:`i`.
* ``dielectric x`` or ``dielectric y`` or ``dielectric z``: Write out
the dielectric map shifted by 1/2 grid spacing in the {``x``, ``y``,
``z``}-direction. The values are unitless.
:raises TypeError: if not a string
:raises ValueError: if invalid value
"""
return self._property
@property.setter
def property(self, value):
if not check.is_string(value):
raise TypeError(
f"Value {value} (type {type(value)}) is not a string."
)
value = value.lower()
if value not in [
"charge density",
"potential",
"atom potential",
"solvent accessibility",
"ion accessibility",
"laplacian",
"energy density",
"ion number density",
"ion charge density",
"dielectric x",
"dielectric y",
"dielectric z",
]:
raise ValueError(f"Property {value} is invalid.")
self._property = value
class UseMap(InputFile):
"""Use a previously read in map.
Objects can be initialized with dictionary/JSON/YAML data with the
following keys:
* ``property``: what property being loaded from the map; see
:func:`property`
* ``alias``: alias assigned when reading in map; see :func:`alias`
"""
def __init__(self, dict_=None, yaml=None, json=None):
self._property = None
self._alias = None
super().__init__(dict_=dict_, yaml=yaml, json=json)
def from_dict(self, input_):
"""Load object from dictionary.
:raises KeyError: if missing items
"""
self.property = input_["property"]
self.alias = input_["alias"]
def to_dict(self) -> dict:
return {"property": self.property, "alias": self.alias}
def validate(self):
errors = []
if self.property is None:
errors.append("property not set.")
if self.alias is None:
errors.append("alias not set.")
if errors:
raise ValueError(" ".join(errors))
@property
def property(self) -> str:
"""Specify the property being read from the map.
One of the following values:
* ``dielectric``: Dielectric function map (as read in
:ref:`read_new_input`); this causes the
:func:`FiniteDifference.solute_dielectric`,
:func:`FiniteDifference.solvent_dielectric`,
:func:`FiniteDifference.solvent_radius`,
:func:`FiniteDifference.surface_method`, and
:func:`FiniteDifference.surface spline window` properties to be
ignored, along with the radii of the solute atoms.
Note that :func:`FiniteDifference.solute_dielectric` and
:func:`FiniteDifference.solvent_dielectric` are still used for some
boundary condition calculations (see
:func:`FiniteDifference.boundary_condition`)
* ``ion accessibility``: Mobile ion-accessibility function map (as read
in :ref:`read_new_input`); this causes the
:func:`FiniteDifference.surface_method`, and
:func:`FiniteDifference.surface spline window` properties to be
ignored, along with the radii of the solute atoms. The
:func:`FiniteDifference.ions` property is not ignored and will still
be used.
* ``charge density``: Charge distribution map (as read in
:ref:`read_new_input`); this causes the :func:`charge discretization`
parameter and the charges of the biomolecular atoms to be ignored when
assembling the fixed charge distribution for the Poisson-Boltzmann
equation.
* ``potential``: Potential map (as read in :ref:`read_new_input`); this
is used to set the boundary condition and causes the
:func:`boundary_condition` property to be ignored.
:raises TypeError: if not string
:raises ValueError: if not valid value
"""
return self._property
@property.setter
def property(self, value):
if not check.is_string(value):
raise TypeError(
f"Value {value} (type {type(value)}) is not a string."
)
value = value.lower()
if value not in [
"dielectric",
"ion accessibility",
"charge density",
"potential",
]:
raise ValueError(f"Value {value} is not valid.")
self._property = value

View File

@@ -0,0 +1,267 @@
"""Test input file calculate.FiniteElement."""
import logging
import json
import pytest
from apbs.input_file.calculate.finite_element import FiniteElement
_LOGGER = logging.getLogger(__name__)
GOOD_TEMPLATE = {
"a priori refinement": None,
"boundary condition": None,
"calculate energy": True,
"calculate forces": True,
"charge discretization": None,
"domain length": [22.5, 19.5, 0.5],
"error based refinement": None,
"error tolerance": 1e-3,
"equation": None,
"ions": None,
"initial mesh resolution": 0.5,
"initial mesh vertices": 100000,
"maximum refinement iterations": 10,
"maximum vertices": 10000000,
"molecule": "foo",
"solute dielectric": 12,
"solvent dielectric": 78.54,
"solvent radius": 1.4,
"surface method": None,
"surface spline window": 0.3,
"temperature": 298.15,
"use maps": None,
"write atom potentials": "atom_potentials.txt",
"write maps": [
{"property": "potential", "format": "dx.gz", "path": "pot.dx.gz"}
],
}
GOOD_A_PRIORI_REFINEMNT = ["geometric", "uniform"]
GOOD_BOUNDARY_CONDITIONS = [
"zero",
"single sphere",
"multiple sphere",
"focus foo",
]
GOOD_CHARGE_DISCRETIZATIONS = ["linear", "cubic", "quintic"]
GOOD_ERROR_BASED_REFINEMENT = ["global", "simplex", "fraction"]
GOOD_EQUATIONS = [
"linearized pbe",
"nonlinear pbe",
"linearized regularized pbe",
"nonlinear regularized pbe",
]
GOOD_IONS = [
{
"species": [
{"charge": +2, "radius": 2.0, "concentration": 0.050},
{"charge": 1, "radius": 1.2, "concentration": 0.100},
{"charge": -1, "radius": 2.0, "concentration": 0.200},
]
},
{
"species": [
{"charge": 1, "radius": 1.2, "concentration": 0.100},
{"charge": -1, "radius": 2.0, "concentration": 0.100},
]
},
]
GOOD_SURFACE_METHODS = [
"molecular surface",
"smoothed molecular surface",
"cubic spline",
"septic spline",
]
GOOD_USEMAP_INPUTS = [
[{"property": prop, "alias": "foo"}]
for prop in [
"dielectric",
"ion accessibility",
"charge density",
"potential",
]
]
@pytest.mark.parametrize("test_variable", GOOD_A_PRIORI_REFINEMNT)
def test_a_priori_refinement(test_variable):
input_dict = GOOD_TEMPLATE
input_dict["a priori refinement"] = test_variable
input_dict["boundary condition"] = GOOD_BOUNDARY_CONDITIONS[0]
input_dict["charge discretization"] = GOOD_CHARGE_DISCRETIZATIONS[0]
input_dict["error based refinement"] = GOOD_ERROR_BASED_REFINEMENT[0]
input_dict["equation"] = GOOD_EQUATIONS[0]
input_dict["ions"] = GOOD_IONS[0]
input_dict["surface method"] = GOOD_SURFACE_METHODS[0]
input_dict["use maps"] = GOOD_USEMAP_INPUTS[0]
_LOGGER.debug(f"Input JSON: {json.dumps(input_dict, indent=2)}")
obj = FiniteElement(dict_=input_dict)
obj.validate()
dict_ = obj.to_dict()
_LOGGER.debug(f"Output JSON: {json.dumps(dict_, indent=2)}")
obj = FiniteElement(dict_=dict_)
obj.validate()
with pytest.raises(ValueError):
input_dict["a priori refinement"] = "foo"
obj = FiniteElement(dict_=input_dict)
obj.validate()
@pytest.mark.parametrize("test_variable", GOOD_BOUNDARY_CONDITIONS)
def test_boundary_conditions(test_variable):
input_dict = GOOD_TEMPLATE
input_dict["a priori refinement"] = GOOD_A_PRIORI_REFINEMNT[0]
input_dict["boundary condition"] = test_variable
input_dict["charge discretization"] = GOOD_CHARGE_DISCRETIZATIONS[0]
input_dict["error based refinement"] = GOOD_ERROR_BASED_REFINEMENT[0]
input_dict["equation"] = GOOD_EQUATIONS[0]
input_dict["ions"] = GOOD_IONS[0]
input_dict["surface method"] = GOOD_SURFACE_METHODS[0]
input_dict["use maps"] = GOOD_USEMAP_INPUTS[0]
_LOGGER.debug(f"Input JSON: {json.dumps(input_dict, indent=2)}")
obj = FiniteElement(dict_=input_dict)
obj.validate()
dict_ = obj.to_dict()
_LOGGER.debug(f"Output JSON: {json.dumps(dict_, indent=2)}")
obj = FiniteElement(dict_=dict_)
obj.validate()
with pytest.raises(ValueError):
input_dict["boundary condition"] = "foo"
obj = FiniteElement(dict_=input_dict)
obj.validate()
@pytest.mark.parametrize("test_variable", GOOD_CHARGE_DISCRETIZATIONS)
def test_charge_discretization(test_variable):
input_dict = GOOD_TEMPLATE
input_dict["a priori refinement"] = GOOD_A_PRIORI_REFINEMNT[0]
input_dict["boundary condition"] = GOOD_BOUNDARY_CONDITIONS[0]
input_dict["charge discretization"] = test_variable
input_dict["error based refinement"] = GOOD_ERROR_BASED_REFINEMENT[0]
input_dict["equation"] = GOOD_EQUATIONS[0]
input_dict["ions"] = GOOD_IONS[0]
input_dict["surface method"] = GOOD_SURFACE_METHODS[0]
input_dict["use maps"] = GOOD_USEMAP_INPUTS[0]
_LOGGER.debug(f"Input JSON: {json.dumps(input_dict, indent=2)}")
obj = FiniteElement(dict_=input_dict)
obj.validate()
dict_ = obj.to_dict()
_LOGGER.debug(f"Output JSON: {json.dumps(dict_, indent=2)}")
obj = FiniteElement(dict_=dict_)
obj.validate()
with pytest.raises(ValueError):
input_dict["charge discretization"] = "foo"
obj = FiniteElement(dict_=input_dict)
obj.validate()
@pytest.mark.parametrize("test_variable", GOOD_ERROR_BASED_REFINEMENT)
def test_error_based_refinement(test_variable):
input_dict = GOOD_TEMPLATE
input_dict["a priori refinement"] = GOOD_A_PRIORI_REFINEMNT[0]
input_dict["boundary condition"] = GOOD_BOUNDARY_CONDITIONS[0]
input_dict["charge discretization"] = GOOD_CHARGE_DISCRETIZATIONS[0]
input_dict["error based refinement"] = test_variable
input_dict["equation"] = GOOD_EQUATIONS[0]
input_dict["ions"] = GOOD_IONS[0]
input_dict["surface method"] = GOOD_SURFACE_METHODS[0]
input_dict["use maps"] = GOOD_USEMAP_INPUTS[0]
_LOGGER.debug(f"Input JSON: {json.dumps(input_dict, indent=2)}")
obj = FiniteElement(dict_=input_dict)
obj.validate()
dict_ = obj.to_dict()
_LOGGER.debug(f"Output JSON: {json.dumps(dict_, indent=2)}")
obj = FiniteElement(dict_=dict_)
obj.validate()
with pytest.raises(ValueError):
input_dict["error based refinement"] = "foo"
obj = FiniteElement(dict_=input_dict)
obj.validate()
@pytest.mark.parametrize("test_variable", GOOD_EQUATIONS)
def test_equation(test_variable):
input_dict = GOOD_TEMPLATE
input_dict["a priori refinement"] = GOOD_A_PRIORI_REFINEMNT[0]
input_dict["boundary condition"] = GOOD_BOUNDARY_CONDITIONS[0]
input_dict["charge discretization"] = GOOD_CHARGE_DISCRETIZATIONS[0]
input_dict["error based refinement"] = GOOD_ERROR_BASED_REFINEMENT[0]
input_dict["equation"] = test_variable
input_dict["ions"] = GOOD_IONS[0]
input_dict["surface method"] = GOOD_SURFACE_METHODS[0]
input_dict["use maps"] = GOOD_USEMAP_INPUTS[0]
_LOGGER.debug(f"Input JSON: {json.dumps(input_dict, indent=2)}")
obj = FiniteElement(dict_=input_dict)
obj.validate()
dict_ = obj.to_dict()
_LOGGER.debug(f"Output JSON: {json.dumps(dict_, indent=2)}")
obj = FiniteElement(dict_=dict_)
obj.validate()
with pytest.raises(ValueError):
input_dict["equation"] = "foo"
obj = FiniteElement(dict_=input_dict)
obj.validate()
@pytest.mark.parametrize("test_variable", GOOD_IONS)
def test_ions(test_variable):
input_dict = GOOD_TEMPLATE
input_dict["a priori refinement"] = GOOD_A_PRIORI_REFINEMNT[0]
input_dict["boundary condition"] = GOOD_BOUNDARY_CONDITIONS[0]
input_dict["charge discretization"] = GOOD_CHARGE_DISCRETIZATIONS[0]
input_dict["error based refinement"] = GOOD_ERROR_BASED_REFINEMENT[0]
input_dict["equation"] = GOOD_EQUATIONS[0]
input_dict["ions"] = test_variable
input_dict["surface method"] = GOOD_SURFACE_METHODS[0]
input_dict["use maps"] = GOOD_USEMAP_INPUTS[0]
_LOGGER.debug(f"Input JSON: {json.dumps(input_dict, indent=2)}")
obj = FiniteElement(dict_=input_dict)
obj.validate()
dict_ = obj.to_dict()
_LOGGER.debug(f"Output JSON: {json.dumps(dict_, indent=2)}")
obj = FiniteElement(dict_=dict_)
obj.validate()
@pytest.mark.parametrize("test_variable", GOOD_SURFACE_METHODS)
def test_surface_methods(test_variable):
input_dict = GOOD_TEMPLATE
input_dict["a priori refinement"] = GOOD_A_PRIORI_REFINEMNT[0]
input_dict["boundary condition"] = GOOD_BOUNDARY_CONDITIONS[0]
input_dict["charge discretization"] = GOOD_CHARGE_DISCRETIZATIONS[0]
input_dict["error based refinement"] = GOOD_ERROR_BASED_REFINEMENT[0]
input_dict["equation"] = GOOD_EQUATIONS[0]
input_dict["ions"] = GOOD_IONS[0]
input_dict["surface method"] = test_variable
input_dict["use maps"] = GOOD_USEMAP_INPUTS[0]
_LOGGER.debug(f"Input JSON: {json.dumps(input_dict, indent=2)}")
obj = FiniteElement(dict_=input_dict)
obj.validate()
dict_ = obj.to_dict()
_LOGGER.debug(f"Output JSON: {json.dumps(dict_, indent=2)}")
obj = FiniteElement(dict_=dict_)
obj.validate()
with pytest.raises(ValueError):
input_dict["surface method"] = "foo"
obj = FiniteElement(dict_=input_dict)
obj.validate()
@pytest.mark.parametrize("test_variable", GOOD_USEMAP_INPUTS)
def test_use_map(test_variable):
input_dict = GOOD_TEMPLATE
input_dict["a priori refinement"] = GOOD_A_PRIORI_REFINEMNT[0]
input_dict["boundary condition"] = GOOD_BOUNDARY_CONDITIONS[0]
input_dict["charge discretization"] = GOOD_CHARGE_DISCRETIZATIONS[0]
input_dict["error based refinement"] = GOOD_ERROR_BASED_REFINEMENT[0]
input_dict["equation"] = GOOD_EQUATIONS[0]
input_dict["ions"] = GOOD_IONS[0]
input_dict["surface method"] = GOOD_SURFACE_METHODS[0]
input_dict["use maps"] = test_variable
_LOGGER.debug(f"Input JSON: {json.dumps(input_dict, indent=2)}")
obj = FiniteElement(dict_=input_dict)
obj.validate()
dict_ = obj.to_dict()
_LOGGER.debug(f"Output JSON: {json.dumps(dict_, indent=2)}")
obj = FiniteElement(dict_=dict_)
obj.validate()

View File

@@ -56,6 +56,7 @@ extensions = [
"sphinx_rtd_theme",
"sphinx.ext.mathjax",
"sphinx_sitemap",
"autodocsumm",
]
todo_include_todos = True
@@ -69,6 +70,10 @@ autosummary_generate = True
autosummary_imported_members = False
autosummary_generate_overwrite = True
autodoc_default_options = {
"autosummary": True,
}
master_doc = "index"
# Add any paths that contain templates here, relative to this directory.

View File

@@ -2,6 +2,8 @@
Protein-RNA binding linked equilibria
=====================================
.. todo:: Update this documentation with the *new APBS syntax* (see :ref:`new_input_format`).
Before reading this example, please review :ref:`errors` for relevant caveats.
------------
@@ -157,7 +159,7 @@ As used in the template file, the READ command, our calculation will have three
The calculations themselves will not be overly demanding, since we will use relatively coarse grids.
This grid coarseness has a significant impact on the absolute electrostatic binding energy we obtain from this particular calculation: the calculated energy isn't converged with respect to grid spacing.
However, the overall slope of binding energy with respect to monovalent ion concentration is rather insensitive with respect to the grid spacing, allowing us to save computational time and effort during the calculations.
The calculation will conclude with a :doc:`/using/input/print` command which will combine the total energies from the three parts to obtain our approximate absolute electrostatic binding energy for the complex at 0.225 M monovalent salt concentration.
The calculation will conclude with a :doc:`/using/input/old/print` command which will combine the total energies from the three parts to obtain our approximate absolute electrostatic binding energy for the complex at 0.225 M monovalent salt concentration.
It is very important to note that this absolute energy no meaning in isolation for several reasons:
* It is not converged with respect to grid spacing

View File

@@ -2,6 +2,8 @@
Solvation energies
==================
.. todo:: Update this documentation with the *new APBS syntax* (see :ref:`new_input_format`).
Solvation energies are usually decomposed into a free energy cycle as shown in the free energy cycle below.
Note that such solvation energies often performed on fixed conformations; as such, they are more correctly called "potentials of mean force".
More details on using APBS for the polar and nonpolar portions of such a cycle are given in the following sections.

View File

@@ -0,0 +1,21 @@
.. _finite_element:
================================================
Finite-element Poisson-Boltzmann calculations
================================================
.. todo:: FINISH
.. todo::
Make this more user-friendly by:
* Adding introductory text with contents
* Only showing inherited members in API documentation
* Only showing undocumented members in API documentation
.. automodule:: apbs.input_file.calculate.finite_element
:members:
:undoc-members:
:inherited-members:
:show-inheritance:

View File

@@ -16,6 +16,7 @@ Calculation types
:maxdepth: 2
finite_difference
finite_element
nonpolar
-------------

View File

@@ -15,5 +15,5 @@ where ``filename`` is a string for the name of the file where a 3D grid will be
.. todo::
The PB-(S)AM ``3dmap`` keyword should not exist; please replace it ASAP with the :ref:`write` command.
The PB-(S)AM ``3dmap`` keyword should not exist; please replace it ASAP with the :ref:`old_write` command.
Documented this todo as https://github.com/Electrostatics/apbs/issues/482

View File

@@ -3,7 +3,9 @@
akeyPRE
=======
.. todo:: This command has not yet been ported to the *new APBS syntax* (see :ref:`new_input_format`).
.. currentmodule:: apbs.input_file.calculate.finite_element
.. note:: This command has been ported to :func:`FiniteElement.a_priori_refinement`.
Specifies how the initial finite element mesh should be constructed (from refinement of a very coarse 8-tetrahedron mesh prior to the solve-estimate-refine iteration in :ref:`femanual` finite element calculations.
The syntax is:

View File

@@ -3,7 +3,7 @@
akeySOLVE
=========
.. todo:: This command has not yet been ported to the *new APBS syntax* (see :ref:`new_input_format`).
.. note:: This command has been eliminated in the *new APBS syntax* (see :ref:`new_input_format`) and will not be ported.
Specifies how the the finite element mesh should be adaptively subdivided during the solve-estimate-refine iterations of a :ref:`femanual` finite element calculation.
The syntax is:

View File

@@ -3,11 +3,14 @@
bcfl
====
.. currentmodule:: apbs.input_file.calculate
.. note::
Some versions of this command have been ported to the *new APBS syntax* (see :ref:`new_input_format`):
* Finite difference boundary conditions; see :func:`apbs.input_file.calculate.finite_difference.FiniteDifference.boundary_condition`.
* Finite difference boundary conditions; see :func:`finite_difference.FiniteDifference.boundary_condition`.
* Finite element boundary conditions; see :func:`finite_element.FiniteElement.boundary_condition`.
Specifies the type of boundary conditions used to solve the Poisson-Boltzmann equation.
The syntax is:

View File

@@ -3,11 +3,14 @@
chgm
====
. currentmodule:: apbs.input_file.calculate.finite_difference
.. currentmodule:: apbs.input_file.calculate
.. note::
This command has been ported to the *new APBS syntax* (see :ref:`new_input_format`): see :func:`Focus.charge_discretization` for more information.
This command has been ported to the *new APBS syntax* (see :ref:`new_input_format`):
* For finite difference, see :func:`finite_difference.FiniteDifference.charge_discretization` for more information.
* For finite element, see :func:`finite_element.FiniteElement.charge_discretization` for more information.
Specify the method by which the biomolecular point charges (i.e., Dirac delta functions) by which charges are mapped to the grid for a multigrid (:ref:`mgmanual`, :ref:`mgauto`, :ref:`mgpara`) Poisson-Boltzmann calculation.
As we are attempting to model delta functions, the support (domain) of these discretized charge distributions is always strongly dependent on the grid spacing.

View File

@@ -7,11 +7,8 @@ dime
.. note::
Some versions of this command have been ported to the *new APBS syntax* (see :ref:`new_input_format`):
This command has been ported to the *new APBS syntax* (see :ref:`new_input_format`); see :class:`GridDimensions` for more information.
* For a focused finite difference calculation, see :func:`Focus.coarse_grid_dimensions` for more information.
.. todo:: add manual finite difference documentation.
Specifies the number of grid points per processor for grid-based discretization.
The syntax is:

View File

@@ -3,7 +3,9 @@
domainLength
============
.. todo:: This command has not yet been ported to the *new APBS syntax* (see :ref:`new_input_format`).
.. currentmodule:: apbs.input_file.calculate.finite_element
.. note:: This command has been ported to the *new APBS syntax* (see :func:`FiniteElement.domain_length`).
Specify the rectangular finite element mesh domain lengths for :ref:`femanual` finite element calculations.
This length may be different in each direction.

View File

@@ -16,5 +16,5 @@ where ``filename`` is a string for the name of the file where an OpenDX file wil
.. todo::
The PB-(S)AM ``dx`` keyword should not exist; please replace it ASAP with the :doc:`write` command.
The PB-(S)AM ``dx`` keyword should not exist; please replace it ASAP with the :ref:`old_write` command.
Documented in https://github.com/Electrostatics/apbs/issues/488

View File

@@ -3,7 +3,9 @@
ekey
====
.. todo:: This command has not yet been ported to the *new APBS syntax* (see :ref:`new_input_format`).
.. currentmodule:: apbs.input_file.calculate.finite_element
.. note:: This command has been ported to the *new APBS syntax* (see :func:`FiniteElement.error_based_refinement`).
Specify the method used to determine the error tolerance in the solve-estimate-refine iterations of the finite element solver (:ref:`femanual`).
The syntax is:

View File

@@ -3,13 +3,14 @@
etol
====
.. currentmodule:: apbs.input_file.calculate.finite_difference
.. currentmodule:: apbs.input_file.calculate
.. note::
Some versions of this command have been ported to the *new APBS syntax* (see :ref:`new_input_format`):
* For a finite difference calculation, see :func:`Focus.coarse_grid_dimensions` for more information.
* For a finite difference calculation, see :func:`finite_difference.FiniteDifference.error_tolerance`.
* For a finite element calculation, see :func:`finite_element.FiniteElement.error_tolerance`.
.. todo:: add documentation links for other instances.

View File

@@ -3,7 +3,9 @@
fe-manual
=========
.. todo:: This command has not yet been ported to the *new APBS syntax* (see :ref:`new_input_format`).
.. currentmodule:: apbs.input_file.calculate.finite_element
.. note:: This command has been ported to the *new APBS syntax* (see :ref:`new_input_format`); see :class:`FiniteElement` for more information.
Manually-configured adaptive finite element Poisson-Boltzmann calculations.

View File

@@ -3,7 +3,9 @@
gcent
======
.. todo:: This command has not yet been ported to the *new APBS syntax* (see :ref:`new_input_format`).
.. currentmodule:: apbs.input_file.calculate.finite_difference
.. note:: This command has been ported to the *new APBS syntax* (see :ref:`new_input_format`); see :class:`GridCenter` for more information.
Specify the center of the grid based on a molecule's center or absolute coordinates :ref:`mgmanual` multigrid calculations.
The syntax is:

View File

@@ -3,8 +3,13 @@
glen
====
.. todo:: This command has not yet been ported to the *new APBS syntax* (see :ref:`new_input_format`).
.. currentmodule:: apbs.input_file.calculate.finite_difference
.. note::
This command has been ported to the *new APBS syntax* (see :ref:`new_input_format`); see :class:`GridDimensions` for more information.
Specify the mesh domain lengths for multigrid :ref:`mgmanual` calculations.
These lengths may be different in each direction.
The syntax is:

View File

@@ -26,6 +26,6 @@ Specify the filename and location of a 2D cross sectional potential to be writte
.. todo::
The PB-(S)AM ``grid2d`` keyword should not exist; please replace it ASAP with the :ref:`write` command.
The PB-(S)AM ``grid2d`` keyword should not exist; please replace it ASAP with the :ref:`old_write` command.
Documented in https://github.com/Electrostatics/apbs/issues/493

View File

@@ -5,9 +5,13 @@ ion
.. note::
.. currentmodule:: apbs.input_file.calculate.generic
.. currentmodule:: apbs.input_file.calculate
This command has been ported to the *new APBS syntax* (see :ref:`new_input_format`); see :class:`MobileIons` for more information.
This command has been ported to the *new APBS syntax* (see :ref:`new_input_format`); see:
* General information about this object: :class:`generic.MobileIons` for more information.
* Finite difference implementation: :func:`finite_difference.FiniteDifference.ions`.
* Finite element implementation: :func:`finite_element.FiniteElement.ions`.
Specify the bulk concentrations of mobile ion species present in the system.
This command can be repeated as necessary to specify multiple types of ions; however, only the largest ionic radius is used to determine the ion-accessibility function.

View File

@@ -3,16 +3,15 @@
lpbe
====
.. currentmodule:: apbs.input_file.calculate
.. note::
Some aspects of this command have been moved to the *new APBS syntax* (see :ref:`new_input_format`):
* Finite difference:
* Finite difference: see :func:`finite_difference.FiniteDifference.equation` for more information.
.. currentmodule:: apbs.input_file.calculate.finite_difference
See :func:`FiniteDifference.equation` for more information.
* Finite element: see :func:`finite_element.FiniteElement.equation` for more information.
.. todo:: port for other types of calculations.

View File

@@ -3,18 +3,19 @@
lrpbe
=====
.. currentmodule:: apbs.input_file.calculate
.. note::
Some aspects of this command have been moved to the *new APBS syntax* (see :ref:`new_input_format`):
* Finite difference:
* Finite difference: see :func:`finite_difference.FiniteDifference.equation` for more information.
.. currentmodule:: apbs.input_file.calculate.finite_difference
See :func:`FiniteDifference.equation` for more information.
* Finite element: see :func:`finite_element.FiniteElement.equation` for more information.
.. todo:: port for other types of calculations.
Specifies that the linear form of the regularized Poisson-Boltzmann equation (RPBE) should be solved.
The regularized PBE equation replaces the point charge distribution with the corresponding Green's function.
As a result of this replacement, the solution corresponds to the reaction field instead of the total potential; the total potential can be recovered by adding the appropriate Coulombic terms to the solution.

View File

@@ -3,7 +3,9 @@
maxsolve
========
.. todo:: This command has not yet been ported to the *new APBS syntax* (see :ref:`new_input_format`).
.. currentmodule:: apbs.input_file.calculate.finite_element
.. note:: This command has been ported to the *new APBS syntax* (see :ref:`new_input_format`); see :func:`FiniteElement.maximum_refinement_iterations`.
Specify the number of times to perform the solve-estimate-refine iteration of the finite element solver (:ref:`femanual`).
The syntax is:

View File

@@ -3,7 +3,9 @@
maxvert
=======
.. todo:: This command has not yet been ported to the *new APBS syntax* (see :ref:`new_input_format`).
.. currentmodule:: apbs.input_file.calculate.finite_element
.. note:: This command has been ported to the *new APBS syntax* (see :ref:`new_input_format`); see :func:`FiniteElement.maximum_vertices`.
Specify the maximum number of vertices to allow during solve-estimate-refine cycle of finite element solver (:ref:`femanual`).
This places a limit on the memory that can be used by the solver.

View File

@@ -3,15 +3,15 @@
npbe
====
.. currentmodule:: apbs.input_file.calculate
.. note::
Some aspects of this command have been moved to the *new APBS syntax* (see :ref:`new_input_format`):
* Finite difference:
* Finite difference: see :func:`finite_difference.FiniteDifference.equation` for more information.
.. currentmodule:: apbs.input_file.calculate.finite_difference
See :func:`FiniteDifference.equation` for more information.
* Finite element: see :func:`finite_element.FiniteElement.equation` for more information.
.. todo:: port for other types of calculations.

View File

@@ -3,15 +3,15 @@
nrpbe
=====
.. currentmodule:: apbs.input_file.calculate
.. note::
Some aspects of this command have been moved to the *new APBS syntax* (see :ref:`new_input_format`):
* Finite difference:
* Finite difference: see :func:`finite_difference.FiniteDifference.equation` for more information.
.. currentmodule:: apbs.input_file.calculate.finite_difference
See :func:`FiniteDifference.equation` for more information.
* Finite element: see :func:`finite_element.FiniteElement.equation` for more information.
.. todo:: port for other types of calculations.

View File

@@ -3,7 +3,9 @@
ofrac
=====
.. todo:: This command has not yet been ported to the *new APBS syntax* (see :ref:`new_input_format`).
.. currentmodule:: apbs.input_file.calculate.finite_difference
.. note:: This command has been ported to the *new APBS syntax* (see :ref:`new_input_format`); see :func:`ParallelFocus.overlap_fraction`.
Specify the amount of overlap to include between the individual processors meshes in a parallel focusing calculation (:ref:`mgpara`).
The syntax is:

View File

@@ -3,13 +3,14 @@
pdie
====
.. currentmodule:: apbs.input_file.calculate
.. note::
Some versions of this command have been ported to the *new APBS syntax* (see :ref:`new_input_format`):
.. currentmodule:: apbs.input_file.calculate.finite_difference
* Finite difference Poisson-Boltzmann calculations: see :func:`FiniteDifference.solute_dielectric` for more information.
* Finite difference Poisson-Boltzmann calculations: see :func:`finite_difference.FiniteDifference.solute_dielectric` for more information.
* Finite element Poisson-Boltzmann calculations: see :func:`finite_element.FiniteElement.solute_dielectric` for more information.
.. todo:: port for other calculation types

View File

@@ -3,7 +3,10 @@
pdime
=====
.. todo:: This command has not yet been ported to the *new APBS syntax* (see :ref:`new_input_format`).
.. currentmodule:: apbs.input_file.calculate.finite_difference
.. note:: This command has been ported to the *new APBS syntax* (see :ref:`new_input_format`); see :func:`ParallelFocus.processor_array`.
Specify the processor array to be used in a parallel focusing (:ref:`mgpara`) calculation.
The syntax is:

View File

@@ -3,13 +3,15 @@
sdie
====
.. currentmodule:: apbs.input_file.calculate
.. note::
Some versions of this command have been ported to the *new APBS syntax* (see :ref:`new_input_format`):
.. currentmodule:: apbs.input_file.calculate.finite_difference
* Finite difference Poisson-Boltzmann calculations: see :func:`FiniteDifference.solvent_dielectric` for more information.
* Finite difference Poisson-Boltzmann calculations: see :func:`finite_difference.FiniteDifference.solvent_dielectric` for more information.
* Finite element Poisson-Boltzmann calculations: see :func:`finite_element.FiniteElement.solvent_dielectric` for more information.
.. todo:: port for other calculation types

View File

@@ -3,16 +3,14 @@
srfm (elec)
===========
.. currentmodule:: apbs.input_file.calculate
.. note::
.. currentmodule:: apbs.input_file.calculate
Some uses of this command have been ported to the *new APBS syntax*
(see :ref:`new_input_format`):
Some uses of this command have been ported to the *new APBS syntax* (see :ref:`new_input_format`):
* Finite differences; see :func:`finite_difference.FiniteDifference` for more information
.. todo:: port other versions of ``srfm`` to new syntax.
* Finite differences; see :func:`finite_difference.FiniteDifference.surface_method` for more information
* Finite elements; see :func:`finite_element.FiniteElement.surface_method` for more information
Specify the model used to construct the dielectric and ion-accessibility coefficients.
The syntax for this command is:

View File

@@ -3,7 +3,11 @@
targetRes
=========
.. todo:: This command has not yet been ported to the *new APBS syntax* (see :ref:`new_input_format`).
.. currentmodule:: apbs.input_file.calculate.finite_element
.. note::
This command has been ported to the *new APBS syntax* (see :ref:`new_input_format`); see :func:`FiniteElement.initial_mesh_resolution`.
Specify the target resolution of the simplices in a finite element mesh (:ref:`femanual`).
The syntax is:

View File

@@ -5,11 +5,9 @@ usemap
.. note::
.. currentmodule:: apbs.input_file.calculate.finite_difference
.. currentmodule:: apbs.input_file.calculate.generic
Some instances of this keyword have been ported to the *new APBS syntax* (see :ref:`new_input_format`):
* Finite difference calculations: see :class:`UseMap`
Some instances of this keyword have been ported to the *new APBS syntax* (see :ref:`new_input_format`); see :class:`UseMap`
.. todo:: Port other uses to new syntax.

View File

@@ -1,9 +1,16 @@
.. _write:
.. _old_write:
write
=====
.. todo:: This command has not yet been ported to the *new APBS syntax* (see :ref:`new_input_format`).
.. currentmodule:: apbs.input_file.calculate
.. note::
This command has been ported to the *new APBS syntax* (see :ref:`new_input_format`); see :class:`generic.WriteMap` and specific functions for different calculations:
* Finite differences; see :func:`finite_difference.write_atom_potentials`.
* Finite elements; see :func:`finite_elements.write_atom_potentials`.
This controls the output of scalar data calculated during the Poisson-Boltzmann run.
This keyword can be repeated several times to provide various types of data output from APBS.

View File

@@ -3,15 +3,18 @@
calcenergy
==========
.. currentmodule:: apbs.input_file.calculate
.. note::
Some versions of this command have been ported to the *new APBS syntax* (see :ref:`new_input_format`):
* Nonpolar calculations:
.. currentmodule:: apbs.input_file.calculate.nonpolar
* Nonpolar calculations: see :func:`nonpolar.Nonpolar.calculate_energy` for more information.
* Polar calculations:
See :func:`Nonpolar.calculate_energy` for more information.
* Finite difference: see :func:`finite_difference.FiniteDifference.calculate_energy`
* Finite element: see :func:`finite_element.FiniteElement.calculate_energy`
This optional keyword controls energy output from an apolar solvation calculation.
The syntax is:

View File

@@ -3,15 +3,18 @@
calcforce
=========
.. currentmodule:: apbs.input_file.calculate
.. note::
Some versions of this command have been ported to the *new APBS syntax* (see :ref:`new_input_format`):
* Nonpolar calculations:
.. currentmodule:: apbs.input_file.calculate.nonpolar
* Nonpolar calculations: see :func:`nonpolar.Nonpolar.calculate_forces` for more information.
* Polar calculations:
See :func:`Nonpolar.calculate_forces` for more information.
* Finite difference: see :func:`finite_difference.FiniteDifference.calculate_forces`
* Finite element: see :func:`finite_element.FiniteElement.calculate_forces`
This optional keyword controls energy output from an apolar solvation calculation.
The syntax is:

View File

@@ -11,6 +11,7 @@ srad
* Nonpolar calculations: see :func:`nonpolar.Nonpolar.solvent_radius` for more information.
* Finite-difference Poisson-Boltzmann calculations: see :func:`finite_difference.FiniteDifference.solvent_radius` for more information.
* Finite-element Poisson-Boltzmann calculations: see :func:`finite_element.FiniteElement.solvent_radius` for more information.
This keyword specifies the radius of the solvent molecules; this parameter is used to define various solvent-related surfaces and volumes (see :ref:`elecsrfm`).
This value is usually set to 1.4 Å for a water-like molecular surface and set to 0 Å for a van der Waals surface.

View File

@@ -3,13 +3,15 @@
swin
====
.. currentmodule:: apbs.input_file.calculate
.. note::
.. currentmodule:: apbs.input_file.calculate.finite_difference
Some instances of this keyword have been moved to the *new APBS syntax* (see :ref:`new_input_format`):
* For finite difference calculations, see :func:`FiniteDifference.surface_spline_window`
* For finite difference calculations, see :func:`finite_difference.FiniteDifference.surface_spline_window`
* For finite element calculations, see :func:`finite_element.FiniteElement.surface_spline_window`
.. todo:: move other instances of this keyword to the new syntax

View File

@@ -9,8 +9,9 @@ temp
.. currentmodule:: apbs.input_file.calculate
* Finite difference calculations: See :func:`finite_difference.FiniteDifference.temperature`.
* Nonpolar calculations: See :func:`nonpolar.Nonpolar.temperature`.
* Finite-difference Poisson-Boltzmann calculations: See :func:`finite_difference.FiniteDifference.temperature`.
* Finite-element Poisson-Boltzmann calculations: See :func:`finite_element.FiniteElement.temperature`.
.. todo:: add other uses to new syntax

View File

@@ -29,7 +29,7 @@ charge
This command allows APBS to read the fixed (molecular) charge density function mapped to a mesh.
The inputs are maps of charge densities; these values have units of e\ :sub:`c` Å\ :sup:`-3`, where e\ :sub:`c` is the electron charge.
In general, this command will read charge-maps written by :ref:`elec` :ref:`write` commands.
In general, this command will read charge-maps written by :ref:`elec` :ref:`old_write` commands.
The syntax of this command is:
.. code-block:: bash
@@ -57,7 +57,7 @@ diel
This command allows APBS to read the dielectric function mapped to 3 meshes shifted by one-half grid spacing in the x, y, and z directions.
The inputs are maps of dielectric variables between the solvent and biomolecular dielectric constants; these values are unitless.
In general, this command will read dielectric maps written by by :ref:`elec` :ref:`write` commands.
In general, this command will read dielectric maps written by by :ref:`elec` :ref:`old_write` commands.
The syntax of this command is:
.. code-block:: bash
@@ -92,7 +92,7 @@ kappa
This command allows APBS to read the ion-accessibility function mapped to a mesh.
The inputs are maps of ion accessibility values which range between 0 and the build Debye-Hückel screening parameter; these values have units of Å\ :sup:`-2`.
In general, this command will read kappa-maps written by by :ref:`elec` :ref:`write` commands.
In general, this command will read kappa-maps written by by :ref:`elec` :ref:`old_write` commands.
The syntax of this command is:
.. code-block:: bash
@@ -176,7 +176,7 @@ pot
This command allows APBS to read the electrostatic potential mapped to a mesh.
The inputs are maps of the electrostatic potential from a previous calculation.
In general, this command will read potential-maps written by by :ref:`elec` :ref:`write` commands.
In general, this command will read potential-maps written by by :ref:`elec` :ref:`old_write` commands.
The syntax of this command is:
.. code-block:: bash

View File

@@ -2,6 +2,8 @@
Conversion utilities
--------------------
.. todo:: Update this documentation with the *new APBS syntax* (see :ref:`new_input_format`).
^^^^^^^^^^^^^^^
amber2charmm.sh
^^^^^^^^^^^^^^^
@@ -133,7 +135,7 @@ Found in :file:`tools/mesh`
mgmesh
^^^^^^
Prints out acceptable combinations of :doc:`input/elec/nlev` and :doc:`input/elec/dime` for multigrd calculations.
Prints out acceptable combinations of :doc:`input/old/elec/nlev` and :doc:`input/old/elec/dime` for multigrd calculations.
Found in :file:`tools/mesh`
^^^^^^^^^^