Merge branch 'development' into 22-NewStyle_disloUCLA-2

This commit is contained in:
Martin Diehl 2018-12-21 06:46:35 +01:00
commit d4c7e8f33b
41 changed files with 605 additions and 956 deletions

View File

@ -158,12 +158,12 @@ Post_AverageDown:
- master - master
- release - release
Post_General: #Post_General:
stage: postprocessing # stage: postprocessing
script: PostProcessing/test.py # script: PostProcessing/test.py
except: # except:
- master # - master
- release # - release
Post_GeometryReconstruction: Post_GeometryReconstruction:
stage: postprocessing stage: postprocessing
@ -364,12 +364,12 @@ Phenopowerlaw_singleSlip:
- master - master
- release - release
TextureComponents: #TextureComponents:
stage: spectral # stage: spectral
script: TextureComponents/test.py # script: TextureComponents/test.py
except: # except:
- master # - master
- release # - release
################################################################################################### ###################################################################################################

View File

@ -79,7 +79,7 @@ ls $PETSC_DIR/lib
firstLevel "Python" firstLevel "Python"
DEFAULT_PYTHON=python3 DEFAULT_PYTHON=python3
for executable in python python2 python3 python2.7; do for executable in python python3; do
getDetails $executable '--version' getDetails $executable '--version'
done done
secondLevel "Details on $DEFAULT_PYTHON:" secondLevel "Details on $DEFAULT_PYTHON:"
@ -119,6 +119,9 @@ for executable in mpirun mpiexec; do
getDetails $executable '--version' getDetails $executable '--version'
done done
firstLevel "CMake"
getDetails cmake --version
firstLevel "Abaqus" firstLevel "Abaqus"
cd installation/mods_Abaqus # to have the right environment file cd installation/mods_Abaqus # to have the right environment file
for executable in abaqus abq2017 abq2018; do for executable in abaqus abq2017 abq2018; do

@ -1 +1 @@
Subproject commit e9f93abaecafbfbf11072ae70bca213a7201ed38 Subproject commit b9a52a85cd65cc27a8e863302bd984abdcad1455

View File

@ -1 +1 @@
v2.0.2-1100-g65ff2157 v2.0.2-1187-gcd8ee450

7
env/DAMASK.csh vendored
View File

