Merge branch 'MiscImprovements' into development

This commit is contained in:
Martin Diehl 2020-03-22 09:38:22 +01:00
commit d920efb8fe
140 changed files with 4873 additions and 7133 deletions

3
.gitignore vendored
View File

@ -1,6 +1,3 @@
*.pyc
*.hdf5
*.xdmf
*.bak
*~
.DS_Store

View File

@ -77,9 +77,9 @@ variables:
IntelMarc: "$IntelCompiler17_8"
HDF5Marc: "HDF5/1.10.5/Intel-17.8"
# ++++++++++++ Documentation ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Doxygen1_8_15: "Documentation/Doxygen/1.8.15"
Doxygen1_8_17: "Documentation/Doxygen/1.8.17"
# ------------ Defaults ----------------------------------------------
Doxygen: "$Doxygen1_8_15"
Doxygen: "$Doxygen1_8_17"
###################################################################################################
@ -490,7 +490,7 @@ GridSolver:
stage: createDocumentation
script:
- module load $IntelCompiler $MPICH_Intel $PETSc_MPICH_Intel $Doxygen
- $DAMASKROOT/PRIVATE/documenting/runDoxygen.sh $DAMASKROOT spectral
- $DAMASKROOT/PRIVATE/documenting/runDoxygen.sh $DAMASKROOT grid
except:
- master
- release

View File

@ -8,13 +8,13 @@ all: grid mesh processing
.PHONY: grid
grid: build/grid
@(cd build/grid;make -j4 all install;)
@(cd build/grid;make -j${DAMASK_NUM_THREADS} all install;)
.PHONY: spectral
spectral: grid
.PHONY: mesh
mesh: build/mesh
@(cd build/mesh; make -j4 all install;)
@(cd build/mesh; make -j${DAMASK_NUM_THREADS} all install;)
.PHONY: FEM
FEM: mesh

@ -1 +1 @@
Subproject commit d0d5b5a22be9778187b100214c782747793bb956
Subproject commit 62bd5ede5260cd4e0e3d1c3930c474c1e045aeef

9
examples/.gitignore vendored
View File

@ -1,9 +1,8 @@
*.C_ref
*.mesh
*.outputConstitutive
*.outputCrystallite
*.outputHomogenization
*.spectralOut
*.hdf5
*.xdmf
*.sta
*.vt*
*.geom
*.seeds
postProc

View File

@ -3,23 +3,16 @@
elasticity hooke
plasticity dislotwin
#(output) edge_density
#(output) dipole_density
#(output) shearrate_slip
#(output) accumulated_shear_slip
#(output) mfp_slip
#(output) resolved_stress_slip
#(output) threshold_stress_slip
#(output) twin_fraction
#(output) shearrate_twin
#(output) accumulated_shear_twin
#(output) mfp_twin
#(output) resolved_stress_twin
#(output) threshold_stress_twin
#(output) shearrate_shearband
#(output) resolved_stress_shearband
#(output) sb_eigenvalues
#(output) sb_eigenvectors
(output) rho_mob
(output) rho_dip
(output) gamma_sl
(output) lambda_sl
(output) tau_pass
(output) f_tw
(output) lambda_tw
(output) tau_hat_tw
(output) f_tr
### Material parameters ###
lattice_structure fcc
@ -45,7 +38,6 @@ 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^3]
Cedgedipmindistance 1.0 # Adj. parameter controlling the minimum dipole distance [in b]
atol_rho 1.0
interactionSlipSlip 0.122 0.122 0.625 0.07 0.137 0.122 # Interaction coefficients (Kubin et al. 2008)
### Shearband parameters ###
@ -68,6 +60,5 @@ Cmfptwin 1.0 # Adj. parameter controlling twin mean free
Cthresholdtwin 1.0 # Adj. parameter controlling twin threshold stress
interactionSlipTwin 0.0 1.0 1.0 # Dislocation-Twin interaction coefficients
interactionTwinTwin 0.0 1.0 # Twin-Twin interaction coefficients
atol_twinFrac 1.0e-7
SFE_0K -0.0396 # stacking fault energy at zero K; TWIP steel: -0.0526; Cu: -0.0396
dSFE_dT 0.0002 # temperature dependance of stacking fault energy

View File

@ -18,4 +18,3 @@ n 20
h0 75e6
tausat 63e6
a 2.25
atol_resistance 1

View File

@ -22,4 +22,3 @@ h0 1e6
n 5
m 3
a 2
atol_resistance 1

View File

@ -66,6 +66,4 @@ cutoffRadius 1e-3 # cutoff radius for dislocation
CFLfactor 2.0 # safety factor for CFL flux check (numerical parameter)
significantRho 1e6 # minimum dislocation density considered relevant in m/m**3
#significantN 0.1 # minimum dislocation number per ip considered relevant
aTol_density 1e4 # absolute tolerance for dislocation density in m/m**3
aTol_shear 1e-20 # absolute tolerance for plasgtic shear
randomMultiplication 0 # switch for probabilistic extension of multiplication rate

View File

@ -27,7 +27,7 @@ Nslip 12 # number of slip systems per family
c11 246.5e9
c12 147.3e9
c44 124.7e9
burgers 2.48e-10 0 0 0 # Burgers vector in m
burgers 2.48e-10 # Burgers vector in m
rhoSglEdgePos0 6e10 # Initial positive edge single dislocation density in m/m**3
rhoSglEdgeNeg0 6e10 # Initial negative edge single dislocation density in m/m**3
rhoSglScrewPos0 6e10 # Initial positive screw single dislocation density in m/m**3
@ -55,8 +55,6 @@ q 1 # exponent for thermal barrier
attackFrequency 50e9 # attack frequency in Hz
surfaceTransmissivity 1.0 # transmissivity of free surfaces for dislocation flux
grainBoundaryTransmissivity 0.0
aTol_rho 1e100 # absolute tolerance for dislocation density in m/m**3
aTol_shear 1e10 # absolute tolerance for dislocation density in m/m**3
significantRho 1e8 # dislocation density considered relevant in m/m**3
significantN 1
shortRangeStressCorrection 0

View File

@ -3,13 +3,10 @@ elasticity hooke
plasticity phenopowerlaw
(output) resistance_slip
(output) shearrate_slip
(output) resolvedstress_slip
(output) accumulated_shear_slip
(output) accumulatedshear_slip
lattice_structure fcc
Nslip 12 # per family
Ntwin 0 # per family
c11 106.75e9
c12 60.41e9
@ -22,4 +19,3 @@ tausat_slip 63e6 # per family
a_slip 2.25
h0_slipslip 75e6
interaction_slipslip 1 1 1.4 1.4 1.4 1.4
atol_resistance 1

View File

@ -1,5 +1,3 @@
# parameters fitted by D. Ma to:
# I. Kovács, G. Vörös
# On the mathematical description of the tensile stress-strain curves of polycrystalline face centered cubic metals
@ -7,20 +5,13 @@
# DOI: 10.1016/S0749-6419(95)00043-7
[gold_phenopowerlaw]
# slip only
elasticity hooke
plasticity phenopowerlaw
(output) resistance_slip
(output) shearrate_slip
(output) resolvedstress_slip
(output) resistance_twin
(output) shearrate_twin
(output) resolvedstress_twin
lattice_structure fcc
Nslip 12 # per family
Ntwin 0 # per family
c11 191.0e9
c12 162.0e9
@ -31,9 +22,6 @@ n_slip 83.3
tau0_slip 26.25e6 # per family
tausat_slip 53.00e6 # per family
a_slip 1.0
gdot0_twin 0.001
n_twin 20
h0_slipslip 75e6
interaction_slipslip 1 1 1.4 1.4 1.4 1.4
atol_resistance 1

View File

@ -7,11 +7,7 @@ plasticity phenopowerlaw
elasticity hooke
(output) resistance_slip
(output) shearrate_slip
(output) resolvedstress_slip
(output) resistance_twin
(output) shearrate_twin
(output) resolvedstress_twin
lattice_structure hex
c/a 1.62350 # from Tromans 2011, Elastic Anisotropy of HCP Metal Crystals and Polycrystals
@ -45,9 +41,6 @@ interaction_twinslip 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
####################################################
# open for discussion
####################################################
atol_resistance 1
atol_shear 1e-6
atol_twinfrac 1e-6
n_twin 20
n_slip 20

View File

@ -2,13 +2,6 @@
plasticity phenopowerlaw
elasticity hooke
# (output) resistance_slip
# (output) shearrate_slip
# (output) resolvedstress_slip
# (output) resistance_twin
# (output) shearrate_twin
# (output) resolvedstress_twin
lattice_structure hex
covera_ratio 1.587
@ -21,28 +14,10 @@ c44 46.5e9
# C. Zambaldi, "Orientation informed nanoindentation of a-titanium: Indentation pileup in hexagonal metals deforming by prismatic slip", J. Mater. Res., Vol. 27, No. 1, Jan 14, 2012
gdot0_slip 0.001
n_slip 20
nslip 3 3 0 6 0 0
tau0_slip 349.3e6 150e6 0 1107.9e6 0 0
tausat_slip 568.6e6 1502.2e6 0 3420.1e6 0 0
nslip 3 3 0 6
tau0_slip 349.3e6 150e6 0 1107.9e6
tausat_slip 568.6e6 1502.2e6 0 3420.1e6
a_slip 2
ntwin 0 0 0 0
gdot0_twin 0.001 0 0 0
n_twin 20
tau0_twin 31e6 0 0 0 0
s_pr 0
twin_b 0
twin_c 0
twin_d 0
twin_e 0
h0_slipslip 15e6
h0_twinslip 15e6
h0_twintwin 15e6
atol_resistance 1
#atol_shear 1e-6
#atol_twinfrac 1e-7
interaction_slipslip 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
interaction_sliptwin 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
interaction_twinslip 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
interaction_twintwin 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
#nonschmid_coefficients 0

View File

@ -14,7 +14,6 @@ plasticity phenopowerlaw
lattice_structure fcc
Nslip 12 # per family
Ntwin 0 # per family
c11 106.75e9
c12 60.41e9
@ -25,22 +24,8 @@ n_slip 20
tau0_slip 31e6 # per family
tausat_slip 63e6 # per family
a_slip 2.25
gdot0_twin 0.001
n_twin 20
tau0_twin 31e6 # per family
s_pr 0 # push-up factor for slip saturation due to twinning
twin_b 0
twin_c 0
twin_d 0
twin_e 0
h0_slipslip 75e6
h0_twinslip 0
h0_twintwin 0
interaction_slipslip 1 1 1.4 1.4 1.4 1.4
interaction_sliptwin 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
interaction_twinslip 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
interaction_twintwin 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
atol_resistance 1
(output) f
(output) p

View File

@ -1,8 +1,7 @@
4 header
3 header
grid a 16 b 16 c 16
microstructures 20
random seed 0
1_pos 2_pos 3_pos 1_eulerangels 2_eulerangels 3_eulerangels
1_pos 2_pos 3_pos 1_euler 2_euler 3_euler
0.375488 0.161813 0.891040 197.572861 16.816409 129.422844
0.187988 0.849313 0.953540 257.468172 53.250534 157.331503
0.750488 0.349313 0.953540 216.994815 94.418518 251.147231

View File

@ -13,15 +13,6 @@ elasticity hooke
plasticity phenopowerlaw
(output) resistance_slip
(output) shearrate_slip
(output) resolvedstress_slip
(output) accumulatedshear_slip
(output) resistance_twin
(output) shearrate_twin
(output) resolvedstress_twin
(output) accumulatedshear_twin
# only for HDF5 out
(output) orientation # quaternion
(output) F # deformation gradient tensor
(output) Fe # elastic deformation gradient tensor
@ -32,7 +23,6 @@ plasticity phenopowerlaw
lattice_structure fcc
Nslip 12 # per family
Ntwin 0 # per family
c11 106.75e9
c12 60.41e9
@ -45,7 +35,6 @@ tausat_slip 63e6 # per family
a_slip 2.25
h0_slipslip 75e6
interaction_slipslip 1 1 1.4 1.4 1.4 1.4
atol_resistance 1
#-------------------#
<microstructure>

View File

@ -15,10 +15,6 @@ scriptID = ' '.join([scriptName,damask.version])
# --------------------------------------------------------------------
parser = argparse.ArgumentParser()
#ToDo: We need to decide on a way of handling arguments of variable lentght
#https://stackoverflow.com/questions/15459997/passing-integer-lists-to-python
#parser.add_argument('--version', action='version', version='%(prog)s {}'.format(scriptID))
parser.add_argument('filenames', nargs='+',
help='DADF5 files')
parser.add_argument('-d','--dir', dest='dir',default='postProc',metavar='string',
@ -33,38 +29,31 @@ options = parser.parse_args()
if options.mat is None: options.mat=[]
if options.con is None: options.con=[]
# --- loop over input files ------------------------------------------------------------------------
for filename in options.filenames:
results = damask.DADF5(filename)
results = damask.Result(filename)
if not results.structured: continue
if results.version_major == 0 and results.version_minor >= 5:
coords = damask.grid_filters.cell_coord0(results.grid,results.size,results.origin)
else:
coords = damask.grid_filters.cell_coord0(results.grid,results.size)
N_digits = int(np.floor(np.log10(int(results.increments[-1][3:]))))+1
N_digits = 5 # hack to keep test intact
for i,inc in enumerate(results.iter_visible('increments')):
print('Output step {}/{}'.format(i+1,len(results.increments)))
for inc in damask.util.show_progress(results.iterate('increments'),len(results.increments)):
table = damask.Table(np.ones(np.product(results.grid),dtype=int)*int(inc[3:]),{'inc':(1,)})
table.add('pos',coords.reshape((-1,3)))
table.add('pos',coords.reshape(-1,3))
results.pick('materialpoints',False)
results.pick('constituents', True)
for label in options.con:
x = results.get_dataset_location(label)
if len(x) != 0:
table.add(label,results.read_dataset(x,0,plain=True).reshape((results.grid.prod(),-1)))
table.add(label,results.read_dataset(x,0,plain=True).reshape(results.grid.prod(),-1))
results.pick('constituents', False)
results.pick('materialpoints',True)
for label in options.mat:
x = results.get_dataset_location(label)
if len(x) != 0:
table.add(label,results.read_dataset(x,0,plain=True).reshape((results.grid.prod(),-1)))
table.add(label,results.read_dataset(x,0,plain=True).reshape(results.grid.prod(),-1))
dirname = os.path.abspath(os.path.join(os.path.dirname(filename),options.dir))
if not os.path.isdir(dirname):

View File

@ -48,35 +48,31 @@ Phase_types = {'Primary': 0} #further additions to these can be done by looking
# MAIN
# --------------------------------------------------------------------
parser = argparse.ArgumentParser(description='Creating a file for DREAM3D from DAMASK data')
parser.add_argument('filenames',nargs='+',help='HDF5 based output file')
parser.add_argument('--inc',nargs='+',help='Increment for which DREAM3D to be used, eg. 25',type=int)
parser.add_argument('filenames', nargs='+',
help='DADF5 files')
parser.add_argument('-d','--dir', dest='dir',default='postProc',metavar='string',
help='name of subdirectory to hold output')
help='name of subdirectory relative to the location of the DADF5 file to hold output')
parser.add_argument('--inc',nargs='+',
help='Increment for which DREAM3D to be used, eg. 25',type=int)
options = parser.parse_args()
# --------------------------------------------------------------------
# loop over input files
for filename in options.filenames:
f = damask.DADF5(filename) #DAMASK output file
for increment in options.inc:
f.set_by_increment(increment,increment)
if len(f.visible['increments']) == 0:
continue
f = damask.Result(filename)
N_digits = int(np.floor(np.log10(int(f.increments[-1][3:]))))+1
#-------output file creation-------------------------------------
f.pick('increments',options.inc)
for inc in damask.util.show_progress(f.iterate('increments'),len(f.selection['increments'])):
dirname = os.path.abspath(os.path.join(os.path.dirname(filename),options.dir))
try:
os.mkdir(dirname)
except FileExistsError:
pass
o = h5py.File(dirname + '/' + os.path.splitext(filename)[0] + '_{}.dream3D'.format(increment),'w')
#-----------------------------------------------------------------
o = h5py.File(dirname + '/' + os.path.splitext(filename)[0] \
+ '_inc_{}.dream3D'.format(inc[3:].zfill(N_digits)),'w')
o.attrs['DADF5toDREAM3D'] = '1.0'
o.attrs['FileVersion'] = '7.0'
#-----------------------------------------------------------------
for g in ['DataContainerBundles','Pipeline']: # empty groups (needed)
o.create_group(g)
@ -84,10 +80,8 @@ for filename in options.filenames:
data_container_label = 'DataContainers/ImageDataContainer'
cell_data_label = data_container_label + '/CellData'
# Phase information of DREAM.3D is constituent ID in DAMASK
o[cell_data_label + '/Phases'] = f.get_constituent_ID().reshape(tuple(f.grid)+(1,))
# Data quaternions
DAMASK_quaternion = f.read_dataset(f.get_dataset_location('orientation'))
# Convert: DAMASK uses P = -1, DREAM.3D uses P = +1. Also change position of imagninary part
DREAM_3D_quaternion = np.hstack((-DAMASK_quaternion['x'],-DAMASK_quaternion['y'],-DAMASK_quaternion['z'],
@ -103,12 +97,10 @@ for filename in options.filenames:
o[cell_data_label + group].attrs['DataArrayVersion'] = np.array([2],np.int32)
o[cell_data_label + group].attrs['Tuple Axis Dimensions'] = 'x={},y={},z={}'.format(*f.grid)
# phase attributes
o[cell_data_label + '/Phases'].attrs['ComponentDimensions'] = np.array([1],np.uint64)
o[cell_data_label + '/Phases'].attrs['ObjectType'] = 'DataArray<int32_t>'
o[cell_data_label + '/Phases'].attrs['TupleDimensions'] = f.grid.astype(np.uint64)
# Quats attributes
o[cell_data_label + '/Quats'].attrs['ComponentDimensions'] = np.array([4],np.uint64)
o[cell_data_label + '/Quats'].attrs['ObjectType'] = 'DataArray<float>'
o[cell_data_label + '/Quats'].attrs['TupleDimensions'] = f.grid.astype(np.uint64)
@ -118,8 +110,8 @@ for filename in options.filenames:
# Data CrystalStructures
o[ensemble_label + '/CrystalStructures'] = np.uint32(np.array([999,\
Crystal_structures[f.get_crystal_structure()]])).reshape((2,1))
o[ensemble_label + '/PhaseTypes'] = np.uint32(np.array([999,Phase_types['Primary']])).reshape((2,1)) # ToDo
Crystal_structures[f.get_crystal_structure()]])).reshape(2,1)
o[ensemble_label + '/PhaseTypes'] = np.uint32(np.array([999,Phase_types['Primary']])).reshape(2,1) # ToDo
# Attributes Ensemble Matrix
o[ensemble_label].attrs['AttributeMatrixType'] = np.array([11],np.uint32)
@ -133,8 +125,6 @@ for filename in options.filenames:
o[ensemble_label+'/'+group].attrs['ObjectType'] = 'DataArray<uint32_t>'
o[ensemble_label+'/'+group].attrs['TupleDimensions'] = np.array([2],np.uint64)
# Create geometry info
geom_label = data_container_label + '/_SIMPL_GEOMETRY'
o[geom_label + '/DIMENSIONS'] = np.int64(f.grid)

View File

@ -40,7 +40,7 @@ def volTetrahedron(coords):
# Get all the squares of all side lengths from the differences between
# the 6 different pairs of vertex positions
vertices = np.concatenate((coords[0],coords[1],coords[2],coords[3])).reshape([4,3])
vertices = np.concatenate((coords[0],coords[1],coords[2],coords[3])).reshape(4,3)
vertex1, vertex2 = vertex_pair_indexes[:,0], vertex_pair_indexes[:,1]
sides_squared = np.sum((vertices[vertex1] - vertices[vertex2])**2,axis=-1)
@ -185,13 +185,13 @@ for name in filenames:
centers = damask.grid_filters.cell_coord(size,F)
shapeMismatch = shapeMismatch( size,table.get(options.defgrad).reshape(grid[2],grid[1],grid[0],3,3),nodes,centers)
table.add('shapeMismatch(({}))'.format(options.defgrad),
shapeMismatch.reshape((-1,1)),
shapeMismatch.reshape(-1,1),
scriptID+' '+' '.join(sys.argv[1:]))
if options.volume:
volumeMismatch = volumeMismatch(size,table.get(options.defgrad).reshape(grid[2],grid[1],grid[0],3,3),nodes)
table.add('volMismatch(({}))'.format(options.defgrad),
volumeMismatch.reshape((-1,1)),
volumeMismatch.reshape(-1,1),
scriptID+' '+' '.join(sys.argv[1:]))
table.to_ASCII(sys.stdout if name is None else name)

View File

@ -51,7 +51,7 @@ for name in filenames:
shape = (3,) if np.prod(field.shape)//np.prod(grid) == 3 else (3,3) # vector or tensor
field = field.reshape(np.append(grid[::-1],shape))
table.add('curlFFT({})'.format(label),
damask.grid_filters.curl(size[::-1],field).reshape((-1,np.prod(shape))),
damask.grid_filters.curl(size[::-1],field).reshape(-1,np.prod(shape)),
scriptID+' '+' '.join(sys.argv[1:]))
table.to_ASCII(sys.stdout if name is None else name)

View File

