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

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

All Pair_.. and ManyBodyPotentials are now also derived from SerializablePotential.

  • added static ParameterNames, skipping "energy_offset" which should not go to file.
  • overrode operator<<() and ..>>() for SaturationPotential to print both potentials independently.
  • adapted LevMartest and all unit tests.
  • Property mode set to 100644
File size: 19.4 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
52// static definitions
53const ManyBodyPotential_Tersoff::ParameterNames_t
54ManyBodyPotential_Tersoff::ParameterNames =
55 boost::assign::list_of<std::string>
56 ("A")
57 ("B")
58 ("lambda")
59 ("mu")
60 ("beta")
61 ("n")
62 ("c")
63 ("d")
64 ("h")
65 ("offset")
66// ("R")
67// ("S")
68// ("lambda3")
69// ("alpha")
70// ("chi")
71// ("omega")
72 ;
73const std::string ManyBodyPotential_Tersoff::potential_token("tersoff");
74
75ManyBodyPotential_Tersoff::ManyBodyPotential_Tersoff(
76 const ParticleTypes_t &_ParticleTypes,
77 boost::function< std::vector<arguments_t>(const argument_t &, const double)> &_triplefunction
78 ) :
79 SerializablePotential(_ParticleTypes),
80 params(parameters_t(MAXPARAMS, 0.)),
81 R(3.2),
82 S(3.5),
83 lambda3(0.),
84 alpha(0.),
85 chi(1.),
86 omega(1.),
87 triplefunction(_triplefunction)
88{}
89
90ManyBodyPotential_Tersoff::ManyBodyPotential_Tersoff(
91 const ParticleTypes_t &_ParticleTypes,
92 const double &_R,
93 const double &_S,
94 const double &_A,
95 const double &_B,
96 const double &_lambda,
97 const double &_mu,
98 const double &_lambda3,
99 const double &_alpha,
100 const double &_beta,
101 const double &_chi,
102 const double &_omega,
103 const double &_n,
104 const double &_c,
105 const double &_d,
106 const double &_h,
107 const double &_offset,
108 boost::function< std::vector<arguments_t>(const argument_t &, const double)> &_triplefunction) :
109 SerializablePotential(_ParticleTypes),
110 params(parameters_t(MAXPARAMS, 0.)),
111 R(_R),
112 S(_S),
113 lambda3(_lambda3),
114 alpha(_alpha),
115 chi(_chi),
116 omega(_mu),
117 triplefunction(_triplefunction)
118{
119// Info info(__func__);
120// R = _R;
121// S = _S;
122 params[A] = _A;
123 params[B] = _B;
124 params[lambda] = _lambda;
125 params[mu] = _mu;
126// lambda3 = _lambda3;
127// alpha = _alpha;
128 params[beta] = _beta;
129// chi = _chi;
130// omega = _omega;
131 params[n] = _n;
132 params[c] = _c;
133 params[d] = _d;
134 params[h] = _h;
135 params[offset] = _offset;
136}
137
138void ManyBodyPotential_Tersoff::setParameters(const parameters_t &_params)
139{
140 const size_t paramsDim = _params.size();
141 ASSERT( paramsDim <= getParameterDimension(),
142 "ManyBodyPotential_Tersoff::setParameters() - we need not more than "
143 +toString(getParameterDimension())+" parameters.");
144 for (size_t i=0; i< paramsDim; ++i)
145 params[i] = _params[i];
146
147#ifndef NDEBUG
148 parameters_t check_params(getParameters());
149 check_params.resize(paramsDim); // truncate to same size
150 ASSERT( check_params == _params,
151 "ManyBodyPotential_Tersoff::setParameters() - failed, mismatch in to be set "
152 +toString(_params)+" and set "+toString(check_params)+" params.");
153#endif
154}
155
156ManyBodyPotential_Tersoff::results_t
157ManyBodyPotential_Tersoff::operator()(
158 const arguments_t &arguments
159 ) const
160{
161// Info info(__func__);
162 double result = 0.;
163 for(arguments_t::const_iterator argiter = arguments.begin();
164 argiter != arguments.end();
165 ++argiter) {
166 const argument_t &r_ij = *argiter;
167 const double cutoff = function_cutoff(r_ij.distance);
168 const double temp = (cutoff == 0.) ?
169 0. :
170 cutoff * (
171 function_prefactor(
172 alpha,
173 function_eta(r_ij))
174 * function_smoother(
175 params[A],
176 params[lambda],
177 r_ij.distance)
178 +
179 function_prefactor(
180 params[beta],
181 function_zeta(r_ij))
182 * function_smoother(
183 -params[B],
184 params[mu],
185 r_ij.distance)
186 );
187 result += temp;
188 }
189// LOG(2, "DEBUG: operator()(" << r_ij.distance << ") = " << result);
190 return std::vector<result_t>(1, params[offset]+result);
191}
192
193ManyBodyPotential_Tersoff::derivative_components_t
194ManyBodyPotential_Tersoff::derivative(
195 const arguments_t &arguments
196 ) const
197{
198// Info info(__func__);
199 return ManyBodyPotential_Tersoff::derivative_components_t();
200}
201
202ManyBodyPotential_Tersoff::results_t
203ManyBodyPotential_Tersoff::parameter_derivative(
204 const arguments_t &arguments,
205 const size_t index
206 ) const
207{
208// Info info(__func__);
209// ASSERT( arguments.size() == 1,
210// "ManyBodyPotential_Tersoff::parameter_derivative() - requires exactly one argument.");
211 if (index == offset)
212 return results_t(1, 1.);
213
214 double result = 0.;
215 for(arguments_t::const_iterator argiter = arguments.begin();
216 argiter != arguments.end();
217 ++argiter) {
218 const argument_t &r_ij = *argiter;
219 switch (index) {
220// case R:
221// {
222// result += 0.;
223// break;
224// }
225// case S:
226// {
227// result += 0.;
228// break;
229// }
230 case A:
231 {
232 const double cutoff = function_cutoff(r_ij.distance);
233 result += (cutoff == 0.) ?
234 0. :
235 cutoff *
236 function_prefactor(
237 alpha,
238 function_eta(r_ij))
239 * function_smoother(
240 1.,
241 params[lambda],
242 r_ij.distance);
243// cutoff * function_prefactor(
244// alpha,
245// function_eta(r_ij))
246// * function_smoother(
247// 1.,
248// params[mu],
249// r_ij.distance);
250 break;
251 }
252 case B:
253 {
254 const double cutoff = function_cutoff(r_ij.distance);
255 result += (cutoff == 0.) ?
256 0. :
257 cutoff * function_prefactor(
258 params[beta],
259 function_zeta(r_ij))
260 * function_smoother(
261 -1.,
262 params[mu],
263 r_ij.distance);
264// cutoff * function_prefactor(
265// beta,
266// function_zeta(r_ij))
267// * function_smoother(
268// -params[B],
269// params[mu],
270// r_ij.distance)/params[B];
271 break;
272 }
273 case lambda:
274 {
275 const double cutoff = function_cutoff(r_ij.distance);
276 result += (cutoff == 0.) ?
277 0. :
278 -r_ij.distance * cutoff *
279 function_prefactor(
280 alpha,
281 function_eta(r_ij))
282 * function_smoother(
283 params[A],
284 params[lambda],
285 r_ij.distance);
286 break;
287 }
288 case mu:
289 {
290 const double cutoff = function_cutoff(r_ij.distance);
291 result += (cutoff == 0.) ?
292 0. :
293 -r_ij.distance * cutoff *(
294 function_prefactor(
295 params[beta],
296 function_zeta(r_ij))
297 * function_smoother(
298 -params[B],
299 params[mu],
300 r_ij.distance)
301 );
302 break;
303 }
304// case lambda3:
305// {
306// result += 0.;
307// break;
308// }
309// case alpha:
310// {
311// const double temp =
312// pow(alpha*function_eta(r_ij), params[n]);
313// const double cutoff = function_cutoff(r_ij.distance);
314// result += (cutoff == 0.) || (alpha == 0. )?
315// 0. :
316// function_smoother(
317// params[A],
318// params[lambda],
319// r_ij.distance)
320// * (-.5) * alpha * (temp/alpha)
321// / (1. + temp)
322// ;
323// break;
324// }
325// case chi:
326// {
327// result += 0.;
328// break;
329// }
330// case omega:
331// {
332// result += 0.;
333// break;
334// }
335 case beta:
336 {
337 const double temp =
338 pow(params[beta]*function_zeta(r_ij), params[n]);
339 const double cutoff = function_cutoff(r_ij.distance);
340 result += (cutoff == 0.) || (params[beta] == 0. )?
341 0. : cutoff *
342 function_smoother(
343 -params[B],
344 params[mu],
345 r_ij.distance)
346 * (-.5)
347 * function_prefactor(
348 params[beta],
349 function_zeta(r_ij))
350 * (temp/params[beta])
351 / (1. + temp)
352 ;
353 break;
354 }
355 case n:
356 {
357 const double zeta = function_zeta(r_ij);
358 const double temp = pow( params[beta]*zeta , params[n]);
359 const double cutoff = function_cutoff(r_ij.distance);
360 const double tempres = ((cutoff == 0.) || (zeta == 0.)) ? // zeta must be caught if zero due to log
361 0. : .5 * cutoff *
362 function_smoother(
363 -params[B],
364 params[mu],
365 r_ij.distance)
366 * function_prefactor(
367 params[beta],
368 function_zeta(r_ij))
369 * ( log(1.+temp)/(params[n]*params[n]) - temp
370 * (log(function_zeta(r_ij)) + log(params[beta]))
371 /(params[n]*(1.+temp)))
372 ;
373// if (tempres != tempres)
374// LOG(2, "DEBUG: tempres is NaN.");
375// LOG(2, "DEBUG: Adding " << tempres << " for p.d. w.r.t n, temp=" << temp << ", cutoff=" << cutoff);
376 result += tempres;
377 break;
378 }
379 case c:
380 {
381 const double zeta = function_zeta(r_ij);
382 if (zeta == 0.)
383 break;
384 const double temp =
385 pow(zeta, params[n]-1.) * pow(params[beta],params[n]);
386 const double cutoff = function_cutoff(r_ij.distance);
387 const double tempres = (cutoff == 0.) ?
388 0. : cutoff *
389 function_smoother(
390 -params[B],
391 params[mu],
392 r_ij.distance)
393 * function_prefactor(
394 params[beta],
395 zeta)
396 * (-1.) * temp / (1.+temp*zeta);
397 double factor = function_derivative_c(r_ij);
398 result += tempres*factor;
399 if (result != result)
400 ELOG(1, "result is NaN, zeta=" << zeta << ", temp=" << temp << ", cutoff=" << cutoff << ", tempres=" << tempres << ", factor=" << factor);
401 break;
402 }
403 case d:
404 {
405 const double zeta = function_zeta(r_ij);
406 const double temp =
407 pow(zeta, params[n]-1.) * pow(params[beta],params[n]);
408 const double cutoff = function_cutoff(r_ij.distance);
409 const double tempres = (cutoff == 0.) ?
410 0. : cutoff *
411 function_smoother(
412 -params[B],
413 params[mu],
414 r_ij.distance)
415 * function_prefactor(
416 params[beta],
417 zeta)
418 * (-1.) * temp / (1.+temp*zeta);
419 double factor = function_derivative_d(r_ij);
420 result += tempres*factor;
421 if (result != result)
422 ELOG(1, "result is NaN, zeta=" << zeta << ", temp=" << temp << ", cutoff=" << cutoff << ", tempres=" << tempres << ", factor=" << factor);
423 break;
424 }
425 case h:
426 {
427 const double zeta = function_zeta(r_ij);
428 const double temp =
429 pow(zeta, params[n]-1.) * pow(params[beta],params[n]);
430 const double cutoff = function_cutoff(r_ij.distance);
431 const double tempres = (cutoff == 0.) ?
432 0. : cutoff *
433 function_smoother(
434 -params[B],
435 params[mu],
436 r_ij.distance)
437 * function_prefactor(
438 params[beta],
439 zeta)
440 * (-1.) * temp / (1.+temp*zeta);
441 double factor = function_derivative_h(r_ij);
442 result += tempres*factor;
443 if (result != result)
444 ELOG(1, "result is NaN, zeta=" << zeta << ", temp=" << temp << ", cutoff=" << cutoff << ", tempres=" << tempres << ", factor=" << factor);
445 break;
446 }
447 case offset:
448 result += 1.;
449 break;
450 default:
451 break;
452 }
453 if (result != result)
454 ELOG(1, "result is NaN.");
455 }
456 return results_t(1,-result);
457}
458
459ManyBodyPotential_Tersoff::result_t
460ManyBodyPotential_Tersoff::function_derivative_c(
461 const argument_t &r_ij
462 ) const
463{
464 double result = 0.;
465 std::vector<arguments_t> triples = triplefunction(r_ij, S);
466 for (std::vector<arguments_t>::const_iterator iter = triples.begin();
467 iter != triples.end(); ++iter) {
468 ASSERT( iter->size() == 2,
469 "ManyBodyPotential_Tersoff::function_derivative_c() - the triples result must contain exactly two distances.");
470 const argument_t &r_ik = (*iter)[0];
471 const argument_t &r_jk = (*iter)[1];
472 const double tempangle = params[h] - function_theta(r_ij.distance, r_ik.distance, r_jk.distance);
473 const double cutoff = function_cutoff(r_ik.distance);
474 result += (cutoff == 0.) ?
475 0. : cutoff * omega * exp( Helpers::pow(lambda3 * (r_ij.distance - r_ik.distance) ,3)) * (
476 params[c]/Helpers::pow(params[d],2)
477 - params[c] / ( Helpers::pow(params[d],2) + Helpers::pow(tempangle,2) )
478 );
479 }
480 return result;
481}
482
483ManyBodyPotential_Tersoff::result_t
484ManyBodyPotential_Tersoff::function_derivative_d(
485 const argument_t &r_ij
486 ) const
487{
488 double result = 0.;
489 std::vector<arguments_t> triples = triplefunction(r_ij, S);
490 for (std::vector<arguments_t>::const_iterator iter = triples.begin();
491 iter != triples.end(); ++iter) {
492 ASSERT( iter->size() == 2,
493 "ManyBodyPotential_Tersoff::function_derivative_d() - the triples result must contain exactly two distances.");
494 const argument_t &r_ik = (*iter)[0];
495 const argument_t &r_jk = (*iter)[1];
496 const double tempangle = params[h] - function_theta(r_ij.distance, r_ik.distance, r_jk.distance);
497 const double cutoff = function_cutoff(r_ik.distance);
498 result += (cutoff == 0.) ?
499 0. : cutoff * omega * exp( Helpers::pow(lambda3 * (r_ij.distance - r_ik.distance) ,3)) * (
500 - Helpers::pow(params[c],2)/Helpers::pow(params[d],3)
501 + Helpers::pow(params[c],2) * params[d]
502 / Helpers::pow(Helpers::pow(params[d],2) + Helpers::pow(tempangle,2),2)
503 );
504 }
505 return result;
506}
507
508ManyBodyPotential_Tersoff::result_t
509ManyBodyPotential_Tersoff::function_derivative_h(
510 const argument_t &r_ij
511 ) const
512{
513 double result = 0.;
514 std::vector<arguments_t> triples = triplefunction(r_ij, S);
515 for (std::vector<arguments_t>::const_iterator iter = triples.begin();
516 iter != triples.end(); ++iter) {
517 ASSERT( iter->size() == 2,
518 "ManyBodyPotential_Tersoff::function_derivative_h() - the triples result must contain exactly two distances.");
519 const argument_t &r_ik = (*iter)[0];
520 const argument_t &r_jk = (*iter)[1];
521 const double tempangle = params[h] - function_theta(r_ij.distance, r_ik.distance, r_jk.distance);
522 const double cutoff = function_cutoff(r_ik.distance);
523 result += (cutoff == 0.) ?
524 0. : cutoff * omega * exp( Helpers::pow(lambda3 * (r_ij.distance - r_ik.distance) ,3)) * (
525 ( Helpers::pow(params[c],2)*tempangle )
526 / Helpers::pow(Helpers::pow(params[d],2) + Helpers::pow(tempangle,2),2)
527 );
528 }
529 return result;
530}
531
532ManyBodyPotential_Tersoff::result_t
533ManyBodyPotential_Tersoff::function_cutoff(
534 const double &distance
535 ) const
536{
537// Info info(__func__);
538 double result = 0.;
539 if (distance < R)
540 result = 1.;
541 else if (distance > S)
542 result = 0.;
543 else {
544 result = (0.5 + 0.5 * cos( M_PI * (distance - R)/(S-R)));
545 }
546// LOG(2, "DEBUG: function_cutoff(" << distance << ") = " << result);
547 return result;
548}
549
550ManyBodyPotential_Tersoff::result_t
551ManyBodyPotential_Tersoff::function_prefactor(
552 const double &alpha,
553 const double &eta
554 ) const
555{
556// Info info(__func__);
557 const double result = chi * pow(
558 (1. + pow(alpha * eta, params[n])),
559 -1./(2.*params[n]));
560// LOG(2, "DEBUG: function_prefactor(" << alpha << "," << eta << ") = " << result);
561 return result;
562}
563
564ManyBodyPotential_Tersoff::result_t
565ManyBodyPotential_Tersoff::function_smoother(
566 const double &prefactor,
567 const double &lambda,
568 const double &distance
569 ) const
570{
571// Info info(__func__);
572 const double result = prefactor * exp(-lambda * distance);
573// LOG(2, "DEBUG: function_smoother(" << prefactor << "," << lambda << "," << distance << ") = " << result);
574 return result;
575}
576
577ManyBodyPotential_Tersoff::result_t
578ManyBodyPotential_Tersoff::function_eta(
579 const argument_t &r_ij
580 ) const
581{
582// Info info(__func__);
583 result_t result = 0.;
584
585 // get all triples within the cutoff
586 std::vector<arguments_t> triples = triplefunction(r_ij, S);
587 for (std::vector<arguments_t>::const_iterator iter = triples.begin();
588 iter != triples.end(); ++iter) {
589 ASSERT( iter->size() == 2,
590 "ManyBodyPotential_Tersoff::function_zeta() - the triples result must contain of exactly two distances.");
591 const argument_t &r_ik = (*iter)[0];
592 result += function_cutoff(r_ik.distance)
593 * exp( Helpers::pow(lambda3 * (r_ij.distance - r_ik.distance) ,3));
594 }
595
596// LOG(2, "DEBUG: function_eta(" << r_ij.distance << ") = " << result);
597 return result;
598}
599
600ManyBodyPotential_Tersoff::result_t
601ManyBodyPotential_Tersoff::function_zeta(
602 const argument_t &r_ij
603 ) const
604{
605// Info info(__func__);
606 result_t result = 0.;
607
608 // get all triples within the cutoff
609 std::vector<arguments_t> triples = triplefunction(r_ij, S);
610 for (std::vector<arguments_t>::const_iterator iter = triples.begin();
611 iter != triples.end(); ++iter) {
612 ASSERT( iter->size() == 2,
613 "ManyBodyPotential_Tersoff::function_zeta() - the triples result must contain exactly two distances.");
614 const argument_t &r_ik = (*iter)[0];
615 const argument_t &r_jk = (*iter)[1];
616 result +=
617 function_cutoff(r_ik.distance)
618 * omega
619 * function_angle(r_ij.distance, r_ik.distance, r_jk.distance)
620 * exp( Helpers::pow(lambda3 * (r_ij.distance - r_ik.distance) ,3));
621 }
622
623// LOG(2, "DEBUG: function_zeta(" << r_ij.distance << ") = " << result);
624 return result;
625}
626
627ManyBodyPotential_Tersoff::result_t
628ManyBodyPotential_Tersoff::function_theta(
629 const double &r_ij,
630 const double &r_ik,
631 const double &r_jk
632 ) const
633{
634 const double angle = Helpers::pow(r_ij,2) + Helpers::pow(r_ik,2) - Helpers::pow(r_jk,2);
635 const double divisor = 2.* r_ij * r_ik;
636 if (divisor != 0.) {
637 LOG(2, "DEBUG: cos(theta)= " << angle/divisor);
638 return angle/divisor;
639 } else
640 return 0.;
641}
642
643ManyBodyPotential_Tersoff::result_t
644ManyBodyPotential_Tersoff::function_angle(
645 const double &r_ij,
646 const double &r_ik,
647 const double &r_jk
648 ) const
649{
650// Info info(__func__);
651 const double result =
652 1.
653 + (Helpers::pow(params[c]/params[d], 2))
654 - Helpers::pow(params[c], 2)/(Helpers::pow(params[d], 2) +
655 Helpers::pow(params[h] - function_theta(r_ij, r_ik, r_jk),2));
656
657// LOG(2, "DEBUG: function_angle(" << r_ij << "," << r_ik << "," << r_jk << ") = " << result);
658 return result;
659}
660
Note: See TracBrowser for help on using the repository browser.