Skip to the content.

The Functional class, found in surfpack/Functional.py, is the core of SurfPack Density Functional Theory. This is the interface to almost all practical computations, such as computation of surface tensions, adsorbtion, etc. and also contains the interfaces to methods used for computing density profiles in systems with various boundary conditions. All DFT models in SurfPack inherit the Functional class.

Table of contents

Profile property interfaces

Compute properties using a given density profile. Note that properties computed using these methods do not generally check whether the Profile is a valid equilibrium Profile. Properties are computed from the Profile as is. For methods to compute equilibrium density profiles, see the Density Profile section. For methods that implicitly compute the density profile for given boundary conditions before computing a property see rho-T properties.

Table of contents

N_adsorbed(self, rho, T=None, dividing_surface='e')

Compute the adsorbtion of each on the interface in a given density profile

Args:

     rho (list[Profile]) :

          The density profile for each component [1 / Å^3]

     T (float) :

          Temperature [K], only required if dividing_surface is ‘t’ or ‘tension’

     dividing_surface (str) :

          The dividing surface to use:

          ‘e’ or ‘equimolar’ for equimolar surface

          ‘t’ or ‘tension’ for surface of tension

         

Returns:

     1D array :

          The adsobtion of each component [1 / Å^2]

         

adsorbtion(self, rho, T=None, dividing_surface='e')

Compute the adsorbtion of each on the interface in a given density profile.

Args:

     rho (list[Profile]) :

          The density profile for each component [1 / Å^3]

     T (float) :

          Temperature [K], only required if dividing_surface is ‘t’ or ‘tension’

     dividing_surface (str) :

          The dividing surface to use:

          ‘e’ or ‘equimolar’ for equimolar surface

          ‘t’ or ‘tension’ for surface of tension

         

Returns:

     1D array :

          The adsobtion of each component [1 / Å^2]

         

correlation(self, rho, T)

Compute the one-body correlation function (sec. 4.2.3 in “introduction to DFT”)

Args:

     rho (list[Profile]) :

          Density profiles [particles / Å^3]

     T (float) :

          Temperature [K]

         

Returns:

     list[Profile] :

          One body correlation function of each species as a function of position,

          indexed as c[][]

         

grand_potential(self, rho, T, Vext=None, bulk=False, property_flag='IR')

Compute the Grand Potential, as defined in sec. 2.7 of R. Roth - Introduction to Density Functional Theory of Classical Systems: Theory and Applications.

Args:

     rho (list[Profile] or Iterable[float]) :

          The density profile for each component,

          or the bulk density of each component [particles / Å^3]

     T (float) :

          Temperature [K]

     Vext (list[callable] or callable) :

          External potential for each component, it is recomended to use the

          callables inherriting ExtPotential in external_potential.py. Defaults to None.

     bulk (bool) :

          Is this a bulk computation? Defaults to False. Note: For bulk computations, the grand

          potential density [J / Å^3] is returned.

     property_flag (str) :

          Return Residual (‘R’), Ideal (‘I’) or total (‘IR’) grand potential

Returns:

     float :

          The Grand Potential [J]. NOTE: For bulk computations, the grand potential

          density (which is equal to the bulk pressure) [J / Å^3] is returned.

         

grand_potential_density(self, rho, T, Vext=None, property_flag='IR')

Compute the Grand Potential density.

Args:

     rho (list[Profile] or Iterable[float]) :

          The density profile for each component,

          or the bulk density of each component [particles / Å^3]

     T (float) :

          Temperature [K]

     Vext (list[callable] or callable) :

          External potential for each component, it is recomended to use the

          callables inherriting ExtPotential in external_potential.py. Defaults to None.

     property_flag (str) :

          Return Residual (‘R’), Ideal (‘I’) or total (‘IR’) grand potential density

          Returns

     Profile :

          The Grand Potential density [J / Å^3].

         

reduced_helmholtz_energy_density(self, *args, **kwargs)

