ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/OpenMD/trunk/src/UseTheForce/DarkSide/eam.F90
Revision: 1386
Committed: Fri Oct 23 18:41:09 2009 UTC (15 years, 9 months ago) by gezelter
File size: 21096 byte(s)
Log Message:
removing MPI responsibilities from the lowest level force routines.  This is
in preparation for migrating these routines (LJ, electrostatic, eam, suttonchen,
gay-berne, sticky) to C++

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,Atid1,Atid2,d,r,rijsq)
356 integer :: atom1, atom2, Atid1, Atid2
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 :: myid_atom1 ! EAM atid
367 integer :: myid_atom2
368
369 ! check to see if we need to be cleaned at the start of a force loop
370
371 Myid_atom1 = Eamlist%atidtoeamtype(Atid1)
372 Myid_atom2 = Eamlist%atidtoeamtype(Atid2)
373
374 if (r.lt.EAMList%EAMParams(myid_atom1)%eam_rcut) then
375
376 call lookupEAMSpline(EAMList%EAMParams(myid_atom1)%rho, r, &
377 rho_i_at_j)
378
379 #ifdef IS_MPI
380 rho_col(atom2) = rho_col(atom2) + rho_i_at_j
381 #else
382 rho(atom2) = rho(atom2) + rho_i_at_j
383 #endif
384 endif
385
386 if (r.lt.EAMList%EAMParams(myid_atom2)%eam_rcut) then
387
388 call lookupEAMSpline(EAMList%EAMParams(myid_atom2)%rho, r, &
389 rho_j_at_i)
390
391 #ifdef IS_MPI
392 rho_row(atom1) = rho_row(atom1) + rho_j_at_i
393 #else
394 rho(atom1) = rho(atom1) + rho_j_at_i
395 #endif
396 endif
397 end subroutine calc_eam_prepair_rho
398
399
400 !! Calculate the functional F(rho) for all local atoms
401 subroutine calc_eam_preforce_Frho(nlocal, pot, particle_pot)
402 integer :: nlocal
403 real(kind=dp) :: pot
404 integer :: i, j
405 integer :: atom
406 real(kind=dp) :: U,U1
407 real( kind = dp ), dimension(nlocal) :: particle_pot
408 integer :: atype1
409 integer :: me, atid1
410
411 cleanme = .true.
412 !! Scatter the electron density from pre-pair calculation back to
413 !! local atoms
414 #ifdef IS_MPI
415 call scatter(rho_row,rho,plan_atom_row,eam_err)
416 if (eam_err /= 0 ) then
417 write(errMsg,*) " Error scattering rho_row into rho"
418 call handleError(RoutineName,errMesg)
419 endif
420 call scatter(rho_col,rho_tmp,plan_atom_col,eam_err)
421 if (eam_err /= 0 ) then
422 write(errMsg,*) " Error scattering rho_col into rho"
423 call handleError(RoutineName,errMesg)
424 endif
425
426 rho(1:nlocal) = rho(1:nlocal) + rho_tmp(1:nlocal)
427 #endif
428
429 !! Calculate F(rho) and derivative
430 do atom = 1, nlocal
431 atid1 = atid(atom)
432 me = eamList%atidToEAMtype(atid1)
433
434 call lookupEAMSpline1d(EAMList%EAMParams(me)%F, rho(atom), &
435 u, u1)
436
437 frho(atom) = u
438 dfrhodrho(atom) = u1
439 pot = pot + u
440 particle_pot(atom) = particle_pot(atom) + u
441
442 enddo
443
444 #ifdef IS_MPI
445 !! communicate f(rho) and derivatives back into row and column arrays
446 call gather(frho,frho_row,plan_atom_row, eam_err)
447 if (eam_err /= 0) then
448 call handleError("cal_eam_forces()","MPI gather frho_row failure")
449 endif
450 call gather(dfrhodrho,dfrhodrho_row,plan_atom_row, eam_err)
451 if (eam_err /= 0) then
452 call handleError("cal_eam_forces()","MPI gather dfrhodrho_row failure")
453 endif
454 call gather(frho,frho_col,plan_atom_col, eam_err)
455 if (eam_err /= 0) then
456 call handleError("cal_eam_forces()","MPI gather frho_col failure")
457 endif
458 call gather(dfrhodrho,dfrhodrho_col,plan_atom_col, eam_err)
459 if (eam_err /= 0) then
460 call handleError("cal_eam_forces()","MPI gather dfrhodrho_col failure")
461 endif
462 #endif
463
464
465 end subroutine calc_eam_preforce_Frho
466
467 !! Does EAM pairwise Force calculation.
468 subroutine do_eam_pair(atom1, atom2, atid1, atid2, d, rij, r2, sw, vpair, particle_pot, &
469 fpair, pot, f1, do_pot)
470 !Arguments
471 integer, intent(in) :: atom1, atom2, atid1, atid2
472 real( kind = dp ), intent(in) :: rij, r2
473 real( kind = dp ) :: pot, sw, vpair
474 real( kind = dp ), dimension(nLocal) :: particle_pot
475 real( kind = dp ), dimension(3) :: f1
476 real( kind = dp ), intent(in), dimension(3) :: d
477 real( kind = dp ), intent(inout), dimension(3) :: fpair
478
479 logical, intent(in) :: do_pot
480
481 real( kind = dp ) :: drdx, drdy, drdz
482 real( kind = dp ) :: phab, pha, dvpdr
483 real( kind = dp ) :: rha, drha, dpha
484 real( kind = dp ) :: rhb, drhb, dphb
485 real( kind = dp ) :: dudr
486 real( kind = dp ) :: rci, rcj
487 real( kind = dp ) :: drhoidr, drhojdr
488 real( kind = dp ) :: Fx, Fy, Fz
489 real( kind = dp ) :: r, phb
490 real( kind = dp ) :: fshift1, fshift2, u1, u2
491
492 integer :: id1, id2
493 integer :: mytype_atom1
494 integer :: mytype_atom2
495
496 phab = 0.0E0_DP
497 dvpdr = 0.0E0_DP
498
499 if (rij .lt. EAM_rcut) then
500
501 mytype_atom1 = EAMList%atidToEAMType(atid1)
502 mytype_atom2 = EAMList%atidTOEAMType(atid2)
503
504
505 ! get cutoff for atom 1
506 rci = EAMList%EAMParams(mytype_atom1)%eam_rcut
507 ! get type specific cutoff for atom 2
508 rcj = EAMList%EAMParams(mytype_atom2)%eam_rcut
509
510 drdx = d(1)/rij
511 drdy = d(2)/rij
512 drdz = d(3)/rij
513
514 if (rij.lt.rci) then
515
516 ! Calculate rho and drho for atom1
517
518 call lookupEAMSpline1d(EAMList%EAMParams(mytype_atom1)%rho, &
519 rij, rha, drha)
520
521 ! Calculate Phi(r) for atom1.
522
523 call lookupEAMSpline1d(EAMList%EAMParams(mytype_atom1)%phi, &
524 rij, pha, dpha)
525
526 endif
527
528 if (rij.lt.rcj) then
529
530 ! Calculate rho and drho for atom2
531
532 call lookupEAMSpline1d(EAMList%EAMParams(mytype_atom2)%rho, &
533 rij, rhb, drhb)
534
535 ! Calculate Phi(r) for atom2.
536
537 call lookupEAMSpline1d(EAMList%EAMParams(mytype_atom2)%phi, &
538 rij, phb, dphb)
539
540 endif
541
542 if (rij.lt.rci) then
543 phab = phab + 0.5E0_DP*(rhb/rha)*pha
544 dvpdr = dvpdr + 0.5E0_DP*((rhb/rha)*dpha + &
545 pha*((drhb/rha) - (rhb*drha/rha/rha)))
546 endif
547
548 if (rij.lt.rcj) then
549 phab = phab + 0.5E0_DP*(rha/rhb)*phb
550 dvpdr = dvpdr + 0.5E0_DP*((rha/rhb)*dphb + &
551 phb*((drha/rhb) - (rha*drhb/rhb/rhb)))
552 endif
553
554 drhoidr = drha
555 drhojdr = drhb
556
557 #ifdef IS_MPI
558 dudr = drhojdr*dfrhodrho_row(atom1)+drhoidr*dfrhodrho_col(atom2) &
559 + dvpdr
560
561 #else
562 dudr = drhojdr*dfrhodrho(atom1)+drhoidr*dfrhodrho(atom2) &
563 + dvpdr
564 #endif
565
566 fx = dudr * drdx
567 fy = dudr * drdy
568 fz = dudr * drdz
569
570
571 #ifdef IS_MPI
572 if (do_pot) then
573 ! particle_pot is the difference between the full potential
574 ! and the full potential without the presence of a particular
575 ! particle (atom1).
576 !
577 ! This reduces the density at other particle locations, so
578 ! we need to recompute the density at atom2 assuming atom1
579 ! didn't contribute. This then requires recomputing the
580 ! density functional for atom2 as well.
581 !
582 ! Most of the particle_pot heavy lifting comes from the
583 ! pair interaction, and will be handled by vpair.
584
585 call lookupEAMSpline1d(EAMList%EAMParams(mytype_atom1)%F, &
586 rho_row(atom1)-rhb, &
587 fshift1, u1)
588 call lookupEAMSpline1d(EAMList%EAMParams(mytype_atom2)%F, &
589 rho_col(atom2)-rha, &
590 fshift2, u2)
591
592 ppot_Row(atom1) = ppot_Row(atom1) - frho_row(atom2) + fshift2
593 ppot_Col(atom2) = ppot_Col(atom2) - frho_col(atom1) + fshift1
594
595 end if
596
597 #else
598
599 if(do_pot) then
600 ! particle_pot is the difference between the full potential
601 ! and the full potential without the presence of a particular
602 ! particle (atom1).
603 !
604 ! This reduces the density at other particle locations, so
605 ! we need to recompute the density at atom2 assuming atom1
606 ! didn't contribute. This then requires recomputing the
607 ! density functional for atom2 as well.
608 !
609 ! Most of the particle_pot heavy lifting comes from the
610 ! pair interaction, and will be handled by vpair.
611
612 call lookupEAMSpline1d(EAMList%EAMParams(mytype_atom1)%F, &
613 rho(atom1)-rhb, &
614 fshift1, u1)
615 call lookupEAMSpline1d(EAMList%EAMParams(mytype_atom2)%F, &
616 rho(atom2)-rha, &
617 fshift2, u2)
618
619 particle_pot(atom1) = particle_pot(atom1) - frho(atom2) + fshift2
620 particle_pot(atom2) = particle_pot(atom2) - frho(atom1) + fshift1
621
622 end if
623
624 #endif
625
626 pot = pot + phab
627
628 f1(1) = f1(1) + fx
629 f1(2) = f1(2) + fy
630 f1(3) = f1(3) + fz
631
632 vpair = vpair + phab
633
634 endif
635 end subroutine do_eam_pair
636
637 subroutine lookupEAMSpline(cs, xval, yval)
638
639 implicit none
640
641 type (cubicSpline), intent(in) :: cs
642 real( kind = DP ), intent(in) :: xval
643 real( kind = DP ), intent(out) :: yval
644 real( kind = DP ) :: dx
645 integer :: i, j
646 !
647 ! Find the interval J = [ cs%x(J), cs%x(J+1) ] that contains
648 ! or is nearest to xval.
649
650 j = MAX(1, MIN(cs%n-1, int((xval-cs%x(1)) * cs%dx_i) + 1))
651
652 dx = xval - cs%x(j)
653 yval = cs%y(j) + dx*(cs%b(j) + dx*(cs%c(j) + dx*cs%d(j)))
654
655 return
656 end subroutine lookupEAMSpline
657
658 subroutine lookupEAMSpline1d(cs, xval, yval, dydx)
659
660 implicit none
661
662 type (cubicSpline), intent(in) :: cs
663 real( kind = DP ), intent(in) :: xval
664 real( kind = DP ), intent(out) :: yval, dydx
665 real( kind = DP ) :: dx
666 integer :: i, j
667
668 ! Find the interval J = [ cs%x(J), cs%x(J+1) ] that contains
669 ! or is nearest to xval.
670
671
672 j = MAX(1, MIN(cs%n-1, int((xval-cs%x(1)) * cs%dx_i) + 1))
673
674 dx = xval - cs%x(j)
675 yval = cs%y(j) + dx*(cs%b(j) + dx*(cs%c(j) + dx*cs%d(j)))
676
677 dydx = cs%b(j) + dx*(2.0d0 * cs%c(j) + 3.0d0 * dx * cs%d(j))
678
679 return
680 end subroutine lookupEAMSpline1d
681
682 end module eam