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

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

Made PotentialFactory friend of all specific potentials and added default cstor.

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