Returns the reduced, residual helmholtz energy density, $\phi$ (i.e. the integrand of eq. 3.4 in “introduction to DFT”)

          \(\phi = \\frac{a^{res}}{k_B T}\)

         

          where $a^{res}$ is the residual helmholtz energy density (per particle), in [J Å$^{-3}$]

         

residual_enthalpy_density(self, rho, T)

Compute the residual enthalpy density [J / Å^3]

Args:

     rho (list[Profile]) :

          The density profile for each component [particles / Å^3]

     T (float) :

          Temperature [K]

Returns:

     Profile :

          The residual enthalpy density [J / Å^3]

         

residual_entropy_density(self, rho, T)

Compute the residual entropy density [J / Å^3 K]

Args:

     rho (list[Profile]) :

          The density profile for each component [particles / Å^3]

     T (float) :

          Temperature [K]

Returns:

     Profile :

          The residual entropy density [J / Å^3 K]

         

residual_helmholtz_energy_density(self, rho, T, bulk=False)

Compute the residual Helmholtz energy density [J / Å^3]

Args:

     rho (list[Profile] or 1d array [float]) :

          The density profile or bulk density for each component [particles / Å^3]

     T (float) :

          Temperature [K]

     bulk (bool) :

          Whether to compute for bulk phase

Returns:

     Profile or float:

          The residual Helmholtz energy density [J / Å^3]

         

residual_internal_energy_density(self, rho, T)

Compute the residual internal energy density [J / Å^3]

Args:

     rho (list[Profile]) :

          The density profile for each component [particles / Å^3]

     T (float) :

          Temperature [K]

Returns:

     Profile :

          The residual internal energy density [J / Å^3]

         

surface_tension(self, rho, T, Vext=None, dividing_surface='equimolar')

Compute the surface tension for a given density profile Args: rho (list[Profile]) : Density profile for each component [particles / Å^3] T (float) : Temperature [K] Vext (list[callable], optional) : External potential dividing_surface (str, optional) : Which deviding surface to use ‘e’ or ‘equimolar’ for Equimolar surface ‘t’ or ‘tension’ for Surface of tension Returns: float : Surface tension [J / Å^2]

         

tolmann_length(self, rho, T)

Compute the Tolmann length, given a density profile.

Args:

     rho (list[Profile]) :

          The density profile of each species.

     T (float) :

          Temperature [K]

         

Returns:

     float :

          The Tolmann lenth

         

$\rho - T$ property interfaces

Compute properties at a given density and temperature, ususally by first computing a density profile for the given state.

Table of contents

adsorbtion_isotherm(self, T, n_points=30, dividing_surface='t', x_min=0.001, x_max=0.999, solver=None, rho0=None, calc_lve=False, verbose=False)

Compute the adsorbtion as a function of molar composition along an isotherm

Args:

     T (float) :

          Temperature [K]

     n_points (int) :

          Number of (evenly distriubted) points to compute. If an array is supplied, those points are used instead.

     dividing_surface (str, optional) :

          ‘t’ or ‘tension’ for surface of tension, ‘e’ or ‘equimolar’ for equimolar surface

     x_min (float, optional) :

          Minimum liquid mole fraction of the first component.

     x_max (float, optional) :

          Maximum liquid mole fraction of the first component.

     solver (SequentialSolver, optional) :

          Custom solver object to use

     rho0 (list[Profile], optional) :

          Initial guess for denisty profile at x = [0, 1]

     calc_lve (bool, optional) :

          If true, return a tuple (x, y, p) with pressure (p), liquid (x) and vapour (y) composition. If false, return only liquid composition.

     verbose (int, optional) :

          Print progress information, higher number gives more output, default 0

         

          Returns

     tuple(gamma, x) or tuple(gamma, lve) :

          Adsorbtion and composition (of first component)

         

radial_distribution_functions(self, rho_b, T, comp_idx=0, grid=None)

Compute the radial distribution functions $g_{i,j}$ for $i =$ comp_idx using the “Percus trick”. To help convergence: First converge the profile for a planar geometry, exposed to an ExtendedSoft potential with a core radius $5R$, where $R$ is the maximum characteristic_length of the mixture. Then, shift that profile to the left, and use it as an initial guess for the spherical case. If that doesn’t work, the profile can be shifted in several steps (by gradually reducing the core radius of the ExtendedSoft potential). The latter possibility is not implemented, but is just a matter of putting the “shift and recompute” part of this method in a for-loop, and adding some appropriate kwargs.

