2016-10-18 01:54:11 +05:30
|
|
|
#!/usr/bin/env python2.7
|
|
|
|
# -*- coding: UTF-8 no BOM -*-
|
|
|
|
|
|
|
|
import os
|
|
|
|
import sys
|
|
|
|
import damask
|
|
|
|
import numpy as np
|
|
|
|
from optparse import OptionParser
|
|
|
|
|
|
|
|
scriptName = os.path.splitext(os.path.basename(__file__))[0]
|
|
|
|
scriptID = ' '.join([scriptName, damask.version])
|
|
|
|
|
|
|
|
|
|
|
|
# ----- Helper functions ----- #
|
|
|
|
def operator(stretch, strain, eigenvalues):
|
|
|
|
# Albrecht Bertram: Elasticity and Plasticity of Large Deformations
|
|
|
|
# An Introduction (3rd Edition, 2012), p. 102
|
|
|
|
return {'V#ln': np.log(eigenvalues),
|
|
|
|
'U#ln': np.log(eigenvalues),
|
|
|
|
'V#Biot': (np.ones(3, 'd') - 1.0/eigenvalues),
|
|
|
|
'U#Biot': (eigenvalues - np.ones(3, 'd')),
|
|
|
|
'V#Green': (np.ones(3, 'd') - 1.0/eigenvalues/eigenvalues)*0.5,
|
|
|
|
'U#Green': (eigenvalues*eigenvalues - np.ones(3, 'd'))*0.5,
|
|
|
|
}[stretch+'#'+strain]
|
|
|
|
|
|
|
|
|
|
|
|
def calcEPS(defgrads, stretchType, strainType):
|
2016-10-25 00:46:29 +05:30
|
|
|
"""Calculate specific type of strain tensor"""
|
2016-10-18 01:54:11 +05:30
|
|
|
eps = np.zeros(defgrads.shape) # initialize container
|
|
|
|
|
|
|
|
# TODO:
|
|
|
|
# this loop can use some performance boost
|
|
|
|
# (multi-threading?)
|
2016-10-25 00:46:29 +05:30
|
|
|
for ri in range(defgrads.shape[0]):
|
2016-10-18 02:28:04 +05:30
|
|
|
f = defgrads[ri, :].reshape(3, 3)
|
|
|
|
U, S, Vh = np.linalg.svd(f)
|
2016-10-18 01:54:11 +05:30
|
|
|
R = np.dot(U, Vh) # rotation of polar decomposition
|
|
|
|
if stretchType == 'U':
|
|
|
|
stretch = np.dot(np.linalg.inv(R), f) # F = RU
|
|
|
|
elif stretchType == 'V':
|
|
|
|
stretch = np.dot(f, np.linalg.inv(R)) # F = VR
|
|
|
|
|
|
|
|
# kill nasty noisy data
|
|
|
|
stretch = np.where(abs(stretch) < 1e-12, 0, stretch)
|
|
|
|
|
|
|
|
(D, V) = np.linalg.eig(stretch)
|
|
|
|
# flip principal component with negative Eigen values
|
|
|
|
neg = np.where(D < 0.0)
|
|
|
|
D[neg] *= -1.
|
|
|
|
V[:, neg] *= -1.
|
|
|
|
|
|
|
|
# check each vector for orthogonality
|
|
|
|
# --> brutal force enforcing orthogonal base
|
|
|
|
# and re-normalize
|
|
|
|
for i, eigval in enumerate(D):
|
|
|
|
if np.dot(V[:, i], V[:, (i+1) % 3]) != 0.0:
|
|
|
|
V[:, (i+1) % 3] = np.cross(V[:, (i+2) % 3], V[:, i])
|
|
|
|
V[:, (i+1) % 3] /= np.sqrt(np.dot(V[:, (i+1) % 3],
|
|
|
|
V[:, (i+1) % 3].conj()))
|
|
|
|
|
|
|
|
# calculate requested version of strain tensor
|
|
|
|
d = operator(stretchType, strainType, D)
|
|
|
|
eps[ri] = (np.dot(V, np.dot(np.diag(d), V.T)).real).reshape(9)
|
|
|
|
|
|
|
|
return eps
|
|
|
|
|
|
|
|
# --------------------------------------------------------------------
|
|
|
|
# MAIN
|
|
|
|
# --------------------------------------------------------------------
|
|
|
|
desp = "Add column(s) containing given strains based on given stretches"
|
|
|
|
parser = OptionParser(option_class=damask.extendableOption,
|
|
|
|
usage='%prog options [file[s]]',
|
|
|
|
description=desp,
|
|
|
|
version=scriptID)
|
|
|
|
msg = 'material strains based on right Cauchy-Green deformation, i.e., C and U'
|
|
|
|
parser.add_option('-u', '--right',
|
|
|
|
dest='right',
|
|
|
|
action='store_true',
|
|
|
|
help=msg)
|
|
|
|
msg = 'spatial strains based on left Cauchy--Green deformation, i.e., B and V'
|
|
|
|
parser.add_option('-v', '--left',
|
|
|
|
dest='left',
|
|
|
|
action='store_true',
|
|
|
|
help=msg)
|
|
|
|
parser.add_option('-0', '--logarithmic',
|
|
|
|
dest='logarithmic',
|
|
|
|
action='store_true',
|
|
|
|
help='calculate logarithmic strain tensor')
|
|
|
|
parser.add_option('-1', '--biot',
|
|
|
|
dest='biot',
|
|
|
|
action='store_true',
|
|
|
|
help='calculate biot strain tensor')
|
|
|
|
parser.add_option('-2', '--green',
|
|
|
|
dest='green',
|
|
|
|
action='store_true',
|
|
|
|
help='calculate green strain tensor')
|
2016-10-18 02:28:04 +05:30
|
|
|
# NOTE:
|
|
|
|
# It might be easier to just calculate one type of deformation gradient
|
|
|
|
# at a time.
|
2016-10-18 01:54:11 +05:30
|
|
|
msg = 'heading(s) of columns containing deformation tensor values'
|
|
|
|
parser.add_option('-f', '--defgrad',
|
|
|
|
dest='defgrad',
|
|
|
|
action='extend',
|
|
|
|
metavar='<string LIST>',
|
|
|
|
help=msg)
|
|
|
|
|
|
|
|
parser.set_defaults(right=False, left=False,
|
|
|
|
logarithmic=False, biot=False, green=False,
|
2016-10-18 02:28:04 +05:30
|
|
|
defgrad='f')
|
2016-10-18 01:54:11 +05:30
|
|
|
|
|
|
|
(options, filenames) = parser.parse_args()
|
|
|
|
|
|
|
|
stretches = []
|
|
|
|
strains = []
|
|
|
|
|
|
|
|
if options.right:
|
|
|
|
stretches.append('U')
|
|
|
|
if options.left:
|
|
|
|
stretches.append('V')
|
|
|
|
|
|
|
|
if options.logarithmic:
|
|
|
|
strains.append('ln')
|
|
|
|
if options.biot:
|
|
|
|
strains.append('Biot')
|
|
|
|
if options.green:
|
|
|
|
strains.append('Green')
|
|
|
|
|
|
|
|
if options.defgrad is None:
|
|
|
|
parser.error('no data column specified.')
|
|
|
|
|
|
|
|
# ----- Loop over input files ----- #
|
|
|
|
for name in filenames:
|
|
|
|
try:
|
|
|
|
h5f = damask.H5Table(name, new_file=False)
|
|
|
|
except:
|
|
|
|
continue
|
|
|
|
damask.util.report(scriptName, name)
|
|
|
|
|
|
|
|
# extract defgrads from HDF5 storage
|
2016-10-18 02:28:04 +05:30
|
|
|
F = h5f.get_data(options.defgrad)
|
2016-10-18 01:54:11 +05:30
|
|
|
|
|
|
|
# allow calculate multiple types of strain within the
|
|
|
|
# same cmd call
|
|
|
|
for stretchType in stretches:
|
|
|
|
for strainType in strains:
|
|
|
|
# calculate strain tensor for this type
|
|
|
|
eps = calcEPS(F, stretchType, strainType)
|
|
|
|
|
|
|
|
# compose labels/headers for this strain tensor
|
|
|
|
labelsStrain = strainType + stretchType
|
|
|
|
|
|
|
|
# prepare log info
|
|
|
|
cmd_log = scriptID + '\t' + ' '.join(sys.argv[1:])
|
|
|
|
|
|
|
|
# write data to HDF5 file
|
|
|
|
h5f.add_data(labelsStrain, eps, cmd_log=cmd_log)
|