Merge branch 'development' into stress-ramp-loadcase
This commit is contained in:
commit
20b393ac06
|
@ -239,6 +239,16 @@ Compile_Intel_Prepare:
|
||||||
- release
|
- release
|
||||||
|
|
||||||
###################################################################################################
|
###################################################################################################
|
||||||
|
Pytest_grid:
|
||||||
|
stage: grid
|
||||||
|
script:
|
||||||
|
- module load $IntelCompiler $MPICH_Intel $PETSc_MPICH_Intel
|
||||||
|
- cd pytest
|
||||||
|
- pytest
|
||||||
|
except:
|
||||||
|
- master
|
||||||
|
- release
|
||||||
|
|
||||||
Thermal:
|
Thermal:
|
||||||
stage: grid
|
stage: grid
|
||||||
script: Thermal/test.py
|
script: Thermal/test.py
|
||||||
|
@ -253,27 +263,6 @@ grid_parsingArguments:
|
||||||
- master
|
- master
|
||||||
- release
|
- release
|
||||||
|
|
||||||
StateIntegration_compareVariants:
|
|
||||||
stage: grid
|
|
||||||
script: StateIntegration_compareVariants/test.py
|
|
||||||
except:
|
|
||||||
- master
|
|
||||||
- release
|
|
||||||
|
|
||||||
nonlocal_densityConservation:
|
|
||||||
stage: grid
|
|
||||||
script: nonlocal_densityConservation/test.py
|
|
||||||
except:
|
|
||||||
- master
|
|
||||||
- release
|
|
||||||
|
|
||||||
RGC_DetectChanges:
|
|
||||||
stage: grid
|
|
||||||
script: RGC_DetectChanges/test.py
|
|
||||||
except:
|
|
||||||
- master
|
|
||||||
- release
|
|
||||||
|
|
||||||
Nonlocal_Damage_DetectChanges:
|
Nonlocal_Damage_DetectChanges:
|
||||||
stage: grid
|
stage: grid
|
||||||
script: Nonlocal_Damage_DetectChanges/test.py
|
script: Nonlocal_Damage_DetectChanges/test.py
|
||||||
|
@ -302,15 +291,6 @@ grid_all_loadCaseRotation:
|
||||||
- master
|
- master
|
||||||
- release
|
- release
|
||||||
|
|
||||||
grid_mech_MPI:
|
|
||||||
stage: grid
|
|
||||||
script:
|
|
||||||
- module load $IntelCompiler $MPICH_Intel $PETSc_MPICH_Intel
|
|
||||||
- grid_mech_MPI/test.py
|
|
||||||
except:
|
|
||||||
- master
|
|
||||||
- release
|
|
||||||
|
|
||||||
grid_all_restartMPI:
|
grid_all_restartMPI:
|
||||||
stage: grid
|
stage: grid
|
||||||
script:
|
script:
|
||||||
|
@ -327,13 +307,6 @@ Plasticity_DetectChanges:
|
||||||
- master
|
- master
|
||||||
- release
|
- release
|
||||||
|
|
||||||
Homogenization:
|
|
||||||
stage: grid
|
|
||||||
script: Homogenization/test.py
|
|
||||||
except:
|
|
||||||
- master
|
|
||||||
- release
|
|
||||||
|
|
||||||
Phenopowerlaw_singleSlip:
|
Phenopowerlaw_singleSlip:
|
||||||
stage: grid
|
stage: grid
|
||||||
script: Phenopowerlaw_singleSlip/test.py
|
script: Phenopowerlaw_singleSlip/test.py
|
||||||
|
@ -341,16 +314,6 @@ Phenopowerlaw_singleSlip:
|
||||||
- master
|
- master
|
||||||
- release
|
- release
|
||||||
|
|
||||||
Pytest_grid:
|
|
||||||
stage: grid
|
|
||||||
script:
|
|
||||||
- module load $IntelCompiler $MPICH_Intel $PETSc_MPICH_Intel
|
|
||||||
- cd pytest
|
|
||||||
- pytest
|
|
||||||
except:
|
|
||||||
- master
|
|
||||||
- release
|
|
||||||
|
|
||||||
###################################################################################################
|
###################################################################################################
|
||||||
Marc_compileIfort:
|
Marc_compileIfort:
|
||||||
stage: compileMarc
|
stage: compileMarc
|
||||||
|
|
8
Makefile
8
Makefile
|
@ -9,18 +9,10 @@ all: grid mesh processing
|
||||||
.PHONY: grid
|
.PHONY: grid
|
||||||
grid: build/grid
|
grid: build/grid
|
||||||
@(cd build/grid;make -j${DAMASK_NUM_THREADS} all install;)
|
@(cd build/grid;make -j${DAMASK_NUM_THREADS} all install;)
|
||||||
@rm -f ${DAMASK_ROOT}/bin/DAMASK_spectral > /dev/null || true
|
|
||||||
@ln -s ${DAMASK_ROOT}/bin/DAMASK_grid ${DAMASK_ROOT}/bin/DAMASK_spectral || true
|
|
||||||
.PHONY: spectral
|
|
||||||
spectral: grid
|
|
||||||
|
|
||||||
.PHONY: mesh
|
.PHONY: mesh
|
||||||
mesh: build/mesh
|
mesh: build/mesh
|
||||||
@(cd build/mesh; make -j${DAMASK_NUM_THREADS} all install;)
|
@(cd build/mesh; make -j${DAMASK_NUM_THREADS} all install;)
|
||||||
@rm -f ${DAMASK_ROOT}/bin/DAMASK_FEM > /dev/null || true
|
|
||||||
@ln -s ${DAMASK_ROOT}/bin/DAMASK_mesh ${DAMASK_ROOT}/bin/DAMASK_FEM || true
|
|
||||||
.PHONY: FEM
|
|
||||||
FEM: mesh
|
|
||||||
|
|
||||||
.PHONY: build/grid
|
.PHONY: build/grid
|
||||||
build/grid:
|
build/grid:
|
||||||
|
|
2
PRIVATE
2
PRIVATE
|
@ -1 +1 @@
|
||||||
Subproject commit b1cb4c7f306b3412704615793d6f61f4218ca24a
|
Subproject commit 05024077bc89350d0313fc33d695a25612ac5130
|
|
@ -1,161 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
from optparse import OptionParser
|
|
||||||
import re
|
|
||||||
import fnmatch
|
|
||||||
import math # noqa
|
|
||||||
|
|
||||||
import numpy as np
|
|
||||||
|
|
||||||
import damask
|
|
||||||
|
|
||||||
|
|
||||||
scriptName = os.path.splitext(os.path.basename(__file__))[0]
|
|
||||||
scriptID = ' '.join([scriptName,damask.version])
|
|
||||||
|
|
||||||
def sortingList(labels,whitelistitems):
|
|
||||||
|
|
||||||
indices = []
|
|
||||||
names = []
|
|
||||||
|
|
||||||
for label in labels:
|
|
||||||
if re.match(r'^\d+_',label):
|
|
||||||
indices.append(int(label.split('_',1)[0]))
|
|
||||||
names.append(label.split('_',1)[1])
|
|
||||||
else:
|
|
||||||
indices.append(0)
|
|
||||||
names.append(label)
|
|
||||||
|
|
||||||
return [indices,names,whitelistitems]
|
|
||||||
|
|
||||||
|
|
||||||
# --------------------------------------------------------------------
|
|
||||||
# MAIN
|
|
||||||
# --------------------------------------------------------------------
|
|
||||||
|
|
||||||
parser = OptionParser(option_class=damask.extendableOption, usage='%prog options [ASCIItable(s)]', description = """
|
|
||||||
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' -- " #s#foo# == 'bar' "
|
|
||||||
|
|
||||||
""", version = scriptID)
|
|
||||||
|
|
||||||
parser.add_option('-w','--white',
|
|
||||||
dest = 'whitelist',
|
|
||||||
action = 'extend', metavar = '<string LIST>',
|
|
||||||
help = 'whitelist of column labels (a,b,c,...)')
|
|
||||||
parser.add_option('-b','--black',
|
|
||||||
dest = 'blacklist',
|
|
||||||
action = 'extend', metavar='<string LIST>',
|
|
||||||
help = 'blacklist of column labels (a,b,c,...)')
|
|
||||||
parser.add_option('-c','--condition',
|
|
||||||
dest = 'condition', metavar='string',
|
|
||||||
help = 'condition to filter rows')
|
|
||||||
|
|
||||||
parser.set_defaults(condition = None,
|
|
||||||
)
|
|
||||||
|
|
||||||
(options,filenames) = parser.parse_args()
|
|
||||||
|
|
||||||
# --- loop over input files -------------------------------------------------------------------------
|
|
||||||
|
|
||||||
if filenames == []: filenames = [None]
|
|
||||||
|
|
||||||
for name in filenames:
|
|
||||||
try:
|
|
||||||
table = damask.ASCIItable(name = name)
|
|
||||||
except IOError:
|
|
||||||
continue
|
|
||||||
damask.util.report(scriptName,name)
|
|
||||||
|
|
||||||
# ------------------------------------------ assemble info ---------------------------------------
|
|
||||||
|
|
||||||
table.head_read()
|
|
||||||
|
|
||||||
# ------------------------------------------ process data ---------------------------------------
|
|
||||||
|
|
||||||
specials = { \
|
|
||||||
'_row_': 0,
|
|
||||||
}
|
|
||||||
labels = []
|
|
||||||
positions = []
|
|
||||||
|
|
||||||
for position,label in enumerate(table.labels(raw = True)):
|
|
||||||
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 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 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) \
|
|
||||||
or fnmatch.fnmatch(label,needle) for needle in options.whitelist] # which whitelist items do match it
|
|
||||||
whitelistitem[i] = match.index(True) if np.sum(match) == 1 else -1 # unique match to a whitelist item --> store which
|
|
||||||
|
|
||||||
order = range(len(labels)) if np.any(whitelistitem < 0) \
|
|
||||||
else np.lexsort(sortingList(labels,whitelistitem)) # reorder if unique, i.e. no "-1" in whitelistitem
|
|
||||||
else:
|
|
||||||
order = range(len(labels)) # maintain original order of labels
|
|
||||||
|
|
||||||
# --------------------------------------- evaluate condition ---------------------------------------
|
|
||||||
if options.condition is not None:
|
|
||||||
condition = options.condition # copy per file, since might be altered inline
|
|
||||||
breaker = False
|
|
||||||
|
|
||||||
for position,(all,marker,column) in enumerate(set(re.findall(r'#(([s]#)?(.+?))#',condition))): # find three groups
|
|
||||||
idx = table.label_index(column)
|
|
||||||
dim = table.label_dimension(column)
|
|
||||||
if idx < 0 and column not in specials:
|
|
||||||
damask.util.croak('column "{}" not found.'.format(column))
|
|
||||||
breaker = True
|
|
||||||
else:
|
|
||||||
if column in specials:
|
|
||||||
replacement = 'specials["{}"]'.format(column)
|
|
||||||
elif dim == 1: # scalar input
|
|
||||||
replacement = '{}(table.data[{}])'.format({ '':'float',
|
|
||||||
's#':'str'}[marker],idx) # take float or string value of data column
|
|
||||||
elif dim > 1: # multidimensional input (vector, tensor, etc.)
|
|
||||||
replacement = 'np.array(table.data[{}:{}],dtype=float)'.format(idx,idx+dim) # use (flat) array representation
|
|
||||||
|
|
||||||
condition = condition.replace('#'+all+'#',replacement)
|
|
||||||
|
|
||||||
if breaker: continue # found mistake in condition evaluation --> next file
|
|
||||||
|
|
||||||
# ------------------------------------------ assemble header ---------------------------------------
|
|
||||||
|
|
||||||
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()
|
|
||||||
|
|
||||||
# ------------------------------------------ process and output data ------------------------------------------
|
|
||||||
|
|
||||||
positions = np.array(positions)[order]
|
|
||||||
|
|
||||||
atOnce = options.condition is None
|
|
||||||
if atOnce: # read full array and filter columns
|
|
||||||
try:
|
|
||||||
table.data_readArray(positions+1) # read desired columns (indexed 1,...)
|
|
||||||
table.data_writeArray() # directly write out
|
|
||||||
except Exception:
|
|
||||||
table.data_rewind()
|
|
||||||
atOnce = False # data contains items that prevent array chunking
|
|
||||||
|
|
||||||
if not atOnce: # read data line by line
|
|
||||||
outputAlive = True
|
|
||||||
while outputAlive and table.data_read(): # read next data line of ASCII table
|
|
||||||
specials['_row_'] += 1 # count row
|
|
||||||
if options.condition is None or eval(condition): # valid row ?
|
|
||||||
table.data = [table.data[position] for position in positions] # retain filtered columns
|
|
||||||
outputAlive = table.data_write() # output processed line
|
|
||||||
|
|
||||||
# ------------------------------------------ finalize output -----------------------------------------
|
|
||||||
|
|
||||||
table.close() # close input ASCII table (works for stdin)
|
|
|
@ -1,226 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
import multiprocessing
|
|
||||||
from io import StringIO
|
|
||||||
from functools import partial
|
|
||||||
from optparse import OptionParser,OptionGroup
|
|
||||||
|
|
||||||
import numpy as np
|
|
||||||
from scipy import spatial
|
|
||||||
|
|
||||||
import damask
|
|
||||||
|
|
||||||
|
|
||||||
scriptName = os.path.splitext(os.path.basename(__file__))[0]
|
|
||||||
scriptID = ' '.join([scriptName,damask.version])
|
|
||||||
|
|
||||||
|
|
||||||
def findClosestSeed(seeds, weights, point):
|
|
||||||
return np.argmin(np.sum((np.broadcast_to(point,(len(seeds),3))-seeds)**2,axis=1) - weights)
|
|
||||||
|
|
||||||
|
|
||||||
def Laguerre_tessellation(grid, size, seeds, weights, origin = np.zeros(3), periodic = True, cpus = 2):
|
|
||||||
|
|
||||||
if periodic:
|
|
||||||
weights_p = np.tile(weights.squeeze(),27) # Laguerre weights (1,2,3,1,2,3,...,1,2,3)
|
|
||||||
seeds_p = np.vstack((seeds -np.array([size[0],0.,0.]),seeds, seeds +np.array([size[0],0.,0.])))
|
|
||||||
seeds_p = np.vstack((seeds_p-np.array([0.,size[1],0.]),seeds_p,seeds_p+np.array([0.,size[1],0.])))
|
|
||||||
seeds_p = np.vstack((seeds_p-np.array([0.,0.,size[2]]),seeds_p,seeds_p+np.array([0.,0.,size[2]])))
|
|
||||||
coords = damask.grid_filters.cell_coord0(grid*3,size*3,-origin-size).reshape(-1,3)
|
|
||||||
else:
|
|
||||||
weights_p = weights.squeeze()
|
|
||||||
seeds_p = seeds
|
|
||||||
coords = damask.grid_filters.cell_coord0(grid,size,-origin).reshape(-1,3)
|
|
||||||
|
|
||||||
if cpus > 1:
|
|
||||||
pool = multiprocessing.Pool(processes = cpus)
|
|
||||||
result = pool.map_async(partial(findClosestSeed,seeds_p,weights_p), [coord for coord in coords])
|
|
||||||
pool.close()
|
|
||||||
pool.join()
|
|
||||||
closest_seed = np.array(result.get()).reshape(-1,3)
|
|
||||||
else:
|
|
||||||
closest_seed= np.array([findClosestSeed(seeds_p,weights_p,coord) for coord in coords])
|
|
||||||
|
|
||||||
if periodic:
|
|
||||||
closest_seed = closest_seed.reshape(grid*3)
|
|
||||||
return closest_seed[grid[0]:grid[0]*2,grid[1]:grid[1]*2,grid[2]:grid[2]*2]%seeds.shape[0]
|
|
||||||
else:
|
|
||||||
return closest_seed
|
|
||||||
|
|
||||||
|
|
||||||
def Voronoi_tessellation(grid, size, seeds, origin = np.zeros(3), periodic = True):
|
|
||||||
|
|
||||||
coords = damask.grid_filters.cell_coord0(grid,size,-origin).reshape(-1,3)
|
|
||||||
KDTree = spatial.cKDTree(seeds,boxsize=size) if periodic else spatial.cKDTree(seeds)
|
|
||||||
devNull,closest_seed = KDTree.query(coords)
|
|
||||||
|
|
||||||
return closest_seed
|
|
||||||
|
|
||||||
|
|
||||||
# --------------------------------------------------------------------
|
|
||||||
# MAIN
|
|
||||||
# --------------------------------------------------------------------
|
|
||||||
|
|
||||||
parser = OptionParser(option_class=damask.extendableOption, usage='%prog option(s) [seedfile(s)]', description = """
|
|
||||||
Generate geometry description and material configuration by tessellation of given seeds file.
|
|
||||||
|
|
||||||
""", version = scriptID)
|
|
||||||
|
|
||||||
|
|
||||||
group = OptionGroup(parser, "Tessellation","")
|
|
||||||
|
|
||||||
group.add_option('-l',
|
|
||||||
'--laguerre',
|
|
||||||
dest = 'laguerre',
|
|
||||||
action = 'store_true',
|
|
||||||
help = 'use Laguerre (weighted Voronoi) tessellation')
|
|
||||||
group.add_option('--cpus',
|
|
||||||
dest = 'cpus',
|
|
||||||
type = 'int', metavar = 'int',
|
|
||||||
help = 'number of parallel processes to use for Laguerre tessellation [%default]')
|
|
||||||
group.add_option('--nonperiodic',
|
|
||||||
dest = 'periodic',
|
|
||||||
action = 'store_false',
|
|
||||||
help = 'nonperiodic tessellation')
|
|
||||||
|
|
||||||
parser.add_option_group(group)
|
|
||||||
|
|
||||||
group = OptionGroup(parser, "Geometry","")
|
|
||||||
|
|
||||||
group.add_option('-g',
|
|
||||||
'--grid',
|
|
||||||
dest = 'grid',
|
|
||||||
type = 'int', nargs = 3, metavar = ' '.join(['int']*3),
|
|
||||||
help = 'a,b,c grid of hexahedral box')
|
|
||||||
group.add_option('-s',
|
|
||||||
'--size',
|
|
||||||
dest = 'size',
|
|
||||||
type = 'float', nargs = 3, metavar=' '.join(['float']*3),
|
|
||||||
help = 'x,y,z size of hexahedral box [1.0 1.0 1.0]')
|
|
||||||
group.add_option('-o',
|
|
||||||
'--origin',
|
|
||||||
dest = 'origin',
|
|
||||||
type = 'float', nargs = 3, metavar=' '.join(['float']*3),
|
|
||||||
help = 'origin of grid [0.0 0.0 0.0]')
|
|
||||||
|
|
||||||
parser.add_option_group(group)
|
|
||||||
|
|
||||||
group = OptionGroup(parser, "Seeds","")
|
|
||||||
|
|
||||||
group.add_option('-p',
|
|
||||||
'--pos', '--seedposition',
|
|
||||||
dest = 'pos',
|
|
||||||
type = 'string', metavar = 'string',
|
|
||||||
help = 'label of coordinates [%default]')
|
|
||||||
group.add_option('-w',
|
|
||||||
'--weight',
|
|
||||||
dest = 'weight',
|
|
||||||
type = 'string', metavar = 'string',
|
|
||||||
help = 'label of weights [%default]')
|
|
||||||
group.add_option('-m',
|
|
||||||
'--microstructure',
|
|
||||||
dest = 'microstructure',
|
|
||||||
type = 'string', metavar = 'string',
|
|
||||||
help = 'label of microstructures [%default]')
|
|
||||||
group.add_option('-e',
|
|
||||||
'--eulers',
|
|
||||||
dest = 'eulers',
|
|
||||||
type = 'string', metavar = 'string',
|
|
||||||
help = 'label of Euler angles [%default]')
|
|
||||||
group.add_option('--axes',
|
|
||||||
dest = 'axes',
|
|
||||||
type = 'string', nargs = 3, metavar = ' '.join(['string']*3),
|
|
||||||
help = 'orientation coordinate frame in terms of position coordinate frame')
|
|
||||||
|
|
||||||
parser.add_option_group(group)
|
|
||||||
|
|
||||||
group = OptionGroup(parser, "Configuration","")
|
|
||||||
|
|
||||||
group.add_option('--without-config',
|
|
||||||
dest = 'config',
|
|
||||||
action = 'store_false',
|
|
||||||
help = 'omit material configuration header')
|
|
||||||
group.add_option('--phase',
|
|
||||||
dest = 'phase',
|
|
||||||
type = 'int', metavar = 'int',
|
|
||||||
help = 'phase index to be used [%default]')
|
|
||||||
|
|
||||||
parser.add_option_group(group)
|
|
||||||
|
|
||||||
parser.set_defaults(pos = 'pos',
|
|
||||||
weight = 'weight',
|
|
||||||
microstructure = 'microstructure',
|
|
||||||
eulers = 'euler',
|
|
||||||
phase = 1,
|
|
||||||
cpus = 2,
|
|
||||||
laguerre = False,
|
|
||||||
periodic = True,
|
|
||||||
config = True,
|
|
||||||
)
|
|
||||||
|
|
||||||
(options,filenames) = parser.parse_args()
|
|
||||||
if filenames == []: filenames = [None]
|
|
||||||
|
|
||||||
for name in filenames:
|
|
||||||
damask.util.report(scriptName,name)
|
|
||||||
|
|
||||||
table = damask.Table.load(StringIO(''.join(sys.stdin.read())) if name is None else name)
|
|
||||||
|
|
||||||
size = np.ones(3)
|
|
||||||
origin = np.zeros(3)
|
|
||||||
for line in table.comments:
|
|
||||||
items = line.lower().strip().split()
|
|
||||||
key = items[0] if items else ''
|
|
||||||
if key == 'grid':
|
|
||||||
grid = np.array([ int(dict(zip(items[1::2],items[2::2]))[i]) for i in ['a','b','c']])
|
|
||||||
elif key == 'size':
|
|
||||||
size = np.array([float(dict(zip(items[1::2],items[2::2]))[i]) for i in ['x','y','z']])
|
|
||||||
elif key == 'origin':
|
|
||||||
origin = np.array([float(dict(zip(items[1::2],items[2::2]))[i]) for i in ['x','y','z']])
|
|
||||||
if options.grid: grid = np.array(options.grid)
|
|
||||||
if options.size: size = np.array(options.size)
|
|
||||||
if options.origin: origin = np.array(options.origin)
|
|
||||||
|
|
||||||
seeds = table.get(options.pos)
|
|
||||||
|
|
||||||
grains = table.get(options.microstructure) if options.microstructure in table.labels else np.arange(len(seeds))+1
|
|
||||||
grainIDs = np.unique(grains).astype('i')
|
|
||||||
|
|
||||||
if options.eulers in table.labels:
|
|
||||||
eulers = table.get(options.eulers)
|
|
||||||
|
|
||||||
if options.laguerre:
|
|
||||||
indices = grains[Laguerre_tessellation(grid,size,seeds,table.get(options.weight),origin,
|
|
||||||
options.periodic,options.cpus)]
|
|
||||||
else:
|
|
||||||
indices = grains[Voronoi_tessellation (grid,size,seeds,origin,options.periodic)]
|
|
||||||
|
|
||||||
config_header = []
|
|
||||||
if options.config:
|
|
||||||
|
|
||||||
if options.eulers in table.labels:
|
|
||||||
config_header += ['<texture>']
|
|
||||||
for ID in grainIDs:
|
|
||||||
eulerID = np.nonzero(grains == ID)[0][0] # find first occurrence of this grain id
|
|
||||||
config_header += ['[Grain{}]'.format(ID),
|
|
||||||
'(gauss)\tphi1 {:.2f}\tPhi {:.2f}\tphi2 {:.2f}'.format(*eulers[eulerID])
|
|
||||||
]
|
|
||||||
if options.axes: config_header += ['axes\t{} {} {}'.format(*options.axes)]
|
|
||||||
|
|
||||||
config_header += ['<microstructure>']
|
|
||||||
for ID in grainIDs:
|
|
||||||
config_header += ['[Grain{}]'.format(ID),
|
|
||||||
'(constituent)\tphase {}\ttexture {}\tfraction 1.0'.format(options.phase,ID)
|
|
||||||
]
|
|
||||||
|
|
||||||
config_header += ['<!skip>']
|
|
||||||
|
|
||||||
header = [scriptID + ' ' + ' '.join(sys.argv[1:])]\
|
|
||||||
+ config_header
|
|
||||||
geom = damask.Geom(indices.reshape(grid),size,origin,
|
|
||||||
comments=header)
|
|
||||||
damask.util.croak(geom)
|
|
||||||
|
|
||||||
geom.save_ASCII(sys.stdout if name is None else os.path.splitext(name)[0]+'.geom',compress=False)
|
|
|
@ -1,349 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
import math
|
|
||||||
import random
|
|
||||||
from io import StringIO
|
|
||||||
from optparse import OptionParser
|
|
||||||
|
|
||||||
import numpy as np
|
|
||||||
|
|
||||||
import damask
|
|
||||||
|
|
||||||
|
|
||||||
scriptName = os.path.splitext(os.path.basename(__file__))[0]
|
|
||||||
scriptID = ' '.join([scriptName,damask.version])
|
|
||||||
|
|
||||||
|
|
||||||
# --- helper functions ---
|
|
||||||
def integerFactorization(i):
|
|
||||||
|
|
||||||
j = int(math.floor(math.sqrt(float(i))))
|
|
||||||
while j>1 and int(i)%j != 0:
|
|
||||||
j -= 1
|
|
||||||
return j
|
|
||||||
|
|
||||||
def binAsBins(bin,intervals):
|
|
||||||
"""Explode compound bin into 3D bins list."""
|
|
||||||
bins = [0]*3
|
|
||||||
bins[0] = (bin//(intervals[1] * intervals[2])) % intervals[0]
|
|
||||||
bins[1] = (bin//intervals[2]) % intervals[1]
|
|
||||||
bins[2] = bin % intervals[2]
|
|
||||||
return bins
|
|
||||||
|
|
||||||
def binsAsBin(bins,intervals):
|
|
||||||
"""Implode 3D bins into compound bin."""
|
|
||||||
return (bins[0]*intervals[1] + bins[1])*intervals[2] + bins[2]
|
|
||||||
|
|
||||||
def EulersAsBins(Eulers,intervals,deltas,center):
|
|
||||||
"""Return list of Eulers translated into 3D bins list."""
|
|
||||||
return [int((euler+(0.5-center)*delta)//delta)%interval \
|
|
||||||
for euler,delta,interval in zip(Eulers,deltas,intervals) \
|
|
||||||
]
|
|
||||||
|
|
||||||
def binAsEulers(bin,intervals,deltas,center):
|
|
||||||
"""Compound bin number translated into list of Eulers."""
|
|
||||||
Eulers = [0.0]*3
|
|
||||||
Eulers[2] = (bin%intervals[2] + center)*deltas[2]
|
|
||||||
Eulers[1] = (bin//intervals[2]%intervals[1] + center)*deltas[1]
|
|
||||||
Eulers[0] = (bin//(intervals[2]*intervals[1]) + center)*deltas[0]
|
|
||||||
return Eulers
|
|
||||||
|
|
||||||
def directInvRepetitions(probability,scale):
|
|
||||||
"""Calculate number of samples drawn by direct inversion."""
|
|
||||||
nDirectInv = 0
|
|
||||||
for bin in range(len(probability)): # loop over bins
|
|
||||||
nDirectInv += int(round(probability[bin]*scale)) # calc repetition
|
|
||||||
return nDirectInv
|
|
||||||
|
|
||||||
|
|
||||||
# ---------------------- sampling methods -----------------------------------------------------------------------
|
|
||||||
|
|
||||||
# ----- efficient algorithm ---------
|
|
||||||
def directInversion (ODF,nSamples):
|
|
||||||
"""ODF contains 'dV_V' (normalized to 1), 'center', 'intervals', 'limits' (in radians)."""
|
|
||||||
nOptSamples = max(ODF['nNonZero'],nSamples) # random subsampling if too little samples requested
|
|
||||||
|
|
||||||
nInvSamples = 0
|
|
||||||
repetition = [None]*ODF['nBins']
|
|
||||||
|
|
||||||
scaleLower = 0.0
|
|
||||||
nInvSamplesLower = 0
|
|
||||||
scaleUpper = float(nOptSamples)
|
|
||||||
incFactor = 1.0
|
|
||||||
nIter = 0
|
|
||||||
nInvSamplesUpper = directInvRepetitions(ODF['dV_V'],scaleUpper)
|
|
||||||
while (\
|
|
||||||
(scaleUpper-scaleLower > scaleUpper*1e-15 or nInvSamplesUpper < nOptSamples) and \
|
|
||||||
nInvSamplesUpper != nOptSamples \
|
|
||||||
): # closer match required?
|
|
||||||
if nInvSamplesUpper < nOptSamples:
|
|
||||||
scaleLower,scaleUpper = scaleUpper,scaleUpper+incFactor*(scaleUpper-scaleLower)/2.0
|
|
||||||
incFactor *= 2.0
|
|
||||||
nInvSamplesLower,nInvSamplesUpper = nInvSamplesUpper,directInvRepetitions(ODF['dV_V'],scaleUpper)
|
|
||||||
else:
|
|
||||||
scaleUpper = (scaleLower+scaleUpper)/2.0
|
|
||||||
incFactor = 1.0
|
|
||||||
nInvSamplesUpper = directInvRepetitions(ODF['dV_V'],scaleUpper)
|
|
||||||
nIter += 1
|
|
||||||
damask.util.croak('%i:(%12.11f,%12.11f) %i <= %i <= %i'%(nIter,scaleLower,scaleUpper,
|
|
||||||
nInvSamplesLower,nOptSamples,nInvSamplesUpper))
|
|
||||||
nInvSamples = nInvSamplesUpper
|
|
||||||
scale = scaleUpper
|
|
||||||
damask.util.croak('created set of %i samples (%12.11f) with scaling %12.11f delivering %i'%(nInvSamples,
|
|
||||||
float(nInvSamples)/nOptSamples-1.0,
|
|
||||||
scale,nSamples))
|
|
||||||
repetition = [None]*ODF['nBins'] # preallocate and clear
|
|
||||||
|
|
||||||
for bin in range(ODF['nBins']): # loop over bins
|
|
||||||
repetition[bin] = int(round(ODF['dV_V'][bin]*scale)) # calc repetition
|
|
||||||
|
|
||||||
# build set
|
|
||||||
set = [None]*nInvSamples
|
|
||||||
i = 0
|
|
||||||
for bin in range(ODF['nBins']):
|
|
||||||
set[i:i+repetition[bin]] = [bin]*repetition[bin] # fill set with bin, i.e. orientation
|
|
||||||
i += repetition[bin] # advance set counter
|
|
||||||
|
|
||||||
orientations = np.zeros((nSamples,3),'f')
|
|
||||||
reconstructedODF = np.zeros(ODF['nBins'],'f')
|
|
||||||
unitInc = 1.0/nSamples
|
|
||||||
for j in range(nSamples):
|
|
||||||
if (j == nInvSamples-1): ex = j
|
|
||||||
else: ex = int(round(random.uniform(j+0.5,nInvSamples-0.5)))
|
|
||||||
bin = set[ex]
|
|
||||||
Eulers = binAsEulers(bin,ODF['interval'],ODF['delta'],ODF['center'])
|
|
||||||
orientations[j] = np.degrees(Eulers)
|
|
||||||
reconstructedODF[bin] += unitInc
|
|
||||||
set[ex] = set[j] # exchange orientations
|
|
||||||
|
|
||||||
return orientations, reconstructedODF
|
|
||||||
|
|
||||||
|
|
||||||
# ----- trial and error algorithms ---------
|
|
||||||
|
|
||||||
def MonteCarloEulers (ODF,nSamples):
|
|
||||||
"""ODF contains 'dV_V' (normalized to 1), 'center', 'intervals', 'limits' (in radians)."""
|
|
||||||
countMC = 0
|
|
||||||
maxdV_V = max(ODF['dV_V'])
|
|
||||||
orientations = np.zeros((nSamples,3),'f')
|
|
||||||
reconstructedODF = np.zeros(ODF['nBins'],'f')
|
|
||||||
unitInc = 1.0/nSamples
|
|
||||||
|
|
||||||
for j in range(nSamples):
|
|
||||||
MC = maxdV_V*2.0
|
|
||||||
bin = 0
|
|
||||||
while MC > ODF['dV_V'][bin]:
|
|
||||||
countMC += 1
|
|
||||||
MC = maxdV_V*random.random()
|
|
||||||
Eulers = [limit*random.random() for limit in ODF['limit']]
|
|
||||||
bins = EulersAsBins(Eulers,ODF['interval'],ODF['delta'],ODF['center'])
|
|
||||||
bin = binsAsBin(bins,ODF['interval'])
|
|
||||||
orientations[j] = np.degrees(Eulers)
|
|
||||||
reconstructedODF[bin] += unitInc
|
|
||||||
|
|
||||||
return orientations, reconstructedODF, countMC
|
|
||||||
|
|
||||||
|
|
||||||
def MonteCarloBins (ODF,nSamples):
|
|
||||||
"""ODF contains 'dV_V' (normalized to 1), 'center', 'intervals', 'limits' (in radians)."""
|
|
||||||
countMC = 0
|
|
||||||
maxdV_V = max(ODF['dV_V'])
|
|
||||||
orientations = np.zeros((nSamples,3),'f')
|
|
||||||
reconstructedODF = np.zeros(ODF['nBins'],'f')
|
|
||||||
unitInc = 1.0/nSamples
|
|
||||||
|
|
||||||
for j in range(nSamples):
|
|
||||||
MC = maxdV_V*2.0
|
|
||||||
bin = 0
|
|
||||||
while MC > ODF['dV_V'][bin]:
|
|
||||||
countMC += 1
|
|
||||||
MC = maxdV_V*random.random()
|
|
||||||
bin = int(ODF['nBins'] * random.random())
|
|
||||||
Eulers = binAsEulers(bin,ODF['interval'],ODF['delta'],ODF['center'])
|
|
||||||
orientations[j] = np.degrees(Eulers)
|
|
||||||
reconstructedODF[bin] += unitInc
|
|
||||||
|
|
||||||
return orientations, reconstructedODF
|
|
||||||
|
|
||||||
|
|
||||||
def TothVanHoutteSTAT (ODF,nSamples):
|
|
||||||
"""ODF contains 'dV_V' (normalized to 1), 'center', 'intervals', 'limits' (in radians)."""
|
|
||||||
orientations = np.zeros((nSamples,3),'f')
|
|
||||||
reconstructedODF = np.zeros(ODF['nBins'],'f')
|
|
||||||
unitInc = 1.0/nSamples
|
|
||||||
|
|
||||||
selectors = [random.random() for i in range(nSamples)]
|
|
||||||
selectors.sort()
|
|
||||||
indexSelector = 0
|
|
||||||
|
|
||||||
cumdV_V = 0.0
|
|
||||||
countSamples = 0
|
|
||||||
|
|
||||||
for bin in range(ODF['nBins']) :
|
|
||||||
cumdV_V += ODF['dV_V'][bin]
|
|
||||||
while indexSelector < nSamples and selectors[indexSelector] < cumdV_V:
|
|
||||||
Eulers = binAsEulers(bin,ODF['interval'],ODF['delta'],ODF['center'])
|
|
||||||
orientations[countSamples] = np.degrees(Eulers)
|
|
||||||
reconstructedODF[bin] += unitInc
|
|
||||||
countSamples += 1
|
|
||||||
indexSelector += 1
|
|
||||||
|
|
||||||
damask.util.croak('created set of %i when asked to deliver %i'%(countSamples,nSamples))
|
|
||||||
|
|
||||||
return orientations, reconstructedODF
|
|
||||||
|
|
||||||
|
|
||||||
# --------------------------------------------------------------------
|
|
||||||
# MAIN
|
|
||||||
# --------------------------------------------------------------------
|
|
||||||
parser = OptionParser(option_class=damask.extendableOption, usage='%prog options [file[s]]', description ="""
|
|
||||||
Transform linear binned ODF data into given number of orientations.
|
|
||||||
IA: integral approximation, STAT: Van Houtte, MC: Monte Carlo
|
|
||||||
|
|
||||||
""", version = scriptID)
|
|
||||||
|
|
||||||
algorithms = ['IA', 'STAT','MC']
|
|
||||||
parser.add_option('-n', '--nsamples',
|
|
||||||
dest = 'number',
|
|
||||||
type = 'int', metavar = 'int',
|
|
||||||
help = 'number of orientations to be generated [%default]')
|
|
||||||
parser.add_option('-a','--algorithm',
|
|
||||||
dest = 'algorithm',
|
|
||||||
choices = algorithms, metavar = 'string',
|
|
||||||
help = 'sampling algorithm {%s} [IA]'%(', '.join(algorithms)))
|
|
||||||
parser.add_option('-p','--phase',
|
|
||||||
dest = 'phase',
|
|
||||||
type = 'int', metavar = 'int',
|
|
||||||
help = 'phase index to be used [%default]')
|
|
||||||
parser.add_option('-r', '--rnd',
|
|
||||||
dest = 'randomSeed',
|
|
||||||
type = 'int', metavar = 'int', \
|
|
||||||
help = 'seed of random number generator [%default]')
|
|
||||||
parser.set_defaults(randomSeed = None,
|
|
||||||
number = 500,
|
|
||||||
algorithm = 'IA',
|
|
||||||
phase = 1,
|
|
||||||
ang = True,
|
|
||||||
)
|
|
||||||
|
|
||||||
(options,filenames) = parser.parse_args()
|
|
||||||
if filenames == []: filenames = [None]
|
|
||||||
|
|
||||||
for name in filenames:
|
|
||||||
damask.util.report(scriptName,name)
|
|
||||||
|
|
||||||
table = damask.Table.load(StringIO(''.join(sys.stdin.read())) if name is None else name)
|
|
||||||
|
|
||||||
randomSeed = int(os.urandom(4).hex(),16) if options.randomSeed is None else options.randomSeed # random seed per file
|
|
||||||
random.seed(randomSeed)
|
|
||||||
|
|
||||||
# --------------- figure out limits (left/right), delta, and interval -----------------------------
|
|
||||||
ODF = {}
|
|
||||||
eulers = table.get('euler')
|
|
||||||
limits = np.array([np.min(eulers,axis=0),np.max(eulers,axis=0)]) # min/max euler angles in degrees
|
|
||||||
ODF['limit'] = np.radians(limits[1,:]) # right hand limits in radians
|
|
||||||
ODF['center'] = 0.0 if all(limits[0,:]<1e-8) else 0.5 # vertex or cell centered
|
|
||||||
|
|
||||||
ODF['interval'] = np.array(list(map(len,[np.unique(eulers[:,i]) for i in range(3)])),'i') # steps are number of distict values
|
|
||||||
ODF['nBins'] = ODF['interval'].prod()
|
|
||||||
ODF['delta'] = np.radians(np.array(limits[1,0:3]-limits[0,0:3])/(ODF['interval']-1)) # step size
|
|
||||||
|
|
||||||
if eulers.shape[0] != ODF['nBins']:
|
|
||||||
damask.util.croak('expecting %i values but got %i'%(ODF['nBins'],eulers.shape[0]))
|
|
||||||
continue
|
|
||||||
|
|
||||||
# ----- build binnedODF array and normalize ------------------------------------------------------
|
|
||||||
sumdV_V = 0.0
|
|
||||||
ODF['dV_V'] = [None]*ODF['nBins']
|
|
||||||
ODF['nNonZero'] = 0
|
|
||||||
dg = ODF['delta'][0]*2.0*math.sin(ODF['delta'][1]/2.0)*ODF['delta'][2]
|
|
||||||
intensity = table.get('intensity')
|
|
||||||
for b in range(ODF['nBins']):
|
|
||||||
ODF['dV_V'][b] = \
|
|
||||||
max(0.0,intensity[b,0]) * dg * \
|
|
||||||
math.sin(((b//ODF['interval'][2])%ODF['interval'][1]+ODF['center'])*ODF['delta'][1])
|
|
||||||
if ODF['dV_V'][b] > 0.0:
|
|
||||||
sumdV_V += ODF['dV_V'][b]
|
|
||||||
ODF['nNonZero'] += 1
|
|
||||||
|
|
||||||
for b in range(ODF['nBins']):
|
|
||||||
ODF['dV_V'][b] /= sumdV_V # normalize dV/V
|
|
||||||
|
|
||||||
damask.util.croak(['non-zero fraction: %12.11f (%i/%i)'%(float(ODF['nNonZero'])/ODF['nBins'],
|
|
||||||
ODF['nNonZero'],
|
|
||||||
ODF['nBins']),
|
|
||||||
'Volume integral of ODF: %12.11f\n'%sumdV_V,
|
|
||||||
'Reference Integral: %12.11f\n'%(ODF['limit'][0]*ODF['limit'][2]*(1-math.cos(ODF['limit'][1]))),
|
|
||||||
])
|
|
||||||
|
|
||||||
Functions = {'IA': 'directInversion', 'STAT': 'TothVanHoutteSTAT', 'MC': 'MonteCarloBins'}
|
|
||||||
method = Functions[options.algorithm]
|
|
||||||
|
|
||||||
Orientations, ReconstructedODF = (globals()[method])(ODF,options.number)
|
|
||||||
|
|
||||||
# calculate accuracy of sample
|
|
||||||
squaredDiff = {'orig':0.0,method:0.0}
|
|
||||||
squaredRelDiff = {'orig':0.0,method:0.0}
|
|
||||||
mutualProd = {'orig':0.0,method:0.0}
|
|
||||||
indivSum = {'orig':0.0,method:0.0}
|
|
||||||
indivSquaredSum = {'orig':0.0,method:0.0}
|
|
||||||
|
|
||||||
for bin in range(ODF['nBins']):
|
|
||||||
squaredDiff[method] += (ODF['dV_V'][bin] - ReconstructedODF[bin])**2
|
|
||||||
if ODF['dV_V'][bin] > 0.0:
|
|
||||||
squaredRelDiff[method] += (ODF['dV_V'][bin] - ReconstructedODF[bin])**2/ODF['dV_V'][bin]**2
|
|
||||||
mutualProd[method] += ODF['dV_V'][bin]*ReconstructedODF[bin]
|
|
||||||
indivSum[method] += ReconstructedODF[bin]
|
|
||||||
indivSquaredSum[method] += ReconstructedODF[bin]**2
|
|
||||||
indivSum['orig'] += ODF['dV_V'][bin]
|
|
||||||
indivSquaredSum['orig'] += ODF['dV_V'][bin]**2
|
|
||||||
|
|
||||||
damask.util.croak(['sqrt(N*)RMSD of ODFs:\t %12.11f'% math.sqrt(options.number*squaredDiff[method]),
|
|
||||||
'RMSrD of ODFs:\t %12.11f'%math.sqrt(squaredRelDiff[method]),
|
|
||||||
'rMSD of ODFs:\t %12.11f'%(squaredDiff[method]/indivSquaredSum['orig']),
|
|
||||||
'nNonZero correlation slope:\t %12.11f'\
|
|
||||||
%((ODF['nNonZero']*mutualProd[method]-indivSum['orig']*indivSum[method])/\
|
|
||||||
(ODF['nNonZero']*indivSquaredSum['orig']-indivSum['orig']**2)),
|
|
||||||
'nNonZero correlation confidence:\t %12.11f'\
|
|
||||||
%((mutualProd[method]-indivSum['orig']*indivSum[method]/ODF['nNonZero'])/\
|
|
||||||
(ODF['nNonZero']*math.sqrt((indivSquaredSum['orig']/ODF['nNonZero']-(indivSum['orig']/ODF['nNonZero'])**2)*\
|
|
||||||
(indivSquaredSum[method]/ODF['nNonZero']-(indivSum[method]/ODF['nNonZero'])**2)))),
|
|
||||||
])
|
|
||||||
|
|
||||||
if method == 'IA' and options.number < ODF['nNonZero']:
|
|
||||||
strOpt = '(%i)'%ODF['nNonZero']
|
|
||||||
|
|
||||||
formatwidth = 1+int(math.log10(options.number))
|
|
||||||
|
|
||||||
materialConfig = [
|
|
||||||
'#' + scriptID + ' ' + ' '.join(sys.argv[1:]),
|
|
||||||
'# random seed %i'%randomSeed,
|
|
||||||
'#-------------------#',
|
|
||||||
'<microstructure>',
|
|
||||||
'#-------------------#',
|
|
||||||
]
|
|
||||||
|
|
||||||
for i,ID in enumerate(range(options.number)):
|
|
||||||
materialConfig += ['[Grain%s]'%(str(ID+1).zfill(formatwidth)),
|
|
||||||
'(constituent) phase %i texture %s fraction 1.0'%(options.phase,str(ID+1).rjust(formatwidth)),
|
|
||||||
]
|
|
||||||
|
|
||||||
materialConfig += [
|
|
||||||
'#-------------------#',
|
|
||||||
'<texture>',
|
|
||||||
'#-------------------#',
|
|
||||||
]
|
|
||||||
|
|
||||||
for ID in range(options.number):
|
|
||||||
eulers = Orientations[ID]
|
|
||||||
|
|
||||||
materialConfig += ['[Grain%s]'%(str(ID+1).zfill(formatwidth)),
|
|
||||||
'(gauss) phi1 {} Phi {} phi2 {} scatter 0.0 fraction 1.0'.format(*eulers),
|
|
||||||
]
|
|
||||||
|
|
||||||
#--- output finalization --------------------------------------------------------------------------
|
|
||||||
|
|
||||||
with (open(os.path.splitext(name)[0]+'_'+method+'_'+str(options.number)+'_material.config','w')) as outfile:
|
|
||||||
outfile.write('\n'.join(materialConfig)+'\n')
|
|
|
@ -48,7 +48,6 @@ class myThread (threading.Thread):
|
||||||
|
|
||||||
myBestSeedsVFile = StringIO() # store local copy of best seeds file
|
myBestSeedsVFile = StringIO() # store local copy of best seeds file
|
||||||
perturbedSeedsVFile = StringIO() # perturbed best seeds file
|
perturbedSeedsVFile = StringIO() # perturbed best seeds file
|
||||||
perturbedGeomVFile = StringIO() # tessellated geom file
|
|
||||||
|
|
||||||
#--- still not matching desired bin class ----------------------------------------------------------
|
#--- still not matching desired bin class ----------------------------------------------------------
|
||||||
while bestMatch < options.threshold:
|
while bestMatch < options.threshold:
|
||||||
|
@ -92,15 +91,10 @@ class myThread (threading.Thread):
|
||||||
perturbedSeedsTable.set('pos',coords).save(perturbedSeedsVFile,legacy=True)
|
perturbedSeedsTable.set('pos',coords).save(perturbedSeedsVFile,legacy=True)
|
||||||
|
|
||||||
#--- do tesselation with perturbed seed file ------------------------------------------------------
|
#--- do tesselation with perturbed seed file ------------------------------------------------------
|
||||||
perturbedGeomVFile.close()
|
perturbedGeom = damask.Geom.from_Voronoi_tessellation(options.grid,np.ones(3),coords)
|
||||||
perturbedGeomVFile = StringIO()
|
|
||||||
perturbedSeedsVFile.seek(0)
|
|
||||||
perturbedGeomVFile.write(damask.util.execute('geom_fromVoronoiTessellation '+
|
|
||||||
' -g '+' '.join(list(map(str, options.grid))),streamIn=perturbedSeedsVFile)[0])
|
|
||||||
perturbedGeomVFile.seek(0)
|
|
||||||
|
|
||||||
#--- evaluate current seeds file ------------------------------------------------------------------
|
#--- evaluate current seeds file ------------------------------------------------------------------
|
||||||
perturbedGeom = damask.Geom.load_ASCII(perturbedGeomVFile)
|
|
||||||
myNmaterials = len(np.unique(perturbedGeom.material))
|
myNmaterials = len(np.unique(perturbedGeom.material))
|
||||||
currentData = np.bincount(perturbedGeom.material.ravel())[1:]/points
|
currentData = np.bincount(perturbedGeom.material.ravel())[1:]/points
|
||||||
currentError=[]
|
currentError=[]
|
||||||
|
@ -227,22 +221,15 @@ for i in range(1,nMaterials+1):
|
||||||
# ----------- create initial seed file or open existing one
|
# ----------- create initial seed file or open existing one
|
||||||
bestSeedsVFile = StringIO()
|
bestSeedsVFile = StringIO()
|
||||||
if os.path.isfile(os.path.splitext(options.seedFile)[0]+'.seeds'):
|
if os.path.isfile(os.path.splitext(options.seedFile)[0]+'.seeds'):
|
||||||
with open(os.path.splitext(options.seedFile)[0]+'.seeds') as initialSeedFile:
|
initial_seeds = damask.Table.load(os.path.splitext(options.seedFile)[0]+'.seeds').get('pos')
|
||||||
for line in initialSeedFile: bestSeedsVFile.write(line)
|
|
||||||
else:
|
else:
|
||||||
bestSeedsVFile.write(damask.util.execute('seeds_fromRandom'+\
|
initial_seeds = damask.seeds.from_random(np.ones(3),nMaterials,options.grid,options.randomSeed)
|
||||||
' -g '+' '.join(list(map(str, options.grid)))+\
|
|
||||||
' -r {:d}'.format(options.randomSeed)+\
|
|
||||||
' -N '+str(nMaterials))[0])
|
|
||||||
bestSeedsUpdate = time.time()
|
bestSeedsUpdate = time.time()
|
||||||
|
|
||||||
# ----------- tessellate initial seed file to get and evaluate geom file
|
# ----------- tessellate initial seed file to get and evaluate geom file
|
||||||
bestSeedsVFile.seek(0)
|
bestSeedsVFile.seek(0)
|
||||||
initialGeomVFile = StringIO()
|
initialGeom = damask.Geom.from_Voronoi_tessellation(options.grid,np.ones(3),initial_seeds)
|
||||||
initialGeomVFile.write(damask.util.execute('geom_fromVoronoiTessellation '+
|
|
||||||
' -g '+' '.join(list(map(str, options.grid))),bestSeedsVFile)[0])
|
|
||||||
initialGeomVFile.seek(0)
|
|
||||||
initialGeom = damask.Geom.load_ASCII(initialGeomVFile)
|
|
||||||
|
|
||||||
if len(np.unique(targetGeom.material)) != nMaterials:
|
if len(np.unique(targetGeom.material)) != nMaterials:
|
||||||
damask.util.croak('error. Material count mismatch')
|
damask.util.croak('error. Material count mismatch')
|
||||||
|
@ -269,7 +256,6 @@ else:
|
||||||
|
|
||||||
if match >0: damask.util.croak('Stage {:d} cleared'.format(match))
|
if match >0: damask.util.croak('Stage {:d} cleared'.format(match))
|
||||||
sys.stdout.flush()
|
sys.stdout.flush()
|
||||||
initialGeomVFile.close()
|
|
||||||
|
|
||||||
# start mulithreaded monte carlo simulation
|
# start mulithreaded monte carlo simulation
|
||||||
threads = []
|
threads = []
|
||||||
|
|
|
@ -1,68 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
from io import StringIO
|
|
||||||
from optparse import OptionParser
|
|
||||||
|
|
||||||
import numpy as np
|
|
||||||
|
|
||||||
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 = """
|
|
||||||
Create seed file taking material indices from given geom file.
|
|
||||||
Indices can be black-listed or white-listed.
|
|
||||||
|
|
||||||
""", version = scriptID)
|
|
||||||
|
|
||||||
parser.add_option('-w',
|
|
||||||
'--white',
|
|
||||||
action = 'extend', metavar = '<int LIST>',
|
|
||||||
dest = 'whitelist',
|
|
||||||
help = 'whitelist of grain IDs')
|
|
||||||
parser.add_option('-b',
|
|
||||||
'--black',
|
|
||||||
action = 'extend', metavar = '<int LIST>',
|
|
||||||
dest = 'blacklist',
|
|
||||||
help = 'blacklist of grain IDs')
|
|
||||||
|
|
||||||
parser.set_defaults(whitelist = [],
|
|
||||||
blacklist = [],
|
|
||||||
)
|
|
||||||
|
|
||||||
(options,filenames) = parser.parse_args()
|
|
||||||
if filenames == []: filenames = [None]
|
|
||||||
|
|
||||||
options.whitelist = [int(i) for i in options.whitelist]
|
|
||||||
options.blacklist = [int(i) for i in options.blacklist]
|
|
||||||
|
|
||||||
for name in filenames:
|
|
||||||
damask.util.report(scriptName,name)
|
|
||||||
|
|
||||||
geom = damask.Geom.load_ASCII(StringIO(''.join(sys.stdin.read())) if name is None else name)
|
|
||||||
material = geom.material.reshape((-1,1),order='F')
|
|
||||||
|
|
||||||
mask = np.logical_and(np.in1d(material,options.whitelist,invert=False) if options.whitelist else \
|
|
||||||
np.full(geom.grid.prod(),True,dtype=bool),
|
|
||||||
np.in1d(material,options.blacklist,invert=True) if options.blacklist else \
|
|
||||||
np.full(geom.grid.prod(),True,dtype=bool))
|
|
||||||
|
|
||||||
seeds = damask.grid_filters.cell_coord0(geom.grid,geom.size).reshape(-1,3,order='F')
|
|
||||||
|
|
||||||
comments = geom.comments \
|
|
||||||
+ [scriptID + ' ' + ' '.join(sys.argv[1:]),
|
|
||||||
'grid\ta {}\tb {}\tc {}'.format(*geom.grid),
|
|
||||||
'size\tx {}\ty {}\tz {}'.format(*geom.size),
|
|
||||||
'origin\tx {}\ty {}\tz {}'.format(*geom.origin),
|
|
||||||
]
|
|
||||||
|
|
||||||
damask.Table(seeds[mask],{'pos':(3,)},comments)\
|
|
||||||
.add('material',material[mask].astype(int))\
|
|
||||||
.save(sys.stdout if name is None else os.path.splitext(name)[0]+'.seeds',legacy=True)
|
|
|
@ -1,165 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
from optparse import OptionParser,OptionGroup
|
|
||||||
|
|
||||||
import numpy as np
|
|
||||||
from scipy import spatial
|
|
||||||
|
|
||||||
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', description = """
|
|
||||||
Distribute given number of points randomly within rectangular cuboid.
|
|
||||||
Reports positions with random crystal orientations in seeds file format to STDOUT.
|
|
||||||
|
|
||||||
""", version = scriptID)
|
|
||||||
|
|
||||||
parser.add_option('-N',
|
|
||||||
dest = 'N',
|
|
||||||
type = 'int', metavar = 'int',
|
|
||||||
help = 'number of seed points [%default]')
|
|
||||||
parser.add_option('-s',
|
|
||||||
'--size',
|
|
||||||
dest = 'size',
|
|
||||||
type = 'float', nargs = 3, metavar = 'float float float',
|
|
||||||
help='size x,y,z of unit cube to fill %default')
|
|
||||||
parser.add_option('-g',
|
|
||||||
'--grid',
|
|
||||||
dest = 'grid',
|
|
||||||
type = 'int', nargs = 3, metavar = 'int int int',
|
|
||||||
help='min a,b,c grid of hexahedral box %default')
|
|
||||||
parser.add_option('-m',
|
|
||||||
'--microstructure',
|
|
||||||
dest = 'microstructure',
|
|
||||||
type = 'int', metavar = 'int',
|
|
||||||
help = 'first microstructure index [%default]')
|
|
||||||
parser.add_option('-r',
|
|
||||||
'--rnd',
|
|
||||||
dest = 'randomSeed', type = 'int', metavar = 'int',
|
|
||||||
help = 'seed of random number generator [%default]')
|
|
||||||
|
|
||||||
group = OptionGroup(parser, "Laguerre Tessellation",
|
|
||||||
"Parameters determining shape of weight distribution of seed points"
|
|
||||||
)
|
|
||||||
group.add_option( '-w',
|
|
||||||
'--weights',
|
|
||||||
action = 'store_true',
|
|
||||||
dest = 'weights',
|
|
||||||
help = 'assign random weights to seed points for Laguerre tessellation [%default]')
|
|
||||||
group.add_option( '--max',
|
|
||||||
dest = 'max',
|
|
||||||
type = 'float', metavar = 'float',
|
|
||||||
help = 'max of uniform distribution for weights [%default]')
|
|
||||||
group.add_option( '--mean',
|
|
||||||
dest = 'mean',
|
|
||||||
type = 'float', metavar = 'float',
|
|
||||||
help = 'mean of normal distribution for weights [%default]')
|
|
||||||
group.add_option( '--sigma',
|
|
||||||
dest = 'sigma',
|
|
||||||
type = 'float', metavar = 'float',
|
|
||||||
help='standard deviation of normal distribution for weights [%default]')
|
|
||||||
parser.add_option_group(group)
|
|
||||||
|
|
||||||
group = OptionGroup(parser, "Selective Seeding",
|
|
||||||
"More uniform distribution of seed points using Mitchell's Best Candidate Algorithm"
|
|
||||||
)
|
|
||||||
group.add_option( '--selective',
|
|
||||||
action = 'store_true',
|
|
||||||
dest = 'selective',
|
|
||||||
help = 'selective picking of seed points from random seed points')
|
|
||||||
group.add_option( '--distance',
|
|
||||||
dest = 'distance',
|
|
||||||
type = 'float', metavar = 'float',
|
|
||||||
help = 'minimum distance to next neighbor [%default]')
|
|
||||||
group.add_option( '--numCandidates',
|
|
||||||
dest = 'numCandidates',
|
|
||||||
type = 'int', metavar = 'int',
|
|
||||||
help = 'size of point group to select best distance from [%default]')
|
|
||||||
parser.add_option_group(group)
|
|
||||||
|
|
||||||
parser.set_defaults(randomSeed = None,
|
|
||||||
grid = (16,16,16),
|
|
||||||
size = (1.0,1.0,1.0),
|
|
||||||
N = 20,
|
|
||||||
weights = False,
|
|
||||||
max = 0.0,
|
|
||||||
mean = 0.2,
|
|
||||||
sigma = 0.05,
|
|
||||||
microstructure = 1,
|
|
||||||
selective = False,
|
|
||||||
distance = 0.2,
|
|
||||||
numCandidates = 10,
|
|
||||||
)
|
|
||||||
|
|
||||||
(options,filenames) = parser.parse_args()
|
|
||||||
if filenames == []: filenames = [None]
|
|
||||||
|
|
||||||
size = np.array(options.size)
|
|
||||||
grid = np.array(options.grid)
|
|
||||||
np.random.seed(int(os.urandom(4).hex(),16) if options.randomSeed is None else options.randomSeed)
|
|
||||||
|
|
||||||
for name in filenames:
|
|
||||||
damask.util.report(scriptName,name)
|
|
||||||
|
|
||||||
if options.N > np.prod(grid):
|
|
||||||
damask.util.croak('More seeds than grid positions.')
|
|
||||||
sys.exit()
|
|
||||||
if options.selective and options.distance < min(size/grid):
|
|
||||||
damask.util.croak('Distance must be larger than grid spacing.')
|
|
||||||
sys.exit()
|
|
||||||
if options.selective and options.distance**3*options.N > 0.5*np.prod(size):
|
|
||||||
damask.util.croak('Number of seeds for given size and distance should be < {}.'\
|
|
||||||
.format(int(0.5*np.prod(size)/options.distance**3)))
|
|
||||||
|
|
||||||
eulers = np.random.rand(options.N,3) # create random Euler triplets
|
|
||||||
eulers[:,0] *= 360.0 # phi_1 is uniformly distributed
|
|
||||||
eulers[:,1] = np.degrees(np.arccos(2*eulers[:,1]-1.0)) # cos(Phi) is uniformly distributed
|
|
||||||
eulers[:,2] *= 360.0 # phi_2 is uniformly distributed
|
|
||||||
|
|
||||||
|
|
||||||
if not options.selective:
|
|
||||||
coords = damask.grid_filters.cell_coord0(grid,size).reshape(-1,3,order='F')
|
|
||||||
seeds = coords[np.random.choice(np.prod(grid), options.N, replace=False)] \
|
|
||||||
+ np.broadcast_to(size/grid,(options.N,3))*(np.random.rand(options.N,3)*.5-.25) # wobble without leaving grid
|
|
||||||
else:
|
|
||||||
seeds = np.empty((options.N,3))
|
|
||||||
seeds[0] = np.random.random(3) * size
|
|
||||||
|
|
||||||
i = 1
|
|
||||||
progress = damask.util._ProgressBar(options.N,'',50)
|
|
||||||
while i < options.N:
|
|
||||||
candidates = np.random.rand(options.numCandidates,3)*np.broadcast_to(size,(options.numCandidates,3))
|
|
||||||
tree = spatial.cKDTree(seeds[:i])
|
|
||||||
distances, dev_null = tree.query(candidates)
|
|
||||||
best = distances.argmax()
|
|
||||||
if distances[best] > options.distance: # require minimum separation
|
|
||||||
seeds[i] = candidates[best] # maximum separation to existing point cloud
|
|
||||||
i += 1
|
|
||||||
progress.update(i)
|
|
||||||
|
|
||||||
|
|
||||||
comments = [scriptID + ' ' + ' '.join(sys.argv[1:]),
|
|
||||||
'grid\ta {}\tb {}\tc {}'.format(*grid),
|
|
||||||
'size\tx {}\ty {}\tz {}'.format(*size),
|
|
||||||
'randomSeed\t{}'.format(options.randomSeed),
|
|
||||||
]
|
|
||||||
|
|
||||||
table = damask.Table(np.hstack((seeds,eulers)),{'pos':(3,),'euler':(3,)},comments)\
|
|
||||||
.add('microstructure',np.arange(options.microstructure,options.microstructure + options.N,dtype=int))
|
|
||||||
|
|
||||||
if options.weights:
|
|
||||||
weights = np.random.uniform(low = 0, high = options.max, size = options.N) if options.max > 0.0 \
|
|
||||||
else np.random.normal(loc = options.mean, scale = options.sigma, size = options.N)
|
|
||||||
table = table.add('weight',weights)
|
|
||||||
|
|
||||||
table.save(sys.stdout if name is None else name,legacy=True)
|
|
|
@ -147,12 +147,12 @@ class Colormap(mpl.colors.ListedColormap):
|
||||||
|
|
||||||
References
|
References
|
||||||
----------
|
----------
|
||||||
.. [1] DAMASK colormap theory
|
[1] DAMASK colormap theory
|
||||||
https://www.kennethmoreland.com/color-maps/ColorMapsExpanded.pdf
|
https://www.kennethmoreland.com/color-maps/ColorMapsExpanded.pdf
|
||||||
.. [2] DAMASK colormaps first use
|
[2] DAMASK colormaps first use
|
||||||
https://doi.org/10.1016/j.ijplas.2012.09.012
|
https://doi.org/10.1016/j.ijplas.2012.09.012
|
||||||
.. [3] Matplotlib colormaps overview
|
[3] Matplotlib colormaps overview
|
||||||
https://matplotlib.org/tutorials/colors/colormaps.html
|
https://matplotlib.org/tutorials/colors/colormaps.html
|
||||||
|
|
||||||
"""
|
"""
|
||||||
print('DAMASK colormaps')
|
print('DAMASK colormaps')
|
||||||
|
|
|
@ -406,9 +406,9 @@ class Geom:
|
||||||
locations (cell centers) are addressed.
|
locations (cell centers) are addressed.
|
||||||
If given as floats, coordinates are addressed.
|
If given as floats, coordinates are addressed.
|
||||||
exponent : numpy.ndarray of shape(3) or float
|
exponent : numpy.ndarray of shape(3) or float
|
||||||
Exponents for the three axis.
|
Exponents for the three axes.
|
||||||
0 gives octahedron (|x|^(2^0) + |y|^(2^0) + |z|^(2^0) < 1)
|
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)
|
1 gives sphere (ǀxǀ^(2^1) + ǀyǀ^(2^1) + ǀzǀ^(2^1) < 1)
|
||||||
fill : int, optional
|
fill : int, optional
|
||||||
Fill value for primitive. Defaults to material.max() + 1.
|
Fill value for primitive. Defaults to material.max() + 1.
|
||||||
R : damask.Rotation, optional
|
R : damask.Rotation, optional
|
||||||
|
|
|
@ -212,7 +212,7 @@ class Rotation:
|
||||||
Returns
|
Returns
|
||||||
-------
|
-------
|
||||||
q : numpy.ndarray of shape (...,4)
|
q : numpy.ndarray of shape (...,4)
|
||||||
Unit quaternion in positive real hemisphere: (q_0, q_1, q_2, q_3), |q|=1, q_0 ≥ 0.
|
Unit quaternion in positive real hemisphere: (q_0, q_1, q_2, q_3), ǀqǀ=1, q_0 ≥ 0.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
return self.quaternion.copy()
|
return self.quaternion.copy()
|
||||||
|
@ -255,7 +255,7 @@ class Rotation:
|
||||||
-------
|
-------
|
||||||
axis_angle : numpy.ndarray of shape (...,4) unless pair == True:
|
axis_angle : numpy.ndarray of shape (...,4) unless pair == True:
|
||||||
tuple containing numpy.ndarray of shapes (...,3) and (...)
|
tuple containing numpy.ndarray of shapes (...,3) and (...)
|
||||||
Axis angle pair: (n_1, n_2, n_3, ω), |n| = 1 and ω ∈ [0,π]
|
Axis angle pair: (n_1, n_2, n_3, ω), ǀnǀ = 1 and ω ∈ [0,π]
|
||||||
unless degrees = True: ω ∈ [0,180].
|
unless degrees = True: ω ∈ [0,180].
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
@ -290,7 +290,7 @@ class Rotation:
|
||||||
-------
|
-------
|
||||||
rho : numpy.ndarray of shape (...,4) unless vector == True:
|
rho : numpy.ndarray of shape (...,4) unless vector == True:
|
||||||
numpy.ndarray of shape (...,3)
|
numpy.ndarray of shape (...,3)
|
||||||
Rodrigues-Frank vector: [n_1, n_2, n_3, tan(ω/2)], |n| = 1 and ω ∈ [0,π].
|
Rodrigues-Frank vector: [n_1, n_2, n_3, tan(ω/2)], ǀnǀ = 1 and ω ∈ [0,π].
|
||||||
|
|
||||||
"""
|
"""
|
||||||
ro = Rotation._qu2ro(self.quaternion)
|
ro = Rotation._qu2ro(self.quaternion)
|
||||||
|
@ -307,7 +307,7 @@ class Rotation:
|
||||||
Returns
|
Returns
|
||||||
-------
|
-------
|
||||||
h : numpy.ndarray of shape (...,3)
|
h : numpy.ndarray of shape (...,3)
|
||||||
Homochoric vector: (h_1, h_2, h_3), |h| < 1/2*π^(2/3).
|
Homochoric vector: (h_1, h_2, h_3), ǀhǀ < 1/2*π^(2/3).
|
||||||
|
|
||||||
"""
|
"""
|
||||||
return Rotation._qu2ho(self.quaternion)
|
return Rotation._qu2ho(self.quaternion)
|
||||||
|
@ -353,7 +353,7 @@ class Rotation:
|
||||||
----------
|
----------
|
||||||
q : numpy.ndarray of shape (...,4)
|
q : numpy.ndarray of shape (...,4)
|
||||||
Unit quaternion in positive real hemisphere: (q_0, q_1, q_2, q_3),
|
Unit quaternion in positive real hemisphere: (q_0, q_1, q_2, q_3),
|
||||||
|q|=1, q_0 ≥ 0.
|
ǀqǀ=1, q_0 ≥ 0.
|
||||||
accept_homomorph : boolean, optional
|
accept_homomorph : boolean, optional
|
||||||
Allow homomorphic variants, i.e. q_0 < 0 (negative real hemisphere).
|
Allow homomorphic variants, i.e. q_0 < 0 (negative real hemisphere).
|
||||||
Defaults to False.
|
Defaults to False.
|
||||||
|
@ -416,12 +416,12 @@ class Rotation:
|
||||||
Parameters
|
Parameters
|
||||||
----------
|
----------
|
||||||
axis_angle : numpy.ndarray of shape (...,4)
|
axis_angle : numpy.ndarray of shape (...,4)
|
||||||
Axis angle pair: [n_1, n_2, n_3, ω], |n| = 1 and ω ∈ [0,π]
|
Axis angle pair: [n_1, n_2, n_3, ω], ǀnǀ = 1 and ω ∈ [0,π]
|
||||||
unless degrees = True: ω ∈ [0,180].
|
unless degrees = True: ω ∈ [0,180].
|
||||||
degrees : boolean, optional
|
degrees : boolean, optional
|
||||||
Angle ω is given in degrees. Defaults to False.
|
Angle ω is given in degrees. Defaults to False.
|
||||||
normalize: boolean, optional
|
normalize: boolean, optional
|
||||||
Allow |n| ≠ 1. Defaults to False.
|
Allow ǀnǀ ≠ 1. Defaults to False.
|
||||||
P : int ∈ {-1,1}, optional
|
P : int ∈ {-1,1}, optional
|
||||||
Convention used. Defaults to -1.
|
Convention used. Defaults to -1.
|
||||||
|
|
||||||
|
@ -503,9 +503,9 @@ class Rotation:
|
||||||
----------
|
----------
|
||||||
rho : numpy.ndarray of shape (...,4)
|
rho : numpy.ndarray of shape (...,4)
|
||||||
Rodrigues-Frank vector (angle separated from axis).
|
Rodrigues-Frank vector (angle separated from axis).
|
||||||
(n_1, n_2, n_3, tan(ω/2)), |n| = 1 and ω ∈ [0,π].
|
(n_1, n_2, n_3, tan(ω/2)), ǀnǀ = 1 and ω ∈ [0,π].
|
||||||
normalize : boolean, optional
|
normalize : boolean, optional
|
||||||
Allow |n| ≠ 1. Defaults to False.
|
Allow ǀnǀ ≠ 1. Defaults to False.
|
||||||
P : int ∈ {-1,1}, optional
|
P : int ∈ {-1,1}, optional
|
||||||
Convention used. Defaults to -1.
|
Convention used. Defaults to -1.
|
||||||
|
|
||||||
|
@ -534,7 +534,7 @@ class Rotation:
|
||||||
Parameters
|
Parameters
|
||||||
----------
|
----------
|
||||||
h : numpy.ndarray of shape (...,3)
|
h : numpy.ndarray of shape (...,3)
|
||||||
Homochoric vector: (h_1, h_2, h_3), |h| < (3/4*π)^(1/3).
|
Homochoric vector: (h_1, h_2, h_3), ǀhǀ < (3/4*π)^(1/3).
|
||||||
P : int ∈ {-1,1}, optional
|
P : int ∈ {-1,1}, optional
|
||||||
Convention used. Defaults to -1.
|
Convention used. Defaults to -1.
|
||||||
|
|
||||||
|
|
|
@ -95,7 +95,7 @@ def from_geom(geom,selection=None,invert=False,average=False,periodic=True):
|
||||||
"""
|
"""
|
||||||
material = geom.material.reshape((-1,1),order='F')
|
material = geom.material.reshape((-1,1),order='F')
|
||||||
mask = _np.full(geom.grid.prod(),True,dtype=bool) if selection is None else \
|
mask = _np.full(geom.grid.prod(),True,dtype=bool) if selection is None else \
|
||||||
_np.isin(material,selection,invert=invert)
|
_np.isin(material,selection,invert=invert).flatten()
|
||||||
coords = grid_filters.cell_coord0(geom.grid,geom.size).reshape(-1,3,order='F')
|
coords = grid_filters.cell_coord0(geom.grid,geom.size).reshape(-1,3,order='F')
|
||||||
|
|
||||||
if not average:
|
if not average:
|
||||||
|
|
|
@ -3,6 +3,7 @@ import numpy as np
|
||||||
from scipy.spatial import cKDTree
|
from scipy.spatial import cKDTree
|
||||||
|
|
||||||
from damask import seeds
|
from damask import seeds
|
||||||
|
from damask import grid_filters
|
||||||
from damask import Geom
|
from damask import Geom
|
||||||
|
|
||||||
class TestSeeds:
|
class TestSeeds:
|
||||||
|
@ -25,7 +26,7 @@ class TestSeeds:
|
||||||
cKDTree(coords).query(coords, 2)
|
cKDTree(coords).query(coords, 2)
|
||||||
assert (0<= coords).all() and (coords<size).all() and np.min(min_dists[:,1])>=distance
|
assert (0<= coords).all() and (coords<size).all() and np.min(min_dists[:,1])>=distance
|
||||||
|
|
||||||
def test_from_geom(self):
|
def test_from_geom_reconstruct(self):
|
||||||
grid = np.random.randint(10,20,3)
|
grid = np.random.randint(10,20,3)
|
||||||
N_seeds = np.random.randint(30,300)
|
N_seeds = np.random.randint(30,300)
|
||||||
size = np.ones(3) + np.random.random(3)
|
size = np.ones(3) + np.random.random(3)
|
||||||
|
@ -34,3 +35,28 @@ class TestSeeds:
|
||||||
coords,material = seeds.from_geom(geom_1)
|
coords,material = seeds.from_geom(geom_1)
|
||||||
geom_2 = Geom.from_Voronoi_tessellation(grid,size,coords,material)
|
geom_2 = Geom.from_Voronoi_tessellation(grid,size,coords,material)
|
||||||
assert (geom_2.material==geom_1.material).all()
|
assert (geom_2.material==geom_1.material).all()
|
||||||
|
|
||||||
|
@pytest.mark.parametrize('periodic',[True,False])
|
||||||
|
@pytest.mark.parametrize('average',[True,False])
|
||||||
|
def test_from_geom_grid(self,periodic,average):
|
||||||
|
grid = np.random.randint(10,20,3)
|
||||||
|
size = np.ones(3) + np.random.random(3)
|
||||||
|
coords = grid_filters.cell_coord0(grid,size).reshape(-1,3)
|
||||||
|
np.random.shuffle(coords)
|
||||||
|
geom_1 = Geom.from_Voronoi_tessellation(grid,size,coords)
|
||||||
|
coords,material = seeds.from_geom(geom_1,average=average,periodic=periodic)
|
||||||
|
geom_2 = Geom.from_Voronoi_tessellation(grid,size,coords,material)
|
||||||
|
assert (geom_2.material==geom_1.material).all()
|
||||||
|
|
||||||
|
@pytest.mark.parametrize('periodic',[True,False])
|
||||||
|
@pytest.mark.parametrize('average',[True,False])
|
||||||
|
@pytest.mark.parametrize('invert',[True,False])
|
||||||
|
def test_from_geom_selection(self,periodic,average,invert):
|
||||||
|
grid = np.random.randint(10,20,3)
|
||||||
|
N_seeds = np.random.randint(30,300)
|
||||||
|
size = np.ones(3) + np.random.random(3)
|
||||||
|
coords = seeds.from_random(size,N_seeds,grid)
|
||||||
|
geom = Geom.from_Voronoi_tessellation(grid,size,coords)
|
||||||
|
selection=np.random.randint(N_seeds)+1
|
||||||
|
coords,material = seeds.from_geom(geom,average=average,periodic=periodic,invert=invert,selection=[selection])
|
||||||
|
assert selection not in material if invert else (selection==material).all()
|
||||||
|
|
|
@ -61,13 +61,13 @@ void signalusr2_c(void (*handler)(int)){
|
||||||
|
|
||||||
void inflate_c(const uLong *s_deflated, const uLong *s_inflated, const Byte deflated[], Byte inflated[]){
|
void inflate_c(const uLong *s_deflated, const uLong *s_inflated, const Byte deflated[], Byte inflated[]){
|
||||||
/* make writable copy, uncompress will write to it */
|
/* make writable copy, uncompress will write to it */
|
||||||
uLong s_inflated_;
|
uLong s_inflated_,i;
|
||||||
s_inflated_ = *s_inflated;
|
s_inflated_ = *s_inflated;
|
||||||
|
|
||||||
if(uncompress((Bytef *)inflated, &s_inflated_, (Bytef *)deflated, *s_deflated) == Z_OK)
|
if(uncompress((Bytef *)inflated, &s_inflated_, (Bytef *)deflated, *s_deflated) == Z_OK)
|
||||||
return;
|
return;
|
||||||
else{
|
else{
|
||||||
for(uLong i=0;i<*s_inflated;i++){
|
for(i=0;i<*s_inflated;i++){
|
||||||
inflated[i] = 0;
|
inflated[i] = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,21 +46,21 @@ subroutine parallelization_init
|
||||||
! If openMP is enabled, check if the MPI libary supports it and initialize accordingly.
|
! If openMP is enabled, check if the MPI libary supports it and initialize accordingly.
|
||||||
! Otherwise, the first call to PETSc will do the initialization.
|
! Otherwise, the first call to PETSc will do the initialization.
|
||||||
call MPI_Init_Thread(MPI_THREAD_FUNNELED,threadLevel,err)
|
call MPI_Init_Thread(MPI_THREAD_FUNNELED,threadLevel,err)
|
||||||
if (err /= 0) error stop 'MPI init failed'
|
if (err /= 0) error stop 'MPI init failed'
|
||||||
if (threadLevel<MPI_THREAD_FUNNELED) error stop 'MPI library does not support OpenMP'
|
if (threadLevel<MPI_THREAD_FUNNELED) error stop 'MPI library does not support OpenMP'
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
call PETScInitializeNoArguments(petsc_err) ! first line in the code according to PETSc manual
|
call PETScInitializeNoArguments(petsc_err) ! first line in the code according to PETSc manual
|
||||||
CHKERRQ(petsc_err)
|
CHKERRQ(petsc_err)
|
||||||
|
|
||||||
call MPI_Comm_rank(PETSC_COMM_WORLD,worldrank,err)
|
call MPI_Comm_rank(PETSC_COMM_WORLD,worldrank,err)
|
||||||
if (err /= 0) error stop 'Could not determine worldrank'
|
if (err /= 0) error stop 'Could not determine worldrank'
|
||||||
|
|
||||||
if (worldrank == 0) print'(/,a)', ' <<<+- parallelization init -+>>>'
|
if (worldrank == 0) print'(/,a)', ' <<<+- parallelization init -+>>>'
|
||||||
if (worldrank == 0) print'(a,i3)', ' MPI processes: ',worldsize
|
|
||||||
|
|
||||||
call MPI_Comm_size(PETSC_COMM_WORLD,worldsize,err)
|
call MPI_Comm_size(PETSC_COMM_WORLD,worldsize,err)
|
||||||
if (err /= 0) error stop 'Could not determine worldsize'
|
if (err /= 0) error stop 'Could not determine worldsize'
|
||||||
|
if (worldrank == 0) print'(a,i3)', ' MPI processes: ',worldsize
|
||||||
|
|
||||||
call MPI_Type_size(MPI_INTEGER,typeSize,err)
|
call MPI_Type_size(MPI_INTEGER,typeSize,err)
|
||||||
if (err /= 0) error stop 'Could not determine MPI integer size'
|
if (err /= 0) error stop 'Could not determine MPI integer size'
|
||||||
|
|
Loading…
Reference in New Issue