FrontISTR  6.0.0
Large-scale structural analysis program with finit element method
utilities.f90
Go to the documentation of this file.
1 !-------------------------------------------------------------------------------
2 ! Copyright (c) 2019 FrontISTR Commons
3 ! This software is released under the MIT License, see LICENSE.txt
4 !-------------------------------------------------------------------------------
6 module m_utilities
7  use hecmw
8  implicit none
9 
10  real(kind=kreal), parameter, private :: pi=3.14159265358979d0
11 
12 contains
13 
15  subroutine memget(var,dimn,syze)
16  integer :: var,dimn,syze,bite
17  parameter(bite=1)
18  var = var + dimn*syze*bite
19  end subroutine memget
20 
21 
23  subroutine insert_int2array( iin, carray )
24  integer, intent(in) :: iin
25  integer, pointer :: carray(:)
26 
27  integer :: i, oldsize
28  integer, pointer :: dumarray(:) => null()
29  if( .not. associated(carray) ) then
30  allocate( carray(1) )
31  carray(1) = iin
32  else
33  oldsize = size( carray )
34  allocate( dumarray(oldsize) )
35  do i=1,oldsize
36  dumarray(i) = carray(i)
37  enddo
38  deallocate( carray )
39  allocate( carray(oldsize+1) )
40  do i=1,oldsize
41  carray(i) = dumarray(i)
42  enddo
43  carray(oldsize+1) = iin
44  endif
45  if( associated(dumarray) ) deallocate( dumarray )
46  end subroutine
47 
49  subroutine tensor_eigen3( tensor, eigval )
50  real(kind=kreal), intent(in) :: tensor(6)
51  real(kind=kreal), intent(out) :: eigval(3)
52 
53  real(kind=kreal) :: i1,i2,i3,r,theta,q, x(3,3), xx(3,3)
54  real(kind=kreal), parameter :: small = 1.0d-10
55 
56  x(1,1)=tensor(1); x(2,2)=tensor(2); x(3,3)=tensor(3)
57  x(1,2)=tensor(4); x(2,1)=x(1,2)
58  x(2,3)=tensor(5); x(3,2)=x(2,3)
59  x(3,1)=tensor(6); x(1,3)=x(3,1)
60 
61  xx= matmul( x,x )
62  i1= x(1,1)+x(2,2)+x(3,3)
63  i2= 0.5d0*( i1*i1 - (xx(1,1)+xx(2,2)+xx(3,3)) )
64  i3= x(1,1)*x(2,2)*x(3,3)+x(2,1)*x(3,2)*x(1,3)+x(3,1)*x(1,2)*x(2,3) &
65  -x(3,1)*x(2,2)*x(1,3)-x(2,1)*x(1,2)*x(3,3)-x(1,1)*x(3,2)*x(2,3)
66 
67  r=(-2.d0*i1*i1*i1+9.d0*i1*i2-27.d0*i3)/54.d0
68  q=(i1*i1-3.d0*i2)/9.d0
69 
70  ! Check discriminant to ensure all eigenvalues are real
71  ! For a 3x3 symmetric matrix, Delta = R^2 - Q^3 must be negative or zero
72  if(r*r - q*q*q > small) then
73  write(*,*) 'ERROR in tensor_eigen3: Discriminant R^2 - Q^3 > 0'
74  write(*,*) 'This indicates the algorithm has numerical issues.'
75  write(*,*) 'Discriminant =', r*r - q*q*q
76  stop 'Eigenvalue calculation failed - possible numerical error'
77  endif
78 
79  ! Add handling for special cases (when Q is close to 0)
80  if(abs(q) < small) then
81  ! Matrix has nearly equal diagonal elements (e.g. close to identity matrix)
82  eigval(1) = i1/3.d0
83  eigval(2) = i1/3.d0
84  eigval(3) = i1/3.d0
85  else
86  ! For Q^3 sufficiently small, address numerical stability
87  if(abs(q*q*q) < small) then
88  ! Q^3 is very small, but not zero - special handling
89  if(abs(r) < small) then
90  ! Both R and Q^3 small means nearly triple root
91  eigval(1) = i1/3.d0
92  eigval(2) = i1/3.d0
93  eigval(3) = i1/3.d0
94  else
95  ! When Q^3 is very small, determine theta based on sign of R only
96  ! This avoids division by a very small number which could cause instability
97  if(r >= 0.0d0) then
98  theta = 0.0d0 ! R > 0 case
99  else
100  theta = pi ! R < 0 case
101  endif
102  endif
103  else
104  ! Ensure R/sqrt(Q^3) is within [-1,1] for numerical stability
105  theta = acos(max(-1.0d0, min(1.0d0, r/dsqrt(q*q*q))))
106  endif
107 
108  eigval(1) = -2.d0*dsqrt(q)*cos(theta/3.d0)+i1/3.d0
109  eigval(2) = -2.d0*dsqrt(q)*cos((theta+2.d0*pi)/3.d0)+i1/3.d0
110  eigval(3) = -2.d0*dsqrt(q)*cos((theta-2.d0*pi)/3.d0)+i1/3.d0
111  endif
112 
113  end subroutine
114 
117  subroutine eigen3 (tensor, eigval, princ)
118  real(kind=kreal), intent(in) :: tensor(6)
119  real(kind=kreal), intent(out) :: eigval(3)
120  real(kind=kreal), intent(out) :: princ(3, 3)
121 
122  integer, parameter :: msweep = 50
123  integer :: i,j, is, ip, iq, ir
124  real(kind=kreal) :: fsum, od, theta, t, c, s, tau, g, h, hd, btens(3,3), factor
125 
126  btens(1,1)=tensor(1); btens(2,2)=tensor(2); btens(3,3)=tensor(3)
127  btens(1,2)=tensor(4); btens(2,1)=btens(1,2)
128  btens(2,3)=tensor(5); btens(3,2)=btens(2,3)
129  btens(3,1)=tensor(6); btens(1,3)=btens(3,1)
130  !
131  ! Initialise princ to the identity
132  !
133  factor = 0.d0
134  do i = 1, 3
135  do j = 1, 3
136  princ(i, j) = 0.d0
137  end do
138  princ(i, i) = 1.d0
139  eigval(i) = btens(i, i)
140  factor = factor + dabs(btens(i,i))
141  end do
142  ! Scaling and iszero/isnan exception
143  if( factor == 0.d0 .or. factor /= factor ) then
144  return
145  else
146  eigval(1:3) = eigval(1:3)/factor
147  btens(1:3,1:3) = btens(1:3,1:3)/factor
148  end if
149 
150  !
151  ! Starts sweeping.
152  !
153  do is = 1, msweep
154  fsum = 0.d0
155  do ip = 1, 2
156  do iq = ip + 1, 3
157  fsum = fsum + abs( btens(ip, iq) )
158  end do
159  end do
160  !
161  ! If the fsum of off-diagonal terms is zero returns
162  !
163  if ( fsum < 1.d-10 ) then
164  eigval(1:3) = eigval(1:3)*factor
165  return
166  endif
167  !
168  ! Performs the sweep in three rotations. One per off diagonal term
169  !
170  do ip = 1, 2
171  do iq = ip + 1, 3
172  od = 100.d0 * abs(btens(ip, iq) )
173  if ( (od+abs(eigval(ip) ) /= abs(eigval(ip) )) &
174  .and. (od+abs(eigval(iq) ) /= abs(eigval(iq) ))) then
175  hd = eigval(iq) - eigval(ip)
176  !
177  ! Evaluates the rotation angle
178  !
179  if ( abs(hd) + od == abs(hd) ) then
180  t = btens(ip, iq) / hd
181  else
182  theta = 0.5d0 * hd / btens(ip, iq)
183  t = 1.d0 / (abs(theta) + sqrt(1.d0 + theta**2) )
184  if ( theta < 0.d0 ) t = - t
185  end if
186  !
187  ! Re-evaluates the diagonal terms
188  !
189  c = 1.d0 / sqrt(1.d0 + t**2)
190  s = t * c
191  tau = s / (1.d0 + c)
192  h = t * btens(ip, iq)
193  eigval(ip) = eigval(ip) - h
194  eigval(iq) = eigval(iq) + h
195  !
196  ! Re-evaluates the remaining off-diagonal terms
197  !
198  ir = 6 - ip - iq
199  g = btens(min(ir, ip), max(ir, ip) )
200  h = btens(min(ir, iq), max(ir, iq) )
201  btens(min(ir, ip), max(ir, ip) ) = g &
202  - s * (h + g * tau)
203  btens(min(ir, iq), max(ir, iq) ) = h &
204  + s * (g - h * tau)
205  !
206  ! Rotates the eigenvectors
207  !
208  do ir = 1, 3
209  g = princ(ir, ip)
210  h = princ(ir, iq)
211  princ(ir, ip) = g - s * (h + g * tau)
212  princ(ir, iq) = h + s * (g - h * tau)
213  end do
214  end if
215  btens(ip, iq) = 0.d0
216  end do
217  end do
218  end do ! over sweeps
219  !
220  ! If convergence is not achieved stops
221  !
222  stop ' Jacobi iteration unable to converge'
223  end subroutine eigen3
224 
226  real(kind=kreal) function determinant( mat )
227  real(kind=kreal) :: mat(6)
228  real(kind=kreal) :: xj(3,3)
229 
230  xj(1,1)=mat(1); xj(2,2)=mat(2); xj(3,3)=mat(3)
231  xj(1,2)=mat(4); xj(2,1)=xj(1,2)
232  xj(2,3)=mat(5); xj(3,2)=xj(2,3)
233  xj(3,1)=mat(6); xj(1,3)=xj(3,1)
234 
235  determinant=xj(1,1)*xj(2,2)*xj(3,3) &
236  +xj(2,1)*xj(3,2)*xj(1,3) &
237  +xj(3,1)*xj(1,2)*xj(2,3) &
238  -xj(3,1)*xj(2,2)*xj(1,3) &
239  -xj(2,1)*xj(1,2)*xj(3,3) &
240  -xj(1,1)*xj(3,2)*xj(2,3)
241  end function determinant
242 
244  real(kind=kreal) function determinant33( XJ )
245  real(kind=kreal) :: xj(3,3)
246 
247  determinant33=xj(1,1)*xj(2,2)*xj(3,3) &
248  +xj(2,1)*xj(3,2)*xj(1,3) &
249  +xj(3,1)*xj(1,2)*xj(2,3) &
250  -xj(3,1)*xj(2,2)*xj(1,3) &
251  -xj(2,1)*xj(1,2)*xj(3,3) &
252  -xj(1,1)*xj(3,2)*xj(2,3)
253  end function determinant33
254 
255  subroutine fstr_chk_alloc( imsg, sub_name, ierr )
256  use hecmw
257  character(*) :: sub_name
258  integer(kind=kint) :: imsg
259  integer(kind=kint) :: ierr
260 
261  if( ierr /= 0 ) then
262  write(imsg,*) 'Memory overflow at ', sub_name
263  write(*,*) 'Memory overflow at ', sub_name
264  call hecmw_abort( hecmw_comm_get_comm( ) )
265  endif
266  end subroutine fstr_chk_alloc
267 
269  subroutine calinverse(NN, A)
270  integer, intent(in) :: NN
271  real(kind=kreal), intent(inout) :: a(nn,nn)
272 
273  integer :: I, J,K,IW,LR,IP(NN)
274  real(kind=kreal) :: w,wmax,pivot,api,eps,det
275  data eps/1.0e-35/
276  det=1.d0
277  lr = 0
278  do i=1,nn
279  ip(i)=i
280  enddo
281  do k=1,nn
282  wmax=0.d0
283  do i=k,nn
284  w=dabs(a(i,k))
285  if (w.GT.wmax) then
286  wmax=w
287  lr=i
288  endif
289  enddo
290  pivot=a(lr,k)
291  api=abs(pivot)
292  if(api.LE.eps) then
293  !$omp critical
294  write(*,'(''PIVOT ERROR AT'',I5)') k
295  !$omp end critical
296  stop
297  end if
298  det=det*pivot
299  if (lr.NE.k) then
300  det=-det
301  iw=ip(k)
302  ip(k)=ip(lr)
303  ip(lr)=iw
304  do j=1,nn
305  w=a(k,j)
306  a(k,j)=a(lr,j)
307  a(lr,j)=w
308  enddo
309  endif
310  do i=1,nn
311  a(k,i)=a(k,i)/pivot
312  enddo
313  do i=1,nn
314  if (i.NE.k) then
315  w=a(i,k)
316  if (w.NE.0.) then
317  do j=1,nn
318  if (j.NE.k) a(i,j)=a(i,j)-w*a(k,j)
319  enddo
320  a(i,k)=-w/pivot
321  endif
322  endif
323  enddo
324  a(k,k)=1.d0/pivot
325  enddo
326 
327  do i=1,nn
328  k=ip(i)
329  if (k.NE.i) then
330  iw=ip(k)
331  ip(k)=ip(i)
332  ip(i)=iw
333  do j=1,nn
334  w=a(j,i)
335  a(j,i)=a(j,k)
336  a(j,k)=w
337  enddo
338  endif
339  enddo
340 
341  end subroutine calinverse
342 
344  subroutine calsolve(NN, A, b)
345  integer, intent(in) :: NN
346  real(kind=kreal), intent(inout) :: a(nn,nn)
347  real(kind=kreal), intent(inout) :: b(nn)
348 
349  integer :: i, j, k, imax
350  real(kind=kreal) :: w, piv
351 
352  ! Forward elimination
353  do k = 1, nn-1
354  imax = k
355  do i = k+1, nn
356  if( dabs(a(i,k)) > dabs(a(imax,k)) ) imax = i
357  end do
358  if( imax /= k ) then
359  do j = k, nn
360  w = a(k,j); a(k,j) = a(imax,j); a(imax,j) = w
361  end do
362  w = b(k); b(k) = b(imax); b(imax) = w
363  end if
364  piv = a(k,k)
365  do i = k+1, nn
366  w = a(i,k) / piv
367  do j = k+1, nn
368  a(i,j) = a(i,j) - w * a(k,j)
369  end do
370  b(i) = b(i) - w * b(k)
371  end do
372  end do
373  ! Back substitution
374  do i = nn, 1, -1
375  do j = i+1, nn
376  b(i) = b(i) - a(i,j) * b(j)
377  end do
378  b(i) = b(i) / a(i,i)
379  end do
380  end subroutine calsolve
381 
382  subroutine cross_product(v1,v2,vn)
383  real(kind=kreal),intent(in) :: v1(3),v2(3)
384  real(kind=kreal),intent(out) :: vn(3)
385 
386  vn(1) = v1(2)*v2(3) - v1(3)*v2(2)
387  vn(2) = v1(3)*v2(1) - v1(1)*v2(3)
388  vn(3) = v1(1)*v2(2) - v1(2)*v2(1)
389  end subroutine cross_product
390 
391  subroutine transformation(jacob, tm)
392  real(kind=kreal),intent(in) :: jacob(3,3)
393  real(kind=kreal),intent(out) :: tm(6,6)
394 
395  integer :: i,j
396 
397  do i=1,3
398  do j=1,3
399  tm(i,j)= jacob(i,j)*jacob(i,j)
400  enddo
401  tm(i,4) = jacob(i,1)*jacob(i,2)
402  tm(i,5) = jacob(i,2)*jacob(i,3)
403  tm(i,6) = jacob(i,3)*jacob(i,1)
404  enddo
405  tm(4,1) = 2.d0*jacob(1,1)*jacob(2,1)
406  tm(5,1) = 2.d0*jacob(2,1)*jacob(3,1)
407  tm(6,1) = 2.d0*jacob(3,1)*jacob(1,1)
408  tm(4,2) = 2.d0*jacob(1,2)*jacob(2,2)
409  tm(5,2) = 2.d0*jacob(2,2)*jacob(3,2)
410  tm(6,2) = 2.d0*jacob(3,2)*jacob(1,2)
411  tm(4,3) = 2.d0*jacob(1,3)*jacob(2,3)
412  tm(5,3) = 2.d0*jacob(2,3)*jacob(3,3)
413  tm(6,3) = 2.d0*jacob(3,3)*jacob(1,3)
414  tm(4,4) = jacob(1,1)*jacob(2,2) + jacob(1,2)*jacob(2,1)
415  tm(5,4) = jacob(2,1)*jacob(3,2) + jacob(2,2)*jacob(3,1)
416  tm(6,4) = jacob(3,1)*jacob(1,2) + jacob(3,2)*jacob(1,1)
417  tm(4,5) = jacob(1,2)*jacob(2,3) + jacob(1,3)*jacob(2,2)
418  tm(5,5) = jacob(2,2)*jacob(3,3) + jacob(2,3)*jacob(3,2)
419  tm(6,5) = jacob(3,2)*jacob(1,3) + jacob(3,3)*jacob(1,2)
420  tm(4,6) = jacob(1,3)*jacob(2,1) + jacob(1,1)*jacob(2,3)
421  tm(5,6) = jacob(2,3)*jacob(3,1) + jacob(2,1)*jacob(3,3)
422  tm(6,6) = jacob(3,3)*jacob(1,1) + jacob(3,1)*jacob(1,3)
423 
424  end subroutine transformation
425 
426  subroutine get_principal (tensor, eigval, princmatrix)
427 
428  implicit none
429  integer i,j
430  real(kind=kreal) :: tensor(1:6)
431  real(kind=kreal) :: eigval(3)
432  real(kind=kreal) :: princmatrix(3,3)
433  real(kind=kreal) :: princnormal(3,3)
434  real(kind=kreal) :: tempv(3)
435  real(kind=kreal) :: temps
436 
437  call eigen3(tensor,eigval,princnormal)
438 
439  if (eigval(1)<eigval(2)) then
440  temps=eigval(1)
441  eigval(1)=eigval(2)
442  eigval(2)=temps
443  tempv(:)=princnormal(:,1)
444  princnormal(:,1)=princnormal(:,2)
445  princnormal(:,2)=tempv(:)
446  end if
447  if (eigval(1)<eigval(3)) then
448  temps=eigval(1)
449  eigval(1)=eigval(3)
450  eigval(3)=temps
451  tempv(:)=princnormal(:,1)
452  princnormal(:,1)=princnormal(:,3)
453  princnormal(:,3)=tempv(:)
454  end if
455  if (eigval(2)<eigval(3)) then
456  temps=eigval(2)
457  eigval(2)=eigval(3)
458  eigval(3)=temps
459  tempv(:)=princnormal(:,2)
460  princnormal(:,2)=princnormal(:,3)
461  princnormal(:,3)=tempv(:)
462  end if
463 
464  do j=1,3
465  do i=1,3
466  princmatrix(i,j) = princnormal(i,j) * eigval(j)
467  end do
468  end do
469 
470  end subroutine get_principal
471 
472  subroutine eigen3d (tensor, eigval, princ)
473  implicit none
474 
475  real(kind=kreal) :: tensor(6)
476  real(kind=kreal) :: eigval(3)
477  real(kind=kreal) :: princ(3,3)
478 
479  real(kind=kreal) :: s11, s22, s33, s12, s23, s13, j1, j2, j3
480  real(kind=kreal) :: ml,nl
481  complex(kind=kreal):: x1,x2,x3
482  real(kind=kreal):: rtemp
483  integer :: i
484  s11 = tensor(1)
485  s22 = tensor(2)
486  s33 = tensor(3)
487  s12 = tensor(4)
488  s23 = tensor(5)
489  s13 = tensor(6)
490 
491  ! invariants of stress tensor
492  j1 = s11 + s22 + s33
493  j2 = -s11*s22 - s22*s33 - s33*s11 + s12**2 + s23**2 + s13**2
494  j3 = s11*s22*s33 + 2*s12*s23*s13 - s11*s23**2 - s22*s13**2 - s33*s12**2
495  ! Cardano's method
496  ! x^3+ ax^2 + bx +c =0
497  ! s^3 - J1*s^2 -J2s -J3 =0
498  call cardano(-j1, -j2, -j3, x1, x2, x3)
499  eigval(1)= real(x1)
500  eigval(2)= real(x2)
501  eigval(3)= real(x3)
502  if (eigval(1)<eigval(2)) then
503  rtemp=eigval(1)
504  eigval(1)=eigval(2)
505  eigval(2)=rtemp
506  end if
507  if (eigval(1)<eigval(3)) then
508  rtemp=eigval(1)
509  eigval(1)=eigval(3)
510  eigval(3)=rtemp
511  end if
512  if (eigval(2)<eigval(3)) then
513  rtemp=eigval(2)
514  eigval(2)=eigval(3)
515  eigval(3)=rtemp
516  end if
517 
518  do i=1,3
519  if (eigval(i)/(eigval(1)+eigval(2)+eigval(3)) < 1.0d-10 )then
520  eigval(i) = 0.0d0
521  princ(i,:) = 0.0d0
522  exit
523  end if
524  ml = ( s23*s13 - s12*(s33-eigval(i)) ) / ( -s23**2 + (s22-eigval(i))*(s33-eigval(i)) )
525  nl = ( s12**2 - (s22-eigval(i))*(s11-eigval(i)) ) / ( s12*s23 - s13*(s22-eigval(i)) )
526  if (abs(ml) >= huge(ml)) then
527  ml=0.0d0
528  end if
529  if (abs(nl) >= huge(nl)) then
530  nl=0.0d0
531  end if
532  princ(i,1) = eigval(i)/sqrt( 1 + ml**2 + nl**2)
533  princ(i,2) = ml * princ(i,1)
534  princ(i,3) = nl * princ(i,1)
535  end do
536 
537  write(*,*)
538  end subroutine eigen3d
539 
540  subroutine cardano(a,b,c,x1,x2,x3)
541  real(kind=kreal):: a,b,c
542  real(kind=kreal):: p,q,d
543  complex(kind=kreal):: w
544  complex(kind=kreal):: u,v,y
545  complex(kind=kreal):: x1,x2,x3
546  w = (-1.0d0 + sqrt(dcmplx(-3.0d0)))/2.0d0
547  p = -a**2/9.0d0 + b/3.0d0
548  q = 2.0d0/2.7d1*a**3 - a*b/3.0d0 + c
549  d = q**2 + 4.0d0*p**3
550 
551  u = ((-dcmplx(q) + sqrt(dcmplx(d)))/2.0d0)**(1.0d0/3.0d0)
552 
553  if(u.ne.0.0d0) then
554  v = -dcmplx(p)/u
555  x1 = u + v -dcmplx(a)/3.0d0
556  x2 = u*w + v*w**2 -dcmplx(a)/3.0d0
557  x3 = u*w**2 + v*w -dcmplx(a)/3.0d0
558  else
559  y = (-dcmplx(q))**(1.0d0/3.0d0)
560  x1 = y -dcmplx(a)/3.0d0
561  x2 = y*w -dcmplx(a)/3.0d0
562  x3 = y*w**2 -dcmplx(a)/3.0d0
563  end if
564 
565  end subroutine cardano
566 
568  real(kind=kreal),intent(in) :: r(3)
569  real(kind=kreal),intent(inout) :: v(3)
570 
571  real(kind=kreal) :: rotv(3), rv
572  real(kind=kreal) :: cosx, sinc(2)
573  real(kind=kreal) :: x, x2, x4, x6
574  real(kind=kreal), parameter :: c0 = 0.5d0
575  real(kind=kreal), parameter :: c2 = -4.166666666666666d-002
576  real(kind=kreal), parameter :: c4 = 1.388888888888889d-003
577  real(kind=kreal), parameter :: c6 = -2.480158730158730d-005
578 
579  x2 = dot_product(r,r)
580  x = dsqrt(x2)
581  cosx = dcos(x)
582  if( x < 1.d-4 ) then
583  x4 = x2*x2
584  x6 = x4*x2
585  sinc(1) = 1.d0-x2/6.d0+x4/120.d0
586  sinc(2) = c0+c2*x2+c4*x4+c6*x6
587  else
588  sinc(1) = dsin(x)/x
589  sinc(2) = (1.d0-cosx)/x2
590  endif
591 
592  ! calc Rot*v
593  rv = dot_product(r,v)
594  rotv(1:3) = cosx*v(1:3)
595  rotv(1:3) = rotv(1:3)+rv*sinc(2)*r(1:3)
596  rotv(1) = rotv(1) + (-v(2)*r(3)+v(3)*r(2))*sinc(1)
597  rotv(2) = rotv(2) + (-v(3)*r(1)+v(1)*r(3))*sinc(1)
598  rotv(3) = rotv(3) + (-v(1)*r(2)+v(2)*r(1))*sinc(1)
599  v = rotv
600 
601  end subroutine
602 
604  subroutine deriv_general_iso_tensor_func_3d(dpydpx, dydx, eigv, px, py)
605  real(kind=kreal), intent(in) :: dpydpx(3,3)
606  real(kind=kreal), intent(out) :: dydx(6,6)
607  real(kind=kreal), intent(in) :: eigv(3,3)
608  real(kind=kreal), intent(in) :: px(3), py(3)
609 
610  real(kind=kreal) :: x(6)
611  real(kind=kreal) :: ep(6,3), dx2dx(6,6)
612  integer(kind=kint) :: i, j, m1, m2, m3, ia, ib, ic, ip, jp, k
613  real(kind=kreal) :: xmax, dif12, dif23, c1, c2, c3, c4, d1, d2, d3
614  real(kind=kreal) :: xa, xc, ya, yc, daa, dac, dca, dcb, dcc
615  real(kind=kreal) :: xa_xc, xa_xc2, xa_xc3, ya_yc, xc2
616  real(kind=kreal) :: s1, s2, s3, s4, s5, s6
617  real(kind=kreal), parameter :: i2(6) = [1.d0, 1.d0, 1.d0, 0.d0, 0.d0, 0.d0]
618  real(kind=kreal), parameter :: is(6,6) = reshape([&
619  1.d0, 0.d0, 0.d0, 0.d0, 0.d0, 0.d0,&
620  0.d0, 1.d0, 0.d0, 0.d0, 0.d0, 0.d0,&
621  0.d0, 0.d0, 1.d0, 0.d0, 0.d0, 0.d0,&
622  0.d0, 0.d0, 0.d0, 0.5d0, 0.d0, 0.d0,&
623  0.d0, 0.d0, 0.d0, 0.d0, 0.5d0, 0.d0,&
624  0.d0, 0.d0, 0.d0, 0.d0, 0.d0, 0.5d0],&
625  [6, 6])
626  real(kind=kreal), parameter :: eps=1.d-6
627 
628  do i=1,3
629  ep(1,i) = eigv(1,i)*eigv(1,i)
630  ep(2,i) = eigv(2,i)*eigv(2,i)
631  ep(3,i) = eigv(3,i)*eigv(3,i)
632  ep(4,i) = eigv(1,i)*eigv(2,i)
633  ep(5,i) = eigv(2,i)*eigv(3,i)
634  ep(6,i) = eigv(3,i)*eigv(1,i)
635  enddo
636  x(:) = 0.d0
637  do i=1,3
638  do j=1,6
639  x(j) = x(j)+px(i)*ep(j,i)
640  enddo
641  enddo
642  dx2dx = reshape([2.d0*x(1), 0.d0, 0.d0, x(4), 0.d0, x(6),&
643  & 0.d0, 2.d0*x(2), 0.d0, x(4), x(5), 0.d0,&
644  & 0.d0, 0.d0, 2.d0*x(3), 0.d0, x(5), x(6),&
645  & x(4), x(4), 0.d0, (x(1)+x(2))/2.d0, x(6)/2.d0, x(5)/2.d0,&
646  & 0.d0, x(5), x(6), x(6)/2.d0, (x(2)+x(3))/2.d0, x(4)/2.d0,&
647  & x(6), 0.d0, x(6), x(5)/2.d0, x(4)/2.d0, (x(1)+x(3))/2.d0],&
648  [6, 6])
649  m1 = maxloc(px, 1)
650  m3 = minloc(px, 1)
651  if( m1 == m3 ) then
652  m1 = 1; m2 = 2; m3 = 3
653  else
654  m2 = 6 - (m1 + m3)
655  endif
656  xmax = maxval(abs(px), 1)
657  if( xmax < eps ) xmax = 1.d0
658  dif12 = abs(px(m1) - px(m2)) / xmax
659  dif23 = abs(px(m2) - px(m3)) / xmax
660  if( dif12 < eps .and. dif23 < eps ) then
661  c1 = dpydpx(1,1)-dpydpx(1,2)
662  c2 = dpydpx(1,2)
663  do j=1,6
664  do i=1,6
665  dydx(i,j) = c1*is(i,j)+c2*i2(i)*i2(j)
666  enddo
667  enddo
668  else if( dif12 < eps .or. dif23 < eps ) then
669  if( dif12 < eps ) then
670  ia = m3; ib = m1; ic = m2
671  else
672  ia = m1; ib = m2; ic = m3
673  endif
674  ya = py(ia); yc = py(ic)
675  xa = px(ia); xc = px(ic)
676  daa = dpydpx(ia,ia)
677  dac = dpydpx(ia,ic)
678  dca = dpydpx(ic,ia)
679  dcb = dpydpx(ic,ib)
680  dcc = dpydpx(ic,ic)
681  xa_xc = xa-xc
682  xa_xc2 = xa_xc*xa_xc
683  xa_xc3 = xa_xc2*xa_xc
684  ya_yc = ya-yc
685  xc2 = xc*xc
686  c1 = ya_yc/xa_xc2
687  c2 = ya_yc/xa_xc3
688  c3 = xc/xa_xc2
689  c4 = (xa+xc)/xa_xc
690  d1 = dac+dca
691  d2 = daa+dcc
692  d3 = d1-d2
693  s1 = c1+(dcb-dcc)/xa_xc
694  s2 = 2.d0*xc*c1+(dcb-dcc)*c4
695  s3 = 2.d0*c2+d3/xa_xc2
696  s4 = 2.d0*xc*c2+(dac-dcb)/xa_xc+d3*c3
697  s5 = 2.d0*xc*c2+(dca-dcb)/xa_xc+d3*c3
698  s6 = 2.d0*xc2*c2+(d1*xa-d2*xc)*c3-dcb*c4
699  do j=1,6
700  do i=1,6
701  dydx(i,j) = s1*dx2dx(i,j)-s2*is(i,j)-s3*x(i)*x(j)+s4*x(i)*i2(j)+s5*i2(i)*x(j)-s6*i2(i)*i2(j)
702  enddo
703  enddo
704  else
705  dydx(:,:) = 0.d0
706  do k=1,3
707  select case(k)
708  case(1)
709  ia = 1; ib = 2; ic = 3
710  case(2)
711  ia = 2; ib = 3; ic = 1
712  case(3)
713  ia = 3; ib = 1; ic = 2
714  end select
715  c1 = py(ia)/((px(ia)-px(ib))*(px(ia)-px(ic)))
716  c2 = px(ib)+px(ic)
717  c3 = (px(ia)-px(ib))+(px(ia)-px(ic))
718  c4 = px(ib)-px(ic)
719  do j=1,6
720  do i=1,6
721  dydx(i,j) = dydx(i,j)+c1*(dx2dx(i,j)-c2*is(i,j)-c3*ep(i,ia)*ep(j,ia)-c4*(ep(i,ib)*ep(j,ib)-ep(i,ic)*ep(j,ic)))
722  enddo
723  enddo
724  enddo
725  do jp=1,3
726  do ip=1,3
727  c1 = dpydpx(ip,jp)
728  do j=1,6
729  do i=1,6
730  dydx(i,j) = dydx(i,j)+c1*ep(i,ip)*ep(j,jp)
731  enddo
732  enddo
733  enddo
734  enddo
735  endif
736  end subroutine deriv_general_iso_tensor_func_3d
737 
738 end module
Definition: hecmw.f90:6
This module provides aux functions.
Definition: utilities.f90:6
subroutine eigen3(tensor, eigval, princ)
Compute eigenvalue and eigenvetor for symmetric 3*3 tensor using Jacobi iteration adapted from numeri...
Definition: utilities.f90:118
subroutine cross_product(v1, v2, vn)
Definition: utilities.f90:383
subroutine eigen3d(tensor, eigval, princ)
Definition: utilities.f90:473
real(kind=kreal) function determinant33(XJ)
Compute determinant for 3*3 matrix.
Definition: utilities.f90:245
subroutine insert_int2array(iin, carray)
Insert an integer into a integer array.
Definition: utilities.f90:24
real(kind=kreal) function determinant(mat)
Compute determinant for symmetric 3*3 matrix.
Definition: utilities.f90:227
subroutine calsolve(NN, A, b)
Solve A x = b for dense NN x NN system (Gaussian elimination with partial pivoting)
Definition: utilities.f90:345
subroutine tensor_eigen3(tensor, eigval)
Given symmetric 3x3 matrix M, compute the eigenvalues.
Definition: utilities.f90:50
subroutine get_principal(tensor, eigval, princmatrix)
Definition: utilities.f90:427
subroutine transformation(jacob, tm)
Definition: utilities.f90:392
subroutine fstr_chk_alloc(imsg, sub_name, ierr)
Definition: utilities.f90:256
subroutine deriv_general_iso_tensor_func_3d(dpydpx, dydx, eigv, px, py)
Compute derivative of a general isotropic tensor function of one tensor.
Definition: utilities.f90:605
subroutine cardano(a, b, c, x1, x2, x3)
Definition: utilities.f90:541
subroutine memget(var, dimn, syze)
Record used memory.
Definition: utilities.f90:16
subroutine rotate_3dvector_by_rodrigues_formula(r, v)
Definition: utilities.f90:568
subroutine calinverse(NN, A)
calculate inverse of matrix a
Definition: utilities.f90:270