@ -41,7 +41,7 @@ for name in filenames:
table = damask.Table.from_ASCII(StringIO(''.join(sys.stdin.read())) if name is None else name)
for tensor in options.tensor:
table.add('dev({})'.format(tensor),
damask.mechanics.deviatoric_part(table.get(tensor).reshape(-1,3,3)).reshape((-1,9)),
damask.mechanics.deviatoric_part(table.get(tensor).reshape(-1,3,3)).reshape(-1,9),
scriptID+' '+' '.join(sys.argv[1:]))
if options.spherical:
table.add('sph({})'.format(tensor),

View File

@ -54,20 +54,20 @@ for name in filenames:
F = table.get(options.f).reshape(np.append(grid[::-1],(3,3)))
if options.nodal:
table = damask.Table(damask.grid_filters.node_coord0(grid[::-1],size[::-1]).reshape((-1,3)),
table = damask.Table(damask.grid_filters.node_coord0(grid[::-1],size[::-1]).reshape(-1,3),
{'pos':(3,)})
table.add('avg({}).{}'.format(options.f,options.pos),
damask.grid_filters.node_displacement_avg(size[::-1],F).reshape((-1,3)),
damask.grid_filters.node_displacement_avg(size[::-1],F).reshape(-1,3),
scriptID+' '+' '.join(sys.argv[1:]))
table.add('fluct({}).{}'.format(options.f,options.pos),
damask.grid_filters.node_displacement_fluct(size[::-1],F).reshape((-1,3)),
damask.grid_filters.node_displacement_fluct(size[::-1],F).reshape(-1,3),
scriptID+' '+' '.join(sys.argv[1:]))
table.to_ASCII(sys.stdout if name is None else os.path.splitext(name)[0]+'_nodal.txt')
else:
table.add('avg({}).{}'.format(options.f,options.pos),
damask.grid_filters.cell_displacement_avg(size[::-1],F).reshape((-1,3)),
damask.grid_filters.cell_displacement_avg(size[::-1],F).reshape(-1,3),
scriptID+' '+' '.join(sys.argv[1:]))
table.add('fluct({}).{}'.format(options.f,options.pos),
damask.grid_filters.cell_displacement_fluct(size[::-1],F).reshape((-1,3)),
damask.grid_filters.cell_displacement_fluct(size[::-1],F).reshape(-1,3),
scriptID+' '+' '.join(sys.argv[1:]))
table.to_ASCII(sys.stdout if name is None else name)

View File

@ -51,7 +51,7 @@ for name in filenames:
shape = (3,) if np.prod(field.shape)//np.prod(grid) == 3 else (3,3) # vector or tensor
field = field.reshape(np.append(grid[::-1],shape))
table.add('divFFT({})'.format(label),
damask.grid_filters.divergence(size[::-1],field).reshape((-1,np.prod(shape)//3)),
damask.grid_filters.divergence(size[::-1],field).reshape(-1,np.prod(shape)//3),
scriptID+' '+' '.join(sys.argv[1:]))
table.to_ASCII(sys.stdout if name is None else name)

View File

@ -68,7 +68,7 @@ for name in filenames:
for label in options.labels:
table.add('Gauss{}({})'.format(options.sigma,label),
ndimage.filters.gaussian_filter(table.get(label).reshape((-1)),
ndimage.filters.gaussian_filter(table.get(label).reshape(-1),
options.sigma,options.order,
mode = 'wrap' if options.periodic else 'nearest'),
scriptID+' '+' '.join(sys.argv[1:]))

View File

@ -51,7 +51,7 @@ for name in filenames:
shape = (1,) if np.prod(field.shape)//np.prod(grid) == 1 else (3,) # scalar or vector
field = field.reshape(np.append(grid[::-1],shape))
table.add('gradFFT({})'.format(label),
damask.grid_filters.gradient(size[::-1],field).reshape((-1,np.prod(shape)*3)),
damask.grid_filters.gradient(size[::-1],field).reshape(-1,np.prod(shape)*3),
scriptID+' '+' '.join(sys.argv[1:]))
table.to_ASCII(sys.stdout if name is None else name)

View File

@ -59,6 +59,6 @@ for name in filenames:
idx = np.reshape(table.get(options.index).astype(int) + options.offset,(-1))-1
for data in options.label:
table.add(data+'addIndexed',indexedTable.get(data)[idx],scriptID+' '+' '.join(sys.argv[1:]))
table.add(data+'_addIndexed',indexedTable.get(data)[idx],scriptID+' '+' '.join(sys.argv[1:]))
table.to_ASCII(sys.stdout if name is None else name)

View File

@ -203,13 +203,11 @@ for name in filenames:
# ------------------------------------------ assemble header ---------------------------------------
table.info_append(scriptID + '\t' + ' '.join(sys.argv[1:]))
table.labels_append(['{id}_'
'S[{direction[0]:.1g}_{direction[1]:.1g}_{direction[2]:.1g}]'
table.labels_append(['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,
.format(normal = theNormal,
direction = theDirection,
) for i,(theNormal,theDirection) in enumerate(zip(slip_normal,slip_direction))])
) for theNormal,theDirection in zip(slip_normal,slip_direction)])
table.head_write()
# ------------------------------------------ process data ------------------------------------------

View File

@ -50,11 +50,9 @@ for name in filenames:
if options.rh: v[np.linalg.det(v) < 0.0,:,2] *= -1.0
for i,o in enumerate(['Min','Mid','Max']):
table.add('eigval{}({})'.format(o,tensor),u[:,i],
scriptID+' '+' '.join(sys.argv[1:]))
table.add('eigval{}({})'.format(o,tensor),u[:,i], scriptID+' '+' '.join(sys.argv[1:]))
for i,o in enumerate(['Min','Mid','Max']):
table.add('eigvec{}({})'.format(o,tensor),v[:,:,i],
scriptID+' '+' '.join(sys.argv[1:]))
table.add('eigvec{}({})'.format(o,tensor),v[:,:,i],scriptID+' '+' '.join(sys.argv[1:]))
table.to_ASCII(sys.stdout if name is None else name)

View File

@ -86,13 +86,13 @@ for name in filenames:
table = damask.Table.from_ASCII(StringIO(''.join(sys.stdin.read())) if name is None else name)
for defgrad in options.defgrad:
F = table.get(defgrad).reshape((-1,3,3))
F = table.get(defgrad).reshape(-1,3,3)
for theStretch in stretches:
for theStrain in strains:
(t,m) = parameters(theStretch,theStrain)
label = '{}({}){}'.format(theStrain,theStretch,defgrad if defgrad != 'f' else '')
table.add(label,
damask.mechanics.strain_tensor(F,t,m).reshape((-1,9)),
damask.mechanics.strain_tensor(F,t,m).reshape(-1,9),
scriptID+' '+' '.join(sys.argv[1:]))
table.to_ASCII(sys.stdout if name is None else name)

View File

@ -91,7 +91,7 @@ for name in filenames:
table = damask.Table(averagedDown,table.shapes,table.comments)
coords = damask.grid_filters.cell_coord0(packedGrid,size,shift/packedGrid*size+origin)
table.set(options.pos, coords.reshape((-1,3)))
table.set(options.pos, coords.reshape(-1,3))
outname = os.path.join(os.path.dirname(name),prefix+os.path.basename(name))

View File

@ -2,6 +2,7 @@
import os
import sys
from io import StringIO
from optparse import OptionParser
import numpy as np
@ -71,60 +72,30 @@ parser.set_defaults(bins = (10,10),
)
(options,filenames) = parser.parse_args()
if filenames == []: filenames = [None]
minmax = np.array([np.array(options.xrange),
np.array(options.yrange),
np.array(options.zrange)])
grid = np.zeros(options.bins,'f')
result = np.zeros((options.bins[0],options.bins[1],3),'f')
minmax = np.array([options.xrange,options.yrange,options.zrange])
result = np.empty((options.bins[0],options.bins[1],3),'f')
if options.data is None: parser.error('no data columns specified.')
labels = list(options.data)
if options.weight is not None: labels += [options.weight] # prevent character splitting of single string value
# --- 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),
'binned-{}-{}_'.format(*options.data) +
('weighted-{}_'.format(options.weight) if options.weight else '') +
os.path.basename(name)) if name else name)
except IOError:
continue
damask.util.report(scriptName,name)
# ------------------------------------------ read header ------------------------------------------
table.head_read()
# ------------------------------------------ sanity checks ----------------------------------------
missing_labels = table.data_readArray(labels)
if len(missing_labels) > 0:
damask.util.croak('column{} {} not found.'.format('s' if len(missing_labels) > 1 else '',', '.join(missing_labels)))
table.close(dismiss = True)
continue
table = damask.Table.from_ASCII(StringIO(''.join(sys.stdin.read())) if name is None else name)
data = np.hstack((table.get(options.data[0]),table.get(options.data[1])))
for c in (0,1): # check data minmax for x and y (i = 0 and 1)
if (minmax[c] == 0.0).all(): minmax[c] = [table.data[:,c].min(),table.data[:,c].max()]
if (minmax[c] == 0.0).all(): minmax[c] = [data[:,c].min(),data[:,c].max()]
if options.type[c].lower() == 'log': # if log scale
table.data[:,c] = np.log(table.data[:,c]) # change x,y coordinates to log
data[:,c] = np.log(data[:,c]) # change x,y coordinates to log
minmax[c] = np.log(minmax[c]) # change minmax to log, too
delta = minmax[:,1]-minmax[:,0]
(grid,xedges,yedges) = np.histogram2d(table.data[:,0],table.data[:,1],
(grid,xedges,yedges) = np.histogram2d(data[:,0],data[:,1],
bins=options.bins,
range=minmax[:2],
weights=None if options.weight is None else table.data[:,2])
weights=table.get(options.weight) if options.weight else None)
if options.normCol:
for x in range(options.bins[0]):
sum = np.sum(grid[x,:])
@ -153,24 +124,20 @@ for name in filenames:
for y in range(options.bins[1]):
result[x,y,:] = [minmax[0,0]+delta[0]/options.bins[0]*(x+0.5),
minmax[1,0]+delta[1]/options.bins[1]*(y+0.5),
min(1.0,max(0.0,(grid[x,y]-minmax[2,0])/delta[2]))]
np.clip((grid[x,y]-minmax[2,0])/delta[2],0.0,1.0)]
for c in (0,1):
if options.type[c].lower() == 'log': result[:,:,c] = np.exp(result[:,:,c])
if options.invert: result[:,:,2] = 1.0 - result[:,:,2]
# --- assemble header -------------------------------------------------------------------------------
table.info_clear()
table.info_append(scriptID + '\t' + ' '.join(sys.argv[1:]))
table.labels_clear()
table.labels_append(['bin_%s'%options.data[0],'bin_%s'%options.data[1],'z'])
table.head_write()
# --- output result ---------------------------------------------------------------------------------
table.data = result.reshape(options.bins[0]*options.bins[1],3)
table.data_writeArray()
table.close()
comments = scriptID + '\t' + ' '.join(sys.argv[1:])
shapes = {'bin_%s'%options.data[0]:(1,),'bin_%s'%options.data[1]:(1,),'z':(1,)}
table = damask.Table(result.reshape(options.bins[0]*options.bins[1],3),shapes,[comments])
if name:
outname = os.path.join(os.path.dirname(name),'binned-{}-{}_'.format(*options.data) +
('weighted-{}_'.format(options.weight) if options.weight else '') +
os.path.basename(name))
table.to_ASCII(outname)
else:
table.to_ASCII(sys.stdout)

View File

@ -60,12 +60,12 @@ for name in filenames:
outSize = grid*packing
data = table.data.values.reshape(tuple(grid)+(-1,))
blownUp = ndimage.interpolation.zoom(data,tuple(packing)+(1,),order=0,mode='nearest').reshape((outSize.prod(),-1))
blownUp = ndimage.interpolation.zoom(data,tuple(packing)+(1,),order=0,mode='nearest').reshape(outSize.prod(),-1)
table = damask.Table(blownUp,table.shapes,table.comments)
coords = damask.grid_filters.cell_coord0(outSize,size,origin)
table.set(options.pos,coords.reshape((-1,3)))
table.set(options.pos,coords.reshape(-1,3))
table.set('elem',np.arange(1,outSize.prod()+1))
outname = os.path.join(os.path.dirname(name),prefix+os.path.basename(name))

View File

@ -1,146 +0,0 @@
#!/usr/bin/env python2.7
import os
import sys
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 = """
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, readonly = True)
except IOError:
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,4 +1,4 @@
#!/usr/bin/env python2.7
#!/usr/bin/env python3
import os
import sys
@ -102,6 +102,7 @@ parser.set_defaults(label = None,
)
(options,filenames) = parser.parse_args()
if filenames == []: filenames = [None]
if options.pixelsize > 1: (options.pixelsizex,options.pixelsizey) = [options.pixelsize]*2
@ -112,9 +113,6 @@ if options.invert: theMap = theMap.invert()
theColors = np.uint8(np.array(theMap.export(format = 'list',steps = 256))*255)
# --- loop over input files -------------------------------------------------------------------------
if filenames == []: filenames = [None]
for name in filenames:
try:
table = damask.ASCIItable(name = name, labeled = options.label is not None, readonly = True)

View File

@ -1,4 +1,4 @@
#!/usr/bin/env python2.7
#!/usr/bin/env python3
import os
import sys
@ -95,6 +95,7 @@ parser.set_defaults(label = None,
)
(options,filenames) = parser.parse_args()
if filenames == []: filenames = [None]
options.size = np.array(options.size)
options.dimension = np.array(options.dimension)
@ -109,16 +110,12 @@ if options.invert: theMap = theMap.invert()
theColors = np.uint8(np.array(theMap.export(format='list',steps=256))*255)
# --- loop over input files -------------------------------------------------------------------------
if filenames == []: filenames = [None]
for name in filenames:
try:
table = damask.ASCIItable(name = name, readonly = True,
labeled = options.label is not None)
table = damask.ASCIItable(name = name, labeled = options.label is not None, readonly = True)
except IOError:
continue
table.report_name(scriptName,name)
damask.util.report(scriptName,name)
# ------------------------------------------ read header ------------------------------------------

View File

@ -1,4 +1,4 @@
#!/usr/bin/env python2.7
#!/usr/bin/env python3
import os
import sys
@ -72,18 +72,15 @@ parser.set_defaults(label = None,
)
(options,filenames) = parser.parse_args()
if filenames == []: filenames = [None]
if options.dimension == []: parser.error('dimension of data array missing')
if options.pixelsize > 1: (options.pixelsizex,options.pixelsizey) = [options.pixelsize]*2
# --- loop over input files -------------------------------------------------------------------------
if filenames == []: filenames = [None]
for name in filenames:
try:
table = damask.ASCIItable(name = name, readonly = True,
labeled = options.label is not None)
table = damask.ASCIItable(name = name, labeled = options.label is not None, readonly = True)
except IOError:
continue
damask.util.report(scriptName,name)

View File

@ -44,9 +44,7 @@ for name in filenames:
damask.util.report(scriptName,name)
table = damask.Table.from_ASCII(StringIO(''.join(sys.stdin.read())) if name is None else name)
for i,label in enumerate(options.label):
table.rename(label,
options.substitute[i],
scriptID+' '+' '.join(sys.argv[1:]))
for label,substitute in zip(options.label,options.substitute):
table.rename(label,substitute,scriptID+' '+' '.join(sys.argv[1:]))
table.to_ASCII(sys.stdout if name is None else name)

View File

@ -2,10 +2,9 @@
import os
import sys
from io import StringIO
from optparse import OptionParser
import numpy as np
import damask
@ -40,65 +39,25 @@ parser.set_defaults(rotation = (1.,1.,1.,0),
)
(options,filenames) = parser.parse_args()
if filenames == []: filenames = [None]
if options.data is None:
parser.error('no data column specified.')
r = damask.Rotation.fromAxisAngle(np.array(options.rotation),options.degrees,normalise=True)
# --- loop over input files -------------------------------------------------------------------------
if filenames == []: filenames = [None]
r = damask.Rotation.fromAxisAngle(options.rotation,options.degrees,normalise=True)
for name in filenames:
try:
table = damask.ASCIItable(name = name)
except IOError:
continue
damask.util.report(scriptName,name)
# --- interpret header ----------------------------------------------------------------------------
table = damask.Table.from_ASCII(StringIO(''.join(sys.stdin.read())) if name is None else name)
table.head_read()
for data in options.data:
d = table.get(data)
if table.shapes[data] == (9,): d=d.reshape(-1,3,3)
for i,l in enumerate(d):
d[i] = r*l
if table.shapes[data] == (9,): d=d.reshape(-1,9)
errors = []
remarks = []
active = {'vector':[],'tensor':[]}
table.set(data,d,scriptID+' '+' '.join(sys.argv[1:]))
for i,dim in enumerate(table.label_dimension(options.data)):
label = options.data[i]
if dim == -1:
remarks.append('"{}" not found...'.format(label))
elif dim == 3:
remarks.append('adding vector "{}"...'.format(label))
active['vector'].append(label)
elif dim == 9:
remarks.append('adding tensor "{}"...'.format(label))
active['tensor'].append(label)
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:]))
table.head_write()
# ------------------------------------------ process data ------------------------------------------
outputAlive = True
while outputAlive and table.data_read(): # read next data line of ASCII table
for v in active['vector']:
column = table.label_index(v)
table.data[column:column+3] = r * np.array(list(map(float,table.data[column:column+3])))
for t in active['tensor']:
column = table.label_index(t)
table.data[column:column+9] = (r * np.array(list(map(float,table.data[column:column+9]))).reshape((3,3))).reshape(9)
outputAlive = table.data_write() # output processed line
# ------------------------------------------ output finalization -----------------------------------
table.close() # close ASCII tables
table.to_ASCII(sys.stdout if name is None else name)

View File

@ -43,9 +43,7 @@ for name in filenames:
damask.util.report(scriptName,name)
table = damask.Table.from_ASCII(StringIO(''.join(sys.stdin.read())) if name is None else name)
for i,label in enumerate(options.labels):
table.set(label,
table.get(label)*float(options.factor[i]),
scriptID+' '+' '.join(sys.argv[1:]))
for label,factor in zip(options.labels,options.factor):
table.set(label,table.get(label)*float(factor),scriptID+' '+' '.join(sys.argv[1:]))
table.to_ASCII(sys.stdout if name is None else name)

View File

@ -43,9 +43,7 @@ for name in filenames:
damask.util.report(scriptName,name)
table = damask.Table.from_ASCII(StringIO(''.join(sys.stdin.read())) if name is None else name)
for i,label in enumerate(options.labels):
table.set(label,
table.get(label)+float(options.offset[i]),
scriptID+' '+' '.join(sys.argv[1:]))
for label,offset in zip(options.labels,options.offset):
table.set(label,table.get(label)+float(offset),scriptID+' '+' '.join(sys.argv[1:]))
table.to_ASCII(sys.stdout if name is None else name)

65
processing/post/vtk_addData.py Executable file
View File

@ -0,0 +1,65 @@
#!/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 [ASCIItable(s)]',
description = 'Add scalars/vectors, tensors, and/or a RGB tuples from ASCIItable '
+ 'to existing VTK file (.vtr/.vtu/.vtp).',
version = scriptID)
parser.add_option( '--vtk',
dest = 'vtk',
type = 'string', metavar = 'string',
help = 'VTK file name')
parser.add_option('-d', '--data',
dest = 'data',
action = 'extend', metavar = '<string LIST>',
help = 'scalar/vector value(s) label(s)')
parser.add_option('-t', '--tensor',
dest = 'tensor',
action = 'extend', metavar = '<string LIST>',
help = 'tensor (3x3) value label(s)')
parser.add_option('-c', '--color',
dest = 'color',
action = 'extend', metavar = '<string LIST>',
help = 'RGB color tuple label')
parser.set_defaults(data = [],
tensor = [],
color = [],
)
(options, filenames) = parser.parse_args()
if filenames == []: filenames = [None]
if not options.vtk:
parser.error('No VTK file specified.')
for name in filenames:
damask.util.report(scriptName,name)
table = damask.Table.from_ASCII(StringIO(''.join(sys.stdin.read())) if name is None else name)
vtk = damask.VTK.from_file(options.vtk)
for data in options.data+options.tensor:
vtk.add(table.get(data),data)
for color in options.color:
vtk.add((table.get(color)*255).astype(np.uint8),color)
vtk.write(options.vtk)

View File

@ -1,162 +0,0 @@
#!/usr/bin/env python3
import os
import sys
from io import StringIO
from optparse import OptionParser
import vtk
from vtk.util import numpy_support
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 [ASCIItable(s)]',
description = "Add scalars, vectors, tensors, and/or an RGB tuple from ASCIItable "
+ "to existing VTK grid (.vtr/.vtk/.vtu).",
version = scriptID)
parser.add_option( '--vtk',
dest = 'vtk',
type = 'string', metavar = 'string',
help = 'VTK file name')
parser.add_option('-r', '--render',
dest = 'render',
action = 'store_true',
help = 'open output in VTK render window')
parser.add_option('-d', '--data',
dest = 'data',
action = 'extend', metavar = '<string LIST>',
help = 'scalar/vector value(s) label(s)')
parser.add_option('-t', '--tensor',
dest = 'tensor',
action = 'extend', metavar = '<string LIST>',
help = 'tensor (3x3) value label(s)')
parser.add_option('-c', '--color',
dest = 'color',
action = 'extend', metavar = '<string LIST>',
help = 'RGB color tuple label')
parser.set_defaults(data = [],
tensor = [],
color = [],
)
(options, filenames) = parser.parse_args()
if filenames == []: filenames = [None]
if not options.vtk: parser.error('No VTK file specified.')
if not os.path.exists(options.vtk): parser.error('VTK file does not exist.')
vtk_file,vtk_ext = os.path.splitext(options.vtk)
if vtk_ext == '.vtr':
reader = vtk.vtkXMLRectilinearGridReader()
reader.SetFileName(options.vtk)
reader.Update()
rGrid = reader.GetOutput()
writer = vtk.vtkXMLRectilinearGridWriter()
elif vtk_ext == '.vtk':
reader = vtk.vtkGenericDataObjectReader()
reader.SetFileName(options.vtk)
reader.Update()
rGrid = reader.GetRectilinearGridOutput()
writer = vtk.vtkXMLRectilinearGridWriter()
elif vtk_ext == '.vtu':
reader = vtk.vtkXMLUnstructuredGridReader()
reader.SetFileName(options.vtk)
reader.Update()
rGrid = reader.GetOutput()
writer = vtk.vtkXMLUnstructuredGridWriter()
else:
parser.error('Unsupported VTK file type extension.')
writer.SetFileName(vtk_file+'.'+writer.GetDefaultFileExtension())
Npoints = rGrid.GetNumberOfPoints()
Ncells = rGrid.GetNumberOfCells()
damask.util.croak('{}: {} points and {} cells...'.format(options.vtk,Npoints,Ncells))
for name in filenames:
damask.util.report(scriptName,name)
table = damask.Table.from_ASCII(StringIO(''.join(sys.stdin.read())) if name is None else name)
VTKarray = {}
for data in options.data:
VTKarray[data] = numpy_support.numpy_to_vtk(table.get(data).copy(),
deep=True,array_type=vtk.VTK_DOUBLE)
VTKarray[data].SetName(data)
for color in options.color:
VTKarray[color] = numpy_support.numpy_to_vtk((table.get(color)*255).astype(int).copy(),
deep=True,array_type=vtk.VTK_UNSIGNED_CHAR)
VTKarray[color].SetName(color)
for tensor in options.tensor:
data = damask.mechanics.symmetric(table.get(tensor).reshape((-1,3,3))).reshape((-1,9))
VTKarray[tensor] = numpy_support.numpy_to_vtk(data.copy(),
deep=True,array_type=vtk.VTK_DOUBLE)
VTKarray[tensor].SetName(tensor)
# ------------------------------------------ add data ---------------------------------------
if len(table.data) == Npoints: mode = 'point'
elif len(table.data) == Ncells: mode = 'cell'
else:
damask.util.croak('Data count is incompatible with grid...')
continue
damask.util.croak('{} mode...'.format(mode))
for data in VTKarray:
if mode == 'cell': rGrid.GetCellData().AddArray(VTKarray[data])
elif mode == 'point': rGrid.GetPointData().AddArray(VTKarray[data])
rGrid.Modified()
# ------------------------------------------ output result ---------------------------------------
writer.SetDataModeToBinary()
writer.SetCompressorTypeToZLib()
writer.SetInputData(rGrid)
writer.Write()
# ------------------------------------------ render result ---------------------------------------
if options.render:
mapper = vtk.vtkDataSetMapper()
mapper.SetInputData(rGrid)
actor = vtk.vtkActor()
actor.SetMapper(mapper)
# Create the graphics structure. The renderer renders into the
# render window. The render window interactively 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,147 +0,0 @@
#!/usr/bin/env python3
import os
import sys
from io import StringIO
from optparse import OptionParser
import vtk
from vtk.util import numpy_support
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 [ASCIItable(s)]',
description = "Add scalars, vectors, tensors, and/or an RGB tuple from ASCIItable "
+ "VTK point cloud (.vtp).",
version = scriptID)
parser.add_option( '--vtk',
dest = 'vtk',
type = 'string', metavar = 'string',
help = 'VTK file name')
parser.add_option('-r', '--render',
dest = 'render',
action = 'store_true',
help = 'open output in VTK render window')
parser.add_option('-d', '--data',
dest = 'data',
action = 'extend', metavar = '<string LIST>',
help = 'scalar/vector value(s) label(s)')
parser.add_option('-t', '--tensor',
dest = 'tensor',
action = 'extend', metavar = '<string LIST>',
help = 'tensor (3x3) value label(s)')
parser.add_option('-c', '--color',
dest = 'color',
action = 'extend', metavar = '<string LIST>',
help = 'RGB color tuple label')
parser.set_defaults(data = [],
tensor = [],
color = [],
)
(options, filenames) = parser.parse_args()
if filenames == []: filenames = [None]
if not options.vtk: parser.error('No VTK file specified.')
if not os.path.exists(options.vtk): parser.error('VTK file does not exist.')
vtk_file,vtk_ext = os.path.splitext(options.vtk)
if vtk_ext == '.vtp':
reader = vtk.vtkXMLPolyDataReader()
reader.SetFileName(options.vtk)
reader.Update()
Polydata = reader.GetOutput()
elif vtk_ext == '.vtk':
reader = vtk.vtkGenericDataObjectReader()
reader.SetFileName(options.vtk)
reader.Update()
Polydata = reader.GetPolyDataOutput()
else:
parser.error('unsupported VTK file type extension.')
Npoints = Polydata.GetNumberOfPoints()
Ncells = Polydata.GetNumberOfCells()
Nvertices = Polydata.GetNumberOfVerts()
if Npoints != Ncells or Npoints != Nvertices:
parser.error('number of points, cells, and vertices in VTK differ from each other.')
damask.util.croak('{}: {} points/vertices/cells...'.format(options.vtk,Npoints))
for name in filenames:
damask.util.report(scriptName,name)
table = damask.Table.from_ASCII(StringIO(''.join(sys.stdin.read())) if name is None else name)
VTKarray = {}
for data in options.data:
VTKarray[data] = numpy_support.numpy_to_vtk(table.get(data).copy(),
deep=True,array_type=vtk.VTK_DOUBLE)
VTKarray[data].SetName(data)
for color in options.color:
VTKarray[color] = numpy_support.numpy_to_vtk((table.get(color)*255).astype(int).copy(),
deep=True,array_type=vtk.VTK_UNSIGNED_CHAR)
VTKarray[color].SetName(color)
for tensor in options.tensor:
data = damask.mechanics.symmetric(table.get(tensor).reshape((-1,3,3))).reshape((-1,9))
VTKarray[tensor] = numpy_support.numpy_to_vtk(data.copy(),
deep=True,array_type=vtk.VTK_DOUBLE)
VTKarray[tensor].SetName(tensor)
for data in VTKarray:
Polydata.GetPointData().AddArray(VTKarray[data])
Polydata.Modified()
# ------------------------------------------ output result ---------------------------------------
writer = vtk.vtkXMLPolyDataWriter()
writer.SetDataModeToBinary()
writer.SetCompressorTypeToZLib()
writer.SetFileName(vtk_file+'.'+writer.GetDefaultFileExtension())
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 interactively 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

@ -5,8 +5,6 @@ import sys
from io import StringIO
from optparse import OptionParser
import vtk
import damask
@ -39,39 +37,9 @@ for name in filenames:
damask.util.report(scriptName,name)
table = damask.Table.from_ASCII(StringIO(''.join(sys.stdin.read())) if name is None else name)
# ------------------------------------------ process data ---------------------------------------
Polydata = vtk.vtkPolyData()
Points = vtk.vtkPoints()
Vertices = vtk.vtkCellArray()
for p in table.get(options.pos):
pointID = Points.InsertNextPoint(p)
Vertices.InsertNextCell(1)
Vertices.InsertCellPoint(pointID)
Polydata.SetPoints(Points)
Polydata.SetVerts(Vertices)
Polydata.Modified()
# ------------------------------------------ output result ---------------------------------------
v = damask.VTK.from_polyData(table.get(options.pos))
if name:
writer = vtk.vtkXMLPolyDataWriter()
writer.SetCompressorTypeToZLib()
writer.SetDataModeToBinary()
writer.SetFileName(os.path.join(os.path.split(name)[0],
os.path.splitext(os.path.split(name)[1])[0] +
'.' + writer.GetDefaultFileExtension()))
v.write(os.path.splitext(name)[0])
else:
writer = vtk.vtkDataSetWriter()
writer.SetHeader('# powered by '+scriptID)
writer.WriteToOutputStringOn()
writer.SetInputData(Polydata)
writer.Write()
if name is None: sys.stdout.write(writer.GetOutputString())
sys.stdout.write(v.__repr__())

View File

@ -5,9 +5,6 @@ import sys
from io import StringIO
from optparse import OptionParser
import vtk
import numpy as np
import damask
@ -48,50 +45,14 @@ for name in filenames:
table = damask.Table.from_ASCII(StringIO(''.join(sys.stdin.read())) if name is None else name)
coords = [np.unique(table.get(options.pos)[:,i]) for i in range(3)]
if options.mode == 'cell':
coords = [0.5 * np.array([3.0 * coords[i][0] - coords[i][0 + int(len(coords[i]) > 1)]] + \
[coords[i][j-1] + coords[i][j] for j in range(1,len(coords[i]))] + \
[3.0 * coords[i][-1] - coords[i][-1 - int(len(coords[i]) > 1)]]) for i in range(3)]
grid, size, origin = damask.grid_filters.cell_coord0_gridSizeOrigin(table.get(options.pos))
elif options.mode == 'point':
grid, size, origin = damask.grid_filters.node_coord0_gridSizeOrigin(table.get(options.pos))
grid = np.array(list(map(len,coords)),'i')
N = grid.prod() if options.mode == 'point' else (grid-1).prod()
# ------------------------------------------ process data ---------------------------------------
rGrid = vtk.vtkRectilinearGrid()
coordArray = [vtk.vtkDoubleArray(),
vtk.vtkDoubleArray(),
vtk.vtkDoubleArray(),
]
rGrid.SetDimensions(*grid)
for i,points in enumerate(coords):
for point in points:
coordArray[i].InsertNextValue(point)
rGrid.SetXCoordinates(coordArray[0])
rGrid.SetYCoordinates(coordArray[1])
rGrid.SetZCoordinates(coordArray[2])
# ------------------------------------------ output result ---------------------------------------
v = damask.VTK.from_rectilinearGrid(grid,size,origin)
if name:
writer = vtk.vtkXMLRectilinearGridWriter()
writer.SetCompressorTypeToZLib()
writer.SetDataModeToBinary()
writer.SetFileName(os.path.join(os.path.split(name)[0],
os.path.splitext(os.path.split(name)[1])[0] +
'_{}({})'.format(options.pos, options.mode) +
'.' + writer.GetDefaultFileExtension()))
v.write('{}_{}({})'.format(os.path.splitext(name)[0],options.pos,options.mode))
else:
writer = vtk.vtkDataSetWriter()
writer.SetHeader('# powered by '+scriptID)
writer.WriteToOutputStringOn()
writer.SetInputData(rGrid)
writer.Write()
if name is None: sys.stdout.write(writer.GetOutputString())
sys.stdout.write(v.__repr__())

View File

@ -22,8 +22,6 @@ Writes vtk file for visualization.
""", version = scriptID)
(options, filenames) = parser.parse_args()
if filenames == []: filenames = [None]
for name in filenames:
@ -33,7 +31,7 @@ for name in filenames:
damask.util.croak(geom)
if name is None:
sys.stdout.write(geom.to_vtk())
else:
if name:
geom.to_vtk(os.path.splitext(name)[0])
else:
sys.stdout.write(geom.to_vtk())

View File

@ -3,6 +3,8 @@
import os
import sys
import multiprocessing
from io import StringIO
from functools import partial
from optparse import OptionParser,OptionGroup
import numpy as np
@ -15,73 +17,40 @@ scriptName = os.path.splitext(os.path.basename(__file__))[0]
scriptID = ' '.join([scriptName,damask.version])
def laguerreTessellation(undeformed, coords, weights, grains, periodic = True, cpus = 2):
def findClosestSeed(seeds, weights, point):
return np.argmin(np.sum((np.broadcast_to(point,(len(seeds),3))-seeds)**2,axis=1) - weights)
def findClosestSeed(fargs):
point, seeds, myWeights = fargs
tmp = np.repeat(point.reshape(3,1), len(seeds), axis=1).T
dist = np.sum((tmp - seeds)**2,axis=1) -myWeights
return np.argmin(dist) # seed point closest to point
copies = \
np.array([
[ -1,-1,-1 ],
[ 0,-1,-1 ],
[ 1,-1,-1 ],
[ -1, 0,-1 ],
[ 0, 0,-1 ],
[ 1, 0,-1 ],
[ -1, 1,-1 ],
[ 0, 1,-1 ],
[ 1, 1,-1 ],
[ -1,-1, 0 ],
[ 0,-1, 0 ],
[ 1,-1, 0 ],
[ -1, 0, 0 ],
[ 0, 0, 0 ],
[ 1, 0, 0 ],
[ -1, 1, 0 ],
[ 0, 1, 0 ],
[ 1, 1, 0 ],
[ -1,-1, 1 ],
[ 0,-1, 1 ],
[ 1,-1, 1 ],
[ -1, 0, 1 ],
[ 0, 0, 1 ],
[ 1, 0, 1 ],
[ -1, 1, 1 ],
[ 0, 1, 1 ],
[ 1, 1, 1 ],
]).astype(float)*info['size'] if periodic else \
np.array([
[ 0, 0, 0 ],
]).astype(float)
def Laguerre_tessellation(grid, seeds, grains, size, periodic, weights, cpus):
repeatweights = np.tile(weights,len(copies)).flatten(order='F') # Laguerre weights (1,2,3,1,2,3,...,1,2,3)
for i,vec in enumerate(copies): # periodic copies of seed points ...
try: seeds = np.append(seeds, coords+vec, axis=0) # ... (1+a,2+a,3+a,...,1+z,2+z,3+z)
except NameError: seeds = coords+vec
if (repeatweights == 0.0).all(): # standard Voronoi (no weights, KD tree)
myKDTree = spatial.cKDTree(seeds)
devNull,closestSeeds = myKDTree.query(undeformed)
if periodic:
weights_p = np.tile(weights,27).flatten(order='F') # 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]])))
else:
damask.util.croak('...using {} cpu{}'.format(options.cpus, 's' if options.cpus > 1 else ''))
arguments = [[arg,seeds,repeatweights] for arg in list(undeformed)]
weights_p = weights.flatten()
seeds_p = seeds
if cpus > 1: # use multithreading
if cpus > 1:
default_args = partial(findClosestSeed,seeds_p,weights_p)
pool = multiprocessing.Pool(processes = cpus) # initialize workers
result = pool.map_async(findClosestSeed, arguments) # evaluate function in parallel
result = pool.map_async(default_args, [point for point in grid]) # evaluate function in parallel
pool.close()
pool.join()
closestSeeds = np.array(result.get()).flatten()
else:
closestSeeds = np.zeros(len(arguments),dtype='i')
for i,arg in enumerate(arguments):
closestSeeds[i] = findClosestSeed(arg)
closestSeeds= np.array([findClosestSeed(seeds_p,weights_p,point) for point in grid])
# closestSeed is modulo number of original seed points (i.e. excluding periodic copies)
return grains[closestSeeds%coords.shape[0]]
return grains[closestSeeds%seeds.shape[0]]
def Voronoi_tessellation(grid, seeds, grains, size, periodic = True):
KDTree = spatial.cKDTree(seeds,boxsize=size) if periodic else spatial.cKDTree(seeds)
devNull,closestSeeds = KDTree.query(grid)
return grains[closestSeeds]
# --------------------------------------------------------------------
@ -123,16 +92,12 @@ group.add_option('-s',
'--size',
dest = 'size',
type = 'float', nargs = 3, metavar=' '.join(['float']*3),
help = 'x,y,z size of hexahedral box')
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')
group.add_option('--nonnormalized',
dest = 'normalized',
action = 'store_false',
help = 'seed coordinates are not normalized to a unit cube')
help = 'origin of grid [0.0 0.0 0.0]')
parser.add_option_group(group)
@ -191,101 +156,60 @@ parser.set_defaults(pos = 'pos',
cpus = 2,
laguerre = False,
periodic = True,
normalized = True,
config = True,
)
(options,filenames) = parser.parse_args()
if filenames == []: filenames = [None]
for name in filenames:
damask.util.report(scriptName,name)
table = damask.ASCIItable(name = name, readonly = True)
table = damask.Table.from_ASCII(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)
# --- read header ----------------------------------------------------------------------------
seeds = table.get(options.pos)
table.head_read()
info,extra_header = table.head_getGeom()
if options.grid is not None: info['grid'] = options.grid
if options.size is not None: info['size'] = options.size
if options.origin is not None: info['origin'] = options.origin
# ------------------------------------------ sanity checks ---------------------------------------
remarks = []
errors = []
labels = []
hasGrains = table.label_dimension(options.microstructure) == 1
hasEulers = table.label_dimension(options.eulers) == 3
hasWeights = table.label_dimension(options.weight) == 1 and options.laguerre
for i in range(3):
if info['size'][i] <= 0.0: # any invalid size?
info['size'][i] = float(info['grid'][i])/max(info['grid']) # normalize to grid
remarks.append('rescaling size {} to {}...'.format(['x','y','z'][i],info['size'][i]))
if table.label_dimension(options.pos) != 3:
errors.append('seed positions "{}" have dimension {}.'.format(options.pos,
table.label_dimension(options.pos)))
else:
labels += [options.pos]
if not options.normalized: remarks.append('using real-space seed coordinates...')
if not hasEulers: remarks.append('missing seed orientations...')
else: labels += [options.eulers]
if not hasGrains: remarks.append('missing seed microstructure indices...')
else: labels += [options.microstructure]
if options.laguerre and not hasWeights: remarks.append('missing seed weights...')
else: labels += [options.weight]
if remarks != []: damask.util.croak(remarks)
if errors != []:
damask.util.croak(errors)
table.close(dismiss=True)
continue
# ------------------------------------------ read seeds ---------------------------------------
table.data_readArray(labels)
coords = table.data[:,table.label_indexrange(options.pos)] * info['size'] if options.normalized \
else table.data[:,table.label_indexrange(options.pos)] - info['origin']
eulers = table.data[:,table.label_indexrange(options.eulers)] if hasEulers \
else np.zeros(3*len(coords))
grains = table.data[:,table.label_indexrange(options.microstructure)].astype(int) if hasGrains \
else 1+np.arange(len(coords))
weights = table.data[:,table.label_indexrange(options.weight)] if hasWeights \
else np.zeros(len(coords))
grains = table.get(options.microstructure) if options.microstructure in table.labels else np.arange(len(seeds))+1
grainIDs = np.unique(grains).astype('i')
NgrainIDs = len(grainIDs)
# --- tessellate microstructure ------------------------------------------------------------
if options.eulers in table.labels:
eulers = table.get(options.eulers)
x = (np.arange(info['grid'][0])+0.5)*info['size'][0]/info['grid'][0]
y = (np.arange(info['grid'][1])+0.5)*info['size'][1]/info['grid'][1]
z = (np.arange(info['grid'][2])+0.5)*info['size'][2]/info['grid'][2]
X,Y,Z = np.meshgrid(x, y, z,indexing='ij')
grid = np.stack((X,Y,Z),axis=-1).reshape((np.prod(info['grid']),3),order='F')
coords = damask.grid_filters.cell_coord0(grid,size,-origin).reshape(-1,3,order='F')
damask.util.croak('tessellating...')
indices = laguerreTessellation(grid, coords, weights, grains, options.periodic, options.cpus)
if options.laguerre:
indices = Laguerre_tessellation(coords,seeds,grains,size,options.periodic,
table.get(options.weight),options.cpus)
else:
indices = Voronoi_tessellation (coords,seeds,grains,size,options.periodic)
config_header = []
if options.config:
if hasEulers:
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 is not None: config_header += ['axes\t{} {} {}'.format(*options.axes)]
if options.axes: config_header += ['axes\t{} {} {}'.format(*options.axes)]
config_header += ['<microstructure>']
for ID in grainIDs:
@ -297,7 +221,7 @@ for name in filenames:
header = [scriptID + ' ' + ' '.join(sys.argv[1:])]\
+ config_header
geom = damask.Geom(indices.reshape(info['grid'],order='F'),info['size'],info['origin'],
geom = damask.Geom(indices.reshape(grid),size,origin,
homogenization=options.homogenization,comments=header)
damask.util.croak(geom)

View File

@ -30,17 +30,16 @@ for name in filenames:
geom = damask.Geom.from_file(StringIO(''.join(sys.stdin.read())) if name is None else name)
damask.util.croak(geom)
coord0 = damask.grid_filters.cell_coord0(geom.grid,geom.size,geom.origin).reshape((-1,3))
coord0 = damask.grid_filters.cell_coord0(geom.grid,geom.size,geom.origin).reshape(-1,3)
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),
"homogenization\t{}".format(geom.homogenization)]
'grid\ta {}\tb {}\tc {}'.format(*geom.grid),
'size\tx {}\ty {}\tz {}'.format(*geom.size),
'origin\tx {}\ty {}\tz {}'.format(*geom.origin),
'homogenization\t{}'.format(geom.homogenization)]
table = damask.Table(coord0,{'pos':(3,)},comments)
table.add('microstructure',geom.microstructure.reshape((-1,1),order='F'))
table.to_ASCII(sys.stdout if name is None else \
os.path.splitext(name)[0]+'.txt')
table.to_ASCII(sys.stdout if name is None else os.path.splitext(name)[0]+'.txt')

View File

