Merge remote-tracking branch 'origin/development' into MiscImprovements

This commit is contained in:
Martin Diehl 2020-02-25 17:33:39 +01:00
commit 48604292e2
23 changed files with 2353 additions and 2440 deletions

@ -1 +1 @@
Subproject commit ec615d249d39e5d01446b01ab9a5b7e7601340ad
Subproject commit 6db5f4666fc651b4de3b44ceaed3f2b848170ac9

View File

@ -1 +1 @@
v2.0.3-1732-gab88ffd2
v2.0.3-1747-ga2e8e5b1

View File

@ -42,8 +42,8 @@ for name in filenames:
table = damask.Table.from_ASCII(StringIO(''.join(sys.stdin.read())) if name is None else name)
table.add('Cauchy',
damask.mechanics.Cauchy(table.get(options.defgrad).reshape(-1,3,3),
table.get(options.stress ).reshape(-1,3,3)).reshape(-1,9),
damask.mechanics.Cauchy(table.get(options.stress ).reshape(-1,3,3),
table.get(options.defgrad).reshape(-1,3,3)).reshape(-1,9),
scriptID+' '+' '.join(sys.argv[1:]))
table.to_ASCII(sys.stdout if name is None else name)

View File

@ -43,8 +43,8 @@ for name in filenames:
table = damask.Table.from_ASCII(StringIO(''.join(sys.stdin.read())) if name is None else name)
table.add('S',
damask.mechanics.PK2(table.get(options.defgrad).reshape(-1,3,3),
table.get(options.stress ).reshape(-1,3,3)).reshape(-1,9),
damask.mechanics.PK2(table.get(options.stress ).reshape(-1,3,3),
table.get(options.defgrad).reshape(-1,3,3)).reshape(-1,9),
scriptID+' '+' '.join(sys.argv[1:]))
table.to_ASCII(sys.stdout if name is None else name)

View File

