Merge remote branch 'origin/development' into cmake

This commit is contained in:
Chen Zhang 2016-04-18 09:11:29 -04:00
commit 672c8d0606
197 changed files with 3203 additions and 3333 deletions

8
.gitattributes vendored Normal file
View File

@ -0,0 +1,8 @@
# from https://help.github.com/articles/dealing-with-line-endings/
#
# always use LF, even if the files are edited on windows, they need to be compiled/used on unix
* text eol=lf
# Denote all files that are truly binary and should not be modified.
*.png binary
*.jpg binary

View File

@ -5,10 +5,10 @@ set LOCATION=%~dp0
set DAMASK_ROOT=%LOCATION%\DAMASK
set DAMASK_NUM_THREADS=2
chcp 1252
Title Düsseldorf Advanced Materials Simulation Kit - DAMASK, MPIE Düsseldorf
Title Düsseldorf Advanced Materials Simulation Kit - DAMASK, MPIE Düsseldorf
echo.
echo Düsseldorf Advanced Materials Simulation Kit - DAMASK
echo Max-Planck-Institut für Eisenforschung, Düsseldorf
echo Düsseldorf Advanced Materials Simulation Kit - DAMASK
echo Max-Planck-Institut für Eisenforschung, Düsseldorf
echo http://damask.mpie.de
echo.
echo Preparing environment ...

View File

@ -2,7 +2,7 @@
# usage: source DAMASK_env.sh
if [ "$OSTYPE" == "linux-gnu" ] || [ "$OSTYPE" == 'linux' ]; then
DAMASK_ROOT=$(readlink -f "`dirname $BASH_SOURCE`")
DAMASK_ROOT=$(python -c "import os,sys; print(os.path.realpath(os.path.expanduser(sys.argv[1])))" "`dirname $BASH_SOURCE`")
else
[[ "${BASH_SOURCE::1}" == "/" ]] && BASE="" || BASE="`pwd`/"
STAT=$(stat "`dirname $BASE$BASH_SOURCE`")
@ -18,11 +18,11 @@ fi
SOLVER=`which DAMASK_spectral 2>/dev/null`
if [ "x$SOLVER" == "x" ]; then
export SOLVER='Not found!'
SOLVER='Not found!'
fi
PROCESSING=`which postResults 2>/dev/null`
if [ "x$PROCESSING" == "x" ]; then
export PROCESSING='Not found!'
PROCESSING='Not found!'
fi
# according to http://software.intel.com/en-us/forums/topic/501500
@ -53,7 +53,11 @@ if [ ! -z "$PS1" ]; then
[[ "x$SOLVER" != "x" ]] && echo "Spectral Solver $SOLVER"
[[ "x$PROCESSING" != "x" ]] && echo "Post Processing $PROCESSING"
echo "Multithreading DAMASK_NUM_THREADS=$DAMASK_NUM_THREADS"
[[ "x$PETSC_DIR" != "x" ]] && echo "PETSc location $PETSC_DIR"
if [ "x$PETSC_DIR" != "x" ]; then
echo "PETSc location $PETSC_DIR"
[[ `python -c "import os,sys; print(os.path.realpath(os.path.expanduser(sys.argv[1])))" "$PETSC_DIR"` == $PETSC_DIR ]] \
|| echo " ~~> "`python -c "import os,sys; print(os.path.realpath(os.path.expanduser(sys.argv[1])))" "$PETSC_DIR"`
fi
[[ "x$PETSC_ARCH" != "x" ]] && echo "PETSc architecture $PETSC_ARCH"
echo "MSC.Marc/Mentat $MSC_ROOT"
echo

View File

@ -51,7 +51,10 @@ if [ ! -z "$PS1" ]; then
[[ "x$SOLVER" != "x" ]] && echo "Spectral Solver $SOLVER"
[[ "x$PROCESSING" != "x" ]] && echo "Post Processing $PROCESSING"
echo "Multithreading DAMASK_NUM_THREADS=$DAMASK_NUM_THREADS"
[[ "x$PETSC_DIR" != "x" ]] && echo "PETSc location $PETSC_DIR"
if [ "x$PETSC_DIR" != "x" ]; then
echo "PETSc location $PETSC_DIR"
[[ `readlink -f $PETSC_DIR` == $PETSC_DIR ]] || echo " ~~> "`readlink -f $PETSC_DIR`
fi
[[ "x$PETSC_ARCH" != "x" ]] && echo "PETSc architecture $PETSC_ARCH"
echo "MSC.Marc/Mentat $MSC_ROOT"
echo

View File

@ -1,4 +1,4 @@
Copyright 2011-15 Max-Planck-Institut für Eisenforschung GmbH
Copyright 2011-16 Max-Planck-Institut für Eisenforschung GmbH
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

4
README
View File

@ -2,9 +2,9 @@ visit damask.mpie.de for installation and usage instructions
CONTACT INFORMATION
Max-Planck-Institut für Eisenforschung GmbH
Max-Planck-Institut für Eisenforschung GmbH
Max-Planck-Str. 1
40237 Düsseldorf
40237 Düsseldorf
Germany
Email: DAMASK@mpie.de

View File

@ -1 +1 @@
revision3813-984-gf13bddd
v2.0.0-97-g8b27de7

8
code/.gitattributes vendored Normal file
View File

@ -0,0 +1,8 @@
# from https://help.github.com/articles/dealing-with-line-endings/
#
# always use LF, even if the files are edited on windows, they need to be compiled/used on unix
* text eol=lf
# Denote all files that are truly binary and should not be modified.
*.png binary
*.jpg binary

3
code/.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
DAMASK_marc*.f90
quit__genmod.f90
*.marc

View File

@ -1,37 +0,0 @@
### $Id$ ###
[Tungsten]
elasticity hooke
plasticity dislokmc
### Material parameters ###
lattice_structure bcc
C11 523.0e9 # From Marinica et al. Journal of Physics: Condensed Matter(2013)
C12 202.0e9
C44 161.0e9
grainsize 2.0e-5 # Average grain size [m] 2.0e-5
SolidSolutionStrength 0.0 # Strength due to elements in solid solution
### Dislocation glide parameters ###
#per family
Nslip 12 0
slipburgers 2.72e-10 # Burgers vector of slip system [m]
rhoedge0 1.0e12 # Initial edge dislocation density [m/m**3]
rhoedgedip0 1.0 # Initial edged dipole dislocation density [m/m**3]
Qedge 2.725e-19 # Activation energy for dislocation glide [J]
v0 3560.3 # Initial glide velocity [m/s](kmC)
p_slip 0.16 # p-exponent in glide velocity
q_slip 1.00 # q-exponent in glide velocity
u_slip 2.47 # u-exponent of stress pre-factor (kmC)
s_slip 0.97 # self hardening in glide velocity (kmC)
tau_peierls 2.03e9 # peierls stress [Pa]
#hardening
dipoleformationfactor 0 # to have hardening due to dipole formation off
CLambdaSlip 10.0 # Adj. parameter controlling dislocation mean free path
D0 4.0e-5 # Vacancy diffusion prefactor [m**2/s]
Qsd 4.5e-19 # Activation energy for climb [J]
Catomicvolume 1.0 # Adj. parameter controlling the atomic volume [in b]
Cedgedipmindistance 1.0 # Adj. parameter controlling the minimum dipole distance [in b]
interaction_slipslip 0.2 0.11 0.19 0.15 0.11 0.17

View File

@ -54,12 +54,12 @@ discrepancyPower_RGC 5.0
fixed_seed 0 # put any number larger than zero, integer, if you want to have a pseudo random distribution
## spectral parameters ##
err_div_tolAbs 1.0e-3 # relative tolerance for fulfillment of stress equilibrium
err_div_tolRel 5.0e-4 # absolute tolerance for fulfillment of stress equilibrium
err_curl_tolAbs 1.0e-12 # relative tolerance for fulfillment of strain compatibility
err_curl_tolRel 5.0e-4 # absolute tolerance for fulfillment of strain compatibility
err_stress_tolrel 0.01 # relative tolerance for fulfillment of stress BC
err_stress_tolabs 1.0e3 # absolute tolerance for fulfillment of stress BC
err_div_tolAbs 1.0e-3 # absolute tolerance for fulfillment of stress equilibrium
err_div_tolRel 5.0e-4 # relative tolerance for fulfillment of stress equilibrium
err_curl_tolAbs 1.0e-12 # absolute tolerance for fulfillment of strain compatibility
err_curl_tolRel 5.0e-4 # relative tolerance for fulfillment of strain compatibility
err_stress_tolAbs 1.0e3 # absolute tolerance for fulfillment of stress BC
err_stress_tolRel 0.01 # relative tolerance for fulfillment of stress BC
fftw_timelimit -1.0 # timelimit of plan creation for FFTW, see manual on www.fftw.org, Default -1.0: disable timelimit
rotation_tol 1.0e-12 # tolerance of rotation specified in loadcase, Default 1.0e-12: first guess
fftw_plan_mode FFTW_PATIENT # reads the planing-rigor flag, see manual on www.fftw.org, Default FFTW_PATIENT: use patient planner flag

2
lib/damask/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
core.so
corientation.so

View File

@ -1,27 +1,27 @@
# -*- coding: UTF-8 no BOM -*-
# $Id$
"""Main aggregator"""
import sys, os
with open(os.path.join(os.path.dirname(__file__),'../../VERSION')) as f:
version = f.readline()[:-1]
from .environment import Environment # only one class
from .asciitable import ASCIItable # only one class
from .config import Material # will be extended to debug and numerics
from .colormaps import Colormap, Color
from .orientation import Quaternion, Rodrigues, Symmetry, Orientation
from .environment import Environment # noqa
from .asciitable import ASCIItable # noqa
from .config import Material # noqa
from .colormaps import Colormap, Color # noqa
from .orientation import Quaternion, Rodrigues, Symmetry, Orientation # noqa
# try:
# from .corientation import Quaternion, Rodrigues, Symmetry, Orientation
# print "Import Cython version of Orientation module"
# except:
# from .orientation import Quaternion, Rodrigues, Symmetry, Orientation
#from .block import Block # only one class
from .result import Result # only one class
from .geometry import Geometry # one class with subclasses
from .solver import Solver # one class with subclasses
from .test import Test
from .util import extendableOption
from .result import Result # noqa
from .geometry import Geometry # noqa
from .solver import Solver # noqa
from .test import Test # noqa
from .util import extendableOption # noqa
try:
from . import core

View File

@ -4,12 +4,9 @@
import os,sys
import numpy as np
import util
class ASCIItable():
'''
There should be a doc string here :)
'''
"""Read and write to ASCII tables"""
__slots__ = ['__IO__',
'info',
@ -28,7 +25,7 @@ class ASCIItable():
readonly = False, # no reading from file
):
self.__IO__ = {'output': [],
'buffered': buffered,
'buffered': buffered,
'labeled': labeled, # header contains labels
'labels': [], # labels according to file info
'readBuffer': [], # buffer to hold non-advancing reads
@ -38,18 +35,18 @@ class ASCIItable():
self.__IO__['inPlace'] = not outname and name and not readonly
if self.__IO__['inPlace']: outname = name + self.tmpext # transparently create tmp file
try:
self.__IO__['in'] = (open( name,'r') if os.access( name, os.R_OK) else None) if name else sys.stdin
self.__IO__['in'] = (open( name,'r') if os.access( name, os.R_OK) else None) if name else sys.stdin
except TypeError:
self.__IO__['in'] = name
try:
self.__IO__['out'] = (open(outname,'w') if (not os.path.isfile(outname) \
or os.access( outname, os.W_OK) \
) \
and (not self.__IO__['inPlace'] \
or not os.path.isfile(name) \
or os.access( name, os.W_OK) \
) else None) if outname else sys.stdout
self.__IO__['out'] = (open(outname,'w') if (not os.path.isfile(outname) or
os.access( outname, os.W_OK)
) and
(not self.__IO__['inPlace'] or
not os.path.isfile(name) or
os.access( name, os.W_OK)
) else None) if outname else sys.stdout
except TypeError:
self.__IO__['out'] = outname
@ -58,8 +55,8 @@ class ASCIItable():
self.data = []
self.line = ''
if self.__IO__['in'] == None \
or self.__IO__['out'] == None: raise IOError # complain if any required file access not possible
if self.__IO__['in'] is None \
or self.__IO__['out'] is None: raise IOError # complain if any required file access not possible
# ------------------------------------------------------------------
def _transliterateToFloat(self,
@ -86,9 +83,7 @@ class ASCIItable():
# ------------------------------------------------------------------
def output_write(self,
what):
'''
aggregate a single row (string) or list of (possibly containing further lists of) rows into output
'''
"""aggregate a single row (string) or list of (possibly containing further lists of) rows into output"""
if not isinstance(what, (str, unicode)):
try:
for item in what: self.output_write(item)
@ -104,7 +99,7 @@ class ASCIItable():
clear = True):
try:
self.__IO__['output'] == [] or self.__IO__['out'].write('\n'.join(self.__IO__['output']) + '\n')
except IOError as e:
except IOError:
return False
if clear: self.output_clear()
return True
@ -127,11 +122,12 @@ class ASCIItable():
# ------------------------------------------------------------------
def head_read(self):
'''
get column labels by either reading
the first row or, if keyword "head[*]" is present,
the last line of the header
'''
"""
get column labels by either reading
the first row or, if keyword "head[*]" is present,
the last line of the header
"""
import re
try:
@ -180,10 +176,7 @@ class ASCIItable():
# ------------------------------------------------------------------
def head_write(self,
header = True):
'''
write current header information (info + labels)
'''
"""write current header information (info + labels)"""
head = ['{}\theader'.format(len(self.info)+self.__IO__['labeled'])] if header else []
head.append(self.info)
if self.__IO__['labeled']: head.append('\t'.join(self.labels))
@ -192,9 +185,7 @@ class ASCIItable():
# ------------------------------------------------------------------
def head_getGeom(self):
'''
interpret geom header
'''
"""interpret geom header"""
identifiers = {
'grid': ['a','b','c'],
'size': ['x','y','z'],
@ -234,9 +225,7 @@ class ASCIItable():
# ------------------------------------------------------------------
def head_putGeom(self,info):
'''
translate geometry description to header
'''
"""translate geometry description to header"""
self.info_append([
"grid\ta {}\tb {}\tc {}".format(*info['grid']),
"size\tx {}\ty {}\tz {}".format(*info['size']),
@ -249,9 +238,7 @@ class ASCIItable():
def labels_append(self,
what,
reset = False):
'''
add item or list to existing set of labels (and switch on labeling)
'''
"""add item or list to existing set of labels (and switch on labeling)"""
if not isinstance(what, (str, unicode)):
try:
for item in what: self.labels_append(item)
@ -265,28 +252,27 @@ class ASCIItable():
# ------------------------------------------------------------------
def labels_clear(self):
'''
delete existing labels and switch to no labeling
'''
"""delete existing labels and switch to no labeling"""
self.labels = []
self.__IO__['labeled'] = False
# ------------------------------------------------------------------
def label_index(self,
labels):
'''
tell index of column label(s).
return numpy array if asked for list of labels.
transparently deals with label positions implicitly given as numbers or their headings given as strings.
'''
"""
tell index of column label(s).
return numpy array if asked for list of labels.
transparently deals with label positions implicitly given as numbers or their headings given as strings.
"""
from collections import Iterable
if isinstance(labels, Iterable) and not isinstance(labels, str): # check whether list of labels is requested
idx = []
for label in labels:
if label != None:
if label is not None:
try:
idx.append(int(label)) # column given as integer number?
idx.append(int(label)-1) # column given as integer number?
except ValueError:
try:
idx.append(self.labels.index(label)) # locate string in label list
@ -297,7 +283,7 @@ class ASCIItable():
idx.append(-1) # not found...
else:
try:
idx = int(labels)
idx = int(labels)-1 # offset for python array indexing
except ValueError:
try:
idx = self.labels.index(labels)
@ -305,28 +291,28 @@ class ASCIItable():
try:
idx = self.labels.index('1_'+labels) # locate '1_'+string in label list
except ValueError:
idx = None if labels == None else -1
idx = None if labels is None else -1
return np.array(idx) if isinstance(idx,list) else idx
return np.array(idx) if isinstance(idx,Iterable) else idx
# ------------------------------------------------------------------
def label_dimension(self,
labels):
'''
tell dimension (length) of column label(s).
return numpy array if asked for list of labels.
transparently deals with label positions implicitly given as numbers or their headings given as strings.
'''
"""
tell dimension (length) of column label(s).
return numpy array if asked for list of labels.
transparently deals with label positions implicitly given as numbers or their headings given as strings.
"""
from collections import Iterable
if isinstance(labels, Iterable) and not isinstance(labels, str): # check whether list of labels is requested
dim = []
for label in labels:
if label != None:
if label is not None:
myDim = -1
try: # column given as number?
idx = int(label)
idx = int(label)-1
myDim = 1 # if found has at least dimension 1
if self.labels[idx].startswith('1_'): # column has multidim indicator?
while idx+myDim < len(self.labels) and self.labels[idx+myDim].startswith("%i_"%(myDim+1)):
@ -345,7 +331,7 @@ class ASCIItable():
dim = -1 # assume invalid label
idx = -1
try: # column given as number?
idx = int(labels)
idx = int(labels)-1
dim = 1 # if found has at least dimension 1
if self.labels[idx].startswith('1_'): # column has multidim indicator?
while idx+dim < len(self.labels) and self.labels[idx+dim].startswith("%i_"%(dim+1)):
@ -359,17 +345,17 @@ class ASCIItable():
while idx+dim < len(self.labels) and self.labels[idx+dim].startswith("%i_"%(dim+1)):
dim += 1 # keep adding while going through object
return np.array(dim) if isinstance(dim,list) else dim
return np.array(dim) if isinstance(dim,Iterable) else dim
# ------------------------------------------------------------------
def label_indexrange(self,
labels):
'''
tell index range for given label(s).
return numpy array if asked for list of labels.
transparently deals with label positions implicitly given as numbers or their headings given as strings.
'''
"""
tell index range for given label(s).
return numpy array if asked for list of labels.
transparently deals with label positions implicitly given as numbers or their headings given as strings.
"""
from collections import Iterable
start = self.label_index(labels)
@ -377,13 +363,11 @@ class ASCIItable():
return map(lambda a,b: xrange(a,a+b), zip(start,dim)) if isinstance(labels, Iterable) and not isinstance(labels, str) \
else xrange(start,start+dim)
# ------------------------------------------------------------------
def info_append(self,
what):
'''
add item or list to existing set of infos
'''
"""add item or list to existing set of infos"""
if not isinstance(what, (str, unicode)):
try:
for item in what: self.info_append(item)
@ -394,9 +378,7 @@ class ASCIItable():
# ------------------------------------------------------------------
def info_clear(self):
'''
delete any info block
'''
"""delete any info block"""
self.info = []
# ------------------------------------------------------------------
@ -409,9 +391,7 @@ class ASCIItable():
# ------------------------------------------------------------------
def data_skipLines(self,
count):
'''
wind forward by count number of lines
'''
"""wind forward by count number of lines"""
for i in xrange(count):
alive = self.data_read()
@ -421,9 +401,7 @@ class ASCIItable():
def data_read(self,
advance = True,
respectLabels = True):
'''
read next line (possibly buffered) and parse it into data array
'''
"""read next line (possibly buffered) and parse it into data array"""
self.line = self.__IO__['readBuffer'].pop(0) if len(self.__IO__['readBuffer']) > 0 \
else self.__IO__['in'].readline().strip() # take buffered content or get next data row from file
@ -434,7 +412,7 @@ class ASCIItable():
if self.__IO__['labeled'] and respectLabels: # if table has labels
items = self.line.split()[:len(self.__IO__['labels'])] # use up to label count (from original file info)
self.data = items if len(items) == len(self.__IO__['labels']) else [] # take entries if correct number, i.e. not too few compared to label count
self.data = items if len(items) == len(self.__IO__['labels']) else [] # take entries if label count matches
else:
self.data = self.line.split() # otherwise take all
@ -443,9 +421,7 @@ class ASCIItable():
# ------------------------------------------------------------------
def data_readArray(self,
labels = []):
'''
read whole data of all (given) labels as numpy array
'''
"""read whole data of all (given) labels as numpy array"""
from collections import Iterable
try:
@ -453,7 +429,7 @@ class ASCIItable():
except:
pass # assume/hope we are at data start already...
if labels == None or labels == []:
if labels is None or labels == []:
use = None # use all columns (and keep labels intact)
labels_missing = []
else:
@ -467,9 +443,10 @@ class ASCIItable():
columns = []
for i,(c,d) in enumerate(zip(indices[present],dimensions[present])): # for all valid labels ...
# ... transparently add all components unless column referenced by number or with explicit dimension
columns += range(c,c + \
(d if str(c) != str(labels[present[i]]) else \
1)) # ... transparently add all components unless column referenced by number or with explicit dimension
1))
use = np.array(columns)
self.labels = list(np.array(self.labels)[use]) # update labels with valid subset
@ -481,9 +458,7 @@ class ASCIItable():
# ------------------------------------------------------------------
def data_write(self,
delimiter = '\t'):
'''
write current data array and report alive output back
'''
"""write current data array and report alive output back"""
if len(self.data) == 0: return True
if isinstance(self.data[0],list):
@ -495,9 +470,7 @@ class ASCIItable():
def data_writeArray(self,
fmt = None,
delimiter = '\t'):
'''
write whole numpy array data
'''
"""write whole numpy array data"""
for row in self.data:
try:
output = [fmt % value for value in row] if fmt else map(repr,row)
@ -520,9 +493,7 @@ class ASCIItable():
# ------------------------------------------------------------------
def data_set(self,
what, where):
'''
update data entry in column "where". grows data array if needed.
'''
"""update data entry in column "where". grows data array if needed."""
idx = -1
try:
idx = self.label_index(where)
@ -546,25 +517,27 @@ class ASCIItable():
# ------------------------------------------------------------------
def microstructure_read(self,
grid):
'''
read microstructure data (from .geom format)
'''
N = grid.prod() # expected number of microstructure indices in data
microstructure = np.zeros(N,'i') # initialize as flat array
grid,
type = 'i',
strict = False):
"""read microstructure data (from .geom format)"""
def datatype(item):
return int(item) if type.lower() == 'i' else float(item)
N = grid.prod() # expected number of microstructure indices in data
microstructure = np.zeros(N,type) # initialize as flat array
i = 0
while i < N and self.data_read():
items = self.data
if len(items) > 2:
if items[1].lower() == 'of': items = [int(items[2])]*int(items[0])
elif items[1].lower() == 'to': items = range(int(items[0]),1+int(items[2]))
else: items = map(int,items)
else: items = map(int,items)
if items[1].lower() == 'of': items = np.ones(datatype(items[0]))*datatype(items[2])
elif items[1].lower() == 'to': items = np.arange(datatype(items[0]),1+datatype(items[2]))
else: items = map(datatype,items)
else: items = map(datatype,items)
s = min(len(items), N-i) # prevent overflow of microstructure array
s = min(len(items), N-i) # prevent overflow of microstructure array
microstructure[i:i+s] = items[:s]
i += s
i += len(items)
return microstructure
return (microstructure, i == N and not self.data_read()) if strict else microstructure # check for proper point count and end of file

View File

@ -5,11 +5,12 @@ import math,numpy as np
### --- COLOR CLASS --------------------------------------------------
class Color():
'''
Conversion of colors between different color-spaces. Colors should be given in the form
Color('model',[vector]).To convert and copy color from one space to other, use the methods
convertTo('model') and expressAs('model')spectively
'''
"""Conversion of colors between different color-spaces.
Colors should be given in the form
Color('model',[vector]).To convert and copy color from one space to other, use the methods
convertTo('model') and expressAs('model')spectively
"""
__slots__ = [
'model',
@ -17,7 +18,7 @@ class Color():
]
# ------------------------------------------------------------------
# ------------------------------------------------------------------
def __init__(self,
model = 'RGB',
color = np.zeros(3,'d')):
@ -32,30 +33,32 @@ class Color():
model = model.upper()
if model not in self.__transforms__.keys(): model = 'RGB'
if model == 'RGB' and max(color) > 1.0: # are we RGB255 ?
if model == 'RGB' and max(color) > 1.0: # are we RGB255 ?
for i in range(3):
color[i] /= 255.0 # rescale to RGB
color[i] /= 255.0 # rescale to RGB
if model == 'HSL': # are we HSL ?
if abs(color[0]) > 1.0: color[0] /= 360.0 # with angular hue?
while color[0] >= 1.0: color[0] -= 1.0 # rewind to proper range
while color[0] < 0.0: color[0] += 1.0 # rewind to proper range
if model == 'HSL': # are we HSL ?
if abs(color[0]) > 1.0: color[0] /= 360.0 # with angular hue?
while color[0] >= 1.0: color[0] -= 1.0 # rewind to proper range
while color[0] < 0.0: color[0] += 1.0 # rewind to proper range
self.model = model
self.color = np.array(color,'d')
# ------------------------------------------------------------------
# ------------------------------------------------------------------
def __repr__(self):
"""Color model and values"""
return 'Model: %s Color: %s'%(self.model,str(self.color))
# ------------------------------------------------------------------
# ------------------------------------------------------------------
def __str__(self):
"""Color model and values"""
return self.__repr__()
# ------------------------------------------------------------------
# ------------------------------------------------------------------
def convertTo(self,toModel = 'RGB'):
toModel = toModel.upper()
if toModel not in self.__transforms__.keys(): return
@ -73,17 +76,19 @@ class Color():
return self
# ------------------------------------------------------------------
# ------------------------------------------------------------------
def expressAs(self,asModel = 'RGB'):
return self.__class__(self.model,self.color).convertTo(asModel)
# ------------------------------------------------------------------
# convert H(ue) S(aturation) L(uminance) to R(red) G(reen) B(lue)
# with S,L,H,R,G,B running from 0 to 1
# from http://en.wikipedia.org/wiki/HSL_and_HSV
def _HSL2RGB(self):
def _HSL2RGB(self):
"""
convert H(ue) S(aturation) L(uminance) to R(red) G(reen) B(lue)
with S,L,H,R,G,B running from 0 to 1
from http://en.wikipedia.org/wiki/HSL_and_HSV
"""
if self.model != 'HSL': return
sextant = self.color[0]*6.0
@ -102,13 +107,14 @@ class Color():
self.model = converted.model
self.color = converted.color
# ------------------------------------------------------------------
# convert R(ed) G(reen) B(lue) to H(ue) S(aturation) L(uminance)
# with S,L,H,R,G,B running from 0 to 1
# from http://130.113.54.154/~monger/hsl-rgb.html
def _RGB2HSL(self):
"""
convert R(ed) G(reen) B(lue) to H(ue) S(aturation) L(uminance)
with S,L,H,R,G,B running from 0 to 1
from http://130.113.54.154/~monger/hsl-rgb.html
"""
if self.model != 'RGB': return
HSL = np.zeros(3,'d')
@ -129,7 +135,7 @@ class Color():
HSL[0] = 2.0 + (self.color[2] - self.color[0])/(maxcolor - mincolor)
elif (maxcolor == self.color[2]):
HSL[0] = 4.0 + (self.color[0] - self.color[1])/(maxcolor - mincolor)
HSL[0] = HSL[0]*60.0 # is it necessary to scale to 360 hue values? might be dangerous for small values <1..!
HSL[0] = HSL[0]*60.0 # scaling to 360 might be dangerous for small values
if (HSL[0] < 0.0):
HSL[0] = HSL[0] + 360.0
for i in xrange(2):
@ -141,12 +147,14 @@ class Color():
self.color = converted.color
# ------------------------------------------------------------------
# convert R(ed) G(reen) B(lue) to CIE XYZ
# with all values in the range of 0 to 1
# from http://www.cs.rit.edu/~ncs/color/t_convert.html
def _RGB2XYZ(self):
def _RGB2XYZ(self):
"""
convert R(ed) G(reen) B(lue) to CIE XYZ
with all values in the range of 0 to 1
from http://www.cs.rit.edu/~ncs/color/t_convert.html
"""
if self.model != 'RGB': return
XYZ = np.zeros(3,'d')
@ -168,12 +176,14 @@ class Color():
self.color = converted.color
# ------------------------------------------------------------------
# convert CIE XYZ to R(ed) G(reen) B(lue)
# with all values in the range of 0 to 1
# from http://www.cs.rit.edu/~ncs/color/t_convert.html
def _XYZ2RGB(self):
def _XYZ2RGB(self):
"""
convert CIE XYZ to R(ed) G(reen) B(lue)
with all values in the range of 0 to 1
from http://www.cs.rit.edu/~ncs/color/t_convert.html
"""
if self.model != 'XYZ': return
convert = np.array([[ 3.240479,-1.537150,-0.498535],
@ -189,7 +199,7 @@ class Color():
RGB[i] = min(RGB[i],1.0)
RGB[i] = max(RGB[i],0.0)
maxVal = max(RGB) # clipping colors according to the display gamut
maxVal = max(RGB) # clipping colors according to the display gamut
if (maxVal > 1.0): RGB /= maxVal
converted = Color('RGB', RGB)
@ -197,15 +207,17 @@ class Color():
self.color = converted.color
# ------------------------------------------------------------------
# convert CIE Lab to CIE XYZ
# with XYZ in the range of 0 to 1
# from http://www.easyrgb.com/index.php?X=MATH&H=07#text7
def _CIELAB2XYZ(self):
def _CIELAB2XYZ(self):
"""
convert CIE Lab to CIE XYZ
with XYZ in the range of 0 to 1
from http://www.easyrgb.com/index.php?X=MATH&H=07#text7
"""
if self.model != 'CIELAB': return
ref_white = np.array([.95047, 1.00000, 1.08883],'d') # Observer = 2, Illuminant = D65
ref_white = np.array([.95047, 1.00000, 1.08883],'d') # Observer = 2, Illuminant = D65
XYZ = np.zeros(3,'d')
XYZ[1] = (self.color[0] + 16.0 ) / 116.0
@ -220,16 +232,16 @@ class Color():
self.model = converted.model
self.color = converted.color
# ------------------------------------------------------------------
# convert CIE XYZ to CIE Lab
# with XYZ in the range of 0 to 1
# from http://en.wikipedia.org/wiki/Lab_color_space, http://www.cs.rit.edu/~ncs/color/t_convert.html
def _XYZ2CIELAB(self):
"""
convert CIE XYZ to CIE Lab
with XYZ in the range of 0 to 1
from http://en.wikipedia.org/wiki/Lab_color_space, http://www.cs.rit.edu/~ncs/color/t_convert.html
"""
if self.model != 'XYZ': return
ref_white = np.array([.95047, 1.00000, 1.08883],'d') # Observer = 2, Illuminant = D65
ref_white = np.array([.95047, 1.00000, 1.08883],'d') # Observer = 2, Illuminant = D65
XYZ = self.color/ref_white
for i in xrange(len(XYZ)):
@ -242,12 +254,13 @@ class Color():
self.model = converted.model
self.color = converted.color
# ------------------------------------------------------------------
# convert CIE Lab to Msh colorspace
# from http://www.cs.unm.edu/~kmorel/documents/ColorMaps/DivergingColorMapWorkshop.xls
def _CIELAB2MSH(self):
"""
convert CIE Lab to Msh colorspace
from http://www.cs.unm.edu/~kmorel/documents/ColorMaps/DivergingColorMapWorkshop.xls
"""
if self.model != 'CIELAB': return
Msh = np.zeros(3,'d')
@ -261,13 +274,14 @@ class Color():
self.model = converted.model
self.color = converted.color
# ------------------------------------------------------------------
# convert Msh colorspace to CIE Lab
# s,h in radians
# from http://www.cs.unm.edu/~kmorel/documents/ColorMaps/DivergingColorMapWorkshop.xls
def _MSH2CIELAB(self):
def _MSH2CIELAB(self):
"""
convert Msh colorspace to CIE Lab
s,h in radians
from http://www.cs.unm.edu/~kmorel/documents/ColorMaps/DivergingColorMapWorkshop.xls
"""
if self.model != 'MSH': return
Lab = np.zeros(3,'d')
@ -280,13 +294,8 @@ class Color():
self.color = converted.color
### --- COLORMAP CLASS -----------------------------------------------
class Colormap():
'''
perceptually uniform diverging or sequential colormaps.
'''
"""perceptually uniform diverging or sequential colormaps."""
__slots__ = [
'left',
@ -294,20 +303,40 @@ class Colormap():
'interpolate',
]
__predefined__ = {
'gray': {'left': Color('HSL',[0,1,1]), 'right': Color('HSL',[0,0,0.15]), 'interpolate': 'perceptualuniform'},
'grey': {'left': Color('HSL',[0,1,1]), 'right': Color('HSL',[0,0,0.15]), 'interpolate': 'perceptualuniform'},
'red': {'left': Color('HSL',[0,1,0.14]), 'right': Color('HSL',[0,0.35,0.91]), 'interpolate': 'perceptualuniform'},
'green': {'left': Color('HSL',[0.33333,1,0.14]), 'right': Color('HSL',[0.33333,0.35,0.91]), 'interpolate': 'perceptualuniform'},
'blue': {'left': Color('HSL',[0.66,1,0.14]), 'right': Color('HSL',[0.66,0.35,0.91]), 'interpolate': 'perceptualuniform'},
'seaweed': {'left': Color('HSL',[0.78,1.0,0.1]), 'right': Color('HSL',[0.40000,0.1,0.9]), 'interpolate': 'perceptualuniform'},
'bluebrown': {'left': Color('HSL',[0.65,0.53,0.49]), 'right': Color('HSL',[0.11,0.75,0.38]), 'interpolate': 'perceptualuniform'},
'redgreen': {'left': Color('HSL',[0.97,0.96,0.36]), 'right': Color('HSL',[0.33333,1.0,0.14]), 'interpolate': 'perceptualuniform'},
'bluered': {'left': Color('HSL',[0.65,0.53,0.49]), 'right': Color('HSL',[0.97,0.96,0.36]), 'interpolate': 'perceptualuniform'},
'blueredrainbow':{'left': Color('HSL',[2.0/3.0,1,0.5]), 'right': Color('HSL',[0,1,0.5]), 'interpolate': 'linear' },
'gray': {'left': Color('HSL',[0,1,1]),
'right': Color('HSL',[0,0,0.15]),
'interpolate': 'perceptualuniform'},
'grey': {'left': Color('HSL',[0,1,1]),
'right': Color('HSL',[0,0,0.15]),
'interpolate': 'perceptualuniform'},
'red': {'left': Color('HSL',[0,1,0.14]),
'right': Color('HSL',[0,0.35,0.91]),
'interpolate': 'perceptualuniform'},
'green': {'left': Color('HSL',[0.33333,1,0.14]),
'right': Color('HSL',[0.33333,0.35,0.91]),
'interpolate': 'perceptualuniform'},
'blue': {'left': Color('HSL',[0.66,1,0.14]),
'right': Color('HSL',[0.66,0.35,0.91]),
'interpolate': 'perceptualuniform'},
'seaweed': {'left': Color('HSL',[0.78,1.0,0.1]),
'right': Color('HSL',[0.40000,0.1,0.9]),
'interpolate': 'perceptualuniform'},
'bluebrown': {'left': Color('HSL',[0.65,0.53,0.49]),
'right': Color('HSL',[0.11,0.75,0.38]),
'interpolate': 'perceptualuniform'},
'redgreen': {'left': Color('HSL',[0.97,0.96,0.36]),
'right': Color('HSL',[0.33333,1.0,0.14]),
'interpolate': 'perceptualuniform'},
'bluered': {'left': Color('HSL',[0.65,0.53,0.49]),
'right': Color('HSL',[0.97,0.96,0.36]),
'interpolate': 'perceptualuniform'},
'blueredrainbow':{'left': Color('HSL',[2.0/3.0,1,0.5]),
'right': Color('HSL',[0,1,0.5]),
'interpolate': 'linear' },
}
# ------------------------------------------------------------------
# ------------------------------------------------------------------
def __init__(self,
left = Color('RGB',[1,1,1]),
right = Color('RGB',[0,0,0]),
@ -330,26 +359,27 @@ class Colormap():
self.interpolate = interpolate
# ------------------------------------------------------------------
# ------------------------------------------------------------------
def __repr__(self):
"""left and right value of colormap"""
return 'Left: %s Right: %s'%(self.left,self.right)
# ------------------------------------------------------------------
# ------------------------------------------------------------------
def invert(self):
(self.left, self.right) = (self.right, self.left)
return self
# ------------------------------------------------------------------
# ------------------------------------------------------------------
def color(self,fraction = 0.5):
def interpolate_Msh(lo, hi, frac):
def rad_diff(a,b):
return abs(a[2]-b[2])
def adjust_hue(Msh_sat, Msh_unsat): # if saturation of one of the two colors is too less than the other, hue of the less
# if saturation of one of the two colors is too less than the other, hue of the less
def adjust_hue(Msh_sat, Msh_unsat):
if Msh_sat[0] >= Msh_unsat[0]:
return Msh_sat[2]
else:
@ -375,10 +405,11 @@ class Colormap():
return Color('MSH',Msh)
def interpolate_linear(lo, hi, frac):
'''
linearly interpolate color at given fraction between lower and higher color in model of lower color
'''
"""
linearly interpolate color at given fraction between lower and
higher color in model of lower color
"""
interpolation = (1.0 - frac) * np.array(lo.color[:]) \
+ frac * np.array(hi.expressAs(lo.model).color[:])
@ -393,23 +424,23 @@ class Colormap():
else:
raise NameError('unknown color interpolation method')
# ------------------------------------------------------------------
# ------------------------------------------------------------------
def export(self,name = 'uniformPerceptualColorMap',\
format = 'paraview',\
steps = 2,\
crop = [-1.0,1.0],
model = 'RGB'):
'''
"""
[RGB] colormap for use in paraview or gmsh, or as raw string, or array.
arguments: name, format, steps, crop.
format is one of (paraview, gmsh, raw, list).
crop selects a (sub)range in [-1.0,1.0].
generates sequential map if one limiting color is either white or black,
diverging map otherwise.
'''
format = format.lower() # consistent comparison basis
frac = 0.5*(np.array(crop) + 1.0) # rescale crop range to fractions
"""
format = format.lower() # consistent comparison basis
frac = 0.5*(np.array(crop) + 1.0) # rescale crop range to fractions
colors = [self.color(float(i)/(steps-1)*(frac[1]-frac[0])+frac[0]).expressAs(model).color for i in xrange(steps)]
if format == 'paraview':
@ -439,4 +470,4 @@ class Colormap():
raise NameError('unknown color export format')
return '\n'.join(colormap) + '\n' if type(colormap[0]) is str else colormap

View File

@ -1,5 +1,5 @@
# -*- coding: UTF-8 no BOM -*-
# $Id$
"""Aggregator for configuration file handling"""
from .material import Material
from .material import Material # noqa

View File

@ -100,20 +100,19 @@ class Texture(Section):
class Material():
'''
Reads, manipulates and writes material.config files
'''
"""Reads, manipulates and writes material.config files"""
__slots__ = ['data']
def __init__(self,verbose=True):
"""generates ordered list of parts"""
self.parts = [
'homogenization',
'microstructure',
'crystallite',
'phase',
'texture',
] # ordered (!) list of parts
]
self.data = {\
'homogenization': {'__order__': []},
'microstructure': {'__order__': []},
@ -124,6 +123,7 @@ class Material():
self.verbose = verbose
def __repr__(self):
"""returns current configuration to be used as material.config"""
me = []
for part in self.parts:
if self.verbose: print('doing '+part)
@ -144,7 +144,6 @@ class Material():
re_sec = re.compile(r'^\[(.+)\]$') # pattern for section
name_section = ''
idx_section = 0
active = False
for line in content:
@ -197,8 +196,7 @@ class Material():
return saveFile
def add_section(self, part=None, section=None, initialData=None, merge = False):
'''adding/updating'''
"""adding/updating"""
part = part.lower()
section = section.lower()
if part not in self.parts: raise Exception('invalid part %s'%part)
@ -227,10 +225,10 @@ class Material():
def add_microstructure(self, section='',
components={}, # dict of phase,texture, and fraction lists
):
''' Experimental! Needs expansion to multi-constituent microstructures...'''
"""Experimental! Needs expansion to multi-constituent microstructures..."""
microstructure = Microstructure()
components=dict((k.lower(), v) for k,v in components.iteritems()) # make keys lower case (http://stackoverflow.com/questions/764235/dictionary-to-lowercase-in-python)
# make keys lower case (http://stackoverflow.com/questions/764235/dictionary-to-lowercase-in-python)
components=dict((k.lower(), v) for k,v in components.iteritems())
for key in ['phase','texture','fraction','crystallite']:
if type(components[key]) is not list:
@ -245,7 +243,8 @@ class Material():
except AttributeError:
pass
for (phase,texture,fraction,crystallite) in zip(components['phase'],components['texture'],components['fraction'],components['crystallite']):
for (phase,texture,fraction,crystallite) in zip(components['phase'],components['texture'],
components['fraction'],components['crystallite']):
microstructure.add_multiKey('constituent','phase %i\ttexture %i\tfraction %g\ncrystallite %i'%(
self.data['phase']['__order__'].index(phase)+1,
self.data['texture']['__order__'].index(texture)+1,
@ -259,8 +258,8 @@ class Material():
section=None,
key=None,
value=None):
if type(value) is not type([]):
if type(value) is not type('s'):
if not isinstance(value,list):
if not isinstance(value,str):
value = '%s'%value
value = [value]
newlen = len(value)
@ -271,17 +270,3 @@ class Material():
if newlen is not oldlen:
print('Length of value was changed from %i to %i!'%(oldlen,newlen))
def ex1():
mat=Material()
p=Phase({'constitution':'lump'})
t=Texture()
t.add_component('gauss',{'eulers':[1,2,3]})
mat.add_section('phase','phase1',p)
mat.add_section('texture','tex1',t)
mat.add_microstructure('mustruct1',{'phase':['phase1']*2,'texture':['tex1']*2,'fraction':[0.2]*2})
print(mat)
mat.write(file='poop')
mat.write(file='poop',overwrite=True)

View File

@ -2,7 +2,7 @@
# $Id$
import os,sys,string,re,subprocess,shlex
import os,subprocess,shlex
class Environment():
__slots__ = [ \

View File

@ -1,7 +1,7 @@
# -*- coding: UTF-8 no BOM -*-
# $Id$
"""Aggregator for geometry handling"""
from .geometry import Geometry # only one class
from .spectral import Spectral # only one class
from .marc import Marc # only one class
from .geometry import Geometry # noqa
from .spectral import Spectral # noqa
from .marc import Marc # noqa

View File

@ -5,10 +5,11 @@
import damask.geometry
class Geometry():
'''
General class for geometry parsing.
Sub-classed by the individual solvers.
'''
"""
General class for geometry parsing.
Sub-classed by the individual solvers.
"""
def __init__(self,solver=''):
solverClass = {

View File

@ -9,7 +9,6 @@ import numpy as np
# ******************************************************************************************
class Rodrigues:
# ******************************************************************************************
def __init__(self, vector = np.zeros(3)):
self.vector = vector
@ -28,20 +27,22 @@ class Rodrigues:
# ******************************************************************************************
class Quaternion:
# ******************************************************************************************
# All methods and naming conventions based off
# http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions
"""
Orientation represented as unit quaternion
All methods and naming conventions based on http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions
# w is the real part, (x, y, z) are the imaginary parts
# Representation of rotation is in ACTIVE form!
# (derived directly or through angleAxis, Euler angles, or active matrix)
# vector "a" (defined in coordinate system "A") is actively rotated to new coordinates "b"
# b = Q * a
# b = np.dot(Q.asMatrix(),a)
w is the real part, (x, y, z) are the imaginary parts
Representation of rotation is in ACTIVE form!
(derived directly or through angleAxis, Euler angles, or active matrix)
vector "a" (defined in coordinate system "A") is actively rotated to new coordinates "b"
b = Q * a
b = np.dot(Q.asMatrix(),a)
"""
def __init__(self,
quatArray = [1.0,0.0,0.0,0.0]):
"""initializes to identity if not given"""
self.w, \
self.x, \
self.y, \
@ -49,19 +50,23 @@ class Quaternion:
self.homomorph()
def __iter__(self):
"""components"""
return iter([self.w,self.x,self.y,self.z])
def __copy__(self):
"""create copy"""
Q = Quaternion([self.w,self.x,self.y,self.z])
return Q
copy = __copy__
def __repr__(self):
"""readbable string"""
return 'Quaternion(real=%+.6f, imag=<%+.6f, %+.6f, %+.6f>)' % \
(self.w, self.x, self.y, self.z)
def __pow__(self, exponent):
"""power"""
omega = math.acos(self.w)
vRescale = math.sin(exponent*omega)/math.sin(omega)
Q = Quaternion()
@ -72,6 +77,7 @@ class Quaternion:
return Q
def __ipow__(self, exponent):
"""in place power"""
omega = math.acos(self.w)
vRescale = math.sin(exponent*omega)/math.sin(omega)
self.w = np.cos(exponent*omega)
@ -81,6 +87,7 @@ class Quaternion:
return self
def __mul__(self, other):
"""multiplication"""
try: # quaternion
Aw = self.w
Ax = self.x
@ -128,6 +135,7 @@ class Quaternion:
return self.copy()
def __imul__(self, other):
"""in place multiplication"""
try: # Quaternion
Ax = self.x
Ay = self.y
@ -145,6 +153,7 @@ class Quaternion:
return self
def __div__(self, other):
"""division"""
if isinstance(other, (int,float,long)):
w = self.w / other
x = self.x / other
@ -155,6 +164,7 @@ class Quaternion:
return NotImplemented
def __idiv__(self, other):
"""in place division"""
if isinstance(other, (int,float,long)):
self.w /= other
self.x /= other
@ -163,6 +173,7 @@ class Quaternion:
return self
def __add__(self, other):
"""addition"""
if isinstance(other, Quaternion):
w = self.w + other.w
x = self.x + other.x
@ -173,6 +184,7 @@ class Quaternion:
return NotImplemented
def __iadd__(self, other):
"""in place division"""
if isinstance(other, Quaternion):
self.w += other.w
self.x += other.x
@ -181,6 +193,7 @@ class Quaternion:
return self
def __sub__(self, other):
"""subtraction"""
if isinstance(other, Quaternion):
Q = self.copy()
Q.w -= other.w
@ -192,6 +205,7 @@ class Quaternion:
return self.copy()
def __isub__(self, other):
"""in place subtraction"""
if isinstance(other, Quaternion):
self.w -= other.w
self.x -= other.x
@ -200,6 +214,7 @@ class Quaternion:
return self
def __neg__(self):
"""additive inverse"""
self.w = -self.w
self.x = -self.x
self.y = -self.y
@ -207,6 +222,7 @@ class Quaternion:
return self
def __abs__(self):
"""norm"""
return math.sqrt(self.w ** 2 + \
self.x ** 2 + \
self.y ** 2 + \
@ -215,6 +231,7 @@ class Quaternion:
magnitude = __abs__
def __eq__(self,other):
"""equal at e-8 precision"""
return (abs(self.w-other.w) < 1e-8 and \
abs(self.x-other.x) < 1e-8 and \
abs(self.y-other.y) < 1e-8 and \
@ -226,9 +243,11 @@ class Quaternion:
abs(-self.z-other.z) < 1e-8)
def __ne__(self,other):
"""not equal at e-8 precision"""
return not self.__eq__(self,other)
def __cmp__(self,other):
"""linear ordering"""
return cmp(self.Rodrigues(),other.Rodrigues())
def magnitude_squared(self):
@ -290,9 +309,10 @@ class Quaternion:
return np.outer([i for i in self],[i for i in self])
def asMatrix(self):
return np.array([[1.0-2.0*(self.y*self.y+self.z*self.z), 2.0*(self.x*self.y-self.z*self.w), 2.0*(self.x*self.z+self.y*self.w)],
[ 2.0*(self.x*self.y+self.z*self.w), 1.0-2.0*(self.x*self.x+self.z*self.z), 2.0*(self.y*self.z-self.x*self.w)],
[ 2.0*(self.x*self.z-self.y*self.w), 2.0*(self.x*self.w+self.y*self.z), 1.0-2.0*(self.x*self.x+self.y*self.y)]])
return np.array(
[[1.0-2.0*(self.y*self.y+self.z*self.z), 2.0*(self.x*self.y-self.z*self.w), 2.0*(self.x*self.z+self.y*self.w)],
[ 2.0*(self.x*self.y+self.z*self.w), 1.0-2.0*(self.x*self.x+self.z*self.z), 2.0*(self.y*self.z-self.x*self.w)],
[ 2.0*(self.x*self.z-self.y*self.w), 2.0*(self.x*self.w+self.y*self.z), 1.0-2.0*(self.x*self.x+self.y*self.y)]])
def asAngleAxis(self,
degrees = False):
@ -315,15 +335,17 @@ class Quaternion:
return np.inf*np.ones(3) if self.w == 0.0 else np.array([self.x, self.y, self.z])/self.w
def asEulers(self,
type = 'bunge',
type = "bunge",
degrees = False,
standardRange = False):
'''
u"""
Orientation as Bunge-Euler angles
conversion of ACTIVE rotation to Euler angles taken from:
Melcher, A.; Unser, A.; Reichhardt, M.; Nestler, B.; Pötschke, M.; Selzer, M.
Conversion of EBSD data by a quaternion based algorithm to be used for grain structure simulations
Technische Mechanik 30 (2010) pp 401--413
'''
"""
angles = [0.0,0.0,0.0]
if type.lower() == 'bunge' or type.lower() == 'zxz':
@ -369,7 +391,7 @@ class Quaternion:
@classmethod
def fromRandom(cls,randomSeed = None):
if randomSeed == None:
if randomSeed is None:
randomSeed = int(os.urandom(4).encode('hex'), 16)
np.random.seed(randomSeed)
r = np.random.random(3)
@ -420,7 +442,6 @@ class Quaternion:
y = - c1 * s2 * s3 + s1 * s2 * c3
z = c1 * c2 * s3 + s1 * c2 * c3
else:
# print 'unknown Euler convention'
w = c1 * c2 * c3 - s1 * s2 * s3
x = s1 * s2 * c3 + c1 * c2 * s3
y = s1 * c2 * c3 + c1 * s2 * s3
@ -428,7 +449,8 @@ class Quaternion:
return cls([w,x,y,z])
## Modified Method to calculate Quaternion from Orientation Matrix, Source: http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/
# Modified Method to calculate Quaternion from Orientation Matrix,
# Source: http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/
@classmethod
def fromMatrix(cls, m):
@ -482,8 +504,12 @@ class Quaternion:
@classmethod
def new_interpolate(cls, q1, q2, t):
# see http://ntrs.nasa.gov/archive/nasa/casi.ntrs.nasa.gov/20070017872_2007014421.pdf for (another?) way to interpolate quaternions
"""
interpolation
see http://ntrs.nasa.gov/archive/nasa/casi.ntrs.nasa.gov/20070017872_2007014421.pdf
for (another?) way to interpolate quaternions
"""
assert isinstance(q1, Quaternion) and isinstance(q2, Quaternion)
Q = cls()
@ -522,11 +548,11 @@ class Quaternion:
# ******************************************************************************************
class Symmetry:
# ******************************************************************************************
lattices = [None,'orthorhombic','tetragonal','hexagonal','cubic',]
def __init__(self, symmetry = None):
"""lattice with given symmetry, defaults to None"""
if isinstance(symmetry, basestring) and symmetry.lower() in Symmetry.lattices:
self.lattice = symmetry.lower()
else:
@ -534,29 +560,31 @@ class Symmetry:
def __copy__(self):
"""copy"""
return self.__class__(self.lattice)
copy = __copy__
def __repr__(self):
"""readbable string"""
return '%s' % (self.lattice)
def __eq__(self, other):
"""equal"""
return self.lattice == other.lattice
def __neq__(self, other):
"""not equal"""
return not self.__eq__(other)
def __cmp__(self,other):
"""linear ordering"""
return cmp(Symmetry.lattices.index(self.lattice),Symmetry.lattices.index(other.lattice))
def symmetryQuats(self,who = []):
'''
List of symmetry operations as quaternions.
'''
"""List of symmetry operations as quaternions."""
if self.lattice == 'cubic':
symQuats = [
[ 1.0, 0.0, 0.0, 0.0 ],
@ -629,18 +657,15 @@ class Symmetry:
def equivalentQuaternions(self,
quaternion,
who = []):
'''
List of symmetrically equivalent quaternions based on own symmetry.
'''
"""List of symmetrically equivalent quaternions based on own symmetry."""
return [quaternion*q for q in self.symmetryQuats(who)]
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
R = abs(R) # fundamental zone in Rodrigues space is point symmetric around origin
# fundamental zone in Rodrigues space is point symmetric around origin
R = abs(R)
if self.lattice == 'cubic':
return math.sqrt(2.0)-1.0 >= R[0] \
and math.sqrt(2.0)-1.0 >= R[1] \
@ -662,12 +687,13 @@ class Symmetry:
def inDisorientationSST(self,R):
'''
"""
Check whether given Rodrigues vector (of misorientation) falls into standard stereographic triangle of own symmetry.
Determination of disorientations follow the work of A. Heinz and P. Neumann:
Representation of Orientation and Disorientation Data for Cubic, Hexagonal, Tetragonal and Orthorhombic Crystals
Acta Cryst. (1991). A47, 780-789
'''
"""
if isinstance(R, Quaternion): R = R.asRodrigues() # translate accidentially passed quaternion
epsilon = 0.0
@ -691,11 +717,12 @@ class Symmetry:
vector,
proper = False,
color = False):
'''
"""
Check whether given vector falls into standard stereographic triangle of own symmetry.
proper considers only vectors with z >= 0, hence uses two neighboring SSTs.
Return inverse pole figure color if requested.
'''
"""
# basis = {'cubic' : np.linalg.inv(np.array([[0.,0.,1.], # direction of red
# [1.,0.,1.]/np.sqrt(2.), # direction of green
# [1.,1.,1.]/np.sqrt(3.)]).transpose()), # direction of blue
@ -752,15 +779,15 @@ class Symmetry:
inSST = np.all(theComponents >= 0.0)
else:
v = np.array(vector,dtype = float)
if proper: # check both improper ...
if proper: # check both improper ...
theComponents = np.dot(basis['improper'],v)
inSST = np.all(theComponents >= 0.0)
if not inSST: # ... and proper SST
theComponents = np.dot(basis['proper'],v)
inSST = np.all(theComponents >= 0.0)
else:
v[2] = abs(v[2]) # z component projects identical for positive and negative values
theComponents = np.dot(basis['improper'],v)
v[2] = abs(v[2]) # z component projects identical
theComponents = np.dot(basis['improper'],v) # for positive and negative values
inSST = np.all(theComponents >= 0.0)
if color: # have to return color array
@ -781,7 +808,6 @@ class Symmetry:
# ******************************************************************************************
class Orientation:
# ******************************************************************************************
__slots__ = ['quaternion','symmetry']
@ -791,7 +817,7 @@ class Orientation:
angleAxis = None,
matrix = None,
Eulers = None,
random = False, # put any integer to have a fixed seed or True for real random
random = False, # integer to have a fixed seed or True for real random
symmetry = None,
):
if random: # produce random orientation
@ -815,12 +841,14 @@ class Orientation:
self.symmetry = Symmetry(symmetry)
def __copy__(self):
"""copy"""
return self.__class__(quaternion=self.quaternion,symmetry=self.symmetry.lattice)
copy = __copy__
def __repr__(self):
"""value as all implemented representations"""
return 'Symmetry: %s\n' % (self.symmetry) + \
'Quaternion: %s\n' % (self.quaternion) + \
'Matrix:\n%s\n' % ( '\n'.join(['\t'.join(map(str,self.asMatrix()[i,:])) for i in range(3)]) ) + \
@ -863,10 +891,7 @@ class Orientation:
self.equivalentQuaternions(who))
def reduced(self):
'''
Transform orientation to fall into fundamental zone according to symmetry
'''
"""Transform orientation to fall into fundamental zone according to symmetry"""
for me in self.symmetry.equivalentQuaternions(self.quaternion):
if self.symmetry.inFZ(me.asRodrigues()): break
@ -876,13 +901,13 @@ class Orientation:
def disorientation(self,
other,
SST = True):
'''
"""
Disorientation between myself and given other orientation.
Rotation axis falls into SST if SST == True.
(Currently requires same symmetry for both orientations.
Look into A. Heinz and P. Neumann 1991 for cases with differing sym.)
'''
"""
if self.symmetry != other.symmetry: raise TypeError('disorientation between different symmetry classes not supported yet.')
misQ = self.quaternion.conjugated()*other.quaternion
@ -900,32 +925,27 @@ class Orientation:
if breaker: break
if breaker: break
# disorientation, own sym, other sym, self-->other: True, self<--other: False
return (Orientation(quaternion = theQ,symmetry = self.symmetry.lattice),
i,j,k == 1) # disorientation, own sym, other sym, self-->other: True, self<--other: False
i,j,k == 1)
def inversePole(self,
axis,
proper = False,
SST = True):
'''
axis rotated according to orientation (using crystal symmetry to ensure location falls into SST)
'''
"""axis rotated according to orientation (using crystal symmetry to ensure location falls into SST)"""
if SST: # pole requested to be within SST
for i,q in enumerate(self.symmetry.equivalentQuaternions(self.quaternion)): # test all symmetric equivalent quaternions
pole = q.conjugated()*axis # align crystal direction to axis
if self.symmetry.inSST(pole,proper): break # found SST version
if self.symmetry.inSST(pole,proper): break # found SST version
else:
pole = self.quaternion.conjugated()*axis # align crystal direction to axis
return (pole,i if SST else 0)
def IPFcolor(self,axis):
'''
TSL color of inverse pole figure for given axis
'''
"""TSL color of inverse pole figure for given axis"""
color = np.zeros(3,'d')
for q in self.symmetry.equivalentQuaternions(self.quaternion):
@ -939,7 +959,9 @@ class Orientation:
def average(cls,
orientations,
multiplicity = []):
"""RETURN THE AVERAGE ORIENTATION
"""
average orientation
ref: F. Landis Markley, Yang Cheng, John Lucas Crassidis, and Yaakov Oshman.
Averaging Quaternions,
Journal of Guidance, Control, and Dynamics, Vol. 30, No. 4 (2007), pp. 1193-1197.
@ -949,7 +971,6 @@ class Orientation:
b = Orientation(Eulers=np.radians([20, 0, 0]), symmetry='hexagonal')
avg = Orientation.average([a,b])
"""
if not all(isinstance(item, Orientation) for item in orientations):
raise TypeError("Only instances of Orientation can be averaged.")
@ -960,8 +981,7 @@ class Orientation:
reference = orientations[0] # take first as reference
for i,(o,n) in enumerate(zip(orientations,multiplicity)):
closest = o.equivalentOrientations(reference.disorientation(o,SST = False)[2])[0] # select sym orientation with lowest misorientation
M = closest.quaternion.asM() * n if i == 0 else M + closest.quaternion.asM() * n # add (multiples) of this orientation to average
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)
return Orientation(quaternion = Quaternion(quatArray = np.real(vec.T[eig.argmax()])),

View File

@ -11,10 +11,11 @@ except (ImportError) as e:
sys.stderr.write('\nREMARK: h5py module not available \n\n')
class Result():
'''
General class for result parsing.
Needs h5py to be installed
'''
"""
General class for result parsing.
Needs h5py to be installed
"""
def __init__(self,resultsFile):
self.data=h5py.File(resultsFile,"r")

View File

@ -1,6 +1,5 @@
# -*- coding: UTF-8 no BOM -*-
# $Id$
# This tool converts a msc.marc result file into the vtk format that
# can be viewed by Paraview software (Kitware), or MayaVi (needs xml-vtk, or ...
#
@ -8,13 +7,8 @@
# Some example vtk files: http://people.sc.fsu.edu/~jburkardt/data/vtk/vtk.html
# www.paraview.org
import os,sys,math,time,re
# python external
try:
import numpy as N
import numpy
except:
print('Could not import numpy.')
import os,sys,re
import numpy as np
import py_post # MSC closed source module to access marc result files
@ -27,7 +21,7 @@ class MARC_POST():
self.fpath=os.path.join(self.projdir,self.postname)
print('Trying to open ',self.fpath,' ...')
self.p=py_post.post_open(self.fpath)
if self.p==None:
if self.p is None:
print('Could not open %s.'%self.postname); #return 'err'#; sys.exit(1)
raise Exception('Could not open t16')
print('Postfile %s%s is open ...'%(self.projdir,self.postname))
@ -105,7 +99,6 @@ class MARC_POST():
def writeNodes2VTK(self, fobj):
self.points=[]
self.VTKcnt=200 # number of values per line in vtk file
ndCnt=1
fobj.write('POINTS %i'%self.p.nodes()+' float\n')
self.nodes_dict={} # store the node IDs in case of holes in the numbering
for iNd in self.nodes:
@ -126,8 +119,6 @@ class MARC_POST():
el=self.p.element(iEl)
cell_nodes=[] # for pyvtk
ndlist=el.items
#for k in [0, 1, 3, 2, 4, 5, 7, 6]: # FOR CELL TPYE VTK_VOXEL
#for k in [0, 4, 3, 1, 5, 7, 6, 2]:
for k in [0, 1, 2, 3, 4, 5, 6, 7]: # FOR CELL TYPE VTK_HEXAHEDRON
node=ndlist[k]-1
cell_nodes.append(self.nodes_dict[node])
@ -147,7 +138,6 @@ class MARC_POST():
fobj.write('\n');cnt=0
fobj.write('\n')
print('Elements written to VTK: %i'%self.p.elements())
#print('Nr of nodes: ',self.nodes)
def writeElScalars2NodesVTK(self,fobj):
fobj.write('\nPOINT_DATA %i\n'%self.p.nodes())
@ -157,7 +147,6 @@ class MARC_POST():
fobj.write('LOOKUP_TABLE default\n')
idxScal=self.nscal_list.index('Displacement Z')
for iNd in self.nodes:
#fobj.write('%f %f '%(self.p.node_scalar(iNd,idxScal), N.random.rand()))
fobj.write('%f '%(self.p.node_scalar(iNd,idxScal)))
for iEl in range(0,self.nel):
el=self.p.element(iEl)
@ -173,8 +162,6 @@ class MARC_POST():
def writeNodeScalars2VTK(self,fobj):
fobj.write('\nPOINT_DATA %i\n'%self.p.nodes())
nNdDat=self.nscals
nComponents=1+nNdDat
self.pointDataScalars=[]
for idxNdScal in range(-3,self.nscals): #now include node x,y,z
if idxNdScal>=0:
@ -209,8 +196,6 @@ class MARC_POST():
idx_sig_vMises=self.getLabelNr('Equivalent Von Mises Stress')
idx_sig33=self.getLabelNr('Comp 33 of Cauchy Stress')
fobj.write('\nCELL_DATA %i\n'%self.p.elements())
nElDat=self.elscals
nComponents=1+nElDat
for idxElScal in range(0,self.elscals):
datalabel=self.elscal_list[idxElScal]
datalabel=re.sub("\s",'_',datalabel)
@ -250,19 +235,16 @@ class MARC_POST():
result.append(avgScal)
return result
def writeUniaxiality2VTK(self,fobj):
#fobj.write('\nCELL_DATA %i\n'%self.p.elements())
def writeUniaxiality2VTK(self,fobj):
datalabel='uniaxiality_sig_vMises_durch_sig33'
fobj.write('SCALARS %s float %i\n'%(datalabel,1))
fobj.write('LOOKUP_TABLE default\n')
cnt=0
for iEl in range(0,self.nel):
cnt=cnt+1
#if abs(self.sig33[iEl])<1e-5:
if abs(self.sig_vMises[iEl])<1e-5:
datum=0.
else:
#datum=self.sig_vMises[iEl]/self.sig33[iEl]
datum=self.sig33[iEl]/self.sig_vMises[iEl]
fobj.write('%E '%(datum))
if cnt>self.VTKcnt:
@ -283,8 +265,8 @@ class MARC_POST():
self.mean_stress.append(self.meanStress(sig))
def triaxiality_per_element(self):
# classical triaxiality
# 1/3 : uniax tension
# classical triaxiality
# 1/3 : uniax tension
self.triaxiality=[]
for iEl in range(0,self.nel):
t=self.mean_stress[iEl]/self.sig_vMises[iEl]
@ -303,10 +285,6 @@ class MARC_POST():
fobj.write('\n')
def calc_lode_parameter(self):
# [-1 ... +1] see e.g. Wippler & Boehlke triaxiality measures doi:10.1002/pamm.201010061
# +1 : uniax tensile?
# 0 : shear
# -1 : uniax compr ?
self.lode=[]
try:
self.stress
@ -328,10 +306,11 @@ class MARC_POST():
def princStress(self, stress):
"""
Function to compute 3D principal stresses and sort them.
from: http://geodynamics.org/svn/cig/short/3D/PyLith/trunk/playpen/postproc/vtkcff.py
"""
stressMat=N.array(stress)
(princStress, princAxes) = numpy.linalg.eigh(stressMat)
stressMat=np.array(stress)
(princStress, princAxes) = np.linalg.eigh(stressMat)
idx = princStress.argsort()
princStressOrdered = princStress[idx]
princAxesOrdered = princAxes[:,idx]
@ -339,36 +318,28 @@ class MARC_POST():
def avg_elten(self,
idxElTen, mat=0, elID=None):
tensum=N.zeros((3,3));
T=N.zeros((3,3));
tensum=np.zeros((3,3));
T=np.zeros((3,3));
pts=0;
avg=N.zeros((3,3));
#print 'Element Scalars'
#print self.p.element_scalar_label(elscal2)
if elID==None:
avg=np.zeros((3,3));
if elID is None:
averaged_elements=range(0,self.nel)
else:
averaged_elements=[elID]
#for i in range (0,self.nel):
for i in averaged_elements:
if mat==0 or int(self.p.element_scalar(i,4)[0].value)==mat:
eldata=self.p.element(i)
T=self.p.element_tensor(i,idxElTen)
for k in range (0,8):
tensum[0][0] = tensum[0][0] + T[k].t11
tensum[0][1] = tensum[0][1] + T[k].t12
tensum[0][2] = tensum[0][2] + T[k].t13
#tensum1[1][0] = tensum1[1][0] + T1[k].t21
tensum[1][1] = tensum[1][1] + T[k].t22
tensum[1][2] = tensum[1][2] + T[k].t23
#tensum1[2][0] = tensum1[2][0] + T1[k].t31
#tensum1[2][1] = tensum1[2][1] + T1[k].t32
tensum[2][2] = tensum[2][2] + T[k].t33
pts=pts+1
avg=tensum/pts
#print avg
avg=self.fillComponents(avg)
#print avg
del [T]
return (avg,tensum,pts)
@ -384,7 +355,7 @@ class MARC_POST():
t=tensor33
s=(t[0,0]-t[1,1])**2+(t[1,1]-t[2,2])**2+(t[0,0]-t[2,2])**2+\
6*(t[0,1]**2+t[1,2]**2+t[2,0]**2)
vM=N.sqrt(s/2.)
vM=np.sqrt(s/2.)
return vM
def meanStress(self,tensor33):
@ -397,8 +368,7 @@ class MARC_POST():
t=tensor33
I1=t[0,0]+t[1,1]+t[2,2]
I2=t[0,0]*t[1,1]+t[1,1]*t[2,2]+t[0,0]*t[2,2]-\
t[0,1]**2-t[1,2]**2-t[0,2]**2
# I3 = det(t)
t[0,1]**2-t[1,2]**2-t[0,2]**2
I3=t[0,0]*t[1,1]*t[2,2]+\
2*t[0,1]*t[1,2]*t[2,0]-\
t[2,2]*t[0,1]**2-t[0,0]*t[1,2]**2-t[1,1]*t[0,2]**2
@ -406,17 +376,18 @@ class MARC_POST():
class VTK_WRITER():
'''
The resulting vtk-file can be imported in Paraview 3.12
Then use Filters: Cell Data to Point Data + Contour
to plot semi-transparent iso-surfaces.
'''
"""
The resulting vtk-file can be imported in Paraview 3.12
Then use Filters: Cell Data to Point Data + Contour
to plot semi-transparent iso-surfaces.
"""
import re
def __init__(self):
self.p=MARC_POST() # self.p
def openFile(self, filename='test.vtp'):
#if not self.f:#==None:
self.f=open(filename,'w+')
self.fname=filename
@ -427,7 +398,7 @@ class VTK_WRITER():
dformat='ASCII', # BINARY | [ASCII]
dtype='UNSTRUCTURED_GRID' # UNSTRUCTURED GRID
):
if vtkFile==None:
if vtkFile is None:
vtkFile=self.f
# First Line contains Data format version
self.versionVTK=version
@ -440,7 +411,6 @@ class VTK_WRITER():
def marc2vtkBatch(self):
for iori in range(1,63):
#self.p=msc_post.MSC_POST()
self.p.postname='indent_fric0.3_R2.70_cA146.0_h0.320_ori%03i_OST_h19d.t16'%(iori)
if os.path.exists(self.p.postname):
self.marc2vtk(mode='fast', batchMode=1)
@ -496,14 +466,14 @@ class VTK_WRITER():
def scaleBar(self, length=1.0, posXYZ=[0., 0., 0.]):
self.fsb=open('micronbar_l%.1f.vtp'%length,'w+')
self.writeFirstLines(self.fsb, comment='micronbar')
pts=N.array([])
pts=np.array([])
width=length*1.
height=length*1.
wVec=N.array([0., width, 0.])
lVec=N.array([length,0.,0.])
hVec=N.array([0.,0.,height])
wVec=np.array([0., width, 0.])
lVec=np.array([length,0.,0.])
hVec=np.array([0.,0.,height])
posXYZ=posXYZ-0.5*wVec-0.5*lVec#-0.5*hVec # CENTERING Y/N
posXYZ=N.array(posXYZ)
posXYZ=np.array(posXYZ)
pts=[posXYZ, posXYZ+lVec,
posXYZ+wVec,
posXYZ+wVec+lVec]
@ -514,34 +484,22 @@ class VTK_WRITER():
self.fsb.write('%f %f %f\n'%(pts[npts][0], pts[npts][1], pts[npts][2]))
if 1: #Triad
nCells=3
#nCells=1 #One Line
ptsPerCell=2 # Lines (Type=3)
#ptsPerCell=4 # Quads (Type=9)
#ptsPerCell=8 # Hexahedron (Type=12)
cellSize=(ptsPerCell+1)*nCells
self.fsb.write('CELLS %i %i\n'%(nCells,cellSize))
self.fsb.write('2 0 1\n') #X-Line
self.fsb.write('2 0 2\n') #Y-Line
self.fsb.write('2 0 4\n') #Z-Line
#self.fsb.write('4 0 1 3 2\n') #Quad
#self.fsb.write('%i 0 1 3 2 4 5 7 6\n'%ptsPerCell) #Hexahedron
self.fsb.write('CELL_TYPES %i\n'%(nCells))
self.fsb.write('3\n3\n3\n')#Line
#self.fsb.write('12\n')#Hexahedron
else: # Cube, change posXYZ
nCells=1
ptsPerCell=2 # Lines (Type=3)
#ptsPerCell=4 # Quads (Type=9)
#ptsPerCell=8 # Hexahedron (Type=12)
cellSize=(ptsPerCell+1)*nCells
self.fsb.write('CELLS %i %i\n'%(nCells,cellSize))
self.fsb.write('2 0 1\n') #Line
#self.fsb.write('4 0 1 3 2\n') #Quad
#self.fsb.write('%i 0 1 3 2 4 5 7 6\n'%ptsPerCell) #Hexahedron
self.fsb.write('CELL_TYPES %i\n'%(nCells))
self.fsb.write('3\n')#Line
#self.fsb.write('12\n')#Hexahedron
self.fsb.write('\n')
self.fsb.close()
@ -549,8 +507,7 @@ class VTK_WRITER():
def example_unstructured(self):
self.openFile(filename='example_unstructured_grid.vtk')
#self.writeFirstLines()
self.f.write('''
self.f.write("""
# vtk DataFile Version 2.0
example_unstruct_grid
ASCII
@ -590,61 +547,40 @@ LOOKUP_TABLE default
1.02
1.50
0.00
3 5 6 23423423423423423423.23423423''')
3 5 6 23423423423423423423.23423423""")
self.f.close()
def writeNodes2VTK(self, fobj):
self.VTKcnt=200 # how many numbers per line in vtk file
#self.VTKcnt=6
ndCnt=1
#self.nodes=range(0,10)
fobj.write('POINTS %i'%self.p.nodes()+' float\n')
for iNd in self.nodes:
nd=self.p.node(iNd)
disp=self.p.node_displacement(iNd)
#contact=self.p.node_scalar(iNd,contactNr)
#ndCnt=ndCnt+1
fobj.write('%f %f %f \n'%
#(nd.x, nd.y, nd.z))
(nd.x+disp[0], nd.y+disp[1], nd.z+disp[2]))
#if ndCnt>6:
# fobj.write('\n')
# ndCnt=1
fobj.write('\n')
print('Nodes written to VTK: %i'%self.p.nodes())
#print('Nr of nodes: ',self.nodes)
def writeElements2VTK(self, fobj):
fobj.write('\nCELLS %i %i'%(self.p.elements(),self.p.elements()*9)+'\n')
for iEl in range(0,self.nel):
el=self.p.element(iEl)
#disp=self.p.node_displacement(iNd)
#contact=self.p.node_scalar(iNd,contactNr)
#ndCnt=ndCnt+1
fobj.write('8 ')
ndlist=el.items
#for k in [0, 1, 3, 2, 4, 5, 7, 6]: # FOR CELL TPYE VTK_VOXEL
#for k in [0, 4, 3, 1, 5, 7, 6, 2]:
for k in [0, 1, 2, 3, 4, 5, 6, 7]: # FOR CELL TYPE VTK_HEXAHEDRON
fobj.write('%6i '%(ndlist[k]-1))
fobj.write('\n')
#if ndCnt>6:
# fobj.write('\n')
# ndCnt=1
fobj.write('\nCELL_TYPES %i'%self.p.elements()+'\n')
cnt=0
for iEl in range(0,self.nel):
cnt=cnt+1
#fobj.write('11\n') #VTK_VOXEL
fobj.write('12 ') #VTK_HEXAHEDRON
if cnt>self.VTKcnt:
fobj.write('\n');cnt=0
fobj.write('\n')
print('Elements written to VTK: %i'%self.p.elements())
#print('Nr of nodes: ',self.nodes)
def writeElScalars2NodesVTK(self,fobj):
fobj.write('\nPOINT_DATA %i\n'%self.p.nodes())
@ -668,10 +604,7 @@ LOOKUP_TABLE default
fobj.write('\n')
def writeNodeScalars2VTK(self,fobj):
#print('writeElementData2VTK')
fobj.write('\nPOINT_DATA %i\n'%self.p.nodes())
nNdDat=self.nscals
nComponents=1+nNdDat
for idxNdScal in range(-3,self.nscals): # include node x,y,z
if idxNdScal>=0:
datalabel=self.nscal_list[idxNdScal]
@ -700,10 +633,7 @@ LOOKUP_TABLE default
fobj.write('\n')
def writeElementData2VTK(self,fobj):
#print('writeElementData2VTK')
fobj.write('\nCELL_DATA %i\n'%self.p.elements())
nElDat=self.elscals
nComponents=1+nElDat
for idxElScal in range(0,self.elscals):
datalabel=self.elscal_list[idxElScal]
datalabel=re.sub("\s",'_',datalabel)
@ -730,7 +660,7 @@ LOOKUP_TABLE default
def example1(self):
self.openFile()
self.writeFirstLines()
self.f.write('''DATASET POLYDATA
self.f.write("""DATASET POLYDATA
POINTS 8 float
0.0 0.0 0.0
1.0 0.0 0.0
@ -789,18 +719,20 @@ LOOKUP_TABLE my_table 8
0.0 0.0 1.0 1.0
1.0 0.0 1.0 1.0
0.0 1.0 1.0 1.0
1.0 1.0 1.0 1.0''')
1.0 1.0 1.0 1.0""")
self.f.close()
import pyvtk
class marc_to_vtk():
'''
Anybody wants to implement it with pyvtk?
The advantage would be that pyvtk can also wirte the
<xml>-VTK format and binary.
These can be plotted with mayavi.
'''
"""
Anybody wants to implement it with pyvtk?
The advantage would be that pyvtk can also wirte the
<xml>-VTK format and binary.
These can be plotted with mayavi.
"""
def __init__(self):
self.p=[]#MARC_POST() # self.p
@ -810,5 +742,4 @@ class marc_to_vtk():
hexahedron=self.p.cells),
'm2v output')
vtk.tofile('m2v_file')
#vtk.tofile('example3b','binary')
#VtkData('example3')

View File

@ -1,8 +1,7 @@
# -*- coding: UTF-8 no BOM -*-
"""Tools to control the various BVP solvers"""
# $Id$
from .solver import Solver # only one class
from .spectral import Spectral # only one class
from .marc import Marc # only one class
from .abaqus import Abaqus # only one class
from .solver import Solver # noqa
from .spectral import Spectral # noqa
from .marc import Marc # noqa
from .abaqus import Abaqus # noqa

View File

@ -7,7 +7,8 @@ from .solver import Solver
class Abaqus(Solver):
def __init__(self,version='',solver=''): # example of version string: 6.12-2, solver: either std or exp
def __init__(self,version='',solver=''): # example version string: 6.12-2, solver: std or exp
self.solver='Abaqus'
if version =='':
import subprocess

View File

@ -7,9 +7,7 @@ from .solver import Solver
class Marc(Solver):
#--------------------------
def __init__(self):
#--------------------------
self.solver = 'Marc'
self.releases = { \
'2015': ['linux64',''],
@ -24,7 +22,6 @@ class Marc(Solver):
#--------------------------
def version(self,rootRelation = ''):
#--------------------------
import os,damask.environment
MSCpath = damask.environment.Environment(rootRelation).options['MSC_ROOT']
@ -40,7 +37,6 @@ class Marc(Solver):
#--------------------------
def libraryPath(self,rootRelation = '',releases = []):
#--------------------------
import os,damask.environment
MSCpath = damask.environment.Environment(rootRelation).options['MSC_ROOT']
@ -59,7 +55,6 @@ class Marc(Solver):
#--------------------------
def toolsPath(self,rootRelation = '',release = ''):
#--------------------------
import os,damask.environment
MSCpath = damask.environment.Environment(rootRelation).options['MSC_ROOT']
@ -72,7 +67,6 @@ class Marc(Solver):
#--------------------------
def submit_job(self,
#--------------------------
rootRelation = '',
release = '',
model = 'model',
@ -84,7 +78,7 @@ class Marc(Solver):
):
import os,damask.environment
import subprocess,shlex,shutil
import subprocess,shlex
if len(release) == 0: release = self.version(rootRelation)
@ -94,7 +88,7 @@ class Marc(Solver):
damaskEnv = damask.environment.Environment(rootRelation)
user = os.path.join(damaskEnv.relPath('code/'),'DAMASK_marc') # might be updated if special version is found (usually symlink)
user = os.path.join(damaskEnv.relPath('code/'),'DAMASK_marc') # might be updated if special version (symlink) is found
if compile:
if os.path.isfile(os.path.join(damaskEnv.relPath('code/'),'DAMASK_marc%s.f90'%release)):
user = os.path.join(damaskEnv.relPath('code/'),'DAMASK_marc%s'%release)
@ -123,7 +117,6 @@ class Marc(Solver):
#--------------------------
def exit_number_from_outFile(self,outFile=None):
#--------------------------
import string
exitnumber = -1
fid_out = open(outFile,'r')

View File

@ -5,10 +5,11 @@
import damask.solver
class Solver():
'''
General class for solver specific functionality.
Sub-classed by the individual solvers.
'''
"""
General class for solver specific functionality.
Sub-classed by the individual solvers.
"""
def __init__(self,solver=''):
solverClass = {

View File

@ -1,5 +1,5 @@
# -*- coding: UTF-8 no BOM -*-
# $Id$
"""Test functionality"""
from .test import Test
from .test import Test # noqa

View File

@ -2,17 +2,19 @@
# $Id$
import os, sys, shlex, inspect
import subprocess,shutil,string
import logging, logging.config
import os,sys,shutil
import logging,logging.config
import damask
import numpy as np
from collections import Iterable
from optparse import OptionParser
class Test():
'''
General class for testing.
Is sub-classed by the individual tests.
'''
"""
General class for testing.
Is sub-classed by the individual tests.
"""
variants = []
@ -20,11 +22,11 @@ class Test():
logger = logging.getLogger()
logger.setLevel(0)
fh = logging.FileHandler('test.log') # create file handler which logs even debug messages
fh = logging.FileHandler('test.log') # create file handler which logs even debug messages
fh.setLevel(logging.DEBUG)
full = logging.Formatter('%(asctime)s - %(levelname)s: \n%(message)s')
fh.setFormatter(full)
ch = logging.StreamHandler(stream=sys.stdout) # create console handler with a higher log level
ch = logging.StreamHandler(stream=sys.stdout) # create console handler with a higher log level
ch.setLevel(logging.INFO)
# create formatter and add it to the handlers
plain = logging.Formatter('%(message)s')
@ -52,18 +54,16 @@ class Test():
accept=False)
def execute(self):
'''
Run all variants and report first failure.
'''
"""Run all variants and report first failure."""
if self.options.debug:
for variant in xrange(len(self.variants)):
try:
self.postprocess(variant)
if not self.compare(variant):
return variant+1 # return culprit
return variant+1 # return culprit
except Exception as e :
logging.critical('\nWARNING:\n %s\n'%e)
return variant+1 # return culprit
logging.critical('\nWARNING:\n {}\n'.format(e))
return variant+1 # return culprit
return 0
else:
if not self.testPossible(): return -1
@ -74,139 +74,109 @@ class Test():
self.prepare(variant)
self.run(variant)
self.postprocess(variant)
if self.updateRequested: # update requested
if self.updateRequested: # update requested
self.update(variant)
elif not (self.options.accept or self.compare(variant)): # no update, do comparison
return variant+1 # return culprit
elif not (self.options.accept or self.compare(variant)): # no update, do comparison
return variant+1 # return culprit
except Exception as e :
logging.critical('\nWARNING:\n %s\n'%e)
return variant+1 # return culprit
logging.critical('\nWARNING:\n {}\n'.format(e))
return variant+1 # return culprit
return 0
def testPossible(self):
'''
Check if test is possible or not (e.g. no license available).
'''
"""Check if test is possible or not (e.g. no license available)."""
return True
def clean(self):
'''
Delete directory tree containing current results.
'''
"""Delete directory tree containing current results."""
status = True
try:
shutil.rmtree(self.dirCurrent())
except:
logging.warning('removal of directory "%s" not possible...'%(self.dirCurrent()))
logging.warning('removal of directory "{}" not possible...'.format(self.dirCurrent()))
status = status and False
try:
os.mkdir(self.dirCurrent())
except:
logging.critical('creation of directory "%s" failed...'%(self.dirCurrent()))
logging.critical('creation of directory "{}" failed...'.format(self.dirCurrent()))
status = status and False
return status
def prepareAll(self):
'''
Do all necessary preparations for the whole test
'''
"""Do all necessary preparations for the whole test"""
return True
def prepare(self,variant):
'''
Do all necessary preparations for the run of each test variant
'''
"""Do all necessary preparations for the run of each test variant"""
return True
def run(self,variant):
'''
Execute the requested test variant.
'''
"""Execute the requested test variant."""
return True
def postprocess(self,variant):
'''
Perform post-processing of generated results for this test variant.
'''
"""Perform post-processing of generated results for this test variant."""
return True
def compare(self,variant):
'''
Compare reference to current results.
'''
"""Compare reference to current results."""
return True
def update(self,variant):
'''
Update reference with current results.
'''
"""Update reference with current results."""
logging.debug('Update not necessary')
return True
def dirReference(self):
'''
Directory containing reference results of the test.
'''
"""Directory containing reference results of the test."""
return os.path.normpath(os.path.join(self.dirBase,'reference/'))
def dirCurrent(self):
'''
Directory containing current results of the test.
'''
"""Directory containing current results of the test."""
return os.path.normpath(os.path.join(self.dirBase,'current/'))
def dirProof(self):
'''
Directory containing human readable proof of correctness for the test.
'''
"""Directory containing human readable proof of correctness for the test."""
return os.path.normpath(os.path.join(self.dirBase,'proof/'))
def fileInRoot(self,dir,file):
'''
Path to a file in the root directory of DAMASK.
'''
"""Path to a file in the root directory of DAMASK."""
return os.path.join(damask.Environment().rootDir(),dir,file)
def fileInReference(self,file):
'''
Path to a file in the refrence directory for the test.
'''
"""Path to a file in the refrence directory for the test."""
return os.path.join(self.dirReference(),file)
def fileInCurrent(self,file):
'''
Path to a file in the current results directory for the test.
'''
"""Path to a file in the current results directory for the test."""
return os.path.join(self.dirCurrent(),file)
def fileInProof(self,file):
'''
Path to a file in the proof directory for the test.
'''
"""Path to a file in the proof directory for the test."""
return os.path.join(self.dirProof(),file)
def copy(self, mapA, mapB,
A = [], B = []):
'''
"""
copy list of files from (mapped) source to target.
mapA/B is one of self.fileInX.
'''
"""
if not B or len(B) == 0: B = A
for source,target in zip(map(mapA,A),map(mapB,B)):
@ -223,19 +193,19 @@ class Test():
try:
shutil.copy2(self.fileInReference(file),self.fileInCurrent(targetfiles[i]))
except:
logging.critical('Reference2Current: Unable to copy file %s'%file)
logging.critical('Reference2Current: Unable to copy file "{}"'.format(file))
def copy_Base2Current(self,sourceDir,sourcefiles=[],targetfiles=[]):
source=os.path.normpath(os.path.join(self.dirBase,'../../../'+sourceDir))
source=os.path.normpath(os.path.join(self.dirBase,'../../..',sourceDir))
if len(targetfiles) == 0: targetfiles = sourcefiles
for i,file in enumerate(sourcefiles):
try:
shutil.copy2(os.path.join(source,file),self.fileInCurrent(targetfiles[i]))
except:
logging.error(os.path.join(source,file))
logging.critical('Base2Current: Unable to copy file %s'%file)
logging.critical('Base2Current: Unable to copy file "{}"'.format(file))
def copy_Current2Reference(self,sourcefiles=[],targetfiles=[]):
@ -245,7 +215,7 @@ class Test():
try:
shutil.copy2(self.fileInCurrent(file),self.fileInReference(targetfiles[i]))
except:
logging.critical('Current2Reference: Unable to copy file %s'%file)
logging.critical('Current2Reference: Unable to copy file "{}"'.format(file))
def copy_Proof2Current(self,sourcefiles=[],targetfiles=[]):
@ -255,7 +225,7 @@ class Test():
try:
shutil.copy2(self.fileInProof(file),self.fileInCurrent(targetfiles[i]))
except:
logging.critical('Proof2Current: Unable to copy file %s'%file)
logging.critical('Proof2Current: Unable to copy file "{}"'.format(file))
def copy_Current2Current(self,sourcefiles=[],targetfiles=[]):
@ -264,7 +234,7 @@ class Test():
try:
shutil.copy2(self.fileInReference(file),self.fileInCurrent(targetfiles[i]))
except:
logging.critical('Current2Current: Unable to copy file %s'%file)
logging.critical('Current2Current: Unable to copy file "{}"'.format(file))
def execute_inCurrentDir(self,cmd,streamIn=None):
@ -282,7 +252,7 @@ class Test():
def compare_Array(self,File1,File2):
import numpy as np
logging.info('comparing\n '+File1+'\n '+File2)
logging.info('\n '.join(['comparing',File1,File2]))
table1 = damask.ASCIItable(name=File1,readonly=True)
table1.head_read()
len1=len(table1.info)+2
@ -300,8 +270,9 @@ class Test():
max_loc=np.argmax(abs(refArrayNonZero[curArray.nonzero()]/curArray[curArray.nonzero()]-1.))
refArrayNonZero = refArrayNonZero[curArray.nonzero()]
curArray = curArray[curArray.nonzero()]
print(' ********\n * maximum relative error %e for %e and %e\n ********'
%(max_err, refArrayNonZero[max_loc],curArray[max_loc]))
print(' ********\n * maximum relative error {} between {} and {}\n ********'.format(max_err,
refArrayNonZero[max_loc],
curArray[max_loc]))
return max_err
else:
raise Exception('mismatch in array size to compare')
@ -325,10 +296,11 @@ class Test():
absoluteTolerance=False,perLine=False,skipLines=[]):
import numpy as np
logging.info('comparing ASCII Tables\n %s \n %s'%(file0,file1))
logging.info('\n '.join(['comparing ASCII Tables',file0,file1]))
if normHeadings == '': normHeadings = headings0
if len(headings0) == len(headings1) == len(normHeadings): #check if comparison is possible and determine lenght of columns
# check if comparison is possible and determine lenght of columns
if len(headings0) == len(headings1) == len(normHeadings):
dataLength = len(headings0)
length = [1 for i in xrange(dataLength)]
shape = [[] for i in xrange(dataLength)]
@ -344,7 +316,7 @@ class Test():
for i in xrange(dataLength):
if headings0[i]['shape'] != headings1[i]['shape']:
raise Exception('shape mismatch when comparing %s with %s '%(headings0[i]['label'],headings1[i]['label']))
raise Exception('shape mismatch between {} and {} '.format(headings0[i]['label'],headings1[i]['label']))
shape[i] = headings0[i]['shape']
for j in xrange(np.shape(shape[i])[0]):
length[i] *= shape[i][j]
@ -352,7 +324,9 @@ class Test():
for j in xrange(np.shape(normShape[i])[0]):
normLength[i] *= normShape[i][j]
else:
raise Exception('trying to compare %i with %i normed by %i data sets'%(len(headings0),len(headings1),len(normHeadings)))
raise Exception('trying to compare {} with {} normed by {} data sets'.format(len(headings0),
len(headings1),
len(normHeadings)))
table0 = damask.ASCIItable(name=file0,readonly=True)
table0.head_read()
@ -360,37 +334,34 @@ class Test():
table1.head_read()
for i in xrange(dataLength):
key0 = {True :'1_%s',
False:'%s' }[length[i]>1]%headings0[i]['label']
key1 = {True :'1_%s',
False:'%s' }[length[i]>1]%headings1[i]['label']
normKey = {True :'1_%s',
False:'%s' }[normLength[i]>1]%normHeadings[i]['label']
key0 = ('1_' if length[i]>1 else '') + headings0[i]['label']
key1 = ('1_' if length[i]>1 else '') + headings1[i]['label']
normKey = ('1_' if normLength[i]>1 else '') + normHeadings[i]['label']
if key0 not in table0.labels:
raise Exception('column %s not found in 1. table...\n'%key0)
raise Exception('column {} not found in 1. table...\n'.format(key0))
elif key1 not in table1.labels:
raise Exception('column %s not found in 2. table...\n'%key1)
raise Exception('column {} not found in 2. table...\n'.format(key1))
elif normKey not in table0.labels:
raise Exception('column %s not found in 1. table...\n'%normKey)
raise Exception('column {} not found in 1. table...\n'.format(normKey))
else:
column[0][i] = table0.labels.index(key0) # remember columns of requested data
column[1][i] = table1.labels.index(key1) # remember columns of requested data in second column
normColumn[i] = table0.labels.index(normKey) # remember columns of requested data in second column
column[0][i] = table0.labels.index(key0)
column[1][i] = table1.labels.index(key1)
normColumn[i] = table0.labels.index(normKey)
line0 = 0
while table0.data_read(): # read next data line of ASCII table
while table0.data_read(): # read next data line of ASCII table
if line0 not in skipLines:
for i in xrange(dataLength):
myData = np.array(map(float,table0.data[column[0][i]:\
column[0][i]+length[i]]),'d')
column[0][i]+length[i]]),'d')
normData = np.array(map(float,table0.data[normColumn[i]:\
normColumn[i]+normLength[i]]),'d')
normColumn[i]+normLength[i]]),'d')
data[i] = np.append(data[i],np.reshape(myData,shape[i]))
if normType == 'pInf':
norm[i] = np.append(norm[i],np.max(np.abs(normData)))
else:
norm[i] = np.append(norm[i],np.linalg.norm(np.reshape(normData,normShape[i]),normType))
line0 +=1
line0 += 1
for i in xrange(dataLength):
if not perLine: norm[i] = [np.max(norm[i]) for j in xrange(line0-len(skipLines))]
@ -399,12 +370,12 @@ class Test():
norm[i] = [1.0 for j in xrange(line0-len(skipLines))]
absTol[i] = True
if perLine:
logging.warning('At least one norm of %s in 1. table is 0.0, using absolute tolerance'%headings0[i]['label'])
logging.warning('At least one norm of {} in 1. table is 0.0, using absolute tolerance'.format(headings0[i]['label']))
else:
logging.warning('Maximum norm of %s in 1. table is 0.0, using absolute tolerance'%headings0[i]['label'])
logging.warning('Maximum norm of {} in 1. table is 0.0, using absolute tolerance'.format(headings0[i]['label']))
line1 = 0
while table1.data_read(): # read next data line of ASCII table
while table1.data_read(): # read next data line of ASCII table
if line1 not in skipLines:
for i in xrange(dataLength):
myData = np.array(map(float,table1.data[column[1][i]:\
@ -413,45 +384,45 @@ class Test():
norm[i][line1-len(skipLines)])
line1 +=1
if (line0 != line1): raise Exception('found %s lines in 1. table and %s in 2. table'%(line0,line1))
if (line0 != line1): raise Exception('found {} lines in 1. table but {} in 2. table'.format(line0,line1))
logging.info(' ********')
for i in xrange(dataLength):
if absTol[i]:
logging.info(' * maximum absolute error %e for %s and %s'%(maxError[i],headings0[i]['label'],headings1[i]['label']))
logging.info(' * maximum absolute error {} between {} and {}'.format(maxError[i],
headings0[i]['label'],
headings1[i]['label']))
else:
logging.info(' * maximum relative error %e for %s and %s'%(maxError[i],headings0[i]['label'],headings1[i]['label']))
logging.info(' * maximum relative error {} between {} and {}'.format(maxError[i],
headings0[i]['label'],
headings1[i]['label']))
logging.info(' ********')
return maxError
def compare_TablesStatistically(self,
files = [None,None], # list of file names
columns = [None], # list of list of column labels (per file)
files = [None,None], # list of file names
columns = [None], # list of list of column labels (per file)
meanTol = 1.0e-4,
stdTol = 1.0e-6,
preFilter = 1.0e-9):
'''
calculate statistics of tables
threshold can be used to ignore small values (a negative number disables this feature)
'''
"""
calculate statistics of tables
import numpy as np
from collections import Iterable
if not (isinstance(files, Iterable) and not isinstance(files, str)): # check whether list of files is requested
threshold can be used to ignore small values (a negative number disables this feature)
"""
if not (isinstance(files, Iterable) and not isinstance(files, str)): # check whether list of files is requested
files = [str(files)]
tables = [damask.ASCIItable(name = filename,readonly = True) for filename in files]
for table in tables:
table.head_read()
columns += [columns[0]]*(len(files)-len(columns)) # extend to same length as files
columns = columns[:len(files)] # truncate to same length as files
columns += [columns[0]]*(len(files)-len(columns)) # extend to same length as files
columns = columns[:len(files)] # truncate to same length as files
for i,column in enumerate(columns):
if column is None: columns[i] = tables[i].labels # if no column is given, read all
if column is None: columns[i] = tables[i].labels # if no column is given, read all
logging.info('comparing ASCIItables statistically')
for i in xrange(len(columns)):
@ -461,7 +432,7 @@ class Test():
)
logging.info(files[i]+':'+','.join(columns[i]))
if len(files) < 2: return True # single table is always close to itself...
if len(files) < 2: return True # single table is always close to itself...
data = []
for table,labels in zip(tables,columns):
@ -476,42 +447,38 @@ class Test():
normedDelta = np.where(normBy>preFilter,delta/normBy,0.0)
mean = np.amax(np.abs(np.mean(normedDelta,0)))
std = np.amax(np.std(normedDelta,0))
logging.info('mean: %f'%mean)
logging.info('std: %f'%std)
logging.info('mean: {:f}'.format(mean))
logging.info('std: {:f}'.format(std))
return (mean<meanTol) & (std < stdTol)
def compare_Tables(self,
files = [None,None], # list of file names
columns = [None], # list of list of column labels (per file)
files = [None,None], # list of file names
columns = [None], # list of list of column labels (per file)
rtol = 1e-5,
atol = 1e-8,
preFilter = -1.0,
postFilter = -1.0,
debug = False):
'''
compare tables with np.allclose
threshold can be used to ignore small values (a negative number disables this feature)
'''
"""
compare tables with np.allclose
import numpy as np
from collections import Iterable
if not (isinstance(files, Iterable) and not isinstance(files, str)): # check whether list of files is requested
threshold can be used to ignore small values (a negative number disables this feature)
"""
if not (isinstance(files, Iterable) and not isinstance(files, str)): # check whether list of files is requested
files = [str(files)]
tables = [damask.ASCIItable(name = filename,readonly = True) for filename in files]
for table in tables:
table.head_read()
columns += [columns[0]]*(len(files)-len(columns)) # extend to same length as files
columns = columns[:len(files)] # truncate to same length as files
columns += [columns[0]]*(len(files)-len(columns)) # extend to same length as files
columns = columns[:len(files)] # truncate to same length as files
for i,column in enumerate(columns):
if column is None: columns[i] = tables[i].labels # if no column is given, read all
if column is None: columns[i] = tables[i].labels # if no column is given, read all
logging.info('comparing ASCIItables')
for i in xrange(len(columns)):
@ -521,7 +488,7 @@ class Test():
)
logging.info(files[i]+':'+','.join(columns[i]))
if len(files) < 2: return True # single table is always close to itself...
if len(files) < 2: return True # single table is always close to itself...
maximum = np.zeros(len(columns[0]),dtype='f')
data = []
@ -532,26 +499,26 @@ class Test():
table.close()
maximum /= len(tables)
maximum = np.where(maximum >0.0, maximum, 1) # do not devide by zero for empty columns
maximum = np.where(maximum >0.0, maximum, 1) # avoid div by zero for empty columns
for i in xrange(len(data)):
data[i] /= maximum
mask = np.zeros_like(table.data,dtype='bool')
for table in data:
mask |= np.where(np.abs(table)<postFilter,True,False) # mask out (all) tiny values
mask |= np.where(np.abs(table)<postFilter,True,False) # mask out (all) tiny values
allclose = True # start optimistic
allclose = True # start optimistic
for i in xrange(1,len(data)):
if debug:
t0 = np.where(mask,0.0,data[i-1])
t1 = np.where(mask,0.0,data[i ])
j = np.argmin(np.abs(t1)*rtol+atol-np.abs(t0-t1))
logging.info('%f'%np.amax(np.abs(t0-t1)/(np.abs(t1)*rtol+atol)))
logging.info('%f %f'%((t0*maximum).flatten()[j],(t1*maximum).flatten()[j]))
logging.info('{:f}'.format(np.amax(np.abs(t0-t1)/(np.abs(t1)*rtol+atol))))
logging.info('{:f} {:f}'.format((t0*maximum).flatten()[j],(t1*maximum).flatten()[j]))
allclose &= np.allclose(np.where(mask,0.0,data[i-1]),
np.where(mask,0.0,data[i ]),rtol,atol) # accumulate "pessimism"
np.where(mask,0.0,data[i ]),rtol,atol) # accumulate "pessimism"
return allclose
@ -580,14 +547,13 @@ class Test():
def report_Success(self,culprit):
if culprit == 0:
logging.critical('%s passed.'%({False: 'The test',
True: 'All %i tests'%(len(self.variants))}[len(self.variants) > 1]))
logging.critical(('The test' if len(self.variants) == 1 else 'All {} tests'.format(len(self.variants))) + ' passed')
logging.critical('\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n')
return 0
if culprit == -1:
logging.warning('Warning: Could not start test')
return 0
else:
logging.critical(' ********\n * Test %i failed...\n ********'%(culprit))
logging.critical(' ********\n * Test {} failed...\n ********'.format(culprit))
logging.critical('\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n')
return culprit

View File

@ -6,11 +6,13 @@ import numpy as np
from optparse import Option
class bcolors:
'''
ASCII Colors (Blender code)
https://svn.blender.org/svnroot/bf-blender/trunk/blender/build_files/scons/tools/bcolors.py
http://stackoverflow.com/questions/287871/print-in-terminal-with-colors-using-python
'''
"""
ASCII Colors (Blender code)
https://svn.blender.org/svnroot/bf-blender/trunk/blender/build_files/scons/tools/bcolors.py
http://stackoverflow.com/questions/287871/print-in-terminal-with-colors-using-python
"""
HEADER = '\033[95m'
OKBLUE = '\033[94m'
OKGREEN = '\033[92m'
@ -32,32 +34,48 @@ class bcolors:
# -----------------------------
def srepr(arg,
glue = '\n'):
# -----------------------------
if (not hasattr(arg, "strip") and
hasattr(arg, "__getitem__") or
hasattr(arg, "__iter__")):
return glue.join(srepr(x) for x in arg)
return arg if isinstance(arg,basestring) else repr(arg)
def srepr(arg,glue = '\n'):
"""joins arguments as individual lines"""
if (not hasattr(arg, "strip") and
hasattr(arg, "__getitem__") or
hasattr(arg, "__iter__")):
return glue.join(srepr(x) for x in arg)
return arg if isinstance(arg,basestring) else repr(arg)
# -----------------------------
def croak(what,
newline = True):
# -----------------------------
def croak(what, newline = True):
"""writes formated to stderr"""
sys.stderr.write(srepr(what,glue = '\n') + ('\n' if newline else ''))
sys.stderr.flush()
# -----------------------------
def report(who,what):
# -----------------------------
"""reports script and file name"""
croak( (emph(who) if who else '') + (': '+what if what else '') )
# -----------------------------
def emph(what):
# -----------------------------
"""emphasizes string on screen"""
return bcolors.BOLD+srepr(what)+bcolors.ENDC
# -----------------------------
def execute(cmd,
streamIn = None,
wd = './'):
"""executes a command in given directory and returns stdout and stderr for optional stdin"""
initialPath = os.getcwd()
os.chdir(wd)
process = subprocess.Popen(shlex.split(cmd),
stdout = subprocess.PIPE,
stderr = subprocess.PIPE,
stdin = subprocess.PIPE)
out,error = [i.replace("\x08","") for i in (process.communicate() if streamIn is None
else process.communicate(streamIn.read()))]
os.chdir(initialPath)
if process.returncode != 0: raise RuntimeError('{} failed with returncode {}'.format(cmd,process.returncode))
return out,error
# -----------------------------
# Matlab like trigonometric functions that take and return angles in degrees.
# -----------------------------
@ -68,7 +86,6 @@ for f in ['cos', 'sin', 'tan']:
# -----------------------------
def gridLocation(idx,res):
# -----------------------------
return ( idx % res[0], \
( idx // res[0]) % res[1], \
( idx // res[0] // res[1]) % res[2] )
@ -76,18 +93,19 @@ def gridLocation(idx,res):
# -----------------------------
def gridIndex(location,res):
# -----------------------------
return ( location[0] % res[0] + \
return ( location[0] % res[0] + \
( location[1] % res[1]) * res[0] + \
( location[2] % res[2]) * res[1] * res[0] )
# -----------------------------
class extendableOption(Option):
# -----------------------------
# used for definition of new option parser action 'extend', which enables to take multiple option arguments
# taken from online tutorial http://docs.python.org/library/optparse.html
"""
used for definition of new option parser action 'extend', which enables to take multiple option arguments
taken from online tutorial http://docs.python.org/library/optparse.html
"""
ACTIONS = Option.ACTIONS + ("extend",)
STORE_ACTIONS = Option.STORE_ACTIONS + ("extend",)
TYPED_ACTIONS = Option.TYPED_ACTIONS + ("extend",)
@ -102,28 +120,36 @@ class extendableOption(Option):
# -----------------------------
class backgroundMessage(threading.Thread):
# -----------------------------
choices = {'bounce': ['_','o','O','°','¯','¯','°','O','o',],
"""reporting with animation to indicate progress"""
choices = {'bounce': ['_', 'o', 'O', u'\u00B0',
u'\u203e',u'\u203e',u'\u00B0','O','o','_'],
'spin': [u'\u25dc',u'\u25dd',u'\u25de',u'\u25df'],
'circle': [u'\u25f4',u'\u25f5',u'\u25f6',u'\u25f7'],
'hexagon': [u'\u2b22',u'\u2b23'],
'square': [u'\u2596',u'\u2598',u'\u259d',u'\u2597'],
'triangle': [u'\u140a',u'\u140a',u'\u1403',u'\u1405',u'\u1405',u'\u1403'],
'amoeba': [u'\u2596',u'\u258f',u'\u2598',u'\u2594',u'\u259d',u'\u2595',u'\u2597',u'\u2582'],
'beat': [u'\u2581',u'\u2582',u'\u2583',u'\u2585',u'\u2586',u'\u2587',u'\u2587',u'\u2586',u'\u2585',u'\u2583',u'\u2582',],
'prison': [u'\u168b',u'\u168c',u'\u168d',u'\u168f',u'\u168e',u'\u168d',u'\u168c',u'\u168b',],
'breath': [u'\u1690',u'\u1691',u'\u1692',u'\u1693',u'\u1694',u'\u1693',u'\u1692',u'\u1691',u'\u1690',],
'amoeba': [u'\u2596',u'\u258f',u'\u2598',u'\u2594',u'\u259d',u'\u2595',
u'\u2597',u'\u2582'],
'beat': [u'\u2581',u'\u2582',u'\u2583',u'\u2585',u'\u2586',u'\u2587',
u'\u2587',u'\u2586',u'\u2585',u'\u2583',u'\u2582',],
'prison': [u'\u168b',u'\u168c',u'\u168d',u'\u168f',u'\u168e',u'\u168d',
u'\u168c',u'\u168b',],
'breath': [u'\u1690',u'\u1691',u'\u1692',u'\u1693',u'\u1694',u'\u1693',
u'\u1692',u'\u1691',u'\u1690',],
'pulse': [u'·',u'',u'\u25cf',u'\u25cf',u'',],
'ant': [u'\u2801',u'\u2802',u'\u2810',u'\u2820',u'\u2804',u'\u2840',u'\u2880',u'\u2820',u'\u2804',u'\u2802',u'\u2810',u'\u2808'],
'juggle': [u'\ua708',u'\ua709',u'\ua70a',u'\ua70b',u'\ua70c',u'\ua711',u'\ua710',u'\ua70f',u'\ua70d',],
'ant': [u'\u2801',u'\u2802',u'\u2810',u'\u2820',u'\u2804',u'\u2840',
u'\u2880',u'\u2820',u'\u2804',u'\u2802',u'\u2810',u'\u2808'],
'juggle': [u'\ua708',u'\ua709',u'\ua70a',u'\ua70b',u'\ua70c',u'\ua711',
u'\ua710',u'\ua70f',u'\ua70d',],
# 'wobbler': [u'\u2581',u'\u25e3',u'\u258f',u'\u25e4',u'\u2594',u'\u25e5',u'\u2595',u'\u25e2',],
'grout': [u'\u2581',u'\u258f',u'\u2594',u'\u2595',],
'partner': [u'\u26ac',u'\u26ad',u'\u26ae',u'\u26af',u'\u26ae',u'\u26ad',],
'classic': ['-', '\\', '|', '/',],
}
def __init__(self,
symbol = None,
wait = 0.1):
def __init__(self,symbol = None,wait = 0.1):
"""sets animation symbol"""
super(backgroundMessage, self).__init__()
self._stop = threading.Event()
self.message = ''
@ -134,20 +160,20 @@ class backgroundMessage(threading.Thread):
self.waittime = wait
def __quit__(self):
"""cleans output"""
length = len(self.symbols[self.counter] + self.gap + self.message)
sys.stderr.write(chr(8)*length + ' '*length + chr(8)*length)
sys.stderr.write('')
sys.stderr.flush()
def stop(self):
self._stop.set()
self._stop.set()
def stopped(self):
return self._stop.is_set()
return self._stop.is_set()
def run(self):
# while not threading.enumerate()[0]._Thread__stopped:
while not self.stopped():
while not threading.enumerate()[0]._Thread__stopped:
time.sleep(self.waittime)
self.update_message()
self.__quit__()
@ -159,7 +185,7 @@ class backgroundMessage(threading.Thread):
def print_message(self):
length = len(self.symbols[self.counter] + self.gap + self.message)
sys.stderr.write(chr(8)*length + ' '*length + chr(8)*length + \
self.symbols[self.counter] + self.gap + self.new_message) # delete former and print new message
self.symbols[self.counter].encode('utf-8') + self.gap + self.new_message) # delete former and print new message
sys.stderr.flush()
self.message = self.new_message
@ -170,24 +196,38 @@ class backgroundMessage(threading.Thread):
def animation(self,which = None):
return ''.join(self.choices[which]) if which in self.choices else ''
'''
Non-linear least square fitting (Levenberg-Marquardt method) with
bounded parameters.
the codes of transformation between int <-> ext refers to the work of
Jonathan J. Helmus: https://github.com/jjhelmus/leastsqbound-scipy
other codes refers to the source code of minpack.py:
..\Lib\site-packages\scipy\optimize\minpack.py
'''
from numpy import (array, arcsin, asarray, cos, dot, eye, empty_like,
isscalar,finfo, take, triu, transpose, sqrt, sin)
def _check_func(checker, argname, thefunc, x0, args, numinputs,
def leastsqBound(func, x0, args=(), bounds=None, Dfun=None, full_output=0,
col_deriv=0, ftol=1.49012e-8, xtol=1.49012e-8,
gtol=0.0, maxfev=0, epsfcn=None, factor=100, diag=None):
from scipy.optimize import _minpack
"""
Non-linear least square fitting (Levenberg-Marquardt method) with
bounded parameters.
the codes of transformation between int <-> ext refers to the work of
Jonathan J. Helmus: https://github.com/jjhelmus/leastsqbound-scipy
other codes refers to the source code of minpack.py:
..\Lib\site-packages\scipy\optimize\minpack.py
An internal parameter list is used to enforce contraints on the fitting
parameters. The transfomation is based on that of MINUIT package.
please see: F. James and M. Winkler. MINUIT User's Guide, 2004.
bounds : list
(min, max) pairs for each parameter, use None for 'min' or 'max'
when there is no bound in that direction.
For example: if there are two parameters needed to be fitting, then
bounds is [(min1,max1), (min2,max2)]
This function is based on 'leastsq' of minpack.py, the annotation of
other parameters can be found in 'leastsq'.
..\Lib\site-packages\scipy\optimize\minpack.py
"""
def _check_func(checker, argname, thefunc, x0, args, numinputs,
output_shape=None):
from numpy import atleast_1d, shape, issubdtype, dtype, inexact
'''
The same as that of minpack.py,
'''
res = atleast_1d(thefunc(*((x0[:numinputs],) + args)))
"""The same as that of minpack.py"""
res = np.atleast_1d(thefunc(*((x0[:numinputs],) + args)))
if (output_shape is not None) and (shape(res) != output_shape):
if (output_shape[0] != 1):
if len(output_shape) > 1:
@ -201,203 +241,171 @@ def _check_func(checker, argname, thefunc, x0, args, numinputs,
else:
msg += "."
raise TypeError(msg)
if issubdtype(res.dtype, inexact):
if np.issubdtype(res.dtype, np.inexact):
dt = res.dtype
else:
dt = dtype(float)
return shape(res), dt
def _int2extGrad(p_int, bounds):
"""
Calculate the gradients of transforming the internal (unconstrained)
to external (constained) parameter.
"""
grad = empty_like(p_int)
def _int2extGrad(p_int, bounds):
"""Calculate the gradients of transforming the internal (unconstrained) to external (constrained) parameter."""
grad = np.empty_like(p_int)
for i, (x, bound) in enumerate(zip(p_int, bounds)):
lower, upper = bound
if lower is None and upper is None: # No constraints
grad[i] = 1.0
elif upper is None: # only lower bound
grad[i] = x/sqrt(x*x + 1.0)
grad[i] = x/np.sqrt(x*x + 1.0)
elif lower is None: # only upper bound
grad[i] = -x/sqrt(x*x + 1.0)
grad[i] = -x/np.sqrt(x*x + 1.0)
else: # lower and upper bounds
grad[i] = (upper - lower)*cos(x)/2.0
grad[i] = (upper - lower)*np.cos(x)/2.0
return grad
def _int2extFunc(bounds):
'''
transform internal parameters into external parameters.
'''
def _int2extFunc(bounds):
"""transform internal parameters into external parameters."""
local = [_int2extLocal(b) for b in bounds]
def _transform_i2e(p_int):
p_ext = empty_like(p_int)
p_ext = np.empty_like(p_int)
p_ext[:] = [i(j) for i, j in zip(local, p_int)]
return p_ext
return _transform_i2e
def _ext2intFunc(bounds):
'''
transform external parameters into internal parameters.
'''
def _ext2intFunc(bounds):
"""transform external parameters into internal parameters."""
local = [_ext2intLocal(b) for b in bounds]
def _transform_e2i(p_ext):
p_int = empty_like(p_ext)
p_int = np.empty_like(p_ext)
p_int[:] = [i(j) for i, j in zip(local, p_ext)]
return p_int
return _transform_e2i
def _int2extLocal(bound):
'''
transform a single internal parameter to an external parameter.
'''
def _int2extLocal(bound):
"""transform a single internal parameter to an external parameter."""
lower, upper = bound
if lower is None and upper is None: # no constraints
return lambda x: x
elif upper is None: # only lower bound
return lambda x: lower - 1.0 + sqrt(x*x + 1.0)
return lambda x: lower - 1.0 + np.sqrt(x*x + 1.0)
elif lower is None: # only upper bound
return lambda x: upper + 1.0 - sqrt(x*x + 1.0)
return lambda x: upper + 1.0 - np.sqrt(x*x + 1.0)
else:
return lambda x: lower + ((upper - lower)/2.0)*(sin(x) + 1.0)
def _ext2intLocal(bound):
'''
transform a single external parameter to an internal parameter.
'''
return lambda x: lower + ((upper - lower)/2.0)*(np.sin(x) + 1.0)
def _ext2intLocal(bound):
"""transform a single external parameter to an internal parameter."""
lower, upper = bound
if lower is None and upper is None: # no constraints
return lambda x: x
elif upper is None: # only lower bound
return lambda x: sqrt((x - lower + 1.0)**2 - 1.0)
return lambda x: np.sqrt((x - lower + 1.0)**2 - 1.0)
elif lower is None: # only upper bound
return lambda x: sqrt((x - upper - 1.0)**2 - 1.0)
return lambda x: np.sqrt((x - upper - 1.0)**2 - 1.0)
else:
return lambda x: arcsin((2.0*(x - lower)/(upper - lower)) - 1.0)
return lambda x: np.arcsin((2.0*(x - lower)/(upper - lower)) - 1.0)
i2e = _int2extFunc(bounds)
e2i = _ext2intFunc(bounds)
x0 = np.asarray(x0).flatten()
n = len(x0)
def leastsqBound(func, x0, args=(), bounds=None, Dfun=None, full_output=0,
col_deriv=0, ftol=1.49012e-8, xtol=1.49012e-8,
gtol=0.0, maxfev=0, epsfcn=None, factor=100, diag=None):
from scipy.optimize import _minpack
'''
An internal parameter list is used to enforce contraints on the fitting
parameters. The transfomation is based on that of MINUIT package.
please see: F. James and M. Winkler. MINUIT User's Guide, 2004.
if len(bounds) != n:
raise ValueError('the length of bounds is inconsistent with the number of parameters ')
if not isinstance(args, tuple):
args = (args,)
shape, dtype = _check_func('leastsq', 'func', func, x0, args, n)
m = shape[0]
bounds : list
(min, max) pairs for each parameter, use None for 'min' or 'max'
when there is no bound in that direction.
For example: if there are two parameters needed to be fitting, then
bounds is [(min1,max1), (min2,max2)]
This function is based on 'leastsq' of minpack.py, the annotation of
other parameters can be found in 'leastsq'.
..\Lib\site-packages\scipy\optimize\minpack.py
'''
i2e = _int2extFunc(bounds)
e2i = _ext2intFunc(bounds)
x0 = asarray(x0).flatten()
n = len(x0)
if n > m:
raise TypeError('Improper input: N=%s must not exceed M=%s' % (n, m))
if epsfcn is None:
epsfcn = np.finfo(dtype).eps
if len(bounds) != n:
raise ValueError('the length of bounds is inconsistent with the number of parameters ')
if not isinstance(args, tuple):
args = (args,)
shape, dtype = _check_func('leastsq', 'func', func, x0, args, n)
m = shape[0]
def funcWarp(x, *args):
return func(i2e(x), *args)
if n > m:
raise TypeError('Improper input: N=%s must not exceed M=%s' % (n, m))
if epsfcn is None:
epsfcn = finfo(dtype).eps
xi0 = e2i(x0)
if Dfun is None:
if maxfev == 0:
maxfev = 200*(n + 1)
retval = _minpack._lmdif(funcWarp, xi0, args, full_output, ftol, xtol,
gtol, maxfev, epsfcn, factor, diag)
else:
if col_deriv:
_check_func('leastsq', 'Dfun', Dfun, x0, args, n, (n, m))
else:
_check_func('leastsq', 'Dfun', Dfun, x0, args, n, (m, n))
if maxfev == 0:
maxfev = 100*(n + 1)
# wrapped func
def funcWarp(x, *args):
return func(i2e(x), *args)
def DfunWarp(x, *args):
return Dfun(i2e(x), *args)
xi0 = e2i(x0)
if Dfun is None:
if maxfev == 0:
maxfev = 200*(n + 1)
retval = _minpack._lmdif(funcWarp, xi0, args, full_output, ftol, xtol,
gtol, maxfev, epsfcn, factor, diag)
else:
if col_deriv:
_check_func('leastsq', 'Dfun', Dfun, x0, args, n, (n, m))
else:
_check_func('leastsq', 'Dfun', Dfun, x0, args, n, (m, n))
if maxfev == 0:
maxfev = 100*(n + 1)
retval = _minpack._lmder(funcWarp, DfunWarp, xi0, args, full_output, col_deriv,
ftol, xtol, gtol, maxfev, factor, diag)
# wrapped Dfun
def DfunWarp(x, *args):
return Dfun(i2e(x), *args)
errors = {0: ["Improper input parameters.", TypeError],
1: ["Both actual and predicted relative reductions "
"in the sum of squares\n are at most %f" % ftol, None],
2: ["The relative error between two consecutive "
"iterates is at most %f" % xtol, None],
3: ["Both actual and predicted relative reductions in "
"the sum of squares\n are at most %f and the "
"relative error between two consecutive "
"iterates is at \n most %f" % (ftol, xtol), None],
4: ["The cosine of the angle between func(x) and any "
"column of the\n Jacobian is at most %f in "
"absolute value" % gtol, None],
5: ["Number of calls to function has reached "
"maxfev = %d." % maxfev, ValueError],
6: ["ftol=%f is too small, no further reduction "
"in the sum of squares\n is possible.""" % ftol,
ValueError],
7: ["xtol=%f is too small, no further improvement in "
"the approximate\n solution is possible." % xtol,
ValueError],
8: ["gtol=%f is too small, func(x) is orthogonal to the "
"columns of\n the Jacobian to machine "
"precision." % gtol, ValueError],
'unknown': ["Unknown error.", TypeError]}
retval = _minpack._lmder(funcWarp, DfunWarp, xi0, args, full_output, col_deriv,
ftol, xtol, gtol, maxfev, factor, diag)
info = retval[-1] # The FORTRAN return value
if info not in [1, 2, 3, 4] and not full_output:
if info in [5, 6, 7, 8]:
np.warnings.warn(errors[info][0], RuntimeWarning)
else:
try:
raise errors[info][1](errors[info][0])
except KeyError:
raise errors['unknown'][1](errors['unknown'][0])
errors = {0: ["Improper input parameters.", TypeError],
1: ["Both actual and predicted relative reductions "
"in the sum of squares\n are at most %f" % ftol, None],
2: ["The relative error between two consecutive "
"iterates is at most %f" % xtol, None],
3: ["Both actual and predicted relative reductions in "
"the sum of squares\n are at most %f and the "
"relative error between two consecutive "
"iterates is at \n most %f" % (ftol, xtol), None],
4: ["The cosine of the angle between func(x) and any "
"column of the\n Jacobian is at most %f in "
"absolute value" % gtol, None],
5: ["Number of calls to function has reached "
"maxfev = %d." % maxfev, ValueError],
6: ["ftol=%f is too small, no further reduction "
"in the sum of squares\n is possible.""" % ftol,
ValueError],
7: ["xtol=%f is too small, no further improvement in "
"the approximate\n solution is possible." % xtol,
ValueError],
8: ["gtol=%f is too small, func(x) is orthogonal to the "
"columns of\n the Jacobian to machine "
"precision." % gtol, ValueError],
'unknown': ["Unknown error.", TypeError]}
mesg = errors[info][0]
x = i2e(retval[0])
info = retval[-1] # The FORTRAN return value
if info not in [1, 2, 3, 4] and not full_output:
if info in [5, 6, 7, 8]:
warnings.warn(errors[info][0], RuntimeWarning)
else:
try:
raise errors[info][1](errors[info][0])
except KeyError:
raise errors['unknown'][1](errors['unknown'][0])
mesg = errors[info][0]
x = i2e(retval[0])
if full_output:
grad = _int2extGrad(retval[0], bounds)
retval[1]['fjac'] = (retval[1]['fjac'].T / take(grad,
retval[1]['ipvt'] - 1)).T
cov_x = None
if info in [1, 2, 3, 4]:
from numpy.dual import inv
from numpy.linalg import LinAlgError
perm = take(eye(n), retval[1]['ipvt'] - 1, 0)
r = triu(transpose(retval[1]['fjac'])[:n, :])
R = dot(r, perm)
try:
cov_x = inv(dot(transpose(R), R))
except LinAlgError as inverror:
print inverror
pass
return (x, cov_x) + retval[1:-1] + (mesg, info)
else:
return (x, info)
if full_output:
grad = _int2extGrad(retval[0], bounds)
retval[1]['fjac'] = (retval[1]['fjac'].T / np.take(grad,
retval[1]['ipvt'] - 1)).T
cov_x = None
if info in [1, 2, 3, 4]:
from numpy.dual import inv
from numpy.linalg import LinAlgError
perm = np.take(np.eye(n), retval[1]['ipvt'] - 1, 0)
r = np.triu(np.transpose(retval[1]['fjac'])[:n, :])
R = np.dot(r, perm)
try:
cov_x = inv(np.dot(np.transpose(R), R))
except LinAlgError as inverror:
print inverror
pass
return (x, cov_x) + retval[1:-1] + (mesg, info)
else:
return (x, info)
def _general_function(params, ydata, xdata, function):
return function(xdata, *params) - ydata
@ -405,7 +413,7 @@ def _weighted_general_function(params, ydata, xdata, function, weights):
return (function(xdata, *params) - ydata)*weights
def curve_fit_bound(f, xdata, ydata, p0=None, sigma=None, bounds=None, **kw):
''' Similar as 'curve_fit' in minpack.py'''
"""Similar as 'curve_fit' in minpack.py"""
if p0 is None:
# determine number of parameters by inspecting the function
import inspect
@ -418,15 +426,15 @@ def curve_fit_bound(f, xdata, ydata, p0=None, sigma=None, bounds=None, **kw):
else:
p0 = [1.0] * (len(args)-1)
if isscalar(p0):
p0 = array([p0])
if np.isscalar(p0):
p0 = np.array([p0])
args = (ydata, xdata, f)
if sigma is None:
func = _general_function
else:
func = _weighted_general_function
args += (1.0/asarray(sigma),)
args += (1.0/np.asarray(sigma),)
return_full = kw.pop('full_output', False)
res = leastsqBound(func, p0, args=args, bounds = bounds, full_output=True, **kw)
@ -440,26 +448,6 @@ def curve_fit_bound(f, xdata, ydata, p0=None, sigma=None, bounds=None, **kw):
s_sq = (func(popt, *args)**2).sum()/(len(ydata)-len(p0))
pcov = pcov * s_sq
else:
pcov = inf
if return_full:
return popt, pcov, infodict, errmsg, ier
else:
return popt, pcov
def execute(cmd,streamIn=None,wd='./'):
'''
executes a command in given directory and returns stdout and stderr for optional stdin
'''
initialPath=os.getcwd()
os.chdir(wd)
process = subprocess.Popen(shlex.split(cmd),stdout=subprocess.PIPE,stderr = subprocess.PIPE,stdin=subprocess.PIPE)
if streamIn != None:
out,error = process.communicate(streamIn.read())
else:
out,error = process.communicate()
os.chdir(initialPath)
if process.returncode !=0: raise RuntimeError(cmd+' failed with returncode '+str(process.returncode))
return out,error
pcov = np.inf
return (popt, pcov, infodict, errmsg, ier) if return_full else (popt, pcov)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 80 KiB

After

Width:  |  Height:  |  Size: 34 KiB

View File

@ -1,8 +1,7 @@
#!/usr/bin/env python
# -*- coding: UTF-8 no BOM -*-
import os,sys,string,vtk
import numpy as np
import os
from optparse import OptionParser
import damask
@ -48,7 +47,7 @@ for name in filenames:
table.labels_append(['1_Euler','2_Euler','3_Euler',
'1_pos','2_pos',
'IQ','CI','PhaseID','Intensity','Fit',
], # labels according to OIM Analysis 7.2 Manual, p 403 (of 517)
], # OIM Analysis 7.2 Manual, p 403 (of 517)
reset = True)
# ------------------------------------------ assemble header ---------------------------------------

View File

@ -1,9 +1,9 @@
#!/usr/bin/python
# -*- coding: UTF-8 no BOM -*-
import threading,time,os,subprocess,shlex,string
import threading,os,string
import numpy as np
from optparse import OptionParser, OptionGroup
from optparse import OptionParser
from shutil import copy2
from re import split
import damask
@ -14,26 +14,10 @@ scriptID = ' '.join([scriptName,damask.version])
def list_split(option, opt, value, parser):
setattr(parser.values, option.dest, value.split(','))
def execute(cmd,streamIn=None,wd='./'):
'''
executes a command in given directory and returns stdout and stderr for optional stdin
'''
initialPath=os.getcwd()
os.chdir(wd)
process = subprocess.Popen(shlex.split(cmd),stdout=subprocess.PIPE,stderr = subprocess.PIPE,stdin=subprocess.PIPE)
if streamIn != None:
out,error = process.communicate(streamIn.read())
else:
out,error = process.communicate()
os.chdir(initialPath)
return out,error
#---------------------------------------------------------------------------------------------------
class myThread (threading.Thread):
#---------------------------------------------------------------------------------------------------
'''
Runner class
'''
"""Runner"""
def __init__(self, threadID):
threading.Thread.__init__(self)
self.threadID = threadID
@ -48,8 +32,6 @@ class myThread (threading.Thread):
s.release()
def doSim(delay,thread):
# s.acquire() and s.release() are couple
#
global dirCurrent
s.acquire()
delta_angle = offsetPhi()
@ -63,22 +45,22 @@ def doSim(delay,thread):
os.mkdir(dire,0755)
for file in [options.geometry+'.geom',options.load+'.load','numerics.config']:
copy2(dirCurrent+'/'+file, dire)
newMatConfig = newMaterialConfig(dirCurrent,delta_angle)
newMaterialConfig(dirCurrent,delta_angle)
os.chdir(dire)
if not os.path.isfile('%s_%s.spectralOut'%(options.geometry,options.load)):
print('starting uniaxial tension in direction of angle %s from %s'%(file_angle,thread))
s.release()
execute('DAMASK_spectral -g %s -l %s'%(options.geometry,options.load))
damask.util.execute('DAMASK_spectral -g %s -l %s'%(options.geometry,options.load))
else: s.release()
s.acquire()
if not os.path.isfile('./%s/%s_%s.txt'%('Rvalues',options.geometry,options.load)):
print('starting post processing for angle %s from %s'%(file_angle,thread))
s.release()
execute('postResults --cr f,p -d %s %s_%s.spectralOut'%('Rvalues',options.geometry,options.load))
execute('addCauchy ./%s/%s_%s.txt'%('Rvalues',options.geometry,options.load))
execute('addStrainTensors -l -v ./%s/%s_%s.txt'%('Rvalues',options.geometry,options.load))
damask.util.execute('postResults --cr f,p -d %s %s_%s.spectralOut'%('Rvalues',options.geometry,options.load))
damask.util.execute('addCauchy ./%s/%s_%s.txt'%('Rvalues',options.geometry,options.load))
damask.util.execute('addStrainTensors -l -v ./%s/%s_%s.txt'%('Rvalues',options.geometry,options.load))
print('post processing for angle %s from %s is finished'%(file_angle,thread))
else:
@ -122,7 +104,6 @@ def newMaterialConfig(dire,angle):
line2 = line
f.write(line2)
f.close()
return True
# --------------------------------------------------------------------
# MAIN
@ -135,16 +116,21 @@ strength anisotropic coefficients (normalized yield stress)
""", version=string.replace(scriptID,'\n','\\n')
)
parser.add_option('-l','--load' , dest='load', type='string',
help='name of the load file [%default]', metavar='string')
parser.add_option('-g','--geometry', dest='geometry', type='string',
help='name of the geometry file [%default]', metavar='string')
parser.add_option('-s', '--strain', dest='strain', type='string', action='callback', callback=list_split,
help='the threshold strains, using comma to seperate multiple strains [%default]', metavar='string')
parser.add_option('-t','--threads', dest='threads', type='int',
help='number of parallel executions [%default]', metavar='int')
parser.add_option('-n','--number', dest='number', type='int',
help='Number of uni-axial tensile tests [%default]', metavar='int')
parser.add_option('-l','--load' ,
dest='load', type='string',
help='name of the load file [%default]', metavar='string')
parser.add_option('-g','--geometry',
dest='geometry', type='string',
help='name of the geometry file [%default]', metavar='string')
parser.add_option('-s', '--strain',
dest='strain', type='string', action='callback', callback=list_split,
help='threshold strains, using comma to seperate multiple strains [%default]', metavar='string')
parser.add_option('-t','--threads',
dest='threads', type='int',
help='number of parallel executions [%default]', metavar='int')
parser.add_option('-n','--number',
dest='number', type='int',
help='Number of uni-axial tensile tests [%default]', metavar='int')
parser.set_defaults(geometry = '20grains16x16x16')
parser.set_defaults(load = 'tensionX')
@ -248,4 +234,4 @@ for i in xrange(2):
aniso_list_ang_strain.append('none')
writeformat = writeformat+'%-12s'
f.write('%-10s'%file_angle + writeformat%(tuple(aniso_list_ang_strain))+'\n')
f.close()
f.close()

View File

@ -1,33 +1,15 @@
#!/usr/bin/env python
# -*- coding: UTF-8 no BOM -*-
import os,sys,string,re,numpy,scipy.ndimage,scipy.signal,vtk
import os,string,scipy
import numpy as np
import damask
from optparse import OptionParser, OptionGroup, Option, SUPPRESS_HELP
from optparse import OptionParser
scriptName = os.path.splitext(os.path.basename(__file__))[0]
scriptID = ' '.join([scriptName,damask.version])
#--------------------------------------------------------------------------------------------------
class extendedOption(Option):
#--------------------------------------------------------------------------------------------------
# used for definition of new option parser action 'extend', which enables to take multiple option arguments
# taken from online tutorial http://docs.python.org/library/optparse.html
ACTIONS = Option.ACTIONS + ("extend",)
STORE_ACTIONS = Option.STORE_ACTIONS + ("extend",)
TYPED_ACTIONS = Option.TYPED_ACTIONS + ("extend",)
ALWAYS_TYPED_ACTIONS = Option.ALWAYS_TYPED_ACTIONS + ("extend",)
def take_action(self, action, dest, opt, value, values, parser):
if action == "extend":
lvalue = value.split(",")
values.ensure_value(dest, []).extend(lvalue)
else:
Option.take_action(self, action, dest, opt, value, values, parser)
parser = OptionParser(option_class=extendedOption, usage='%prog options [file[s]]', description = """
parser = OptionParser(option_class=damask.extendableOption, usage='%prog options [file[s]]', description = """
Apply filter(s) to Gwyddion data.
""" + string.replace(scriptID,'\n','\\n')
)
@ -59,7 +41,7 @@ for file in filenames:
if pieces[1] == 'Height:': height = float(pieces[2])
header.append(line.lstrip('#').strip())
elevation = numpy.loadtxt(file)#*1e6
elevation = np.loadtxt(file)#*1e6
if options.opening > 0:
elevation = scipy.ndimage.morphology.grey_opening(elevation,options.opening)
@ -80,5 +62,5 @@ for file in filenames:
elevation = scipy.ndimage.filters.median_filter(elevation,options.median)
filters += '_median%i'%options.median
numpy.savetxt(os.path.splitext(file)[0]+filters+os.path.splitext(file)[1],elevation,header='\n'.join(header))
np.savetxt(os.path.splitext(file)[0]+filters+os.path.splitext(file)[1],elevation,header='\n'.join(header))

View File

@ -1,9 +1,10 @@
#!/usr/bin/env python
# -*- coding: UTF-8 no BOM -*-
import os,sys,string,re,numpy,scipy.ndimage,scipy.signal,vtk
import os,string,vtk
import numpy as np
import damask
from optparse import OptionParser, OptionGroup, Option, SUPPRESS_HELP
from optparse import OptionParser
scriptName = os.path.splitext(os.path.basename(__file__))[0]
scriptID = ' '.join([scriptName,damask.version])
@ -26,26 +27,7 @@ scalingFactor = { \
},
}
#--------------------------------------------------------------------------------------------------
class extendedOption(Option):
#--------------------------------------------------------------------------------------------------
# used for definition of new option parser action 'extend', which enables to take multiple option arguments
# taken from online tutorial http://docs.python.org/library/optparse.html
ACTIONS = Option.ACTIONS + ("extend",)
STORE_ACTIONS = Option.STORE_ACTIONS + ("extend",)
TYPED_ACTIONS = Option.TYPED_ACTIONS + ("extend",)
ALWAYS_TYPED_ACTIONS = Option.ALWAYS_TYPED_ACTIONS + ("extend",)
def take_action(self, action, dest, opt, value, values, parser):
if action == "extend":
lvalue = value.split(",")
values.ensure_value(dest, []).extend(lvalue)
else:
Option.take_action(self, action, dest, opt, value, values, parser)
parser = OptionParser(option_class=extendedOption, usage='%prog options [file[s]]', description = """
parser = OptionParser(option_class=damask.extendableOption, usage='%prog options [file[s]]', description = """
Produce VTK rectilinear grid from Gwyddion dataset exported as text.
""" + string.replace(scriptID,'\n','\\n')
)
@ -78,16 +60,16 @@ for file in filenames:
if options.scaling == 0.0:
options.scaling = scalingFactor[lateralunit][elevationunit]
elevation = numpy.loadtxt(file)*options.scaling
elevation = np.loadtxt(file)*options.scaling
grid = vtk.vtkRectilinearGrid()
grid.SetDimensions(elevation.shape[1],elevation.shape[0],1)
xCoords = vtk.vtkDoubleArray()
for x in numpy.arange(0.0,width,width/elevation.shape[1],'d'):
for x in np.arange(0.0,width,width/elevation.shape[1],'d'):
xCoords.InsertNextValue(x)
yCoords = vtk.vtkDoubleArray()
for y in numpy.arange(0.0,height,height/elevation.shape[0],'d'):
for y in np.arange(0.0,height,height/elevation.shape[0],'d'):
yCoords.InsertNextValue(y)
zCoords = vtk.vtkDoubleArray()
zCoords.InsertNextValue(0.0)
@ -99,8 +81,8 @@ for file in filenames:
vector = vtk.vtkFloatArray()
vector.SetName("elevation");
vector.SetNumberOfComponents(3);
vector.SetNumberOfTuples(numpy.prod(elevation.shape));
for i,z in enumerate(numpy.ravel(elevation)):
vector.SetNumberOfTuples(np.prod(elevation.shape));
for i,z in enumerate(np.ravel(elevation)):
vector.SetTuple3(i,0,0,z)
grid.GetPointData().AddArray(vector)

View File

@ -1,7 +1,7 @@
#!/usr/bin/python
# -*- coding: UTF-8 no BOM -*-
import threading,time,os,subprocess,string,sys
import threading,time,os
import numpy as np
from optparse import OptionParser
import damask
@ -56,10 +56,11 @@ def runFit(exponent, eqStress, dimension, criterion):
damask.util.croak(fitResidual)
def principalStresses(sigmas):
'''
computes principal stresses (i.e. eigenvalues) for a set of Cauchy stresses.
sorted in descending order.
'''
"""
computes principal stresses (i.e. eigenvalues) for a set of Cauchy stresses.
sorted in descending order.
"""
lambdas=np.zeros(0,'d')
for i in xrange(np.shape(sigmas)[1]):
eigenvalues = np.linalg.eigvalsh(sym6toT33(sigmas[:,i]))
@ -82,27 +83,25 @@ def principalStress(p):
t1 + t2*np.cos(phi+np.pi*4.0/3.0)])
def principalStrs_Der(p, (s1, s2, s3, s4, s5, s6), dim, Karafillis=False):
'''
Derivative of principal stress with respect to stress
'''
"""Derivative of principal stress with respect to stress"""
third = 1.0/3.0
third2 = 2.0*third
I = invariant(p)
I1s3I2= np.sqrt(I[0]**2 - 3.0*I[1])
numer = 2.0*I1**3 - 9.0*I[0]*I[1] + 27.0*I[2]
numer = 2.0*I[0]**3 - 9.0*I[0]*I[1] + 27.0*I[2]
denom = 2.0*I1s3I2**3
cs = numer/denom
phi = np.arccos(cs)/3.0
dphidcs = -third/np.sqrt(1.0 - cs**2)
dcsddenom = 0.5*numer*(-1.5)*I1s3I2**(-5.0)
dcsdI1 = (6.0*I1**2 - 9.0*I2)*denom + dcsddenom*(2.0*I1)
dcsdI2 = ( - 9.0*I1)*denom + dcsddenom*(-3.0)
dcsdI1 = (6.0*I[0]**2 - 9.0*I[1])*denom + dcsddenom*(2.0*I[0])
dcsdI2 = ( - 9.0*I[0])*denom + dcsddenom*(-3.0)
dcsdI3 = 27.0*denom
dphidI1, dphidI2, dphidI3 = dphidcs*dcsdI1, dphidcs*dcsdI2, dphidcs*dcsdI3
dI1s3I2dI1 = I1/I1s3I2
dI1s3I2dI1 = I[0]/I1s3I2
dI1s3I2dI2 = -1.5/I1s3I2
tcoeff = third2*I1s3I2
@ -150,13 +149,13 @@ def math_ln(x):
return np.log(x + 1.0e-32)
def sym6toT33(sym6):
''' Shape the symmetric stress tensor(6) into (3,3) '''
"""Shape the symmetric stress tensor(6) into (3,3)"""
return np.array([[sym6[0],sym6[3],sym6[5]],
[sym6[3],sym6[1],sym6[4]],
[sym6[5],sym6[4],sym6[2]]])
def t33toSym6(t33):
''' Shape the stress tensor(3,3) into symmetric (6) '''
"""Shape the stress tensor(3,3) into symmetric (6)"""
return np.array([ t33[0,0],
t33[1,1],
t33[2,2],
@ -165,9 +164,6 @@ def t33toSym6(t33):
(t33[2,0] + t33[0,2])/2.0,]) # * * 2
class Criteria(object):
'''
needs doc string
'''
def __init__(self, criterion, uniaxialStress,exponent, dimension):
self.stress0 = uniaxialStress
if exponent < 0.0: # Fitting exponent m
@ -183,9 +179,8 @@ class Criteria(object):
return self.func(self.stress0, paras, sigmas,self.mFix,self.criteria,self.dim,Jac=True)
class Vegter(object):
'''
Vegter yield criterion
'''
"""Vegter yield criterion"""
def __init__(self, refPts, refNormals,nspace=11):
self.refPts, self.refNormals = self._getRefPointsNormals(refPts, refNormals)
self.hingePts = self._getHingePoints()
@ -211,11 +206,12 @@ class Vegter(object):
return refPts,refNormals
def _getHingePoints(self):
'''
calculate the hinge point B according to the reference points A,C and the normals n,m
refPoints = np.array([[p1_x, p1_y], [p2_x, p2_y]]);
refNormals = np.array([[n1_x, n1_y], [n2_x, n2_y]])
'''
"""
calculate the hinge point B according to the reference points A,C and the normals n,m
refPoints = np.array([[p1_x, p1_y], [p2_x, p2_y]]);
refNormals = np.array([[n1_x, n1_y], [n2_x, n2_y]])
"""
def hingPoint(points, normals):
A1 = points[0][0]; A2 = points[0][1]
C1 = points[1][0]; C2 = points[1][1]
@ -235,9 +231,7 @@ class Vegter(object):
return np.array([bezier(self.refPts[i:i+2],self.hingePts[i]) for i in xrange(len(self.refPts)-1)])
def VetgerCriterion(stress,lankford, rhoBi0, theta=0.0):
'''
0-pure shear; 1-uniaxial; 2-plane strain; 3-equi-biaxial
'''
"""0-pure shear; 1-uniaxial; 2-plane strain; 3-equi-biaxial"""
def getFourierParas(r):
# get the value after Fourier transformation
nset = len(r)
@ -262,12 +256,6 @@ def VetgerCriterion(stress,lankford, rhoBi0, theta=0.0):
for j in xrange(3):
refPts[j,i] = np.dot(getFourierParas(strsSet[:,j,i]), fouriercoeffs)
rhoUn = np.dot(getFourierParas(-lankford/(lankford+1)), fouriercoeffs)
rhoBi = (rhoBi0+1 + (rhoBi0-1)*np.cos(2.0*theta))/(rhoBi0+1 - (rhoBi0-1)*np.cos(2.0*theta))
nVec = lambda rho : np.array([1.0,rho]/np.sqrt(1.0+rho**2))
refNormals = np.array([nVec(-1.0),nVec(rhoUn),nVec(0.0),nVec(rhoBi)])
vegter = Vegter(refPts, refNormals)
def Tresca(eqStress=None, #not needed/supported
paras=None,
@ -276,10 +264,11 @@ def Tresca(eqStress=None, #not needed/supported
criteria=None, #not needed/supported
dim=3,
Jac=False):
'''
Tresca yield criterion
the fitted parameters is: paras(sigma0)
'''
"""
Tresca yield criterion
the fitted parameter is paras(sigma0)
"""
if not Jac:
lambdas = principalStresses(sigmas)
r = np.amax(np.array([abs(lambdas[2,:]-lambdas[1,:]),\
@ -296,13 +285,14 @@ def Cazacu_Barlat(eqStress=None,
criteria=None,
dim=3, #2D also possible
Jac=False):
'''
Cazacu-Barlat (CB) yield criterion
the fitted parameters are:
a1,a2,a3,a6; b1,b2,b3,b4,b5,b10; c for plane stress
a1,a2,a3,a4,a5,a6; b1,b2,b3,b4,b5,b6,b7,b8,b9,b10,b11; c: for general case
mFix are invalid input
'''
"""
Cazacu-Barlat (CB) yield criterion
the fitted parameters are:
a1,a2,a3,a6; b1,b2,b3,b4,b5,b10; c for plane stress
a1,a2,a3,a4,a5,a6; b1,b2,b3,b4,b5,b6,b7,b8,b9,b10,b11; c: for general case
mFix is ignored
"""
s11,s22,s33,s12,s23,s31 = sigmas
if dim == 2:
(a1,a2,a3,a4), (b1,b2,b3,b4,b5,b10), c = paras[0:4],paras[4:10],paras[10]
@ -356,13 +346,14 @@ def Drucker(eqStress=None,#not needed/supported
criteria=None,
dim=3,
Jac=False):
'''
Drucker yield criterion
the fitted parameters are
sigma0, C_D for Drucker(p=1);
sigma0, C_D, p for general Drucker
eqStress, mFix are invalid inputs
'''
"""
Drucker yield criterion
the fitted parameters are
sigma0, C_D for Drucker(p=1);
sigma0, C_D, p for general Drucker
eqStress, mFix are invalid inputs
"""
if criteria == 'drucker':
sigma0, C_D= paras
p = 1.0
@ -386,7 +377,7 @@ def Drucker(eqStress=None,#not needed/supported
if criteria == 'drucker':
return np.vstack((-r/sigma0, -drdl*J3_2p)).T
else:
dldp = 3.0*J2_3p*math_ln(J2) - 2.0*C_D*J3_2p*math_ln(J3)
dldp = 3.0*J2_3p*math_ln(J[1]) - 2.0*C_D*J3_2p*math_ln(J[2])
jp = drdl*dldp + r*math_ln(left)/(-6.0*p*p)
if mFix[0]: return np.vstack((-r/sigma0, -drdl*J3_2p)).T
@ -399,12 +390,13 @@ def Hill1948(eqStress=None,#not needed/supported
criteria=None,#not needed/supported
dim=3,
Jac=False):
'''
Hill 1948 yield criterion
the fitted parameters are:
F, G, H, L, M, N for 3D
F, G, H, N for 2D
'''
"""
Hill 1948 yield criterion
the fitted parameters are:
F, G, H, L, M, N for 3D
F, G, H, N for 2D
"""
s11,s22,s33,s12,s23,s31 = sigmas
if dim == 2: # plane stress
jac = np.array([ s22**2, s11**2, (s11-s22)**2, 2.0*s12**2])
@ -423,11 +415,11 @@ def Hill1979(eqStress=None,#not needed/supported
criteria=None,#not needed/supported
dim=3,
Jac=False):
'''
Hill 1979 yield criterion
the fitted parameters are: f,g,h,a,b,c,m
'''
"""
Hill 1979 yield criterion
the fitted parameters are: f,g,h,a,b,c,m
"""
if mFix[0]:
m = mFix[1]
else:
@ -458,14 +450,14 @@ def Hosford(eqStress=None,
criteria=None,
dim=3,
Jac=False):
'''
Hosford family criteria
the fitted parameters are:
von Mises: sigma0
Hershey: (1) sigma0, a, when a is not fixed; (2) sigma0, when a is fixed
general Hosford: (1) F,G,H, a, when a is not fixed; (2) F,G,H, when a is fixed
'''
"""
Hosford family criteria
the fitted parameters are:
von Mises: sigma0
Hershey: (1) sigma0, a, when a is not fixed; (2) sigma0, when a is fixed
general Hosford: (1) F,G,H, a, when a is not fixed; (2) F,G,H, when a is fixed
"""
if criteria == 'vonmises':
sigma0 = paras
coeff = np.ones(3)
@ -509,11 +501,12 @@ def Barlat1989(eqStress=None,
criteria=None,
dim=3,
Jac=False):
'''
Barlat-Lian 1989 yield criteria
the fitted parameters are:
Anisotropic: a, h, p, m; m is optional
'''
"""
Barlat-Lian 1989 yield criteria
the fitted parameters are:
Anisotropic: a, h, p, m; m is optional
"""
a, h, p = paras[0:3]
if mFix[0]: m = mFix[1]
else: m = paras[-1]
@ -536,7 +529,7 @@ def Barlat1989(eqStress=None,
drdl, drdm = r/m/left, r*math_ln(0.5*left)*(-1.0/m/m)
dldm = np.dot(np.array([a,a,c]),fm*math_ln(fs))*0.5
ja = drdl*dlda
ja,jc = drdl*dlda, drdl*dldc
jh,jp = drdl*(dldk1*dk1dh + dldk2*dk2dh), drdl*dldk2*dk2dp
jm = drdl*dldm + drdm
@ -544,13 +537,14 @@ def Barlat1989(eqStress=None,
else: return np.vstack((ja,jc,jh,jp,jm)).T
def Barlat1991(eqStress, paras, sigmas, mFix, criteria, dim, Jac=False):
'''
Barlat 1991 criteria
the fitted parameters are:
Anisotropic: a, b, c, f, g, h, m for 3D
a, b, c, h, m for plane stress
m is optional
'''
"""
Barlat 1991 criteria
the fitted parameters are:
Anisotropic: a, b, c, f, g, h, m for 3D
a, b, c, h, m for plane stress
m is optional
"""
if dim == 2: coeff = paras[0:4] # plane stress
else: coeff = paras[0:6] # general case
if mFix[0]: m = mFix[1]
@ -605,12 +599,13 @@ def Barlat1991(eqStress, paras, sigmas, mFix, criteria, dim, Jac=False):
else: return np.vstack((dfdI2*dI2dx + dfdI3*dI3dx, jm)).T
def BBC2000(eqStress, paras, sigmas, mFix, criteria, dim, Jac=False):
'''
BBC2000 yield criterion
the fitted parameters are
d,e,f,g, b,c,a, k; k is optional
criteria are invalid input
'''
"""
BBC2000 yield criterion
the fitted parameters are
d,e,f,g, b,c,a, k; k is optional
criteria are invalid input
"""
d,e,f,g, b,c,a= paras[0:7]
if mFix[0]: k = mFix[1]
else: k = paras[-1]
@ -647,12 +642,13 @@ def BBC2000(eqStress, paras, sigmas, mFix, criteria, dim, Jac=False):
def BBC2003(eqStress, paras, sigmas, mFix, criteria, dim, Jac=False):
'''
BBC2003 yield criterion
the fitted parameters are
M,N,P,Q,R,S,T,a, k; k is optional
criteria are invalid input
'''
"""
BBC2003 yield criterion
the fitted parameters are
M,N,P,Q,R,S,T,a, k; k is optional
criteria are invalid input
"""
M,N,P,Q,R,S,T,a = paras[0:8]
if mFix[0]: k = mFix[1]
else: k = paras[-1]
@ -689,12 +685,13 @@ def BBC2003(eqStress, paras, sigmas, mFix, criteria, dim, Jac=False):
else : return np.vstack((J, drdl*dldk+drdk)).T
def BBC2005(eqStress, paras, sigmas, mFix, criteria, dim, Jac=False):
'''
BBC2005 yield criterion
the fitted parameters are
a, b, L ,M, N, P, Q, R, k; k is optional
criteria are invalid input
'''
"""
BBC2005 yield criterion
the fitted parameters are
a, b, L ,M, N, P, Q, R, k k are optional
criteria is invalid input
"""
a,b,L, M, N, P, Q, R = paras[0:8]
if mFix[0]: k = mFix[1]
else: k = paras[-1]
@ -739,10 +736,12 @@ def BBC2005(eqStress, paras, sigmas, mFix, criteria, dim, Jac=False):
else : return np.vstack(J, dldk+dsBarde*dedk).T
def Yld2000(eqStress, paras, sigmas, mFix, criteria, dim, Jac=False):
'''
C: c11,c22,c66 c12=c21=1.0 JAC NOT PASS
D: d11,d12,d21,d22,d66
'''
"""
Yld2000 yield criterion
C: c11,c22,c66 c12=c21=1.0 JAC NOT PASS
D: d11,d12,d21,d22,d66
"""
C,D = paras[0:3], paras[3:8]
if mFix[0]: m = mFix[1]
else: m = paras[-1]
@ -769,8 +768,7 @@ def Yld2000(eqStress, paras, sigmas, mFix, criteria, dim, Jac=False):
drdl, drdm = r/m/left, r*math_ln(0.5*left)*(-1.0/m/m) #/(-m*m)
dldm = ( phi1*math_ln(phi1s) + phi21*math_ln(phi21s) + phi22*math_ln(phi22s) )*0.5
zero = np.zeros_like(s11); num = len(s11)
def dPrincipalds((X1,X2,X12)):
# the derivative of principla with regards to stress
def dPrincipalds((X1,X2,X12)): # derivative of principla with respect to stress
temp = 1.0/np.sqrt( (X1-X2)**2 + 4.0*X12**2 )
dP1dsi = 0.5*np.array([ 1.0+temp*(X1-X2), 1.0-temp*(X1-X2), temp*4.0*X12])
dP2dsi = 0.5*np.array([ 1.0-temp*(X1-X2), 1.0+temp*(X1-X2), -temp*4.0*X12])
@ -798,14 +796,15 @@ def Yld2000(eqStress, paras, sigmas, mFix, criteria, dim, Jac=False):
else: return np.vstack((jC,jD,jm)).T
def Yld200418p(eqStress, paras, sigmas, mFix, criteria, dim, Jac=False):
'''
Yld2004-18p yield criterion
the fitted parameters are
C: c12,c21,c23,c32,c31,c13,c44,c55,c66; D: d12,d21,d23,d32,d31,d13,d44,d55,d66 for 3D
C: c12,c21,c23,c32,c31,c13,c44; D: d12,d21,d23,d32,d31,d13,d44 for 2D
and m, m is optional
criteria are invalid input
'''
"""
Yld2004-18p yield criterion
the fitted parameters are
C: c12,c21,c23,c32,c31,c13,c44,c55,c66; D: d12,d21,d23,d32,d31,d13,d44,d55,d66 for 3D
C: c12,c21,c23,c32,c31,c13,c44; D: d12,d21,d23,d32,d31,d13,d44 for 2D
and m, m are optional
criteria is ignored
"""
if dim == 2: C,D = np.append(paras[0:7],[0.0,0.0]), np.append(paras[7:14],[0.0,0.0])
else: C,D = paras[0:9], paras[9:18]
if mFix[0]: m = mFix[1]
@ -843,14 +842,15 @@ def Yld200418p(eqStress, paras, sigmas, mFix, criteria, dim, Jac=False):
else: return np.vstack((jc,jd,jm)).T
def KarafillisBoyce(eqStress, paras, sigmas, mFix, criteria, dim, Jac=False):
'''
Karafillis-Boyce
the fitted parameters are
c11,c12,c13,c14,c15,c16,c,m for 3D
c11,c12,c13,c14,c,m for plane stress
0<c<1, m are optional
criteria are invalid input
'''
"""
Karafillis-Boyce
the fitted parameters are
c11,c12,c13,c14,c15,c16,c,m for 3D
c11,c12,c13,c14,c,m for plane stress
0<c<1, m are optional
criteria are invalid input
"""
ks = lambda (s1,s2,s3,s4,s5,s6),(c1,c2,c3,c4,c5,c6): np.array( [
((c2+c3)*s1-c3*s2-c2*s3)/3.0, ((c3+c1)*s2-c3*s1-c1*s3)/3.0,
((c1+c2)*s3-c2*s1-c1*s2)/3.0, c4*s4, c5*s5, c6*s6 ])
@ -1007,7 +1007,8 @@ fitCriteria = {
'nExpo': 1,'err':np.inf,
'dimen': [3],
'bound': [[(None,None)]*18+[(1.0,8.0)], [(None,None)]*14+[(1.0,8.0)]],
'labels': [['c12','c21','c23','c32','c31','c13','c44','c55','c66','d12','d21','d23','d32','d31','d13','d44','d55','d66','m'],
'labels': [['c12','c21','c23','c32','c31','c13','c44','c55','c66',
'd12','d21','d23','d32','d31','d13','d44','d55','d66','m'],
['c12','c21','c23','c32','c31','c13','c44','d12','d21','d23','d32','d31','d13','d44','m']],
},
'karafillis' :{'name': 'Karafillis-Boyce',
@ -1028,12 +1029,8 @@ thresholdParameter = ['totalshear','equivalentStrain']
#---------------------------------------------------------------------------------------------------
class Loadcase():
#---------------------------------------------------------------------------------------------------
'''
Class for generating load cases for the spectral solver
'''
"""generating load cases for the spectral solver"""
# ------------------------------------------------------------------
def __init__(self,finalStrain,incs,time,nSet=1,dimension=3,vegter=False):
self.finalStrain = finalStrain
self.incs = incs
@ -1087,7 +1084,6 @@ class Loadcase():
' time %s'%self.time
def _getLoadcase2dVegter(self,number): #for a 2D simulation, I would use this generator before switching to a random 2D generator
NDzero=[[1,2,3,6],[1,3,5,7],[2,5,6,7]] # no deformation / * for stress
# biaxial f1 = f2
# shear f1 = -f2
# unixaial f1 , f2 =0
@ -1102,9 +1098,7 @@ class Loadcase():
' time %s'%self.time
def _vegterLoadcase(self):
'''
generate the stress points for Vegter criteria
'''
"""generate the stress points for Vegter criteria (incomplete/untested)"""
theta = np.linspace(0.0,np.pi/2.0,self.nSet)
f = [0.0, 0.0, '*']*3; loadcase = []
for i in xrange(self.nSet*4): loadcase.append(f)
@ -1115,16 +1109,14 @@ class Loadcase():
[[1.1, 0.1], [0.1, 1.1]], # eq-biaxial
[[1.1, 0.1], [0.1, 1.1]], # eq-biaxial
])
# for i,t in enumerate(theta):
# R = np.array([np.cos(t), np.sin(t), -np.sin(t), np.cos(t)]).reshape(2,2)
# for j in xrange(4):
# loadcase[i*4+j][0],loadcase[i*4+j][1],loadcase[i*4+j][3],loadcase[i*4+j][4] = np.dot(R.T,np.dot(F[j],R)).reshape(4)
# return loadcase
for i,t in enumerate(theta):
R = np.array([np.cos(t), np.sin(t), -np.sin(t), np.cos(t)]).reshape(2,2)
for j in xrange(4):
loadcase[i*4+j][0],loadcase[i*4+j][1],loadcase[i*4+j][3],loadcase[i*4+j][4] = np.dot(R.T,np.dot(F[j],R)).reshape(4)
return loadcase
def _getLoadcase2dRandom(self):
'''
generate random stress points for 2D tests
'''
"""generate random stress points for 2D tests"""
self.NgeneratedLoadCases+=1
defgrad=['0', '0', '*']*3
stress =['*', '*', '0']*3
@ -1135,8 +1127,6 @@ class Loadcase():
' incs %s'%self.incs+\
' time %s'%self.time
def _defgradScale(self, defgrad):
'''
'''
def fill_star(a,b):
if a != '*' and b != '*': return a,b
elif a == '*' and b != '*': return b,b
@ -1160,10 +1150,8 @@ class Loadcase():
#---------------------------------------------------------------------------------------------------
class Criterion(object):
#---------------------------------------------------------------------------------------------------
'''
Fitting to certain criterion
'''
"""Fitting to certain criterion"""
def __init__(self, exponent, uniaxial, dimension, label='vonmises'):
self.name = label
self.expo = exponent
@ -1187,7 +1175,7 @@ class Criterion(object):
def fit(self,stress):
global fitResults; fitErrors; fitResidual
if options.exponent > 0.0: nExponent = nExpo
if options.exponent > 0.0: nExponent = options.exponent
else: nExponent = 0
nameCriterion = self.name.lower()
criteria = Criteria(nameCriterion,self.uniaxial,self.expo, self.dimen)
@ -1225,13 +1213,10 @@ class Criterion(object):
pass
return popt
#---------------------------------------------------------------------------------------------------
class myThread (threading.Thread):
#---------------------------------------------------------------------------------------------------
'''
Runner class
'''
"""Runner"""
def __init__(self, threadID):
threading.Thread.__init__(self)
self.threadID = threadID
@ -1246,8 +1231,6 @@ class myThread (threading.Thread):
s.release()
def doSim(thread):
# if load case do not exist, create new one
s.acquire()
global myLoad
loadNo=loadcaseNo()
@ -1337,7 +1320,7 @@ def doSim(thread):
strainAll[i]=np.append(strainAll[i], deformationRate[i])
f.write( str(threshold)+' '+
' '.join(map(str,myFit.fit(stressAll[i].reshape(len(stressAll[i])//6,6).transpose())))+'\n')
except Exception as detail:
except Exception:
damask.util.croak('Could not fit results of simulation (%s)'%thread)
s.release()
return
@ -1440,7 +1423,7 @@ else : stressUnit = 1.0e6
if options.dimension not in fitCriteria[options.criterion]['dimen']:
parser.error('invalid dimension for selected criterion')
if options.criterion not in ['vonmises','tresca','drucker','hill1984'] and options.eqStress == None:
if options.criterion not in ['vonmises','tresca','drucker','hill1984'] and options.eqStress is None:
parser.error('please specifie an equivalent stress (e.g. fitting to von Mises)')
run = runFit(options.exponent, options.eqStress, options.dimension, options.criterion)

View File

@ -1,7 +1,7 @@
#!/usr/bin/env python
# -*- coding: UTF-8 no BOM -*-
import os,sys,re,string,fnmatch,vtk
import os,sys,re,fnmatch,vtk
import numpy as np
from optparse import OptionParser
import damask
@ -56,8 +56,7 @@ def unravel(item):
# ++++++++++++++++++++++++++++++++++++++++++++++++++++
def vtk_writeASCII_mesh(mesh,data,res,sep):
# ++++++++++++++++++++++++++++++++++++++++++++++++++++
""" function writes data array defined on a hexahedral mesh (geometry) """
"""function writes data array defined on a hexahedral mesh (geometry)"""
info = {\
'tensor': {'name':'tensor','len':9},\
'vector': {'name':'vector','len':3},\
@ -110,11 +109,10 @@ def vtk_writeASCII_mesh(mesh,data,res,sep):
]
return cmds
# +++++++++++++++++++++++++++++++++++++++++++++++++++
#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
def vtk_writeASCII_points(coordinates,data,res,sep):
# +++++++++++++++++++++++++++++++++++++++++++++++++++
""" function writes data array defined on a point field """
"""function writes data array defined on a point field"""
N = res[0]*res[1]*res[2]
cmds = [\
@ -216,7 +214,7 @@ for filename in args:
content = file.readlines()
file.close()
m = re.search('(\d+)\s*head', content[0].lower())
if m == None:
if m is None:
continue
print filename,'\n'
sys.stdout.flush()
@ -432,4 +430,4 @@ for filename in args:
vtk = open(os.path.join(head,what+'_'+os.path.splitext(tail)[0]+'.vtk'), 'w')
output(out[what],{'filepointer':vtk},'File')
vtk.close()
print
print

View File

@ -1,7 +1,7 @@
#!/usr/bin/env python
# -*- coding: UTF-8 no BOM -*-
import os,sys,string
import os,sys
import numpy as np
from optparse import OptionParser
import damask
@ -19,13 +19,13 @@ Transform X,Y,Z,F APS BeamLine 34 coordinates to x,y,z APS strain coordinates.
""", version = scriptID)
parser.add_option('-f','--frame', dest='frame', nargs=4, type='string', metavar='<string string string string>',
parser.add_option('-f','--frame', dest='frame', nargs=4, type='string', metavar='string string string string',
help='APS X,Y,Z coords, and depth F')
parser.set_defaults(frame = None)
(options,filenames) = parser.parse_args()
if options.frame == None:
if options.frame is None:
parser.error('no data column specified...')
@ -33,7 +33,7 @@ datainfo = {'len':3,
'label':[]
}
if options.frame != None: datainfo['label'] += options.frame
datainfo['label'] += options.frame
# --- loop over input files -------------------------------------------------------------------------
if filenames == []:
@ -75,8 +75,8 @@ for name in filenames:
# ------------------------------------------ process data ------------------------------------------
theta=-0.75*np.pi
RotMat2TSL=np.array([[1., 0., 0.],
[0., np.cos(theta), np.sin(theta)],
[0., -np.sin(theta), np.cos(theta)]]) # Orientation Matrix to account for -135 degree rotation for TSL Convention[Adapted from Chen Zhang's code]
[0., np.cos(theta), np.sin(theta)], # Orientation to account for -135 deg
[0., -np.sin(theta), np.cos(theta)]]) # rotation for TSL convention
vec = np.zeros(4)
outputAlive = True
@ -94,4 +94,4 @@ for name in filenames:
table.input_close() # close input ASCII table (works for stdin)
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
os.rename(file['name']+'_tmp',file['name']) # overwrite old one with tmp new

View File

@ -1,8 +1,8 @@
#!/usr/bin/env python
# -*- coding: UTF-8 no BOM -*-
import os,re,sys,string
import math # flake8: noqa
import os,re,sys
import math # noqa
import numpy as np
from optparse import OptionParser
import damask
@ -39,7 +39,7 @@ parser.add_option('-f','--formula',
(options,filenames) = parser.parse_args()
if options.labels == None or options.formulas == None:
if options.labels is None or options.formulas is None:
parser.error('no formulas and/or labels specified.')
if len(options.labels) != len(options.formulas):
parser.error('number of labels ({}) and formulas ({}) do not match.'.format(len(options.labels),len(options.formulas)))
@ -126,4 +126,4 @@ for name in filenames:
# ------------------------------------------ output finalization -----------------------------------
table.close() # close ASCII tables
table.close() # close ASCII tables

View File

@ -1,7 +1,7 @@
#!/usr/bin/env python
# -*- coding: UTF-8 no BOM -*-
import os,sys,string
import os,sys
import numpy as np
from optparse import OptionParser
import damask

View File

@ -1,36 +1,16 @@
#!/usr/bin/env python
# -*- coding: UTF-8 no BOM -*-
import os,re,sys,math,string,h5py
import os,string,h5py
import numpy as np
from optparse import OptionParser
import damask
from optparse import OptionParser, Option
# -----------------------------
class extendableOption(Option):
# -----------------------------
# used for definition of new option parser action 'extend', which enables to take multiple option arguments
# taken from online tutorial http://docs.python.org/library/optparse.html
ACTIONS = Option.ACTIONS + ("extend",)
STORE_ACTIONS = Option.STORE_ACTIONS + ("extend",)
TYPED_ACTIONS = Option.TYPED_ACTIONS + ("extend",)
ALWAYS_TYPED_ACTIONS = Option.ALWAYS_TYPED_ACTIONS + ("extend",)
def take_action(self, action, dest, opt, value, values, parser):
if action == "extend":
lvalue = value.split(",")
values.ensure_value(dest, []).extend(lvalue)
else:
Option.take_action(self, action, dest, opt, value, values, parser)
# --------------------------------------------------------------------
# MAIN
# --------------------------------------------------------------------
parser = OptionParser(option_class=extendableOption, usage='%prog options [file[s]]', description = """
parser = OptionParser(option_class=damask.extendableOption, usage='%prog options [file[s]]', description = """
Add column(s) containing Cauchy stress based on given column(s) of
deformation gradient and first Piola--Kirchhoff stress.
@ -50,7 +30,7 @@ parser.set_defaults(output = 'crystallite')
(options,filenames) = parser.parse_args()
if options.defgrad == None or options.stress == None or options.output == None:
if options.defgrad is None or options.stress is None or options.output is None:
parser.error('missing data column...')
@ -79,6 +59,3 @@ for myFile in files:
cauchy[p,...] = 1.0/np.linalg.det(defgrad[p,...])*np.dot(stress[p,...],defgrad[p,...].T) # [Cauchy] = (1/det(F)) * [P].[F_transpose]
cauchyFile = myFile['file']['increments/'+inc+'/'+options.output+'/'+instance].create_dataset('cauchy', data=cauchy)
cauchyFile.attrs['units'] = 'Pa'

View File

@ -1,7 +1,7 @@
#!/usr/bin/env python
# -*- coding: UTF-8 no BOM -*-
import os,sys,string
import os,sys
import numpy as np
from optparse import OptionParser
import damask
@ -81,7 +81,6 @@ for name in filenames:
table.info_append(scriptID + '\t' + ' '.join(sys.argv[1:]))
if options.shape: table.labels_append('shapeMismatch({})'.format(options.defgrad))
if options.volume: table.labels_append('volMismatch({})'.format(options.defgrad))
#table.head_write()
# --------------- figure out size and grid ---------------------------------------------------------
@ -92,7 +91,7 @@ for name in filenames:
maxcorner = np.array(map(max,coords))
grid = np.array(map(len,coords),'i')
size = grid/np.maximum(np.ones(3,'d'), grid-1.0) * (maxcorner-mincorner) # size from edge to edge = dim * n/(n-1)
size = np.where(grid > 1, size, min(size[grid > 1]/grid[grid > 1])) # spacing for grid==1 equal to smallest among other spacings
size = np.where(grid > 1, size, min(size[grid > 1]/grid[grid > 1])) # spacing for grid==1 set to smallest among other spacings
N = grid.prod()
@ -116,8 +115,8 @@ for name in filenames:
while table.data_read():
(x,y,z) = damask.util.gridLocation(idx,grid) # figure out (x,y,z) position from line count
idx += 1
F[0:3,0:3,x,y,z] = np.array(map(float,table.data[column:column+9]),'d').reshape(3,3)
print 'hm'
F[0:3,0:3,x,y,z] = np.array(map(float,table.data[column:column+9]),'d').reshape(3,3)
Favg = damask.core.math.tensorAvg(F)
centres = damask.core.mesh.deformedCoordsFFT(size,F,Favg,[1.0,1.0,1.0])

View File

@ -1,7 +1,7 @@
#!/usr/bin/env python
# -*- coding: UTF-8 no BOM -*-
import os,sys,string
import os,sys
import numpy as np
from optparse import OptionParser
import damask

View File

@ -1,7 +1,7 @@
#!/usr/bin/env python
# -*- coding: UTF-8 no BOM -*-
import os,sys,string,math
import os,sys,math
import numpy as np
from optparse import OptionParser
import damask
@ -10,40 +10,35 @@ scriptName = os.path.splitext(os.path.basename(__file__))[0]
scriptID = ' '.join([scriptName,damask.version])
def curlFFT(geomdim,field):
N = grid.prod() # field size
n = np.array(np.shape(field)[3:]).prod() # data size
grid = np.array(np.shape(field)[2::-1])
N = grid.prod() # field size
n = np.array(np.shape(field)[3:]).prod() # data size
if n == 3:
dataType = 'vector'
elif n == 9:
dataType = 'tensor'
if n == 3: dataType = 'vector'
elif n == 9: dataType = 'tensor'
field_fourier = np.fft.fftpack.rfftn(field,axes=(0,1,2))
curl_fourier = np.zeros(field_fourier.shape,'c16')
# differentiation in Fourier space
k_s = np.zeros([3],'i')
TWOPIIMG = (0.0+2.0j*math.pi)
TWOPIIMG = 2.0j*math.pi
for i in xrange(grid[2]):
k_s[0] = i
if(grid[2]%2==0 and i == grid[2]//2): # for even grid, set Nyquist freq to 0 (Johnson, MIT, 2011)
k_s[0]=0
elif (i > grid[2]//2):
k_s[0] = k_s[0] - grid[2]
if grid[2]%2 == 0 and i == grid[2]//2: k_s[0] = 0 # for even grid, set Nyquist freq to 0 (Johnson, MIT, 2011)
elif i > grid[2]//2: k_s[0] -= grid[2]
for j in xrange(grid[1]):
k_s[1] = j
if(grid[1]%2==0 and j == grid[1]//2): # for even grid, set Nyquist freq to 0 (Johnson, MIT, 2011)
k_s[1]=0
elif (j > grid[1]//2):
k_s[1] = k_s[1] - grid[1]
if grid[1]%2 == 0 and j == grid[1]//2: k_s[1] = 0 # for even grid, set Nyquist freq to 0 (Johnson, MIT, 2011)
elif j > grid[1]//2: k_s[1] -= grid[1]
for k in xrange(grid[0]//2+1):
k_s[2] = k
if(grid[0]%2==0 and k == grid[0]//2): # for even grid, set Nyquist freq to 0 (Johnson, MIT, 2011)
k_s[2]=0
if grid[0]%2 == 0 and k == grid[0]//2: k_s[2] = 0 # for even grid, set Nyquist freq to 0 (Johnson, MIT, 2011)
xi = (k_s/geomdim)[2::-1].astype('c16') # reversing the field input order
xi = np.array([k_s[2]/geomdim[2]+0.0j,k_s[1]/geomdim[1]+0.j,k_s[0]/geomdim[0]+0.j],'c16')
if dataType == 'tensor':
for l in xrange(3):
curl_fourier[i,j,k,0,l] = ( field_fourier[i,j,k,l,2]*xi[1]\
@ -76,23 +71,23 @@ Deals with both vector- and tensor-valued fields.
parser.add_option('-c','--coordinates',
dest = 'coords',
type = 'string', metavar='string',
help = 'column heading for coordinates [%default]')
type = 'string', metavar = 'string',
help = 'column label of coordinates [%default]')
parser.add_option('-v','--vector',
dest = 'vector',
action = 'extend', metavar = '<string LIST>',
help = 'heading of columns containing vector field values')
help = 'column label(s) of vector field values')
parser.add_option('-t','--tensor',
dest = 'tensor',
action = 'extend', metavar = '<string LIST>',
help = 'heading of columns containing tensor field values')
help = 'column label(s) of tensor field values')
parser.set_defaults(coords = 'ipinitialcoord',
parser.set_defaults(coords = 'pos',
)
(options,filenames) = parser.parse_args()
if options.vector == None and options.tensor == None:
if options.vector is None and options.tensor is None:
parser.error('no data column specified.')
# --- loop over input files -------------------------------------------------------------------------
@ -100,10 +95,8 @@ if options.vector == None and options.tensor == None:
if filenames == []: filenames = [None]
for name in filenames:
try:
table = damask.ASCIItable(name = name,buffered = False)
except:
continue
try: table = damask.ASCIItable(name = name,buffered = False)
except: continue
damask.util.report(scriptName,name)
# ------------------------------------------ read header ------------------------------------------
@ -161,8 +154,9 @@ for name in filenames:
stack = [table.data]
for type, data in items.iteritems():
for i,label in enumerate(data['active']):
stack.append(curlFFT(size[::-1], # we need to reverse order here, because x is fastest,ie rightmost, but leftmost in our x,y,z notation
table.data[:,data['column'][i]:data['column'][i]+data['dim']].\
# we need to reverse order here, because x is fastest,ie rightmost, but leftmost in our x,y,z notation
stack.append(curlFFT(size[::-1],
table.data[:,data['column'][i]:data['column'][i]+data['dim']].
reshape([grid[2],grid[1],grid[0]]+data['shape'])))
# ------------------------------------------ output result -----------------------------------------

View File

@ -1,164 +0,0 @@
#!/usr/bin/env python
# -*- coding: UTF-8 no BOM -*-
import os,sys,string,math
import numpy as np
from optparse import OptionParser
import damask
scriptName = os.path.splitext(os.path.basename(__file__))[0]
scriptID = ' '.join([scriptName,damask.version])
#--------------------------------------------------------------------------------------------------
def deformedCoordsFFT(F,undeformed=False):
#--------------------------------------------------------------------------------------------------
wgt = 1.0/grid.prod()
integrator = np.array([0.+1.j,0.+1.j,0.+1.j],'c16') * size/ 2.0 / math.pi
step = size/grid
F_fourier = np.fft.rfftn(F,axes=(0,1,2))
coords_fourier = np.zeros(F_fourier.shape[0:4],'c16')
if undeformed:
Favg=np.eye(3)
else:
Favg=np.real(F_fourier[0,0,0,:,:])*wgt
#--------------------------------------------------------------------------------------------------
# integration in Fourier space
k_s = np.zeros([3],'i')
for i in xrange(grid[2]):
k_s[2] = i
if(i > grid[2]//2 ): k_s[2] = k_s[2] - grid[2]
for j in xrange(grid[1]):
k_s[1] = j
if(j > grid[1]//2 ): k_s[1] = k_s[1] - grid[1]
for k in xrange(grid[0]//2+1):
k_s[0] = k
for m in xrange(3):
coords_fourier[i,j,k,m] = sum(F_fourier[i,j,k,m,0:3]*k_s*integrator)
if (any(k_s != 0)):
coords_fourier[i,j,k,0:3] /= -sum(k_s*k_s)
#--------------------------------------------------------------------------------------------------
# add average to scaled fluctuation and put (0,0,0) on (0,0,0)
coords = np.fft.irfftn(coords_fourier,F.shape[0:3],axes=(0,1,2))
offset_coords = np.dot(F[0,0,0,:,:],step/2.0) - scaling*coords[0,0,0,0:3]
for z in xrange(grid[2]):
for y in xrange(grid[1]):
for x in xrange(grid[0]):
coords[z,y,x,0:3] = scaling*coords[z,y,x,0:3] \
+ offset_coords \
+ np.dot(Favg,step*np.array([x,y,z]))
return coords
# --------------------------------------------------------------------
# MAIN
# --------------------------------------------------------------------
parser = OptionParser(option_class=damask.extendableOption, usage='%prog options file[s]', description = """
Add deformed configuration of given initial coordinates.
Operates on periodic three-dimensional x,y,z-ordered data sets.
""", version = scriptID)
parser.add_option('-f', '--defgrad',dest='defgrad', metavar = 'string',
help='heading of deformation gradient columns [%default]')
parser.add_option('--reference', dest='undeformed', action='store_true',
help='map results to reference (undeformed) average configuration [%default]')
parser.add_option('--scaling', dest='scaling', action='extend', metavar = '<float LIST>',
help='scaling of fluctuation')
parser.add_option('-u', '--unitlength', dest='unitlength', type='float', metavar = 'float',
help='set unit length for 2D model [%default]')
parser.add_option('--coordinates', dest='coords', metavar='string',
help='column heading for coordinates [%default]')
parser.set_defaults(defgrad = 'f')
parser.set_defaults(coords = 'ipinitialcoord')
parser.set_defaults(scaling = [])
parser.set_defaults(undeformed = False)
parser.set_defaults(unitlength = 0.0)
(options,filenames) = parser.parse_args()
options.scaling += [1.0 for i in xrange(max(0,3-len(options.scaling)))]
scaling = map(float, options.scaling)
# --- loop over input files -------------------------------------------------------------------------
if filenames == []: filenames = [None]
for name in filenames:
try:
table = damask.ASCIItable(name = name,
buffered = False)
except: continue
damask.util.report(scriptName,name)
# ------------------------------------------ read header ------------------------------------------
table.head_read()
# ------------------------------------------ sanity checks ----------------------------------------
errors = []
remarks = []
if table.label_dimension(options.coords) != 3: errors.append('coordinates {} are not a vector.'.format(options.coords))
else: colCoord = table.label_index(options.coords)
if table.label_dimension(options.defgrad) != 9: errors.append('deformation gradient {} is not a tensor.'.format(options.defgrad))
else: colF = table.label_index(options.defgrad)
if remarks != []: damask.util.croak(remarks)
if errors != []:
damask.util.croak(errors)
table.close(dismiss = True)
continue
# --------------- figure out size and grid ---------------------------------------------------------
table.data_readArray()
coords = [np.unique(table.data[:,colCoord+i]) for i in xrange(3)]
mincorner = np.array(map(min,coords))
maxcorner = np.array(map(max,coords))
grid = np.array(map(len,coords),'i')
size = grid/np.maximum(np.ones(3,'d'), grid-1.0) * (maxcorner-mincorner) # size from edge to edge = dim * n/(n-1)
size = np.where(grid > 1, size, min(size[grid > 1]/grid[grid > 1])) # spacing for grid==1 equal to smallest among other spacings
N = grid.prod()
if N != len(table.data): errors.append('data count {} does not match grid {}x{}x{}.'.format(N,*grid))
if errors != []:
damask.util.croak(errors)
table.close(dismiss = True)
continue
# ------------------------------------------ assemble header ---------------------------------------
table.info_append(scriptID + '\t' + ' '.join(sys.argv[1:]))
for coord in xrange(3):
label = '{}_{}_{}'.format(coord+1,options.defgrad,options.coords)
if np.any(scaling) != 1.0: label+='_{}_{}_{}'.format(scaling)
if options.undeformed: label+='_undeformed'
table.labels_append([label]) # extend ASCII header with new labels
table.head_write()
# ------------------------------------------ read deformation gradient field -----------------------
centroids = deformedCoordsFFT(table.data[:,colF:colF+9].reshape(grid[2],grid[1],grid[0],3,3),
options.undeformed)
# ------------------------------------------ process data ------------------------------------------
table.data_rewind()
for z in xrange(grid[2]):
for y in xrange(grid[1]):
for x in xrange(grid[0]):
table.data_read()
table.data_append(list(centroids[z,y,x,:]))
table.data_write()
# ------------------------------------------ output finalization -----------------------------------
table.close() # close ASCII tables

View File

@ -1,7 +1,7 @@
#!/usr/bin/env python
# -*- coding: UTF-8 no BOM -*-
import os,sys,string
import os,sys
from optparse import OptionParser
import damask
@ -32,7 +32,7 @@ parser.add_option('-t','--tensor',
(options,filenames) = parser.parse_args()
if options.tensor == None:
if options.tensor is None:
parser.error('no data column specified.')
# --- loop over input files -------------------------------------------------------------------------
@ -89,4 +89,4 @@ for name in filenames:
# ------------------------------------------ output finalization -----------------------------------
table.close() # close input ASCII table (works for stdin)
table.close() # close input ASCII table (works for stdin)

View File

@ -1,7 +1,7 @@
#!/usr/bin/env python
# -*- coding: UTF-8 no BOM -*-
import os,sys,string
import os,sys
from optparse import OptionParser
import damask
@ -10,7 +10,7 @@ scriptID = ' '.join([scriptName,damask.version])
oneThird = 1.0/3.0
def deviator(m,spherical = False): # Carefull, do not change the value of m (its intent(inout)!)
def deviator(m,spherical = False): # Careful, do not change the value of m, its intent(inout)!
sph = oneThird*(m[0]+m[4]+m[8])
dev = [
m[0]-sph, m[1], m[2],
@ -39,7 +39,7 @@ parser.add_option('-s','--spherical',
(options,filenames) = parser.parse_args()
if options.tensor == None:
if options.tensor is None:
parser.error('no data column specified...')
# --- loop over input files -------------------------------------------------------------------------
@ -101,4 +101,4 @@ for name in filenames:
# ------------------------------------------ output finalization -----------------------------------
table.close() # close input ASCII table (works for stdin)
table.close() # close input ASCII table (works for stdin)

View File

@ -0,0 +1,227 @@
#!/usr/bin/env python
# -*- coding: UTF-8 no BOM -*-
import os,sys,math
import numpy as np
import scipy.ndimage
from optparse import OptionParser
import damask
scriptName = os.path.splitext(os.path.basename(__file__))[0]
scriptID = ' '.join([scriptName,damask.version])
#--------------------------------------------------------------------------------------------------
def cell2node(cellData,grid):
nodeData = 0.0
datalen = np.array(cellData.shape[3:]).prod()
for i in xrange(datalen):
node = scipy.ndimage.convolve(cellData.reshape(tuple(grid)+(datalen,))[...,i],
np.ones((2,2,2))/8., # 2x2x2 neighborhood of cells
mode = 'wrap',
origin = -1, # offset to have cell origin as center
) # now averaged at cell origins
node = np.append(node,node[np.newaxis,0,:,:,...],axis=0) # wrap along z
node = np.append(node,node[:,0,np.newaxis,:,...],axis=1) # wrap along y
node = np.append(node,node[:,:,0,np.newaxis,...],axis=2) # wrap along x
nodeData = node[...,np.newaxis] if i==0 else np.concatenate((nodeData,node[...,np.newaxis]),axis=-1)
return nodeData
#--------------------------------------------------------------------------------------------------
def displacementAvgFFT(F,grid,size,nodal=False,transformed=False):
"""calculate average cell center (or nodal) displacement for deformation gradient field specified in each grid cell"""
if nodal:
x, y, z = np.meshgrid(np.linspace(0,size[0],1+grid[0]),
np.linspace(0,size[1],1+grid[1]),
np.linspace(0,size[2],1+grid[2]),
indexing = 'ij')
else:
x, y, z = np.meshgrid(np.linspace(0,size[0],grid[0],endpoint=False),
np.linspace(0,size[1],grid[1],endpoint=False),
np.linspace(0,size[2],grid[2],endpoint=False),
indexing = 'ij')
origCoords = np.concatenate((z[:,:,:,None],y[:,:,:,None],x[:,:,:,None]),axis = 3)
F_fourier = F if transformed else np.fft.rfftn(F,axes=(0,1,2)) # transform or use provided data
Favg = np.real(F_fourier[0,0,0,:,:])/grid.prod() # take zero freq for average
avgDisplacement = np.einsum('ml,ijkl->ijkm',Favg-np.eye(3),origCoords) # dX = Favg.X
return avgDisplacement
#--------------------------------------------------------------------------------------------------
def displacementFluctFFT(F,grid,size,nodal=False,transformed=False):
"""calculate cell center (or nodal) displacement for deformation gradient field specified in each grid cell"""
integrator = 0.5j * size / math.pi
kk, kj, ki = np.meshgrid(np.where(np.arange(grid[2])>grid[2]//2,np.arange(grid[2])-grid[2],np.arange(grid[2])),
np.where(np.arange(grid[1])>grid[1]//2,np.arange(grid[1])-grid[1],np.arange(grid[1])),
np.arange(grid[0]//2+1),
indexing = 'ij')
k_s = np.concatenate((ki[:,:,:,None],kj[:,:,:,None],kk[:,:,:,None]),axis = 3)
k_sSquared = np.einsum('...l,...l',k_s,k_s)
k_sSquared[0,0,0] = 1.0 # ignore global average frequency
#--------------------------------------------------------------------------------------------------
# integration in Fourier space
displacement_fourier = -np.einsum('ijkml,ijkl,l->ijkm',
F if transformed else np.fft.rfftn(F,axes=(0,1,2)),
k_s,
integrator,
) / k_sSquared[...,np.newaxis]
#--------------------------------------------------------------------------------------------------
# backtransformation to real space
displacement = np.fft.irfftn(displacement_fourier,grid,axes=(0,1,2))
return cell2node(displacement,grid) if nodal else displacement
# --------------------------------------------------------------------
# MAIN
# --------------------------------------------------------------------
parser = OptionParser(option_class=damask.extendableOption, usage='%prog options file[s]', description = """
Add displacments resulting from deformation gradient field.
Operates on periodic three-dimensional x,y,z-ordered data sets.
Outputs at cell centers or cell nodes (into separate file).
""", version = scriptID)
parser.add_option('-f', '--defgrad',
dest = 'defgrad',
metavar = 'string',
help = 'column label of deformation gradient [%default]')
parser.add_option('-c', '--coordinates',
dest = 'coords',
metavar = 'string',
help = 'column label of coordinates [%default]')
parser.add_option('--nodal',
dest = 'nodal',
action = 'store_true',
help = 'output nodal (not cell-centered) displacements')
parser.set_defaults(defgrad = 'f',
coords = 'pos',
nodal = False,
)
(options,filenames) = parser.parse_args()
# --- loop over input files -------------------------------------------------------------------------
if filenames == []: filenames = [None]
for name in filenames:
try: table = damask.ASCIItable(name = name,
outname = (os.path.splitext(name)[0]+
'_nodal'+
os.path.splitext(name)[1]) if (options.nodal and name) else None,
buffered = False)
except: continue
damask.util.report(scriptName,name)
# ------------------------------------------ read header ------------------------------------------
table.head_read()
# ------------------------------------------ sanity checks ----------------------------------------
errors = []
remarks = []
if table.label_dimension(options.defgrad) != 9:
errors.append('deformation gradient "{}" is not a 3x3 tensor.'.format(options.defgrad))
coordDim = table.label_dimension(options.coords)
if not 3 >= coordDim >= 1:
errors.append('coordinates "{}" need to have one, two, or three dimensions.'.format(options.coords))
elif coordDim < 3:
remarks.append('appending {} dimension{} to coordinates "{}"...'.format(3-coordDim,
's' if coordDim < 2 else '',
options.coords))
if remarks != []: damask.util.croak(remarks)
if errors != []:
damask.util.croak(errors)
table.close(dismiss=True)
continue
# --------------- figure out size and grid ---------------------------------------------------------
table.data_readArray([options.defgrad,options.coords])
table.data_rewind()
if len(table.data.shape) < 2: table.data.shape += (1,) # expand to 2D shape
if table.data[:,9:].shape[1] < 3:
table.data = np.hstack((table.data,
np.zeros((table.data.shape[0],
3-table.data[:,9:].shape[1]),dtype='f'))) # fill coords up to 3D with zeros
if remarks != []: damask.util.croak(remarks)
if errors != []:
damask.util.croak(errors)
table.close(dismiss = True)
continue
# --------------- figure out size and grid ---------------------------------------------------------
coords = [np.unique(table.data[:,9+i]) for i in xrange(3)]
mincorner = np.array(map(min,coords))
maxcorner = np.array(map(max,coords))
grid = np.array(map(len,coords),'i')
size = grid/np.maximum(np.ones(3,'d'), grid-1.0) * (maxcorner-mincorner) # size from edge to edge = dim * n/(n-1)
size = np.where(grid > 1, size, min(size[grid > 1]/grid[grid > 1])) # spacing for grid==1 set to smallest among other spacings
N = grid.prod()
if N != len(table.data): errors.append('data count {} does not match grid {}x{}x{}.'.format(N,*grid))
if errors != []:
damask.util.croak(errors)
table.close(dismiss = True)
continue
# ------------------------------------------ process data ------------------------------------------
F_fourier = np.fft.rfftn(table.data[:,:9].reshape(grid[2],grid[1],grid[0],3,3),axes=(0,1,2)) # perform transform only once...
displacement = displacementFluctFFT(F_fourier,grid,size,options.nodal,transformed=True)
avgDisplacement = displacementAvgFFT (F_fourier,grid,size,options.nodal,transformed=True)
# ------------------------------------------ assemble header ---------------------------------------
if options.nodal:
table.info_clear()
table.labels_clear()
table.info_append(scriptID + '\t' + ' '.join(sys.argv[1:]))
table.labels_append((['{}_pos' .format(i+1) for i in xrange(3)] if options.nodal else []) +
['{}_avg({}).{}' .format(i+1,options.defgrad,options.coords) for i in xrange(3)] +
['{}_fluct({}).{}'.format(i+1,options.defgrad,options.coords) for i in xrange(3)] )
table.head_write()
# ------------------------------------------ output data -------------------------------------------
zrange = np.linspace(0,size[2],1+grid[2]) if options.nodal else xrange(grid[2])
yrange = np.linspace(0,size[1],1+grid[1]) if options.nodal else xrange(grid[1])
xrange = np.linspace(0,size[0],1+grid[0]) if options.nodal else xrange(grid[0])
for i,z in enumerate(zrange):
for j,y in enumerate(yrange):
for k,x in enumerate(xrange):
if options.nodal: table.data_clear()
else: table.data_read()
table.data_append([x,y,z] if options.nodal else [])
table.data_append(list(avgDisplacement[i,j,k,:]))
table.data_append(list( displacement[i,j,k,:]))
table.data_write()
# ------------------------------------------ output finalization -----------------------------------
table.close() # close ASCII tables

View File

@ -1,7 +1,7 @@
#!/usr/bin/env python
# -*- coding: UTF-8 no BOM -*-
import os,sys,string,math
import os,sys,math
import numpy as np
from optparse import OptionParser
import damask
@ -10,39 +10,35 @@ scriptName = os.path.splitext(os.path.basename(__file__))[0]
scriptID = ' '.join([scriptName,damask.version])
def divFFT(geomdim,field):
N = grid.prod() # field size
n = np.array(np.shape(field)[3:]).prod() # data size
grid = np.array(np.shape(field)[2::-1])
N = grid.prod() # field size
n = np.array(np.shape(field)[3:]).prod() # data size
field_fourier = np.fft.fftpack.rfftn(field,axes=(0,1,2))
div_fourier = np.zeros(field_fourier.shape[0:len(np.shape(field))-1],'c16') # size depents on whether tensor or vector
div_fourier = np.zeros(field_fourier.shape[0:len(np.shape(field))-1],'c16') # size depents on whether tensor or vector
# differentiation in Fourier space
k_s=np.zeros([3],'i')
TWOPIIMG = (0.0+2.0j*math.pi)
TWOPIIMG = 2.0j*math.pi
for i in xrange(grid[2]):
k_s[0] = i
if(grid[2]%2==0 and i == grid[2]//2): # for even grid, set Nyquist freq to 0 (Johnson, MIT, 2011)
k_s[0]=0
elif (i > grid[2]//2):
k_s[0] = k_s[0] - grid[2]
if grid[2]%2 == 0 and i == grid[2]//2: k_s[0] = 0 # for even grid, set Nyquist freq to 0 (Johnson, MIT, 2011)
elif i > grid[2]//2: k_s[0] -= grid[2]
for j in xrange(grid[1]):
k_s[1] = j
if(grid[1]%2==0 and j == grid[1]//2): # for even grid, set Nyquist freq to 0 (Johnson, MIT, 2011)
k_s[1]=0
elif (j > grid[1]//2):
k_s[1] = k_s[1] - grid[1]
if grid[1]%2 == 0 and j == grid[1]//2: k_s[1] = 0 # for even grid, set Nyquist freq to 0 (Johnson, MIT, 2011)
elif j > grid[1]//2: k_s[1] -= grid[1]
for k in xrange(grid[0]//2+1):
k_s[2] = k
if(grid[0]%2==0 and k == grid[0]//2): # for even grid, set Nyquist freq to 0 (Johnson, MIT, 2011)
k_s[2]=0
if grid[0]%2 == 0 and k == grid[0]//2: k_s[2] = 0 # for even grid, set Nyquist freq to 0 (Johnson, MIT, 2011)
xi=np.array([k_s[2]/geomdim[2]+0.0j,k_s[1]/geomdim[1]+0.j,k_s[0]/geomdim[0]+0.j],'c16')
if n == 9: # tensor, 3x3 -> 3
xi = (k_s/geomdim)[2::-1].astype('c16') # reversing the field input order
if n == 9: # tensor, 3x3 -> 3
for l in xrange(3):
div_fourier[i,j,k,l] = sum(field_fourier[i,j,k,l,0:3]*xi) *TWOPIIMG
elif n == 3: # vector, 3 -> 1
elif n == 3: # vector, 3 -> 1
div_fourier[i,j,k] = sum(field_fourier[i,j,k,0:3]*xi) *TWOPIIMG
return np.fft.fftpack.irfftn(div_fourier,axes=(0,1,2)).reshape([N,n/3])
@ -62,33 +58,31 @@ Deals with both vector- and tensor-valued fields.
parser.add_option('-c','--coordinates',
dest = 'coords',
type = 'string', metavar = 'string',
help = 'column heading for coordinates [%default]')
help = 'column label of coordinates [%default]')
parser.add_option('-v','--vector',
dest = 'vector',
action = 'extend', metavar = '<string LIST>',
help = 'heading of columns containing vector field values')
help = 'column label(s) of vector field values')
parser.add_option('-t','--tensor',
dest = 'tensor',
action = 'extend', metavar = '<string LIST>',
help = 'heading of columns containing tensor field values')
help = 'column label(s) of tensor field values')
parser.set_defaults(coords = 'ipinitialcoord',
parser.set_defaults(coords = 'pos',
)
(options,filenames) = parser.parse_args()
if options.vector == None and options.tensor == None:
if options.vector is None and options.tensor is None:
parser.error('no data column specified.')
# --- loop over input files -------------------------------------------------------------------------
# --- loop over input files ------------------------------------------------------------------------
if filenames == []: filenames = [None]
for name in filenames:
try:
table = damask.ASCIItable(name = name,buffered = False)
except:
continue
try: table = damask.ASCIItable(name = name,buffered = False)
except: continue
damask.util.report(scriptName,name)
# ------------------------------------------ read header ------------------------------------------
@ -140,15 +134,16 @@ for name in filenames:
maxcorner = np.array(map(max,coords))
grid = np.array(map(len,coords),'i')
size = grid/np.maximum(np.ones(3,'d'), grid-1.0) * (maxcorner-mincorner) # size from edge to edge = dim * n/(n-1)
size = np.where(grid > 1, size, min(size[grid > 1]/grid[grid > 1])) # spacing for grid==1 equal to smallest among other spacings
size = np.where(grid > 1, size, min(size[grid > 1]/grid[grid > 1])) # spacing for grid==1 equal to smallest among other ones
# ------------------------------------------ process value field -----------------------------------
stack = [table.data]
for type, data in items.iteritems():
for i,label in enumerate(data['active']):
stack.append(divFFT(size[::-1], # we need to reverse order here, because x is fastest,ie rightmost, but leftmost in our x,y,z notation
table.data[:,data['column'][i]:data['column'][i]+data['dim']].\
# we need to reverse order here, because x is fastest,ie rightmost, but leftmost in our x,y,z notation
stack.append(divFFT(size[::-1],
table.data[:,data['column'][i]:data['column'][i]+data['dim']].
reshape([grid[2],grid[1],grid[0]]+data['shape'])))
# ------------------------------------------ output result -----------------------------------------

View File

@ -1,7 +1,7 @@
#!/usr/bin/env python
# -*- coding: UTF-8 no BOM -*-
import os,sys,string
import os,sys
import numpy as np
from optparse import OptionParser
import damask
@ -48,7 +48,7 @@ parser.set_defaults(hkl = (1,1,1),
(options,filenames) = parser.parse_args()
if options.stiffness == None:
if options.stiffness is None:
parser.error('no data column specified...')
# --- loop over input files -------------------------------------------------------------------------
@ -93,4 +93,4 @@ for name in filenames:
# ------------------------------------------ output finalization -----------------------------------
table.close() # close ASCII tables
table.close() # close ASCII tables

View File

@ -1,7 +1,7 @@
#!/usr/bin/env python
# -*- coding: UTF-8 no BOM -*-
import os,sys,string,itertools
import os,sys,itertools
import numpy as np
from scipy import ndimage
from optparse import OptionParser
@ -89,23 +89,24 @@ Add column(s) containing Euclidean distance to grain structural features: bounda
""", version = scriptID)
parser.add_option('-c','--coordinates', dest='coords', metavar='string',
help='column heading for coordinates [%default]')
help='column label of coordinates [%default]')
parser.add_option('-i','--identifier', dest='id', metavar = 'string',
help='heading of column containing grain identifier [%default]')
help='column label of grain identifier [%default]')
parser.add_option('-t','--type', dest = 'type', action = 'extend', metavar = '<string LIST>',
help = 'feature type {%s} '%(', '.join(map(lambda x:'/'.join(x['names']),features))) )
parser.add_option('-n','--neighborhood',dest='neighborhood', choices = neighborhoods.keys(), metavar = 'string',
help = 'type of neighborhood [neumann] {%s}'%(', '.join(neighborhoods.keys())))
parser.add_option('-s', '--scale', dest = 'scale', type = 'float', metavar='float',
parser.add_option('-s', '--scale', dest = 'scale', type = 'float', metavar = 'float',
help = 'voxel size [%default]')
parser.set_defaults(coords = 'ipinitialcoord')
parser.set_defaults(id = 'texture')
parser.set_defaults(neighborhood = 'neumann')
parser.set_defaults(scale = 1.0)
parser.set_defaults(coords = 'pos',
id = 'texture',
neighborhood = 'neumann',
scale = 1.0,
)
(options,filenames) = parser.parse_args()
if options.type == None:
if options.type is None:
parser.error('no feature type selected.')
if not set(options.type).issubset(set(list(itertools.chain(*map(lambda x: x['names'],features))))):
parser.error('type must be chosen from (%s).'%(', '.join(map(lambda x:'|'.join(x['names']),features))) )
@ -125,10 +126,8 @@ for i,feature in enumerate(features):
if filenames == []: filenames = [None]
for name in filenames:
try:
table = damask.ASCIItable(name = name, buffered = False)
except:
continue
try: table = damask.ASCIItable(name = name, buffered = False)
except: continue
damask.util.report(scriptName,name)
# ------------------------------------------ read header ------------------------------------------
@ -141,9 +140,11 @@ for name in filenames:
remarks = []
column = {}
if table.label_dimension(options.coords) != 3: errors.append('coordinates {} are not a vector.'.format(options.coords))
coordDim = table.label_dimension(options.coords)
if not 3 >= coordDim >= 1:
errors.append('coordinates "{}" need to have one, two, or three dimensions.'.format(options.coords))
else: coordCol = table.label_index(options.coords)
if table.label_dimension(options.id) != 1: errors.append('grain identifier {} not found.'.format(options.id))
else: idCol = table.label_index(options.id)
@ -164,18 +165,20 @@ for name in filenames:
table.data_readArray()
coords = [{},{},{}]
for i in xrange(len(table.data)):
for j in xrange(3):
coords[j][str(table.data[i,coordCol+j])] = True
grid = np.array(map(len,coords),'i')
size = grid/np.maximum(np.ones(3,'d'),grid-1.0)* \
np.array([max(map(float,coords[0].keys()))-min(map(float,coords[0].keys())),\
max(map(float,coords[1].keys()))-min(map(float,coords[1].keys())),\
max(map(float,coords[2].keys()))-min(map(float,coords[2].keys())),\
],'d') # size from bounding box, corrected for cell-centeredness
coords = [np.unique(table.data[:,coordCol+i]) for i in xrange(coordDim)]
mincorner = np.array(map(min,coords))
maxcorner = np.array(map(max,coords))
grid = np.array(map(len,coords)+[1]*(3-len(coords)),'i')
size = np.where(grid > 1, size, min(size[grid > 1]/grid[grid > 1])) # spacing for grid==1 equal to smallest among other spacings
N = grid.prod()
if N != len(table.data): errors.append('data count {} does not match grid '.format(N) +
'x'.join(map(str,grid)) +
'.')
if errors != []:
damask.util.croak(errors)
table.close(dismiss = True)
continue
# ------------------------------------------ process value field -----------------------------------
@ -219,4 +222,4 @@ for name in filenames:
# ------------------------------------------ output finalization -----------------------------------
table.close() # close input ASCII table (works for stdin)
table.close() # close input ASCII table (works for stdin)

160
processing/post/addGradient.py Executable file
View File

@ -0,0 +1,160 @@
#!/usr/bin/env python
# -*- coding: UTF-8 no BOM -*-
import os,sys,math
import numpy as np
from optparse import OptionParser
import damask
scriptName = os.path.splitext(os.path.basename(__file__))[0]
scriptID = ' '.join([scriptName,damask.version])
#--------------------------------------------------------------------------------------------------
def gradFFT(geomdim,field):
grid = np.array(np.shape(field)[2::-1])
N = grid.prod() # field size
n = np.array(np.shape(field)[3:]).prod() # data size
if n == 3: dataType = 'vector'
elif n == 1: dataType = 'scalar'
field_fourier = np.fft.fftpack.rfftn(field,axes=(0,1,2))
grad_fourier = np.zeros(field_fourier.shape+(3,),'c16')
# differentiation in Fourier space
k_s = np.zeros([3],'i')
TWOPIIMG = 2.0j*math.pi
for i in xrange(grid[2]):
k_s[0] = i
if grid[2]%2 == 0 and i == grid[2]//2: k_s[0] = 0 # for even grid, set Nyquist freq to 0 (Johnson, MIT, 2011)
elif i > grid[2]//2: k_s[0] -= grid[2]
for j in xrange(grid[1]):
k_s[1] = j
if grid[1]%2 == 0 and j == grid[1]//2: k_s[1] = 0 # for even grid, set Nyquist freq to 0 (Johnson, MIT, 2011)
elif j > grid[1]//2: k_s[1] -= grid[1]
for k in xrange(grid[0]//2+1):
k_s[2] = k
if grid[0]%2 == 0 and k == grid[0]//2: k_s[2] = 0 # for even grid, set Nyquist freq to 0 (Johnson, MIT, 2011)
xi = (k_s/geomdim)[2::-1].astype('c16') # reversing the field order
grad_fourier[i,j,k,0,:] = field_fourier[i,j,k,0]*xi *TWOPIIMG # vector field from scalar data
if dataType == 'vector':
grad_fourier[i,j,k,1,:] = field_fourier[i,j,k,1]*xi *TWOPIIMG # tensor field from vector data
grad_fourier[i,j,k,2,:] = field_fourier[i,j,k,2]*xi *TWOPIIMG
return np.fft.fftpack.irfftn(grad_fourier,axes=(0,1,2)).reshape([N,3*n])
# --------------------------------------------------------------------
# MAIN
# --------------------------------------------------------------------
parser = OptionParser(option_class=damask.extendableOption, usage='%prog options [file[s]]', description = """
Add column(s) containing gradient of requested column(s).
Operates on periodic ordered three-dimensional data sets.
Deals with both vector- and scalar fields.
""", version = scriptID)
parser.add_option('-c','--coordinates',
dest = 'coords',
type = 'string', metavar='string',
help = 'column label of coordinates [%default]')
parser.add_option('-v','--vector',
dest = 'vector',
action = 'extend', metavar = '<string LIST>',
help = 'column label(s) of vector field values')
parser.add_option('-s','--scalar',
dest = 'scalar',
action = 'extend', metavar = '<string LIST>',
help = 'column label(s) of scalar field values')
parser.set_defaults(coords = 'pos',
)
(options,filenames) = parser.parse_args()
if options.vector is None and options.scalar is None:
parser.error('no data column specified.')
# --- loop over input files ------------------------------------------------------------------------
if filenames == []: filenames = [None]
for name in filenames:
try: table = damask.ASCIItable(name = name,buffered = False)
except: continue
damask.util.report(scriptName,name)
# ------------------------------------------ read header ------------------------------------------
table.head_read()
# ------------------------------------------ sanity checks ----------------------------------------
items = {
'scalar': {'dim': 1, 'shape': [1], 'labels':options.scalar, 'active':[], 'column': []},
'vector': {'dim': 3, 'shape': [3], 'labels':options.vector, 'active':[], 'column': []},
}
errors = []
remarks = []
column = {}
if table.label_dimension(options.coords) != 3: errors.append('coordinates {} are not a vector.'.format(options.coords))
else: colCoord = table.label_index(options.coords)
for type, data in items.iteritems():
for what in (data['labels'] if data['labels'] is not None else []):
dim = table.label_dimension(what)
if dim != data['dim']: remarks.append('column {} is not a {}.'.format(what,type))
else:
items[type]['active'].append(what)
items[type]['column'].append(table.label_index(what))
if remarks != []: damask.util.croak(remarks)
if errors != []:
damask.util.croak(errors)
table.close(dismiss = True)
continue
# ------------------------------------------ assemble header --------------------------------------
table.info_append(scriptID + '\t' + ' '.join(sys.argv[1:]))
for type, data in items.iteritems():
for label in data['active']:
table.labels_append(['{}_gradFFT({})'.format(i+1,label) for i in xrange(3 * data['dim'])]) # extend ASCII header with new labels
table.head_write()
# --------------- figure out size and grid ---------------------------------------------------------
table.data_readArray()
coords = [np.unique(table.data[:,colCoord+i]) for i in xrange(3)]
mincorner = np.array(map(min,coords))
maxcorner = np.array(map(max,coords))
grid = np.array(map(len,coords),'i')
size = grid/np.maximum(np.ones(3,'d'), grid-1.0) * (maxcorner-mincorner) # size from edge to edge = dim * n/(n-1)
size = np.where(grid > 1, size, min(size[grid > 1]/grid[grid > 1]))
# ------------------------------------------ process value field -----------------------------------
stack = [table.data]
for type, data in items.iteritems():
for i,label in enumerate(data['active']):
# we need to reverse order here, because x is fastest,ie rightmost, but leftmost in our x,y,z notation
stack.append(gradFFT(size[::-1],
table.data[:,data['column'][i]:data['column'][i]+data['dim']].
reshape([grid[2],grid[1],grid[0]]+data['shape'])))
# ------------------------------------------ output result -----------------------------------------
if len(stack) > 1: table.data = np.hstack(tuple(stack))
table.data_writeArray('%.12g')
# ------------------------------------------ output finalization -----------------------------------
table.close() # close input ASCII table (works for stdin)

View File

@ -1,11 +1,10 @@
#!/usr/bin/env python
import os,sys,string,time,copy
import os,sys,time,copy
import numpy as np
import damask
from optparse import OptionParser
from scipy import spatial
from collections import defaultdict
scriptName = os.path.splitext(os.path.basename(__file__))[0]
scriptID = ' '.join([scriptName,damask.version])
@ -23,7 +22,7 @@ parser.add_option('-r', '--radius',
parser.add_option('-d', '--disorientation',
dest = 'disorientation',
type = 'float', metavar = 'float',
help = 'disorientation threshold per grain [%default] (degrees)')
help = 'disorientation threshold in degrees [%default]')
parser.add_option('-s', '--symmetry',
dest = 'symmetry',
type = 'string', metavar = 'string',
@ -61,22 +60,23 @@ parser.add_option('-p', '--position',
type = 'string', metavar = 'string',
help = 'spatial position of voxel [%default]')
parser.set_defaults(symmetry = 'cubic',
parser.set_defaults(disorientation = 5,
symmetry = 'cubic',
coords = 'pos',
degrees = False,
)
(options, filenames) = parser.parse_args()
if options.radius == None:
if options.radius is None:
parser.error('no radius specified.')
input = [options.eulers != None,
options.a != None and \
options.b != None and \
options.c != None,
options.matrix != None,
options.quaternion != None,
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.')
@ -86,17 +86,16 @@ if np.sum(input) != 1: parser.error('needs exactly one input format.')
(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(options.disorientation/2.*toRadians)
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
# --- loop over input files -------------------------------------------------------------------------
if filenames == []: filenames = [None]
for name in filenames:
try:
table = damask.ASCIItable(name = name,
buffered = False)
try: table = damask.ASCIItable(name = name,
buffered = False)
except: continue
damask.util.report(scriptName,name)
@ -109,8 +108,10 @@ for name in filenames:
errors = []
remarks = []
if table.label_dimension(options.coords) != 3: errors.append('coordinates {} are not a vector.'.format(options.coords))
if not np.all(table.label_dimension(label) == dim): errors.append('input {} has wrong dimension {}.'.format(label,dim))
if not 3 >= table.label_dimension(options.coords) >= 1:
errors.append('coordinates "{}" need to have one, two, or three dimensions.'.format(options.coords))
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)
@ -122,8 +123,10 @@ for name in filenames:
# ------------------------------------------ assemble header ---------------------------------------
table.info_append(scriptID + '\t' + ' '.join(sys.argv[1:]))
table.labels_append('grainID_{}@{}'.format(label,
options.disorientation if options.degrees else np.degrees(options.disorientation))) # report orientation source and disorientation in degrees
table.labels_append('grainID_{}@{:g}'.format('+'.join(label)
if isinstance(label, (list,tuple))
else label,
options.disorientation)) # report orientation source and disorientation
table.head_write()
# ------------------------------------------ process data ------------------------------------------
@ -161,7 +164,8 @@ for name in filenames:
if p > 0 and p % 1000 == 0:
time_delta = (time.clock()-tick) * (len(grainID) - p) / p
bg.set_message('(%02i:%02i:%02i) processing point %i of %i (grain count %i)...'%(time_delta//3600,time_delta%3600//60,time_delta%60,p,len(grainID),len(orientations)))
bg.set_message('(%02i:%02i:%02i) processing point %i of %i (grain count %i)...'\
%(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,
@ -178,83 +182,51 @@ for name in filenames:
o = damask.Orientation(quaternion = np.array(map(float,table.data[column:column+4])),
symmetry = options.symmetry).reduced()
matched = False
matched = False
alreadyChecked = {}
candidates = []
bestDisorientation = damask.Quaternion([0,0,0,1]) # initialize to 180 deg rotation as worst case
# check against last matched needs to be really picky. best would be to exclude jumps across the poke (checking distance between last and me?)
# when walking through neighborhood first check whether grainID of that point has already been tested, if yes, skip!
if matchedID != -1: # has matched before?
matched = (o.quaternion.conjugated() * orientations[matchedID].quaternion).w > cos_disorientation
if not matched:
alreadyChecked = {}
bestDisorientation = damask.Quaternion([0,0,0,1]) # initialize to 180 deg rotation as worst case
for i in kdtree.query_ball_point(kdtree.data[p],options.radius): # check all neighboring points
gID = grainID[i]
if gID != -1 and gID not in alreadyChecked: # an already indexed point belonging to a grain not yet tested?
alreadyChecked[gID] = True # remember not to check again
disorientation = o.disorientation(orientations[gID],SST = False)[0] # compare against that grain's orientation (and skip requirement of axis within SST)
if disorientation.quaternion.w > cos_disorientation and \
disorientation.quaternion.w >= bestDisorientation.w: # within disorientation threshold and better than current best?
for i in kdtree.query_ball_point(kdtree.data[p],options.radius): # check all neighboring points
gID = grainID[i]
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
disorientation = o.disorientation(orientations[gID],SST = False)[0] # compare against other orientation
if disorientation.quaternion.w > cos_disorientation: # within threshold ...
candidates.append(gID) # remember as potential candidate
if disorientation.quaternion.w >= bestDisorientation.w: # ... and better than current best?
matched = True
matchedID = gID # remember that grain
bestDisorientation = disorientation.quaternion
if not matched: # no match -> new grain found
memberCounts += [1] # start new membership counter
if matched: # did match existing grain
memberCounts[matchedID] += 1
if len(candidates) > 1: # ambiguity in grain identification?
largestGrain = sorted(candidates,key=lambda x:memberCounts[x])[-1] # find largest among potential candidate grains
matchedID = largestGrain
for c in [c for c in candidates if c != largestGrain]: # loop over smaller candidates
memberCounts[largestGrain] += memberCounts[c] # reassign member count of smaller to largest
memberCounts[c] = 0
grainID = np.where(np.in1d(grainID,candidates), largestGrain, grainID) # relabel grid points of smaller candidates as largest one
else: # no match -> new grain found
orientations += [o] # initialize with current orientation
memberCounts += [1] # start new membership counter
matchedID = g
g += 1 # increment grain counter
else: # did match existing grain
memberCounts[matchedID] += 1
grainID[p] = matchedID # remember grain index assigned to point
p += 1 # increment point
bg.set_message('identifying similar orientations among {} grains...'.format(len(orientations)))
memberCounts = np.array(memberCounts)
similarOrientations = [[] for i in xrange(len(orientations))]
for i,orientation in enumerate(orientations[:-1]): # compare each identified orientation...
for j in xrange(i+1,len(orientations)): # ...against all others that were defined afterwards
if orientation.disorientation(orientations[j],SST = False)[0].quaternion.w > cos_disorientation: # similar orientations in both grainIDs?
similarOrientations[i].append(j) # remember in upper triangle...
similarOrientations[j].append(i) # ...and lower triangle of matrix
if similarOrientations[i] != []:
bg.set_message('grainID {} is as: {}'.format(i,' '.join(map(str,similarOrientations[i]))))
stillShifting = True
while stillShifting:
stillShifting = False
tick = time.clock()
for p,gID in enumerate(grainID): # walk through all points
if p > 0 and p % 1000 == 0:
time_delta = (time.clock()-tick) * (len(grainID) - p) / p
bg.set_message('(%02i:%02i:%02i) shifting ID of point %i out of %i (grain count %i)...'%(time_delta//3600,time_delta%3600//60,time_delta%60,p,len(grainID),len(orientations)))
if similarOrientations[gID] != []: # orientation of my grainID is similar to someone else?
similarNeighbors = defaultdict(int) # dict holding frequency of neighboring grainIDs that share my orientation (freq info not used...)
for i in kdtree.query_ball_point(kdtree.data[p],options.radius): # check all neighboring points
if grainID[i] in similarOrientations[gID]: # neighboring point shares my orientation?
similarNeighbors[grainID[i]] += 1 # remember its grainID
if similarNeighbors != {}: # found similar orientation(s) in neighborhood
candidates = np.array([gID]+similarNeighbors.keys()) # possible replacement grainIDs for me
grainID[p] = candidates[np.argsort(memberCounts[candidates])[-1]] # adopt ID that is most frequent in overall dataset
memberCounts[gID] -= 1 # my former ID loses one fellow
memberCounts[grainID[p]] += 1 # my new ID gains one fellow
bg.set_message('{}:{} --> {}'.format(p,gID,grainID[p])) # report switch of grainID
stillShifting = True
grainIDs = np.where(np.array(memberCounts) > 0)[0] # identify "live" grain identifiers
packingMap = dict(zip(list(grainIDs),range(len(grainIDs)))) # map to condense into consecutive IDs
table.data_rewind()
outputAlive = True
p = 0
while outputAlive and table.data_read(): # read next data line of ASCII table
table.data_append(1+grainID[p]) # add grain ID
table.data_append(1+packingMap[grainID[p]]) # add (condensed) grain ID
outputAlive = table.data_write() # output processed line
p += 1

View File

@ -1,7 +1,7 @@
#!/usr/bin/env python
# -*- coding: UTF-8 no BOM -*-
import os,sys,string,math
import os,sys,math
import numpy as np
from optparse import OptionParser
import damask
@ -62,12 +62,12 @@ parser.set_defaults(pole = (0.0,0.0,1.0),
(options, filenames) = parser.parse_args()
input = [options.eulers != None,
options.a != None and \
options.b != None and \
options.c != None,
options.matrix != None,
options.quaternion != None,
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.')
@ -99,7 +99,7 @@ for name in filenames:
# ------------------------------------------ sanity checks ----------------------------------------
if not np.all(table.label_dimension(label) == dim):
damask.util.croak('input {} has wrong dimension {}.'.format(label,dim))
damask.util.croak('input {} does not have dimension {}.'.format(label,dim))
table.close(dismiss = True) # close ASCIItable and remove empty file
continue

View File

@ -1,7 +1,7 @@
#!/usr/bin/env python
# -*- coding: UTF-8 no BOM -*-
import os,sys,string
import os,sys
from optparse import OptionParser
import damask
@ -39,14 +39,14 @@ parser.set_defaults(offset = 0,
(options,filenames) = parser.parse_args()
if options.label == None:
if options.label is None:
parser.error('no data columns specified.')
if options.map == None:
if options.map is None:
parser.error('no mapping column given.')
# ------------------------------------------ process mapping ASCIItable ---------------------------
if options.asciitable != None and os.path.isfile(options.asciitable):
if options.asciitable is not None and os.path.isfile(options.asciitable):
mappedTable = damask.ASCIItable(name = options.asciitable,
buffered = False, readonly = True)

View File

@ -1,7 +1,7 @@
#!/usr/bin/env python
# -*- coding: UTF-8 no BOM -*-
import os,sys,math,string
import os,sys,math
import numpy as np
from optparse import OptionParser
import damask

View File

@ -1,7 +1,7 @@
#!/usr/bin/env python
# -*- coding: UTF-8 no BOM -*-
import os,sys,math,string
import os,sys,math
from optparse import OptionParser
import damask
@ -43,7 +43,7 @@ parser.set_defaults(norm = 'frobenius',
(options,filenames) = parser.parse_args()
if options.label == None:
if options.label is None:
parser.error('no data column specified.')
# --- loop over input files -------------------------------------------------------------------------

View File

@ -1,7 +1,7 @@
#!/usr/bin/env python
# -*- coding: UTF-8 no BOM -*-
import os,sys,string,math
import os,sys,math
import numpy as np
from optparse import OptionParser
import damask
@ -15,7 +15,8 @@ scriptID = ' '.join([scriptName,damask.version])
parser = OptionParser(option_class=damask.extendableOption, usage='%prog options [file[s]]', description = """
Add quaternion and/or Bunge Euler angle representation of crystal lattice orientation.
Orientation is given by quaternion, Euler angles, rotation matrix, or crystal frame coordinates (i.e. component vectors of rotation matrix).
Orientation is given by quaternion, Euler angles, rotation matrix, or crystal frame coordinates
(i.e. component vectors of rotation matrix).
""", version = scriptID)
@ -74,12 +75,12 @@ options.output = map(lambda x: x.lower(), options.output)
if options.output == [] or (not set(options.output).issubset(set(outputChoices))):
parser.error('output must be chosen from {}.'.format(', '.join(outputChoices)))
input = [options.eulers != None,
options.a != None and \
options.b != None and \
options.c != None,
options.matrix != None,
options.quaternion != None,
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.')
@ -112,7 +113,7 @@ for name in filenames:
errors = []
remarks = []
if not np.all(table.label_dimension(label) == dim): errors.append('input {} has wrong dimension {}.'.format(label,dim))
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)

View File

@ -1,7 +1,7 @@
#!/usr/bin/env python
# -*- coding: UTF-8 no BOM -*-
import os,sys,string
import os,sys
import numpy as np
from optparse import OptionParser
import damask
@ -14,7 +14,8 @@ scriptID = ' '.join([scriptName,damask.version])
# --------------------------------------------------------------------
parser = OptionParser(option_class=damask.extendableOption, usage='%prog options [file[s]]', description = """
Add column(s) containing Second Piola--Kirchhoff stress based on given column(s) of deformation gradient and first Piola--Kirchhoff stress.
Add column(s) containing Second Piola--Kirchhoff stress based on given column(s) of deformation
gradient and first Piola--Kirchhoff stress.
""", version = scriptID)

View File

@ -1,7 +1,7 @@
#!/usr/bin/env python
# -*- coding: UTF-8 no BOM -*-
import os,sys,string,math
import os,sys,math
import numpy as np
from optparse import OptionParser
import damask
@ -62,12 +62,12 @@ parser.set_defaults(pole = (1.0,0.0,0.0),
(options, filenames) = parser.parse_args()
input = [options.eulers != None,
options.a != None and \
options.b != None and \
options.c != None,
options.matrix != None,
options.quaternion != None,
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.')
@ -101,7 +101,7 @@ for name in filenames:
errors = []
remarks = []
if not np.all(table.label_dimension(label) == dim): errors.append('input {} has wrong dimension {}.'.format(label,dim))
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)
@ -133,7 +133,7 @@ for name in filenames:
rotatedPole = o.quaternion*pole # rotate pole according to crystal orientation
(x,y) = rotatedPole[0:2]/(1.+abs(pole[2])) # stereographic projection
table.data_append([np.sqrt(x*x+y*y),np.arctan2(y,x)] if options.polar else [x,y]) # cartesian coordinates
table.data_append([np.sqrt(x*x+y*y),np.arctan2(y,x)] if options.polar else [x,y]) # cartesian coordinates
outputAlive = table.data_write() # output processed line

View File

@ -1,98 +0,0 @@
#!/usr/bin/env python
# -*- coding: UTF-8 no BOM -*-
import os,sys,string,numpy as np
from optparse import OptionParser
import damask
scriptName = os.path.splitext(os.path.basename(__file__))[0]
scriptID = ' '.join([scriptName,damask.version])
# --------------------------------------------------------------------
# MAIN
# --------------------------------------------------------------------
parser = OptionParser(option_class=damask.extendableOption, usage='%prog options [file[s]]', description = """
Add Quaternions based on Crystal Frame Coordinates.
""", version = scriptID)
parser.add_option('-f','--frame', dest='frame', nargs=4, type='string', metavar='<string string string string>',
help='heading of columns containing b* vector components and three frame vectors in that order')
parser.add_option('-s','--symmetry', dest='crysym', nargs=1,type='string',metavar='<string>',
help='crystal symmetry definition')
parser.set_defaults(frame = None)
(options,filenames) = parser.parse_args()
if options.frame == None:
parser.error('no data column specified...')
datainfo = {'len':4,
'label':[]
}
if options.frame != None: datainfo['label'] += options.frame
# --- loop over input files -------------------------------------------------------------------------
if filenames == []: filenames = [None]
for name in filenames:
try:
table = damask.ASCIItable(name = name,
buffered = False)
except: continue
damask.util.report(scriptName,name)
table.head_read() # read ASCII header info
# --------------- figure out columns to process ---------------------------------------------------
active = []
column = {}
for label in datainfo['label']:
key = '1_'+label if datainfo['len'] > 1 else label # non-special labels have to start with '1_'
if key in table.labels:
active.append(label)
column[label] = table.labels.index(key) # remember columns of requested data
else:
damask.util.croak('column %s not found...'%label)
# ------------------------------------------ assemble header ---------------------------------------
table.info_append(scriptID + '\t' + ' '.join(sys.argv[1:]))
table.labels_append(['Q_%i'%(i+1) for i in xrange(4)]) # extend ASCII header with new labels [1 real, 3 imaginary components]
table.head_write()
# ------------------------------------------ process data ------------------------------------------
outputAlive = True
while outputAlive and table.data_read(): # read next data line of ASCII table
vec = np.zeros([4,3])
for i,label in enumerate(active):
vec[i,:] = np.array(table.data[column[label]:
column[label]+3])
if sys.argv[1:][6]=='hexagonal': # Ensure Input matrix is orthogonal
M=np.dot(vec[0,:],vec[2,:])
vec[1,:]=vec[1,:]/np.linalg.norm(vec[1,:])
vec[2,:]=M*(vec[0,:]/np.linalg.norm(vec[0,:]))
vec[3,:]=vec[3,:]/np.linalg.norm(vec[3,:])
else:
vec[1,:]=vec[1,:]/np.linalg.norm(vec[1,:])
vec[2,:]=vec[2,:]/np.linalg.norm(vec[2,:])
vec[3,:]=vec[3,:]/np.linalg.norm(vec[3,:])
Ori=damask.Orientation(matrix=vec[1:,:],symmetry=sys.argv[1:][6])
table.data_append(np.asarray(Ori.asQuaternion()))
outputAlive = table.data_write() # output processed line
# ------------------------------------------ output result -----------------------------------------
outputAlive and table.output_flush() # just in case of buffered ASCII table
table.close() # close ASCII tables

View File

@ -1,7 +1,7 @@
#!/usr/bin/env python
# -*- coding: UTF-8 no BOM -*-
import os,sys,math,string
import os,sys,math
import numpy as np
from optparse import OptionParser
import damask
@ -9,226 +9,95 @@ import damask
scriptName = os.path.splitext(os.path.basename(__file__))[0]
scriptID = ' '.join([scriptName,damask.version])
slipnormal_temp = [
[0,0,0,1],
[0,0,0,1],
[0,0,0,1],
[0,1,-1,0],
[-1,0,1,0],
[1,-1,0,0],
[0,1,-1,1],
[-1,1,0,1],
[-1,0,1,1],
[0,-1,1,1],
[1,-1,0,1],
[1,0,-1,1],
[0,1,-1,1],
[0,1,-1,1],
[-1,1,0,1],
[-1,1,0,1],
[-1,0,1,1],
[-1,0,1,1],
[0,-1,1,1],
[0,-1,1,1],
[1,-1,0,1],
[1,-1,0,1],
[1,0,-1,1],
[1,0,-1,1],
]
slipdirection_temp = [
[2,-1,-1,0],
[-1,2,-1,0],
[-1,-1,2,0],
[2,-1,-1,0],
[-1,2,-1,0],
[-1,-1,2,0],
[2,-1,-1,0],
[1,1,-2,0],
[-1,2,-1,0],
[-2,1,1,0],
[-1,-1,2,0],
[1,-2,1,0],
[-1,2,-1,3],
[1,1,-2,3],
[-2,1,1,3],
[-1,2,-1,3],
[-1,-1,2,3],
[-2,1,1,3],
[1,-2,1,3],
[-1,-1,2,3],
[2,-1,-1,3],
[1,-2,1,3],
[1,1,-2,3],
[2,-1,-1,3],
]
# slip normals and directions according to cpfem implementation
Nslipsystems = {'fcc': 12, 'bcc': 24, 'hex': 24}
slipnormal = { \
'fcc': [
[1,1,1],
[1,1,1],
[1,1,1],
[-1,-1,1],
[-1,-1,1],
[-1,-1,1],
[1,-1,-1],
[1,-1,-1],
[1,-1,-1],
[-1,1,-1],
[-1,1,-1],
[-1,1,-1],
],
'bcc': [
[0,1,1],
[0,1,1],
[0,-1,1],
[0,-1,1],
[1,0,1],
[1,0,1],
[-1,0,1],
[-1,0,1],
[1,1,0],
[1,1,0],
[-1,1,0],
[-1,1,0],
[2,1,1],
[-2,1,1],
[2,-1,1],
[2,1,-1],
[1,2,1],
[-1,2,1],
[1,-2,1],
[1,2,-1],
[1,1,2],
[-1,1,2],
[1,-1,2],
[1,1,-2],
],
'hex': [ # these are dummy numbers and are recalculated based on the above hex real slip systems.
[1,1,0],
[1,1,0],
[1,0,1],
[1,0,1],
[0,1,1],
[0,1,1],
[1,-1,0],
[1,-1,0],
[-1,0,1],
[-1,0,1],
[0,-1,1],
[0,-1,1],
[2,-1,1],
[1,-2,-1],
[1,1,2],
[2,1,1],
[1,2,-1],
[1,-1,2],
[2,1,-1],
[1,2,1],
[1,-1,-2],
[2,-1,-1],
[1,-2,1],
[1,1,-2],
],
}
slipdirection = { \
'fcc': [
[0,1,-1],
[-1,0,1],
[1,-1,0],
[0,-1,-1],
[1,0,1],
[-1,1,0],
[0,-1,1],
[-1,0,-1],
[1,1,0],
[0,1,1],
[1,0,-1],
[-1,-1,0],
],
'bcc': [
[1,-1,1],
[-1,-1,1],
[1,1,1],
[-1,1,1],
[-1,1,1],
[-1,-1,1],
[1,1,1],
[1,-1,1],
[-1,1,1],
[-1,1,-1],
[1,1,1],
[1,1,-1],
[-1,1,1],
[1,1,1],
[1,1,-1],
[1,-1,1],
[1,-1,1],
[1,1,-1],
[1,1,1],
[-1,1,1],
[1,1,-1],
[1,-1,1],
[-1,1,1],
[1,1,1],
],
'hex': [ # these are dummy numbers and are recalculated based on the above hex real slip systems.
[-1,1,1],
[1,-1,1],
[-1,-1,1],
[-1,1,1],
[-1,-1,1],
[1,-1,1],
[1,1,1],
[-1,-1,1],
[1,-1,1],
[1,1,1],
[1,1,1],
[-1,1,1],
[1,1,-1],
[1,1,-1],
[1,1,-1],
[1,-1,-1],
[1,-1,-1],
[1,-1,-1],
[1,-1,1],
[1,-1,1],
[1,-1,1],
[1,1,1],
[1,1,1],
[1,1,1],
],
}
def applyEulers(phi1,Phi,phi2,x):
""" transform x given in crystal coordinates to xbar returned in lab coordinates for Euler angles phi1,Phi,phi2 """
eulerRot = [[ math.cos(phi1)*math.cos(phi2) - math.cos(Phi)*math.sin(phi1)*math.sin(phi2),
-math.cos(phi1)*math.sin(phi2) - math.cos(Phi)*math.cos(phi2)*math.sin(phi1),
math.sin(Phi)*math.sin(phi1)
],
[ math.cos(phi2)*math.sin(phi1) + math.cos(Phi)*math.cos(phi1)*math.sin(phi2),
math.cos(Phi)*math.cos(phi1)*math.cos(phi2) - math.sin(phi1)*math.sin(phi2),
-math.sin(Phi)*math.cos(phi1)
],
[ math.sin(Phi)*math.sin(phi2),
math.sin(Phi)*math.cos(phi2),
math.cos(Phi)
]]
xbar = [0,0,0]
if len(x) == 3:
for i in range(3):
xbar[i] = sum([eulerRot[i][j]*x[j] for j in range(3)])
return xbar
def normalize(x):
norm = math.sqrt(sum([x[i]*x[i] for i in range(len(x))]))
return [x[i]/norm for i in range(len(x))]
slipSystems = {
'fcc':
np.array([
# Slip direction Plane normal
[ 0, 1,-1, 1, 1, 1, ],
[-1, 0, 1, 1, 1, 1, ],
[ 1,-1, 0, 1, 1, 1, ],
[ 0,-1,-1, -1,-1, 1, ],
[ 1, 0, 1, -1,-1, 1, ],
[-1, 1, 0, -1,-1, 1, ],
[ 0,-1, 1, 1,-1,-1, ],
[-1, 0,-1, 1,-1,-1, ],
[ 1, 1, 0, 1,-1,-1, ],
[ 0, 1, 1, -1, 1,-1, ],
[ 1, 0,-1, -1, 1,-1, ],
[-1,-1, 0, -1, 1,-1, ],
],'f'),
'bcc':
np.array([
# Slip system <111>{110}
[ 1,-1, 1, 0, 1, 1, ],
[-1,-1, 1, 0, 1, 1, ],
[ 1, 1, 1, 0,-1, 1, ],
[-1, 1, 1, 0,-1, 1, ],
[-1, 1, 1, 1, 0, 1, ],
[-1,-1, 1, 1, 0, 1, ],
[ 1, 1, 1, -1, 0, 1, ],
[ 1,-1, 1, -1, 0, 1, ],
[-1, 1, 1, 1, 1, 0, ],
[-1, 1,-1, 1, 1, 0, ],
[ 1, 1, 1, -1, 1, 0, ],
[ 1, 1,-1, -1, 1, 0, ],
# Slip system <111>{112}
[-1, 1, 1, 2, 1, 1, ],
[ 1, 1, 1, -2, 1, 1, ],
[ 1, 1,-1, 2,-1, 1, ],
[ 1,-1, 1, 2, 1,-1, ],
[ 1,-1, 1, 1, 2, 1, ],
[ 1, 1,-1, -1, 2, 1, ],
[ 1, 1, 1, 1,-2, 1, ],
[-1, 1, 1, 1, 2,-1, ],
[ 1, 1,-1, 1, 1, 2, ],
[ 1,-1, 1, -1, 1, 2, ],
[-1, 1, 1, 1,-1, 2, ],
[ 1, 1, 1, 1, 1,-2, ],
],'f'),
'hex':
np.array([
# Basal systems <11.0>{00.1} (independent of c/a-ratio, Bravais notation (4 coordinate base))
[ 2, -1, -1, 0, 0, 0, 0, 1, ],
[-1, 2, -1, 0, 0, 0, 0, 1, ],
[-1, -1, 2, 0, 0, 0, 0, 1, ],
# 1st type prismatic systems <11.0>{10.0} (independent of c/a-ratio)
[ 2, -1, -1, 0, 0, 1, -1, 0, ],
[-1, 2, -1, 0, -1, 0, 1, 0, ],
[-1, -1, 2, 0, 1, -1, 0, 0, ],
# 2nd type prismatic systems <10.0>{11.0} -- a slip; plane normals independent of c/a-ratio
[ 0, 1, -1, 0, 2, -1, -1, 0, ],
[-1, 0, 1, 0, -1, 2, -1, 0, ],
[ 1, -1, 0, 0, -1, -1, 2, 0, ],
# 1st type 1st order pyramidal systems <11.0>{-11.1} -- plane normals depend on the c/a-ratio
[ 2, -1, -1, 0, 0, 1, -1, 1, ],
[-1, 2, -1, 0, -1, 0, 1, 1, ],
[-1, -1, 2, 0, 1, -1, 0, 1, ],
[ 1, 1, -2, 0, -1, 1, 0, 1, ],
[-2, 1, 1, 0, 0, -1, 1, 1, ],
[ 1, -2, 1, 0, 1, 0, -1, 1, ],
# pyramidal system: c+a slip <11.3>{-10.1} -- plane normals depend on the c/a-ratio
[ 2, -1, -1, 3, -1, 1, 0, 1, ],
[ 1, -2, 1, 3, -1, 1, 0, 1, ],
[-1, -1, 2, 3, 1, 0, -1, 1, ],
[-2, 1, 1, 3, 1, 0, -1, 1, ],
[-1, 2, -1, 3, 0, -1, 1, 1, ],
[ 1, 1, -2, 3, 0, -1, 1, 1, ],
[-2, 1, 1, 3, 1, -1, 0, 1, ],
[-1, 2, -1, 3, 1, -1, 0, 1, ],
[ 1, 1, -2, 3, -1, 0, 1, 1, ],
[ 2, -1, -1, 3, -1, 0, 1, 1, ],
[ 1, -2, 1, 3, 0, 1, -1, 1, ],
[-1, -1, 2, 3, 0, 1, -1, 1, ],
# pyramidal system: c+a slip <11.3>{-1-1.2} -- as for hexagonal ice (Castelnau et al. 1996, similar to twin system found below)
[ 2, -1, -1, 3, -2, 1, 1, 2, ], # sorted according to similar twin system
[-1, 2, -1, 3, 1, -2, 1, 2, ], # <11.3>{-1-1.2} shear = 2((c/a)^2-2)/(3 c/a)
[-1, -1, 2, 3, 1, 1, -2, 2, ],
[-2, 1, 1, 3, 2, -1, -1, 2, ],
[ 1, -2, 1, 3, -1, 2, -1, 2, ],
[ 1, 1, -2, 3, -1, -1, 2, 2, ],
],'f'),
}
# --------------------------------------------------------------------
# MAIN
@ -239,126 +108,166 @@ Add columns listing Schmid factors (and optional trace vector of selected system
""", version = scriptID)
parser.add_option('-l','--lattice', dest='lattice', type='choice', choices=('fcc','bcc','hex'), metavar='string',
help="type of lattice structure [%default] {fcc,bcc',hex}")
parser.add_option('--direction', dest='forcedirection', type='int', nargs=3, metavar='int int int',
help='force direction in lab coordinates %default')
parser.add_option('-n','--normal', dest='stressnormal', type='int', nargs=3, metavar='int int int',
help='stress plane normal in lab coordinates ')
parser.add_option('--trace', dest='traceplane', type='int', nargs=3, metavar='int int int',
help='normal (in lab coordinates) of plane on which the plane trace of the Schmid factor(s) is reported')
parser.add_option('--covera', dest='CoverA', type='float', metavar='float',
help='C over A ratio for hexagonal systems')
parser.add_option('-r','--rank', dest='rank', type='int', nargs=3, metavar='int int int',
help="report trace of r'th highest Schmid factor [%default]")
parser.add_option('-e', '--eulers', dest='eulers', 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.set_defaults(lattice = 'fcc')
parser.set_defaults(forcedirection = [0, 0, 1])
parser.set_defaults(stressnormal = None)
parser.set_defaults(traceplane = None)
parser.set_defaults(rank = 0)
parser.set_defaults(CoverA = 1.587)
parser.set_defaults(eulers = 'eulerangles')
latticeChoices = ('fcc','bcc','hex')
parser.add_option('-l','--lattice',
dest = 'lattice', type = 'choice', choices = latticeChoices, metavar='string',
help = 'type of lattice structure [%default] {}'.format(latticeChoices))
parser.add_option('--covera',
dest = 'CoverA', type = 'float', metavar = 'float',
help = 'C over A ratio for hexagonal systems')
parser.add_option('-f', '--force',
dest = 'force',
type = 'float', nargs = 3, metavar = 'float float float',
help = 'force direction in lab frame [%default]')
parser.add_option('-n', '--normal',
dest = 'normal',
type = 'float', nargs = 3, metavar = 'float float float',
help = 'stress plane normal in lab frame [%default]')
parser.add_option('-e', '--eulers',
dest = 'eulers',
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',
type = 'string', metavar = 'string',
help = 'quaternion label')
(options,filenames) = parser.parse_args()
parser.set_defaults(force = (0.0,0.0,1.0),
normal = None,
lattice = latticeChoices[0],
CoverA = math.sqrt(8./3.),
degrees = False,
)
options.forcedirection = normalize(options.forcedirection)
if options.stressnormal:
if abs(sum([options.forcedirection[i] * options.stressnormal[i] for i in range(3)])) < 1e-3:
options.stressnormal = normalize(options.stressnormal)
else:
parser.error('stress plane normal not orthogonal to force direction')
else:
options.stressnormal = options.forcedirection
if options.traceplane:
options.traceplane = normalize(options.traceplane)
options.rank = min(options.rank,Nslipsystems[options.lattice])
datainfo = { # list of requested labels per datatype
'vector': {'len':3,
'label':[]},
}
datainfo['vector']['label'] += [options.eulers]
(options, filenames) = parser.parse_args()
toRadians = math.pi/180.0 if options.degrees else 1.0 # rescale degrees to radians
if options.lattice=='hex': # Convert 4 Miller indices notation of hex to orthogonal 3 Miller indices notation
for i in range(Nslipsystems[options.lattice]):
slipnormal[options.lattice][i][0]=slipnormal_temp[i][0]
slipnormal[options.lattice][i][1]=(slipnormal_temp[i][0]+2.0*slipnormal_temp[i][1])/math.sqrt(3.0)
slipnormal[options.lattice][i][2]=slipnormal_temp[i][3]/options.CoverA
slipdirection[options.lattice][i][0]=slipdirection_temp[i][0]*1.5 # direction [uvtw]->[3u/2 (u+2v)*sqrt(3)/2 w*(c/a)] ,
slipdirection[options.lattice][i][1]=(slipdirection_temp[i][0]+2.0*slipdirection_temp[i][1])*(0.5*math.sqrt(3.0))
slipdirection[options.lattice][i][2]=slipdirection_temp[i][3]*options.CoverA
force = np.array(options.force)
force /= np.linalg.norm(force)
for i in range(Nslipsystems[options.lattice]):
slipnormal[options.lattice][i]=normalize(slipnormal[options.lattice][i])
slipdirection[options.lattice][i]=normalize(slipdirection[options.lattice][i])
if options.normal:
damask.util.croak('got normal')
normal = np.array(options.normal)
normal /= np.linalg.norm(normal)
if abs(np.dot(force,normal)) > 1e-3:
parser.error('stress plane normal not orthogonal to force direction')
else:
normal = force
# --- loop over input files -------------------------------------------------------------------------
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
c_direction = np.zeros((len(slipSystems[options.lattice]),3),'f')
c_normal = np.zeros_like(c_direction)
if options.lattice in latticeChoices[:2]:
c_direction = slipSystems[options.lattice][:,:3]
c_normal = slipSystems[options.lattice][:,3:]
elif options.lattice == latticeChoices[2]:
# convert 4 Miller index notation of hex to orthogonal 3 Miller index notation
for i in xrange(len(c_direction)):
c_direction[i] = np.array([slipSystems['hex'][i,0]*1.5,
(slipSystems['hex'][i,0] + 2.*slipSystems['hex'][i,1])*0.5*np.sqrt(3),
slipSystems['hex'][i,3]*options.CoverA,
])
c_normal[i] = np.array([slipSystems['hex'][i,4],
(slipSystems['hex'][i,4] + 2.*slipSystems['hex'][i,5])/np.sqrt(3),
slipSystems['hex'][i,7]/options.CoverA,
])
c_direction /= np.tile(np.linalg.norm(c_direction,axis=1),(3,1)).T
c_normal /= np.tile(np.linalg.norm(c_normal ,axis=1),(3,1)).T
# --- loop over input files ------------------------------------------------------------------------
if filenames == []: filenames = [None]
for name in filenames:
try:
table = damask.ASCIItable(name = name,buffered = False)
except:
continue
try: table = damask.ASCIItable(name = name,
buffered = False)
except: continue
damask.util.report(scriptName,name)
table.head_read() # read ASCII header info
table.info_append(scriptID + '\t' + ' '.join(sys.argv[1:]))
# ------------------------------------------ read header ------------------------------------------
key = '1_%s'%datainfo['vector']['label'][0]
if key not in table.labels:
file['croak'].write('column %s not found...\n'%key)
table.head_read()
# ------------------------------------------ sanity checks ----------------------------------------
if not np.all(table.label_dimension(label) == dim):
damask.util.croak('input {} does not have dimension {}.'.format(label,dim))
table.close(dismiss = True) # close ASCIItable and remove empty file
continue
else:
column = table.labels.index(key) # remember columns of requested data
column = table.label_index(label)
# ------------------------------------------ assemble header ---------------------------------------
table.labels_append(['%i_S(%i_%i_%i)[%i_%i_%i]'%(i+1,
slipnormal[options.lattice][i][0],
slipnormal[options.lattice][i][1],
slipnormal[options.lattice][i][2],
slipdirection[options.lattice][i][0],
slipdirection[options.lattice][i][1],
slipdirection[options.lattice][i][2],
) for i in range(Nslipsystems[options.lattice])])
if options.traceplane:
if options.rank > 0:
table.labels_append('trace_x trace_y trace_z system')
else:
table.labels_append(['(%i)tx\tty\ttz'%(i+1) for i in range(Nslipsystems[options.lattice])])
table.info_append(scriptID + '\t' + ' '.join(sys.argv[1:]))
table.labels_append(['{id}_'
'S[{direction[0]:.1g}_{direction[1]:.1g}_{direction[2]:.1g}]'
'({normal[0]:.1g}_{normal[1]:.1g}_{normal[2]:.1g})'\
.format( id = i+1,
normal = theNormal,
direction = theDirection,
) for i,(theNormal,theDirection) in enumerate(zip(c_normal,c_direction))])
table.head_write()
# ------------------------------------------ process data ------------------------------------------
outputAlive = True
while outputAlive and table.data_read(): # read next data line of ASCII table
[phi1,Phi,phi2] = Eulers=toRadians*np.array(map(\
float,table.data[column:column+datainfo['vector']['len']]))
S = [ sum( [applyEulers(phi1,Phi,phi2,normalize( \
slipnormal[options.lattice][slipsystem]))[i]*options.stressnormal[i] for i in range(3)] ) * \
sum( [applyEulers(phi1,Phi,phi2,normalize( \
slipdirection[options.lattice][slipsystem]))[i]*options.forcedirection[i] for i in range(3)] ) \
for slipsystem in range(Nslipsystems[options.lattice]) ]
table.data_append(S)
if options.traceplane:
trace = [np.cross(options.traceplane,applyEulers(phi1,Phi,phi2,normalize(slipnormal[options.lattice][slipsystem]))) \
for slipsystem in range(Nslipsystems[options.lattice]) ]
if options.rank == 0:
table.data_append('\t'.join(map(lambda x:'%f\t%f\t%f'%(x[0],x[1],x[2]),trace)))
elif options.rank > 0:
SabsSorted = sorted([(abs(S[i]),i) for i in range(len(S))])
table.data_append('\t'.join(map(str,trace[SabsSorted[-options.rank][1]])) + '\t%i'%(1+SabsSorted[-options.rank][1]))
if inputtype == 'eulers':
o = damask.Orientation(Eulers = np.array(map(float,table.data[column:column+3]))*toRadians,)
elif inputtype == 'matrix':
o = damask.Orientation(matrix = np.array(map(float,table.data[column:column+9])).reshape(3,3).transpose(),)
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),)
elif inputtype == 'quaternion':
o = damask.Orientation(quaternion = np.array(map(float,table.data[column:column+4])),)
rotForce = o.quaternion.conjugated() * force
rotNormal = o.quaternion.conjugated() * normal
table.data_append(np.abs(np.sum(c_direction*rotForce,axis=1) * np.sum(c_normal*rotNormal,axis=1)))
outputAlive = table.data_write() # output processed line
# ------------------------------------------ output finalization -----------------------------------
# ------------------------------------------ output finalization -----------------------------------
table.close() # close input ASCII table (works for stdin)
table.close() # close ASCII tables

View File

@ -1,7 +1,7 @@
#!/usr/bin/env python
# -*- coding: UTF-8 no BOM -*-
import os,sys,string
import os,sys
import numpy as np
from optparse import OptionParser
import damask
@ -25,7 +25,7 @@ parser.add_option('-t','--tensor',
(options,filenames) = parser.parse_args()
if options.tensor == None:
if options.tensor is None:
parser.error('no data column specified.')
# --- loop over input files -------------------------------------------------------------------------

View File

@ -1,7 +1,7 @@
#!/usr/bin/env python
# -*- coding: UTF-8 no BOM -*-
import os,sys,string
import os,sys
import numpy as np
from optparse import OptionParser
import damask
@ -10,7 +10,7 @@ scriptName = os.path.splitext(os.path.basename(__file__))[0]
scriptID = ' '.join([scriptName,damask.version])
def operator(stretch,strain,eigenvalues):
''' Albrecht Bertram: Elasticity and Plasticity of Large Deformations An Introduction (3rd Edition, 2012), p. 102 '''
"""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) ,
@ -75,7 +75,7 @@ if options.logarithmic: strains.append('ln')
if options.biot: strains.append('Biot')
if options.green: strains.append('Green')
if options.defgrad == None:
if options.defgrad is None:
parser.error('no data column specified.')
# --- loop over input files -------------------------------------------------------------------------

View File

@ -1,7 +1,7 @@
#!/usr/bin/env python
# -*- coding: UTF-8 no BOM -*-
import os,sys,string
import os,sys
from optparse import OptionParser
import damask

View File

@ -1,7 +1,7 @@
#!/usr/bin/env python
# -*- coding: UTF-8 no BOM -*-
import os,sys,string
import os,sys
import numpy as np
import scipy.ndimage
from optparse import OptionParser
@ -22,7 +22,7 @@ Average each data block of size 'packing' into single values thus reducing the f
parser.add_option('-c','--coordinates',
dest = 'coords',
type = 'string', metavar = 'string',
help = 'column heading for coordinates [%default]')
help = 'column label of coordinates [%default]')
parser.add_option('-p','--packing',
dest = 'packing',
type = 'int', nargs = 3, metavar = 'int int int',
@ -39,7 +39,7 @@ parser.add_option('-s', '--size',
dest = 'size',
type = 'float', nargs = 3, metavar = 'float float float',
help = 'size in x,y,z [autodetect]')
parser.set_defaults(coords = 'ipinitialcoord',
parser.set_defaults(coords = 'pos',
packing = (2,2,2),
shift = (0,0,0),
grid = (0,0,0),
@ -59,11 +59,10 @@ if any(shift != 0): prefix += 'shift{:+}{:+}{:+}_'.format(*shift)
if filenames == []: filenames = [None]
for name in filenames:
try:
table = damask.ASCIItable(name = name,
outname = os.path.join(os.path.dirname(name),
prefix+os.path.basename(name)) if name else name,
buffered = False)
try: table = damask.ASCIItable(name = name,
outname = os.path.join(os.path.dirname(name),
prefix+os.path.basename(name)) if name else name,
buffered = False)
except: continue
damask.util.report(scriptName,name)
@ -75,7 +74,6 @@ for name in filenames:
errors = []
remarks = []
colCoord = None
if table.label_dimension(options.coords) != 3: errors.append('coordinates {} are not a vector.'.format(options.coords))
else: colCoord = table.label_index(options.coords)
@ -86,7 +84,6 @@ for name in filenames:
table.close(dismiss = True)
continue
# ------------------------------------------ assemble header ---------------------------------------
table.info_append(scriptID + '\t' + ' '.join(sys.argv[1:]))
@ -101,10 +98,10 @@ for name in filenames:
mincorner = np.array(map(min,coords))
maxcorner = np.array(map(max,coords))
grid = np.array(map(len,coords),'i')
size = grid/np.maximum(np.ones(3,'d'), grid-1.0) * (maxcorner-mincorner) # size from edge to edge = dim * n/(n-1)
size = np.where(grid > 1, size, min(size[grid > 1]/grid[grid > 1])) # spacing for grid==1 equal to smallest among other spacings
size = grid/np.maximum(np.ones(3,'d'), grid-1.0) * (maxcorner-mincorner) # size from edge to edge = dim * n/(n-1)
size = np.where(grid > 1, size, min(size[grid > 1]/grid[grid > 1])) # spacing for grid==1 set to smallest among other spacings
delta = size/np.maximum(np.ones(3,'d'), grid)
origin = mincorner - 0.5*delta # shift from cell center to corner
origin = mincorner - 0.5*delta # shift from cell center to corner
else:
grid = np.array(options.grid,'i')

View File

@ -1,7 +1,7 @@
#!/usr/bin/env python
# -*- coding: UTF-8 no BOM -*-
import os,sys,string
import os,sys
import numpy as np
from optparse import OptionParser
import damask
@ -28,7 +28,7 @@ parser.add_option('-l','--label',
(options,filenames) = parser.parse_args()
if options.label == None:
if options.label is None:
parser.error('no grouping column specified.')
@ -37,10 +37,14 @@ if options.label == None:
if filenames == []: filenames = [None]
for name in filenames:
try:
table = damask.ASCIItable(name = name,
outname = options.label+'_averaged_'+name if name else name,
buffered = False)
damask.util.croak(name)
try: table = damask.ASCIItable(name = name,
outname = os.path.join(
os.path.split(name)[0],
options.label+'_averaged_'+os.path.split(name)[1]
) if name else name,
buffered = False)
except: continue
damask.util.report(scriptName,name)

View File

@ -1,7 +1,7 @@
#!/usr/bin/env python
# -*- coding: UTF-8 no BOM -*-
import os,sys,string
import os,sys
import numpy as np
from optparse import OptionParser
import damask
@ -77,11 +77,11 @@ minmax = np.array([np.array(options.xrange),
grid = np.zeros(options.bins,'f')
result = np.zeros((options.bins[0],options.bins[1],3),'f')
if options.data == None: parser.error('no data columns specified.')
if options.data is None: parser.error('no data columns specified.')
labels = options.data
if options.weight != None: labels += [options.weight] # prevent character splitting of single string value
if options.weight is not None: labels += [options.weight] # prevent character splitting of single string value
# --- loop over input files -------------------------------------------------------------------------
@ -124,7 +124,7 @@ for name in filenames:
x = int(options.bins[0]*(table.data[i,0]-minmax[0,0])/delta[0])
y = int(options.bins[1]*(table.data[i,1]-minmax[1,0])/delta[1])
if x >= 0 and x < options.bins[0] and y >= 0 and y < options.bins[1]:
grid[x,y] += 1. if options.weight == None else table.data[i,2] # count (weighted) occurrences
grid[x,y] += 1. if options.weight is None else table.data[i,2] # count (weighted) occurrences
if options.normCol:
for x in xrange(options.bins[0]):

View File

@ -1,7 +1,7 @@
#!/usr/bin/env python
# -*- coding: UTF-8 no BOM -*-
import os,sys,string
import os,sys
import numpy as np
from optparse import OptionParser
import damask
@ -19,36 +19,38 @@ to resolution*packing.
""", version = scriptID)
parser.add_option('-c','--coordinates', dest='coords', metavar='string',
help='column heading for coordinates [%default]')
parser.add_option('-p','--packing', dest='packing', type='int', nargs=3, metavar='int int int',
help='dimension of packed group [%default]')
parser.add_option('-g','--grid', dest='resolution', type='int', nargs=3, metavar='int int int',
help='resolution in x,y,z [autodetect]')
parser.add_option('-s','--size', dest='dimension', type='float', nargs=3, metavar='int int int',
help='dimension in x,y,z [autodetect]')
parser.set_defaults(coords = 'ipinitialcoord')
parser.set_defaults(packing = (2,2,2))
parser.set_defaults(grid = (0,0,0))
parser.set_defaults(size = (0.0,0.0,0.0))
parser.add_option('-c','--coordinates',
dest = 'coords', metavar = 'string',
help = 'column label of coordinates [%default]')
parser.add_option('-p','--packing',
dest = 'packing', type = 'int', nargs = 3, metavar = 'int int int',
help = 'dimension of packed group [%default]')
parser.add_option('-g','--grid',
dest = 'resolution', type = 'int', nargs = 3, metavar = 'int int int',
help = 'resolution in x,y,z [autodetect]')
parser.add_option('-s','--size',
dest = 'dimension', type = 'float', nargs = 3, metavar = 'int int int',
help = 'dimension in x,y,z [autodetect]')
parser.set_defaults(coords = 'pos',
packing = (2,2,2),
grid = (0,0,0),
size = (0.0,0.0,0.0),
)
(options,filenames) = parser.parse_args()
options.packing = np.array(options.packing)
prefix = 'blowUp%ix%ix%i_'%(options.packing[0],options.packing[1],options.packing[2])
prefix = 'blowUp{}x{}x{}_'.format(*options.packing)
# --- loop over input files -------------------------------------------------------------------------
if filenames == []: filenames = [None]
for name in filenames:
try:
table = damask.ASCIItable(name = name,
outname = os.path.join(os.path.dirname(name),
prefix+ \
os.path.basename(name)) if name else name,
buffered = False)
try: table = damask.ASCIItable(name = name,
outname = os.path.join(os.path.dirname(name),
prefix+os.path.basename(name)) if name else name,
buffered = False)
except: continue
damask.util.report(scriptName,name)
@ -58,39 +60,41 @@ for name in filenames:
# ------------------------------------------ sanity checks ----------------------------------------
if table.label_dimension(options.coords) != 3: errors.append('coordinates {} are not a vector.'.format(options.coords))
else: coordCol = table.label_index(options.coords)
errors = []
remarks = []
if table.label_dimension(options.coords) != 3: errors.append('coordinates {} are not a vector.'.format(options.coords))
else: colCoord = table.label_index(options.coords)
# ------------------------------------------ assemble header --------------------------------------
table.info_append(scriptID + '\t' + ' '.join(sys.argv[1:]))
colElem = table.label_index('elem')
if remarks != []: damask.util.croak(remarks)
if errors != []:
damask.util.croak(errors)
table.close(dismiss = True)
continue
# --------------- figure out size and grid ---------------------------------------------------------
table.data_readArray()
coords = [{},{},{}]
for i in xrange(len(table.data)):
for j in xrange(3):
coords[j][str(table.data[i,coordCol+j])] = True
grid = np.array(map(len,coords),'i')
size = grid/np.maximum(np.ones(3,'d'),grid-1.0)* \
np.array([max(map(float,coords[0].keys()))-min(map(float,coords[0].keys())),\
max(map(float,coords[1].keys()))-min(map(float,coords[1].keys())),\
max(map(float,coords[2].keys()))-min(map(float,coords[2].keys())),\
],'d') # size from bounding box, corrected for cell-centeredness
size = np.where(grid > 1, size, min(size[grid > 1]/grid[grid > 1])) # spacing for grid==1 equal to smallest among other spacings
table.data_readArray(options.coords)
coords = [np.unique(table.data[:,i]) for i in xrange(3)]
mincorner = np.array(map(min,coords))
maxcorner = np.array(map(max,coords))
grid = np.array(map(len,coords),'i')
size = grid/np.maximum(np.ones(3,'d'), grid-1.0) * (maxcorner-mincorner) # size from edge to edge = dim * n/(n-1)
size = np.where(grid > 1, size, min(size[grid > 1]/grid[grid > 1])) # spacing for grid==1 set to smallest among other spacings
packing = np.array(options.packing,'i')
outSize = grid*packing
# ------------------------------------------ assemble header ---------------------------------------
# ------------------------------------------ assemble header --------------------------------------
table.info_append(scriptID + '\t' + ' '.join(sys.argv[1:]))
table.head_write()
# ------------------------------------------ process data -------------------------------------------
table.data_rewind()
data = np.zeros(outSize.tolist()+[len(table.labels)])
p = np.zeros(3,'i')
@ -102,15 +106,15 @@ for name in filenames:
table.data_read()
data[d[0]:d[0]+packing[0],
d[1]:d[1]+packing[1],
d[2]:d[2]+packing[2],
d[2]:d[2]+packing[2],
: ] = np.tile(np.array(table.data_asFloat(),'d'),packing.tolist()+[1]) # tile to match blowUp voxel size
elementSize = size/grid/packing
elem = 1
for c in xrange(outSize[2]):
for b in xrange(outSize[1]):
for a in xrange(outSize[0]):
data[a,b,c,coordCol:coordCol+3] = [a+0.5,b+0.5,c+0.5]*elementSize
data[a,b,c,table.label_index('elem')] = elem
data[a,b,c,colCoord:colCoord+3] = [a+0.5,b+0.5,c+0.5]*elementSize
if colElem != -1: data[a,b,c,colElem] = elem
table.data = data[a,b,c,:].tolist()
outputAlive = table.data_write() # output processed line
elem += 1

View File

@ -1,7 +1,8 @@
#!/usr/bin/env python
# -*- coding: UTF-8 no BOM -*-
import os,re,sys,string,fnmatch,math,random
import os,re,sys
import math # noqa
import numpy as np
from optparse import OptionParser
import damask
@ -42,7 +43,7 @@ parser.set_defaults(condition = '',
(options,filenames) = parser.parse_args()
if options.labels == None or options.formulae == None:
if options.labels is None or options.formulae is None:
parser.error('no formulae specified.')
if len(options.labels) != len(options.formulae):
parser.error('number of labels ({}) and formulae ({}) do not match.'.format(len(options.labels),len(options.formulae)))

View File

@ -1,7 +1,8 @@
#!/usr/bin/env python
# -*- coding: UTF-8 no BOM -*-
import os,re,sys,fnmatch,math,random
import os,re,sys,fnmatch
import math # noqa
import numpy as np
from optparse import OptionParser
import damask
@ -34,7 +35,7 @@ Filter rows according to condition and columns by either white or black listing.
Examples:
Every odd row if x coordinate is positive -- " #ip.x# >= 0.0 and #_row_#%2 == 1 ).
All rows where label 'foo' equals 'bar' -- " #foo# == \"bar\" "
All rows where label 'foo' equals 'bar' -- " #s#foo# == 'bar' "
""", version = scriptID)
@ -79,14 +80,14 @@ for name in filenames:
positions = []
for position,label in enumerate(table.labels):
if (options.whitelist == None or any([ position in table.label_indexrange(needle) \
if (options.whitelist is None or any([ position in table.label_indexrange(needle) \
or fnmatch.fnmatch(label,needle) for needle in options.whitelist])) \
and (options.blacklist == None or not any([ position in table.label_indexrange(needle) \
and (options.blacklist is None or not any([ position in table.label_indexrange(needle) \
or fnmatch.fnmatch(label,needle) for needle in options.blacklist])): # a label to keep?
labels.append(label) # remember name...
positions.append(position) # ...and position
if len(labels) > 0 and options.whitelist != None and options.blacklist == None: # check whether reordering is possible
if len(labels) > 0 and options.whitelist is not None and options.blacklist is None: # check whether reordering is possible
whitelistitem = np.zeros(len(labels),dtype=int)
for i,label in enumerate(labels): # check each selected label
match = [ positions[i] in table.label_indexrange(needle) \
@ -118,7 +119,7 @@ for name in filenames:
# ------------------------------------------ assemble header ---------------------------------------
table.info_append(scriptID + '\t' + ' '.join(sys.argv[1:])) # read ASCII header info
table.info_append(scriptID + '\t' + ' '.join(sys.argv[1:]))
table.labels_clear()
table.labels_append(np.array(labels)[order]) # update with new label set
table.head_write()

142
processing/post/histogram.py Executable file
View File

@ -0,0 +1,142 @@
#!/usr/bin/env python
# -*- coding: UTF-8 no BOM -*-
import os,sys
import numpy as np
from optparse import OptionParser
import damask
scriptName = os.path.splitext(os.path.basename(__file__))[0]
scriptID = ' '.join([scriptName,damask.version])
# --------------------------------------------------------------------
# MAIN
# --------------------------------------------------------------------
parser = OptionParser(option_class=damask.extendableOption, usage='%prog options [file[s]]', description = """
Generate histogram of N bins in given data range.
""", version = scriptID)
parser.add_option('-d','--data',
dest = 'data',
type = 'string', metavar = 'string',
help = 'column heading for data')
parser.add_option('-w','--weights',
dest = 'weights',
type = 'string', metavar = 'string',
help = 'column heading for weights')
parser.add_option('--range',
dest = 'range',
type = 'float', nargs = 2, metavar = 'float float',
help = 'data range of histogram [min - max]')
parser.add_option('-N',
dest = 'N',
type = 'int', metavar = 'int',
help = 'number of bins')
parser.add_option('--density',
dest = 'density',
action = 'store_true',
help = 'report probability density')
parser.add_option('--logarithmic',
dest = 'log',
action = 'store_true',
help = 'logarithmically spaced bins')
parser.set_defaults(data = None,
weights = None,
range = None,
N = None,
density = False,
log = False,
)
(options,filenames) = parser.parse_args()
if not options.data: parser.error('no data specified.')
if not options.N: parser.error('no bin number specified.')
if options.log:
def forward(x):
return np.log(x)
def reverse(x):
return np.exp(x)
else:
def forward(x):
return x
def reverse(x):
return x
# --- loop over input files ------------------------------------------------------------------------
if filenames == []: filenames = [None]
for name in filenames:
try: table = damask.ASCIItable(name = name,
buffered = False,
readonly = True)
except: continue
damask.util.report(scriptName,name)
# ------------------------------------------ read header ------------------------------------------
table.head_read()
# ------------------------------------------ sanity checks ----------------------------------------
errors = []
remarks = []
if table.label_dimension(options.data) != 1: errors.append('data {} are not scalar.'.format(options.data))
if options.weights and \
table.label_dimension(options.data) != 1: errors.append('weights {} are not scalar.'.format(options.weights))
if remarks != []: damask.util.croak(remarks)
if errors != []:
damask.util.croak(errors)
table.close(dismiss = True)
continue
# --------------- read data ----------------------------------------------------------------
table.data_readArray([options.data,options.weights])
# --------------- auto range ---------------------------------------------------------------
if options.range is None:
rangeMin,rangeMax = min(table.data[:,0]),max(table.data[:,0])
else:
rangeMin,rangeMax = min(options.range),max(options.range)
# --------------- bin data ----------------------------------------------------------------
count,edges = np.histogram(table.data[:,0],
bins = reverse(forward(rangeMin) + np.arange(options.N+1) *
(forward(rangeMax)-forward(rangeMin))/options.N),
range = (rangeMin,rangeMax),
weights = None if options.weights is None else table.data[:,1],
density = options.density,
)
bincenter = reverse(forward(rangeMin) + (0.5+np.arange(options.N)) *
(forward(rangeMax)-forward(rangeMin))/options.N) # determine center of bins
# ------------------------------------------ assemble header ---------------------------------------
table.info_clear()
table.info_append([scriptID + '\t' + ' '.join(sys.argv[1:]),
scriptID + ':\t' +
'data range {} -- {}'.format(rangeMin,rangeMax) +
(' (log)' if options.log else ''),
])
table.labels_clear()
table.labels_append(['bincenter','count'])
table.head_write()
# ------------------------------------------ output result -----------------------------------------
table.data = np.squeeze(np.dstack((bincenter,count)))
table.data_writeArray()
# ------------------------------------------ output finalization -----------------------------------
table.close() # close ASCII tables

View File

@ -1,7 +1,7 @@
#!/usr/bin/env python
# -*- coding: UTF-8 no BOM -*-
import os,sys,string
import os,sys
import numpy as np
from optparse import OptionParser
from PIL import Image
@ -115,7 +115,7 @@ for name in filenames:
try:
table = damask.ASCIItable(name = name,
buffered = False,
labeled = options.label != None,
labeled = options.label is not None,
readonly = True)
except: continue
damask.util.report(scriptName,name)
@ -131,15 +131,15 @@ for name in filenames:
damask.util.croak('column {} not found.'.format(options.label))
table.close(dismiss = True) # close ASCIItable and remove empty file
continue
# convert data to values between 0 and 1 and arrange according to given options
# convert data to values between 0 and 1 and arrange according to given options
if options.dimension != []: table.data = table.data.reshape(options.dimension[1],options.dimension[0])
if options.abs: table.data = np.abs(table.data)
if options.log: table.data = np.log10(table.data);options.range = np.log10(options.range)
if options.flipLR: table.data = np.fliplr(table.data)
if options.flipUD: table.data = np.flipud(table.data)
mask = np.logical_or(table.data == options.gap, np.isnan(table.data)) if options.gap else np.logical_not(np.isnan(table.data)) # mask gap and NaN (if gap present)
mask = np.logical_or(table.data == options.gap, np.isnan(table.data))\
if options.gap else np.logical_not(np.isnan(table.data)) # mask gap and NaN (if gap present)
if np.all(np.array(options.range) == 0.0):
options.range = [table.data[mask].min(),
table.data[mask].max()]
@ -176,7 +176,7 @@ for name in filenames:
im.save(sys.stdout if not name else
os.path.splitext(name)[0]+ \
('' if options.label == None else '_'+options.label)+ \
('' if options.label is None else '_'+options.label)+ \
'.png',
format = "PNG")

View File

@ -1,7 +1,7 @@
#!/usr/bin/env python
# -*- coding: UTF-8 no BOM -*-
import os,sys,string
import os,sys
import numpy as np
from optparse import OptionParser
from PIL import Image, ImageDraw
@ -112,7 +112,7 @@ for name in filenames:
try:
table = damask.ASCIItable(name = name,
buffered = False,
labeled = options.label != None,
labeled = options.label is not None,
readonly = True)
except: continue
table.report_name(scriptName,name)
@ -161,9 +161,10 @@ for name in filenames:
]) # find x-y bounding box for given z layer
nodes -= boundingBox[0].repeat(np.prod(options.dimension+1)).reshape([3]+list(options.dimension+1))
nodes *= (options.pixelsize*options.dimension/options.size).repeat(np.prod(options.dimension+1)).reshape([3]+list(options.dimension+1))
imagesize = (options.pixelsize*(boundingBox[1]-boundingBox[0])*options.dimension\
/options.size)[:2].astype('i') # determine image size from number of cells in overall bounding box
nodes *= (options.pixelsize*options.dimension/options.size).repeat(np.prod(options.dimension+1)).\
reshape([3]+list(options.dimension+1))
imagesize = (options.pixelsize*(boundingBox[1]-boundingBox[0])* # determine image size from number of
options.dimension/options.size)[:2].astype('i') # cells in overall bounding box
im = Image.new('RGBA',imagesize)
draw = ImageDraw.Draw(im)

View File

@ -1,7 +1,7 @@
#!/usr/bin/env python
# -*- coding: UTF-8 no BOM -*-
import os,sys,string
import os,sys
import numpy as np
from optparse import OptionParser
from PIL import Image
@ -80,7 +80,7 @@ for name in filenames:
try:
table = damask.ASCIItable(name = name,
buffered = False,
labeled = options.label != None,
labeled = options.label is not None,
readonly = True)
except: continue
damask.util.report(scriptName,name)
@ -98,14 +98,13 @@ for name in filenames:
errors.append('column{} {} not found'.format('s' if len(missing_labels) > 1 else '',
', '.join(missing_labels)))
if table.label_dimension(options.label) != 3:
errors.append('column {} has wrong dimension'.format(options.label))
errors.append('column {} does not have dimension'.format(options.label))
if errors != []:
damask.util.croak(errors)
table.close(dismiss = True) # close ASCII table file handles and delete output file
continue
# convert data to shape and arrange according to given options
# convert data to shape and arrange according to given options
if options.dimension != []: table.data = table.data.reshape(options.dimension[1],options.dimension[0],3)
if options.flipLR: table.data = np.fliplr(table.data)
if options.flipUD: table.data = np.flipud(table.data)

View File

@ -55,7 +55,7 @@ else:
sys.path.append(damask.solver.Marc().libraryPath('../../'))
try:
from py_post import *
import py_post
except:
print('error: no valid Mentat release found')
sys.exit(-1)
@ -63,7 +63,7 @@ except:
# --------------------------- open results file and initialize mesh ----------
p = post_open(filename+'.t16')
p = py_post.post_open(filename+'.t16')
p.moveto(0)
Nnodes = p.nodes()
Nincrements = p.increments() - 1 # t16 contains one "virtual" increment (at 0)
@ -114,7 +114,7 @@ for incCount,position in enumerate(locations): # walk through locations
p.moveto(position+1) # wind to correct position
# --- get displacements
# --- get displacements
node_displacement = [[0,0,0] for i in range(Nnodes)]
for n in range(Nnodes):
@ -124,10 +124,11 @@ for incCount,position in enumerate(locations): # walk through locations
cellnode_displacement = [[c[i][n] for i in range(3)] for n in range(Ncellnodes)]
# --- append displacements to corresponding files
# --- append displacements to corresponding files
for geomtype in options.type:
outFilename = eval('"'+eval("'%%s_%%s_inc%%0%ii.vtk'%(math.log10(max(increments+[1]))+1)")+'"%(dirname + os.sep + os.path.split(filename)[1],geomtype,increments[incCount])')
outFilename = eval('"'+eval("'%%s_%%s_inc%%0%ii.vtk'%(math.log10(max(increments+[1]))+1)")\
+'"%(dirname + os.sep + os.path.split(filename)[1],geomtype,increments[incCount])')
print outFilename
shutil.copyfile('%s_%s.vtk'%(filename,geomtype),outFilename)

View File

@ -10,12 +10,8 @@ scriptID = ' '.join([scriptName,damask.version])
# -----------------------------
def ParseOutputFormat(filename,homogID,crystID,phaseID):
#
# parse .output* files in order to get a list of outputs
# -----------------------------
myID = {
'Homogenization': homogID,
"""parse .output* files in order to get a list of outputs"""
myID = {'Homogenization': homogID,
'Crystallite': crystID,
'Constitutive': phaseID,
}
@ -61,24 +57,24 @@ def ParseOutputFormat(filename,homogID,crystID,phaseID):
elif length > 0:
format[what]['outputs'].append([output,length])
if not '_id' in format[what]['specials']:
if '_id' not in format[what]['specials']:
print "\nsection '%s' not found in <%s>"%(myID[what], what)
print '\n'.join(map(lambda x:' [%s]'%x, format[what]['specials']['brothers']))
return format
# -----------------------------
def ParsePostfile(p,filename, outputFormat, legacyFormat):
#
# parse postfile in order to get position and labels of outputs
# needs "outputFormat" for mapping of output names to postfile output indices
# -----------------------------
"""
parse postfile in order to get position and labels of outputs
needs "outputFormat" for mapping of output names to postfile output indices
"""
startVar = {True: 'GrainCount',
False:'HomogenizationCount'}
# --- build statistics
# --- build statistics
stat = { \
'IndexOfLabel': {}, \
@ -95,7 +91,7 @@ def ParsePostfile(p,filename, outputFormat, legacyFormat):
'LabelOfElementalTensor': [None]*p.element_tensors(), \
}
# --- find labels
# --- find labels
for labelIndex in range(stat['NumberOfNodalScalars']):
label = p.node_scalar_label(labelIndex)
@ -119,9 +115,9 @@ def ParsePostfile(p,filename, outputFormat, legacyFormat):
startIndex = stat['IndexOfLabel'][startVar[legacyFormat]]
stat['LabelOfElementalScalar'][startIndex] = startVar[legacyFormat]
# We now have to find a mapping for each output label as defined in the .output* files to the output position in the post file
# Since we know where the user defined outputs start ("startIndex"), we can simply assign increasing indices to the labels
# given in the .output* file
# We now have to find a mapping for each output label as defined in the .output* files to the output position in the post file
# Since we know where the user defined outputs start ("startIndex"), we can simply assign increasing indices to the labels
# given in the .output* file
offset = 1
if legacyFormat:
@ -177,10 +173,7 @@ def ParsePostfile(p,filename, outputFormat, legacyFormat):
# -----------------------------
def GetIncrementLocations(p,Nincrements,options):
#
# get mapping between positions in postfile and increment number
# -----------------------------
"""get mapping between positions in postfile and increment number"""
incAtPosition = {}
positionOfInc = {}
@ -209,7 +202,6 @@ def GetIncrementLocations(p,Nincrements,options):
# -----------------------------
def SummarizePostfile(stat,where=sys.stdout):
# -----------------------------
where.write('\n\n')
where.write('title:\t%s'%stat['Title'] + '\n\n')
@ -217,16 +209,18 @@ def SummarizePostfile(stat,where=sys.stdout):
where.write('increments:\t%i'%(stat['NumberOfIncrements']) + '\n\n')
where.write('nodes:\t%i'%stat['NumberOfNodes'] + '\n\n')
where.write('elements:\t%i'%stat['NumberOfElements'] + '\n\n')
where.write('nodal scalars:\t%i'%stat['NumberOfNodalScalars'] + '\n\n ' + '\n '.join(stat['LabelOfNodalScalar']) + '\n\n')
where.write('elemental scalars:\t%i'%stat['NumberOfElementalScalars'] + '\n\n ' + '\n '.join(stat['LabelOfElementalScalar']) + '\n\n')
where.write('elemental tensors:\t%i'%stat['NumberOfElementalTensors'] + '\n\n ' + '\n '.join(stat['LabelOfElementalTensor']) + '\n\n')
where.write('nodal scalars:\t%i'%stat['NumberOfNodalScalars'] + '\n\n '\
+'\n '.join(stat['LabelOfNodalScalar']) + '\n\n')
where.write('elemental scalars:\t%i'%stat['NumberOfElementalScalars'] + '\n\n '\
+ '\n '.join(stat['LabelOfElementalScalar']) + '\n\n')
where.write('elemental tensors:\t%i'%stat['NumberOfElementalTensors'] + '\n\n '\
+ '\n '.join(stat['LabelOfElementalTensor']) + '\n\n')
return True
# -----------------------------
def SummarizeOutputfile(format,where=sys.stdout):
# -----------------------------
where.write('\nUser Defined Outputs')
for what in format.keys():
@ -239,7 +233,6 @@ def SummarizeOutputfile(format,where=sys.stdout):
# -----------------------------
def writeHeader(myfile,stat,geomtype):
# -----------------------------
myfile.write('2\theader\n')
myfile.write(string.replace('$Id$','\n','\\n')+
@ -316,7 +309,7 @@ if not os.path.exists(filename+'.t16'):
sys.path.append(damask.solver.Marc().libraryPath('../../'))
try:
from py_post import *
import py_post
except:
print('error: no valid Mentat release found')
sys.exit(-1)
@ -336,14 +329,14 @@ if damask.core.mesh.mesh_init_postprocessing(filename+'.mesh'):
# --- check if ip data available for all elements; if not, then .t19 file is required
p = post_open(filename+'.t16')
p = py_post.post_open(filename+'.t16')
asciiFile = False
p.moveto(1)
for e in range(p.elements()):
if not damask.core.mesh.mesh_get_nodeAtIP(str(p.element(e).type),1):
if os.path.exists(filename+'.t19'):
p.close()
p = post_open(filename+'.t19')
p = py_post.post_open(filename+'.t19')
asciiFile = True
break
@ -383,18 +376,20 @@ time_start = time.time()
for incCount,position in enumerate(locations): # walk through locations
p.moveto(position+1) # wind to correct position
time_delta = (float(len(locations)) / float(incCount+1) - 1.0) * (time.time() - time_start)
sys.stdout.write("\r(%02i:%02i:%02i) processing increment %i of %i..."%(time_delta//3600,time_delta%3600//60,time_delta%60,incCount+1,len(locations)))
sys.stdout.write("\r(%02i:%02i:%02i) processing increment %i of %i..."\
%(time_delta//3600,time_delta%3600//60,time_delta%60,incCount+1,len(locations)))
sys.stdout.flush()
# --- write header
# --- write header
outFilename = {}
for geomtype in options.type:
outFilename[geomtype] = eval('"'+eval("'%%s_%%s_inc%%0%ii.txt'%(math.log10(max(increments+[1]))+1)")+'"%(dirname + os.sep + os.path.split(filename)[1],geomtype,increments[incCount])')
outFilename[geomtype] = eval('"'+eval("'%%s_%%s_inc%%0%ii.txt'%(math.log10(max(increments+[1]))+1)")\
+'"%(dirname + os.sep + os.path.split(filename)[1],geomtype,increments[incCount])')
with open(outFilename[geomtype],'w') as myfile:
writeHeader(myfile,stat,geomtype)
# --- write node based data
# --- write node based data
if geomtype == 'nodebased':
for n in range(stat['NumberOfNodes']):
@ -403,7 +398,7 @@ for incCount,position in enumerate(locations): # walk through locations
myfile.write('\t'+str(p.node_scalar(n,l)))
myfile.write('\n')
# --- write ip based data
# --- write ip based data
elif geomtype == 'ipbased':
for e in range(stat['NumberOfElements']):
@ -424,5 +419,3 @@ for incCount,position in enumerate(locations): # walk through locations
p.close()
sys.stdout.write("\n")
# --------------------------- DONE --------------------------------

View File

@ -1,7 +1,7 @@
#!/usr/bin/env python
# -*- coding: UTF-8 no BOM -*-
import os, sys, string
import os,sys
import damask
from optparse import OptionParser
@ -14,9 +14,9 @@ def outMentat(cmd,locals):
exec(cmd[3:])
elif cmd[0:3] == '(?)':
cmd = eval(cmd[3:])
py_send(cmd)
py_mentat.py_send(cmd)
else:
py_send(cmd)
py_mentat.py_send(cmd)
return
@ -59,7 +59,8 @@ def colorMap(colors,baseIdx=32):
# MAIN FUNCTION STARTS HERE
# -----------------------------
parser = OptionParser(option_class=damask.extendableOption, usage="%prog [options] predefinedScheme | (lower_h,s,l upper_h,s,l)", description = """
parser = OptionParser(option_class=damask.extendableOption,
usage="%prog [options] predefinedScheme | (lower_h,s,l upper_h,s,l)", description = """
Changes the color map in MSC.Mentat.
Interpolates colors between "lower_hsl" and "upper_hsl".
@ -121,13 +122,12 @@ if options.palettef:
elif options.palette:
for theColor in theMap.export(format='list',steps=options.colorcount):
print '\t'.join(map(lambda x: str(int(255*x)),theColor))
else:
### connect to Mentat and change colorMap
else: # connect to Mentat and change colorMap
sys.path.append(damask.solver.Marc().libraryPath('../../'))
try:
from py_mentat import *
import py_mentat
print 'waiting to connect...'
py_connect('',options.port)
py_mentat.py_connect('',options.port)
print 'connected...'
mentat = True
except:
@ -138,7 +138,7 @@ else:
cmds = colorMap(theMap.export(format='list',steps=options.colorcount),options.baseIdx)
if mentat:
output(['*show_table']+cmds+['*show_model *redraw'],outputLocals,'Mentat')
py_disconnect()
py_mentat.py_disconnect()
if options.verbose:
output(cmds,outputLocals,'Stdout')

View File

@ -1,7 +1,7 @@
#!/usr/bin/env python
# -*- coding: UTF-8 no BOM -*-
import string,sys,os
import sys,os
import damask
from optparse import OptionParser
@ -9,7 +9,7 @@ scriptName = os.path.splitext(os.path.basename(__file__))[0]
scriptID = ' '.join([scriptName,damask.version])
# --------------------------------------------------------------------
# MAIN
# MAIN
# --------------------------------------------------------------------
#Borland, D., & Taylor, R. M. (2007). Rainbow Color Map (Still) Considered Harmful. Computer Graphics and Applications, IEEE, 27(2), 14--17.
#Moreland, K. (2009). Diverging Color Maps for Scientific Visualization. In Proc. 5th Int. Symp. Visual Computing (pp. 92--103).
@ -62,8 +62,10 @@ if options.trim[0] < -1.0 or \
parser.error('invalid trim range (-1 +1).')
name = options.format if options.basename == None else options.basename
output = sys.stdout if options.basename == None else open(os.path.basename(options.basename)+extensions[outtypes.index(options.format)],'w')
name = options.format if options.basename is None\
else options.basename
output = sys.stdout if options.basename is None\
else open(os.path.basename(options.basename)+extensions[outtypes.index(options.format)],'w')
colorLeft = damask.Color(options.colormodel.upper(), list(options.left))
colorRight = damask.Color(options.colormodel.upper(), list(options.right))

View File

@ -1,7 +1,7 @@
#!/usr/bin/env python
# -*- coding: UTF-8 no BOM -*-
import os,sys,string
import os,sys
import numpy as np
from optparse import OptionParser
import damask
@ -79,7 +79,7 @@ for name in filenames:
# ------------------------------------------ assemble header ---------------------------------------
randomSeed = int(os.urandom(4).encode('hex'), 16) if options.randomSeed == None else options.randomSeed # random seed per file
randomSeed = int(os.urandom(4).encode('hex'), 16) if options.randomSeed is None else options.randomSeed # random seed per file
np.random.seed(randomSeed)
table.info_append([scriptID + '\t' + ' '.join(sys.argv[1:]),

View File

@ -1,7 +1,7 @@
#!/usr/bin/env python
# -*- coding: UTF-8 no BOM -*-
import os,sys,math,re,threading,time,struct,string
import os,sys,math,re,time,struct,string
import damask
from optparse import OptionParser, OptionGroup
@ -17,7 +17,6 @@ fileExtensions = { \
# -----------------------------
class vector: # mimic py_post node object
# -----------------------------
x,y,z = [None,None,None]
def __init__(self,coords):
@ -27,7 +26,6 @@ class vector: # mimic py_post node object
# -----------------------------
class element: # mimic py_post element object
# -----------------------------
items = []
type = None
@ -37,7 +35,6 @@ class element: # mimic py_post element object
# -----------------------------
class elemental_scalar: # mimic py_post element_scalar object
# -----------------------------
id = None
value = None
@ -48,7 +45,6 @@ class elemental_scalar: # mimic py_post element_scalar object
# -----------------------------
class MPIEspectral_result: # mimic py_post result object
# -----------------------------
file = None
dataOffset = 0
@ -68,7 +64,8 @@ class MPIEspectral_result: # mimic py_post result object
increment = 0
startingIncrement = 0
position = 0
time = 0.0 # this is a dummy at the moment, we need to parse the load file and figure out what time a particular increment corresponds to
# this is a dummy at the moment, we need to parse the load file and figure out what time a particular increment corresponds to
time = 0.0
N_nodes = 0
N_node_scalars = 0
N_elements = 0
@ -87,40 +84,40 @@ class MPIEspectral_result: # mimic py_post result object
self.dataOffset += 7
#search first for the new keywords with ':', if not found try to find the old ones
self.theTitle = self._keyedString('load:')
if self.theTitle == None:
if self.theTitle is None:
self.theTitle = self._keyedString('load')
self.wd = self._keyedString('workingdir:')
if self.wd == None:
if self.wd is None:
self.wd = self._keyedString('workingdir')
self.geometry = self._keyedString('geometry:')
if self.geometry == None:
if self.geometry is None:
self.geometry = self._keyedString('geometry')
self.N_loadcases = self._keyedPackedArray('loadcases:',count=1,type='i')[0]
if self.N_loadcases == None:
if self.N_loadcases is None:
self.N_loadcases = self._keyedPackedArray('loadcases',count=1,type='i')[0]
self._frequencies = self._keyedPackedArray('frequencies:',count=self.N_loadcases,type='i')
if all ( i == None for i in self._frequencies):
if all ( i is None for i in self._frequencies):
self._frequencies = self._keyedPackedArray('frequencies',count=self.N_loadcases,type='i')
self._increments = self._keyedPackedArray('increments:',count=self.N_loadcases,type='i')
if all (i == None for i in self._increments):
if all (i is None for i in self._increments):
self._increments = self._keyedPackedArray('increments',count=self.N_loadcases,type='i')
self.startingIncrement = self._keyedPackedArray('startingIncrement:',count=1,type='i')[0]
if self.startingIncrement == None:
if self.startingIncrement is None:
self.startingIncrement = self._keyedPackedArray('startingIncrement',count=1,type='i')[0]
self._times = self._keyedPackedArray('times:',count=self.N_loadcases,type='d')
if all (i == None for i in self._times):
if all (i is None for i in self._times):
self._times = self._keyedPackedArray('times',count=self.N_loadcases,type='d')
self._logscales = self._keyedPackedArray('logscales:',count=self.N_loadcases,type='i')
if all (i == None for i in self._logscales):
if all (i is None for i in self._logscales):
self._logscales = self._keyedPackedArray('logscales',count=self.N_loadcases,type='i')
self.size = self._keyedPackedArray('size:',count=3,type='d')
@ -135,7 +132,7 @@ class MPIEspectral_result: # mimic py_post result object
self.N_elements = self.grid[0] * self.grid[1] * self.grid[2]
self.N_element_scalars = self._keyedPackedArray('materialpoint_sizeResults:',count=1,type='i')[0]
if self.N_element_scalars == None:
if self.N_element_scalars is None:
self.N_element_scalars = self._keyedPackedArray('materialpoint_sizeResults',count=1,type='i')[0]
self.N_positions = (self.filesize-self.dataOffset)/(self.N_elements*self.N_element_scalars*8)
@ -156,8 +153,7 @@ class MPIEspectral_result: # mimic py_post result object
print '\n**\n* Unexpected file size. Incomplete simulation or file corrupted!\n**'
def __str__(self):
"""Summary of results file"""
return '\n'.join([
'workdir: %s'%self.wd,
'geometry: %s'%self.geometry,
@ -181,13 +177,14 @@ class MPIEspectral_result: # mimic py_post result object
filepos=0 # start at the beginning
while name != identifier and filepos < self.dataOffset: # stop searching when found or when reached end of header
self.file.seek(filepos)
dataLen=struct.unpack('i',self.file.read(4))[0] # read the starting tag in front of the keyword (Fortran indicates start and end of writing by a 4 byte tag indicating the length of the following data)
name = self.file.read(len(identifier)) # anticipate identifier
start=filepos+(4+len(identifier)) # this is the position where the values for the found key are stored
filepos=filepos+(4+dataLen+4) # forward to next keyword
# read the starting tag in front of the keyword (Fortran indicates start and end of writing by a 4 byte tag indicating the length of the following data)
dataLen=struct.unpack('i',self.file.read(4))[0]
name = self.file.read(len(identifier)) # anticipate identifier
start=filepos+(4+len(identifier)) # position of the values for the found key
filepos=filepos+(4+dataLen+4) # forward to next keyword
if name==identifier: # found the correct name
key['pos'] = start # save position
if name==identifier: # found the correct name
key['pos'] = start # save position
key['name'] = name
return key
@ -195,7 +192,7 @@ class MPIEspectral_result: # mimic py_post result object
bytecount = {'d': 8,'i': 4}
values = [default]*count
key = self.locateKeyValue(identifier)
if key['name'] == identifier and key['pos'] != None:
if key['name'] == identifier and key['pos'] is not None:
self.file.seek(key['pos'])
for i in range(count):
values[i] = struct.unpack(type,self.file.read(bytecount[type]))[0]
@ -286,8 +283,6 @@ class MPIEspectral_result: # mimic py_post result object
if not options.legacy:
incStart = self.dataOffset \
+ self.position*8*self.N_elements*self.N_element_scalars
# header & footer + extra header and footer for 4 byte int range (Fortran)
# values
where = (e*self.N_element_scalars + idx)*8
try:
self.file.seek(incStart+where)
@ -299,15 +294,15 @@ class MPIEspectral_result: # mimic py_post result object
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)
# header & footer + extra header and footer for 4 byte int range (Fortran)
# values
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
if where%self.fourByteLimit + 8 >= self.fourByteLimit: # danger of reading into fortran record footer at 4 byte limit
data=''
for i in xrange(8):
self.file.seek(incStart+where+(where//self.fourByteLimit)*8+4)
@ -329,51 +324,10 @@ class MPIEspectral_result: # mimic py_post result object
def element_tensors(self):
return self.N_element_tensors
# -----------------------------
class backgroundMessage(threading.Thread):
# -----------------------------
def __init__(self):
threading.Thread.__init__(self)
self.message = ''
self.new_message = ''
self.counter = 0
self.symbols = ['- ', '\ ', '| ', '/ ',]
self.waittime = 0.5
def __quit__(self):
length = len(self.message) + len(self.symbols[self.counter])
sys.stderr.write(chr(8)*length + ' '*length + chr(8)*length)
sys.stderr.write('')
def run(self):
while not threading.enumerate()[0]._Thread__stopped:
time.sleep(self.waittime)
self.update_message()
self.__quit__()
def set_message(self, new_message):
self.new_message = new_message
self.print_message()
def print_message(self):
length = len(self.message) + len(self.symbols[self.counter])
sys.stderr.write(chr(8)*length + ' '*length + chr(8)*length) # delete former message
sys.stderr.write(self.symbols[self.counter] + self.new_message) # print new message
self.message = self.new_message
def update_message(self):
self.counter = (self.counter + 1)%len(self.symbols)
self.print_message()
# -----------------------------
def ipCoords(elemType, nodalCoordinates):
#
# returns IP coordinates for a given element
# -----------------------------
"""returns IP coordinates for a given element"""
nodeWeightsPerNode = {
7: [ [27.0, 9.0, 3.0, 9.0, 9.0, 3.0, 1.0, 3.0],
[ 9.0, 27.0, 9.0, 3.0, 3.0, 9.0, 3.0, 1.0],
@ -422,10 +376,7 @@ def ipCoords(elemType, nodalCoordinates):
# -----------------------------
def ipIDs(elemType):
#
# returns IP numbers for given element type
# -----------------------------
"""returns IP numbers for given element type"""
ipPerNode = {
7: [ 1, 2, 4, 3, 5, 6, 8, 7 ],
57: [ 1, 2, 4, 3, 5, 6, 8, 7 ],
@ -441,9 +392,7 @@ def ipIDs(elemType):
# -----------------------------
def substituteLocation(string, mesh, coords):
#
# do variable interpolation in group and filter strings
# -----------------------------
"""do variable interpolation in group and filter strings"""
substitute = string
substitute = substitute.replace('elem', str(mesh[0]))
substitute = substitute.replace('node', str(mesh[1]))
@ -458,10 +407,7 @@ def substituteLocation(string, mesh, coords):
# -----------------------------
def heading(glue,parts):
#
# joins pieces from parts by glue. second to last entry in pieces tells multiplicity
# -----------------------------
"""joins pieces from parts by glue. second to last entry in pieces tells multiplicity"""
header = []
for pieces in parts:
if pieces[-2] == 0:
@ -473,12 +419,12 @@ def heading(glue,parts):
# -----------------------------
def mapIncremental(label, mapping, N, base, new):
#
# applies the function defined by "mapping"
# (can be either 'min','max','avg', 'sum', or user specified)
# to a list of data
# -----------------------------
"""
applies the function defined by "mapping"
(can be either 'min','max','avg', 'sum', or user specified)
to a list of data
"""
theMap = { 'min': lambda n,b,a: a if n==0 else min(b,a),
'max': lambda n,b,a: a if n==0 else max(b,a),
'avg': lambda n,b,a: (n*b+a)/(n+1),
@ -504,10 +450,7 @@ def mapIncremental(label, mapping, N, base, new):
# -----------------------------
def OpenPostfile(name,type,nodal = False):
#
# open postfile with extrapolation mode "translate"
# -----------------------------
"""open postfile with extrapolation mode 'translate'"""
p = {\
'spectral': MPIEspectral_result,\
'marc': post_open,\
@ -520,10 +463,7 @@ def OpenPostfile(name,type,nodal = False):
# -----------------------------
def ParseOutputFormat(filename,what,me):
#
# parse .output* files in order to get a list of outputs
# -----------------------------
"""parse .output* files in order to get a list of outputs"""
content = []
format = {'outputs':{},'specials':{'brothers':[]}}
for prefix in ['']+map(str,range(1,17)):
@ -567,13 +507,11 @@ def ParseOutputFormat(filename,what,me):
# -----------------------------
def ParsePostfile(p,filename, outputFormat):
#
# parse postfile in order to get position and labels of outputs
# needs "outputFormat" for mapping of output names to postfile output indices
# -----------------------------
# --- build statistics
"""
parse postfile in order to get position and labels of outputs
needs "outputFormat" for mapping of output names to postfile output indices
"""
stat = { \
'IndexOfLabel': {}, \
'Title': p.title(), \
@ -589,7 +527,7 @@ def ParsePostfile(p,filename, outputFormat):
'LabelOfElementalTensor': [None]*p.element_tensors(), \
}
# --- find labels
# --- find labels
for labelIndex in range(stat['NumberOfNodalScalars']):
label = p.node_scalar_label(labelIndex)
@ -613,9 +551,9 @@ def ParsePostfile(p,filename, outputFormat):
startIndex = stat['IndexOfLabel']['HomogenizationCount']
stat['LabelOfElementalScalar'][startIndex] = 'HomogenizationCount'
# We now have to find a mapping for each output label as defined in the .output* files to the output position in the post file
# Since we know where the user defined outputs start ("startIndex"), we can simply assign increasing indices to the labels
# given in the .output* file
# We now have to find a mapping for each output label as defined in the .output* files to the output position in the post file
# Since we know where the user defined outputs start ("startIndex"), we can simply assign increasing indices to the labels
# given in the .output* file
offset = 1
for (name,N) in outputFormat['Homogenization']['outputs']:
@ -663,7 +601,6 @@ def ParsePostfile(p,filename, outputFormat):
# -----------------------------
def SummarizePostfile(stat,where=sys.stdout,format='marc'):
# -----------------------------
where.write('\n\n')
where.write('title:\t%s'%stat['Title'] + '\n\n')
@ -671,9 +608,12 @@ def SummarizePostfile(stat,where=sys.stdout,format='marc'):
where.write('increments:\t%i'%(stat['NumberOfIncrements']) + '\n\n')
where.write('nodes:\t%i'%stat['NumberOfNodes'] + '\n\n')
where.write('elements:\t%i'%stat['NumberOfElements'] + '\n\n')
where.write('nodal scalars:\t%i'%stat['NumberOfNodalScalars'] + '\n\n ' + '\n '.join(stat['LabelOfNodalScalar']) + '\n\n')
where.write('elemental scalars:\t%i'%stat['NumberOfElementalScalars'] + '\n\n ' + '\n '.join(stat['LabelOfElementalScalar']) + '\n\n')
where.write('elemental tensors:\t%i'%stat['NumberOfElementalTensors'] + '\n\n ' + '\n '.join(stat['LabelOfElementalTensor']) + '\n\n')
where.write('nodal scalars:\t%i'%stat['NumberOfNodalScalars'] + '\n\n '\
+'\n '.join(stat['LabelOfNodalScalar']) + '\n\n')
where.write('elemental scalars:\t%i'%stat['NumberOfElementalScalars'] + '\n\n '\
+ '\n '.join(stat['LabelOfElementalScalar']) + '\n\n')
where.write('elemental tensors:\t%i'%stat['NumberOfElementalTensors'] + '\n\n '\
+ '\n '.join(stat['LabelOfElementalTensor']) + '\n\n')
return True
@ -799,14 +739,14 @@ if not os.path.exists(files[0]):
# --- figure out filetype
if options.filetype == None:
if options.filetype is None:
ext = os.path.splitext(files[0])[1]
for theType in fileExtensions.keys():
if ext in fileExtensions[theType]:
options.filetype = theType
break
if options.filetype != None: options.filetype = options.filetype.lower()
if options.filetype is not None: options.filetype = options.filetype.lower()
if options.filetype == 'marc': offset_pos = 1
else: offset_pos = 0
@ -822,7 +762,7 @@ if options.filetype == 'marc':
sys.path.append(damask.solver.Marc().libraryPath('../../'))
try:
from py_post import *
from py_post import post_open
except:
print('error: no valid Mentat release found')
sys.exit(-1)
@ -834,7 +774,7 @@ if options.constitutiveResult and not options.phase:
parser.print_help()
parser.error('constitutive results require phase...')
if options.nodalScalar and ( options.elemScalar or options.elemTensor
if options.nodalScalar and ( options.elemScalar or options.elemTensor\
or options.homogenizationResult or options.crystalliteResult or options.constitutiveResult ):
parser.print_help()
parser.error('not allowed to mix nodal with elemental results...')
@ -851,7 +791,7 @@ options.sep.reverse()
# --- start background messaging
bg = backgroundMessage()
bg = damask.util.backgroundMessage()
bg.start()
# --- parse .output and .t16 files
@ -874,7 +814,7 @@ bg.set_message('parsing .output files...')
for what in me:
outputFormat[what] = ParseOutputFormat(filename, what, me[what])
if not '_id' in outputFormat[what]['specials']:
if '_id' not in outputFormat[what]['specials']:
print "\nsection '%s' not found in <%s>"%(me[what], what)
print '\n'.join(map(lambda x:' [%s]'%x, outputFormat[what]['specials']['brothers']))
@ -886,15 +826,18 @@ if options.filetype == 'marc':
stat['NumberOfIncrements'] -= 1 # t16 contains one "virtual" increment (at 0)
# --- sanity check for output variables
# for mentat variables (nodalScalar,elemScalar,elemTensor) we simply have to check whether the label is found in the stat[indexOfLabel] dictionary
# for user defined variables (homogenizationResult,crystalliteResult,constitutiveResult) we have to check the corresponding outputFormat, since the namescheme in stat['IndexOfLabel'] is different
# for mentat variables (nodalScalar,elemScalar,elemTensor) we simply have to check whether the label
# is found in the stat[indexOfLabel] dictionary for user defined variables (homogenizationResult,
# crystalliteResult,constitutiveResult) we have to check the corresponding outputFormat, since the
# namescheme in stat['IndexOfLabel'] is different
for opt in ['nodalScalar','elemScalar','elemTensor','homogenizationResult','crystalliteResult','constitutiveResult']:
if eval('options.%s'%opt):
for label in eval('options.%s'%opt):
if (opt in ['nodalScalar','elemScalar','elemTensor'] and label not in stat['IndexOfLabel'] and label not in ['elements',]) \
or (opt in ['homogenizationResult','crystalliteResult','constitutiveResult'] \
and (not outputFormat[opt[:-6].capitalize()]['outputs'] or not label in zip(*outputFormat[opt[:-6].capitalize()]['outputs'])[0])):
and (not outputFormat[opt[:-6].capitalize()]['outputs'] \
or label not in zip(*outputFormat[opt[:-6].capitalize()]['outputs'])[0])):
parser.error('%s "%s" unknown...'%(opt,label))
@ -952,15 +895,14 @@ if options.nodalScalar:
myIpID = 0
myGrainID = 0
# --- filter valid locations
filter = substituteLocation(options.filter, [myElemID,myNodeID,myIpID,myGrainID], myNodeCoordinates) # generates 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)
if filter != '' and not eval(filter): # for all filter expressions that are not true:...
continue # ... ignore this data point and continue with next
# --- group data locations
grp = substituteLocation('#'.join(options.sep), [myElemID,myNodeID,myIpID,myGrainID], myNodeCoordinates) # generates 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)
if grp not in index: # create a new group if not yet present
index[grp] = groupCount
@ -983,26 +925,28 @@ else:
if e%1000 == 0:
bg.set_message('scan elem %i...'%e)
myElemID = p.element_id(e)
myIpCoordinates = ipCoords(p.element(e).type, map(lambda node: [node.x, node.y, node.z], map(p.node, map(p.node_sequence, p.element(e).items))))
myIpCoordinates = ipCoords(p.element(e).type, map(lambda node: [node.x, node.y, node.z],
map(p.node, map(p.node_sequence, p.element(e).items))))
myIpIDs = ipIDs(p.element(e).type)
Nips = len(myIpIDs)
myNodeIDs = p.element(e).items[:Nips]
for n in range(Nips):
myIpID = myIpIDs[n]
myNodeID = myNodeIDs[n]
for g in range(('GrainCount' in stat['IndexOfLabel'] and int(p.element_scalar(e, stat['IndexOfLabel']['GrainCount'])[0].value))
or 1):
for g in range(('GrainCount' in stat['IndexOfLabel']\
and int(p.element_scalar(e, stat['IndexOfLabel']['GrainCount'])[0].value))\
or 1):
myGrainID = g + 1
# --- filter valid locations
filter = substituteLocation(options.filter, [myElemID,myNodeID,myIpID,myGrainID], myIpCoordinates[n]) # generates an expression that is only true for the locations specified by options.filter
# generates an expression that is only true for the locations specified by options.filter
filter = substituteLocation(options.filter, [myElemID,myNodeID,myIpID,myGrainID], myIpCoordinates[n])
if filter != '' and not eval(filter): # for all filter expressions that are not true:...
continue # ... ignore this data point and continue with next
# --- group data locations
grp = substituteLocation('#'.join(options.sep), [myElemID,myNodeID,myIpID,myGrainID], myIpCoordinates[n]) # generates a unique key for a group of separated data based on the separation criterium for the location
# generates 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], myIpCoordinates[n])
if grp not in index: # create a new group if not yet present
index[grp] = groupCount
@ -1059,11 +1003,8 @@ fileOpen = False
assembleHeader = True
header = []
standard = ['inc'] + \
{True: ['time'],
False:[]}[options.time] + \
['elem','node','ip','grain'] + \
{True: ['1_nodeinitialcoord','2_nodeinitialcoord','3_nodeinitialcoord'],
False:['1_ipinitialcoord','2_ipinitialcoord','3_ipinitialcoord']}[options.nodalScalar != []]
['time'] if options.time else [] + \
['elem','node','ip','grain','1_pos','2_pos','3_pos']
# --------------------------- loop over positions --------------------------------
@ -1104,7 +1045,8 @@ for incCount,position in enumerate(locations): # walk through locations
if fileOpen:
file.close()
fileOpen = False
outFilename = eval('"'+eval("'%%s_inc%%0%ii%%s.txt'%(math.log10(max(increments+[1]))+1)")+'"%(dirname + os.sep + options.prefix + os.path.split(filename)[1],increments[incCount],options.suffix)')
outFilename = eval('"'+eval("'%%s_inc%%0%ii%%s.txt'%(math.log10(max(increments+[1]))+1)")\
+'"%(dirname + os.sep + options.prefix + os.path.split(filename)[1],increments[incCount],options.suffix)')
else:
outFilename = '%s.txt'%(dirname + os.sep + options.prefix + os.path.split(filename)[1] + options.suffix)
@ -1128,7 +1070,8 @@ for incCount,position in enumerate(locations): # walk through locations
member += 1
if member%1000 == 0:
time_delta = ((len(locations)*memberCount)/float(member+incCount*memberCount)-1.0)*(time.time()-time_start)
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))
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
@ -1140,7 +1083,9 @@ for incCount,position in enumerate(locations): # walk through locations
else:
length = 1
content = [ p.node_scalar(p.node_sequence(n),stat['IndexOfLabel'][label]) ]
if assembleHeader: header += heading('_',[[component,''.join( label.split() )] for component in range(int(length>1),length+int(length>1))])
if assembleHeader:
header += heading('_',[[component,''.join( label.split() )]
for component in range(int(length>1),length+int(length>1))])
newby.append({'label':label,
'len':length,
'content':content })
@ -1156,7 +1101,8 @@ for incCount,position in enumerate(locations): # walk through locations
if options.elemTensor:
for label in options.elemTensor:
if assembleHeader:
header += heading('.',[[''.join( label.split() ),component] for component in ['intensity','t11','t22','t33','t12','t23','t13']])
header += heading('.',[[''.join( label.split() ),component]
for component in ['intensity','t11','t22','t33','t12','t23','t13']])
myTensor = p.element_tensor(p.element_sequence(e),stat['IndexOfLabel'][label])[n_local]
newby.append({'label':label,
'len':7,

View File

@ -1,7 +1,7 @@
#!/usr/bin/env python
# -*- coding: UTF-8 no BOM -*-
import os,sys,string
import os,sys,re
import damask
from optparse import OptionParser
@ -32,14 +32,17 @@ parser.set_defaults(label = [],
(options,filenames) = parser.parse_args()
pattern = [re.compile('^()(.+)$'), # label pattern for scalar
re.compile('^(\d+_)?(.+)$'), # label pattern for multidimension
]
# --- loop over input files -------------------------------------------------------------------------
if filenames == []: filenames = [None]
for name in filenames:
try:
table = damask.ASCIItable(name = name,
buffered = False)
try: table = damask.ASCIItable(name = name,
buffered = False)
except: continue
damask.util.report(scriptName,name)
@ -63,8 +66,9 @@ for name in filenames:
for i,index in enumerate(indices):
if index == -1: remarks.append('label {} not present...'.format(options.label[i]))
else:
m = pattern[dimensions[i]>1].match(table.labels[index]) # isolate label name
for j in xrange(dimensions[i]):
table.labels[index+j] = table.labels[index+j].replace(options.label[i],options.substitute[i])
table.labels[index+j] = table.labels[index+j].replace(m.group(2),options.substitute[i]) # replace name with substitute
if remarks != []: damask.util.croak(remarks)
if errors != []:

View File

@ -1,7 +1,7 @@
#!/usr/bin/env python
# -*- coding: UTF-8 no BOM -*-
import os,sys,string,math
import os,sys,math
import numpy as np
from optparse import OptionParser
import damask
@ -41,7 +41,7 @@ parser.set_defaults(rotation = (0.,1.,1.,1.),
(options,filenames) = parser.parse_args()
if options.vector == None and options.tensor == None:
if options.vector is None and options.tensor is None:
parser.error('no data column specified.')
toRadians = math.pi/180.0 if options.degrees else 1.0 # rescale degrees to radians
@ -107,8 +107,7 @@ for name in filenames:
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(map(float,table.data[column:column+items[datatype]['dim']])).\
reshape(items[datatype]['shape']),R.transpose())).\
reshape(items[datatype]['dim'])
reshape(items[datatype]['shape']),R.transpose())).reshape(items[datatype]['dim'])
outputAlive = table.data_write() # output processed line

View File

@ -1,7 +1,7 @@
#!/usr/bin/env python
# -*- coding: UTF-8 no BOM -*-
import os,sys,string
import os,sys
import numpy as np
from optparse import OptionParser
import damask
@ -36,7 +36,7 @@ parser.set_defaults(key = [],
(options,filenames) = parser.parse_args()
if options.keys == None:
if options.keys is None:
parser.error('No sorting column(s) specified.')
options.keys.reverse() # numpy sorts with most significant column as last

View File

@ -144,16 +144,12 @@ for file in files:
posOffset = (shift+[0.5,0.5,0.5])*dimension/resolution
elementSize = dimension/resolution*packing
elem = 1
for c in xrange(downSized[2]):
for b in xrange(downSized[1]):
for a in xrange(downSized[0]):
datavar[a,b,c,locationCol:locationCol+3] = posOffset + [a,b,c]*elementSize
datavar[a,b,c,elemCol] = elem
table.data = datavar[a,b,c,:].tolist()
table.data_write() # output processed line
elem += 1
# ------------------------------------------ output result ---------------------------------------

View File

@ -4,17 +4,15 @@
import os,string,math,sys
import numpy as np
from optparse import OptionParser
from vtk import *
import vtk
import damask
scriptName = os.path.splitext(os.path.basename(__file__))[0]
scriptID = ' '.join([scriptName,damask.version])
# -----------------------------
def getHeader(filename,sizeFastIndex,sizeSlowIndex,stepsize):
# -----------------------------
# returns header for ang file
# step size in micrometer
"""returns header for ang file step size in micrometer"""
return '\n'.join([ \
'# TEM_PIXperUM 1.000000', \
'# x-star 1.000000', \
@ -50,10 +48,7 @@ def getHeader(filename,sizeFastIndex,sizeSlowIndex,stepsize):
# -----------------------------
def positiveRadians(angle):
# -----------------------------
# returns positive angle in radians
# gets angle in degrees
"""returns positive angle in radians from angle in degrees"""
angle = math.radians(float(angle))
while angle < 0.0:
angle += 2.0 * math.pi
@ -63,14 +58,16 @@ def positiveRadians(angle):
# -----------------------------
def getDataLine(angles,x,y,validData=True):
# -----------------------------
# returns string of one line in ang file
# convention in ang file: y coordinate comes first and is fastest index
# positions in micrometer
"""
returns string of one line in ang file
convention in ang file: y coordinate comes first and is fastest index
positions in micrometer
"""
info = {True: (9999.9, 1.0, 0,99999,0.0),
False: ( -1.0,-1.0,-1, -1,1.0)}
return '%9.5f %9.5f %9.5f %12.5f %12.5f %6.1f %6.3f %2i %6i %6.3f \n'%(tuple(map(positiveRadians,angles))+(y*1e6,x*1e6)+info[validData])
return '%9.5f %9.5f %9.5f %12.5f %12.5f %6.1f %6.3f %2i %6i %6.3f \n'\
%(tuple(map(positiveRadians,angles))+(y*1e6,x*1e6)+info[validData])
@ -155,10 +152,9 @@ if options.hexagonal:
for filename in filenames:
# Read the source file
if options.verbose: sys.stdout.write("\nREADING VTK FILE\n")
reader = vtkUnstructuredGridReader()
# Read the source file
reader = vtk.vtkUnstructuredGridReader()
reader.SetFileName(filename)
reader.ReadAllScalarsOn()
reader.ReadAllVectorsOn()
@ -166,7 +162,7 @@ for filename in filenames:
undeformedMesh = reader.GetOutput()
# Get euler angles from cell data
# Get euler angles from cell data
if options.verbose: sys.stdout.write("\nGETTING EULER ANGLES\n")
angles = {}
@ -177,14 +173,14 @@ for filename in filenames:
if options.verbose: sys.stdout.write(" found scalar with name %s\n"%scalarName)
if len(angles) < 3: # found data for all three euler angles?
for label in options.eulerLabel:
if not label in angles.keys():
if label not in angles.keys():
parser.error('Could not find scalar data with name %s'%label)
# Get deformed mesh
# Get deformed mesh
if options.verbose: sys.stdout.write("\nDEFORM MESH\n")
warpVector = vtkWarpVector()
warpVector = vtk.vtkWarpVector()
undeformedMesh.GetPointData().SetActiveVectors(options.dispLabel)
warpVector.SetInput(undeformedMesh)
warpVector.Update()
@ -197,29 +193,29 @@ for filename in filenames:
sys.stdout.write(" z (% .8f % .8f)\n"%(box[4],box[5]))
# Get cell centers of deformed mesh (position of ips)
# Get cell centers of deformed mesh (position of ips)
if options.verbose: sys.stdout.write("\nGETTING CELL CENTERS OF DEFORMED MESH\n")
cellCenter = vtkCellCenters()
cellCenter = vtk.vtkCellCenters()
cellCenter.SetVertexCells(0) # do not generate vertex cells, just points
cellCenter.SetInput(deformedMesh)
cellCenter.Update()
meshIPs = cellCenter.GetOutput()
# Get outer surface of deformed mesh
# Get outer surface of deformed mesh
if options.verbose: sys.stdout.write("\nGETTING OUTER SURFACE OF DEFORMED MESH\n")
surfaceFilter = vtkDataSetSurfaceFilter()
surfaceFilter = vtk.vtkDataSetSurfaceFilter()
surfaceFilter.SetInput(deformedMesh)
surfaceFilter.Update()
surface = surfaceFilter.GetOutput()
# Get coordinate system for ang files
# z-vector is normal to slices
# x-vector corresponds to the up-direction
# "R" rotates coordinates from the mesh system into the TSL system
# Get coordinate system for ang files
# z-vector is normal to slices
# x-vector corresponds to the up-direction
# "R" rotates coordinates from the mesh system into the TSL system
if options.verbose: sys.stdout.write("\nGETTING COORDINATE SYSTEM FOR ANG FILES\n")
z = np.array(options.normal,dtype='float')
@ -235,7 +231,7 @@ for filename in filenames:
sys.stdout.write(" z (% .8f % .8f % .8f)\n"%tuple(z))
# Get bounding box in rotated system (x,y,z)
# Get bounding box in rotated system (x,y,z)
if options.verbose: sys.stdout.write("\nGETTING BOUNDING BOX IN ROTATED SYSTEM\n")
rotatedbox = [[np.inf,-np.inf] for i in range(3)] # bounding box in rotated TSL system
@ -254,8 +250,8 @@ for filename in filenames:
sys.stdout.write(" z (% .8f % .8f)\n"%tuple(rotatedbox[2]))
# Correct bounding box so that a multiplicity of the resolution fits into it
# and get number of points and extent in each (rotated) axis direction
# Correct bounding box so that a multiplicity of the resolution fits into it
# and get number of points and extent in each (rotated) axis direction
if options.verbose: sys.stdout.write("\nCORRECTING EXTENT OF BOUNDING BOX IN ROTATED SYSTEM\n")
correction = []
@ -284,12 +280,12 @@ for filename in filenames:
sys.stdout.write(" z (% .8f % .8f)\n"%tuple(rotatedbox[2]))
# Generate new regular point grid for ang files
# Use "polydata" object with points as single vertices
# beware of TSL convention: y direction is fastest index
# Generate new regular point grid for ang files
# Use "polydata" object with points as single vertices
# beware of TSL convention: y direction is fastest index
if options.verbose: sys.stdout.write("\nGENERATING POINTS FOR POINT GRID")
points = vtkPoints()
points = vtk.vtkPoints()
for k in xrange(Npoints[2]):
for j in xrange(Npoints[0]):
for i in xrange(Npoints[1]): # y is fastest index
@ -309,9 +305,9 @@ for filename in filenames:
sys.stdout.write(" grid resolution: %.8f\n"%options.resolution)
if options.verbose: sys.stdout.write("\nGENERATING VERTICES FOR POINT GRID")
vertices = vtkCellArray()
vertices = vtk.vtkCellArray()
for i in xrange(totalNpoints):
vertex = vtkVertex()
vertex = vtk.vtkVertex()
vertex.GetPointIds().SetId(0,i) # each vertex consists of exactly one (index 0) point with ID "i"
vertices.InsertNextCell(vertex)
if options.verbose:
@ -319,34 +315,35 @@ for filename in filenames:
sys.stdout.flush()
if options.verbose: sys.stdout.write("\n\nGENERATING POINT GRID\n")
pointgrid = vtkPolyData()
pointgrid = vtk.vtkPolyData()
pointgrid.SetPoints(points)
pointgrid.SetVerts(vertices)
pointgrid.Update()
# Find out which points reside inside mesh geometry
# Find out which points reside inside mesh geometry
if options.verbose: sys.stdout.write("\nIDENTIFYING POINTS INSIDE MESH GEOMETRY\n")
enclosedPoints = vtkSelectEnclosedPoints()
enclosedPoints = vtk.vtkSelectEnclosedPoints()
enclosedPoints.SetSurface(surface)
enclosedPoints.SetInput(pointgrid)
enclosedPoints.Update()
# Build kdtree from mesh IPs and match mesh IPs to point grid
# Build kdtree from mesh IPs and match mesh IPs to point grid
if options.verbose: sys.stdout.write("\nBUILDING MAPPING OF GRID POINTS")
kdTree = vtkKdTree()
kdTree = vtk.vtkKdTree()
kdTree.BuildLocatorFromPoints(meshIPs.GetPoints())
gridToMesh = []
ids = vtkIdList()
ids = vtk.vtkIdList()
NenclosedPoints = 0
for i in range(pointgrid.GetNumberOfPoints()):
gridToMesh.append([])
if enclosedPoints.IsInside(i):
NenclosedPoints += 1
kdTree.FindClosestNPoints(options.interpolation,pointgrid.GetPoint(i),ids) # here one could use faster(?) "FindClosestPoint" if only first nearest neighbor required
# here one could use faster(?) "FindClosestPoint" if only first nearest neighbor required
kdTree.FindClosestNPoints(options.interpolation,pointgrid.GetPoint(i),ids)
for j in range(ids.GetNumberOfIds()):
gridToMesh[-1].extend([ids.GetId(j)])
if options.verbose:
@ -358,7 +355,7 @@ for filename in filenames:
# ITERATE OVER SLICES AND CREATE ANG FILE
# ITERATE OVER SLICES AND CREATE ANG FILE
if options.verbose:
sys.stdout.write("\nWRITING OUT ANG FILES\n")
@ -404,13 +401,13 @@ for filename in filenames:
angfile.write(getDataLine(interpolatedPhi,x,y,enclosedPoints.IsInside(i)))
# Visualize slices
# Visualize slices
if options.visualize:
meshMapper = vtkDataSetMapper()
meshMapper = vtk.vtkDataSetMapper()
meshMapper.SetInput(surface)
meshMapper.ScalarVisibilityOff() # do not use scalar data for coloring
meshActor = vtkActor()
meshActor = vtk.vtkActor()
meshActor.SetMapper(meshMapper)
meshActor.GetProperty().SetOpacity(0.2)
meshActor.GetProperty().SetColor(1.0,1.0,0)
@ -418,43 +415,43 @@ for filename in filenames:
# meshActor.GetProperty().SetEdgeColor(1,1,0.5)
# meshActor.GetProperty().EdgeVisibilityOn()
boxpoints = vtkPoints()
boxpoints = vtk.vtkPoints()
for n in range(8):
P = [rotatedbox[0][(n/1)%2],
rotatedbox[1][(n/2)%2],
rotatedbox[2][(n/4)%2]]
boxpoints.InsertNextPoint(list(np.dot(R.T,np.array(P))))
box = vtkHexahedron()
box = vtk.vtkHexahedron()
for n,i in enumerate([0,1,3,2,4,5,7,6]):
box.GetPointIds().SetId(n,i)
boxgrid = vtkUnstructuredGrid()
boxgrid = vtk.vtkUnstructuredGrid()
boxgrid.SetPoints(boxpoints)
boxgrid.InsertNextCell(box.GetCellType(), box.GetPointIds())
boxsurfaceFilter = vtkDataSetSurfaceFilter()
boxsurfaceFilter = vtk.vtkDataSetSurfaceFilter()
boxsurfaceFilter.SetInput(boxgrid)
boxsurfaceFilter.Update()
boxsurface = boxsurfaceFilter.GetOutput()
boxMapper = vtkDataSetMapper()
boxMapper = vtk.vtkDataSetMapper()
boxMapper.SetInput(boxsurface)
boxActor = vtkActor()
boxActor = vtk.vtkActor()
boxActor.SetMapper(boxMapper)
boxActor.GetProperty().SetLineWidth(2.0)
boxActor.GetProperty().SetRepresentationToWireframe()
gridMapper = vtkDataSetMapper()
gridMapper = vtk.vtkDataSetMapper()
gridMapper.SetInput(pointgrid)
gridActor = vtkActor()
gridActor = vtk.vtkActor()
gridActor.SetMapper(gridMapper)
gridActor.GetProperty().SetColor(0,0,0)
gridActor.GetProperty().SetPointSize(3)
renderer = vtkRenderer()
renderWindow = vtkRenderWindow()
renderer = vtk.vtkRenderer()
renderWindow = vtk.vtkRenderWindow()
renderWindow.FullScreenOn()
renderWindow.AddRenderer(renderer)
renderWindowInteractor = vtkRenderWindowInteractor()
renderWindowInteractor = vtk.vtkRenderWindowInteractor()
renderWindowInteractor.SetRenderWindow(renderWindow)
renderer.AddActor(meshActor)
renderer.AddActor(boxActor)
@ -462,6 +459,6 @@ for filename in filenames:
renderer.SetBackground(1,1,1)
renderWindow.Render()
renderWindowInteractor.SetInteractorStyle(vtkInteractorStyleTrackballCamera())
renderWindowInteractor.SetInteractorStyle(vtk.vtkInteractorStyleTrackballCamera())
renderWindowInteractor.Start()

View File

@ -1,7 +1,7 @@
#!/usr/bin/env python
# -*- coding: UTF-8 no BOM -*-
import os,string,glob,re
import os,glob,re
import damask
from optparse import OptionParser
@ -10,7 +10,6 @@ scriptID = ' '.join([scriptName,damask.version])
# -----------------------------
def findTag(filename,tag):
# -----------------------------
with open(filename,'r') as myfile:
mypattern = re.compile(str(tag))

View File

@ -1,8 +1,9 @@
#!/usr/bin/env python
# -*- coding: UTF-8 no BOM -*-
import os,sys,string,vtk
import os,vtk
import damask
from collections import defaultdict
from optparse import OptionParser
scriptName = os.path.splitext(os.path.basename(__file__))[0]
@ -17,125 +18,157 @@ Add scalar and RGB tuples from ASCIItable to existing VTK point cloud (.vtp).
""", version = scriptID)
parser.add_option('-v', '--vtk', dest='vtk', \
parser.add_option( '--vtk',
dest = 'vtk',
type = 'string', metavar = 'string',
help = 'VTK file name')
parser.add_option( '--inplace',
dest = 'inplace',
action = 'store_true',
help = 'modify VTK file in-place')
parser.add_option('-r', '--render',
dest = 'render',
action = 'store_true',
help = 'open output in VTK render window')
parser.add_option('-s', '--scalar', dest='scalar', action='extend', \
help = 'scalar values')
parser.add_option('-v', '--vector',
dest = 'vector',
action = 'extend', metavar = '<string LIST>',
help = 'vector value label(s)')
parser.add_option('-c', '--color', dest='color', action='extend', \
help = 'RGB color tuples')
parser.set_defaults(scalar = [])
parser.set_defaults(color = [])
parser.set_defaults(scalar = [],
vector = [],
color = [],
inplace = False,
render = False,
)
(options, filenames) = parser.parse_args()
datainfo = { # list of requested labels per datatype
'scalar': {'len':1,
'label':[]},
'color': {'len':3,
'label':[]},
}
if not os.path.exists(options.vtk):
parser.error('VTK file does not exist'); sys.exit()
if not options.vtk: parser.error('No VTK file specified.')
if not os.path.exists(options.vtk): parser.error('VTK file does not exist.')
reader = vtk.vtkXMLPolyDataReader()
reader.SetFileName(options.vtk)
reader.Update()
Npoints = reader.GetNumberOfPoints()
Ncells = reader.GetNumberOfCells()
Npoints = reader.GetNumberOfPoints()
Ncells = reader.GetNumberOfCells()
Nvertices = reader.GetNumberOfVerts()
Polydata = reader.GetOutput()
Polydata = reader.GetOutput()
if Npoints != Ncells or Npoints != Nvertices:
parser.error('Number of points, cells, and vertices in VTK differ from each other'); sys.exit()
if options.scalar != None: datainfo['scalar']['label'] += options.scalar
if options.color != None: datainfo['color']['label'] += options.color
parser.error('Number of points, cells, and vertices in VTK differ from each other.')
# ------------------------------------------ setup file handles ---------------------------------------
damask.util.croak('{}: {} points, {} vertices, and {} cells...'.format(options.vtk,Npoints,Nvertices,Ncells))
files = []
if filenames == []:
files.append({'name':'STDIN', 'input':sys.stdin, 'output':sys.stdout, 'croak':sys.stderr})
else:
for name in filenames:
if os.path.exists(name):
files.append({'name':name, 'input':open(name), 'output':sys.stderr, 'croak':sys.stderr})
# --- loop over input files -------------------------------------------------------------------------
#--- loop over input files ------------------------------------------------------------------------
for file in files:
if file['name'] != 'STDIN': file['croak'].write('\033[1m'+scriptName+'\033[0m: '+file['name']+'\n')
else: file['croak'].write('\033[1m'+scriptName+'\033[0m\n')
if filenames == []: filenames = [None]
table = damask.ASCIItable(file['input'],file['output'],False) # make unbuffered ASCII_table
table.head_read() # read ASCII header info
for name in filenames:
try: table = damask.ASCIItable(name = name,
buffered = False,
readonly = True)
except: continue
damask.util.report(scriptName, name)
# --------------- figure out columns to process
active = {}
column = {}
# --- interpret header ----------------------------------------------------------------------------
array = {}
table.head_read()
remarks = []
errors = []
VTKarray = {}
active = defaultdict(list)
for datatype,info in datainfo.items():
for label in info['label']:
foundIt = False
for key in ['1_'+label,label]:
if key in table.labels:
foundIt = True
if datatype not in active: active[datatype] = []
if datatype not in column: column[datatype] = {}
if datatype not in array: array[datatype] = {}
active[datatype].append(label)
column[datatype][label] = table.labels.index(key) # remember columns of requested data
if datatype == 'scalar':
array[datatype][label] = vtk.vtkDoubleArray()
array[datatype][label].SetNumberOfComponents(1)
array[datatype][label].SetName(label)
elif datatype == 'color':
array[datatype][label] = vtk.vtkUnsignedCharArray()
array[datatype][label].SetNumberOfComponents(3)
array[datatype][label].SetName(label)
if not foundIt:
file['croak'].write('column %s not found...\n'%label)
for datatype,dimension,label in [['scalar',1,options.scalar],
['vector',3,options.vector],
['color',3,options.color],
]:
for i,dim in enumerate(table.label_dimension(label)):
me = label[i]
if dim == -1: remarks.append('{} "{}" not found...'.format(datatype,me))
elif dim > dimension: remarks.append('"{}" not of dimension {}...'.format(me,dimension))
else:
remarks.append('adding {} "{}"...'.format(datatype,me))
active[datatype].append(me)
if datatype in ['scalar','vector']: VTKarray[me] = vtk.vtkDoubleArray()
elif datatype == 'color': VTKarray[me] = vtk.vtkUnsignedCharArray()
VTKarray[me].SetNumberOfComponents(dimension)
VTKarray[me].SetName(label[i])
if remarks != []: damask.util.croak(remarks)
if errors != []:
damask.util.croak(errors)
table.close(dismiss = True)
continue
# ------------------------------------------ process data ---------------------------------------
while table.data_read(): # read next data line of ASCII table
while table.data_read(): # read next data line of ASCII table
for datatype,labels in active.items(): # loop over scalar,color
for label in labels: # loop over all requested items
theData = table.data[column[datatype][label]:\
column[datatype][label]+datainfo[datatype]['len']] # read strings
if datatype == 'color':
theData = map(lambda x: int(255.*float(x)),theData)
array[datatype][label].InsertNextTuple3(theData[0],theData[1],theData[2],)
elif datatype == 'scalar':
array[datatype][label].InsertNextValue(float(theData[0]))
for datatype,labels in active.items(): # loop over scalar,color
for me in labels: # loop over all requested items
theData = [table.data[i] for i in table.label_indexrange(me)] # read strings
if datatype == 'color': VTKarray[me].InsertNextTuple3(*map(lambda x: int(255.*float(x)),theData))
elif datatype == 'vector': VTKarray[me].InsertNextTuple3(*map(float,theData))
elif datatype == 'scalar': VTKarray[me].InsertNextValue(float(theData[0]))
table.input_close() # close input ASCII table
# ------------------------------------------ add data ---------------------------------------
for datatype,labels in active.items(): # loop over scalar,color
for datatype,labels in active.items(): # loop over scalar,color
if datatype == 'color':
Polydata.GetPointData().SetScalars(array[datatype][labels[0]])
Polydata.GetCellData().SetScalars(array[datatype][labels[0]])
for label in labels: # loop over all requested items
Polydata.GetPointData().AddArray(array[datatype][label])
Polydata.GetCellData().AddArray(array[datatype][label])
Polydata.GetPointData().SetScalars(VTKarray[active['color'][0]])
Polydata.GetCellData().SetScalars(VTKarray[active['color'][0]])
for me in labels: # loop over all requested items
Polydata.GetPointData().AddArray(VTKarray[me])
Polydata.GetCellData().AddArray(VTKarray[me])
Polydata.Modified()
if vtk.VTK_MAJOR_VERSION <= 5:
Polydata.Update()
if vtk.VTK_MAJOR_VERSION <= 5: Polydata.Update()
# ------------------------------------------ output result ---------------------------------------
writer = vtk.vtkXMLPolyDataWriter()
writer.SetDataModeToBinary()
writer.SetCompressorTypeToZLib()
writer.SetFileName(os.path.splitext(options.vtk)[0]+'_added.vtp')
if vtk.VTK_MAJOR_VERSION <= 5:
writer.SetInput(Polydata)
else:
writer.SetInputData(Polydata)
writer.Write()
writer = vtk.vtkXMLPolyDataWriter()
writer.SetDataModeToBinary()
writer.SetCompressorTypeToZLib()
writer.SetFileName(os.path.splitext(options.vtk)[0]+('.vtp' if options.inplace else '_added.vtp'))
if vtk.VTK_MAJOR_VERSION <= 5: writer.SetInput(Polydata)
else: writer.SetInputData(Polydata)
writer.Write()
# ------------------------------------------ render result ---------------------------------------
if options.render:
mapper = vtk.vtkDataSetMapper()
mapper.SetInputData(Polydata)
actor = vtk.vtkActor()
actor.SetMapper(mapper)
# Create the graphics structure. The renderer renders into the
# render window. The render window interactor captures mouse events
# and will perform appropriate camera or actor manipulation
# depending on the nature of the events.
ren = vtk.vtkRenderer()
renWin = vtk.vtkRenderWindow()
renWin.AddRenderer(ren)
ren.AddActor(actor)
ren.SetBackground(1, 1, 1)
renWin.SetSize(200, 200)
iren = vtk.vtkRenderWindowInteractor()
iren.SetRenderWindow(renWin)
iren.Initialize()
renWin.Render()
iren.Start()

View File

@ -1,7 +1,7 @@
#!/usr/bin/env python
# -*- coding: UTF-8 no BOM -*-
import os,sys,string,vtk
import os,vtk
import damask
from collections import defaultdict
from optparse import OptionParser
@ -30,10 +30,6 @@ parser.add_option('-r', '--render',
dest = 'render',
action = 'store_true',
help = 'open output in VTK render window')
parser.add_option('-m', '--mode',
dest = 'mode',
type = 'choice', metavar = 'string', choices = ['cell', 'point'],
help = 'cell-centered or point-centered data')
parser.add_option('-s', '--scalar',
dest = 'scalar',
action = 'extend', metavar = '<string LIST>',
@ -56,7 +52,6 @@ parser.set_defaults(scalar = [],
(options, filenames) = parser.parse_args()
if not options.mode: parser.error('No data mode specified.')
if not options.vtk: parser.error('No VTK file specified.')
if not os.path.exists(options.vtk): parser.error('VTK file does not exist.')
@ -83,9 +78,9 @@ damask.util.croak('{}: {} points and {} cells...'.format(options.vtk,Npoints,Nce
if filenames == []: filenames = [None]
for name in filenames:
try:
table = damask.ASCIItable(name = name,
buffered = False, readonly = True)
try: table = damask.ASCIItable(name = name,
buffered = False,
readonly = True)
except: continue
damask.util.report(scriptName, name)
@ -124,8 +119,11 @@ for name in filenames:
# ------------------------------------------ process data ---------------------------------------
datacount = 0
while table.data_read(): # read next data line of ASCII table
datacount += 1 # count data lines
for datatype,labels in active.items(): # loop over scalar,color
for me in labels: # loop over all requested items
theData = [table.data[i] for i in table.label_indexrange(me)] # read strings
@ -133,15 +131,25 @@ for name in filenames:
elif datatype == 'vector': VTKarray[me].InsertNextTuple3(*map(float,theData))
elif datatype == 'scalar': VTKarray[me].InsertNextValue(float(theData[0]))
table.close() # close input ASCII table
# ------------------------------------------ add data ---------------------------------------
if datacount == Npoints: mode = 'point'
elif datacount == Ncells: mode = 'cell'
else:
damask.util.croak('Data count is incompatible with grid...')
continue
damask.util.croak('{} mode...'.format(mode))
for datatype,labels in active.items(): # loop over scalar,color
if datatype == 'color':
if options.mode == 'cell': rGrid.GetCellData().SetScalars(VTKarray[active['color'][0]])
elif options.mode == 'point': rGrid.GetPointData().SetScalars(VTKarray[active['color'][0]])
if mode == 'cell': rGrid.GetCellData().SetScalars(VTKarray[active['color'][0]])
elif mode == 'point': rGrid.GetPointData().SetScalars(VTKarray[active['color'][0]])
for me in labels: # loop over all requested items
if options.mode == 'cell': rGrid.GetCellData().AddArray(VTKarray[me])
elif options.mode == 'point': rGrid.GetPointData().AddArray(VTKarray[me])
if mode == 'cell': rGrid.GetCellData().AddArray(VTKarray[me])
elif mode == 'point': rGrid.GetPointData().AddArray(VTKarray[me])
rGrid.Modified()
if vtk.VTK_MAJOR_VERSION <= 5: rGrid.Update()
@ -151,7 +159,7 @@ for name in filenames:
writer = vtk.vtkXMLRectilinearGridWriter()
writer.SetDataModeToBinary()
writer.SetCompressorTypeToZLib()
writer.SetFileName(os.path.splitext(options.vtk)[0]+('' if options.inplace else '_added.vtr'))
writer.SetFileName(os.path.splitext(options.vtk)[0]+('.vtr' if options.inplace else '_added.vtr'))
if vtk.VTK_MAJOR_VERSION <= 5: writer.SetInput(rGrid)
else: writer.SetInputData(rGrid)
writer.Write()
@ -164,10 +172,10 @@ if options.render:
actor = vtk.vtkActor()
actor.SetMapper(mapper)
# Create the graphics structure. The renderer renders into the
# render window. The render window interactor captures mouse events
# and will perform appropriate camera or actor manipulation
# depending on the nature of the events.
# Create the graphics structure. The renderer renders into the
# render window. The render window interactor captures mouse events
# and will perform appropriate camera or actor manipulation
# depending on the nature of the events.
ren = vtk.vtkRenderer()
@ -181,9 +189,6 @@ if options.render:
iren = vtk.vtkRenderWindowInteractor()
iren.SetRenderWindow(renWin)
#ren.ResetCamera()
#ren.GetActiveCamera().Zoom(1.5)
iren.Initialize()
renWin.Render()
iren.Start()

View File

@ -1,7 +1,7 @@
#!/usr/bin/env python
# -*- coding: UTF-8 no BOM -*-
import os,sys,string,vtk
import os,sys,vtk
import damask
from collections import defaultdict
from optparse import OptionParser
@ -32,7 +32,7 @@ parser.set_defaults(scalar = [],
(options, filenames) = parser.parse_args()
if options.vtk == None or not os.path.exists(options.vtk):
if options.vtk is None or not os.path.exists(options.vtk):
parser.error('VTK file does not exist')
if os.path.splitext(options.vtk)[1] == '.vtu':

View File

@ -1,7 +1,7 @@
#!/usr/bin/env python
# -*- coding: UTF-8 no BOM -*-
import os,sys,string,vtk
import os,sys,vtk
import numpy as np
import damask
from optparse import OptionParser
@ -18,12 +18,12 @@ Produce a VTK point cloud dataset based on coordinates given in an ASCIItable.
""", version = scriptID)
parser.add_option('-d', '--deformed',
dest = 'deformed',
parser.add_option('-c', '--coordinates',
dest = 'pos',
type = 'string', metavar = 'string',
help = 'deformed coordinate label [%default]')
help = 'coordinate label [%default]')
parser.set_defaults(deformed = 'ipdeformedcoord'
parser.set_defaults(pos = 'pos'
)
(options, filenames) = parser.parse_args()
@ -46,9 +46,9 @@ for name in filenames:
errors = []
remarks = []
coordDim = table.label_dimension(options.deformed)
if not 3 >= coordDim >= 1: errors.append('coordinates "{}" need to have one, two, or three dimensions.'.format(options.deformed))
elif coordDim < 3: remarks.append('appending {} dimensions to coordinates "{}"...'.format(3-coordDim,options.deformed))
coordDim = table.label_dimension(options.pos)
if not 3 >= coordDim >= 1: errors.append('coordinates "{}" need to have one, two, or three dimensions.'.format(options.pos))
elif coordDim < 3: remarks.append('appending {} dimensions to coordinates "{}"...'.format(3-coordDim,options.pos))
if remarks != []: damask.util.croak(remarks)
if errors != []:
@ -58,7 +58,7 @@ for name in filenames:
# ------------------------------------------ process data ---------------------------------------
table.data_readArray(options.deformed)
table.data_readArray(options.pos)
if len(table.data.shape) < 2: table.data.shape += (1,) # expand to 2D shape
if table.data.shape[1] < 3:
table.data = np.hstack((table.data,
@ -86,8 +86,8 @@ for name in filenames:
(directory,filename) = os.path.split(name)
writer.SetDataModeToBinary()
writer.SetCompressorTypeToZLib()
writer.SetFileName(os.path.join(directory,os.path.splitext(filename)[0]
+'.'+writer.GetDefaultFileExtension()))
writer.SetFileName(os.path.join(directory,os.path.splitext(filename)[0]\
+'.'+writer.GetDefaultFileExtension()))
else:
writer = vtk.vtkDataSetWriter()
writer.WriteToOutputStringOn()
@ -96,6 +96,6 @@ for name in filenames:
if vtk.VTK_MAJOR_VERSION <= 5: writer.SetInput(Polydata)
else: writer.SetInputData(Polydata)
writer.Write()
if name == None: sys.stdout.write(writer.GetOutputString()[0:writer.GetOutputStringLength()])
if name is None: sys.stdout.write(writer.GetOutputString()[0:writer.GetOutputStringLength()])
table.close()

View File

@ -24,11 +24,11 @@ parser.add_option('-m', '--mode',
type = 'choice', choices = ['cell','point'],
help = 'cell-centered or point-centered coordinates ')
parser.add_option('-c', '--coordinates',
dest = 'position',
dest = 'coords',
type = 'string', metavar = 'string',
help = 'coordinate label [%default]')
parser.set_defaults(position ='ipinitialcoord',
mode ='cell'
parser.set_defaults(coords = 'pos',
mode = 'cell'
)
(options, filenames) = parser.parse_args()
@ -38,9 +38,9 @@ parser.set_defaults(position ='ipinitialcoord',
if filenames == []: filenames = [None]
for name in filenames:
try:
table = damask.ASCIItable(name = name,
buffered = False, readonly = True)
try: table = damask.ASCIItable(name = name,
buffered = False,
readonly = True)
except: continue
damask.util.report(scriptName,name)
@ -48,10 +48,13 @@ for name in filenames:
table.head_read()
errors = []
if table.label_dimension(options.position) != 3:
errors.append('coordinates {} are not a vector.'.format(options.position))
remarks = []
errors = []
coordDim = table.label_dimension(options.coords)
if not 3 >= coordDim >= 1: errors.append('coordinates "{}" need to have one, two, or three dimensions.'.format(options.coords))
elif coordDim < 3: remarks.append('appending {} dimensions to coordinates "{}"...'.format(3-coordDim,options.coords))
if remarks != []: damask.util.croak(remarks)
if errors != []:
damask.util.croak(errors)
table.close(dismiss=True)
@ -59,7 +62,12 @@ for name in filenames:
# --------------- figure out size and grid ---------------------------------------------------------
table.data_readArray(options.position)
table.data_readArray(options.coords)
if len(table.data.shape) < 2: table.data.shape += (1,) # expand to 2D shape
if table.data.shape[1] < 3:
table.data = np.hstack((table.data,
np.zeros((table.data.shape[0],
3-table.data.shape[1]),dtype='f'))) # fill coords up to 3D with zeros
coords = [np.unique(table.data[:,i]) for i in xrange(3)]
if options.mode == 'cell':
@ -101,7 +109,7 @@ for name in filenames:
writer.SetDataModeToBinary()
writer.SetCompressorTypeToZLib()
writer.SetFileName(os.path.join(directory,os.path.splitext(filename)[0] \
+'_{}({})'.format(options.position, options.mode) \
+'_{}({})'.format(options.coords, options.mode) \
+'.'+writer.GetDefaultFileExtension()))
else:
writer = vtk.vtkDataSetWriter()
@ -111,6 +119,6 @@ for name in filenames:
if vtk.VTK_MAJOR_VERSION <= 5: writer.SetInput(rGrid)
else: writer.SetInputData(rGrid)
writer.Write()
if name == None: sys.stdout.write(writer.GetOutputString()[0:writer.GetOutputStringLength()])
if name is None: sys.stdout.write(writer.GetOutputString()[0:writer.GetOutputStringLength()])
table.close()

View File

@ -1,10 +1,10 @@
#!/usr/bin/env python
# -*- coding: UTF-8 no BOM -*-
import os,sys,string,shutil
import os,sys,shutil
import damask
from optparse import OptionParser
from vtk import *
import vtk
scriptName = os.path.splitext(os.path.basename(__file__))[0]
scriptID = ' '.join([scriptName,damask.version])
@ -44,18 +44,16 @@ for filename in filenames:
for filename in filenames:
# Read the source file
sys.stdout.write('read file "%s" ...'%filename)
sys.stdout.flush()
suffix = os.path.splitext(filename)[1]
if suffix == '.vtk':
reader = vtkUnstructuredGridReader()
reader = vtk.vtkUnstructuredGridReader()
reader.ReadAllScalarsOn()
reader.ReadAllVectorsOn()
reader.ReadAllTensorsOn()
elif suffix == '.vtu':
reader = vtkXMLUnstructuredGridReader()
reader = vtk.vtkXMLUnstructuredGridReader()
else:
parser.error('filetype "%s" not supported'%suffix)
reader.SetFileName(filename)
@ -65,7 +63,7 @@ for filename in filenames:
sys.stdout.flush()
# Read the scalar data
# Read the scalar data
scalarData = {}
scalarsToBeRemoved = []
@ -83,19 +81,18 @@ for filename in filenames:
scalarsToBeRemoved.append(scalarName)
for scalarName in scalarsToBeRemoved:
uGrid.GetCellData().RemoveArray(scalarName)
# uGrid.UpdateData()
sys.stdout.write('\rread scalar data done\n')
sys.stdout.flush()
# Convert the scalar data to vector data
# Convert the scalar data to vector data
NscalarData = len(scalarData)
for n,label in enumerate(scalarData):
sys.stdout.write("\rconvert to vector data %d%%" %(100*n/NscalarData))
sys.stdout.flush()
Nvalues = scalarData[label][0].GetNumberOfTuples()
vectorData = vtkDoubleArray()
vectorData = vtk.vtkDoubleArray()
vectorData.SetName(label)
vectorData.SetNumberOfComponents(3) # set this before NumberOfTuples !!!
vectorData.SetNumberOfTuples(Nvalues)
@ -103,16 +100,15 @@ for filename in filenames:
for j in range(3):
vectorData.SetComponent(i,j,scalarData[label][j].GetValue(i))
uGrid.GetCellData().AddArray(vectorData)
# uGrid.GetCellData().SetActiveVectors(label)
sys.stdout.write('\rconvert to vector data done\n')
# Write to new vtk file
# Write to new vtk file
outfilename = os.path.splitext(filename)[0]+'.vtu'
sys.stdout.write('write to file "%s" ...'%outfilename)
sys.stdout.flush()
writer = vtkXMLUnstructuredGridWriter()
writer = vtk.vtkXMLUnstructuredGridWriter()
writer.SetFileName(outfilename+'_tmp')
writer.SetDataModeToAscii()
writer.SetInput(uGrid)

View File

@ -48,9 +48,10 @@ for name in filenames:
# --------------- interprete header -----------------------------------------------------------------
table.head_read()
errors=[]
if table.label_dimension(options.deformed) != 3: errors.append('columns "{}" have dimension {}'.format(options.deformed,
table.label_dimension(options.deformed)))
if table.label_dimension(options.coords) != 3: errors.append('coordinates {} are not a vector.'.format(options.coords))
if table.label_dimension(options.deformed) != 3:
errors.append('columns "{}" have dimension {}'.format(options.deformed,table.label_dimension(options.deformed)))
if table.label_dimension(options.coords) != 3:
errors.append('coordinates {} are not a vector.'.format(options.coords))
table.data_readArray([options.coords,options.deformed])
@ -66,7 +67,7 @@ for name in filenames:
max(map(float,coords[2].keys()))-min(map(float,coords[2].keys())),\
],'d') # size from bounding box, corrected for cell-centeredness
size = np.where(grid > 1, size, min(size[grid > 1]/grid[grid > 1])) # spacing for grid==1 equal to smallest among other spacings
size = np.where(grid > 1, size, min(size[grid > 1]/grid[grid > 1])) # spacing for grid==1 set to smallest among other spacings
# ------------------------------------------ process data ---------------------------------------
hexPoints = np.array([[-1,-1,-1],
@ -101,8 +102,8 @@ for name in filenames:
(directory,filename) = os.path.split(name)
writer.SetDataModeToBinary()
writer.SetCompressorTypeToZLib()
writer.SetFileName(os.path.join(directory,os.path.splitext(filename)[0]
+'.'+writer.GetDefaultFileExtension()))
writer.SetFileName(os.path.join(directory,os.path.splitext(filename)[0]\
+'.'+writer.GetDefaultFileExtension()))
else:
writer = vtk.vtkDataSetWriter()
writer.WriteToOutputStringOn()
@ -111,7 +112,7 @@ for name in filenames:
if vtk.VTK_MAJOR_VERSION <= 5: writer.SetInput(uGrid)
else: writer.SetInputData(uGrid)
writer.Write()
if name == None: sys.stdout.write(writer.GetOutputString()[0:writer.GetOutputStringLength()])
if name is None: sys.stdout.write(writer.GetOutputString()[0:writer.GetOutputStringLength()])
table.close() # close input ASCII table

View File

@ -1,7 +1,7 @@
#!/usr/bin/python
# -*- coding: UTF-8 no BOM -*-
import os,string,sys,re
import os,sys
from optparse import OptionParser
import numpy as np
import damask
@ -73,7 +73,7 @@ for file in files:
for iPhi1 in range(nPhi1):
for iPHI in range(nPHI):
for iPhi2 in range(nPhi2):
ODF[iPhi1,iPHI,iPhi2] = float(line.split()[3])*0.125 # extract intensity (in column 4) and weight by 1/8 (since we convert from the 8 corners to the center later on)
ODF[iPhi1,iPHI,iPhi2] = float(line.split()[3])*0.125 # extract intensity (in column 4) and weight by 1/8
line = file['input'].readline()
for iPhi1 in range(nPhi1-1):

View File

@ -1,16 +1,7 @@
#!/usr/bin/env python
# -*- coding: UTF-8 no BOM -*-
'''
Writes meaningful labels to the Abaqus input file (*.inp)
based on the files
<modelname_jobname>.output<Homogenization/Crystallite/Constitutive>
that are written during the first run of the model.
See Abaqus Keyword Reference Manual (AKRM) *DEPVAR for details.
Original script: marc_addUserOutput.py modified by Benjamin Bode
'''
import sys,os,re,string
import sys,os,re
from optparse import OptionParser
import damask
@ -19,7 +10,6 @@ scriptID = ' '.join([scriptName,damask.version])
# -----------------------------
def ParseOutputFormat(filename,what,me):
# -----------------------------
format = {'outputs':{},'specials':{'brothers':[]}}
outputmetafile = filename+'.output'+what
@ -120,7 +110,7 @@ for file in files:
for what in me:
outputFormat[what] = ParseOutputFormat(formatFile,what,me[what])
if not '_id' in outputFormat[what]['specials']:
if '_id' not in outputFormat[what]['specials']:
print "'%s' not found in <%s>"%(me[what],what)
print '\n'.join(map(lambda x:' '+x,outputFormat[what]['specials']['brothers']))
sys.exit(1)
@ -164,19 +154,14 @@ for file in files:
if m:
lastSection = thisSection
thisSection = m.group(1)
#Abaqus keyword can be upper or lower case
if (lastSection.upper() == '*DEPVAR' and thisSection.upper() == '*USER'):
#Abaqus SDVs are named SDV1...SDVn if no specific name is given
#Abaqus needs total number of SDVs in the line after *Depvar keyword
if (lastSection.upper() == '*DEPVAR' and thisSection.upper() == '*USER'): #Abaqus keyword can be upper or lower case
if options.number > 0:
#number of SDVs
output.write('%i\n'%options.number)
output.write('%i\n'%options.number) #Abaqus needs total number of SDVs in the line after *Depvar keyword
else:
#number of SDVs
output.write('%i\n'%len(UserVars))
#index,output variable key,output variable description
for i in range(len(UserVars)):
output.write('%i,"%i%s","%i%s"\n'%(i+1,0,UserVars[i],0,UserVars[i]))
output.write('%i,"%i%s","%i%s"\n'%(i+1,0,UserVars[i],0,UserVars[i])) #index,output variable key,output variable description
if (thisSection.upper() != '*DEPVAR' or not re.match('\s*\d',line)):
output.write(line)
output.close()

View File

@ -1,7 +1,7 @@
#!/usr/bin/env python
# -*- coding: UTF-8 no BOM -*-
import os,sys,math,string
import os,sys,math
import numpy as np
from optparse import OptionParser
import damask
@ -114,7 +114,7 @@ for name in filenames:
microstructure = microstructure.reshape(info['grid'],order='F')
if options.dimension != None:
if options.dimension is not None:
mask = (np.array(options.dimension) < 0).astype(float) # zero where positive dimension, otherwise one
dim = abs(np.array(options.dimension)) # dimensions of primitive body
pos = np.zeros(3,dtype='float')
@ -134,10 +134,9 @@ for name in filenames:
# --- report ---------------------------------------------------------------------------------------
if ( newInfo['microstructures'] != info['microstructures']):
damask.util.croak('--> microstructures: %i'%newInfo['microstructures'])
remarks = []
if ( newInfo['microstructures'] != info['microstructures']): remarks.append('--> microstructures: %i'%newInfo['microstructures'])
if remarks != []: damask.util.croak(remarks)
#--- write header ---------------------------------------------------------------------------------

View File

@ -1,7 +1,7 @@
#!/usr/bin/env python
# -*- coding: UTF-8 no BOM -*-
import os,sys,math,string
import os,sys,math
import numpy as np
from optparse import OptionParser
import damask
@ -28,24 +28,32 @@ parser.add_option('-o', '--offset',
help = 'a,b,c offset from old to new origin of grid [%default]')
parser.add_option('-f', '--fill',
dest = 'fill',
type = 'int', metavar = 'int',
type = 'float', metavar = 'float',
help = '(background) canvas grain index. "0" selects maximum microstructure index + 1 [%default]')
parser.add_option('--float',
dest = 'real',
action = 'store_true',
help = 'input data is float [%default]')
parser.set_defaults(grid = ['0','0','0'],
offset = (0,0,0),
fill = 0,
real = False,
)
(options, filenames) = parser.parse_args()
datatype = 'f' if options.real else 'i'
# --- loop over input files -------------------------------------------------------------------------
if filenames == []: filenames = [None]
for name in filenames:
try:
table = damask.ASCIItable(name = name,
buffered = False, labeled = False)
try: table = damask.ASCIItable(name = name,
buffered = False,
labeled = False)
except: continue
damask.util.report(scriptName,name)
@ -71,7 +79,7 @@ for name in filenames:
# --- read data ------------------------------------------------------------------------------------
microstructure = table.microstructure_read(info['grid']).reshape(info['grid'],order='F') # read microstructure
microstructure = table.microstructure_read(info['grid'],datatype).reshape(info['grid'],order='F') # read microstructure
# --- do work ------------------------------------------------------------------------------------
@ -81,11 +89,12 @@ for name in filenames:
'microstructures': 0,
}
newInfo['grid'] = np.array([int(o*float(n.translate(None,'xX'))) if n[-1].lower() == 'x' else int(n) for o,n in zip(info['grid'],options.grid)],'i')
newInfo['grid'] = np.array([int(o*float(n.translate(None,'xX'))) if n[-1].lower() == 'x'\
else int(n) for o,n in zip(info['grid'],options.grid)],'i')
newInfo['grid'] = np.where(newInfo['grid'] > 0, newInfo['grid'],info['grid'])
microstructure_cropped = np.zeros(newInfo['grid'],'i')
microstructure_cropped.fill(options.fill if options.fill > 0 else microstructure.max()+1)
microstructure_cropped = np.zeros(newInfo['grid'],datatype)
microstructure_cropped.fill(options.fill if options.real or options.fill > 0 else microstructure.max()+1)
xindex = list(set(xrange(options.offset[0],options.offset[0]+newInfo['grid'][0])) & \
set(xrange(info['grid'][0])))
yindex = list(set(xrange(options.offset[1],options.offset[1]+newInfo['grid'][1])) & \
@ -143,7 +152,7 @@ for name in filenames:
"origin\tx {origin[0]}\ty {origin[1]}\tz {origin[2]}".format(origin=newInfo['origin']),
"homogenization\t{homog}".format(homog=info['homogenization']),
"microstructures\t{microstructures}".format(microstructures=newInfo['microstructures']),
extra_header
extra_header
])
table.labels_clear()
table.head_write()
@ -151,9 +160,9 @@ for name in filenames:
# --- write microstructure information ------------------------------------------------------------
formatwidth = int(math.floor(math.log10(microstructure_cropped.max())+1))
format = '%g' if options.real else '%{}i'.format(int(math.floor(math.log10(microstructure_cropped.max())+1)))
table.data = microstructure_cropped.reshape((newInfo['grid'][0],newInfo['grid'][1]*newInfo['grid'][2]),order='F').transpose()
table.data_writeArray('%%%ii'%(formatwidth),delimiter=' ')
table.data_writeArray(format,delimiter=' ')
# --- output finalization --------------------------------------------------------------------------

View File

@ -1,7 +1,7 @@
#!/usr/bin/env python
# -*- coding: UTF-8 no BOM -*-
import os,sys,string,vtk
import os,sys,vtk
import numpy as np
from optparse import OptionParser
import damask
@ -54,12 +54,25 @@ for name in filenames:
errors = []
if np.any(info['grid'] < 1): errors.append('invalid grid a b c.')
if np.any(info['size'] <= 0.0): errors.append('invalid size x y z.')
#--- read microstructure information --------------------------------------------------------------
if options.data:
microstructure,ok = table.microstructure_read(info['grid'],strict = True) # read microstructure
if ok:
structure = vtk.vtkIntArray()
structure.SetName('Microstructures')
for idx in microstructure: structure.InsertNextValue(idx)
else: errors.append('mismatch between data and grid dimension.')
if errors != []:
damask.util.croak(errors)
table.close(dismiss = True)
continue
# --- generate VTK rectilinear grid --------------------------------------------------------------------------------
# --- generate VTK rectilinear grid ---------------------------------------------------------------
grid = vtk.vtkRectilinearGrid()
grid.SetDimensions([x+1 for x in info['grid']])
@ -72,18 +85,8 @@ for name in filenames:
elif i == 1: grid.SetYCoordinates(temp)
elif i == 2: grid.SetZCoordinates(temp)
#--- read microstructure information --------------------------------------------------------------
if options.data:
microstructure = table.microstructure_read(info['grid']) # read microstructure
structure = vtk.vtkIntArray()
structure.SetName('Microstructures')
for idx in microstructure:
structure.InsertNextValue(idx)
grid.GetCellData().AddArray(structure)
if options.data: grid.GetCellData().AddArray(structure)
# --- write data -----------------------------------------------------------------------------------
if name:
@ -91,8 +94,7 @@ for name in filenames:
(directory,filename) = os.path.split(name)
writer.SetDataModeToBinary()
writer.SetCompressorTypeToZLib()
writer.SetFileName(os.path.join(directory,os.path.splitext(filename)[0]
+'.'+writer.GetDefaultFileExtension()))
writer.SetFileName(os.path.join(directory,os.path.splitext(filename)[0]+'.'+writer.GetDefaultFileExtension()))
else:
writer = vtk.vtkDataSetWriter()
writer.WriteToOutputStringOn()
@ -101,6 +103,6 @@ for name in filenames:
if vtk.VTK_MAJOR_VERSION <= 5: writer.SetInput(grid)
else: writer.SetInputData(grid)
writer.Write()
if name == None: sys.stdout.write(writer.GetOutputString()[0:writer.GetOutputStringLength()])
if name is None: sys.stdout.write(writer.GetOutputString()[0:writer.GetOutputStringLength()])
table.close()

View File

@ -1,20 +1,17 @@
#!/usr/bin/env python
# -*- coding: UTF-8 no BOM -*-
import os,sys,string,math
import os,sys,math
import numpy as np
import damask
from scipy import ndimage
from optparse import OptionParser
from collections import defaultdict
scriptName = os.path.splitext(os.path.basename(__file__))[0]
scriptID = ' '.join([scriptName,damask.version])
def mostFrequent(arr):
d = defaultdict(int)
for i in arr: d[i] += 1
return sorted(d.iteritems(), key=lambda x: x[1], reverse=True)[0][0] # return value of most frequent microstructure
return np.argmax(np.bincount(arr))
#--------------------------------------------------------------------------------------------------
@ -43,10 +40,9 @@ parser.set_defaults(stencil = 3,
if filenames == []: filenames = [None]
for name in filenames:
try:
table = damask.ASCIItable(name = name,
buffered = False,
labeled = False)
try: table = damask.ASCIItable(name = name,
buffered = False,
labeled = False)
except: continue
damask.util.report(scriptName,name)
@ -72,7 +68,7 @@ for name in filenames:
# --- read data ------------------------------------------------------------------------------------
microstructure = table.microstructure_read(info['grid']).reshape(info['grid'],order='F') # read microstructure
microstructure = table.microstructure_read(info['grid']).reshape(info['grid'],order='F') # read microstructure
# --- do work ------------------------------------------------------------------------------------

Some files were not shown because too many files have changed in this diff Show More