Args:

     rho_b (list[float]) :

          The bulk densities [particles / Å^3]

     T (float) :

          Temperature [K]

     comp_idx (int) :

          The first component in the pair, defaults to the first component

     grid (Grid) :

          The spatial discretisation (should have Spherical geometry for results to make sense)

Returns:

     list[Profile] :

          The radial distribution functions around a particle of type comp_idx

         

surface_tension_isotherm(self, T, n_points=30, dividing_surface='t', solver=None, rho0=None, calc_lve=False, verbose=False, cache_dir='')

Compute the surface tension as a function of molar composition along an isotherm

Args:

     T (float) :

          Temperature [K]

     n_points (int) :

          Number of (evenly distriubted) points to compute. If an array is supplied, those points are used instead.

     dividing_surface (str, optional) :

          ‘t’ or ‘tension’ for surface of tension, ‘e’ or ‘equimolar’ for equimolar surface

     solver (SequentialSolver, optional) :

          Custom solver object to use

     rho0 (list[Profile], optional) :

          Initial guess for denisty profile at x = [0, 1]

     calc_lve (bool, optional) :

          If true, return a tuple (x, y, p) with pressure (p), liquid (x) and vapour (y) composition. If false, return only liquid composition.

     verbose (int, optional) :

          Print progress information, higher number gives more output, default 0

         

          Returns

     tuple(gamma, x) or tuple(gamma, lve) :

          Surface tension and composition (of first component)

         

Density profile interfaces

Methods for converging a density profile given various boundary conditions.

Table of contents

density_profile_singlecomp(self, T, grid, rho_0=None, solver=None, verbose=False)

Compute the equilibrium density profile across a gas-liquid interface. For multicomponent systems, twophase_tpflash is used to compute the composition of the two phases. For single component systems, p is ignored, and pressure is computed from dew_pressure.

Args:

     T (float) :

          Temperature [K]

     grid (Grid) :

          Spatial discretisation

     rho_0 (list[Profile], optional) :

          Initial guess for density profile

     solver (SequentialSolver or GridRefiner) :

          Solver to use, uses a default SequentialSolver if none is supplied

     verbose (bool, optional) :

          Whether to print progress info

Returns:

     list[Profile] :

          The density profile for each component across the interface.

         

density_profile_tp(self, T, p, z, grid, rho_0=None, solver=None, verbose=False)

Compute the equilibrium density profile across a gas-liquid interface. For multicomponent systems, twophase_tpflash is used to compute the composition of the two phases. For single component systems, p is ignored, and pressure is computed from dew_pressure.

Args:

     T (float) :

          Temperature [K]

     p (float) :

          Pressure [Pa]

     z (Iterable) :

          Total Molar composition

     grid (Grid) :

          Spatial discretisation

     rho_0 (list[Profile], optional) :

          Initial guess for density profile

     solver (SequentialSolver or GridRefiner) :

          Solver to use, uses a default SequentialSolver if none is supplied

     verbose (bool, optional) :

          Whether to print progress info

Returns:

     list[Profile] :

          The density profile for each component across the interface.

         

density_profile_twophase(self, rho_g, rho_l, T, grid, beta_V=0.5, rho_0=None, solver=None, verbose=0)

Compute the density profile separating two phases with denisties rho_g and rho_l

Args:

     rho_g (list[float]) :

          Density of each component in phase 1 [particles / Å^3]

     rho_l (list[float]) :

          Density of each component in phase 2 [particles / Å^3]

     beta_V (float) :

          Liquid fraction

     T (float) :

          Temperature [K]

     grid (Grid or GridSpec) :

          The spacial discretisation. Using a GridSpec is preferred, as the method then generates a

          grid that is likely to be a suitable width.

     rho_0 (list[Profile], optional) :

          Initial guess, optional

     solver (SequentialSolver or GridRefiner) :

          Solver to use, uses a default SequentialSolver if none is supplied

     verbose (bool, options) :

          Print progress info while running solver

         