@ -1,11 +1,17 @@
#!/usr/bin/env python3
# -*- coding: UTF-8 no BOM -*-
import os
import sys
import math
import random
from io import StringIO
from optparse import OptionParser
import damask
import os,sys,math,random
import numpy as np
import damask
scriptName = os.path.splitext(os.path.basename(__file__))[0]
scriptID = ' '.join([scriptName,damask.version])
@ -223,54 +229,29 @@ parser.set_defaults(randomSeed = None,
)
(options,filenames) = parser.parse_args()
nSamples = options.number
methods = [options.algorithm]
# --- loop over input files -------------------------------------------------------------------------
if filenames == []: filenames = [None]
for name in filenames:
try:
table = damask.ASCIItable(name = name, readonly=True)
except IOError:
continue
damask.util.report(scriptName,name)
randomSeed = int(os.urandom(4).hex(), 16) if options.randomSeed is None else options.randomSeed # random seed per file for second phase
table = damask.Table.from_ASCII(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)
# ------------------------------------------ read header and data ---------------------------------
table.head_read()
errors = []
labels = ['1_euler','2_euler','3_euler','intensity']
for i,index in enumerate(table.label_index(labels)):
if index < 0: errors.append('label {} not present.'.format(labels[i]))
if errors != []:
damask.util.croak(errors)
table.close(dismiss = True)
continue
table.data_readArray(labels)
# --------------- figure out limits (left/right), delta, and interval -----------------------------
ODF = {}
limits = np.array([np.min(table.data[:,0:3],axis=0),
np.max(table.data[:,0:3],axis=0)]) # min/max euler angles in degrees
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(table.data[:,i]) for i in range(3)])),'i') # steps are number of distict values
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 table.data.shape[0] != ODF['nBins']:
damask.util.croak('expecting %i values but got %i'%(ODF['nBins'],table.data.shape[0]))
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 ------------------------------------------------------
@ -278,9 +259,10 @@ for name in filenames:
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,table.data[b,table.label_index('intensity')]) * dg * \
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]
@ -296,11 +278,10 @@ for name in filenames:
'Reference Integral: %12.11f\n'%(ODF['limit'][0]*ODF['limit'][2]*(1-math.cos(ODF['limit'][1]))),
])
# call methods
Functions = {'IA': 'directInversion', 'STAT': 'TothVanHoutteSTAT', 'MC': 'MonteCarloBins'}
method = Functions[options.algorithm]
Orientations, ReconstructedODF = (globals()[method])(ODF,nSamples)
Orientations, ReconstructedODF = (globals()[method])(ODF,options.number)
# calculate accuracy of sample
squaredDiff = {'orig':0.0,method:0.0}
@ -319,7 +300,7 @@ for name in filenames:
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(nSamples*squaredDiff[method]),
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'\
@ -331,10 +312,10 @@ for name in filenames:
(indivSquaredSum[method]/ODF['nNonZero']-(indivSum[method]/ODF['nNonZero'])**2)))),
])
if method == 'IA' and nSamples < ODF['nNonZero']:
if method == 'IA' and options.number < ODF['nNonZero']:
strOpt = '(%i)'%ODF['nNonZero']
formatwidth = 1+int(math.log10(nSamples))
formatwidth = 1+int(math.log10(options.number))
materialConfig = [
'#' + scriptID + ' ' + ' '.join(sys.argv[1:]),
@ -344,7 +325,7 @@ for name in filenames:
'#-------------------#',
]
for i,ID in enumerate(range(nSamples)):
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)),
]
@ -355,7 +336,7 @@ for name in filenames:
'#-------------------#',
]
for ID in range(nSamples):
for ID in range(options.number):
eulers = Orientations[ID]
materialConfig += ['[Grain%s]'%(str(ID+1).zfill(formatwidth)),
@ -364,7 +345,5 @@ for name in filenames:
#--- output finalization --------------------------------------------------------------------------
with (open(os.path.splitext(name)[0]+'_'+method+'_'+str(nSamples)+'_material.config','w')) as outfile:
with (open(os.path.splitext(name)[0]+'_'+method+'_'+str(options.number)+'_material.config','w')) as outfile:
outfile.write('\n'.join(materialConfig)+'\n')
table.close()

File diff suppressed because it is too large Load Diff

39
processing/pre/seeds_check.py Executable file
View File

@ -0,0 +1,39 @@
#!/usr/bin/env python3
import os
import sys
from io import StringIO
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 [seedfile(s)]', description = """
Writes vtk file for visualization.
""", version = scriptID)
(options, filenames) = parser.parse_args()
if filenames == []: filenames = [None]
for name in filenames:
damask.util.report(scriptName,name)
seeds = damask.Table.from_ASCII(StringIO(''.join(sys.stdin.read())) if name is None else name)
v = damask.VTK.from_polyData(seeds.get('pos'))
for label in seeds.shapes.keys():
if label == 'pos': pass
v.add(seeds.get(label),label)
if name:
v.write(os.path.splitext(name)[0])
else:
sys.stdout.write(v.__repr__())

View File

@ -1,11 +0,0 @@
#!/usr/bin/env bash
for seeds in "$@"
do
vtk_pointCloud $seeds
vtk_addPointCloudData $seeds \
--data microstructure,weight \
--vtk ${seeds%.*}.vtp \
done

View File

@ -1,9 +1,15 @@
#!/usr/bin/env python3
import threading,time,os,sys,random
import numpy as np
import threading
import time
import os
import sys
import random
from optparse import OptionParser
from io import StringIO
import numpy as np
import damask
scriptName = os.path.splitext(os.path.basename(__file__))[0]
@ -49,12 +55,11 @@ class myThread (threading.Thread):
s.acquire() # ensure only one thread acces global data
if bestSeedsUpdate > knownSeedsUpdate: # write best fit to virtual file
knownSeedsUpdate = bestSeedsUpdate
bestSeedsVFile.reset()
bestSeedsVFile.seek(0)
myBestSeedsVFile.close()
myBestSeedsVFile = StringIO()
i=0
for line in bestSeedsVFile:
myBestSeedsVFile.write(line)
myBestSeedsVFile.writelines(bestSeedsVFile.readlines())
s.release()
if randReset: # new direction because current one led to worse fit
@ -67,46 +72,38 @@ class myThread (threading.Thread):
for i in range(NmoveGrains):
selectedMs.append(random.randrange(1,nMicrostructures))
direction.append(np.array(((random.random()-0.5)*delta[0],
(random.random()-0.5)*delta[1],
(random.random()-0.5)*delta[2])))
direction.append((np.random.random()-0.5)*delta)
perturbedSeedsVFile.close() # reset virtual file
perturbedSeedsVFile = StringIO()
myBestSeedsVFile.reset()
myBestSeedsVFile.seek(0)
perturbedSeedsTable = damask.ASCIItable(myBestSeedsVFile,perturbedSeedsVFile,labeled=True) # write best fit to perturbed seed file
perturbedSeedsTable.head_read()
perturbedSeedsTable.head_write()
outputAlive=True
ms = 1
perturbedSeedsTable = damask.Table.from_ASCII(myBestSeedsVFile)
coords = perturbedSeedsTable.get('pos')
i = 0
while outputAlive and perturbedSeedsTable.data_read(): # perturbe selected microstructure
for ms,coord in enumerate(coords):
if ms in selectedMs:
newCoords=np.array(tuple(map(float,perturbedSeedsTable.data[0:3]))+direction[i])
newCoords=coord+direction[i]
newCoords=np.where(newCoords>=1.0,newCoords-1.0,newCoords) # ensure that the seeds remain in the box
newCoords=np.where(newCoords <0.0,newCoords+1.0,newCoords)
perturbedSeedsTable.data[0:3]=[format(f, '8.6f') for f in newCoords]
coords[i]=newCoords
direction[i]*=2.
i+= 1
ms+=1
perturbedSeedsTable.data_write()
#--- do tesselation with perturbed seed file ----------------------------------------------------------
perturbedSeedsTable.set('pos',coords)
perturbedSeedsTable.to_ASCII(perturbedSeedsVFile)
#--- do tesselation with perturbed seed file ------------------------------------------------------
perturbedGeomVFile.close()
perturbedGeomVFile = StringIO()
perturbedSeedsVFile.reset()
perturbedSeedsVFile.seek(0)
perturbedGeomVFile.write(damask.util.execute('geom_fromVoronoiTessellation '+
' -g '+' '.join(list(map(str, options.grid))),streamIn=perturbedSeedsVFile)[0])
perturbedGeomVFile.reset()
perturbedGeomVFile.seek(0)
#--- evaluate current seeds file ----------------------------------------------------------------------
perturbedGeomTable = damask.ASCIItable(perturbedGeomVFile,None,labeled=False,readonly=True)
perturbedGeomTable.head_read()
for i in perturbedGeomTable.info:
if i.startswith('microstructures'): myNmicrostructures = int(i.split('\t')[1])
perturbedGeomTable.data_readArray()
perturbedGeomTable.output_flush()
currentData=np.bincount(perturbedGeomTable.data.astype(int).ravel())[1:]/points
#--- evaluate current seeds file ------------------------------------------------------------------
perturbedGeom = damask.Geom.from_file(perturbedGeomVFile)
myNmicrostructures = len(np.unique(perturbedGeom.microstructure))
currentData=np.bincount(perturbedGeom.microstructure.ravel())[1:]/points
currentError=[]
currentHist=[]
for i in range(nMicrostructures): # calculate the deviation in all bins per histogram
@ -137,7 +134,7 @@ class myThread (threading.Thread):
damask.util.croak(' target: '+np.array_str(target[i]['histogram']))
damask.util.croak(' best: '+np.array_str(currentHist[i]))
currentSeedsName = baseFile+'_'+str(bestSeedsUpdate).replace('.','-') # name of new seed file (use time as unique identifier)
perturbedSeedsVFile.reset()
perturbedSeedsVFile.seek(0)
bestSeedsVFile.close()
bestSeedsVFile = StringIO()
sys.stdout.flush()
@ -154,11 +151,10 @@ class myThread (threading.Thread):
break
if i == min(nMicrostructures,myMatch+options.bins)-1: # same quality as before: take it to keep on moving
bestSeedsUpdate = time.time()
perturbedSeedsVFile.reset()
perturbedSeedsVFile.seek(0)
bestSeedsVFile.close()
bestSeedsVFile = StringIO()
for line in perturbedSeedsVFile:
bestSeedsVFile.write(line)
bestSeedsVFile.writelines(perturbedSeedsVFile.readlines())
for j in range(nMicrostructures):
target[j]['error'] = currentError[j]
randReset = True
@ -216,7 +212,7 @@ damask.util.report(scriptName,options.seedFile)
if options.randomSeed is None:
options.randomSeed = int(os.urandom(4).hex(),16)
damask.util.croak(options.randomSeed)
delta = (options.scale/options.grid[0],options.scale/options.grid[1],options.scale/options.grid[2])
delta = options.scale/np.array(options.grid)
baseFile=os.path.splitext(os.path.basename(options.seedFile))[0]
points = np.array(options.grid).prod().astype('float')

View File

@ -54,17 +54,16 @@ for name in filenames:
np.in1d(microstructure,options.blacklist,invert=True) if options.blacklist else \
np.full(geom.grid.prod(),True,dtype=bool))
seeds = np.concatenate((damask.grid_filters.cell_coord0(geom.grid,geom.size).reshape((-1,3)),
microstructure),
axis=1)[mask]
seeds = damask.grid_filters.cell_coord0(geom.grid,geom.size).reshape(-1,3)
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),
"homogenization\t{}".format(geom.homogenization)]
'grid\ta {}\tb {}\tc {}'.format(*geom.grid),
'size\tx {}\ty {}\tz {}'.format(*geom.size),
'origin\tx {}\ty {}\tz {}'.format(*geom.origin),
'homogenization\t{}'.format(geom.homogenization)]
table = damask.Table(seeds,{'pos':(3,),'microstructure':(1,)},comments)
table = damask.Table(seeds[mask],{'pos':(3,)},comments)
table.add('microstructure',microstructure[mask])
table.to_ASCII(sys.stdout if name is None else \
os.path.splitext(name)[0]+'.seeds')

View File

@ -64,8 +64,8 @@ for name in filenames:
damask.util.croak('poking {} x {} x {} in box {} {} {}...'.format(Nx,Ny,Nz,*box))
seeds = np.zeros((Nx*Ny*Nz,4),'d')
g = np.zeros(3,'i')
seeds = np.zeros((Nx*Ny*Nz,4))
g = np.zeros(3,dtype=np.int)
n = 0
for i in range(Nx):
@ -84,12 +84,13 @@ for name in filenames:
comments = geom.comments \
+ [scriptID + ' ' + ' '.join(sys.argv[1:]),
"poking\ta {}\tb {}\tc {}".format(Nx,Ny,Nz),
"grid\ta {}\tb {}\tc {}".format(*geom.grid),
"size\tx {}\ty {}\tz {}".format(*geom.size),
"origin\tx {}\ty {}\tz {}".format(*geom.origin),
"homogenization\t{}".format(geom.homogenization)]
'poking\ta {}\tb {}\tc {}'.format(Nx,Ny,Nz),
'grid\ta {}\tb {}\tc {}'.format(*geom.grid),
'size\tx {}\ty {}\tz {}'.format(*geom.size),
'origin\tx {}\ty {}\tz {}'.format(*geom.origin),
'homogenization\t{}'.format(geom.homogenization)]
table = damask.Table(seeds,{'pos':(3,),'microstructure':(1,)},comments)
table.set('microstructure',table.get('microstructure').astype(np.int))
table.to_ASCII(sys.stdout if name is None else \
os.path.splitext(name)[0]+'_poked_{}.seeds'.format(options.N))

View File

@ -1,36 +1,25 @@
#!/usr/bin/env python3
# -*- coding: UTF-8 no BOM -*-
import os,sys,math,random
import numpy as np
import damask
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])
# ------------------------------------------ aux functions ---------------------------------
def kdtree_search(cloud, queryPoints):
"""Find distances to nearest neighbor among cloud (N,d) for each of the queryPoints (n,d)."""
n = queryPoints.shape[0]
distances = np.zeros(n,dtype=float)
tree = spatial.cKDTree(cloud)
for i in range(n):
distances[i], index = tree.query(queryPoints[i])
return distances
# --------------------------------------------------------------------
# MAIN
# --------------------------------------------------------------------
parser = OptionParser(option_class=damask.extendableOption, usage='%prog options', description = """
Distribute given number of points randomly within (a fraction of) the three-dimensional cube [0.0,0.0,0.0]--[1.0,1.0,1.0].
Distribute given number of points randomly within rectangular cuboid.
Reports positions with random crystal orientations in seeds file format to STDOUT.
""", version = scriptID)
@ -39,11 +28,11 @@ parser.add_option('-N',
dest = 'N',
type = 'int', metavar = 'int',
help = 'number of seed points [%default]')
parser.add_option('-f',
'--fraction',
dest = 'fraction',
parser.add_option('-s',
'--size',
dest = 'size',
type = 'float', nargs = 3, metavar = 'float float float',
help='fractions along x,y,z of unit cube to fill %default')
help='size x,y,z of unit cube to fill %default')
parser.add_option('-g',
'--grid',
dest = 'grid',
@ -58,9 +47,6 @@ parser.add_option('-r',
'--rnd',
dest = 'randomSeed', type = 'int', metavar = 'int',
help = 'seed of random number generator [%default]')
parser.add_option('--format',
dest = 'format', type = 'string', metavar = 'string',
help = 'output number format [auto]')
group = OptionGroup(parser, "Laguerre Tessellation",
"Parameters determining shape of weight distribution of seed points"
@ -87,8 +73,7 @@ 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( '-s',
'--selective',
group.add_option( '--selective',
action = 'store_true',
dest = 'selective',
help = 'selective picking of seed points from random seed points')
@ -104,7 +89,7 @@ parser.add_option_group(group)
parser.set_defaults(randomSeed = None,
grid = (16,16,16),
fraction = (1.0,1.0,1.0),
size = (1.0,1.0,1.0),
N = 20,
weights = False,
max = 0.0,
@ -114,116 +99,67 @@ parser.set_defaults(randomSeed = None,
selective = False,
distance = 0.2,
numCandidates = 10,
format = None,
)
(options,filenames) = parser.parse_args()
options.fraction = np.array(options.fraction)
options.grid = np.array(options.grid)
gridSize = options.grid.prod()
if options.randomSeed is None: options.randomSeed = int(os.urandom(4).hex(), 16)
np.random.seed(options.randomSeed) # init random generators
random.seed(options.randomSeed)
# --- loop over output files -------------------------------------------------------------------------
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:
try:
table = damask.ASCIItable(outname = name)
except IOError:
continue
damask.util.report(scriptName,name)
# --- sanity checks -------------------------------------------------------------------------
remarks = []
errors = []
if gridSize == 0:
errors.append('zero grid dimension for {}.'.format(', '.join([['a','b','c'][x] for x in np.where(options.grid == 0)[0]])))
if options.N > gridSize/10.:
remarks.append('seed count exceeds 0.1 of grid points.')
if options.selective and 4./3.*math.pi*(options.distance/2.)**3*options.N > 0.5:
remarks.append('maximum recommended seed point count for given distance is {}.{}'.
format(int(3./8./math.pi/(options.distance/2.)**3)))
if remarks != []: damask.util.croak(remarks)
if errors != []:
damask.util.croak(errors)
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)))
# --- do work ------------------------------------------------------------------------------------
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
grainEuler = np.random.rand(3,options.N) # create random Euler triplets
grainEuler[0,:] *= 360.0 # phi_1 is uniformly distributed
grainEuler[1,:] = np.degrees(np.arccos(2*grainEuler[1,:]-1)) # cos(Phi) is uniformly distributed
grainEuler[2,:] *= 360.0 # phi_2 is uniformly distributed
if not options.selective:
n = np.maximum(np.ones(3),np.array(options.grid*options.fraction),
dtype=int,casting='unsafe') # find max grid indices within fraction
meshgrid = np.meshgrid(*map(np.arange,n),indexing='ij') # create a meshgrid within fraction
coords = np.vstack((meshgrid[0],meshgrid[1],meshgrid[2])).reshape(3,n.prod()).T # assemble list of 3D coordinates
seeds = ((random.sample(list(coords),options.N)+np.random.random(options.N*3).reshape(options.N,3))\
/ \
(n/options.fraction)).T # pick options.N of those, rattle position,
# and rescale to fall within fraction
coords = damask.grid_filters.cell_coord0(grid,size).reshape(-1,3)
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.zeros((options.N,3),dtype=float) # seed positions array
seeds[0] = np.random.random(3)*options.grid/max(options.grid)
i = 1 # start out with one given point
if i%(options.N/100.) < 1: damask.util.croak('.',False)
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.random(options.numCandidates*3).reshape(options.numCandidates,3)
distances = kdtree_search(seeds[:i],candidates)
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
if i%(options.N/100.) < 1: damask.util.croak('.',False)
progress.update(i)
damask.util.croak('')
seeds = seeds.T # prepare shape for stacking
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)
table.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)]
else:
weights = []
seeds = np.transpose(np.vstack(tuple([seeds,
grainEuler,
np.arange(options.microstructure,
options.microstructure + options.N),
] + 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.add('weight',weights)
# ------------------------------------------ assemble header ---------------------------------------
table.info_clear()
table.info_append([
scriptID + ' ' + ' '.join(sys.argv[1:]),
"grid\ta {}\tb {}\tc {}".format(*options.grid),
"microstructures\t{}".format(options.N),
"randomSeed\t{}".format(options.randomSeed),
])
table.labels_clear()
table.labels_append( ['{dim}_{label}'.format(dim = 1+k,label = 'pos') for k in range(3)] +
['{dim}_{label}'.format(dim = 1+k,label = 'euler') for k in range(3)] +
['microstructure'] +
(['weight'] if options.weights else []))
table.head_write()
table.output_flush()
# --- write seeds information ------------------------------------------------------------
table.data = seeds
table.data_writeArray(fmt = options.format)
# --- output finalization --------------------------------------------------------------------------
table.close() # close ASCII table
table.to_ASCII(sys.stdout if name is None else name)

1
python/.gitignore vendored
View File

@ -1,2 +1,3 @@
*.pyc
dist
damask.egg-info

View File

@ -36,7 +36,7 @@ sc = np.pi**(1./6.)/6.**(1./6.)
beta = np.pi**(5./6.)/6.**(1./6.)/2.
R1 = (3.*np.pi/4.)**(1./3.)
def CubeToBall(cube):
def cube_to_ball(cube):
"""
Map a point in a uniform refinable cubical grid to a point on a uniform refinable grid on a ball.
@ -59,7 +59,7 @@ def CubeToBall(cube):
ball = np.zeros(3)
else:
# get pyramide and scale by grid parameter ratio
p = get_order(cube)
p = _get_order(cube)
XYZ = cube[p] * sc
# intercept all the points along the z-axis
@ -87,7 +87,7 @@ def CubeToBall(cube):
return ball
def BallToCube(ball):
def ball_to_cube(ball):
"""
Map a point on a uniform refinable grid on a ball to a point in a uniform refinable cubical grid.
@ -109,7 +109,7 @@ def BallToCube(ball):
if np.allclose(ball,0.0,rtol=0.0,atol=1.0e-300):
cube = np.zeros(3)
else:
p = get_order(ball)
p = _get_order(ball)
xyz3 = ball[p]
# inverse M_3
@ -137,7 +137,7 @@ def BallToCube(ball):
return cube
def get_order(xyz):
def _get_order(xyz):
"""
Get order of the coordinates.

View File

@ -1,37 +1,25 @@
"""Main aggregator."""
import os
import re
import os as _os
import re as _re
name = 'damask'
with open(os.path.join(os.path.dirname(__file__),'VERSION')) as f:
version = re.sub(r'^v','',f.readline().strip())
with open(_os.path.join(_os.path.dirname(__file__),'VERSION')) as _f:
version = _re.sub(r'^v','',_f.readline().strip())
# classes
from .environment import Environment # noqa
from .table import Table # noqa
from .ktv import VTK # noqa
from .colormaps import Colormap, Color # noqa
from .rotation import Rotation # noqa
from .lattice import Symmetry, Lattice# noqa
from .orientation import Orientation # noqa
from .result import Result # noqa
from .geom import Geom # noqa
from .solver import Solver # noqa
# compatibility hack
from .result import Result as DADF5 # noqa
from ._environment import Environment # noqa
from ._table import Table # noqa
from ._vtk import VTK # noqa
from ._colormaps import Colormap, Color # noqa
from ._rotation import Rotation # noqa
from ._lattice import Symmetry, Lattice# noqa
from ._orientation import Orientation # noqa
from ._result import Result # noqa
from ._geom import Geom # noqa
from . import solver # noqa
# deprecated
from .asciitable import ASCIItable # noqa
from .util import extendableOption # noqa
from ._asciitable import ASCIItable # noqa
from ._test import Test # noqa
from .config import Material # noqa
from .test import Test # noqa
# functions in modules
from . import mechanics # noqa
from . import grid_filters # noqa
# clean temporary variables
del os
del re
del f
from .util import extendableOption # noqa

View File

@ -14,9 +14,7 @@ class ASCIItable():
# ------------------------------------------------------------------
def __init__(self,
name = None,
outname = None,
buffered = False, # is ignored, only exists for compatibility reasons
name,
labeled = True, # assume table has labels
readonly = False, # no reading from file
):
@ -27,8 +25,9 @@ class ASCIItable():
'dataStart': 0,
}
self.__IO__['inPlace'] = not outname and name and not readonly
if self.__IO__['inPlace']: outname = name + self.tmpext # transparently create tmp file
self.__IO__['inPlace'] = name and not readonly
outname = name + self.tmpext if self.__IO__['inPlace'] else None # 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
except TypeError:
@ -166,42 +165,6 @@ class ASCIItable():
return self.output_write(head)
# ------------------------------------------------------------------
def head_getGeom(self):
"""Interpret geom header."""
identifiers = {
'grid': ['a','b','c'],
'size': ['x','y','z'],
'origin': ['x','y','z'],
}
mappings = {
'grid': lambda x: int(x),
'size': lambda x: float(x),
'origin': lambda x: float(x),
}
info = {
'grid': np.zeros(3,'i'),
'size': np.zeros(3,'d'),
'origin': np.zeros(3,'d'),
}
extra_header = []
for header in self.info:
headitems = list(map(str.lower,header.split()))
if len(headitems) == 0: continue # skip blank lines
if headitems[0] in list(mappings.keys()):
if headitems[0] in list(identifiers.keys()):
for i in range(len(identifiers[headitems[0]])):
info[headitems[0]][i] = \
mappings[headitems[0]](headitems[headitems.index(identifiers[headitems[0]][i])+1])
else:
info[headitems[0]] = mappings[headitems[0]](headitems[1])
else:
extra_header.append(header)
return info,extra_header
# ------------------------------------------------------------------
def labels_append(self,
what,
@ -424,29 +387,26 @@ class ASCIItable():
return labels_missing
# ------------------------------------------------------------------
def data_write(self,
delimiter = '\t'):
def data_write(self):
"""Write current data array and report alive output back."""
if len(self.data) == 0: return True
if isinstance(self.data[0],list):
return self.output_write([delimiter.join(map(self._quote,items)) for items in self.data])
return self.output_write(['\t'.join(map(self._quote,items)) for items in self.data])
else:
return self.output_write( delimiter.join(map(self._quote,self.data)))
return self.output_write( '\t'.join(map(self._quote,self.data)))
# ------------------------------------------------------------------
def data_writeArray(self,
fmt = None,
delimiter = '\t'):
def data_writeArray(self):
"""Write whole numpy array data."""
for row in self.data:
try:
output = [fmt % value for value in row] if fmt else list(map(repr,row))
output = list(map(repr,row))
except Exception:
output = [fmt % row] if fmt else [repr(row)]
output = [repr(row)]
try:
self.__IO__['out'].write(delimiter.join(output) + '\n')
self.__IO__['out'].write('\t'.join(output) + '\n')
except Exception:
pass

541
python/damask/_colormaps.py Normal file
View File

@ -0,0 +1,541 @@
import numpy as np
class Color:
"""Color representation in and conversion between different color-spaces."""
__slots__ = [
'model',
'color',
'__dict__',
]
def __init__(self,
model = 'RGB',
color = np.zeros(3)):
"""
Create a Color object.
Parameters
----------
model : string
color model
color : numpy.ndarray
vector representing the color according to the selected model
"""
self.__transforms__ = \
{'HSV': {'index': 0, 'next': self._HSV2HSL},
'HSL': {'index': 1, 'next': self._HSL2RGB, 'prev': self._HSL2HSV},
'RGB': {'index': 2, 'next': self._RGB2XYZ, 'prev': self._RGB2HSL},
'XYZ': {'index': 3, 'next': self._XYZ2CIELAB, 'prev': self._XYZ2RGB},
'CIELAB': {'index': 4, 'next': self._CIELAB2MSH, 'prev': self._CIELAB2XYZ},
'MSH': {'index': 5, 'prev': self._MSH2CIELAB},
}
model = model.upper()
if model not in list(self.__transforms__.keys()): model = 'RGB'
if model == 'RGB' and max(color) > 1.0: # are we RGB255 ?
for i in range(3):
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
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 convert_to(self,toModel = 'RGB'):
"""
Change the color model permanently.
Parameters
----------
toModel : string
color model
"""
toModel = toModel.upper()
if toModel not in list(self.__transforms__.keys()): return
sourcePos = self.__transforms__[self.model]['index']
targetPos = self.__transforms__[toModel]['index']
while sourcePos < targetPos:
self.__transforms__[self.model]['next']()
sourcePos += 1
while sourcePos > targetPos:
self.__transforms__[self.model]['prev']()
sourcePos -= 1
return self
def express_as(self,asModel = 'RGB'):
"""
Return the color in a different model.
Parameters
----------
asModel : string
color model
"""
return self.__class__(self.model,self.color).convert_to(asModel)
def _HSV2HSL(self):
"""
Convert H(ue) S(aturation) V(alue or brightness) to H(ue) S(aturation) L(uminance).
All values are in the range [0,1]
http://codeitdown.com/hsl-hsb-hsv-color
"""
if self.model != 'HSV': return
converted = Color('HSL',np.array([
self.color[0],
1. if self.color[2] == 0.0 or (self.color[1] == 0.0 and self.color[2] == 1.0) \
else self.color[1]*self.color[2]/(1.-abs(self.color[2]*(2.-self.color[1])-1.)),
0.5*self.color[2]*(2.-self.color[1]),
]))
self.model = converted.model
self.color = converted.color
def _HSL2HSV(self):
"""
Convert H(ue) S(aturation) L(uminance) to H(ue) S(aturation) V(alue or brightness).
All values are in the range [0,1]
http://codeitdown.com/hsl-hsb-hsv-color
"""
if self.model != 'HSL': return
h = self.color[0]
b = self.color[2]+0.5*(self.color[1]*(1.-abs(2*self.color[2]-1)))
s = 1.0 if b == 0.0 else 2.*(b-self.color[2])/b
converted = Color('HSV',np.array([h,s,b]))
self.model = converted.model
self.color = converted.color
def _HSL2RGB(self):
"""
Convert H(ue) S(aturation) L(uminance) to R(red) G(reen) B(lue).
All values are in the range [0,1]
from http://en.wikipedia.org/wiki/HSL_and_HSV
"""
if self.model != 'HSL': return
sextant = self.color[0]*6.0
c = (1.0 - abs(2.0 * self.color[2] - 1.0))*self.color[1]
x = c*(1.0 - abs(sextant%2 - 1.0))
m = self.color[2] - 0.5*c
converted = Color('RGB',np.array([
[c+m, x+m, m],
[x+m, c+m, m],
[m, c+m, x+m],
[m, x+m, c+m],
[x+m, m, c+m],
[c+m, m, x+m],
][int(sextant)]))
self.model = converted.model
self.color = converted.color
def _RGB2HSL(self):
"""
Convert R(ed) G(reen) B(lue) to H(ue) S(aturation) L(uminance).
All values are in the range [0,1]
from http://130.113.54.154/~monger/hsl-rgb.html
"""
if self.model != 'RGB': return
HSL = np.zeros(3)
maxcolor = self.color.max()
mincolor = self.color.min()
HSL[2] = (maxcolor + mincolor)/2.0
if(mincolor == maxcolor):
HSL[0] = 0.0
HSL[1] = 0.0
else:
if (HSL[2]<0.5):
HSL[1] = (maxcolor - mincolor)/(maxcolor + mincolor)
else:
HSL[1] = (maxcolor - mincolor)/(2.0 - maxcolor - mincolor)
if (maxcolor == self.color[0]):
HSL[0] = 0.0 + (self.color[1] - self.color[2])/(maxcolor - mincolor)
elif (maxcolor == self.color[1]):
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 # scaling to 360 might be dangerous for small values
if (HSL[0] < 0.0):
HSL[0] = HSL[0] + 360.0
HSL[1:] = np.clip(HSL[1:],0.0,1.0)
converted = Color('HSL', HSL)
self.model = converted.model
self.color = converted.color
def _RGB2XYZ(self):
"""
Convert R(ed) G(reen) B(lue) to CIE XYZ.
All values are in the range [0,1]
from http://www.cs.rit.edu/~ncs/color/t_convert.html
"""
if self.model != 'RGB': return
XYZ = np.zeros(3)
RGB_lin = np.zeros(3)
convert = np.array([[0.412453,0.357580,0.180423],
[0.212671,0.715160,0.072169],
[0.019334,0.119193,0.950227]])
for i in range(3):
if (self.color[i] > 0.04045): RGB_lin[i] = ((self.color[i]+0.0555)/1.0555)**2.4
else: RGB_lin[i] = self.color[i] /12.92
XYZ = np.dot(convert,RGB_lin)
XYZ = np.clip(XYZ,0.0,None)
converted = Color('XYZ', XYZ)
self.model = converted.model
self.color = converted.color
def _XYZ2RGB(self):
"""
Convert CIE XYZ to R(ed) G(reen) B(lue).
All values are in the range [0,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],
[-0.969256, 1.875992, 0.041556],
[ 0.055648,-0.204043, 1.057311]])
RGB_lin = np.dot(convert,self.color)
RGB = np.zeros(3)
for i in range(3):
if (RGB_lin[i] > 0.0031308): RGB[i] = ((RGB_lin[i])**(1.0/2.4))*1.0555-0.0555
else: RGB[i] = RGB_lin[i] *12.92
RGB = np.clip(RGB,0.0,1.0)
maxVal = max(RGB) # clipping colors according to the display gamut
if (maxVal > 1.0): RGB /= maxVal
converted = Color('RGB', RGB)
self.model = converted.model
self.color = converted.color
def _CIELAB2XYZ(self):
"""
Convert CIE Lab to CIE XYZ.
All values are in the range [0,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]) # Observer = 2, Illuminant = D65
XYZ = np.zeros(3)
XYZ[1] = (self.color[0] + 16.0 ) / 116.0
XYZ[0] = XYZ[1] + self.color[1]/ 500.0
XYZ[2] = XYZ[1] - self.color[2]/ 200.0
for i in range(len(XYZ)):
if (XYZ[i] > 6./29. ): XYZ[i] = XYZ[i]**3.
else: XYZ[i] = 108./841. * (XYZ[i] - 4./29.)
converted = Color('XYZ', XYZ*ref_white)
self.model = converted.model
self.color = converted.color
def _XYZ2CIELAB(self):
"""
Convert CIE XYZ to CIE Lab.
All values are in the range [0,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]) # Observer = 2, Illuminant = D65
XYZ = self.color/ref_white
for i in range(len(XYZ)):
if (XYZ[i] > 216./24389 ): XYZ[i] = XYZ[i]**(1.0/3.0)
else: XYZ[i] = (841./108. * XYZ[i]) + 16.0/116.0
converted = Color('CIELAB', np.array([ 116.0 * XYZ[1] - 16.0,
500.0 * (XYZ[0] - XYZ[1]),
200.0 * (XYZ[1] - XYZ[2]) ]))
self.model = converted.model
self.color = converted.color
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)
Msh[0] = np.sqrt(np.dot(self.color,self.color))
if (Msh[0] > 0.001):
Msh[1] = np.arccos(self.color[0]/Msh[0])
if (self.color[1] != 0.0):
Msh[2] = np.arctan2(self.color[2],self.color[1])
converted = Color('MSH', Msh)
self.model = converted.model
self.color = converted.color
def _MSH2CIELAB(self):
"""
Convert Msh colorspace to CIE Lab.
with s,h in radians
from http://www.cs.unm.edu/~kmorel/documents/ColorMaps/DivergingColorMapWorkshop.xls
"""
if self.model != 'MSH': return
Lab = np.zeros(3)
Lab[0] = self.color[0] * np.cos(self.color[1])
Lab[1] = self.color[0] * np.sin(self.color[1]) * np.cos(self.color[2])
Lab[2] = self.color[0] * np.sin(self.color[1]) * np.sin(self.color[2])
converted = Color('CIELAB', Lab)
self.model = converted.model
self.color = converted.color
class Colormap:
"""Perceptually uniform diverging or sequential colormap."""
__slots__ = [
'left',
'right',
'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' },
'orientation': {'left': Color('RGB',[0.933334,0.878432,0.878431]),
'right': Color('RGB',[0.250980,0.007843,0.000000]),
'interpolate': 'perceptualuniform'},
'strain': {'left': Color('RGB',[0.941177,0.941177,0.870588]),
'right': Color('RGB',[0.266667,0.266667,0.000000]),
'interpolate': 'perceptualuniform'},
'stress': {'left': Color('RGB',[0.878432,0.874511,0.949019]),
'right': Color('RGB',[0.000002,0.000000,0.286275]),
'interpolate': 'perceptualuniform'},
}
def __init__(self,
left = Color('RGB',[1,1,1]),
right = Color('RGB',[0,0,0]),
interpolate = 'perceptualuniform',
predefined = None
):
"""
Create a Colormap object.
Parameters
----------
left : Color
left color (minimum value)
right : Color
right color (maximum value)
interpolate : str
interpolation scheme (either 'perceptualuniform' or 'linear')
predefined : bool
ignore other arguments and use predefined definition
"""
if predefined is not None:
left = self.__predefined__[predefined.lower()]['left']
right= self.__predefined__[predefined.lower()]['right']
interpolate = self.__predefined__[predefined.lower()]['interpolate']
if left.__class__.__name__ != 'Color':
left = Color()
if right.__class__.__name__ != 'Color':
right = Color()
self.left = left
self.right = right
self.interpolate = interpolate
def __repr__(self):
"""Left and right value of colormap."""
return 'Left: %s Right: %s'%(self.left,self.right)
def invert(self):
"""Switch left/minimum with right/maximum."""
(self.left, self.right) = (self.right, self.left)
return self
def show_predefined(self):
"""Show the labels of the predefined colormaps."""
print('\n'.join(self.__predefined__.keys()))
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 Msh_sat[0] >= Msh_unsat[0]:
return Msh_sat[2]
else:
hSpin = Msh_sat[1]/np.sin(Msh_sat[1])*np.sqrt(Msh_unsat[0]**2.0-Msh_sat[0]**2)/Msh_sat[0]
if Msh_sat[2] < - np.pi/3.0: hSpin *= -1.0
return Msh_sat[2] + hSpin
Msh1 = np.array(lo[:])
Msh2 = np.array(hi[:])
if (Msh1[1] > 0.05 and Msh2[1] > 0.05 and rad_diff(Msh1,Msh2) > np.pi/3.0):
M_mid = max(Msh1[0],Msh2[0],88.0)
if frac < 0.5:
Msh2 = np.array([M_mid,0.0,0.0])
frac *= 2.0
else:
Msh1 = np.array([M_mid,0.0,0.0])
frac = 2.0*frac - 1.0
if Msh1[1] < 0.05 and Msh2[1] > 0.05: Msh1[2] = adjust_hue(Msh2,Msh1)
elif Msh1[1] > 0.05 and Msh2[1] < 0.05: Msh2[2] = adjust_hue(Msh1,Msh2)
Msh = (1.0 - frac) * Msh1 + frac * Msh2
return Color('MSH',Msh)
def interpolate_linear(lo, hi, frac):
"""Linear interpolation between lo and hi color at given fraction; output in model of lo color."""
interpolation = (1.0 - frac) * np.array(lo.color[:]) \
+ frac * np.array(hi.express_as(lo.model).color[:])
return Color(lo.model,interpolation)
if self.interpolate == 'perceptualuniform':
return interpolate_Msh(self.left.express_as('MSH').color,
self.right.express_as('MSH').color,fraction)
elif self.interpolate == 'linear':
return interpolate_linear(self.left,self.right,fraction)
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
colors = [self.color(float(i)/(steps-1)*(frac[1]-frac[0])+frac[0]).express_as(model).color for i in range(steps)]
if format == 'paraview':
colormap = ['[\n {{\n "ColorSpace": "RGB", "Name": "{}", "DefaultMap": true,\n "RGBPoints" : ['.format(name)] \
+ [' {:4d},{:8.6f},{:8.6f},{:8.6f},'.format(i,color[0],color[1],color[2],) \
for i,color in enumerate(colors[:-1])] \
+ [' {:4d},{:8.6f},{:8.6f},{:8.6f} '.format(len(colors),colors[-1][0],colors[-1][1],colors[-1][2],)] \
+ [' ]\n }\n]']
elif format == 'gmsh':
colormap = ['View.ColorTable = {'] \
+ [',\n'.join(['{%s}'%(','.join([str(x*255.0) for x in color])) for color in colors])] \
+ ['}']
elif format == 'gom':
colormap = ['1 1 ' + str(name)
+ ' 9 ' + str(name)
+ ' 0 1 0 3 0 0 -1 9 \\ 0 0 0 255 255 255 0 0 255 '
+ '30 NO_UNIT 1 1 64 64 64 255 1 0 0 0 0 0 0 3 0 ' + str(len(colors))
+ ' '.join([' 0 %s 255 1'%(' '.join([str(int(x*255.0)) for x in color])) for color in reversed(colors)])]
elif format == 'raw':
colormap = ['\t'.join(map(str,color)) for color in colors]
elif format == 'list':
colormap = colors
else:
raise NameError('unknown color export format')
return '\n'.join(colormap) + '\n' if type(colormap[0]) is str else colormap

View File

@ -1,16 +1,17 @@
import os
import tkinter
class Environment():
class Environment:
def __init__(self):
"""Read and provide values of DAMASK configuration."""
self.options = self._get_options()
try:
import tkinter
tk = tkinter.Tk()
self.screen_width = tk.winfo_screenwidth()
self.screen_height = tk.winfo_screenheight()
except Exception:
tk.destroy()
except tkinter.TclError:
self.screen_width = 1024
self.screen_height = 768

View File

@ -8,7 +8,7 @@ from . import VTK
from . import util
class Geom():
class Geom:
"""Geometry definition for grid solvers."""
def __init__(self,microstructure,size,origin=[0.0,0.0,0.0],homogenization=1,comments=[]):
@ -47,6 +47,7 @@ class Geom():
'max microstructure: {}'.format(np.nanmax(self.microstructure)),
])
def update(self,microstructure=None,size=None,origin=None,rescale=False):
"""
Updates microstructure and size.
@ -109,6 +110,7 @@ class Geom():
return util.return_message(message)
def set_comments(self,comments):
"""
Replaces all existing comments.
@ -122,6 +124,7 @@ class Geom():
self.comments = []
self.add_comments(comments)
def add_comments(self,comments):
"""
Appends comments to existing comments.
@ -134,6 +137,7 @@ class Geom():
"""
self.comments += [str(c) for c in comments] if isinstance(comments,list) else [str(comments)]
def set_microstructure(self,microstructure):
"""
Replaces the existing microstructure representation.
@ -152,6 +156,7 @@ class Geom():
else:
self.microstructure = np.copy(microstructure)
def set_size(self,size):
"""
Replaces the existing size information.
@ -171,6 +176,7 @@ class Geom():
else:
self.size = np.array(size)
def set_origin(self,origin):
"""
Replaces the existing origin information.
@ -187,6 +193,7 @@ class Geom():
else:
self.origin = np.array(origin)
def set_homogenization(self,homogenization):
"""
Replaces the existing homogenization index.
@ -203,34 +210,47 @@ class Geom():
else:
self.homogenization = homogenization
@property
def grid(self):
return self.get_grid()
@property
def N_microstructure(self):
return len(np.unique(self.microstructure))
def get_microstructure(self):
"""Return the microstructure representation."""
return np.copy(self.microstructure)
def get_size(self):
"""Return the physical size in meter."""
return np.copy(self.size)
def get_origin(self):
"""Return the origin in meter."""
return np.copy(self.origin)
def get_grid(self):
"""Return the grid discretization."""
return np.array(self.microstructure.shape)
def get_homogenization(self):
"""Return the homogenization index."""
return self.homogenization
def get_comments(self):
"""Return the comments."""
return self.comments[:]
def get_header(self):
"""Return the full header (grid, size, origin, homogenization, comments)."""
header = ['{} header'.format(len(self.comments)+4)] + self.comments
@ -240,6 +260,7 @@ class Geom():
header.append('homogenization {}'.format(self.get_homogenization()))
return header
@staticmethod
def from_file(fname):
"""
@ -425,8 +446,8 @@ class Geom():
if 'x' in directions:
ms = np.concatenate([ms,ms[limits[0]:limits[1]:-1,:,:]],0)
#self.add_comments('geom.py:mirror v{}'.format(version)
return self.update(ms,rescale=True)
#self.add_comments('tbd')
def scale(self,grid):
@ -439,6 +460,7 @@ class Geom():
new grid dimension
"""
#self.add_comments('geom.py:scale v{}'.format(version)
return self.update(
ndimage.interpolation.zoom(
self.microstructure,
@ -449,7 +471,6 @@ class Geom():
prefilter=False
)
)
#self.add_comments('tbd')
def clean(self,stencil=3):
@ -466,13 +487,13 @@ class Geom():
unique, inverse = np.unique(arr, return_inverse=True)
return unique[np.argmax(np.bincount(inverse))]
#self.add_comments('geom.py:clean v{}'.format(version)
return self.update(ndimage.filters.generic_filter(
self.microstructure,
mostFrequent,
size=(stencil,)*3
).astype(self.microstructure.dtype)
)
#self.add_comments('tbd')
def renumber(self):
@ -481,5 +502,5 @@ class Geom():
for i, oldID in enumerate(np.unique(self.microstructure)):
renumbered = np.where(self.microstructure == oldID, i+1, renumbered)
#self.add_comments('geom.py:renumber v{}'.format(version)
return self.update(renumbered)
#self.add_comments('tbd')

View File

@ -1,10 +1,8 @@
import numpy as np
from .rotation import Rotation
from . import Rotation
P = -1
# ******************************************************************************************
class Symmetry:
"""
Symmetry operations for lattice systems.

View File

