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

Action_Thermostats Add_AtomRandomPerturbation Add_RotateAroundBondAction Add_SelectAtomByNameAction Adding_Graph_to_ChangeBondActions Adding_MD_integration_tests Adding_StructOpt_integration_tests Automaking_mpqc_open AutomationFragmentation_failures Candidate_v1.6.0 Candidate_v1.6.1 ChangeBugEmailaddress ChangingTestPorts ChemicalSpaceEvaluator 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_ChronosMutex Fix_StatusMsg Fix_StepWorldTime_single_argument Fix_Verbose_Codepatterns ForceAnnealing_goodresults ForceAnnealing_oldresults ForceAnnealing_tocheck ForceAnnealing_with_BondGraph ForceAnnealing_with_BondGraph_continued ForceAnnealing_with_BondGraph_continued_betteresults ForceAnnealing_with_BondGraph_contraction-expansion GeometryObjects Gui_displays_atomic_force_velocity IndependentFragmentGrids_IntegrationTest JobMarket_RobustOnKillsSegFaults JobMarket_StableWorkerPool JobMarket_unresolvable_hostname_fix ODR_violation_mpqc_open PartialCharges_OrthogonalSummation PythonUI_with_named_parameters QtGui_reactivate_TimeChanged_changes Recreated_GuiChecks RotateToPrincipalAxisSystem_UndoRedo StoppableMakroAction Subpackage_CodePatterns Subpackage_JobMarket Subpackage_LinearAlgebra Subpackage_levmar Subpackage_mpqc_open Subpackage_vmg ThirdParty_MPQC_rebuilt_buildsystem TremoloParser_IncreasedPrecision TremoloParser_MultipleTimesteps Ubuntu_1604_changes stable
Last change on this file since e60558 was e60558, checked in by Frederik Heber <heber@…>, 8 years ago

Extractors require additionally the binding graph of the fragment itself.

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