source: src/Potentials/Specifics/ManyBodyPotential_Tersoff.cpp@ caa00e9

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 caa00e9 was dbf8c8, checked in by Frederik Heber <heber@…>, 12 years ago

FIX: Now default parameters are present for every potential and used for check_derivatives.

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