@ -1,7 +1,7 @@
import numpy as np
from .lattice import Lattice
from .rotation import Rotation
from . import Lattice
from . import Rotation
class Orientation:
"""

View File

@ -22,7 +22,7 @@ class Result:
"""
Read and write to DADF5 files.
DADF5 (DAKMASK HDF5) files contain DAMASK results.
DADF5 (DAMASK HDF5) files contain DAMASK results.
"""
def __init__(self,fname):
@ -85,7 +85,14 @@ class Result:
def __repr__(self):
"""Show selected data."""
return util.srepr(self.list_data())
all_selected_increments = self.selection['increments']
self.pick('increments',all_selected_increments[0:1])
first = self.list_data()
self.pick('increments',all_selected_increments[-1:])
last = self.list_data()
self.pick('increments',all_selected_increments)
in_between = ''.join(['\n{}\n ...\n'.format(inc) for inc in all_selected_increments[1:-2]])
return util.srepr(first+ in_between + last)
def _manage_selection(self,action,what,datasets):
@ -171,13 +178,13 @@ class Result:
"""
datasets = self.selection[what]
last_datasets = datasets.copy()
last_selection = datasets.copy()
for dataset in datasets:
if last_datasets != self.selection[what]:
if last_selection != self.selection[what]:
self._manage_selection('set',what,datasets)
raise Exception
self._manage_selection('set',what,dataset)
last_datasets = self.selection[what]
last_selection = self.selection[what]
yield dataset
self._manage_selection('set',what,datasets)
@ -664,7 +671,7 @@ class Result:
'meta' : {
'Unit': 'RGB (8bit)',
'Lattice': lattice,
'Description': 'Inverse Pole Figure (IPF) colors for direction/plane [{} {} {})'.format(*m),
'Description': 'Inverse Pole Figure (IPF) colors along sample direction [{} {} {}]'.format(*m),
'Creator': 'result.py:add_IPFcolor v{}'.format(version)
}
}
@ -1014,13 +1021,13 @@ class Result:
pool.join()
def to_vtk(self,labels,mode='cell'):
def to_vtk(self,labels=[],mode='cell'):
"""
Export to vtk cell/point data.
Parameters
----------
labels : str or list of
labels : str or list of, optional
Labels of the datasets to be exported.
mode : str, either 'cell' or 'point'
Export in cell format or point format.
@ -1039,7 +1046,7 @@ class Result:
elif mode.lower()=='point':
v = VTK.from_polyData(self.cell_coordinates())
N_digits = int(np.floor(np.log10(min(int(self.increments[-1][3:]),1))))+1
N_digits = int(np.floor(np.log10(int(self.increments[-1][3:]))))+1
for i,inc in enumerate(util.show_progress(self.iterate('increments'),len(self.selection['increments']))):
@ -1093,9 +1100,6 @@ class Result:
###################################################################################################
# BEGIN DEPRECATED
iter_visible = iterate
iter_selection = iterate
def _time_to_inc(self,start,end):
selected = []
@ -1118,21 +1122,3 @@ class Result:
"""
self._manage_selection('set','increments',self._time_to_inc(start,end))
def set_by_increment(self,start,end):
"""
Set active time increments based on start and end increment.
Parameters
----------
start : int
start increment (included)
end : int
end increment (included)
"""
if self.version_minor >= 4:
self._manage_selection('set','increments',[ 'inc{}'.format(i) for i in range(start,end+1)])
else:
self._manage_selection('set','increments',['inc{:05d}'.format(i) for i in range(start,end+1)])

View File

@ -1,6 +1,6 @@
import numpy as np
from . import Lambert
from ._Lambert import ball_to_cube, cube_to_ball
P = -1
@ -304,7 +304,7 @@ class Rotation:
reciprocal = False,
):
om = basis if isinstance(basis, np.ndarray) else np.array(basis).reshape((3,3))
om = basis if isinstance(basis, np.ndarray) else np.array(basis).reshape(3,3)
if reciprocal:
om = np.linalg.inv(om.T/np.pi) # transform reciprocal basis set
orthonormal = False # contains stretch
@ -338,7 +338,7 @@ class Rotation:
if not np.isclose(np.linalg.norm(ro[0:3]), 1.0):
raise ValueError('Rodrigues rotation axis is not of unit length.\n{} {} {}'.format(*ro[0:3]))
if ro[3] < 0.0:
raise ValueError('Rodriques rotation angle not positive.\n'.format(ro[3]))
raise ValueError('Rodrigues rotation angle not positive.\n'.format(ro[3]))
return Rotation(Rotation.ro2qu(ro))
@ -492,7 +492,7 @@ class Rotation:
@staticmethod
def qu2ro(qu):
"""Quaternion to Rodriques-Frank vector."""
"""Quaternion to Rodrigues-Frank vector."""
if iszero(qu[0]):
ro = [qu[1], qu[2], qu[3], np.inf]
else:
@ -567,7 +567,7 @@ class Rotation:
@staticmethod
def om2ro(om):
"""Rotation matrix to Rodriques-Frank vector."""
"""Rotation matrix to Rodrigues-Frank vector."""
return Rotation.eu2ro(Rotation.om2eu(om))
@staticmethod
@ -628,7 +628,7 @@ class Rotation:
@staticmethod
def eu2ro(eu):
"""Bunge-Euler angles to Rodriques-Frank vector."""
"""Bunge-Euler angles to Rodrigues-Frank vector."""
ro = Rotation.eu2ax(eu) # convert to axis angle pair representation
if ro[3] >= np.pi: # Differs from original implementation. check convention 5
ro[3] = np.inf
@ -682,7 +682,7 @@ class Rotation:
@staticmethod
def ax2ro(ax):
"""Axis angle pair to Rodriques-Frank vector."""
"""Axis angle pair to Rodrigues-Frank vector."""
if iszero(ax[3]):
ro = [ 0.0, 0.0, P, 0.0 ]
else:
@ -708,7 +708,7 @@ class Rotation:
#---------- Rodrigues-Frank vector ----------
@staticmethod
def ro2qu(ro):
"""Rodriques-Frank vector to quaternion."""
"""Rodrigues-Frank vector to quaternion."""
return Rotation.ax2qu(Rotation.ro2ax(ro))
@staticmethod
@ -718,12 +718,12 @@ class Rotation:
@staticmethod
def ro2eu(ro):
"""Rodriques-Frank vector to Bunge-Euler angles."""
"""Rodrigues-Frank vector to Bunge-Euler angles."""
return Rotation.om2eu(Rotation.ro2om(ro))
@staticmethod
def ro2ax(ro):
"""Rodriques-Frank vector to axis angle pair."""
"""Rodrigues-Frank vector to axis angle pair."""
ta = ro[3]
if iszero(ta):
@ -738,7 +738,7 @@ class Rotation:
@staticmethod
def ro2ho(ro):
"""Rodriques-Frank vector to homochoric vector."""
"""Rodrigues-Frank vector to homochoric vector."""
if iszero(np.sum(ro[0:3]**2.0)):
ho = [ 0.0, 0.0, 0.0 ]
else:
@ -748,7 +748,7 @@ class Rotation:
@staticmethod
def ro2cu(ro):
"""Rodriques-Frank vector to cubochoric vector."""
"""Rodrigues-Frank vector to cubochoric vector."""
return Rotation.ho2cu(Rotation.ro2ho(ro))
@ -796,13 +796,13 @@ class Rotation:
@staticmethod
def ho2ro(ho):
"""Axis angle pair to Rodriques-Frank vector."""
"""Axis angle pair to Rodrigues-Frank vector."""
return Rotation.ax2ro(Rotation.ho2ax(ho))
@staticmethod
def ho2cu(ho):
"""Homochoric vector to cubochoric vector."""
return Lambert.BallToCube(ho)
return ball_to_cube(ho)
#---------- Cubochoric ----------
@ -828,10 +828,10 @@ class Rotation:
@staticmethod
def cu2ro(cu):
"""Cubochoric vector to Rodriques-Frank vector."""
"""Cubochoric vector to Rodrigues-Frank vector."""
return Rotation.ho2ro(Rotation.cu2ho(cu))
@staticmethod
def cu2ho(cu):
"""Cubochoric vector to homochoric vector."""
return Lambert.CubeToBall(cu)
return cube_to_ball(cu)

View File

@ -5,7 +5,7 @@ import numpy as np
from . import version
class Table():
class Table:
"""Store spreadsheet-like data."""
def __init__(self,data,shapes,comments=None):
@ -25,10 +25,10 @@ class Table():
self.comments = [] if comments is None else [c for c in comments]
self.data = pd.DataFrame(data=data)
self.shapes = shapes
self.__label_condensed()
self._label_condensed()
def __label_flat(self):
def _label_flat(self):
"""Label data individually, e.g. v v v ==> 1_v 2_v 3_v."""
labels = []
for label,shape in self.shapes.items():
@ -37,7 +37,7 @@ class Table():
self.data.columns = labels
def __label_condensed(self):
def _label_condensed(self):
"""Label data condensed, e.g. 1_v 2_v 3_v ==> v v v."""
labels = []
for label,shape in self.shapes.items():
@ -45,11 +45,10 @@ class Table():
self.data.columns = labels
def __add_comment(self,label,shape,info):
def _add_comment(self,label,shape,info):
if info is not None:
self.comments.append('{}{}: {}'.format(label,
' '+str(shape) if np.prod(shape,dtype=int) > 1 else '',
info))
c = '{}{}: {}'.format(label,' '+str(shape) if np.prod(shape,dtype=int) > 1 else '',info)
self.comments.append(c)
@staticmethod
@ -57,7 +56,8 @@ class Table():
"""
Create table from ASCII file.
The first line needs to indicate the number of subsequent header lines as 'n header'.
The first line can indicate the number of subsequent header lines as 'n header',
alternatively first line is the header and comments are marked by '#' ('new style').
Vector data column labels are indicated by '1_v, 2_v, ..., n_v'.
Tensor data column labels are indicated by '3x3:1_T, 3x3:2_T, ..., 3x3:9_T'.
@ -167,7 +167,7 @@ class Table():
"""
if re.match(r'[0-9]*?_',label):
idx,key = label.split('_',1)
data = self.data[key].to_numpy()[:,int(idx)-1].reshape((-1,1))
data = self.data[key].to_numpy()[:,int(idx)-1].reshape(-1,1)
else:
data = self.data[label].to_numpy().reshape((-1,)+self.shapes[label])
@ -188,7 +188,7 @@ class Table():
Human-readable information about the new data.
"""
self.__add_comment(label,data.shape[1:],info)
self._add_comment(label,data.shape[1:],info)
if re.match(r'[0-9]*?_',label):
idx,key = label.split('_',1)
@ -212,7 +212,7 @@ class Table():
Human-readable information about the modified data.
"""
self.__add_comment(label,data.shape[1:],info)
self._add_comment(label,data.shape[1:],info)
self.shapes[label] = data.shape[1:] if len(data.shape) > 1 else (1,)
size = np.prod(data.shape[1:],dtype=int)
@ -251,12 +251,8 @@ class Table():
"""
self.data.rename(columns={label_old:label_new},inplace=True)
self.comments.append('{} => {}{}'.format(label_old,
label_new,
'' if info is None else ': {}'.format(info),
))
c = '{} => {}{}'.format(label_old,label_new,'' if info is None else ': {}'.format(info))
self.comments.append(c)
self.shapes = {(label if label != label_old else label_new):self.shapes[label] for label in self.shapes}
@ -272,9 +268,9 @@ class Table():
Set sort order.
"""
self.__label_flat()
self._label_flat()
self.data.sort_values(labels,axis=0,inplace=True,ascending=ascending)
self.__label_condensed()
self._label_condensed()
self.comments.append('sorted by [{}]'.format(', '.join(labels)))
@ -287,7 +283,7 @@ class Table():
Parameters
----------
other : Table
Table to append
Table to append.
"""
if self.shapes != other.shapes or not self.data.columns.equals(other.data.columns):
@ -305,7 +301,7 @@ class Table():
Parameters
----------
other : Table
Table to join
Table to join.
"""
if set(self.shapes) & set(other.shapes) or self.data.shape[0] != other.data.shape[0]:
@ -316,14 +312,16 @@ class Table():
self.shapes[key] = other.shapes[key]
def to_ASCII(self,fname,new=False):
def to_ASCII(self,fname,new_style=False):
"""
Store as plain text file.
Parameters
----------
fname : file, str, or pathlib.Path
Filename or file for reading.
Filename or file for writing.
new_style : Boolean, optional
Write table in new style, indicating header lines by comment sign ('#') only.
"""
seen = set()
@ -338,7 +336,7 @@ class Table():
labels += ['{}:{}_{}'.format('x'.join([str(d) for d in self.shapes[l]]),i+1,l) \
for i in range(np.prod(self.shapes[l]))]
if new:
if new_style:
header = ['# {}'.format(comment) for comment in self.comments]
else:
header = ['{} header'.format(len(self.comments)+1)] \

View File

@ -1,11 +1,16 @@
import os,sys,shutil
import logging,logging.config
import damask
import numpy as np
import os
import sys
import shutil
import logging
import logging.config
from collections.abc import Iterable
from optparse import OptionParser
class Test():
import numpy as np
import damask
class Test:
"""
General class for testing.
@ -282,12 +287,10 @@ class Test():
import numpy as np
logging.info('\n '.join(['comparing',File1,File2]))
table1 = damask.ASCIItable(name=File1,readonly=True)
table1.head_read()
len1=len(table1.info)+2
table2 = damask.ASCIItable(name=File2,readonly=True)
table2.head_read()
len2=len(table2.info)+2
table = damask.Table.from_ASCII(File1)
len1=len(table.comments)+2
table = damask.Table.from_ASCII(File2)
len2=len(table.comments)+2
refArray = np.nan_to_num(np.genfromtxt(File1,missing_values='n/a',skip_header = len1,autostrip=True))
curArray = np.nan_to_num(np.genfromtxt(File2,missing_values='n/a',skip_header = len2,autostrip=True))
@ -445,15 +448,15 @@ class Test():
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]
tables = [damask.Table.from_ASCII(filename) for filename in files]
for table in tables:
table.head_read()
table._label_flat()
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(raw = True) # if no column is given, read all
if column is None: columns[i] = list(tables[i].data.columns) # if no column is given, read all
logging.info('comparing ASCIItables statistically')
for i in range(len(columns)):
@ -467,9 +470,8 @@ class Test():
data = []
for table,labels in zip(tables,columns):
table.data_readArray(labels)
data.append(table.data)
table.close()
table._label_condensed()
data.append(np.hstack(list(table.get(label) for label in labels)))
for i in range(1,len(data)):
@ -497,15 +499,13 @@ class Test():
if len(files) < 2: return True # single table is always close to itself...
tables = [damask.ASCIItable(name = filename,readonly = True) for filename in files]
for table in tables:
table.head_read()
tables = [damask.Table.from_ASCII(filename) for filename in 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(raw = False) # if no column is given, use all
if column is None: columns[i] = list(tables[i].shapes.keys()) # if no column is given, use all
logging.info('comparing ASCIItables')
for i in range(len(columns)):
@ -515,22 +515,20 @@ class Test():
)
logging.info(files[i]+': '+','.join(columns[i]))
dimensions = tables[0].label_dimension(columns[0]) # width of each requested column
dimensions = [np.prod(tables[0].shapes[c]) for c in columns[0]] # width of each requested column
maximum = np.zeros_like(columns[0],dtype=float) # one magnitude per column entry
data = [] # list of feature table extracted from each file (ASCII table)
for i,(table,labels) in enumerate(zip(tables,columns)):
if np.any(dimensions != table.label_dimension(labels)): # check data object consistency
if np.any(dimensions != [np.prod(table.shapes[c]) for c in labels]): # check data object consistency
logging.critical('Table {} differs in data layout.'.format(files[i]))
return False
table.data_readArray(labels) # read data, ...
data.append(table.data) # ... store, ...
table.close() # ... close
data.append(np.hstack(list(table.get(label) for label in labels)).astype(np.float)) # store
for j,label in enumerate(labels): # iterate over object labels
maximum[j] = np.maximum(
maximum[j],
np.amax(np.linalg.norm(table.data[:,table.label_indexrange(label)],
np.amax(np.linalg.norm(table.get(label),
axis=1))
) # find maximum Euclidean norm across rows
@ -552,8 +550,6 @@ class Test():
logging.info('data : {}'.format(np.absolute(data[1][j])[culprits]))
logging.info('deviation: {}'.format(np.absolute(data[0][j]-data[1][j])[goodguys]))
logging.info('data : {}'.format(np.absolute(data[1][j])[goodguys]))
# for ok,valA,valB in zip(allclose,data[0],data[1]):
# logging.debug('{}:\n{}\n{}'.format(ok,valA,valB))
allclose = True # start optimistic
for i in range(1,len(data)):

View File

@ -4,6 +4,7 @@ import pandas as pd
import numpy as np
import vtk
from vtk.util.numpy_support import numpy_to_vtk as np_to_vtk
from vtk.util.numpy_support import numpy_to_vtkIdTypeArray as np_to_vtkIdTypeArray
from . import Table
from . import Environment
@ -30,6 +31,7 @@ class VTK:
"""
self.geom = geom
@staticmethod
def from_rectilinearGrid(grid,size,origin=np.zeros(3)):
"""
@ -47,16 +49,11 @@ class VTK:
Spatial origin.
"""
coordArray = [vtk.vtkDoubleArray(),vtk.vtkDoubleArray(),vtk.vtkDoubleArray()]
for dim in [0,1,2]:
coords = np.linspace(origin[dim],origin[dim]+size[dim],grid[dim]+1)
coordArray[dim].SetArray(np_to_vtk(coords),grid[dim]+1,1)
geom = vtk.vtkRectilinearGrid()
geom.SetDimensions(*(grid+1))
geom.SetXCoordinates(coordArray[0])
geom.SetYCoordinates(coordArray[1])
geom.SetZCoordinates(coordArray[2])
geom.SetXCoordinates(np_to_vtk(np.linspace(origin[0],origin[0]+size[0],grid[0]+1),deep=True))
geom.SetYCoordinates(np_to_vtk(np.linspace(origin[1],origin[1]+size[1],grid[1]+1),deep=True))
geom.SetZCoordinates(np_to_vtk(np.linspace(origin[2],origin[2]+size[2],grid[2]+1),deep=True))
return VTK(geom)
@ -84,7 +81,7 @@ class VTK:
cells.SetNumberOfCells(connectivity.shape[0])
T = np.concatenate((np.ones((connectivity.shape[0],1),dtype=np.int64)*connectivity.shape[1],
connectivity),axis=1).ravel()
cells.SetCells(connectivity.shape[0],np_to_vtk(T, deep=True, array_type=vtk.VTK_ID_TYPE))
cells.SetCells(connectivity.shape[0],np_to_vtkIdTypeArray(T,deep=True))
geom = vtk.vtkUnstructuredGrid()
geom.SetPoints(vtk_nodes)
@ -123,9 +120,9 @@ class VTK:
Parameters
----------
fname : str
Filename for reading. Valid extensions are .vtk, .vtr, .vtu, and .vtp.
Filename for reading. Valid extensions are *.vtr, *.vtu, *.vtp, and *.vtk.
dataset_type : str, optional
Name of the vtk.vtkDataSet subclass when opening an .vtk file. Valid types are vtkRectilinearGrid,
Name of the vtk.vtkDataSet subclass when opening an *.vtk file. Valid types are vtkRectilinearGrid,
vtkUnstructuredGrid, and vtkPolyData.
"""
@ -134,11 +131,13 @@ class VTK:
reader = vtk.vtkGenericDataObjectReader()
reader.SetFileName(fname)
reader.Update()
if 'rectilineargrid' in dataset_type.lower():
if dataset_type is None:
raise TypeError('Dataset type for *.vtk file not given.')
elif dataset_type.lower().endswith('rectilineargrid'):
geom = reader.GetRectilinearGridOutput()
elif 'unstructuredgrid' in dataset_type.lower():
elif dataset_type.lower().endswith('unstructuredgrid'):
geom = reader.GetUnstructuredGridOutput()
elif 'polydata' in dataset_type.lower():
elif dataset_type.lower().endswith('polydata'):
geom = reader.GetPolyDataOutput()
else:
raise TypeError('Unknown dataset type for vtk file {}'.format(dataset_type))
@ -159,7 +158,6 @@ class VTK:
return VTK(geom)
# ToDo: If extension is given, check for consistency.
def write(self,fname):
"""
Write to file.
@ -177,8 +175,11 @@ class VTK:
elif(isinstance(self.geom,vtk.vtkPolyData)):
writer = vtk.vtkXMLPolyDataWriter()
writer.SetFileName('{}.{}'.format(os.path.splitext(fname)[0],
writer.GetDefaultFileExtension()))
default_ext = writer.GetDefaultFileExtension()
name, ext = os.path.splitext(fname)
if ext and ext != '.'+default_ext:
raise ValueError('Given extension {} is not .{}'.format(ext,default_ext))
writer.SetFileName('{}.{}'.format(name,default_ext))
writer.SetCompressorTypeToZLib()
writer.SetDataModeToBinary()
writer.SetInputData(self.geom)
@ -195,15 +196,19 @@ class VTK:
if isinstance(data,np.ndarray):
d = np_to_vtk(num_array=data.reshape(data.shape[0],-1),deep=True)
if label is None:
raise ValueError('No label defined for numpy.ndarray')
d.SetName(label)
if data.shape[0] == N_cells:
self.geom.GetCellData().AddArray(d)
elif data.shape[0] == N_points:
self.geom.GetPointData().AddArray(d)
elif isinstance(data,pd.DataFrame):
pass
raise NotImplementedError('pd.DataFrame')
elif isinstance(data,Table):
pass
raise NotImplementedError('damask.Table')
else:
raise TypeError
def __repr__(self):

View File

@ -1,556 +0,0 @@
import numpy as np
class Color():
"""Color representation in and conversion between different color-spaces."""
__slots__ = [
'model',
'color',
'__dict__',
]
def __init__(self,
model = 'RGB',
color = np.zeros(3,'d')):
"""
Create a Color object.
Parameters
----------
model : string
color model
color : numpy.ndarray
vector representing the color according to the selected model
"""
self.__transforms__ = \
{'HSV': {'index': 0, 'next': self._HSV2HSL},
'HSL': {'index': 1, 'next': self._HSL2RGB, 'prev': self._HSL2HSV},
'RGB': {'index': 2, 'next': self._RGB2XYZ, 'prev': self._RGB2HSL},
'XYZ': {'index': 3, 'next': self._XYZ2CIELAB, 'prev': self._XYZ2RGB},
'CIELAB': {'index': 4, 'next': self._CIELAB2MSH, 'prev': self._CIELAB2XYZ},
'MSH': {'index': 5, 'prev': self._MSH2CIELAB},
}
model = model.upper()
if model not in list(self.__transforms__.keys()): model = 'RGB'
if model == 'RGB' and max(color) > 1.0: # are we RGB255 ?
for i in range(3):
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
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 convert_to(self,toModel = 'RGB'):
"""
Change the color model permanently.
Parameters
----------
toModel : string
color model
"""
toModel = toModel.upper()
if toModel not in list(self.__transforms__.keys()): return
sourcePos = self.__transforms__[self.model]['index']
targetPos = self.__transforms__[toModel]['index']
while sourcePos < targetPos:
self.__transforms__[self.model]['next']()
sourcePos += 1
while sourcePos > targetPos:
self.__transforms__[self.model]['prev']()
sourcePos -= 1
return self
def express_as(self,asModel = 'RGB'):
"""
Return the color in a different model.
Parameters
----------
asModel : string
color model
"""
return self.__class__(self.model,self.color).convert_to(asModel)
def _HSV2HSL(self):
"""
Convert H(ue) S(aturation) V(alue or brightness) to H(ue) S(aturation) L(uminance).
All values are in the range [0,1]
http://codeitdown.com/hsl-hsb-hsv-color
"""
if self.model != 'HSV': return
converted = Color('HSL',np.array([
self.color[0],
1. if self.color[2] == 0.0 or (self.color[1] == 0.0 and self.color[2] == 1.0) \
else self.color[1]*self.color[2]/(1.-abs(self.color[2]*(2.-self.color[1])-1.)),
0.5*self.color[2]*(2.-self.color[1]),
]))
self.model = converted.model
self.color = converted.color
def _HSL2HSV(self):
"""
Convert H(ue) S(aturation) L(uminance) to H(ue) S(aturation) V(alue or brightness).
All values are in the range [0,1]
http://codeitdown.com/hsl-hsb-hsv-color
"""
if self.model != 'HSL': return
h = self.color[0]
b = self.color[2]+0.5*(self.color[1]*(1.-abs(2*self.color[2]-1)))
s = 1.0 if b == 0.0 else 2.*(b-self.color[2])/b
converted = Color('HSV',np.array([h,s,b]))
self.model = converted.model
self.color = converted.color
def _HSL2RGB(self):
"""
Convert H(ue) S(aturation) L(uminance) to R(red) G(reen) B(lue).
All values are in the range [0,1]
from http://en.wikipedia.org/wiki/HSL_and_HSV
"""
if self.model != 'HSL': return
sextant = self.color[0]*6.0
c = (1.0 - abs(2.0 * self.color[2] - 1.0))*self.color[1]
x = c*(1.0 - abs(sextant%2 - 1.0))
m = self.color[2] - 0.5*c
converted = Color('RGB',np.array([
[c+m, x+m, m],
[x+m, c+m, m],
[m, c+m, x+m],
[m, x+m, c+m],
[x+m, m, c+m],
[c+m, m, x+m],
][int(sextant)],'d'))
self.model = converted.model
self.color = converted.color
def _RGB2HSL(self):
"""
Convert R(ed) G(reen) B(lue) to H(ue) S(aturation) L(uminance).
All values are in the range [0,1]
from http://130.113.54.154/~monger/hsl-rgb.html
"""
if self.model != 'RGB': return
HSL = np.zeros(3,'d')
maxcolor = self.color.max()
mincolor = self.color.min()
HSL[2] = (maxcolor + mincolor)/2.0
if(mincolor == maxcolor):
HSL[0] = 0.0
HSL[1] = 0.0
else:
if (HSL[2]<0.5):
HSL[1] = (maxcolor - mincolor)/(maxcolor + mincolor)
else:
HSL[1] = (maxcolor - mincolor)/(2.0 - maxcolor - mincolor)
if (maxcolor == self.color[0]):
HSL[0] = 0.0 + (self.color[1] - self.color[2])/(maxcolor - mincolor)
elif (maxcolor == self.color[1]):
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 # scaling to 360 might be dangerous for small values
if (HSL[0] < 0.0):
HSL[0] = HSL[0] + 360.0
for i in range(2):
HSL[i+1] = min(HSL[i+1],1.0)
HSL[i+1] = max(HSL[i+1],0.0)
converted = Color('HSL', HSL)
self.model = converted.model
self.color = converted.color
def _RGB2XYZ(self):
"""
Convert R(ed) G(reen) B(lue) to CIE XYZ.
All values are in the range [0,1]
from http://www.cs.rit.edu/~ncs/color/t_convert.html
"""
if self.model != 'RGB': return
XYZ = np.zeros(3,'d')
RGB_lin = np.zeros(3,'d')
convert = np.array([[0.412453,0.357580,0.180423],
[0.212671,0.715160,0.072169],
[0.019334,0.119193,0.950227]])
for i in range(3):
if (self.color[i] > 0.04045): RGB_lin[i] = ((self.color[i]+0.0555)/1.0555)**2.4
else: RGB_lin[i] = self.color[i] /12.92
XYZ = np.dot(convert,RGB_lin)
for i in range(3):
XYZ[i] = max(XYZ[i],0.0)
converted = Color('XYZ', XYZ)
self.model = converted.model
self.color = converted.color
def _XYZ2RGB(self):
"""
Convert CIE XYZ to R(ed) G(reen) B(lue).
All values are in the range [0,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],
[-0.969256, 1.875992, 0.041556],
[ 0.055648,-0.204043, 1.057311]])
RGB_lin = np.dot(convert,self.color)
RGB = np.zeros(3,'d')
for i in range(3):
if (RGB_lin[i] > 0.0031308): RGB[i] = ((RGB_lin[i])**(1.0/2.4))*1.0555-0.0555
else: RGB[i] = RGB_lin[i] *12.92
for i in range(3):
RGB[i] = min(RGB[i],1.0)
RGB[i] = max(RGB[i],0.0)
maxVal = max(RGB) # clipping colors according to the display gamut
if (maxVal > 1.0): RGB /= maxVal
converted = Color('RGB', RGB)
self.model = converted.model
self.color = converted.color
def _CIELAB2XYZ(self):
"""
Convert CIE Lab to CIE XYZ.
All values are in the range [0,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
XYZ = np.zeros(3,'d')
XYZ[1] = (self.color[0] + 16.0 ) / 116.0
XYZ[0] = XYZ[1] + self.color[1]/ 500.0
XYZ[2] = XYZ[1] - self.color[2]/ 200.0
for i in range(len(XYZ)):
if (XYZ[i] > 6./29. ): XYZ[i] = XYZ[i]**3.
else: XYZ[i] = 108./841. * (XYZ[i] - 4./29.)
converted = Color('XYZ', XYZ*ref_white)
self.model = converted.model
self.color = converted.color
def _XYZ2CIELAB(self):
"""
Convert CIE XYZ to CIE Lab.
All values are in the range [0,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
XYZ = self.color/ref_white
for i in range(len(XYZ)):
if (XYZ[i] > 216./24389 ): XYZ[i] = XYZ[i]**(1.0/3.0)
else: XYZ[i] = (841./108. * XYZ[i]) + 16.0/116.0
converted = Color('CIELAB', np.array([ 116.0 * XYZ[1] - 16.0,
500.0 * (XYZ[0] - XYZ[1]),
200.0 * (XYZ[1] - XYZ[2]) ]))
self.model = converted.model
self.color = converted.color
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')
Msh[0] = np.sqrt(np.dot(self.color,self.color))
if (Msh[0] > 0.001):
Msh[1] = np.arccos(self.color[0]/Msh[0])
if (self.color[1] != 0.0):
Msh[2] = np.arctan2(self.color[2],self.color[1])
converted = Color('MSH', Msh)
self.model = converted.model
self.color = converted.color
def _MSH2CIELAB(self):
"""
Convert Msh colorspace to CIE Lab.
with 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')
Lab[0] = self.color[0] * np.cos(self.color[1])
Lab[1] = self.color[0] * np.sin(self.color[1]) * np.cos(self.color[2])
Lab[2] = self.color[0] * np.sin(self.color[1]) * np.sin(self.color[2])
converted = Color('CIELAB', Lab)
self.model = converted.model
self.color = converted.color
class Colormap():
"""Perceptually uniform diverging or sequential colormap."""
__slots__ = [
'left',
'right',
'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' },
'orientation': {'left': Color('RGB',[0.933334,0.878432,0.878431]),
'right': Color('RGB',[0.250980,0.007843,0.000000]),
'interpolate': 'perceptualuniform'},
'strain': {'left': Color('RGB',[0.941177,0.941177,0.870588]),
'right': Color('RGB',[0.266667,0.266667,0.000000]),
'interpolate': 'perceptualuniform'},
'stress': {'left': Color('RGB',[0.878432,0.874511,0.949019]),
'right': Color('RGB',[0.000002,0.000000,0.286275]),
'interpolate': 'perceptualuniform'},
}
# ------------------------------------------------------------------
def __init__(self,
left = Color('RGB',[1,1,1]),
right = Color('RGB',[0,0,0]),
interpolate = 'perceptualuniform',
predefined = None
):
"""
Create a Colormap object.
Parameters
----------
left : Color
left color (minimum value)
right : Color
right color (maximum value)
interpolate : str
interpolation scheme (either 'perceptualuniform' or 'linear')
predefined : bool
ignore other arguments and use predefined definition
"""
if predefined is not None:
left = self.__predefined__[predefined.lower()]['left']
right= self.__predefined__[predefined.lower()]['right']
interpolate = self.__predefined__[predefined.lower()]['interpolate']
if left.__class__.__name__ != 'Color':
left = Color()
if right.__class__.__name__ != 'Color':
right = Color()
self.left = left
self.right = right
self.interpolate = interpolate
# ------------------------------------------------------------------
def __repr__(self):
"""Left and right value of colormap."""
return 'Left: %s Right: %s'%(self.left,self.right)
# ------------------------------------------------------------------
def invert(self):
"""Switch left/minimum with right/maximum."""
(self.left, self.right) = (self.right, self.left)
return self
# ------------------------------------------------------------------
def show_predefined(self):
"""Show the labels of the predefined colormaps."""
print('\n'.join(self.__predefined__.keys()))
# ------------------------------------------------------------------
def color(self,fraction = 0.5):
def interpolate_Msh(lo, hi, frac):
def rad_diff(a,b):
return abs(a[2]-b[2])
# 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:
hSpin = Msh_sat[1]/np.sin(Msh_sat[1])*np.sqrt(Msh_unsat[0]**2.0-Msh_sat[0]**2)/Msh_sat[0]
if Msh_sat[2] < - np.pi/3.0: hSpin *= -1.0
return Msh_sat[2] + hSpin
Msh1 = np.array(lo[:])
Msh2 = np.array(hi[:])
if (Msh1[1] > 0.05 and Msh2[1] > 0.05 and rad_diff(Msh1,Msh2) > np.pi/3.0):
M_mid = max(Msh1[0],Msh2[0],88.0)
if frac < 0.5:
Msh2 = np.array([M_mid,0.0,0.0],'d')
frac *= 2.0
else:
Msh1 = np.array([M_mid,0.0,0.0],'d')
frac = 2.0*frac - 1.0
if Msh1[1] < 0.05 and Msh2[1] > 0.05: Msh1[2] = adjust_hue(Msh2,Msh1)
elif Msh1[1] > 0.05 and Msh2[1] < 0.05: Msh2[2] = adjust_hue(Msh1,Msh2)
Msh = (1.0 - frac) * Msh1 + frac * Msh2
return Color('MSH',Msh)
def interpolate_linear(lo, hi, frac):
"""Linear interpolation between lo and hi color at given fraction; output in model of lo color."""
interpolation = (1.0 - frac) * np.array(lo.color[:]) \
+ frac * np.array(hi.express_as(lo.model).color[:])
return Color(lo.model,interpolation)
if self.interpolate == 'perceptualuniform':
return interpolate_Msh(self.left.express_as('MSH').color,
self.right.express_as('MSH').color,fraction)
elif self.interpolate == 'linear':
return interpolate_linear(self.left,
self.right,fraction)
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
colors = [self.color(float(i)/(steps-1)*(frac[1]-frac[0])+frac[0]).express_as(model).color for i in range(steps)]
if format == 'paraview':
colormap = ['[\n {{\n "ColorSpace": "RGB", "Name": "{}", "DefaultMap": true,\n "RGBPoints" : ['.format(name)] \
+ [' {:4d},{:8.6f},{:8.6f},{:8.6f},'.format(i,color[0],color[1],color[2],) \
for i,color in enumerate(colors[:-1])] \
+ [' {:4d},{:8.6f},{:8.6f},{:8.6f} '.format(len(colors),colors[-1][0],colors[-1][1],colors[-1][2],)] \
+ [' ]\n }\n]']
elif format == 'gmsh':
colormap = ['View.ColorTable = {'] \
+ [',\n'.join(['{%s}'%(','.join([str(x*255.0) for x in color])) for color in colors])] \
+ ['}']
elif format == 'gom':
colormap = ['1 1 ' + str(name)
+ ' 9 ' + str(name)
+ ' 0 1 0 3 0 0 -1 9 \\ 0 0 0 255 255 255 0 0 255 '
+ '30 NO_UNIT 1 1 64 64 64 255 1 0 0 0 0 0 0 3 0 ' + str(len(colors))
+ ' '.join([' 0 %s 255 1'%(' '.join([str(int(x*255.0)) for x in color])) for color in reversed(colors)])]
elif format == 'raw':
colormap = ['\t'.join(map(str,color)) for color in colors]
elif format == 'list':
colormap = colors
else:
raise NameError('unknown color export format')
return '\n'.join(colormap) + '\n' if type(colormap[0]) is str else colormap

View File

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

View File