@ -7,6 +7,11 @@ set DAMASK_ROOT=`python -c "import os,sys; print(os.path.realpath(os.path.expand
source $DAMASK_ROOT/CONFIG source $DAMASK_ROOT/CONFIG
# add BRANCH if DAMASK_ROOT is a git repository
cd $DAMASK_ROOT >/dev/null
set BRANCH = `git branch 2>/dev/null| grep -E '^\* ')`
cd - >/dev/null
# if DAMASK_BIN is present # if DAMASK_BIN is present
if ( $?DAMASK_BIN) then if ( $?DAMASK_BIN) then
set path = ($DAMASK_BIN $path) set path = ($DAMASK_BIN $path)
@ -41,7 +46,7 @@ if ( $?prompt ) then
echo https://damask.mpie.de echo https://damask.mpie.de
echo echo
echo Using environment with ... echo Using environment with ...
echo "DAMASK $DAMASK_ROOT" echo "DAMASK $DAMASK_ROOT $BRANCH"
echo "Spectral Solver $SOLVER" echo "Spectral Solver $SOLVER"
echo "Post Processing $PROCESSING" echo "Post Processing $PROCESSING"
if ( $?PETSC_DIR) then if ( $?PETSC_DIR) then

7
env/DAMASK.sh vendored
View File

@ -30,6 +30,9 @@ set() {
source $DAMASK_ROOT/CONFIG source $DAMASK_ROOT/CONFIG
unset -f set unset -f set
# add BRANCH if DAMASK_ROOT is a git repository
cd $DAMASK_ROOT >/dev/null; BRANCH=$(git branch 2>/dev/null| grep -E '^\* '); cd - >/dev/null
# add DAMASK_BIN if present # add DAMASK_BIN if present
[ "x$DAMASK_BIN" != "x" ] && PATH=$DAMASK_BIN:$PATH [ "x$DAMASK_BIN" != "x" ] && PATH=$DAMASK_BIN:$PATH
@ -59,7 +62,7 @@ if [ ! -z "$PS1" ]; then
echo https://damask.mpie.de echo https://damask.mpie.de
echo echo
echo Using environment with ... echo Using environment with ...
echo "DAMASK $DAMASK_ROOT" echo "DAMASK $DAMASK_ROOT $BRANCH"
echo "Spectral Solver $SOLVER" echo "Spectral Solver $SOLVER"
echo "Post Processing $PROCESSING" echo "Post Processing $PROCESSING"
if [ "x$PETSC_DIR" != "x" ]; then if [ "x$PETSC_DIR" != "x" ]; then
@ -94,7 +97,7 @@ fi
export DAMASK_NUM_THREADS export DAMASK_NUM_THREADS
export PYTHONPATH=$DAMASK_ROOT/lib:$PYTHONPATH export PYTHONPATH=$DAMASK_ROOT/lib:$PYTHONPATH
for var in BASE STAT SOLVER PROCESSING FREE DAMASK_BIN; do for var in BASE STAT SOLVER PROCESSING FREE DAMASK_BIN BRANCH; do
unset "${var}" unset "${var}"
done done
for var in DAMASK MSC; do for var in DAMASK MSC; do

19
env/DAMASK.zsh vendored
View File

@ -21,16 +21,19 @@ set() {
source $DAMASK_ROOT/CONFIG source $DAMASK_ROOT/CONFIG
unset -f set unset -f set
# add BRANCH if DAMASK_ROOT is a git repository
cd $DAMASK_ROOT >/dev/null; BRANCH=$(git branch 2>/dev/null| grep -E '^\* '); cd - >/dev/null
# add DAMASK_BIN if present # add DAMASK_BIN if present
[ "x$DAMASK_BIN != x" ] && PATH=$DAMASK_BIN:$PATH [[ "x$DAMASK_BIN" != "x" ]] && PATH=$DAMASK_BIN:$PATH
SOLVER=$(which DAMASK_spectral || true 2>/dev/null) SOLVER=$(which DAMASK_spectral || true 2>/dev/null)
[ "x$SOLVER" = "x" ] && SOLVER=$(blink 'Not found!') [[ "x$SOLVER" == "x" ]] && SOLVER=$(blink 'Not found!')
PROCESSING=$(which postResults || true 2>/dev/null) PROCESSING=$(which postResults || true 2>/dev/null)
[ "x$PROCESSING" = "x" ] && PROCESSING=$(blink 'Not found!') [[ "x$PROCESSING" == "x" ]] && PROCESSING=$(blink 'Not found!')
[ "x$DAMASK_NUM_THREADS" = "x" ] && DAMASK_NUM_THREADS=1 [[ "x$DAMASK_NUM_THREADS" == "x" ]] && DAMASK_NUM_THREADS=1
# currently, there is no information that unlimited causes problems # currently, there is no information that unlimited causes problems
# still, http://software.intel.com/en-us/forums/topic/501500 suggest to fix it # still, http://software.intel.com/en-us/forums/topic/501500 suggest to fix it
@ -50,16 +53,16 @@ if [ ! -z "$PS1" ]; then
echo https://damask.mpie.de echo https://damask.mpie.de
echo echo
echo "Using environment with ..." echo "Using environment with ..."
echo "DAMASK $DAMASK_ROOT" echo "DAMASK $DAMASK_ROOT $BRANCH"
echo "Spectral Solver $SOLVER" echo "Spectral Solver $SOLVER"
echo "Post Processing $PROCESSING" echo "Post Processing $PROCESSING"
if [ "x$PETSC_DIR" != "x" ]; then if [ "x$PETSC_DIR" != "x" ]; then
echo -n "PETSc location " echo -n "PETSc location "
[ -d $PETSC_DIR ] && echo $PETSC_DIR || blink $PETSC_DIR [ -d $PETSC_DIR ] && echo $PETSC_DIR || blink $PETSC_DIR
[[ $(canonicalPath "$PETSC_DIR") == $PETSC_DIR ]] \ [[ $(canonicalPath "$PETSC_DIR") == $PETSC_DIR ]] \
|| echo " ~~> "$(canonicalPath "$PETSC_DIR") || echo " ~~> "$(canonicalPath "$PETSC_DIR")
fi fi
[[ "x$PETSC_ARCH" == "x" ]] \ [[ "x$PETSC_ARCH" == "x" ]] \
|| echo "PETSc architecture $PETSC_ARCH" || echo "PETSc architecture $PETSC_ARCH"
echo -n "MSC.Marc/Mentat " echo -n "MSC.Marc/Mentat "
[ -d $MSC_ROOT ] && echo $MSC_ROOT || blink $MSC_ROOT [ -d $MSC_ROOT ] && echo $MSC_ROOT || blink $MSC_ROOT
@ -87,7 +90,7 @@ fi
export DAMASK_NUM_THREADS export DAMASK_NUM_THREADS
export PYTHONPATH=$DAMASK_ROOT/lib:$PYTHONPATH export PYTHONPATH=$DAMASK_ROOT/lib:$PYTHONPATH
for var in BASE STAT SOLVER PROCESSING FREE DAMASK_BIN; do for var in BASE STAT SOLVER PROCESSING FREE DAMASK_BIN BRANCH; do
unset "${var}" unset "${var}"
done done
for var in DAMASK MSC; do for var in DAMASK MSC; do

View File

@ -6,7 +6,6 @@ plasticity phenopowerlaw
(output) shearrate_slip (output) shearrate_slip
(output) resolvedstress_slip (output) resolvedstress_slip
(output) accumulated_shear_slip (output) accumulated_shear_slip
(output) totalshear
lattice_structure fcc lattice_structure fcc
Nslip 12 # per family Nslip 12 # per family

View File

@ -19,4 +19,3 @@ tausat_slip 222.e6 412.7e6 # per family, optimization long
h0_slipslip 1000.0e6 h0_slipslip 1000.0e6
interaction_slipslip 1 1 1.4 1.4 1.4 1.4 interaction_slipslip 1 1 1.4 1.4 1.4 1.4
w0_slip 2.0 w0_slip 2.0
(output) totalshear

View File

@ -19,4 +19,3 @@ tausat_slip 872.9e6 971.2e6 # per family
h0_slipslip 563.0e9 h0_slipslip 563.0e9
interaction_slipslip 1 1 1.4 1.4 1.4 1.4 interaction_slipslip 1 1 1.4 1.4 1.4 1.4
a_slip 2.0 a_slip 2.0
(output) totalshear

View File

@ -14,11 +14,9 @@ plasticity phenopowerlaw
(output) resistance_slip (output) resistance_slip
(output) shearrate_slip (output) shearrate_slip
(output) resolvedstress_slip (output) resolvedstress_slip
(output) totalshear
(output) resistance_twin (output) resistance_twin
(output) shearrate_twin (output) shearrate_twin
(output) resolvedstress_twin (output) resolvedstress_twin
(output) totalvolfrac_twin
lattice_structure fcc lattice_structure fcc
Nslip 12 # per family Nslip 12 # per family

View File

@ -9,11 +9,9 @@ elasticity hooke
(output) resistance_slip (output) resistance_slip
(output) shearrate_slip (output) shearrate_slip
(output) resolvedstress_slip (output) resolvedstress_slip
(output) totalshear
(output) resistance_twin (output) resistance_twin
(output) shearrate_twin (output) shearrate_twin
(output) resolvedstress_twin (output) resolvedstress_twin
(output) totalvolfrac_twin
lattice_structure hex lattice_structure hex
covera_ratio 1.62350 # from Tromans 2011, Elastic Anisotropy of HCP Metal Crystals and Polycrystals covera_ratio 1.62350 # from Tromans 2011, Elastic Anisotropy of HCP Metal Crystals and Polycrystals

View File

@ -5,11 +5,9 @@ elasticity hooke
# (output) resistance_slip # (output) resistance_slip
# (output) shearrate_slip # (output) shearrate_slip
# (output) resolvedstress_slip # (output) resolvedstress_slip
# (output) totalshear
# (output) resistance_twin # (output) resistance_twin
# (output) shearrate_twin # (output) shearrate_twin
# (output) resolvedstress_twin # (output) resolvedstress_twin
# (output) totalvolfrac_twin
lattice_structure hex lattice_structure hex
covera_ratio 1.587 covera_ratio 1.587

View File

@ -6,12 +6,10 @@ plasticity phenopowerlaw
(output) shearrate_slip (output) shearrate_slip
(output) resolvedstress_slip (output) resolvedstress_slip
(output) accumulated_shear_slip (output) accumulated_shear_slip
(output) totalshear
(output) resistance_twin (output) resistance_twin
(output) shearrate_twin (output) shearrate_twin
(output) resolvedstress_twin (output) resolvedstress_twin
(output) accumulated_shear_twin (output) accumulated_shear_twin
(output) totalvolfrac_twin
lattice_structure fcc lattice_structure fcc
Nslip 12 # per family Nslip 12 # per family

View File

@ -13,7 +13,7 @@ from .asciitable import ASCIItable # noqa
from .config import Material # noqa from .config import Material # noqa
from .colormaps import Colormap, Color # noqa from .colormaps import Colormap, Color # noqa
from .orientation import Quaternion, Rodrigues, Symmetry, Orientation # noqa from .orientation import Quaternion, Symmetry, Orientation # noqa
#from .block import Block # only one class #from .block import Block # only one class
from .result import Result # noqa from .result import Result # noqa

View File

@ -493,8 +493,8 @@ class ASCIItable():
(d if str(c) != str(labels[present[i]]) else (d if str(c) != str(labels[present[i]]) else
1))) 1)))
use = np.array(columns) if len(columns) > 0 else None use = np.array(columns) if len(columns) > 0 else None
self.tags = list(np.array(self.tags)[use]) # update labels with valid subset self.tags = list(np.array(self.__IO__['tags'])[use]) # update labels with valid subset
self.data = np.loadtxt(self.__IO__['in'],usecols=use,ndmin=2) self.data = np.loadtxt(self.__IO__['in'],usecols=use,ndmin=2)
# self.data = np.genfromtxt(self.__IO__['in'],dtype=None,names=self.tags,usecols=use) # self.data = np.genfromtxt(self.__IO__['in'],dtype=None,names=self.tags,usecols=use)

View File

@ -7,24 +7,6 @@
import math,os import math,os
import numpy as np import numpy as np
# ******************************************************************************************
class Rodrigues:
def __init__(self, vector = np.zeros(3)):
self.vector = vector
def asQuaternion(self):
norm = np.linalg.norm(self.vector)
halfAngle = np.arctan(norm)
return Quaternion(np.cos(halfAngle),np.sin(halfAngle)*self.vector/norm)
def asAngleAxis(self):
norm = np.linalg.norm(self.vector)
halfAngle = np.arctan(norm)
return (2.0*halfAngle,self.vector/norm)
# ****************************************************************************************** # ******************************************************************************************
class Quaternion: class Quaternion:
u""" u"""
@ -33,7 +15,7 @@ class Quaternion:
All methods and naming conventions based on Rowenhorst_etal2015 All methods and naming conventions based on Rowenhorst_etal2015
Convention 1: coordinate frames are right-handed Convention 1: coordinate frames are right-handed
Convention 2: a rotation angle ω is taken to be positive for a counterclockwise rotation Convention 2: a rotation angle ω is taken to be positive for a counterclockwise rotation
when viewing from the end point of the rotation axis unit vector towards the origin when viewing from the end point of the rotation axis towards the origin
Convention 3: rotations will be interpreted in the passive sense Convention 3: rotations will be interpreted in the passive sense
Convention 4: Euler angle triplets are implemented using the Bunge convention, Convention 4: Euler angle triplets are implemented using the Bunge convention,
with the angular ranges as [0, 2π],[0, π],[0, 2π] with the angular ranges as [0, 2π],[0, π],[0, 2π]
@ -48,253 +30,167 @@ class Quaternion:
""" """
def __init__(self, def __init__(self,
quatArray = [1.0,0.0,0.0,0.0]): quat = None,
"""Initializes to identity if not given""" q = 1.0,
self.w, \ p = np.zeros(3,dtype=float)):
self.x, \ """Initializes to identity unless specified"""
self.y, \ self.q = quat[0] if quat is not None else q
self.z = quatArray self.p = np.array(quat[1:4]) if quat is not None else p
self.homomorph() self.homomorph()
def __iter__(self): def __iter__(self):
"""Components""" """Components"""
return iter([self.w,self.x,self.y,self.z]) return iter(self.asList())
def __copy__(self): def __copy__(self):
"""Create copy""" """Copy"""
Q = Quaternion([self.w,self.x,self.y,self.z]) return self.__class__(q=self.q,p=self.p.copy())
return Q
copy = __copy__ copy = __copy__
def __repr__(self): def __repr__(self):
"""Readbable string""" """Readable string"""
return 'Quaternion(real=%+.6f, imag=<%+.6f, %+.6f, %+.6f>)' % \ return 'Quaternion(real={q:+.6f}, imag=<{p[0]:+.6f}, {p[1]:+.6f}, {p[2]:+.6f}>)'.format(q=self.q,p=self.p)
(self.w, self.x, self.y, self.z)
def __pow__(self, exponent): def __pow__(self, exponent):
"""Power""" """Power"""
omega = math.acos(self.w) omega = math.acos(self.q)
vRescale = math.sin(exponent*omega)/math.sin(omega) return self.__class__(q= math.cos(exponent*omega),
Q = Quaternion() p=self.p * math.sin(exponent*omega)/math.sin(omega))
Q.w = math.cos(exponent*omega)
Q.x = self.x * vRescale
Q.y = self.y * vRescale
Q.z = self.z * vRescale
return Q
def __ipow__(self, exponent): def __ipow__(self, exponent):
"""In-place power""" """In-place power"""
omega = math.acos(self.w) omega = math.acos(self.q)
vRescale = math.sin(exponent*omega)/math.sin(omega) self.q = math.cos(exponent*omega)
self.w = np.cos(exponent*omega) self.p *= math.sin(exponent*omega)/math.sin(omega)
self.x *= vRescale
self.y *= vRescale
self.z *= vRescale
return self return self
def __mul__(self, other): def __mul__(self, other):
"""Multiplication""" """Multiplication"""
try: # quaternion # Rowenhorst_etal2015 MSMSE: value of P is selected as -1
Aw = self.w P = -1.0
Ax = self.x try: # quaternion
Ay = self.y return self.__class__(q=self.q*other.q - np.dot(self.p,other.p),
Az = self.z p=self.q*other.p + other.q*self.p + P * np.cross(self.p,other.p))
Bw = other.w
Bx = other.x
By = other.y
Bz = other.z
Q = Quaternion()
Q.w = - Ax * Bx - Ay * By - Az * Bz + Aw * Bw
Q.x = + Ax * Bw + Ay * Bz - Az * By + Aw * Bx
Q.y = - Ax * Bz + Ay * Bw + Az * Bx + Aw * By
Q.z = + Ax * By - Ay * Bx + Az * Bw + Aw * Bz
return Q
except: pass except: pass
try: # vector (perform active rotation, i.e. q*v*q.conjugated) try: # vector (perform passive rotation)
w = self.w ( x, y, z) = self.p
x = self.x (Vx,Vy,Vz) = other[0:3]
y = self.y A = self.q*self.q - np.dot(self.p,self.p)
z = self.z B = 2.0 * (x*Vx + y*Vy + z*Vz)
Vx = other[0] C = 2.0 * P*self.q
Vy = other[1]
Vz = other[2]
return np.array([\ return np.array([
w * w * Vx + 2 * y * w * Vz - 2 * z * w * Vy + \ A*Vx + B*x + C*(y*Vz - z*Vy),
x * x * Vx + 2 * y * x * Vy + 2 * z * x * Vz - \ A*Vy + B*y + C*(z*Vx - x*Vz),
z * z * Vx - y * y * Vx, A*Vz + B*z + C*(x*Vy - y*Vx),
2 * x * y * Vx + y * y * Vy + 2 * z * y * Vz + \ ])
2 * w * z * Vx - z * z * Vy + w * w * Vy - \
2 * x * w * Vz - x * x * Vy,
2 * x * z * Vx + 2 * y * z * Vy + \
z * z * Vz - 2 * w * y * Vx - y * y * Vz + \
2 * w * x * Vy - x * x * Vz + w * w * Vz ])
except: pass except: pass
try: # scalar try: # scalar
Q = self.copy() return self.__class__(q=self.q*other,
Q.w *= other p=self.p*other)
Q.x *= other
Q.y *= other
Q.z *= other
return Q
except: except:
return self.copy() return self.copy()
def __imul__(self, other): def __imul__(self, other):
"""In-place multiplication""" """In-place multiplication"""
try: # Quaternion # Rowenhorst_etal2015 MSMSE: value of P is selected as -1
Aw = self.w P = -1.0
Ax = self.x try: # Quaternion
Ay = self.y self.q = self.q*other.q - np.dot(self.p,other.p)
Az = self.z self.p = self.q*other.p + other.q*self.p + P * np.cross(self.p,other.p)
Bw = other.w
Bx = other.x
By = other.y
Bz = other.z
self.w = - Ax * Bx - Ay * By - Az * Bz + Aw * Bw
self.x = + Ax * Bw + Ay * Bz - Az * By + Aw * Bx
self.y = - Ax * Bz + Ay * Bw + Az * Bx + Aw * By
self.z = + Ax * By - Ay * Bx + Az * Bw + Aw * Bz
except: pass except: pass
return self return self
def __div__(self, other): def __div__(self, other):
"""Division""" """Division"""
if isinstance(other, (int,float)): if isinstance(other, (int,float)):
w = self.w / other return self.__class__(q=self.q / other,
x = self.x / other p=self.p / other)
y = self.y / other
z = self.z / other
return self.__class__([w,x,y,z])
else: else:
return NotImplemented return NotImplemented
def __idiv__(self, other): def __idiv__(self, other):
"""In-place division""" """In-place division"""
if isinstance(other, (int,float)): if isinstance(other, (int,float)):
self.w /= other self.q /= other
self.x /= other self.p /= other
self.y /= other
self.z /= other
return self return self
def __add__(self, other): def __add__(self, other):
"""Addition""" """Addition"""
if isinstance(other, Quaternion): if isinstance(other, Quaternion):
w = self.w + other.w return self.__class__(q=self.q + other.q,
x = self.x + other.x p=self.p + other.p)
y = self.y + other.y
z = self.z + other.z
return self.__class__([w,x,y,z])
else: else:
return NotImplemented return NotImplemented
def __iadd__(self, other): def __iadd__(self, other):
"""In-place addition""" """In-place addition"""
if isinstance(other, Quaternion): if isinstance(other, Quaternion):
self.w += other.w self.q += other.q
self.x += other.x self.p += other.p
self.y += other.y
self.z += other.z
return self return self
def __sub__(self, other): def __sub__(self, other):
"""Subtraction""" """Subtraction"""
if isinstance(other, Quaternion): if isinstance(other, Quaternion):
Q = self.copy() return self.__class__(q=self.q - other.q,
Q.w -= other.w p=self.p - other.p)
Q.x -= other.x
Q.y -= other.y
Q.z -= other.z
return Q
else: else:
return self.copy() return NotImplemented
def __isub__(self, other): def __isub__(self, other):
"""In-place subtraction""" """In-place subtraction"""
if isinstance(other, Quaternion): if isinstance(other, Quaternion):
self.w -= other.w self.q -= other.q
self.x -= other.x self.p -= other.p
self.y -= other.y
self.z -= other.z
return self return self
def __neg__(self): def __neg__(self):
"""Additive inverse""" """Additive inverse"""
self.w = -self.w self.q = -self.q
self.x = -self.x self.p = -self.p
self.y = -self.y
self.z = -self.z
return self return self
def __abs__(self): def __abs__(self):
"""Norm""" """Norm"""
return math.sqrt(self.w ** 2 + \ return math.sqrt(self.q ** 2 + np.dot(self.p,self.p))
self.x ** 2 + \
self.y ** 2 + \
self.z ** 2)
magnitude = __abs__ magnitude = __abs__
def __eq__(self,other): def __eq__(self,other):
"""Equal at e-8 precision""" """Equal (sufficiently close) to each other"""
return (abs(self.w-other.w) < 1e-8 and \ return np.isclose(( self-other).magnitude(),0.0) \
abs(self.x-other.x) < 1e-8 and \ or np.isclose((-self-other).magnitude(),0.0)
abs(self.y-other.y) < 1e-8 and \
abs(self.z-other.z) < 1e-8) \
or \
(abs(-self.w-other.w) < 1e-8 and \
abs(-self.x-other.x) < 1e-8 and \
abs(-self.y-other.y) < 1e-8 and \
abs(-self.z-other.z) < 1e-8)
def __ne__(self,other): def __ne__(self,other):
"""Not equal at e-8 precision""" """Not equal (sufficiently close) to each other"""
return not self.__eq__(self,other) return not self.__eq__(other)
def __cmp__(self,other): def __cmp__(self,other):
"""Linear ordering""" """Linear ordering"""
return (self.Rodrigues()>other.Rodrigues()) - (self.Rodrigues()<other.Rodrigues()) return (1 if np.linalg.norm(self.asRodrigues()) > np.linalg.norm(other.asRodrigues()) else 0) \
- (1 if np.linalg.norm(self.asRodrigues()) < np.linalg.norm(other.asRodrigues()) else 0)
def magnitude_squared(self): def magnitude_squared(self):
return self.w ** 2 + \ return self.q ** 2 + np.dot(self.p,self.p)
self.x ** 2 + \
self.y ** 2 + \
self.z ** 2
def identity(self):
self.w = 1.
self.x = 0.
self.y = 0.
self.z = 0.
return self
def normalize(self): def normalize(self):
d = self.magnitude() d = self.magnitude()
if d > 0.0: if d > 0.0:
self /= d self.q /= d
self.p /= d
return self return self
def conjugate(self): def conjugate(self):
self.x = -self.x self.p = -self.p
self.y = -self.y
self.z = -self.z
return self
def inverse(self):
d = self.magnitude()
if d > 0.0:
self.conjugate()
self /= d
return self return self
def homomorph(self): def homomorph(self):
if self.w < 0.0: if self.q < 0.0:
self.w = -self.w self.q = -self.q
self.x = -self.x self.p = -self.p
self.y = -self.y
self.z = -self.z
return self return self
def normalized(self): def normalized(self):
@ -303,63 +199,73 @@ class Quaternion:
def conjugated(self): def conjugated(self):
return self.copy().conjugate() return self.copy().conjugate()
def inversed(self):
return self.copy().inverse()
def homomorphed(self): def homomorphed(self):
return self.copy().homomorph() return self.copy().homomorph()
def asList(self): def asList(self):
return [i for i in self] return [self.q]+list(self.p)
def asM(self): # to find Averaging Quaternions (see F. Landis Markley et al.)
return np.outer([i for i in self],[i for i in self])
def asM(self): # to find Averaging Quaternions (see F. Landis Markley et al.)
return np.outer(self.asList(),self.asList())
def asMatrix(self): def asMatrix(self):
qbarhalf = 0.5*(self.w**2 - self.x**2 - self.y**2 - self.z**2) # Rowenhorst_etal2015 MSMSE: value of P is selected as -1
P = -1.0
qbarhalf = 0.5*(self.q**2 - np.dot(self.p,self.p))
return 2.0*np.array( return 2.0*np.array(
[[ qbarhalf + self.x**2 , self.x*self.y - self.w*self.z, self.x*self.z + self.w*self.y], [[ qbarhalf + self.p[0]**2 ,
[ self.x*self.y + self.w*self.z, qbarhalf + self.y**2 , self.y*self.z - self.w*self.x], self.p[0]*self.p[1] -P* self.q*self.p[2],
[ self.x*self.z - self.w*self.y, self.y*self.z + self.w*self.x, qbarhalf + self.z**2 ], self.p[0]*self.p[2] +P* self.q*self.p[1] ],
[ self.p[0]*self.p[1] +P* self.q*self.p[2],
qbarhalf + self.p[1]**2 ,
self.p[1]*self.p[2] -P* self.q*self.p[0] ],
[ self.p[0]*self.p[2] -P* self.q*self.p[1],
self.p[1]*self.p[2] +P* self.q*self.p[0],
qbarhalf + self.p[2]**2 ],
]) ])
def asAngleAxis(self, def asAngleAxis(self,
degrees = False): degrees = False,
if self.w > 1: flat = False):
self.normalize()
s = math.sqrt(1. - self.w**2) angle = 2.0*math.acos(self.q)
x = 2*self.w**2 - 1.
y = 2*self.w * s
angle = math.atan2(y,x) if np.isclose(angle,0.0):
if angle < 0.0: angle = 0.0
angle *= -1. axis = np.array([0.0,0.0,1.0])
s *= -1. elif np.isclose(self.q,0.0):
angle = math.pi
axis = self.p
else:
axis = np.sign(self.q)*self.p/np.linalg.norm(self.p)
return (np.degrees(angle) if degrees else angle, angle = np.degrees(angle) if degrees else angle
np.array([1.0, 0.0, 0.0] if np.abs(angle) < 1e-6 else [self.x / s, self.y / s, self.z / s]))
return np.hstack((angle,axis)) if flat else (angle,axis)
def asRodrigues(self): def asRodrigues(self):
return np.inf*np.ones(3) if self.w == 0.0 else np.array([self.x, self.y, self.z])/self.w return np.inf*np.ones(3) if np.isclose(self.q,0.0) else self.p/self.q
def asEulers(self, def asEulers(self,
degrees = False): degrees = False):
"""Orientation as Bunge-Euler angles.""" """Orientation as Bunge-Euler angles."""
q03 = self.w**2+self.z**2 # Rowenhorst_etal2015 MSMSE: value of P is selected as -1
q12 = self.x**2+self.y**2 P = -1.0
q03 = self.q**2 + self.p[2]**2
q12 = self.p[0]**2 + self.p[1]**2
chi = np.sqrt(q03*q12) chi = np.sqrt(q03*q12)
if abs(chi) < 1e-10 and abs(q12) < 1e-10: if np.isclose(chi,0.0) and np.isclose(q12,0.0):
eulers = np.array([math.atan2(-2*self.w*self.z,self.w**2-self.z**2),0,0]) eulers = np.array([math.atan2(-2*P*self.q*self.p[2],self.q**2-self.p[2]**2),0,0])
elif abs(chi) < 1e-10 and abs(q03) < 1e-10: elif np.isclose(chi,0.0) and np.isclose(q03,0.0):
eulers = np.array([math.atan2( 2*self.x*self.y,self.x**2-self.y**2),np.pi,0]) eulers = np.array([math.atan2( 2 *self.p[0]*self.p[1],self.p[0]**2-self.p[1]**2),np.pi,0])
else: else:
eulers = np.array([math.atan2((self.x*self.z-self.w*self.y)/chi,(-self.w*self.x-self.y*self.z)/chi), eulers = np.array([math.atan2((self.p[0]*self.p[2]-P*self.q*self.p[1])/chi,(-P*self.q*self.p[0]-self.p[1]*self.p[2])/chi),
math.atan2(2*chi,q03-q12), math.atan2(2*chi,q03-q12),
math.atan2((self.w*self.y+self.x*self.z)/chi,( self.y*self.z-self.w*self.x)/chi), math.atan2((P*self.q*self.p[1]+self.p[0]*self.p[2])/chi,( self.p[1]*self.p[2]-P*self.q*self.p[0])/chi),
]) ])
eulers %= 2.0*math.pi # enforce positive angles
return np.degrees(eulers) if degrees else eulers return np.degrees(eulers) if degrees else eulers
@ -371,25 +277,28 @@ class Quaternion:
@classmethod @classmethod
def fromRandom(cls,randomSeed = None): def fromRandom(cls,randomSeed = None):
import binascii
if randomSeed is None: if randomSeed is None:
randomSeed = int(os.urandom(4).encode('hex'), 16) randomSeed = int(binascii.hexlify(os.urandom(4)),16)
np.random.seed(randomSeed) np.random.seed(randomSeed)
r = np.random.random(3) r = np.random.random(3)
w = math.cos(2.0*math.pi*r[0])*math.sqrt(r[2]) A = math.sqrt(max(0.0,r[2]))
x = math.sin(2.0*math.pi*r[1])*math.sqrt(1.0-r[2]) B = math.sqrt(max(0.0,1.0-r[2]))
y = math.cos(2.0*math.pi*r[1])*math.sqrt(1.0-r[2]) w = math.cos(2.0*math.pi*r[0])*A
z = math.sin(2.0*math.pi*r[0])*math.sqrt(r[2]) x = math.sin(2.0*math.pi*r[1])*B
return cls([w,x,y,z]) y = math.cos(2.0*math.pi*r[1])*B
z = math.sin(2.0*math.pi*r[0])*A
return cls(quat=[w,x,y,z])
@classmethod @classmethod
def fromRodrigues(cls, rodrigues): def fromRodrigues(cls, rodrigues):
if not isinstance(rodrigues, np.ndarray): rodrigues = np.array(rodrigues) if not isinstance(rodrigues, np.ndarray): rodrigues = np.array(rodrigues)
halfangle = math.atan(np.linalg.norm(rodrigues)) norm = np.linalg.norm(rodrigues)
halfangle = math.atan(norm)
s = math.sin(halfangle)
c = math.cos(halfangle) c = math.cos(halfangle)
w = c return cls(q=c,p=s*rodrigues/norm)
x,y,z = rodrigues/c
return cls([w,x,y,z])
@classmethod @classmethod
@ -397,22 +306,19 @@ class Quaternion:
angle, angle,
axis, axis,
degrees = False): degrees = False):
if not isinstance(axis, np.ndarray): axis = np.array(axis,dtype='d') if not isinstance(axis, np.ndarray): axis = np.array(axis,dtype=float)
axis = axis.astype(float)/np.linalg.norm(axis) axis = axis.astype(float)/np.linalg.norm(axis)
angle = np.radians(angle) if degrees else angle angle = np.radians(angle) if degrees else angle
s = math.sin(0.5 * angle) s = math.sin(0.5 * angle)
w = math.cos(0.5 * angle) c = math.cos(0.5 * angle)
x = axis[0] * s return cls(q=c,p=axis*s)
y = axis[1] * s
z = axis[2] * s
return cls([w,x,y,z])
@classmethod @classmethod
def fromEulers(cls, def fromEulers(cls,
eulers, eulers,
degrees = False): degrees = False):
if not isinstance(eulers, np.ndarray): eulers = np.array(eulers,dtype='d') if not isinstance(eulers, np.ndarray): eulers = np.array(eulers,dtype=float)
eulers = np.radians(eulers) if degrees else eulers eulers = np.radians(eulers) if degrees else eulers
sigma = 0.5*(eulers[0]+eulers[2]) sigma = 0.5*(eulers[0]+eulers[2])
@ -420,11 +326,13 @@ class Quaternion:
c = np.cos(0.5*eulers[1]) c = np.cos(0.5*eulers[1])
s = np.sin(0.5*eulers[1]) s = np.sin(0.5*eulers[1])
w = c * np.cos(sigma) # Rowenhorst_etal2015 MSMSE: value of P is selected as -1
x = -s * np.cos(delta) P = -1.0
y = -s * np.sin(delta) w = c * np.cos(sigma)
z = -c * np.sin(sigma) x = -P * s * np.cos(delta)
return cls([w,x,y,z]) y = -P * s * np.sin(delta)
z = -P * c * np.sin(sigma)
return cls(quat=[w,x,y,z])
# Modified Method to calculate Quaternion from Orientation Matrix, # Modified Method to calculate Quaternion from Orientation Matrix,
@ -435,16 +343,18 @@ class Quaternion:
if m.shape != (3,3) and np.prod(m.shape) == 9: if m.shape != (3,3) and np.prod(m.shape) == 9:
m = m.reshape(3,3) m = m.reshape(3,3)
w = 0.5*math.sqrt(1.+m[0,0]+m[1,1]+m[2,2]) # Rowenhorst_etal2015 MSMSE: value of P is selected as -1
x = 0.5*math.sqrt(1.+m[0,0]-m[1,1]-m[2,2]) P = -1.0
y = 0.5*math.sqrt(1.-m[0,0]+m[1,1]-m[2,2]) w = 0.5*math.sqrt(max(0.0,1.0+m[0,0]+m[1,1]+m[2,2]))
z = 0.5*math.sqrt(1.-m[0,0]-m[1,1]+m[2,2]) x = P*0.5*math.sqrt(max(0.0,1.0+m[0,0]-m[1,1]-m[2,2]))
y = P*0.5*math.sqrt(max(0.0,1.0-m[0,0]+m[1,1]-m[2,2]))
z = P*0.5*math.sqrt(max(0.0,1.0-m[0,0]-m[1,1]+m[2,2]))
x *= -1 if m[2,1] < m[1,2] else 1 x *= -1 if m[2,1] < m[1,2] else 1
y *= -1 if m[0,2] < m[2,0] else 1 y *= -1 if m[0,2] < m[2,0] else 1
z *= -1 if m[1,0] < m[0,1] else 1 z *= -1 if m[1,0] < m[0,1] else 1
return cls( np.array([w,x,y,z])/math.sqrt(w**2 + x**2 + y**2 + z**2)) return cls(quat=np.array([w,x,y,z])/math.sqrt(w**2 + x**2 + y**2 + z**2))
@classmethod @classmethod
@ -458,36 +368,30 @@ class Quaternion:
assert isinstance(q1, Quaternion) and isinstance(q2, Quaternion) assert isinstance(q1, Quaternion) and isinstance(q2, Quaternion)
Q = cls() Q = cls()
costheta = q1.w * q2.w + q1.x * q2.x + q1.y * q2.y + q1.z * q2.z costheta = q1.q*q2.q + np.dot(q1.p,q2.p)
if costheta < 0.: if costheta < 0.:
costheta = -costheta costheta = -costheta
q1 = q1.conjugated() q1 = q1.conjugated()
elif costheta > 1: elif costheta > 1.:
costheta = 1 costheta = 1.
theta = math.acos(costheta) theta = math.acos(costheta)
if abs(theta) < 0.01: if abs(theta) < 0.01:
Q.w = q2.w Q.q = q2.q
Q.x = q2.x Q.p = q2.p
Q.y = q2.y
Q.z = q2.z
return Q return Q
sintheta = math.sqrt(1.0 - costheta * costheta) sintheta = math.sqrt(1.0 - costheta * costheta)
if abs(sintheta) < 0.01: if abs(sintheta) < 0.01:
Q.w = (q1.w + q2.w) * 0.5 Q.q = (q1.q + q2.q) * 0.5
Q.x = (q1.x + q2.x) * 0.5 Q.p = (q1.p + q2.p) * 0.5
Q.y = (q1.y + q2.y) * 0.5
Q.z = (q1.z + q2.z) * 0.5
return Q return Q
ratio1 = math.sin((1 - t) * theta) / sintheta ratio1 = math.sin((1.0 - t) * theta) / sintheta
ratio2 = math.sin(t * theta) / sintheta ratio2 = math.sin( t * theta) / sintheta
Q.w = q1.w * ratio1 + q2.w * ratio2 Q.q = q1.q * ratio1 + q2.q * ratio2
Q.x = q1.x * ratio1 + q2.x * ratio2 Q.p = q1.p * ratio1 + q2.p * ratio2
Q.y = q1.y * ratio1 + q2.y * ratio2
Q.z = q1.z * ratio1 + q2.z * ratio2
return Q return Q
@ -512,21 +416,21 @@ class Symmetry:
def __repr__(self): def __repr__(self):
"""Readbable string""" """Readable string"""
return '%s' % (self.lattice) return '{}'.format(self.lattice)
def __eq__(self, other): def __eq__(self, other):
"""Equal""" """Equal to other"""
return self.lattice == other.lattice return self.lattice == other.lattice
def __neq__(self, other): def __neq__(self, other):
"""Not equal""" """Not equal to other"""
return not self.__eq__(other) return not self.__eq__(other)
def __cmp__(self,other): def __cmp__(self,other):
"""Linear ordering""" """Linear ordering"""
myOrder = Symmetry.lattices.index(self.lattice) myOrder = Symmetry.lattices.index(self.lattice)
otherOrder = Symmetry.lattices.index(other.lattice) otherOrder = Symmetry.lattices.index(other.lattice)
return (myOrder > otherOrder) - (myOrder < otherOrder) return (myOrder > otherOrder) - (myOrder < otherOrder)
@ -598,7 +502,7 @@ class Symmetry:
] ]
return list(map(Quaternion, return list(map(Quaternion,
np.array(symQuats)[np.atleast_1d(np.array(who)) if who != [] else range(len(symQuats))])) np.array(symQuats)[np.atleast_1d(np.array(who)) if who != [] else range(len(symQuats))]))
def equivalentQuaternions(self, def equivalentQuaternions(self,
@ -610,7 +514,7 @@ class Symmetry:
def inFZ(self,R): def inFZ(self,R):
"""Check whether given Rodrigues vector falls into fundamental zone of own symmetry.""" """Check whether given Rodrigues vector falls into fundamental zone of own symmetry."""
if isinstance(R, Quaternion): R = R.asRodrigues() # translate accidentially passed quaternion if isinstance(R, Quaternion): R = R.asRodrigues() # translate accidentally passed quaternion
# fundamental zone in Rodrigues space is point symmetric around origin # fundamental zone in Rodrigues space is point symmetric around origin
R = abs(R) R = abs(R)
if self.lattice == 'cubic': if self.lattice == 'cubic':
@ -722,7 +626,7 @@ class Symmetry:
else: else:
return True return True
v = np.array(vector,dtype = float) v = np.array(vector,dtype=float)
if proper: # check both improper ... if proper: # check both improper ...
theComponents = np.dot(basis['improper'],v) theComponents = np.dot(basis['improper'],v)
inSST = np.all(theComponents >= 0.0) inSST = np.all(theComponents >= 0.0)
@ -737,10 +641,10 @@ class Symmetry:
if color: # have to return color array if color: # have to return color array
if inSST: if inSST:
rgb = np.power(theComponents/np.linalg.norm(theComponents),0.5) # smoothen color ramps rgb = np.power(theComponents/np.linalg.norm(theComponents),0.5) # smoothen color ramps
rgb = np.minimum(np.ones(3,'d'),rgb) # limit to maximum intensity rgb = np.minimum(np.ones(3,dtype=float),rgb) # limit to maximum intensity
rgb /= max(rgb) # normalize to (HS)V = 1 rgb /= max(rgb) # normalize to (HS)V = 1
else: else:
rgb = np.zeros(3,'d') rgb = np.zeros(3,dtype=float)
return (inSST,rgb) return (inSST,rgb)
else: else:
return inSST return inSST
@ -780,8 +684,9 @@ class Orientation:
self.quaternion = Quaternion.fromRodrigues(Rodrigues) self.quaternion = Quaternion.fromRodrigues(Rodrigues)
elif isinstance(quaternion, Quaternion): # based on given quaternion elif isinstance(quaternion, Quaternion): # based on given quaternion
self.quaternion = quaternion.homomorphed() self.quaternion = quaternion.homomorphed()
elif isinstance(quaternion, np.ndarray) and quaternion.shape == (4,): # based on given quaternion-like array elif (isinstance(quaternion, np.ndarray) and quaternion.shape == (4,)) or \
self.quaternion = Quaternion(quaternion).homomorphed() (isinstance(quaternion, list) and len(quaternion) == 4 ): # based on given quaternion-like array
self.quaternion = Quaternion(quat=quaternion).homomorphed()
self.symmetry = Symmetry(symmetry) self.symmetry = Symmetry(symmetry)
@ -794,10 +699,12 @@ class Orientation:
def __repr__(self): def __repr__(self):
"""Value as all implemented representations""" """Value as all implemented representations"""
return 'Symmetry: %s\n' % (self.symmetry) + \ return '\n'.join([
'Quaternion: %s\n' % (self.quaternion) + \ 'Symmetry: {}'.format(self.symmetry),
'Matrix:\n%s\n' % ( '\n'.join(['\t'.join(map(str,self.asMatrix()[i,:])) for i in range(3)]) ) + \ 'Quaternion: {}'.format(self.quaternion),
'Bunge Eulers / deg: %s' % ('\t'.join(map(str,self.asEulers(degrees=True))) ) 'Matrix:\n{}'.format( '\n'.join(['\t'.join(list(map(str,self.asMatrix()[i,:]))) for i in range(3)]) ),
'Bunge Eulers / deg: {}'.format('\t'.join(list(map(str,self.asEulers(degrees=True)))) ),
])
def asQuaternion(self): def asQuaternion(self):
return self.quaternion.asList() return self.quaternion.asList()
@ -813,8 +720,9 @@ class Orientation:
rodrigues = property(asRodrigues) rodrigues = property(asRodrigues)
def asAngleAxis(self, def asAngleAxis(self,
degrees = False): degrees = False,
return self.quaternion.asAngleAxis(degrees) flat = False):
return self.quaternion.asAngleAxis(degrees,flat)
angleAxis = property(asAngleAxis) angleAxis = property(asAngleAxis)
def asMatrix(self): def asMatrix(self):
@ -927,7 +835,7 @@ class Orientation:
M = closest.quaternion.asM() * n if i == 0 else M + closest.quaternion.asM() * n # noqa add (multiples) of this orientation to average noqa M = closest.quaternion.asM() * n if i == 0 else M + closest.quaternion.asM() * n # noqa add (multiples) of this orientation to average noqa
eig, vec = np.linalg.eig(M/N) eig, vec = np.linalg.eig(M/N)
return Orientation(quaternion = Quaternion(quatArray = np.real(vec.T[eig.argmax()])), return Orientation(quaternion = Quaternion(quat = np.real(vec.T[eig.argmax()])),
symmetry = reference.symmetry.lattice) symmetry = reference.symmetry.lattice)

View File

@ -132,6 +132,30 @@ class extendableOption(Option):
else: else:
Option.take_action(self, action, dest, opt, value, values, parser) Option.take_action(self, action, dest, opt, value, values, parser)
# Print iterations progress
# from https://gist.github.com/aubricus/f91fb55dc6ba5557fbab06119420dd6a
def progressBar(iteration, total, prefix='', suffix='', decimals=1, bar_length=100):
"""
Call in a loop to create terminal progress bar
@params:
iteration - Required : current iteration (Int)
total - Required : total iterations (Int)
prefix - Optional : prefix string (Str)
suffix - Optional : suffix string (Str)
decimals - Optional : positive number of decimals in percent complete (Int)
bar_length - Optional : character length of bar (Int)
"""
str_format = "{0:." + str(decimals) + "f}"
percents = str_format.format(100 * (iteration / float(total)))
filled_length = int(round(bar_length * iteration / float(total)))
bar = '' * filled_length + '-' * (bar_length - filled_length)
sys.stderr.write('\r%s |%s| %s%s %s' % (prefix, bar, percents, '%', suffix)),
if iteration == total: sys.stderr.write('\n\n')
sys.stderr.flush()
# ----------------------------- # -----------------------------
class backgroundMessage(threading.Thread): class backgroundMessage(threading.Thread):
"""Reporting with animation to indicate progress""" """Reporting with animation to indicate progress"""

View File

@ -1,4 +1,4 @@
#!/usr/bin/env python2.7 #!/usr/bin/env python3
# -*- coding: UTF-8 no BOM -*- # -*- coding: UTF-8 no BOM -*-
import os,sys import os,sys
@ -19,55 +19,50 @@ Transform X,Y,Z,F APS BeamLine 34 coordinates to x,y,z APS strain coordinates.
""", version = scriptID) """, version = scriptID)
parser.add_option('-f','--frame', dest='frame', nargs=4, type='string', metavar='string string string string', parser.add_option('-f',
help='APS X,Y,Z coords, and depth F') '--frame',
parser.set_defaults(frame = None) dest='frame',
metavar='string',
help='APS X,Y,Z coords')
parser.add_option('--depth',
dest='depth',
metavar='string',
help='depth')
(options,filenames) = parser.parse_args() (options,filenames) = parser.parse_args()
if options.frame is None: if options.frame is None:
parser.error('no data column specified...') parser.error('frame not specified')
if options.depth is None:
parser.error('depth not specified')
# --- loop over input files ------------------------------------------------------------------------
datainfo = {'len':3, if filenames == []: filenames = [None]
'label':[]
}
datainfo['label'] += options.frame
# --- loop over input files -------------------------------------------------------------------------
if filenames == []:
filenames = ['STDIN']
for name in filenames: for name in filenames:
if name == 'STDIN': try: table = damask.ASCIItable(name = name,
file = {'name':'STDIN', 'input':sys.stdin, 'output':sys.stdout, 'croak':sys.stderr} buffered = False)
file['croak'].write('\033[1m'+scriptName+'\033[0m\n') except: continue
else: damask.util.report(scriptName,name)
if not os.path.exists(name): continue
file = {'name':name, 'input':open(name), 'output':open(name+'_tmp','w'), 'croak':sys.stderr} # ------------------------------------------ read header ------------------------------------------
file['croak'].write('\033[1m'+scriptName+'\033[0m: '+file['name']+'\n')
table.head_read()
# ------------------------------------------ sanity checks -----------------------------------------
errors = []
if table.label_dimension(options.frame) != 3:
errors.append('input {} does not have dimension 3.'.format(options.frame))
if table.label_dimension(options.depth) != 1:
errors.append('input {} does not have dimension 1.'.format(options.depth))
if errors != []:
damask.util.croak(errors)
table.close(dismiss = True)
continue
table = damask.ASCIItable(file['input'],file['output'],buffered=False) # make unbuffered ASCII_table
table.head_read() # read ASCII header info
table.info_append(scriptID + '\t' + ' '.join(sys.argv[1:])) table.info_append(scriptID + '\t' + ' '.join(sys.argv[1:]))
# --------------- figure out columns to process ---------------------------------------------------
active = []
column = {}
columnMissing = False
for label in datainfo['label']:
key = label
if key in table.labels(raw = True):
active.append(label)
column[label] = table.labels.index(key) # remember columns of requested data
else:
file['croak'].write('column %s not found...\n'%label)
columnMissing = True
if columnMissing: continue
# ------------------------------------------ assemble header --------------------------------------- # ------------------------------------------ assemble header ---------------------------------------
table.labels_append(['%i_coord'%(i+1) for i in range(3)]) # extend ASCII header with new labels table.labels_append(['%i_coord'%(i+1) for i in range(3)]) # extend ASCII header with new labels
table.head_write() table.head_write()
@ -77,21 +72,15 @@ for name in filenames:
RotMat2TSL=np.array([[1., 0., 0.], RotMat2TSL=np.array([[1., 0., 0.],
[0., np.cos(theta), np.sin(theta)], # Orientation to account for -135 deg [0., np.cos(theta), np.sin(theta)], # Orientation to account for -135 deg
[0., -np.sin(theta), np.cos(theta)]]) # rotation for TSL convention [0., -np.sin(theta), np.cos(theta)]]) # rotation for TSL convention
vec = np.zeros(4)
outputAlive = True outputAlive = True
while outputAlive and table.data_read(): # read next data line of ASCII table while outputAlive and table.data_read(): # read next data line of ASCII table
for i,label in enumerate(active): coord = list(map(float,table.data[table.label_index(options.frame):table.label_index(options.frame)+3]))
vec[i] = table.data[column[label]] depth = float(table.data[table.label_index(options.depth)])
table.data_append(np.dot(RotMat2TSL,np.array([-vec[0], -vec[1],-vec[2]+vec[3]]))) table.data_append(np.dot(RotMat2TSL,np.array([-coord[0],-coord[1],-coord[2]+depth])))
outputAlive = table.data_write() # output processed line outputAlive = table.data_write() # output processed line
# ------------------------------------------ output result ----------------------------------------- # ------------------------------------------ output finalization -----------------------------------
outputAlive and table.output_flush() # just in case of buffered ASCII table
table.input_close() # close input ASCII table (works for stdin) table.close() # close ASCII tables
table.output_close() # close output ASCII table (works for stdout)
if file['name'] != 'STDIN':
os.rename(file['name']+'_tmp',file['name']) # overwrite old one with tmp new

View File

@ -1,7 +1,7 @@
#!/usr/bin/env python2.7 #!/usr/bin/env python3
# -*- coding: UTF-8 no BOM -*- # -*- coding: UTF-8 no BOM -*-
import os,sys,time,copy import os,sys,copy
import numpy as np import numpy as np
import damask import damask
from optparse import OptionParser from optparse import OptionParser
@ -29,49 +29,28 @@ parser.add_option('-d',
parser.add_option('-s', parser.add_option('-s',
'--symmetry', '--symmetry',
dest = 'symmetry', dest = 'symmetry',
type = 'string', metavar = 'string', metavar = 'string',
help = 'crystal symmetry [%default]') help = 'crystal symmetry [%default]')
parser.add_option('-e', parser.add_option('-o',
'--eulers', '--orientation',
dest = 'eulers',
type = 'string', metavar = 'string',
help = 'label of Euler angles')
parser.add_option('--degrees',
dest = 'degrees',
action = 'store_true',
help = 'Euler angles are given in degrees [%default]')
parser.add_option('-m',
'--matrix',
dest = 'matrix',
type = 'string', metavar = 'string',
help = 'label of orientation matrix')
parser.add_option('-a',
dest = 'a',
type = 'string', metavar = 'string',
help = 'label of crystal frame a vector')
parser.add_option('-b',
dest = 'b',
type = 'string', metavar = 'string',
help = 'label of crystal frame b vector')
parser.add_option('-c',
dest = 'c',
type = 'string', metavar = 'string',
help = 'label of crystal frame c vector')
parser.add_option('-q',
'--quaternion',
dest = 'quaternion', dest = 'quaternion',
type = 'string', metavar = 'string', metavar = 'string',
help = 'label of quaternion') help = 'label of crystal orientation given as unit quaternion [%default]')
parser.add_option('-p', parser.add_option('-p',
'--pos', '--position', '--pos', '--position',
dest = 'pos', dest = 'pos',
type = 'string', metavar = 'string', metavar = 'string',
help = 'label of coordinates [%default]') help = 'label of coordinates [%default]')
parser.add_option('--quiet',
dest='verbose',
action = 'store_false',
help = 'hide status bar (useful when piping to file)')
parser.set_defaults(disorientation = 5, parser.set_defaults(disorientation = 5,
verbose = True,
quaternion = 'orientation',
symmetry = 'cubic', symmetry = 'cubic',
pos = 'pos', pos = 'pos',
degrees = False,
) )
(options, filenames) = parser.parse_args() (options, filenames) = parser.parse_args()
@ -79,22 +58,6 @@ parser.set_defaults(disorientation = 5,
if options.radius is None: if options.radius is None:
parser.error('no radius specified.') parser.error('no radius specified.')
input = [options.eulers is not None,
options.a is not None and \
options.b is not None and \
options.c is not None,
options.matrix is not None,
options.quaternion is not None,
]
if np.sum(input) != 1: parser.error('needs exactly one input format.')
(label,dim,inputtype) = [(options.eulers,3,'eulers'),
([options.a,options.b,options.c],[3,3,3],'frame'),
(options.matrix,9,'matrix'),
(options.quaternion,4,'quaternion'),
][np.where(input)[0][0]] # select input label that was requested
toRadians = np.pi/180.0 if options.degrees else 1.0 # rescale degrees to radians
cos_disorientation = np.cos(np.radians(options.disorientation/2.)) # cos of half the disorientation angle cos_disorientation = np.cos(np.radians(options.disorientation/2.)) # cos of half the disorientation angle
# --- loop over input files ------------------------------------------------------------------------- # --- loop over input files -------------------------------------------------------------------------
@ -118,9 +81,9 @@ for name in filenames:
if not 3 >= table.label_dimension(options.pos) >= 1: if not 3 >= table.label_dimension(options.pos) >= 1:
errors.append('coordinates "{}" need to have one, two, or three dimensions.'.format(options.pos)) errors.append('coordinates "{}" need to have one, two, or three dimensions.'.format(options.pos))
if not np.all(table.label_dimension(label) == dim): if not np.all(table.label_dimension(options.quaternion) == 4):
errors.append('input "{}" does not have dimension {}.'.format(label,dim)) errors.append('input "{}" does not have dimension 4.'.format(options.quaternion))
else: column = table.label_index(label) else: column = table.label_index(options.quaternion)
if remarks != []: damask.util.croak(remarks) if remarks != []: damask.util.croak(remarks)
if errors != []: if errors != []:
@ -131,34 +94,18 @@ for name in filenames:
# ------------------------------------------ assemble header --------------------------------------- # ------------------------------------------ assemble header ---------------------------------------
table.info_append(scriptID + '\t' + ' '.join(sys.argv[1:])) table.info_append(scriptID + '\t' + ' '.join(sys.argv[1:]))
table.labels_append('grainID_{}@{:g}'.format('+'.join(label) table.labels_append('grainID_{}@{:g}'.format(options.quaternion,options.disorientation)) # report orientation source and disorientation
if isinstance(label, (list,tuple))
else label,
options.disorientation)) # report orientation source and disorientation
table.head_write() table.head_write()
# ------------------------------------------ process data ------------------------------------------
# ------------------------------------------ build KD tree ----------------------------------------- # ------------------------------------------ build KD tree -----------------------------------------
# --- start background messaging
bg = damask.util.backgroundMessage()
bg.start()
bg.set_message('reading positions...')
table.data_readArray(options.pos) # read position vectors table.data_readArray(options.pos) # read position vectors
grainID = -np.ones(len(table.data),dtype=int) grainID = -np.ones(len(table.data),dtype=int)
Npoints = table.data.shape[0]
start = tick = time.clock()
bg.set_message('building KD tree...')
kdtree = spatial.KDTree(copy.deepcopy(table.data)) kdtree = spatial.KDTree(copy.deepcopy(table.data))
# ------------------------------------------ assign grain IDs -------------------------------------- # ------------------------------------------ assign grain IDs --------------------------------------
tick = time.clock()
orientations = [] # quaternions found for grain orientations = [] # quaternions found for grain
memberCounts = [] # number of voxels in grain memberCounts = [] # number of voxels in grain
p = 0 # point counter p = 0 # point counter
@ -169,26 +116,11 @@ for name in filenames:
table.data_rewind() table.data_rewind()
while table.data_read(): # read next data line of ASCII table while table.data_read(): # read next data line of ASCII table
if p > 0 and p % 1000 == 0: if options.verbose and Npoints > 100 and p%(Npoints//100) == 0: # report in 1% steps if possible and avoid modulo by zero
damask.util.progressBar(iteration=p,total=Npoints)
time_delta = (time.clock()-tick) * (len(grainID) - p) / p o = damask.Orientation(quaternion = np.array(list(map(float,table.data[column:column+4]))),
bg.set_message('(%02i:%02i:%02i) processing point %i of %i (grain count %i)...'\ symmetry = options.symmetry).reduced()
%(time_delta//3600,time_delta%3600//60,time_delta%60,p,len(grainID),np.count_nonzero(memberCounts)))
if inputtype == 'eulers':
o = damask.Orientation(Eulers = np.array(map(float,table.data[column:column+3]))*toRadians,
symmetry = options.symmetry).reduced()
elif inputtype == 'matrix':
o = damask.Orientation(matrix = np.array(map(float,table.data[column:column+9])).reshape(3,3).transpose(),
symmetry = options.symmetry).reduced()
elif inputtype == 'frame':
o = damask.Orientation(matrix = np.array(map(float,table.data[column[0]:column[0]+3] + \
table.data[column[1]:column[1]+3] + \
table.data[column[2]:column[2]+3])).reshape(3,3),
symmetry = options.symmetry).reduced()
elif inputtype == 'quaternion':
o = damask.Orientation(quaternion = np.array(map(float,table.data[column:column+4])),
symmetry = options.symmetry).reduced()
matched = False matched = False
alreadyChecked = {} alreadyChecked = {}
@ -200,9 +132,9 @@ for name in filenames:
if gID != -1 and gID not in alreadyChecked: # indexed point belonging to a grain not yet tested? if gID != -1 and gID not in alreadyChecked: # indexed point belonging to a grain not yet tested?
alreadyChecked[gID] = True # remember not to check again alreadyChecked[gID] = True # remember not to check again
disorientation = o.disorientation(orientations[gID],SST = False)[0] # compare against other orientation disorientation = o.disorientation(orientations[gID],SST = False)[0] # compare against other orientation
if disorientation.quaternion.w > cos_disorientation: # within threshold ... if disorientation.quaternion.q > cos_disorientation: # within threshold ...
candidates.append(gID) # remember as potential candidate candidates.append(gID) # remember as potential candidate
if disorientation.quaternion.w >= bestDisorientation.w: # ... and better than current best? if disorientation.quaternion.q >= bestDisorientation.q: # ... and better than current best?
matched = True matched = True
matchedID = gID # remember that grain matchedID = gID # remember that grain
bestDisorientation = disorientation.quaternion bestDisorientation = disorientation.quaternion
@ -233,13 +165,12 @@ for name in filenames:
outputAlive = True outputAlive = True
p = 0 p = 0
damask.util.progressBar(iteration=1,total=1)
while outputAlive and table.data_read(): # read next data line of ASCII table while outputAlive and table.data_read(): # read next data line of ASCII table
table.data_append(1+packingMap[grainID[p]]) # add (condensed) grain ID table.data_append(1+packingMap[grainID[p]]) # add (condensed) grain ID
outputAlive = table.data_write() # output processed line outputAlive = table.data_write() # output processed line
p += 1 p += 1
bg.set_message('done after {} seconds'.format(time.clock()-start))
# ------------------------------------------ output finalization ----------------------------------- # ------------------------------------------ output finalization -----------------------------------
table.close() # close ASCII tables table.close() # close ASCII tables

View File

@ -1,7 +1,7 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# -*- coding: UTF-8 no BOM -*- # -*- coding: UTF-8 no BOM -*-
import os,sys,math import os,sys
import numpy as np import numpy as np
from optparse import OptionParser from optparse import OptionParser
import damask import damask
@ -18,66 +18,29 @@ Add RGB color value corresponding to TSL-OIM scheme for inverse pole figures.
""", version = scriptID) """, version = scriptID)
parser.add_option('-p', '--pole', parser.add_option('-p',
'--pole',
dest = 'pole', dest = 'pole',
type = 'float', nargs = 3, metavar = 'float float float', type = 'float', nargs = 3, metavar = 'float float float',
help = 'lab frame direction for inverse pole figure [%default]') help = 'lab frame direction for inverse pole figure [%default]')
parser.add_option('-s', '--symmetry', parser.add_option('-s',
'--symmetry',
dest = 'symmetry', dest = 'symmetry',
type = 'choice', choices = damask.Symmetry.lattices[1:], metavar='string', type = 'choice', choices = damask.Symmetry.lattices[1:], metavar='string',
help = 'crystal symmetry [%default] {{{}}} '.format(', '.join(damask.Symmetry.lattices[1:]))) help = 'crystal symmetry [%default] {{{}}} '.format(', '.join(damask.Symmetry.lattices[1:])))
parser.add_option('-e', '--eulers', parser.add_option('-o',
dest = 'eulers', '--orientation',
type = 'string', metavar = 'string',
help = 'Euler angles label')
parser.add_option('-d', '--degrees',
dest = 'degrees',
action = 'store_true',
help = 'Euler angles are given in degrees [%default]')
parser.add_option('-m', '--matrix',
dest = 'matrix',
type = 'string', metavar = 'string',
help = 'orientation matrix label')
parser.add_option('-a',
dest = 'a',
type = 'string', metavar = 'string',
help = 'crystal frame a vector label')
parser.add_option('-b',
dest = 'b',
type = 'string', metavar = 'string',
help = 'crystal frame b vector label')
parser.add_option('-c',
dest = 'c',
type = 'string', metavar = 'string',
help = 'crystal frame c vector label')
parser.add_option('-q', '--quaternion',
dest = 'quaternion', dest = 'quaternion',
type = 'string', metavar = 'string', metavar = 'string',
help = 'quaternion label') help = 'label of crystal orientation given as unit quaternion [%default]')
parser.set_defaults(pole = (0.0,0.0,1.0), parser.set_defaults(pole = (0.0,0.0,1.0),
quaternion = 'orientation',
symmetry = damask.Symmetry.lattices[-1], symmetry = damask.Symmetry.lattices[-1],
degrees = False,
) )
(options, filenames) = parser.parse_args() (options, filenames) = parser.parse_args()
input = [options.eulers is not None,
options.a is not None and \
options.b is not None and \
options.c is not None,
options.matrix is not None,
options.quaternion is not None,
]
if np.sum(input) != 1: parser.error('needs exactly one input format.')
(label,dim,inputtype) = [(options.eulers,3,'eulers'),
([options.a,options.b,options.c],[3,3,3],'frame'),
(options.matrix,9,'matrix'),
(options.quaternion,4,'quaternion'),
][np.where(input)[0][0]] # select input label that was requested
toRadians = math.pi/180.0 if options.degrees else 1.0 # rescale degrees to radians
pole = np.array(options.pole) pole = np.array(options.pole)
pole /= np.linalg.norm(pole) pole /= np.linalg.norm(pole)
@ -98,12 +61,12 @@ for name in filenames:
# ------------------------------------------ sanity checks ---------------------------------------- # ------------------------------------------ sanity checks ----------------------------------------
if not np.all(table.label_dimension(label) == dim): if not table.label_dimension(options.quaternion) == 4:
damask.util.croak('input {} does not have dimension {}.'.format(label,dim)) damask.util.croak('input {} does not have dimension 4.'.format(options.quaternion))
table.close(dismiss = True) # close ASCIItable and remove empty file table.close(dismiss = True) # close ASCIItable and remove empty file
continue continue
column = table.label_index(label) column = table.label_index(options.quaternion)
# ------------------------------------------ assemble header --------------------------------------- # ------------------------------------------ assemble header ---------------------------------------
@ -115,20 +78,8 @@ for name in filenames:
outputAlive = True outputAlive = True
while outputAlive and table.data_read(): # read next data line of ASCII table while outputAlive and table.data_read(): # read next data line of ASCII table
if inputtype == 'eulers': o = damask.Orientation(quaternion = np.array(list(map(float,table.data[column:column+4]))),
o = damask.Orientation(Eulers = np.array(list(map(float,table.data[column:column+3])))*toRadians, symmetry = options.symmetry).reduced()
symmetry = options.symmetry).reduced()
elif inputtype == 'matrix':
o = damask.Orientation(matrix = np.array(list(map(float,table.data[column:column+9]))).reshape(3,3).transpose(),
symmetry = options.symmetry).reduced()
elif inputtype == 'frame':
o = damask.Orientation(matrix = np.array(list(map(float,table.data[column[0]:column[0]+3] + \
table.data[column[1]:column[1]+3] + \
table.data[column[2]:column[2]+3]))).reshape(3,3),
symmetry = options.symmetry).reduced()
elif inputtype == 'quaternion':
o = damask.Orientation(quaternion = np.array(list(map(float,table.data[column:column+4]))),
symmetry = options.symmetry).reduced()
table.data_append(o.IPFcolor(pole)) table.data_append(o.IPFcolor(pole))
outputAlive = table.data_write() # output processed line outputAlive = table.data_write() # output processed line

View File

@ -1,4 +1,4 @@
#!/usr/bin/env python2.7 #!/usr/bin/env python3
# -*- coding: UTF-8 no BOM -*- # -*- coding: UTF-8 no BOM -*-
import os import os

View File

@ -1,4 +1,4 @@
#!/usr/bin/env python2.7 #!/usr/bin/env python3
# -*- coding: UTF-8 no BOM -*- # -*- coding: UTF-8 no BOM -*-
import os,sys,math import os,sys,math

View File

@ -1,7 +1,7 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# -*- coding: UTF-8 no BOM -*- # -*- coding: UTF-8 no BOM -*-
import os,sys,math import os,sys
import numpy as np import numpy as np
from optparse import OptionParser from optparse import OptionParser
import damask import damask
@ -9,6 +9,31 @@ import damask
scriptName = os.path.splitext(os.path.basename(__file__))[0] scriptName = os.path.splitext(os.path.basename(__file__))[0]
scriptID = ' '.join([scriptName,damask.version]) scriptID = ' '.join([scriptName,damask.version])
# --------------------------------------------------------------------
# convention conformity checks
# --------------------------------------------------------------------
def check_Eulers(eulers):
if np.any(eulers < 0.0) or np.any(eulers > 2.0*np.pi) or eulers[1] > np.pi: # Euler angles within valid range?
raise ValueError('Euler angles outside of [0..2π],[0..π],[0..2π].\n{} {} {}.'.format(*eulers))
return eulers
def check_quaternion(q):
if q[0] < 0.0: # positive first quaternion component?
raise ValueError('quaternion has negative first component.\n{}'.format(q[0]))
if not np.isclose(np.linalg.norm(q), 1.0): # unit quaternion?
raise ValueError('quaternion is not of unit length.\n{} {} {} {}'.format(*q))
return q
def check_matrix(M):
if not np.isclose(np.linalg.det(M),1.0): # proper rotation?
raise ValueError('matrix is not a proper rotation.\n{}'.format(M))
if not np.isclose(np.dot(M[0],M[1]), 0.0) \
or not np.isclose(np.dot(M[1],M[2]), 0.0) \
or not np.isclose(np.dot(M[2],M[0]), 0.0): # all orthogonal?
raise ValueError('matrix is not orthogonal.\n{}'.format(M))
return M
# -------------------------------------------------------------------- # --------------------------------------------------------------------
# MAIN # MAIN
# -------------------------------------------------------------------- # --------------------------------------------------------------------
@ -21,58 +46,64 @@ Additional (globally fixed) rotations of the lab frame and/or crystal frame can
""", version = scriptID) """, version = scriptID)
outputChoices = ['quaternion','rodrigues','eulers'] outputChoices = {
parser.add_option('-o', '--output', 'quaternion': ['quat',4],
'rodrigues': ['rodr',3],
'eulers': ['eulr',3],
'matrix': ['mtrx',9],
'angleaxis': ['aaxs',4],
}
parser.add_option('-o',
'--output',
dest = 'output', dest = 'output',
action = 'extend', metavar = '<string LIST>', action = 'extend', metavar = '<string LIST>',
help = 'output orientation formats {{{}}}'.format(', '.join(outputChoices))) help = 'output orientation formats {{{}}}'.format(', '.join(outputChoices)))
parser.add_option('-s', '--symmetry', parser.add_option('-d',
dest = 'symmetry', '--degrees',
type = 'choice', choices = damask.Symmetry.lattices[1:], metavar='string',
help = 'crystal symmetry [%default] {{{}}} '.format(', '.join(damask.Symmetry.lattices[1:])))
parser.add_option('-d', '--degrees',
dest = 'degrees', dest = 'degrees',
action = 'store_true', action = 'store_true',
help = 'angles are given in degrees [%default]') help = 'all angles in degrees')
parser.add_option('-R', '--labrotation', parser.add_option('-R',
'--labrotation',
dest='labrotation', dest='labrotation',
type = 'float', nargs = 4, metavar = ' '.join(['float']*4), type = 'float', nargs = 4, metavar = ' '.join(['float']*4),
help = 'angle and axis of additional lab frame rotation') help = 'angle and axis of additional lab frame rotation')
parser.add_option('-r', '--crystalrotation', parser.add_option('-r',
'--crystalrotation',
dest='crystalrotation', dest='crystalrotation',
type = 'float', nargs = 4, metavar = ' '.join(['float']*4), type = 'float', nargs = 4, metavar = ' '.join(['float']*4),
help = 'angle and axis of additional crystal frame rotation') help = 'angle and axis of additional crystal frame rotation')
parser.add_option( '--eulers', parser.add_option('--eulers',
dest = 'eulers', dest = 'eulers',
type = 'string', metavar = 'string', metavar = 'string',
help = 'Euler angles label') help = 'Euler angles label')
parser.add_option( '--rodrigues', parser.add_option('--rodrigues',
dest = 'rodrigues', dest = 'rodrigues',
type = 'string', metavar = 'string', metavar = 'string',
help = 'Rodrigues vector label') help = 'Rodrigues vector label')
parser.add_option( '--matrix', parser.add_option('--matrix',
dest = 'matrix', dest = 'matrix',
type = 'string', metavar = 'string', metavar = 'string',
help = 'orientation matrix label') help = 'orientation matrix label')
parser.add_option( '--quaternion', parser.add_option('--quaternion',
dest = 'quaternion', dest = 'quaternion',
type = 'string', metavar = 'string', metavar = 'string',
help = 'quaternion label') help = 'quaternion label')
parser.add_option('-a', parser.add_option('-x',
dest = 'a', dest = 'x',
type = 'string', metavar = 'string', metavar = 'string',
help = 'crystal frame a vector label') help = 'label of lab x vector (expressed in crystal coords)')
parser.add_option('-b', parser.add_option('-y',
dest = 'b', dest = 'y',
type = 'string', metavar = 'string', metavar = 'string',
help = 'crystal frame b vector label') help = 'label of lab y vector (expressed in crystal coords)')
parser.add_option('-c', parser.add_option('-z',
dest = 'c', dest = 'z',
type = 'string', metavar = 'string', metavar = 'string',
help = 'crystal frame c vector label') help = 'label of lab z vector (expressed in crystal coords)')
parser.set_defaults(output = [], parser.set_defaults(output = [],
symmetry = damask.Symmetry.lattices[-1],
labrotation = (0.,1.,1.,1.), # no rotation about 1,1,1 labrotation = (0.,1.,1.,1.), # no rotation about 1,1,1
crystalrotation = (0.,1.,1.,1.), # no rotation about 1,1,1 crystalrotation = (0.,1.,1.,1.), # no rotation about 1,1,1
degrees = False, degrees = False,
@ -86,9 +117,9 @@ if options.output == [] or (not set(options.output).issubset(set(outputChoices))
input = [options.eulers is not None, input = [options.eulers is not None,
options.rodrigues is not None, options.rodrigues is not None,
options.a is not None and \ options.x is not None and \
options.b is not None and \ options.y is not None and \
options.c is not None, options.z is not None,
options.matrix is not None, options.matrix is not None,
options.quaternion is not None, options.quaternion is not None,
] ]
@ -97,13 +128,14 @@ if np.sum(input) != 1: parser.error('needs exactly one input format.')
(label,dim,inputtype) = [(options.eulers,3,'eulers'), (label,dim,inputtype) = [(options.eulers,3,'eulers'),
(options.rodrigues,3,'rodrigues'), (options.rodrigues,3,'rodrigues'),
([options.a,options.b,options.c],[3,3,3],'frame'), ([options.x,options.y,options.z],[3,3,3],'frame'),
(options.matrix,9,'matrix'), (options.matrix,9,'matrix'),
(options.quaternion,4,'quaternion'), (options.quaternion,4,'quaternion'),
][np.where(input)[0][0]] # select input label that was requested ][np.where(input)[0][0]] # select input label that was requested
toRadians = math.pi/180.0 if options.degrees else 1.0 # rescale degrees to radians
r = damask.Quaternion().fromAngleAxis(toRadians*options.crystalrotation[0],options.crystalrotation[1:]) # crystal frame rotation toRadians = np.pi/180.0 if options.degrees else 1.0 # rescale degrees to radians
R = damask.Quaternion().fromAngleAxis(toRadians*options. labrotation[0],options. labrotation[1:]) # lab frame rotation r = damask.Quaternion.fromAngleAxis(toRadians*options.crystalrotation[0],options.crystalrotation[1:]) # crystal frame rotation
R = damask.Quaternion.fromAngleAxis(toRadians*options. labrotation[0],options. labrotation[1:]) # lab frame rotation
# --- loop over input files ------------------------------------------------------------------------ # --- loop over input files ------------------------------------------------------------------------
@ -137,32 +169,31 @@ for name in filenames:
table.info_append(scriptID + '\t' + ' '.join(sys.argv[1:])) table.info_append(scriptID + '\t' + ' '.join(sys.argv[1:]))
for output in options.output: for output in options.output:
if output == 'quaternion': table.labels_append(['{}_{}_{}({})'.format(i+1,'quat',options.symmetry,label) for i in range(4)]) if output in outputChoices:
elif output == 'rodrigues': table.labels_append(['{}_{}_{}({})'.format(i+1,'rodr',options.symmetry,label) for i in range(3)]) table.labels_append(['{}_{}({})'.format(i+1,outputChoices[output][0],label) \
elif output == 'eulers': table.labels_append(['{}_{}_{}({})'.format(i+1,'eulr',options.symmetry,label) for i in range(3)]) for i in range(outputChoices[output][1])])
table.head_write() table.head_write()
# ------------------------------------------ process data ------------------------------------------ # ------------------------------------------ process data ------------------------------------------
outputAlive = True outputAlive = True
while outputAlive and table.data_read(): # read next data line of ASCII table while outputAlive and table.data_read(): # read next data line of ASCII table
if inputtype == 'eulers': if inputtype == 'eulers':
o = damask.Orientation(Eulers = np.array(list(map(float,table.data[column:column+3])))*toRadians,
symmetry = options.symmetry).reduced() o = damask.Orientation(Eulers = check_Eulers(np.array(list(map(float,table.data[column:column+3])))*toRadians))
elif inputtype == 'rodrigues': elif inputtype == 'rodrigues':
o = damask.Orientation(Rodrigues= np.array(list(map(float,table.data[column:column+3]))), o = damask.Orientation(Rodrigues = np.array(list(map(float,table.data[column:column+3]))))
symmetry = options.symmetry).reduced()
elif inputtype == 'matrix': elif inputtype == 'matrix':
o = damask.Orientation(matrix = np.array(list(map(float,table.data[column:column+9]))).reshape(3,3).transpose(),
symmetry = options.symmetry).reduced() o = damask.Orientation(matrix = check_matrix(np.array(list(map(float,table.data[column:column+9]))).reshape(3,3)))
elif inputtype == 'frame': elif inputtype == 'frame':
o = damask.Orientation(matrix = np.array(list(map(float,table.data[column[0]:column[0]+3] + \ M = np.array(list(map(float,table.data[column[0]:column[0]+3] + \
table.data[column[1]:column[1]+3] + \ table.data[column[1]:column[1]+3] + \
table.data[column[2]:column[2]+3]))).reshape(3,3), table.data[column[2]:column[2]+3]))).reshape(3,3).T
symmetry = options.symmetry).reduced() o = damask.Orientation(matrix = check_matrix(M/np.linalg.norm(M,axis=0)))
elif inputtype == 'quaternion': elif inputtype == 'quaternion':
o = damask.Orientation(quaternion = np.array(list(map(float,table.data[column:column+4]))),
symmetry = options.symmetry).reduced() o = damask.Orientation(quaternion = check_quaternion(np.array(list(map(float,table.data[column:column+4])))))
o.quaternion = r*o.quaternion*R # apply additional lab and crystal frame rotations o.quaternion = r*o.quaternion*R # apply additional lab and crystal frame rotations
@ -170,6 +201,8 @@ for name in filenames:
if output == 'quaternion': table.data_append(o.asQuaternion()) if output == 'quaternion': table.data_append(o.asQuaternion())
elif output == 'rodrigues': table.data_append(o.asRodrigues()) elif output == 'rodrigues': table.data_append(o.asRodrigues())
elif output == 'eulers': table.data_append(o.asEulers(degrees=options.degrees)) elif output == 'eulers': table.data_append(o.asEulers(degrees=options.degrees))
elif output == 'matrix': table.data_append(o.asMatrix())
elif output == 'angleaxis': table.data_append(o.asAngleAxis(degrees=options.degrees,flat=True))
outputAlive = table.data_write() # output processed line outputAlive = table.data_write() # output processed line
# ------------------------------------------ output finalization ----------------------------------- # ------------------------------------------ output finalization -----------------------------------

View File

@ -1,7 +1,7 @@
#!/usr/bin/env python2.7 #!/usr/bin/env python3
# -*- coding: UTF-8 no BOM -*- # -*- coding: UTF-8 no BOM -*-
import os,sys,math import os,sys
import numpy as np import numpy as np
from optparse import OptionParser from optparse import OptionParser
import damask import damask
@ -14,70 +14,32 @@ scriptID = ' '.join([scriptName,damask.version])
# -------------------------------------------------------------------- # --------------------------------------------------------------------
parser = OptionParser(option_class=damask.extendableOption, usage='%prog options [file[s]]', description = """ parser = OptionParser(option_class=damask.extendableOption, usage='%prog options [file[s]]', description = """
Add x,y coordinates of stereographic projection of given direction (pole) in crystal frame. Add coordinates of stereographic projection of given direction (pole) in crystal frame.
""", version = scriptID) """, version = scriptID)
parser.add_option('-p', '--pole', parser.add_option('-p',
'--pole',
dest = 'pole', dest = 'pole',
type = 'float', nargs = 3, metavar = 'float float float', type = 'float', nargs = 3, metavar = 'float float float',
help = 'crystal frame direction for pole figure [%default]') help = 'crystal frame direction for pole figure [%default]')
parser.add_option('--polar', parser.add_option('--polar',
dest = 'polar', dest = 'polar',
action = 'store_true', action = 'store_true',
help = 'output polar coordinates r,phi [%default]') help = 'output polar coordinates (r,φ) instead of Cartesian coordinates (x,y)')
parser.add_option('-e', '--eulers', parser.add_option('-o',
dest = 'eulers', '--orientation',
type = 'string', metavar = 'string',
help = 'Euler angles label')
parser.add_option('-d', '--degrees',
dest = 'degrees',
action = 'store_true',
help = 'Euler angles are given in degrees [%default]')
parser.add_option('-m', '--matrix',
dest = 'matrix',
type = 'string', metavar = 'string',
help = 'orientation matrix label')
parser.add_option('-a',
dest = 'a',
type = 'string', metavar = 'string',
help = 'crystal frame a vector label')
parser.add_option('-b',
dest = 'b',
type = 'string', metavar = 'string',
help = 'crystal frame b vector label')
parser.add_option('-c',
dest = 'c',
type = 'string', metavar = 'string',
help = 'crystal frame c vector label')
parser.add_option('-q', '--quaternion',
dest = 'quaternion', dest = 'quaternion',
type = 'string', metavar = 'string', metavar = 'string',
help = 'quaternion label') help = 'label of crystal orientation given as unit quaternion [%default]')
parser.set_defaults(pole = (1.0,0.0,0.0), parser.set_defaults(pole = (1.0,0.0,0.0),
degrees = False, quaternion = 'orientation',
polar = False, polar = False,
) )
(options, filenames) = parser.parse_args() (options, filenames) = parser.parse_args()
input = [options.eulers is not None,
options.a is not None and \
options.b is not None and \
options.c is not None,
options.matrix is not None,
options.quaternion is not None,
]
if np.sum(input) != 1: parser.error('needs exactly one input format.')
(label,dim,inputtype) = [(options.eulers,3,'eulers'),
([options.a,options.b,options.c],[3,3,3],'frame'),
(options.matrix,9,'matrix'),
(options.quaternion,4,'quaternion'),
][np.where(input)[0][0]] # select input label that was requested
toRadians = math.pi/180.0 if options.degrees else 1.0 # rescale degrees to radians
pole = np.array(options.pole) pole = np.array(options.pole)
pole /= np.linalg.norm(pole) pole /= np.linalg.norm(pole)
@ -98,18 +60,13 @@ for name in filenames:
# ------------------------------------------ sanity checks ---------------------------------------- # ------------------------------------------ sanity checks ----------------------------------------
errors = [] if not table.label_dimension(options.quaternion) == 4:
remarks = [] damask.util.croak('input {} does not have dimension 4.'.format(options.quaternion))
table.close(dismiss = True) # close ASCIItable and remove empty file
if not np.all(table.label_dimension(label) == dim): errors.append('input {} does not have dimension {}.'.format(label,dim))
else: column = table.label_index(label)
if remarks != []: damask.util.croak(remarks)
if errors != []:
damask.util.croak(errors)
table.close(dismiss = True)
continue continue
column = table.label_index(options.quaternion)
# ------------------------------------------ assemble header --------------------------------------- # ------------------------------------------ assemble header ---------------------------------------
table.info_append(scriptID + '\t' + ' '.join(sys.argv[1:])) table.info_append(scriptID + '\t' + ' '.join(sys.argv[1:]))
@ -119,16 +76,7 @@ for name in filenames:
# ------------------------------------------ process data ------------------------------------------ # ------------------------------------------ process data ------------------------------------------
outputAlive = True outputAlive = True
while outputAlive and table.data_read(): # read next data line of ASCII table while outputAlive and table.data_read(): # read next data line of ASCII table
if inputtype == 'eulers': o = damask.Orientation(quaternion = np.array(list(map(float,table.data[column:column+4]))))
o = damask.Orientation(Eulers = np.array(list(map(float,table.data[column:column+3])))*toRadians)
elif inputtype == 'matrix':
o = damask.Orientation(matrix = np.array(list(map(float,table.data[column:column+9]))).reshape(3,3).transpose())
elif inputtype == 'frame':
o = damask.Orientation(matrix = np.array(list(map(float,table.data[column[0]:column[0]+3] + \
table.data[column[1]:column[1]+3] + \
table.data[column[2]:column[2]+3]))).reshape(3,3))
elif inputtype == 'quaternion':
o = damask.Orientation(quaternion = np.array(list(map(float,table.data[column:column+4]))))
rotatedPole = o.quaternion*pole # rotate pole according to crystal orientation rotatedPole = o.quaternion*pole # rotate pole according to crystal orientation
(x,y) = rotatedPole[0:2]/(1.+abs(pole[2])) # stereographic projection (x,y) = rotatedPole[0:2]/(1.+abs(pole[2])) # stereographic projection

View File

@ -109,64 +109,42 @@ Add columns listing Schmid factors (and optional trace vector of selected system
""", version = scriptID) """, version = scriptID)
latticeChoices = ('fcc','bcc','hex') latticeChoices = ('fcc','bcc','hex')
parser.add_option('-l','--lattice', parser.add_option('-l',
'--lattice',
dest = 'lattice', type = 'choice', choices = latticeChoices, metavar='string', dest = 'lattice', type = 'choice', choices = latticeChoices, metavar='string',
help = 'type of lattice structure [%default] {}'.format(latticeChoices)) help = 'type of lattice structure [%default] {}'.format(latticeChoices))
parser.add_option('--covera', parser.add_option('--covera',
dest = 'CoverA', type = 'float', metavar = 'float', dest = 'CoverA', type = 'float', metavar = 'float',
help = 'C over A ratio for hexagonal systems') help = 'C over A ratio for hexagonal systems')
parser.add_option('-f', '--force', parser.add_option('-f',
'--force',
dest = 'force', dest = 'force',
type = 'float', nargs = 3, metavar = 'float float float', type = 'float', nargs = 3, metavar = 'float float float',
help = 'force direction in lab frame [%default]') help = 'force direction in lab frame [%default]')
parser.add_option('-n', '--normal', parser.add_option('-n',
'--normal',
dest = 'normal', dest = 'normal',
type = 'float', nargs = 3, metavar = 'float float float', type = 'float', nargs = 3, metavar = 'float float float',
help = 'stress plane normal in lab frame [%default]') help = 'stress plane normal in lab frame, per default perpendicular to the force')
parser.add_option('-e', '--eulers', parser.add_option('-o',
dest = 'eulers', '--orientation',
type = 'string', metavar = 'string',
help = 'Euler angles label')
parser.add_option('-d', '--degrees',
dest = 'degrees',
action = 'store_true',
help = 'Euler angles are given in degrees [%default]')
parser.add_option('-m', '--matrix',
dest = 'matrix',
type = 'string', metavar = 'string',
help = 'orientation matrix label')
parser.add_option('-a',
dest = 'a',
type = 'string', metavar = 'string',
help = 'crystal frame a vector label')
parser.add_option('-b',
dest = 'b',
type = 'string', metavar = 'string',
help = 'crystal frame b vector label')
parser.add_option('-c',
dest = 'c',
type = 'string', metavar = 'string',
help = 'crystal frame c vector label')
parser.add_option('-q', '--quaternion',
dest = 'quaternion', dest = 'quaternion',
type = 'string', metavar = 'string', metavar = 'string',
help = 'quaternion label') help = 'label of crystal orientation given as unit quaternion [%default]')
parser.set_defaults(force = (0.0,0.0,1.0), parser.set_defaults(force = (0.0,0.0,1.0),
quaternion='orientation',
normal = None, normal = None,
lattice = latticeChoices[0], lattice = latticeChoices[0],
CoverA = math.sqrt(8./3.), CoverA = math.sqrt(8./3.),
degrees = False,
) )
(options, filenames) = parser.parse_args() (options, filenames) = parser.parse_args()
toRadians = math.pi/180.0 if options.degrees else 1.0 # rescale degrees to radians
force = np.array(options.force) force = np.array(options.force)
force /= np.linalg.norm(force) force /= np.linalg.norm(force)
if options.normal: if options.normal is not None:
normal = np.array(options.normal) normal = np.array(options.normal)
normal /= np.linalg.norm(normal) normal /= np.linalg.norm(normal)
if abs(np.dot(force,normal)) > 1e-3: if abs(np.dot(force,normal)) > 1e-3:
@ -174,22 +152,6 @@ if options.normal:
else: else:
normal = force normal = force
input = [options.eulers is not None,
options.a is not None and \
options.b is not None and \
options.c is not None,
options.matrix is not None,
options.quaternion is not None,
]
if np.sum(input) != 1: parser.error('needs exactly one input format.')
(label,dim,inputtype) = [(options.eulers,3,'eulers'),
([options.a,options.b,options.c],[3,3,3],'frame'),
(options.matrix,9,'matrix'),
(options.quaternion,4,'quaternion'),
][np.where(input)[0][0]] # select input label that was requested
slip_direction = np.zeros((len(slipSystems[options.lattice]),3),'f') slip_direction = np.zeros((len(slipSystems[options.lattice]),3),'f')
slip_normal = np.zeros_like(slip_direction) slip_normal = np.zeros_like(slip_direction)
@ -227,13 +189,12 @@ for name in filenames:
table.head_read() table.head_read()
# ------------------------------------------ sanity checks ---------------------------------------- # ------------------------------------------ sanity checks ----------------------------------------
if not table.label_dimension(options.quaternion) == 4:
if not np.all(table.label_dimension(label) == dim): damask.util.croak('input {} does not have dimension 4.'.format(options.quaternion))
damask.util.croak('input {} does not have dimension {}.'.format(label,dim))
table.close(dismiss = True) # close ASCIItable and remove empty file table.close(dismiss = True) # close ASCIItable and remove empty file
continue continue
column = table.label_index(label) column = table.label_index(options.quaternion)
# ------------------------------------------ assemble header --------------------------------------- # ------------------------------------------ assemble header ---------------------------------------
@ -251,17 +212,7 @@ for name in filenames:
outputAlive = True outputAlive = True
while outputAlive and table.data_read(): # read next data line of ASCII table while outputAlive and table.data_read(): # read next data line of ASCII table
if inputtype == 'eulers': o = damask.Orientation(quaternion = np.array(list(map(float,table.data[column:column+4]))))
o = damask.Orientation(Eulers = np.array(list(map(float,table.data[column:column+3])))*toRadians,)
elif inputtype == 'matrix':
o = damask.Orientation(matrix = np.array(list(map(float,table.data[column:column+9]))).reshape(3,3).transpose(),)
elif inputtype == 'frame':
o = damask.Orientation(matrix = np.array(list(map(float,table.data[column[0]:column[0]+3] + \
table.data[column[1]:column[1]+3] + \
table.data[column[2]:column[2]+3]))).reshape(3,3),)
elif inputtype == 'quaternion':
o = damask.Orientation(quaternion = np.array(list(map(float,table.data[column:column+4]))),)
table.data_append( np.abs( np.sum(slip_direction * (o.quaternion * force) ,axis=1) \ table.data_append( np.abs( np.sum(slip_direction * (o.quaternion * force) ,axis=1) \
* np.sum(slip_normal * (o.quaternion * normal),axis=1))) * np.sum(slip_normal * (o.quaternion * normal),axis=1)))

View File

@ -1,4 +1,4 @@
#!/usr/bin/env python2.7 #!/usr/bin/env python3
# -*- coding: UTF-8 no BOM -*- # -*- coding: UTF-8 no BOM -*-
import os,sys import os,sys
@ -118,10 +118,9 @@ for name in filenames:
minmax[c] = np.log(minmax[c]) # change minmax to log, too minmax[c] = np.log(minmax[c]) # change minmax to log, too
delta = minmax[:,1]-minmax[:,0] delta = minmax[:,1]-minmax[:,0]
(grid,xedges,yedges) = np.histogram2d(table.data[:,0],table.data[:,1], (grid,xedges,yedges) = np.histogram2d(table.data[:,0],table.data[:,1],
bins=options.bins, bins=options.bins,
range=minmax, range=minmax[:2],
weights=None if options.weight is None else table.data[:,2]) weights=None if options.weight is None else table.data[:,2])
if options.normCol: if options.normCol:

View File

@ -121,12 +121,8 @@ class MPIEspectral_result: # mimic py_post result object
self._logscales = self._keyedPackedArray('logscales',count=self.N_loadcases,type='i') self._logscales = self._keyedPackedArray('logscales',count=self.N_loadcases,type='i')
self.size = self._keyedPackedArray('size:',count=3,type='d') self.size = self._keyedPackedArray('size:',count=3,type='d')
if self.size == [None,None,None]: # no 'size' found, try legacy alias 'dimension'
self.size = self._keyedPackedArray('dimension',count=3,type='d')
self.grid = self._keyedPackedArray('grid:',count=3,type='i') self.grid = self._keyedPackedArray('grid:',count=3,type='i')
if self.grid == [None,None,None]: # no 'grid' found, try legacy alias 'resolution'
self.grid = self._keyedPackedArray('resolution',count=3,type='i')
self.N_nodes = (self.grid[0]+1)*(self.grid[1]+1)*(self.grid[2]+1) self.N_nodes = (self.grid[0]+1)*(self.grid[1]+1)*(self.grid[2]+1)
self.N_elements = self.grid[0] * self.grid[1] * self.grid[2] self.N_elements = self.grid[0] * self.grid[1] * self.grid[2]
@ -142,13 +138,8 @@ class MPIEspectral_result: # mimic py_post result object
# parameters for file handling depending on output format # parameters for file handling depending on output format
if options.legacy: self.tagLen=0
self.tagLen=8
self.fourByteLimit = 2**31 -1 -8
else:
self.tagLen=0
self.expectedFileSize = self.dataOffset+self.N_increments*(self.tagLen+self.N_elements*self.N_element_scalars*8) self.expectedFileSize = self.dataOffset+self.N_increments*(self.tagLen+self.N_elements*self.N_element_scalars*8)
if options.legacy: self.expectedFileSize+=self.expectedFileSize//self.fourByteLimit*8 # add extra 8 bytes for additional headers at 4 GB limits
if self.expectedFileSize != self.filesize: if self.expectedFileSize != self.filesize:
print('\n**\n* Unexpected file size. Incomplete simulation or file corrupted!\n**') print('\n**\n* Unexpected file size. Incomplete simulation or file corrupted!\n**')
@ -280,42 +271,16 @@ class MPIEspectral_result: # mimic py_post result object
return self.N_element_scalars return self.N_element_scalars
def element_scalar(self,e,idx): def element_scalar(self,e,idx):
if not options.legacy: incStart = self.dataOffset \
incStart = self.dataOffset \ + self.position*8*self.N_elements*self.N_element_scalars
+ self.position*8*self.N_elements*self.N_element_scalars where = (e*self.N_element_scalars + idx)*8
where = (e*self.N_element_scalars + idx)*8 try:
try: self.file.seek(incStart+where)
self.file.seek(incStart+where) value = struct.unpack('d',self.file.read(8))[0]
value = struct.unpack('d',self.file.read(8))[0] except:
except: print('seeking {}'.format(incStart+where))
print('seeking {}'.format(incStart+where)) print('e {} idx {}'.format(e,idx))
print('e {} idx {}'.format(e,idx)) sys.exit(1)
sys.exit(1)
else:
self.fourByteLimit = 2**31 -1 -8
# header & footer + extra header and footer for 4 byte int range (Fortran)
# values
incStart = self.dataOffset \
+ self.position*8*( 1 + self.N_elements*self.N_element_scalars*8//self.fourByteLimit \
+ self.N_elements*self.N_element_scalars)
where = (e*self.N_element_scalars + idx)*8
try:
if where%self.fourByteLimit + 8 >= self.fourByteLimit: # danger of reading into fortran record footer at 4 byte limit
data=''
for i in range(8):
self.file.seek(incStart+where+(where//self.fourByteLimit)*8+4)
data += self.file.read(1)
where += 1
value = struct.unpack('d',data)[0]
else:
self.file.seek(incStart+where+(where//self.fourByteLimit)*8+4)
value = struct.unpack('d',self.file.read(8))[0]
except:
print('seeking {}'.format(incStart+where+(where//self.fourByteLimit)*8+4))
print('e {} idx {}'.format(e,idx))
sys.exit(1)
return [elemental_scalar(node,value) for node in self.element(e).items] return [elemental_scalar(node,value) for node in self.element(e).items]
@ -645,8 +610,6 @@ of already processed data points for evaluation.
parser.add_option('-i','--info', action='store_true', dest='info', parser.add_option('-i','--info', action='store_true', dest='info',
help='list contents of resultfile') help='list contents of resultfile')
parser.add_option('-l','--legacy', action='store_true', dest='legacy',
help='data format of spectral solver is in legacy format (no MPI out)')
parser.add_option('-n','--nodal', action='store_true', dest='nodal', parser.add_option('-n','--nodal', action='store_true', dest='nodal',
help='data is extrapolated to nodal value') help='data is extrapolated to nodal value')
parser.add_option( '--prefix', dest='prefix', parser.add_option( '--prefix', dest='prefix',
@ -673,10 +636,7 @@ parser.add_option('-p','--type', dest='filetype',
help = 'type of result file [auto]') help = 'type of result file [auto]')
parser.add_option('-q','--quiet', dest='verbose', parser.add_option('-q','--quiet', dest='verbose',
action = 'store_false', action = 'store_false',
help = 'suppress verbose output') help = 'hide status bar (useful when piping to file)')
parser.add_option('--verbose', dest='verbose',
action = 'store_true',
help = 'enable verbose output')
group_material = OptionGroup(parser,'Material identifier') group_material = OptionGroup(parser,'Material identifier')
@ -718,9 +678,8 @@ parser.add_option_group(group_general)
parser.add_option_group(group_special) parser.add_option_group(group_special)
parser.set_defaults(info = False, parser.set_defaults(info = False,
verbose = False,
legacy = False,
nodal = False, nodal = False,
verbose = True,
prefix = '', prefix = '',
suffix = '', suffix = '',
dir = 'postProc', dir = 'postProc',
@ -747,6 +706,8 @@ if files == []:
parser.print_help() parser.print_help()
parser.error('no file specified...') parser.error('no file specified...')
damask.util.report(scriptName,files[0])
if not os.path.exists(files[0]): if not os.path.exists(files[0]):
parser.print_help() parser.print_help()
parser.error('invalid file "%s" specified...'%files[0]) parser.error('invalid file "%s" specified...'%files[0])
@ -803,12 +764,6 @@ if not options.constitutiveResult: options.constitutiveResult = []
options.sort.reverse() options.sort.reverse()
options.sep.reverse() options.sep.reverse()
# --- start background messaging
if options.verbose:
bg = damask.util.backgroundMessage()
bg.start()
# --- parse .output and .t16 files # --- parse .output and .t16 files
if os.path.splitext(files[0])[1] == '': if os.path.splitext(files[0])[1] == '':
@ -825,18 +780,13 @@ me = {
'Constitutive': options.phase, 'Constitutive': options.phase,
} }
if options.verbose: bg.set_message('parsing .output files...')
for what in me: for what in me:
outputFormat[what] = ParseOutputFormat(filename, what, me[what]) outputFormat[what] = ParseOutputFormat(filename, what, me[what])
if '_id' not in outputFormat[what]['specials']: if '_id' not in outputFormat[what]['specials']:
print("\nsection '{}' not found in <{}>".format(me[what], what)) print("\nsection '{}' not found in <{}>".format(me[what], what))
print('\n'.join(map(lambda x:' [%s]'%x, outputFormat[what]['specials']['brothers']))) print('\n'.join(map(lambda x:' [%s]'%x, outputFormat[what]['specials']['brothers'])))
if options.verbose: bg.set_message('opening result file...')
p = OpenPostfile(filename+extension,options.filetype,options.nodal) p = OpenPostfile(filename+extension,options.filetype,options.nodal)
if options.verbose: bg.set_message('parsing result file...')
stat = ParsePostfile(p, filename, outputFormat) stat = ParsePostfile(p, filename, outputFormat)
if options.filetype == 'marc': if options.filetype == 'marc':
stat['NumberOfIncrements'] -= 1 # t16 contains one "virtual" increment (at 0) stat['NumberOfIncrements'] -= 1 # t16 contains one "virtual" increment (at 0)
@ -879,8 +829,10 @@ if options.info:
# --- build connectivity maps # --- build connectivity maps
elementsOfNode = {} elementsOfNode = {}
for e in range(stat['NumberOfElements']): Nelems = stat['NumberOfElements']
if options.verbose and e%1000 == 0: bg.set_message('connect elem %i...'%e) for e in range(Nelems):
if options.verbose and Nelems > 100 and e%(Nelems//100) == 0: # report in 1% steps if possible and avoid modulo by zero
damask.util.progressBar(iteration=e,total=Nelems,prefix='1/3: connecting elements')
for n in map(p.node_sequence,p.element(e).items): for n in map(p.node_sequence,p.element(e).items):
if n not in elementsOfNode: if n not in elementsOfNode:
elementsOfNode[n] = [p.element_id(e)] elementsOfNode[n] = [p.element_id(e)]
@ -899,10 +851,13 @@ index = {}
groups = [] groups = []
groupCount = 0 groupCount = 0
memberCount = 0 memberCount = 0
damask.util.progressBar(iteration=1,total=1,prefix='1/3: connecting elements')
if options.nodalScalar: if options.nodalScalar:
for n in range(stat['NumberOfNodes']): Npoints = stat['NumberOfNodes']
if options.verbose and n%1000 == 0: bg.set_message('scan node %i...'%n) for n in range(Npoints):
if options.verbose and Npoints > 100 and e%(Npoints//100) == 0: # report in 1% steps if possible and avoid modulo by zero
damask.util.progressBar(iteration=n,total=Npoints,prefix='2/3: scanning nodes ')
myNodeID = p.node_id(n) myNodeID = p.node_id(n)
myNodeCoordinates = [p.node(n).x, p.node(n).y, p.node(n).z] myNodeCoordinates = [p.node(n).x, p.node(n).y, p.node(n).z]
myElemID = 0 myElemID = 0
@ -911,32 +866,35 @@ if options.nodalScalar:
# generate an expression that is only true for the locations specified by options.filter # generate an expression that is only true for the locations specified by options.filter
filter = substituteLocation(options.filter, [myElemID,myNodeID,myIpID,myGrainID], myNodeCoordinates) filter = substituteLocation(options.filter, [myElemID,myNodeID,myIpID,myGrainID], myNodeCoordinates)
if filter != '' and not eval(filter): # for all filter expressions that are not true:... if filter != '' and not eval(filter): # for all filter expressions that are not true:...
continue # ... ignore this data point and continue with next continue # ... ignore this data point and continue with next
# --- group data locations # --- group data locations
# generate a unique key for a group of separated data based on the separation criterium for the location # generate a unique key for a group of separated data based on the separation criterium for the location
grp = substituteLocation('#'.join(options.sep), [myElemID,myNodeID,myIpID,myGrainID], myNodeCoordinates) grp = substituteLocation('#'.join(options.sep), [myElemID,myNodeID,myIpID,myGrainID], myNodeCoordinates)
if grp not in index: # create a new group if not yet present if grp not in index: # create a new group if not yet present
index[grp] = groupCount index[grp] = groupCount
groups.append([[0,0,0,0,0.0,0.0,0.0]]) # initialize with avg location groups.append([[0,0,0,0,0.0,0.0,0.0]]) # initialize with avg location
groupCount += 1 groupCount += 1
groups[index[grp]][0][:4] = mapIncremental('','unique', groups[index[grp]][0][:4] = mapIncremental('','unique',
len(groups[index[grp]])-1, len(groups[index[grp]])-1,
groups[index[grp]][0][:4], groups[index[grp]][0][:4],
[myElemID,myNodeID,myIpID,myGrainID]) # keep only if unique average location [myElemID,myNodeID,myIpID,myGrainID]) # keep only if unique average location
groups[index[grp]][0][4:] = mapIncremental('','avg', groups[index[grp]][0][4:] = mapIncremental('','avg',
len(groups[index[grp]])-1, len(groups[index[grp]])-1,
groups[index[grp]][0][4:], groups[index[grp]][0][4:],
myNodeCoordinates) # incrementally update average location myNodeCoordinates) # incrementally update average location
groups[index[grp]].append([myElemID,myNodeID,myIpID,myGrainID,0]) # append a new list defining each group member groups[index[grp]].append([myElemID,myNodeID,myIpID,myGrainID,0]) # append a new list defining each group member
memberCount += 1 memberCount += 1
damask.util.progressBar(iteration=1,total=1,prefix='2/3: scanning nodes ')
else: else:
for e in range(stat['NumberOfElements']): Nelems = stat['NumberOfElements']
if options.verbose and e%1000 == 0: bg.set_message('scan elem %i...'%e) for e in range(Nelems):
if options.verbose and Nelems > 100 and e%(Nelems//100) == 0: # report in 1% steps if possible and avoid modulo by zero
damask.util.progressBar(iteration=e,total=Nelems,prefix='2/3: scanning elements ')
myElemID = p.element_id(e) myElemID = p.element_id(e)
myIpCoordinates = ipCoords(p.element(e).type, list(map(lambda node: [node.x, node.y, node.z], myIpCoordinates = ipCoords(p.element(e).type, list(map(lambda node: [node.x, node.y, node.z],
list(map(p.node, map(p.node_sequence, p.element(e).items)))))) list(map(p.node, map(p.node_sequence, p.element(e).items))))))
@ -976,6 +934,7 @@ else:
myIpCoordinates[n]) # incrementally update average location myIpCoordinates[n]) # incrementally update average location
groups[index[grp]].append([myElemID,myNodeID,myIpID,myGrainID,n]) # append a new list defining each group member groups[index[grp]].append([myElemID,myNodeID,myIpID,myGrainID,n]) # append a new list defining each group member
memberCount += 1 memberCount += 1
damask.util.progressBar(iteration=1,total=1,prefix='2/3: scanning elements ')
# --------------------------- sort groups -------------------------------- # --------------------------- sort groups --------------------------------
@ -1002,7 +961,6 @@ if 'none' not in map(str.lower, options.sort):
theKeys.append('x[0][%i]'%where[criterium]) theKeys.append('x[0][%i]'%where[criterium])
sortKeys = eval('lambda x:(%s)'%(','.join(theKeys))) sortKeys = eval('lambda x:(%s)'%(','.join(theKeys)))
if options.verbose: bg.set_message('sorting groups...')
groups.sort(key = sortKeys) # in-place sorting to save mem groups.sort(key = sortKeys) # in-place sorting to save mem
@ -1021,8 +979,6 @@ standard = ['inc'] + \
# --------------------------- loop over positions -------------------------------- # --------------------------- loop over positions --------------------------------
if options.verbose: bg.set_message('getting map between positions and increments...')
incAtPosition = {} incAtPosition = {}
positionOfInc = {} positionOfInc = {}
@ -1048,8 +1004,8 @@ increments = [incAtPosition[x] for x in locations] # build list of increments to
time_start = time.time() time_start = time.time()
Nincs = len([i for i in locations])
for incCount,position in enumerate(locations): # walk through locations for incCount,position in enumerate(locations): # walk through locations
p.moveto(position+offset_pos) # wind to correct position p.moveto(position+offset_pos) # wind to correct position
# --------------------------- file management -------------------------------- # --------------------------- file management --------------------------------
@ -1075,16 +1031,14 @@ for incCount,position in enumerate(locations): # walk through locations
# --------------------------- read and map data per group -------------------------------- # --------------------------- read and map data per group --------------------------------
member = 0 member = 0
for group in groups: Ngroups = len(groups)
for j,group in enumerate(groups):
f = incCount*Ngroups + j
if options.verbose and (Ngroups*Nincs) > 100 and f%((Ngroups*Nincs)//100) == 0: # report in 1% steps if possible and avoid modulo by zero
damask.util.progressBar(iteration=f,total=Ngroups*Nincs,prefix='3/3: processing points ')
N = 0 # group member counter N = 0 # group member counter
for (e,n,i,g,n_local) in group[1:]: # loop over group members for (e,n,i,g,n_local) in group[1:]: # loop over group members
member += 1 member += 1
if member%1000 == 0:
time_delta = ((len(locations)*memberCount)/float(member+incCount*memberCount)-1.0)*(time.time()-time_start)
if options.verbose: bg.set_message('(%02i:%02i:%02i) processing point %i of %i from increment %i (position %i)...'
%(time_delta//3600,time_delta%3600//60,time_delta%60,member,memberCount,increments[incCount],position))
newby = [] # current member's data newby = [] # current member's data
if options.nodalScalar: if options.nodalScalar:
@ -1172,6 +1126,7 @@ for incCount,position in enumerate(locations): # walk through locations
group[0] + \ group[0] + \
mappedResult) mappedResult)
)) + '\n') )) + '\n')
damask.util.progressBar(iteration=1,total=1,prefix='3/3: processing points ')
if fileOpen: if fileOpen:
file.close() file.close()

View File

@ -18,19 +18,15 @@ Rotate vector and/or tensor column data by given angle around given axis.
""", version = scriptID) """, version = scriptID)
parser.add_option('-v','--vector', parser.add_option('-d', '--data',
dest = 'vector', dest = 'data',
action = 'extend', metavar = '<string LIST>', action = 'extend', metavar = '<string LIST>',
help = 'column heading of vector(s) to rotate') help = 'vector/tensor value(s) label(s)')
parser.add_option('-t','--tensor',
dest = 'tensor',
action = 'extend', metavar = '<string LIST>',
help = 'column heading of tensor(s) to rotate')
parser.add_option('-r', '--rotation', parser.add_option('-r', '--rotation',
dest = 'rotation', dest = 'rotation',
type = 'float', nargs = 4, metavar = ' '.join(['float']*4), type = 'float', nargs = 4, metavar = ' '.join(['float']*4),
help = 'angle and axis to rotate data [%default]') help = 'angle and axis to rotate data [%default]')
parser.add_option('-d', '--degrees', parser.add_option('--degrees',
dest = 'degrees', dest = 'degrees',
action = 'store_true', action = 'store_true',
help = 'angles are given in degrees [%default]') help = 'angles are given in degrees [%default]')
@ -41,7 +37,7 @@ parser.set_defaults(rotation = (0.,1.,1.,1.),
(options,filenames) = parser.parse_args() (options,filenames) = parser.parse_args()
if options.vector is None and options.tensor is None: if options.data is None:
parser.error('no data column specified.') parser.error('no data column specified.')
toRadians = math.pi/180.0 if options.degrees else 1.0 # rescale degrees to radians toRadians = math.pi/180.0 if options.degrees else 1.0 # rescale degrees to radians
@ -59,27 +55,24 @@ for name in filenames:
except: continue except: continue
damask.util.report(scriptName,name) damask.util.report(scriptName,name)
# ------------------------------------------ read header ------------------------------------------ # --- interpret header ----------------------------------------------------------------------------
table.head_read() table.head_read()
# ------------------------------------------ sanity checks ----------------------------------------
items = {
'tensor': {'dim': 9, 'shape': [3,3], 'labels':options.tensor, 'active':[], 'column': []},
'vector': {'dim': 3, 'shape': [3], 'labels':options.vector, 'active':[], 'column': []},
}
errors = [] errors = []
remarks = [] remarks = []
column = {} active = {'vector':[],'tensor':[]}
for type, data in items.items(): for i,dim in enumerate(table.label_dimension(options.data)):
for what in data['labels']: label = options.data[i]
dim = table.label_dimension(what) if dim == -1:
if dim != data['dim']: remarks.append('column {} is not a {}.'.format(what,type)) remarks.append('"{}" not found...'.format(label))
else: elif dim == 3:
items[type]['active'].append(what) remarks.append('adding vector "{}"...'.format(label))
items[type]['column'].append(table.label_index(what)) active['vector'].append(label)
elif dim == 9:
remarks.append('adding tensor "{}"...'.format(label))
active['tensor'].append(label)
if remarks != []: damask.util.croak(remarks) if remarks != []: damask.util.croak(remarks)
if errors != []: if errors != []:
@ -95,20 +88,14 @@ for name in filenames:
# ------------------------------------------ process data ------------------------------------------ # ------------------------------------------ process data ------------------------------------------
outputAlive = True outputAlive = True
while outputAlive and table.data_read(): # read next data line of ASCII table while outputAlive and table.data_read(): # read next data line of ASCII table
for v in active['vector']:
datatype = 'vector' column = table.label_index(v)
table.data[column:column+3] = q * np.array(list(map(float,table.data[column:column+3])))
for column in items[datatype]['column']: # loop over all requested labels for t in active['tensor']:
table.data[column:column+items[datatype]['dim']] = \ column = table.label_index(t)
q * np.array(list(map(float,table.data[column:column+items[datatype]['dim']]))) table.data[column:column+9] = \
np.dot(R,np.dot(np.array(list(map(float,table.data[column:column+9]))).reshape((3,3)),
datatype = 'tensor' R.transpose())).reshape((9))
for column in items[datatype]['column']: # loop over all requested labels
table.data[column:column+items[datatype]['dim']] = \
np.dot(R,np.dot(np.array(list(map(float,table.data[column:column+items[datatype]['dim']]))).\
reshape(items[datatype]['shape']),R.transpose())).reshape(items[datatype]['dim'])
outputAlive = table.data_write() # output processed line outputAlive = table.data_write() # output processed line
# ------------------------------------------ output finalization ----------------------------------- # ------------------------------------------ output finalization -----------------------------------

View File

@ -64,11 +64,11 @@ if options.dimension is None:
parser.error('no dimension specified.') parser.error('no dimension specified.')
if options.angleaxis is not None: if options.angleaxis is not None:
options.angleaxis = list(map(float,options.angleaxis)) options.angleaxis = list(map(float,options.angleaxis))
rotation = damask.Quaternion().fromAngleAxis(np.radians(options.angleaxis[0]) if options.degrees else options.angleaxis[0], rotation = damask.Quaternion.fromAngleAxis(np.radians(options.angleaxis[0]) if options.degrees else options.angleaxis[0],
options.angleaxis[1:4]) options.angleaxis[1:4])
elif options.quaternion is not None: elif options.quaternion is not None:
options.quaternion = map(float,options.quaternion) options.quaternion = list(map(float,options.quaternion))
rotation = damask.Quaternion(options.quaternion) rotation = damask.Quaternion(quat=options.quaternion)
else: else:
rotation = damask.Quaternion() rotation = damask.Quaternion()

View File

@ -43,7 +43,7 @@ parser.add_option('-e', '--eulers',
parser.add_option('-d', '--degrees', parser.add_option('-d', '--degrees',
dest = 'degrees', dest = 'degrees',
action = 'store_true', action = 'store_true',
help = 'angles are given in degrees [%default]') help = 'all angles are in degrees')
parser.add_option('-m', '--matrix', parser.add_option('-m', '--matrix',
dest = 'matrix', dest = 'matrix',
type = 'string', metavar = 'string', type = 'string', metavar = 'string',
@ -71,7 +71,7 @@ parser.add_option('--axes',
parser.add_option('-s', '--symmetry', parser.add_option('-s', '--symmetry',
dest = 'symmetry', dest = 'symmetry',
action = 'extend', metavar = '<string LIST>', action = 'extend', metavar = '<string LIST>',
help = 'crystal symmetry %default {{{}}} '.format(', '.join(damask.Symmetry.lattices[1:]))) help = 'crystal symmetry of each phase %default {{{}}} '.format(', '.join(damask.Symmetry.lattices[1:])))
parser.add_option('--homogenization', parser.add_option('--homogenization',
dest = 'homogenization', dest = 'homogenization',
type = 'int', metavar = 'int', type = 'int', metavar = 'int',
@ -234,7 +234,7 @@ for name in filenames:
o = damask.Orientation(Eulers = myData[colOri:colOri+3]*toRadians, o = damask.Orientation(Eulers = myData[colOri:colOri+3]*toRadians,
symmetry = mySym) symmetry = mySym)
elif inputtype == 'matrix': elif inputtype == 'matrix':
o = damask.Orientation(matrix = myData[colOri:colOri+9].reshape(3,3).transpose(), o = damask.Orientation(matrix = myData[colOri:colOri+9].reshape(3,3),
symmetry = mySym) symmetry = mySym)
elif inputtype == 'frame': elif inputtype == 'frame':
o = damask.Orientation(matrix = np.hstack((myData[colOri[0]:colOri[0]+3], o = damask.Orientation(matrix = np.hstack((myData[colOri[0]:colOri[0]+3],
@ -246,7 +246,7 @@ for name in filenames:
o = damask.Orientation(quaternion = myData[colOri:colOri+4], o = damask.Orientation(quaternion = myData[colOri:colOri+4],
symmetry = mySym) symmetry = mySym)
cos_disorientations = -np.ones(1,dtype='f') # largest possible disorientation cos_disorientations = -np.ones(1,dtype=float) # largest possible disorientation
closest_grain = -1 # invalid neighbor closest_grain = -1 # invalid neighbor
if options.tolerance > 0.0: # only try to compress orientations if asked to if options.tolerance > 0.0: # only try to compress orientations if asked to
@ -258,7 +258,7 @@ for name in filenames:
if len(grains) > 0: # check immediate neighborhood first if len(grains) > 0: # check immediate neighborhood first
cos_disorientations = np.array([o.disorientation(orientations[grainID], cos_disorientations = np.array([o.disorientation(orientations[grainID],
SST = False)[0].quaternion.w \ SST = False)[0].quaternion.q \
for grainID in grains]) # store disorientation per grainID for grainID in grains]) # store disorientation per grainID
closest_grain = np.argmax(cos_disorientations) # grain among grains with closest orientation to myself closest_grain = np.argmax(cos_disorientations) # grain among grains with closest orientation to myself
match = 'local' match = 'local'
@ -269,7 +269,7 @@ for name in filenames:
if len(grains) > 0: if len(grains) > 0:
cos_disorientations = np.array([o.disorientation(orientations[grainID], cos_disorientations = np.array([o.disorientation(orientations[grainID],
SST = False)[0].quaternion.w \ SST = False)[0].quaternion.q \
for grainID in grains]) # store disorientation per grainID for grainID in grains]) # store disorientation per grainID
closest_grain = np.argmax(cos_disorientations) # grain among grains with closest orientation to myself closest_grain = np.argmax(cos_disorientations) # grain among grains with closest orientation to myself
match = 'global' match = 'global'

View File

@ -323,12 +323,13 @@ for name in filenames:
] ]
if hasEulers: if hasEulers:
config_header += ['<texture>'] config_header += ['<texture>']
theAxes = [] if options.axes is None else ['axes\t{} {} {}'.format(*options.axes)]
for ID in grainIDs: for ID in grainIDs:
eulerID = np.nonzero(grains == ID)[0][0] # find first occurrence of this grain id eulerID = np.nonzero(grains == ID)[0][0] # find first occurrence of this grain id
config_header += ['[Grain{}]'.format(str(ID).zfill(formatwidth)), config_header += ['[Grain{}]'.format(str(ID).zfill(formatwidth)),
'(gauss)\tphi1 {:g}\tPhi {:g}\tphi2 {:g}\tscatter 0.0\tfraction 1.0'.format(*eulers[eulerID]) '(gauss)\tphi1 {:g}\tPhi {:g}\tphi2 {:g}\tscatter 0.0\tfraction 1.0'.format(*eulers[eulerID])
] ] + theAxes
if options.axes is not None: config_header.append('axes\t{} {} {}'.format(*options.axes)) config_header += ['<!skip>']
table.labels_clear() table.labels_clear()
table.info_clear() table.info_clear()

View File

@ -60,8 +60,6 @@ eulers = np.array(damask.orientation.Orientation(
degrees = options.degrees, degrees = options.degrees,
).asEulers(degrees=True)) ).asEulers(degrees=True))
damask.util.croak('{} {} {}'.format(*eulers))
# --- loop over input files ------------------------------------------------------------------------- # --- loop over input files -------------------------------------------------------------------------
if filenames == []: filenames = [None] if filenames == []: filenames = [None]

View File

@ -244,7 +244,7 @@ for name in filenames:
continue continue
damask.util.report(scriptName,name) damask.util.report(scriptName,name)
randomSeed = int(os.urandom(4).encode('hex'), 16) if options.randomSeed is None else options.randomSeed # random seed per file for second phase randomSeed = int(os.urandom(4).hex(), 16) if options.randomSeed is None else options.randomSeed # random seed per file for second phase
random.seed(randomSeed) random.seed(randomSeed)
# ------------------------------------------ read header and data --------------------------------- # ------------------------------------------ read header and data ---------------------------------

View File

@ -191,7 +191,9 @@ recursive function IO_recursiveRead(fileName,cnt) result(fileContent)
l,i, & l,i, &
myStat myStat
if (merge(cnt,0_pInt,present(cnt))>10_pInt) call IO_error(106_pInt,ext_msg=trim(fileName)) if (present(cnt)) then
if (cnt>10_pInt) call IO_error(106_pInt,ext_msg=trim(fileName))
endif
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
! read data as stream ! read data as stream
@ -684,7 +686,11 @@ function IO_stringValue(string,chunkPos,myChunk,silent)
logical :: warn logical :: warn
warn = merge(silent,.false.,present(silent)) if (present(silent)) then
warn = silent
else
warn = .false.
endif
IO_stringValue = '' IO_stringValue = ''
valuePresent: if (myChunk > chunkPos(1) .or. myChunk < 1_pInt) then valuePresent: if (myChunk > chunkPos(1) .or. myChunk < 1_pInt) then

View File

@ -142,7 +142,7 @@ subroutine config_init()
case (trim(material_partPhase)) case (trim(material_partPhase))
call parseFile(phase_name,config_phase,line,fileContent(i+1:)) call parseFile(phase_name,config_phase,line,fileContent(i+1:))
if (iand(myDebug,debug_levelBasic) /= 0_pInt) write(6,'(a)') ' Phase parsed'; flush(6) if (iand(myDebug,debug_levelBasic) /= 0_pInt) write(6,'(a)') ' Phase parsed'; flush(6)
case (trim(material_partMicrostructure)) case (trim(material_partMicrostructure))
call parseFile(microstructure_name,config_microstructure,line,fileContent(i+1:)) call parseFile(microstructure_name,config_microstructure,line,fileContent(i+1:))
@ -150,7 +150,7 @@ subroutine config_init()
case (trim(material_partCrystallite)) case (trim(material_partCrystallite))
call parseFile(crystallite_name,config_crystallite,line,fileContent(i+1:)) call parseFile(crystallite_name,config_crystallite,line,fileContent(i+1:))
if (iand(myDebug,debug_levelBasic) /= 0_pInt) write(6,'(a)') ' Crystallite parsed'; flush(6) if (iand(myDebug,debug_levelBasic) /= 0_pInt) write(6,'(a)') ' Crystallite parsed'; flush(6)
case (trim(material_partHomogenization)) case (trim(material_partHomogenization))
call parseFile(homogenization_name,config_homogenization,line,fileContent(i+1:)) call parseFile(homogenization_name,config_homogenization,line,fileContent(i+1:))
@ -158,7 +158,7 @@ subroutine config_init()
case (trim(material_partTexture)) case (trim(material_partTexture))
call parseFile(texture_name,config_texture,line,fileContent(i+1:)) call parseFile(texture_name,config_texture,line,fileContent(i+1:))
if (iand(myDebug,debug_levelBasic) /= 0_pInt) write(6,'(a)') ' Texture parsed'; flush(6) if (iand(myDebug,debug_levelBasic) /= 0_pInt) write(6,'(a)') ' Texture parsed'; flush(6)
end select end select
@ -513,8 +513,12 @@ character(len=65536) function getString(this,key,defaultVal,raw)
type(tPartitionedStringList), pointer :: item type(tPartitionedStringList), pointer :: item
logical :: found, & logical :: found, &
whole whole
if (present(raw)) then
whole = raw
else
whole = .false.
endif
whole = merge(raw,.false.,present(raw)) ! whole string or white space splitting
found = present(defaultVal) found = present(defaultVal)
if (found) then if (found) then
getString = trim(defaultVal) getString = trim(defaultVal)
@ -661,7 +665,11 @@ function getStrings(this,key,defaultVal,requiredShape,raw)
cumulative cumulative
cumulative = (key(1:1) == '(' .and. key(len_trim(key):len_trim(key)) == ')') cumulative = (key(1:1) == '(' .and. key(len_trim(key):len_trim(key)) == ')')
whole = merge(raw,.false.,present(raw)) if (present(raw)) then
whole = raw
else
whole = .false.
endif
found = .false. found = .false.
item => this item => this

View File

@ -225,7 +225,7 @@ subroutine kinematics_thermal_expansion_LiAndItsTangent(Li, dLi_dTstar3333, ipc,
+ lattice_thermalExpansion33(1:3,1:3,2,phase)*(T - TRef)**1 & ! linear coefficient + lattice_thermalExpansion33(1:3,1:3,2,phase)*(T - TRef)**1 & ! linear coefficient
+ lattice_thermalExpansion33(1:3,1:3,3,phase)*(T - TRef)**2 & ! quadratic coefficient + lattice_thermalExpansion33(1:3,1:3,3,phase)*(T - TRef)**2 & ! quadratic coefficient
) / & ) / &
(1.0_pReal \ (1.0_pReal &
+ lattice_thermalExpansion33(1:3,1:3,1,phase)*(T - TRef)**1 / 1. & + lattice_thermalExpansion33(1:3,1:3,1,phase)*(T - TRef)**1 / 1. &
+ lattice_thermalExpansion33(1:3,1:3,2,phase)*(T - TRef)**2 / 2. & + lattice_thermalExpansion33(1:3,1:3,2,phase)*(T - TRef)**2 / 2. &
+ lattice_thermalExpansion33(1:3,1:3,3,phase)*(T - TRef)**3 / 3. & + lattice_thermalExpansion33(1:3,1:3,3,phase)*(T - TRef)**3 / 3. &

View File

@ -302,7 +302,7 @@ subroutine math_check
endif endif
end subroutine math_check end subroutine math_check
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
!> @brief Quicksort algorithm for two-dimensional integer arrays !> @brief Quicksort algorithm for two-dimensional integer arrays
@ -2625,12 +2625,9 @@ real(pReal) pure elemental function math_clip(a, left, right)
real(pReal), intent(in) :: a real(pReal), intent(in) :: a
real(pReal), intent(in), optional :: left, right real(pReal), intent(in), optional :: left, right
math_clip = a
math_clip = min ( & if (present(left)) math_clip = max(left,math_clip)
max (merge(left, -huge(a), present(left)), a), & if (present(right)) math_clip = min(right,math_clip)
merge(right, huge(a), present(right)) &
)
if (present(left) .and. present(right)) & if (present(left) .and. present(right)) &
math_clip = merge (IEEE_value(1.0_pReal,IEEE_quiet_NaN),math_clip, left>right) math_clip = merge (IEEE_value(1.0_pReal,IEEE_quiet_NaN),math_clip, left>right)

View File

@ -24,12 +24,10 @@ module plastic_phenopowerlaw
accumulatedshear_slip_ID, & accumulatedshear_slip_ID, &
shearrate_slip_ID, & shearrate_slip_ID, &
resolvedstress_slip_ID, & resolvedstress_slip_ID, &
totalshear_ID, &
resistance_twin_ID, & resistance_twin_ID, &
accumulatedshear_twin_ID, & accumulatedshear_twin_ID, &
shearrate_twin_ID, & shearrate_twin_ID, &
resolvedstress_twin_ID, & resolvedstress_twin_ID
totalvolfrac_twin_ID
end enum end enum
type, private :: tParameters type, private :: tParameters
@ -55,7 +53,7 @@ module plastic_phenopowerlaw
xi_twin_0, & !< initial critical shear stress for twin xi_twin_0, & !< initial critical shear stress for twin
xi_slip_sat, & !< maximum critical shear stress for slip xi_slip_sat, & !< maximum critical shear stress for slip
nonSchmidCoeff, & nonSchmidCoeff, &
H_int, & !< per family hardening activity (optional) !ToDo: Better name! H_int, & !< per family hardening activity (optional)
gamma_twin_char !< characteristic shear for twins gamma_twin_char !< characteristic shear for twins
real(pReal), allocatable, dimension(:,:) :: & real(pReal), allocatable, dimension(:,:) :: &
interaction_SlipSlip, & !< slip resistance from slip activity interaction_SlipSlip, & !< slip resistance from slip activity
@ -80,9 +78,6 @@ module plastic_phenopowerlaw
type(tParameters), dimension(:), allocatable, private :: param !< containers of constitutive parameters (len Ninstance) type(tParameters), dimension(:), allocatable, private :: param !< containers of constitutive parameters (len Ninstance)
type, private :: tPhenopowerlawState type, private :: tPhenopowerlawState
real(pReal), pointer, dimension(:) :: &
sumGamma, & ! ToDo: why not make a dependent state?
sumF ! ToDo: why not make a dependent state?
real(pReal), pointer, dimension(:,:) :: & real(pReal), pointer, dimension(:,:) :: &
xi_slip, & xi_slip, &
xi_twin, & xi_twin, &
@ -153,12 +148,6 @@ subroutine plastic_phenopowerlaw_init
real(pReal), dimension(0), parameter :: emptyRealArray = [real(pReal)::] real(pReal), dimension(0), parameter :: emptyRealArray = [real(pReal)::]
character(len=65536), dimension(0), parameter :: emptyStringArray = [character(len=65536)::] character(len=65536), dimension(0), parameter :: emptyStringArray = [character(len=65536)::]
type(tParameters) :: &
prm
type(tPhenopowerlawState) :: &
stt, &
dot
integer(kind(undefined_ID)) :: & integer(kind(undefined_ID)) :: &
outputID !< ID of each post result output outputID !< ID of each post result output
@ -166,7 +155,7 @@ subroutine plastic_phenopowerlaw_init
structure = '',& structure = '',&
extmsg = '' extmsg = ''
character(len=65536), dimension(:), allocatable :: & character(len=65536), dimension(:), allocatable :: &
outputs outputs
write(6,'(/,a)') ' <<<+- constitutive_'//PLASTICITY_PHENOPOWERLAW_label//' init -+>>>' write(6,'(/,a)') ' <<<+- constitutive_'//PLASTICITY_PHENOPOWERLAW_label//' init -+>>>'
write(6,'(a15,a)') ' Current time: ',IO_timeStamp() write(6,'(a15,a)') ' Current time: ',IO_timeStamp()
@ -245,8 +234,8 @@ subroutine plastic_phenopowerlaw_init
! sanity checks ! sanity checks
if (prm%gdot0_slip <= 0.0_pReal) extmsg = trim(extmsg)//'gdot0_slip ' if (prm%gdot0_slip <= 0.0_pReal) extmsg = trim(extmsg)//'gdot0_slip '
if (dEq0(prm%a_slip)) extmsg = trim(extmsg)//'a_slip ' ! ToDo: negative values ok? if (dEq0(prm%a_slip)) extmsg = trim(extmsg)//'a_slip ' ! ToDo: negative values ok?
if (dEq0(prm%n_slip)) extmsg = trim(extmsg)//'n_slip ' ! ToDo: negative values ok? if (dEq0(prm%n_slip)) extmsg = trim(extmsg)//'n_slip ' ! ToDo: negative values ok?
if (any(prm%xi_slip_0 <= 0.0_pReal)) extmsg = trim(extmsg)//'xi_slip_0 ' if (any(prm%xi_slip_0 <= 0.0_pReal)) extmsg = trim(extmsg)//'xi_slip_0 '
if (any(prm%xi_slip_sat < prm%xi_slip_0)) extmsg = trim(extmsg)//'xi_slip_sat ' if (any(prm%xi_slip_sat < prm%xi_slip_0)) extmsg = trim(extmsg)//'xi_slip_sat '
else slipActive else slipActive
@ -279,10 +268,11 @@ subroutine plastic_phenopowerlaw_init
! sanity checks ! sanity checks
if (prm%gdot0_twin <= 0.0_pReal) extmsg = trim(extmsg)//'gdot0_twin ' if (prm%gdot0_twin <= 0.0_pReal) extmsg = trim(extmsg)//'gdot0_twin '
if (dEq0(prm%n_twin)) extmsg = trim(extmsg)//'n_twin ' ! ToDo: negative values ok? if (dEq0(prm%n_twin)) extmsg = trim(extmsg)//'n_twin ' ! ToDo: negative values ok?
else twinActive else twinActive
allocate(prm%interaction_TwinTwin(0,0)) allocate(prm%interaction_TwinTwin(0,0))
allocate(prm%xi_twin_0(0)) allocate(prm%xi_twin_0(0))
allocate(prm%gamma_twin_char(0))
endif twinActive endif twinActive
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
@ -295,8 +285,8 @@ subroutine plastic_phenopowerlaw_init
config_phase(p)%getFloats('interaction_twinslip'), & config_phase(p)%getFloats('interaction_twinslip'), &
structure(1:3)) structure(1:3))
else slipAndTwinActive else slipAndTwinActive
allocate(prm%interaction_SlipTwin(prm%totalNslip,prm%TotalNtwin)) ! at least one dimension is 0 allocate(prm%interaction_SlipTwin(prm%totalNslip,prm%TotalNtwin)) ! at least one dimension is 0
allocate(prm%interaction_TwinSlip(prm%totalNtwin,prm%TotalNslip)) ! at least one dimension is 0 allocate(prm%interaction_TwinSlip(prm%totalNtwin,prm%TotalNslip)) ! at least one dimension is 0
prm%h0_TwinSlip = 0.0_pReal prm%h0_TwinSlip = 0.0_pReal
endif slipAndTwinActive endif slipAndTwinActive
@ -338,12 +328,6 @@ subroutine plastic_phenopowerlaw_init
outputID = merge(resolvedstress_twin_ID,undefined_ID,prm%totalNtwin>0_pInt) outputID = merge(resolvedstress_twin_ID,undefined_ID,prm%totalNtwin>0_pInt)
outputSize = prm%totalNtwin outputSize = prm%totalNtwin
case ('totalshear')
outputID = merge(totalshear_ID,undefined_ID,prm%totalNslip>0_pInt)
outputSize = 1_pInt
case ('totalvolfrac_twin')
outputID = merge(totalvolfrac_twin_ID,undefined_ID,prm%totalNtwin>0_pInt)
outputSize = 1_pInt
end select end select
if (outputID /= undefined_ID) then if (outputID /= undefined_ID) then
@ -358,8 +342,7 @@ subroutine plastic_phenopowerlaw_init
! allocate state arrays ! allocate state arrays
NipcMyPhase = count(material_phase == p) ! number of IPCs containing my phase NipcMyPhase = count(material_phase == p) ! number of IPCs containing my phase
sizeState = size(['tau_slip ','gamma_slip']) * prm%TotalNslip & sizeState = size(['tau_slip ','gamma_slip']) * prm%TotalNslip &
+ size(['tau_twin ','gamma_twin']) * prm%TotalNtwin & + size(['tau_twin ','gamma_twin']) * prm%TotalNtwin
+ size(['sum(gamma)','sum(f) ']) ! ToDo: only needed if either twin or slip active!
sizeDotState = sizeState sizeDotState = sizeState
call material_allocatePlasticState(p,NipcMyPhase,sizeState,sizeDotState,0_pInt, & call material_allocatePlasticState(p,NipcMyPhase,sizeState,sizeDotState,0_pInt, &
@ -383,18 +366,6 @@ subroutine plastic_phenopowerlaw_init
dot%xi_twin => plasticState(p)%dotState(startIndex:endIndex,:) dot%xi_twin => plasticState(p)%dotState(startIndex:endIndex,:)
plasticState(p)%aTolState(startIndex:endIndex) = prm%aTolResistance plasticState(p)%aTolState(startIndex:endIndex) = prm%aTolResistance
startIndex = endIndex + 1_pInt
endIndex = endIndex + 1_pInt
stt%sumGamma => plasticState(p)%state (startIndex,:)
dot%sumGamma => plasticState(p)%dotState(startIndex,:)
plasticState(p)%aTolState(startIndex:endIndex) = prm%aTolShear
startIndex = endIndex + 1_pInt
endIndex = endIndex + 1_pInt
stt%sumF=>plasticState(p)%state (startIndex,:)
dot%sumF=>plasticState(p)%dotState(startIndex,:)
plasticState(p)%aTolState(startIndex:endIndex) = prm%aTolTwinFrac
startIndex = endIndex + 1_pInt startIndex = endIndex + 1_pInt
endIndex = endIndex + prm%totalNslip endIndex = endIndex + prm%totalNslip
stt%gamma_slip => plasticState(p)%state (startIndex:endIndex,:) stt%gamma_slip => plasticState(p)%state (startIndex:endIndex,:)
@ -421,6 +392,8 @@ end subroutine plastic_phenopowerlaw_init
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
!> @brief calculates plastic velocity gradient and its tangent !> @brief calculates plastic velocity gradient and its tangent
!> @details asumme that deformation by dislocation glide affects twinned and untwinned volume
! equally (Taylor assumption). Twinning happens only in untwinned volume (
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
subroutine plastic_phenopowerlaw_LpAndItsTangent(Lp,dLp_dMp,Mp,instance,of) subroutine plastic_phenopowerlaw_LpAndItsTangent(Lp,dLp_dMp,Mp,instance,of)
@ -443,18 +416,15 @@ subroutine plastic_phenopowerlaw_LpAndItsTangent(Lp,dLp_dMp,Mp,instance,of)
gdot_slip_pos,gdot_slip_neg gdot_slip_pos,gdot_slip_neg
real(pReal), dimension(param(instance)%totalNtwin) :: & real(pReal), dimension(param(instance)%totalNtwin) :: &
gdot_twin,dgdot_dtautwin gdot_twin,dgdot_dtautwin
type(tParameters) :: prm
type(tPhenopowerlawState) :: stt
associate(prm => param(instance), stt => state(instance))
Lp = 0.0_pReal Lp = 0.0_pReal
dLp_dMp = 0.0_pReal dLp_dMp = 0.0_pReal
associate(prm => param(instance), stt => state(instance))
call kinetics_slip(prm,stt,of,Mp,gdot_slip_pos,gdot_slip_neg,dgdot_dtauslip_pos,dgdot_dtauslip_neg) call kinetics_slip(prm,stt,of,Mp,gdot_slip_pos,gdot_slip_neg,dgdot_dtauslip_pos,dgdot_dtauslip_neg)
slipSystems: do i = 1_pInt, prm%totalNslip slipSystems: do i = 1_pInt, prm%totalNslip
Lp = Lp + (1.0_pReal-stt%sumF(of))*(gdot_slip_pos(i)+gdot_slip_neg(i))*prm%Schmid_slip(1:3,1:3,i) Lp = Lp + (gdot_slip_pos(i)+gdot_slip_neg(i))*prm%Schmid_slip(1:3,1:3,i)
forall (k=1_pInt:3_pInt,l=1_pInt:3_pInt,m=1_pInt:3_pInt,n=1_pInt:3_pInt) & forall (k=1_pInt:3_pInt,l=1_pInt:3_pInt,m=1_pInt:3_pInt,n=1_pInt:3_pInt) &
dLp_dMp(k,l,m,n) = dLp_dMp(k,l,m,n) & dLp_dMp(k,l,m,n) = dLp_dMp(k,l,m,n) &
+ dgdot_dtauslip_pos(i) * prm%Schmid_slip(k,l,i) * prm%nonSchmid_pos(m,n,i) & + dgdot_dtauslip_pos(i) * prm%Schmid_slip(k,l,i) * prm%nonSchmid_pos(m,n,i) &
@ -468,9 +438,9 @@ subroutine plastic_phenopowerlaw_LpAndItsTangent(Lp,dLp_dMp,Mp,instance,of)
dLp_dMp(k,l,m,n) = dLp_dMp(k,l,m,n) & dLp_dMp(k,l,m,n) = dLp_dMp(k,l,m,n) &
+ dgdot_dtautwin(i)*prm%Schmid_twin(k,l,i)*prm%Schmid_twin(m,n,i) + dgdot_dtautwin(i)*prm%Schmid_twin(k,l,i)*prm%Schmid_twin(m,n,i)
enddo twinSystems enddo twinSystems
end associate end associate
end subroutine plastic_phenopowerlaw_LpAndItsTangent end subroutine plastic_phenopowerlaw_LpAndItsTangent
@ -490,29 +460,28 @@ subroutine plastic_phenopowerlaw_dotState(Mp,instance,of)
i i
real(pReal) :: & real(pReal) :: &
c_SlipSlip,c_TwinSlip,c_TwinTwin, & c_SlipSlip,c_TwinSlip,c_TwinTwin, &
xi_slip_sat_offset xi_slip_sat_offset,&
sumGamma,sumF
real(pReal), dimension(param(instance)%totalNslip) :: & real(pReal), dimension(param(instance)%totalNslip) :: &
left_SlipSlip,right_SlipSlip, & left_SlipSlip,right_SlipSlip, &
gdot_slip_pos,gdot_slip_neg gdot_slip_pos,gdot_slip_neg
type(tParameters) :: prm
type(tPhenopowerlawState) :: dot,stt
associate(prm => param(instance), stt => state(instance), dot => dotState(instance)) associate(prm => param(instance), stt => state(instance), dot => dotState(instance))
dot%whole(:,of) = 0.0_pReal dot%whole(:,of) = 0.0_pReal
sumGamma = sum(stt%gamma_slip(:,of))
sumF = sum(stt%gamma_twin(:,of)/prm%gamma_twin_char)
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
! system-independent (nonlinear) prefactors to M_Xx (X influenced by x) matrices ! system-independent (nonlinear) prefactors to M_Xx (X influenced by x) matrices
c_SlipSlip = prm%h0_slipslip * (1.0_pReal + prm%twinC*stt%sumF(of)** prm%twinB) c_SlipSlip = prm%h0_slipslip * (1.0_pReal + prm%twinC*sumF** prm%twinB)
c_TwinSlip = prm%h0_TwinSlip * stt%sumGamma(of)**prm%twinE c_TwinSlip = prm%h0_TwinSlip * sumGamma**prm%twinE
c_TwinTwin = prm%h0_TwinTwin * stt%sumF(of)**prm%twinD c_TwinTwin = prm%h0_TwinTwin * sumF**prm%twinD
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
! calculate left and right vectors ! calculate left and right vectors
left_SlipSlip = 1.0_pReal + prm%H_int left_SlipSlip = 1.0_pReal + prm%H_int
xi_slip_sat_offset = prm%spr*sqrt(stt%sumF(of)) xi_slip_sat_offset = prm%spr*sqrt(sumF)
right_SlipSlip = abs(1.0_pReal-stt%xi_slip(:,of) / (prm%xi_slip_sat+xi_slip_sat_offset)) **prm%a_slip & right_SlipSlip = abs(1.0_pReal-stt%xi_slip(:,of) / (prm%xi_slip_sat+xi_slip_sat_offset)) **prm%a_slip &
* sign(1.0_pReal,1.0_pReal-stt%xi_slip(:,of) / (prm%xi_slip_sat+xi_slip_sat_offset)) * sign(1.0_pReal,1.0_pReal-stt%xi_slip(:,of) / (prm%xi_slip_sat+xi_slip_sat_offset))
@ -520,17 +489,13 @@ subroutine plastic_phenopowerlaw_dotState(Mp,instance,of)
! shear rates ! shear rates
call kinetics_slip(prm,stt,of,Mp,gdot_slip_pos,gdot_slip_neg) call kinetics_slip(prm,stt,of,Mp,gdot_slip_pos,gdot_slip_neg)
dot%gamma_slip(:,of) = abs(gdot_slip_pos+gdot_slip_neg) dot%gamma_slip(:,of) = abs(gdot_slip_pos+gdot_slip_neg)
dot%sumGamma(of) = sum(dot%gamma_slip(:,of))
call kinetics_twin(prm,stt,of,Mp,dot%gamma_twin(:,of)) call kinetics_twin(prm,stt,of,Mp,dot%gamma_twin(:,of))
if (prm%totalNtwin > 0_pInt) dot%sumF(of) = merge(sum(dot%gamma_twin(:,of)/prm%gamma_twin_char), &
0.0_pReal, &
stt%sumF(of) < 0.98_pReal)
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
! hardening ! hardening
hardeningSlip: do i = 1_pInt, prm%totalNslip hardeningSlip: do i = 1_pInt, prm%totalNslip
dot%xi_slip(i,of) = dot_product(prm%interaction_SlipSlip(i,:),right_SlipSlip*dot%gamma_slip(:,of)) & dot%xi_slip(i,of) = dot_product(prm%interaction_SlipSlip(i,:),right_SlipSlip*dot%gamma_slip(:,of)) &
* c_SlipSlip * left_SlipSlip(i) & * c_SlipSlip * left_SlipSlip(i) &
+ dot_product(prm%interaction_SlipTwin(i,:),dot%gamma_twin(:,of)) + dot_product(prm%interaction_SlipTwin(i,:),dot%gamma_twin(:,of))
enddo hardeningSlip enddo hardeningSlip
@ -546,8 +511,9 @@ end subroutine plastic_phenopowerlaw_dotState
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
!> @brief calculates shear rates on slip systems and derivatives with respect to resolved stress !> @brief calculates shear rates on slip systems and derivatives with respect to resolved stress
!> @details: Shear rates are calculated only optionally. NOTE: Against the common convention, the !> @details Shear rates are calculated only optionally.
!> result (i.e. intent(out)) variables are the last to have the optional arguments at the end ! NOTE: Against the common convention, the result (i.e. intent(out)) variables are the last to
! have the optional arguments at the end
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
pure subroutine kinetics_slip(prm,stt,of,Mp,gdot_slip_pos,gdot_slip_neg, & pure subroutine kinetics_slip(prm,stt,of,Mp,gdot_slip_pos,gdot_slip_neg, &
dgdot_dtau_slip_pos,dgdot_dtau_slip_neg) dgdot_dtau_slip_pos,dgdot_dtau_slip_neg)
@ -619,9 +585,11 @@ end subroutine kinetics_slip
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
!> @brief calculates shear rates on twin systems and derivatives with respect to resolved stress !> @brief calculates shear rates on twin systems and derivatives with respect to resolved stress.
!> @details: Shear rates are calculated only optionally. NOTE: Against the common convention, the ! twinning is assumed to take place only in untwinned volume.
!> result (i.e. intent(out)) variables are the last to have the optional arguments at the end !> @details Derivates are calculated only optionally.
! NOTE: Against the common convention, the result (i.e. intent(out)) variables are the last to
! have the optional arguments at the end.
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
pure subroutine kinetics_twin(prm,stt,of,Mp,gdot_twin,dgdot_dtau_twin) pure subroutine kinetics_twin(prm,stt,of,Mp,gdot_twin,dgdot_dtau_twin)
use prec, only: & use prec, only: &
@ -652,7 +620,8 @@ pure subroutine kinetics_twin(prm,stt,of,Mp,gdot_twin,dgdot_dtau_twin)
enddo enddo
where(tau_twin > 0.0_pReal) where(tau_twin > 0.0_pReal)
gdot_twin = (1.0_pReal-stt%sumF(of))*prm%gdot0_twin*(abs(tau_twin)/stt%xi_twin(:,of))**prm%n_twin gdot_twin = (1.0_pReal-sum(stt%gamma_twin(:,of)/prm%gamma_twin_char)) & ! only twin in untwinned volume fraction
* prm%gdot0_twin*(abs(tau_twin)/stt%xi_twin(:,of))**prm%n_twin
else where else where
gdot_twin = 0.0_pReal gdot_twin = 0.0_pReal
end where end where
@ -690,13 +659,10 @@ function plastic_phenopowerlaw_postResults(Mp,instance,of) result(postResults)
real(pReal), dimension(param(instance)%totalNslip) :: & real(pReal), dimension(param(instance)%totalNslip) :: &
gdot_slip_pos,gdot_slip_neg gdot_slip_pos,gdot_slip_neg
type(tParameters) :: prm
type(tPhenopowerlawState) :: stt
associate( prm => param(instance), stt => state(instance))
postResults = 0.0_pReal postResults = 0.0_pReal
c = 0_pInt c = 0_pInt
associate( prm => param(instance), stt => state(instance))
outputsLoop: do o = 1_pInt,size(prm%outputID) outputsLoop: do o = 1_pInt,size(prm%outputID)
select case(prm%outputID(o)) select case(prm%outputID(o))
@ -732,15 +698,9 @@ function plastic_phenopowerlaw_postResults(Mp,instance,of) result(postResults)
enddo enddo
c = c + prm%totalNtwin c = c + prm%totalNtwin
case (totalshear_ID)
postResults(c+1_pInt) = stt%sumGamma(of)
c = c + 1_pInt
case (totalvolfrac_twin_ID)
postResults(c+1_pInt) = stt%sumF(of)
c = c + 1_pInt
end select end select
enddo outputsLoop enddo outputsLoop
end associate end associate
end function plastic_phenopowerlaw_postResults end function plastic_phenopowerlaw_postResults

View File

@ -120,8 +120,8 @@ subroutine spectral_damage_init()
trim(snes_type) == 'vinewtonssls') then trim(snes_type) == 'vinewtonssls') then
call DMGetGlobalVector(damage_grid,lBound,ierr); CHKERRQ(ierr) call DMGetGlobalVector(damage_grid,lBound,ierr); CHKERRQ(ierr)
call DMGetGlobalVector(damage_grid,uBound,ierr); CHKERRQ(ierr) call DMGetGlobalVector(damage_grid,uBound,ierr); CHKERRQ(ierr)
call VecSet(lBound,0.0,ierr); CHKERRQ(ierr) call VecSet(lBound,0.0_pReal,ierr); CHKERRQ(ierr)
call VecSet(uBound,1.0,ierr); CHKERRQ(ierr) call VecSet(uBound,1.0_pReal,ierr); CHKERRQ(ierr)
call SNESVISetVariableBounds(damage_snes,lBound,uBound,ierr) !< variable bounds for variational inequalities like contact mechanics, damage etc. call SNESVISetVariableBounds(damage_snes,lBound,uBound,ierr) !< variable bounds for variational inequalities like contact mechanics, damage etc.
call DMRestoreGlobalVector(damage_grid,lBound,ierr); CHKERRQ(ierr) call DMRestoreGlobalVector(damage_grid,lBound,ierr); CHKERRQ(ierr)
call DMRestoreGlobalVector(damage_grid,uBound,ierr); CHKERRQ(ierr) call DMRestoreGlobalVector(damage_grid,uBound,ierr); CHKERRQ(ierr)
@ -134,7 +134,7 @@ subroutine spectral_damage_init()
xend = xstart + xend - 1 xend = xstart + xend - 1
yend = ystart + yend - 1 yend = ystart + yend - 1
zend = zstart + zend - 1 zend = zstart + zend - 1
call VecSet(solution,1.0,ierr); CHKERRQ(ierr) call VecSet(solution,1.0_pReal,ierr); CHKERRQ(ierr)
allocate(damage_current(grid(1),grid(2),grid3), source=1.0_pReal) allocate(damage_current(grid(1),grid(2),grid3), source=1.0_pReal)
allocate(damage_lastInc(grid(1),grid(2),grid3), source=1.0_pReal) allocate(damage_lastInc(grid(1),grid(2),grid3), source=1.0_pReal)
allocate(damage_stagInc(grid(1),grid(2),grid3), source=1.0_pReal) allocate(damage_stagInc(grid(1),grid(2),grid3), source=1.0_pReal)