source: src/Potentials/Specifics/ManyBodyPotential_Tersoff.cpp@ 7b019a

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 Candidate_v1.7.0 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 7b019a was 7b019a, checked in by Frederik Heber <heber@…>, 13 years ago

Extended FunctionModel by getFragmentSpecificExtractor() definition.

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