@ -1,11 +1,10 @@
# -*- coding: UTF-8 no BOM -*-
import re
import os
class Section():
def __init__(self,data = {'__order__':[]},part = ''):
"""New material.config section."""
classes = {
'homogenization':Homogenization,
'microstructure':Microstructure,
@ -35,26 +34,31 @@ class Section():
class Homogenization(Section):
def __init__(self,data = {'__order__':[]}):
"""New material.config <homogenization> section."""
Section.__init__(self,data)
class Crystallite(Section):
def __init__(self,data = {'__order__':[]}):
"""New material.config <crystallite> section."""
Section.__init__(self,data)
class Phase(Section):
def __init__(self,data = {'__order__':[]}):
"""New material.config <Phase> section."""
Section.__init__(self,data)
class Microstructure(Section):
def __init__(self,data = {'__order__':[]}):
"""New material.config <microstructure> section."""
Section.__init__(self,data)
class Texture(Section):
def __init__(self,data = {'__order__':[]}):
"""New material.config <texture> section."""
Section.__init__(self,data)
def add_component(self,theType,properties):
@ -79,10 +83,10 @@ class Texture(Section):
class Material():
"""Reads, manipulates and writes material.config files"""
"""Read, manipulate, and write material.config files."""
def __init__(self,verbose=True):
"""Generates ordered list of parts"""
"""Generates ordered list of parts."""
self.parts = [
'homogenization',
'crystallite',
@ -100,7 +104,7 @@ class Material():
self.verbose = verbose
def __repr__(self):
"""Returns current data structure in material.config format"""
"""Returns current data structure in material.config format."""
me = []
for part in self.parts:
if self.verbose: print('processing <{}>'.format(part))
@ -158,9 +162,9 @@ class Material():
def read(self,filename=None):
"""Reads material.config file"""
"""Read material.config file."""
def recursiveRead(filename):
"""Takes care of include statements like '{}'"""
"""Takes care of include statements like '{}'."""
result = []
re_include = re.compile(r'^{(.+)}$')
with open(filename) as f: lines = f.readlines()
@ -176,7 +180,7 @@ class Material():
self.parse(part=p, content=c)
def write(self,filename='material.config', overwrite=False):
"""Writes to material.config"""
"""Write to material.config."""
i = 0
outname = filename
while os.path.exists(outname) and not overwrite:
@ -189,7 +193,7 @@ class Material():
return outname
def add_section(self, part=None, section=None, initialData=None, merge=False):
"""adding/updating"""
"""Add Update."""
part = part.lower()
section = section.lower()
if part not in self.parts: raise Exception('invalid part {}'.format(part))

View File

@ -98,17 +98,12 @@ def cell_coord0(grid,size,origin=np.zeros(3)):
size : numpy.ndarray
physical size of the periodic field.
origin : numpy.ndarray, optional
physical origin of the periodic field. Default is [0.0,0.0,0.0].
physical origin of the periodic field. Defaults to [0.0,0.0,0.0].
"""
start = origin + size/grid*.5
end = origin - size/grid*.5 + size
x, y, z = np.meshgrid(np.linspace(start[2],end[2],grid[2]),
np.linspace(start[1],end[1],grid[1]),
np.linspace(start[0],end[0],grid[0]),
indexing = 'ij')
return np.concatenate((z[:,:,:,None],y[:,:,:,None],x[:,:,:,None]),axis = 3)
end = origin + size - size/grid*.5
return np.mgrid[start[0]:end[0]:grid[0]*1j,start[1]:end[1]:grid[1]*1j,start[2]:end[2]:grid[2]*1j].T
def cell_displacement_fluct(size,F):
@ -180,7 +175,7 @@ def cell_coord(size,F,origin=np.zeros(3)):
F : numpy.ndarray
deformation gradient field.
origin : numpy.ndarray, optional
physical origin of the periodic field. Default is [0.0,0.0,0.0].
physical origin of the periodic field. Defaults to [0.0,0.0,0.0].
"""
return cell_coord0(F.shape[:3][::-1],size,origin) + cell_displacement(size,F)
@ -251,15 +246,12 @@ def node_coord0(grid,size,origin=np.zeros(3)):
size : numpy.ndarray
physical size of the periodic field.
origin : numpy.ndarray, optional
physical origin of the periodic field. Default is [0.0,0.0,0.0].
physical origin of the periodic field. Defaults to [0.0,0.0,0.0].
"""
x, y, z = np.meshgrid(np.linspace(origin[2],size[2]+origin[2],1+grid[2]),
np.linspace(origin[1],size[1]+origin[1],1+grid[1]),
np.linspace(origin[0],size[0]+origin[0],1+grid[0]),
indexing = 'ij')
return np.concatenate((z[:,:,:,None],y[:,:,:,None],x[:,:,:,None]),axis = 3)
return np.mgrid[origin[0]:size[0]+origin[0]:(grid[0]+1)*1j,
origin[1]:size[1]+origin[1]:(grid[1]+1)*1j,
origin[2]:size[2]+origin[2]:(grid[2]+1)*1j].T
def node_displacement_fluct(size,F):
@ -319,7 +311,7 @@ def node_coord(size,F,origin=np.zeros(3)):
F : numpy.ndarray
deformation gradient field.
origin : numpy.ndarray, optional
physical origin of the periodic field. Default is [0.0,0.0,0.0].
physical origin of the periodic field. Defaults to [0.0,0.0,0.0].
"""
return node_coord0(F.shape[:3][::-1],size,origin) + node_displacement(size,F)
@ -399,5 +391,5 @@ def regrid(size,F,new_grid):
c[np.where(c[:,:,:,d]<0)] += outer[d]
c[np.where(c[:,:,:,d]>outer[d])] -= outer[d]
tree = spatial.cKDTree(c.reshape((-1,3)),boxsize=outer)
tree = spatial.cKDTree(c.reshape(-1,3),boxsize=outer)
return tree.query(cell_coord0(new_grid,outer))[1].flatten()

View File

@ -8,10 +8,10 @@ def Cauchy(P,F):
Parameters
----------
F : numpy.array of shape (:,3,3) or (3,3)
F : numpy.ndarray of shape (:,3,3) or (3,3)
Deformation gradient.
P : numpy.array of shape (:,3,3) or (3,3)
1. Piola-Kirchhoff stress.
P : numpy.ndarray of shape (:,3,3) or (3,3)
First Piola-Kirchhoff stress.
"""
if np.shape(F) == np.shape(P) == (3,3):
@ -27,7 +27,7 @@ def deviatoric_part(T):
Parameters
----------
T : numpy.array of shape (:,3,3) or (3,3)
T : numpy.ndarray of shape (:,3,3) or (3,3)
Tensor of which the deviatoric part is computed.
"""
@ -44,7 +44,7 @@ def eigenvalues(T_sym):
Parameters
----------
T_sym : numpy.array of shape (:,3,3) or (3,3)
T_sym : numpy.ndarray of shape (:,3,3) or (3,3)
Symmetric tensor of which the eigenvalues are computed.
"""
@ -59,7 +59,7 @@ def eigenvectors(T_sym,RHS=False):
Parameters
----------
T_sym : numpy.array of shape (:,3,3) or (3,3)
T_sym : numpy.ndarray of shape (:,3,3) or (3,3)
Symmetric tensor of which the eigenvectors are computed.
RHS: bool, optional
Enforce right-handed coordinate system. Default is False.
@ -81,11 +81,11 @@ def left_stretch(T):
Parameters
----------
T : numpy.array of shape (:,3,3) or (3,3)
T : numpy.ndarray of shape (:,3,3) or (3,3)
Tensor of which the left stretch is computed.
"""
return __polar_decomposition(T,'V')[0]
return _polar_decomposition(T,'V')[0]
def maximum_shear(T_sym):
@ -94,7 +94,7 @@ def maximum_shear(T_sym):
Parameters
----------
T_sym : numpy.array of shape (:,3,3) or (3,3)
T_sym : numpy.ndarray of shape (:,3,3) or (3,3)
Symmetric tensor of which the maximum shear is computed.
"""
@ -109,11 +109,11 @@ def Mises_strain(epsilon):
Parameters
----------
epsilon : numpy.array of shape (:,3,3) or (3,3)
epsilon : numpy.ndarray of shape (:,3,3) or (3,3)
Symmetric strain tensor of which the von Mises equivalent is computed.
"""
return __Mises(epsilon,2.0/3.0)
return _Mises(epsilon,2.0/3.0)
def Mises_stress(sigma):
@ -122,11 +122,11 @@ def Mises_stress(sigma):
Parameters
----------
sigma : numpy.array of shape (:,3,3) or (3,3)
sigma : numpy.ndarray of shape (:,3,3) or (3,3)
Symmetric stress tensor of which the von Mises equivalent is computed.
"""
return __Mises(sigma,3.0/2.0)
return _Mises(sigma,3.0/2.0)
def PK2(P,F):
@ -135,9 +135,9 @@ def PK2(P,F):
Parameters
----------
P : numpy.array of shape (:,3,3) or (3,3)
1. Piola-Kirchhoff stress.
F : numpy.array of shape (:,3,3) or (3,3)
P : numpy.ndarray of shape (:,3,3) or (3,3)
First Piola-Kirchhoff stress.
F : numpy.ndarray of shape (:,3,3) or (3,3)
Deformation gradient.
"""
@ -154,11 +154,11 @@ def right_stretch(T):
Parameters
----------
T : numpy.array of shape (:,3,3) or (3,3)
T : numpy.ndarray of shape (:,3,3) or (3,3)
Tensor of which the right stretch is computed.
"""
return __polar_decomposition(T,'U')[0]
return _polar_decomposition(T,'U')[0]
def rotational_part(T):
@ -167,11 +167,11 @@ def rotational_part(T):
Parameters
----------
T : numpy.array of shape (:,3,3) or (3,3)
T : numpy.ndarray of shape (:,3,3) or (3,3)
Tensor of which the rotational part is computed.
"""
return __polar_decomposition(T,'R')[0]
return _polar_decomposition(T,'R')[0]
def spherical_part(T,tensor=False):
@ -180,7 +180,7 @@ def spherical_part(T,tensor=False):
Parameters
----------
T : numpy.array of shape (:,3,3) or (3,3)
T : numpy.ndarray of shape (:,3,3) or (3,3)
Tensor of which the hydrostatic part is computed.
tensor : bool, optional
Map spherical part onto identity tensor. Default is false
@ -206,7 +206,7 @@ def strain_tensor(F,t,m):
Parameters
----------
F : numpy.array of shape (:,3,3) or (3,3)
F : numpy.ndarray of shape (:,3,3) or (3,3)
Deformation gradient.
t : {V, U}
Type of the polar decomposition, V for left stretch tensor and U for right stretch tensor.
@ -214,7 +214,7 @@ def strain_tensor(F,t,m):
Order of the strain.
"""
F_ = F.reshape((1,3,3)) if F.shape == (3,3) else F
F_ = F.reshape(1,3,3) if F.shape == (3,3) else F
if t == 'V':
B = np.matmul(F_,transpose(F_))
w,n = np.linalg.eigh(B)
@ -231,7 +231,7 @@ def strain_tensor(F,t,m):
else:
eps = np.matmul(n,np.einsum('ij,ikj->ijk',0.5*np.log(w),n))
return eps.reshape((3,3)) if np.shape(F) == (3,3) else \
return eps.reshape(3,3) if np.shape(F) == (3,3) else \
eps
@ -241,7 +241,7 @@ def symmetric(T):
Parameters
----------
T : numpy.array of shape (:,3,3) or (3,3)
T : numpy.ndarray of shape (:,3,3) or (3,3)
Tensor of which the symmetrized values are computed.
"""
@ -254,7 +254,7 @@ def transpose(T):
Parameters
----------
T : numpy.array of shape (:,3,3) or (3,3)
T : numpy.ndarray of shape (:,3,3) or (3,3)
Tensor of which the transpose is computed.
"""
@ -262,13 +262,13 @@ def transpose(T):
np.transpose(T,(0,2,1))
def __polar_decomposition(T,requested):
def _polar_decomposition(T,requested):
"""
Singular value decomposition.
Parameters
----------
T : numpy.array of shape (:,3,3) or (3,3)
T : numpy.ndarray of shape (:,3,3) or (3,3)
Tensor of which the singular values are computed.
requested : iterable of str
Requested outputs: R for the rotation tensor,
@ -290,13 +290,13 @@ def __polar_decomposition(T,requested):
return tuple(output)
def __Mises(T_sym,s):
def _Mises(T_sym,s):
"""
Base equation for Mises equivalent of a stres or strain tensor.
Parameters
----------
T_sym : numpy.array of shape (:,3,3) or (3,3)
T_sym : numpy.ndarray of shape (:,3,3) or (3,3)
Symmetric tensor of which the von Mises equivalent is computed.
s : float
Scaling factor (2/3 for strain, 3/2 for stress).

View File

@ -1,4 +1,3 @@
"""Tools to control the various solvers."""
from .solver import Solver # noqa
from .marc import Marc # noqa
from ._marc import Marc # noqa

View File

@ -3,13 +3,12 @@ import subprocess
import shlex
import string
from .solver import Solver
import damask
from .._environment import Environment
class Marc(Solver):
class Marc:
"""Wrapper to run DAMASK with MSCMarc."""
def __init__(self,version=damask.Environment().options['MARC_VERSION']):
def __init__(self,version=Environment().options['MARC_VERSION']):
"""
Create a Marc solver object.
@ -29,7 +28,7 @@ class Marc(Solver):
#--------------------------
def libraryPath(self):
path_MSC = damask.Environment().options['MSC_ROOT']
path_MSC = Environment().options['MSC_ROOT']
path_lib = '{}/mentat{}/shlib/linux64'.format(path_MSC,self.version)
return path_lib if os.path.exists(path_lib) else ''
@ -38,7 +37,7 @@ class Marc(Solver):
#--------------------------
def toolsPath(self):
path_MSC = damask.Environment().options['MSC_ROOT']
path_MSC = Environment().options['MSC_ROOT']
path_tools = '{}/marc{}/tools'.format(path_MSC,self.version)
return path_tools if os.path.exists(path_tools) else ''
@ -54,7 +53,7 @@ class Marc(Solver):
):
damaskEnv = damask.Environment()
damaskEnv = Environment()
user = os.path.join(damaskEnv.relPath('src'),'DAMASK_marc{}.{}'.format(self.version,'f90' if compile else 'marc'))
if not os.path.isfile(user):

View File

@ -1,6 +0,0 @@
class Solver():
"""
General class for solver specific functionality.
Sub-classed by the individual solvers.
"""

View File

@ -66,12 +66,12 @@ def croak(what, newline = True):
Parameters
----------
what : str or iterable
Content to be displayed
Content to be displayed.
newline : bool, optional
Separate items of what by newline. Defaults to True.
"""
if not what:
if what is not None:
sys.stderr.write(srepr(what,glue = '\n') + ('\n' if newline else ''))
sys.stderr.flush()
@ -122,8 +122,8 @@ def execute(cmd,
Input (via pipe) for executed process.
wd : str, optional
Working directory of process. Defaults to ./ .
env :
Environment
env : dict, optional
Environment for execution.
"""
initialPath = os.getcwd()
@ -258,7 +258,7 @@ def scale_to_coprime(v):
return m//reduce(np.gcd,m)
class return_message():
class return_message:
"""Object with formatted return message."""
def __init__(self,message):

View File

@ -18,7 +18,7 @@ def default():
x=np.concatenate((np.ones(40,dtype=int),
np.arange(2,42),
np.ones(40,dtype=int)*2,
np.arange(1,41))).reshape((8,5,4))
np.arange(1,41))).reshape(8,5,4)
return Geom(x,[8e-6,5e-6,4e-6])
@pytest.fixture

View File

@ -27,7 +27,7 @@ class TestResult:
def test_time_increments(self,default):
shape = default.read_dataset(default.get_dataset_location('F'),0).shape
default.set_by_time(0.0,20.0)
for i in default.iter_visible('increments'):
for i in default.iterate('increments'):
assert shape == default.read_dataset(default.get_dataset_location('F'),0).shape
@ -61,7 +61,7 @@ class TestResult:
default.add_determinant('P')
loc = {'P': default.get_dataset_location('P'),
'det(P)':default.get_dataset_location('det(P)')}
in_memory = np.linalg.det(default.read_dataset(loc['P'],0)).reshape((-1,1))
in_memory = np.linalg.det(default.read_dataset(loc['P'],0)).reshape(-1,1)
in_file = default.read_dataset(loc['det(P)'],0)
assert np.allclose(in_memory,in_file)

View File

@ -49,7 +49,7 @@ class TestTable:
def test_write_read_new_style(self,default,tmpdir):
with open(tmpdir.join('new_style.txt'),'w') as f:
default.to_ASCII(f,new=True)
default.to_ASCII(f,new_style=True)
with open(tmpdir.join('new_style.txt')) as f:
new = Table.from_ASCII(f)
assert all(default.data==new.data) and default.shapes == new.shapes
@ -173,4 +173,4 @@ class TestTable:
['test data'])
t.add('s',np.array(['b','a']))
t.sort_by('s')
assert np.all(t.get('1_v') == np.array([2,0]).reshape((2,1)))
assert np.all(t.get('1_v') == np.array([2,0]).reshape(2,1))

View File

@ -31,7 +31,7 @@ class TestGridFilters:
size = np.random.random(3)
origin = np.random.random(3)
coord0 = eval('grid_filters.{}_coord0(grid,size,origin)'.format(mode)) # noqa
_grid,_size,_origin = eval('grid_filters.{}_coord0_gridSizeOrigin(coord0.reshape((-1,3)))'.format(mode))
_grid,_size,_origin = eval('grid_filters.{}_coord0_gridSizeOrigin(coord0.reshape(-1,3))'.format(mode))
assert np.allclose(grid,_grid) and np.allclose(size,_size) and np.allclose(origin,_origin)
def test_displacement_fluct_equivalence(self):

3
src/.gitignore vendored
View File

@ -1,4 +1 @@
Makefile
cmake_install.cmake
quit__genmod.f90
*.marc

View File

