kim-api  2.2.1+v2.2.1.GNU.GNU.
An Application Programming Interface (API) for the Knowledgebase of Interatomic Models (KIM).
ex_model_Ar_P_MLJ_Fortran.f90
Go to the documentation of this file.
1 !
2 ! CDDL HEADER START
3 !
4 ! The contents of this file are subject to the terms of the Common Development
5 ! and Distribution License Version 1.0 (the "License").
6 !
7 ! You can obtain a copy of the license at
8 ! http://www.opensource.org/licenses/CDDL-1.0. See the License for the
9 ! specific language governing permissions and limitations under the License.
10 !
11 ! When distributing Covered Code, include this CDDL HEADER in each file and
12 ! include the License file in a prominent location with the name LICENSE.CDDL.
13 ! If applicable, add the following below this CDDL HEADER, with the fields
14 ! enclosed by brackets "[]" replaced with your own identifying information:
15 !
16 ! Portions Copyright (c) [yyyy] [name of copyright owner]. All rights reserved.
17 !
18 ! CDDL HEADER END
19 !
20 
21 !
22 ! Copyright (c) 2013--2020, Regents of the University of Minnesota.
23 ! All rights reserved.
24 !
25 ! Contributors:
26 ! Ryan S. Elliott
27 ! Ellad B. Tadmor
28 ! Valeriu Smirichinski
29 ! Stephen M. Whalen
30 !
31 
32 !****************************************************************************
33 !**
34 !** MODULE ex_model_Ar_P_MLJ_F03
35 !**
36 !** Modified Lennard-Jones pair potential (with smooth cutoff) model for Ar
37 !**
38 !** Reference: Ashcroft and Mermin
39 !**
40 !** Language: Fortran 2003
41 !**
42 !****************************************************************************
43 
45 
46  use, intrinsic :: iso_c_binding
48  implicit none
49 
50  save
51  private
52  public compute_energy_forces, &
56  model_cutoff, &
57  speccode, &
58  buffer_type
59 
60 ! Below are the definitions and values of all Model parameters
61  integer(c_int), parameter :: cd = c_double ! used for literal constants
62  integer(c_int), parameter :: dim = 3 ! dimensionality of space
63  integer(c_int), parameter :: speccode = 1 ! internal species code
64  real(c_double), parameter :: model_cutoff = 8.15_cd ! cutoff radius
65  ! in angstroms
66  real(c_double), parameter :: model_cutsq = model_cutoff**2
67 
68  !-----------------------------------------------------------------------------
69  ! Below are the definitions and values of all additional model parameters
70  !
71  ! Recall that the Fortran 2003 format for declaring parameters is as follows:
72  !
73  ! integer(c_int), parameter :: parname = value ! This defines an integer
74  ! ! parameter called `parname'
75  ! ! with a value equal to
76  ! ! `value' (a number)
77  !
78  ! real(c_double), parameter :: parname = value ! This defines a real(c_double)
79  ! ! parameter called `parname'
80  ! ! with a value equal to
81  ! ! `value' (a number)
82  !-----------------------------------------------------------------------------
83  real(c_double), parameter :: lj_epsilon = 0.0104_cd
84  real(c_double), parameter :: lj_sigma = 3.40_cd
85  real(c_double), parameter :: lj_cutnorm = model_cutoff / lj_sigma
86  real(c_double), parameter :: &
87  lj_a = 12.0_cd * lj_epsilon * (-26.0_cd + 7.0_cd * lj_cutnorm**6) &
88  / (lj_cutnorm**14 * lj_sigma**2)
89  real(c_double), parameter :: &
90  lj_b = 96.0_cd * lj_epsilon * (7.0_cd - 2.0_cd * lj_cutnorm**6) &
91  / (lj_cutnorm**13 * lj_sigma)
92  real(c_double), parameter :: &
93  lj_c = 28.0_cd * lj_epsilon * (-13.0_cd + 4.0_cd * lj_cutnorm**6) &
94  / (lj_cutnorm**12)
95 
96  type, bind(c) :: buffer_type
97  real(c_double) :: influence_distance
98  real(c_double) :: cutoff(1)
99  integer(c_int) :: &
100  model_will_not_request_neighbors_of_noncontributing_particles(1)
101  end type buffer_type
102 
103 contains
104 
105  !-----------------------------------------------------------------------------
106  !
107  ! Calculate pair potential phi(r)
108  !
109  !-----------------------------------------------------------------------------
110  recursive subroutine calc_phi(r, phi)
111  implicit none
112 
113  !-- Transferred variables
114  real(c_double), intent(in) :: r
115  real(c_double), intent(out) :: phi
116 
117  !-- Local variables
118  real(c_double) rsq, sor, sor6, sor12
119 
120  rsq = r * r ! r^2
121  sor = lj_sigma / r ! (sig/r)
122  sor6 = sor * sor * sor !
123  sor6 = sor6 * sor6 ! (sig/r)^6
124  sor12 = sor6 * sor6 ! (sig/r)^12
125  if (r > model_cutoff) then
126  ! Argument exceeds cutoff radius
127  phi = 0.0_cd
128  else
129  phi = 4.0_cd * lj_epsilon * (sor12 - sor6) + lj_a * rsq + lj_b * r + lj_c
130  end if
131 
132  end subroutine calc_phi
133 
134  !-----------------------------------------------------------------------------
135  !
136  ! Calculate pair potential phi(r) and its derivative dphi(r)
137  !
138  !-----------------------------------------------------------------------------
139  recursive subroutine calc_phi_dphi(r, phi, dphi)
140  implicit none
141 
142  !-- Transferred variables
143  real(c_double), intent(in) :: r
144  real(c_double), intent(out) :: phi, dphi
145 
146  !-- Local variables
147  real(c_double) rsq, sor, sor6, sor12
148 
149  rsq = r * r ! r^2
150  sor = lj_sigma / r ! (sig/r)
151  sor6 = sor * sor * sor !
152  sor6 = sor6 * sor6 ! (sig/r)^6
153  sor12 = sor6 * sor6 ! (sig/r)^12
154  if (r > model_cutoff) then
155  ! Argument exceeds cutoff radius
156  phi = 0.0_cd
157  dphi = 0.0_cd
158  else
159  phi = 4.0_cd * lj_epsilon * (sor12 - sor6) + lj_a * rsq + lj_b * r + lj_c
160  dphi = 24.0_cd * lj_epsilon * (-2.0_cd * sor12 + sor6) / r &
161  + 2.0_cd * lj_a * r + lj_b
162  end if
163 
164  end subroutine calc_phi_dphi
165 
166  !-----------------------------------------------------------------------------
167  !
168  ! Compute energy and forces on particles from the positions.
169  !
170  !-----------------------------------------------------------------------------
171  recursive subroutine compute_energy_forces( &
172  model_compute_handle, model_compute_arguments_handle, ierr) bind(c)
173  implicit none
174 
175  !-- Transferred variables
176  type(kim_model_compute_handle_type), intent(in) :: model_compute_handle
177  type(kim_model_compute_arguments_handle_type), intent(in) :: &
178  model_compute_arguments_handle
179  integer(c_int), intent(out) :: ierr
180 
181  !-- Local variables
182  real(c_double) :: Rij(dim)
183  real(c_double) :: r, Rsqij, phi, dphi, dEidr = 0.0_cd
184  integer(c_int) :: i, j, jj, numnei, comp_force, comp_enepot, &
185  comp_virial, comp_energy
186  integer(c_int) :: ierr2
187 
188  !-- KIM variables
189  integer(c_int), pointer :: N
190  real(c_double), pointer :: energy
191  real(c_double), pointer :: coor(:, :)
192  real(c_double), pointer :: force(:, :)
193  real(c_double), pointer :: enepot(:)
194  integer(c_int), pointer :: nei1part(:)
195  integer(c_int), pointer :: particleSpeciesCodes(:)
196  integer(c_int), pointer :: particleContributing(:)
197  real(c_double), pointer :: virial(:)
198 
199  ! Unpack data from KIM object
200  !
201  ierr = 0
202  call kim_get_argument_pointer( &
203  model_compute_arguments_handle, &
204  kim_compute_argument_name_number_of_particles, n, ierr2)
205  ierr = ierr + ierr2
206  call kim_get_argument_pointer( &
207  model_compute_arguments_handle, &
208  kim_compute_argument_name_particle_species_codes, n, &
209  particlespeciescodes, ierr2)
210  ierr = ierr + ierr2
211  call kim_get_argument_pointer( &
212  model_compute_arguments_handle, &
213  kim_compute_argument_name_particle_contributing, n, &
214  particlecontributing, ierr2)
215  ierr = ierr + ierr2
216  call kim_get_argument_pointer( &
217  model_compute_arguments_handle, &
218  kim_compute_argument_name_coordinates, dim, n, coor, ierr2)
219  ierr = ierr + ierr2
220  call kim_get_argument_pointer( &
221  model_compute_arguments_handle, &
222  kim_compute_argument_name_partial_energy, energy, ierr2)
223  ierr = ierr + ierr2
224  call kim_get_argument_pointer( &
225  model_compute_arguments_handle, &
226  kim_compute_argument_name_partial_forces, dim, n, force, ierr2)
227  ierr = ierr + ierr2
228  call kim_get_argument_pointer( &
229  model_compute_arguments_handle, &
230  kim_compute_argument_name_partial_particle_energy, n, enepot, ierr2)
231  ierr = ierr + ierr2
232  call kim_get_argument_pointer( &
233  model_compute_arguments_handle, &
234  kim_compute_argument_name_partial_virial, 6, virial, ierr2)
235  ierr = ierr + ierr2
236  if (ierr /= 0) then
237  call kim_log_entry(model_compute_arguments_handle, &
238  kim_log_verbosity_error, "get data")
239  ierr = 1
240  return
241  end if
242 
243  ! Check to see if we have been asked to compute the forces, energyperpart,
244  ! energy and virial
245  !
246  if (associated(energy)) then
247  comp_energy = 1
248  else
249  comp_energy = 0
250  end if
251  if (associated(force)) then
252  comp_force = 1
253  else
254  comp_force = 0
255  end if
256  if (associated(enepot)) then
257  comp_enepot = 1
258  else
259  comp_enepot = 0
260  end if
261  if (associated(virial)) then
262  comp_virial = 1
263  else
264  comp_virial = 0
265  end if
266 
267  ! Check to be sure that the species are correct
268  !
269  ierr = 1 ! assume an error
270  do i = 1, n
271  if (particlespeciescodes(i) /= speccode) then
272  call kim_log_entry( &
273  model_compute_handle, kim_log_verbosity_error, &
274  "Unexpected species code detected")
275  ierr = 1
276  return
277  end if
278  end do
279  ierr = 0 ! everything is ok
280 
281  ! Initialize potential energies, forces, virial term
282  !
283  if (comp_enepot == 1) enepot = 0.0_cd
284  if (comp_energy == 1) energy = 0.0_cd
285  if (comp_force == 1) force = 0.0_cd
286  if (comp_virial == 1) virial = 0.0_cd
287 
288  !
289  ! Compute energy and forces
290  !
291 
292  ! Loop over particles and compute energy and forces
293  !
294  do i = 1, n
295  if (particlecontributing(i) == 1) then
296  ! Set up neighbor list for next particle
297  call kim_get_neighbor_list( &
298  model_compute_arguments_handle, 1, i, numnei, nei1part, ierr)
299  if (ierr /= 0) then
300  ! some sort of problem, exit
301  call kim_log_entry( &
302  model_compute_arguments_handle, kim_log_verbosity_error, &
303  "GetNeighborList failed")
304  ierr = 1
305  return
306  end if
307 
308  ! Loop over the neighbors of particle i
309  !
310  do jj = 1, numnei
311 
312  j = nei1part(jj) ! get neighbor ID
313 
314  ! compute relative position vector
315  !
316  rij(:) = coor(:, j) - coor(:, i) ! distance vector between i j
317 
318  ! compute energy and forces
319  !
320  rsqij = dot_product(rij, rij) ! compute square distance
321  if (rsqij < model_cutsq) then ! particles are interacting?
322 
323  r = sqrt(rsqij) ! compute distance
324  if (comp_force == 1 .or. comp_virial == 1) then
325  call calc_phi_dphi(r, phi, dphi) ! compute pair potential
326  ! and it derivative
327  deidr = 0.5_cd * dphi
328  else
329  call calc_phi(r, phi) ! compute just pair potential
330  end if
331 
332  ! contribution to energy
333  !
334  if (comp_enepot == 1) then
335  enepot(i) = enepot(i) + 0.5_cd * phi ! accumulate energy
336  end if
337  if (comp_energy == 1) then
338  energy = energy + 0.5_cd * phi
339  end if
340 
341  ! contribution to virial tensor, virial(i,j)=r(i)*r(j)*(dV/dr)/r
342  !
343  if (comp_virial == 1) then
344  virial(1) = virial(1) + rij(1) * rij(1) * deidr / r
345  virial(2) = virial(2) + rij(2) * rij(2) * deidr / r
346  virial(3) = virial(3) + rij(3) * rij(3) * deidr / r
347  virial(4) = virial(4) + rij(2) * rij(3) * deidr / r
348  virial(5) = virial(5) + rij(1) * rij(3) * deidr / r
349  virial(6) = virial(6) + rij(1) * rij(2) * deidr / r
350  end if
351 
352  ! contribution to forces
353  !
354  if (comp_force == 1) then
355  force(:, i) = force(:, i) + deidr * rij / r ! accumulate force on i
356  force(:, j) = force(:, j) - deidr * rij / r ! accumulate force on j
357  end if
358 
359  end if
360 
361  end do ! loop on jj
362 
363  end if ! if particleContributing
364 
365  end do ! do i
366 
367  ! Everything is great
368  !
369  ierr = 0
370  return
371 
372  end subroutine compute_energy_forces
373 
374  !-----------------------------------------------------------------------------
375  !
376  ! Model destroy routine (REQUIRED)
377  !
378  !-----------------------------------------------------------------------------
379  recursive subroutine model_destroy_func(model_destroy_handle, ierr) bind(c)
380  use, intrinsic :: iso_c_binding
381  implicit none
382 
383  !-- Transferred variables
384  type(kim_model_destroy_handle_type), intent(inout) :: model_destroy_handle
385  integer(c_int), intent(out) :: ierr
386 
387  type(buffer_type), pointer :: buf; type(c_ptr) :: pbuf
388 
389  call kim_get_model_buffer_pointer(model_destroy_handle, pbuf)
390  call c_f_pointer(pbuf, buf)
391  call kim_log_entry(model_destroy_handle, &
392  kim_log_verbosity_error, "deallocating model buffer")
393  deallocate (buf)
394  ierr = 0 ! everything is good
395  end subroutine model_destroy_func
396 
397  !-----------------------------------------------------------------------------
398  !
399  ! Model compute arguments create routine (REQUIRED)
400  !
401  !-----------------------------------------------------------------------------
402  recursive subroutine model_compute_arguments_create( &
403  model_compute_handle, model_compute_arguments_create_handle, ierr) bind(c)
404  use, intrinsic :: iso_c_binding
405  implicit none
406 
407  !-- Transferred variables
408  type(kim_model_compute_handle_type), intent(in) :: model_compute_handle
409  type(kim_model_compute_arguments_create_handle_type), intent(inout) :: &
410  model_compute_arguments_create_handle
411  integer(c_int), intent(out) :: ierr
412 
413  integer(c_int) :: ierr2
414 
415  ! avoid unused dummy argument warnings
416  if (model_compute_handle == kim_model_compute_null_handle) continue
417 
418  ierr = 0
419  ierr2 = 0
420 
421  ! register arguments
422  call kim_set_argument_support_status( &
423  model_compute_arguments_create_handle, &
424  kim_compute_argument_name_partial_energy, &
425  kim_support_status_optional, ierr2)
426  ierr = ierr + ierr2
427  call kim_set_argument_support_status( &
428  model_compute_arguments_create_handle, &
429  kim_compute_argument_name_partial_forces, &
430  kim_support_status_optional, ierr2)
431  ierr = ierr + ierr2
432  call kim_set_argument_support_status( &
433  model_compute_arguments_create_handle, &
434  kim_compute_argument_name_partial_particle_energy, &
435  kim_support_status_optional, ierr2)
436  ierr = ierr + ierr2
437  call kim_set_argument_support_status( &
438  model_compute_arguments_create_handle, &
439  kim_compute_argument_name_partial_virial, &
440  kim_support_status_optional, ierr2)
441  ierr = ierr + ierr2
442 
443  ! register call backs
444  ! NONE
445 
446  if (ierr /= 0) then
447  ierr = 1
448  call kim_log_entry( &
449  model_compute_arguments_create_handle, kim_log_verbosity_error, &
450  "Unable to successfully create compute_arguments object")
451  end if
452 
453  ierr = 0
454  return
455  end subroutine model_compute_arguments_create
456 
457  !-----------------------------------------------------------------------------
458  !
459  ! Model compute arguments destroy routine (REQUIRED)
460  !
461  !-----------------------------------------------------------------------------
462  recursive subroutine model_compute_arguments_destroy( &
463  model_compute_handle, model_compute_arguments_destroy_handle, ierr) bind(c)
464  use, intrinsic :: iso_c_binding
465  implicit none
466 
467  !-- Transferred variables
468  type(kim_model_compute_handle_type), intent(in) :: model_compute_handle
469  type(kim_model_compute_arguments_destroy_handle_type), intent(inout) :: &
470  model_compute_arguments_destroy_handle
471  integer(c_int), intent(out) :: ierr
472 
473  ! avoid unused dummy argument warnings
474  if (model_compute_handle == kim_model_compute_null_handle) continue
475  if (model_compute_arguments_destroy_handle == &
476  kim_model_compute_arguments_destroy_null_handle) continue
477 
478  ierr = 0
479  return
480  end subroutine model_compute_arguments_destroy
481 
482 end module ex_model_ar_p_mlj_f03
483 
484 !-------------------------------------------------------------------------------
485 !
486 ! Model create routine (REQUIRED)
487 !
488 !-------------------------------------------------------------------------------
489 recursive subroutine model_create_routine( &
490  model_create_handle, requested_length_unit, requested_energy_unit, &
491  requested_charge_unit, requested_temperature_unit, requested_time_unit, &
492  ierr) bind(c)
493  use, intrinsic :: iso_c_binding
496  implicit none
497 
498  !-- Transferred variables
499  type(kim_model_create_handle_type), intent(inout) :: model_create_handle
500  type(kim_length_unit_type), intent(in), value :: requested_length_unit
501  type(kim_energy_unit_type), intent(in), value :: requested_energy_unit
502  type(kim_charge_unit_type), intent(in), value :: requested_charge_unit
503  type(kim_temperature_unit_type), intent(in), value :: &
504  requested_temperature_unit
505  type(kim_time_unit_type), intent(in), value :: requested_time_unit
506  integer(c_int), intent(out) :: ierr
507 
508  !-- KIM variables
509  integer(c_int) :: ierr2
510  type(buffer_type), pointer :: buf
511 
512  ierr = 0
513  ierr2 = 0
514 
515  ! avoid unsed dummy argument warnings
516  if (requested_length_unit == kim_length_unit_unused) continue
517  if (requested_energy_unit == kim_energy_unit_unused) continue
518  if (requested_charge_unit == kim_charge_unit_unused) continue
519  if (requested_temperature_unit == kim_temperature_unit_unused) continue
520  if (requested_time_unit == kim_time_unit_unused) continue
521 
522  ! set units
523  call kim_set_units(model_create_handle, &
524  kim_length_unit_a, &
525  kim_energy_unit_ev, &
526  kim_charge_unit_unused, &
527  kim_temperature_unit_unused, &
528  kim_time_unit_unused, &
529  ierr2)
530  ierr = ierr + ierr2
531 
532  ! register species
533  call kim_set_species_code(model_create_handle, &
534  kim_species_name_ar, speccode, ierr2)
535  ierr = ierr + ierr2
536 
537  ! register numbering
538  call kim_set_model_numbering(model_create_handle, &
539  kim_numbering_one_based, ierr2)
540  ierr = ierr + ierr2
541 
542  ! register function pointers
543  call kim_set_routine_pointer( &
544  model_create_handle, &
545  kim_model_routine_name_compute, kim_language_name_fortran, &
546  1, c_funloc(compute_energy_forces), ierr2)
547  ierr = ierr + ierr2
548  call kim_set_routine_pointer( &
549  model_create_handle, kim_model_routine_name_compute_arguments_create, &
550  kim_language_name_fortran, 1, c_funloc(model_compute_arguments_create), &
551  ierr2)
552  ierr = ierr + ierr2
553  call kim_set_routine_pointer( &
554  model_create_handle, kim_model_routine_name_compute_arguments_destroy, &
555  kim_language_name_fortran, 1, c_funloc(model_compute_arguments_destroy), &
556  ierr2)
557  ierr = ierr + ierr2
558  call kim_set_routine_pointer( &
559  model_create_handle, &
560  kim_model_routine_name_destroy, kim_language_name_fortran, &
561  1, c_funloc(model_destroy_func), ierr2)
562  ierr = ierr + ierr2
563 
564  ! allocate buffer
565  allocate (buf)
566 
567  ! store model buffer in KIM object
568  call kim_set_model_buffer_pointer(model_create_handle, &
569  c_loc(buf))
570 
571  ! set buffer values
572  buf%influence_distance = model_cutoff
573  buf%cutoff = model_cutoff
574  buf%model_will_not_request_neighbors_of_noncontributing_particles = 1
575 
576  ! register influence distance
577  call kim_set_influence_distance_pointer( &
578  model_create_handle, buf%influence_distance)
579 
580  ! register cutoff
581  call kim_set_neighbor_list_pointers( &
582  model_create_handle, 1, buf%cutoff, &
583  buf%model_will_not_request_neighbors_of_noncontributing_particles)
584 
585  if (ierr /= 0) then
586  ierr = 1
587  deallocate (buf)
588  call kim_log_entry(model_create_handle, kim_log_verbosity_error, &
589  "Unable to successfully initialize model")
590  end if
591 
592  ierr = 0
593  return
594 
595 end subroutine model_create_routine
recursive subroutine, public compute_energy_forces(model_compute_handle, model_compute_arguments_handle, ierr)
static void calc_phi_dphi(double const *epsilon, double const *C, double const *Rzero, double const *shift, double const cutoff, double const r, double *phi, double *dphi)
recursive subroutine, public model_destroy_func(model_destroy_handle, ierr)
recursive subroutine, public model_compute_arguments_create(model_compute_handle, model_compute_arguments_create_handle, ierr)
static void calc_phi(double const *epsilon, double const *C, double const *Rzero, double const *shift, double const cutoff, double const r, double *phi)
real(c_double), parameter, public model_cutoff
recursive subroutine, public model_compute_arguments_destroy(model_compute_handle, model_compute_arguments_destroy_handle, ierr)
integer(c_int), parameter, public speccode