Returns:

     list[Profile] :

          The density profile for of each component

         

density_profile_tz(self, T, z, grid, z_phase=1, rho_0=None, solver=None, verbose=0)

Compute the density profile separating two phases at temperature T, with liquid (or optionally vapour) composition x

Args:

     T (float) :

          Temperature [K]

     z (ndarray[float]) :

          Molar composition of liquid phase (unless x_phase=2)

     grid (Grid or GridSpec) :

          The spatial discretization

     z_phase (int) :

          ThermoPack Phase flag, indicating which phase has composition x. x_phase=1 for liquid (default)

          x_phase=2 for vapour.

     rho_0 (list[Profile], optional) :

          Initial guess

     solver (SequentialSolver or GridRefiner, optional) :

          Solver to use

     verbose (int) :

          Print debugging information (higher number gives more output), default 0

         

Returns:

     list[Profile] :

          The converged density profiles.

         

density_profile_wall(self, rho_b, T, grid, Vext=None, rho_0=None, verbose=False)

Calculate equilibrium density profile for a given external potential Note: Uses lazy evaluation for (rho_b, T, x, grid, Vext) to return a copy of previous result if the same calculation is done several times.

Args:

     rho_b (list[float]) :

          The bulk densities [particles / Å^3]

     T (float) :

          Temperature [K]

     grid (Grid) :

          Spatial discretization

     Vext (ExtPotential, optional) :

          External potential as a function of position (default : Vext(r) = 0)

     Note:

          Must be hashable, to use with lazy evaluation

     Recomended:

          Use the callable classes inherriting ExtPotential

     rho_0 (list[Profile], optional) :

          Initial guess for density profiles.

     verbose (bool) :

          Print progression information during run

Returns:

     list[Profile] :

          The equilibrium density profiles

         

density_profile_wall_tp(self, T, p, z, grid, Vext, rho0=None, verbose=0)

Calculate equilibrium density profile for a given external potential

Args:

     T (float) :

          Temperature [K]

     p (float) :

          Pressure [Pa]

     z (list[float]) :

          Bulk composition

     grid (Grid) :

          Spatial discretization

     Vext (ExtPotential, optional) :

          External potential as a function of position (default : Vext(r) = 0)

     Note:

          Must be hashable, to use with lazy evaluation

     Recomended:

          Use the callable classes inherriting ExtPotential

     rho0 (list[Profile], optional) :

          Initial guess for density profiles.

     verbose (bool) :

          Print progression information during run

Returns:

     list[Profile] :

          The equilibrium density profiles

         

drubble_profile_rT(self, rho_i, rho_o, T, r, grid, rho_0=None)

Compute the density profile across the interface of a droplet or bubble (drubble).

Args:

     rho_i (list[float]) :

          The particle densities inside the drubble.

     rho_o (list[float]) :

          The particle densities outside the drubble.

     T (float) :

          Temperature [K]

     r (float) :

          Drubble radius [Å]

     grid (Grid) :

          The grid to use (must have Geometry.SPHERICAL)

     rho_0 (list[Profile], optional) :

          Initial guess

         

Returns:

     list[Profile] :

          The density profiles across the interface.

         

Bulk property interfaces

Evaluating bulk properties.

Table of contents

chemical_potential(self, rho, T, bulk=True, property_flag='IR')

Compute the chemical potential [J]

Args:

     rho (list[float]) :

          Density [particles / Å^3]

     T (float) :

          Temperature [K]

     bulk (bool) :

          Only True is implemented

     property_flag (str, optional) :

          ‘I’ for ideal, ‘R’ for residual, ‘IR’ for total.

         

Returns:

     1d array (float) :

          The chemical potentials [J / particle]

         

fugacity(self, rho, T, Vext=None)

Compute the fugacity at given density and temperature

Args:

     rho (list[float]) :

          Particle density of each species

     T (flaot) :

          Temperature [K]

     Vext (ExternalPotential, optional) :

          External potential for each particle

         

