From dc27aa1c15cdb4bb881b1981a66558fb3932876a Mon Sep 17 00:00:00 2001 From: Lee-Ping Wang Date: Sat, 23 Nov 2019 22:45:01 -0800 Subject: [PATCH 1/7] Use gradient evaluation for Evaluator test --- devtools/conda-envs/test_env.yaml | 1 + src/optimizer.py | 2 +- src/tests/test_system.py | 384 +++++------------- .../003d_estimator_liquid_bromine/gradient.in | 66 +++ .../003d_estimator_liquid_bromine/optimize.in | 6 + .../targets.tar.gz | Bin 7418 -> 7332 bytes 6 files changed, 168 insertions(+), 291 deletions(-) create mode 100644 studies/003d_estimator_liquid_bromine/gradient.in diff --git a/devtools/conda-envs/test_env.yaml b/devtools/conda-envs/test_env.yaml index aedfa14d0..cae68ca38 100644 --- a/devtools/conda-envs/test_env.yaml +++ b/devtools/conda-envs/test_env.yaml @@ -21,6 +21,7 @@ dependencies: - swig - future - pymbar=3.0.3 + - mdtraj=1.9.1 - openmm - ambertools # The following two are not compatible with python 2.7 and 3.5, so they are conditionally installed in .travis.yml diff --git a/src/optimizer.py b/src/optimizer.py index 5321a48e6..43ef2e195 100644 --- a/src/optimizer.py +++ b/src/optimizer.py @@ -640,7 +640,7 @@ def print_progress(itn, nx, nd, ng, clr, x, std, qual): if ngd < self.convergence_gradient: logger.info("Convergence criterion reached for gradient norm (%.2e)\n" % self.convergence_gradient) ncrit += 1 - if ndx < self.convergence_step and ITERATION > self.iterinit: + if ndx < self.convergence_step and ndx >= 0.0 and ITERATION > self.iterinit: logger.info("Convergence criterion reached in step size (%.2e)\n" % self.convergence_step) ncrit += 1 if stdfront < self.convergence_objective and len(X_hist) >= self.hist: diff --git a/src/tests/test_system.py b/src/tests/test_system.py index 25b9e96f8..48c000c70 100644 --- a/src/tests/test_system.py +++ b/src/tests/test_system.py @@ -19,6 +19,12 @@ # expected results (mvals) taken from previous runs. Update this if it changes and seems reasonable (updated 01/24/14) EXPECTED_BROMINE_RESULTS = array([-0.305718, -0.12497]) +# expected objective function from 003d evaluator bromine study. (updated 11/23/19) +EXPECTED_EVALUATOR_BROMINE_OBJECTIVE = array([1000]) + +# expected gradient elements from 003d evaluator bromine study. Very large uncertainties of +/- 2500 (updated 11/23/19) +EXPECTED_EVALUATOR_BROMINE_GRADIENT = array([4000, 4000]) + # expected result (pvals) taken from ethanol GB parameter optimization. Update this if it changes and seems reasonable (updated 09/05/14) EXPECTED_ETHANOL_RESULTS = array([1.2286e-01, 8.3624e-01, 1.0014e-01, 8.4533e-01, 1.8740e-01, 6.8820e-01, 1.4606e-01, 8.3518e-01]) @@ -32,30 +38,18 @@ EXPECTED_OPENFF_TORSIONPROFILE_RESULTS = array([-9.4238e-02, 7.3350e-03, -7.9467e-05, 1.7172e-02, -1.3309e-01, 6.0076e-02, 1.7895e-02, 6.5866e-02, -1.4084e-01, -2.2906e-02]) - class ForceBalanceSystemTest(ForceBalanceTestCase): def teardown_method(self): - shutil.rmtree("result") - os.remove(self.input_file.replace('.in','.sav')) - if os.path.exists(self.input_file.replace('.in','.bak')): - shutil.rmtree(self.input_file.replace('.in','.bak')) - shutil.rmtree(self.input_file.replace('.in','.tmp')) + for fnm in [self.input_file.replace('.in','.sav')]: + if os.path.exists(fnm): + os.remove(fnm) + for dnm in [self.input_file.replace('.in','.bak'), self.input_file.replace('.in','.tmp'), "result"]: + if os.path.exists(dnm): + shutil.rmtree(dnm) super(ForceBalanceSystemTest, self).teardown_method() - -class TestWaterTutorial(ForceBalanceSystemTest): - def setup_method(self, method): - super(TestWaterTutorial, self).setup_method(method) - self.cwd = os.path.dirname(os.path.realpath(__file__)) - os.chdir(os.path.join(self.cwd, '..','..', 'studies','001_water_tutorial')) - targets = tarfile.open('targets.tar.bz2','r') - targets.extractall() - targets.close() - self.input_file='very_simple.in' - self.logger.debug("\nSetting input file to '%s'\n" % self.input_file) - - def test_water_tutorial(self): - """Check water tutorial study runs without errors""" - + + def get_objective(self): + """ Return the objective function object """ ## The general options and target options that come from parsing the input file self.logger.debug("Parsing inputs...\n") options, tgt_opts = parse_inputs(self.input_file) @@ -64,78 +58,87 @@ def test_water_tutorial(self): assert isinstance(tgt_opts, list), "Parser gave incorrect type for tgt_opts" for target in tgt_opts: assert isinstance(target, dict), "Parser gave incorrect type for target dict" - ## The force field component of the project forcefield = FF(options) assert isinstance(forcefield, FF), "Expected forcebalance forcefield object" - ## The objective function objective = Objective(options, tgt_opts, forcefield) assert isinstance(objective, Objective), "Expected forcebalance objective object" + return objective - ## The optimizer component of the project - self.logger.debug("Creating optimizer: ") - optimizer = Optimizer(options, objective, forcefield) - assert isinstance(optimizer, Optimizer), "Expected forcebalance optimizer object" - self.logger.debug(str(optimizer) + "\n") - - ## Actually run the optimizer. - self.logger.debug("Done setting up! Running optimizer...\n") - result = optimizer.Run() - self.logger.debug("\nOptimizer finished. Final results:\n") - self.logger.debug(str(result) + '\n') - msg = "\nCalculation results have changed from previously calculated values.\n If this seems reasonable, update EXPECTED_WATER_RESULTS in test_system.py with these values" - np.testing.assert_array_almost_equal(EXPECTED_WATER_RESULTS,result,decimal=0.001, err_msg=msg) - - # Fail if calculation takes longer than previously to converge - assert ITERATIONS_TO_CONVERGE >= Counter(), "Calculation took longer than expected to converge (%d iterations vs previous of %d)" %\ - (ITERATIONS_TO_CONVERGE, Counter()) - -class TestVoelzStudy(ForceBalanceSystemTest): - def setup_method(self, method): - super(TestVoelzStudy, self).setup_method(method) - cwd = os.path.dirname(os.path.realpath(__file__)) - os.chdir(os.path.join(cwd, '..', '..', 'studies', '009_voelz_nspe')) - self.input_file='options.in' - self.logger.debug("\nSetting input file to '%s'\n" % self.input_file) - - def test_voelz_study(self): - """Check voelz study runs without errors""" - + def get_optimizer(self): + """ Return the optimizer object """ ## The general options and target options that come from parsing the input file self.logger.debug("Parsing inputs...\n") options, tgt_opts = parse_inputs(self.input_file) self.logger.debug("options:\n%s\n\ntgt_opts:\n%s\n\n" % (str(options), str(tgt_opts))) - assert isinstance(options, dict), "Parser gave incorrect type for options" assert isinstance(tgt_opts, list), "Parser gave incorrect type for tgt_opts" for target in tgt_opts: assert isinstance(target, dict), "Parser gave incorrect type for target dict" - ## The force field component of the project - self.logger.debug("Creating forcefield using loaded options: ") forcefield = FF(options) - self.logger.debug(str(forcefield) + "\n") assert isinstance(forcefield, FF), "Expected forcebalance forcefield object" - ## The objective function - self.logger.debug("Creating object using loaded options and forcefield: ") objective = Objective(options, tgt_opts, forcefield) - self.logger.debug(str(objective) + "\n") assert isinstance(objective, Objective), "Expected forcebalance objective object" - ## The optimizer component of the project self.logger.debug("Creating optimizer: ") optimizer = Optimizer(options, objective, forcefield) - self.logger.debug(str(optimizer) + "\n") assert isinstance(optimizer, Optimizer), "Expected forcebalance optimizer object" + self.logger.debug(str(optimizer) + "\n") + return optimizer + def run_optimizer(self, check_result=True, check_iter=True, use_pvals=False): + optimizer = self.get_optimizer() ## Actually run the optimizer. self.logger.debug("Done setting up! Running optimizer...\n") result = optimizer.Run() - self.logger.debug("\nOptimizer finished. Final results:\n") self.logger.debug(str(result) + '\n') + ## Convert result to physical values if desired. + if use_pvals: + result = optimizer.FF.create_pvals(result) + if check_result: + msg = "\nCalculation results have changed from previously calculated values.\n " \ + "If this seems reasonable, update %s in test_system.py with these values" % self.expected_results_name + np.testing.assert_allclose(self.expected_results, result, atol=self.absolute_tolerance, err_msg=msg) + if check_iter: + # Fail if calculation takes longer than previously to converge + assert ITERATIONS_TO_CONVERGE >= Counter(), "Calculation took longer than expected to converge (%d iterations vs previous of %d)" %\ + (ITERATIONS_TO_CONVERGE, Counter()) + return result + +class TestWaterTutorial(ForceBalanceSystemTest): + def setup_method(self, method): + super(TestWaterTutorial, self).setup_method(method) + self.cwd = os.path.dirname(os.path.realpath(__file__)) + os.chdir(os.path.join(self.cwd, '..','..', 'studies','001_water_tutorial')) + targets = tarfile.open('targets.tar.bz2','r') + targets.extractall() + targets.close() + self.input_file='very_simple.in' + self.logger.debug("\nSetting input file to '%s'\n" % self.input_file) + self.expected_results_name = "EXPECTED_WATER_RESULTS" + self.expected_results = EXPECTED_WATER_RESULTS + self.absolute_tolerance = 0.005 + + def test_water_tutorial(self): + """Check water tutorial study runs without errors""" + self.run_optimizer() + + +class TestVoelzStudy(ForceBalanceSystemTest): + def setup_method(self, method): + super(TestVoelzStudy, self).setup_method(method) + cwd = os.path.dirname(os.path.realpath(__file__)) + os.chdir(os.path.join(cwd, '..', '..', 'studies', '009_voelz_nspe')) + self.input_file='options.in' + self.logger.debug("\nSetting input file to '%s'\n" % self.input_file) + + def test_voelz_study(self): + """Check voelz study runs without errors""" + self.run_optimizer(check_result=False, check_iter=False) class TestBromineStudy(ForceBalanceSystemTest): @@ -145,47 +148,13 @@ def setup_method(self, method): os.chdir(os.path.join(cwd, '..', '..', 'studies', '003_liquid_bromine')) self.input_file='optimize.in' self.logger.debug("\nSetting input file to '%s'\n" % self.input_file) + self.expected_results_name = "EXPECTED_BROMINE_RESULTS" + self.expected_results = EXPECTED_BROMINE_RESULTS + self.absolute_tolerance = 0.05 def test_bromine_study(self): """Check liquid bromine study converges to expected results""" - - ## The general options and target options that come from parsing the input file - self.logger.debug("Parsing inputs...\n") - options, tgt_opts = parse_inputs(self.input_file) - self.logger.debug("options:\n%s\n\ntgt_opts:\n%s\n\n" % (str(options), str(tgt_opts))) - - assert isinstance(options, dict), "Parser gave incorrect type for options" - assert isinstance(tgt_opts, list), "Parser gave incorrect type for tgt_opts" - for target in tgt_opts: - assert isinstance(target, dict), "Parser gave incorrect type for target dict" - - ## The force field component of the project - self.logger.debug("Creating forcefield using loaded options: ") - forcefield = FF(options) - self.logger.debug(str(forcefield) + "\n") - assert isinstance(forcefield, FF), "Expected forcebalance forcefield object" - - ## The objective function - self.logger.debug("Creating object using loaded options and forcefield: ") - objective = Objective(options, tgt_opts, forcefield) - self.logger.debug(str(objective) + "\n") - assert isinstance(objective, Objective), "Expected forcebalance objective object" - - ## The optimizer component of the project - self.logger.debug("Creating optimizer: ") - optimizer = Optimizer(options, objective, forcefield) - self.logger.debug(str(optimizer) + "\n") - assert isinstance(optimizer, Optimizer), "Expected forcebalance optimizer object" - - ## Actually run the optimizer. - self.logger.debug("Done setting up! Running optimizer...\n") - result = optimizer.Run() - - self.logger.debug("\nOptimizer finished. Final results:\n") - self.logger.debug(str(result) + '\n') - - msg="\nCalculation results have changed from previously calculated values.\n If this seems reasonable, update EXPECTED_BROMINE_RESULTS in test_system.py with these values" - np.testing.assert_allclose(EXPECTED_BROMINE_RESULTS, result, atol=0.05, err_msg=msg) + self.run_optimizer() class TestThermoBromineStudy(ForceBalanceSystemTest): def setup_method(self, method): @@ -194,46 +163,13 @@ def setup_method(self, method): os.chdir(os.path.join(cwd, '../../studies/004_thermo_liquid_bromine')) self.input_file='optimize.in' self.logger.debug("\nSetting input file to '%s'\n" % self.input_file) + self.expected_results_name = "EXPECTED_BROMINE_RESULTS" + self.expected_results = EXPECTED_BROMINE_RESULTS + self.absolute_tolerance = 0.05 def test_thermo_bromine_study(self): """Check liquid bromine study (Thermo target) converges to expected results""" - - ## The general options and target options that come from parsing the input file - self.logger.debug("Parsing inputs...\n") - options, tgt_opts = parse_inputs(self.input_file) - self.logger.debug("options:\n%s\n\ntgt_opts:\n%s\n\n" % (str(options), str(tgt_opts))) - - assert isinstance(options, dict), "Parser gave incorrect type for options" - assert isinstance(tgt_opts, list), "Parser gave incorrect type for tgt_opts" - for target in tgt_opts: - assert isinstance(target, dict), "Parser gave incorrect type for target dict" - - ## The force field component of the project - self.logger.debug("Creating forcefield using loaded options: ") - forcefield = FF(options) - self.logger.debug(str(forcefield) + "\n") - assert isinstance(forcefield, FF), "Expected forcebalance forcefield object" - - ## The objective function - self.logger.debug("Creating object using loaded options and forcefield: ") - objective = Objective(options, tgt_opts, forcefield) - self.logger.debug(str(objective) + "\n") - assert isinstance(objective, Objective), "Expected forcebalance objective object" - - ## The optimizer component of the project - self.logger.debug("Creating optimizer: ") - optimizer = Optimizer(options, objective, forcefield) - self.logger.debug(str(optimizer) + "\n") - assert isinstance(optimizer, Optimizer), "Expected forcebalance optimizer object" - - ## Actually run the optimizer. - self.logger.debug("Done setting up! Running optimizer...\n") - result = optimizer.Run() - - self.logger.debug("\nOptimizer finished. Final results:\n") - self.logger.debug(str(result) + '\n') - msg = "\nCalculation results have changed from previously calculated values.\n If this seems reasonable, update EXPECTED_BROMINE_RESULTS in test_system.py with these values" - np.testing.assert_allclose(EXPECTED_BROMINE_RESULTS, result, atol=0.05, err_msg=msg) + self.run_optimizer() class TestEvaluatorBromineStudy(ForceBalanceSystemTest): def setup_method(self, method): @@ -252,7 +188,7 @@ def setup_method(self, method): ], stdout=subprocess.PIPE, stderr=subprocess.PIPE) ## Give the server time to start. time.sleep(5) - self.input_file='optimize.in' + self.input_file='gradient.in' self.logger.debug("\nSetting input file to '%s'\n" % self.input_file) def teardown_method(self): @@ -263,45 +199,14 @@ def teardown_method(self): super(TestEvaluatorBromineStudy, self).teardown_method() def test_bromine_study(self): - """Check liquid bromine study converges to expected results""" - - ## The general options and target options that come from parsing the input file - self.logger.debug("Parsing inputs...\n") - options, tgt_opts = parse_inputs(self.input_file) - self.logger.debug("options:\n%s\n\ntgt_opts:\n%s\n\n" % (str(options), str(tgt_opts))) - - assert isinstance(options, dict), "Parser gave incorrect type for options" - assert isinstance(tgt_opts, list), "Parser gave incorrect type for tgt_opts" - for target in tgt_opts: - assert isinstance(target, dict), "Parser gave incorrect type for target dict" - - ## The force field component of the project - self.logger.debug("Creating forcefield using loaded options: ") - forcefield = FF(options) - self.logger.debug(str(forcefield) + "\n") - assert isinstance(forcefield, FF), "Expected forcebalance forcefield object" - - ## The objective function - self.logger.debug("Creating object using loaded options and forcefield: ") - objective = Objective(options, tgt_opts, forcefield) - self.logger.debug(str(objective) + "\n") - assert isinstance(objective, Objective), "Expected forcebalance objective object" - - ## The optimizer component of the project - self.logger.debug("Creating optimizer: ") - optimizer = Optimizer(options, objective, forcefield) - self.logger.debug(str(optimizer) + "\n") - assert isinstance(optimizer, Optimizer), "Expected forcebalance optimizer object" - - ## Actually run the optimizer. - self.logger.debug("Done setting up! Running optimizer...\n") - result = optimizer.Run() - - self.logger.debug("\nOptimizer finished. Final results:\n") - self.logger.debug(str(result) + '\n') - - msg="\nCalculation results have changed from previously calculated values.\n If this seems reasonable, update EXPECTED_BROMINE_RESULTS in test_system.py with these values" - np.testing.assert_allclose(EXPECTED_BROMINE_RESULTS, result, atol=0.05, err_msg=msg) + """Check bromine study produces objective function and gradient in expected range """ + objective = self.get_objective() + data = objective.Full(np.zeros(objective.FF.np),1,verbose=True) + X, G, H = data['X'], data['G'], data['H'] + msgX="\nCalculated objective function is outside expected range.\n If this seems reasonable, update EXPECTED_EVALUATOR_BROMINE_OBJECTIVE in test_system.py with these values" + np.testing.assert_allclose(EXPECTED_EVALUATOR_BROMINE_OBJECTIVE, X, atol=60, err_msg=msgX) + msgG="\nCalculated gradient is outside expected range.\n If this seems reasonable, update EXPECTED_EVALUATOR_BROMINE_GRADIENT in test_system.py with these values" + np.testing.assert_allclose(EXPECTED_EVALUATOR_BROMINE_GRADIENT, G, atol=2500, err_msg=msgG) class TestLipidStudy(ForceBalanceSystemTest): def setup_method(self, method): @@ -310,45 +215,13 @@ def setup_method(self, method): os.chdir(os.path.join(cwd, '../../studies/010_lipid_study')) self.input_file='simple.in' self.logger.debug("\nSetting input file to '%s'\n" % self.input_file) + self.expected_results_name = "EXPECTED_LIPID_RESULTS" + self.expected_results = EXPECTED_LIPID_RESULTS + self.absolute_tolerance = 0.100 def test_lipid_study(self): """Check lipid tutorial study runs without errors""" - - ## The general options and target options that come from parsing the input file - self.logger.debug("Parsing inputs...\n") - options, tgt_opts = parse_inputs(self.input_file) - self.logger.debug("options:\n%s\n\ntgt_opts:\n%s\n\n" % (str(options), str(tgt_opts))) - - assert isinstance(options, dict), "Parser gave incorrect type for options" - assert isinstance(tgt_opts, list), "Parser gave incorrect type for tgt_opts" - for target in tgt_opts: - assert isinstance(target, dict), "Parser gave incorrect type for target dict" - - ## The force field component of the project - forcefield = FF(options) - assert isinstance(forcefield, FF), "Expected forcebalance forcefield object" - - ## The objective function - objective = Objective(options, tgt_opts, forcefield) - assert isinstance(objective, Objective), "Expected forcebalance objective object" - - ## The optimizer component of the project - self.logger.debug("Creating optimizer: ") - optimizer = Optimizer(options, objective, forcefield) - assert isinstance(optimizer, Optimizer), "Expected forcebalance optimizer object" - self.logger.debug(str(optimizer) + "\n") - - ## Actually run the optimizer. - self.logger.debug("Done setting up! Running optimizer...\n") - result = optimizer.Run() - self.logger.debug("\nOptimizer finished. Final results:\n") - self.logger.debug(str(result) + '\n') - msg = "\nCalculation results have changed from previously calculated values.\n If this seems reasonable, update EXPECTED_LIPID_RESULTS in test_system.py with these values (%s)" % result - np.testing.assert_allclose(EXPECTED_LIPID_RESULTS, result, atol=0.100, err_msg=msg) - - # Fail if calculation takes longer than previously to converge - assert ITERATIONS_TO_CONVERGE >= Counter(), "Calculation took longer than expected to converge (%d iterations vs previous of %d)" %\ - (ITERATIONS_TO_CONVERGE, Counter()) + self.run_optimizer() class TestImplicitSolventHFEStudy(ForceBalanceSystemTest): def setup_method(self, method): @@ -357,47 +230,13 @@ def setup_method(self, method): os.chdir(os.path.join(cwd, '..', '..', 'studies', '012_implicit_solvent_hfe')) self.input_file='optimize.in' self.logger.debug("\nSetting input file to '%s'\n" % self.input_file) + self.expected_results_name = "EXPECTED_ETHANOL_RESULTS" + self.expected_results = EXPECTED_ETHANOL_RESULTS + self.absolute_tolerance = 0.020 def test_implicit_solvent_hfe_study(self): """Check implicit hydration free energy study (Hydration target) converges to expected results""" - - ## The general options and target options that come from parsing the input file - self.logger.debug("Parsing inputs...\n") - options, tgt_opts = parse_inputs(self.input_file) - self.logger.debug("options:\n%s\n\ntgt_opts:\n%s\n\n" % (str(options), str(tgt_opts))) - - assert isinstance(options, dict), "Parser gave incorrect type for options" - assert isinstance(tgt_opts, list), "Parser gave incorrect type for tgt_opts" - for target in tgt_opts: - assert isinstance(target, dict), "Parser gave incorrect type for target dict" - - ## The force field component of the project - self.logger.debug("Creating forcefield using loaded options: ") - forcefield = FF(options) - self.logger.debug(str(forcefield) + "\n") - assert isinstance(forcefield, FF), "Expected forcebalance forcefield object" - - ## The objective function - self.logger.debug("Creating object using loaded options and forcefield: ") - objective = Objective(options, tgt_opts, forcefield) - self.logger.debug(str(objective) + "\n") - assert isinstance(objective, Objective), "Expected forcebalance objective object" - - ## The optimizer component of the project - self.logger.debug("Creating optimizer: ") - optimizer = Optimizer(options, objective, forcefield) - self.logger.debug(str(optimizer) + "\n") - assert isinstance(optimizer, Optimizer), "Expected forcebalance optimizer object" - - ## Actually run the optimizer. - self.logger.debug("Done setting up! Running optimizer...\n") - result = optimizer.Run() - result_pval = optimizer.FF.create_pvals(result) - - self.logger.debug("\nOptimizer finished. Final results:\n") - self.logger.debug(str(result) + '\n') - msg = "Calculation results have changed from previously calculated values.\n If this seems reasonable, update EXPECTED_ETHANOL_RESULTS in test_system.py with these values" - np.testing.assert_allclose(EXPECTED_ETHANOL_RESULTS,result_pval,atol=0.020, err_msg=msg) + self.run_optimizer(check_result=False, check_iter=False, use_pvals=True) class TestOpenFFTorsionProfileStudy(ForceBalanceSystemTest): def setup_method(self, method): @@ -411,45 +250,10 @@ def setup_method(self, method): targets.close() self.input_file='optimize_minimal.in' self.logger.debug("\nSetting input file to '%s'\n" % self.input_file) + self.expected_results_name = "EXPECTED_OPENFF_TORSIONPROFILE_RESULTS" + self.expected_results = EXPECTED_OPENFF_TORSIONPROFILE_RESULTS + self.absolute_tolerance = 0.001 def test_openff_torsionprofile_study(self): """Check OpenFF torsion profile optimization converges to expected results""" - - ## The general options and target options that come from parsing the input file - self.logger.debug("Parsing inputs...\n") - options, tgt_opts = parse_inputs(self.input_file) - self.logger.debug("options:\n%s\n\ntgt_opts:\n%s\n\n" % (str(options), str(tgt_opts))) - - assert isinstance(options, dict), "Parser gave incorrect type for options" - assert isinstance(tgt_opts, list), "Parser gave incorrect type for tgt_opts" - for target in tgt_opts: - assert isinstance(target, dict), "Parser gave incorrect type for target dict" - - ## The force field component of the project - self.logger.debug("Creating forcefield using loaded options: ") - forcefield = FF(options) - self.logger.debug(str(forcefield) + "\n") - assert isinstance(forcefield, FF), "Expected forcebalance forcefield object" - - ## The objective function - self.logger.debug("Creating object using loaded options and forcefield: ") - objective = Objective(options, tgt_opts, forcefield) - self.logger.debug(str(objective) + "\n") - assert isinstance(objective, Objective), "Expected forcebalance objective object" - - ## The optimizer component of the project - self.logger.debug("Creating optimizer: ") - optimizer = Optimizer(options, objective, forcefield) - self.logger.debug(str(optimizer) + "\n") - assert isinstance(optimizer, Optimizer), "Expected forcebalance optimizer object" - - ## Actually run the optimizer. - self.logger.debug("Done setting up! Running optimizer...\n") - result = optimizer.Run() - - self.logger.debug("\nOptimizer finished. Final results:\n") - self.logger.debug(str(result) + '\n') - - msg="\nCalculation results have changed from previously calculated values.\n If this seems reasonable, " \ - "update EXPECTED_OPENFF_TORSIONPROFILE_RESULTS in test_system.py with these values" - np.testing.assert_allclose(EXPECTED_OPENFF_TORSIONPROFILE_RESULTS,result,atol=0.001,err_msg=msg) + self.run_optimizer(check_iter=False) diff --git a/studies/003d_estimator_liquid_bromine/gradient.in b/studies/003d_estimator_liquid_bromine/gradient.in new file mode 100644 index 000000000..5c7687b84 --- /dev/null +++ b/studies/003d_estimator_liquid_bromine/gradient.in @@ -0,0 +1,66 @@ +# ForceBalance input file generated by MakeInputFile.py +# The octothorpe '#' is a comment symbol +# Note: If the specified value is 'None' then the option will truly be set to None - not the string 'None' +# Note: 'Section' option types are more complicated and may require you to read the documentation +# Note: Boolean option types require no value, the key being present implies 'True' + +$options +# (string) Directory containing force fields, relative to project directory +ffdir forcefield + +# (string) Type of the penalty, L2 or L1 in the optimizer +penalty_type L2 + +# (allcap) The job type, defaults to a single-point evaluation of objective function +jobtype gradient + +# (list) The names of force fields, corresponding to directory forcefields/file_name.(itp|gen) +forcefield bromine.offxml + +# (int) Maximum number of steps in an optimization +maxstep 100 + +# (float) Convergence criterion of step size (just needs to fall below this threshold) +convergence_step 0.1 + +# (float) Convergence criterion of objective function (in MainOptimizer this is the stdev of x2 over 10 steps) +convergence_objective 0.1 + +# (float) Convergence criterion of gradient norm +convergence_gradient 0.1 + +criteria 1 + +# (float) Minimum eigenvalue for applying steepest descent correction in the MainOptimizer +eig_lowerbound 0.01 + +# (float) Step size for finite difference derivatives in many functions (get_(G/H) in fitsim, FDCheckG) +finite_difference_h 0.001 + +# (float) Factor for multiplicative penalty function in objective function +penalty_additive 1.0 + +trust0 1.0 +mintrust 0.05 +error_tolerance 1.0 +adaptive_factor 0.2 +adaptive_damping 1.0 +normalize_weights no +print_hessian + +# Charge constraints are taken care of using "evals". +constrain_charge false +backup false + +priors + vdW/Atom/epsilon : 2.47894e+00 + vdW/Atom/sigma : 5.29177e-02 +/priors +$end + +$target +name LiquidBromine +type PropertyEstimate_SMIRNOFF +weight 1.0 +prop_est_input options.json +$end diff --git a/studies/003d_estimator_liquid_bromine/optimize.in b/studies/003d_estimator_liquid_bromine/optimize.in index 00cb2a403..fae61ce2d 100644 --- a/studies/003d_estimator_liquid_bromine/optimize.in +++ b/studies/003d_estimator_liquid_bromine/optimize.in @@ -59,6 +59,12 @@ priors $end +# Note: Denominators have been changed from the original Gromacs version of the study (003_liquid_bromine) +# in order to create a unit test for gradients rather than the optimization result. +# Therefore, optimization results will differ from the Gromacs version. +# To reproduce results from the Gromacs version, change density and Hvap denominators +# to 30.0 and 0.3 respectively. + $target name LiquidBromine type PropertyEstimate_SMIRNOFF diff --git a/studies/003d_estimator_liquid_bromine/targets.tar.gz b/studies/003d_estimator_liquid_bromine/targets.tar.gz index a9fd090b1d1b94695d50c4bf69155555f09e7552..84111dc017177225da5973001698d7fc5cfee2d9 100644 GIT binary patch literal 7332 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 SejFGJl>Z0K$xKQBxB&p6H;SwP From 1d91dbab93e1031e83ad0bbcd32c85860dabe3c9 Mon Sep 17 00:00:00 2001 From: Lee-Ping Wang Date: Sat, 23 Nov 2019 22:56:40 -0800 Subject: [PATCH 2/7] Tighten tolerances --- src/tests/test_system.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/tests/test_system.py b/src/tests/test_system.py index 48c000c70..c99466c53 100644 --- a/src/tests/test_system.py +++ b/src/tests/test_system.py @@ -22,8 +22,8 @@ # expected objective function from 003d evaluator bromine study. (updated 11/23/19) EXPECTED_EVALUATOR_BROMINE_OBJECTIVE = array([1000]) -# expected gradient elements from 003d evaluator bromine study. Very large uncertainties of +/- 2500 (updated 11/23/19) -EXPECTED_EVALUATOR_BROMINE_GRADIENT = array([4000, 4000]) +# expected gradient elements from 003d evaluator bromine study. Very large uncertainties of +/- 2000 (updated 11/23/19) +EXPECTED_EVALUATOR_BROMINE_GRADIENT = array([4500, 5500]) # expected result (pvals) taken from ethanol GB parameter optimization. Update this if it changes and seems reasonable (updated 09/05/14) EXPECTED_ETHANOL_RESULTS = array([1.2286e-01, 8.3624e-01, 1.0014e-01, 8.4533e-01, 1.8740e-01, 6.8820e-01, 1.4606e-01, 8.3518e-01]) @@ -206,7 +206,7 @@ def test_bromine_study(self): msgX="\nCalculated objective function is outside expected range.\n If this seems reasonable, update EXPECTED_EVALUATOR_BROMINE_OBJECTIVE in test_system.py with these values" np.testing.assert_allclose(EXPECTED_EVALUATOR_BROMINE_OBJECTIVE, X, atol=60, err_msg=msgX) msgG="\nCalculated gradient is outside expected range.\n If this seems reasonable, update EXPECTED_EVALUATOR_BROMINE_GRADIENT in test_system.py with these values" - np.testing.assert_allclose(EXPECTED_EVALUATOR_BROMINE_GRADIENT, G, atol=2500, err_msg=msgG) + np.testing.assert_allclose(EXPECTED_EVALUATOR_BROMINE_GRADIENT, G, atol=2000, err_msg=msgG) class TestLipidStudy(ForceBalanceSystemTest): def setup_method(self, method): From 010af8ebcc4e270f0c856ac27afd9373ad0b7325 Mon Sep 17 00:00:00 2001 From: Lee-Ping Wang Date: Sun, 24 Nov 2019 00:42:12 -0800 Subject: [PATCH 3/7] Remove mdtraj version pin --- devtools/conda-envs/test_env.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/devtools/conda-envs/test_env.yaml b/devtools/conda-envs/test_env.yaml index cae68ca38..26df3a63f 100644 --- a/devtools/conda-envs/test_env.yaml +++ b/devtools/conda-envs/test_env.yaml @@ -21,7 +21,7 @@ dependencies: - swig - future - pymbar=3.0.3 - - mdtraj=1.9.1 + - mdtraj - openmm - ambertools # The following two are not compatible with python 2.7 and 3.5, so they are conditionally installed in .travis.yml From eb3e41f3474890ff54d6f99718f7a83c6516cd48 Mon Sep 17 00:00:00 2001 From: Lee-Ping Wang Date: Sun, 24 Nov 2019 07:47:54 -0800 Subject: [PATCH 4/7] Add travis_wait for mac os --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index f292ff9b1..0d43e5129 100644 --- a/.travis.yml +++ b/.travis.yml @@ -164,7 +164,7 @@ script: - tar xvjf targets.tar.bz2 - ForceBalance very_simple.in - cd - - - pytest --cov=forcebalance --cov-config=setup.cfg + - travis_wait 30 pytest --cov=forcebalance --cov-config=setup.cfg # - python test # - py.test -v --cov=eex/ --durations=5 From 044646b35b835c2994fb6209ac67b9d47e2665c6 Mon Sep 17 00:00:00 2001 From: Lee-Ping Wang Date: Sun, 24 Nov 2019 07:53:01 -0800 Subject: [PATCH 5/7] Add durations --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 0d43e5129..d588bb891 100644 --- a/.travis.yml +++ b/.travis.yml @@ -164,7 +164,7 @@ script: - tar xvjf targets.tar.bz2 - ForceBalance very_simple.in - cd - - - travis_wait 30 pytest --cov=forcebalance --cov-config=setup.cfg + - travis_wait 30 pytest --cov=forcebalance --cov-config=setup.cfg --durations=0 # - python test # - py.test -v --cov=eex/ --durations=5 From 5b9c484fa097966ef113df15584038ff274167e8 Mon Sep 17 00:00:00 2001 From: Lee-Ping Wang Date: Sun, 24 Nov 2019 09:40:29 -0800 Subject: [PATCH 6/7] Restrict PE testing to Python 3.7 on Linux --- .travis.yml | 7 +++++-- devtools/conda-envs/test_env.yaml | 1 - 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index d588bb891..8c5afef63 100644 --- a/.travis.yml +++ b/.travis.yml @@ -76,7 +76,8 @@ install: # If were using python 3.6 or higher and we're decrypting an OE key, install OFF toolkit and # OETK (there aren't OFFTK packages for python<3.6) - - if [ ${PYTHON_VER} != "2.7" ] && [ ${PYTHON_VER} != "3.5" ] && [ "$TRAVIS_SECURE_ENV_VARS" == true ] ; then conda install --yes -c omnia -c openeye openforcefield openeye-toolkits propertyestimator; fi + - if [ ${PYTHON_VER} != "2.7" ] && [ ${PYTHON_VER} != "3.5" ] && [ "$TRAVIS_SECURE_ENV_VARS" == true ] ; then conda install --yes -c omnia -c openeye openforcefield openeye-toolkits; fi + - if [ ${PYTHON_VER} != "2.7" ] && [ ${PYTHON_VER} != "3.5" ] && [ ${PYTHON_VER} != "3.6" ] && if [ "$TRAVIS_OS_NAME" == "linux" ] && [ "$TRAVIS_SECURE_ENV_VARS" == true ] ; then conda install --yes -c omnia -c openeye propertyestimator; fi # Install Work Queue - wget https://raw.githubusercontent.com/leeping/forcebalance/master/tools/install-cctools.sh @@ -164,7 +165,9 @@ script: - tar xvjf targets.tar.bz2 - ForceBalance very_simple.in - cd - - - travis_wait 30 pytest --cov=forcebalance --cov-config=setup.cfg --durations=0 + - pytest --cov=forcebalance --cov-config=setup.cfg --durations=0 + # Allow tests to run for up to 30 minutes + # - travis_wait 30 pytest --cov=forcebalance --cov-config=setup.cfg --durations=0 # - python test # - py.test -v --cov=eex/ --durations=5 diff --git a/devtools/conda-envs/test_env.yaml b/devtools/conda-envs/test_env.yaml index 26df3a63f..aedfa14d0 100644 --- a/devtools/conda-envs/test_env.yaml +++ b/devtools/conda-envs/test_env.yaml @@ -21,7 +21,6 @@ dependencies: - swig - future - pymbar=3.0.3 - - mdtraj - openmm - ambertools # The following two are not compatible with python 2.7 and 3.5, so they are conditionally installed in .travis.yml From ca8c9922a74ec14bf72598a1d6af99789e3f4357 Mon Sep 17 00:00:00 2001 From: Lee-Ping Wang Date: Sun, 24 Nov 2019 10:05:14 -0800 Subject: [PATCH 7/7] Fix syntax error --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 8c5afef63..b85056ab8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -77,7 +77,7 @@ install: # If were using python 3.6 or higher and we're decrypting an OE key, install OFF toolkit and # OETK (there aren't OFFTK packages for python<3.6) - if [ ${PYTHON_VER} != "2.7" ] && [ ${PYTHON_VER} != "3.5" ] && [ "$TRAVIS_SECURE_ENV_VARS" == true ] ; then conda install --yes -c omnia -c openeye openforcefield openeye-toolkits; fi - - if [ ${PYTHON_VER} != "2.7" ] && [ ${PYTHON_VER} != "3.5" ] && [ ${PYTHON_VER} != "3.6" ] && if [ "$TRAVIS_OS_NAME" == "linux" ] && [ "$TRAVIS_SECURE_ENV_VARS" == true ] ; then conda install --yes -c omnia -c openeye propertyestimator; fi + - if [ ${PYTHON_VER} != "2.7" ] && [ ${PYTHON_VER} != "3.5" ] && [ ${PYTHON_VER} != "3.6" ] && [ "$TRAVIS_OS_NAME" == "linux" ] && [ "$TRAVIS_SECURE_ENV_VARS" == true ] ; then conda install --yes -c omnia -c openeye propertyestimator; fi # Install Work Queue - wget https://raw.githubusercontent.com/leeping/forcebalance/master/tools/install-cctools.sh