#!/usr/local/bin/env python

#=============================================================================================
# MODULE DOCSTRING
#=============================================================================================

"""
Validation tests for ensuring correctness of forcefield implementations.

DESCRIPTION

This module provides a facility for energy minimization algorithms that use iterative calls
to OpenMM to compute the force.  As such, it will not be as fast as optimization methods
implemented as OpenMM integrators, but it will be more flexible.

COPYRIGHT AND LICENSE

@author John D. Chodera <jchodera@gmail.com>

All code in this repository is released under the GNU General Public License.

This program is free software: you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation, either version 3 of the License, or (at your option) any later
version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.  See the GNU General Public License for more details.
 
You should have received a copy of the GNU General Public License along with
this program.  If not, see <http://www.gnu.org/licenses/>.

"""

#=============================================================================================
# GLOBAL IMPORTS
#=============================================================================================

import os
import math
import numpy
import copy
import time

import simtk.chem.openmm as openmm
import simtk.unit as units

import scipy.optimize

#=============================================================================================
# REVISION CONTROL
#=============================================================================================

__version__ = "$Revision$" # TODO: Fix me for svn.

#=============================================================================================
# MODULE CONSTANTS
#=============================================================================================

#=============================================================================================
# Exceptions
#=============================================================================================

class NotImplementedException(Exception):
    """
    Exception denoting that the requested feature has not yet been implemented.

    """

class ParameterException(Exception):
    """
    Exception denoting that a parameter has been incorrectly furnished.

    """
    
#=============================================================================================
# MAIN AND TESTS
#=============================================================================================

if __name__ == "__main__":    
    # Create test system.
    import testsystems
    [system, coordinates] = testsystems.LennardJonesFluid()
    #[system, coordinates] = testsystems.KobAndersen()
    # Perturb coordinates
    coordinates = units.Quantity(coordinates / units.angstrom + numpy.random.randn(system.getNumParticles(),3) * 5.0, units.angstrom)
    # Initialize a gradient descent minimizer with default options.
    minimizer = BFGSMinimizer(system, verbose=True)
    # Minimize the initial coordinates.
    minimized_coordinates = minimizer.minimize(coordinates)
    # Clean up to release the Context.
    del minimizer

    import doctest
    doctest.testmod()