@ -9,13 +9,11 @@ file(GLOB damask-sources *.f90 *.c)
# probably we should have a subfolder for MSC.Marc
list(FILTER damask-sources EXCLUDE REGEX ".*CPFEM.f90")
list(FILTER damask-sources EXCLUDE REGEX ".*DAMASK_marc.*.f90")
list(FILTER damask-sources EXCLUDE REGEX ".*mesh_marc.*.f90")
list(FILTER damask-sources EXCLUDE REGEX ".*commercialFEM_fileList.*.f90")
if (PROJECT_NAME STREQUAL "damask-grid")
list(FILTER damask-sources EXCLUDE REGEX ".*mesh_FEM.*.f90")
file(GLOB grid-sources grid/*.f90)
if(NOT CMAKE_BUILD_TYPE STREQUAL "SYNTAXONLY")
@ -30,7 +28,6 @@ if (PROJECT_NAME STREQUAL "damask-grid")
elseif (PROJECT_NAME STREQUAL "damask-mesh")
list(FILTER damask-sources EXCLUDE REGEX ".*mesh_grid.*.f90")
file(GLOB mesh-sources mesh/*.f90)
add_executable(DAMASK_FEM ${damask-sources} ${mesh-sources})

View File

@ -10,7 +10,7 @@ module CPFEM
use FEsolving
use math
use rotations
use mesh
use discretization_marc
use material
use config
use crystallite
@ -85,7 +85,7 @@ subroutine CPFEM_initAll(el,ip)
call rotations_init
call HDF5_utilities_init
call results_init
call mesh_init(ip, el)
call discretization_marc_init(ip, el)
call lattice_init
call material_init
call constitutive_init
@ -139,8 +139,8 @@ subroutine CPFEM_general(mode, parallelExecution, ffn, ffn1, temperature_inp, dt
real(pReal) J_inverse, & ! inverse of Jacobian
rnd
real(pReal), dimension (3,3) :: Kirchhoff, & ! Piola-Kirchhoff stress in Matrix notation
cauchyStress33 ! stress vector in Matrix notation
real(pReal), dimension (3,3) :: Kirchhoff, & ! Piola-Kirchhoff stress
cauchyStress33 ! stress vector
real(pReal), dimension (3,3,3,3) :: H_sym, &
H, &
jacobian3333 ! jacobian in Matrix notation
@ -180,7 +180,6 @@ subroutine CPFEM_general(mode, parallelExecution, ffn, ffn1, temperature_inp, dt
!*** collection of FEM input with returning of randomize odd stress and jacobian
!* If no parallel execution is required, there is no need to collect FEM input
if (.not. parallelExecution) then
chosenThermal1: select case (thermal_type(material_homogenizationAt(elCP)))
case (THERMAL_conduction_ID) chosenThermal1
@ -203,12 +202,10 @@ subroutine CPFEM_general(mode, parallelExecution, ffn, ffn1, temperature_inp, dt
materialpoint_F0(1:3,1:3,ip,elCP) = ffn
materialpoint_F(1:3,1:3,ip,elCP) = ffn1
CPFEM_calc_done = .false.
endif ! collection
endif
!*** calculation of stress and jacobian
if (iand(mode, CPFEM_CALCRESULTS) /= 0_pInt) then
!*** deformation gradient outdated or any actual deformation gradient differs more than relevantStrain from the stored one
@ -230,25 +227,22 @@ subroutine CPFEM_general(mode, parallelExecution, ffn, ffn1, temperature_inp, dt
CPFEM_dcsde(1:6,1:6,ip,elCP) = ODD_JACOBIAN * math_identity2nd(6)
!*** deformation gradient is not outdated
else validCalculation
updateJaco = mod(cycleCounter,iJacoStiffness) == 0
!* no parallel computation, so we use just one single elFE and ip for computation
if (.not. parallelExecution) then
FEsolving_execElem = elCP
FEsolving_execIP = ip
if (iand(debug_level(debug_CPFEM), debug_levelExtensive) /= 0_pInt) &
write(6,'(a,i8,1x,i2)') '<< CPFEM >> calculation for elFE ip ',elFE,ip
call materialpoint_stressAndItsTangent(updateJaco, dt) ! calculate stress and its tangent
call materialpoint_stressAndItsTangent(updateJaco, dt)
!* parallel computation and calulation not yet done
elseif (.not. CPFEM_calc_done) then
if (iand(debug_level(debug_CPFEM), debug_levelExtensive) /= 0_pInt) &
write(6,'(a,i8,a,i8)') '<< CPFEM >> calculation for elements ',FEsolving_execElem(1),&
' to ',FEsolving_execElem(2)
call materialpoint_stressAndItsTangent(updateJaco, dt) ! calculate stress and its tangent (parallel execution inside)
call materialpoint_stressAndItsTangent(updateJaco, dt)
CPFEM_calc_done = .true.
endif
@ -262,7 +256,6 @@ subroutine CPFEM_general(mode, parallelExecution, ffn, ffn1, temperature_inp, dt
else terminalIllness
! translate from P to CS
Kirchhoff = matmul(materialpoint_P(1:3,1:3,ip,elCP), transpose(materialpoint_F(1:3,1:3,ip,elCP)))
J_inverse = 1.0_pReal / math_det33(materialpoint_F(1:3,1:3,ip,elCP))

View File

@ -21,11 +21,11 @@ module CPFEM2
use homogenization
use constitutive
use crystallite
#ifdef FEM
use FEM_Zoo
use mesh
#else
use mesh_grid
#if defined(FEM)
use FEM_quadrature
use discretization_mesh
#elif defined(Grid)
use discretization_grid
#endif
implicit none
@ -43,7 +43,7 @@ subroutine CPFEM_initAll
call prec_init
call IO_init
#ifdef FEM
call FEM_Zoo_init
call FEM_quadrature_init
#endif
call numerics_init
call debug_init
@ -53,7 +53,11 @@ subroutine CPFEM_initAll
call lattice_init
call HDF5_utilities_init
call results_init
call mesh_init
#if defined(FEM)
call discretization_mesh_init
#elif defined(Grid)
call discretization_grid_init
#endif
call material_init
call constitutive_init
call crystallite_init

View File

@ -178,7 +178,7 @@ subroutine hypela2(d,g,e,de,s,t,dt,ngens,m,nn,kcus,matus,ndi,nshear,disp, &
use numerics
use FEsolving
use debug
use mesh
use discretization_marc
use CPFEM
implicit none
@ -233,8 +233,8 @@ subroutine hypela2(d,g,e,de,s,t,dt,ngens,m,nn,kcus,matus,ndi,nshear,disp, &
! Marc common blocks are in fixed format so they have to be reformated to free format (f90)
! Beware of changes in newer Marc versions
#include QUOTE(PASTE(./MarcInclude/concom,Marc4DAMASK)) ! concom is needed for inc, lovl
#include QUOTE(PASTE(./MarcInclude/creeps,Marc4DAMASK)) ! creeps is needed for timinc (time increment)
#include QUOTE(PASTE(./marc/include/concom,Marc4DAMASK)) ! concom is needed for inc, lovl
#include QUOTE(PASTE(./marc/include/creeps,Marc4DAMASK)) ! creeps is needed for timinc (time increment)
logical :: cutBack
real(pReal), dimension(6) :: stress
@ -378,7 +378,7 @@ end subroutine hypela2
subroutine flux(f,ts,n,time)
use prec
use thermal_conduction
use mesh
use discretization_marc
implicit none
real(pReal), dimension(6), intent(in) :: &
@ -408,7 +408,7 @@ subroutine uedinc(inc,incsub)
implicit none
integer, intent(in) :: inc, incsub
integer, save :: inc_written
#include QUOTE(PASTE(./MarcInclude/creeps,Marc4DAMASK)) ! creeps is needed for timinc (time increment)
#include QUOTE(PASTE(./marc/include/creeps,Marc4DAMASK)) ! creeps is needed for timinc (time increment)
if (inc > inc_written) then
call CPFEM_results(inc,cptim)

View File

@ -525,10 +525,10 @@ end subroutine HDF5_setLink
!--------------------------------------------------------------------------------------------------
subroutine HDF5_read_real1(loc_id,dataset,datasetName,parallel)
real(pReal), intent(inout), dimension(:) :: dataset
real(pReal), intent(out), dimension(:) :: dataset !< data read from file
integer(HID_T), intent(in) :: loc_id !< file or group handle
character(len=*), intent(in) :: datasetName !< name of the dataset in the file
logical, intent(in), optional :: parallel
logical, intent(in), optional :: parallel !< dataset is distributed over multiple processes
integer(HID_T) :: dset_id, filespace_id, memspace_id, plist_id, aplist_id
integer(HSIZE_T), dimension(size(shape(dataset))) :: & ! ToDo: Fortran 2018 size(shape(A)) = rank(A)
@ -565,10 +565,10 @@ end subroutine HDF5_read_real1
!--------------------------------------------------------------------------------------------------
subroutine HDF5_read_real2(loc_id,dataset,datasetName,parallel)
real(pReal), intent(inout), dimension(:,:) :: dataset
real(pReal), intent(out), dimension(:,:) :: dataset !< data read from file
integer(HID_T), intent(in) :: loc_id !< file or group handle
character(len=*), intent(in) :: datasetName !< name of the dataset in the file
logical, intent(in), optional :: parallel
logical, intent(in), optional :: parallel !< dataset is distributed over multiple processes
integer(HID_T) :: dset_id, filespace_id, memspace_id, plist_id, aplist_id
integer(HSIZE_T), dimension(size(shape(dataset))) :: &
@ -605,10 +605,10 @@ end subroutine HDF5_read_real2
!--------------------------------------------------------------------------------------------------
subroutine HDF5_read_real3(loc_id,dataset,datasetName,parallel)
real(pReal), intent(inout), dimension(:,:,:) :: dataset
real(pReal), intent(out), dimension(:,:,:) :: dataset !< data read from file
integer(HID_T), intent(in) :: loc_id !< file or group handle
character(len=*), intent(in) :: datasetName !< name of the dataset in the file
logical, intent(in), optional :: parallel
logical, intent(in), optional :: parallel !< dataset is distributed over multiple processes
integer(HID_T) :: dset_id, filespace_id, memspace_id, plist_id, aplist_id
integer(HSIZE_T), dimension(size(shape(dataset))) :: &
@ -645,10 +645,10 @@ end subroutine HDF5_read_real3
!--------------------------------------------------------------------------------------------------
subroutine HDF5_read_real4(loc_id,dataset,datasetName,parallel)
real(pReal), intent(inout), dimension(:,:,:,:) :: dataset
real(pReal), intent(out), dimension(:,:,:,:) :: dataset !< read data
integer(HID_T), intent(in) :: loc_id !< file or group handle
character(len=*), intent(in) :: datasetName !< name of the dataset in the file
logical, intent(in), optional :: parallel
logical, intent(in), optional :: parallel !< dataset is distributed over multiple processes
integer(HID_T) :: dset_id, filespace_id, memspace_id, plist_id, aplist_id
integer(HSIZE_T), dimension(size(shape(dataset))) :: &
@ -685,10 +685,10 @@ end subroutine HDF5_read_real4
!--------------------------------------------------------------------------------------------------
subroutine HDF5_read_real5(loc_id,dataset,datasetName,parallel)
real(pReal), intent(inout), dimension(:,:,:,:,:) :: dataset
real(pReal), intent(out), dimension(:,:,:,:,:) :: dataset !< data read from file
integer(HID_T), intent(in) :: loc_id !< file or group handle
character(len=*), intent(in) :: datasetName !< name of the dataset in the file
logical, intent(in), optional :: parallel
logical, intent(in), optional :: parallel !< dataset is distributed over multiple processes
integer(HID_T) :: dset_id, filespace_id, memspace_id, plist_id, aplist_id
integer(HSIZE_T), dimension(size(shape(dataset))) :: &
@ -725,10 +725,10 @@ end subroutine HDF5_read_real5
!--------------------------------------------------------------------------------------------------
subroutine HDF5_read_real6(loc_id,dataset,datasetName,parallel)
real(pReal), intent(inout), dimension(:,:,:,:,:,:) :: dataset
real(pReal), intent(out), dimension(:,:,:,:,:,:) :: dataset !< data read from file
integer(HID_T), intent(in) :: loc_id !< file or group handle
character(len=*), intent(in) :: datasetName !< name of the dataset in the file
logical, intent(in), optional :: parallel
logical, intent(in), optional :: parallel !< dataset is distributed over multiple processes
integer(HID_T) :: dset_id, filespace_id, memspace_id, plist_id, aplist_id
integer(HSIZE_T), dimension(size(shape(dataset))) :: &
@ -765,10 +765,10 @@ end subroutine HDF5_read_real6
!--------------------------------------------------------------------------------------------------
subroutine HDF5_read_real7(loc_id,dataset,datasetName,parallel)
real(pReal), intent(inout), dimension(:,:,:,:,:,:,:) :: dataset
real(pReal), intent(out), dimension(:,:,:,:,:,:,:) :: dataset !< data read from file
integer(HID_T), intent(in) :: loc_id !< file or group handle
character(len=*), intent(in) :: datasetName !< name of the dataset in the file
logical, intent(in), optional :: parallel
logical, intent(in), optional :: parallel !< dataset is distributed over multiple processes
integer(HID_T) :: dset_id, filespace_id, memspace_id, plist_id, aplist_id
integer(HSIZE_T), dimension(size(shape(dataset))) :: &
@ -806,10 +806,11 @@ end subroutine HDF5_read_real7
!--------------------------------------------------------------------------------------------------
subroutine HDF5_read_int1(loc_id,dataset,datasetName,parallel)
integer, intent(inout), dimension(:) :: dataset
integer, intent(out), dimension(:) :: dataset !< data read from file
integer(HID_T), intent(in) :: loc_id !< file or group handle
character(len=*), intent(in) :: datasetName !< name of the dataset in the file
logical, intent(in), optional :: parallel
logical, intent(in), optional :: parallel !< dataset is distributed over multiple processes
integer(HID_T) :: dset_id, filespace_id, memspace_id, plist_id, aplist_id
integer(HSIZE_T), dimension(size(shape(dataset))) :: &
@ -846,10 +847,10 @@ end subroutine HDF5_read_int1
!--------------------------------------------------------------------------------------------------
subroutine HDF5_read_int2(loc_id,dataset,datasetName,parallel)
integer, intent(inout), dimension(:,:) :: dataset
integer, intent(out), dimension(:,:) :: dataset !< data read from file
integer(HID_T), intent(in) :: loc_id !< file or group handle
character(len=*), intent(in) :: datasetName !< name of the dataset in the file
logical, intent(in), optional :: parallel
logical, intent(in), optional :: parallel !< dataset is distributed over multiple processes
integer(HID_T) :: dset_id, filespace_id, memspace_id, plist_id, aplist_id
integer(HSIZE_T), dimension(size(shape(dataset))) :: &
@ -886,10 +887,10 @@ end subroutine HDF5_read_int2
!--------------------------------------------------------------------------------------------------
subroutine HDF5_read_int3(loc_id,dataset,datasetName,parallel)
integer, intent(inout), dimension(:,:,:) :: dataset
integer, intent(out), dimension(:,:,:) :: dataset !< data read from file
integer(HID_T), intent(in) :: loc_id !< file or group handle
character(len=*), intent(in) :: datasetName !< name of the dataset in the file
logical, intent(in), optional :: parallel
logical, intent(in), optional :: parallel !< dataset is distributed over multiple processes
integer(HID_T) :: dset_id, filespace_id, memspace_id, plist_id, aplist_id
integer(HSIZE_T), dimension(size(shape(dataset))) :: &
@ -926,10 +927,10 @@ end subroutine HDF5_read_int3
!--------------------------------------------------------------------------------------------------
subroutine HDF5_read_int4(loc_id,dataset,datasetName,parallel)
integer, intent(inout), dimension(:,:,:,:) :: dataset
integer, intent(out), dimension(:,:,:,:) :: dataset !< data read from file
integer(HID_T), intent(in) :: loc_id !< file or group handle
character(len=*), intent(in) :: datasetName !< name of the dataset in the file
logical, intent(in), optional :: parallel
logical, intent(in), optional :: parallel !< dataset is distributed over multiple processes
integer(HID_T) :: dset_id, filespace_id, memspace_id, plist_id, aplist_id
integer(HSIZE_T), dimension(size(shape(dataset))) :: &
@ -966,10 +967,10 @@ end subroutine HDF5_read_int4
!--------------------------------------------------------------------------------------------------
subroutine HDF5_read_int5(loc_id,dataset,datasetName,parallel)
integer, intent(inout), dimension(:,:,:,:,:) :: dataset
integer, intent(out), dimension(:,:,:,:,:) :: dataset !< data read from file
integer(HID_T), intent(in) :: loc_id !< file or group handle
character(len=*), intent(in) :: datasetName !< name of the dataset in the file
logical, intent(in), optional :: parallel
logical, intent(in), optional :: parallel !< dataset is distributed over multiple processes
integer(HID_T) :: dset_id, filespace_id, memspace_id, plist_id, aplist_id
integer(HSIZE_T), dimension(size(shape(dataset))) :: &
@ -1006,10 +1007,10 @@ end subroutine HDF5_read_int5
!--------------------------------------------------------------------------------------------------
subroutine HDF5_read_int6(loc_id,dataset,datasetName,parallel)
integer, intent(inout), dimension(:,:,:,:,:,:) :: dataset
integer, intent(out), dimension(:,:,:,:,:,:) :: dataset !< data read from file
integer(HID_T), intent(in) :: loc_id !< file or group handle
character(len=*), intent(in) :: datasetName !< name of the dataset in the file
logical, intent(in), optional :: parallel
logical, intent(in), optional :: parallel !< dataset is distributed over multiple processes
integer(HID_T) :: dset_id, filespace_id, memspace_id, plist_id, aplist_id
integer(HSIZE_T), dimension(size(shape(dataset))) :: &
@ -1046,10 +1047,10 @@ end subroutine HDF5_read_int6
!--------------------------------------------------------------------------------------------------
subroutine HDF5_read_int7(loc_id,dataset,datasetName,parallel)
integer, intent(inout), dimension(:,:,:,:,:,:,:) :: dataset
integer, intent(out), dimension(:,:,:,:,:,:,:) :: dataset !< data read from file
integer(HID_T), intent(in) :: loc_id !< file or group handle
character(len=*), intent(in) :: datasetName !< name of the dataset in the file
logical, intent(in), optional :: parallel
logical, intent(in), optional :: parallel !< dataset is distributed over multiple processes
integer(HID_T) :: dset_id, filespace_id, memspace_id, plist_id, aplist_id
integer(HSIZE_T), dimension(size(shape(dataset))) :: &
@ -1087,10 +1088,10 @@ end subroutine HDF5_read_int7
!--------------------------------------------------------------------------------------------------
subroutine HDF5_write_real1(loc_id,dataset,datasetName,parallel)
real(pReal), intent(inout), dimension(:) :: dataset
real(pReal), intent(inout), dimension(:) :: dataset !< data written to file
integer(HID_T), intent(in) :: loc_id !< file or group handle
character(len=*), intent(in) :: datasetName !< name of the dataset in the file
logical, intent(in), optional :: parallel
logical, intent(in), optional :: parallel !< dataset is distributed over multiple processes
integer :: hdferr
@ -1128,10 +1129,10 @@ end subroutine HDF5_write_real1
!--------------------------------------------------------------------------------------------------
subroutine HDF5_write_real2(loc_id,dataset,datasetName,parallel)
real(pReal), intent(inout), dimension(:,:) :: dataset
real(pReal), intent(inout), dimension(:,:) :: dataset !< data written to file
integer(HID_T), intent(in) :: loc_id !< file or group handle
character(len=*), intent(in) :: datasetName !< name of the dataset in the file
logical, intent(in), optional :: parallel
logical, intent(in), optional :: parallel !< dataset is distributed over multiple processes
integer :: hdferr
@ -1169,10 +1170,10 @@ end subroutine HDF5_write_real2
!--------------------------------------------------------------------------------------------------
subroutine HDF5_write_real3(loc_id,dataset,datasetName,parallel)
real(pReal), intent(inout), dimension(:,:,:) :: dataset
real(pReal), intent(inout), dimension(:,:,:) :: dataset !< data written to file
integer(HID_T), intent(in) :: loc_id !< file or group handle
character(len=*), intent(in) :: datasetName !< name of the dataset in the file
logical, intent(in), optional :: parallel
logical, intent(in), optional :: parallel !< dataset is distributed over multiple processes
integer :: hdferr
@ -1210,10 +1211,10 @@ end subroutine HDF5_write_real3
!--------------------------------------------------------------------------------------------------
subroutine HDF5_write_real4(loc_id,dataset,datasetName,parallel)
real(pReal), intent(inout), dimension(:,:,:,:) :: dataset
real(pReal), intent(inout), dimension(:,:,:,:) :: dataset !< data written to file
integer(HID_T), intent(in) :: loc_id !< file or group handle
character(len=*), intent(in) :: datasetName !< name of the dataset in the file
logical, intent(in), optional :: parallel
logical, intent(in), optional :: parallel !< dataset is distributed over multiple processes
integer :: hdferr
@ -1252,10 +1253,10 @@ end subroutine HDF5_write_real4
!--------------------------------------------------------------------------------------------------
subroutine HDF5_write_real5(loc_id,dataset,datasetName,parallel)
real(pReal), intent(inout), dimension(:,:,:,:,:) :: dataset
real(pReal), intent(inout), dimension(:,:,:,:,:) :: dataset !< data written to file
integer(HID_T), intent(in) :: loc_id !< file or group handle
character(len=*), intent(in) :: datasetName !< name of the dataset in the file
logical, intent(in), optional :: parallel
logical, intent(in), optional :: parallel !< dataset is distributed over multiple processes
integer :: hdferr
@ -1293,10 +1294,10 @@ end subroutine HDF5_write_real5
!--------------------------------------------------------------------------------------------------
subroutine HDF5_write_real6(loc_id,dataset,datasetName,parallel)
real(pReal), intent(inout), dimension(:,:,:,:,:,:) :: dataset
real(pReal), intent(inout), dimension(:,:,:,:,:,:) :: dataset !< data written to file
integer(HID_T), intent(in) :: loc_id !< file or group handle
character(len=*), intent(in) :: datasetName !< name of the dataset in the file
logical, intent(in), optional :: parallel
logical, intent(in), optional :: parallel !< dataset is distributed over multiple processes
integer :: hdferr
@ -1334,10 +1335,10 @@ end subroutine HDF5_write_real6
!--------------------------------------------------------------------------------------------------
subroutine HDF5_write_real7(loc_id,dataset,datasetName,parallel)
real(pReal), intent(inout), dimension(:,:,:,:,:,:,:) :: dataset
real(pReal), intent(inout), dimension(:,:,:,:,:,:,:) :: dataset !< data written to file
integer(HID_T), intent(in) :: loc_id !< file or group handle
character(len=*), intent(in) :: datasetName !< name of the dataset in the file
logical, intent(in), optional :: parallel
logical, intent(in), optional :: parallel !< dataset is distributed over multiple processes
integer :: hdferr
@ -1376,10 +1377,10 @@ end subroutine HDF5_write_real7
!--------------------------------------------------------------------------------------------------
subroutine HDF5_write_int1(loc_id,dataset,datasetName,parallel)
integer, intent(inout), dimension(:) :: dataset
integer, intent(inout), dimension(:) :: dataset !< data written to file
integer(HID_T), intent(in) :: loc_id !< file or group handle
character(len=*), intent(in) :: datasetName !< name of the dataset in the file
logical, intent(in), optional :: parallel
logical, intent(in), optional :: parallel !< dataset is distributed over multiple processes
integer :: hdferr
@ -1417,10 +1418,10 @@ end subroutine HDF5_write_int1
!--------------------------------------------------------------------------------------------------
subroutine HDF5_write_int2(loc_id,dataset,datasetName,parallel)
integer, intent(inout), dimension(:,:) :: dataset
integer, intent(inout), dimension(:,:) :: dataset !< data written to file
integer(HID_T), intent(in) :: loc_id !< file or group handle
character(len=*), intent(in) :: datasetName !< name of the dataset in the file
logical, intent(in), optional :: parallel
logical, intent(in), optional :: parallel !< dataset is distributed over multiple processes
integer :: hdferr
@ -1458,10 +1459,10 @@ end subroutine HDF5_write_int2
!--------------------------------------------------------------------------------------------------
subroutine HDF5_write_int3(loc_id,dataset,datasetName,parallel)
integer, intent(inout), dimension(:,:,:) :: dataset
integer, intent(inout), dimension(:,:,:) :: dataset !< data written to file
integer(HID_T), intent(in) :: loc_id !< file or group handle
character(len=*), intent(in) :: datasetName !< name of the dataset in the file
logical, intent(in), optional :: parallel
logical, intent(in), optional :: parallel !< dataset is distributed over multiple processes
integer :: hdferr
@ -1499,10 +1500,10 @@ end subroutine HDF5_write_int3
!--------------------------------------------------------------------------------------------------
subroutine HDF5_write_int4(loc_id,dataset,datasetName,parallel)
integer, intent(inout), dimension(:,:,:,:) :: dataset
integer, intent(inout), dimension(:,:,:,:) :: dataset !< data written to file
integer(HID_T), intent(in) :: loc_id !< file or group handle
character(len=*), intent(in) :: datasetName !< name of the dataset in the file
logical, intent(in), optional :: parallel
logical, intent(in), optional :: parallel !< dataset is distributed over multiple processes
integer :: hdferr
@ -1540,10 +1541,10 @@ end subroutine HDF5_write_int4
!--------------------------------------------------------------------------------------------------
subroutine HDF5_write_int5(loc_id,dataset,datasetName,parallel)
integer, intent(inout), dimension(:,:,:,:,:) :: dataset
integer, intent(inout), dimension(:,:,:,:,:) :: dataset !< data written to file
integer(HID_T), intent(in) :: loc_id !< file or group handle
character(len=*), intent(in) :: datasetName !< name of the dataset in the file
logical, intent(in), optional :: parallel
logical, intent(in), optional :: parallel !< dataset is distributed over multiple processes
integer :: hdferr
@ -1581,10 +1582,10 @@ end subroutine HDF5_write_int5
!--------------------------------------------------------------------------------------------------
subroutine HDF5_write_int6(loc_id,dataset,datasetName,parallel)
integer, intent(inout), dimension(:,:,:,:,:,:) :: dataset
integer, intent(inout), dimension(:,:,:,:,:,:) :: dataset !< data written to file
integer(HID_T), intent(in) :: loc_id !< file or group handle
character(len=*), intent(in) :: datasetName !< name of the dataset in the file
logical, intent(in), optional :: parallel
logical, intent(in), optional :: parallel !< dataset is distributed over multiple processes
integer :: hdferr
@ -1622,10 +1623,10 @@ end subroutine HDF5_write_int6
!--------------------------------------------------------------------------------------------------
subroutine HDF5_write_int7(loc_id,dataset,datasetName,parallel)
integer, intent(inout), dimension(:,:,:,:,:,:,:) :: dataset
integer, intent(inout), dimension(:,:,:,:,:,:,:) :: dataset !< data written to file
integer(HID_T), intent(in) :: loc_id !< file or group handle
character(len=*), intent(in) :: datasetName !< name of the dataset in the file
logical, intent(in), optional :: parallel
logical, intent(in), optional :: parallel !< dataset is distributed over multiple processes
integer :: hdferr
@ -1666,7 +1667,7 @@ end subroutine HDF5_write_int7
!--------------------------------------------------------------------------------------------------
subroutine HDF5_write_rotation(loc_id,dataset,datasetName,parallel)
type(rotation), intent(in), dimension(:) :: dataset
type(rotation), intent(in), dimension(:) :: dataset !< data written to file
integer(HID_T), intent(in) :: loc_id !< file or group handle
character(len=*), intent(in) :: datasetName !< name of the dataset in the file
logical, intent(in), optional :: parallel

View File

@ -7,14 +7,15 @@
!--------------------------------------------------------------------------------------------------
module IO
use prec
use DAMASK_interface
implicit none
private
character(len=*), parameter, public :: &
IO_EOF = '#EOF#' !< end of file string
IO_EOF = '#EOF#', & !< end of file string
IO_WHITESPACE = achar(44)//achar(32)//achar(9)//achar(10)//achar(13) !< whitespace characters
character, parameter, public :: &
IO_EOL = new_line(' ') !< end of line str
IO_EOL = new_line('DAMASK'), & !< end of line character
IO_COMMENT = '#'
character(len=*), parameter, private :: &
IO_DIVIDER = '───────────────────'//&
'───────────────────'//&
@ -23,7 +24,7 @@ module IO
public :: &
IO_init, &
IO_read_ASCII, &
IO_open_jobFile_binary, &
IO_open_binary, &
IO_isBlank, &
IO_getTag, &
IO_stringPos, &
@ -43,6 +44,7 @@ contains
subroutine IO_init
write(6,'(/,a)') ' <<<+- IO init -+>>>'; flush(6)
call unitTest
end subroutine IO_init
@ -114,24 +116,6 @@ function IO_read_ASCII(fileName) result(fileContent)
end function IO_read_ASCII
!--------------------------------------------------------------------------------------------------
!> @brief opens an existing file for reading or a new file for writing. Name is the job name
!> @details replaces an existing file when writing
!--------------------------------------------------------------------------------------------------
integer function IO_open_jobFile_binary(extension,mode)
character(len=*), intent(in) :: extension
character, intent(in), optional :: mode
if (present(mode)) then
IO_open_jobFile_binary = IO_open_binary(trim(getSolverJobName())//'.'//trim(extension),mode)
else
IO_open_jobFile_binary = IO_open_binary(trim(getSolverJobName())//'.'//trim(extension))
endif
end function IO_open_jobFile_binary
!--------------------------------------------------------------------------------------------------
!> @brief opens an existing file for reading or a new file for writing.
!> @details replaces an existing file when writing
@ -172,14 +156,10 @@ logical pure function IO_isBlank(string)
character(len=*), intent(in) :: string !< string to check for content
character(len=*), parameter :: blankChar = achar(32)//achar(9)//achar(10)//achar(13) ! whitespaces
character(len=*), parameter :: comment = achar(35) ! comment id '#'
integer :: posNonBlank
integer :: posNonBlank, posComment
posNonBlank = verify(string,blankChar)
posComment = scan(string,comment)
IO_isBlank = posNonBlank == 0 .or. posNonBlank == posComment
posNonBlank = verify(string,IO_WHITESPACE)
IO_isBlank = posNonBlank == 0 .or. posNonBlank == scan(string,IO_COMMENT)
end function IO_isBlank
@ -194,18 +174,14 @@ pure function IO_getTag(string,openChar,closeChar)
closeChar !< indicates end of tag
character(len=:), allocatable :: IO_getTag
character(len=*), parameter :: SEP=achar(32)//achar(9)//achar(10)//achar(13) ! whitespaces
integer :: left,right
if (openChar /= closeChar) then
left = scan(string,openChar)
right = scan(string,closeChar)
else
left = scan(string,openChar)
right = left + merge(scan(string(left+1:),openChar),0,len(string) > left)
endif
right = merge(scan(string,closeChar), &
left + merge(scan(string(left+1:),openChar),0,len(string) > left), &
openChar /= closeChar)
foundTag: if (left == verify(string,SEP) .and. right > left) then
foundTag: if (left == verify(string,IO_WHITESPACE) .and. right > left) then
IO_getTag = string(left+1:right-1)
else foundTag
IO_getTag = ''
@ -215,8 +191,8 @@ end function IO_getTag
!--------------------------------------------------------------------------------------------------
!> @brief locates all space-separated chunks in given string and returns array containing number
!! them and the left/right position to be used by IO_xxxVal
!> @brief locates all whitespace-separated chunks in given string and returns array containing
!! number them and the left/right position to be used by IO_xxxVal
!! Array size is dynamically adjusted to number of chunks found in string
!! IMPORTANT: first element contains number of chunks!
!--------------------------------------------------------------------------------------------------
@ -225,16 +201,15 @@ pure function IO_stringPos(string)
character(len=*), intent(in) :: string !< string in which chunk positions are searched for
integer, dimension(:), allocatable :: IO_stringPos
character(len=*), parameter :: SEP=achar(44)//achar(32)//achar(9)//achar(10)//achar(13) ! comma and whitespaces
integer :: left, right
allocate(IO_stringPos(1), source=0)
right = 0
do while (verify(string(right+1:),SEP)>0)
left = right + verify(string(right+1:),SEP)
right = left + scan(string(left:),SEP) - 2
if ( string(left:left) == '#' ) exit
do while (verify(string(right+1:),IO_WHITESPACE)>0)
left = right + verify(string(right+1:),IO_WHITESPACE)
right = left + scan(string(left:),IO_WHITESPACE) - 2
if ( string(left:left) == IO_COMMENT) exit
IO_stringPos = [IO_stringPos,left,right]
IO_stringPos(1) = IO_stringPos(1)+1
endOfString: if (right < left) then
@ -677,7 +652,7 @@ end function verifyFloatValue
!--------------------------------------------------------------------------------------------------
!> @brief check correctness of IO functions
!> @brief check correctness of some IO functions
!--------------------------------------------------------------------------------------------------
subroutine unitTest
@ -704,6 +679,10 @@ subroutine unitTest
chunkPos = IO_stringPos(str)
if(3112019 /= IO_intValue(str,chunkPos,2)) call IO_error(0,ext_msg='IO_intValue')
if(.not. IO_isBlank(' ')) call IO_error(0,ext_msg='IO_isBlank/1')
if(.not. IO_isBlank(' #isBlank')) call IO_error(0,ext_msg='IO_isBlank/2')
if( IO_isBlank(' i#s')) call IO_error(0,ext_msg='IO_isBlank/3')
end subroutine unitTest
end module IO

View File

@ -20,7 +20,7 @@
#include "geometry_plastic_nonlocal.f90"
#include "discretization.f90"
#ifdef Marc4DAMASK
#include "mesh_marc.f90"
#include "marc/discretization_marc.f90"
#endif
#include "material.f90"
#include "lattice.f90"

View File

@ -132,7 +132,7 @@ contains
!--------------------------------------------------------------------------------------------------
recursive function read_materialConfig(fileName,cnt) result(fileContent)
character(len=*), intent(in) :: fileName
character(len=*), intent(in) :: fileName !< name of the material configuration file
integer, intent(in), optional :: cnt !< recursion counter
character(len=pStringLen), dimension(:), allocatable :: fileContent !< file content, separated per lines
character(len=pStringLen), dimension(:), allocatable :: includedContent

View File

@ -127,7 +127,7 @@ module constitutive
end subroutine plastic_disloUCLA_LpAndItsTangent
module subroutine plastic_nonlocal_LpAndItsTangent(Lp,dLp_dMp, &
Mp, Temperature, volume, ip, el)
Mp,Temperature,instance,of,ip,el)
real(pReal), dimension(3,3), intent(out) :: &
Lp !< plastic velocity gradient
real(pReal), dimension(3,3,3,3), intent(out) :: &
@ -136,9 +136,10 @@ module constitutive
real(pReal), dimension(3,3), intent(in) :: &
Mp !< Mandel stress
real(pReal), intent(in) :: &
Temperature, &
volume
Temperature
integer, intent(in) :: &
instance, &
of, &
ip, & !< current integration point
el !< current element number
end subroutine plastic_nonlocal_LpAndItsTangent
@ -202,19 +203,21 @@ module constitutive
of
end subroutine plastic_disloUCLA_dotState
module subroutine plastic_nonlocal_dotState(Mp, F, Fp, Temperature, &
timestep,ip,el)
integer, intent(in) :: &
ip, & !< current integration point
el !< current element number
real(pReal), intent(in) :: &
Temperature, & !< temperature
timestep !< substepped crystallite time increment
module subroutine plastic_nonlocal_dotState(Mp, F, Fp, Temperature,timestep, &
instance,of,ip,el)
real(pReal), dimension(3,3), intent(in) ::&
Mp !< MandelStress
real(pReal), dimension(3,3,homogenization_maxNgrains,discretization_nIP,discretization_nElem), intent(in) :: &
F, & !< deformation gradient
Fp !< plastic deformation gradient
real(pReal), intent(in) :: &
Temperature, & !< temperature
timestep !< substepped crystallite time increment
integer, intent(in) :: &
instance, &
of, &
ip, & !< current integration point
el !< current element number
end subroutine plastic_nonlocal_dotState
@ -232,13 +235,15 @@ module constitutive
of
end subroutine plastic_disloUCLA_dependentState
module subroutine plastic_nonlocal_dependentState(F, Fp, ip, el)
integer, intent(in) :: &
ip, &
el
module subroutine plastic_nonlocal_dependentState(F, Fp, instance, of, ip, el)
real(pReal), dimension(3,3), intent(in) :: &
F, &
Fp
integer, intent(in) :: &
instance, &
of, &
ip, &
el
end subroutine plastic_nonlocal_dependentState
@ -250,12 +255,14 @@ module constitutive
of
end subroutine plastic_kinehardening_deltaState
module subroutine plastic_nonlocal_deltaState(Mp,ip,el)
integer, intent(in) :: &
ip, &
el
module subroutine plastic_nonlocal_deltaState(Mp,instance,of,ip,el)
real(pReal), dimension(3,3), intent(in) :: &
Mp
integer, intent(in) :: &
instance, &
of, &
ip, &
el
end subroutine plastic_nonlocal_deltaState
@ -268,8 +275,9 @@ module constitutive
el !< element
end function plastic_dislotwin_homogenizedC
module subroutine plastic_nonlocal_updateCompatibility(orientation,i,e)
module subroutine plastic_nonlocal_updateCompatibility(orientation,instance,i,e)
integer, intent(in) :: &
instance, &
i, &
e
type(rotation), dimension(1,discretization_nIP,discretization_nElem), intent(in) :: &
@ -364,9 +372,7 @@ subroutine constitutive_init
write(6,'(/,a)') ' <<<+- constitutive init -+>>>'; flush(6)
constitutive_plasticity_maxSizeDotState = 0
constitutive_source_maxSizeDotState = 0
PhaseLoop2:do ph = 1,material_Nphase
!--------------------------------------------------------------------------------------------------
! partition and inititalize state
@ -377,12 +383,11 @@ subroutine constitutive_init
sourceState(ph)%p(s)%state = sourceState(ph)%p(s)%partionedState0
end forall
!--------------------------------------------------------------------------------------------------
! determine max size of state and output
constitutive_plasticity_maxSizeDotState = max(constitutive_plasticity_maxSizeDotState, &
plasticState(ph)%sizeDotState)
! determine max size of source state
constitutive_source_maxSizeDotState = max(constitutive_source_maxSizeDotState, &
maxval(sourceState(ph)%p(:)%sizeDotState))
maxval(sourceState(ph)%p%sizeDotState))
enddo PhaseLoop2
constitutive_plasticity_maxSizeDotState = maxval(plasticState%sizeDotState)
end subroutine constitutive_init
@ -428,18 +433,16 @@ subroutine constitutive_dependentState(F, Fp, ipc, ip, el)
ho = material_homogenizationAt(el)
tme = thermalMapping(ho)%p(ip,el)
of = material_phasememberAt(ipc,ip,el)
instance = phase_plasticityInstance(material_phaseAt(ipc,el))
plasticityType: select case (phase_plasticity(material_phaseAt(ipc,el)))
case (PLASTICITY_DISLOTWIN_ID) plasticityType
of = material_phasememberAt(ipc,ip,el)
instance = phase_plasticityInstance(material_phaseAt(ipc,el))
call plastic_dislotwin_dependentState(temperature(ho)%p(tme),instance,of)
case (PLASTICITY_DISLOUCLA_ID) plasticityType
of = material_phasememberAt(ipc,ip,el)
instance = phase_plasticityInstance(material_phaseAt(ipc,el))
call plastic_disloUCLA_dependentState(instance,of)
case (PLASTICITY_NONLOCAL_ID) plasticityType
call plastic_nonlocal_dependentState (F,Fp,ip,el)
call plastic_nonlocal_dependentState (F,Fp,instance,of,ip,el)
end select plasticityType
end subroutine constitutive_dependentState
@ -478,6 +481,8 @@ subroutine constitutive_LpAndItsTangents(Lp, dLp_dS, dLp_dFi, &
tme = thermalMapping(ho)%p(ip,el)
Mp = matmul(matmul(transpose(Fi),Fi),S)
of = material_phasememberAt(ipc,ip,el)
instance = phase_plasticityInstance(material_phaseAt(ipc,el))
plasticityType: select case (phase_plasticity(material_phaseAt(ipc,el)))
@ -486,32 +491,21 @@ subroutine constitutive_LpAndItsTangents(Lp, dLp_dS, dLp_dFi, &
dLp_dMp = 0.0_pReal
case (PLASTICITY_ISOTROPIC_ID) plasticityType
of = material_phasememberAt(ipc,ip,el)
instance = phase_plasticityInstance(material_phaseAt(ipc,el))
call plastic_isotropic_LpAndItsTangent (Lp,dLp_dMp,Mp,instance,of)
case (PLASTICITY_PHENOPOWERLAW_ID) plasticityType
of = material_phasememberAt(ipc,ip,el)
instance = phase_plasticityInstance(material_phaseAt(ipc,el))
call plastic_phenopowerlaw_LpAndItsTangent(Lp,dLp_dMp,Mp,instance,of)
case (PLASTICITY_KINEHARDENING_ID) plasticityType
of = material_phasememberAt(ipc,ip,el)
instance = phase_plasticityInstance(material_phaseAt(ipc,el))
call plastic_kinehardening_LpAndItsTangent(Lp,dLp_dMp,Mp,instance,of)
case (PLASTICITY_NONLOCAL_ID) plasticityType
call plastic_nonlocal_LpAndItsTangent (Lp,dLp_dMp,Mp, &
temperature(ho)%p(tme),geometry_plastic_nonlocal_IPvolume0(ip,el),ip,el)
call plastic_nonlocal_LpAndItsTangent (Lp,dLp_dMp,Mp, temperature(ho)%p(tme),instance,of,ip,el)
case (PLASTICITY_DISLOTWIN_ID) plasticityType
of = material_phasememberAt(ipc,ip,el)
instance = phase_plasticityInstance(material_phaseAt(ipc,el))
call plastic_dislotwin_LpAndItsTangent (Lp,dLp_dMp,Mp,temperature(ho)%p(tme),instance,of)
case (PLASTICITY_DISLOUCLA_ID) plasticityType
of = material_phasememberAt(ipc,ip,el)
instance = phase_plasticityInstance(material_phaseAt(ipc,el))
call plastic_disloucla_LpAndItsTangent (Lp,dLp_dMp,Mp,temperature(ho)%p(tme),instance,of)
end select plasticityType
@ -740,39 +734,31 @@ subroutine constitutive_collectDotState(S, FArray, Fi, FpArray, subdt, ipc, ip,
ho = material_homogenizationAt(el)
tme = thermalMapping(ho)%p(ip,el)
of = material_phasememberAt(ipc,ip,el)
instance = phase_plasticityInstance(material_phaseAt(ipc,el))
Mp = matmul(matmul(transpose(Fi),Fi),S)
plasticityType: select case (phase_plasticity(material_phaseAt(ipc,el)))
case (PLASTICITY_ISOTROPIC_ID) plasticityType
of = material_phasememberAt(ipc,ip,el)
instance = phase_plasticityInstance(material_phaseAt(ipc,el))
call plastic_isotropic_dotState (Mp,instance,of)
case (PLASTICITY_PHENOPOWERLAW_ID) plasticityType
of = material_phasememberAt(ipc,ip,el)
instance = phase_plasticityInstance(material_phaseAt(ipc,el))
call plastic_phenopowerlaw_dotState(Mp,instance,of)
case (PLASTICITY_KINEHARDENING_ID) plasticityType
of = material_phasememberAt(ipc,ip,el)
instance = phase_plasticityInstance(material_phaseAt(ipc,el))
call plastic_kinehardening_dotState(Mp,instance,of)
case (PLASTICITY_DISLOTWIN_ID) plasticityType
of = material_phasememberAt(ipc,ip,el)
instance = phase_plasticityInstance(material_phaseAt(ipc,el))
call plastic_dislotwin_dotState (Mp,temperature(ho)%p(tme),instance,of)
case (PLASTICITY_DISLOUCLA_ID) plasticityType
of = material_phasememberAt(ipc,ip,el)
instance = phase_plasticityInstance(material_phaseAt(ipc,el))
call plastic_disloucla_dotState (Mp,temperature(ho)%p(tme),instance,of)
case (PLASTICITY_NONLOCAL_ID) plasticityType
call plastic_nonlocal_dotState (Mp,FArray,FpArray,temperature(ho)%p(tme), &
subdt,ip,el)
call plastic_nonlocal_dotState (Mp,FArray,FpArray,temperature(ho)%p(tme),subdt, &
instance,of,ip,el)
end select plasticityType
SourceLoop: do i = 1, phase_Nsources(material_phaseAt(ipc,el))
@ -789,7 +775,6 @@ subroutine constitutive_collectDotState(S, FArray, Fi, FpArray, subdt, ipc, ip,
call source_damage_anisoDuctile_dotState ( ipc, ip, el)
case (SOURCE_thermal_externalheat_ID) sourceType
of = material_phasememberAt(ipc,ip,el)
call source_thermal_externalheat_dotState(material_phaseAt(ipc,el),of)
end select sourceType
@ -820,16 +805,16 @@ subroutine constitutive_collectDeltaState(S, Fe, Fi, ipc, ip, el)
instance, of
Mp = matmul(matmul(transpose(Fi),Fi),S)
of = material_phasememberAt(ipc,ip,el)
instance = phase_plasticityInstance(material_phaseAt(ipc,el))
plasticityType: select case (phase_plasticity(material_phaseAt(ipc,el)))
case (PLASTICITY_KINEHARDENING_ID) plasticityType
of = material_phasememberAt(ipc,ip,el)
instance = phase_plasticityInstance(material_phaseAt(ipc,el))
call plastic_kinehardening_deltaState(Mp,instance,of)
case (PLASTICITY_NONLOCAL_ID) plasticityType
call plastic_nonlocal_deltaState(Mp,ip,el)
call plastic_nonlocal_deltaState(Mp,instance,of,ip,el)
end select plasticityType

View File

@ -12,16 +12,12 @@ submodule(constitutive) plastic_disloUCLA
type :: tParameters
real(pReal) :: &
aTol_rho, &
D, & !< grain size
mu, &
D_0, & !< prefactor for self-diffusion coefficient
Q_cl !< activation energy for dislocation climb
D = 1.0_pReal, & !< grain size
mu = 1.0_pReal, & !< equivalent shear modulus
D_0 = 1.0_pReal, & !< prefactor for self-diffusion coefficient
Q_cl = 1.0_pReal !< activation energy for dislocation climb
real(pReal), allocatable, dimension(:) :: &
rho_mob_0, & !< initial dislocation density
rho_dip_0, & !< initial dipole density
b_sl, & !< magnitude of burgers vector [m]
nonSchmidCoeff, &
D_a, &
i_sl, & !< Adj. parameter for distance between 2 forest dislocations
atomicVolume, &
@ -37,15 +33,13 @@ submodule(constitutive) plastic_disloUCLA
omega !< attempt frequency for kink pair nucleation
real(pReal), allocatable, dimension(:,:) :: &
h_sl_sl, & !< slip resistance from slip activity
forestProjectionEdge
forestProjection
real(pReal), allocatable, dimension(:,:,:) :: &
Schmid, &
P_sl, &
nonSchmid_pos, &
nonSchmid_neg
integer :: &
sum_N_sl !< total number of active slip system
integer, allocatable, dimension(:) :: &
N_sl !< number of active slip systems for each family
character(len=pStringLen), allocatable, dimension(:) :: &
output
logical :: &
@ -88,11 +82,16 @@ module subroutine plastic_disloUCLA_init
NipcMyPhase, &
sizeState, sizeDotState, &
startIndex, endIndex
integer, dimension(:), allocatable :: &
N_sl
real(pReal),dimension(:), allocatable :: &
rho_mob_0, & !< initial dislocation density
rho_dip_0, & !< initial dipole density
a !< non-Schmid coefficients
character(len=pStringLen) :: &
extmsg = ''
write(6,'(/,a)') ' <<<+- plastic_'//PLASTICITY_DISLOUCLA_label//' init -+>>>'; flush(6)
write(6,'(/,a)') ' <<<+- plastic_'//PLASTICITY_DISLOUCLA_LABEL//' init -+>>>'; flush(6)
write(6,'(/,a)') ' Cereceda et al., International Journal of Plasticity 78:242256, 2016'
write(6,'(a)') ' https://dx.doi.org/10.1016/j.ijplas.2015.09.002'
@ -106,7 +105,6 @@ module subroutine plastic_disloUCLA_init
allocate(dotState(Ninstance))
allocate(dependentState(Ninstance))
do p = 1, size(phase_plasticity)
if (phase_plasticity(p) /= PLASTICITY_DISLOUCLA_ID) cycle
associate(prm => param(phase_plasticityInstance(p)), &
@ -115,57 +113,50 @@ module subroutine plastic_disloUCLA_init
dst => dependentState(phase_plasticityInstance(p)), &
config => config_phase(p))
!--------------------------------------------------------------------------------------------------
! optional parameters that need to be defined
prm%output = config%getStrings('(output)',defaultVal=emptyStringArray)
! This data is read in already in lattice
prm%mu = lattice_mu(p)
prm%aTol_rho = config%getFloat('atol_rho')
! sanity checks
if (prm%aTol_rho <= 0.0_pReal) extmsg = trim(extmsg)//' atol_rho'
!--------------------------------------------------------------------------------------------------
! slip related parameters
prm%N_sl = config%getInts('nslip',defaultVal=emptyIntArray)
prm%sum_N_sl = sum(prm%N_sl)
N_sl = config%getInts('nslip',defaultVal=emptyIntArray)
prm%sum_N_sl = sum(abs(N_sl))
slipActive: if (prm%sum_N_sl > 0) then
prm%Schmid = lattice_SchmidMatrix_slip(prm%N_sl,config%getString('lattice_structure'),&
prm%P_sl = lattice_SchmidMatrix_slip(N_sl,config%getString('lattice_structure'),&
config%getFloat('c/a',defaultVal=0.0_pReal))
if(trim(config%getString('lattice_structure')) == 'bcc') then
prm%nonSchmidCoeff = config%getFloats('nonschmid_coefficients',&
defaultVal = emptyRealArray)
prm%nonSchmid_pos = lattice_nonSchmidMatrix(prm%N_sl,prm%nonSchmidCoeff,+1)
prm%nonSchmid_neg = lattice_nonSchmidMatrix(prm%N_sl,prm%nonSchmidCoeff,-1)
a = config%getFloats('nonschmid_coefficients',defaultVal = emptyRealArray)
prm%nonSchmid_pos = lattice_nonSchmidMatrix(N_sl,a,+1)
prm%nonSchmid_neg = lattice_nonSchmidMatrix(N_sl,a,-1)
else
allocate(prm%nonSchmidCoeff(0))
prm%nonSchmid_pos = prm%Schmid
prm%nonSchmid_neg = prm%Schmid
prm%nonSchmid_pos = prm%P_sl
prm%nonSchmid_neg = prm%P_sl
endif
prm%h_sl_sl = lattice_interaction_SlipBySlip(prm%N_sl, &
config%getFloats('interaction_slipslip'), &
prm%h_sl_sl = lattice_interaction_SlipBySlip(N_sl,config%getFloats('interaction_slipslip'), &
config%getString('lattice_structure'))
prm%forestProjectionEdge = lattice_forestProjection_edge(prm%N_sl,config%getString('lattice_structure'),&
prm%forestProjection = lattice_forestProjection_edge(N_sl,config%getString('lattice_structure'),&
config%getFloat('c/a',defaultVal=0.0_pReal))
prm%forestProjectionEdge = transpose(prm%forestProjectionEdge)
prm%forestProjection = transpose(prm%forestProjection)
prm%rho_mob_0 = config%getFloats('rhoedge0', requiredSize=size(prm%N_sl))
prm%rho_dip_0 = config%getFloats('rhoedgedip0', requiredSize=size(prm%N_sl))
prm%v0 = config%getFloats('v0', requiredSize=size(prm%N_sl))
prm%b_sl = config%getFloats('slipburgers', requiredSize=size(prm%N_sl))
prm%delta_F = config%getFloats('qedge', requiredSize=size(prm%N_sl))
rho_mob_0 = config%getFloats('rhoedge0', requiredSize=size(N_sl))
rho_dip_0 = config%getFloats('rhoedgedip0', requiredSize=size(N_sl))
prm%v0 = config%getFloats('v0', requiredSize=size(N_sl))
prm%b_sl = config%getFloats('slipburgers', requiredSize=size(N_sl))
prm%delta_F = config%getFloats('qedge', requiredSize=size(N_sl))
prm%i_sl = config%getFloats('clambdaslip', requiredSize=size(prm%N_sl))
prm%tau_0 = config%getFloats('tau_peierls', requiredSize=size(prm%N_sl))
prm%p = config%getFloats('p_slip', requiredSize=size(prm%N_sl), &
defaultVal=[(1.0_pReal,i=1,size(prm%N_sl))])
prm%q = config%getFloats('q_slip', requiredSize=size(prm%N_sl), &
defaultVal=[(1.0_pReal,i=1,size(prm%N_sl))])
prm%kink_height = config%getFloats('kink_height', requiredSize=size(prm%N_sl))
prm%w = config%getFloats('kink_width', requiredSize=size(prm%N_sl))
prm%omega = config%getFloats('omega', requiredSize=size(prm%N_sl))
prm%B = config%getFloats('friction_coeff', requiredSize=size(prm%N_sl))
prm%i_sl = config%getFloats('clambdaslip', requiredSize=size(N_sl))
prm%tau_0 = config%getFloats('tau_peierls', requiredSize=size(N_sl))
prm%p = config%getFloats('p_slip', requiredSize=size(N_sl), &
defaultVal=[(1.0_pReal,i=1,size(N_sl))])
prm%q = config%getFloats('q_slip', requiredSize=size(N_sl), &
defaultVal=[(1.0_pReal,i=1,size(N_sl))])
prm%kink_height = config%getFloats('kink_height', requiredSize=size(N_sl))
prm%w = config%getFloats('kink_width', requiredSize=size(N_sl))
prm%omega = config%getFloats('omega', requiredSize=size(N_sl))
prm%B = config%getFloats('friction_coeff', requiredSize=size(N_sl))
prm%D = config%getFloat('grainsize')
prm%D_0 = config%getFloat('d0')
@ -175,49 +166,43 @@ module subroutine plastic_disloUCLA_init
prm%dipoleformation = config%getFloat('dipoleformationfactor') > 0.0_pReal !should be on by default, ToDo: change to /key/-type key
! expand: family => system
prm%rho_mob_0 = math_expand(prm%rho_mob_0, prm%N_sl)
prm%rho_dip_0 = math_expand(prm%rho_dip_0, prm%N_sl)
prm%q = math_expand(prm%q, prm%N_sl)
prm%p = math_expand(prm%p, prm%N_sl)
prm%delta_F = math_expand(prm%delta_F, prm%N_sl)
prm%b_sl = math_expand(prm%b_sl, prm%N_sl)
prm%kink_height = math_expand(prm%kink_height, prm%N_sl)
prm%w = math_expand(prm%w, prm%N_sl)
prm%omega = math_expand(prm%omega, prm%N_sl)
prm%tau_0 = math_expand(prm%tau_0, prm%N_sl)
prm%v0 = math_expand(prm%v0, prm%N_sl)
prm%B = math_expand(prm%B, prm%N_sl)
prm%i_sl = math_expand(prm%i_sl, prm%N_sl)
prm%atomicVolume = math_expand(prm%atomicVolume, prm%N_sl)
prm%D_a = math_expand(prm%D_a, prm%N_sl)
rho_mob_0 = math_expand(rho_mob_0, N_sl)
rho_dip_0 = math_expand(rho_dip_0, N_sl)
prm%q = math_expand(prm%q, N_sl)
prm%p = math_expand(prm%p, N_sl)
prm%delta_F = math_expand(prm%delta_F, N_sl)
prm%b_sl = math_expand(prm%b_sl, N_sl)
prm%kink_height = math_expand(prm%kink_height, N_sl)
prm%w = math_expand(prm%w, N_sl)
prm%omega = math_expand(prm%omega, N_sl)
prm%tau_0 = math_expand(prm%tau_0, N_sl)
prm%v0 = math_expand(prm%v0, N_sl)
prm%B = math_expand(prm%B, N_sl)
prm%i_sl = math_expand(prm%i_sl, N_sl)
prm%atomicVolume = math_expand(prm%atomicVolume, N_sl)
prm%D_a = math_expand(prm%D_a, N_sl)
! sanity checks
if ( prm%D_0 <= 0.0_pReal) extmsg = trim(extmsg)//' D_0'
if ( prm%Q_cl <= 0.0_pReal) extmsg = trim(extmsg)//' Q_cl'
if (any(prm%rho_mob_0 < 0.0_pReal)) extmsg = trim(extmsg)//' rhoedge0'
if (any(prm%rho_dip_0 < 0.0_pReal)) extmsg = trim(extmsg)//' rhoedgedip0'
if (any(rho_mob_0 < 0.0_pReal)) extmsg = trim(extmsg)//' rhoedge0'
if (any(rho_dip_0 < 0.0_pReal)) extmsg = trim(extmsg)//' rhoedgedip0'
if (any(prm%v0 < 0.0_pReal)) extmsg = trim(extmsg)//' v0'
if (any(prm%b_sl <= 0.0_pReal)) extmsg = trim(extmsg)//' slipb_sl'
if (any(prm%b_sl <= 0.0_pReal)) extmsg = trim(extmsg)//' b_sl'
if (any(prm%delta_F <= 0.0_pReal)) extmsg = trim(extmsg)//' qedge'
if (any(prm%tau_0 < 0.0_pReal)) extmsg = trim(extmsg)//' tau_0'
if (any(prm%D_a <= 0.0_pReal)) extmsg = trim(extmsg)//' cedgedipmindistance or slipb_sl'
if (any(prm%atomicVolume <= 0.0_pReal)) extmsg = trim(extmsg)//' catomicvolume or slipb_sl'
if (any(prm%D_a <= 0.0_pReal)) extmsg = trim(extmsg)//' cedgedipmindistance or b_sl'
if (any(prm%atomicVolume <= 0.0_pReal)) extmsg = trim(extmsg)//' catomicvolume or b_sl'
else slipActive
allocate(prm%rho_mob_0(0))
allocate(prm%rho_dip_0(0))
rho_mob_0= emptyRealArray; rho_dip_0 = emptyRealArray
allocate(prm%b_sl,prm%D_a,prm%i_sl,prm%atomicVolume,prm%tau_0, &
prm%delta_F,prm%v0,prm%p,prm%q,prm%B,prm%kink_height,prm%w,prm%omega, &
source = emptyRealArray)
allocate(prm%forestProjection(0,0))
allocate(prm%h_sl_sl (0,0))
endif slipActive
!--------------------------------------------------------------------------------------------------
! exit if any parameter is out of range
if (extmsg /= '') &
call IO_error(211,ext_msg=trim(extmsg)//'('//PLASTICITY_DISLOUCLA_label//')')
!--------------------------------------------------------------------------------------------------
! output pararameters
prm%output = config%getStrings('(output)',defaultVal=emptyStringArray)
!--------------------------------------------------------------------------------------------------
! allocate state arrays
NipcMyPhase = count(material_phaseAt == p) * discretization_nIP
@ -227,26 +212,27 @@ module subroutine plastic_disloUCLA_init
call material_allocatePlasticState(p,NipcMyPhase,sizeState,sizeDotState,0)
!--------------------------------------------------------------------------------------------------
! locally defined state aliases and initialization of state0 and aTolState
! state aliases and initialization
startIndex = 1
endIndex = prm%sum_N_sl
stt%rho_mob => plasticState(p)%state(startIndex:endIndex,:)
stt%rho_mob= spread(prm%rho_mob_0,2,NipcMyPhase)
stt%rho_mob = spread(rho_mob_0,2,NipcMyPhase)
dot%rho_mob => plasticState(p)%dotState(startIndex:endIndex,:)
plasticState(p)%aTolState(startIndex:endIndex) = prm%aTol_rho
plasticState(p)%atol(startIndex:endIndex) = config%getFloat('atol_rho',defaultVal=1.0_pReal)
if (any(plasticState(p)%atol(startIndex:endIndex) < 0.0_pReal)) extmsg = trim(extmsg)//' atol_rho'
startIndex = endIndex + 1
endIndex = endIndex + prm%sum_N_sl
stt%rho_dip => plasticState(p)%state(startIndex:endIndex,:)
stt%rho_dip= spread(prm%rho_dip_0,2,NipcMyPhase)
stt%rho_dip = spread(rho_dip_0,2,NipcMyPhase)
dot%rho_dip => plasticState(p)%dotState(startIndex:endIndex,:)
plasticState(p)%aTolState(startIndex:endIndex) = prm%aTol_rho
plasticState(p)%atol(startIndex:endIndex) = config%getFloat('atol_rho',defaultVal=1.0_pReal)
startIndex = endIndex + 1
endIndex = endIndex + prm%sum_N_sl
stt%gamma_sl => plasticState(p)%state(startIndex:endIndex,:)
dot%gamma_sl => plasticState(p)%dotState(startIndex:endIndex,:)
plasticState(p)%aTolState(startIndex:endIndex) = 1.0e6_pReal ! Don't use for convergence check
plasticState(p)%atol(startIndex:endIndex) = 1.0e-2_pReal
! global alias
plasticState(p)%slipRate => plasticState(p)%dotState(startIndex:endIndex,:)
@ -257,6 +243,10 @@ module subroutine plastic_disloUCLA_init
end associate
!--------------------------------------------------------------------------------------------------
! exit if any parameter is out of range
if (extmsg /= '') call IO_error(211,ext_msg=trim(extmsg)//'('//PLASTICITY_DISLOUCLA_LABEL//')')
enddo
end subroutine plastic_disloUCLA_init
@ -293,11 +283,11 @@ pure module subroutine plastic_disloUCLA_LpAndItsTangent(Lp,dLp_dMp, &
call kinetics(Mp,T,instance,of,dot_gamma_pos,dot_gamma_neg,ddot_gamma_dtau_pos,ddot_gamma_dtau_neg)
do i = 1, prm%sum_N_sl
Lp = Lp + (dot_gamma_pos(i)+dot_gamma_neg(i))*prm%Schmid(1:3,1:3,i)
Lp = Lp + (dot_gamma_pos(i)+dot_gamma_neg(i))*prm%P_sl(1:3,1:3,i)
forall (k=1:3,l=1:3,m=1:3,n=1:3) &
dLp_dMp(k,l,m,n) = dLp_dMp(k,l,m,n) &
+ ddot_gamma_dtau_pos(i) * prm%Schmid(k,l,i) * prm%nonSchmid_pos(m,n,i) &
+ ddot_gamma_dtau_neg(i) * prm%Schmid(k,l,i) * prm%nonSchmid_neg(m,n,i)
+ ddot_gamma_dtau_pos(i) * prm%P_sl(k,l,i) * prm%nonSchmid_pos(m,n,i) &
+ ddot_gamma_dtau_neg(i) * prm%P_sl(k,l,i) * prm%nonSchmid_neg(m,n,i)
enddo
end associate
@ -379,8 +369,7 @@ module subroutine plastic_disloUCLA_dependentState(instance,of)
associate(prm => param(instance), stt => state(instance),dst => dependentState(instance))
dislocationSpacing = sqrt(matmul(prm%forestProjectionEdge, &
stt%rho_mob(:,of)+stt%rho_dip(:,of)))
dislocationSpacing = sqrt(matmul(prm%forestProjection,stt%rho_mob(:,of)+stt%rho_dip(:,of)))
dst%threshold_stress(:,of) = prm%mu*prm%b_sl &
* sqrt(matmul(prm%h_sl_sl,stt%rho_mob(:,of)+stt%rho_dip(:,of)))
@ -464,8 +453,8 @@ pure subroutine kinetics(Mp,T,instance,of, &
associate(prm => param(instance), stt => state(instance), dst => dependentState(instance))
do j = 1, prm%sum_N_sl
tau_pos(j) = math_mul33xx33(Mp,prm%nonSchmid_pos(1:3,1:3,j))
tau_neg(j) = math_mul33xx33(Mp,prm%nonSchmid_neg(1:3,1:3,j))
tau_pos(j) = math_tensordot(Mp,prm%nonSchmid_pos(1:3,1:3,j))
tau_neg(j) = math_tensordot(Mp,prm%nonSchmid_neg(1:3,1:3,j))
enddo

View File

@ -14,36 +14,31 @@ submodule(constitutive) plastic_dislotwin
type :: tParameters
real(pReal) :: &
mu, &
nu, &
D0, & !< prefactor for self-diffusion coefficient
Qsd, & !< activation energy for dislocation climb
omega, & !< frequency factor for dislocation climb
D, & !< grain size
p_sb, & !< p-exponent in shear band velocity
q_sb, & !< q-exponent in shear band velocity
CEdgeDipMinDistance, & !<
i_tw, & !<
tau_0, & !< strength due to elements in solid solution
L_tw, & !< Length of twin nuclei in Burgers vectors
L_tr, & !< Length of trans nuclei in Burgers vectors
xc_twin, & !< critical distance for formation of twin nucleus
xc_trans, & !< critical distance for formation of trans nucleus
V_cs, & !< cross slip volume
sbResistance, & !< value for shearband resistance (might become an internal state variable at some point)
sbVelocity, & !< value for shearband velocity_0
sbQedge, & !< activation energy for shear bands
SFE_0K, & !< stacking fault energy at zero K
dSFE_dT, & !< temperature dependance of stacking fault energy
aTol_rho, & !< absolute tolerance for integration of dislocation density
aTol_f_tw, & !< absolute tolerance for integration of twin volume fraction
aTol_f_tr, & !< absolute tolerance for integration of trans volume fraction
gamma_fcc_hex, & !< Free energy difference between austensite and martensite
i_tr, & !<
h !< Stack height of hex nucleus
mu = 1.0_pReal, & !< equivalent shear modulus
nu = 1.0_pReal, & !< equivalent shear Poisson's ratio
D0 = 1.0_pReal, & !< prefactor for self-diffusion coefficient
Qsd = 1.0_pReal, & !< activation energy for dislocation climb
omega = 1.0_pReal, & !< frequency factor for dislocation climb
D = 1.0_pReal, & !< grain size
p_sb = 1.0_pReal, & !< p-exponent in shear band velocity
q_sb = 1.0_pReal, & !< q-exponent in shear band velocity
CEdgeDipMinDistance = 1.0_pReal, & !<
i_tw = 1.0_pReal, & !<
tau_0 = 1.0_pReal, & !< strength due to elements in solid solution
L_tw = 1.0_pReal, & !< Length of twin nuclei in Burgers vectors
L_tr = 1.0_pReal, & !< Length of trans nuclei in Burgers vectors
xc_twin = 1.0_pReal, & !< critical distance for formation of twin nucleus
xc_trans = 1.0_pReal, & !< critical distance for formation of trans nucleus
V_cs = 1.0_pReal, & !< cross slip volume
sbResistance = 1.0_pReal, & !< value for shearband resistance
sbVelocity = 1.0_pReal, & !< value for shearband velocity_0
E_sb = 1.0_pReal, & !< activation energy for shear bands
SFE_0K = 1.0_pReal, & !< stacking fault energy at zero K
dSFE_dT = 1.0_pReal, & !< temperature dependence of stacking fault energy
gamma_fcc_hex = 1.0_pReal, & !< Free energy difference between austensite and martensite
i_tr = 1.0_pReal, & !<
h = 1.0_pReal !< Stack height of hex nucleus
real(pReal), allocatable, dimension(:) :: &
rho_mob_0, & !< initial unipolar dislocation density per slip system
rho_dip_0, & !< initial dipole dislocation density per slip system
b_sl, & !< absolute length of burgers vector [m] for each slip system
b_tw, & !< absolute length of burgers vector [m] for each twin system
b_tr, & !< absolute length of burgers vector [m] for each transformation system
@ -53,7 +48,6 @@ submodule(constitutive) plastic_dislotwin
dot_N_0_tr, & !< trans nucleation rate [1/m³s] for each trans system
t_tw, & !< twin thickness [m] for each twin system
CLambdaSlip, & !< Adj. parameter for distance between 2 forest dislocations for each slip system
atomicVolume, &
t_tr, & !< martensite lamellar thickness [m] for each trans system and instance
p, & !< p-exponent in glide velocity
q, & !< q-exponent in glide velocity
@ -71,19 +65,15 @@ submodule(constitutive) plastic_dislotwin
forestProjection, &
C66
real(pReal), allocatable, dimension(:,:,:) :: &
P_tr, &
P_sl, &
P_tw, &
P_tr, &
C66_tw, &
C66_tr
integer :: &
sum_N_sl, & !< total number of active slip system
sum_N_tw, & !< total number of active twin system
sum_N_tr !< total number of active transformation system
integer, allocatable, dimension(:) :: &
N_sl, & !< number of active slip systems for each family
N_tw, & !< number of active twin systems for each family
N_tr !< number of active transformation systems for each family
integer, allocatable, dimension(:,:) :: &
fcc_twinNucleationSlipPair ! ToDo: Better name? Is also use for trans
character(len=pStringLen), allocatable, dimension(:) :: &
@ -140,11 +130,15 @@ module subroutine plastic_dislotwin_init
NipcMyPhase, &
sizeState, sizeDotState, &
startIndex, endIndex
integer, dimension(:), allocatable :: &
N_sl, N_tw, N_tr
real(pReal), allocatable, dimension(:) :: &
rho_mob_0, & !< initial unipolar dislocation density per slip system
rho_dip_0 !< initial dipole dislocation density per slip system
character(len=pStringLen) :: &
extmsg = ''
write(6,'(/,a)') ' <<<+- constitutive_'//PLASTICITY_DISLOTWIN_label//' init -+>>>'; flush(6)
write(6,'(/,a)') ' <<<+- constitutive_'//PLASTICITY_DISLOTWIN_LABEL//' init -+>>>'; flush(6)
write(6,'(/,a)') ' Ma and Roters, Acta Materialia 52(12):36033612, 2004'
write(6,'(a)') ' https://doi.org/10.1016/j.actamat.2004.04.012'
@ -173,9 +167,7 @@ module subroutine plastic_dislotwin_init
dst => dependentState(phase_plasticityInstance(p)), &
config => config_phase(p))
prm%aTol_rho = config%getFloat('atol_rho', defaultVal=0.0_pReal)
prm%aTol_f_tw = config%getFloat('atol_twinfrac', defaultVal=0.0_pReal)
prm%aTol_f_tr = config%getFloat('atol_transfrac', defaultVal=0.0_pReal)
prm%output = config%getStrings('(output)', defaultVal=emptyStringArray)
! This data is read in already in lattice
prm%mu = lattice_mu(p)
@ -184,72 +176,67 @@ module subroutine plastic_dislotwin_init
!--------------------------------------------------------------------------------------------------
! slip related parameters
prm%N_sl = config%getInts('nslip',defaultVal=emptyIntArray)
prm%sum_N_sl = sum(prm%N_sl)
N_sl = config%getInts('nslip',defaultVal=emptyIntArray)
prm%sum_N_sl = sum(abs(N_sl))
slipActive: if (prm%sum_N_sl > 0) then
prm%P_sl = lattice_SchmidMatrix_slip(prm%N_sl,config%getString('lattice_structure'),&
prm%P_sl = lattice_SchmidMatrix_slip(N_sl,config%getString('lattice_structure'),&
config%getFloat('c/a',defaultVal=0.0_pReal))
prm%h_sl_sl = lattice_interaction_SlipBySlip(prm%N_sl, &
config%getFloats('interaction_slipslip'), &
prm%h_sl_sl = lattice_interaction_SlipBySlip(N_sl,config%getFloats('interaction_slipslip'), &
config%getString('lattice_structure'))
prm%forestProjection = lattice_forestProjection_edge(prm%N_sl,config%getString('lattice_structure'),&
prm%forestProjection = lattice_forestProjection_edge(N_sl,config%getString('lattice_structure'),&
config%getFloat('c/a',defaultVal=0.0_pReal))
prm%forestProjection = transpose(prm%forestProjection)
prm%n0_sl = lattice_slip_normal(prm%N_sl,config%getString('lattice_structure'),&
prm%n0_sl = lattice_slip_normal(N_sl,config%getString('lattice_structure'),&
config%getFloat('c/a',defaultVal=0.0_pReal))
prm%fccTwinTransNucleation = merge(.true., .false., lattice_structure(p) == lattice_FCC_ID) &
.and. (prm%N_sl(1) == 12)
if(prm%fccTwinTransNucleation) &
prm%fcc_twinNucleationSlipPair = lattice_FCC_TWINNUCLEATIONSLIPPAIR
.and. (N_sl(1) == 12)
if(prm%fccTwinTransNucleation) prm%fcc_twinNucleationSlipPair = lattice_FCC_TWINNUCLEATIONSLIPPAIR
prm%rho_mob_0 = config%getFloats('rhoedge0', requiredSize=size(prm%N_sl))
prm%rho_dip_0 = config%getFloats('rhoedgedip0',requiredSize=size(prm%N_sl))
prm%v0 = config%getFloats('v0', requiredSize=size(prm%N_sl))
prm%b_sl = config%getFloats('slipburgers',requiredSize=size(prm%N_sl))
prm%Delta_F = config%getFloats('qedge', requiredSize=size(prm%N_sl))
prm%CLambdaSlip = config%getFloats('clambdaslip',requiredSize=size(prm%N_sl))
prm%p = config%getFloats('p_slip', requiredSize=size(prm%N_sl))
prm%q = config%getFloats('q_slip', requiredSize=size(prm%N_sl))
prm%B = config%getFloats('b', requiredSize=size(prm%N_sl), &
defaultVal=[(0.0_pReal, i=1,size(prm%N_sl))])
rho_mob_0 = config%getFloats('rhoedge0', requiredSize=size(N_sl))
rho_dip_0 = config%getFloats('rhoedgedip0',requiredSize=size(N_sl))
prm%v0 = config%getFloats('v0', requiredSize=size(N_sl))
prm%b_sl = config%getFloats('slipburgers',requiredSize=size(N_sl))
prm%Delta_F = config%getFloats('qedge', requiredSize=size(N_sl))
prm%CLambdaSlip = config%getFloats('clambdaslip',requiredSize=size(N_sl))
prm%p = config%getFloats('p_slip', requiredSize=size(N_sl))
prm%q = config%getFloats('q_slip', requiredSize=size(N_sl))
prm%B = config%getFloats('b', requiredSize=size(N_sl), &
defaultVal=[(0.0_pReal, i=1,size(N_sl))])
prm%tau_0 = config%getFloat('solidsolutionstrength')
prm%CEdgeDipMinDistance = config%getFloat('cedgedipmindistance')
prm%D0 = config%getFloat('d0')
prm%Qsd = config%getFloat('qsd')
prm%atomicVolume = config%getFloat('catomicvolume') * prm%b_sl**3.0_pReal
prm%ExtendedDislocations = config%keyExists('/extend_dislocations/')
if (prm%ExtendedDislocations) then
prm%SFE_0K = config%getFloat('sfe_0k')
prm%dSFE_dT = config%getFloat('dsfe_dt')
endif
! multiplication factor according to crystal structure (nearest neighbors bcc vs fcc/hex)
!@details: Refer: Argon & Moffat, Acta Metallurgica, Vol. 29, pg 293 to 299, 1981
prm%omega = config%getFloat('omega', defaultVal = 1000.0_pReal) &
* merge(12.0_pReal, &
8.0_pReal, &
lattice_structure(p) == lattice_FCC_ID .or. lattice_structure(p) == lattice_HEX_ID)
prm%dipoleformation = .not. config%keyExists('/nodipoleformation/')
! multiplication factor according to crystal structure (nearest neighbors bcc vs fcc/hex)
! details: Argon & Moffat, Acta Metallurgica, Vol. 29, pg 293 to 299, 1981
prm%omega = config%getFloat('omega', defaultVal = 1000.0_pReal) &
* merge(12.0_pReal,8.0_pReal,any(lattice_structure(p) == [lattice_FCC_ID,lattice_HEX_ID]))
! expand: family => system
prm%rho_mob_0 = math_expand(prm%rho_mob_0, prm%N_sl)
prm%rho_dip_0 = math_expand(prm%rho_dip_0, prm%N_sl)
prm%v0 = math_expand(prm%v0, prm%N_sl)
prm%b_sl = math_expand(prm%b_sl, prm%N_sl)
prm%Delta_F = math_expand(prm%Delta_F, prm%N_sl)
prm%CLambdaSlip = math_expand(prm%CLambdaSlip, prm%N_sl)
prm%p = math_expand(prm%p, prm%N_sl)
prm%q = math_expand(prm%q, prm%N_sl)
prm%B = math_expand(prm%B, prm%N_sl)
prm%atomicVolume = math_expand(prm%atomicVolume,prm%N_sl)
rho_mob_0 = math_expand(rho_mob_0, N_sl)
rho_dip_0 = math_expand(rho_dip_0, N_sl)
prm%v0 = math_expand(prm%v0, N_sl)
prm%b_sl = math_expand(prm%b_sl, N_sl)
prm%Delta_F = math_expand(prm%Delta_F, N_sl)
prm%CLambdaSlip = math_expand(prm%CLambdaSlip, N_sl)
prm%p = math_expand(prm%p, N_sl)
prm%q = math_expand(prm%q, N_sl)
prm%B = math_expand(prm%B, N_sl)
! sanity checks
if ( prm%D0 <= 0.0_pReal) extmsg = trim(extmsg)//' D0'
if ( prm%Qsd <= 0.0_pReal) extmsg = trim(extmsg)//' Qsd'
if (any(prm%rho_mob_0 < 0.0_pReal)) extmsg = trim(extmsg)//' rho_mob_0'
if (any(prm%rho_dip_0 < 0.0_pReal)) extmsg = trim(extmsg)//' rho_dip_0'
if (any(rho_mob_0 < 0.0_pReal)) extmsg = trim(extmsg)//' rho_mob_0'
if (any(rho_dip_0 < 0.0_pReal)) extmsg = trim(extmsg)//' rho_dip_0'
if (any(prm%v0 < 0.0_pReal)) extmsg = trim(extmsg)//' v0'
if (any(prm%b_sl <= 0.0_pReal)) extmsg = trim(extmsg)//' b_sl'
if (any(prm%Delta_F <= 0.0_pReal)) extmsg = trim(extmsg)//' Delta_F'
@ -257,61 +244,69 @@ module subroutine plastic_dislotwin_init
if (any(prm%B < 0.0_pReal)) extmsg = trim(extmsg)//' B'
if (any(prm%p<=0.0_pReal .or. prm%p>1.0_pReal)) extmsg = trim(extmsg)//' p'
if (any(prm%q< 1.0_pReal .or. prm%q>2.0_pReal)) extmsg = trim(extmsg)//' q'
else slipActive
allocate(prm%b_sl(0))
rho_mob_0 = emptyRealArray; rho_dip_0 = emptyRealArray
allocate(prm%b_sl,prm%Delta_F,prm%v0,prm%CLambdaSlip,prm%p,prm%q,prm%B,source=emptyRealArray)
allocate(prm%forestProjection(0,0),prm%h_sl_sl(0,0))
endif slipActive
!--------------------------------------------------------------------------------------------------
! twin related parameters
prm%N_tw = config%getInts('ntwin', defaultVal=emptyIntArray)
prm%sum_N_tw = sum(prm%N_tw)
if (prm%sum_N_tw > 0) then
prm%P_tw = lattice_SchmidMatrix_twin(prm%N_tw,config%getString('lattice_structure'),&
N_tw = config%getInts('ntwin', defaultVal=emptyIntArray)
prm%sum_N_tw = sum(abs(N_tw))
twinActive: if (prm%sum_N_tw > 0) then
prm%P_tw = lattice_SchmidMatrix_twin(N_tw,config%getString('lattice_structure'),&
config%getFloat('c/a',defaultVal=0.0_pReal))
prm%h_tw_tw = lattice_interaction_TwinByTwin(prm%N_tw,&
prm%h_tw_tw = lattice_interaction_TwinByTwin(N_tw,&
config%getFloats('interaction_twintwin'), &
config%getString('lattice_structure'))
prm%b_tw = config%getFloats('twinburgers', requiredSize=size(prm%N_tw))
prm%t_tw = config%getFloats('twinsize', requiredSize=size(prm%N_tw))
prm%r = config%getFloats('r_twin', requiredSize=size(prm%N_tw))
prm%b_tw = config%getFloats('twinburgers', requiredSize=size(N_tw))
prm%t_tw = config%getFloats('twinsize', requiredSize=size(N_tw))
prm%r = config%getFloats('r_twin', requiredSize=size(N_tw))
prm%xc_twin = config%getFloat('xc_twin')
prm%L_tw = config%getFloat('l0_twin')
prm%i_tw = config%getFloat('cmfptwin')
prm%gamma_char= lattice_characteristicShear_Twin(prm%N_tw,config%getString('lattice_structure'),&
prm%gamma_char= lattice_characteristicShear_Twin(N_tw,config%getString('lattice_structure'),&
config%getFloat('c/a',defaultVal=0.0_pReal))
prm%C66_tw = lattice_C66_twin(prm%N_tw,prm%C66,config%getString('lattice_structure'),&
prm%C66_tw = lattice_C66_twin(N_tw,prm%C66,config%getString('lattice_structure'),&
config%getFloat('c/a',defaultVal=0.0_pReal))
if (.not. prm%fccTwinTransNucleation) then
prm%dot_N_0_tw = config%getFloats('ndot0_twin')
prm%dot_N_0_tw = math_expand(prm%dot_N_0_tw,prm%N_tw)
prm%dot_N_0_tw = math_expand(prm%dot_N_0_tw,N_tw)
endif
! expand: family => system
prm%b_tw = math_expand(prm%b_tw,prm%N_tw)
prm%t_tw = math_expand(prm%t_tw,prm%N_tw)
prm%r = math_expand(prm%r,prm%N_tw)
prm%b_tw = math_expand(prm%b_tw,N_tw)
prm%t_tw = math_expand(prm%t_tw,N_tw)
prm%r = math_expand(prm%r,N_tw)
else
allocate(prm%gamma_char(0))
allocate(prm%t_tw (0))
allocate(prm%b_tw (0))
allocate(prm%r (0))
allocate(prm%h_tw_tw (0,0))
! sanity checks
if ( prm%xc_twin < 0.0_pReal) extmsg = trim(extmsg)//' xc_twin'
if ( prm%L_tw < 0.0_pReal) extmsg = trim(extmsg)//' L_tw'
if ( prm%i_tw < 0.0_pReal) extmsg = trim(extmsg)//' i_tw'
if (any(prm%b_tw < 0.0_pReal)) extmsg = trim(extmsg)//' b_tw'
if (any(prm%t_tw < 0.0_pReal)) extmsg = trim(extmsg)//' t_tw'
if (any(prm%r < 0.0_pReal)) extmsg = trim(extmsg)//' r'
if (.not. prm%fccTwinTransNucleation) then
if (any(prm%dot_N_0_tw < 0.0_pReal)) extmsg = trim(extmsg)//' dot_N_0_tw'
endif
else twinActive
allocate(prm%gamma_char,prm%b_tw,prm%dot_N_0_tw,prm%t_tw,prm%r,source=emptyRealArray)
allocate(prm%h_tw_tw(0,0))
endif twinActive
!--------------------------------------------------------------------------------------------------
! transformation related parameters
prm%N_tr = config%getInts('ntrans', defaultVal=emptyIntArray)
prm%sum_N_tr = sum(prm%N_tr)
if (prm%sum_N_tr > 0) then
N_tr = config%getInts('ntrans', defaultVal=emptyIntArray)
prm%sum_N_tr = sum(abs(N_tr))
transActive: if (prm%sum_N_tr > 0) then
prm%b_tr = config%getFloats('transburgers')
prm%b_tr = math_expand(prm%b_tr,prm%N_tr)
prm%b_tr = math_expand(prm%b_tr,N_tr)
prm%h = config%getFloat('transstackheight', defaultVal=0.0_pReal) ! ToDo: How to handle that???
prm%i_tr = config%getFloat('cmfptrans', defaultVal=0.0_pReal) ! ToDo: How to handle that???
@ -319,96 +314,82 @@ module subroutine plastic_dislotwin_init
prm%xc_trans = config%getFloat('xc_trans', defaultVal=0.0_pReal) ! ToDo: How to handle that???
prm%L_tr = config%getFloat('l0_trans')
prm%h_tr_tr = lattice_interaction_TransByTrans(prm%N_tr,&
config%getFloats('interaction_transtrans'), &
prm%h_tr_tr = lattice_interaction_TransByTrans(N_tr,config%getFloats('interaction_transtrans'), &
config%getString('lattice_structure'))
prm%C66_tr = lattice_C66_trans(prm%N_tr,prm%C66, &
config%getString('trans_lattice_structure'), &
prm%C66_tr = lattice_C66_trans(N_tr,prm%C66,config%getString('trans_lattice_structure'), &
0.0_pReal, &
config%getFloat('a_bcc', defaultVal=0.0_pReal), &
config%getFloat('a_fcc', defaultVal=0.0_pReal))
prm%P_tr = lattice_SchmidMatrix_trans(prm%N_tr, &
config%getString('trans_lattice_structure'), &
prm%P_tr = lattice_SchmidMatrix_trans(N_tr,config%getString('trans_lattice_structure'), &
0.0_pReal, &
config%getFloat('a_bcc', defaultVal=0.0_pReal), &
config%getFloat('a_fcc', defaultVal=0.0_pReal))
if (lattice_structure(p) /= lattice_FCC_ID) then
prm%dot_N_0_tr = config%getFloats('ndot0_trans')
prm%dot_N_0_tr = math_expand(prm%dot_N_0_tr,prm%N_tr)
prm%dot_N_0_tr = math_expand(prm%dot_N_0_tr,N_tr)
endif
prm%t_tr = config%getFloats('lamellarsize')
prm%t_tr = math_expand(prm%t_tr,prm%N_tr)
prm%t_tr = math_expand(prm%t_tr,N_tr)
prm%s = config%getFloats('s_trans',defaultVal=[0.0_pReal])
prm%s = math_expand(prm%s,prm%N_tr)
else
allocate(prm%t_tr (0))
allocate(prm%b_tr (0))
allocate(prm%s (0))
prm%s = math_expand(prm%s,N_tr)
! sanity checks
if ( prm%xc_trans < 0.0_pReal) extmsg = trim(extmsg)//' xc_trans'
if ( prm%L_tr < 0.0_pReal) extmsg = trim(extmsg)//' L_tr'
if ( prm%i_tr < 0.0_pReal) extmsg = trim(extmsg)//' i_tr'
if (any(prm%t_tr < 0.0_pReal)) extmsg = trim(extmsg)//' t_tr'
if (any(prm%s < 0.0_pReal)) extmsg = trim(extmsg)//' s'
if (lattice_structure(p) /= lattice_FCC_ID) then
if (any(prm%dot_N_0_tr < 0.0_pReal)) extmsg = trim(extmsg)//' dot_N_0_tr'
endif
else transActive
allocate(prm%s,prm%b_tr,prm%t_tr,prm%dot_N_0_tr,source=emptyRealArray)
allocate(prm%h_tr_tr(0,0))
endif
if (sum(prm%N_tw) > 0 .or. prm%sum_N_tr > 0) then
prm%SFE_0K = config%getFloat('sfe_0k')
prm%dSFE_dT = config%getFloat('dsfe_dt')
prm%V_cs = config%getFloat('vcrossslip')
endif
if (prm%sum_N_sl > 0 .and. prm%sum_N_tw > 0) then
prm%h_sl_tw = lattice_interaction_SlipByTwin(prm%N_sl,prm%N_tw,&
config%getFloats('interaction_sliptwin'), &
config%getString('lattice_structure'))
if (prm%fccTwinTransNucleation .and. prm%sum_N_tw > 12) write(6,*) 'mist' ! ToDo: implement better test. The model will fail also if N_tw is [6,6]
endif
if (prm%sum_N_sl > 0 .and. prm%sum_N_tr > 0) then
prm%h_sl_tr = lattice_interaction_SlipByTrans(prm%N_sl,prm%N_tr,&
config%getFloats('interaction_sliptrans'), &
config%getString('lattice_structure'))
if (prm%fccTwinTransNucleation .and. prm%sum_N_tr > 12) write(6,*) 'mist' ! ToDo: implement better test. The model will fail also if N_tr is [6,6]
endif
endif transActive
!--------------------------------------------------------------------------------------------------
! shearband related parameters
prm%sbVelocity = config%getFloat('shearbandvelocity',defaultVal=0.0_pReal)
if (prm%sbVelocity > 0.0_pReal) then
prm%sbResistance = config%getFloat('shearbandresistance')
prm%sbQedge = config%getFloat('qedgepersbsystem')
prm%E_sb = config%getFloat('qedgepersbsystem')
prm%p_sb = config%getFloat('p_shearband')
prm%q_sb = config%getFloat('q_shearband')
! sanity checks
if (prm%sbResistance < 0.0_pReal) extmsg = trim(extmsg)//' shearbandresistance'
if (prm%sbQedge < 0.0_pReal) extmsg = trim(extmsg)//' qedgepersbsystem'
if (prm%E_sb < 0.0_pReal) extmsg = trim(extmsg)//' qedgepersbsystem'
if (prm%p_sb <= 0.0_pReal) extmsg = trim(extmsg)//' p_shearband'
if (prm%q_sb <= 0.0_pReal) extmsg = trim(extmsg)//' q_shearband'
endif
!--------------------------------------------------------------------------------------------------
! parameters required for several mechanisms and their interactions
if(prm%sum_N_sl + prm%sum_N_tw + prm%sum_N_tw > 0) &
prm%D = config%getFloat('grainsize')
if (config%keyExists('dipoleformationfactor')) call IO_error(1,ext_msg='use /nodipoleformation/')
prm%dipoleformation = .not. config%keyExists('/nodipoleformation/')
twinOrSlipActive: if (prm%sum_N_tw + prm%sum_N_tr > 0) then
prm%SFE_0K = config%getFloat('sfe_0k')
prm%dSFE_dT = config%getFloat('dsfe_dt')
prm%V_cs = config%getFloat('vcrossslip')
endif twinOrSlipActive
slipAndTwinActive: if (prm%sum_N_sl * prm%sum_N_tw > 0) then
prm%h_sl_tw = lattice_interaction_SlipByTwin(N_sl,N_tw,&
config%getFloats('interaction_sliptwin'), &
config%getString('lattice_structure'))
if (prm%fccTwinTransNucleation .and. size(N_tw) /= 1) extmsg = trim(extmsg)//' interaction_sliptwin'
endif slipAndTwinActive
!if (Ndot0PerTwinFamily(f,p) < 0.0_pReal) &
! call IO_error(211,el=p,ext_msg='dot_N_0_tw ('//PLASTICITY_DISLOTWIN_label//')')
if (any(prm%atomicVolume <= 0.0_pReal)) &
call IO_error(211,el=p,ext_msg='cAtomicVolume ('//PLASTICITY_DISLOTWIN_label//')')
if (prm%sum_N_tw > 0) then
if (prm%aTol_rho <= 0.0_pReal) &
call IO_error(211,el=p,ext_msg='aTol_rho ('//PLASTICITY_DISLOTWIN_label//')')
if (prm%aTol_f_tw <= 0.0_pReal) &
call IO_error(211,el=p,ext_msg='aTol_f_tw ('//PLASTICITY_DISLOTWIN_label//')')
endif
if (prm%sum_N_tr > 0) then
if (prm%aTol_f_tr <= 0.0_pReal) &
call IO_error(211,el=p,ext_msg='aTol_f_tr ('//PLASTICITY_DISLOTWIN_label//')')
endif
prm%output = config%getStrings('(output)', defaultVal=emptyStringArray)
slipAndTransActive: if (prm%sum_N_sl * prm%sum_N_tr > 0) then
prm%h_sl_tr = lattice_interaction_SlipByTrans(N_sl,N_tr,&
config%getFloats('interaction_sliptrans'), &
config%getString('lattice_structure'))
if (prm%fccTwinTransNucleation .and. size(N_tr) /= 1) extmsg = trim(extmsg)//' interaction_sliptrans'
endif slipAndTransActive
!--------------------------------------------------------------------------------------------------
! allocate state arrays
@ -421,26 +402,27 @@ module subroutine plastic_dislotwin_init
call material_allocatePlasticState(p,NipcMyPhase,sizeState,sizeDotState,0)
!--------------------------------------------------------------------------------------------------
! locally defined state aliases and initialization of state0 and aTolState
! locally defined state aliases and initialization of state0 and atol
startIndex = 1
endIndex = prm%sum_N_sl
stt%rho_mob=>plasticState(p)%state(startIndex:endIndex,:)
stt%rho_mob= spread(prm%rho_mob_0,2,NipcMyPhase)
stt%rho_mob= spread(rho_mob_0,2,NipcMyPhase)
dot%rho_mob=>plasticState(p)%dotState(startIndex:endIndex,:)
plasticState(p)%aTolState(startIndex:endIndex) = prm%aTol_rho
plasticState(p)%atol(startIndex:endIndex) = config%getFloat('atol_rho',defaultVal=1.0_pReal)
if (any(plasticState(p)%atol(startIndex:endIndex) < 0.0_pReal)) extmsg = trim(extmsg)//' atol_rho'
startIndex = endIndex + 1
endIndex = endIndex + prm%sum_N_sl
stt%rho_dip=>plasticState(p)%state(startIndex:endIndex,:)
stt%rho_dip= spread(prm%rho_dip_0,2,NipcMyPhase)
stt%rho_dip= spread(rho_dip_0,2,NipcMyPhase)
dot%rho_dip=>plasticState(p)%dotState(startIndex:endIndex,:)
plasticState(p)%aTolState(startIndex:endIndex) = prm%aTol_rho
plasticState(p)%atol(startIndex:endIndex) = config%getFloat('atol_rho',defaultVal=1.0_pReal)
startIndex = endIndex + 1
endIndex = endIndex + prm%sum_N_sl
stt%gamma_sl=>plasticState(p)%state(startIndex:endIndex,:)
dot%gamma_sl=>plasticState(p)%dotState(startIndex:endIndex,:)
plasticState(p)%aTolState(startIndex:endIndex) = 1.0e6_pReal !ToDo: better make optional parameter
plasticState(p)%atol(startIndex:endIndex) = 1.0e-2_pReal
! global alias
plasticState(p)%slipRate => plasticState(p)%dotState(startIndex:endIndex,:)
@ -448,13 +430,15 @@ module subroutine plastic_dislotwin_init
endIndex = endIndex + prm%sum_N_tw
stt%f_tw=>plasticState(p)%state(startIndex:endIndex,:)
dot%f_tw=>plasticState(p)%dotState(startIndex:endIndex,:)
plasticState(p)%aTolState(startIndex:endIndex) = prm%aTol_f_tw
plasticState(p)%atol(startIndex:endIndex) = config%getFloat('f_twin',defaultVal=1.0e-7_pReal)
if (any(plasticState(p)%atol(startIndex:endIndex) < 0.0_pReal)) extmsg = trim(extmsg)//' f_twin'
startIndex = endIndex + 1
endIndex = endIndex + prm%sum_N_tr
stt%f_tr=>plasticState(p)%state(startIndex:endIndex,:)
dot%f_tr=>plasticState(p)%dotState(startIndex:endIndex,:)
plasticState(p)%aTolState(startIndex:endIndex) = prm%aTol_f_tr
plasticState(p)%atol(startIndex:endIndex) = config%getFloat('f_trans',defaultVal=1.0e-6_pReal)
if (any(plasticState(p)%atol(startIndex:endIndex) < 0.0_pReal)) extmsg = trim(extmsg)//' f_trans'
allocate(dst%Lambda_sl (prm%sum_N_sl,NipcMyPhase),source=0.0_pReal)
allocate(dst%tau_pass (prm%sum_N_sl,NipcMyPhase),source=0.0_pReal)
@ -469,11 +453,14 @@ module subroutine plastic_dislotwin_init
allocate(dst%tau_r_tr (prm%sum_N_tr,NipcMyPhase),source=0.0_pReal)
allocate(dst%V_tr (prm%sum_N_tr,NipcMyPhase),source=0.0_pReal)
plasticState(p)%state0 = plasticState(p)%state ! ToDo: this could be done centrally
end associate
!--------------------------------------------------------------------------------------------------
! exit if any parameter is out of range
if (extmsg /= '') call IO_error(211,ext_msg=trim(extmsg)//'('//PLASTICITY_DISLOTWIN_LABEL//')')
enddo
end subroutine plastic_dislotwin_init
@ -544,7 +531,6 @@ module subroutine plastic_dislotwin_LpAndItsTangent(Lp,dLp_dMp,Mp,T,instance,of)
real(pReal):: dot_gamma_sb
real(pReal), dimension(3,3) :: eigVectors, P_sb
real(pReal), dimension(3) :: eigValues
logical :: error
real(pReal), dimension(3,6), parameter :: &
sb_sComposition = &
reshape(real([&
@ -588,13 +574,13 @@ module subroutine plastic_dislotwin_LpAndItsTangent(Lp,dLp_dMp,Mp,T,instance,of)
shearBandingContribution: if(dNeq0(prm%sbVelocity)) then
BoltzmannRatio = prm%sbQedge/(kB*T)
call math_eigenValuesVectorsSym(Mp,eigValues,eigVectors,error)
BoltzmannRatio = prm%E_sb/(kB*T)
call math_eigh33(Mp,eigValues,eigVectors) ! is Mp symmetric by design?
do i = 1,6
P_sb = 0.5_pReal * math_outer(matmul(eigVectors,sb_sComposition(1:3,i)),&
matmul(eigVectors,sb_mComposition(1:3,i)))
tau = math_mul33xx33(Mp,P_sb)
tau = math_tensordot(Mp,P_sb)
significantShearBandStress: if (abs(tau) > tol_math_check) then
StressRatio_p = (abs(tau)/prm%sbResistance)**prm%p_sb
@ -650,7 +636,6 @@ module subroutine plastic_dislotwin_dotState(Mp,T,instance,of)
integer :: i
real(pReal) :: &
f_unrotated, &
VacancyDiffusion, &
rho_dip_distance, &
v_cl, & !< climb velocity
Gamma, & !< stacking fault energy
@ -673,7 +658,6 @@ module subroutine plastic_dislotwin_dotState(Mp,T,instance,of)
f_unrotated = 1.0_pReal &
- sum(stt%f_tw(1:prm%sum_N_tw,of)) &
- sum(stt%f_tr(1:prm%sum_N_tr,of))
VacancyDiffusion = prm%D0*exp(-prm%Qsd/(kB*T))
call kinetics_slip(Mp,T,instance,of,dot_gamma_sl)
dot%gamma_sl(:,of) = abs(dot_gamma_sl)
@ -681,7 +665,7 @@ module subroutine plastic_dislotwin_dotState(Mp,T,instance,of)
rho_dip_distance_min = prm%CEdgeDipMinDistance*prm%b_sl
slipState: do i = 1, prm%sum_N_sl
tau = math_mul33xx33(Mp,prm%P_sl(1:3,1:3,i))
tau = math_tensordot(Mp,prm%P_sl(1:3,1:3,i))
significantSlipStress: if (dEq0(tau)) then
dot_rho_dip_formation(i) = 0.0_pReal
@ -922,7 +906,7 @@ pure subroutine kinetics_slip(Mp,T,instance,of, &
associate(prm => param(instance), stt => state(instance), dst => dependentState(instance))
do i = 1, prm%sum_N_sl
tau(i) = math_mul33xx33(Mp,prm%P_sl(1:3,1:3,i))
tau(i) = math_tensordot(Mp,prm%P_sl(1:3,1:3,i))
enddo
tau_eff = abs(tau)-dst%tau_pass(:,of)
@ -993,7 +977,7 @@ pure subroutine kinetics_twin(Mp,T,dot_gamma_sl,instance,of,&
associate(prm => param(instance), stt => state(instance), dst => dependentState(instance))
do i = 1, prm%sum_N_tw
tau(i) = math_mul33xx33(Mp,prm%P_tw(1:3,1:3,i))
tau(i) = math_tensordot(Mp,prm%P_tw(1:3,1:3,i))
isFCC: if (prm%fccTwinTransNucleation) then
s1=prm%fcc_twinNucleationSlipPair(1,i)
s2=prm%fcc_twinNucleationSlipPair(2,i)
@ -1061,7 +1045,7 @@ pure subroutine kinetics_trans(Mp,T,dot_gamma_sl,instance,of,&
associate(prm => param(instance), stt => state(instance), dst => dependentState(instance))
do i = 1, prm%sum_N_tr
tau(i) = math_mul33xx33(Mp,prm%P_tr(1:3,1:3,i))
tau(i) = math_tensordot(Mp,prm%P_tr(1:3,1:3,i))
isFCC: if (prm%fccTwinTransNucleation) then
s1=prm%fcc_twinNucleationSlipPair(1,i)
s2=prm%fcc_twinNucleationSlipPair(2,i)

View File

@ -12,7 +12,6 @@ submodule(constitutive) plastic_isotropic
type :: tParameters
real(pReal) :: &
M, & !< Taylor factor
xi_0, & !< initial critical stress
dot_gamma_0, & !< reference strain rate
n, & !< stress exponent
h0, &
@ -22,9 +21,7 @@ submodule(constitutive) plastic_isotropic
c_1, &
c_4, &
c_3, &
c_2, &
aTol_xi, &
aTol_gamma
c_2
integer :: &
of_debug = 0
logical :: &
@ -59,11 +56,12 @@ module subroutine plastic_isotropic_init
p, &
NipcMyPhase, &
sizeState, sizeDotState
real(pReal) :: &
xi_0 !< initial critical stress
character(len=pStringLen) :: &
extmsg = ''
write(6,'(/,a)') ' <<<+- plastic_'//PLASTICITY_ISOTROPIC_label//' init -+>>>'; flush(6)
write(6,'(/,a)') ' <<<+- plastic_'//PLASTICITY_ISOTROPIC_LABEL//' init -+>>>'; flush(6)
write(6,'(/,a)') ' Maiti and Eisenlohr, Scripta Materialia 145:3740, 2018'
write(6,'(a)') ' https://doi.org/10.1016/j.scriptamat.2017.09.047'
@ -83,12 +81,14 @@ module subroutine plastic_isotropic_init
stt => state(phase_plasticityInstance(p)), &
config => config_phase(p))
prm%output = config%getStrings('(output)',defaultVal=emptyStringArray)
#ifdef DEBUG
if (p==material_phaseAt(debug_g,debug_e)) &
prm%of_debug = material_phasememberAt(debug_g,debug_i,debug_e)
#endif
prm%xi_0 = config%getFloat('tau0')
xi_0 = config%getFloat('tau0')
prm%xi_inf = config%getFloat('tausat')
prm%dot_gamma_0 = config%getFloat('gdot0')
prm%n = config%getFloat('n')
@ -100,31 +100,16 @@ module subroutine plastic_isotropic_init
prm%c_3 = config%getFloat('tausat_sinhfitc',defaultVal=0.0_pReal)
prm%c_2 = config%getFloat('tausat_sinhfitd',defaultVal=0.0_pReal)
prm%a = config%getFloat('a')
prm%aTol_xi = config%getFloat('atol_flowstress',defaultVal=1.0_pReal)
prm%aTol_gamma = config%getFloat('atol_shear', defaultVal=1.0e-6_pReal)
prm%dilatation = config%keyExists('/dilatation/')
!--------------------------------------------------------------------------------------------------
! sanity checks
extmsg = ''
if (prm%aTol_gamma <= 0.0_pReal) extmsg = trim(extmsg)//' aTol_gamma'
if (prm%xi_0 < 0.0_pReal) extmsg = trim(extmsg)//' xi_0'
if (xi_0 < 0.0_pReal) extmsg = trim(extmsg)//' xi_0'
if (prm%dot_gamma_0 <= 0.0_pReal) extmsg = trim(extmsg)//' dot_gamma_0'
if (prm%n <= 0.0_pReal) extmsg = trim(extmsg)//' n'
if (prm%a <= 0.0_pReal) extmsg = trim(extmsg)//' a'
if (prm%M <= 0.0_pReal) extmsg = trim(extmsg)//' m'
if (prm%aTol_xi <= 0.0_pReal) extmsg = trim(extmsg)//' atol_xi'
if (prm%aTol_gamma <= 0.0_pReal) extmsg = trim(extmsg)//' atol_shear'
!--------------------------------------------------------------------------------------------------
! exit if any parameter is out of range
if (extmsg /= '') &
call IO_error(211,ext_msg=trim(extmsg)//'('//PLASTICITY_ISOTROPIC_label//')')
!--------------------------------------------------------------------------------------------------
! output pararameters
prm%output = config%getStrings('(output)',defaultVal=emptyStringArray)
if (prm%M <= 0.0_pReal) extmsg = trim(extmsg)//' M'
!--------------------------------------------------------------------------------------------------
! allocate state arrays
@ -135,15 +120,17 @@ module subroutine plastic_isotropic_init
call material_allocatePlasticState(p,NipcMyPhase,sizeState,sizeDotState,0)
!--------------------------------------------------------------------------------------------------
! locally defined state aliases and initialization of state0 and aTolState
! state aliases and initialization
stt%xi => plasticState(p)%state (1,:)
stt%xi = prm%xi_0
stt%xi = xi_0
dot%xi => plasticState(p)%dotState(1,:)
plasticState(p)%aTolState(1) = prm%aTol_xi
plasticState(p)%atol(1) = config%getFloat('atol_xi',defaultVal=1.0_pReal)
if (plasticState(p)%atol(1) < 0.0_pReal) extmsg = trim(extmsg)//' atol_xi'
stt%gamma => plasticState(p)%state (2,:)
dot%gamma => plasticState(p)%dotState(2,:)
plasticState(p)%aTolState(2) = prm%aTol_gamma
plasticState(p)%atol(2) = config%getFloat('atol_gamma',defaultVal=1.0e-6_pReal)
if (plasticState(p)%atol(2) < 0.0_pReal) extmsg = trim(extmsg)//' atol_gamma'
! global alias
plasticState(p)%slipRate => plasticState(p)%dotState(2:2,:)
@ -151,6 +138,10 @@ module subroutine plastic_isotropic_init
end associate
!--------------------------------------------------------------------------------------------------
! exit if any parameter is out of range
if (extmsg /= '') call IO_error(211,ext_msg=trim(extmsg)//'('//PLASTICITY_ISOTROPIC_LABEL//')')
enddo
end subroutine plastic_isotropic_init
@ -184,7 +175,7 @@ module subroutine plastic_isotropic_LpAndItsTangent(Lp,dLp_dMp,Mp,instance,of)
associate(prm => param(instance), stt => state(instance))
Mp_dev = math_deviatoric33(Mp)
squarenorm_Mp_dev = math_mul33xx33(Mp_dev,Mp_dev)
squarenorm_Mp_dev = math_tensordot(Mp_dev,Mp_dev)
norm_Mp_dev = sqrt(squarenorm_Mp_dev)
if (norm_Mp_dev > 0.0_pReal) then
@ -288,9 +279,9 @@ module subroutine plastic_isotropic_dotState(Mp,instance,of)
associate(prm => param(instance), stt => state(instance), dot => dotState(instance))
if (prm%dilatation) then
norm_Mp = sqrt(math_mul33xx33(Mp,Mp))
norm_Mp = sqrt(math_tensordot(Mp,Mp))
else
norm_Mp = sqrt(math_mul33xx33(math_deviatoric33(Mp),math_deviatoric33(Mp)))
norm_Mp = sqrt(math_tensordot(math_deviatoric33(Mp),math_deviatoric33(Mp)))
endif
dot_gamma = prm%dot_gamma_0 * (sqrt(1.5_pReal) * norm_Mp /(prm%M*stt%xi(of))) **prm%n

View File

@ -9,30 +9,26 @@ submodule(constitutive) plastic_kinehardening
type :: tParameters
real(pReal) :: &
gdot0, & !< reference shear strain rate for slip
n, & !< stress exponent for slip
aTolResistance, &
aTolShear
gdot0 = 1.0_pReal, & !< reference shear strain rate for slip
n = 1.0_pReal !< stress exponent for slip
real(pReal), allocatable, dimension(:) :: &
crss0, & !< initial critical shear stress for slip
theta0, & !< initial hardening rate of forward stress for each slip
theta1, & !< asymptotic hardening rate of forward stress for each slip
theta0_b, & !< initial hardening rate of back stress for each slip
theta1_b, & !< asymptotic hardening rate of back stress for each slip
tau1, &
tau1_b, &
nonSchmidCoeff
tau1_b
real(pReal), allocatable, dimension(:,:) :: &
interaction_slipslip !< slip resistance from slip activity
real(pReal), allocatable, dimension(:,:,:) :: &
Schmid, &
P, &
nonSchmid_pos, &
nonSchmid_neg
integer :: &
totalNslip, & !< total number of active slip system
sum_N_sl, & !< total number of active slip system
of_debug = 0
integer, allocatable, dimension(:) :: &
Nslip !< number of active slip systems for each family
logical :: &
nonSchmidActive = .false.
character(len=pStringLen), allocatable, dimension(:) :: &
output
end type tParameters
@ -70,11 +66,15 @@ module subroutine plastic_kinehardening_init
NipcMyPhase, &
sizeState, sizeDeltaState, sizeDotState, &
startIndex, endIndex
integer, dimension(:), allocatable :: &
N_sl
real(pReal), dimension(:), allocatable :: &
xi_0, & !< initial resistance against plastic flow
a !< non-Schmid coefficients
character(len=pStringLen) :: &
extmsg = ''
write(6,'(/,a)') ' <<<+- plastic_'//PLASTICITY_KINEHARDENING_label//' init -+>>>'; flush(6)
write(6,'(/,a)') ' <<<+- plastic_'//PLASTICITY_KINEHARDENING_LABEL//' init -+>>>'; flush(6)
Ninstance = count(phase_plasticity == PLASTICITY_KINEHARDENING_ID)
if (iand(debug_level(debug_constitutive),debug_levelBasic) /= 0) &
@ -93,130 +93,117 @@ module subroutine plastic_kinehardening_init
stt => state(phase_plasticityInstance(p)),&
config => config_phase(p))
prm%output = config%getStrings('(output)',defaultVal=emptyStringArray)
#ifdef DEBUG
if (p==material_phaseAt(debug_g,debug_e)) then
prm%of_debug = material_phasememberAt(debug_g,debug_i,debug_e)
endif
#endif
!--------------------------------------------------------------------------------------------------
! optional parameters that need to be defined
prm%aTolResistance = config%getFloat('atol_resistance',defaultVal=1.0_pReal)
prm%aTolShear = config%getFloat('atol_shear', defaultVal=1.0e-6_pReal)
! sanity checks
if (prm%aTolResistance <= 0.0_pReal) extmsg = trim(extmsg)//' aTolresistance'
if (prm%aTolShear <= 0.0_pReal) extmsg = trim(extmsg)//' aTolShear'
!--------------------------------------------------------------------------------------------------
! slip related parameters
prm%Nslip = config%getInts('nslip',defaultVal=emptyIntArray)
prm%totalNslip = sum(prm%Nslip)
slipActive: if (prm%totalNslip > 0) then
prm%Schmid = lattice_SchmidMatrix_slip(prm%Nslip,config%getString('lattice_structure'),&
N_sl = config%getInts('nslip',defaultVal=emptyIntArray)
prm%sum_N_sl = sum(abs(N_sl))
slipActive: if (prm%sum_N_sl > 0) then
prm%P = lattice_SchmidMatrix_slip(N_sl,config%getString('lattice_structure'),&
config%getFloat('c/a',defaultVal=0.0_pReal))
if(trim(config%getString('lattice_structure')) == 'bcc') then
prm%nonSchmidCoeff = config%getFloats('nonschmid_coefficients',&
defaultVal = emptyRealArray)
prm%nonSchmid_pos = lattice_nonSchmidMatrix(prm%Nslip,prm%nonSchmidCoeff,+1)
prm%nonSchmid_neg = lattice_nonSchmidMatrix(prm%Nslip,prm%nonSchmidCoeff,-1)
a = config%getFloats('nonschmid_coefficients',defaultVal = emptyRealArray)
if(size(a) > 0) prm%nonSchmidActive = .true.
prm%nonSchmid_pos = lattice_nonSchmidMatrix(N_sl,a,+1)
prm%nonSchmid_neg = lattice_nonSchmidMatrix(N_sl,a,-1)
else
prm%nonSchmid_pos = prm%Schmid
prm%nonSchmid_neg = prm%Schmid
prm%nonSchmid_pos = prm%P
prm%nonSchmid_neg = prm%P
endif
prm%interaction_SlipSlip = lattice_interaction_SlipBySlip(prm%Nslip, &
prm%interaction_SlipSlip = lattice_interaction_SlipBySlip(N_sl, &
config%getFloats('interaction_slipslip'), &
config%getString('lattice_structure'))
prm%crss0 = config%getFloats('crss0', requiredSize=size(prm%Nslip))
prm%tau1 = config%getFloats('tau1', requiredSize=size(prm%Nslip))
prm%tau1_b = config%getFloats('tau1_b', requiredSize=size(prm%Nslip))
prm%theta0 = config%getFloats('theta0', requiredSize=size(prm%Nslip))
prm%theta1 = config%getFloats('theta1', requiredSize=size(prm%Nslip))
prm%theta0_b = config%getFloats('theta0_b', requiredSize=size(prm%Nslip))
prm%theta1_b = config%getFloats('theta1_b', requiredSize=size(prm%Nslip))
xi_0 = config%getFloats('crss0', requiredSize=size(N_sl))
prm%tau1 = config%getFloats('tau1', requiredSize=size(N_sl))
prm%tau1_b = config%getFloats('tau1_b', requiredSize=size(N_sl))
prm%theta0 = config%getFloats('theta0', requiredSize=size(N_sl))
prm%theta1 = config%getFloats('theta1', requiredSize=size(N_sl))
prm%theta0_b = config%getFloats('theta0_b', requiredSize=size(N_sl))
prm%theta1_b = config%getFloats('theta1_b', requiredSize=size(N_sl))
prm%gdot0 = config%getFloat('gdot0')
prm%n = config%getFloat('n_slip')
! expand: family => system
prm%crss0 = math_expand(prm%crss0, prm%Nslip)
prm%tau1 = math_expand(prm%tau1, prm%Nslip)
prm%tau1_b = math_expand(prm%tau1_b, prm%Nslip)
prm%theta0 = math_expand(prm%theta0, prm%Nslip)
prm%theta1 = math_expand(prm%theta1, prm%Nslip)
prm%theta0_b = math_expand(prm%theta0_b,prm%Nslip)
prm%theta1_b = math_expand(prm%theta1_b,prm%Nslip)
xi_0 = math_expand(xi_0, N_sl)
prm%tau1 = math_expand(prm%tau1, N_sl)
prm%tau1_b = math_expand(prm%tau1_b, N_sl)
prm%theta0 = math_expand(prm%theta0, N_sl)
prm%theta1 = math_expand(prm%theta1, N_sl)
prm%theta0_b = math_expand(prm%theta0_b,N_sl)
prm%theta1_b = math_expand(prm%theta1_b,N_sl)
!--------------------------------------------------------------------------------------------------
! sanity checks
if ( prm%gdot0 <= 0.0_pReal) extmsg = trim(extmsg)//' gdot0'
if ( prm%n <= 0.0_pReal) extmsg = trim(extmsg)//' n_slip'
if (any(prm%crss0 <= 0.0_pReal)) extmsg = trim(extmsg)//' crss0'
if (any(xi_0 <= 0.0_pReal)) extmsg = trim(extmsg)//' crss0'
if (any(prm%tau1 <= 0.0_pReal)) extmsg = trim(extmsg)//' tau1'
if (any(prm%tau1_b <= 0.0_pReal)) extmsg = trim(extmsg)//' tau1_b'
!ToDo: Any sensible checks for theta?
else slipActive
xi_0 = emptyRealArray
allocate(prm%tau1,prm%tau1_b,prm%theta0,prm%theta1,prm%theta0_b,prm%theta1_b,source=emptyRealArray)
allocate(prm%interaction_SlipSlip(0,0))
endif slipActive
!--------------------------------------------------------------------------------------------------
! exit if any parameter is out of range
if (extmsg /= '') &
call IO_error(211,ext_msg=trim(extmsg)//'('//PLASTICITY_KINEHARDENING_label//')')
!--------------------------------------------------------------------------------------------------
! output pararameters
prm%output = config%getStrings('(output)',defaultVal=emptyStringArray)
!--------------------------------------------------------------------------------------------------
! allocate state arrays
NipcMyPhase = count(material_phaseAt == p) * discretization_nIP
sizeDotState = size(['crss ','crss_back', 'accshear ']) * prm%totalNslip
sizeDeltaState = size(['sense ', 'chi0 ', 'gamma0' ]) * prm%totalNslip
sizeDotState = size(['crss ','crss_back', 'accshear ']) * prm%sum_N_sl
sizeDeltaState = size(['sense ', 'chi0 ', 'gamma0' ]) * prm%sum_N_sl
sizeState = sizeDotState + sizeDeltaState
call material_allocatePlasticState(p,NipcMyPhase,sizeState,sizeDotState,sizeDeltaState)
!--------------------------------------------------------------------------------------------------
! locally defined state aliases and initialization of state0 and aTolState
! state aliases and initialization
startIndex = 1
endIndex = prm%totalNslip
endIndex = prm%sum_N_sl
stt%crss => plasticState(p)%state (startIndex:endIndex,:)
stt%crss = spread(prm%crss0, 2, NipcMyPhase)
stt%crss = spread(xi_0, 2, NipcMyPhase)
dot%crss => plasticState(p)%dotState(startIndex:endIndex,:)
plasticState(p)%aTolState(startIndex:endIndex) = prm%aTolResistance
plasticState(p)%atol(startIndex:endIndex) = config%getFloat('atol_xi',defaultVal=1.0_pReal)
if(any(plasticState(p)%atol(startIndex:endIndex) < 0.0_pReal)) extmsg = trim(extmsg)//' atol_xi'
startIndex = endIndex + 1
endIndex = endIndex + prm%totalNslip
endIndex = endIndex + prm%sum_N_sl
stt%crss_back => plasticState(p)%state (startIndex:endIndex,:)
dot%crss_back => plasticState(p)%dotState(startIndex:endIndex,:)
plasticState(p)%aTolState(startIndex:endIndex) = prm%aTolResistance
plasticState(p)%atol(startIndex:endIndex) = config%getFloat('atol_xi',defaultVal=1.0_pReal)
startIndex = endIndex + 1
endIndex = endIndex + prm%totalNslip
endIndex = endIndex + prm%sum_N_sl
stt%accshear => plasticState(p)%state (startIndex:endIndex,:)
dot%accshear => plasticState(p)%dotState(startIndex:endIndex,:)
plasticState(p)%aTolState(startIndex:endIndex) = prm%aTolShear
plasticState(p)%atol(startIndex:endIndex) = config%getFloat('atol_gamma',defaultVal=1.0e-6_pReal)
if(any(plasticState(p)%atol(startIndex:endIndex) < 0.0_pReal)) extmsg = trim(extmsg)//' atol_gamma'
! global alias
plasticState(p)%slipRate => plasticState(p)%dotState(startIndex:endIndex,:)
o = plasticState(p)%offsetDeltaState
startIndex = endIndex + 1
endIndex = endIndex + prm%totalNslip
endIndex = endIndex + prm%sum_N_sl
stt%sense => plasticState(p)%state (startIndex :endIndex ,:)
dlt%sense => plasticState(p)%deltaState(startIndex-o:endIndex-o,:)
startIndex = endIndex + 1
endIndex = endIndex + prm%totalNslip
endIndex = endIndex + prm%sum_N_sl
stt%chi0 => plasticState(p)%state (startIndex :endIndex ,:)
dlt%chi0 => plasticState(p)%deltaState(startIndex-o:endIndex-o,:)
startIndex = endIndex + 1
endIndex = endIndex + prm%totalNslip
endIndex = endIndex + prm%sum_N_sl
stt%gamma0 => plasticState(p)%state (startIndex :endIndex ,:)
dlt%gamma0 => plasticState(p)%deltaState(startIndex-o:endIndex-o,:)
@ -224,8 +211,13 @@ module subroutine plastic_kinehardening_init
end associate
!--------------------------------------------------------------------------------------------------
! exit if any parameter is out of range
if (extmsg /= '') call IO_error(211,ext_msg=trim(extmsg)//'('//PLASTICITY_KINEHARDENING_LABEL//')')
enddo
end subroutine plastic_kinehardening_init
@ -247,7 +239,7 @@ pure module subroutine plastic_kinehardening_LpAndItsTangent(Lp,dLp_dMp,Mp,insta
integer :: &
i,k,l,m,n
real(pReal), dimension(param(instance)%totalNslip) :: &
real(pReal), dimension(param(instance)%sum_N_sl) :: &
gdot_pos,gdot_neg, &
dgdot_dtau_pos,dgdot_dtau_neg
@ -258,12 +250,12 @@ pure module subroutine plastic_kinehardening_LpAndItsTangent(Lp,dLp_dMp,Mp,insta
call kinetics(Mp,instance,of,gdot_pos,gdot_neg,dgdot_dtau_pos,dgdot_dtau_neg)
do i = 1, prm%totalNslip
Lp = Lp + (gdot_pos(i)+gdot_neg(i))*prm%Schmid(1:3,1:3,i)
do i = 1, prm%sum_N_sl
Lp = Lp + (gdot_pos(i)+gdot_neg(i))*prm%P(1:3,1:3,i)
forall (k=1:3,l=1:3,m=1:3,n=1:3) &
dLp_dMp(k,l,m,n) = dLp_dMp(k,l,m,n) &
+ dgdot_dtau_pos(i) * prm%Schmid(k,l,i) * prm%nonSchmid_pos(m,n,i) &
+ dgdot_dtau_neg(i) * prm%Schmid(k,l,i) * prm%nonSchmid_neg(m,n,i)
+ dgdot_dtau_pos(i) * prm%P(k,l,i) * prm%nonSchmid_pos(m,n,i) &
+ dgdot_dtau_neg(i) * prm%P(k,l,i) * prm%nonSchmid_neg(m,n,i)
enddo
end associate
@ -284,7 +276,7 @@ module subroutine plastic_kinehardening_dotState(Mp,instance,of)
real(pReal) :: &
sumGamma
real(pReal), dimension(param(instance)%totalNslip) :: &
real(pReal), dimension(param(instance)%sum_N_sl) :: &
gdot_pos,gdot_neg
@ -324,7 +316,7 @@ module subroutine plastic_kinehardening_deltaState(Mp,instance,of)
instance, &
of
real(pReal), dimension(param(instance)%totalNslip) :: &
real(pReal), dimension(param(instance)%sum_N_sl) :: &
gdot_pos,gdot_neg, &
sense
@ -375,22 +367,22 @@ module subroutine plastic_kinehardening_results(instance,group)
outputsLoop: do o = 1,size(prm%output)
select case(trim(prm%output(o)))
case('resistance')
if(prm%totalNslip>0) call results_writeDataset(group,stt%crss,'xi_sl', &
if(prm%sum_N_sl>0) call results_writeDataset(group,stt%crss,'xi_sl', &
'resistance against plastic slip','Pa')
case('backstress') ! ToDo: should be 'tau_back'
if(prm%totalNslip>0) call results_writeDataset(group,stt%crss_back,'tau_back', &
if(prm%sum_N_sl>0) call results_writeDataset(group,stt%crss_back,'tau_back', &
'back stress against plastic slip','Pa')
case ('sense')
if(prm%totalNslip>0) call results_writeDataset(group,stt%sense,'sense_of_shear', &
if(prm%sum_N_sl>0) call results_writeDataset(group,stt%sense,'sense_of_shear', &
'tbd','1')
case ('chi0')
if(prm%totalNslip>0) call results_writeDataset(group,stt%chi0,'chi0', &
if(prm%sum_N_sl>0) call results_writeDataset(group,stt%chi0,'chi0', &
'tbd','Pa')
case ('gamma0')
if(prm%totalNslip>0) call results_writeDataset(group,stt%gamma0,'gamma0', &
if(prm%sum_N_sl>0) call results_writeDataset(group,stt%gamma0,'gamma0', &
'tbd','1')
case ('accumulatedshear')
if(prm%totalNslip>0) call results_writeDataset(group,stt%accshear,'gamma_sl', &
if(prm%sum_N_sl>0) call results_writeDataset(group,stt%accshear,'gamma_sl', &
'plastic shear','1')
end select
enddo outputsLoop
@ -415,31 +407,28 @@ pure subroutine kinetics(Mp,instance,of, &
instance, &
of
real(pReal), intent(out), dimension(param(instance)%totalNslip) :: &
real(pReal), intent(out), dimension(param(instance)%sum_N_sl) :: &
gdot_pos, &
gdot_neg
real(pReal), intent(out), optional, dimension(param(instance)%totalNslip) :: &
real(pReal), intent(out), optional, dimension(param(instance)%sum_N_sl) :: &
dgdot_dtau_pos, &
dgdot_dtau_neg
real(pReal), dimension(param(instance)%totalNslip) :: &
real(pReal), dimension(param(instance)%sum_N_sl) :: &
tau_pos, &
tau_neg
integer :: i
logical :: nonSchmidActive
associate(prm => param(instance), stt => state(instance))
nonSchmidActive = size(prm%nonSchmidCoeff) > 0
do i = 1, prm%totalNslip
tau_pos(i) = math_mul33xx33(Mp,prm%nonSchmid_pos(1:3,1:3,i)) - stt%crss_back(i,of)
tau_neg(i) = merge(math_mul33xx33(Mp,prm%nonSchmid_neg(1:3,1:3,i)) - stt%crss_back(i,of), &
0.0_pReal, nonSchmidActive)
do i = 1, prm%sum_N_sl
tau_pos(i) = math_tensordot(Mp,prm%nonSchmid_pos(1:3,1:3,i)) - stt%crss_back(i,of)
tau_neg(i) = merge(math_tensordot(Mp,prm%nonSchmid_neg(1:3,1:3,i)) - stt%crss_back(i,of), &
0.0_pReal, prm%nonSchmidActive)
enddo
where(dNeq0(tau_pos))
gdot_pos = prm%gdot0 * merge(0.5_pReal,1.0_pReal, nonSchmidActive) & ! 1/2 if non-Schmid active
gdot_pos = prm%gdot0 * merge(0.5_pReal,1.0_pReal, prm%nonSchmidActive) & ! 1/2 if non-Schmid active
* sign(abs(tau_pos/stt%crss(:,of))**prm%n, tau_pos)
else where
gdot_pos = 0.0_pReal

View File

@ -19,7 +19,7 @@ module subroutine plastic_none_init
p, &
NipcMyPhase
write(6,'(/,a)') ' <<<+- plastic_'//PLASTICITY_NONE_label//' init -+>>>'; flush(6)
write(6,'(/,a)') ' <<<+- plastic_'//PLASTICITY_NONE_LABEL//' init -+>>>'; flush(6)
Ninstance = count(phase_plasticity == PLASTICITY_NONE_ID)
if (iand(debug_level(debug_constitutive),debug_levelBasic) /= 0) &

File diff suppressed because it is too large Load Diff

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