source: src/Potentials/Specifics/ManyBodyPotential_Tersoff.cpp@ 1dbbeb

Action_Thermostats Add_AtomRandomPerturbation Add_FitFragmentPartialChargesAction Add_RotateAroundBondAction Add_SelectAtomByNameAction Added_ParseSaveFragmentResults AddingActions_SaveParseParticleParameters Adding_Graph_to_ChangeBondActions Adding_MD_integration_tests Adding_ParticleName_to_Atom Adding_StructOpt_integration_tests AtomFragments Automaking_mpqc_open AutomationFragmentation_failures Candidate_v1.5.4 Candidate_v1.6.0 Candidate_v1.6.1 ChangeBugEmailaddress ChangingTestPorts ChemicalSpaceEvaluator CombiningParticlePotentialParsing Combining_Subpackages Debian_Package_split Debian_package_split_molecuildergui_only Disabling_MemDebug Docu_Python_wait EmpiricalPotential_contain_HomologyGraph EmpiricalPotential_contain_HomologyGraph_documentation Enable_parallel_make_install Enhance_userguide Enhanced_StructuralOptimization Enhanced_StructuralOptimization_continued Example_ManyWaysToTranslateAtom Exclude_Hydrogens_annealWithBondGraph FitPartialCharges_GlobalError Fix_BoundInBox_CenterInBox_MoleculeActions Fix_ChargeSampling_PBC Fix_ChronosMutex Fix_FitPartialCharges Fix_FitPotential_needs_atomicnumbers Fix_ForceAnnealing Fix_IndependentFragmentGrids Fix_ParseParticles Fix_ParseParticles_split_forward_backward_Actions Fix_PopActions Fix_QtFragmentList_sorted_selection Fix_Restrictedkeyset_FragmentMolecule Fix_StatusMsg Fix_StepWorldTime_single_argument Fix_Verbose_Codepatterns Fix_fitting_potentials Fixes ForceAnnealing_goodresults ForceAnnealing_oldresults ForceAnnealing_tocheck ForceAnnealing_with_BondGraph ForceAnnealing_with_BondGraph_continued ForceAnnealing_with_BondGraph_continued_betteresults ForceAnnealing_with_BondGraph_contraction-expansion FragmentAction_writes_AtomFragments FragmentMolecule_checks_bonddegrees GeometryObjects Gui_Fixes Gui_displays_atomic_force_velocity ImplicitCharges IndependentFragmentGrids IndependentFragmentGrids_IndividualZeroInstances IndependentFragmentGrids_IntegrationTest IndependentFragmentGrids_Sole_NN_Calculation JobMarket_RobustOnKillsSegFaults JobMarket_StableWorkerPool JobMarket_unresolvable_hostname_fix MoreRobust_FragmentAutomation ODR_violation_mpqc_open PartialCharges_OrthogonalSummation PdbParser_setsAtomName PythonUI_with_named_parameters QtGui_reactivate_TimeChanged_changes Recreated_GuiChecks Rewrite_FitPartialCharges RotateToPrincipalAxisSystem_UndoRedo SaturateAtoms_findBestMatching SaturateAtoms_singleDegree StoppableMakroAction Subpackage_CodePatterns Subpackage_JobMarket Subpackage_LinearAlgebra Subpackage_levmar Subpackage_mpqc_open Subpackage_vmg Switchable_LogView ThirdParty_MPQC_rebuilt_buildsystem TrajectoryDependenant_MaxOrder TremoloParser_IncreasedPrecision TremoloParser_MultipleTimesteps TremoloParser_setsAtomName Ubuntu_1604_changes stable
Last change on this file since 1dbbeb was 0932c2, checked in by Frederik Heber <heber@…>, 11 years ago

