ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/OpenMD/branches/development/src/UseTheForce/DarkSide/switcheroo.F90
Revision: 938
Committed: Mon Apr 17 21:49:12 2006 UTC (19 years, 3 months ago) by gezelter
Original Path: trunk/src/UseTheForce/DarkSide/switcheroo.F90
File size: 7376 byte(s)
Log Message:
Many performance improvements

File Contents

# User Rev Content
1 gezelter 246 !!
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 gezelter 115 module switcheroo
43    
44     use definitions
45 chrisfen 937 use interpolation
46 gezelter 115
47     implicit none
48     PRIVATE
49    
50     #define __FORTRAN90
51     #include "UseTheForce/fSwitchingFunction.h"
52 chrisfen 725 #include "UseTheForce/DarkSide/fSwitchingFunctionType.h"
53 gezelter 115
54     real ( kind = dp ), dimension(NSWITCHTYPES) :: rin
55     real ( kind = dp ), dimension(NSWITCHTYPES) :: rout
56     real ( kind = dp ), dimension(NSWITCHTYPES) :: rin2
57     real ( kind = dp ), dimension(NSWITCHTYPES) :: rout2
58 chrisfen 725 real ( kind = dp ), save :: c0, c1, c2, c3, c4, c5
59 gezelter 115
60     logical, dimension(NSWITCHTYPES) :: isOK
61 chrisfen 725 logical, save :: haveFunctionType = .false.
62 chrisfen 937 logical, save :: haveSqrtSpline = .false.
63     logical, save :: useSpline = .true.
64 chrisfen 725 integer, save :: functionType = CUBIC
65 gezelter 115
66 gezelter 938 ! spline structure
67     type(cubicSpline), save :: splineSqrt
68 gezelter 115
69     public::set_switch
70 chrisfen 725 public::set_function_type
71 gezelter 115 public::get_switch
72    
73     contains
74    
75 gezelter 938 subroutine setupSqrtSpline(rmin, rmax, np)
76     real( kind = dp ), intent(in) :: rmin, rmax
77     integer, intent(in) :: np
78     real( kind = dp ) :: rvals(np), yvals(np)
79     real( kind = dp ) :: dr, r
80     real( kind = dp ) :: yprime1, yprimen
81     integer :: i
82    
83     dr = (rmax-rmin) / float(np-1)
84    
85     do i = 1, np
86     r = rmin + float(i-1)*dr
87     rvals(i) = r
88     yvals(i) = dsqrt(r)
89     enddo
90    
91     yprime1 = 1.0d0 / ( 2.0d0 * dsqrt( rmin ) )
92     yprimeN = 1.0d0 / ( 2.0d0 * dsqrt( rmax ) )
93    
94     call newSpline(splineSqrt, rvals, yvals, yprime1, yprimen, .true.)
95    
96     return
97     end subroutine setupSqrtSpline
98    
99 gezelter 115 subroutine set_switch(SwitchType, rinner, router)
100    
101     real ( kind = dp ), intent(in):: rinner, router
102     integer, intent(in) :: SwitchType
103 chrisfen 937 integer :: i
104 gezelter 115
105     if (SwitchType .gt. NSWITCHTYPES) then
106     write(default_error, *) &
107     'set_switch: not that many switch types! '
108     return
109     endif
110    
111     isOK(SwitchType) = .false.
112    
113     if (router .lt. rinner) then
114     write(default_error, *) &
115     'set_switch: router is less than rinner '
116     return
117     endif
118    
119     if ((router .lt. 0.0d0) .or. (rinner .lt. 0.0d0)) then
120     write(default_error, *) &
121     'set_switch: one of the switches is negative!'
122     return
123     endif
124 gezelter 507
125 gezelter 115 rin(SwitchType) = rinner
126     rout(SwitchType) = router
127     rin2(SwitchType) = rinner * rinner
128     rout2(SwitchType) = router * router
129     isOK(SwitchType) = .true.
130    
131 chrisfen 937 if (.not.haveSqrtSpline) then
132     ! fill arrays for building the spline
133 gezelter 938 call setupSqrtSpline(1.0d0, rout2(switchType), SPLINE_SEGMENTS)
134     haveSqrtSpline = .true.
135 chrisfen 937 endif
136    
137 gezelter 115 end subroutine set_switch
138    
139 chrisfen 725 subroutine set_function_type(functionForm)
140     integer, intent(in) :: functionForm
141     functionType = functionForm
142    
143     if (functionType .eq. FIFTH_ORDER_POLY) then
144     c0 = 1.0d0
145     c1 = 0.0d0
146     c2 = 0.0d0
147     c3 = -10.0d0
148     c4 = 15.0d0
149     c5 = -6.0d0
150     endif
151     end subroutine set_function_type
152    
153 gezelter 115 subroutine get_switch(r2, sw, dswdr, r, SwitchType, in_switching_region)
154    
155     real( kind = dp ), intent(in) :: r2
156     real( kind = dp ), intent(inout) :: sw, dswdr, r
157 gezelter 938 real( kind = dp ) :: ron, roff, a, b, c, d, dx
158 chrisfen 725 real( kind = dp ) :: rval, rval2, rval3, rval4, rval5
159     real( kind = dp ) :: rvaldi, rvaldi2, rvaldi3, rvaldi4, rvaldi5
160 gezelter 115 integer, intent(in) :: SwitchType
161     logical, intent(inout) :: in_switching_region
162 gezelter 938 integer :: j
163 gezelter 115
164     sw = 0.0d0
165     dswdr = 0.0d0
166     in_switching_region = .false.
167    
168     if (.not.isOK(SwitchType)) then
169     write(default_error, *) &
170     'get_switch: this switching function has not been set up!'
171     return
172     endif
173    
174     if (r2.lt.rout2(SwitchType)) then
175     if (r2.lt.rin2(SwitchType)) then
176 gezelter 507
177 gezelter 115 sw = 1.0d0
178     dswdr = 0.0d0
179     return
180 gezelter 507
181 gezelter 115 else
182 chrisfen 937 if (useSpline) then
183 gezelter 938 j = MAX(1, MIN(splineSqrt%np, idint((r2-splineSqrt%x(1)) * splineSqrt%dx_i) + 1))
184    
185     dx = r2 - splineSqrt%x(j)
186    
187     a = splineSqrt%c(1,j)
188     b = splineSqrt%c(2,j)
189     c = splineSqrt%c(3,j)
190     d = splineSqrt%c(4,j)
191    
192     r = c + dx * d
193     r = b + dx * r
194     r = a + dx * r
195 chrisfen 937 else
196     r = dsqrt(r2)
197     endif
198 gezelter 507
199 gezelter 115 ron = rin(SwitchType)
200     roff = rout(SwitchType)
201 gezelter 507
202 chrisfen 725 if (functionType .eq. FIFTH_ORDER_POLY) then
203     rval = ( r - ron )
204     rval2 = rval*rval
205     rval3 = rval2*rval
206     rval4 = rval2*rval2
207     rval5 = rval3*rval2
208     rvaldi = 1.0d0/( roff - ron )
209     rvaldi2 = rvaldi*rvaldi
210     rvaldi3 = rvaldi2*rvaldi
211     rvaldi4 = rvaldi2*rvaldi2
212     rvaldi5 = rvaldi3*rvaldi2
213     sw = c0 + c1*rval*rvaldi + c2*rval2*rvaldi2 + c3*rval3*rvaldi3 &
214     + c4*rval4*rvaldi4 + c5*rval5*rvaldi5
215     dswdr = c1*rvaldi + 2.0d0*c2*rval*rvaldi2 &
216     + 3.0d0*c3*rval2*rvaldi3 + 4.0d0*c4*rval3*rvaldi4 &
217     + 5.0d0*c5*rval4*rvaldi5
218 gezelter 507
219 chrisfen 725 else
220     sw = (roff + 2.0d0*r - 3.0d0*ron)*(roff-r)**2/ ((roff-ron)**3)
221     dswdr = 6.0d0*(r*r - r*ron - r*roff +roff*ron)/((roff-ron)**3)
222    
223     endif
224 gezelter 115 in_switching_region = .true.
225     return
226     endif
227     else
228     return
229 gezelter 507 endif
230    
231 gezelter 115 end subroutine get_switch
232 chrisfen 725
233 gezelter 115 end module switcheroo