2018-11-17 12:42:12 +05:30
|
|
|
#!/usr/bin/env python3
|
2014-08-29 00:20:48 +05:30
|
|
|
|
2019-05-25 14:15:58 +05:30
|
|
|
import os
|
|
|
|
import sys
|
|
|
|
from io import StringIO
|
|
|
|
from optparse import OptionParser
|
2014-08-29 00:20:48 +05:30
|
|
|
|
2019-05-27 00:06:41 +05:30
|
|
|
import numpy as np
|
|
|
|
|
|
|
|
import damask
|
|
|
|
|
2019-05-31 13:57:26 +05:30
|
|
|
|
2016-01-27 22:36:00 +05:30
|
|
|
scriptName = os.path.splitext(os.path.basename(__file__))[0]
|
|
|
|
scriptID = ' '.join([scriptName,damask.version])
|
2014-08-29 00:20:48 +05:30
|
|
|
|
2019-05-27 00:06:41 +05:30
|
|
|
|
2014-08-29 00:20:48 +05:30
|
|
|
#--------------------------------------------------------------------------------------------------
|
|
|
|
# MAIN
|
|
|
|
#--------------------------------------------------------------------------------------------------
|
|
|
|
|
2019-05-27 00:06:41 +05:30
|
|
|
parser = OptionParser(option_class=damask.extendableOption, usage='%prog options [geomfile(s)]', description = """
|
|
|
|
Inserts a primitive geometric object at a given position.
|
2019-05-29 03:15:17 +05:30
|
|
|
These objects can be boxes, cylinders, or ellipsoids.
|
2014-11-07 16:43:14 +05:30
|
|
|
|
|
|
|
""", version = scriptID)
|
2014-08-29 00:20:48 +05:30
|
|
|
|
2019-05-27 00:06:41 +05:30
|
|
|
parser.add_option('-c', '--center',
|
2019-05-30 17:37:49 +05:30
|
|
|
dest='center',
|
2019-03-10 00:48:28 +05:30
|
|
|
type='float', nargs = 3, metavar=' '.join(['float']*3),
|
2014-08-29 00:20:48 +05:30
|
|
|
help='a,b,c origin of primitive %default')
|
2019-05-27 00:06:41 +05:30
|
|
|
parser.add_option('-d', '--dimension',
|
|
|
|
dest='dimension',
|
2019-03-10 00:48:28 +05:30
|
|
|
type='float', nargs = 3, metavar=' '.join(['float']*3),
|
2019-05-27 00:06:41 +05:30
|
|
|
help='a,b,c extension of hexahedral box')
|
|
|
|
parser.add_option('-e', '--exponent',
|
|
|
|
dest='exponent',
|
2019-03-10 00:48:28 +05:30
|
|
|
type='float', nargs = 3, metavar=' '.join(['float']*3),
|
2019-05-29 11:08:11 +05:30
|
|
|
help='i,j,k exponents for axes: '+
|
|
|
|
'0 gives octahedron (|x|^(2^0) + |y|^(2^0) + |z|^(2^0) < 1), '+
|
|
|
|
'1 gives a sphere (|x|^(2^1) + |y|^(2^1) + |z|^(2^1) < 1), '+
|
|
|
|
'large values produce boxes, negative turn concave.')
|
2019-05-27 00:06:41 +05:30
|
|
|
parser.add_option('-f', '--fill',
|
|
|
|
dest='fill',
|
|
|
|
type='float', metavar = 'int',
|
|
|
|
help='microstructure index to fill primitive, defaults to max microstructure index + 1')
|
|
|
|
parser.add_option('-q', '--quaternion',
|
|
|
|
dest='quaternion',
|
2019-03-10 00:48:28 +05:30
|
|
|
type='float', nargs = 4, metavar=' '.join(['float']*4),
|
2014-08-29 00:20:48 +05:30
|
|
|
help = 'rotation of primitive as quaternion')
|
2019-05-27 00:06:41 +05:30
|
|
|
parser.add_option('-a', '--angleaxis',
|
|
|
|
dest='angleaxis',
|
|
|
|
type=float, nargs = 4, metavar=' '.join(['float']*4),
|
2019-03-10 00:48:28 +05:30
|
|
|
help = 'axis and angle to rotate primitive')
|
2019-05-27 00:06:41 +05:30
|
|
|
parser.add_option( '--degrees',
|
|
|
|
dest='degrees',
|
2019-03-10 00:48:28 +05:30
|
|
|
action='store_true',
|
2019-05-27 00:06:41 +05:30
|
|
|
help = 'angle is given in degrees')
|
|
|
|
parser.add_option( '--nonperiodic',
|
|
|
|
dest='periodic',
|
2019-03-10 00:48:28 +05:30
|
|
|
action='store_false',
|
2019-05-27 00:06:41 +05:30
|
|
|
help = 'wrap around edges')
|
|
|
|
parser.add_option( '--realspace',
|
|
|
|
dest='realspace',
|
2019-03-10 00:48:28 +05:30
|
|
|
action='store_true',
|
2017-08-03 21:38:51 +05:30
|
|
|
help = '-c and -d span [origin,origin+size] instead of [0,grid] coordinates')
|
2019-05-27 00:06:41 +05:30
|
|
|
parser.add_option( '--invert',
|
|
|
|
dest='inside',
|
2019-05-23 21:33:54 +05:30
|
|
|
action='store_false',
|
|
|
|
help = 'invert the volume filled by the primitive (inside/outside)')
|
2019-05-27 00:06:41 +05:30
|
|
|
|
2017-03-08 23:16:53 +05:30
|
|
|
parser.set_defaults(center = (.0,.0,.0),
|
2014-08-29 00:20:48 +05:30
|
|
|
degrees = False,
|
2017-08-03 21:42:47 +05:30
|
|
|
exponent = (20,20,20), # box shape by default
|
2017-03-08 07:07:30 +05:30
|
|
|
periodic = True,
|
2017-08-03 21:38:51 +05:30
|
|
|
realspace = False,
|
2019-05-23 21:33:54 +05:30
|
|
|
inside = True,
|
2014-08-29 00:20:48 +05:30
|
|
|
)
|
|
|
|
|
|
|
|
(options, filenames) = parser.parse_args()
|
2019-05-23 21:33:54 +05:30
|
|
|
|
2017-03-08 23:16:53 +05:30
|
|
|
if options.dimension is None:
|
2019-05-30 17:37:49 +05:30
|
|
|
parser.error('no dimension specified.')
|
2019-05-28 06:44:09 +05:30
|
|
|
if [options.angleaxis,options.quaternion].count(None) == 0:
|
2019-05-27 00:06:41 +05:30
|
|
|
parser.error('more than one rotation specified.')
|
|
|
|
|
2017-03-08 23:16:53 +05:30
|
|
|
if options.angleaxis is not None:
|
2019-03-10 12:46:01 +05:30
|
|
|
rotation = damask.Rotation.fromAxisAngle(np.array(options.angleaxis),options.degrees,normalise=True)
|
2017-03-08 23:16:53 +05:30
|
|
|
elif options.quaternion is not None:
|
2019-02-12 12:25:54 +05:30
|
|
|
rotation = damask.Rotation.fromQuaternion(options.quaternion)
|
2014-08-29 00:20:48 +05:30
|
|
|
else:
|
2019-02-12 04:41:22 +05:30
|
|
|
rotation = damask.Rotation()
|
2014-08-29 00:20:48 +05:30
|
|
|
|
2015-08-18 10:02:19 +05:30
|
|
|
|
2019-05-25 14:15:58 +05:30
|
|
|
if filenames == []: filenames = [None]
|
2014-08-29 00:20:48 +05:30
|
|
|
|
2019-05-25 14:15:58 +05:30
|
|
|
for name in filenames:
|
|
|
|
damask.util.report(scriptName,name)
|
2019-05-30 17:37:49 +05:30
|
|
|
|
2019-05-28 06:44:09 +05:30
|
|
|
geom = damask.Geom.from_file(StringIO(''.join(sys.stdin.read())) if name is None else name)
|
|
|
|
grid = geom.get_grid()
|
|
|
|
size = geom.get_size()
|
2014-08-29 00:20:48 +05:30
|
|
|
|
2019-05-29 03:15:17 +05:30
|
|
|
# scale to box of size [1.0,1.0,1.0]
|
2017-08-03 21:38:51 +05:30
|
|
|
if options.realspace:
|
2019-05-29 03:15:17 +05:30
|
|
|
center = (np.array(options.center) - geom.get_origin())/size
|
|
|
|
r = np.array(options.dimension)/size/2.0
|
|
|
|
else:
|
|
|
|
center = (np.array(options.center) + 0.5)/grid
|
|
|
|
r = np.array(options.dimension)/grid/2.0
|
2019-05-30 17:37:49 +05:30
|
|
|
|
2019-05-29 03:15:17 +05:30
|
|
|
if np.any(center<0.0) or np.any(center>=1.0): print('error')
|
2017-03-05 22:20:17 +05:30
|
|
|
|
2019-05-29 03:15:17 +05:30
|
|
|
offset = np.ones(3)*0.5 if options.periodic else center
|
|
|
|
mask = np.full(grid,False)
|
|
|
|
# High exponents can cause underflow & overflow - okay here, just compare to 1, so +infinity and 0 are fine
|
2017-03-05 22:20:17 +05:30
|
|
|
np.seterr(over='ignore', under='ignore')
|
2019-05-29 03:15:17 +05:30
|
|
|
|
2019-05-29 11:08:11 +05:30
|
|
|
e = 2.0**np.array(options.exponent)
|
2019-05-29 03:15:17 +05:30
|
|
|
for x in range(grid[0]):
|
|
|
|
for y in range(grid[1]):
|
|
|
|
for z in range(grid[2]):
|
|
|
|
coords = np.array([x+0.5,y+0.5,z+0.5])/grid
|
|
|
|
mask[x,y,z] = np.sum(np.abs((rotation*(coords-offset))/r)**e) < 1
|
2019-05-30 17:37:49 +05:30
|
|
|
|
2019-05-29 03:15:17 +05:30
|
|
|
if options.periodic:
|
|
|
|
shift = ((offset-center)*grid).astype(int)
|
|
|
|
mask = np.roll(mask,shift,(0,1,2))
|
2019-05-30 17:37:49 +05:30
|
|
|
|
2019-05-29 03:15:17 +05:30
|
|
|
if options.inside: mask = np.logical_not(mask)
|
2019-05-29 11:08:11 +05:30
|
|
|
fill = np.nanmax(geom.microstructure)+1 if options.fill is None else options.fill
|
2014-08-29 00:20:48 +05:30
|
|
|
|
2019-05-29 11:08:11 +05:30
|
|
|
damask.util.croak(geom.update(np.where(mask,geom.microstructure,fill)))
|
2019-05-28 06:44:09 +05:30
|
|
|
geom.add_comments(scriptID + ' ' + ' '.join(sys.argv[1:]))
|
2019-05-30 17:37:49 +05:30
|
|
|
|
2019-11-24 23:32:19 +05:30
|
|
|
geom.to_file(sys.stdout if name is None else name,pack=False)
|