Returns:

     1d array (flaot) :

          The fugacity of each species.

         

residual_chemical_potential(self, rho, T, bulk=True)

Compute the residual chemical potential [J]

Args:

     rho (list[float]) :

          Density [particles / Å^3]

     T (float) :

          Temperature [K]

     bulk (bool) :

          Only True is implemented

         

Returns:

     1d array (float) :

          The chemical potentials [J / particle]

         

Pure fluid properties

Methods to efficiently and conveninetly compute properties for pure fluids. Contain some optimisations, tuning and convenience factors that are only possible for pure fluids.

Table of contents

surface_tension_singlecomp(self, n_points=30, t_min=0.5, t_max=0.99, grid=None, solver=None, rho0=None, verbose=0)

Compute the surface tension of a pure component for a series of temperatures.

Args:

     n_points (int) :

          Number of points to compute

     t_min (float) :

          Start temperature, if 0 < t_min < 1, start temperature will be t_min * Tc, where Tc is the critical temperature.

     t_max (float) :

          Stop temperature, if 0 < t_max < 1, stop temperature will be t_max * Tc, where Tc is the critical temperature.

     grid (Grid) :

          Grid to use for initial calculation.

     solver (Solver) :

          Solver to use for all calculations

     rho0 (list[Profile]) :

          Initial guess for first density profile.

     verbose (int) :

          Larger number gives more output during progress.

         

Returns:

     tuple(gamma, T) :

          Where gamma and T are matching 1d arrays of the surface tension and temperature.

         

Weight function interfaces

Get-methods for weight functions.

Table of contents

get_weights(self, T)

Returns the weights for weighted densities in a 2D array, ordered as weight[][]. See arrayshapes.md for a description of the ordering of different arrays.

         

Weighted density computations

Compute weighted densities

Table of contents

get_weighted_densities(self, *args, **kwargs)

Compute the weighted densities, and optionally differentials

Args:

     rho (ndarray[Profile]) :

          2D array of component densities indexed as rho[][]

     bulk (bool) :

          If True, use simplified expressions for bulk - not requiring FFT

     dndrho (bool) :

          Flag to activate calculation of differential

         

Returns:

     ndarray :

          array of weighted densities indexed as n[][]

     ndarray :

          array of differentials

         

Utility methods

Methods for setting … and getting …

Table of contents

clear_cache_dir(self, clear_dir)

Clear the directory clear_dir, after prompting for confirmation.

Args:

     clear_dir (str) :

          The name of the directory.

         

Raises:

     NotADirectoryError :

          If clear_dir does not exist or is not a directory.

         

dividing_surface_position(self, rho, T=None, dividing_surface='e')

Compute the position of a dividing surface on a given density profile.

Args:

     rho (list[Profile]) :

          The density profile for each species

     T (float) :

          The temperature

     dividing_surface (str, optional) :

          Can be ‘(e)quimolar’ (default) or ‘(t)ension’.

         

Returns:

     float :

          Position of the dividing surface.

         

equimolar_surface_position(rho)

Calculate the position of the equimolar surface for a given density profile

Args:

     rho (list[Profile]) :

          The density profile for each component [1 / Å^3]

         

Returns:

     float :

          The position of the equimolar surface [Å]

         

get_caching_id(self)

Returns a unique ID for an initialized model. Should include information about the model type, components, parameters and mixing parameters (if applicable). Used for caching profiles.

Returns:

     str :

          A model identifier

         

get_characteristic_lengths(self)

Used to generate initial guesses for density profiles. Should return lengths that give an indication of molecular sizes. For example diameters of hard-spheres, or the Barker-Henderson diameter.

Returns:

     ndarray(float) :

          The characteristic length of the molecules.

         

get_load_dir(self)

Get the current directory used to search and load Profiles

Returns:

     str :

          Path to the current load directory

         

get_save_dir(self)

Get the current directory used to save Profiles

Returns:

     str :

          Path to the current save directory

         

reduce_temperature(self, T, c=0)

Reduce the temperature in some meaningful manner, using LJ units when possible, doing nothing for hard spheres.

