ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE-4/src/UseTheForce/DarkSide/eam.F90
Revision: 3440
Committed: Thu Jul 31 19:10:47 2008 UTC (17 years, 1 month ago) by gezelter
File size: 20146 byte(s)
Log Message:
fixed a missing F[\rho] error for calculating
particle potentials in the many body force fields

File Contents

# Content
1 !!
2 !! Copyright (c) 2005 The University of Notre Dame. All Rights Reserved.
3 !!
4 !! The University of Notre Dame grants you ("Licensee") a
5 !! non-exclusive, royalty free, license to use, modify and
6 !! redistribute this software in source and binary code form, provided
7 !! that the following conditions are met:
8 !!
9 !! 1. Acknowledgement of the program authors must be made in any
10 !! publication of scientific results based in part on use of the
11 !! program. An acceptable form of acknowledgement is citation of
12 !! the article in which the program was described (Matthew
13 !! A. Meineke, Charles F. Vardeman II, Teng Lin, Christopher
14 !! J. Fennell and J. Daniel Gezelter, "OOPSE: An Object-Oriented
15 !! Parallel Simulation Engine for Molecular Dynamics,"
16 !! J. Comput. Chem. 26, pp. 252-271 (2005))
17 !!
18 !! 2. Redistributions of source code must retain the above copyright
19 !! notice, this list of conditions and the following disclaimer.
20 !!
21 !! 3. Redistributions in binary form must reproduce the above copyright
22 !! notice, this list of conditions and the following disclaimer in the
23 !! documentation and/or other materials provided with the
24 !! distribution.
25 !!
26 !! This software is provided "AS IS," without a warranty of any
27 !! kind. All express or implied conditions, representations and
28 !! warranties, including any implied warranty of merchantability,
29 !! fitness for a particular purpose or non-infringement, are hereby
30 !! excluded. The University of Notre Dame and its licensors shall not
31 !! be liable for any damages suffered by licensee as a result of
32 !! using, modifying or distributing the software or its
33 !! derivatives. In no event will the University of Notre Dame or its
34 !! licensors be liable for any lost revenue, profit or data, or for
35 !! direct, indirect, special, consequential, incidental or punitive
36 !! damages, however caused and regardless of the theory of liability,
37 !! arising out of the use of or inability to use software, even if the
38 !! University of Notre Dame has been advised of the possibility of
39 !! such damages.
40 !!
41
42 module eam
43 use definitions
44 use simulation
45 use force_globals
46 use status
47 use atype_module
48 use vector_class
49 use interpolation
50 #ifdef IS_MPI
51 use mpiSimulation
52 #endif
53 implicit none
54 PRIVATE
55 #define __FORTRAN90
56 #include "UseTheForce/DarkSide/fInteractionMap.h"
57
58 logical, save :: EAM_FF_initialized = .false.
59 integer, save :: EAM_Mixing_Policy
60 real(kind = dp), save :: EAM_rcut
61 logical, save :: haveRcut = .false.
62
63 character(len = statusMsgSize) :: errMesg
64 integer :: eam_err
65
66 character(len = 200) :: errMsg
67 character(len=*), parameter :: RoutineName = "EAM MODULE"
68 !! Logical that determines if eam arrays should be zeroed
69 logical :: cleanme = .true.
70
71 type, private :: EAMtype
72 integer :: eam_atype
73 real( kind = DP ) :: eam_lattice
74 real( kind = DP ) :: eam_rcut
75 integer :: eam_atype_map
76 type(cubicSpline) :: rho
77 type(cubicSpline) :: Z
78 type(cubicSpline) :: F
79 type(cubicSpline) :: phi
80 end type EAMtype
81
82 !! Arrays for derivatives used in force calculation
83 real( kind = dp), dimension(:), allocatable :: frho
84 real( kind = dp), dimension(:), allocatable :: rho
85 real( kind = dp), dimension(:), allocatable :: dfrhodrho
86
87 !! Arrays for MPI storage
88 #ifdef IS_MPI
89 real( kind = dp),save, dimension(:), allocatable :: dfrhodrho_col
90 real( kind = dp),save, dimension(:), allocatable :: dfrhodrho_row
91 real( kind = dp),save, dimension(:), allocatable :: frho_row
92 real( kind = dp),save, dimension(:), allocatable :: frho_col
93 real( kind = dp),save, dimension(:), allocatable :: rho_row
94 real( kind = dp),save, dimension(:), allocatable :: rho_col
95 real( kind = dp),save, dimension(:), allocatable :: rho_tmp
96 #endif
97
98 type, private :: EAMTypeList
99 integer :: n_eam_types = 0
100 integer :: currentAddition = 0
101
102 type (EAMtype), pointer :: EAMParams(:) => null()
103 integer, pointer :: atidToEAMType(:) => null()
104 end type EAMTypeList
105
106 type (eamTypeList), save :: EAMList
107
108 !! standard eam stuff
109
110
111 public :: init_EAM_FF
112 public :: setCutoffEAM
113 public :: do_eam_pair
114 public :: newEAMtype
115 public :: calc_eam_prepair_rho
116 public :: calc_eam_preforce_Frho
117 public :: clean_EAM
118 public :: destroyEAMTypes
119 public :: getEAMCut
120 public :: lookupEAMSpline
121 public :: lookupEAMSpline1d
122
123 contains
124
125 subroutine newEAMtype(lattice_constant,eam_nrho,eam_drho,eam_nr,&
126 eam_dr,rcut,eam_Z_r,eam_rho_r,eam_F_rho, c_ident, status)
127 real (kind = dp ) :: lattice_constant
128 integer :: eam_nrho
129 real (kind = dp ) :: eam_drho
130 integer :: eam_nr
131 real (kind = dp ) :: eam_dr
132 real (kind = dp ) :: rcut
133 real (kind = dp ), dimension(eam_nr) :: eam_Z_r, rvals
134 real (kind = dp ), dimension(eam_nr) :: eam_rho_r, eam_phi_r
135 real (kind = dp ), dimension(eam_nrho) :: eam_F_rho, rhovals
136 integer :: c_ident
137 integer :: status
138
139 integer :: nAtypes,nEAMTypes,myATID
140 integer :: maxVals
141 integer :: alloc_stat
142 integer :: current, j
143 integer,pointer :: Matchlist(:) => null()
144
145 status = 0
146
147 !! Assume that atypes has already been set and get the total number of types in atypes
148 !! Also assume that every member of atypes is a EAM model.
149
150 ! check to see if this is the first time into
151 if (.not.associated(EAMList%EAMParams)) then
152 call getMatchingElementList(atypes, "is_EAM", .true., nEAMtypes, MatchList)
153 EAMList%n_eam_types = nEAMtypes
154 allocate(EAMList%EAMParams(nEAMTypes))
155 nAtypes = getSize(atypes)
156 allocate(EAMList%atidToEAMType(nAtypes))
157 end if
158
159 EAMList%currentAddition = EAMList%currentAddition + 1
160 current = EAMList%currentAddition
161
162 myATID = getFirstMatchingElement(atypes, "c_ident", c_ident)
163 EAMList%atidToEAMType(myATID) = current
164
165 EAMList%EAMParams(current)%eam_atype = c_ident
166 EAMList%EAMParams(current)%eam_lattice = lattice_constant
167 EAMList%EAMParams(current)%eam_rcut = rcut
168
169 ! Build array of r values
170 do j = 1, eam_nr
171 rvals(j) = real(j-1,kind=dp) * eam_dr
172 end do
173
174 ! Build array of rho values
175 do j = 1, eam_nrho
176 rhovals(j) = real(j-1,kind=dp) * eam_drho
177 end do
178
179 ! convert from eV to kcal / mol:
180 do j = 1, eam_nrho
181 eam_F_rho(j) = eam_F_rho(j) * 23.06054E0_DP
182 end do
183
184 ! precompute the pair potential and get it into kcal / mol:
185 eam_phi_r(1) = 0.0E0_DP
186 do j = 2, eam_nr
187 eam_phi_r(j) = 331.999296E0_DP * (eam_Z_r(j)**2) / rvals(j)
188 enddo
189
190 call newSpline(EAMList%EAMParams(current)%rho, rvals, eam_rho_r, .true.)
191 call newSpline(EAMList%EAMParams(current)%Z, rvals, eam_Z_r, .true.)
192 call newSpline(EAMList%EAMParams(current)%F, rhovals, eam_F_rho, .true.)
193 call newSpline(EAMList%EAMParams(current)%phi, rvals, eam_phi_r, .true.)
194 end subroutine newEAMtype
195
196
197 ! kills all eam types entered and sets simulation to uninitalized
198 subroutine destroyEAMtypes()
199 integer :: i
200 type(EAMType), pointer :: tempEAMType=>null()
201
202 do i = 1, EAMList%n_eam_types
203 tempEAMType => eamList%EAMParams(i)
204 call deallocate_EAMType(tempEAMType)
205 end do
206 if(associated( eamList%EAMParams)) deallocate( eamList%EAMParams)
207 eamList%EAMParams => null()
208
209 eamList%n_eam_types = 0
210 eamList%currentAddition = 0
211 end subroutine destroyEAMtypes
212
213 function getEAMCut(atomID) result(cutValue)
214 integer, intent(in) :: atomID
215 integer :: eamID
216 real(kind=dp) :: cutValue
217
218 eamID = EAMList%atidToEAMType(atomID)
219 cutValue = EAMList%EAMParams(eamID)%eam_rcut
220 end function getEAMCut
221
222 subroutine init_EAM_FF(status)
223 integer :: status
224 integer :: i,j
225 real(kind=dp) :: current_rcut_max
226 #ifdef IS_MPI
227 integer :: nAtomsInRow
228 integer :: nAtomsInCol
229 #endif
230 integer :: alloc_stat
231 integer :: number_r, number_rho
232
233 status = 0
234 if (EAMList%currentAddition == 0) then
235 call handleError("init_EAM_FF","No members in EAMList")
236 status = -1
237 return
238 end if
239
240 !! Allocate arrays for force calculation
241
242 #ifdef IS_MPI
243 nAtomsInRow = getNatomsInRow(plan_atom_row)
244 nAtomsInCol = getNatomsInCol(plan_atom_col)
245 #endif
246
247 if (allocated(frho)) deallocate(frho)
248 allocate(frho(nlocal),stat=alloc_stat)
249 if (alloc_stat /= 0) then
250 status = -1
251 return
252 end if
253
254 if (allocated(rho)) deallocate(rho)
255 allocate(rho(nlocal),stat=alloc_stat)
256 if (alloc_stat /= 0) then
257 status = -1
258 return
259 end if
260
261 if (allocated(dfrhodrho)) deallocate(dfrhodrho)
262 allocate(dfrhodrho(nlocal),stat=alloc_stat)
263 if (alloc_stat /= 0) then
264 status = -1
265 return
266 end if
267
268 #ifdef IS_MPI
269
270 if (allocated(rho_tmp)) deallocate(rho_tmp)
271 allocate(rho_tmp(nlocal),stat=alloc_stat)
272 if (alloc_stat /= 0) then
273 status = -1
274 return
275 end if
276
277 if (allocated(frho_row)) deallocate(frho_row)
278 allocate(frho_row(nAtomsInRow),stat=alloc_stat)
279 if (alloc_stat /= 0) then
280 status = -1
281 return
282 end if
283 if (allocated(rho_row)) deallocate(rho_row)
284 allocate(rho_row(nAtomsInRow),stat=alloc_stat)
285 if (alloc_stat /= 0) then
286 status = -1
287 return
288 end if
289 if (allocated(dfrhodrho_row)) deallocate(dfrhodrho_row)
290 allocate(dfrhodrho_row(nAtomsInRow),stat=alloc_stat)
291 if (alloc_stat /= 0) then
292 status = -1
293 return
294 end if
295
296 ! Now do column arrays
297
298 if (allocated(frho_col)) deallocate(frho_col)
299 allocate(frho_col(nAtomsInCol),stat=alloc_stat)
300 if (alloc_stat /= 0) then
301 status = -1
302 return
303 end if
304 if (allocated(rho_col)) deallocate(rho_col)
305 allocate(rho_col(nAtomsInCol),stat=alloc_stat)
306 if (alloc_stat /= 0) then
307 status = -1
308 return
309 end if
310 if (allocated(dfrhodrho_col)) deallocate(dfrhodrho_col)
311 allocate(dfrhodrho_col(nAtomsInCol),stat=alloc_stat)
312 if (alloc_stat /= 0) then
313 status = -1
314 return
315 end if
316
317 #endif
318
319 end subroutine init_EAM_FF
320
321 subroutine setCutoffEAM(rcut)
322 real(kind=dp) :: rcut
323 EAM_rcut = rcut
324 end subroutine setCutoffEAM
325
326 subroutine clean_EAM()
327
328 ! clean non-IS_MPI first
329 frho = 0.0_dp
330 rho = 0.0_dp
331 dfrhodrho = 0.0_dp
332 ! clean MPI if needed
333 #ifdef IS_MPI
334 frho_row = 0.0_dp
335 frho_col = 0.0_dp
336 rho_row = 0.0_dp
337 rho_col = 0.0_dp
338 rho_tmp = 0.0_dp
339 dfrhodrho_row = 0.0_dp
340 dfrhodrho_col = 0.0_dp
341 #endif
342 end subroutine clean_EAM
343
344 subroutine deallocate_EAMType(thisEAMType)
345 type (EAMtype), pointer :: thisEAMType
346
347 call deleteSpline(thisEAMType%F)
348 call deleteSpline(thisEAMType%rho)
349 call deleteSpline(thisEAMType%phi)
350 call deleteSpline(thisEAMType%Z)
351
352 end subroutine deallocate_EAMType
353
354 !! Calculates rho_r
355 subroutine calc_eam_prepair_rho(atom1,atom2,d,r,rijsq)
356 integer :: atom1, atom2
357 real(kind = dp), dimension(3) :: d
358 real(kind = dp), intent(inout) :: r
359 real(kind = dp), intent(inout) :: rijsq
360 ! value of electron density rho do to atom i at atom j
361 real(kind = dp) :: rho_i_at_j
362 ! value of electron density rho do to atom j at atom i
363 real(kind = dp) :: rho_j_at_i
364 integer :: eam_err
365
366 integer :: atid1, atid2 ! Global atid
367 integer :: myid_atom1 ! EAM atid
368 integer :: myid_atom2
369
370 ! check to see if we need to be cleaned at the start of a force loop
371
372 #ifdef IS_MPI
373 Atid1 = Atid_row(Atom1)
374 Atid2 = Atid_col(Atom2)
375 #else
376 Atid1 = Atid(Atom1)
377 Atid2 = Atid(Atom2)
378 #endif
379
380 Myid_atom1 = Eamlist%atidtoeamtype(Atid1)
381 Myid_atom2 = Eamlist%atidtoeamtype(Atid2)
382
383 if (r.lt.EAMList%EAMParams(myid_atom1)%eam_rcut) then
384
385 call lookupEAMSpline(EAMList%EAMParams(myid_atom1)%rho, r, &
386 rho_i_at_j)
387
388 #ifdef IS_MPI
389 rho_col(atom2) = rho_col(atom2) + rho_i_at_j
390 #else
391 rho(atom2) = rho(atom2) + rho_i_at_j
392 #endif
393 endif
394
395 if (r.lt.EAMList%EAMParams(myid_atom2)%eam_rcut) then
396
397 call lookupEAMSpline(EAMList%EAMParams(myid_atom2)%rho, r, &
398 rho_j_at_i)
399
400 #ifdef IS_MPI
401 rho_row(atom1) = rho_row(atom1) + rho_j_at_i
402 #else
403 rho(atom1) = rho(atom1) + rho_j_at_i
404 #endif
405 endif
406 end subroutine calc_eam_prepair_rho
407
408
409 !! Calculate the functional F(rho) for all local atoms
410 subroutine calc_eam_preforce_Frho(nlocal, pot, particle_pot)
411 integer :: nlocal
412 real(kind=dp) :: pot
413 integer :: i, j
414 integer :: atom
415 real(kind=dp) :: U,U1
416 real( kind = dp ), dimension(nlocal) :: particle_pot
417 integer :: atype1
418 integer :: me, atid1
419
420 cleanme = .true.
421 !! Scatter the electron density from pre-pair calculation back to
422 !! local atoms
423 #ifdef IS_MPI
424 call scatter(rho_row,rho,plan_atom_row,eam_err)
425 if (eam_err /= 0 ) then
426 write(errMsg,*) " Error scattering rho_row into rho"
427 call handleError(RoutineName,errMesg)
428 endif
429 call scatter(rho_col,rho_tmp,plan_atom_col,eam_err)
430 if (eam_err /= 0 ) then
431 write(errMsg,*) " Error scattering rho_col into rho"
432 call handleError(RoutineName,errMesg)
433 endif
434
435 rho(1:nlocal) = rho(1:nlocal) + rho_tmp(1:nlocal)
436 #endif
437
438 !! Calculate F(rho) and derivative
439 do atom = 1, nlocal
440 atid1 = atid(atom)
441 me = eamList%atidToEAMtype(atid1)
442
443 call lookupEAMSpline1d(EAMList%EAMParams(me)%F, rho(atom), &
444 u, u1)
445
446 frho(atom) = u
447 dfrhodrho(atom) = u1
448 pot = pot + u
449 particle_pot(atom) = particle_pot(atom) + u
450
451 enddo
452
453 #ifdef IS_MPI
454 !! communicate f(rho) and derivatives back into row and column arrays
455 call gather(frho,frho_row,plan_atom_row, eam_err)
456 if (eam_err /= 0) then
457 call handleError("cal_eam_forces()","MPI gather frho_row failure")
458 endif
459 call gather(dfrhodrho,dfrhodrho_row,plan_atom_row, eam_err)
460 if (eam_err /= 0) then
461 call handleError("cal_eam_forces()","MPI gather dfrhodrho_row failure")
462 endif
463 call gather(frho,frho_col,plan_atom_col, eam_err)
464 if (eam_err /= 0) then
465 call handleError("cal_eam_forces()","MPI gather frho_col failure")
466 endif
467 call gather(dfrhodrho,dfrhodrho_col,plan_atom_col, eam_err)
468 if (eam_err /= 0) then
469 call handleError("cal_eam_forces()","MPI gather dfrhodrho_col failure")
470 endif
471 #endif
472
473
474 end subroutine calc_eam_preforce_Frho
475
476 !! Does EAM pairwise Force calculation.
477 subroutine do_eam_pair(atom1, atom2, d, rij, r2, sw, vpair, fpair, &
478 pot, f, do_pot)
479 !Arguments
480 integer, intent(in) :: atom1, atom2
481 real( kind = dp ), intent(in) :: rij, r2
482 real( kind = dp ) :: pot, sw, vpair
483 real( kind = dp ), dimension(3,nLocal) :: f
484 real( kind = dp ), intent(in), dimension(3) :: d
485 real( kind = dp ), intent(inout), dimension(3) :: fpair
486
487 logical, intent(in) :: do_pot
488
489 real( kind = dp ) :: drdx, drdy, drdz
490 real( kind = dp ) :: phab, pha, dvpdr
491 real( kind = dp ) :: rha, drha, dpha
492 real( kind = dp ) :: rhb, drhb, dphb
493 real( kind = dp ) :: dudr
494 real( kind = dp ) :: rci, rcj
495 real( kind = dp ) :: drhoidr, drhojdr
496 real( kind = dp ) :: Fx, Fy, Fz
497 real( kind = dp ) :: r, phb
498
499 integer :: id1, id2
500 integer :: mytype_atom1
501 integer :: mytype_atom2
502 integer :: atid1, atid2
503
504 phab = 0.0E0_DP
505 dvpdr = 0.0E0_DP
506
507 if (rij .lt. EAM_rcut) then
508
509 #ifdef IS_MPI
510 atid1 = atid_row(atom1)
511 atid2 = atid_col(atom2)
512 #else
513 atid1 = atid(atom1)
514 atid2 = atid(atom2)
515 #endif
516
517 mytype_atom1 = EAMList%atidToEAMType(atid1)
518 mytype_atom2 = EAMList%atidTOEAMType(atid2)
519
520
521 ! get cutoff for atom 1
522 rci = EAMList%EAMParams(mytype_atom1)%eam_rcut
523 ! get type specific cutoff for atom 2
524 rcj = EAMList%EAMParams(mytype_atom2)%eam_rcut
525
526 drdx = d(1)/rij
527 drdy = d(2)/rij
528 drdz = d(3)/rij
529
530 if (rij.lt.rci) then
531
532 ! Calculate rho and drho for atom1
533
534 call lookupEAMSpline1d(EAMList%EAMParams(mytype_atom1)%rho, &
535 rij, rha, drha)
536
537 ! Calculate Phi(r) for atom1.
538
539 call lookupEAMSpline1d(EAMList%EAMParams(mytype_atom1)%phi, &
540 rij, pha, dpha)
541
542 endif
543
544 if (rij.lt.rcj) then
545
546 ! Calculate rho and drho for atom2
547
548 call lookupEAMSpline1d(EAMList%EAMParams(mytype_atom2)%rho, &
549 rij, rhb, drhb)
550
551 ! Calculate Phi(r) for atom2.
552
553 call lookupEAMSpline1d(EAMList%EAMParams(mytype_atom2)%phi, &
554 rij, phb, dphb)
555
556 endif
557
558 if (rij.lt.rci) then
559 phab = phab + 0.5E0_DP*(rhb/rha)*pha
560 dvpdr = dvpdr + 0.5E0_DP*((rhb/rha)*dpha + &
561 pha*((drhb/rha) - (rhb*drha/rha/rha)))
562 endif
563
564 if (rij.lt.rcj) then
565 phab = phab + 0.5E0_DP*(rha/rhb)*phb
566 dvpdr = dvpdr + 0.5E0_DP*((rha/rhb)*dphb + &
567 phb*((drha/rhb) - (rha*drhb/rhb/rhb)))
568 endif
569
570 drhoidr = drha
571 drhojdr = drhb
572
573 #ifdef IS_MPI
574 dudr = drhojdr*dfrhodrho_row(atom1)+drhoidr*dfrhodrho_col(atom2) &
575 + dvpdr
576
577 #else
578 dudr = drhojdr*dfrhodrho(atom1)+drhoidr*dfrhodrho(atom2) &
579 + dvpdr
580 #endif
581
582 fx = dudr * drdx
583 fy = dudr * drdy
584 fz = dudr * drdz
585
586
587 #ifdef IS_MPI
588 if (do_pot) then
589 pot_Row(METALLIC_POT,atom1) = pot_Row(METALLIC_POT,atom1) + phab*0.5
590 pot_Col(METALLIC_POT,atom2) = pot_Col(METALLIC_POT,atom2) + phab*0.5
591 end if
592
593 f_Row(1,atom1) = f_Row(1,atom1) + fx
594 f_Row(2,atom1) = f_Row(2,atom1) + fy
595 f_Row(3,atom1) = f_Row(3,atom1) + fz
596
597 f_Col(1,atom2) = f_Col(1,atom2) - fx
598 f_Col(2,atom2) = f_Col(2,atom2) - fy
599 f_Col(3,atom2) = f_Col(3,atom2) - fz
600 #else
601
602 if(do_pot) then
603 pot = pot + phab
604 end if
605
606 f(1,atom1) = f(1,atom1) + fx
607 f(2,atom1) = f(2,atom1) + fy
608 f(3,atom1) = f(3,atom1) + fz
609
610 f(1,atom2) = f(1,atom2) - fx
611 f(2,atom2) = f(2,atom2) - fy
612 f(3,atom2) = f(3,atom2) - fz
613 #endif
614
615 vpair = vpair + phab
616
617 #ifdef IS_MPI
618 id1 = AtomRowToGlobal(atom1)
619 id2 = AtomColToGlobal(atom2)
620 #else
621 id1 = atom1
622 id2 = atom2
623 #endif
624
625 if (molMembershipList(id1) .ne. molMembershipList(id2)) then
626
627 fpair(1) = fpair(1) + fx
628 fpair(2) = fpair(2) + fy
629 fpair(3) = fpair(3) + fz
630
631 endif
632 endif
633 end subroutine do_eam_pair
634
635 subroutine lookupEAMSpline(cs, xval, yval)
636
637 implicit none
638
639 type (cubicSpline), intent(in) :: cs
640 real( kind = DP ), intent(in) :: xval
641 real( kind = DP ), intent(out) :: yval
642 real( kind = DP ) :: dx
643 integer :: i, j
644 !
645 ! Find the interval J = [ cs%x(J), cs%x(J+1) ] that contains
646 ! or is nearest to xval.
647
648 j = MAX(1, MIN(cs%n-1, int((xval-cs%x(1)) * cs%dx_i) + 1))
649
650 dx = xval - cs%x(j)
651 yval = cs%y(j) + dx*(cs%b(j) + dx*(cs%c(j) + dx*cs%d(j)))
652
653 return
654 end subroutine lookupEAMSpline
655
656 subroutine lookupEAMSpline1d(cs, xval, yval, dydx)
657
658 implicit none
659
660 type (cubicSpline), intent(in) :: cs
661 real( kind = DP ), intent(in) :: xval
662 real( kind = DP ), intent(out) :: yval, dydx
663 real( kind = DP ) :: dx
664 integer :: i, j
665
666 ! Find the interval J = [ cs%x(J), cs%x(J+1) ] that contains
667 ! or is nearest to xval.
668
669
670 j = MAX(1, MIN(cs%n-1, int((xval-cs%x(1)) * cs%dx_i) + 1))
671
672 dx = xval - cs%x(j)
673 yval = cs%y(j) + dx*(cs%b(j) + dx*(cs%c(j) + dx*cs%d(j)))
674
675 dydx = cs%b(j) + dx*(2.0d0 * cs%c(j) + 3.0d0 * dx * cs%d(j))
676
677 return
678 end subroutine lookupEAMSpline1d
679
680 end module eam