source: src/Potentials/Specifics/ManyBodyPotential_Tersoff.cpp@ 2e9486

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

FIX: Tersoff must sum potential over every of the arguments.

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