Args:

     T (float) :

          The temperature

     c (float, optional) :

          ???

Returns:

     float :

          The reduced temperature

         

set_cache_dir(self, cache_dir)

Forwards call to self.set_load_dir and self.set_save_dir.

Args:

     cache_dir (str) :

          Name of directory save and load files in.

         

Raises:

     FileExistsError :

          If cache_dir is the name of an existing file that is not a directory.

     NotADirectoryError :

          If cache_dir does not exist after successfull call to self.set_save_dir

         

set_load_dir(self, load_dir)

Sets this model to automatically search for computed profiles in load_dir.

Args:

     load_dir (str) :

          Name of directory to load files from.

         

Raises:

     NotADirectoryError :

          If load_dir does not exist.

         

set_save_dir(self, save_dir)

Sets this model to automatically save computed density profiles in the directory ‘save_dir’.

Args:

     save_dir (str) :

          Name of directory to save to

         

Raises:

     FileExistsError :

          If save_dir is the name of an existing file that is not a directory.

         

surface_of_tension_position(self, rho, T)

Calculate the position of the surface of tension on a given density profile

Args:

     rho (list[Profile]) :

          The density profile for each component [1 / Å^3]

     T (float) :

          Temperature [K]

         

Returns:

     float :

          The position of the surface of tension [Å]

         

Internal methods

Methods for handling communication with the Fortran library.

Table of contents

__init__(self, ncomps)

Handles initialisation that is common for all functionals

Args:

     ncomps (int) :

          Number of components

         

__repr__(self)

All Functionals must implement a unique __repr__, as these are used to generate the hashes that are used when saving profiles. The __repr__ should contain a human-readable text with (at least) the name of the model and all model parameters.

         

sanitize_Vext(self, Vext)

Ensure that Vext is a tuple with the proper ammount of elements.

         

split_component_weighted_densities(self, n)

Unsure if this is still in use, but I believe it takes in fmt-weighted densities as a 1d array and returns the same densities as a 2d array.

Args:

     n (list[Profile]) :

          FMT-weighted densities

         

Returns:

     list[list[Profile]] :

          FMT-weighted densities, indexed as n[][]

     :

          return:

         

validate_composition(self, z)

Check that the composition z has length equal to number of components, and sums to one.

Args:

     z (Iterable(float)) :

          The composition

         

Raises:

     IndexError :

          If number of fractions does not match number of components.

     ValueError :

          If fractions do not sum to unity.

         

Deprecated methods

Deprecated methods are not maintained, and may be removed in the future.

Table of contents

_Functional__density_profile_twophase(self, rho_left, rho_right, T, grid, rho_0=None, constraints=None)

         

adsorbed_mean_density(self, profile)

Compute the mean density of an adsorbed film.

Args:

     profile (Profile) :

          The density profile

         

Returns:

     float :

          The mean density.

         

adsorbed_thickness(self, profile)

Find the thickness of an adsorbed film.

Args:

     profile (Profile) :

          The density profile

         

Returns:

     float :

          The thickness of the adsorbed layer.

         

density_profile_NT(self, rho1, rho2, T, grid, rho, rho_is_frac, rho_0=None)

         

density_profile_muT(self, rho1, rho2, T, grid, rho, rho_is_frac, rho_0=None)

         

find_non_bulk_idx(self, profile, rho_b, tol=0.01, start_idx=-1)

Possibly no longer working, used to find the the first index in a Profile which is no longer considered a point in the bulk phase, by checking the change in density and comparing to tol.

Args:

     profile (Profile) :

          The density profile

     rho_b (float) :

          The bulk density

     tol (float) :

          Tolerance for relative change in density within bulk.

     start_idx (int) :

          Where to start searching. If start_idx < 0, search goes “right-to-left”, otherwise “left-to-right”.

         

Returns:

     int :

          The index at which the bulk ends.

         

interface_thickness(self, profile, positions=False)

Find the thickness of an interface.

Args:

     profile (Profile) :

          The density profile

     positions (bool) :

          Also return the position where the interface starts and stops.

Returns:

     float :

          The thickness of the interface.