@ -2,6 +2,7 @@
import os
import sys
from io import StringIO
from optparse import OptionParser
import numpy as np
@ -33,69 +34,27 @@ parser.add_option('--no-check',
parser.set_defaults(rh = True,
)
(options,filenames) = parser.parse_args()
if options.tensor is None:
parser.error('no data column specified.')
# --- loop over input files -------------------------------------------------------------------------
if filenames == []: filenames = [None]
for name in filenames:
try:
table = damask.ASCIItable(name = name,
buffered = False)
except: continue
damask.util.report(scriptName,name)
# ------------------------------------------ read header ------------------------------------------
table = damask.Table.from_ASCII(StringIO(''.join(sys.stdin.read())) if name is None else name)
table.head_read()
for tensor in options.tensor:
t = table.get(tensor).reshape(-1,3,3)
(u,v) = np.linalg.eigh(damask.mechanics.symmetric(t))
if options.rh: v[np.linalg.det(v) < 0.0,:,2] *= -1.0
# ------------------------------------------ assemble header 1 ------------------------------------
for i,o in enumerate(['Min','Mid','Max']):
table.add('eigval{}({})'.format(o,tensor),u[:,i],
scriptID+' '+' '.join(sys.argv[1:]))
items = {
'tensor': {'dim': 9, 'shape': [3,3], 'labels':options.tensor, 'column': []},
}
errors = []
remarks = []
for i,o in enumerate(['Min','Mid','Max']):
table.add('eigvec{}({})'.format(o,tensor),v[:,:,i],
scriptID+' '+' '.join(sys.argv[1:]))
for type, data in items.items():
for what in data['labels']:
dim = table.label_dimension(what)
if dim != data['dim']: remarks.append('column {} is not a {}...'.format(what,type))
else:
items[type]['column'].append(table.label_index(what))
for order in ['Min','Mid','Max']:
table.labels_append(['eigval{}({})'.format(order,what)]) # extend ASCII header with new labels
for order in ['Min','Mid','Max']:
table.labels_append(['{}_eigvec{}({})'.format(i+1,order,what) for i in range(3)]) # extend ASCII header with new labels
if remarks != []: damask.util.croak(remarks)
if errors != []:
damask.util.croak(errors)
table.close(dismiss = True)
continue
# ------------------------------------------ assemble header 2 ------------------------------------
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 type, data in items.items():
for column in data['column']:
(u,v) = np.linalg.eigh(np.array(list(map(float,table.data[column:column+data['dim']]))).reshape(data['shape']))
if options.rh and np.dot(np.cross(v[:,0], v[:,1]), v[:,2]) < 0.0 : v[:, 2] *= -1.0 # ensure right-handed eigenvector basis
table.data_append(list(u)) # vector of max,mid,min eigval
table.data_append(list(v.transpose().reshape(data['dim']))) # 3x3=9 combo vector of max,mid,min eigvec coordinates
outputAlive = table.data_write() # output processed line in accordance with column labeling
# ------------------------------------------ output finalization -----------------------------------
table.close() # close input ASCII table (works for stdin)
table.to_ASCII(sys.stdout if name is None else name)

View File

@ -15,6 +15,7 @@ from .config import Material # noqa
from .colormaps import Colormap, Color # noqa
from .orientation import Symmetry, Lattice, Rotation, Orientation # noqa
from .dadf5 import DADF5 # noqa
from .dadf5 import DADF5 as Result # noqa
from .geom import Geom # noqa
from .solver import Solver # noqa

View File

@ -11,8 +11,11 @@ import numpy as np
from . import util
from . import version
from . import mechanics
from . import Rotation
from . import Orientation
from . import Environment
from . import grid_filters
# ------------------------------------------------------------------
class DADF5():
"""
Read and write to DADF5 files.
@ -20,7 +23,6 @@ class DADF5():
DADF5 files contain DAMASK results.
"""
# ------------------------------------------------------------------
def __init__(self,fname):
"""
Opens an existing DADF5 file.
@ -72,10 +74,9 @@ class DADF5():
self.mat_physics += f['/'.join([self.increments[0],'materialpoint',m])].keys()
self.mat_physics = list(set(self.mat_physics)) # make unique
self.visible= {'increments': self.increments,
self.selection= {'increments': self.increments,
'constituents': self.constituents,
'materialpoints': self.materialpoints,
'constituent': range(self.Nconstituents), # ToDo: stupid naming
'con_physics': self.con_physics,
'mat_physics': self.mat_physics}
@ -92,7 +93,7 @@ class DADF5():
name of datasets as list, supports ? and * wildcards.
True is equivalent to [*], False is equivalent to []
what : str
attribute to change (must be in self.visible)
attribute to change (must be in self.selection)
action : str
select from 'set', 'add', and 'del'
@ -105,15 +106,18 @@ class DADF5():
choice = [datasets] if isinstance(datasets,str) else datasets
valid = [e for e_ in [glob.fnmatch.filter(getattr(self,what),s) for s in choice] for e in e_]
existing = set(self.visible[what])
existing = set(self.selection[what])
if action == 'set':
self.visible[what] = valid
self.selection[what] = valid
elif action == 'add':
self.visible[what] = list(existing.union(valid))
add=existing.union(valid)
add_sorted=sorted(add, key=lambda x: int("".join([i for i in x if i.isdigit()])))
self.selection[what] = add_sorted
elif action == 'del':
self.visible[what] = list(existing.difference_update(valid))
diff=existing.difference(valid)
diff_sorted=sorted(diff, key=lambda x: int("".join([i for i in x if i.isdigit()])))
self.selection[what] = diff_sorted
def __time_to_inc(self,start,end):
selected = []
@ -229,17 +233,17 @@ class DADF5():
Parameters
----------
what : str
attribute to change (must be in self.visible)
attribute to change (must be in self.selection)
"""
datasets = self.visible[what]
datasets = self.selection[what]
last_datasets = datasets.copy()
for dataset in datasets:
if last_datasets != self.visible[what]:
if last_datasets != self.selection[what]:
self.__manage_visible(datasets,what,'set')
raise Exception
self.__manage_visible(dataset,what,'set')
last_datasets = self.visible[what]
last_datasets = self.selection[what]
yield dataset
self.__manage_visible(datasets,what,'set')
@ -254,7 +258,7 @@ class DADF5():
name of datasets as list, supports ? and * wildcards.
True is equivalent to [*], False is equivalent to []
what : str
attribute to change (must be in self.visible)
attribute to change (must be in self.selection)
"""
self.__manage_visible(datasets,what,'set')
@ -270,7 +274,7 @@ class DADF5():
name of datasets as list, supports ? and * wildcards.
True is equivalent to [*], False is equivalent to []
what : str
attribute to change (must be in self.visible)
attribute to change (must be in self.selection)
"""
self.__manage_visible(datasets,what,'add')
@ -278,7 +282,7 @@ class DADF5():
def del_visible(self,what,datasets):
"""
Delete from active groupse.
Delete from active groupe.
Parameters
----------
@ -286,7 +290,7 @@ class DADF5():
name of datasets as list, supports ? and * wildcards.
True is equivalent to [*], False is equivalent to []
what : str
attribute to change (must be in self.visible)
attribute to change (must be in self.selection)
"""
self.__manage_visible(datasets,what,'del')
@ -351,7 +355,8 @@ class DADF5():
for d in f[group].keys():
try:
dataset = f['/'.join([group,d])]
message+=' {} / ({}): {}\n'.format(d,dataset.attrs['Unit'].decode(),dataset.attrs['Description'].decode())
message+=' {} / ({}): {}\n'.\
format(d,dataset.attrs['Unit'].decode(),dataset.attrs['Description'].decode())
except KeyError:
pass
return message
@ -435,12 +440,7 @@ class DADF5():
def cell_coordinates(self):
"""Return initial coordinates of the cell centers."""
if self.structured:
delta = self.size/self.grid*0.5
z, y, x = np.meshgrid(np.linspace(delta[2],self.size[2]-delta[2],self.grid[2]),
np.linspace(delta[1],self.size[1]-delta[1],self.grid[1]),
np.linspace(delta[0],self.size[0]-delta[0],self.grid[0]),
)
return np.concatenate((x[:,:,:,None],y[:,:,:,None],z[:,:,:,None]),axis = 3).reshape([np.product(self.grid),3])
return grid_filters.cell_coord0(self.grid,self.size,self.origin)
else:
with h5py.File(self.fname,'r') as f:
return f['geometry/x_c'][()]
@ -453,10 +453,10 @@ class DADF5():
Parameters
----------
x : str
Label of the dataset containing a scalar, vector, or tensor.
Label of scalar, vector, or tensor dataset to take absolute value of.
"""
def __add_absolute(x):
def _add_absolute(x):
return {
'data': np.abs(x['data']),
@ -468,33 +468,31 @@ class DADF5():
}
}
requested = [{'label':x,'arg':'x'}]
self.__add_generic_pointwise(__add_absolute,requested)
self.__add_generic_pointwise(_add_absolute,{'x':x})
def add_calculation(self,formula,label,unit='n/a',description=None,vectorized=True):
def add_calculation(self,label,formula,unit='n/a',description=None,vectorized=True):
"""
Add result of a general formula.
Parameters
----------
formula : str
Formula, refer to datasets by #Label#.
label : str
Label of the dataset containing the result of the calculation.
Label of resulting dataset.
formula : str
Formula to calculate resulting dataset. Existing datasets are referenced by #TheirLabel#.
unit : str, optional
Physical unit of the result.
description : str, optional
Human readable description of the result.
Human-readable description of the result.
vectorized : bool, optional
Indicate whether the formula is written in vectorized form. Default is True.
Indicate whether the formula can be used in vectorized form. Defaults to True.
"""
if vectorized is False:
if not vectorized:
raise NotImplementedError
def __add_calculation(**kwargs):
def _add_calculation(**kwargs):
formula = kwargs['formula']
for d in re.findall(r'#(.*?)#',formula):
@ -510,154 +508,233 @@ class DADF5():
}
}
requested = [{'label':d,'arg':d} for d in set(re.findall(r'#(.*?)#',formula))] # datasets used in the formula
pass_through = {'formula':formula,'label':label,'unit':unit,'description':description}
dataset_mapping = {d:d for d in set(re.findall(r'#(.*?)#',formula))} # datasets used in the formula
args = {'formula':formula,'label':label,'unit':unit,'description':description}
self.__add_generic_pointwise(__add_calculation,requested,pass_through)
self.__add_generic_pointwise(_add_calculation,dataset_mapping,args)
def add_Cauchy(self,P='P',F='F'):
"""
Add Cauchy stress calculated from 1. Piola-Kirchhoff stress and deformation gradient.
Add Cauchy stress calculated from first Piola-Kirchhoff stress and deformation gradient.
Parameters
----------
P : str, optional
Label of the dataset containing the 1. Piola-Kirchhoff stress. Default value is P.
Label of the dataset containing the first Piola-Kirchhoff stress. Defaults to P.
F : str, optional
Label of the dataset containing the deformation gradient. Default value is F.
Label of the dataset containing the deformation gradient. Defaults to F.
"""
def __add_Cauchy(F,P):
def _add_Cauchy(P,F):
return {
'data': mechanics.Cauchy(F['data'],P['data']),
'data': mechanics.Cauchy(P['data'],F['data']),
'label': 'sigma',
'meta': {
'Unit': P['meta']['Unit'],
'Description': 'Cauchy stress calculated from {} ({}) '.format(P['label'],P['meta']['Description'])+\
'and deformation gradient {} ({})'.format(F['label'],F['meta']['Description']),
'Description': 'Cauchy stress calculated from {} ({}) '.format(P['label'],
P['meta']['Description'])+\
'and {} ({})'.format(F['label'],F['meta']['Description']),
'Creator': 'dadf5.py:add_Cauchy v{}'.format(version)
}
}
requested = [{'label':F,'arg':'F'},
{'label':P,'arg':'P'} ]
self.__add_generic_pointwise(__add_Cauchy,requested)
self.__add_generic_pointwise(_add_Cauchy,{'P':P,'F':F})
def add_determinant(self,x):
def add_determinant(self,T):
"""
Add the determinant of a tensor.
Parameters
----------
x : str
Label of the dataset containing a tensor.
T : str
Label of tensor dataset.
"""
def __add_determinant(x):
def _add_determinant(T):
return {
'data': np.linalg.det(x['data']),
'label': 'det({})'.format(x['label']),
'data': np.linalg.det(T['data']),
'label': 'det({})'.format(T['label']),
'meta': {
'Unit': x['meta']['Unit'],
'Description': 'Determinant of tensor {} ({})'.format(x['label'],x['meta']['Description']),
'Unit': T['meta']['Unit'],
'Description': 'Determinant of tensor {} ({})'.format(T['label'],T['meta']['Description']),
'Creator': 'dadf5.py:add_determinant v{}'.format(version)
}
}
requested = [{'label':x,'arg':'x'}]
self.__add_generic_pointwise(__add_determinant,requested)
self.__add_generic_pointwise(_add_determinant,{'T':T})
def add_deviator(self,x):
def add_deviator(self,T):
"""
Add the deviatoric part of a tensor.
Parameters
----------
x : str
Label of the dataset containing a tensor.
T : str
Label of tensor dataset.
"""
def __add_deviator(x):
def _add_deviator(T):
if not np.all(np.array(x['data'].shape[1:]) == np.array([3,3])):
if not np.all(np.array(T['data'].shape[1:]) == np.array([3,3])):
raise ValueError
return {
'data': mechanics.deviatoric_part(x['data']),
'label': 's_{}'.format(x['label']),
'data': mechanics.deviatoric_part(T['data']),
'label': 's_{}'.format(T['label']),
'meta': {
'Unit': x['meta']['Unit'],
'Description': 'Deviator of tensor {} ({})'.format(x['label'],x['meta']['Description']),
'Unit': T['meta']['Unit'],
'Description': 'Deviator of tensor {} ({})'.format(T['label'],T['meta']['Description']),
'Creator': 'dadf5.py:add_deviator v{}'.format(version)
}
}
requested = [{'label':x,'arg':'x'}]
self.__add_generic_pointwise(__add_deviator,requested)
self.__add_generic_pointwise(_add_deviator,{'T':T})
def add_maximum_shear(self,x):
def add_eigenvalues(self,S):
"""
Add eigenvalues of symmetric tensor.
Parameters
----------
S : str
Label of symmetric tensor dataset.
"""
def _add_eigenvalue(S):
return {
'data': mechanics.eigenvalues(S['data']),
'label': 'lambda({})'.format(S['label']),
'meta' : {
'Unit': S['meta']['Unit'],
'Description': 'Eigenvalues of {} ({})'.format(S['label'],S['meta']['Description']),
'Creator': 'dadf5.py:add_eigenvalues v{}'.format(version)
}
}
self.__add_generic_pointwise(_add_eigenvalue,{'S':S})
def add_eigenvectors(self,S):
"""
Add eigenvectors of symmetric tensor.
Parameters
----------
S : str
Label of symmetric tensor dataset.
"""
def _add_eigenvector(S):
return {
'data': mechanics.eigenvectors(S['data']),
'label': 'v({})'.format(S['label']),
'meta' : {
'Unit': '1',
'Description': 'Eigenvectors of {} ({})'.format(S['label'],S['meta']['Description']),
'Creator': 'dadf5.py:add_eigenvectors v{}'.format(version)
}
}
self.__add_generic_pointwise(_add_eigenvector,{'S':S})
def add_IPFcolor(self,q,l):
"""
Add RGB color tuple of inverse pole figure (IPF) color.
Parameters
----------
q : str
Label of the dataset containing the crystallographic orientation as quaternions.
l : numpy.array of shape (3)
Lab frame direction for inverse pole figure.
"""
def _add_IPFcolor(q,l):
d = np.array(l)
d_unit = d/np.linalg.norm(d)
m = util.scale_to_coprime(d)
colors = np.empty((len(q['data']),3),np.uint8)
lattice = q['meta']['Lattice']
for i,q in enumerate(q['data']):
o = Orientation(np.array([q['w'],q['x'],q['y'],q['z']]),lattice).reduced()
colors[i] = np.uint8(o.IPFcolor(d_unit)*255)
return {
'data': colors,
'label': 'IPFcolor_[{} {} {}]'.format(*m),
'meta' : {
'Unit': 'RGB (8bit)',
'Lattice': lattice,
'Description': 'Inverse Pole Figure (IPF) colors for direction/plane [{} {} {})'.format(*m),
'Creator': 'dadf5.py:add_IPFcolor v{}'.format(version)
}
}
self.__add_generic_pointwise(_add_IPFcolor,{'q':q},{'l':l})
def add_maximum_shear(self,S):
"""
Add maximum shear components of symmetric tensor.
Parameters
----------
x : str
Label of the dataset containing a symmetric tensor.
S : str
Label of symmetric tensor dataset.
"""
def __add_maximum_shear(x):
def _add_maximum_shear(S):
return {
'data': mechanics.maximum_shear(x['data']),
'label': 'max_shear({})'.format(x['label']),
'data': mechanics.maximum_shear(S['data']),
'label': 'max_shear({})'.format(S['label']),
'meta': {
'Unit': x['meta']['Unit'],
'Description': 'Maximum shear component of of {} ({})'.format(x['label'],x['meta']['Description']),
'Unit': S['meta']['Unit'],
'Description': 'Maximum shear component of {} ({})'.format(S['label'],S['meta']['Description']),
'Creator': 'dadf5.py:add_maximum_shear v{}'.format(version)
}
}
requested = [{'label':x,'arg':'x'}]
self.__add_generic_pointwise(__add_maximum_shear,requested)
self.__add_generic_pointwise(_add_maximum_shear,{'S':S})
def add_Mises(self,x):
def add_Mises(self,S):
"""
Add the equivalent Mises stress or strain of a symmetric tensor.
Parameters
----------
x : str
Label of the dataset containing a symmetric stress or strain tensor.
S : str
Label of symmetric tensorial stress or strain dataset.
"""
def __add_Mises(x):
def _add_Mises(S):
t = 'strain' if x['meta']['Unit'] == '1' else \
t = 'strain' if S['meta']['Unit'] == '1' else \
'stress'
return {
'data': mechanics.Mises_strain(x['data']) if t=='strain' else mechanics.Mises_stress(x['data']),
'label': '{}_vM'.format(x['label']),
'data': mechanics.Mises_strain(S['data']) if t=='strain' else mechanics.Mises_stress(S['data']),
'label': '{}_vM'.format(S['label']),
'meta': {
'Unit': x['meta']['Unit'],
'Description': 'Mises equivalent {} of {} ({})'.format(t,x['label'],x['meta']['Description']),
'Unit': S['meta']['Unit'],
'Description': 'Mises equivalent {} of {} ({})'.format(t,S['label'],S['meta']['Description']),
'Creator': 'dadf5.py:add_Mises v{}'.format(version)
}
}
requested = [{'label':x,'arg':'x'}]
self.__add_generic_pointwise(__add_Mises,requested)
self.__add_generic_pointwise(_add_Mises,{'S':S})
def add_norm(self,x,ord=None):
@ -667,12 +744,12 @@ class DADF5():
Parameters
----------
x : str
Label of the dataset containing a vector or tensor.
Label of vector or tensor dataset.
ord : {non-zero int, inf, -inf, fro, nuc}, optional
Order of the norm. inf means numpys inf object. For details refer to numpy.linalg.norm.
Order of the norm. inf means NumPys inf object. For details refer to numpy.linalg.norm.
"""
def __add_norm(x,ord):
def _add_norm(x,ord):
o = ord
if len(x['data'].shape) == 2:
@ -691,93 +768,155 @@ class DADF5():
'label': '|{}|_{}'.format(x['label'],o),
'meta': {
'Unit': x['meta']['Unit'],
'Description': '{}-Norm of {} {} ({})'.format(ord,t,x['label'],x['meta']['Description']),
'Description': '{}-norm of {} {} ({})'.format(ord,t,x['label'],x['meta']['Description']),
'Creator': 'dadf5.py:add_norm v{}'.format(version)
}
}
requested = [{'label':x,'arg':'x'}]
self.__add_generic_pointwise(__add_norm,requested,{'ord':ord})
self.__add_generic_pointwise(_add_norm,{'x':x},{'ord':ord})
def add_principal_components(self,x):
def add_PK2(self,P='P',F='F'):
"""
Add principal components of symmetric tensor.
The principal components are sorted in descending order, each repeated according to its multiplicity.
Add 2. Piola-Kirchhoff calculated from first Piola-Kirchhoff stress and deformation gradient.
Parameters
----------
x : str
Label of the dataset containing a symmetric tensor.
P : str, optional
Label first Piola-Kirchhoff stress dataset. Defaults to P.
F : str, optional
Label of deformation gradient dataset. Defaults to F.
"""
def __add_principal_components(x):
def _add_PK2(P,F):
return {
'data': mechanics.principal_components(x['data']),
'label': 'lambda_{}'.format(x['label']),
'data': mechanics.PK2(P['data'],F['data']),
'label': 'S',
'meta': {
'Unit': x['meta']['Unit'],
'Description': 'Pricipal components of {} ({})'.format(x['label'],x['meta']['Description']),
'Creator': 'dadf5.py:add_principal_components v{}'.format(version)
'Unit': P['meta']['Unit'],
'Description': '2. Kirchhoff stress calculated from {} ({}) '.format(P['label'],
P['meta']['Description'])+\
'and {} ({})'.format(F['label'],F['meta']['Description']),
'Creator': 'dadf5.py:add_PK2 v{}'.format(version)
}
}
requested = [{'label':x,'arg':'x'}]
self.__add_generic_pointwise(__add_principal_components,requested)
self.__add_generic_pointwise(_add_PK2,{'P':P,'F':F})
def add_spherical(self,x):
def add_pole(self,q,p,polar=False):
"""
Add coordinates of stereographic projection of given pole in crystal frame.
Parameters
----------
q : str
Label of the dataset containing the crystallographic orientation as quaternions.
p : numpy.array of shape (3)
Crystallographic direction or plane.
polar : bool, optional
Give pole in polar coordinates. Defaults to False.
"""
def _add_pole(q,p,polar):
pole = np.array(p)
unit_pole = pole/np.linalg.norm(pole)
m = util.scale_to_coprime(pole)
coords = np.empty((len(q['data']),2))
for i,q in enumerate(q['data']):
o = Rotation(np.array([q['w'],q['x'],q['y'],q['z']]))
rotatedPole = o*unit_pole # rotate pole according to crystal orientation
(x,y) = rotatedPole[0:2]/(1.+abs(unit_pole[2])) # stereographic projection
coords[i] = [np.sqrt(x*x+y*y),np.arctan2(y,x)] if polar else [x,y]
return {
'data': coords,
'label': 'p^{}_[{} {} {})'.format(u'' if polar else 'xy',*m),
'meta' : {
'Unit': '1',
'Description': '{} coordinates of stereographic projection of pole (direction/plane) in crystal frame'\
.format('Polar' if polar else 'Cartesian'),
'Creator' : 'dadf5.py:add_pole v{}'.format(version)
}
}
self.__add_generic_pointwise(_add_pole,{'q':q},{'p':p,'polar':polar})
def add_rotational_part(self,F):
"""
Add rotational part of a deformation gradient.
Parameters
----------
F : str, optional
Label of deformation gradient dataset.
"""
def _add_rotational_part(F):
return {
'data': mechanics.rotational_part(F['data']),
'label': 'R({})'.format(F['label']),
'meta': {
'Unit': F['meta']['Unit'],
'Description': 'Rotational part of {} ({})'.format(F['label'],F['meta']['Description']),
'Creator': 'dadf5.py:add_rotational_part v{}'.format(version)
}
}
self.__add_generic_pointwise(_add_rotational_part,{'F':F})
def add_spherical(self,T):
"""
Add the spherical (hydrostatic) part of a tensor.
Parameters
----------
x : str
Label of the dataset containing a tensor.
T : str
Label of tensor dataset.
"""
def __add_spherical(x):
def _add_spherical(T):
if not np.all(np.array(x['data'].shape[1:]) == np.array([3,3])):
if not np.all(np.array(T['data'].shape[1:]) == np.array([3,3])):
raise ValueError
return {
'data': mechanics.spherical_part(x['data']),
'label': 'p_{}'.format(x['label']),
'data': mechanics.spherical_part(T['data']),
'label': 'p_{}'.format(T['label']),
'meta': {
'Unit': x['meta']['Unit'],
'Description': 'Spherical component of tensor {} ({})'.format(x['label'],x['meta']['Description']),
'Unit': T['meta']['Unit'],
'Description': 'Spherical component of tensor {} ({})'.format(T['label'],T['meta']['Description']),
'Creator': 'dadf5.py:add_spherical v{}'.format(version)
}
}
requested = [{'label':x,'arg':'x'}]
self.__add_generic_pointwise(__add_spherical,requested)
self.__add_generic_pointwise(_add_spherical,{'T':T})
def add_strain_tensor(self,F='F',t='U',m=0):
def add_strain_tensor(self,F='F',t='V',m=0.0):
"""
Add strain tensor calculated from a deformation gradient.
Add strain tensor of a deformation gradient.
For details refer to damask.mechanics.strain_tensor
Parameters
----------
F : str, optional
Label of the dataset containing the deformation gradient. Default value is F.
Label of deformation gradient dataset. Defaults to F.
t : {V, U}, optional
Type of the polar decomposition, V for right stretch tensor and U for left stretch tensor.
Defaults value is U.
Type of the polar decomposition, V for left stretch tensor and U for right stretch tensor.
Defaults to V.
m : float, optional
Order of the strain calculation. Default value is 0.0.
Order of the strain calculation. Defaults to 0.0.
"""
def __add_strain_tensor(F,t,m):
def _add_strain_tensor(F,t,m):
return {
'data': mechanics.strain_tensor(F['data'],t,m),
@ -789,12 +928,39 @@ class DADF5():
}
}
requested = [{'label':F,'arg':'F'}]
self.__add_generic_pointwise(__add_strain_tensor,requested,{'t':t,'m':m})
self.__add_generic_pointwise(_add_strain_tensor,{'F':F},{'t':t,'m':m})
def __add_generic_pointwise(self,func,datasets_requested,extra_args={}):
def add_stretch_tensor(self,F='F',t='V'):
"""
Add stretch tensor of a deformation gradient.
Parameters
----------
F : str, optional
Label of deformation gradient dataset. Defaults to F.
t : {V, U}, optional
Type of the polar decomposition, V for left stretch tensor and U for right stretch tensor.
Defaults to V.
"""
def _add_stretch_tensor(F,t):
return {
'data': mechanics.left_stretch(F['data']) if t == 'V' else mechanics.right_stretch(F['data']),
'label': '{}({})'.format(t,F['label']),
'meta': {
'Unit': F['meta']['Unit'],
'Description': '{} stretch tensor of {} ({})'.format('Left' if t == 'V' else 'Right',
F['label'],F['meta']['Description']),
'Creator': 'dadf5.py:add_stretch_tensor v{}'.format(version)
}
}
self.__add_generic_pointwise(_add_stretch_tensor,{'F':F},{'t':t})
def __add_generic_pointwise(self,func,dataset_mapping,args={}):
"""
General function to add pointwise data.
@ -802,8 +968,8 @@ class DADF5():
----------
func : function
Function that calculates a new dataset from one or more datasets per HDF5 group.
datasets_requested : list of dictionaries
Details of the datasets to be used: label (in HDF5 file) and arg (argument to which the data is parsed in func).
dataset_mapping : dictionary
Mapping HDF5 data label to callback function argument
extra_args : dictionary, optional
Any extra arguments parsed to func.
@ -812,8 +978,9 @@ class DADF5():
"""Call function with input data + extra arguments, returns results + group."""
args['results'].put({**args['func'](**args['in']),'group':args['group']})
N_threads = 1 # ToDo: should be a parameter
env = Environment()
N_threads = int(env.options['DAMASK_NUM_THREADS'])
N_threads //=N_threads # disable for the moment
results = Queue(N_threads)
pool = util.ThreadPool(N_threads)
@ -821,16 +988,16 @@ class DADF5():
todo = []
# ToDo: It would be more memory efficient to read only from file when required, i.e. do to it in pool.add_task
for group in self.groups_with_datasets([d['label'] for d in datasets_requested]):
for group in self.groups_with_datasets(dataset_mapping.values()):
with h5py.File(self.fname,'r') as f:
datasets_in = {}
for d in datasets_requested:
loc = f[group+'/'+d['label']]
for arg,label in dataset_mapping.items():
loc = f[group+'/'+label]
data = loc[()]
meta = {k:loc.attrs[k].decode() for k in loc.attrs.keys()}
datasets_in[d['arg']] = {'data': data, 'meta' : meta, 'label' : d['label']}
datasets_in[arg] = {'data': data, 'meta': meta, 'label': label}
todo.append({'in':{**datasets_in,**extra_args},'func':func,'group':group,'results':results})
todo.append({'in':{**datasets_in,**args},'func':func,'group':group,'results':results})
pool.map(job, todo[:N_added]) # initialize
@ -850,7 +1017,7 @@ class DADF5():
pool.wait_completion()
def to_vtk(self,labels,mode='Cell'):
def to_vtk(self,labels,mode='cell'):
"""
Export to vtk cell/point data.
@ -858,12 +1025,12 @@ class DADF5():
----------
labels : str or list of
Labels of the datasets to be exported.
mode : str, either 'Cell' or 'Point'
mode : str, either 'cell' or 'point'
Export in cell format or point format.
Default value is 'Cell'.
Defaults to 'cell'.
"""
if mode=='Cell':
if mode.lower()=='cell':
if self.structured:
@ -908,7 +1075,7 @@ class DADF5():
for i in f['/geometry/T_c']:
vtk_geom.InsertNextCell(vtk_type,n_nodes,i-1)
elif mode == 'Point':
elif mode.lower()=='point':
Points = vtk.vtkPoints()
Vertices = vtk.vtkCellArray()
for c in self.cell_coordinates():
@ -926,7 +1093,7 @@ class DADF5():
for i,inc in enumerate(self.iter_visible('increments')):
vtk_data = []
materialpoints_backup = self.visible['materialpoints'].copy()
materialpoints_backup = self.selection['materialpoints'].copy()
self.set_visible('materialpoints',False)
for label in (labels if isinstance(labels,list) else [labels]):
for p in self.iter_visible('con_physics'):
@ -957,7 +1124,7 @@ class DADF5():
self.set_visible('materialpoints',materialpoints_backup)
constituents_backup = self.visible['constituents'].copy()
constituents_backup = self.selection['constituents'].copy()
self.set_visible('constituents',False)
for label in (labels if isinstance(labels,list) else [labels]):
for p in self.iter_visible('mat_physics'):
@ -984,7 +1151,7 @@ class DADF5():
vtk_geom.GetCellData().AddArray(vtk_data[-1])
self.set_visible('constituents',constituents_backup)
if mode=='Cell':
if mode.lower()=='cell':
writer = vtk.vtkXMLRectilinearGridWriter() if self.structured else \
vtk.vtkXMLUnstructuredGridWriter()
x = self.get_dataset_location('u_n')
@ -992,7 +1159,7 @@ class DADF5():
deep=True,array_type=vtk.VTK_DOUBLE))
vtk_data[-1].SetName('u')
vtk_geom.GetPointData().AddArray(vtk_data[-1])
elif mode == 'Point':
elif mode.lower()=='point':
writer = vtk.vtkXMLPolyDataWriter()

View File

@ -8,7 +8,7 @@ class Environment():
def __init__(self):
"""Read and provide values of DAMASK configuration."""
self.options = {}
self.get_options()
self.__get_options()
def relPath(self,relative = '.'):
return os.path.join(self.rootDir(),relative)
@ -16,7 +16,7 @@ class Environment():
def rootDir(self):
return os.path.normpath(os.path.join(os.path.realpath(__file__),'../../../'))
def get_options(self):
def __get_options(self):
for item in ['DAMASK_NUM_THREADS',
'MSC_ROOT',
'MARC_VERSION',

View File

@ -1,8 +1,8 @@
import numpy as np
def Cauchy(F,P):
def Cauchy(P,F):
"""
Return Cauchy stress calculated from 1. Piola-Kirchhoff stress and deformation gradient.
Return Cauchy stress calculated from first Piola-Kirchhoff stress and deformation gradient.
Resulting tensor is symmetrized as the Cauchy stress needs to be symmetric.
@ -21,23 +21,179 @@ def Cauchy(F,P):
return symmetric(sigma)
def PK2(F,P):
def deviatoric_part(x):
"""
Return 2. Piola-Kirchhoff stress calculated from 1. Piola-Kirchhoff stress and deformation gradient.
Return deviatoric part of a tensor.
Parameters
----------
x : numpy.array of shape (:,3,3) or (3,3)
Tensor of which the deviatoric part is computed.
"""
return x - np.eye(3)*spherical_part(x) if np.shape(x) == (3,3) else \
x - np.einsum('ijk,i->ijk',np.broadcast_to(np.eye(3),[x.shape[0],3,3]),spherical_part(x))
def eigenvalues(x):
"""
Return the eigenvalues, i.e. principal components, of a symmetric tensor.
The eigenvalues are sorted in ascending order, each repeated according to
its multiplicity.
Parameters
----------
x : numpy.array of shape (:,3,3) or (3,3)
Symmetric tensor of which the eigenvalues are computed.
"""
return np.linalg.eigvalsh(symmetric(x))
def eigenvectors(x,RHS=False):
"""
Return eigenvectors of a symmetric tensor.
The eigenvalues are sorted in ascending order of their associated eigenvalues.
Parameters
----------
x : numpy.array 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.
"""
(u,v) = np.linalg.eigh(symmetric(x))
if RHS:
if np.shape(x) == (3,3):
if np.linalg.det(v) < 0.0: v[:,2] *= -1.0
else:
v[np.linalg.det(v) < 0.0,:,2] *= -1.0
return v
def left_stretch(x):
"""
Return the left stretch of a tensor.
Parameters
----------
x : numpy.array of shape (:,3,3) or (3,3)
Tensor of which the left stretch is computed.
"""
return __polar_decomposition(x,'V')[0]
def maximum_shear(x):
"""
Return the maximum shear component of a symmetric tensor.
Parameters
----------
x : numpy.array of shape (:,3,3) or (3,3)
Symmetric tensor of which the maximum shear is computed.
"""
w = eigenvalues(x)
return (w[0] - w[2])*0.5 if np.shape(x) == (3,3) else \
(w[:,0] - w[:,2])*0.5
def Mises_strain(epsilon):
"""
Return the Mises equivalent of a strain tensor.
Parameters
----------
epsilon : numpy.array 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)
def Mises_stress(sigma):
"""
Return the Mises equivalent of a stress tensor.
Parameters
----------
sigma : numpy.array 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)
def PK2(P,F):
"""
Calculate second Piola-Kirchhoff stress from first Piola-Kirchhoff stress and deformation gradient.
Parameters
----------
F : numpy.array of shape (:,3,3) or (3,3)
Deformation gradient.
P : numpy.array of shape (:,3,3) or (3,3)
1. Piola-Kirchhoff stress.
F : numpy.array of shape (:,3,3) or (3,3)
Deformation gradient.
"""
if np.shape(F) == np.shape(P) == (3,3):
S = np.dot(np.linalg.inv(F),P)
else:
S = np.einsum('ijk,ikl->ijl',np.linalg.inv(F),P)
return S
return symmetric(S)
def right_stretch(x):
"""
Return the right stretch of a tensor.
Parameters
----------
x : numpy.array of shape (:,3,3) or (3,3)
Tensor of which the right stretch is computed.
"""
return __polar_decomposition(x,'U')[0]
def rotational_part(x):
"""
Return the rotational part of a tensor.
Parameters
----------
x : numpy.array of shape (:,3,3) or (3,3)
Tensor of which the rotational part is computed.
"""
return __polar_decomposition(x,'R')[0]
def spherical_part(x,tensor=False):
"""
Return spherical (hydrostatic) part of a tensor.
Parameters
----------
x : numpy.array 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
"""
if x.shape == (3,3):
sph = np.trace(x)/3.0
return sph if not tensor else np.eye(3)*sph
else:
sph = np.trace(x,axis1=1,axis2=2)/3.0
if not tensor:
return sph
else:
return np.einsum('ijk,i->ijk',np.broadcast_to(np.eye(3),(x.shape[0],3,3)),sph)
def strain_tensor(F,t,m):
@ -78,73 +234,6 @@ def strain_tensor(F,t,m):
eps
def deviatoric_part(x):
"""
Return deviatoric part of a tensor.
Parameters
----------
x : numpy.array of shape (:,3,3) or (3,3)
Tensor of which the deviatoric part is computed.
"""
return x - np.eye(3)*spherical_part(x) if np.shape(x) == (3,3) else \
x - np.einsum('ijk,i->ijk',np.broadcast_to(np.eye(3),[x.shape[0],3,3]),spherical_part(x))
def spherical_part(x,tensor=False):
"""
Return spherical (hydrostatic) part of a tensor.
Parameters
----------
x : numpy.array 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
"""
if x.shape == (3,3):
sph = np.trace(x)/3.0
return sph if not tensor else np.eye(3)*sph
else:
sph = np.trace(x,axis1=1,axis2=2)/3.0
if not tensor:
return sph
else:
return np.einsum('ijk,i->ijk',np.broadcast_to(np.eye(3),(x.shape[0],3,3)),sph)
def Mises_stress(sigma):
"""
Return the Mises equivalent of a stress tensor.
Parameters
----------
sigma : numpy.array of shape (:,3,3) or (3,3)
Symmetric stress tensor of which the von Mises equivalent is computed.
"""
s = deviatoric_part(sigma)
return np.sqrt(3.0/2.0*(np.sum(s**2.0))) if np.shape(sigma) == (3,3) else \
np.sqrt(3.0/2.0*np.einsum('ijk->i',s**2.0))
def Mises_strain(epsilon):
"""
Return the Mises equivalent of a strain tensor.
Parameters
----------
epsilon : numpy.array of shape (:,3,3) or (3,3)
Symmetric strain tensor of which the von Mises equivalent is computed.
"""
s = deviatoric_part(epsilon)
return np.sqrt(2.0/3.0*(np.sum(s**2.0))) if np.shape(epsilon) == (3,3) else \
np.sqrt(2.0/3.0*np.einsum('ijk->i',s**2.0))
def symmetric(x):
"""
Return the symmetrized tensor.
@ -158,39 +247,6 @@ def symmetric(x):
return (x+transpose(x))*0.5
def maximum_shear(x):
"""
Return the maximum shear component of a symmetric tensor.
Parameters
----------
x : numpy.array of shape (:,3,3) or (3,3)
Symmetric tensor of which the maximum shear is computed.
"""
w = np.linalg.eigvalsh(symmetric(x)) # eigenvalues in ascending order
return (w[2] - w[0])*0.5 if np.shape(x) == (3,3) else \
(w[:,2] - w[:,0])*0.5
def principal_components(x):
"""
Return the principal components of a symmetric tensor.
The principal components (eigenvalues) are sorted in descending order, each repeated according to
its multiplicity.
Parameters
----------
x : numpy.array of shape (:,3,3) or (3,3)
Symmetric tensor of which the principal compontents are computed.
"""
w = np.linalg.eigvalsh(symmetric(x)) # eigenvalues in ascending order
return w[::-1] if np.shape(x) == (3,3) else \
w[:,::-1]
def transpose(x):
"""
Return the transpose of a tensor.
@ -205,45 +261,6 @@ def transpose(x):
np.transpose(x,(0,2,1))
def rotational_part(x):
"""
Return the rotational part of a tensor.
Parameters
----------
x : numpy.array of shape (:,3,3) or (3,3)
Tensor of which the rotational part is computed.
"""
return __polar_decomposition(x,'R')[0]
def left_stretch(x):
"""
Return the left stretch of a tensor.
Parameters
----------
x : numpy.array of shape (:,3,3) or (3,3)
Tensor of which the left stretch is computed.
"""
return __polar_decomposition(x,'V')[0]
def right_stretch(x):
"""
Return the right stretch of a tensor.
Parameters
----------
x : numpy.array of shape (:,3,3) or (3,3)
Tensor of which the right stretch is computed.
"""
return __polar_decomposition(x,'U')[0]
def __polar_decomposition(x,requested):
"""
Singular value decomposition.
@ -270,3 +287,20 @@ def __polar_decomposition(x,requested):
output.append(np.dot(R.T,x) if np.shape(x) == (3,3) else np.einsum('ikj,ikl->ijl',R,x))
return tuple(output)
def __Mises(x,s):
"""
Base equation for Mises equivalent of a stres or strain tensor.
Parameters
----------
x : numpy.array 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).
"""
d = deviatoric_part(x)
return np.sqrt(s*(np.sum(d**2.0))) if np.shape(x) == (3,3) else \
np.sqrt(s*np.einsum('ijk->i',d**2.0))

View File

@ -3,10 +3,14 @@ import time
import os
import subprocess
import shlex
from fractions import Fraction
from functools import reduce
from optparse import Option
from queue import Queue
from threading import Thread
import numpy as np
class bcolors:
"""
ASCII Colors (Blender code).
@ -161,6 +165,24 @@ def progressBar(iteration, total, prefix='', bar_length=50):
sys.stderr.flush()
def scale_to_coprime(v):
"""Scale vector to co-prime (relatively prime) integers."""
MAX_DENOMINATOR = 1000
def get_square_denominator(x):
"""Denominator of the square of a number."""
return Fraction(x ** 2).limit_denominator(MAX_DENOMINATOR).denominator
def lcm(a, b):
"""Least common multiple."""
return a * b // np.gcd(a, b)
denominators = [int(get_square_denominator(i)) for i in v]
s = reduce(lcm, denominators) ** 0.5
m = (np.array(v)*s).astype(np.int)
return m//reduce(np.gcd,m)
class return_message():
"""Object with formatted return message."""

