ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/mdtools/md_code/lj_FF.F90
(Generate patch)

Comparing trunk/mdtools/md_code/lj_FF.F90 (file contents):
Revision 215 by chuckv, Thu Dec 19 21:59:51 2002 UTC vs.
Revision 246 by chuckv, Fri Jan 24 21:36:52 2003 UTC

# Line 1 | Line 1
1 + !! Calculates Long Range forces Lennard-Jones interactions.
2 + !! Corresponds to the force field defined in lj_FF.cpp
3 + !! @author Charles F. Vardeman II
4 + !! @author Matthew Meineke
5 + !! @version $Id: lj_FF.F90,v 1.10 2003-01-24 21:36:52 chuckv Exp $, $Date: 2003-01-24 21:36:52 $, $Name: not supported by cvs2svn $, $Revision: 1.10 $
6 +
7 +
8 +
9   module lj_ff
10    use simulation
11 <  use definitions, ONLY : dp, ndim
11 >  use definitions
12 > #ifdef IS_MPI
13 >  use mpiSimulation
14 > #endif
15    implicit none
16 +  PRIVATE
17  
18 + !! Number of lj_atypes in lj_atype_list
19    integer, save :: n_lj_atypes = 0
20  
21 + !! Starting Size for ljMixed Array
22 +  integer, parameter :: ljMixed_blocksize = 10
23 +
24 + !! Basic atom type for a Lennard-Jones Atom.
25    type, public :: lj_atype
26       private
27       sequence
28 + !! Unique number for place in linked list
29 +     integer :: atype_number = 0
30 + !! Unique indentifier number (ie atomic no, etc)
31       integer :: atype_ident = 0
32 <     character(len = 15) :: name = "NULL"
32 > !! Mass of Particle
33       real ( kind = dp )  :: mass = 0.0_dp
34 <     real ( kind = dp )  :: epslon = 0.0_dp
34 > !! Lennard-Jones epslon
35 >     real ( kind = dp )  :: epsilon = 0.0_dp
36 > !! Lennard-Jones Sigma
37       real ( kind = dp )  :: sigma = 0.0_dp
38 + !! Lennard-Jones Sigma Squared
39 +     real ( kind = dp )  :: sigma2 = 0.0_dp
40 + !! Lennard-Jones Sigma to sixth
41 +     real ( kind = dp )  :: sigma6 = 0.0_dp
42 + !! Pointer for linked list creation
43       type (lj_atype), pointer :: next => null()
44    end type lj_atype
45  
46 + !! Pointer type for atype ident array
47 +  type, public :: lj_atypePtr
48 +     type (lj_atype), pointer :: this => null()
49 +  end type lj_atypePtr
50 +
51 + !! Global list of lj atypes in simulation
52    type (lj_atype), pointer :: lj_atype_list => null()
53 + !! LJ mixing array  
54 +  type (lj_atype), dimension(:,:), pointer :: ljMixed => null()
55 + !! identity pointer list for force loop.
56 +  type (lj_atypePtr), dimension(:), pointer :: identPtrList => null()
57  
58 +
59 + !! Neighbor list and commom arrays
60 + !! This should eventally get moved to a neighbor list type
61 +  integer, allocatable, dimension(:) :: point
62 +  integer, allocatable, dimension(:) :: list
63 +  integer, parameter :: listMultiplier = 80
64 +  integer :: nListAllocs = 0
65 +  integer, parameter :: maxListAllocs = 5
66 +
67 + #ifdef IS_MPI
68 + ! Universal routines: All types of force calculations will need these arrays
69 + ! Arrays specific to a type of force calculation should be declared in that module.
70 + !! Row position array.
71 +  real( kind = dp ), allocatable, dimension(:,:) :: qRow
72 + !! Column position array.
73 +  real( kind = dp ), allocatable, dimension(:,:) :: qColumn
74 +
75 + !! Row Force array.
76 +  real( kind = dp ), allocatable, dimension(:,:) :: fRow
77 + !! Column Force Array.
78 +  real( kind = dp ), allocatable, dimension(:,:) :: fColumn
79 +
80 + !! Row potential energy array
81 +  real( kind = dp ), allocatable, dimension(:) :: eRow
82 + !! Column potential energy array
83 +  real( kind = dp ), allocatable, dimension(:) :: eColumn
84 +
85 +
86 + !! Row lj_atype pointer list
87 +  type (lj_atypePtr), dimension(:), pointer :: identPtrListRow => null()
88 + !! Column lj_atype pointer list
89 +  type (lj_atypePtr), dimension(:), pointer :: identPtrListColumn => null()
90 + #endif
91 +
92 +
93 + !! Logical has lj force field module been initialized?
94 +  logical, save :: isljFFinit = .false.
95 +
96 +
97 + !! Public methods and data
98    public :: new_lj_atype
99 +  public :: do_lj_ff
100 +  public :: getLjPot
101 +  public :: init_ljFF
102  
103 +  
104 +
105 +
106   contains
107  
108 <  subroutine new_lj_atype(name,mass,epslon,sigma,status)
26 <    character( len = 15 ) :: name
108 >  subroutine new_lj_atype(ident,mass,epsilon,sigma,status)
109      real( kind = dp ), intent(in) :: mass
110 <    real( kind = dp ), intent(in) :: epslon
111 <    real( kind = dp ), intent(in) :: sigam
110 >    real( kind = dp ), intent(in) :: epsilon
111 >    real( kind = dp ), intent(in) :: sigma
112 >    integer, intent(in) :: ident
113      integer, intent(out) :: status
114  
115 +    type (lj_atype), pointer :: this_lj_atype
116 +    type (lj_atype), pointer :: lj_atype_ptr
117 +
118 +    type (lj_atype), dimension(:,:), pointer :: thisMix
119 +    type (lj_atype), dimension(:,:), pointer :: oldMix
120 +    integer :: alloc_error
121 +    integer :: atype_counter = 0
122 +    integer :: alloc_size
123 +
124      status = 0
125  
126 +
127 +
128 + ! allocate a new atype    
129 +    allocate(this_lj_atype,stat=alloc_error)
130 +    if (alloc_error /= 0 ) then
131 +       status = -1
132 +       return
133 +    end if
134 +
135 + ! assign our new lj_atype information
136 +    this_lj_atype%mass        = mass
137 +    this_lj_atype%epsilon     = epsilon
138 +    this_lj_atype%sigma       = sigma
139 +    this_lj_atype%sigma2      = sigma * sigma
140 +    this_lj_atype%sigma6      = this_lj_atype%sigma2 * this_lj_atype%sigma2 &
141 +         * this_lj_atype%sigma2
142 + ! assume that this atype will be successfully added
143 +    this_lj_atype%atype_ident = ident
144 +    this_lj_atype%atype_number = n_lj_atypes + 1
145 +
146 +
147 + ! First time through allocate a array of size ljMixed_blocksize
148 +    if(.not. associated(ljMixed)) then
149 +       allocate(thisMix(ljMixed_blocksize,ljMixed_blocksize))
150 +       if (alloc_error /= 0 ) then
151 +          status = -1
152 +          return
153 +       end if
154 +       ljMixed => thisMix
155 + ! If we have outgrown ljMixed_blocksize, allocate a new matrix twice the size and
156 + ! point ljMix at the new matrix.
157 +    else if( (n_lj_atypes + 1) > size(ljMixed)) then
158 +       alloc_size = 2*size(ljMixed)
159 +       allocate(thisMix(alloc_size,alloc_size))
160 +       if (alloc_error /= 0 ) then
161 +          status = -1
162 +          return
163 +       end if
164 + ! point oldMix at old ljMixed array
165 +       oldMix => ljMixed
166 + ! Copy oldMix into new Mixed array      
167 +       thisMix = oldMix
168 + ! Point ljMixed at new array
169 +       ljMixed => thisMix
170 + ! Free old array so we don't have a memory leak
171 +       deallocate(oldMix)
172 +    endif
173 +
174 +
175 +
176 +
177 +
178 + ! Find bottom of atype master list
179 + ! if lj_atype_list is null then we are at the top of the list.
180 +    if (.not. associated(lj_atype_list)) then
181 +
182 +       write(*,*) "Associating lists for first time"
183 +      
184 +
185 +       this_lj_atype%atype_number = 1
186 +      
187 +       ljMixed(n_lj_atypes,n_lj_atypes)%sigma  = this_lj_atype%sigma
188 +      
189 +       ljMixed(n_lj_atypes,n_lj_atypes)%sigma2  = ljMixed(n_lj_atypes,n_lj_atypes)%sigma &
190 +            * ljMixed(n_lj_atypes,n_lj_atypes)%sigma
191 +      
192 +       ljMixed(n_lj_atypes,n_lj_atypes)%sigma6 = ljMixed(n_lj_atypes,n_lj_atypes)%sigma2 &
193 +            * ljMixed(n_lj_atypes,n_lj_atypes)%sigma2 &
194 +            * ljMixed(n_lj_atypes,n_lj_atypes)%sigma2
195 +      
196 +       ljMixed(n_lj_atypes,n_lj_atypes)%epsilon = this_lj_atype%epsilon
197 +      
198 +       lj_atype_list => this_lj_atype
199 +      
200 +       write(*,*) "lj_atype_list first time through -- ident", lj_atype_list%atype_ident
201 +    else ! we need to find the bottom of the list to insert new atype
202 +       write(*,*) "Second time through"
203 +       lj_atype_ptr => lj_atype_list
204 +       write(*,*) "lj_atype_ptr to next"
205 +       atype_counter = 1
206 +       find_end: do
207 +          if (.not. associated(lj_atype_ptr)) exit find_end
208 +
209 +          write(*,*) "Inside find_end-this ident", lj_atype_ptr%atype_ident
210 + ! Set up mixing for new atype and current atype in list
211 +       ljMixed(this_lj_atype%atype_number,lj_atype_ptr%atype_number)%sigma  =  &
212 +            calcLJMix("sigma",this_lj_atype%sigma, &
213 +            lj_atype_ptr%sigma)
214 +
215 +       ljMixed(this_lj_atype%atype_number,lj_atype_ptr%atype_number)%sigma2  = &
216 +            ljMixed(this_lj_atype%atype_number,lj_atype_ptr%atype_number)%sigma &
217 +            * ljMixed(this_lj_atype%atype_number,lj_atype_ptr%atype_number)%sigma
218 +
219 +       ljMixed(this_lj_atype%atype_number,lj_atype_ptr%atype_number)%sigma6 = &
220 +            ljMixed(this_lj_atype%atype_number,lj_atype_ptr%atype_number)%sigma2 &
221 +            * ljMixed(this_lj_atype%atype_number,lj_atype_ptr%atype_number)%sigma2 &
222 +            * ljMixed(this_lj_atype%atype_number,lj_atype_ptr%atype_number)%sigma2
223 +
224 +       ljMixed(this_lj_atype%atype_number,lj_atype_ptr%atype_number)%epsilon = &
225 +            calcLJMix("epsilon",this_lj_atype%epsilon, &
226 +            lj_atype_ptr%epsilon)
227 +
228 + ! Advance to next pointer
229 +       lj_atype_ptr => lj_atype_ptr%next          
230 +       atype_counter = atype_counter + 1          
231 +       end do find_end
232 +
233 +       lj_atype_ptr => this_lj_atype
234 +       write(*,*) "just added: ", lj_atype_ptr%atype_ident
235 +    end if
236 +
237 +    write(*,*) "lj_atype_list now contains.."
238 +    
239 +    lj_atype_ptr => lj_atype_list
240 +    do while (associated(lj_atype_ptr))
241 +       write(*,*) "lj_atype_list contains ident", lj_atype_ptr%atype_ident
242 +       lj_atype_ptr => lj_atype_ptr%next
243 +    end do
244 +    
245 + ! Insert new atype at end of list
246 +
247 + ! Increment number of atypes
248 +
249 +    n_lj_atypes = n_lj_atypes + 1
250 +
251 + ! Set up self mixing
252 +
253    end subroutine new_lj_atype
254 +
255 +
256 +  subroutine init_ljFF(nComponents,ident, status)
257 + !! Number of components in ident array
258 +    integer, intent(inout) :: nComponents
259 + !! Array of identities nComponents long corresponding to
260 + !! ljatype ident.
261 +    integer, dimension(nComponents),intent(inout) :: ident
262 + !!  Result status, success = 0, error = -1
263 +    integer, intent(out) :: Status
264 +
265 +    integer :: alloc_stat
266  
267 +    integer :: thisStat
268 +    integer :: i
269 + #ifdef IS_MPI
270 +    integer, allocatable, dimension(:) :: identRow
271 +    integer, allocatable, dimension(:) :: identCol
272 +    integer :: nrow
273 +    integer :: ncol
274 +    integer :: alloc_stat
275 + #endif
276 +    status = 0
277  
278 +    write(*,*) "Initializing ljFF"
279 + !! if were're not in MPI, we just update ljatypePtrList
280 + #ifndef IS_MPI
281 +    call new_ljatypePtrList(nComponents,ident,identPtrList,thisStat)
282 +    if ( thisStat /= 0 ) then
283 +       status = -1
284 +       return
285 +    endif
286 +    write(*,*) "component pointer list initialized"
287 + !! Allocate pointer lists
288 +    allocate(point(nComponents),stat=alloc_stat)
289 +    if (alloc_stat /=0) then
290 +       status = -1
291 +       return
292 +    endif
293  
294 +    allocate(list(nComponents*listMultiplier),stat=alloc_stat)
295 +    if (alloc_stat /=0) then
296 +       status = -1
297 +       return
298 +    endif
299 +    
300 + ! if were're in MPI, we also have to worry about row and col lists    
301 + #else
302 + ! We can only set up forces if mpiSimulation has been setup.
303 +    if (.not. isMPISimSet()) then
304 +       status = -1
305 +       return
306 +    endif
307 +    nrow = getNrow()
308 +    ncol = getNcol()
309 + !! Allocate temperary arrays to hold gather information
310 +    allocate(identRow(nrow),stat=alloc_stat)
311 +    if (alloc_stat /= 0 ) then
312 +       status = -1
313 +       return
314 +    endif
315  
316 +    allocate(identCol(ncol),stat=alloc_stat)
317 +    if (alloc_stat /= 0 ) then
318 +       status = -1
319 +       return
320 +    endif
321 + !! Gather idents into row and column idents
322 +    call gather(ident,identRow,plan_row)
323 +    call gather(ident,identCol,plan_col)
324  
325 + !! Create row and col pointer lists
326 +    call new_ljatypePtrList(nrow,identRow,identPtrListRow,thisStat)
327 +    if (thisStat /= 0 ) then
328 +       status = -1
329 +       return
330 +    endif
331  
332 +    call new_ljatypePtrList(ncol,identCol,identPtrListCol,thisStat)
333 +    if (thisStat /= 0 ) then
334 +       status = -1
335 +       return
336 +    endif
337 +
338 + !! free temporary ident arrays
339 +    deallocate(identCol)
340 +    deallocate(identRow)
341 +
342 + !! Allocate Simulation arrays
343 + !! NOTE: This bit of code should be fixed, it can cause large
344 + !! memory fragmentation if call repeatedly
345 +
346 +    if (.not.allocated(qRow)) then
347 +       allocate(qRow(3,nrow),stat=alloc_stat)
348 +       if (alloc_stat /= 0 ) then
349 +          status = -1
350 +          return
351 +       endif
352 +    else
353 +       deallocate(qrow)
354 +       allocate(qRow(3,nrow),stat=alloc_stat)
355 +       if (alloc_stat /= 0 ) then
356 +          status = -1
357 +          return
358 +       endif
359 +    endif
360 +
361 +    if (.not.allocated(3,qCol)) then
362 +       allocate(qCol(ncol),stat=alloc_stat)
363 +       if (alloc_stat /= 0 ) then
364 +          status = -1
365 +          return
366 +       endif
367 +    else
368 +       deallocate(qCol)
369 +       allocate(qCol(3,ncol),stat=alloc_stat)
370 +       if (alloc_stat /= 0 ) then
371 +          status = -1
372 +          return
373 +       endif
374 +    endif
375 +
376 +    if (.not.allocated(fRow)) then
377 +       allocate(fRow(3,nrow),stat=alloc_stat)
378 +       if (alloc_stat /= 0 ) then
379 +          status = -1
380 +          return
381 +       endif
382 +    else
383 +       deallocate(fRow)
384 +       allocate(fRow(3,nrow),stat=alloc_stat)
385 +       if (alloc_stat /= 0 ) then
386 +          status = -1
387 +          return
388 +       endif
389 +    endif
390 +
391 +    if (.not.allocated(fCol)) then
392 +       allocate(fCol(3,ncol),stat=alloc_stat)
393 +       if (alloc_stat /= 0 ) then
394 +          status = -1
395 +          return
396 +       endif
397 +    else
398 +       deallocate(fCol)
399 +       allocate(fCol(3,ncol),stat=alloc_stat)
400 +       if (alloc_stat /= 0 ) then
401 +          status = -1
402 +          return
403 +       endif
404 +    endif
405 +
406 +    if (.not.allocated(eRow)) then
407 +       allocate(eRow(nrow),stat=alloc_stat)
408 +       if (alloc_stat /= 0 ) then
409 +          status = -1
410 +          return
411 +       endif
412 +    else
413 +       deallocate(eRow)
414 +       allocate(eRow(nrow),stat=alloc_stat)
415 +       if (alloc_stat /= 0 ) then
416 +          status = -1
417 +          return
418 +       endif
419 +    endif
420 +
421 +    if (.not.allocated(eCol)) then
422 +       allocate(eCol(ncol),stat=alloc_stat)
423 +       if (alloc_stat /= 0 ) then
424 +          status = -1
425 +          return
426 +       endif
427 +    else
428 +       deallocate(eCol)
429 +       allocate(eCol(ncol),stat=alloc_stat)
430 +       if (alloc_stat /= 0 ) then
431 +          status = -1
432 +          return
433 +       endif
434 +    endif
435 +
436 +    if (.not.allocated(eTemp)) then
437 +       allocate(eTemp(nComponents),stat=alloc_stat)
438 +       if (alloc_stat /= 0 ) then
439 +          status = -1
440 +          return
441 +       endif
442 +    else
443 +       deallocate(eTemp)
444 +       allocate(eTemp(nComponets),stat=alloc_stat)
445 +       if (alloc_stat /= 0 ) then
446 +          status = -1
447 +          return
448 +       endif
449 +    endif
450 +
451 +
452 + !! Allocate neighbor lists for mpi simulations.
453 +    if (.not. allocated(point)) then
454 +       allocate(point(nrow),stat=alloc_stat)
455 +       if (alloc_stat /=0) then
456 +          status = -1
457 +          return
458 +       endif
459 +
460 +       allocate(list(ncol*listMultiplier),stat=alloc_stat)
461 +       if (alloc_stat /=0) then
462 +          status = -1
463 +          return
464 +       endif
465 +    else
466 +       deallocate(list)
467 +       deallocate(point)
468 +       allocate(point(nrow),stat=alloc_stat)
469 +       if (alloc_stat /=0) then
470 +          status = -1
471 +          return
472 +       endif
473 +
474 +       allocate(list(ncol*listMultiplier),stat=alloc_stat)
475 +       if (alloc_stat /=0) then
476 +          status = -1
477 +          return
478 +       endif
479 +    endif
480 +
481 + #endif
482 +    
483 +    
484 +    do i = 1, nComponents
485 +       write(*,*) "Ident pointer list ident: ", identPtrList(i)%this%atype_ident
486 +    end do
487 +
488 +    isljFFinit = .true.
489 +
490 +  end subroutine init_ljFF
491 +
492 +
493 +
494 +
495 +
496 + !! Takes an ident array and creates an atype pointer list
497 + !! based on those identities
498 +  subroutine new_ljatypePtrList(mysize,ident,PtrList,status)
499 +    integer, intent(in) :: mysize
500 +    integer,dimension(:), intent(in) :: ident
501 +    integer, optional :: status
502 +    type(lj_atypePtr), dimension(:), pointer :: PtrList
503 +
504 +    integer :: thisIdent
505 +    integer :: i
506 +    integer :: alloc_error
507 +    type (lj_atype), pointer :: tmpPtr
508 +
509 +    if (present(status)) status = 0
510 +
511 +    write(*,*) "Creating new ljatypePtrList...."
512 + ! First time through, allocate list
513 +    if (.not.associated(PtrList)) then
514 +       write(*,*) "allocating pointer list...."
515 +       allocate(PtrList(mysize))
516 +    else
517 + ! We want to creat a new ident list so free old list
518 +       deallocate(PtrList)
519 +       allocate(PtrList(mysize))
520 +    endif
521 +
522 + ! Match pointer list
523 +    write(*,*) "Doing ident search"
524 +    do i = 1, mysize
525 +       thisIdent = ident(i)
526 +       write(*,*) "Calling getLJatype for ident ", thisIdent
527 +       call getLJatype(thisIdent,tmpPtr)
528 +
529 +      if (.not. associated(tmpPtr)) then
530 +         write(*,*) "tmpptr was not associated"
531 +          status = -1
532 +          return
533 +       endif
534 +      
535 +       PtrList(i)%this => tmpPtr
536 +    end do
537 +
538 +  end subroutine new_ljatypePtrList
539 +
540 + !! Finds a lj_atype based upon numerical ident
541 + !! returns a null pointer if error
542 +  subroutine getLJatype(ident,ljAtypePtr)
543 +    integer, intent(in) :: ident
544 +    type (lj_atype), pointer :: ljAtypePtr    
545 +    type (lj_atype), pointer :: tmplj_atype_ptr => null()
546 +
547 +    write(*,*) "Finding ljAtype for ident ", ident
548 +    ljAtypePtr => null()
549 +
550 +    if(.not. associated(lj_atype_list)) return
551 +
552 + ! Point at head of list.
553 +    write(*,*) "Searching at head of list"
554 +    tmplj_atype_ptr => lj_atype_list
555 +    find_ident: do
556 +       if (.not.associated(tmplj_atype_ptr)) then
557 +          write(*,*) "Find_ident, pointer not associated"
558 +          exit find_ident
559 +       else if( tmplj_atype_ptr%atype_ident == ident) then
560 +          ljAtypePtr => tmplj_atype_ptr
561 +          exit find_ident
562 +       endif
563 +       tmplj_atype_ptr => tmplj_atype_ptr%next
564 +    end do find_ident
565 +
566 +
567 +
568 +
569 +  end subroutine getLJatype
570 +
571 +
572 + !! FORCE routine Calculates Lennard Jones forces.
573 + !------------------------------------------------------------->
574 +  subroutine do_lj_ff(q,f,potE,do_pot)
575 + !! Position array provided by C, dimensioned by getNlocal
576 +    real ( kind = dp ), dimension(3,getNlocal()) :: q
577 + !! Force array provided by C, dimensioned by getNlocal
578 +    real ( kind = dp ), dimension(3,getNlocal()) :: f
579 +    real ( kind = dp ) :: potE
580 +    logical ( kind = 2) :: do_pot
581 +    
582 +    type(lj_atype), pointer :: ljAtype_i
583 +    type(lj_atype), pointer :: ljAtype_j
584 +
585 + #ifdef MPI
586 +  real( kind = DP ), dimension(3,getNcol()) :: efr
587 +  real( kind = DP ) :: pot_local
588 + #else
589 +  real( kind = DP ), dimension(3,getNlocal()) :: efr
590 + #endif
591 +  
592 +  real( kind = DP )   :: pe
593 +  logical             :: update_nlist
594 +
595 +
596 +  integer ::  i, j, jbeg, jend, jnab, idim, jdim, idim2, jdim2, dim, dim2
597 +  integer :: nlist
598 +  integer :: j_start
599 +  integer :: tag_i,tag_j
600 +  real( kind = DP ) ::  r, pot, ftmp, dudr, d2, drdx1, kt1, kt2, kt3, ktmp
601 +  real( kind = DP ) ::  rxi, ryi, rzi, rxij, ryij, rzij, rijsq
602 +  real( kind = DP ) ::  rlistsq, rcutsq,rlist,rcut
603 +
604 + ! a rig that need to be fixed.
605 + #ifdef IS_MPI
606 +  logical :: newtons_thrd = .true.
607 +  real( kind = dp ) :: pe_local
608 +  integer :: nlocal
609 + #endif
610 +  integer :: nrow
611 +  integer :: ncol
612 +  integer :: natoms
613 +
614 + ! Make sure we are properly initialized.
615 +  if (.not. isljFFInit) then
616 +     write(default_error,*) "ERROR: lj_FF has not been properly initialized"
617 +     return
618 +  endif
619 + #ifdef IS_MPI
620 +    if (.not. isMPISimSet()) then
621 +     write(default_error,*) "ERROR: mpiSimulation has not been properly initialized"
622 +     return
623 +  endif
624 + #endif
625 +
626 + !! initialize local variables  
627 +  natoms = getNlocal()
628 +  call getRcut(rcut,rcut2=rcutsq)
629 +  call getRlist(rlist,rlistsq)
630 + #ifndef IS_MPI
631 +  nrow = natoms - 1
632 +  ncol = natoms
633 + #else
634 +  nrow = getNrow(plan_row)
635 +  ncol = getNcol(plan_col)
636 +  nlocal = natoms
637 +  j_start = 1
638 + #endif
639 +
640 +  
641 + !! See if we need to update neighbor lists
642 +  call check(q,update_nlist)
643 +
644 + !--------------WARNING...........................
645 + ! Zero variables, NOTE:::: Forces are zeroed in C
646 + ! Zeroing them here could delete previously computed
647 + ! Forces.
648 + !------------------------------------------------
649 + #ifndef IS_MPI
650 + !  nloops = nloops + 1
651 +  pe = 0.0E0_DP
652 +
653 + #else
654 +    f_row = 0.0E0_DP
655 +    f_col = 0.0E0_DP
656 +
657 +    pe_local = 0.0E0_DP
658 +
659 +    eRow = 0.0E0_DP
660 +    eCol = 0.0E0_DP
661 +    eTemp = 0.0E0_DP
662 + #endif
663 +    efr = 0.0E0_DP
664 +
665 + ! communicate MPI positions
666 + #ifdef MPI    
667 +    call gather(q,qRow,plan_row3)
668 +    call gather(q,qCol,plan_col3)
669 + #endif
670 +
671 +
672 +  if (update_nlist) then
673 +
674 +     ! save current configuration, contruct neighbor list,
675 +     ! and calculate forces
676 +     call save_nlist(q)
677 +    
678 +     nlist = 0
679 +    
680 +    
681 +
682 +     do i = 1, nrow
683 +        point(i) = nlist + 1
684 + #ifdef MPI
685 +        ljAtype_i => identPtrListRow(i)%this
686 +        tag_i = tagRow(i)
687 +        rxi = qRow(1,i)
688 +        ryi = qRow(2,i)
689 +        rzi = qRow(3,i)
690 + #else
691 +        ljAtype_i   => identPtrList(i)%this
692 +        j_start = i + 1
693 +        rxi = q(1,i)
694 +        ryi = q(2,i)
695 +        rzi = q(3,i)
696 + #endif
697 +
698 +        inner: do j = j_start, ncol
699 + #ifdef MPI
700 + ! Assign identity pointers and tags
701 +           ljAtype_j => identPtrListColumn(j)%this
702 +           tag_j = tagCol(j)
703 +           if (newtons_thrd) then
704 +              if (tag_i <= tag_j) then
705 +                 if (mod(tag_i + tag_j,2) == 0) cycle inner
706 +              else                
707 +                 if (mod(tag_i + tag_j,2) == 1) cycle inner
708 +              endif
709 +           endif
710 +
711 +           rxij = wrap(rxi - qCol(1,j), 1)
712 +           ryij = wrap(ryi - qCol(2,j), 2)
713 +           rzij = wrap(rzi - qCol(3,j), 3)
714 + #else          
715 +           ljAtype_j   => identPtrList(j)%this
716 +           rxij = wrap(rxi - q(1,j), 1)
717 +           ryij = wrap(ryi - q(2,j), 2)
718 +           rzij = wrap(rzi - q(3,j), 3)
719 +      
720 + #endif          
721 +           rijsq = rxij*rxij + ryij*ryij + rzij*rzij
722 +
723 + #ifdef MPI
724 +             if (rijsq <=  rlistsq .AND. &
725 +                  tag_j /= tag_i) then
726 + #else
727 +             if (rijsq <  rlistsq) then
728 + #endif
729 +            
730 +              nlist = nlist + 1
731 +              if (nlist > size(list)) then
732 + !!  "Change how nlist size is done"
733 +                 write(DEFAULT_ERROR,*) "ERROR: nlist > list size"
734 +              endif
735 +              list(nlist) = j
736 +
737 +              
738 +              if (rijsq <  rcutsq) then
739 +                
740 +                 r = dsqrt(rijsq)
741 +      
742 +                 call getLJPot(r,pot,dudr,ljAtype_i,ljAtype_j)
743 +      
744 + #ifdef MPI
745 +                eRow(i) = eRow(i) + pot*0.5
746 +                eCol(i) = eCol(i) + pot*0.5
747 + #else
748 +                pe = pe + pot
749 + #endif                
750 +            
751 +                 efr(1,j) = -rxij
752 +                 efr(2,j) = -ryij
753 +                 efr(3,j) = -rzij
754 +
755 +                 do dim = 1, 3  
756 +
757 +            
758 +                    drdx1 = efr(dim,j) / r
759 +                    ftmp = dudr * drdx1
760 +
761 +
762 + #ifdef MPI
763 +                    fCol(dim,j) = fCol(dim,j) - ftmp
764 +                    fRow(dim,i) = fRow(dim,i) + ftmp
765 + #else                    
766 +            
767 +                    f(dim,j) = f(dim,j) - ftmp
768 +                    f(dim,i) = f(dim,i) + ftmp
769 +
770 + #endif                    
771 +                 enddo
772 +              endif
773 +           endif
774 +        enddo inner
775 +     enddo
776 +
777 + #ifdef MPI
778 +     point(nrow + 1) = nlist + 1
779 + #else
780 +     point(natoms) = nlist + 1
781 + #endif
782 +
783 +  else
784 +
785 +     ! use the list to find the neighbors
786 +     do i = 1, nrow
787 +        JBEG = POINT(i)
788 +        JEND = POINT(i+1) - 1
789 +        ! check thiat molecule i has neighbors
790 +        if (jbeg .le. jend) then
791 + #ifdef MPI
792 +           ljAtype_i => identPtrListRow(i)%this
793 +           rxi = qRow(1,i)
794 +           ryi = qRow(2,i)
795 +           rzi = qRow(3,i)
796 + #else
797 +           ljAtype_i   => identPtrList(i)%this
798 +           rxi = q(1,i)
799 +           ryi = q(2,i)
800 +           rzi = q(3,i)
801 + #endif
802 +           do jnab = jbeg, jend
803 +              j = list(jnab)
804 + #ifdef MPI
805 +              ljAtype_j = identPtrListColumn(j)%this
806 +              rxij = wrap(rxi - q_col(1,j), 1)
807 +              ryij = wrap(ryi - q_col(2,j), 2)
808 +              rzij = wrap(rzi - q_col(3,j), 3)
809 + #else
810 +              ljAtype_j = identPtrList(j)%this
811 +              rxij = wrap(rxi - q(1,j), 1)
812 +              ryij = wrap(ryi - q(2,j), 2)
813 +              rzij = wrap(rzi - q(3,j), 3)
814 + #endif
815 +              rijsq = rxij*rxij + ryij*ryij + rzij*rzij
816 +              
817 +              if (rijsq <  rcutsq) then
818 +
819 +                 r = dsqrt(rijsq)
820 +                
821 +                 call getLJPot(r,pot,dudr,ljAtype_i,ljAtype_j)
822 + #ifdef MPI
823 +                eRow(i) = eRow(i) + pot*0.5
824 +                eCol(i) = eCol(i) + pot*0.5
825 + #else
826 +                pe = pe + pot
827 + #endif                
828 +
829 +                
830 +                 efr(1,j) = -rxij
831 +                 efr(2,j) = -ryij
832 +                 efr(3,j) = -rzij
833 +
834 +                 do dim = 1, 3                        
835 +                    
836 +                    drdx1 = efr(dim,j) / r
837 +                    ftmp = dudr * drdx1
838 + #ifdef MPI
839 +                    fCol(dim,j) = fCol(dim,j) - ftmp
840 +                    fRow(dim,i) = fRow(dim,i) + ftmp
841 + #else                    
842 +                    f(dim,j) = f(dim,j) - ftmp
843 +                    f(dim,i) = f(dim,i) + ftmp
844 + #endif                    
845 +                 enddo
846 +              endif
847 +           enddo
848 +        endif
849 +     enddo
850 +  endif
851 +
852 +
853 +
854 + #ifdef MPI
855 +    !!distribute forces
856 +    call scatter(fRow,f,plan_row3)
857 +
858 +    call scatter(fCol,f_tmp,plan_col3)
859 +
860 +    do i = 1,nlocal
861 +       f(1:3,i) = f(1:3,i) + f_tmp(1:3,i)
862 +    end do
863 +
864 +
865 +    
866 +    if (do_pot) then
867 + ! scatter/gather pot_row into the members of my column
868 +       call scatter(e_row,e_tmp,plan_row)
869 +      
870 +       ! scatter/gather pot_local into all other procs
871 +       ! add resultant to get total pot
872 +       do i = 1, nlocal
873 +          pe_local = pe_local + e_tmp(i)
874 +       enddo
875 +       if (newtons_thrd) then
876 +          e_tmp = 0.0E0_DP
877 +          call scatter(e_col,e_tmp,plan_col)
878 +          do i = 1, nlocal
879 +             pe_local = pe_local + e_tmp(i)
880 +          enddo
881 +       endif
882 +    endif
883 +    potE = pe_local
884 + #endif
885 +
886 +    potE = pe
887 +
888 +
889 +  end subroutine do_lj_ff
890 +
891 + !! Calculates the potential between two lj particles based on two lj_atype pointers, optionally returns second
892 + !! derivatives.
893 +  subroutine getLjPot(r,pot,dudr,atype1,atype2,d2,status)
894 + ! arguments
895 + !! Length of vector between particles
896 +    real( kind = dp ), intent(in)  :: r
897 + !! Potential Energy
898 +    real( kind = dp ), intent(out) :: pot
899 + !! Derivatve wrt postion
900 +    real( kind = dp ), intent(out) :: dudr
901 + !! Second Derivative, optional, used mainly for normal mode calculations.
902 +    real( kind = dp ), intent(out), optional :: d2
903 +    
904 +    type (lj_atype), pointer :: atype1
905 +    type (lj_atype), pointer :: atype2
906 +
907 +    integer, intent(out), optional :: status
908 +
909 + ! local Variables
910 +    real( kind = dp ) :: sigma
911 +    real( kind = dp ) :: sigma2
912 +    real( kind = dp ) :: sigma6
913 +    real( kind = dp ) :: epsilon
914 +
915 +    real( kind = dp ) :: rcut
916 +    real( kind = dp ) :: rcut2
917 +    real( kind = dp ) :: rcut6
918 +    real( kind = dp ) :: r2
919 +    real( kind = dp ) :: r6
920 +
921 +    real( kind = dp ) :: t6
922 +    real( kind = dp ) :: t12
923 +    real( kind = dp ) :: tp6
924 +    real( kind = dp ) :: tp12
925 +    real( kind = dp ) :: delta
926 +
927 +    logical :: doSec = .false.
928 +
929 +    integer :: errorStat
930 +
931 + !! Optional Argument Checking
932 + ! Check to see if we need to do second derivatives
933 +    
934 +    if (present(d2))     doSec = .true.
935 +    if (present(status)) status = 0
936 +
937 + ! Look up the correct parameters in the mixing matrix
938 +    sigma    = ljMixed(atype1%atype_ident,atype2%atype_ident)%sigma
939 +    sigma2   = ljMixed(atype1%atype_ident,atype2%atype_ident)%sigma2
940 +    sigma6   = ljMixed(atype1%atype_ident,atype2%atype_ident)%sigma6
941 +    epsilon  = ljMixed(atype1%atype_ident,atype2%atype_ident)%epsilon
942 +
943 +
944 +
945 +    call getRcut(rcut,rcut2=rcut2,rcut6=rcut6,status=errorStat)
946 +    
947 +    r2 = r * r
948 +    r6 = r2 * r2 * r2
949 +
950 +    t6  = sigma6/ r6
951 +    t12 = t6 * t6
952 +
953 +
954 +                                                                              
955 +    tp6 = sigma6 / rcut6
956 +    tp12 = tp6*tp6
957 +                                                                              
958 +    delta = -4.0E0_DP*epsilon * (tp12 - tp6)
959 +                                                                              
960 +    if (r.le.rcut) then
961 +       pot = 4.0E0_DP * epsilon * (t12 - t6) + delta
962 +       dudr = 24.0E0_DP * epsilon * (t6 - 2.0E0_DP*t12) / r
963 +       if(doSec)  d2 = 24.0E0_DP * epsilon * (26.0E0_DP*t12 - 7.0E0_DP*t6)/r/r
964 +    else
965 +       pot = 0.0E0_DP
966 +       dudr = 0.0E0_DP
967 +       if(doSec) d2 = 0.0E0_DP
968 +    endif
969 +                                                                              
970 +  return
971 +
972 +
973 +
974 +  end subroutine getLjPot
975 +
976 +
977 + !! Calculates the mixing for sigma or epslon based on character string for initialzition of mixing array.
978 +  function calcLJMix(thisParam,param1,param2,status) result(myMixParam)
979 +    character(len=*) :: thisParam
980 +    real(kind = dp)  :: param1
981 +    real(kind = dp)  :: param2
982 +    real(kind = dp ) :: myMixParam
983 +    integer, optional :: status
984 +
985 +
986 +    myMixParam = 0.0_dp
987 +
988 +    if (present(status)) status = 0
989 +
990 +    select case (thisParam)
991 +
992 +    case ("sigma")
993 +       myMixParam = 0.5_dp * (param1 + param2)
994 +    case ("epsilon")
995 +       myMixParam = sqrt(param1 * param2)
996 +    case default
997 +       status = -1
998 +    end select
999 +
1000 +  end function calcLJMix
1001 +
1002 +
1003 +
1004   end module lj_ff

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines