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