View File

@ -40,7 +40,7 @@ class TestDADF5:
assert np.allclose(in_memory,in_file)
def test_add_calculation(self,default):
default.add_calculation('2.0*np.abs(#F#)-1.0','x','-','test')
default.add_calculation('x','2.0*np.abs(#F#)-1.0','-','my notes')
loc = {'F': default.get_dataset_location('F'),
'x': default.get_dataset_location('x')}
in_memory = 2.0*np.abs(default.read_dataset(loc['F'],0))-1.0
@ -52,8 +52,8 @@ class TestDADF5:
loc = {'F': default.get_dataset_location('F'),
'P': default.get_dataset_location('P'),
'sigma':default.get_dataset_location('sigma')}
in_memory = mechanics.Cauchy(default.read_dataset(loc['F'],0),
default.read_dataset(loc['P'],0))
in_memory = mechanics.Cauchy(default.read_dataset(loc['P'],0),
default.read_dataset(loc['F'],0))
in_file = default.read_dataset(loc['sigma'],0)
assert np.allclose(in_memory,in_file)
@ -73,6 +73,54 @@ class TestDADF5:
in_file = default.read_dataset(loc['s_P'],0)
assert np.allclose(in_memory,in_file)
def test_add_eigenvalues(self,default):
default.add_Cauchy('P','F')
default.add_eigenvalues('sigma')
loc = {'sigma' :default.get_dataset_location('sigma'),
'lambda(sigma)':default.get_dataset_location('lambda(sigma)')}
in_memory = mechanics.eigenvalues(default.read_dataset(loc['sigma'],0))
in_file = default.read_dataset(loc['lambda(sigma)'],0)
assert np.allclose(in_memory,in_file)
def test_add_eigenvectors(self,default):
default.add_Cauchy('P','F')
default.add_eigenvectors('sigma')
loc = {'sigma' :default.get_dataset_location('sigma'),
'v(sigma)':default.get_dataset_location('v(sigma)')}
in_memory = mechanics.eigenvectors(default.read_dataset(loc['sigma'],0))
in_file = default.read_dataset(loc['v(sigma)'],0)
assert np.allclose(in_memory,in_file)
def test_add_maximum_shear(self,default):
default.add_Cauchy('P','F')
default.add_maximum_shear('sigma')
loc = {'sigma' :default.get_dataset_location('sigma'),
'max_shear(sigma)':default.get_dataset_location('max_shear(sigma)')}
in_memory = mechanics.maximum_shear(default.read_dataset(loc['sigma'],0)).reshape(-1,1)
in_file = default.read_dataset(loc['max_shear(sigma)'],0)
assert np.allclose(in_memory,in_file)
def test_add_Mises_strain(self,default):
t = ['V','U'][np.random.randint(0,2)]
m = np.random.random()*2.0 - 1.0
default.add_strain_tensor('F',t,m)
label = 'epsilon_{}^{}(F)'.format(t,m)
default.add_Mises(label)
loc = {label :default.get_dataset_location(label),
label+'_vM':default.get_dataset_location(label+'_vM')}
in_memory = mechanics.Mises_strain(default.read_dataset(loc[label],0)).reshape(-1,1)
in_file = default.read_dataset(loc[label+'_vM'],0)
assert np.allclose(in_memory,in_file)
def test_add_Mises_stress(self,default):
default.add_Cauchy('P','F')
default.add_Mises('sigma')
loc = {'sigma' :default.get_dataset_location('sigma'),
'sigma_vM':default.get_dataset_location('sigma_vM')}
in_memory = mechanics.Mises_stress(default.read_dataset(loc['sigma'],0)).reshape(-1,1)
in_file = default.read_dataset(loc['sigma_vM'],0)
assert np.allclose(in_memory,in_file)
def test_add_norm(self,default):
default.add_norm('F',1)
loc = {'F': default.get_dataset_location('F'),
@ -81,6 +129,24 @@ class TestDADF5:
in_file = default.read_dataset(loc['|F|_1'],0)
assert np.allclose(in_memory,in_file)
def test_add_PK2(self,default):
default.add_PK2('P','F')
loc = {'F':default.get_dataset_location('F'),
'P':default.get_dataset_location('P'),
'S':default.get_dataset_location('S')}
in_memory = mechanics.PK2(default.read_dataset(loc['P'],0),
default.read_dataset(loc['F'],0))
in_file = default.read_dataset(loc['S'],0)
assert np.allclose(in_memory,in_file)
def test_add_rotational_part(self,default):
default.add_rotational_part('F')
loc = {'F': default.get_dataset_location('F'),
'R(F)': default.get_dataset_location('R(F)')}
in_memory = mechanics.rotational_part(default.read_dataset(loc['F'],0))
in_file = default.read_dataset(loc['R(F)'],0)
assert np.allclose(in_memory,in_file)
def test_add_spherical(self,default):
default.add_spherical('P')
loc = {'P': default.get_dataset_location('P'),
@ -88,3 +154,30 @@ class TestDADF5:
in_memory = mechanics.spherical_part(default.read_dataset(loc['P'],0)).reshape(-1,1)
in_file = default.read_dataset(loc['p_P'],0)
assert np.allclose(in_memory,in_file)
def test_add_strain(self,default):
t = ['V','U'][np.random.randint(0,2)]
m = np.random.random()*2.0 - 1.0
default.add_strain_tensor('F',t,m)
label = 'epsilon_{}^{}(F)'.format(t,m)
loc = {'F': default.get_dataset_location('F'),
label: default.get_dataset_location(label)}
in_memory = mechanics.strain_tensor(default.read_dataset(loc['F'],0),t,m)
in_file = default.read_dataset(loc[label],0)
assert np.allclose(in_memory,in_file)
def test_add_stretch_right(self,default):
default.add_stretch_tensor('F','U')
loc = {'F': default.get_dataset_location('F'),
'U(F)': default.get_dataset_location('U(F)')}
in_memory = mechanics.right_stretch(default.read_dataset(loc['F'],0))
in_file = default.read_dataset(loc['U(F)'],0)
assert np.allclose(in_memory,in_file)
def test_add_stretch_left(self,default):
default.add_stretch_tensor('F','V')
loc = {'F': default.get_dataset_location('F'),
'V(F)': default.get_dataset_location('V(F)')}
in_memory = mechanics.left_stretch(default.read_dataset(loc['F'],0))
in_file = default.read_dataset(loc['V(F)'],0)
assert np.allclose(in_memory,in_file)

View File

@ -10,9 +10,64 @@ class TestMechanics:
def test_vectorize_Cauchy(self):
P = np.random.random((self.n,3,3))
F = np.random.random((self.n,3,3))
assert np.allclose(mechanics.Cauchy(F,P)[self.c],
mechanics.Cauchy(F[self.c],P[self.c]))
assert np.allclose(mechanics.Cauchy(P,F)[self.c],
mechanics.Cauchy(P[self.c],F[self.c]))
def test_vectorize_deviatoric_part(self):
x = np.random.random((self.n,3,3))
assert np.allclose(mechanics.deviatoric_part(x)[self.c],
mechanics.deviatoric_part(x[self.c]))
def test_vectorize_eigenvalues(self):
x = np.random.random((self.n,3,3))
assert np.allclose(mechanics.eigenvalues(x)[self.c],
mechanics.eigenvalues(x[self.c]))
def test_vectorize_eigenvectors(self):
x = np.random.random((self.n,3,3))
assert np.allclose(mechanics.eigenvectors(x)[self.c],
mechanics.eigenvectors(x[self.c]))
def test_vectorize_left_stretch(self):
x = np.random.random((self.n,3,3))
assert np.allclose(mechanics.left_stretch(x)[self.c],
mechanics.left_stretch(x[self.c]))
def test_vectorize_maximum_shear(self):
x = np.random.random((self.n,3,3))
assert np.allclose(mechanics.maximum_shear(x)[self.c],
mechanics.maximum_shear(x[self.c]))
def test_vectorize_Mises_strain(self):
epsilon = np.random.random((self.n,3,3))
assert np.allclose(mechanics.Mises_strain(epsilon)[self.c],
mechanics.Mises_strain(epsilon[self.c]))
def test_vectorize_Mises_stress(self):
sigma = np.random.random((self.n,3,3))
assert np.allclose(mechanics.Mises_stress(sigma)[self.c],
mechanics.Mises_stress(sigma[self.c]))
def test_vectorize_PK2(self):
F = np.random.random((self.n,3,3))
P = np.random.random((self.n,3,3))
assert np.allclose(mechanics.PK2(P,F)[self.c],
mechanics.PK2(P[self.c],F[self.c]))
def test_vectorize_right_stretch(self):
x = np.random.random((self.n,3,3))
assert np.allclose(mechanics.right_stretch(x)[self.c],
mechanics.right_stretch(x[self.c]))
def test_vectorize_rotational_part(self):
x = np.random.random((self.n,3,3))
assert np.allclose(mechanics.rotational_part(x)[self.c],
mechanics.rotational_part(x[self.c]))
def test_vectorize_spherical_part(self):
x = np.random.random((self.n,3,3))
assert np.allclose(mechanics.spherical_part(x,True)[self.c],
mechanics.spherical_part(x[self.c],True))
def test_vectorize_strain_tensor(self):
F = np.random.random((self.n,3,3))
@ -21,79 +76,24 @@ class TestMechanics:
assert np.allclose(mechanics.strain_tensor(F,t,m)[self.c],
mechanics.strain_tensor(F[self.c],t,m))
def test_vectorize_deviatoric_part(self):
x = np.random.random((self.n,3,3))
assert np.allclose(mechanics.deviatoric_part(x)[self.c],
mechanics.deviatoric_part(x[self.c]))
def test_vectorize_spherical_part(self):
x = np.random.random((self.n,3,3))
assert np.allclose(mechanics.spherical_part(x,True)[self.c],
mechanics.spherical_part(x[self.c],True))
def test_vectorize_Mises_stress(self):
sigma = np.random.random((self.n,3,3))
assert np.allclose(mechanics.Mises_stress(sigma)[self.c],
mechanics.Mises_stress(sigma[self.c]))
def test_vectorize_Mises_strain(self):
epsilon = np.random.random((self.n,3,3))
assert np.allclose(mechanics.Mises_strain(epsilon)[self.c],
mechanics.Mises_strain(epsilon[self.c]))
def test_vectorize_symmetric(self):
x = np.random.random((self.n,3,3))
assert np.allclose(mechanics.symmetric(x)[self.c],
mechanics.symmetric(x[self.c]))
def test_vectorize_maximum_shear(self):
x = np.random.random((self.n,3,3))
assert np.allclose(mechanics.maximum_shear(x)[self.c],
mechanics.maximum_shear(x[self.c]))
def test_vectorize_principal_components(self):
x = np.random.random((self.n,3,3))
assert np.allclose(mechanics.principal_components(x)[self.c],
mechanics.principal_components(x[self.c]))
def test_vectorize_transpose(self):
x = np.random.random((self.n,3,3))
assert np.allclose(mechanics.transpose(x)[self.c],
mechanics.transpose(x[self.c]))
def test_vectorize_rotational_part(self):
x = np.random.random((self.n,3,3))
assert np.allclose(mechanics.rotational_part(x)[self.c],
mechanics.rotational_part(x[self.c]))
def test_vectorize_left_stretch(self):
x = np.random.random((self.n,3,3))
assert np.allclose(mechanics.left_stretch(x)[self.c],
mechanics.left_stretch(x[self.c]))
def test_vectorize_right_stretch(self):
x = np.random.random((self.n,3,3))
assert np.allclose(mechanics.right_stretch(x)[self.c],
mechanics.right_stretch(x[self.c]))
def test_Cauchy(self):
"""Ensure Cauchy stress is symmetrized 1. Piola-Kirchhoff stress for no deformation."""
P = np.random.random((self.n,3,3))
assert np.allclose(mechanics.Cauchy(np.broadcast_to(np.eye(3),(self.n,3,3)),P),
assert np.allclose(mechanics.Cauchy(P,np.broadcast_to(np.eye(3),(self.n,3,3))),
mechanics.symmetric(P))
def test_polar_decomposition(self):
"""F = RU = VR."""
F = np.broadcast_to(np.eye(3),[self.n,3,3])*np.random.random((self.n,3,3))
@ -104,6 +104,13 @@ class TestMechanics:
np.matmul(V,R))
def test_PK2(self):
"""Ensure 2. Piola-Kirchhoff stress is symmetrized 1. Piola-Kirchhoff stress for no deformation."""
P = np.random.random((self.n,3,3))
assert np.allclose(mechanics.PK2(P,np.broadcast_to(np.eye(3),(self.n,3,3))),
mechanics.symmetric(P))
def test_strain_tensor_no_rotation(self):
"""Ensure that left and right stretch give same results for no rotation."""
F = np.broadcast_to(np.eye(3),[self.n,3,3])*np.random.random((self.n,3,3))
@ -186,3 +193,33 @@ class TestMechanics:
x = np.random.random((self.n,3,3))
assert np.allclose(mechanics.Mises_stress(x)/mechanics.Mises_strain(x),
1.5)
def test_eigenvalues(self):
"""Ensure that the characteristic polynomial can be solved."""
A = mechanics.symmetric(np.random.random((self.n,3,3)))
lambd = mechanics.eigenvalues(A)
s = np.random.randint(self.n)
for i in range(3):
assert np.allclose(np.linalg.det(A[s]-lambd[s,i]*np.eye(3)),.0)
def test_eigenvalues_and_vectors(self):
"""Ensure that eigenvalues and -vectors are the solution to the characteristic polynomial."""
A = mechanics.symmetric(np.random.random((self.n,3,3)))
lambd = mechanics.eigenvalues(A)
x = mechanics.eigenvectors(A)
s = np.random.randint(self.n)
for i in range(3):
assert np.allclose(np.dot(A[s]-lambd[s,i]*np.eye(3),x[s,:,i]),.0)
def test_eigenvectors_RHS(self):
"""Ensure that RHS coordinate system does only change sign of determinant."""
A = mechanics.symmetric(np.random.random((self.n,3,3)))
LRHS = np.linalg.det(mechanics.eigenvectors(A,RHS=False))
RHS = np.linalg.det(mechanics.eigenvectors(A,RHS=True))
assert np.allclose(np.abs(LRHS),RHS)
def test_spherical_no_shear(self):
"""Ensure that sherical stress has max shear of 0.0."""
A = mechanics.spherical_part(mechanics.symmetric(np.random.random((self.n,3,3))),True)
assert np.allclose(mechanics.maximum_shear(A),0.0)

View File

@ -10,17 +10,6 @@ submodule(constitutive) plastic_disloUCLA
real(pReal), parameter :: &
kB = 1.38e-23_pReal !< Boltzmann constant in J/Kelvin
enum, bind(c)
enumerator :: &
undefined_ID, &
rho_mob_ID, &
rho_dip_ID, &
dot_gamma_sl_ID, &
gamma_sl_ID, &
Lambda_sl_ID, &
tau_pass_ID
end enum
type :: tParameters
real(pReal) :: &
aTol_rho, &
@ -28,7 +17,7 @@ submodule(constitutive) plastic_disloUCLA
mu, &
D_0, & !< prefactor for self-diffusion coefficient
Q_cl !< activation energy for dislocation climb
real(pReal), dimension(:), allocatable :: &
real(pReal), allocatable, dimension(:) :: &
rho_mob_0, & !< initial dislocation density
rho_dip_0, & !< initial dipole density
b_sl, & !< magnitude of burgers vector [m]
@ -46,19 +35,19 @@ submodule(constitutive) plastic_disloUCLA
kink_height, & !< height of the kink pair
w, & !< width of the kink pair
omega !< attempt frequency for kink pair nucleation
real(pReal), dimension(:,:), allocatable :: &
real(pReal), allocatable, dimension(:,:) :: &
h_sl_sl, & !< slip resistance from slip activity
forestProjectionEdge
real(pReal), dimension(:,:,:), allocatable :: &
real(pReal), allocatable, dimension(:,:,:) :: &
Schmid, &
nonSchmid_pos, &
nonSchmid_neg
integer :: &
sum_N_sl !< total number of active slip system
integer, dimension(:), allocatable :: &
integer, allocatable, dimension(:) :: &
N_sl !< number of active slip systems for each family
integer(kind(undefined_ID)), dimension(:),allocatable :: &
outputID !< ID of each post result output
character(len=pStringLen), allocatable, dimension(:) :: &
output
logical :: &
dipoleFormation !< flag indicating consideration of dipole formation
end type !< container type for internal constitutive parameters
@ -88,7 +77,7 @@ contains
!--------------------------------------------------------------------------------------------------
!> @brief module initialization
!> @brief Perform module initialization.
!> @details reads in material parameters, allocates arrays, and does sanity checks
!--------------------------------------------------------------------------------------------------
module subroutine plastic_disloUCLA_init
@ -100,15 +89,10 @@ module subroutine plastic_disloUCLA_init
sizeState, sizeDotState, &
startIndex, endIndex
integer(kind(undefined_ID)) :: &
outputID
character(len=pStringLen) :: &
extmsg = ''
character(len=pStringLen), dimension(:), allocatable :: &
outputs
write(6,'(/,a)') ' <<<+- plastic_'//PLASTICITY_DISLOUCLA_label//' init -+>>>'
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'
@ -232,32 +216,7 @@ module subroutine plastic_disloUCLA_init
!--------------------------------------------------------------------------------------------------
! output pararameters
outputs = config%getStrings('(output)',defaultVal=emptyStringArray)
allocate(prm%outputID(0))
do i=1, size(outputs)
outputID = undefined_ID
select case(trim(outputs(i)))
case ('edge_density')
outputID = merge(rho_mob_ID,undefined_ID,prm%sum_N_sl>0)
case ('dipole_density')
outputID = merge(rho_dip_ID,undefined_ID,prm%sum_N_sl>0)
case ('shear_rate','shearrate','shear_rate_slip','shearrate_slip')
outputID = merge(dot_gamma_sl_ID,undefined_ID,prm%sum_N_sl>0)
case ('accumulated_shear','accumulatedshear','accumulated_shear_slip')
outputID = merge(gamma_sl_ID,undefined_ID,prm%sum_N_sl>0)
case ('mfp','mfp_slip')
outputID = merge(Lambda_sl_ID,undefined_ID,prm%sum_N_sl>0)
case ('threshold_stress','threshold_stress_slip')
outputID = merge(tau_pass_ID,undefined_ID,prm%sum_N_sl>0)
end select
if (outputID /= undefined_ID) then
prm%outputID = [prm%outputID, outputID]
endif
enddo
prm%output = config%getStrings('(output)',defaultVal=emptyStringArray)
!--------------------------------------------------------------------------------------------------
! allocate state arrays
@ -304,7 +263,7 @@ end subroutine plastic_disloUCLA_init
!--------------------------------------------------------------------------------------------------
!> @brief calculates plastic velocity gradient and its tangent
!> @brief Calculate plastic velocity gradient and its tangent.
!--------------------------------------------------------------------------------------------------
pure module subroutine plastic_disloUCLA_LpAndItsTangent(Lp,dLp_dMp, &
Mp,T,instance,of)
@ -347,7 +306,7 @@ end subroutine plastic_disloUCLA_LpAndItsTangent
!--------------------------------------------------------------------------------------------------
!> @brief calculates the rate of change of microstructure
!> @brief Calculate the rate of change of microstructure.
!--------------------------------------------------------------------------------------------------
module subroutine plastic_disloUCLA_dotState(Mp,T,instance,of)
@ -407,7 +366,7 @@ end subroutine plastic_disloUCLA_dotState
!--------------------------------------------------------------------------------------------------
!> @brief calculates derived quantities from state
!> @brief Calculate derived quantities from state.
!--------------------------------------------------------------------------------------------------
module subroutine plastic_disloUCLA_dependentState(instance,of)
@ -433,7 +392,7 @@ end subroutine plastic_disloUCLA_dependentState
!--------------------------------------------------------------------------------------------------
!> @brief writes results to HDF5 output file
!> @brief Write results to HDF5 output file.
!--------------------------------------------------------------------------------------------------
module subroutine plastic_disloUCLA_results(instance,group)
@ -443,22 +402,22 @@ module subroutine plastic_disloUCLA_results(instance,group)
integer :: o
associate(prm => param(instance), stt => state(instance), dst => dependentState(instance))
outputsLoop: do o = 1,size(prm%outputID)
select case(prm%outputID(o))
case (rho_mob_ID)
call results_writeDataset(group,stt%rho_mob,'rho_mob',&
outputsLoop: do o = 1,size(prm%output)
select case(trim(prm%output(o)))
case('edge_density') ! ToDo: should be rho_mob
if(prm%sum_N_sl>0) call results_writeDataset(group,stt%rho_mob,'rho_mob',&
'mobile dislocation density','1/m²')
case (rho_dip_ID)
call results_writeDataset(group,stt%rho_dip,'rho_dip',&
case('dipole_density') ! ToDo: should be rho_dip
if(prm%sum_N_sl>0) call results_writeDataset(group,stt%rho_dip,'rho_dip',&
'dislocation dipole density''1/m²')
case (dot_gamma_sl_ID)
call results_writeDataset(group,stt%gamma_sl,'dot_gamma_sl',& ! this is not dot!!
case('shear_rate_slip') ! should be gamma
if(prm%sum_N_sl>0) call results_writeDataset(group,stt%gamma_sl,'dot_gamma_sl',& ! this is not dot!!
'plastic shear','1')
case (Lambda_sl_ID)
call results_writeDataset(group,dst%Lambda_sl,'Lambda_sl',&
case('mfp_slip') !ToDo: should be Lambda
if(prm%sum_N_sl>0) call results_writeDataset(group,dst%Lambda_sl,'Lambda_sl',&
'mean free path for slip','m')
case (tau_pass_ID)
call results_writeDataset(group,dst%threshold_stress,'tau_pass',&
case('threshold_stress_slip') !ToDo: should be tau_pass
if(prm%sum_N_sl>0) call results_writeDataset(group,dst%threshold_stress,'tau_pass',&
'threshold stress for slip','Pa')
end select
enddo outputsLoop
@ -468,8 +427,8 @@ end subroutine plastic_disloUCLA_results
!--------------------------------------------------------------------------------------------------
!> @brief Shear rates on slip systems, their derivatives with respect to resolved stress and the
! resolved stresss
!> @brief Calculate shear rates on slip systems, their derivatives with respect to resolved
! stress, and the resolved stress.
!> @details Derivatives and resolved stress are calculated only optionally.
! NOTE: Against the common convention, the result (i.e. intent(out)) variables are the last to
! have the optional arguments at the end

View File

@ -12,24 +12,6 @@ submodule(constitutive) plastic_dislotwin
real(pReal), parameter :: &
kB = 1.38e-23_pReal !< Boltzmann constant in J/Kelvin
enum, bind(c)
enumerator :: &
undefined_ID, &
rho_mob_ID, &
rho_dip_ID, &
dot_gamma_sl_ID, &
gamma_sl_ID, &
Lambda_sl_ID, &
resolved_stress_slip_ID, &
tau_pass_ID, &
edge_dipole_distance_ID, &
f_tw_ID, &
Lambda_tw_ID, &
resolved_stress_twin_ID, &
tau_hat_tw_ID, &
f_tr_ID
end enum
type :: tParameters
real(pReal) :: &
mu, &
@ -59,7 +41,7 @@ submodule(constitutive) plastic_dislotwin
gamma_fcc_hex, & !< Free energy difference between austensite and martensite
i_tr, & !<
h !< Stack height of hex nucleus
real(pReal), dimension(:), allocatable :: &
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
@ -79,19 +61,16 @@ submodule(constitutive) plastic_dislotwin
s, & !< s-exponent in trans nucleation rate
gamma_char, & !< characteristic shear for twins
B !< drag coefficient
real(pReal), dimension(:,:), allocatable :: &
real(pReal), allocatable, dimension(:,:) :: &
h_sl_sl, & !<
h_sl_tw, & !<
h_tw_tw, & !<
h_sl_tr, & !<
h_tr_tr !<
integer, dimension(:,:), allocatable :: &
fcc_twinNucleationSlipPair ! ToDo: Better name? Is also use for trans
real(pReal), dimension(:,:), allocatable :: &
h_tr_tr, & !<
n0_sl, & !< slip system normal
forestProjection, &
C66
real(pReal), dimension(:,:,:), allocatable :: &
real(pReal), allocatable, dimension(:,:,:) :: &
P_tr, &
P_sl, &
P_tw, &
@ -101,12 +80,14 @@ submodule(constitutive) plastic_dislotwin
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, dimension(:), allocatable :: &
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(kind(undefined_ID)), dimension(:), allocatable :: &
outputID !< ID of each post result output
integer, allocatable, dimension(:,:) :: &
fcc_twinNucleationSlipPair ! ToDo: Better name? Is also use for trans
character(len=pStringLen), allocatable, dimension(:) :: &
output
logical :: &
ExtendedDislocations, & !< consider split into partials for climb calculation
fccTwinTransNucleation, & !< twinning and transformation models are for fcc
@ -148,7 +129,7 @@ contains
!--------------------------------------------------------------------------------------------------
!> @brief module initialization
!> @brief Perform module initialization.
!> @details reads in material parameters, allocates arrays, and does sanity checks
!--------------------------------------------------------------------------------------------------
module subroutine plastic_dislotwin_init
@ -156,19 +137,14 @@ module subroutine plastic_dislotwin_init
integer :: &
Ninstance, &
p, i, &
NipcMyPhase, outputSize, &
NipcMyPhase, &
sizeState, sizeDotState, &
startIndex, endIndex
integer(kind(undefined_ID)) :: &
outputID
character(len=pStringLen) :: &
extmsg = ''
character(len=pStringLen), dimension(:), allocatable :: &
outputs
write(6,'(/,a)') ' <<<+- constitutive_'//PLASTICITY_DISLOTWIN_label//' init -+>>>'
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'
@ -206,7 +182,6 @@ module subroutine plastic_dislotwin_init
prm%nu = lattice_nu(p)
prm%C66 = lattice_C66(1:6,1:6,p)
!--------------------------------------------------------------------------------------------------
! slip related parameters
prm%N_sl = config%getInts('nslip',defaultVal=emptyIntArray)
@ -411,8 +386,6 @@ module subroutine plastic_dislotwin_init
if (prm%q_sb <= 0.0_pReal) extmsg = trim(extmsg)//' q_shearband'
endif
prm%D = config%getFloat('grainsize')
if (config%keyExists('dipoleformationfactor')) call IO_error(1,ext_msg='use /nodipoleformation/')
@ -435,48 +408,7 @@ module subroutine plastic_dislotwin_init
call IO_error(211,el=p,ext_msg='aTol_f_tr ('//PLASTICITY_DISLOTWIN_label//')')
endif
outputs = config%getStrings('(output)', defaultVal=emptyStringArray)
allocate(prm%outputID(0))
do i= 1, size(outputs)
outputID = undefined_ID
select case(outputs(i))
case ('rho_mob')
outputID = merge(rho_mob_ID,undefined_ID,prm%sum_N_sl > 0)
outputSize = prm%sum_N_sl
case ('rho_dip')
outputID = merge(rho_dip_ID,undefined_ID,prm%sum_N_sl > 0)
outputSize = prm%sum_N_sl
case ('gamma_sl')
outputID = merge(gamma_sl_ID,undefined_ID,prm%sum_N_sl > 0)
outputSize = prm%sum_N_sl
case ('lambda_sl')
outputID = merge(Lambda_sl_ID,undefined_ID,prm%sum_N_sl > 0)
outputSize = prm%sum_N_sl
case ('tau_pass')
outputID= merge(tau_pass_ID,undefined_ID,prm%sum_N_sl > 0)
outputSize = prm%sum_N_sl
case ('f_tw')
outputID = merge(f_tw_ID,undefined_ID,prm%sum_N_tw >0)
outputSize = prm%sum_N_tw
case ('lambda_tw')
outputID = merge(Lambda_tw_ID,undefined_ID,prm%sum_N_tw >0)
outputSize = prm%sum_N_tw
case ('tau_hat_tw')
outputID = merge(tau_hat_tw_ID,undefined_ID,prm%sum_N_tw >0)
outputSize = prm%sum_N_tw
case ('f_tr')
outputID = f_tr_ID
outputSize = prm%sum_N_tr
end select
if (outputID /= undefined_ID) then
prm%outputID = [prm%outputID, outputID]
endif
enddo
prm%output = config%getStrings('(output)', defaultVal=emptyStringArray)
!--------------------------------------------------------------------------------------------------
! allocate state arrays
@ -548,7 +480,7 @@ end subroutine plastic_dislotwin_init
!--------------------------------------------------------------------------------------------------
!> @brief returns the homogenized elasticity matrix
!> @brief Return the homogenized elasticity matrix.
!--------------------------------------------------------------------------------------------------
module function plastic_dislotwin_homogenizedC(ipc,ip,el) result(homogenizedC)
@ -587,7 +519,7 @@ end function plastic_dislotwin_homogenizedC
!--------------------------------------------------------------------------------------------------
!> @brief calculates plastic velocity gradient and its tangent
!> @brief Calculate plastic velocity gradient and its tangent.
!--------------------------------------------------------------------------------------------------
module subroutine plastic_dislotwin_LpAndItsTangent(Lp,dLp_dMp,Mp,T,instance,of)
@ -703,7 +635,7 @@ end subroutine plastic_dislotwin_LpAndItsTangent
!--------------------------------------------------------------------------------------------------
!> @brief calculates the rate of change of microstructure
!> @brief Calculate the rate of change of microstructure.
!--------------------------------------------------------------------------------------------------
module subroutine plastic_dislotwin_dotState(Mp,T,instance,of)
@ -806,7 +738,7 @@ end subroutine plastic_dislotwin_dotState
!--------------------------------------------------------------------------------------------------
!> @brief calculates derived quantities from state
!> @brief Calculate derived quantities from state.
!--------------------------------------------------------------------------------------------------
module subroutine plastic_dislotwin_dependentState(T,instance,of)
@ -898,46 +830,47 @@ end subroutine plastic_dislotwin_dependentState
!--------------------------------------------------------------------------------------------------
!> @brief writes results to HDF5 output file
!> @brief Write results to HDF5 output file.
!--------------------------------------------------------------------------------------------------
module subroutine plastic_dislotwin_results(instance,group)
integer, intent(in) :: instance
character(len=*), intent(in) :: group
integer :: o
associate(prm => param(instance), stt => state(instance), dst => dependentState(instance))
outputsLoop: do o = 1,size(prm%outputID)
select case(prm%outputID(o))
outputsLoop: do o = 1,size(prm%output)
select case(trim(prm%output(o)))
case (rho_mob_ID)
call results_writeDataset(group,stt%rho_mob,'rho_mob',&
case('rho_mob')
if(prm%sum_N_sl>0) call results_writeDataset(group,stt%rho_mob,'rho_mob',&
'mobile dislocation density','1/m²')
case (rho_dip_ID)
call results_writeDataset(group,stt%rho_dip,'rho_dip',&
case('rho_dip')
if(prm%sum_N_sl>0) call results_writeDataset(group,stt%rho_dip,'rho_dip',&
'dislocation dipole density''1/m²')
case (gamma_sl_ID)
call results_writeDataset(group,stt%gamma_sl,'gamma_sl',&
case('gamma_sl')
if(prm%sum_N_sl>0) call results_writeDataset(group,stt%gamma_sl,'gamma_sl',&
'plastic shear','1')
case (Lambda_sl_ID)
call results_writeDataset(group,dst%Lambda_sl,'Lambda_sl',&
case('lambda_sl')
if(prm%sum_N_sl>0) call results_writeDataset(group,dst%Lambda_sl,'Lambda_sl',&
'mean free path for slip','m')
case (tau_pass_ID)
call results_writeDataset(group,dst%tau_pass,'tau_pass',&
case('tau_pass')
if(prm%sum_N_sl>0) call results_writeDataset(group,dst%tau_pass,'tau_pass',&
'passing stress for slip','Pa')
case (f_tw_ID)
call results_writeDataset(group,stt%f_tw,'f_tw',&
case('f_tw')
if(prm%sum_N_tw>0) call results_writeDataset(group,stt%f_tw,'f_tw',&
'twinned volume fraction','m³/m³')
case (Lambda_tw_ID)
call results_writeDataset(group,dst%Lambda_tw,'Lambda_tw',&
case('lambda_tw')
if(prm%sum_N_tw>0) call results_writeDataset(group,dst%Lambda_tw,'Lambda_tw',&
'mean free path for twinning','m')
case (tau_hat_tw_ID)
call results_writeDataset(group,dst%tau_hat_tw,'tau_hat_tw',&
case('tau_hat_tw')
if(prm%sum_N_tw>0) call results_writeDataset(group,dst%tau_hat_tw,'tau_hat_tw',&
'threshold stress for twinning','Pa')
case (f_tr_ID)
call results_writeDataset(group,stt%f_tr,'f_tr',&
case('f_tr')
if(prm%sum_N_tr>0) call results_writeDataset(group,stt%f_tr,'f_tr',&
'martensite volume fraction','m³/m³')
end select
@ -948,8 +881,8 @@ end subroutine plastic_dislotwin_results
!--------------------------------------------------------------------------------------------------
!> @brief Shear rates on slip systems, their derivatives with respect to resolved stress and the
! resolved stresss
!> @brief Calculate shear rates on slip systems, their derivatives with respect to resolved
! stress, and the resolved stress.
!> @details Derivatives and resolved stress are calculated only optionally.
! NOTE: Against the common convention, the result (i.e. intent(out)) variables are the last to
! have the optional arguments at the end
@ -1025,7 +958,11 @@ end subroutine kinetics_slip
!--------------------------------------------------------------------------------------------------
!> @brief calculates shear rates on twin systems
!> @brief Calculate shear rates on twin systems and their derivatives with respect to resolved
! stress.
!> @details Derivatives are calculated only optionally.
! NOTE: Against the common convention, the result (i.e. intent(out)) variables are the last to
! have the optional arguments at the end.
!--------------------------------------------------------------------------------------------------
pure subroutine kinetics_twin(Mp,T,dot_gamma_sl,instance,of,&
dot_gamma_twin,ddot_gamma_dtau_twin)
@ -1090,7 +1027,11 @@ end subroutine kinetics_twin
!--------------------------------------------------------------------------------------------------
!> @brief calculates shear rates on twin systems
!> @brief Calculate shear rates on transformation systems and their derivatives with respect to
! resolved stress.
!> @details Derivatives are calculated only optionally.
! NOTE: Against the common convention, the result (i.e. intent(out)) variables are the last to
! have the optional arguments at the end.
!--------------------------------------------------------------------------------------------------
pure subroutine kinetics_trans(Mp,T,dot_gamma_sl,instance,of,&
dot_gamma_tr,ddot_gamma_dtau_trans)

View File

@ -9,13 +9,6 @@
!--------------------------------------------------------------------------------------------------
submodule(constitutive) plastic_isotropic
enum, bind(c)
enumerator :: &
undefined_ID, &
xi_ID, &
dot_gamma_ID
end enum
type :: tParameters
real(pReal) :: &
M, & !< Taylor factor
@ -34,10 +27,10 @@ submodule(constitutive) plastic_isotropic
aTol_gamma
integer :: &
of_debug = 0
integer(kind(undefined_ID)), allocatable, dimension(:) :: &
outputID
logical :: &
dilatation
character(len=pStringLen), allocatable, dimension(:) :: &
output
end type tParameters
type :: tIsotropicState
@ -56,26 +49,21 @@ submodule(constitutive) plastic_isotropic
contains
!--------------------------------------------------------------------------------------------------
!> @brief module initialization
!> @brief Perform module initialization.
!> @details reads in material parameters, allocates arrays, and does sanity checks
!--------------------------------------------------------------------------------------------------
module subroutine plastic_isotropic_init
integer :: &
Ninstance, &
p, i, &
p, &
NipcMyPhase, &
sizeState, sizeDotState
integer(kind(undefined_ID)) :: &
outputID
character(len=pStringLen) :: &
extmsg = ''
character(len=pStringLen), dimension(:), allocatable :: &
outputs
write(6,'(/,a)') ' <<<+- plastic_'//PLASTICITY_ISOTROPIC_label//' init -+>>>'
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'
@ -136,24 +124,7 @@ module subroutine plastic_isotropic_init
!--------------------------------------------------------------------------------------------------
! output pararameters
outputs = config%getStrings('(output)',defaultVal=emptyStringArray)
allocate(prm%outputID(0))
do i=1, size(outputs)
outputID = undefined_ID
select case(outputs(i))
case ('flowstress')
outputID = xi_ID
case ('strainrate')
outputID = dot_gamma_ID
end select
if (outputID /= undefined_ID) then
prm%outputID = [prm%outputID, outputID]
endif
enddo
prm%output = config%getStrings('(output)',defaultVal=emptyStringArray)
!--------------------------------------------------------------------------------------------------
! allocate state arrays
@ -186,7 +157,7 @@ end subroutine plastic_isotropic_init
!--------------------------------------------------------------------------------------------------
!> @brief calculates plastic velocity gradient and its tangent
!> @brief Calculate plastic velocity gradient and its tangent.
!--------------------------------------------------------------------------------------------------
module subroutine plastic_isotropic_LpAndItsTangent(Lp,dLp_dMp,Mp,instance,of)
@ -247,7 +218,7 @@ end subroutine plastic_isotropic_LpAndItsTangent
!--------------------------------------------------------------------------------------------------
!> @brief calculates plastic velocity gradient and its tangent
!> @brief Calculate inelastic velocity gradient and its tangent.
!--------------------------------------------------------------------------------------------------
module subroutine plastic_isotropic_LiAndItsTangent(Li,dLi_dMi,Mi,instance,of)
@ -299,7 +270,7 @@ module subroutine plastic_isotropic_LiAndItsTangent(Li,dLi_dMi,Mi,instance,of)
!--------------------------------------------------------------------------------------------------
!> @brief calculates the rate of change of microstructure
!> @brief Calculate the rate of change of microstructure.
!--------------------------------------------------------------------------------------------------
module subroutine plastic_isotropic_dotState(Mp,instance,of)
@ -348,7 +319,7 @@ end subroutine plastic_isotropic_dotState
!--------------------------------------------------------------------------------------------------
!> @brief writes results to HDF5 output file
!> @brief Write results to HDF5 output file.
!--------------------------------------------------------------------------------------------------
module subroutine plastic_isotropic_results(instance,group)
@ -358,9 +329,9 @@ module subroutine plastic_isotropic_results(instance,group)
integer :: o
associate(prm => param(instance), stt => state(instance))
outputsLoop: do o = 1,size(prm%outputID)
select case(prm%outputID(o))
case (xi_ID)
outputsLoop: do o = 1,size(prm%output)
select case(trim(prm%output(o)))
case ('flowstress') ! ToDo: should be 'xi'
call results_writeDataset(group,stt%xi,'xi','resistance against plastic flow','Pa')
end select
enddo outputsLoop

View File

@ -7,19 +7,6 @@
!--------------------------------------------------------------------------------------------------
submodule(constitutive) plastic_kinehardening
enum, bind(c)
enumerator :: &
undefined_ID, &
crss_ID, & !< critical resolved stress
crss_back_ID, & !< critical resolved back stress
sense_ID, & !< sense of acting shear stress (-1 or +1)
chi0_ID, & !< backstress at last switch of stress sense (positive?)
gamma0_ID, & !< accumulated shear at last switch of stress sense (at current switch?)
accshear_ID, &
shearrate_ID, &
resolvedstress_ID
end enum
type :: tParameters
real(pReal) :: &
gdot0, & !< reference shear strain rate for slip
@ -46,8 +33,8 @@ submodule(constitutive) plastic_kinehardening
of_debug = 0
integer, allocatable, dimension(:) :: &
Nslip !< number of active slip systems for each family
integer(kind(undefined_ID)), allocatable, dimension(:) :: &
outputID !< ID of each post result output
character(len=pStringLen), allocatable, dimension(:) :: &
output
end type tParameters
type :: tKinehardeningState
@ -72,27 +59,22 @@ contains
!--------------------------------------------------------------------------------------------------
!> @brief module initialization
!> @brief Perform module initialization.
!> @details reads in material parameters, allocates arrays, and does sanity checks
!--------------------------------------------------------------------------------------------------
module subroutine plastic_kinehardening_init
integer :: &
Ninstance, &
p, i, o, &
p, o, &
NipcMyPhase, &
sizeState, sizeDeltaState, sizeDotState, &
startIndex, endIndex
integer(kind(undefined_ID)) :: &
outputID
character(len=pStringLen) :: &
extmsg = ''
character(len=pStringLen), dimension(:), allocatable :: &
outputs
write(6,'(/,a)') ' <<<+- plastic_'//PLASTICITY_KINEHARDENING_label//' init -+>>>'
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) &
@ -188,36 +170,7 @@ module subroutine plastic_kinehardening_init
!--------------------------------------------------------------------------------------------------
! output pararameters
outputs = config%getStrings('(output)',defaultVal=emptyStringArray)
allocate(prm%outputID(0))
do i=1, size(outputs)
outputID = undefined_ID
select case(outputs(i))
case ('resistance')
outputID = merge(crss_ID,undefined_ID,prm%totalNslip>0)
case ('accumulatedshear')
outputID = merge(accshear_ID,undefined_ID,prm%totalNslip>0)
case ('shearrate')
outputID = merge(shearrate_ID,undefined_ID,prm%totalNslip>0)
case ('resolvedstress')
outputID = merge(resolvedstress_ID,undefined_ID,prm%totalNslip>0)
case ('backstress')
outputID = merge(crss_back_ID,undefined_ID,prm%totalNslip>0)
case ('sense')
outputID = merge(sense_ID,undefined_ID,prm%totalNslip>0)
case ('chi0')
outputID = merge(chi0_ID,undefined_ID,prm%totalNslip>0)
case ('gamma0')
outputID = merge(gamma0_ID,undefined_ID,prm%totalNslip>0)
end select
if (outputID /= undefined_ID) then
prm%outputID = [prm%outputID , outputID]
endif
enddo
prm%output = config%getStrings('(output)',defaultVal=emptyStringArray)
!--------------------------------------------------------------------------------------------------
! allocate state arrays
@ -277,7 +230,7 @@ end subroutine plastic_kinehardening_init
!--------------------------------------------------------------------------------------------------
!> @brief calculates plastic velocity gradient and its tangent
!> @brief Calculate plastic velocity gradient and its tangent.
!--------------------------------------------------------------------------------------------------
pure module subroutine plastic_kinehardening_LpAndItsTangent(Lp,dLp_dMp,Mp,instance,of)
@ -319,7 +272,7 @@ end subroutine plastic_kinehardening_LpAndItsTangent
!--------------------------------------------------------------------------------------------------
!> @brief calculates the rate of change of microstructure
!> @brief Calculate the rate of change of microstructure.
!--------------------------------------------------------------------------------------------------
module subroutine plastic_kinehardening_dotState(Mp,instance,of)
@ -361,7 +314,7 @@ end subroutine plastic_kinehardening_dotState
!--------------------------------------------------------------------------------------------------
!> @brief calculates (instantaneous) incremental change of microstructure
!> @brief Calculate (instantaneous) incremental change of microstructure.
!--------------------------------------------------------------------------------------------------
module subroutine plastic_kinehardening_deltaState(Mp,instance,of)
@ -409,38 +362,36 @@ end subroutine plastic_kinehardening_deltaState
!--------------------------------------------------------------------------------------------------
!> @brief writes results to HDF5 output file
!> @brief Write results to HDF5 output file.
!--------------------------------------------------------------------------------------------------
module subroutine plastic_kinehardening_results(instance,group)
integer, intent(in) :: instance
character(len=*), intent(in) :: group
integer :: o
associate(prm => param(instance), stt => state(instance))
outputsLoop: do o = 1,size(prm%outputID)
select case(prm%outputID(o))
case (crss_ID)
call results_writeDataset(group,stt%crss,'xi_sl', &
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', &
'resistance against plastic slip','Pa')
case(crss_back_ID)
call results_writeDataset(group,stt%crss_back,'tau_back', &
case('backstress') ! ToDo: should be 'tau_back'
if(prm%totalNslip>0) call results_writeDataset(group,stt%crss_back,'tau_back', &
'back stress against plastic slip','Pa')
case (sense_ID)
call results_writeDataset(group,stt%sense,'sense_of_shear','tbd','1')
case (chi0_ID)
call results_writeDataset(group,stt%chi0,'chi0','tbd','Pa')
case (gamma0_ID)
call results_writeDataset(group,stt%gamma0,'gamma0','tbd','1')
case (accshear_ID)
call results_writeDataset(group,stt%accshear,'gamma_sl', &
case ('sense')
if(prm%totalNslip>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', &
'tbd','Pa')
case ('gamma0')
if(prm%totalNslip>0) call results_writeDataset(group,stt%gamma0,'gamma0', &
'tbd','1')
case ('accumulatedshear')
if(prm%totalNslip>0) call results_writeDataset(group,stt%accshear,'gamma_sl', &
'plastic shear','1')
end select
enddo outputsLoop
end associate
@ -449,10 +400,11 @@ end subroutine plastic_kinehardening_results
!--------------------------------------------------------------------------------------------------
!> @brief calculates shear rates on slip systems and derivatives with respect to resolved stress
!> @details: Shear rates are calculated only optionally.
!> @brief Calculate shear rates on slip systems and their derivatives with respect to resolved
! stress.
!> @details: Derivatives are calculated only optionally.
! NOTE: Against the common convention, the result (i.e. intent(out)) variables are the last to
! have the optional arguments at the end
! have the optional arguments at the end.
!--------------------------------------------------------------------------------------------------
pure subroutine kinetics(Mp,instance,of, &
gdot_pos,gdot_neg,dgdot_dtau_pos,dgdot_dtau_neg)

View File

@ -19,7 +19,7 @@ module subroutine plastic_none_init
p, &
NipcMyPhase
write(6,'(/,a)') ' <<<+- plastic_'//PLASTICITY_NONE_label//' init -+>>>'
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) &

View File

@ -48,32 +48,6 @@ submodule(constitutive) plastic_nonlocal
real(pReal), dimension(:,:,:,:,:,:), allocatable :: &
compatibility !< slip system compatibility between me and my neighbors
enum, bind(c)
enumerator :: &
undefined_ID, &
rho_sgl_mob_edg_pos_ID, &
rho_sgl_mob_edg_neg_ID, &
rho_sgl_mob_scr_pos_ID, &
rho_sgl_mob_scr_neg_ID, &
rho_sgl_imm_edg_pos_ID, &
rho_sgl_imm_edg_neg_ID, &
rho_sgl_imm_scr_pos_ID, &
rho_sgl_imm_scr_neg_ID, &
rho_dip_edg_ID, &
rho_dip_scr_ID, &
rho_forest_ID, &
resolvedstress_back_ID, &
tau_pass_ID, &
rho_dot_sgl_ID, &
rho_dot_sgl_mobile_ID, &
rho_dot_dip_ID, &
v_edg_pos_ID, &
v_edg_neg_ID, &
v_scr_pos_ID, &
v_scr_neg_ID, &
gamma_ID
end enum
type :: tParameters !< container type for internal constitutive parameters
real(pReal) :: &
atomicVolume, & !< atomic volume
@ -135,14 +109,12 @@ submodule(constitutive) plastic_nonlocal
integer, dimension(:) ,allocatable :: &
Nslip,&
colinearSystem !< colinear system to the active slip system (only valid for fcc!)
character(len=pStringLen), allocatable, dimension(:) :: &
output
logical :: &
shortRangeStressCorrection, & !< flag indicating the use of the short range stress correction by a excess density gradient term
probabilisticMultiplication
integer(kind(undefined_ID)), dimension(:), allocatable :: &
outputID !< ID of each post result output
end type tParameters
type :: tNonlocalMicrostructure
@ -198,22 +170,19 @@ module subroutine plastic_nonlocal_init
integer :: &
sizeState, sizeDotState,sizeDependentState, sizeDeltaState, &
maxNinstances, &
p, i, &
p, &
l, &
s1, s2, &
s, &
t, &
c
integer(kind(undefined_ID)) :: &
outputID
character(len=pStringLen) :: &
extmsg = '', &
structure
character(len=pStringLen), dimension(:), allocatable :: outputs
integer :: NofMyPhase
write(6,'(/,a)') ' <<<+- constitutive_'//PLASTICITY_NONLOCAL_label//' init -+>>>'
write(6,'(/,a)') ' <<<+- constitutive_'//PLASTICITY_NONLOCAL_label//' init -+>>>'; flush(6)
write(6,'(/,a)') ' Reuber et al., Acta Materialia 71:333348, 2014'
write(6,'(a)') ' https://doi.org/10.1016/j.actamat.2014.03.012'
@ -407,60 +376,7 @@ module subroutine plastic_nonlocal_init
endif slipActive
outputs = config%getStrings('(output)',defaultVal=emptyStringArray)
allocate(prm%outputID(0))
do i=1, size(outputs)
outputID = undefined_ID
select case(trim(outputs(i)))
case ('rho_sgl_mob_edg_pos')
outputID = merge(rho_sgl_mob_edg_pos_ID,undefined_ID,prm%totalNslip>0)
case ('rho_sgl_mob_edg_neg')
outputID = merge(rho_sgl_mob_edg_neg_ID,undefined_ID,prm%totalNslip>0)
case ('rho_sgl_mob_scr_pos')
outputID = merge(rho_sgl_mob_scr_pos_ID,undefined_ID,prm%totalNslip>0)
case ('rho_sgl_mob_scr_neg')
outputID = merge(rho_sgl_mob_scr_neg_ID,undefined_ID,prm%totalNslip>0)
case ('rho_sgl_imm_edg_pos')
outputID = merge(rho_sgl_imm_edg_pos_ID,undefined_ID,prm%totalNslip>0)
case ('rho_sgl_imm_edg_neg')
outputID = merge(rho_sgl_imm_edg_neg_ID,undefined_ID,prm%totalNslip>0)
case ('rho_sgl_imm_scr_pos')
outputID = merge(rho_sgl_imm_scr_pos_ID,undefined_ID,prm%totalNslip>0)
case ('rho_sgl_imm_scr_neg')
outputID = merge(rho_sgl_imm_scr_neg_ID,undefined_ID,prm%totalNslip>0)
case ('rho_dip_edg')
outputID = merge(rho_dip_edg_ID,undefined_ID,prm%totalNslip>0)
case ('rho_dip_scr')
outputID = merge(rho_dip_scr_ID,undefined_ID,prm%totalNslip>0)
case ('rho_forest')
outputID = merge(rho_forest_ID,undefined_ID,prm%totalNslip>0)
case ('resolvedstress_back')
outputID = merge(resolvedstress_back_ID,undefined_ID,prm%totalNslip>0)
case ('tau_pass')
outputID = merge(tau_pass_ID,undefined_ID,prm%totalNslip>0)
case ('rho_dot_sgl')
outputID = merge(rho_dot_sgl_ID,undefined_ID,prm%totalNslip>0)
case ('rho_dot_sgl_mobile')
outputID = merge(rho_dot_sgl_mobile_ID,undefined_ID,prm%totalNslip>0)
case ('rho_dot_dip')
outputID = merge(rho_dot_dip_ID,undefined_ID,prm%totalNslip>0)
case ('v_edg_pos')
outputID = merge(v_edg_pos_ID,undefined_ID,prm%totalNslip>0)
case ('v_edg_neg')
outputID = merge(v_edg_neg_ID,undefined_ID,prm%totalNslip>0)
case ('v_scr_pos')
outputID = merge(v_scr_pos_ID,undefined_ID,prm%totalNslip>0)
case ('v_scr_neg')
outputID = merge(v_scr_neg_ID,undefined_ID,prm%totalNslip>0)
case ('gamma')
outputID = merge(gamma_ID,undefined_ID,prm%totalNslip>0)
end select
if (outputID /= undefined_ID) then
prm%outputID = [prm%outputID , outputID]
endif
enddo
prm%output = config%getStrings('(output)',defaultVal=emptyStringArray)
!--------------------------------------------------------------------------------------------------
! allocate state arrays
@ -561,7 +477,7 @@ module subroutine plastic_nonlocal_init
stt%v_scr_neg => plasticState(p)%state (15*prm%totalNslip + 1:16*prm%totalNslip ,1:NofMyPhase)
allocate(dst%tau_pass(prm%totalNslip,NofMyPhase),source=0.0_pReal)
allocate(dst%tau_Back(prm%totalNslip,NofMyPhase), source=0.0_pReal)
allocate(dst%tau_back(prm%totalNslip,NofMyPhase),source=0.0_pReal)
end associate
if (NofMyPhase > 0) call stateInit(p,NofMyPhase)
@ -1968,61 +1884,62 @@ module subroutine plastic_nonlocal_results(instance,group)
integer, intent(in) :: instance
character(len=*),intent(in) :: group
integer :: o
associate(prm => param(instance),dst => microstructure(instance),stt=>state(instance))
outputsLoop: do o = 1,size(prm%outputID)
select case(prm%outputID(o))
case (rho_sgl_mob_edg_pos_ID)
call results_writeDataset(group,stt%rho_sgl_mob_edg_pos, 'rho_sgl_mob_edg_pos', &
outputsLoop: do o = 1,size(prm%output)
select case(trim(prm%output(o)))
case('rho_sgl_mob_edg_pos')
if(prm%totalNslip>0) call results_writeDataset(group,stt%rho_sgl_mob_edg_pos, 'rho_sgl_mob_edg_pos', &
'positive mobile edge density','1/m²')
case (rho_sgl_imm_edg_pos_ID)
call results_writeDataset(group,stt%rho_sgl_imm_edg_pos, 'rho_sgl_imm_edg_pos',&
case('rho_sgl_imm_edg_pos')
if(prm%totalNslip>0) call results_writeDataset(group,stt%rho_sgl_imm_edg_pos, 'rho_sgl_imm_edg_pos',&
'positive immobile edge density','1/m²')
case (rho_sgl_mob_edg_neg_ID)
call results_writeDataset(group,stt%rho_sgl_mob_edg_neg, 'rho_sgl_mob_edg_neg',&
case('rho_sgl_mob_edg_neg')
if(prm%totalNslip>0) call results_writeDataset(group,stt%rho_sgl_mob_edg_neg, 'rho_sgl_mob_edg_neg',&
'negative mobile edge density','1/m²')
case (rho_sgl_imm_edg_neg_ID)
call results_writeDataset(group,stt%rho_sgl_imm_edg_neg, 'rho_sgl_imm_edg_neg',&
case('rho_sgl_imm_edg_neg')
if(prm%totalNslip>0) call results_writeDataset(group,stt%rho_sgl_imm_edg_neg, 'rho_sgl_imm_edg_neg',&
'negative immobile edge density','1/m²')
case (rho_dip_edg_ID)
call results_writeDataset(group,stt%rho_dip_edg, 'rho_dip_edg',&
case('rho_dip_edg')
if(prm%totalNslip>0) call results_writeDataset(group,stt%rho_dip_edg, 'rho_dip_edg',&
'edge dipole density','1/m²')
case (rho_sgl_mob_scr_pos_ID)
call results_writeDataset(group,stt%rho_sgl_mob_scr_pos, 'rho_sgl_mob_scr_pos',&
case('rho_sgl_mob_scr_pos')
if(prm%totalNslip>0) call results_writeDataset(group,stt%rho_sgl_mob_scr_pos, 'rho_sgl_mob_scr_pos',&
'positive mobile screw density','1/m²')
case (rho_sgl_imm_scr_pos_ID)
call results_writeDataset(group,stt%rho_sgl_imm_scr_pos, 'rho_sgl_imm_scr_pos',&
case('rho_sgl_imm_scr_pos')
if(prm%totalNslip>0) call results_writeDataset(group,stt%rho_sgl_imm_scr_pos, 'rho_sgl_imm_scr_pos',&
'positive immobile screw density','1/m²')
case (rho_sgl_mob_scr_neg_ID)
call results_writeDataset(group,stt%rho_sgl_mob_scr_neg, 'rho_sgl_mob_scr_neg',&
case('rho_sgl_mob_scr_neg')
if(prm%totalNslip>0) call results_writeDataset(group,stt%rho_sgl_mob_scr_neg, 'rho_sgl_mob_scr_neg',&
'negative mobile screw density','1/m²')
case (rho_sgl_imm_scr_neg_ID)
call results_writeDataset(group,stt%rho_sgl_imm_scr_neg, 'rho_sgl_imm_scr_neg',&
case('rho_sgl_imm_scr_neg')
if(prm%totalNslip>0) call results_writeDataset(group,stt%rho_sgl_imm_scr_neg, 'rho_sgl_imm_scr_neg',&
'negative immobile screw density','1/m²')
case (rho_dip_scr_ID)
call results_writeDataset(group,stt%rho_dip_scr, 'rho_dip_scr',&
case('rho_dip_scr')
if(prm%totalNslip>0) call results_writeDataset(group,stt%rho_dip_scr, 'rho_dip_scr',&
'screw dipole density','1/m²')
case (rho_forest_ID)
call results_writeDataset(group,stt%rho_forest, 'rho_forest',&
case('rho_forest')
if(prm%totalNslip>0) call results_writeDataset(group,stt%rho_forest, 'rho_forest',&
'forest density','1/m²')
case (v_edg_pos_ID)
call results_writeDataset(group,stt%v_edg_pos, 'v_edg_pos',&
case('v_edg_pos')
if(prm%totalNslip>0) call results_writeDataset(group,stt%v_edg_pos, 'v_edg_pos',&
'positive edge velocity','m/s')
case (v_edg_neg_ID)
call results_writeDataset(group,stt%v_edg_neg, 'v_edg_neg',&
case('v_edg_neg')
if(prm%totalNslip>0) call results_writeDataset(group,stt%v_edg_neg, 'v_edg_neg',&
'negative edge velocity','m/s')
case (v_scr_pos_ID)
call results_writeDataset(group,stt%v_scr_pos, 'v_scr_pos',&
case('v_scr_pos')
if(prm%totalNslip>0) call results_writeDataset(group,stt%v_scr_pos, 'v_scr_pos',&
'positive srew velocity','m/s')
case (v_scr_neg_ID)
call results_writeDataset(group,stt%v_scr_neg, 'v_scr_neg',&
case('v_scr_neg')
if(prm%totalNslip>0) call results_writeDataset(group,stt%v_scr_neg, 'v_scr_neg',&
'negative screw velocity','m/s')
case(gamma_ID)
call results_writeDataset(group,stt%gamma,'gamma',&
case('gamma')
if(prm%totalNslip>0) call results_writeDataset(group,stt%gamma,'gamma',&
'plastic shear','1')
case (tau_pass_ID)
call results_writeDataset(group,dst%tau_pass,'tau_pass',&
case('tau_pass')
if(prm%totalNslip>0) call results_writeDataset(group,dst%tau_pass,'tau_pass',&
'passing stress for slip','Pa')
end select
enddo outputsLoop

View File

@ -6,19 +6,6 @@
!--------------------------------------------------------------------------------------------------
submodule(constitutive) plastic_phenopowerlaw
enum, bind(c)
enumerator :: &
undefined_ID, &
resistance_slip_ID, &
accumulatedshear_slip_ID, &
shearrate_slip_ID, &
resolvedstress_slip_ID, &
resistance_twin_ID, &
accumulatedshear_twin_ID, &
shearrate_twin_ID, &
resolvedstress_twin_ID
end enum
type :: tParameters
real(pReal) :: &
gdot0_slip, & !< reference shear strain rate for slip
@ -60,8 +47,8 @@ submodule(constitutive) plastic_phenopowerlaw
integer, allocatable, dimension(:) :: &
Nslip, & !< number of active slip systems for each family
Ntwin !< number of active twin systems for each family
integer(kind(undefined_ID)), allocatable, dimension(:) :: &
outputID !< ID of each post result output
character(len=pStringLen), allocatable, dimension(:) :: &
output
end type tParameters
type :: tPhenopowerlawState
@ -83,7 +70,7 @@ contains
!--------------------------------------------------------------------------------------------------
!> @brief module initialization
!> @brief Perform module initialization.
!> @details reads in material parameters, allocates arrays, and does sanity checks
!--------------------------------------------------------------------------------------------------
module subroutine plastic_phenopowerlaw_init
@ -91,19 +78,14 @@ module subroutine plastic_phenopowerlaw_init
integer :: &
Ninstance, &
p, i, &
NipcMyPhase, outputSize, &
NipcMyPhase, &
sizeState, sizeDotState, &
startIndex, endIndex
integer(kind(undefined_ID)) :: &
outputID
character(len=pStringLen) :: &
extmsg = ''
character(len=pStringLen), dimension(:), allocatable :: &
outputs
write(6,'(/,a)') ' <<<+- plastic_'//PLASTICITY_PHENOPOWERLAW_label//' init -+>>>'
write(6,'(/,a)') ' <<<+- plastic_'//PLASTICITY_PHENOPOWERLAW_label//' init -+>>>'; flush(6)
Ninstance = count(phase_plasticity == PLASTICITY_PHENOPOWERLAW_ID)
if (iand(debug_level(debug_constitutive),debug_levelBasic) /= 0) &
@ -239,45 +221,7 @@ module subroutine plastic_phenopowerlaw_init
!--------------------------------------------------------------------------------------------------
! output pararameters
outputs = config%getStrings('(output)',defaultVal=emptyStringArray)
allocate(prm%outputID(0))
do i=1, size(outputs)
outputID = undefined_ID
select case(outputs(i))
case ('resistance_slip')
outputID = merge(resistance_slip_ID,undefined_ID,prm%totalNslip>0)
outputSize = prm%totalNslip
case ('accumulatedshear_slip')
outputID = merge(accumulatedshear_slip_ID,undefined_ID,prm%totalNslip>0)
outputSize = prm%totalNslip
case ('shearrate_slip')
outputID = merge(shearrate_slip_ID,undefined_ID,prm%totalNslip>0)
outputSize = prm%totalNslip
case ('resolvedstress_slip')
outputID = merge(resolvedstress_slip_ID,undefined_ID,prm%totalNslip>0)
outputSize = prm%totalNslip
case ('resistance_twin')
outputID = merge(resistance_twin_ID,undefined_ID,prm%totalNtwin>0)
outputSize = prm%totalNtwin
case ('accumulatedshear_twin')
outputID = merge(accumulatedshear_twin_ID,undefined_ID,prm%totalNtwin>0)
outputSize = prm%totalNtwin
case ('shearrate_twin')
outputID = merge(shearrate_twin_ID,undefined_ID,prm%totalNtwin>0)
outputSize = prm%totalNtwin
case ('resolvedstress_twin')
outputID = merge(resolvedstress_twin_ID,undefined_ID,prm%totalNtwin>0)
outputSize = prm%totalNtwin
end select
if (outputID /= undefined_ID) then
prm%outputID = [prm%outputID, outputID]
endif
enddo
prm%output = config%getStrings('(output)',defaultVal=emptyStringArray)
!--------------------------------------------------------------------------------------------------
! allocate state arrays
@ -328,7 +272,7 @@ end subroutine plastic_phenopowerlaw_init
!--------------------------------------------------------------------------------------------------
!> @brief calculates plastic velocity gradient and its tangent
!> @brief Calculate plastic velocity gradient and its tangent.
!> @details asummes that deformation by dislocation glide affects twinned and untwinned volume
! equally (Taylor assumption). Twinning happens only in untwinned volume
!--------------------------------------------------------------------------------------------------
@ -381,7 +325,7 @@ end subroutine plastic_phenopowerlaw_LpAndItsTangent
!--------------------------------------------------------------------------------------------------
!> @brief calculates the rate of change of microstructure
!> @brief Calculate the rate of change of microstructure.
!--------------------------------------------------------------------------------------------------
module subroutine plastic_phenopowerlaw_dotState(Mp,instance,of)
@ -437,7 +381,7 @@ end subroutine plastic_phenopowerlaw_dotState
!--------------------------------------------------------------------------------------------------
!> @brief writes results to HDF5 output file
!> @brief Write results to HDF5 output file.
!--------------------------------------------------------------------------------------------------
module subroutine plastic_phenopowerlaw_results(instance,group)
@ -447,21 +391,21 @@ module subroutine plastic_phenopowerlaw_results(instance,group)
integer :: o
associate(prm => param(instance), stt => state(instance))
outputsLoop: do o = 1,size(prm%outputID)
select case(prm%outputID(o))
outputsLoop: do o = 1,size(prm%output)
select case(trim(prm%output(o)))
case (resistance_slip_ID)
call results_writeDataset(group,stt%xi_slip, 'xi_sl', &
case('resistance_slip')
if(prm%totalNslip>0) call results_writeDataset(group,stt%xi_slip, 'xi_sl', &
'resistance against plastic slip','Pa')
case (accumulatedshear_slip_ID)
call results_writeDataset(group,stt%gamma_slip,'gamma_sl', &
case('accumulatedshear_slip')
if(prm%totalNslip>0) call results_writeDataset(group,stt%gamma_slip,'gamma_sl', &
'plastic shear','1')
case (resistance_twin_ID)
call results_writeDataset(group,stt%xi_twin, 'xi_tw', &
case('resistance_twin')
if(prm%totalNtwin>0) call results_writeDataset(group,stt%xi_twin, 'xi_tw', &
'resistance against twinning','Pa')
case (accumulatedshear_twin_ID)
call results_writeDataset(group,stt%gamma_twin,'gamma_tw', &
case('accumulatedshear_twin')
if(prm%totalNtwin>0) call results_writeDataset(group,stt%gamma_twin,'gamma_tw', &
'twinning shear','1')
end select
@ -472,10 +416,11 @@ end subroutine plastic_phenopowerlaw_results
!--------------------------------------------------------------------------------------------------
!> @brief Shear rates on slip systems and their derivatives with respect to resolved stress
!> @brief Calculate shear rates on slip systems and their derivatives with respect to resolved
! stress.
!> @details Derivatives are calculated only optionally.
! NOTE: Against the common convention, the result (i.e. intent(out)) variables are the last to
! have the optional arguments at the end
! have the optional arguments at the end.
!--------------------------------------------------------------------------------------------------
pure subroutine kinetics_slip(Mp,instance,of, &
gdot_slip_pos,gdot_slip_neg,dgdot_dtau_slip_pos,dgdot_dtau_slip_neg)
@ -543,9 +488,9 @@ end subroutine kinetics_slip
!--------------------------------------------------------------------------------------------------
!> @brief Shear rates on twin systems and their derivatives with respect to resolved stress.
! twinning is assumed to take place only in untwinned volume.
!> @details Derivates are calculated only optionally.
!> @brief Calculate shear rates on twin systems and their derivatives with respect to resolved
! stress. Twinning is assumed to take place only in untwinned volume.
!> @details Derivatives are calculated only optionally.
! NOTE: Against the common convention, the result (i.e. intent(out)) variables are the last to
! have the optional arguments at the end.
!--------------------------------------------------------------------------------------------------

View File

@ -57,9 +57,7 @@ module crystallite
crystallite_Li0, & !< intermediate velocitiy grad at start of FE inc
crystallite_partionedLi0 !< intermediate velocity grad at start of homog inc
real(pReal), dimension(:,:,:,:,:), allocatable :: &
crystallite_invFp, & !< inverse of current plastic def grad (end of converged time step)
crystallite_subFp0,& !< plastic def grad at start of crystallite inc
crystallite_invFi, & !< inverse of current intermediate def grad (end of converged time step)
crystallite_subFi0,& !< intermediate def grad at start of crystallite inc
crystallite_subF, & !< def grad to be reached at end of crystallite inc
crystallite_subF0, & !< def grad at start of crystallite inc
@ -145,12 +143,10 @@ subroutine crystallite_init
allocate(crystallite_partionedFp0(3,3,cMax,iMax,eMax), source=0.0_pReal)
allocate(crystallite_subFp0(3,3,cMax,iMax,eMax), source=0.0_pReal)
allocate(crystallite_Fp(3,3,cMax,iMax,eMax), source=0.0_pReal)
allocate(crystallite_invFp(3,3,cMax,iMax,eMax), source=0.0_pReal)
allocate(crystallite_Fi0(3,3,cMax,iMax,eMax), source=0.0_pReal)
allocate(crystallite_partionedFi0(3,3,cMax,iMax,eMax), source=0.0_pReal)
allocate(crystallite_subFi0(3,3,cMax,iMax,eMax), source=0.0_pReal)
allocate(crystallite_Fi(3,3,cMax,iMax,eMax), source=0.0_pReal)
allocate(crystallite_invFi(3,3,cMax,iMax,eMax), source=0.0_pReal)
allocate(crystallite_Fe(3,3,cMax,iMax,eMax), source=0.0_pReal)
allocate(crystallite_Lp0(3,3,cMax,iMax,eMax), source=0.0_pReal)
allocate(crystallite_partionedLp0(3,3,cMax,iMax,eMax), source=0.0_pReal)
@ -408,9 +404,7 @@ function crystallite_stress(dummyArgumentToPreventInternalCompilerErrorWithGCC)
else
crystallite_subStep(c,i,e) = num%subStepSizeCryst * crystallite_subStep(c,i,e)
crystallite_Fp (1:3,1:3,c,i,e) = crystallite_subFp0(1:3,1:3,c,i,e)
crystallite_invFp(1:3,1:3,c,i,e) = math_inv33(crystallite_Fp (1:3,1:3,c,i,e))
crystallite_Fi (1:3,1:3,c,i,e) = crystallite_subFi0(1:3,1:3,c,i,e)
crystallite_invFi(1:3,1:3,c,i,e) = math_inv33(crystallite_Fi (1:3,1:3,c,i,e))
crystallite_S (1:3,1:3,c,i,e) = crystallite_S0 (1:3,1:3,c,i,e)
if (crystallite_subStep(c,i,e) < 1.0_pReal) then ! actual (not initial) cutback
crystallite_Lp (1:3,1:3,c,i,e) = crystallite_subLp0(1:3,1:3,c,i,e)
@ -434,8 +428,8 @@ function crystallite_stress(dummyArgumentToPreventInternalCompilerErrorWithGCC)
+ crystallite_subStep(c,i,e) *( crystallite_partionedF (1:3,1:3,c,i,e) &
-crystallite_partionedF0(1:3,1:3,c,i,e))
crystallite_Fe(1:3,1:3,c,i,e) = matmul(matmul(crystallite_subF(1:3,1:3,c,i,e), &
crystallite_invFp(1:3,1:3,c,i,e)), &
crystallite_invFi(1:3,1:3,c,i,e))
math_inv33(crystallite_Fp(1:3,1:3,c,i,e))), &
math_inv33(crystallite_Fi(1:3,1:3,c,i,e)))
crystallite_subdt(c,i,e) = crystallite_subStep(c,i,e) * crystallite_dt(c,i,e)
crystallite_converged(c,i,e) = .false.
endif
@ -477,7 +471,9 @@ subroutine crystallite_stressTangent
o, &
p
real(pReal), dimension(3,3) :: temp_33_1, devNull,invSubFi0, temp_33_2, temp_33_3, temp_33_4
real(pReal), dimension(3,3) :: devNull, &
invSubFp0,invSubFi0,invFp,invFi, &
temp_33_1, temp_33_2, temp_33_3, temp_33_4
real(pReal), dimension(3,3,3,3) :: dSdFe, &
dSdF, &
dSdFi, &
@ -493,7 +489,8 @@ subroutine crystallite_stressTangent
real(pReal), dimension(9,9):: temp_99
logical :: error
!$OMP PARALLEL DO PRIVATE(dSdF,dSdFe,dSdFi,dLpdS,dLpdFi,dFpinvdF,dLidS,dLidFi,dFidS,invSubFi0,o,p, &
!$OMP PARALLEL DO PRIVATE(dSdF,dSdFe,dSdFi,dLpdS,dLpdFi,dFpinvdF,dLidS,dLidFi,dFidS,o,p, &
!$OMP invSubFp0,invSubFi0,invFp,invFi, &
!$OMP rhs_3333,lhs_3333,temp_99,temp_33_1,temp_33_2,temp_33_3,temp_33_4,temp_3333,error)
elementLooping: do e = FEsolving_execElem(1),FEsolving_execElem(2)
do i = FEsolving_execIP(1),FEsolving_execIP(2)
@ -507,16 +504,20 @@ subroutine crystallite_stressTangent
crystallite_Fi(1:3,1:3,c,i,e), &
c,i,e)
invFp = math_inv33(crystallite_Fp(1:3,1:3,c,i,e))
invFi = math_inv33(crystallite_Fi(1:3,1:3,c,i,e))
invSubFp0 = math_inv33(crystallite_subFp0(1:3,1:3,c,i,e))
invSubFi0 = math_inv33(crystallite_subFi0(1:3,1:3,c,i,e))
if (sum(abs(dLidS)) < tol_math_check) then
dFidS = 0.0_pReal
else
invSubFi0 = math_inv33(crystallite_subFi0(1:3,1:3,c,i,e))
lhs_3333 = 0.0_pReal; rhs_3333 = 0.0_pReal
do o=1,3; do p=1,3
lhs_3333(1:3,1:3,o,p) = lhs_3333(1:3,1:3,o,p) &
+ crystallite_subdt(c,i,e)*matmul(invSubFi0,dLidFi(1:3,1:3,o,p))
lhs_3333(1:3,o,1:3,p) = lhs_3333(1:3,o,1:3,p) &
+ crystallite_invFi(1:3,1:3,c,i,e)*crystallite_invFi(p,o,c,i,e)
+ invFi*invFi(p,o)
rhs_3333(1:3,1:3,o,p) = rhs_3333(1:3,1:3,o,p) &
- crystallite_subdt(c,i,e)*matmul(invSubFi0,dLidS(1:3,1:3,o,p))
enddo; enddo
@ -538,18 +539,13 @@ subroutine crystallite_stressTangent
!--------------------------------------------------------------------------------------------------
! calculate dSdF
temp_33_1 = transpose(matmul(crystallite_invFp(1:3,1:3,c,i,e), &
crystallite_invFi(1:3,1:3,c,i,e)))
temp_33_2 = matmul(crystallite_subF(1:3,1:3,c,i,e), &
math_inv33(crystallite_subFp0(1:3,1:3,c,i,e)))
temp_33_3 = matmul(matmul(crystallite_subF(1:3,1:3,c,i,e), &
crystallite_invFp (1:3,1:3,c,i,e)), &
math_inv33(crystallite_subFi0(1:3,1:3,c,i,e)))
temp_33_1 = transpose(matmul(invFp,invFi))
temp_33_2 = matmul(crystallite_subF(1:3,1:3,c,i,e),invSubFp0)
temp_33_3 = matmul(matmul(crystallite_subF(1:3,1:3,c,i,e),invFp), invSubFi0)
do o=1,3; do p=1,3
rhs_3333(p,o,1:3,1:3) = matmul(dSdFe(p,o,1:3,1:3),temp_33_1)
temp_3333(1:3,1:3,p,o) = matmul(matmul(temp_33_2,dLpdS(1:3,1:3,p,o)), &
crystallite_invFi(1:3,1:3,c,i,e)) &
temp_3333(1:3,1:3,p,o) = matmul(matmul(temp_33_2,dLpdS(1:3,1:3,p,o)), invFi) &
+ matmul(temp_33_3,dLidS(1:3,1:3,p,o))
enddo; enddo
lhs_3333 = crystallite_subdt(c,i,e)*math_mul3333xx3333(dSdFe,temp_3333) &
@ -569,15 +565,14 @@ subroutine crystallite_stressTangent
temp_3333 = math_mul3333xx3333(dLpdS,dSdF)
do o=1,3; do p=1,3
dFpinvdF(1:3,1:3,p,o) = -crystallite_subdt(c,i,e) &
* matmul(math_inv33(crystallite_subFp0(1:3,1:3,c,i,e)), &
matmul(temp_3333(1:3,1:3,p,o),crystallite_invFi(1:3,1:3,c,i,e)))
* matmul(invSubFp0, matmul(temp_3333(1:3,1:3,p,o),invFi))
enddo; enddo
!--------------------------------------------------------------------------------------------------
! assemble dPdF
temp_33_1 = matmul(crystallite_S(1:3,1:3,c,i,e),transpose(crystallite_invFp(1:3,1:3,c,i,e)))
temp_33_2 = matmul(crystallite_invFp(1:3,1:3,c,i,e),temp_33_1)
temp_33_3 = matmul(crystallite_subF(1:3,1:3,c,i,e),crystallite_invFp(1:3,1:3,c,i,e))
temp_33_1 = matmul(crystallite_S(1:3,1:3,c,i,e),transpose(invFp))
temp_33_2 = matmul(invFp,temp_33_1)
temp_33_3 = matmul(crystallite_subF(1:3,1:3,c,i,e),invFp)
temp_33_4 = matmul(temp_33_3,crystallite_S(1:3,1:3,c,i,e))
crystallite_dPdF(1:3,1:3,1:3,1:3,c,i,e) = 0.0_pReal
@ -589,7 +584,7 @@ subroutine crystallite_stressTangent
+ matmul(matmul(crystallite_subF(1:3,1:3,c,i,e), &
dFpinvdF(1:3,1:3,p,o)),temp_33_1) &
+ matmul(matmul(temp_33_3,dSdF(1:3,1:3,p,o)), &
transpose(crystallite_invFp(1:3,1:3,c,i,e))) &
transpose(invFp)) &
+ matmul(temp_33_4,transpose(dFpinvdF(1:3,1:3,p,o)))
enddo; enddo
@ -793,28 +788,28 @@ logical function integrateStress(ipc,ip,el,timeFraction)
real(pReal), dimension(3,3):: F, & ! deformation gradient at end of timestep
Fp_new, & ! plastic deformation gradient at end of timestep
Fe_new, & ! elastic deformation gradient at end of timestep
invFp_new, & ! inverse of Fp_new
Fi_new, & ! gradient of intermediate deformation stages
invFi_new, &
invFp_current, & ! inverse of Fp_current
invFi_current, & ! inverse of Fp_current
Lpguess, & ! current guess for plastic velocity gradient
Lpguess_old, & ! known last good guess for plastic velocity gradient
Lp_constitutive, & ! plastic velocity gradient resulting from constitutive law
residuumLp, & ! current residuum of plastic velocity gradient
residuumLp_old, & ! last residuum of plastic velocity gradient
deltaLp, & ! direction of next guess
Fi_new, & ! gradient of intermediate deformation stages
invFi_new, &
invFi_current, & ! inverse of Fi_current
Liguess, & ! current guess for intermediate velocity gradient
Liguess_old, & ! known last good guess for intermediate velocity gradient
Li_constitutive, & ! intermediate velocity gradient resulting from constitutive law
residuumLi, & ! current residuum of intermediate velocity gradient
residuumLi_old, & ! last residuum of intermediate velocity gradient
deltaLi, & ! direction of next guess
Fe, & ! elastic deformation gradient
Fe_new, &
S, & ! 2nd Piola-Kirchhoff Stress in plastic (lattice) configuration
A, &
B, &
Fe, & ! elastic deformation gradient
temp_33
real(pReal), dimension(9) :: temp_9 ! needed for matrix inversion by LAPACK
integer, dimension(9) :: devNull_9 ! needed for matrix inversion by LAPACK
@ -993,16 +988,13 @@ logical function integrateStress(ipc,ip,el,timeFraction)
Fe_new = matmul(matmul(F,invFp_new),invFi_new)
integrateStress = .true.
crystallite_P (1:3,1:3,ipc,ip,el) = matmul(matmul(F,invFp_new),matmul(S,transpose(invFp_new))) ! ToDo: We propably do not need to store P!
crystallite_P (1:3,1:3,ipc,ip,el) = matmul(matmul(F,invFp_new),matmul(S,transpose(invFp_new)))
crystallite_S (1:3,1:3,ipc,ip,el) = S
crystallite_Lp (1:3,1:3,ipc,ip,el) = Lpguess
crystallite_Li (1:3,1:3,ipc,ip,el) = Liguess
crystallite_Fp (1:3,1:3,ipc,ip,el) = Fp_new
crystallite_Fi (1:3,1:3,ipc,ip,el) = Fi_new
crystallite_Fe (1:3,1:3,ipc,ip,el) = Fe_new
crystallite_invFp(1:3,1:3,ipc,ip,el) = invFp_new
crystallite_invFi(1:3,1:3,ipc,ip,el) = invFi_new
end function integrateStress

View File

@ -9,17 +9,6 @@
submodule(homogenization) homogenization_mech_RGC
use rotations
enum, bind(c)
enumerator :: &
undefined_ID, &
constitutivework_ID, &
penaltyenergy_ID, &
volumediscrepancy_ID, &
averagerelaxrate_ID,&
maximumrelaxrate_ID,&
magnitudemismatch_ID
end enum
type :: tParameters
integer, dimension(:), allocatable :: &
Nconstituents
@ -31,8 +20,8 @@ submodule(homogenization) homogenization_mech_RGC
angles
integer :: &
of_debug = 0
integer(kind(undefined_ID)), dimension(:), allocatable :: &
outputID
character(len=pStringLen), allocatable, dimension(:) :: &
output
end type tParameters
type :: tRGCstate
@ -71,17 +60,12 @@ module subroutine mech_RGC_init
integer :: &
Ninstance, &
h, i, &
h, &
NofMyHomog, &
sizeState, nIntFaceTot
integer(kind(undefined_ID)) :: &
outputID
character(len=pStringLen), dimension(:), allocatable :: &
outputs
write(6,'(/,a)') ' <<<+- homogenization_'//HOMOGENIZATION_RGC_label//' init -+>>>'
write(6,'(/,a)') ' <<<+- homogenization_'//HOMOGENIZATION_RGC_label//' init -+>>>'; flush(6)
write(6,'(/,a)') ' Tjahjanto et al., International Journal of Material Forming 2(1):939942, 2009'
write(6,'(a)') ' https://doi.org/10.1007/s12289-009-0619-1'
@ -123,33 +107,7 @@ module subroutine mech_RGC_init
prm%dAlpha = config%getFloats('grainsize', requiredSize=3)
prm%angles = config%getFloats('clusterorientation',requiredSize=3)
outputs = config%getStrings('(output)',defaultVal=emptyStringArray)
allocate(prm%outputID(0))
do i=1, size(outputs)
outputID = undefined_ID
select case(outputs(i))
case('constitutivework')
outputID = constitutivework_ID
case('penaltyenergy')
outputID = penaltyenergy_ID
case('volumediscrepancy')
outputID = volumediscrepancy_ID
case('averagerelaxrate')
outputID = averagerelaxrate_ID
case('maximumrelaxrate')
outputID = maximumrelaxrate_ID
case('magnitudemismatch')
outputID = magnitudemismatch_ID
end select
if (outputID /= undefined_ID) then
prm%outputID = [prm%outputID , outputID]
endif
enddo
prm%output = config%getStrings('(output)',defaultVal=emptyStringArray)
NofMyHomog = count(material_homogenizationAt == h)
nIntFaceTot = 3*( (prm%Nconstituents(1)-1)*prm%Nconstituents(2)*prm%Nconstituents(3) &
@ -934,26 +892,24 @@ module subroutine mech_RGC_results(instance,group)
integer :: o
associate(stt => state(instance), dst => dependentState(instance), prm => param(instance))
outputsLoop: do o = 1,size(prm%outputID)
select case(prm%outputID(o))
case (constitutivework_ID)
outputsLoop: do o = 1,size(prm%output)
select case(trim(prm%output(o)))
case('constitutivework')
call results_writeDataset(group,stt%work,'W',&
'work density','J/m³')
case (magnitudemismatch_ID)
case('magnitudemismatch')
call results_writeDataset(group,dst%mismatch,'N',&
'average mismatch tensor','1')
case (penaltyenergy_ID)
case('penaltyenergy')
call results_writeDataset(group,stt%penaltyEnergy,'R',&
'mismatch penalty density','J/m³')
case (volumediscrepancy_ID)
case('volumediscrepancy')
call results_writeDataset(group,dst%volumeDiscrepancy,'Delta_V',&
'volume discrepancy','m³')
case (maximumrelaxrate_ID)
case('maximumrelaxrate')
call results_writeDataset(group,dst%relaxationrate_max,'max_alpha_dot',&
'maximum relaxation rate','m/s')
case (averagerelaxrate_ID)
case('averagerelaxrate')
call results_writeDataset(group,dst%relaxationrate_avg,'avg_alpha_dot',&
'average relaxation rate','m/s')
end select

View File

@ -16,14 +16,9 @@ module thermal_adiabatic
implicit none
private
enum, bind(c)
enumerator :: undefined_ID, &
temperature_ID
end enum
type :: tParameters
integer(kind(undefined_ID)), dimension(:), allocatable :: &
outputID
character(len=pStringLen), allocatable, dimension(:) :: &
output
end type tParameters
type(tparameters), dimension(:), allocatable :: &
@ -46,8 +41,7 @@ contains
!--------------------------------------------------------------------------------------------------
subroutine thermal_adiabatic_init
integer :: maxNinstance,o,h,NofMyHomog
character(len=pStringLen), dimension(:), allocatable :: outputs
integer :: maxNinstance,h,NofMyHomog
write(6,'(/,a)') ' <<<+- thermal_'//THERMAL_ADIABATIC_label//' init -+>>>'; flush(6)
@ -60,15 +54,7 @@ subroutine thermal_adiabatic_init
if (thermal_type(h) /= THERMAL_adiabatic_ID) cycle
associate(prm => param(thermal_typeInstance(h)),config => config_homogenization(h))
outputs = config%getStrings('(output)',defaultVal=emptyStringArray)
allocate(prm%outputID(0))
do o=1, size(outputs)
select case(outputs(o))
case('temperature')
prm%outputID = [prm%outputID, temperature_ID]
end select
enddo
prm%output = config%getStrings('(output)',defaultVal=emptyStringArray)
NofMyHomog=count(material_homogenizationAt==h)
thermalState(h)%sizeState = 1
@ -76,7 +62,6 @@ subroutine thermal_adiabatic_init
allocate(thermalState(h)%subState0(1,NofMyHomog), source=thermal_initialT(h))
allocate(thermalState(h)%state (1,NofMyHomog), source=thermal_initialT(h))
nullify(thermalMapping(h)%p)
thermalMapping(h)%p => material_homogenizationMemberAt
deallocate(temperature(h)%p)
temperature(h)%p => thermalState(h)%state(1,:)
@ -246,14 +231,13 @@ subroutine thermal_adiabatic_results(homog,group)
integer, intent(in) :: homog
character(len=*), intent(in) :: group
integer :: o
associate(prm => param(damage_typeInstance(homog)))
outputsLoop: do o = 1,size(prm%outputID)
select case(prm%outputID(o))
case (temperature_ID)
outputsLoop: do o = 1,size(prm%output)
select case(trim(prm%output(o)))
case('temperature') ! ToDo: should be 'T'
call results_writeDataset(group,temperature(homog)%p,'T',&
'temperature','K')
end select

View File

@ -15,15 +15,9 @@ module thermal_conduction
implicit none
private
enum, bind(c)
enumerator :: &
undefined_ID, &
temperature_ID
end enum
type :: tParameters
integer(kind(undefined_ID)), dimension(:), allocatable :: &
outputID
character(len=pStringLen), allocatable, dimension(:) :: &
output
end type tParameters
type(tparameters), dimension(:), allocatable :: &
@ -48,8 +42,7 @@ contains
subroutine thermal_conduction_init
integer :: maxNinstance,o,NofMyHomog,h
character(len=pStringLen), dimension(:), allocatable :: outputs
integer :: maxNinstance,NofMyHomog,h
write(6,'(/,a)') ' <<<+- thermal_'//THERMAL_CONDUCTION_label//' init -+>>>'; flush(6)
@ -62,15 +55,7 @@ subroutine thermal_conduction_init
if (thermal_type(h) /= THERMAL_conduction_ID) cycle
associate(prm => param(thermal_typeInstance(h)),config => config_homogenization(h))
outputs = config%getStrings('(output)',defaultVal=emptyStringArray)
allocate(prm%outputID(0))
do o=1, size(outputs)
select case(outputs(o))
case('temperature')
prm%outputID = [prm%outputID, temperature_ID]
end select
enddo
prm%output = config%getStrings('(output)',defaultVal=emptyStringArray)
NofMyHomog=count(material_homogenizationAt==h)
thermalState(h)%sizeState = 0
@ -78,7 +63,6 @@ subroutine thermal_conduction_init
allocate(thermalState(h)%subState0(0,NofMyHomog))
allocate(thermalState(h)%state (0,NofMyHomog))
nullify(thermalMapping(h)%p)
thermalMapping(h)%p => material_homogenizationMemberAt
deallocate(temperature (h)%p)
allocate (temperature (h)%p(NofMyHomog), source=thermal_initialT(h))
@ -259,14 +243,13 @@ subroutine thermal_conduction_results(homog,group)
integer, intent(in) :: homog
character(len=*), intent(in) :: group
integer :: o
associate(prm => param(damage_typeInstance(homog)))
outputsLoop: do o = 1,size(prm%outputID)
select case(prm%outputID(o))
case (temperature_ID)
outputsLoop: do o = 1,size(prm%output)
select case(trim(prm%output(o)))
case('temperature') ! ToDo: should be 'T'
call results_writeDataset(group,temperature(homog)%p,'T',&
'temperature','K')
end select