DAMASK with grid solvers  Revision: v2.0.3-2204-gdb1f2151
The Düsseldorf Advanced Material Simulation Kit with Grid Solvers
Lambert.f90
Go to the documentation of this file.
1 # 1 "/home/damask_user/GitLabCI_Pipeline_4301/DAMASK/src/Lambert.f90"
2 # 1 "<built-in>"
3 # 1 "<command-line>"
4 # 1 "/home/damask_user/GitLabCI_Pipeline_4301/DAMASK/src/Lambert.f90"
5 ! ###################################################################
6 ! Copyright (c) 2013-2015, Marc De Graef/Carnegie Mellon University
7 ! Modified 2017-2019, Martin Diehl/Max-Planck-Institut für Eisenforschung GmbH
8 ! All rights reserved.
9 !
10 ! Redistribution and use in source and binary forms, with or without modification, are
11 ! permitted provided that the following conditions are met:
12 !
13 ! - Redistributions of source code must retain the above copyright notice, this list
14 ! of conditions and the following disclaimer.
15 ! - Redistributions in binary form must reproduce the above copyright notice, this
16 ! list of conditions and the following disclaimer in the documentation and/or
17 ! other materials provided with the distribution.
18 ! - Neither the names of Marc De Graef, Carnegie Mellon University nor the names
19 ! of its contributors may be used to endorse or promote products derived from
20 ! this software without specific prior written permission.
21 !
22 ! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23 ! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 ! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 ! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
26 ! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 ! DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
28 ! SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29 ! CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30 ! OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
31 ! USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 ! ###################################################################
33 
34 !--------------------------------------------------------------------------
38 !
43 !--------------------------------------------------------------------------
44 module lambert
45  use prec
46  use math
47 
48  implicit none
49  private
50 
51  real(preal), parameter :: &
52  spi = sqrt(pi), &
53  pref = sqrt(6.0_preal/pi), &
54  a = pi**(5.0_preal/6.0_preal)/6.0_preal**(1.0_preal/6.0_preal), &
55  ap = pi**(2.0_preal/3.0_preal), &
56  sc = a/ap, &
57  beta = a/2.0_preal, &
58  r1 = (3.0_preal*pi/4.0_preal)**(1.0_preal/3.0_preal), &
59  r2 = sqrt(2.0_preal), &
60  pi12 = pi/12.0_preal, &
61  prek = r1 * 2.0_preal**(1.0_preal/4.0_preal)/beta
62 
63  public :: &
66 
67 contains
68 
69 
70 !--------------------------------------------------------------------------
74 !--------------------------------------------------------------------------
75 pure function lambert_cubetoball(cube) result(ball)
76 
77  real(preal), intent(in), dimension(3) :: cube
78  real(preal), dimension(3) :: ball, lamxyz, xyz
79  real(preal), dimension(2) :: t
80  real(preal) :: c, s, q
81  real(preal), parameter :: eps = 1.0e-8_preal
82  integer, dimension(3) :: p
83  integer, dimension(2) :: order
84 
85  if (maxval(abs(cube)) > ap/2.0+eps) then
86  ball = ieee_value(cube,ieee_positive_inf)
87  return
88  end if
89 
90  ! transform to the sphere grid via the curved square, and intercept the zero point
91  center: if (all(deq0(cube))) then
92  ball = 0.0_preal
93  else center
94  ! get pyramide and scale by grid parameter ratio
95  p = getpyramidorder(cube)
96  xyz = cube(p) * sc
97 
98  ! intercept all the points along the z-axis
99  special: if (all(deq0(xyz(1:2)))) then
100  lamxyz = [ 0.0_preal, 0.0_preal, pref * xyz(3) ]
101  else special
102  order = merge( [2,1], [1,2], abs(xyz(2)) <= abs(xyz(1))) ! order of absolute values of XYZ
103  q = pi12 * xyz(order(1))/xyz(order(2)) ! smaller by larger
104  c = cos(q)
105  s = sin(q)
106  q = prek * xyz(order(2))/ sqrt(r2-c)
107  t = [ (r2*c - 1.0), r2 * s] * q
108 
109  ! transform to sphere grid (inverse Lambert)
110  ! [note that there is no need to worry about dividing by zero, since XYZ(3) can not become zero]
111  c = sum(t**2)
112  s = pi * c/(24.0*xyz(3)**2)
113  c = spi * c / sqrt(24.0_preal) / xyz(3)
114  q = sqrt( 1.0 - s )
115  lamxyz = [ t(order(2)) * q, t(order(1)) * q, pref * xyz(3) - c ]
116  endif special
117 
118  ! reverse the coordinates back to order according to the original pyramid number
119  ball = lamxyz(p)
120 
121  endif center
122 
123 end function lambert_cubetoball
124 
125 
126 !--------------------------------------------------------------------------
130 !--------------------------------------------------------------------------
131 pure function lambert_balltocube(xyz) result(cube)
132 
133  real(preal), intent(in), dimension(3) :: xyz
134  real(preal), dimension(3) :: cube, xyz1, xyz3
135  real(preal), dimension(2) :: tinv, xyz2
136  real(preal) :: rs, qxy, q2, sq2, q, tt
137  integer, dimension(3) :: p
138 
139  rs = norm2(xyz)
140  if (rs > r1) then
141  cube = ieee_value(cube,ieee_positive_inf)
142  return
143  endif
144 
145  center: if (all(deq0(xyz))) then
146  cube = 0.0_preal
147  else center
148  p = getpyramidorder(xyz)
149  xyz3 = xyz(p)
150 
151  ! inverse M_3
152  xyz2 = xyz3(1:2) * sqrt( 2.0*rs/(rs+abs(xyz3(3))) )
153 
154  ! inverse M_2
155  qxy = sum(xyz2**2)
156 
157  special: if (deq0(qxy)) then
158  tinv = 0.0_preal
159  else special
160  q2 = qxy + maxval(abs(xyz2))**2
161  sq2 = sqrt(q2)
162  q = (beta/r2/r1) * sqrt(q2*qxy/(q2-maxval(abs(xyz2))*sq2))
163  tt = (minval(abs(xyz2))**2+maxval(abs(xyz2))*sq2)/r2/qxy
164  tinv = q * sign(1.0_preal,xyz2) * merge([ 1.0_preal, acos(math_clip(tt,-1.0_preal,1.0_preal))/pi12], &
165  [ acos(math_clip(tt,-1.0_preal,1.0_preal))/pi12, 1.0_preal], &
166  abs(xyz2(2)) <= abs(xyz2(1)))
167  endif special
168 
169  ! inverse M_1
170  xyz1 = [ tinv(1), tinv(2), sign(1.0_preal,xyz3(3)) * rs / pref ] /sc
171 
172  ! reverse the coordinates back to order according to the original pyramid number
173  cube = xyz1(p)
174 
175  endif center
176 
177 end function lambert_balltocube
178 
179 
180 !--------------------------------------------------------------------------
184 !--------------------------------------------------------------------------
185 pure function getpyramidorder(xyz)
186 
187  real(preal),intent(in),dimension(3) :: xyz
188  integer, dimension(3) :: getpyramidorder
189 
190  if (((abs(xyz(1)) <= xyz(3)).and.(abs(xyz(2)) <= xyz(3))) .or. &
191  ((abs(xyz(1)) <= -xyz(3)).and.(abs(xyz(2)) <= -xyz(3)))) then
192  getpyramidorder = [1,2,3]
193  else if (((abs(xyz(3)) <= xyz(1)).and.(abs(xyz(2)) <= xyz(1))) .or. &
194  ((abs(xyz(3)) <= -xyz(1)).and.(abs(xyz(2)) <= -xyz(1)))) then
195  getpyramidorder = [2,3,1]
196  else if (((abs(xyz(1)) <= xyz(2)).and.(abs(xyz(3)) <= xyz(2))) .or. &
197  ((abs(xyz(1)) <= -xyz(2)).and.(abs(xyz(3)) <= -xyz(2)))) then
198  getpyramidorder = [3,1,2]
199  else
200  getpyramidorder = -1 ! should be impossible, but might simplify debugging
201  end if
202 
203 end function getpyramidorder
204 
205 end module lambert
lambert::lambert_balltocube
pure real(preal) function, dimension(3), public lambert_balltocube(xyz)
map from 3D ball to 3D cubic grid
Definition: Lambert.f90:132
lambert
Mapping homochoric <-> cubochoric.
Definition: Lambert.f90:44
lambert::a
real(preal), parameter a
Definition: Lambert.f90:51
lambert::sc
real(preal), parameter sc
Definition: Lambert.f90:51
lambert::ap
real(preal), parameter ap
Definition: Lambert.f90:51
lambert::pref
real(preal), parameter pref
Definition: Lambert.f90:51
prec
setting precision for real and int type
Definition: prec.f90:13
lambert::getpyramidorder
pure integer function, dimension(3) getpyramidorder(xyz)
determine to which pyramid a point in a cubic grid belongs
Definition: Lambert.f90:186
lambert::beta
real(preal), parameter beta
Definition: Lambert.f90:51
prec::preal
integer, parameter preal
number with 15 significant digits, up to 1e+-307 (typically 64 bit)
Definition: prec.f90:20
lambert::prek
real(preal), parameter prek
Definition: Lambert.f90:51
math::math_clip
real(preal) pure elemental function math_clip(a, left, right)
limits a scalar value to a certain range (either one or two sided)
Definition: math.f90:1197
lambert::r1
real(preal), parameter r1
Definition: Lambert.f90:51
lambert::pi12
real(preal), parameter pi12
Definition: Lambert.f90:51
math
Mathematical library, including random number generation and tensor representations.
Definition: math.f90:12
lambert::lambert_cubetoball
pure real(preal) function, dimension(3), public lambert_cubetoball(cube)
map from 3D cubic grid to 3D ball
Definition: Lambert.f90:76
math::pi
real(preal), parameter pi
ratio of a circle's circumference to its diameter
Definition: math.f90:27
lambert::spi
real(preal), parameter spi
Definition: Lambert.f90:51
lambert::r2
real(preal), parameter r2
Definition: Lambert.f90:51
prec::deq0
logical elemental pure function deq0(a, tol)
equality to 0 comparison for float with double precision
Definition: prec.f90:166