FIX: RandomNumberEngine_Encapsulation::clone() did not set the seed obtained from its prototype.

  • this caused all engines to always start with default seed of 1, irrespective of the set parameter. The engine is always cloned from prototypes in the factory that can be manipulated to change their parameters. Hence, clone needs to set the seed (the engine's only parameter).
  • EmpiricalPotentials now use RandomNumberGenerator to obtain random starting values.
  • TESTFIX: fit-potential regression tests now use fixed seed in order to always take the same amount of time (some test runs in debug mode take very long because of ill-chosen random values).
  • Property mode set to 100644
File size: 22.5 KB
Line 
1/*
2 * Project: MoleCuilder
3 * Description: creates and alters molecular systems
4 * Copyright (C) 2012 University of Bonn. All rights reserved.
5 * Copyright (C) 2013 Frederik Heber. All rights reserved.
6 * Please see the COPYING file or "Copyright notice" in builder.cpp for details.
7 *
8 *
9 * This file is part of MoleCuilder.
10 *
11 * MoleCuilder is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation, either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * MoleCuilder is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with MoleCuilder. If not, see <http://www.gnu.org/licenses/>.
23 */
24
25/*
26 * ManyBodyPotential_Tersoff.cpp
27 *
28 * Created on: Sep 26, 2012
29 * Author: heber
30 */
31
32
33// include config.h
34#ifdef HAVE_CONFIG_H
35#include <config.h>
36#endif
37
38#include "CodePatterns/MemDebug.hpp"
39
40#include "ManyBodyPotential_Tersoff.hpp"
41
42#include <boost/assign/list_of.hpp> // for 'map_list_of()'
43#include <boost/bind.hpp>
44#include <cmath>
45#include <string>
46
47#include "CodePatterns/Assert.hpp"
48//#include "CodePatterns/Info.hpp"
49#include "CodePatterns/Log.hpp"
50
51#include "FunctionApproximation/Extractors.hpp"
52#include "FunctionApproximation/TrainingData.hpp"
53#include "Potentials/helpers.hpp"
54#include "Potentials/InternalCoordinates/OneBody_Constant.hpp"
55#include "Potentials/ParticleTypeCheckers.hpp"
56#include "RandomNumbers/RandomNumberGeneratorFactory.hpp"
57#include "RandomNumbers/RandomNumberGenerator.hpp"
58
59class Fragment;
60
61// static definitions
62const ManyBodyPotential_Tersoff::ParameterNames_t
63ManyBodyPotential_Tersoff::ParameterNames =
64 boost::assign::list_of<std::string>
65 ("A")
66 ("B")
67 ("lambda")
68 ("mu")
69 ("beta")
70 ("n")
71 ("c")
72 ("d")
73 ("h")
74// ("R")
75// ("S")
76// ("lambda3")
77// ("alpha")
78// ("chi")
79// ("omega")
80 ;
81const std::string ManyBodyPotential_Tersoff::potential_token("tersoff");
82Coordinator::ptr ManyBodyPotential_Tersoff::coordinator(new OneBody_Constant());
83
84ManyBodyPotential_Tersoff::ManyBodyPotential_Tersoff() :
85 EmpiricalPotential(),
86 params(parameters_t(MAXPARAMS, 0.)),
87 R(3.2),
88 S(3.5),
89 lambda3(0.),
90 alpha(0.),
91 chi(1.),
92 omega(1.),
93 triplefunction(&Helpers::NoOp_Triplefunction)
94{}
95
96ManyBodyPotential_Tersoff::ManyBodyPotential_Tersoff(
97 const ParticleTypes_t &_ParticleTypes
98 ) :
99 EmpiricalPotential(_ParticleTypes),
100 params(parameters_t(MAXPARAMS, 0.)),
101 R(3.2),
102 S(3.5),
103 lambda3(0.),
104 alpha(0.),
105 chi(1.),
106 omega(1.),
107 triplefunction(&Helpers::NoOp_Triplefunction)
108{
109 // have some decent defaults for parameter_derivative checking
110 params[A] = 3000.;
111 params[B] = 300.;
112 params[lambda] = 5.;
113 params[mu] = 3.;
114 params[beta] = 2.;
115 params[n] = 1.;
116 params[c] = 0.01;
117 params[d] = 1.;
118 params[h] = 0.01;
119}
120
121ManyBodyPotential_Tersoff::ManyBodyPotential_Tersoff(
122 const ParticleTypes_t &_ParticleTypes,
123 const double &_R,
124 const double &_S,
125 const double &_A,
126 const double &_B,
127 const double &_lambda,
128 const double &_mu,
129 const double &_lambda3,
130 const double &_alpha,
131 const double &_beta,
132 const double &_chi,
133 const double &_omega,
134 const double &_n,
135 const double &_c,
136 const double &_d,
137 const double &_h) :
138 EmpiricalPotential(_ParticleTypes),
139 params(parameters_t(MAXPARAMS, 0.)),
140 R(_R),
141 S(_S),
142 lambda3(_lambda3),
143 alpha(_alpha),
144 chi(_chi),
145 omega(_mu),
146 triplefunction(&Helpers::NoOp_Triplefunction)
147{
148// Info info(__func__);
149// R = _R;
150// S = _S;
151 params[A] = _A;
152 params[B] = _B;
153 params[lambda] = _lambda;
154 params[mu] = _mu;
155// lambda3 = _lambda3;
156// alpha = _alpha;
157 params[beta] = _beta;
158// chi = _chi;
159// omega = _omega;
160 params[n] = _n;
161 params[c] = _c;
162 params[d] = _d;
163 params[h] = _h;
164}
165
166void ManyBodyPotential_Tersoff::setParameters(const parameters_t &_params)
167{
168 const size_t paramsDim = _params.size();
169 ASSERT( paramsDim <= getParameterDimension(),
170 "ManyBodyPotential_Tersoff::setParameters() - we need not more than "
171 +toString(getParameterDimension())+" parameters.");
172 for (size_t i=0; i< paramsDim; ++i)
173 params[i] = _params[i];
174
175#ifndef NDEBUG
176 parameters_t check_params(getParameters());
177 check_params.resize(paramsDim); // truncate to same size
178 ASSERT( check_params == _params,
179 "ManyBodyPotential_Tersoff::setParameters() - failed, mismatch in to be set "
180 +toString(_params)+" and set "+toString(check_params)+" params.");
181#endif
182}
183
184ManyBodyPotential_Tersoff::results_t
185ManyBodyPotential_Tersoff::operator()(
186 const arguments_t &arguments
187 ) const
188{
189// Info info(__func__);
190 double result = 0.;
191 for(arguments_t::const_iterator argiter = arguments.begin();
192 argiter != arguments.end();
193 ++argiter) {
194 const argument_t &r_ij = *argiter;
195 ASSERT( ParticleTypeChecker::checkArgumentsAgainstParticleTypes(
196 arguments_t(1, r_ij), getParticleTypes()),
197 "ManyBodyPotential_Tersoff::operator() - types don't match with ones in arguments.");
198
199 const double cutoff = function_cutoff(r_ij.distance);
200 const double temp = (cutoff == 0.) ?
201 0. :
202 cutoff * (
203 function_prefactor(
204 alpha,
205 function_eta(r_ij))
206 * function_smoother(
207 params[A],
208 params[lambda],
209 r_ij.distance)
210 +
211 function_prefactor(
212 params[beta],
213 function_zeta(r_ij))
214 * function_smoother(
215 -params[B],
216 params[mu],
217 r_ij.distance)
218 );
219 result += temp;
220 }
221// LOG(2, "DEBUG: operator()(" << r_ij.distance << ") = " << result);
222 return std::vector<result_t>(1, result);
223}
224
225ManyBodyPotential_Tersoff::derivative_components_t
226ManyBodyPotential_Tersoff::derivative(
227 const arguments_t &arguments
228 ) const
229{
230// Info info(__func__);
231 return ManyBodyPotential_Tersoff::derivative_components_t();
232}
233
234ManyBodyPotential_Tersoff::results_t
235ManyBodyPotential_Tersoff::parameter_derivative(
236 const arguments_t &arguments,
237 const size_t index
238 ) const
239{
240// Info info(__func__);
241// ASSERT( arguments.size() == 1,
242// "ManyBodyPotential_Tersoff::parameter_derivative() - requires exactly one argument.");
243
244 double result = 0.;
245 for(arguments_t::const_iterator argiter = arguments.begin();
246 argiter != arguments.end();
247 ++argiter) {
248 const argument_t &r_ij = *argiter;
249 ASSERT( ParticleTypeChecker::checkArgumentsAgainstParticleTypes(
250 arguments_t(1, r_ij), getParticleTypes()),
251 "ManyBodyPotential_Tersoff::operator() - types don't match with ones in arguments.");
252
253 switch (index) {
254// case R:
255// {
256// result += 0.;
257// break;
258// }
259// case S:
260// {
261// result += 0.;
262// break;
263// }
264 case A:
265 {
266 const double cutoff = function_cutoff(r_ij.distance);
267 result += (cutoff == 0.) ?
268 0. :
269 cutoff *
270 function_prefactor(
271 alpha,
272 function_eta(r_ij))
273 * function_smoother(
274 1.,
275 params[lambda],
276 r_ij.distance);
277// cutoff * function_prefactor(
278// alpha,
279// function_eta(r_ij))
280// * function_smoother(
281// 1.,
282// params[mu],
283// r_ij.distance);
284 break;
285 }
286 case B:
287 {
288 const double cutoff = function_cutoff(r_ij.distance);
289 result += (cutoff == 0.) ?
290 0. :
291 cutoff * function_prefactor(
292 params[beta],
293 function_zeta(r_ij))
294 * function_smoother(
295 -1.,
296 params[mu],
297 r_ij.distance);
298// cutoff * function_prefactor(
299// beta,
300// function_zeta(r_ij))
301// * function_smoother(
302// -params[B],
303// params[mu],
304// r_ij.distance)/params[B];
305 break;
306 }
307 case lambda:
308 {
309 const double cutoff = function_cutoff(r_ij.distance);
310 result += (cutoff == 0.) ?
311 0. :
312 -r_ij.distance * cutoff *
313 function_prefactor(
314 alpha,
315 function_eta(r_ij))
316 * function_smoother(
317 params[A],
318 params[lambda],
319 r_ij.distance);
320 break;
321 }
322 case mu:
323 {
324 const double cutoff = function_cutoff(r_ij.distance);
325 result += (cutoff == 0.) ?
326 0. :
327 -r_ij.distance * cutoff *(
328 function_prefactor(
329 params[beta],
330 function_zeta(r_ij))
331 * function_smoother(
332 -params[B],
333 params[mu],
334 r_ij.distance)
335 );
336 break;
337 }
338// case lambda3:
339// {
340// result += 0.;
341// break;
342// }
343// case alpha:
344// {
345// const double temp =
346// pow(alpha*function_eta(r_ij), params[n]);
347// const double cutoff = function_cutoff(r_ij.distance);
348// result += (cutoff == 0.) || (alpha == 0. )?
349// 0. :
350// function_smoother(
351// params[A],
352// params[lambda],
353// r_ij.distance)
354// * (-.5) * alpha * (temp/alpha)
355// / (1. + temp)
356// ;
357// break;
358// }
359// case chi:
360// {
361// result += 0.;
362// break;
363// }
364// case omega:
365// {
366// result += 0.;
367// break;
368// }
369 case beta:
370 {
371 const double temp =
372 pow(params[beta]*function_zeta(r_ij), params[n]);
373 const double cutoff = function_cutoff(r_ij.distance);
374 result += (cutoff == 0.) || (params[beta] == 0. )?
375 0. : cutoff *
376 function_smoother(
377 -params[B],
378 params[mu],
379 r_ij.distance)
380 * (-.5)
381 * function_prefactor(
382 params[beta],
383 function_zeta(r_ij))
384 * (temp/params[beta])
385 / (1. + temp)
386 ;
387 break;
388 }
389 case n:
390 {
391 const double zeta = function_zeta(r_ij);
392 const double temp = pow( params[beta]*zeta , params[n]);
393 const double cutoff = function_cutoff(r_ij.distance);
394 const double tempres = ((cutoff == 0.) || (zeta == 0.)) ? // zeta must be caught if zero due to log
395 0. : .5 * cutoff *
396 function_smoother(
397 -params[B],
398 params[mu],
399 r_ij.distance)
400 * function_prefactor(
401 params[beta],
402 function_zeta(r_ij))
403 * ( log(1.+temp)/(params[n]*params[n]) - temp
404 * (log(function_zeta(r_ij)) + log(params[beta]))
405 /(params[n]*(1.+temp)))
406 ;
407// if (tempres != tempres)
408// LOG(2, "DEBUG: tempres is NaN.");
409// LOG(2, "DEBUG: Adding " << tempres << " for p.d. w.r.t n, temp=" << temp << ", cutoff=" << cutoff);
410 result += tempres;
411 break;
412 }
413 case c:
414 {
415 const double zeta = function_zeta(r_ij);
416 if (zeta == 0.)
417 break;
418 const double temp =
419 pow(zeta, params[n]-1.) * pow(params[beta],params[n]);
420 const double cutoff = function_cutoff(r_ij.distance);
421 const double tempres = (cutoff == 0.) ?
422 0. : cutoff *
423 function_smoother(
424 -params[B],
425 params[mu],
426 r_ij.distance)
427 * function_prefactor(
428 params[beta],
429 zeta)
430 * (-1.) * temp / (1.+temp*zeta);
431 double factor = function_derivative_c(r_ij);
432 result += tempres*factor;
433 if (result != result)
434 ELOG(1, "result is NaN, zeta=" << zeta << ", temp=" << temp << ", cutoff=" << cutoff << ", tempres=" << tempres << ", factor=" << factor);
435 break;
436 }
437 case d:
438 {
439 const double zeta = function_zeta(r_ij);
440 const double temp =
441 pow(zeta, params[n]-1.) * pow(params[beta],params[n]);
442 const double cutoff = function_cutoff(r_ij.distance);
443 const double tempres = (cutoff == 0.) ?
444 0. : cutoff *
445 function_smoother(
446 -params[B],
447 params[mu],
448 r_ij.distance)
449 * function_prefactor(
450 params[beta],
451 zeta)
452 * (-1.) * temp / (1.+temp*zeta);
453 double factor = function_derivative_d(r_ij);
454 result += tempres*factor;
455 if (result != result)
456 ELOG(1, "result is NaN, zeta=" << zeta << ", temp=" << temp << ", cutoff=" << cutoff << ", tempres=" << tempres << ", factor=" << factor);
457 break;
458 }
459 case h:
460 {
461 const double zeta = function_zeta(r_ij);
462 const double temp =
463 pow(zeta, params[n]-1.) * pow(params[beta],params[n]);
464 const double cutoff = function_cutoff(r_ij.distance);
465 const double tempres = (cutoff == 0.) ?
466 0. : cutoff *
467 function_smoother(
468 -params[B],
469 params[mu],
470 r_ij.distance)
471 * function_prefactor(
472 params[beta],
473 zeta)
474 * (-1.) * temp / (1.+temp*zeta);
475 double factor = function_derivative_h(r_ij);
476 result += tempres*factor;
477 if (result != result)
478 ELOG(1, "result is NaN, zeta=" << zeta << ", temp=" << temp << ", cutoff=" << cutoff << ", tempres=" << tempres << ", factor=" << factor);
479 break;
480 }
481 default:
482 ASSERT(0, "ManyBodyPotential_Tersoff::parameter_derivative() - derivative to unknown parameter desired.");
483 break;
484 }
485 if (result != result)
486 ELOG(1, "result is NaN.");
487 }
488 return results_t(1,-result);
489}
490
491ManyBodyPotential_Tersoff::result_t
492ManyBodyPotential_Tersoff::function_derivative_c(
493 const argument_t &r_ij
494 ) const
495{
496 double result = 0.;
497 std::vector<arguments_t> triples = triplefunction(r_ij, S);
498 for (std::vector<arguments_t>::const_iterator iter = triples.begin();
499 iter != triples.end(); ++iter) {
500 ASSERT( iter->size() == 2,
501 "ManyBodyPotential_Tersoff::function_derivative_c() - the triples result must contain exactly two distances.");
502 const argument_t &r_ik = (*iter)[0];
503 const argument_t &r_jk = (*iter)[1];
504 const double tempangle = params[h] - function_theta(r_ij.distance, r_ik.distance, r_jk.distance);
505 const double cutoff = function_cutoff(r_ik.distance);
506 result += (cutoff == 0.) ?
507 0. : cutoff * omega * exp( Helpers::pow(lambda3 * (r_ij.distance - r_ik.distance) ,3)) * (
508 params[c]/Helpers::pow(params[d],2)
509 - params[c] / ( Helpers::pow(params[d],2) + Helpers::pow(tempangle,2) )
510 );
511 }
512 return result;
513}
514
515ManyBodyPotential_Tersoff::result_t
516ManyBodyPotential_Tersoff::function_derivative_d(
517 const argument_t &r_ij
518 ) const
519{
520 double result = 0.;
521 std::vector<arguments_t> triples = triplefunction(r_ij, S);
522 for (std::vector<arguments_t>::const_iterator iter = triples.begin();
523 iter != triples.end(); ++iter) {
524 ASSERT( iter->size() == 2,
525 "ManyBodyPotential_Tersoff::function_derivative_d() - the triples result must contain exactly two distances.");
526 const argument_t &r_ik = (*iter)[0];
527 const argument_t &r_jk = (*iter)[1];
528 const double tempangle = params[h] - function_theta(r_ij.distance, r_ik.distance, r_jk.distance);
529 const double cutoff = function_cutoff(r_ik.distance);
530 result += (cutoff == 0.) ?
531 0. : cutoff * omega * exp( Helpers::pow(lambda3 * (r_ij.distance - r_ik.distance) ,3)) * (
532 - Helpers::pow(params[c],2)/Helpers::pow(params[d],3)
533 + Helpers::pow(params[c],2) * params[d]
534 / Helpers::pow(Helpers::pow(params[d],2) + Helpers::pow(tempangle,2),2)
535 );
536 }
537 return result;
538}
539
540ManyBodyPotential_Tersoff::result_t
541ManyBodyPotential_Tersoff::function_derivative_h(
542 const argument_t &r_ij
543 ) const
544{
545 double result = 0.;
546 std::vector<arguments_t> triples = triplefunction(r_ij, S);
547 for (std::vector<arguments_t>::const_iterator iter = triples.begin();
548 iter != triples.end(); ++iter) {
549 ASSERT( iter->size() == 2,
550 "ManyBodyPotential_Tersoff::function_derivative_h() - the triples result must contain exactly two distances.");
551 const argument_t &r_ik = (*iter)[0];
552 const argument_t &r_jk = (*iter)[1];
553 const double tempangle = params[h] - function_theta(r_ij.distance, r_ik.distance, r_jk.distance);
554 const double cutoff = function_cutoff(r_ik.distance);
555 result += (cutoff == 0.) ?
556 0. : cutoff * omega * exp( Helpers::pow(lambda3 * (r_ij.distance - r_ik.distance) ,3)) * (
557 ( Helpers::pow(params[c],2)*tempangle )
558 / Helpers::pow(Helpers::pow(params[d],2) + Helpers::pow(tempangle,2),2)
559 );
560 }
561 return result;
562}
563
564ManyBodyPotential_Tersoff::result_t
565ManyBodyPotential_Tersoff::function_cutoff(
566 const double &distance
567 ) const
568{
569// Info info(__func__);
570 double result = 0.;
571 if (distance < R)
572 result = 1.;
573 else if (distance > S)
574 result = 0.;
575 else {
576 result = (0.5 + 0.5 * cos( M_PI * (distance - R)/(S-R)));
577 }
578// LOG(2, "DEBUG: function_cutoff(" << distance << ") = " << result);
579 return result;
580}
581
582ManyBodyPotential_Tersoff::result_t
583ManyBodyPotential_Tersoff::function_prefactor(
584 const double &alpha,
585 const double &eta
586 ) const
587{
588// Info info(__func__);
589 const double result = chi * pow(
590 (1. + pow(alpha * eta, params[n])),
591 -1./(2.*params[n]));
592// LOG(2, "DEBUG: function_prefactor(" << alpha << "," << eta << ") = " << result);
593 return result;
594}
595
596ManyBodyPotential_Tersoff::result_t
597ManyBodyPotential_Tersoff::function_smoother(
598 const double &prefactor,
599 const double &lambda,
600 const double &distance
601 ) const
602{
603// Info info(__func__);
604 const double result = prefactor * exp(-lambda * distance);
605// LOG(2, "DEBUG: function_smoother(" << prefactor << "," << lambda << "," << distance << ") = " << result);
606 return result;
607}
608
609ManyBodyPotential_Tersoff::result_t
610ManyBodyPotential_Tersoff::function_eta(
611 const argument_t &r_ij
612 ) const
613{
614// Info info(__func__);
615 result_t result = 0.;
616
617 // get all triples within the cutoff
618 std::vector<arguments_t> triples = triplefunction(r_ij, S);
619 for (std::vector<arguments_t>::const_iterator iter = triples.begin();
620 iter != triples.end(); ++iter) {
621 ASSERT( iter->size() == 2,
622 "ManyBodyPotential_Tersoff::function_zeta() - the triples result must contain of exactly two distances.");
623 const argument_t &r_ik = (*iter)[0];
624 result += function_cutoff(r_ik.distance)
625 * exp( Helpers::pow(lambda3 * (r_ij.distance - r_ik.distance) ,3));
626 }
627
628// LOG(2, "DEBUG: function_eta(" << r_ij.distance << ") = " << result);
629 return result;
630}
631
632ManyBodyPotential_Tersoff::result_t
633ManyBodyPotential_Tersoff::function_zeta(
634 const argument_t &r_ij
635 ) const
636{
637// Info info(__func__);
638 result_t result = 0.;
639
640 // get all triples within the cutoff
641 std::vector<arguments_t> triples = triplefunction(r_ij, S);
642 for (std::vector<arguments_t>::const_iterator iter = triples.begin();
643 iter != triples.end(); ++iter) {
644 ASSERT( iter->size() == 2,
645 "ManyBodyPotential_Tersoff::function_zeta() - the triples result must contain exactly two distances.");
646 const argument_t &r_ik = (*iter)[0];
647 const argument_t &r_jk = (*iter)[1];
648 result +=
649 function_cutoff(r_ik.distance)
650 * omega
651 * function_angle(r_ij.distance, r_ik.distance, r_jk.distance)
652 * exp( Helpers::pow(lambda3 * (r_ij.distance - r_ik.distance) ,3));
653 }
654
655// LOG(2, "DEBUG: function_zeta(" << r_ij.distance << ") = " << result);
656 return result;
657}
658
659ManyBodyPotential_Tersoff::result_t
660ManyBodyPotential_Tersoff::function_theta(
661 const double &r_ij,
662 const double &r_ik,
663 const double &r_jk
664 ) const
665{
666 const double angle = Helpers::pow(r_ij,2) + Helpers::pow(r_ik,2) - Helpers::pow(r_jk,2);
667 const double divisor = 2.* r_ij * r_ik;
668 if (divisor != 0.) {
669 LOG(2, "DEBUG: cos(theta)= " << angle/divisor);
670 return angle/divisor;
671 } else
672 return 0.;
673}
674
675ManyBodyPotential_Tersoff::result_t
676ManyBodyPotential_Tersoff::function_angle(
677 const double &r_ij,
678 const double &r_ik,
679 const double &r_jk
680 ) const
681{
682// Info info(__func__);
683 const double result =
684 1.
685 + (Helpers::pow(params[c]/params[d], 2))
686 - Helpers::pow(params[c], 2)/(Helpers::pow(params[d], 2) +
687 Helpers::pow(params[h] - function_theta(r_ij, r_ik, r_jk),2));
688
689// LOG(2, "DEBUG: function_angle(" << r_ij << "," << r_ik << "," << r_jk << ") = " << result);
690 return result;
691}
692
693FunctionModel::extractor_t
694ManyBodyPotential_Tersoff::getSpecificExtractor() const
695{
696 FunctionModel::extractor_t returnfunction =
697 boost::bind(&Extractors::gatherAllDistances,
698 boost::bind(&Fragment::getPositions, _1),
699 boost::bind(&Fragment::getCharges, _1),
700 _2);
701 return returnfunction;
702}
703
704FunctionModel::filter_t ManyBodyPotential_Tersoff::getSpecificFilter() const
705{
706 FunctionModel::filter_t returnfunction =
707 boost::bind(&Extractors::filterArgumentsByParticleTypes,
708 _1,
709 getParticleTypes());
710 return returnfunction;
711}
712
713void
714ManyBodyPotential_Tersoff::setParametersToRandomInitialValues(
715 const TrainingData &data)
716{
717 RandomNumberGenerator &random = RandomNumberGeneratorFactory::getInstance().makeRandomNumberGenerator();
718 const double rng_min = random.min();
719 const double rng_max = random.max();
720// params[ManyBodyPotential_Tersoff::R] = 1./AtomicLengthToAngstroem;
721// params[ManyBodyPotential_Tersoff::S] = 2./AtomicLengthToAngstroem;
722 params[ManyBodyPotential_Tersoff::A] = 1e+4*(random()/(rng_max-rng_min));//1.393600e+03;
723 params[ManyBodyPotential_Tersoff::B] = 1e+4*(random()/(rng_max-rng_min));//3.467000e+02;
724 params[ManyBodyPotential_Tersoff::lambda] = 1e+1*(random()/(rng_max-rng_min));//3.487900e+00;
725 params[ManyBodyPotential_Tersoff::mu] = 1e+1*(random()/(rng_max-rng_min));//2.211900e+00;
726 // params[ManyBodyPotential_Tersoff::lambda3] = 0.;
727 // params[ManyBodyPotential_Tersoff::alpha] = 0.;
728 params[ManyBodyPotential_Tersoff::beta] = 1e-1*(random()/(rng_max-rng_min));//1.572400e-07;
729 // params[ManyBodyPotential_Tersoff::chi] = 1.;
730 // params[ManyBodyPotential_Tersoff::omega] = 1.;
731 params[ManyBodyPotential_Tersoff::n] = 1e+1*(random()/(rng_max-rng_min));//7.275100e-01;
732 params[ManyBodyPotential_Tersoff::c] = 1e+1*(random()/(rng_max-rng_min));//3.804900e+04;
733 params[ManyBodyPotential_Tersoff::d] = 1e+1*(random()/(rng_max-rng_min));//4.384000e+00;
734 params[ManyBodyPotential_Tersoff::h] = 1e+1*(random()/(rng_max-rng_min));//-5.705800e-01;
735}
736
Note: See TracBrowser for help on using the repository browser.