ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/mdtools/md_code/lj_FF.F90
Revision: 246
Committed: Fri Jan 24 21:36:52 2003 UTC (21 years, 5 months ago) by chuckv
File size: 27267 byte(s)
Log Message:
lj_FF.F90 and simulation_module now compile. Logical bug still
exists in lj_FF.F90 lj_atypes_list.

File Contents

# User Rev Content
1 chuckv 239 !! 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 chuckv 246 !! @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 chuckv 239
7    
8    
9 chuckv 215 module lj_ff
10     use simulation
11 chuckv 246 use definitions
12 chuckv 230 #ifdef IS_MPI
13     use mpiSimulation
14     #endif
15 chuckv 215 implicit none
16 chuckv 230 PRIVATE
17 chuckv 215
18 chuckv 230 !! Number of lj_atypes in lj_atype_list
19 chuckv 215 integer, save :: n_lj_atypes = 0
20    
21 chuckv 230 !! Starting Size for ljMixed Array
22     integer, parameter :: ljMixed_blocksize = 10
23    
24 chuckv 239 !! Basic atom type for a Lennard-Jones Atom.
25 chuckv 215 type, public :: lj_atype
26     private
27     sequence
28 chuckv 230 !! Unique number for place in linked list
29     integer :: atype_number = 0
30     !! Unique indentifier number (ie atomic no, etc)
31 chuckv 215 integer :: atype_ident = 0
32 chuckv 230 !! Mass of Particle
33 chuckv 215 real ( kind = dp ) :: mass = 0.0_dp
34 chuckv 230 !! Lennard-Jones epslon
35 chuckv 246 real ( kind = dp ) :: epsilon = 0.0_dp
36 chuckv 230 !! Lennard-Jones Sigma
37 chuckv 215 real ( kind = dp ) :: sigma = 0.0_dp
38 chuckv 230 !! 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 chuckv 215 type (lj_atype), pointer :: next => null()
44     end type lj_atype
45    
46 chuckv 230 !! Pointer type for atype ident array
47 chuckv 232 type, public :: lj_atypePtr
48 chuckv 230 type (lj_atype), pointer :: this => null()
49     end type lj_atypePtr
50    
51     !! Global list of lj atypes in simulation
52 chuckv 215 type (lj_atype), pointer :: lj_atype_list => null()
53 chuckv 230 !! LJ mixing array
54 chuckv 246 type (lj_atype), dimension(:,:), pointer :: ljMixed => null()
55 chuckv 230 !! identity pointer list for force loop.
56 chuckv 246 type (lj_atypePtr), dimension(:), pointer :: identPtrList => null()
57 chuckv 215
58 chuckv 230
59     !! Neighbor list and commom arrays
60 chuckv 239 !! This should eventally get moved to a neighbor list type
61 chuckv 230 integer, allocatable, dimension(:) :: point
62     integer, allocatable, dimension(:) :: list
63 chuckv 239 integer, parameter :: listMultiplier = 80
64     integer :: nListAllocs = 0
65     integer, parameter :: maxListAllocs = 5
66 chuckv 230
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 chuckv 246 !! Row position array.
71 chuckv 230 real( kind = dp ), allocatable, dimension(:,:) :: qRow
72 chuckv 246 !! Column position array.
73 chuckv 230 real( kind = dp ), allocatable, dimension(:,:) :: qColumn
74    
75 chuckv 246 !! Row Force array.
76 chuckv 230 real( kind = dp ), allocatable, dimension(:,:) :: fRow
77 chuckv 246 !! Column Force Array.
78 chuckv 230 real( kind = dp ), allocatable, dimension(:,:) :: fColumn
79 chuckv 239
80 chuckv 246 !! 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 chuckv 230 #endif
91    
92    
93 chuckv 246 !! Logical has lj force field module been initialized?
94     logical, save :: isljFFinit = .false.
95 chuckv 230
96    
97     !! Public methods and data
98 chuckv 215 public :: new_lj_atype
99 chuckv 230 public :: do_lj_ff
100     public :: getLjPot
101 chuckv 246 public :: init_ljFF
102 chuckv 215
103 chuckv 230
104    
105    
106 chuckv 215 contains
107    
108 chuckv 246 subroutine new_lj_atype(ident,mass,epsilon,sigma,status)
109 chuckv 215 real( kind = dp ), intent(in) :: mass
110 chuckv 246 real( kind = dp ), intent(in) :: epsilon
111 chuckv 230 real( kind = dp ), intent(in) :: sigma
112     integer, intent(in) :: ident
113 chuckv 215 integer, intent(out) :: status
114    
115 chuckv 216 type (lj_atype), pointer :: this_lj_atype
116     type (lj_atype), pointer :: lj_atype_ptr
117    
118 chuckv 246 type (lj_atype), dimension(:,:), pointer :: thisMix
119     type (lj_atype), dimension(:,:), pointer :: oldMix
120 chuckv 216 integer :: alloc_error
121     integer :: atype_counter = 0
122 chuckv 230 integer :: alloc_size
123 chuckv 216
124 chuckv 215 status = 0
125    
126 chuckv 230
127    
128     ! allocate a new atype
129 chuckv 216 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 chuckv 246 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 chuckv 230 * this_lj_atype%sigma2
142     ! assume that this atype will be successfully added
143     this_lj_atype%atype_ident = ident
144 chuckv 246 this_lj_atype%atype_number = n_lj_atypes + 1
145 chuckv 216
146    
147 chuckv 230 ! 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 chuckv 246 alloc_size = 2*size(ljMixed)
159 chuckv 230 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 chuckv 216 ! if lj_atype_list is null then we are at the top of the list.
180     if (.not. associated(lj_atype_list)) then
181 chuckv 230
182 chuckv 246 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 chuckv 230 else ! we need to find the bottom of the list to insert new atype
202 chuckv 246 write(*,*) "Second time through"
203     lj_atype_ptr => lj_atype_list
204     write(*,*) "lj_atype_ptr to next"
205 chuckv 230 atype_counter = 1
206 chuckv 216 find_end: do
207 chuckv 246 if (.not. associated(lj_atype_ptr)) exit find_end
208    
209     write(*,*) "Inside find_end-this ident", lj_atype_ptr%atype_ident
210 chuckv 230 ! Set up mixing for new atype and current atype in list
211 chuckv 246 ljMixed(this_lj_atype%atype_number,lj_atype_ptr%atype_number)%sigma = &
212 chuckv 230 calcLJMix("sigma",this_lj_atype%sigma, &
213 chuckv 246 lj_atype_ptr%sigma)
214 chuckv 230
215 chuckv 246 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 chuckv 230
219 chuckv 246 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 chuckv 230
224 chuckv 246 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 chuckv 230
228     ! Advance to next pointer
229 chuckv 246 lj_atype_ptr => lj_atype_ptr%next
230     atype_counter = atype_counter + 1
231 chuckv 216 end do find_end
232 chuckv 246
233     lj_atype_ptr => this_lj_atype
234     write(*,*) "just added: ", lj_atype_ptr%atype_ident
235 chuckv 216 end if
236 chuckv 230
237 chuckv 246 write(*,*) "lj_atype_list now contains.."
238 chuckv 216
239 chuckv 246 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 chuckv 230 ! Insert new atype at end of list
246 chuckv 246
247 chuckv 230 ! Increment number of atypes
248    
249     n_lj_atypes = n_lj_atypes + 1
250    
251     ! Set up self mixing
252    
253 chuckv 215 end subroutine new_lj_atype
254    
255    
256 chuckv 239 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 chuckv 215
265 chuckv 246 integer :: alloc_stat
266    
267 chuckv 239 integer :: thisStat
268 chuckv 246 integer :: i
269 chuckv 230 #ifdef IS_MPI
270 chuckv 239 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 chuckv 215
278 chuckv 246 write(*,*) "Initializing ljFF"
279 chuckv 239 !! 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 chuckv 246 write(*,*) "component pointer list initialized"
287 chuckv 239 !! 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 chuckv 230
300 chuckv 239 ! 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 chuckv 215
316 chuckv 239 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 chuckv 246
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 chuckv 239 !! 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 chuckv 230 #endif
482 chuckv 239
483 chuckv 246
484     do i = 1, nComponents
485     write(*,*) "Ident pointer list ident: ", identPtrList(i)%this%atype_ident
486     end do
487 chuckv 230
488 chuckv 239 isljFFinit = .true.
489    
490 chuckv 230 end subroutine init_ljFF
491    
492 chuckv 239
493    
494    
495    
496 chuckv 230 !! 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 chuckv 246 integer,dimension(:), intent(in) :: ident
501 chuckv 230 integer, optional :: status
502 chuckv 246 type(lj_atypePtr), dimension(:), pointer :: PtrList
503 chuckv 230
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 chuckv 246 write(*,*) "Creating new ljatypePtrList...."
512 chuckv 230 ! First time through, allocate list
513 chuckv 246 if (.not.associated(PtrList)) then
514     write(*,*) "allocating pointer list...."
515 chuckv 230 allocate(PtrList(mysize))
516     else
517     ! We want to creat a new ident list so free old list
518 chuckv 246 deallocate(PtrList)
519 chuckv 230 allocate(PtrList(mysize))
520     endif
521    
522     ! Match pointer list
523 chuckv 246 write(*,*) "Doing ident search"
524 chuckv 230 do i = 1, mysize
525     thisIdent = ident(i)
526 chuckv 246 write(*,*) "Calling getLJatype for ident ", thisIdent
527 chuckv 230 call getLJatype(thisIdent,tmpPtr)
528    
529     if (.not. associated(tmpPtr)) then
530 chuckv 246 write(*,*) "tmpptr was not associated"
531 chuckv 230 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 chuckv 246 type (lj_atype), pointer :: ljAtypePtr
545 chuckv 230 type (lj_atype), pointer :: tmplj_atype_ptr => null()
546    
547 chuckv 246 write(*,*) "Finding ljAtype for ident ", ident
548     ljAtypePtr => null()
549    
550 chuckv 230 if(.not. associated(lj_atype_list)) return
551    
552     ! Point at head of list.
553 chuckv 246 write(*,*) "Searching at head of list"
554 chuckv 230 tmplj_atype_ptr => lj_atype_list
555     find_ident: do
556     if (.not.associated(tmplj_atype_ptr)) then
557 chuckv 246 write(*,*) "Find_ident, pointer not associated"
558 chuckv 230 exit find_ident
559 chuckv 246 else if( tmplj_atype_ptr%atype_ident == ident) then
560 chuckv 230 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 chuckv 246
567    
568    
569 chuckv 230 end subroutine getLJatype
570    
571    
572 chuckv 239 !! FORCE routine Calculates Lennard Jones forces.
573 chuckv 230 !------------------------------------------------------------->
574     subroutine do_lj_ff(q,f,potE,do_pot)
575 chuckv 246 !! 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 chuckv 222 real ( kind = dp ) :: potE
580 mmeineke 235 logical ( kind = 2) :: do_pot
581 chuckv 239
582     type(lj_atype), pointer :: ljAtype_i
583     type(lj_atype), pointer :: ljAtype_j
584    
585 chuckv 230 #ifdef MPI
586 chuckv 246 real( kind = DP ), dimension(3,getNcol()) :: efr
587 chuckv 230 real( kind = DP ) :: pot_local
588     #else
589 chuckv 246 real( kind = DP ), dimension(3,getNlocal()) :: efr
590 chuckv 230 #endif
591    
592     real( kind = DP ) :: pe
593 chuckv 246 logical :: update_nlist
594 chuckv 216
595 chuckv 232
596 chuckv 230 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 chuckv 246 real( kind = DP ) :: rlistsq, rcutsq,rlist,rcut
603 chuckv 222
604 chuckv 246 ! 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 chuckv 230 integer :: nrow
611     integer :: ncol
612 chuckv 246 integer :: natoms
613 chuckv 222
614 chuckv 246 ! Make sure we are properly initialized.
615 chuckv 239 if (.not. isljFFInit) then
616     write(default_error,*) "ERROR: lj_FF has not been properly initialized"
617     return
618     endif
619 chuckv 246 #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 chuckv 222
626 chuckv 246 !! initialize local variables
627     natoms = getNlocal()
628     call getRcut(rcut,rcut2=rcutsq)
629     call getRlist(rlist,rlistsq)
630 chuckv 230 #ifndef IS_MPI
631     nrow = natoms - 1
632     ncol = natoms
633     #else
634 chuckv 239 nrow = getNrow(plan_row)
635     ncol = getNcol(plan_col)
636 chuckv 246 nlocal = natoms
637 chuckv 230 j_start = 1
638     #endif
639 chuckv 222
640 chuckv 239
641 chuckv 246 !! See if we need to update neighbor lists
642     call check(q,update_nlist)
643 chuckv 239
644     !--------------WARNING...........................
645     ! Zero variables, NOTE:::: Forces are zeroed in C
646     ! Zeroing them here could delete previously computed
647     ! Forces.
648     !------------------------------------------------
649 chuckv 230 #ifndef IS_MPI
650 chuckv 246 ! nloops = nloops + 1
651     pe = 0.0E0_DP
652    
653 chuckv 230 #else
654     f_row = 0.0E0_DP
655     f_col = 0.0E0_DP
656    
657 chuckv 246 pe_local = 0.0E0_DP
658 chuckv 230
659 chuckv 246 eRow = 0.0E0_DP
660     eCol = 0.0E0_DP
661     eTemp = 0.0E0_DP
662 chuckv 230 #endif
663     efr = 0.0E0_DP
664    
665     ! communicate MPI positions
666     #ifdef MPI
667 chuckv 239 call gather(q,qRow,plan_row3)
668     call gather(q,qCol,plan_col3)
669 chuckv 230 #endif
670    
671    
672     if (update_nlist) then
673    
674     ! save current configuration, contruct neighbor list,
675     ! and calculate forces
676 chuckv 246 call save_nlist(q)
677 chuckv 230
678     nlist = 0
679    
680    
681    
682     do i = 1, nrow
683     point(i) = nlist + 1
684     #ifdef MPI
685 chuckv 239 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 chuckv 230 #else
691 chuckv 239 ljAtype_i => identPtrList(i)%this
692 chuckv 230 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 chuckv 239 ! Assign identity pointers and tags
701     ljAtype_j => identPtrListColumn(j)%this
702     tag_j = tagCol(j)
703 chuckv 230 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 chuckv 239 rxij = wrap(rxi - qCol(1,j), 1)
712     ryij = wrap(ryi - qCol(2,j), 2)
713     rzij = wrap(rzi - qCol(3,j), 3)
714 chuckv 230 #else
715 chuckv 239 ljAtype_j => identPtrList(j)%this
716 chuckv 230 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 chuckv 246 if (rijsq <= rlistsq .AND. &
725 chuckv 230 tag_j /= tag_i) then
726     #else
727 chuckv 246 if (rijsq < rlistsq) then
728 chuckv 230 #endif
729    
730     nlist = nlist + 1
731     if (nlist > size(list)) then
732 chuckv 246 !! "Change how nlist size is done"
733 chuckv 239 write(DEFAULT_ERROR,*) "ERROR: nlist > list size"
734 chuckv 230 endif
735     list(nlist) = j
736    
737    
738     if (rijsq < rcutsq) then
739    
740     r = dsqrt(rijsq)
741    
742 chuckv 239 call getLJPot(r,pot,dudr,ljAtype_i,ljAtype_j)
743 chuckv 230
744     #ifdef MPI
745 chuckv 246 eRow(i) = eRow(i) + pot*0.5
746     eCol(i) = eCol(i) + pot*0.5
747 chuckv 230 #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 chuckv 239 fCol(dim,j) = fCol(dim,j) - ftmp
764     fRow(dim,i) = fRow(dim,i) + ftmp
765 chuckv 230 #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 chuckv 239 ljAtype_i => identPtrListRow(i)%this
793     rxi = qRow(1,i)
794     ryi = qRow(2,i)
795     rzi = qRow(3,i)
796 chuckv 230 #else
797 chuckv 239 ljAtype_i => identPtrList(i)%this
798 chuckv 230 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 chuckv 239 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 chuckv 230 #else
810 chuckv 239 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 chuckv 230 #endif
815     rijsq = rxij*rxij + ryij*ryij + rzij*rzij
816    
817     if (rijsq < rcutsq) then
818    
819     r = dsqrt(rijsq)
820    
821 chuckv 239 call getLJPot(r,pot,dudr,ljAtype_i,ljAtype_j)
822 chuckv 230 #ifdef MPI
823 chuckv 246 eRow(i) = eRow(i) + pot*0.5
824     eCol(i) = eCol(i) + pot*0.5
825 chuckv 230 #else
826 chuckv 246 pe = pe + pot
827 chuckv 230 #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 chuckv 239 fCol(dim,j) = fCol(dim,j) - ftmp
840     fRow(dim,i) = fRow(dim,i) + ftmp
841 chuckv 230 #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 chuckv 239 call scatter(fRow,f,plan_row3)
857 chuckv 230
858 chuckv 239 call scatter(fCol,f_tmp,plan_col3)
859 chuckv 246
860 chuckv 230 do i = 1,nlocal
861 chuckv 246 f(1:3,i) = f(1:3,i) + f_tmp(1:3,i)
862 chuckv 230 end do
863    
864    
865    
866     if (do_pot) then
867     ! scatter/gather pot_row into the members of my column
868 chuckv 232 call scatter(e_row,e_tmp,plan_row)
869 chuckv 230
870     ! scatter/gather pot_local into all other procs
871     ! add resultant to get total pot
872     do i = 1, nlocal
873 chuckv 246 pe_local = pe_local + e_tmp(i)
874 chuckv 230 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 chuckv 246 pe_local = pe_local + e_tmp(i)
880 chuckv 230 enddo
881     endif
882     endif
883 chuckv 246 potE = pe_local
884 chuckv 230 #endif
885    
886 chuckv 246 potE = pe
887 chuckv 230
888    
889 chuckv 222 end subroutine do_lj_ff
890    
891 chuckv 239 !! Calculates the potential between two lj particles based on two lj_atype pointers, optionally returns second
892 chuckv 230 !! 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 chuckv 246 type (lj_atype), pointer :: atype1
905     type (lj_atype), pointer :: atype2
906 chuckv 222
907 chuckv 230 integer, intent(out), optional :: status
908 chuckv 222
909 chuckv 230 ! local Variables
910     real( kind = dp ) :: sigma
911     real( kind = dp ) :: sigma2
912     real( kind = dp ) :: sigma6
913 chuckv 246 real( kind = dp ) :: epsilon
914 chuckv 230
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 chuckv 246 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 chuckv 230
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 chuckv 246 pot = 4.0E0_DP * epsilon * (t12 - t6) + delta
962 chuckv 230 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 chuckv 246 pot = 0.0E0_DP
966 chuckv 230 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 chuckv 239 !! Calculates the mixing for sigma or epslon based on character string for initialzition of mixing array.
978 chuckv 230 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 chuckv 246 case ("epsilon")
995 chuckv 230 myMixParam = sqrt(param1 * param2)
996     case default
997     status = -1
998     end select
999    
1000     end function calcLJMix
1001    
1002    
1003    
1004 chuckv 215 end module lj_ff