MFIX  2016-1
calc_force_dem.f
Go to the documentation of this file.
1 !vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv!
2 ! !
3 ! Subroutine: CALC_FORCE_DEM !
4 ! Author: Jay Boyalakuntla Date: 12-Jun-04 !
5 ! !
6 ! Purpose: Calculate contact force and torque on particle from !
7 ! particle-particle and particle-wall collisions. Treats !
8 ! wall interaction also as a two-particle interaction but !
9 ! accounting for the wall properties !
10 ! !
11 !^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^!
12 #include "version.inc"
13  SUBROUTINE calc_force_dem
14 
15 ! Modules
16 !---------------------------------------------------------------------//
18  USE constant, ONLY: pi
19  USE derived_types, only: multisap, boxhandle
20  USE des_thermo
21  USE des_thermo_cond
22  USE discretelement
23  USE run
24  use pair_manager
25  use param1, only: one, small_number, zero
26 
27  IMPLICIT NONE
28 
29 ! Local variables
30 !---------------------------------------------------------------------//
31 ! percent of particle radius when excess overlap will be flagged
32  DOUBLE PRECISION, PARAMETER :: flag_overlap = 0.20d0
33 ! particle no. indices
34  INTEGER :: I, LL, cc, CC_START, CC_END
35 ! the overlap occuring between particle-particle or particle-wall
36 ! collision in the normal direction
37  DOUBLE PRECISION :: OVERLAP_N, OVERLAP_T(3)
38 ! square root of the overlap
39  DOUBLE PRECISION :: SQRT_OVERLAP
40 ! distance vector between two particle centers or between a particle
41 ! center and wall when the two surfaces are just at contact (i.e. no
42 ! overlap)
43  DOUBLE PRECISION :: R_LM,DIST_CI,DIST_CL
44 ! the normal and tangential components of the translational relative
45 ! velocity
46  DOUBLE PRECISION :: V_REL_TRANS_NORM, rad
47 ! distance vector between two particle centers or between a particle
48 ! center and wall at current and previous time steps
49  DOUBLE PRECISION :: DIST(3), NORMAL(3), DIST_MAG, POS(3)
50 ! tangent to the plane of contact at current time step
51  DOUBLE PRECISION :: VREL_T(3)
52 ! normal and tangential forces
53  DOUBLE PRECISION :: FN(3), FT(3)
54 ! temporary storage of force
55  DOUBLE PRECISION :: FC_TMP(3)
56 ! temporary storage of force for torque
57  DOUBLE PRECISION :: TOW_FORCE(3)
58 ! temporary storage of torque
59  DOUBLE PRECISION :: TOW_TMP(3,2)
60 ! temporary storage of conduction/radiation
61  DOUBLE PRECISION :: QQ_TMP
62 
63 ! store solids phase index of particle (i.e. pijk(np,5))
64  INTEGER :: PHASEI, PHASELL
65 ! local values used spring constants and damping coefficients
66  DOUBLE PRECISION :: ETAN_DES, ETAT_DES
67  DOUBLE PRECISION :: KN_DES, KT_DES
68 ! local values used for calculating cohesive forces
69  DOUBLE PRECISION :: FORCE_COH, EQ_RADIUS, DistApart
70 
71  LOGICAL, PARAMETER :: report_excess_overlap = .false.
72 
73  DOUBLE PRECISION :: FNMD, FTMD, MAG_OVERLAP_T, TANGENT(3)
74 
75  integer :: nn, mm, box_id, box_id2
76  logical :: found
77  integer :: pair(2)
78 
79 !......................................................................!
80 
81 ! Initialize cohesive forces
82  IF(use_cohesion) postcohesive(:) = zero
83 
85 
86 #ifdef do_sap
87  ! do nn=0, size(multisap%saps)-1
88  ! !print *,"nn = ",nn
89  ! if (.not.check_boxes(multisap%saps(nn))) ERROR_STOP __LINE__
90  ! if (.not.check_sort(multisap%saps(nn))) ERROR_STOP __LINE__
91  ! enddo
92 
93 !print *,"CALC_FORCE_DEM =================================================================================="
94 
95 print *," TOTAL NUM OF NEIGHBORS IS ",neighbor_index(max_pip-1)
96 
97 open (unit=123,file="neighbors.txt",action="write",status="replace")
98 
99 DO ll = 1, max_pip
100  cc_start = 1
101  IF (ll.gt.1) cc_start = neighbor_index(ll-1)
102  cc_end = neighbor_index(ll)
103 
104  DO cc = cc_start, cc_end-1
105  i = neighbors(cc)
106  write (123,*) ll,i
107  enddo
108 enddo
109 
110 close (unit=123)
111 
112  call reset_pairs(multisap%hashtable)
113  do
114  call get_pair(multisap%hashtable,pair)
115  if (pair(1).eq.0 .and. pair(2).eq.0) exit
116 
117  if ( des_radius(pair(1))+des_radius(pair(2))> sqrt(dot_product(des_pos_new(pair(1),:)-des_pos_new(pair(2),:),des_pos_new(pair(1),:)-des_pos_new(pair(2),:)))) then
118  print *,"invalid pair: ",pair(1),pair(2)
119  stop __line__
120  endif
121  enddo
122 #endif
123 
124 ! Check particle LL neighbor contacts
125 !---------------------------------------------------------------------//
126 
127 !!$omp parallel default(none) private(pos,rad,cc,cc_start,cc_end,ll,i, &
128 !!$omp overlap_n,vrel_t,v_rel_trans_norm,sqrt_overlap,dist,r_lm, &
129 !!$omp kn_des,kt_des,hert_kn,hert_kt,phasell,phasei,etan_des, &
130 !!$omp etat_des,fn,ft,overlap_t,tangent,mag_overlap_t, &
131 !!$omp eq_radius,distapart,force_coh,dist_mag,NORMAL,ftmd,fnmd, &
132 !!$omp dist_cl, dist_ci, fc_tmp, tow_tmp, tow_force, qq_tmp, box_id, box_id2, found) &
133 !!$omp shared(max_pip,neighbors,neighbor_index,des_pos_new,des_radius, &
134 !!$omp des_coll_model_enum,kn,kt,pft_neighbor,pijk, &
135 !!$omp des_etan,des_etat,mew,use_cohesion, calc_cond_des, dtsolid, &
136 !!$omp van_der_waals,vdw_outer_cutoff,vdw_inner_cutoff, &
137 !!$omp hamaker_constant,asperities,surface_energy, &
138 !!$omp tow, fc, energy_eq, grav_mag, postcohesive, pmass, q_source, multisap, boxhandle)
139 
140 !!$omp do
141 
142  DO ll = 1, max_pip
143  IF(is_nonexistent(ll)) cycle
144  pos = des_pos_new(ll,:)
145  rad = des_radius(ll)
146 
147  cc_start = 1
148  IF (ll.gt.1) cc_start = neighbor_index(ll-1)
149  cc_end = neighbor_index(ll)
150 
151  DO cc = cc_start, cc_end-1
152  i = neighbors(cc)
153  IF(is_nonexistent(i)) cycle
154 
155  r_lm = rad + des_radius(i)
156  dist(:) = des_pos_new(i,:) - pos(:)
157  dist_mag = dot_product(dist,dist)
158 
159  fc_tmp(:) = zero
160 
161 ! Compute particle-particle VDW cohesive short-range forces
162  IF(use_cohesion .AND. van_der_waals) THEN
163  IF(dist_mag < (r_lm+vdw_outer_cutoff)**2) THEN
164  eq_radius = 2d0 * des_radius(ll)*des_radius(i) / &
165  (des_radius(ll)+des_radius(i))
166  IF(dist_mag > (vdw_inner_cutoff+r_lm)**2) THEN
167  distapart = (sqrt(dist_mag)-r_lm)
168  force_coh = hamaker_constant * eq_radius / &
169  (12d0*distapart**2) * (asperities/(asperities+ &
170  eq_radius) + one/(one+asperities/distapart)**2 )
171  ELSE
172  force_coh = 2d0 * pi * surface_energy * eq_radius * &
173  (asperities/(asperities+eq_radius) + one/ &
174  (one+asperities/vdw_inner_cutoff)**2 )
175  ENDIF
176  fc_tmp(:) = dist(:)*force_coh/sqrt(dist_mag)
177  tow_tmp(:,:) = zero
178 
179 ! just for post-processing mag. of cohesive forces on each particle
180  postcohesive(ll) = postcohesive(ll) + force_coh / pmass(ll)
181  ENDIF
182  ENDIF
183 
184  IF (energy_eq) THEN
185  ! Calculate conduction and radiation for thermodynamic neighbors
186  IF(calc_cond_des(pijk(ll,5))) THEN
187  qq_tmp = des_conduction(ll, i, sqrt(dist_mag), pijk(ll,5), pijk(ll,4))
188 
189 !!$omp atomic
190  q_source(ll) = q_source(ll) + qq_tmp
191 
192 !!$omp atomic
193  q_source(i) = q_source(i) - qq_tmp
194  ENDIF
195  ENDIF
196 
197  IF(dist_mag > (r_lm - small_number)**2) THEN
198  pft_neighbor(:,cc) = 0.0
199  cycle
200  ENDIF
201 
202 #ifdef do_sap
203  if (.not.is_pair(multisap%hashtable,ll,i)) then
204 
205  print *,"SAP DIDNT FIND PAIR: ",ll,i
206  print *,"PARTICLE (",ll,"): ",des_pos_new(:,ll), " WITH RADIUS: ",des_radius(ll)
207  print *,"PARTICLE (",i,"): ",des_pos_new(:,i), " WITH RADIUS: ",des_radius(i)
208 
209  print *,""
210  print *," ****** ",sqrt(dot_product(des_pos_new(:,ll)-des_pos_new(:,i),des_pos_new(:,ll)-des_pos_new(:,i)))," *********"
211  print *,""
212 
213  ! print *,"LLLLLLLLL ",boxhandle(ll)%list(:)
214  ! print *,"IIIIIIIII ",boxhandle(i)%list(:)
215 
216  do mm=1,size(boxhandle(ll)%list)
217  if (boxhandle(ll)%list(mm)%sap_id < 0 ) cycle
218  print *," PARTICLE ",ll," IS IN ",boxhandle(ll)%list(mm)%sap_id
219  box_id = boxhandle(ll)%list(mm)%box_id
220 
221  found = .false.
222  do nn=1,size(boxhandle(i)%list)
223  if (boxhandle(i)%list(nn)%sap_id .eq. boxhandle(ll)%list(mm)%sap_id) then
224  ! print *," PARTICLE ",i," IS ALSO IN ",boxhandle(i)%list(nn)
225  box_id2 = boxhandle(i)%list(nn)%box_id
226  found = .true.
227  endif
228  enddo
229 
230  if (.not.found) cycle
231 
232  ! print *,"BOTH ",ll,i," ARE IN ",boxhandle(ll)%list(mm)
233 
234  enddo
235 
236  error_stop __line__
237  endif
238 #endif
239 
240  IF(dist_mag == 0) THEN
241  WRITE(*,8550) ll, i
242  error_stop "division by zero"
243  8550 FORMAT('distance between particles is zero:',2(2x,i10))
244  ENDIF
245 
246  dist_mag = sqrt(dist_mag)
247  normal(:)= dist(:)/dist_mag
248 
249 ! Calcuate the normal overlap
250  overlap_n = r_lm-dist_mag
251  IF(report_excess_overlap) CALL print_excess_overlap
252 
253 ! Calculate the components of translational relative velocity for a
254 ! contacting particle pair and the tangent to the plane of contact
255  CALL cfrelvel(ll, i, v_rel_trans_norm, vrel_t, &
256  normal(:), dist_mag)
257 
258  phasell = pijk(ll,5)
259  phasei = pijk(i,5)
260 
261 ! Hertz spring-dashpot contact model
262  IF (des_coll_model_enum .EQ. hertzian) THEN
263  sqrt_overlap = sqrt(overlap_n)
264  kn_des = hert_kn(phasell,phasei)*sqrt_overlap
265  kt_des = hert_kt(phasell,phasei)*sqrt_overlap
266  sqrt_overlap = sqrt(sqrt_overlap)
267  etan_des = des_etan(phasell,phasei)*sqrt_overlap
268  etat_des = des_etat(phasell,phasei)*sqrt_overlap
269 
270 ! Linear spring-dashpot contact model
271  ELSE
272  kn_des = kn
273  kt_des = kt
274  etan_des = des_etan(phasell,phasei)
275  etat_des = des_etat(phasell,phasei)
276  ENDIF
277 
278 ! Calculate the normal contact force
279  fn(:) = -(kn_des * overlap_n * normal(:) + &
280  etan_des * v_rel_trans_norm * normal(:))
281 
282 ! Calcuate the tangential overlap
283  overlap_t(:) = dtsolid*vrel_t(:) + pft_neighbor(:,cc)
284  mag_overlap_t = sqrt(dot_product(overlap_t,overlap_t))
285 
286 ! Calculate the tangential contact force.
287  IF(mag_overlap_t > 0.0) THEN
288 ! Tangential froce from spring.
289  ftmd = kt_des*mag_overlap_t
290 ! Max force before the on set of frictional slip.
291  fnmd = mew*sqrt(dot_product(fn,fn))
292 ! Direction of tangential force.
293  tangent = overlap_t/mag_overlap_t
294 ! Frictional slip
295  IF(ftmd > fnmd) THEN
296  ft = -fnmd * tangent
297  overlap_t = (fnmd/kt_des) * tangent
298  ELSE
299  ft = -ftmd * tangent
300  ENDIF
301  ELSE
302  ft = 0.0
303  ENDIF
304 
305 ! Add in the tangential dashpot damping force
306  ft = ft - etat_des * vrel_t(:)
307 
308 ! Save tangential displacement history
309  pft_neighbor(:,cc) = overlap_t(:)
310 
311 ! calculate the distance from the particles' centers to the contact point,
312 ! which is taken as the radical line
313 ! dist_ci+dist_cl=dist_li; dist_ci^2+a^2=ri^2; dist_cl^2+a^2=rl^2
314  dist_cl = dist_mag/2.d0 + (des_radius(ll)**2 - &
315  des_radius(i)**2)/(2.d0*dist_mag)
316 
317  dist_ci = dist_mag - dist_cl
318 
319  tow_force(:) = des_crossprdct(normal(:), ft(:))
320  tow_tmp(:,1) = dist_cl*tow_force(:)
321  tow_tmp(:,2) = dist_ci*tow_force(:)
322 
323 ! Calculate the total force FC of a collision pair
324 ! total contact force ( FC_TMP may already include cohesive force)
325  fc_tmp(:) = fc_tmp(:) + fn(:) + ft(:)
326 
327  fc(ll,:) = fc(ll,:) + fc_tmp(:)
328 
329 !!$omp atomic
330  fc(i,1) = fc(i,1) - fc_tmp(1)
331 !!$omp atomic
332  fc(i,2) = fc(i,2) - fc_tmp(2)
333 !!$omp atomic
334  fc(i,3) = fc(i,3) - fc_tmp(3)
335 
336 ! for each particle the signs of norm and ft both flip, so add the same torque
337  tow(ll,:) = tow(ll,:) + tow_tmp(:,1)
338 
339 !!$omp atomic
340  tow(i,1) = tow(i,1) + tow_tmp(1,2)
341 !!$omp atomic
342  tow(i,2) = tow(i,2) + tow_tmp(2,2)
343 !!$omp atomic
344  tow(i,3) = tow(i,3) + tow_tmp(3,2)
345 
346  ENDDO
347  ENDDO
348 !!$omp end do
349 
350 !!$omp end parallel
351 
352 ! just for post-processing mag. of cohesive forces on each particle
353  IF(use_cohesion .AND. van_der_waals .AND. grav_mag > zero) THEN
354  postcohesive(:) = postcohesive(:)/grav_mag
355  ENDIF
356 
357  RETURN
358 
359  contains
360 
361  include 'functions.inc'
362 
363 !vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv!
364 ! !
365 ! Subroutine: print_excess_overlap !
366 ! !
367 ! Purpose: Print overlap warning messages. !
368 ! !
369 !^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^!
370  SUBROUTINE print_excess_overlap
372  use error_manager
373 
374  IF(overlap_n > flag_overlap*des_radius(ll) .OR. &
375  overlap_n > flag_overlap*des_radius(i)) THEN
376 
377  WRITE(err_msg,1000) trim(ival(ll)), trim(ival(i)), s_time, &
378  des_radius(ll), des_radius(i), overlap_n
379 
380  CALL flush_err_msg(header=.false., footer=.false.)
381  ENDIF
382 
383  1000 FORMAT('WARNING: Excessive overplay detected between ', &
384  'particles ',a,' and ',/a,' at time ',g11.4,'.',/ &
385  'RADII: ',g11.4,' and ',g11.4,4x,'OVERLAP: ',g11.4)
386 
387  END SUBROUTINE print_excess_overlap
388 
389  END SUBROUTINE calc_force_dem
subroutine, public reset_pairs(this)
Definition: pair_manager.f:78
double precision, parameter one
Definition: param1_mod.f:29
subroutine print_excess_overlap
logical, dimension(dim_m) calc_cond_des
subroutine cfrelvel(L, II, VRN, VSLIP, NORM, DIST_LI)
Definition: cfrelvel.f:19
subroutine calc_force_dem
double precision, parameter small_number
Definition: param1_mod.f:24
logical function, public is_pair(this, i0, j0)
Definition: pair_manager.f:180
Definition: run_mod.f:13
subroutine, public get_pair(this, pair)
Definition: pair_manager.f:153
type(multisap_t) multisap
logical energy_eq
Definition: run_mod.f:100
character(len=line_length), dimension(line_count) err_msg
double precision, dimension(:), allocatable q_source
subroutine, public calc_dem_force_with_wall_stl
double precision, parameter pi
Definition: constant_mod.f:158
type(boxhandlelist_t), dimension(:), allocatable boxhandle
double precision function des_conduction(I, J, CENTER_DIST, iM, iIJK)
double precision, parameter zero
Definition: param1_mod.f:27
subroutine flush_err_msg(DEBUG, HEADER, FOOTER, ABORT, LOG, CALL_TREE)